diff --git a/backend/src/db.js b/backend/src/db.js index 202a012..56075bc 100644 --- a/backend/src/db.js +++ b/backend/src/db.js @@ -155,6 +155,8 @@ if (!cols.includes('bemerkung')) db.exec("ALTER TABLE calculations ADD COLUMN be const ordCols = db.prepare("PRAGMA table_info(orders)").all().map(r => r.name); if (!ordCols.includes('bezahlt')) db.exec("ALTER TABLE orders ADD COLUMN bezahlt INTEGER NOT NULL DEFAULT 0"); if (!ordCols.includes('bezahlt_am')) db.exec("ALTER TABLE orders ADD COLUMN bezahlt_am DATETIME"); +if (!ordCols.includes('abgeholt')) db.exec("ALTER TABLE orders ADD COLUMN abgeholt INTEGER NOT NULL DEFAULT 0"); +if (!ordCols.includes('abgeholt_am'))db.exec("ALTER TABLE orders ADD COLUMN abgeholt_am DATETIME"); // Migrationen order_items // files migrations diff --git a/backend/src/tools/bestellungen/routes.js b/backend/src/tools/bestellungen/routes.js index 9c4ddb3..7f4e290 100644 --- a/backend/src/tools/bestellungen/routes.js +++ b/backend/src/tools/bestellungen/routes.js @@ -77,8 +77,16 @@ router.put('/:id', authenticate, (req, res) => { bezahlt_am = req.body.bezahlt ? new Date().toISOString() : null; } - db.prepare('UPDATE orders SET name=?,bemerkung=?,status=?,custom_price=?,bezahlt=?,bezahlt_am=?,updated_at=CURRENT_TIMESTAMP WHERE id=? AND user_id=?') - .run(name, bemerkung, status, custom_price, bezahlt, bezahlt_am, req.params.id, uid(req)); + // Abgeholt-Status mit Datum + let abgeholt = ex.abgeholt; + let abgeholt_am = ex.abgeholt_am; + if (req.body.abgeholt !== undefined) { + abgeholt = req.body.abgeholt ? 1 : 0; + abgeholt_am = req.body.abgeholt ? new Date().toISOString() : null; + } + + db.prepare('UPDATE orders SET name=?,bemerkung=?,status=?,custom_price=?,bezahlt=?,bezahlt_am=?,abgeholt=?,abgeholt_am=?,updated_at=CURRENT_TIMESTAMP WHERE id=? AND user_id=?') + .run(name, bemerkung, status, custom_price, bezahlt, bezahlt_am, abgeholt, abgeholt_am, req.params.id, uid(req)); res.json(loadOrder(req.params.id, uid(req))); }); diff --git a/frontend/src/tools/bestellungen.jsx b/frontend/src/tools/bestellungen.jsx index 8b3fe7e..e64c4be 100644 --- a/frontend/src/tools/bestellungen.jsx +++ b/frontend/src/tools/bestellungen.jsx @@ -128,6 +128,12 @@ function BestellungDetail({ id, toast, onBack }) { api(`/tools/bestellungen/${id}`,{method:'PUT',body:{bezahlt:!order.bezahlt}}) .then(u=>{setOrder(u);toast(u.bezahlt?'Als bezahlt markiert':'Bezahlung aufgehoben');}); + const toggleAbgeholt = () => + api(`/tools/bestellungen/${id}`,{method:'PUT',body:{abgeholt:!order.abgeholt}}) + .then(u=>{setOrder(u);toast(u.abgeholt?'Als abgeholt markiert':'Abholung aufgehoben');}); + + const isAbgeschlossen = order && !!order.bezahlt && !!order.abgeholt; + return (
@@ -178,6 +184,27 @@ function BestellungDetail({ id, toast, onBack }) { πŸ”’ Bearbeitung gesperrt.
)} + + {/* Abgeholt – nur bei fertig oder bezahlt anzeigen */} + {(order.status==='fertig' || !!order.bezahlt) && ( +
+ + {!!order.abgeholt && order.abgeholt_am && ( + + am {new Date(order.abgeholt_am).toLocaleDateString('de-DE',{day:'2-digit',month:'2-digit',year:'numeric'})} + + )} +
+ )} )} @@ -598,6 +625,7 @@ export default function Bestellungen({ toast, mobile }) { const [openId, setOpenId] = useState(null); const [newMode, setNewMode] = useState(false); const [archivItem, setArchivItem] = useState(null); + const [archivOpen, setArchivOpen] = useState(false); const load = () => { setLoading(true); @@ -612,7 +640,11 @@ export default function Bestellungen({ toast, mobile }) { }; const sq = search.trim().toLowerCase(); + // Abgeschlossen = bezahlt UND abgeholt + const isAbgeschlossen = o => !!o.bezahlt && !!o.abgeholt; + const filtered = orders.filter(o => { + if (isAbgeschlossen(o)) return false; // nie in aktiver Liste const ms = !sq || o.name.toLowerCase().includes(sq) || (o.items && o.items.some(i => i.calc_name.toLowerCase().includes(sq))); const mf = filterStatus==='alle' @@ -623,6 +655,9 @@ export default function Bestellungen({ toast, mobile }) { return ms && mf; }); + const abgeschlossen = orders.filter(o => isAbgeschlossen(o) + && (!sq || o.name.toLowerCase().includes(sq))); + if (openId !== null || newMode) { return ( ); })} + + {/* ── Archiv-Drawer ───────────────────────────────────────────────── */} + {abgeschlossen.length > 0 && ( +
+ + + {archivOpen && ( +
+ {abgeschlossen.map(order => { + const customSum = order.custom_price_sum || 0; + return ( +
+
+ +
+ πŸ“¦ + πŸ’œ + {customSum > 0 && ( + + {customSum.toFixed(2)}€ + + )} +
+
+
+ + +
+
+ ); + })} +
+ )} +
+ )} ); }