/* ===================================================================== routes/verwaltung.js — GET /api/verwaltung/orders (Liste) + PATCH /api/verwaltung/orders/:id (Status/Tracking ändern). 1:1 portiert aus functions/api/verwaltung/orders.js + functions/api/verwaltung/orders/[id].js. Prüft zusätzlich zur gate-Middleware (siehe middleware/gate.js) hier nochmal eigenständig beide Schranken — Verteidigung in der Tiefe. ===================================================================== */ import { Router } from "express"; import { getGateRole, unauthorizedJson } from "../lib/auth.js"; import { hatGueltigeVerwaltungSitzung } from "../lib/verwaltung-auth.js"; import { db } from "../db.js"; export const verwaltungRouter = Router(); const ERLAUBTE_STATUS = ["zahlungOffen", "bezahlt", "bearbeitung", "versandVorbereitet", "versendet", "abgeschlossen", "storniert"]; async function pruefeSchranken(req, res) { const role = await getGateRole(req); if (!role) { unauthorizedJson(res); return false; } if (!(await hatGueltigeVerwaltungSitzung(req))) { res.status(401).json({ ok: false, error: "Zusätzlicher Verwaltungs-Code erforderlich." }); return false; } return true; } verwaltungRouter.get("/api/verwaltung/orders", async (req, res) => { if (!(await pruefeSchranken(req, res))) return; try { const orders = db.prepare(`SELECT * FROM orders ORDER BY created_at DESC`).all(); if (orders.length === 0) return res.json({ ok: true, orders: [] }); const ids = orders.map((o) => o.id); const placeholders = ids.map(() => "?").join(","); const items = db.prepare(`SELECT * FROM order_items WHERE order_id IN (${placeholders}) ORDER BY id ASC`).all(...ids); const itemsByOrder = new Map(); items.forEach((item) => { const liste = itemsByOrder.get(item.order_id) ?? []; liste.push(item); itemsByOrder.set(item.order_id, liste); }); const result = orders.map((o) => ({ ...o, artikel: itemsByOrder.get(o.id) ?? [] })); return res.json({ ok: true, orders: result }); } catch (err) { return res.status(500).json({ ok: false, error: "Bestellungen konnten nicht geladen werden." }); } }); verwaltungRouter.patch("/api/verwaltung/orders/:id", async (req, res) => { if (!(await pruefeSchranken(req, res))) return; const id = Number(req.params.id); if (!Number.isInteger(id) || id <= 0) { return res.status(400).json({ ok: false, error: "Ungültige Bestell-ID." }); } const body = req.body || {}; const updates = []; const values = []; if (body.status !== undefined) { if (!ERLAUBTE_STATUS.includes(body.status)) { return res.status(400).json({ ok: false, error: "Ungültiger Status." }); } updates.push("status = ?"); values.push(body.status); } if (body.tracking !== undefined) { updates.push("tracking = ?"); values.push(String(body.tracking || "")); } if (updates.length === 0) { return res.status(400).json({ ok: false, error: "Nichts zu ändern übergeben." }); } updates.push("updated_at = ?"); values.push(new Date().toISOString()); values.push(id); try { const result = db.prepare(`UPDATE orders SET ${updates.join(", ")} WHERE id = ?`).run(...values); if (result.changes === 0) { return res.status(404).json({ ok: false, error: "Bestellung nicht gefunden." }); } return res.json({ ok: true }); } catch (err) { return res.status(500).json({ ok: false, error: "Bestellung konnte nicht aktualisiert werden." }); } });