import uuid from datetime import datetime from typing import List, Optional from fastapi import APIRouter, Depends, HTTPException from sqlalchemy.orm import Session import auth import database import models import schemas router = APIRouter( prefix="/clients", tags=["clients"], dependencies=[Depends(auth.get_current_user)], ) DEFAULT_CLIENT_COLOR = "#bb86fc" def get_current_timestamp() -> str: return datetime.utcnow().strftime("%Y-%m-%dT%H:%M:%fZ") def new_sync_id() -> str: return uuid.uuid4().hex def get_owned_client( db: Session, client_id: int, user: models.User, ) -> models.Client: client = ( db.query(models.Client) .filter( models.Client.id == client_id, models.Client.owner_id == user.id, ) .first() ) if not client: raise HTTPException(status_code=404, detail="Client not found") return client @router.post("/", response_model=schemas.ClientOut) def create_client( client: schemas.ClientCreate, current_user: models.User = Depends(auth.get_current_user), db: Session = Depends(database.get_db), ): sync_id = client.sync_id or new_sync_id() timestamp = get_current_timestamp() existing = db.query(models.Client).filter(models.Client.sync_id == sync_id).first() if existing: if existing.owner_id != current_user.id: raise HTTPException(status_code=409, detail="Client sync_id belongs to another user") existing.full_name = client.full_name existing.birth_date = client.birth_date existing.goal = client.goal or "" existing.notes = client.notes or "" existing.color = client.color or existing.color or DEFAULT_CLIENT_COLOR existing.is_active = client.is_active if client.is_active is not None else existing.is_active existing.updated_at = timestamp db.commit() db.refresh(existing) return existing db_client = models.Client( sync_id=sync_id, owner_id=current_user.id, full_name=client.full_name, birth_date=client.birth_date, goal=client.goal or "", notes=client.notes or "", color=client.color or DEFAULT_CLIENT_COLOR, is_active=client.is_active if client.is_active is not None else 1, created_at=timestamp, updated_at=timestamp, ) db.add(db_client) db.commit() db.refresh(db_client) return db_client @router.get("/", response_model=List[schemas.ClientOut]) def list_clients( skip: int = 0, limit: int = 100, current_user: models.User = Depends(auth.get_current_user), db: Session = Depends(database.get_db), ): return ( db.query(models.Client) .filter(models.Client.owner_id == current_user.id) .order_by(models.Client.full_name) .offset(skip) .limit(limit) .all() ) @router.get("/{client_id}", response_model=schemas.ClientOut) def get_client( client_id: int, current_user: models.User = Depends(auth.get_current_user), db: Session = Depends(database.get_db), ): return get_owned_client(db, client_id, current_user) @router.put("/{client_id}", response_model=schemas.ClientOut) def update_client( client_id: int, client: schemas.ClientUpdate, current_user: models.User = Depends(auth.get_current_user), db: Session = Depends(database.get_db), ): db_client = get_owned_client(db, client_id, current_user) update_data = client.dict(exclude_unset=True) for key, value in update_data.items(): setattr(db_client, key, value) db_client.updated_at = get_current_timestamp() db.commit() db.refresh(db_client) return db_client @router.delete("/{client_id}") def delete_client( client_id: int, current_user: models.User = Depends(auth.get_current_user), db: Session = Depends(database.get_db), ): db_client = get_owned_client(db, client_id, current_user) db.delete(db_client) db.commit() return {"status": "deleted"}