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

@@ -13,7 +13,7 @@ from schemas.table import (
TableGroupCreate, TableGroupUpdate, TableGroupOut,
TableBatchCreate, MAX_TABLE_NAME_LENGTH,
)
from routers.deps import get_current_user, require_manager
from routers.deps import get_current_user, require_tables_manager
from services.sse_bus import broadcast_sync
# Tables with a pending reservation due within this many hours get the RESERVED badge
@@ -30,7 +30,7 @@ def list_groups(db: Session = Depends(get_db), user: User = Depends(get_current_
@router.post("/groups", response_model=TableGroupOut, status_code=status.HTTP_201_CREATED)
def create_group(body: TableGroupCreate, db: Session = Depends(get_db), user: User = Depends(require_manager)):
def create_group(body: TableGroupCreate, db: Session = Depends(get_db), user: User = Depends(require_tables_manager)):
if db.query(TableGroup).filter(TableGroup.name == body.name).first():
raise HTTPException(status_code=400, detail="Group name already exists")
sort_order = db.query(TableGroup).count()
@@ -42,14 +42,14 @@ def create_group(body: TableGroupCreate, db: Session = Depends(get_db), user: Us
@router.put("/groups/reorder", status_code=status.HTTP_204_NO_CONTENT)
def reorder_groups(body: List[int] = Body(...), db: Session = Depends(get_db), user: User = Depends(require_manager)):
def reorder_groups(body: List[int] = Body(...), db: Session = Depends(get_db), user: User = Depends(require_tables_manager)):
for idx, group_id in enumerate(body):
db.query(TableGroup).filter(TableGroup.id == group_id).update({"sort_order": idx})
db.commit()
@router.put("/groups/{group_id}", response_model=TableGroupOut)
def update_group(group_id: int, body: TableGroupUpdate, db: Session = Depends(get_db), user: User = Depends(require_manager)):
def update_group(group_id: int, body: TableGroupUpdate, db: Session = Depends(get_db), user: User = Depends(require_tables_manager)):
group = db.query(TableGroup).filter(TableGroup.id == group_id).first()
if not group:
raise HTTPException(status_code=404, detail="Group not found")
@@ -61,7 +61,7 @@ def update_group(group_id: int, body: TableGroupUpdate, db: Session = Depends(ge
@router.delete("/groups/{group_id}", status_code=status.HTTP_204_NO_CONTENT)
def delete_group(group_id: int, db: Session = Depends(get_db), user: User = Depends(require_manager)):
def delete_group(group_id: int, db: Session = Depends(get_db), user: User = Depends(require_tables_manager)):
group = db.query(TableGroup).filter(TableGroup.id == group_id).first()
if not group:
raise HTTPException(status_code=404, detail="Group not found")
@@ -84,7 +84,7 @@ def list_tables(include_inactive: bool = False, db: Session = Depends(get_db), u
q = q.filter(Table.is_active == True)
# Zone-based filtering for waiters
if user.role not in ("manager", "sysadmin"):
if user.role != "superadmin" and not user.perm_access_dashboard:
zones = db.query(WaiterZone).filter(WaiterZone.waiter_id == user.id).all()
# No zone rows → sees nothing
if not zones:
@@ -134,9 +134,9 @@ def list_tables(include_inactive: bool = False, db: Session = Depends(get_db), u
@router.post("/", response_model=TableOut, status_code=status.HTTP_201_CREATED)
def create_table(body: TableCreate, db: Session = Depends(get_db), user: User = Depends(require_manager)):
def create_table(body: TableCreate, db: Session = Depends(get_db), user: User = Depends(require_tables_manager)):
number = _next_global_number(db)
table = Table(number=number, label=body.label, group_id=body.group_id, is_active=True)
table = Table(number=number, label=body.label, group_id=body.group_id, is_active=True, seat_count=body.seat_count)
db.add(table)
db.commit()
db.refresh(table)
@@ -145,7 +145,7 @@ def create_table(body: TableCreate, db: Session = Depends(get_db), user: User =
@router.post("/batch", response_model=List[TableOut], status_code=status.HTTP_201_CREATED)
def batch_create_tables(body: TableBatchCreate, db: Session = Depends(get_db), user: User = Depends(require_manager)):
def batch_create_tables(body: TableBatchCreate, db: Session = Depends(get_db), user: User = Depends(require_tables_manager)):
if body.count < 1 or body.count > 200:
raise HTTPException(status_code=400, detail="Count must be between 1 and 200")
@@ -194,7 +194,7 @@ def batch_create_tables(body: TableBatchCreate, db: Session = Depends(get_db), u
@router.put("/{table_id}", response_model=TableOut)
def update_table(table_id: int, body: TableUpdate, db: Session = Depends(get_db), user: User = Depends(require_manager)):
def update_table(table_id: int, body: TableUpdate, db: Session = Depends(get_db), user: User = Depends(require_tables_manager)):
table = db.query(Table).filter(Table.id == table_id).first()
if not table:
raise HTTPException(status_code=404, detail="Table not found")
@@ -206,7 +206,7 @@ def update_table(table_id: int, body: TableUpdate, db: Session = Depends(get_db)
@router.delete("/{table_id}", status_code=status.HTTP_204_NO_CONTENT)
def delete_table(table_id: int, hard: bool = False, db: Session = Depends(get_db), user: User = Depends(require_manager)):
def delete_table(table_id: int, hard: bool = False, db: Session = Depends(get_db), user: User = Depends(require_tables_manager)):
table = db.query(Table).filter(Table.id == table_id).first()
if not table:
raise HTTPException(status_code=404, detail="Table not found")
@@ -250,7 +250,7 @@ def table_status(table_id: int, db: Session = Depends(get_db), user: User = Depe
@router.put("/{table_id}/floorplan", response_model=TableOut)
def update_floorplan(table_id: int, body: TableFloorplanUpdate, db: Session = Depends(get_db), user: User = Depends(require_manager)):
def update_floorplan(table_id: int, body: TableFloorplanUpdate, db: Session = Depends(get_db), user: User = Depends(require_tables_manager)):
table = db.query(Table).filter(Table.id == table_id).first()
if not table:
raise HTTPException(status_code=404, detail="Table not found")