"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.syncToDatabase = syncToDatabase; function log(msg) { console.log(`[db] ${new Date().toISOString()} ${msg}`); } /** * Map FDISK Dienstgrad (abbreviation or full name) to the DB enum value. * Returns null if no match found — the field will be left unchanged. */ function mapDienstgrad(raw) { const map = { // Abbreviations 'fa': 'Feuerwehranwärter', 'fm': 'Feuerwehrmann', 'ff': 'Feuerwehrfrau', 'ofm': 'Oberfeuerwehrmann', 'off': 'Oberfeuerwehrfrau', 'hfm': 'Hauptfeuerwehrmann', 'hff': 'Hauptfeuerwehrfrau', 'lm': 'Löschmeister', 'olm': 'Oberlöschmeister', 'hlm': 'Hauptlöschmeister', 'bm': 'Brandmeister', 'obm': 'Oberbrandmeister', 'hbm': 'Hauptbrandmeister', 'bi': 'Brandinspektor', 'obi': 'Oberbrandinspektor', 'boi': 'Brandoberinspektor', 'bam': 'Brandamtmann', // Full names (pass-through if already matching) 'feuerwehranwärter': 'Feuerwehranwärter', 'feuerwehrmann': 'Feuerwehrmann', 'feuerwehrfrau': 'Feuerwehrfrau', 'oberfeuerwehrmann': 'Oberfeuerwehrmann', 'oberfeuerwehrfrau': 'Oberfeuerwehrfrau', 'hauptfeuerwehrmann': 'Hauptfeuerwehrmann', 'hauptfeuerwehrfrau': 'Hauptfeuerwehrfrau', 'löschmeister': 'Löschmeister', 'oberlöschmeister': 'Oberlöschmeister', 'hauptlöschmeister': 'Hauptlöschmeister', 'brandmeister': 'Brandmeister', 'oberbrandmeister': 'Oberbrandmeister', 'hauptbrandmeister': 'Hauptbrandmeister', 'brandinspektor': 'Brandinspektor', 'oberbrandinspektor': 'Oberbrandinspektor', 'brandoberinspektor': 'Brandoberinspektor', 'brandamtmann': 'Brandamtmann', }; return map[raw.trim().toLowerCase()] ?? null; } async function syncToDatabase(pool, members, ausbildungen) { const client = await pool.connect(); try { await client.query('BEGIN'); let updated = 0; let skipped = 0; for (const member of members) { // Find the matching mitglieder_profile by fdisk_standesbuch_nr first, // then fall back to matching by name (given_name + family_name) const profileResult = await client.query(`SELECT mp.user_id FROM mitglieder_profile mp WHERE mp.fdisk_standesbuch_nr = $1`, [member.standesbuchNr]); let userId = null; if (profileResult.rows.length > 0) { userId = profileResult.rows[0].user_id; } else { // Fallback: match by name (case-insensitive) const nameResult = await client.query(`SELECT u.id FROM users u JOIN mitglieder_profile mp ON mp.user_id = u.id WHERE LOWER(u.given_name) = LOWER($1) AND LOWER(u.family_name) = LOWER($2) LIMIT 1`, [member.vorname, member.zuname]); if (nameResult.rows.length > 0) { userId = nameResult.rows[0].id; // Store the Standesbuch-Nr now that we found a match await client.query(`UPDATE mitglieder_profile SET fdisk_standesbuch_nr = $1 WHERE user_id = $2`, [member.standesbuchNr, userId]); log(`Linked ${member.vorname} ${member.zuname} → Standesbuch-Nr ${member.standesbuchNr}`); } } if (!userId) { skipped++; continue; } // Update mitglieder_profile with FDISK data const dienstgrad = mapDienstgrad(member.dienstgrad); await client.query(`UPDATE mitglieder_profile SET fdisk_standesbuch_nr = $1, status = $2, eintrittsdatum = COALESCE($3::date, eintrittsdatum), austrittsdatum = $4::date, geburtsdatum = COALESCE($5::date, geburtsdatum), ${dienstgrad ? 'dienstgrad = $6,' : ''} updated_at = NOW() WHERE user_id = ${dienstgrad ? '$7' : '$6'}`, dienstgrad ? [member.standesbuchNr, member.status, member.eintrittsdatum, member.abmeldedatum, member.geburtsdatum, dienstgrad, userId] : [member.standesbuchNr, member.status, member.eintrittsdatum, member.abmeldedatum, member.geburtsdatum, userId]); updated++; } log(`Members: ${updated} updated, ${skipped} skipped (no dashboard account)`); // Upsert Ausbildungen let ausbildungUpserted = 0; let ausbildungSkipped = 0; for (const ausb of ausbildungen) { // Find user_id by standesbuch_nr const result = await client.query(`SELECT user_id FROM mitglieder_profile WHERE fdisk_standesbuch_nr = $1`, [ausb.standesbuchNr]); if (result.rows.length === 0) { ausbildungSkipped++; continue; } const userId = result.rows[0].user_id; await client.query(`INSERT INTO ausbildung (user_id, kursname, kurs_datum, ablaufdatum, ort, bemerkung, fdisk_sync_key) VALUES ($1, $2, $3::date, $4::date, $5, $6, $7) ON CONFLICT (user_id, fdisk_sync_key) DO UPDATE SET kursname = EXCLUDED.kursname, kurs_datum = EXCLUDED.kurs_datum, ablaufdatum = EXCLUDED.ablaufdatum, ort = EXCLUDED.ort, bemerkung = EXCLUDED.bemerkung, updated_at = NOW()`, [userId, ausb.kursname, ausb.kursDatum, ausb.ablaufdatum, ausb.ort, ausb.bemerkung, ausb.syncKey]); ausbildungUpserted++; } await client.query('COMMIT'); log(`Ausbildungen: ${ausbildungUpserted} upserted, ${ausbildungSkipped} skipped`); } catch (err) { await client.query('ROLLBACK'); throw err; } finally { client.release(); } }