feat: Feature 2 — waiter order cancellation + report updates
Backend: - Add can_cancel_orders to User model and schema - Add global orders.waiter_cancellations_allowed setting (migration) - Cancel endpoints: mark items with cancelled_by/cancelled_at, fire cancellation print - print_cancellation_ticket: routes to same printer zones, prints ΑΚΥΡΩΣΗ banner - Fix cancellations_log: date filter, waiter filter, join syntax - shift/orders: add cancellations count and hours_worked per waiter - _enrich_shift: add cancellations count to shift data - Add cancel-permissions endpoint for PWA Manager dashboard: - Global cancel setting toggle in Settings > Operation > Shift Settings - Per-waiter can_cancel_orders checkbox in staff modal - Manager cancel flow: print confirmation prompt (Ναι/Όχι) in DashboardPage - ShiftsOverview: Ακυρώσεις column per shift - Activity: multi-bar chart with ORDERS/ITEMS/CANCELLATIONS/ΕΣΟΔΑ/ΩΡΕΣ checkboxes, grouped/stacked switch, right X-axis for hours, full waiter name on hover - OrderHistory: cancelled items count column per order - WorkDaySummary drill-down: cancelled items column in orders tab Waiter PWA: - Replace 3 pills with CLEAR | ALL | ACTIONS - ACTIONS opens ItemActionModal for selected items - ItemActionModal: ORDER AGAIN, MOVE TO OTHER TABLE, SPLIT, CANCEL ORDER - ActionsSheet: Cancel Παραγγελίας option (greyed if no permission) - CancelConfirmModal: requires confirmation before cancelling - TableListPage: cancel order from long-press quick modal Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -75,6 +75,15 @@ def _enrich_shift(shift: WaiterShift, db: Session) -> dict:
|
||||
wname = (w.full_name or w.username) if w else f"#{shift.waiter_id}"
|
||||
total = compute_shift_total(shift.id, db) if shift.ended_at is None else (shift.total_collected or 0.0)
|
||||
pay_data = compute_shift_pay(shift)
|
||||
# Count cancelled items attributed to this waiter during shift window
|
||||
cancelled_q = db.query(OrderItem).filter(
|
||||
OrderItem.status == "cancelled",
|
||||
OrderItem.added_by == shift.waiter_id,
|
||||
OrderItem.added_at >= shift.started_at,
|
||||
)
|
||||
if shift.ended_at:
|
||||
cancelled_q = cancelled_q.filter(OrderItem.added_at <= shift.ended_at)
|
||||
cancellations = cancelled_q.count()
|
||||
return {
|
||||
"id": shift.id,
|
||||
"waiter_id": shift.waiter_id,
|
||||
@@ -90,6 +99,7 @@ def _enrich_shift(shift: WaiterShift, db: Session) -> dict:
|
||||
"hourly_rate_snapshot": shift.hourly_rate_snapshot,
|
||||
"duration_hours": pay_data["duration_hours"],
|
||||
"shift_pay": pay_data["shift_pay"],
|
||||
"cancellations": cancellations,
|
||||
# Phase 2E
|
||||
"counted_cash_end": shift.counted_cash_end,
|
||||
"cash_discrepancy": shift.cash_discrepancy,
|
||||
|
||||
Reference in New Issue
Block a user