Implement age validation for political applications in FalukantService: Added MIN_AGE_POLITICS_DAYS constant and logic to check user age before allowing applications. Updated PoliticsView to reflect age eligibility and display appropriate hints. Enhanced error handling for age-related restrictions.

This commit is contained in:
Torsten Schulz (local)
2026-02-06 00:00:11 +01:00
parent 23b0c45518
commit 6b96ee9856
4 changed files with 33 additions and 14 deletions

View File

@@ -4408,9 +4408,15 @@ class FalukantService extends BaseService {
});
}
/** Mindestalter für Bewerbung auf politische Ämter (in Tagen; 16 Tage Realzeit = 16 Spieljahre) */
static MIN_AGE_POLITICS_DAYS = 16;
async getOpenPolitics(hashedUserId) {
const user = await this.getFalukantUserByHashedId(hashedUserId);
const characterId = user.character.id;
const character = user.character;
const characterId = character.id;
const ageDays = character.birthdate ? calcAge(character.birthdate) : 0;
const canApplyByAge = ageDays >= FalukantService.MIN_AGE_POLITICS_DAYS;
const rows = await sequelize.query(
FalukantService.RECURSIVE_REGION_SEARCH,
{
@@ -4481,7 +4487,8 @@ class FalukantService extends BaseService {
return {
...e,
history: matchingHistory,
alreadyApplied
alreadyApplied,
canApplyByAge
};
})
.filter(election => !election.alreadyApplied); // Nur Positionen ohne bestehende Bewerbung
@@ -4499,24 +4506,30 @@ class FalukantService extends BaseService {
throw new Error('Kein Charakter zum User gefunden');
}
// 2) NoncivilTitel aussperren
// 2) Mindestalter 16 (Spieljahre = 16 Tage Realzeit)
const ageDays = character.birthdate ? calcAge(character.birthdate) : 0;
if (ageDays < FalukantService.MIN_AGE_POLITICS_DAYS) {
throw new Error('too_young');
}
// 3) NoncivilTitel aussperren
if (character.nobleTitle.labelTr === 'noncivil') {
return { applied: [], skipped: electionIds };
}
// 3) Ermittle die offenen Wahlen, auf die er zugreifen darf
// 4) Ermittle die offenen Wahlen, auf die er zugreifen darf
// Verwende getOpenPolitics statt getElections, da getOpenPolitics die gleichen Wahlen
// zurückgibt, die im Frontend angezeigt werden
const openPolitics = await this.getOpenPolitics(hashedUserId);
const allowedIds = new Set(openPolitics.map(e => e.id));
// 4) Filter alle electionIds auf gültige/erlaubte
// 5) Filter alle electionIds auf gültige/erlaubte
const toTry = electionIds.filter(id => allowedIds.has(id));
if (toTry.length === 0) {
return { applied: [], skipped: electionIds };
}
// 5) Prüfe, auf welche dieser Wahlen der Character bereits als Candidate eingetragen ist
// 6) Prüfe, auf welche dieser Wahlen der Character bereits als Candidate eingetragen ist
const existing = await Candidate.findAll({
where: {
electionId: { [Op.in]: toTry },
@@ -4526,13 +4539,11 @@ class FalukantService extends BaseService {
});
const alreadyIds = new Set(existing.map(c => c.electionId));
// 6) Erstelle Liste der Wahlen, für die er sich noch nicht beworben hat
// 7) Erstelle Liste der Wahlen, für die er sich noch nicht beworben hat
const newApplications = toTry.filter(id => !alreadyIds.has(id));
const skipped = electionIds.filter(id => !newApplications.includes(id));
console.log(newApplications, skipped);
// 7) Bulk-Insert aller neuen Bewerbungen
// 8) Bulk-Insert aller neuen Bewerbungen
if (newApplications.length > 0) {
const toInsert = newApplications.map(eid => ({
electionId: eid,