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:
2026-07-19 10:00:14 +03:00
parent 02ec1aa28f
commit 34ae328b0d
182 changed files with 34874 additions and 3556 deletions

View File

@@ -1,4 +1,4 @@
from sqlalchemy import Column, Integer, String, Boolean, DateTime, Float, ForeignKey
from sqlalchemy import Column, Integer, String, Boolean, DateTime, Float, ForeignKey, Text
from sqlalchemy.orm import relationship
from datetime import datetime, timezone
from database import Base
@@ -16,7 +16,8 @@ class User(Base):
pin_hash = Column(String, nullable=False)
password_hash = Column(String, nullable=True)
email = Column(String, nullable=True)
role = Column(String, nullable=False) # 'waiter' | 'manager' | 'sysadmin'
# Role is a label + default-permission template. Valid values: see roles.py
role = Column(String, nullable=False)
is_active = Column(Boolean, default=True, nullable=False)
full_name = Column(String, nullable=True)
nickname = Column(String, nullable=True)
@@ -26,8 +27,28 @@ class User(Base):
created_at = Column(DateTime(timezone=True), default=_utcnow)
# Phase 2B — payroll
hourly_rate = Column(Float, nullable=True)
# Waiter cancellation permission
can_cancel_orders = Column(Boolean, default=False, nullable=False)
# ── Access permissions (which sites/areas this user can enter) ────────────
perm_access_dashboard = Column(Boolean, default=False, nullable=False)
perm_access_waiter_app = Column(Boolean, default=True, nullable=False)
perm_access_kds = Column(Boolean, default=False, nullable=False)
# ── Order action permissions ──────────────────────────────────────────────
perm_cancel_orders = Column(Boolean, default=False, nullable=False)
perm_apply_discounts = Column(Boolean, default=False, nullable=False)
perm_modify_prices = Column(Boolean, default=False, nullable=False)
perm_open_orders = Column(Boolean, default=True, nullable=False)
perm_close_orders = Column(Boolean, default=True, nullable=False)
# ── Management permissions ────────────────────────────────────────────────
perm_view_reports = Column(Boolean, default=False, nullable=False)
perm_manage_staff = Column(Boolean, default=False, nullable=False)
perm_manage_tables = Column(Boolean, default=False, nullable=False)
perm_manage_menu = Column(Boolean, default=False, nullable=False)
perm_manage_settings = Column(Boolean, default=False, nullable=False)
# Per-waiter app settings + favorites (JSON blob, synced from PWA)
waiter_settings = Column(Text, nullable=True)
orders_opened = relationship("Order", foreign_keys="Order.opened_by", back_populates="opener")
orders_closed = relationship("Order", foreign_keys="Order.closed_by", back_populates="closer")
@@ -47,6 +68,15 @@ class User(Base):
back_populates="assistant_waiter",
)
@property
def can_cancel_orders(self):
"""Back-compat alias used by orders router."""
return self.perm_cancel_orders
@property
def is_superadmin(self):
return self.role == "superadmin"
class WaiterZone(Base):
"""Maps a waiter to a table group they are allowed to operate in.