From e36de3199a06ad12ae289d19127c99c4202fffab Mon Sep 17 00:00:00 2001 From: Matthias Hochmeister Date: Fri, 13 Mar 2026 13:29:21 +0100 Subject: [PATCH] update --- sync/src/db.ts | 58 ++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 51 insertions(+), 7 deletions(-) diff --git a/sync/src/db.ts b/sync/src/db.ts index 1f454a5..3a72958 100644 --- a/sync/src/db.ts +++ b/sync/src/db.ts @@ -61,6 +61,7 @@ export async function syncToDatabase( await client.query('BEGIN'); let updated = 0; + let unchanged = 0; let skipped = 0; for (const member of members) { @@ -109,6 +110,23 @@ export async function syncToDatabase( continue; } + // Fetch current values to detect what actually changed + const currentResult = await client.query<{ + status: string; + dienstgrad: string | null; + eintrittsdatum: string | null; + austrittsdatum: string | null; + geburtsdatum: string | null; + }>( + `SELECT status, dienstgrad, + to_char(eintrittsdatum, 'YYYY-MM-DD') AS eintrittsdatum, + to_char(austrittsdatum, 'YYYY-MM-DD') AS austrittsdatum, + to_char(geburtsdatum, 'YYYY-MM-DD') AS geburtsdatum + FROM mitglieder_profile WHERE user_id = $1`, + [userId] + ); + const cur = currentResult.rows[0]; + // Update mitglieder_profile with FDISK data const dienstgrad = mapDienstgrad(member.dienstgrad); @@ -127,13 +145,32 @@ export async function syncToDatabase( : [member.standesbuchNr, member.status, member.eintrittsdatum, member.abmeldedatum, member.geburtsdatum, userId] ); - updated++; + // Detect and log what changed + const changes: string[] = []; + if (cur) { + if (cur.status !== member.status) + changes.push(`Status ${cur.status}→${member.status}`); + if (dienstgrad && cur.dienstgrad !== dienstgrad) + changes.push(`Dienstgrad ${cur.dienstgrad ?? '—'}→${dienstgrad}`); + if (member.eintrittsdatum && cur.eintrittsdatum !== member.eintrittsdatum) + changes.push(`Eintrittsdatum ${cur.eintrittsdatum ?? '—'}→${member.eintrittsdatum}`); + if (cur.austrittsdatum !== (member.abmeldedatum ?? null)) + changes.push(`Austrittsdatum ${cur.austrittsdatum ?? '—'}→${member.abmeldedatum ?? '—'}`); + } + + if (changes.length > 0) { + log(`Updated ${member.vorname} ${member.zuname} (${member.standesbuchNr}): ${changes.join(', ')}`); + updated++; + } else { + unchanged++; + } } - log(`Members: ${updated} updated, ${skipped} skipped (no dashboard account)`); + log(`Members: ${updated} changed, ${unchanged} unchanged, ${skipped} skipped (no dashboard account)`); // Upsert Ausbildungen - let ausbildungUpserted = 0; + let ausbildungNew = 0; + let ausbildungUpdated = 0; let ausbildungSkipped = 0; for (const ausb of ausbildungen) { @@ -150,7 +187,8 @@ export async function syncToDatabase( const userId = result.rows[0].user_id; - await client.query( + // xmax = 0 means a fresh INSERT (not an update of an existing row) + const upsertResult = await client.query<{ was_inserted: boolean }>( `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 @@ -159,15 +197,21 @@ export async function syncToDatabase( ablaufdatum = EXCLUDED.ablaufdatum, ort = EXCLUDED.ort, bemerkung = EXCLUDED.bemerkung, - updated_at = NOW()`, + updated_at = NOW() + RETURNING (xmax = 0) AS was_inserted`, [userId, ausb.kursname, ausb.kursDatum, ausb.ablaufdatum, ausb.ort, ausb.bemerkung, ausb.syncKey] ); - ausbildungUpserted++; + if (upsertResult.rows[0]?.was_inserted) { + log(`New Ausbildung: ${ausb.standesbuchNr} — ${ausb.kursname}${ausb.kursDatum ? ` (${ausb.kursDatum})` : ''}`); + ausbildungNew++; + } else { + ausbildungUpdated++; + } } await client.query('COMMIT'); - log(`Ausbildungen: ${ausbildungUpserted} upserted, ${ausbildungSkipped} skipped`); + log(`Ausbildungen: ${ausbildungNew} neu, ${ausbildungUpdated} unverändert, ${ausbildungSkipped} übersprungen`); } catch (err) { await client.query('ROLLBACK'); throw err;