feat(FalukantService): implement marriage honeymoon pregnancy scheduling logic
All checks were successful
Deploy to production / deploy (push) Successful in 2m5s

- 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.
This commit is contained in:
Torsten Schulz (local)
2026-05-13 22:07:46 +02:00
parent b59526b20d
commit 464208e30e

View File

@@ -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) { async getFamily(hashedUserId) {
const user = await this.getFalukantUserByHashedId(hashedUserId); const user = await this.getFalukantUserByHashedId(hashedUserId);
if (!user) throw new Error('User not found'); if (!user) throw new Error('User not found');
@@ -3824,6 +3915,19 @@ class FalukantService extends BaseService {
family.possiblePartners = await this.getPossiblePartners(character.id); 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; return family;
} }