From 8e20fbd24d72fefde1786a3402642a4f7de4d8d8 Mon Sep 17 00:00:00 2001 From: "Torsten Schulz (local)" Date: Wed, 28 Jan 2026 16:52:44 +0100 Subject: [PATCH] Add church office requirements validation in FalukantService: Implement checks for prerequisite office types when determining available positions, enhancing the application process for church offices based on user qualifications. --- backend/services/falukantService.js | 77 ++++++++++++++++++++++++++++- 1 file changed, 75 insertions(+), 2 deletions(-) diff --git a/backend/services/falukantService.js b/backend/services/falukantService.js index 95a9244..42fb8d2 100644 --- a/backend/services/falukantService.js +++ b/backend/services/falukantService.js @@ -51,6 +51,7 @@ import Election from '../models/falukant/data/election.js'; import ChurchOffice from '../models/falukant/data/church_office.js'; import ChurchOfficeType from '../models/falukant/type/church_office_type.js'; import ChurchApplication from '../models/falukant/data/church_application.js'; +import ChurchOfficeRequirement from '../models/falukant/predefine/church_office_requirement.js'; import PoliticalOfficeType from '../models/falukant/type/political_office_type.js'; import Candidate from '../models/falukant/data/candidate.js'; import Vote from '../models/falukant/data/vote.js'; @@ -4103,7 +4104,8 @@ class FalukantService extends BaseService { history: matchingHistory, alreadyApplied }; - }); + }) + .filter(election => !election.alreadyApplied); // Nur Positionen ohne bestehende Bewerbung return result; } @@ -4955,17 +4957,70 @@ class FalukantService extends BaseService { return []; } + // Prüfe welche Kirchenämter der Charakter bereits innehat + const heldOffices = await ChurchOffice.findAll({ + where: { characterId: character.id }, + include: [ + { + model: ChurchOfficeType, + as: 'type', + attributes: ['id'] + } + ] + }); + const heldOfficeTypeIds = heldOffices.map(o => o.type.id); + + // Prüfe welche Bewerbungen bereits existieren + const existingApplications = await ChurchApplication.findAll({ + where: { + characterId: character.id, + status: 'pending' + }, + attributes: ['officeTypeId', 'regionId'] + }); + const appliedPositions = new Set( + existingApplications.map(a => `${a.officeTypeId}-${a.regionId}`) + ); + // Alle relevanten Regionen (Region + Eltern) laden const relevantRegionIds = await this.getRegionAndParentIds(character.regionId); - // Alle Kirchenamt-Typen laden + // Alle Kirchenamt-Typen mit Voraussetzungen laden const officeTypes = await ChurchOfficeType.findAll({ + include: [ + { + model: ChurchOfficeRequirement, + as: 'requirements', + required: false + } + ], order: [['hierarchyLevel', 'ASC']] }); const availablePositions = []; for (const officeType of officeTypes) { + // Prüfe Voraussetzungen: Hat der User bereits das erforderliche niedrigere Amt? + const requirement = officeType.requirements?.[0]; + if (requirement && requirement.prerequisiteOfficeTypeId) { + // Prüfe ob der User das erforderliche Amt innehat + if (!heldOfficeTypeIds.includes(requirement.prerequisiteOfficeTypeId)) { + continue; // Voraussetzung nicht erfüllt + } + } else if (requirement && requirement.prerequisiteOfficeTypeId === null) { + // Keine Voraussetzung = Einstiegsposition, OK + } else if (heldOfficeTypeIds.length === 0) { + // Wenn keine Voraussetzung definiert ist, aber User hat noch kein Amt, nur Einstiegspositionen zeigen + if (officeType.hierarchyLevel > 0) { + continue; + } + } + + // Prüfe ob der User bereits dieses Amt innehat + if (heldOfficeTypeIds.includes(officeType.id)) { + continue; // User hat bereits dieses Amt + } + // Finde den RegionType für diesen officeType const regionType = await RegionType.findOne({ where: { labelTr: officeType.regionType } @@ -4982,6 +5037,24 @@ class FalukantService extends BaseService { }); for (const region of regions) { + // Prüfe ob bereits eine Bewerbung für diese Position existiert + const applicationKey = `${officeType.id}-${region.id}`; + if (appliedPositions.has(applicationKey)) { + continue; // Bereits beworben + } + + // Prüfe ob der User bereits dieses Amt in dieser Region innehat + const hasOfficeInRegion = await ChurchOffice.findOne({ + where: { + characterId: character.id, + officeTypeId: officeType.id, + regionId: region.id + } + }); + if (hasOfficeInRegion) { + continue; // User hat bereits dieses Amt in dieser Region + } + // Zähle besetzte Positionen dieses Typs in dieser Region const occupiedCount = await ChurchOffice.count({ where: {