from fastapi import APIRouter, Depends, HTTPException from sqlalchemy.orm import Session 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 models.user import User router = APIRouter() VALID_SETTINGS = { # Security / auth "security.login_method": "How managers authenticate on first login: 'password' | 'pin' | 'none'", "security.autofill_username": "Auto-fill username when only one manager exists: 'true' | 'false'", "security.auto_lock": "Lock screen after inactivity: 'true' | 'false'", "security.auto_lock_seconds": "Seconds of inactivity before locking (0 = disabled)", "security.auto_logout": "Log out after inactivity: 'true' | 'false'", "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", "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.", "dev.spoof_printing": "When enabled, all print jobs are silently dropped. Devices behave as if printing succeeded.", # Print layout "print.ticket_mode": "Kitchen ticket layout mode: 'detailed' or 'compact'", "print.divider_style": "Divider character used between sections: dash, equals, star, or empty", # Print font settings — values are "SIZE:BOLD:CAPS" where SIZE is ESC ! base byte (0/16/32/48), BOLD 0|1, CAPS 0|1 "print.font_order_number": "Font for order number header: SIZE:BOLD:CAPS", "print.font_meta": "Font for table/waiter/time header block: SIZE:BOLD:CAPS", "print.font_item_name": "Font for item name lines: SIZE:BOLD:CAPS", "print.font_quick": "Font for quick option lines (* marker): SIZE:BOLD:CAPS", "print.font_pref": "Font for preference choice lines (> marker): SIZE:BOLD:CAPS", "print.font_extra": "Font for extra/option lines (+ marker): SIZE:BOLD:CAPS", "print.font_ingredient": "Font for removed ingredient lines (- marker): SIZE:BOLD:CAPS", "print.font_item_note": "Font for per-item note lines: SIZE:BOLD:CAPS", "print.font_order_note": "Font for order-level notes: SIZE:BOLD:CAPS", } DEFAULTS = { "security.login_method": "password", "security.autofill_username": "true", "security.auto_lock": "false", "security.auto_lock_seconds": "300", "security.auto_logout": "false", "security.auto_logout_seconds": "1800", "shifts.waiter_self_start": "true", "shifts.waiter_self_end": "true", "business_day.force_close_allowed": "true", "system.timezone": "Europe/Athens", "ui.table_colours": "", "dev.spoof_printing": "false", "print.ticket_mode": "detailed", "print.divider_style": "dash", "print.font_order_number": "48:1:0", "print.font_meta": "0:0:0", "print.font_item_name": "16:1:0", "print.font_quick": "0:0:0", "print.font_pref": "0:0:0", "print.font_extra": "0:0:0", "print.font_ingredient": "0:0:0", "print.font_item_note": "0:0:0", "print.font_order_note": "0:1:0", } @router.get("/") def get_all_settings( db: Session = Depends(get_db), user: User = Depends(get_current_user), ): stored = {s.key: s.value for s in db.query(PosSettings).all()} result = {} for key, description in VALID_SETTINGS.items(): result[key] = { "value": stored.get(key, DEFAULTS.get(key, "true")), "description": description, } return result @router.put("/{key}") def update_setting( key: str, body: UpdateSettingRequest, db: Session = Depends(get_db), user: User = Depends(require_manager), ): if key not in VALID_SETTINGS: raise HTTPException(status_code=400, detail=f"Unknown setting key: {key}") setting = db.query(PosSettings).filter(PosSettings.key == key).first() if setting: setting.value = body.value setting.updated_at = datetime.now(timezone.utc) setting.updated_by_id = user.id else: setting = PosSettings(key=key, value=body.value, updated_by_id=user.id) db.add(setting) db.commit() db.refresh(setting) return {"key": setting.key, "value": setting.value}