4.1 — cloud_sync.py
- _push_menu_snapshot(): serializes digital-visible products+categories
and POSTs to cloud /api/menu/sync every 5 minutes
- _pull_pending_orders(): polls cloud /api/orders/pending/{site_id}
every CONNECT_SYNC_INTERVAL_SECONDS (default 30s); creates local
Order + OrderItem rows, marks synced on cloud, broadcasts SSE event
- _connect_loop(): second asyncio task running the fast poll loop;
piggybacked menu push fires every 5 min regardless of poll interval
- _sync_once(): captures site_numeric_id from heartbeat response and
stores it in license_state so Connect loops can use it
- start_cloud_sync(): now creates and returns both tasks
4.2 — orders model/schema/migrations
- models/order.py: table_id made nullable (online orders have no
table); 7 new online_* columns added to Order
- schemas/order.py: OrderOut table_id Optional, all 7 online_* fields
added
- main.py: 8 additive ALTER TABLE migrations for orders table
4.3 — routers/connect_orders.py (NEW)
GET /api/connect/orders/incoming — pending online orders (any auth)
POST /api/connect/orders/{id}/accept — accept (manager)
POST /api/connect/orders/{id}/reject — reject with optional reason (manager)
POST /api/connect/orders/{id}/status — progress through lifecycle (manager)
All state changes mirror to cloud via background task and broadcast SSE
4.4 — main.py router registration
connect_orders router registered at /api/connect
config.py
CONNECT_SYNC_INTERVAL_SECONDS setting added (default 30)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Backend (reports.py):
- Cache order DB objects to avoid N+1 queries per log entry
- Track seen_order_totals keyed by order_id so reprinting the same
order doesn't inflate the total; returns total_amount pre-computed
Frontend (PrinterHistory.jsx):
- Remove client-side accumulation that caused the same issue; use
total_amount directly from the API response
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Backend:
- tables.py: PUT /api/tables/groups/reorder accepts an ordered list
of group IDs and updates sort_order accordingly
Frontend (TablesConfigTab):
- Zone tabs are now draggable for group tabs (not All/Ungrouped)
- HTML5 drag-and-drop with visual drop-target highlight and a
grab cursor; fires reorderGroups mutation on drop
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds configurable buzzer control so the printer alerts kitchen staff
on each new ticket print.
Backend:
- printer_service.py: ESC 0x07 beep command fired before paper cut,
reads print.beep_on_ticket / print.beep_pattern settings; supports
single/double/triple/long presets and a custom:n1:n2:n3 format
- settings.py: registers the two new print.beep_* settings with
defaults (beep_on_ticket=true, beep_pattern=double)
- system.py: POST /api/system/printers/test-beep endpoint for
live testing from the dashboard
Frontend (PrintFontsTab):
- BeepSection component with preset grid, custom n1/n2/n3 inputs,
and a live test-beep button targeting any configured printer
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Includes all work to date:
- local_backend: FastAPI backend with products, orders, tables, shifts, cloud sync
- manager_dashboard: React manager UI with product/category management, reports, settings
- waiter_pwa: React PWA for waiter devices
- Category reparent endpoint and UI
- Waiter domain: local_ip sent on heartbeat, waiter_domain persisted from cloud response
- QR code modal in AppInfoTab for waiter domain
- Product form: number input spinners removed, category pre-selected on new product
- Category row: count badge moved to far right
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>