diff --git a/backend/services/falukantService.js b/backend/services/falukantService.js index 031453d..90f64b4 100644 --- a/backend/services/falukantService.js +++ b/backend/services/falukantService.js @@ -5930,8 +5930,10 @@ async function enrichNotificationsWithCharacterNames(notifications) { if (!Array.isArray(notifications) || notifications.length === 0) return; const charIds = new Set(); + const firstNameIds = new Set(); + const lastNameIds = new Set(); - // recursive collector that extracts any character id fields + // recursive collector that extracts any character id fields and name IDs function collectIds(obj) { if (!obj) return; if (Array.isArray(obj)) { @@ -5945,6 +5947,15 @@ async function enrichNotificationsWithCharacterNames(notifications) { charIds.add(Number(v)); continue; } + // Sammle first_name und last_name IDs + if (k === 'character_first_name' && !isNaN(Number(v))) { + firstNameIds.add(Number(v)); + continue; + } + if (k === 'character_last_name' && !isNaN(Number(v))) { + lastNameIds.add(Number(v)); + continue; + } if (k === 'character' && typeof v === 'object') { if (v.id) charIds.add(Number(v.id)); if (v.character_id) charIds.add(Number(v.character_id)); @@ -5982,18 +5993,29 @@ async function enrichNotificationsWithCharacterNames(notifications) { if (n.characterId) charIds.add(Number(n.characterId)); } + // Batch load first names and last names + const [firstNames, lastNames] = await Promise.all([ + firstNameIds.size > 0 + ? FalukantPredefineFirstname.findAll({ where: { id: { [Op.in]: Array.from(firstNameIds) } }, attributes: ['id', 'name'] }) + : [], + lastNameIds.size > 0 + ? FalukantPredefineLastname.findAll({ where: { id: { [Op.in]: Array.from(lastNameIds) } }, attributes: ['id', 'name'] }) + : [] + ]); + const firstNameMap = new Map(firstNames.map(fn => [fn.id, fn.name])); + const lastNameMap = new Map(lastNames.map(ln => [ln.id, ln.name])); + const ids = Array.from(charIds).filter(Boolean); - if (!ids.length) return; // Batch load characters and their display names - const characters = await FalukantCharacter.findAll({ + const characters = ids.length > 0 ? await FalukantCharacter.findAll({ where: { id: { [Op.in]: ids } }, include: [ { model: FalukantPredefineFirstname, as: 'definedFirstName', attributes: ['name'] }, { model: FalukantPredefineLastname, as: 'definedLastName', attributes: ['name'] } ], attributes: ['id'] - }); + }) : []; const nameMap = new Map(); for (const c of characters) { @@ -6028,13 +6050,31 @@ async function enrichNotificationsWithCharacterNames(notifications) { return null; } + // Helper: resolve name IDs in an object and build characterName + function resolveNameFromObject(obj) { + if (!obj || typeof obj !== 'object') return null; + const firstNameId = obj.character_first_name; + const lastNameId = obj.character_last_name; + if (firstNameId || lastNameId) { + const first = firstNameMap.get(Number(firstNameId)) || ''; + const last = lastNameMap.get(Number(lastNameId)) || ''; + const name = `${first} ${last}`.trim(); + if (name) return name; + } + return null; + } + // Attach resolved name to notifications (set both characterName and character_name) for (const n of notifications) { let foundId = null; + let resolvedName = null; + try { if (typeof n.tr === 'string' && n.tr.trim().startsWith('{')) { const parsed = JSON.parse(n.tr); foundId = findFirstId(parsed) || foundId; + // Versuche Namen aus first_name/last_name IDs aufzulösen + resolvedName = resolveNameFromObject(parsed.value || parsed) || resolvedName; } } catch (err) { /* ignore */ } @@ -6045,13 +6085,25 @@ async function enrichNotificationsWithCharacterNames(notifications) { eff = JSON.parse(eff); } foundId = findFirstId(eff) || foundId; + // Auch in effects nach Namen suchen + if (Array.isArray(eff)) { + for (const e of eff) { + resolvedName = resolveNameFromObject(e) || resolvedName; + } + } else { + resolvedName = resolveNameFromObject(eff) || resolvedName; + } } } catch (err) { /* ignore */ } if (!foundId && n.character_id) foundId = Number(n.character_id); if (!foundId && n.characterId) foundId = Number(n.characterId); - if (foundId && nameMap.has(Number(foundId))) { + // Priorität: aufgelöster Name aus IDs > Name aus character_id > Fallback + if (resolvedName) { + n.characterName = resolvedName; + n.character_name = resolvedName; + } else if (foundId && nameMap.has(Number(foundId))) { const resolved = nameMap.get(Number(foundId)); n.characterName = resolved; n.character_name = resolved;