ItemOptionsModal:
- Supports inline sub-choices on both preference choices and checkbox options;
sub-choices appear indented when the parent is selected
- Supports shared_subset at the preference-set level (shown unless the selected
choice has disables_subset)
- Pre-selects default choices and their default sub-choices on open
- Add button disabled + red validation hints until all required selections made
- Price total reflects sub-choice extra_cost
TableListPage:
- Zone filter dropdown with multi-select; filters by table group_id
(fetches /api/tables/groups alongside tables and orders)
- Fixed 'mine' and 'free' filters to compose correctly with zone filter
LoginPage:
- Switch to JSON body { username, pin } to match updated /api/auth/login
- Read user fields from data.user.* instead of flat response
vite.config.js: enable SW devOptions so PWA works in dev mode
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
TableGroup gains prefix and color columns for display in the PWA zone filter.
Table creation now assigns a global auto-increment number; batch creation uses
group-local label numbering (avoids gaps/conflicts when adding to existing groups).
DELETE table now blocks if an active order exists (soft or hard delete).
Hard delete cascades past orders before removing the table row.
list_tables enriches each TableOut with has_active_order computed server-side.
TableOut no longer requires number in the input payload; TableCreate simplified.
Migration runner refactored to give each ALTER TABLE its own connection so a
no-op (column already exists) doesn't leave a dirty transaction blocking later
migrations. New migrations added for all new columns.
Order.print_logs relationship gains cascade="all, delete-orphan" so print logs
are removed when an order is deleted.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- ProductOption and ProductPreferenceChoice gain sub_choices (JSON Text column)
for nested inline choices shown when the parent is selected
- ProductPreferenceSet gains default_choice_id and shared_subset (set-level
sub-choice group shown for all choices that don't disable it)
- Product gains sort_order column; list endpoint orders by sort_order
- New PUT /products/reorder endpoint for drag-and-drop ordering
- DELETE /products/{id} now accepts ?hard=true for permanent deletion (blocked
if product appears in any past order)
- Schemas updated with model_validators to parse stored JSON back to typed objects
- Add python-multipart to requirements (needed for file upload form parsing)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Token creation/decoding/blacklisting was split across auth.py and deps.py
causing a circular import. Consolidate make_token, decode_token, and
blacklist_token in deps.py; auth.py now imports from there.
Also switches /login to accept JSON body (username+pin) instead of
form-encoded, and returns a proper user object in the response.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- New cloud_backend/ FastAPI service on port 8001 (SQLite for dev, swappable to PostgreSQL)
- Endpoints: sysadmin auth (JWT), site registration, lock/unlock, heartbeat (X-Site-ID + X-Site-Key headers)
- Default sysadmin seeded on first startup from ADMIN_USERNAME/ADMIN_PASSWORD env vars
- cloud_backend added to docker-compose.yml with persistent data volume at ./data/cloud/
- local_backend cloud_sync.py updated to use correct /api/heartbeat/ endpoint with header auth
- local_backend config.py: added SITE_KEY setting
- Smoke tested: login, register site, heartbeat, lock, unlock, list all pass
Backend:
- OrderItemInput accepts option objects {id,name,price_delta} instead of int IDs
- extra_cost from selected options added to unit_price snapshot
- GET /api/products/?all=true for manager (includes unavailable)
- PUT /api/products/{id} now replaces options, ingredients, preference_sets
- POST /api/products/{id}/image — persistent image upload to /app/data/product_images
- New models: ProductPreferenceSet, ProductPreferenceChoice, TableGroup
- tables: group_id FK, hard delete (?hard=true), batch create POST /api/tables/batch
- GET /api/tables/groups + POST/PUT/DELETE groups endpoints
- POST /api/auth/me endpoint for token rehydration
- Auto-migration on startup for new columns
PWA:
- AuthRehydrator: fetches /auth/me on load so isMyOrder works after page reload
- 401 response force-logs out (covers blocked waiters)
- ItemOptionsModal: uses extra_cost correctly, shows preferences as radio buttons
Manager:
- ProductsPage: shows unavailable products greyed out, category color picker + reorder,
full option/ingredient/preference editing, image upload
- TablesPage: table groups, auto-increment, deactivate vs hard delete, batch add