from fastapi import APIRouter, Depends, HTTPException, status, Query from sqlalchemy.orm import Session from typing import List, Optional from database import get_db from models.customers import Customer from models.order import Order, OrderItem from models.user import User from schemas.customers import CustomerCreate, CustomerUpdate, CustomerOut, AssignCustomerRequest from routers.deps import require_manager, get_current_user router = APIRouter() def _customer_out(c: Customer, db: Session) -> dict: orders = db.query(Order).filter( Order.customer_id == c.id, Order.status.in_(["closed", "paid"]), ).all() total_spent = sum( sum(i.unit_price * i.quantity for i in o.items if i.status in ("active", "paid")) for o in orders ) return { "id": c.id, "name": c.name, "nickname": c.nickname, "phone": c.phone, "email": c.email, "notes": c.notes, "is_active": c.is_active, "created_at": c.created_at, "created_by_id": c.created_by_id, "visit_count": len(orders), "total_spent": round(total_spent, 2), } @router.get("/", response_model=List[CustomerOut]) def list_customers( search: Optional[str] = None, include_inactive: bool = False, db: Session = Depends(get_db), user: User = Depends(require_manager), ): q = db.query(Customer) if not include_inactive: q = q.filter(Customer.is_active == True) if search: term = f"%{search}%" q = q.filter( Customer.name.ilike(term) | Customer.nickname.ilike(term) | Customer.phone.ilike(term) ) customers = q.order_by(Customer.name).all() return [_customer_out(c, db) for c in customers] @router.post("/", response_model=CustomerOut, status_code=status.HTTP_201_CREATED) def create_customer(body: CustomerCreate, db: Session = Depends(get_db), user: User = Depends(require_manager)): customer = Customer(**body.model_dump(), created_by_id=user.id) db.add(customer) db.commit() db.refresh(customer) return _customer_out(customer, db) @router.get("/{customer_id}", response_model=CustomerOut) def get_customer(customer_id: int, db: Session = Depends(get_db), user: User = Depends(require_manager)): c = db.query(Customer).filter(Customer.id == customer_id).first() if not c: raise HTTPException(status_code=404, detail="Customer not found") return _customer_out(c, db) @router.put("/{customer_id}", response_model=CustomerOut) def update_customer(customer_id: int, body: CustomerUpdate, db: Session = Depends(get_db), user: User = Depends(require_manager)): c = db.query(Customer).filter(Customer.id == customer_id).first() if not c: raise HTTPException(status_code=404, detail="Customer not found") for field, value in body.model_dump(exclude_none=True).items(): setattr(c, field, value) db.commit() db.refresh(c) return _customer_out(c, db) @router.delete("/{customer_id}", status_code=status.HTTP_204_NO_CONTENT) def delete_customer(customer_id: int, db: Session = Depends(get_db), user: User = Depends(require_manager)): c = db.query(Customer).filter(Customer.id == customer_id).first() if not c: raise HTTPException(status_code=404, detail="Customer not found") c.is_active = False db.commit() @router.get("/{customer_id}/orders") def customer_orders(customer_id: int, db: Session = Depends(get_db), user: User = Depends(require_manager)): c = db.query(Customer).filter(Customer.id == customer_id).first() if not c: raise HTTPException(status_code=404, detail="Customer not found") from models.table import Table orders = db.query(Order).filter(Order.customer_id == customer_id).order_by(Order.opened_at.desc()).all() tables_map = {t.id: (t.label or f"T{t.number}") for t in db.query(Table).all()} result = [] for o in orders: total = sum(i.unit_price * i.quantity for i in o.items if i.status in ("active", "paid")) result.append({ "id": o.id, "table_name": tables_map.get(o.table_id) if o.table_id else None, "opened_at": o.opened_at, "status": o.status, "total": round(total, 2), "item_count": sum(i.quantity for i in o.items if i.status in ("active", "paid")), }) return {"orders": result}