Improve AI logic

This commit is contained in:
Urtzi Alfaro
2025-11-05 13:34:56 +01:00
parent 5c87fbcf48
commit 394ad3aea4
218 changed files with 30627 additions and 7658 deletions

View File

@@ -8,7 +8,7 @@ Procurement Plans API - Endpoints for procurement planning
import uuid
from typing import List, Optional
from datetime import date
from fastapi import APIRouter, Depends, HTTPException, Query, Request
from fastapi import APIRouter, Depends, HTTPException, Path, Query, Request
from sqlalchemy.ext.asyncio import AsyncSession
from app.core.database import get_db
@@ -22,11 +22,14 @@ from app.schemas.procurement_schemas import (
AutoGenerateProcurementResponse,
PaginatedProcurementPlans,
)
from shared.routing import RouteBuilder
import structlog
logger = structlog.get_logger()
router = APIRouter(prefix="/api/v1/tenants/{tenant_id}/procurement", tags=["Procurement Plans"])
# Create route builder for consistent URL structure
route_builder = RouteBuilder('procurement')
router = APIRouter(tags=["procurement-plans"])
def get_procurement_service(db: AsyncSession = Depends(get_db)) -> ProcurementService:
@@ -38,10 +41,13 @@ def get_procurement_service(db: AsyncSession = Depends(get_db)) -> ProcurementSe
# ORCHESTRATOR ENTRY POINT
# ================================================================
@router.post("/auto-generate", response_model=AutoGenerateProcurementResponse)
@router.post(
route_builder.build_operations_route("auto-generate"),
response_model=AutoGenerateProcurementResponse
)
async def auto_generate_procurement(
tenant_id: str,
request_data: AutoGenerateProcurementRequest,
tenant_id: str = Path(..., description="Tenant ID"),
service: ProcurementService = Depends(get_procurement_service),
db: AsyncSession = Depends(get_db)
):
@@ -82,10 +88,13 @@ async def auto_generate_procurement(
# MANUAL PROCUREMENT PLAN GENERATION
# ================================================================
@router.post("/plans/generate", response_model=GeneratePlanResponse)
@router.post(
route_builder.build_base_route("plans"),
response_model=GeneratePlanResponse
)
async def generate_procurement_plan(
tenant_id: str,
request_data: GeneratePlanRequest,
tenant_id: str = Path(..., description="Tenant ID"),
service: ProcurementService = Depends(get_procurement_service)
):
"""
@@ -122,9 +131,12 @@ async def generate_procurement_plan(
# PROCUREMENT PLAN CRUD
# ================================================================
@router.get("/plans/current", response_model=Optional[ProcurementPlanResponse])
@router.get(
route_builder.build_base_route("plans/current"),
response_model=Optional[ProcurementPlanResponse]
)
async def get_current_plan(
tenant_id: str,
tenant_id: str = Path(..., description="Tenant ID"),
service: ProcurementService = Depends(get_procurement_service)
):
"""Get the current day's procurement plan"""
@@ -137,10 +149,13 @@ async def get_current_plan(
raise HTTPException(status_code=500, detail=str(e))
@router.get("/plans/{plan_id}", response_model=ProcurementPlanResponse)
@router.get(
route_builder.build_resource_detail_route("plans", "plan_id"),
response_model=ProcurementPlanResponse
)
async def get_plan_by_id(
tenant_id: str,
plan_id: str,
tenant_id: str = Path(..., description="Tenant ID"),
service: ProcurementService = Depends(get_procurement_service)
):
"""Get procurement plan by ID"""
@@ -159,10 +174,13 @@ async def get_plan_by_id(
raise HTTPException(status_code=500, detail=str(e))
@router.get("/plans/date/{plan_date}", response_model=Optional[ProcurementPlanResponse])
@router.get(
route_builder.build_base_route("plans/date/{plan_date}"),
response_model=Optional[ProcurementPlanResponse]
)
async def get_plan_by_date(
tenant_id: str,
plan_date: date,
tenant_id: str = Path(..., description="Tenant ID"),
service: ProcurementService = Depends(get_procurement_service)
):
"""Get procurement plan for a specific date"""
@@ -175,9 +193,12 @@ async def get_plan_by_date(
raise HTTPException(status_code=500, detail=str(e))
@router.get("/plans", response_model=PaginatedProcurementPlans)
@router.get(
route_builder.build_base_route("plans"),
response_model=PaginatedProcurementPlans
)
async def list_procurement_plans(
tenant_id: str,
tenant_id: str = Path(..., description="Tenant ID"),
skip: int = Query(default=0, ge=0),
limit: int = Query(default=50, ge=1, le=100),
service: ProcurementService = Depends(get_procurement_service),
@@ -206,11 +227,13 @@ async def list_procurement_plans(
raise HTTPException(status_code=500, detail=str(e))
@router.patch("/plans/{plan_id}/status")
@router.patch(
route_builder.build_resource_action_route("plans", "plan_id", "status")
)
async def update_plan_status(
tenant_id: str,
plan_id: str,
status: str = Query(..., regex="^(draft|pending_approval|approved|in_execution|completed|cancelled)$"),
tenant_id: str = Path(..., description="Tenant ID"),
notes: Optional[str] = None,
service: ProcurementService = Depends(get_procurement_service)
):
@@ -235,11 +258,13 @@ async def update_plan_status(
raise HTTPException(status_code=500, detail=str(e))
@router.post("/plans/{plan_id}/create-purchase-orders")
@router.post(
route_builder.build_resource_action_route("plans", "plan_id", "create-purchase-orders")
)
async def create_purchase_orders_from_plan(
tenant_id: str,
plan_id: str,
auto_approve: bool = Query(default=False, description="Auto-approve qualifying purchase orders"),
tenant_id: str = Path(..., description="Tenant ID"),
service: ProcurementService = Depends(get_procurement_service)
):
"""
@@ -279,10 +304,12 @@ async def create_purchase_orders_from_plan(
# TESTING AND UTILITIES
# ================================================================
@router.get("/plans/{plan_id}/requirements")
@router.get(
route_builder.build_resource_action_route("plans", "plan_id", "requirements")
)
async def get_plan_requirements(
tenant_id: str,
plan_id: str,
tenant_id: str = Path(..., description="Tenant ID"),
service: ProcurementService = Depends(get_procurement_service),
db: AsyncSession = Depends(get_db)
):