- New nullable anbieter.default_vo_id column (migration adds it to existing DBs); deleting a VO that some provider points at clears the reference automatically. - GET /api/anbieter now includes default_vo_id + default_vo_nummer + default_vo_bezeichnung so the wizard can preselect without an extra round-trip. - New PUT /api/anbieter/:id/default-vo endpoint. Validates the VO belongs to the given provider; accepts vo_id=null to clear. - VO admin table grew a "Standard" column and an "Als Standard" / "Standard entfernen" button on each row. - When the user picks a provider in step 1 of the wizard, the VO dropdown now preselects the default VO (falling back to the only VO if there is exactly one), and immediately loads the matching tariffs. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
95 lines
4.0 KiB
JavaScript
95 lines
4.0 KiB
JavaScript
const express = require('express');
|
|
const db = require('../db');
|
|
const asyncHandler = require('../middleware/asyncHandler');
|
|
|
|
const router = express.Router();
|
|
|
|
// List all VOs (optionally filtered by anbieter via ?anbieter_id=)
|
|
router.get('/', asyncHandler(async (req, res) => {
|
|
const { anbieter_id } = req.query;
|
|
if (anbieter_id) {
|
|
const rows = await db.all(
|
|
`SELECT v.*, a.name AS anbieter_name
|
|
FROM vos v JOIN anbieter a ON v.anbieter_id = a.id
|
|
WHERE v.anbieter_id = ? AND v.aktiv = 1
|
|
ORDER BY v.nummer`,
|
|
[anbieter_id]
|
|
);
|
|
return res.json(rows);
|
|
}
|
|
const rows = await db.all(
|
|
`SELECT v.*, a.name AS anbieter_name
|
|
FROM vos v JOIN anbieter a ON v.anbieter_id = a.id
|
|
ORDER BY a.name, v.nummer`
|
|
);
|
|
res.json(rows);
|
|
}));
|
|
|
|
router.post('/', asyncHandler(async (req, res) => {
|
|
const { anbieter_id, nummer, bezeichnung } = req.body || {};
|
|
if (!anbieter_id) return res.status(400).json({ error: 'Anbieter ist erforderlich' });
|
|
if (!nummer || !String(nummer).trim()) return res.status(400).json({ error: 'VO-Nummer ist erforderlich' });
|
|
try {
|
|
const result = await db.run(
|
|
'INSERT INTO vos (anbieter_id, nummer, bezeichnung) VALUES (?, ?, ?)',
|
|
[anbieter_id, String(nummer).trim(), bezeichnung ? String(bezeichnung).trim() : null]
|
|
);
|
|
res.json({ id: result.lastID, anbieter_id, nummer: String(nummer).trim(), bezeichnung: bezeichnung || null });
|
|
} catch (err) {
|
|
if (/UNIQUE/.test(err.message)) {
|
|
return res.status(400).json({ error: 'VO mit dieser Nummer existiert bereits für diesen Anbieter' });
|
|
}
|
|
throw err;
|
|
}
|
|
}));
|
|
|
|
router.put('/:id', asyncHandler(async (req, res) => {
|
|
const { id } = req.params;
|
|
const { nummer, bezeichnung, aktiv } = req.body || {};
|
|
const current = await db.get('SELECT * FROM vos WHERE id = ?', [id]);
|
|
if (!current) return res.status(404).json({ error: 'VO nicht gefunden' });
|
|
const nextNummer = nummer !== undefined ? String(nummer).trim() : current.nummer;
|
|
if (!nextNummer) return res.status(400).json({ error: 'VO-Nummer darf nicht leer sein' });
|
|
try {
|
|
await db.run(
|
|
'UPDATE vos SET nummer = ?, bezeichnung = ?, aktiv = ? WHERE id = ?',
|
|
[
|
|
nextNummer,
|
|
bezeichnung !== undefined ? (bezeichnung ? String(bezeichnung).trim() : null) : current.bezeichnung,
|
|
aktiv !== undefined ? (aktiv ? 1 : 0) : current.aktiv,
|
|
id,
|
|
]
|
|
);
|
|
res.json({ message: 'VO erfolgreich aktualisiert' });
|
|
} catch (err) {
|
|
if (/UNIQUE/.test(err.message)) {
|
|
return res.status(400).json({ error: 'VO mit dieser Nummer existiert bereits für diesen Anbieter' });
|
|
}
|
|
throw err;
|
|
}
|
|
}));
|
|
|
|
router.delete('/:id', asyncHandler(async (req, res) => {
|
|
const { id } = req.params;
|
|
// Prevent deletion if any tariff or schaltung references it.
|
|
const used = await db.get(
|
|
`SELECT
|
|
(SELECT COUNT(*) FROM tarife WHERE vo_id = ?) AS n_tarife,
|
|
(SELECT COUNT(*) FROM schaltungen WHERE vo_id = ?) AS n_schaltungen`,
|
|
[id, id]
|
|
);
|
|
if (used.n_tarife + used.n_schaltungen > 0) {
|
|
const parts = [];
|
|
if (used.n_tarife > 0) parts.push(`${used.n_tarife} Tarif(e)`);
|
|
if (used.n_schaltungen > 0) parts.push(`${used.n_schaltungen} Schaltung(en)`);
|
|
return res.status(400).json({ error: `VO kann nicht gelöscht werden: ${parts.join(', ')} verwenden diese VO` });
|
|
}
|
|
// Clear any anbieter pointing at this VO as their default before removing it.
|
|
await db.run('UPDATE anbieter SET default_vo_id = NULL WHERE default_vo_id = ?', [id]);
|
|
const result = await db.run('DELETE FROM vos WHERE id = ?', [id]);
|
|
if (result.changes === 0) return res.status(404).json({ error: 'VO nicht gefunden' });
|
|
res.json({ message: 'VO erfolgreich gelöscht' });
|
|
}));
|
|
|
|
module.exports = router;
|