Files
Mieterportal/server/src/seed.js
T

174 lines
6.8 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/** Idempotenter Seed: füllt die Datenbank beim ersten Start mit den
* Demo-Daten (50 Wohnungen, 552 Buchungen, Tickets, Dokumente, Threads,
* Ankündigungen, Demo-Benutzer, Registrierungscode). Läuft nur, wenn die
* users-Tabelle leer ist – bestehende Daten werden nie überschrieben.
*/
const { pool } = require('./db')
const { users, registrationCodes, tickets, documents, threads, announcements, meters, buildings, kosten } = require('./seed-data')
const generated = require('../seed/generated.json')
async function seed() {
const { rows } = await pool.query('SELECT COUNT(*)::int AS n FROM users')
if (rows[0].n > 0) return false
const client = await pool.connect()
try {
await client.query('BEGIN')
for (const u of generated.units) {
await client.query(
`INSERT INTO units (id, building, number, floor, size, cold_rent, warm_rent, tenant, status)
VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9)`,
[u.id, u.building, u.number, u.floor, u.size, u.coldRent, u.warmRent, u.tenant, u.status],
)
}
for (const t of generated.transactions) {
await client.query(
`INSERT INTO transactions (id, unit_id, tenant, month, year, amount, type, status, paid_at)
VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9)`,
[t.id, t.unitId, t.tenant, t.month, t.year, t.amount, t.type, t.status, t.paidAt ?? null],
)
}
// Mieter-Namen in Tickets/Threads aus der units-Tabelle nachziehen
const { rows: unitRows } = await client.query('SELECT id, tenant FROM units')
const mieterVon = Object.fromEntries(unitRows.map((u) => [u.id, u.tenant]))
for (const t of tickets) {
await client.query(
`INSERT INTO tickets (id, unit_id, tenant, title, description, category, priority, status, created_at)
VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9)`,
[t.id, t.unit_id, mieterVon[t.unit_id] ?? t.tenant, t.title, t.description, t.category, t.priority, t.status, t.created_at],
)
}
for (const d of documents) {
await client.query(
`INSERT INTO documents (id, unit_id, title, category, size, date) VALUES ($1,$2,$3,$4,$5,$6)`,
[d.id, d.unit_id, d.title, d.category, d.size, d.date],
)
}
for (const th of threads) {
await client.query(
`INSERT INTO threads (id, unit_id, tenant, subject, unread_by_admin, unread_by_tenant)
VALUES ($1,$2,$3,$4,$5,$6)`,
[th.id, th.unit_id, mieterVon[th.unit_id] ?? th.tenant, th.subject, th.unread_by_admin, th.unread_by_tenant],
)
for (const m of th.messages) {
await client.query(
`INSERT INTO messages (id, thread_id, from_role, author, text, at) VALUES ($1,$2,$3,$4,$5,$6)`,
[m.id, th.id, m.from_role, m.author, m.text, m.at],
)
}
}
for (const a of announcements) {
await client.query(
`INSERT INTO announcements (id, title, text, date, tag) VALUES ($1,$2,$3,$4,$5)`,
[a.id, a.title, a.text, a.date, a.tag],
)
}
for (const b of users) {
await client.query(
`INSERT INTO users (id, benutzername, name, passwort_hash, rolle, email, einheit_id, aktiv, erstellt_am, letzter_login)
VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10)`,
[b.id, b.benutzername, b.name, b.passwort_hash, b.rolle, b.email, b.einheit_id, b.aktiv, b.erstellt_am, b.letzter_login ?? null],
)
}
for (const c of registrationCodes) {
await client.query(
`INSERT INTO registration_codes (code, einheit_id, erstellt_am, verwendet_am) VALUES ($1,$2,$3,$4)`,
[c.code, c.einheit_id, c.erstellt_am, c.verwendet_am],
)
}
for (const z of meters) {
await client.query(
`INSERT INTO meters (id, unit_id, building, nummer, art, stand, stand_am, geaendert_am)
VALUES ($1,$2,$3,$4,$5,$6,$7,$8)`,
[z.id, z.unit_id, z.building, z.nummer, z.art, z.stand, z.stand_am, z.geaendert_am],
)
}
await client.query('COMMIT')
return true
} catch (e) {
await client.query('ROLLBACK')
throw e
} finally {
client.release()
}
}
module.exports = { seed }
/** Der Demo-Bestand (Einheit hs-7) muss existieren, sonst gehören die
* Demo-Nachseeds (Zähler/Häuser/Kosten) nicht in diese Datenbank – z. B. nach
* dem Live-Import (v1.21) darf nichts mehr nachgeseedet werden. */
async function demoBestandVorhanden() {
const { rows } = await pool.query(`SELECT 1 FROM units WHERE id = 'hs-7'`)
return rows.length > 0
}
/** Zähler-Demo-Daten: idempotent – läuft bei jedem Start und füllt die
* Zähler-Tabelle nur, wenn sie leer ist (auch nachträglich auf bestehenden
* Datenbanken, z. B. nach dem v1.9-Update). */
async function seedeZaehler() {
const { rows } = await pool.query('SELECT COUNT(*)::int AS n FROM meters')
if (rows[0].n > 0 || !(await demoBestandVorhanden())) return false
for (const z of meters) {
await pool.query(
`INSERT INTO meters (id, unit_id, building, nummer, art, stand, stand_am, geaendert_am)
VALUES ($1,$2,$3,$4,$5,$6,$7,$8)`,
[z.id, z.unit_id, z.building, z.nummer, z.art, z.stand, z.stand_am, z.geaendert_am],
)
}
return true
}
module.exports = { seed, seedeZaehler }
/** Haus-Demo-Daten: idempotent – füllt die buildings-Tabelle nur, wenn sie
* leer ist (auch nachträglich auf bestehenden Datenbanken, z. B. v1.10). */
async function seedeHaeuser() {
const { rows } = await pool.query('SELECT COUNT(*)::int AS n FROM buildings')
if (rows[0].n > 0 || !(await demoBestandVorhanden())) return false
for (const h of buildings) {
const teile = String(h.adresse).trim().split(/\s+/)
const hausnummer = teile.length > 1 ? teile.pop() : ''
const strasse = teile.join(' ')
await pool.query(
`INSERT INTO buildings (name, adresse, strasse, hausnummer, plz, ort, lage,
baujahr, stockwerke, etagenhoehe, wohneinheiten, quadratmeter, wohnflaeche)
VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13)`,
[h.name, h.adresse, strasse, hausnummer, '', '', '',
h.baujahr, h.stockwerke, h.etagenhoehe, h.wohneinheiten, h.quadratmeter, h.quadratmeter],
)
}
return true
}
module.exports = { seed, seedeZaehler, seedeHaeuser }
/** Kosten-Demo-Daten: idempotent – füllt die costs-Tabelle nur, wenn sie
* leer ist (auch nachträglich auf bestehenden Datenbanken, z. B. v1.14). */
async function seedeKosten() {
const { rows } = await pool.query('SELECT COUNT(*)::int AS n FROM costs')
if (rows[0].n > 0 || !(await demoBestandVorhanden())) return false
for (const k of kosten) {
await pool.query(
`INSERT INTO costs (id, building, unit_id, jahr, kostenart, betrag, umlegbar, notiz, erfasst_am)
VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9)`,
[k.id, k.building, k.unit_id, k.jahr, k.kostenart, k.betrag, k.umlegbar, k.notiz, k.erfasst_am],
)
}
return true
}
module.exports = { seed, seedeZaehler, seedeHaeuser, seedeKosten }