From 464208e30e00dbaf5d96379d70e8d7e097b38214 Mon Sep 17 00:00:00 2001 From: "Torsten Schulz (local)" Date: Wed, 13 May 2026 22:07:46 +0200 Subject: [PATCH] feat(FalukantService): implement marriage honeymoon pregnancy scheduling logic - Added a new method to ensure pregnancy scheduling for married couples after the wedding, allowing the system to manage pregnancy due dates effectively. - Integrated checks for existing pregnancy and relationship flags to prevent duplicate scheduling. - Updated family retrieval logic to include pregnancy status based on the new scheduling method, enhancing user experience in family management. --- backend/services/falukantService.js | 104 ++++++++++++++++++++++++++++ 1 file changed, 104 insertions(+) diff --git a/backend/services/falukantService.js b/backend/services/falukantService.js index bd94c1c..55640f6 100644 --- a/backend/services/falukantService.js +++ b/backend/services/falukantService.js @@ -3534,6 +3534,97 @@ class FalukantService extends BaseService { } } + /** + * Nach der Trauung (relationship = married): geplante Geburt auf der Mutter-Charakterzeile setzen, + * damit der Daemon den UserCharacterWorker-Pfad mit pregnancy_due_at nutzen kann. + * Läuft idempotent pro Ehe über relationship_state.flags_json.honeymoonPregnancyScheduled. + * @returns {{ scheduled: boolean, motherCharacterId?: number }} + */ + async _ensureMarriageHoneymoonPregnancyScheduled({ + playerCharacterId, + playerGender, + spouseCharacterId, + spouseGender, + relationshipId, + }) { + if (!relationshipId || !playerCharacterId || !spouseCharacterId) { + return { scheduled: false }; + } + const norm = (g) => String(g || '').trim().toLowerCase(); + const isFemale = (g) => { + const s = norm(g); + return s === 'female' || s === 'f'; + }; + const isMale = (g) => { + const s = norm(g); + return s === 'male' || s === 'm'; + }; + let motherId; + let fatherId; + if (isFemale(playerGender) && isMale(spouseGender)) { + motherId = playerCharacterId; + fatherId = spouseCharacterId; + } else if (isFemale(spouseGender) && isMale(playerGender)) { + motherId = spouseCharacterId; + fatherId = playerCharacterId; + } else { + return { scheduled: false }; + } + + const stateRow = await RelationshipState.findOne({ where: { relationshipId } }); + const flags = stateRow?.flagsJson && typeof stateRow.flagsJson === 'object' + ? { ...stateRow.flagsJson } + : {}; + if (flags.honeymoonPregnancyScheduled) { + return { scheduled: false }; + } + + const pregRows = await sequelize.query( + `SELECT pregnancy_due_at FROM falukant_data."character" WHERE id = :id`, + { replacements: { id: motherId }, type: Sequelize.QueryTypes.SELECT } + ); + if (pregRows[0]?.pregnancy_due_at) { + return { scheduled: false }; + } + + // Gleicher Default wie adminForceFalukantPregnancy (21 Tage bis Geburt — komprimierte Spielzeit). + const BIRTH_DUE_DAYS = 21; + const due = new Date(); + due.setDate(due.getDate() + BIRTH_DUE_DAYS); + + await FalukantCharacter.unscoped().update( + { + pregnancyDueAt: due, + pregnancyFatherCharacterId: fatherId, + }, + { where: { id: motherId } } + ); + + const mergedFlags = { ...flags, honeymoonPregnancyScheduled: true }; + if (stateRow) { + await stateRow.update({ flagsJson: mergedFlags }); + } else { + await RelationshipState.create({ + relationshipId, + ...this.buildDefaultRelationshipState('married'), + flagsJson: mergedFlags, + }); + } + + const mother = await FalukantCharacter.unscoped().findByPk(motherId, { attributes: ['id', 'userId'] }); + if (mother?.userId) { + const fu = await FalukantUser.findByPk(mother.userId); + if (fu) { + const u = await User.findByPk(fu.userId); + if (u?.hashedId) { + await notifyUser(u.hashedId, 'familychanged', {}); + } + } + } + + return { scheduled: true, motherCharacterId: motherId }; + } + async getFamily(hashedUserId) { const user = await this.getFalukantUserByHashedId(hashedUserId); if (!user) throw new Error('User not found'); @@ -3824,6 +3915,19 @@ class FalukantService extends BaseService { family.possiblePartners = await this.getPossiblePartners(character.id); } } + const marriedRel = family.relationships.find((r) => r.relationshipType === 'married'); + if (marriedRel?.id && marriedRel.character2?.id != null) { + const honeymoon = await this._ensureMarriageHoneymoonPregnancyScheduled({ + playerCharacterId: character.id, + playerGender: character.gender, + spouseCharacterId: marriedRel.character2.id, + spouseGender: marriedRel.character2.gender, + relationshipId: marriedRel.id, + }); + if (honeymoon.scheduled && honeymoon.motherCharacterId === character.id) { + family.pregnancy = await this._getCharacterPregnancyOptional(character.id); + } + } return family; }