fix: Nettogewinn-Linie zieht Materialkosten ab, Bestellungen nach Status gruppiert mit Summen
This commit is contained in:
@@ -106,39 +106,71 @@ function OrdersInPeriod({ period, custom }) {
|
|||||||
api(`/tools/statistik/month-orders${q}`).then(setOrders).catch(()=>setOrders([]));
|
api(`/tools/statistik/month-orders${q}`).then(setOrders).catch(()=>setOrders([]));
|
||||||
}, [period, custom]);
|
}, [period, custom]);
|
||||||
|
|
||||||
const statusColor = { warteliste:'#ffe66d', in_arbeit:'#4ecdc4', fertig:'#6bcb77' };
|
const STATUS_ORDER = ['warteliste','in_arbeit','fertig','bezahlt','abgeschlossen'];
|
||||||
|
const STATUS_COLOR = { warteliste:'#ffe66d', in_arbeit:'#4ecdc4', fertig:'#6bcb77', bezahlt:'#c084fc', abgeschlossen:'#4ade80' };
|
||||||
|
const STATUS_LABEL = { warteliste:'Warteliste', in_arbeit:'In Arbeit', fertig:'Fertig', bezahlt:'Bezahlt', abgeschlossen:'Abgeschlossen' };
|
||||||
|
|
||||||
const periodLabel = period==='week'?'DIESER WOCHE':period==='month'?'DIESEM MONAT':period==='year'?'DIESEM JAHR':period==='all'?'GESAMT':'IM ZEITRAUM';
|
const periodLabel = period==='week'?'DIESER WOCHE':period==='month'?'DIESEM MONAT':period==='year'?'DIESEM JAHR':period==='all'?'GESAMT':'IM ZEITRAUM';
|
||||||
|
|
||||||
|
// Gruppieren nach Status
|
||||||
|
const grouped = {};
|
||||||
|
(orders||[]).forEach(o => {
|
||||||
|
const st = !!o.bezahlt && !!o.abgeholt ? 'abgeschlossen' : !!o.bezahlt ? 'bezahlt' : o.status;
|
||||||
|
if (!grouped[st]) grouped[st] = [];
|
||||||
|
grouped[st].push({ ...o, _st: st });
|
||||||
|
});
|
||||||
|
|
||||||
|
// Innerhalb jeder Gruppe nach Datum sortieren (neueste zuerst)
|
||||||
|
Object.values(grouped).forEach(g => g.sort((a,b) => new Date(b.created_at) - new Date(a.created_at)));
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div style={S.card}>
|
<div style={S.card}>
|
||||||
<div style={S.head}>
|
<div style={S.head}>BESTELLUNGEN {periodLabel} {orders ? `(${orders.length})` : ''}</div>
|
||||||
BESTELLUNGEN {periodLabel} {orders ? `(${orders.length})` : ''}
|
|
||||||
</div>
|
|
||||||
{!orders
|
{!orders
|
||||||
? <div style={{color:'rgba(255,255,255,0.3)',fontFamily:'monospace',fontSize:12}}>Lädt…</div>
|
? <div style={{color:'rgba(255,255,255,0.3)',fontFamily:'monospace',fontSize:12}}>Lädt…</div>
|
||||||
: !orders.length
|
: !orders.length
|
||||||
? <div style={{color:'rgba(255,255,255,0.3)',fontFamily:'monospace',fontSize:12}}>Keine Bestellungen diesen Monat.</div>
|
? <div style={{color:'rgba(255,255,255,0.3)',fontFamily:'monospace',fontSize:12}}>Keine Bestellungen im Zeitraum.</div>
|
||||||
: orders.map(o => {
|
: STATUS_ORDER.filter(st => grouped[st]?.length).map(st => {
|
||||||
const st = !!o.bezahlt && !!o.abgeholt ? 'abgeschlossen' : !!o.bezahlt ? 'bezahlt' : o.status;
|
const col = STATUS_COLOR[st];
|
||||||
const col = st==='abgeschlossen'?'#4ade80': st==='bezahlt'?'#c084fc': statusColor[st]||'#888';
|
const group = grouped[st];
|
||||||
|
const total = group.reduce((s,o)=>s+(o.revenue||0),0);
|
||||||
return (
|
return (
|
||||||
<div key={o.id} style={{display:'flex',alignItems:'center',gap:10,padding:'8px 0',
|
<div key={st} style={{marginBottom:16}}>
|
||||||
borderBottom:'1px solid rgba(255,255,255,0.05)',flexWrap:'wrap'}}>
|
{/* Status-Header mit Summe */}
|
||||||
<span style={{color:'rgba(255,255,255,0.3)',fontFamily:'monospace',fontSize:10,flexShrink:0}}>
|
<div style={{display:'flex',alignItems:'center',justifyContent:'space-between',
|
||||||
{new Date(o.created_at).toLocaleDateString('de-DE')}
|
padding:'6px 10px',background:`${col}10`,borderRadius:8,marginBottom:6}}>
|
||||||
|
<div style={{display:'flex',alignItems:'center',gap:8}}>
|
||||||
|
<span style={{background:`${col}20`,border:`1px solid ${col}44`,borderRadius:10,
|
||||||
|
padding:'2px 10px',color:col,fontFamily:'monospace',fontSize:10}}>
|
||||||
|
{STATUS_LABEL[st]}
|
||||||
|
</span>
|
||||||
|
<span style={{color:'rgba(255,255,255,0.35)',fontFamily:'monospace',fontSize:10}}>
|
||||||
|
{group.length} Bestellung{group.length!==1?'en':''}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
{total > 0 && (
|
||||||
|
<span style={{color:col,fontFamily:"'Space Mono',monospace",fontSize:12,fontWeight:700}}>
|
||||||
|
Σ {fmt(total)}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
{/* Einträge */}
|
||||||
|
{group.map(o => (
|
||||||
|
<div key={o.id} style={{display:'flex',alignItems:'center',gap:10,padding:'7px 10px',
|
||||||
|
borderBottom:'1px solid rgba(255,255,255,0.04)'}}>
|
||||||
|
<span style={{color:'rgba(255,255,255,0.3)',fontFamily:'monospace',fontSize:10,flexShrink:0,width:60}}>
|
||||||
|
{new Date(o.created_at).toLocaleDateString('de-DE',{day:'2-digit',month:'2-digit'})}
|
||||||
</span>
|
</span>
|
||||||
<span style={{color:'rgba(255,255,255,0.8)',fontFamily:'monospace',fontSize:12,flex:1}}>
|
<span style={{color:'rgba(255,255,255,0.8)',fontFamily:'monospace',fontSize:12,flex:1}}>
|
||||||
{o.name}
|
{o.name}
|
||||||
</span>
|
</span>
|
||||||
<span style={{background:`${col}18`,border:`1px solid ${col}44`,borderRadius:6,
|
<span style={{color:o.revenue>0?'#4ade80':'rgba(255,255,255,0.25)',
|
||||||
padding:'2px 8px',color:col,fontFamily:'monospace',fontSize:9,flexShrink:0}}>
|
|
||||||
{st}
|
|
||||||
</span>
|
|
||||||
<span style={{color:o.revenue>0?'#4ade80':'rgba(255,255,255,0.3)',
|
|
||||||
fontFamily:"'Space Mono',monospace",fontSize:12,fontWeight:700,flexShrink:0}}>
|
fontFamily:"'Space Mono',monospace",fontSize:12,fontWeight:700,flexShrink:0}}>
|
||||||
{fmt(o.revenue||0)}
|
{fmt(o.revenue||0)}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
);
|
);
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user