""" Endpoints API para gestión de clientes y proveedores """ from typing import List, Optional from core.database import get_core_db from core.security import get_current_user, validate_access_to_resource from fastapi import APIRouter, Depends, HTTPException, Query from sqlalchemy.orm import Session from api.v1.common.tenant_crud_routes import TenantCRUDRoutes from .dto import ( ClientProviderBasicDTO, ClientProviderCreateDTO, ClientProviderResponseDTO, ClientProviderUpdateDTO, ) from .service import ClientProviderService from .models import ClientProvider # Create base CRUD router using TenantCRUDRoutes factory base_router = TenantCRUDRoutes( service=ClientProviderService, create_schema=ClientProviderCreateDTO, update_schema=ClientProviderUpdateDTO, response_schema=ClientProviderResponseDTO, prefix="", tags=[], resource_name="Client/Provider", id_name="id", # Using numeric ID enable_list=True, # Enable GET /clients-providers with pagination enable_filters=True, # Enable filtering default_page_size=50, max_page_size=100, ).router # Create main router to add custom endpoints router = APIRouter(prefix="/clients-providers") # Include base CRUD routes router.include_router(base_router, prefix="") # Custom endpoints @router.get("/clients", response_model=List[ClientProviderBasicDTO]) async def get_clients_only( company_id: int = Query(..., description="Company ID"), skip: int = Query(0, ge=0), limit: int = Query(100, ge=1, le=1000), db: Session = Depends(get_core_db), current_user: dict = Depends(get_current_user), ): """Get only clients (client_or_provider = 'client')""" tenant_id = validate_access_to_resource(db, company_id, current_user) clients = ( db.query(ClientProvider) .filter( ClientProvider.tenant_id == tenant_id, ClientProvider.company_id == company_id, ClientProvider.client_or_provider == "client" ) .offset(skip) .limit(limit) .all() ) return [ClientProviderBasicDTO.model_validate(c) for c in clients] @router.get("/providers", response_model=List[ClientProviderBasicDTO]) async def get_providers_only( company_id: int = Query(..., description="Company ID"), skip: int = Query(0, ge=0), limit: int = Query(100, ge=1, le=1000), db: Session = Depends(get_core_db), current_user: dict = Depends(get_current_user), ): """Get only providers (client_or_provider = 'provider')""" tenant_id = validate_access_to_resource(db, company_id, current_user) providers = ( db.query(ClientProvider) .filter( ClientProvider.tenant_id == tenant_id, ClientProvider.company_id == company_id, ClientProvider.client_or_provider == "provider" ) .offset(skip) .limit(limit) .all() ) return [ClientProviderBasicDTO.model_validate(p) for p in providers] @router.get("/search/rfc/{rfc}", response_model=List[ClientProviderBasicDTO]) async def search_by_rfc( rfc: str, company_id: int = Query(..., description="Company ID"), db: Session = Depends(get_core_db), current_user: dict = Depends(get_current_user), ): """Search clients/providers by RFC""" tenant_id = validate_access_to_resource(db, company_id, current_user) clients = ( db.query(ClientProvider) .filter( ClientProvider.tenant_id == tenant_id, ClientProvider.company_id == company_id, ClientProvider.rfc.ilike(f"%{rfc}%") ) .all() ) return [ClientProviderBasicDTO.model_validate(c) for c in clients] @router.patch("/{client_id}/toggle-status", response_model=ClientProviderResponseDTO) async def toggle_clients_and_providers_status( client_id: int, company_id: int = Query(..., description="Company ID"), db: Session = Depends(get_core_db), current_user: dict = Depends(get_current_user), ): """Toggle client/provider enabled/disabled status""" tenant_id = validate_access_to_resource(db, company_id, current_user) client = ClientProviderService.get_by_id(db, client_id, tenant_id, company_id) if not client: raise HTTPException(status_code=404, detail="Client/Provider not found") # Toggle status (1 = enabled, 0 = disabled) client.enabled_disabled = 1 if client.enabled_disabled == 0 else 0 try: db.commit() db.refresh(client) return client except Exception as e: db.rollback() raise HTTPException(status_code=500, detail="Error updating status") @router.get("/{client_id}/basic", response_model=ClientProviderBasicDTO) async def get_clients_and_providers_basic_info( client_id: int, company_id: int = Query(..., description="Company ID"), db: Session = Depends(get_core_db), current_user: dict = Depends(get_current_user), ): """Get basic information for a client/provider (without address and programs)""" tenant_id = validate_access_to_resource(db, company_id, current_user) client = ClientProviderService.get_by_id(db, client_id, tenant_id, company_id) if not client: raise HTTPException(status_code=404, detail="Client/Provider not found") return ClientProviderBasicDTO.model_validate(client)