feat: 3D-Statistik Gewinn-Sektion + Status-Badges im zugeklappten Zustand

This commit is contained in:
2026-06-16 14:48:09 +02:00
parent 6f51302700
commit 30ecc89ba6
2 changed files with 98 additions and 16 deletions

View File

@@ -133,7 +133,38 @@ router.get('/stats', authenticate, (req, res) => {
byStatus[r.status] = r.c;
}
res.json({ totalOrders, bezahltOrders, totalRevenue, offeneRevenue, ordersThisMonth, totalCalcs, byStatus });
// Grundkosten berechnen (preis_freundschaft = Selbstkosten pro Stück aus Kalkulation)
function getBaseCost(orderId) {
const items = db.prepare(`
SELECT oi.stueckzahl, oi.custom_price,
COALESCE(c.preis_freundschaft, oi.preis_freundschaft) as basis
FROM order_items oi
LEFT JOIN calculations c ON c.id = oi.calculation_id
WHERE oi.order_id = ?
`).all(orderId);
return items.reduce((sum, i) => sum + (i.basis * i.stueckzahl), 0);
}
function getRevenue(order) {
if (order.custom_price != null) return parseFloat(order.custom_price);
return db.prepare('SELECT COALESCE(SUM(custom_price*stueckzahl),0) s FROM order_items WHERE order_id=? AND custom_price IS NOT NULL').get(order.id).s;
}
let totalProfit = 0;
for (const o of paidOrders) {
const rev = getRevenue(o);
const cost = getBaseCost(o.id);
totalProfit += rev - cost;
}
let offeneProfit = 0;
for (const o of openOrders) {
const rev = getRevenue(o);
const cost = getBaseCost(o.id);
offeneProfit += rev - cost;
}
res.json({ totalOrders, bezahltOrders, totalRevenue, offeneRevenue, ordersThisMonth, totalCalcs, byStatus, totalProfit, offeneProfit });
});
// ── Ideen-Board ───────────────────────────────────────────────────────────────