Files
bonamin 2ff48730f7 feat: Phase 2G — pay-later tab system
Backend:
- New models: Tab, TabEntry, TabPayment (3 new tables)
  - Tab: open|closed|forgiven, one open tab per customer enforced
  - TabEntry: what went ON the tab (per-item snapshot with description)
  - TabPayment: what came OFF the tab; balance = sum(entries) - sum(payments), never stored
- New router /api/tabs/:
  - GET / — list open tabs (sorted by balance desc); ?tab_status= override
  - GET /{id} — full tab detail with entries + payments
  - POST / — open new tab for a customer (400 if one already exists)
  - POST /{id}/entries — add entry directly (amount + description)
  - POST /{id}/pay — record payment; validates amount <= balance
  - POST /{id}/close — close tab (requires balance = 0)
  - POST /{id}/forgive — write off remaining balance
  - GET /customer/{customer_id} — all tabs for a customer (open first)
- POST /api/orders/{id}/items/{item_id}/tab:
  - Requires order has a customer assigned
  - Finds or auto-creates open tab for that customer
  - Sets order_item.status = "tabbed" (new valid status value)
  - Creates TabEntry with auto-generated description
  - Broadcasts order_updated SSE event
- Migrations: CREATE TABLE IF NOT EXISTS for tabs, tab_entries, tab_payments

Frontend:
- TabsPage (/tabs): open tabs list sorted by balance; each card shows charges/payments
  history, live balance, Πληρωμή modal (defaults to full balance), Κλείσιμο button
  (only shown when balance=0), Χάρισμα Υπολοίπου with confirm modal + reason
- CustomersPage CustomerDetail: open tab banner showing balance + entry count
  (appears between stats and contact info when customer has an open tab)
- OrderDetailPage: 📋 Καρτέλα button appears on active items when order has a customer;
  tabbed items show a 📋 Καρτέλα badge; tabItem mutation calls /items/{id}/tab
- Sidebar: CreditCard icon for Καρτέλες (after Πελάτες)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-08 03:07:22 +03:00

1.5 KiB