refactor external orders

This commit is contained in:
Matthias Hochmeister
2026-03-25 14:26:41 +01:00
parent 561334791b
commit 5add6590e5
10 changed files with 740 additions and 259 deletions

View File

@@ -21,6 +21,40 @@ class BestellungController {
}
}
async getVendor(req: Request, res: Response): Promise<void> {
const id = parseInt(param(req, 'id'), 10);
if (isNaN(id)) {
res.status(400).json({ success: false, message: 'Ungültige ID' });
return;
}
try {
const vendor = await bestellungService.getVendorById(id);
if (!vendor) {
res.status(404).json({ success: false, message: 'Lieferant nicht gefunden' });
return;
}
res.status(200).json({ success: true, data: vendor });
} catch (error) {
logger.error('BestellungController.getVendor error', { error });
res.status(500).json({ success: false, message: 'Lieferant konnte nicht geladen werden' });
}
}
async getVendorOrders(req: Request, res: Response): Promise<void> {
const id = parseInt(param(req, 'id'), 10);
if (isNaN(id)) {
res.status(400).json({ success: false, message: 'Ungültige ID' });
return;
}
try {
const orders = await bestellungService.getOrders({ lieferant_id: id });
res.status(200).json({ success: true, data: orders });
} catch (error) {
logger.error('BestellungController.getVendorOrders error', { error });
res.status(500).json({ success: false, message: 'Bestellungen konnten nicht geladen werden' });
}
}
async createVendor(req: Request, res: Response): Promise<void> {
const { name } = req.body;
if (!name || typeof name !== 'string' || name.trim().length === 0) {

View File

@@ -0,0 +1,14 @@
-- Add laufende_nummer (sequential number per year) to bestellungen
ALTER TABLE bestellungen ADD COLUMN laufende_nummer INTEGER;
-- Backfill existing rows with sequential numbers per year
WITH numbered AS (
SELECT id, ROW_NUMBER() OVER (
PARTITION BY EXTRACT(YEAR FROM erstellt_am) ORDER BY erstellt_am, id
) AS nr
FROM bestellungen
)
UPDATE bestellungen b SET laufende_nummer = n.nr FROM numbered n WHERE b.id = n.id;
-- Make NOT NULL after backfill
ALTER TABLE bestellungen ALTER COLUMN laufende_nummer SET NOT NULL;

View File

@@ -17,6 +17,20 @@ router.get(
bestellungController.listVendors.bind(bestellungController)
);
router.get(
'/vendors/:id',
authenticate,
requirePermission('bestellungen:view'),
bestellungController.getVendor.bind(bestellungController)
);
router.get(
'/vendors/:id/orders',
authenticate,
requirePermission('bestellungen:view'),
bestellungController.getVendorOrders.bind(bestellungController)
);
router.post(
'/vendors',
authenticate,

View File

@@ -119,13 +119,17 @@ async function getOrders(filters?: { status?: string; lieferant_id?: number; bes
l.name AS lieferant_name,
COALESCE(u.name, u.preferred_username, u.email) AS besteller_name,
COALESCE(pos.total_cost, 0) AS total_cost,
COALESCE(pos.items_count, 0) AS items_count
COALESCE(pos.items_count, 0) AS items_count,
COALESCE(pos.total_received, 0) AS total_received,
COALESCE(pos.total_ordered, 0) AS total_ordered
FROM bestellungen b
LEFT JOIN lieferanten l ON l.id = b.lieferant_id
LEFT JOIN users u ON u.id = b.erstellt_von
LEFT JOIN LATERAL (
SELECT SUM(einzelpreis * menge) AS total_cost,
COUNT(*) AS items_count
COUNT(*) AS items_count,
SUM(erhalten_menge) AS total_received,
SUM(menge) AS total_ordered
FROM bestellpositionen
WHERE bestellung_id = b.id
) pos ON true
@@ -178,12 +182,21 @@ async function createOrder(data: { bezeichnung: string; lieferant_id?: number; b
const client = await pool.connect();
try {
await client.query('BEGIN');
// Get next laufende_nummer for the current year
const nrResult = await client.query(
`SELECT COALESCE(MAX(laufende_nummer), 0) + 1 AS next_nr
FROM bestellungen
WHERE EXTRACT(YEAR FROM erstellt_am) = EXTRACT(YEAR FROM NOW())`
);
const laufendeNummer = nrResult.rows[0].next_nr;
const bestellerId = data.besteller_id && data.besteller_id.trim() ? data.besteller_id.trim() : null;
const result = await client.query(
`INSERT INTO bestellungen (bezeichnung, lieferant_id, besteller_id, notizen, budget, steuersatz, erstellt_von)
VALUES ($1, $2, $3, $4, $5, $6, $7)
`INSERT INTO bestellungen (bezeichnung, lieferant_id, besteller_id, notizen, budget, steuersatz, laufende_nummer, erstellt_von)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8)
RETURNING *`,
[data.bezeichnung, data.lieferant_id || null, bestellerId, data.notizen || null, data.budget || null, data.steuersatz ?? 20, userId]
[data.bezeichnung, data.lieferant_id || null, bestellerId, data.notizen || null, data.budget || null, data.steuersatz ?? 20, laufendeNummer, userId]
);
const order = result.rows[0];