feat: bump client-services (accumulated feature work + deploy fixes)
Snapshot of in-progress work across local_backend, manager_dashboard, and waiter_pwa (pricing, chat, fiscal, prep zones, recovery codes, CRM, inventory, permissions), plus the nginx/docker-compose deploy fixes for the Unraid + NPM reverse-proxy setup. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -5,7 +5,7 @@ from datetime import datetime, timezone
|
||||
from database import get_db
|
||||
from models.settings import PosSettings
|
||||
from schemas.settings import UpdateSettingRequest
|
||||
from routers.deps import get_current_user, require_manager
|
||||
from routers.deps import get_current_user, require_settings_manager
|
||||
from models.user import User
|
||||
|
||||
router = APIRouter()
|
||||
@@ -20,6 +20,7 @@ VALID_SETTINGS = {
|
||||
"security.auto_logout_seconds":"Seconds of inactivity before logging out (0 = disabled)",
|
||||
"shifts.waiter_self_start": "Allow waiters to start their own shifts without manager action",
|
||||
"shifts.waiter_self_end": "Allow waiters to end their own shifts without manager action",
|
||||
"shifts.hide_revenue_from_waiters": "Hide ΕΙΣΠΡΑΞΗ and ΠΑΡΑΔ. ΠΟΣΟ stats from waiters in Shift Overview: 'true' | 'false'",
|
||||
"business_day.force_close_allowed": "Allow force-closing business day with open tables",
|
||||
"system.timezone": "IANA timezone name used by the backend container (e.g. Europe/Athens). Requires container restart to take effect.",
|
||||
"ui.table_colours": "JSON blob of table card colour scheme (light + dark modes) for the Waiter PWA.",
|
||||
@@ -43,6 +44,27 @@ VALID_SETTINGS = {
|
||||
"print.beep_pattern": "Beep pattern: 'single' | 'double' | 'triple' | 'long' | 'custom:n1:n2:n3'",
|
||||
# Phase 2 — cancellations
|
||||
"orders.waiter_cancellations_allowed": "Allow waiters with per-account permission to cancel sent orders: 'true' | 'false'",
|
||||
"orders.waiter_price_adjust_allowed": "Allow waiters to adjust item prices (before or after ordering): 'true' | 'false'",
|
||||
# Payment options
|
||||
"payments.card_enabled": "Allow waiters to record card payments (in addition to cash): 'true' | 'false'",
|
||||
"payments.waiter_revert_allowed": "Allow waiters to revert individual paid items back to unpaid: 'true' | 'false'",
|
||||
# Tables & orders behaviour
|
||||
"orders.auto_close_on_full_payment": "Automatically close the table order when all items have been paid: 'true' | 'false'",
|
||||
"orders.bypass_kds_serve": "Skip KDS pending/serve flow — new orders and items are immediately marked as served: 'true' | 'false'",
|
||||
# Courses
|
||||
"orders.courses_enabled": "Enable per-item course assignment when ordering: 'true' | 'false'",
|
||||
"orders.courses": "JSON array of course objects [{id, name, color}] defining available courses",
|
||||
# Quick notes
|
||||
"orders.quick_notes": "JSON array of quick-note strings shown in the waiter note tab",
|
||||
# Fiscal printer (ΦΗΜ)
|
||||
"fiscal.enabled": "Master switch for fiscal printing: 'true' | 'false'",
|
||||
"fiscal.type": "Fiscal driver type: 'txt_file' (dTEC100extra) — more types coming",
|
||||
"fiscal.out_folder": "Path the backend writes fiscal command files TO (input for the fiscal driver)",
|
||||
"fiscal.in_folder": "Path the backend reads fiscal reply files FROM (output of the fiscal driver)",
|
||||
"fiscal.clerk_id": "Clerk ID sent in CR/CD commands (integer string, e.g. '2')",
|
||||
"fiscal.eftpos_id": "EFTPOS terminal ID sent in CD commands (integer string, e.g. '1')",
|
||||
"fiscal.end_message": "JSON array of up to 5 strings printed at end of receipt via FM commands",
|
||||
"fiscal.vat_groups": "JSON array of VAT group definitions: [{machine_id: int, friendly_name: str}]",
|
||||
}
|
||||
|
||||
DEFAULTS = {
|
||||
@@ -54,9 +76,10 @@ DEFAULTS = {
|
||||
"security.auto_logout_seconds": "1800",
|
||||
"shifts.waiter_self_start": "true",
|
||||
"shifts.waiter_self_end": "true",
|
||||
"shifts.hide_revenue_from_waiters": "false",
|
||||
"business_day.force_close_allowed": "true",
|
||||
"system.timezone": "Europe/Athens",
|
||||
"ui.table_colours": '{"light":{"free":{"cardBg":"#dde5ef","badgeBg":"rgba(255,255,255,0.92)","nameText":"#3d5270","badgeText":"#3d5270"},"mine":{"cardBg":"#e8610a","badgeBg":"rgba(255,255,255,0.92)","nameText":"#ffffff","badgeText":"#e8610a"},"open":{"cardBg":"#FF8F60","badgeBg":"rgba(255,255,255,0.92)","nameText":"#ffffff","badgeText":"#FF8F60"},"partially_paid":{"cardBg":"#FFDC67","badgeBg":"rgba(255,255,255,0.92)","nameText":"#ffffff","badgeText":"#d4a800"},"paid":{"cardBg":"#81D264","badgeBg":"rgba(255,255,255,0.92)","nameText":"#ffffff","badgeText":"#81D264"}},"dark":{"free":{"cardBg":"#243044","badgeBg":"rgba(255,255,255,0.92)","nameText":"#94b8d4","badgeText":"#94b8d4"},"mine":{"cardBg":"#e8610a","badgeBg":"rgba(255,255,255,0.92)","nameText":"#ffffff","badgeText":"#e8610a"},"open":{"cardBg":"#FF8F60","badgeBg":"rgba(255,255,255,0.92)","nameText":"#ffffff","badgeText":"#FF8F60"},"partially_paid":{"cardBg":"#FFDC67","badgeBg":"rgba(255,255,255,0.92)","nameText":"#ffffff","badgeText":"#d4a800"},"paid":{"cardBg":"#81D264","badgeBg":"rgba(255,255,255,0.92)","nameText":"#ffffff","badgeText":"#81D264"}}}',
|
||||
"ui.table_colours": '{"light":{"free":{"cardBg":"#dde5ef","badgeBg":"rgba(255,255,255,0.92)","nameText":"#3d5270","badgeText":"#3d5270"},"mine":{"cardBg":"#e8610a","badgeBg":"rgba(255,255,255,0.92)","nameText":"#ffffff","badgeText":"#e8610a"},"open":{"cardBg":"#FF8F60","badgeBg":"rgba(255,255,255,0.92)","nameText":"#ffffff","badgeText":"#FF8F60"},"partially_paid":{"cardBg":"#FFDC67","badgeBg":"rgba(255,255,255,0.92)","nameText":"#ffffff","badgeText":"#d4a800"},"paid":{"cardBg":"#81D264","badgeBg":"rgba(255,255,255,0.92)","nameText":"#ffffff","badgeText":"#81D264"},"kds_ready":{"cardBg":"#22c55e","cardBg2":"#ffffff","badgeBg":"rgba(255,255,255,0.92)","badgeBg2":"rgba(255,255,255,0.92)","nameText":"#ffffff","nameText2":"#15803d","badgeText":"#15803d","badgeText2":"#22c55e","flash":true}},"dark":{"free":{"cardBg":"#243044","badgeBg":"rgba(255,255,255,0.92)","nameText":"#94b8d4","badgeText":"#94b8d4"},"mine":{"cardBg":"#e8610a","badgeBg":"rgba(255,255,255,0.92)","nameText":"#ffffff","badgeText":"#e8610a"},"open":{"cardBg":"#FF8F60","badgeBg":"rgba(255,255,255,0.92)","nameText":"#ffffff","badgeText":"#FF8F60"},"partially_paid":{"cardBg":"#FFDC67","badgeBg":"rgba(255,255,255,0.92)","nameText":"#ffffff","badgeText":"#d4a800"},"paid":{"cardBg":"#81D264","badgeBg":"rgba(255,255,255,0.92)","nameText":"#ffffff","badgeText":"#81D264"},"kds_ready":{"cardBg":"#16a34a","cardBg2":"#ffffff","badgeBg":"rgba(255,255,255,0.92)","badgeBg2":"rgba(255,255,255,0.92)","nameText":"#ffffff","nameText2":"#bbf7d0","badgeText":"#bbf7d0","badgeText2":"#16a34a","flash":true}}}',
|
||||
"dev.spoof_printing": "false",
|
||||
"print.ticket_mode": "detailed",
|
||||
"print.divider_style": "dash",
|
||||
@@ -72,6 +95,23 @@ DEFAULTS = {
|
||||
"print.font_order_note": "0:1:0",
|
||||
"print.beep_on_ticket": "true",
|
||||
"print.beep_pattern": "double",
|
||||
"payments.card_enabled": "false",
|
||||
"payments.waiter_revert_allowed": "false",
|
||||
"orders.auto_close_on_full_payment": "false",
|
||||
"orders.bypass_kds_serve": "false",
|
||||
"orders.waiter_price_adjust_allowed": "false",
|
||||
"orders.courses_enabled": "false",
|
||||
"orders.courses": "[]",
|
||||
"orders.quick_notes": '["Χωρίς αλάτι","Βγάλτε γρήγορα","Αλλεργία!","Κόψτε σε μικρά κομμάτια","Έξτρα χαρτοπετσέτες"]',
|
||||
# Fiscal printer (ΦΗΜ)
|
||||
"fiscal.enabled": "false",
|
||||
"fiscal.type": "txt_file",
|
||||
"fiscal.out_folder": "",
|
||||
"fiscal.in_folder": "",
|
||||
"fiscal.clerk_id": "2",
|
||||
"fiscal.eftpos_id": "1",
|
||||
"fiscal.end_message": "[]",
|
||||
"fiscal.vat_groups": "[]",
|
||||
}
|
||||
|
||||
|
||||
@@ -95,7 +135,7 @@ def update_setting(
|
||||
key: str,
|
||||
body: UpdateSettingRequest,
|
||||
db: Session = Depends(get_db),
|
||||
user: User = Depends(require_manager),
|
||||
user: User = Depends(require_settings_manager),
|
||||
):
|
||||
if key not in VALID_SETTINGS:
|
||||
raise HTTPException(status_code=400, detail=f"Unknown setting key: {key}")
|
||||
|
||||
Reference in New Issue
Block a user