Remove deprecated relationship change log migration and enhance error handling in FalukantService for partner retrieval
This commit is contained in:
@@ -1,105 +0,0 @@
|
||||
/* eslint-disable */
|
||||
'use strict';
|
||||
|
||||
/** Log-Tabelle für alle Änderungen an relationship und marriage_proposals (keine Einträge werden gelöscht).
|
||||
* Hilft zu analysieren, warum z.B. Werbungen um einen Partner über Nacht verschwinden. */
|
||||
|
||||
module.exports = {
|
||||
async up(queryInterface, Sequelize) {
|
||||
await queryInterface.sequelize.query(`
|
||||
CREATE TABLE IF NOT EXISTS falukant_log.relationship_change_log (
|
||||
id serial PRIMARY KEY,
|
||||
changed_at timestamp with time zone NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
table_name character varying(64) NOT NULL,
|
||||
operation character varying(16) NOT NULL,
|
||||
record_id integer,
|
||||
payload_old jsonb,
|
||||
payload_new jsonb
|
||||
);
|
||||
`);
|
||||
await queryInterface.sequelize.query(`
|
||||
CREATE INDEX IF NOT EXISTS relationship_change_log_changed_at_idx
|
||||
ON falukant_log.relationship_change_log (changed_at);
|
||||
`);
|
||||
await queryInterface.sequelize.query(`
|
||||
CREATE INDEX IF NOT EXISTS relationship_change_log_table_operation_idx
|
||||
ON falukant_log.relationship_change_log (table_name, operation);
|
||||
`);
|
||||
|
||||
const triggerFunction = `
|
||||
CREATE OR REPLACE FUNCTION falukant_log.log_relationship_change()
|
||||
RETURNS TRIGGER AS $$
|
||||
DECLARE
|
||||
v_record_id INTEGER;
|
||||
v_payload_old JSONB;
|
||||
v_payload_new JSONB;
|
||||
BEGIN
|
||||
IF TG_OP = 'INSERT' THEN
|
||||
v_record_id := NEW.id;
|
||||
v_payload_old := NULL;
|
||||
v_payload_new := to_jsonb(NEW);
|
||||
ELSIF TG_OP = 'UPDATE' THEN
|
||||
v_record_id := NEW.id;
|
||||
v_payload_old := to_jsonb(OLD);
|
||||
v_payload_new := to_jsonb(NEW);
|
||||
ELSIF TG_OP = 'DELETE' THEN
|
||||
v_record_id := OLD.id;
|
||||
v_payload_old := to_jsonb(OLD);
|
||||
v_payload_new := NULL;
|
||||
END IF;
|
||||
|
||||
INSERT INTO falukant_log.relationship_change_log (
|
||||
table_name,
|
||||
operation,
|
||||
record_id,
|
||||
payload_old,
|
||||
payload_new
|
||||
) VALUES (
|
||||
TG_TABLE_NAME,
|
||||
TG_OP,
|
||||
v_record_id,
|
||||
v_payload_old,
|
||||
v_payload_new
|
||||
);
|
||||
|
||||
IF TG_OP = 'DELETE' THEN
|
||||
RETURN OLD;
|
||||
ELSE
|
||||
RETURN NEW;
|
||||
END IF;
|
||||
END;
|
||||
$$ LANGUAGE plpgsql;
|
||||
`;
|
||||
await queryInterface.sequelize.query(triggerFunction);
|
||||
|
||||
await queryInterface.sequelize.query(`
|
||||
DROP TRIGGER IF EXISTS trg_log_relationship_change ON falukant_data.relationship;
|
||||
CREATE TRIGGER trg_log_relationship_change
|
||||
AFTER INSERT OR UPDATE OR DELETE ON falukant_data.relationship
|
||||
FOR EACH ROW
|
||||
EXECUTE FUNCTION falukant_log.log_relationship_change();
|
||||
`);
|
||||
await queryInterface.sequelize.query(`
|
||||
DROP TRIGGER IF EXISTS trg_log_relationship_change ON falukant_data.marriage_proposals;
|
||||
CREATE TRIGGER trg_log_relationship_change
|
||||
AFTER INSERT OR UPDATE OR DELETE ON falukant_data.marriage_proposals
|
||||
FOR EACH ROW
|
||||
EXECUTE FUNCTION falukant_log.log_relationship_change();
|
||||
`);
|
||||
},
|
||||
|
||||
async down(queryInterface, Sequelize) {
|
||||
await queryInterface.sequelize.query(`
|
||||
DROP TRIGGER IF EXISTS trg_log_relationship_change ON falukant_data.relationship;
|
||||
`);
|
||||
await queryInterface.sequelize.query(`
|
||||
DROP TRIGGER IF EXISTS trg_log_relationship_change ON falukant_data.marriage_proposals;
|
||||
`);
|
||||
await queryInterface.sequelize.query(`
|
||||
DROP FUNCTION IF EXISTS falukant_log.log_relationship_change();
|
||||
`);
|
||||
await queryInterface.sequelize.query(`
|
||||
DROP TABLE IF EXISTS falukant_log.relationship_change_log;
|
||||
`);
|
||||
},
|
||||
};
|
||||
@@ -3158,6 +3158,7 @@ class FalukantService extends BaseService {
|
||||
const step7Start = Date.now();
|
||||
const ownAge = calcAge(character.birthdate);
|
||||
if (ownAge >= 12 && family.relationships.length === 0) {
|
||||
try {
|
||||
family.possiblePartners = await this.getPossiblePartners(character.id);
|
||||
if (family.possiblePartners.length === 0) {
|
||||
// Asynchron erstellen, nicht blockieren
|
||||
@@ -3169,6 +3170,12 @@ class FalukantService extends BaseService {
|
||||
ownAge
|
||||
).catch(err => console.error('[getFamily] Error creating partners (async):', err));
|
||||
}
|
||||
} catch (err) {
|
||||
// Fehler beim Laden nicht an Frontend durchreichen – Seite bleibt nutzbar, Log für Analyse
|
||||
console.error('[getFamily] getPossiblePartners failed (characterId=%s):', character.id, err?.message || err);
|
||||
if (err?.stack) console.error('[getFamily] getPossiblePartners stack:', err.stack);
|
||||
family.possiblePartners = [];
|
||||
}
|
||||
}
|
||||
timings.step7_possible_partners = Date.now() - step7Start;
|
||||
|
||||
@@ -3399,33 +3406,44 @@ class FalukantService extends BaseService {
|
||||
{
|
||||
model: FalukantCharacter,
|
||||
as: 'proposedCharacter',
|
||||
required: false,
|
||||
attributes: ['id', 'firstName', 'lastName', 'gender', 'regionId', 'birthdate'],
|
||||
include: [
|
||||
{ model: FalukantPredefineFirstname, as: 'definedFirstName', attributes: ['name'] },
|
||||
{ model: FalukantPredefineLastname, as: 'definedLastName', attributes: ['name'] },
|
||||
{ model: TitleOfNobility, as: 'nobleTitle', attributes: ['labelTr'] },
|
||||
{ model: FalukantPredefineFirstname, as: 'definedFirstName', attributes: ['name'], required: false },
|
||||
{ model: FalukantPredefineLastname, as: 'definedLastName', attributes: ['name'], required: false },
|
||||
{ model: TitleOfNobility, as: 'nobleTitle', attributes: ['labelTr'], required: false },
|
||||
],
|
||||
},
|
||||
],
|
||||
});
|
||||
return proposals
|
||||
.filter(proposal => proposal.proposedCharacter !== null)
|
||||
.map(proposal => {
|
||||
const birthdate = new Date(proposal.proposedCharacter.birthdate);
|
||||
const age = calcAge(birthdate);
|
||||
return {
|
||||
const valid = [];
|
||||
for (const proposal of proposals) {
|
||||
if (proposal.proposedCharacter == null) {
|
||||
console.warn('[getPossiblePartners] Proposal id=%s filtered out (proposedCharacterId=%s missing)', proposal.id, proposal.proposedCharacterId);
|
||||
continue;
|
||||
}
|
||||
const pc = proposal.proposedCharacter;
|
||||
const birthdate = pc.birthdate ? new Date(pc.birthdate) : null;
|
||||
const age = birthdate ? calcAge(birthdate) : 0;
|
||||
const name = `${pc.definedFirstName?.name ?? ''} ${pc.definedLastName?.name ?? ''}`.trim() || null;
|
||||
if (!name) {
|
||||
console.warn('[getPossiblePartners] Proposal id=%s filtered out (proposedCharacterId=%s has no name)', proposal.id, pc.id);
|
||||
continue;
|
||||
}
|
||||
valid.push({
|
||||
id: proposal.id,
|
||||
requesterCharacterId: proposal.requesterCharacterId,
|
||||
proposedCharacterId: proposal.proposedCharacter.id,
|
||||
proposedCharacterName: `${proposal.proposedCharacter.definedFirstName?.name} ${proposal.proposedCharacter.definedLastName?.name}`,
|
||||
proposedCharacterGender: proposal.proposedCharacter.gender,
|
||||
proposedCharacterRegionId: proposal.proposedCharacter.regionId,
|
||||
proposedCharacterId: pc.id,
|
||||
proposedCharacterName: name,
|
||||
proposedCharacterGender: pc.gender,
|
||||
proposedCharacterRegionId: pc.regionId,
|
||||
proposedCharacterAge: age,
|
||||
proposedCharacterNobleTitle: proposal.proposedCharacter.nobleTitle?.labelTr || null,
|
||||
proposedCharacterNobleTitle: pc.nobleTitle?.labelTr ?? null,
|
||||
cost: proposal.cost,
|
||||
};
|
||||
});
|
||||
}
|
||||
return valid;
|
||||
}
|
||||
|
||||
async createPossiblePartners(requestingCharacterId, requestingCharacterGender, requestingRegionId, requestingCharacterTitleOfNobility, ownAge) {
|
||||
try {
|
||||
|
||||
@@ -387,6 +387,77 @@ const syncDatabase = async () => {
|
||||
console.warn('⚠️ Konnte Vocab-Trainer Tabellen nicht sicherstellen:', e?.message || e);
|
||||
}
|
||||
|
||||
// Relationship-/Marriage-Proposal-Änderungen loggen (keine Einträge löschen; ohne db:migrate)
|
||||
console.log("Ensuring relationship change log (falukant) exists...");
|
||||
try {
|
||||
await sequelize.query(`
|
||||
CREATE TABLE IF NOT EXISTS falukant_log.relationship_change_log (
|
||||
id serial PRIMARY KEY,
|
||||
changed_at timestamp with time zone NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
table_name character varying(64) NOT NULL,
|
||||
operation character varying(16) NOT NULL,
|
||||
record_id integer,
|
||||
payload_old jsonb,
|
||||
payload_new jsonb
|
||||
);
|
||||
`);
|
||||
await sequelize.query(`
|
||||
CREATE INDEX IF NOT EXISTS relationship_change_log_changed_at_idx
|
||||
ON falukant_log.relationship_change_log (changed_at);
|
||||
`);
|
||||
await sequelize.query(`
|
||||
CREATE INDEX IF NOT EXISTS relationship_change_log_table_operation_idx
|
||||
ON falukant_log.relationship_change_log (table_name, operation);
|
||||
`);
|
||||
await sequelize.query(`
|
||||
CREATE OR REPLACE FUNCTION falukant_log.log_relationship_change()
|
||||
RETURNS TRIGGER AS $$
|
||||
DECLARE
|
||||
v_record_id INTEGER;
|
||||
v_payload_old JSONB;
|
||||
v_payload_new JSONB;
|
||||
BEGIN
|
||||
IF TG_OP = 'INSERT' THEN
|
||||
v_record_id := NEW.id;
|
||||
v_payload_old := NULL;
|
||||
v_payload_new := to_jsonb(NEW);
|
||||
ELSIF TG_OP = 'UPDATE' THEN
|
||||
v_record_id := NEW.id;
|
||||
v_payload_old := to_jsonb(OLD);
|
||||
v_payload_new := to_jsonb(NEW);
|
||||
ELSIF TG_OP = 'DELETE' THEN
|
||||
v_record_id := OLD.id;
|
||||
v_payload_old := to_jsonb(OLD);
|
||||
v_payload_new := NULL;
|
||||
END IF;
|
||||
INSERT INTO falukant_log.relationship_change_log (
|
||||
table_name, operation, record_id, payload_old, payload_new
|
||||
) VALUES (
|
||||
TG_TABLE_NAME, TG_OP, v_record_id, v_payload_old, v_payload_new
|
||||
);
|
||||
IF TG_OP = 'DELETE' THEN RETURN OLD; ELSE RETURN NEW; END IF;
|
||||
END;
|
||||
$$ LANGUAGE plpgsql;
|
||||
`);
|
||||
await sequelize.query(`
|
||||
DROP TRIGGER IF EXISTS trg_log_relationship_change ON falukant_data.relationship;
|
||||
CREATE TRIGGER trg_log_relationship_change
|
||||
AFTER INSERT OR UPDATE OR DELETE ON falukant_data.relationship
|
||||
FOR EACH ROW
|
||||
EXECUTE FUNCTION falukant_log.log_relationship_change();
|
||||
`);
|
||||
await sequelize.query(`
|
||||
DROP TRIGGER IF EXISTS trg_log_relationship_change ON falukant_data.marriage_proposals;
|
||||
CREATE TRIGGER trg_log_relationship_change
|
||||
AFTER INSERT OR UPDATE OR DELETE ON falukant_data.marriage_proposals
|
||||
FOR EACH ROW
|
||||
EXECUTE FUNCTION falukant_log.log_relationship_change();
|
||||
`);
|
||||
console.log("✅ relationship_change_log und Trigger sind vorhanden.");
|
||||
} catch (e) {
|
||||
console.warn('⚠️ relationship_change_log/Trigger konnten nicht sichergestellt werden:', e?.message || e);
|
||||
}
|
||||
|
||||
// Vorab: Stelle kritische Spalten sicher, damit Index-Erstellung nicht fehlschlägt
|
||||
console.log("Pre-ensure Taxi columns (traffic_light) ...");
|
||||
try {
|
||||
|
||||
Reference in New Issue
Block a user