v1.12: Dokumente-CRUD fuer die Verwaltung (Mietvertraege & Co. im Dokumentenmodul)

This commit is contained in:
2026-10-04 11:58:27 +02:00
parent bedbda640b
commit 8bef23665a
5 changed files with 287 additions and 14 deletions
+64
View File
@@ -482,6 +482,70 @@ app.patch('/api/meters/:id', auth, adminOnly, async (req, res, next) => {
res.json({ meter: mapMeter(aktualisiert[0]) })
} catch (e) { next(e) }
})
// ── Dokumente (Verwaltung) ───────────────────────────────────
const DOKUMENT_KATEGORIEN = ['Mietvertrag', 'Nebenkostenabrechnung', 'Hausordnung', 'Protokoll', 'Sonstiges']
async function dokumentGueltig(b, res) {
const titel = String(b.title || '').trim()
const kategorie = String(b.category || '').trim()
if (!titel) { res.status(400).json({ fehler: 'Titel fehlt.' }); return null }
if (!DOKUMENT_KATEGORIEN.includes(kategorie)) { res.status(400).json({ fehler: 'Ungültige Kategorie.' }); return null }
let einheitId = b.unitId !== undefined ? (b.unitId || null) : undefined
if (einheitId) {
const { rows: u } = await pool.query('SELECT id FROM units WHERE id = $1', [einheitId])
if (!u.length) { res.status(400).json({ fehler: 'Wohnung unbekannt.' }); return null }
}
return { titel, kategorie, einheitId }
}
app.post('/api/documents', auth, adminOnly, async (req, res, next) => {
try {
const g = await dokumentGueltig(req.body || {}, res)
if (!g) return
const { rows } = await pool.query(
`INSERT INTO documents (id, unit_id, title, category, size, date)
VALUES ($1,$2,$3,$4,$5,$6) RETURNING *`,
[`d-${Date.now()}`, g.einheitId ?? null, g.titel, g.kategorie,
String(req.body.size || '').trim() || '–', String(req.body.date || '').trim() || deutschesDatum()],
)
res.json({ dokument: mapDocument(rows[0]) })
} catch (e) { next(e) }
})
app.patch('/api/documents/:id', auth, adminOnly, async (req, res, next) => {
try {
const { rows } = await pool.query('SELECT * FROM documents WHERE id = $1', [req.params.id])
if (!rows.length) return res.status(404).json({ fehler: 'Dokument nicht gefunden.' })
const d = rows[0]
const b = req.body || {}
const kandidat = {
title: b.title !== undefined ? b.title : d.title,
category: b.category !== undefined ? b.category : d.category,
unitId: b.unitId !== undefined ? b.unitId : d.unit_id,
}
const g = await dokumentGueltig(kandidat, res)
if (!g) return
const einheitId = g.einheitId === undefined ? d.unit_id : g.einheitId
const { rows: aktualisiert } = await pool.query(
`UPDATE documents SET unit_id = $1, title = $2, category = $3, size = $4, date = $5
WHERE id = $6 RETURNING *`,
[einheitId, g.titel, g.kategorie,
b.size !== undefined ? (String(b.size).trim() || '–') : d.size,
b.date !== undefined ? (String(b.date).trim() || d.date) : d.date,
req.params.id],
)
res.json({ dokument: mapDocument(aktualisiert[0]) })
} catch (e) { next(e) }
})
app.delete('/api/documents/:id', auth, adminOnly, async (req, res, next) => {
try {
const { rowCount } = await pool.query('DELETE FROM documents WHERE id = $1', [req.params.id])
if (!rowCount) return res.status(404).json({ fehler: 'Dokument nicht gefunden.' })
res.json({ ok: true })
} catch (e) { next(e) }
})
// ── Bestand: Häuser & Wohnungen (Verwaltung) ────────────────
function pruefeHaus(b) {
const fehler = []