import bcrypt from fastapi import APIRouter, Depends, HTTPException, status from sqlalchemy.orm import Session from typing import List from database import get_db from models.user import User, AssistantAssignment from schemas.user import UserCreate, UserUpdate, UserOut, AssistantAssignmentOut from routers.deps import require_manager router = APIRouter() class ResetPinRequest: def __init__(self, pin: str): self.pin = pin @router.get("/", response_model=List[UserOut]) def list_waiters(db: Session = Depends(get_db), user: User = Depends(require_manager)): return db.query(User).filter(User.role == "waiter").all() @router.post("/", response_model=UserOut, status_code=status.HTTP_201_CREATED) def create_waiter(body: UserCreate, db: Session = Depends(get_db), user: User = Depends(require_manager)): if db.query(User).filter(User.username == body.username).first(): raise HTTPException(status_code=400, detail="Username already exists") pin_hash = bcrypt.hashpw(body.pin.encode(), bcrypt.gensalt()).decode() new_user = User(username=body.username, pin_hash=pin_hash, role=body.role, is_active=body.is_active) db.add(new_user) db.commit() db.refresh(new_user) return new_user @router.put("/{waiter_id}", response_model=UserOut) def update_waiter(waiter_id: int, body: UserUpdate, db: Session = Depends(get_db), user: User = Depends(require_manager)): waiter = db.query(User).filter(User.id == waiter_id).first() if not waiter: raise HTTPException(status_code=404, detail="Waiter not found") for field, value in body.model_dump(exclude_none=True).items(): setattr(waiter, field, value) db.commit() db.refresh(waiter) return waiter @router.put("/{waiter_id}/reset-pin") def reset_pin(waiter_id: int, pin: str, db: Session = Depends(get_db), user: User = Depends(require_manager)): waiter = db.query(User).filter(User.id == waiter_id).first() if not waiter: raise HTTPException(status_code=404, detail="Waiter not found") waiter.pin_hash = bcrypt.hashpw(pin.encode(), bcrypt.gensalt()).decode() db.commit() return {"status": "pin reset"} @router.put("/{waiter_id}/block") def toggle_block(waiter_id: int, db: Session = Depends(get_db), user: User = Depends(require_manager)): waiter = db.query(User).filter(User.id == waiter_id).first() if not waiter: raise HTTPException(status_code=404, detail="Waiter not found") waiter.is_active = not waiter.is_active db.commit() return {"is_active": waiter.is_active} @router.delete("/{waiter_id}", status_code=status.HTTP_204_NO_CONTENT) def delete_waiter(waiter_id: int, db: Session = Depends(get_db), user: User = Depends(require_manager)): waiter = db.query(User).filter(User.id == waiter_id).first() if not waiter: raise HTTPException(status_code=404, detail="Waiter not found") db.delete(waiter) db.commit() @router.post("/{waiter_id}/assign-assistant", response_model=AssistantAssignmentOut) def assign_assistant(waiter_id: int, assistant_id: int, db: Session = Depends(get_db), user: User = Depends(require_manager)): existing = db.query(AssistantAssignment).filter( AssistantAssignment.primary_waiter_id == waiter_id, AssistantAssignment.assistant_waiter_id == assistant_id, ).first() if existing: raise HTTPException(status_code=400, detail="Assignment already exists") assignment = AssistantAssignment(primary_waiter_id=waiter_id, assistant_waiter_id=assistant_id) db.add(assignment) db.commit() db.refresh(assignment) return assignment @router.delete("/{waiter_id}/assistant", status_code=status.HTTP_204_NO_CONTENT) def remove_assistant(waiter_id: int, db: Session = Depends(get_db), user: User = Depends(require_manager)): assignment = db.query(AssistantAssignment).filter( AssistantAssignment.primary_waiter_id == waiter_id ).first() if not assignment: raise HTTPException(status_code=404, detail="Assignment not found") db.delete(assignment) db.commit()