update
This commit is contained in:
164
sync/src/db.ts
164
sync/src/db.ts
@@ -1,5 +1,11 @@
|
||||
import { Pool } from 'pg';
|
||||
import { FdiskMember, FdiskAusbildung } from './types';
|
||||
import {
|
||||
FdiskMember,
|
||||
FdiskAusbildung,
|
||||
FdiskBefoerderung,
|
||||
FdiskUntersuchung,
|
||||
FdiskFahrgenehmigung,
|
||||
} from './types';
|
||||
|
||||
function log(msg: string) {
|
||||
console.log(`[db] ${new Date().toISOString()} ${msg}`);
|
||||
@@ -63,6 +69,9 @@ export async function syncToDatabase(
|
||||
pool: Pool,
|
||||
members: FdiskMember[],
|
||||
ausbildungen: FdiskAusbildung[],
|
||||
befoerderungen: FdiskBefoerderung[],
|
||||
untersuchungen: FdiskUntersuchung[],
|
||||
fahrgenehmigungen: FdiskFahrgenehmigung[],
|
||||
force = false
|
||||
): Promise<void> {
|
||||
const client = await pool.connect();
|
||||
@@ -137,7 +146,7 @@ export async function syncToDatabase(
|
||||
);
|
||||
const cur = currentResult.rows[0];
|
||||
|
||||
// Update mitglieder_profile with FDISK data
|
||||
// Update mitglieder_profile with FDISK data (core + extended profile fields)
|
||||
const dienstgrad = mapDienstgrad(member.dienstgrad);
|
||||
|
||||
await client.query(
|
||||
@@ -147,12 +156,21 @@ export async function syncToDatabase(
|
||||
eintrittsdatum = COALESCE($3::date, eintrittsdatum),
|
||||
austrittsdatum = $4::date,
|
||||
geburtsdatum = COALESCE($5::date, geburtsdatum),
|
||||
${dienstgrad ? 'dienstgrad = $6,' : ''}
|
||||
geburtsort = COALESCE($6, geburtsort),
|
||||
geschlecht = COALESCE($7, geschlecht),
|
||||
beruf = COALESCE($8, beruf),
|
||||
wohnort = COALESCE($9, wohnort),
|
||||
plz = COALESCE($10, plz),
|
||||
${dienstgrad ? 'dienstgrad = $11,' : ''}
|
||||
updated_at = NOW()
|
||||
WHERE user_id = ${dienstgrad ? '$7' : '$6'}`,
|
||||
WHERE user_id = ${dienstgrad ? '$12' : '$11'}`,
|
||||
dienstgrad
|
||||
? [member.standesbuchNr, member.status, member.eintrittsdatum, member.abmeldedatum, member.geburtsdatum, dienstgrad, userId]
|
||||
: [member.standesbuchNr, member.status, member.eintrittsdatum, member.abmeldedatum, member.geburtsdatum, userId]
|
||||
? [member.standesbuchNr, member.status, member.eintrittsdatum, member.abmeldedatum, member.geburtsdatum,
|
||||
member.geburtsort, member.geschlecht, member.beruf, member.wohnort, member.plz,
|
||||
dienstgrad, userId]
|
||||
: [member.standesbuchNr, member.status, member.eintrittsdatum, member.abmeldedatum, member.geburtsdatum,
|
||||
member.geburtsort, member.geschlecht, member.beruf, member.wohnort, member.plz,
|
||||
userId]
|
||||
);
|
||||
|
||||
// Detect and log what changed
|
||||
@@ -195,7 +213,6 @@ export async function syncToDatabase(
|
||||
let ausbildungSkipped = 0;
|
||||
|
||||
for (const ausb of ausbildungen) {
|
||||
// Find user_id by standesbuch_nr
|
||||
const result = await client.query<{ user_id: string }>(
|
||||
`SELECT user_id FROM mitglieder_profile WHERE fdisk_standesbuch_nr = $1`,
|
||||
[ausb.standesbuchNr]
|
||||
@@ -208,7 +225,6 @@ export async function syncToDatabase(
|
||||
|
||||
const userId = result.rows[0].user_id;
|
||||
|
||||
// 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)
|
||||
@@ -227,13 +243,25 @@ export async function syncToDatabase(
|
||||
log(`New Ausbildung: ${ausb.standesbuchNr} — ${ausb.kursname}${ausb.kursDatum ? ` (${ausb.kursDatum})` : ''}`);
|
||||
ausbildungNew++;
|
||||
} else {
|
||||
log(`Updated Ausbildung: ${ausb.standesbuchNr} — ${ausb.kursname}${ausb.kursDatum ? ` (${ausb.kursDatum})` : ''}`);
|
||||
ausbildungUpdated++;
|
||||
}
|
||||
}
|
||||
|
||||
await client.query('COMMIT');
|
||||
log(`Ausbildungen: ${ausbildungNew} neu, ${ausbildungUpdated} unverändert, ${ausbildungSkipped} übersprungen`);
|
||||
|
||||
// Upsert Beförderungen
|
||||
const befoerderungStats = await syncBefoerderungen(client, befoerderungen);
|
||||
log(`Beförderungen: ${befoerderungStats.neu} neu, ${befoerderungStats.updated} unverändert, ${befoerderungStats.skipped} übersprungen`);
|
||||
|
||||
// Upsert Untersuchungen
|
||||
const untersuchungStats = await syncUntersuchungen(client, untersuchungen);
|
||||
log(`Untersuchungen: ${untersuchungStats.neu} neu, ${untersuchungStats.updated} unverändert, ${untersuchungStats.skipped} übersprungen`);
|
||||
|
||||
// Upsert Fahrgenehmigungen
|
||||
const fahrgenStats = await syncFahrgenehmigungen(client, fahrgenehmigungen);
|
||||
log(`Fahrgenehmigungen: ${fahrgenStats.neu} neu, ${fahrgenStats.updated} unverändert, ${fahrgenStats.skipped} übersprungen`);
|
||||
|
||||
await client.query('COMMIT');
|
||||
} catch (err) {
|
||||
await client.query('ROLLBACK');
|
||||
throw err;
|
||||
@@ -241,3 +269,119 @@ export async function syncToDatabase(
|
||||
client.release();
|
||||
}
|
||||
}
|
||||
|
||||
async function syncBefoerderungen(
|
||||
client: any,
|
||||
befoerderungen: FdiskBefoerderung[]
|
||||
): Promise<{ neu: number; updated: number; skipped: number }> {
|
||||
let neu = 0, updated = 0, skipped = 0;
|
||||
|
||||
for (const b of befoerderungen) {
|
||||
const result = await client.query<{ user_id: string }>(
|
||||
`SELECT user_id FROM mitglieder_profile WHERE fdisk_standesbuch_nr = $1`,
|
||||
[b.standesbuchNr]
|
||||
);
|
||||
|
||||
if (result.rows.length === 0) { skipped++; continue; }
|
||||
const userId = result.rows[0].user_id;
|
||||
|
||||
const upsertResult = await client.query<{ was_inserted: boolean }>(
|
||||
`INSERT INTO befoerderungen (user_id, datum, dienstgrad, fdisk_sync_key)
|
||||
VALUES ($1, $2::date, $3, $4)
|
||||
ON CONFLICT (user_id, fdisk_sync_key) DO UPDATE SET
|
||||
datum = EXCLUDED.datum,
|
||||
dienstgrad = EXCLUDED.dienstgrad,
|
||||
updated_at = NOW()
|
||||
RETURNING (xmax = 0) AS was_inserted`,
|
||||
[userId, b.datum, b.dienstgrad, b.syncKey]
|
||||
);
|
||||
|
||||
if (upsertResult.rows[0]?.was_inserted) {
|
||||
log(`New Beförderung: ${b.standesbuchNr} — ${b.dienstgrad}${b.datum ? ` (${b.datum})` : ''}`);
|
||||
neu++;
|
||||
} else {
|
||||
updated++;
|
||||
}
|
||||
}
|
||||
|
||||
return { neu, updated, skipped };
|
||||
}
|
||||
|
||||
async function syncUntersuchungen(
|
||||
client: any,
|
||||
untersuchungen: FdiskUntersuchung[]
|
||||
): Promise<{ neu: number; updated: number; skipped: number }> {
|
||||
let neu = 0, updated = 0, skipped = 0;
|
||||
|
||||
for (const u of untersuchungen) {
|
||||
const result = await client.query<{ user_id: string }>(
|
||||
`SELECT user_id FROM mitglieder_profile WHERE fdisk_standesbuch_nr = $1`,
|
||||
[u.standesbuchNr]
|
||||
);
|
||||
|
||||
if (result.rows.length === 0) { skipped++; continue; }
|
||||
const userId = result.rows[0].user_id;
|
||||
|
||||
const upsertResult = await client.query<{ was_inserted: boolean }>(
|
||||
`INSERT INTO untersuchungen (user_id, datum, anmerkungen, art, ergebnis, fdisk_sync_key)
|
||||
VALUES ($1, $2::date, $3, $4, $5, $6)
|
||||
ON CONFLICT (user_id, fdisk_sync_key) DO UPDATE SET
|
||||
datum = EXCLUDED.datum,
|
||||
anmerkungen = EXCLUDED.anmerkungen,
|
||||
art = EXCLUDED.art,
|
||||
ergebnis = EXCLUDED.ergebnis,
|
||||
updated_at = NOW()
|
||||
RETURNING (xmax = 0) AS was_inserted`,
|
||||
[userId, u.datum, u.anmerkungen, u.art, u.ergebnis, u.syncKey]
|
||||
);
|
||||
|
||||
if (upsertResult.rows[0]?.was_inserted) {
|
||||
log(`New Untersuchung: ${u.standesbuchNr} — [${u.art}] ${u.ergebnis ?? '—'}${u.datum ? ` (${u.datum})` : ''} | ${u.anmerkungen ?? ''}`);
|
||||
neu++;
|
||||
} else {
|
||||
updated++;
|
||||
}
|
||||
}
|
||||
|
||||
return { neu, updated, skipped };
|
||||
}
|
||||
|
||||
async function syncFahrgenehmigungen(
|
||||
client: any,
|
||||
fahrgenehmigungen: FdiskFahrgenehmigung[]
|
||||
): Promise<{ neu: number; updated: number; skipped: number }> {
|
||||
let neu = 0, updated = 0, skipped = 0;
|
||||
|
||||
for (const f of fahrgenehmigungen) {
|
||||
const result = await client.query<{ user_id: string }>(
|
||||
`SELECT user_id FROM mitglieder_profile WHERE fdisk_standesbuch_nr = $1`,
|
||||
[f.standesbuchNr]
|
||||
);
|
||||
|
||||
if (result.rows.length === 0) { skipped++; continue; }
|
||||
const userId = result.rows[0].user_id;
|
||||
|
||||
const upsertResult = await client.query<{ was_inserted: boolean }>(
|
||||
`INSERT INTO fahrgenehmigungen (user_id, ausstellungsdatum, gueltig_bis, behoerde, nummer, klasse, fdisk_sync_key)
|
||||
VALUES ($1, $2::date, $3::date, $4, $5, $6, $7)
|
||||
ON CONFLICT (user_id, fdisk_sync_key) DO UPDATE SET
|
||||
ausstellungsdatum = EXCLUDED.ausstellungsdatum,
|
||||
gueltig_bis = EXCLUDED.gueltig_bis,
|
||||
behoerde = EXCLUDED.behoerde,
|
||||
nummer = EXCLUDED.nummer,
|
||||
klasse = EXCLUDED.klasse,
|
||||
updated_at = NOW()
|
||||
RETURNING (xmax = 0) AS was_inserted`,
|
||||
[userId, f.ausstellungsdatum, f.gueltigBis, f.behoerde, f.nummer, f.klasse, f.syncKey]
|
||||
);
|
||||
|
||||
if (upsertResult.rows[0]?.was_inserted) {
|
||||
log(`New Fahrgenehmigung: ${f.standesbuchNr} — [${f.klasse}]${f.ausstellungsdatum ? ` (${f.ausstellungsdatum})` : ''}`);
|
||||
neu++;
|
||||
} else {
|
||||
updated++;
|
||||
}
|
||||
}
|
||||
|
||||
return { neu, updated, skipped };
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user