"""Nomenclature API endpoints.""" from typing import Optional, List from fastapi import APIRouter, Depends, HTTPException from sqlalchemy.ext.asyncio import AsyncSession from pydantic import BaseModel from app.db.database import get_session from app.services.sync_service import SyncService # Import auth dependencies import sys from pathlib import Path project_root = Path(__file__).parent.parent.parent.parent.parent sys.path.insert(0, str(project_root / "shared")) from auth.dependencies import get_current_user from auth.models import CurrentUser router = APIRouter() # Request/Response Models class SupplierSearchResult(BaseModel): found: bool supplier: Optional[dict] = None source: str # 'synced', 'local', 'not_found' class LocalSupplierCreate(BaseModel): name: str fiscal_code: Optional[str] = None address: Optional[str] = None class LocalSupplierResponse(BaseModel): id: int name: str fiscal_code: Optional[str] address: Optional[str] is_local: bool = True class SyncResult(BaseModel): synced: int errors: int message: str class SupplierOption(BaseModel): id: int oracle_id: Optional[int] = None name: str fiscal_code: Optional[str] source: str # 'synced' or 'local' class CashRegisterOption(BaseModel): id: int oracle_id: int name: str account_code: str register_type: str # Endpoints @router.get("/suppliers/search", response_model=SupplierSearchResult) async def search_supplier( fiscal_code: Optional[str] = None, name: Optional[str] = None, company_id: Optional[int] = None, session: AsyncSession = Depends(get_session), current_user: CurrentUser = Depends(get_current_user), ): """Search for supplier by fiscal code or name.""" if not fiscal_code and not name: raise HTTPException(status_code=400, detail="Provide fiscal_code or name") # Use provided company_id or first from user cid = company_id or (current_user.companies[0] if current_user.companies else 1) found, supplier, source = await SyncService.search_supplier( session, cid, fiscal_code, name ) return SupplierSearchResult(found=found, supplier=supplier, source=source) @router.get("/suppliers", response_model=List[SupplierOption]) async def get_suppliers( search: Optional[str] = None, company_id: Optional[int] = None, session: AsyncSession = Depends(get_session), current_user: CurrentUser = Depends(get_current_user), ): """Get all suppliers (synced + local) for dropdown/autocomplete.""" cid = company_id or (current_user.companies[0] if current_user.companies else 1) suppliers = await SyncService.get_all_suppliers(session, cid, search) return [ SupplierOption( id=s["id"], oracle_id=s.get("oracle_id"), name=s["name"], fiscal_code=s.get("fiscal_code"), source=s["source"] ) for s in suppliers ] @router.post("/suppliers/local", response_model=LocalSupplierResponse) async def create_local_supplier( data: LocalSupplierCreate, company_id: Optional[int] = None, session: AsyncSession = Depends(get_session), current_user: CurrentUser = Depends(get_current_user), ): """Create a local supplier from OCR data.""" cid = company_id or (current_user.companies[0] if current_user.companies else 1) supplier = await SyncService.create_local_supplier( session, cid, data.name, data.fiscal_code, data.address, current_user.username ) return LocalSupplierResponse( id=supplier.id, name=supplier.name, fiscal_code=supplier.fiscal_code, address=supplier.address, ) @router.get("/cash-registers", response_model=List[CashRegisterOption]) async def get_cash_registers( company_id: Optional[int] = None, session: AsyncSession = Depends(get_session), current_user: CurrentUser = Depends(get_current_user), ): """Get all cash registers for a company.""" cid = company_id or (current_user.companies[0] if current_user.companies else 1) registers = await SyncService.get_all_cash_registers(session, cid) return [ CashRegisterOption( id=r["id"], oracle_id=r["oracle_id"], name=r["name"], account_code=r["account_code"], register_type=r["register_type"] ) for r in registers ] @router.post("/sync/suppliers", response_model=SyncResult) async def sync_suppliers( company_id: Optional[int] = None, session: AsyncSession = Depends(get_session), current_user: CurrentUser = Depends(get_current_user), ): """Manually trigger supplier sync from Oracle.""" cid = company_id or (current_user.companies[0] if current_user.companies else 1) synced, errors = await SyncService.sync_suppliers(session, cid) return SyncResult( synced=synced, errors=errors, message=f"Synced {synced} suppliers with {errors} errors" ) @router.post("/sync/cash-registers", response_model=SyncResult) async def sync_cash_registers( company_id: Optional[int] = None, session: AsyncSession = Depends(get_session), current_user: CurrentUser = Depends(get_current_user), ): """Manually trigger cash register sync from Oracle.""" cid = company_id or (current_user.companies[0] if current_user.companies else 1) synced, errors = await SyncService.sync_cash_registers(session, cid) return SyncResult( synced=synced, errors=errors, message=f"Synced {synced} cash registers with {errors} errors" ) @router.post("/sync/all", response_model=dict) async def sync_all_nomenclatures( company_id: Optional[int] = None, session: AsyncSession = Depends(get_session), current_user: CurrentUser = Depends(get_current_user), ): """Sync all nomenclatures (suppliers + cash registers) from Oracle.""" cid = company_id or (current_user.companies[0] if current_user.companies else 1) # Sync suppliers suppliers_synced, suppliers_errors = await SyncService.sync_suppliers(session, cid) # Sync cash registers registers_synced, registers_errors = await SyncService.sync_cash_registers(session, cid) return { "suppliers": { "synced": suppliers_synced, "errors": suppliers_errors }, "cash_registers": { "synced": registers_synced, "errors": registers_errors }, "total_synced": suppliers_synced + registers_synced, "total_errors": suppliers_errors + registers_errors, "message": f"Synced {suppliers_synced} suppliers and {registers_synced} cash registers" }