Add POI feature and imporve the overall backend implementation
This commit is contained in:
@@ -13,6 +13,7 @@ from sqlalchemy.ext.asyncio import AsyncSession
|
||||
from app.core.database import get_db
|
||||
from app.core.config import settings
|
||||
from app.services.purchase_order_service import PurchaseOrderService
|
||||
from app.services.overdue_po_detector import OverduePODetector
|
||||
from app.schemas.purchase_order_schemas import (
|
||||
PurchaseOrderCreate,
|
||||
PurchaseOrderUpdate,
|
||||
@@ -25,6 +26,7 @@ from app.schemas.purchase_order_schemas import (
|
||||
SupplierInvoiceResponse,
|
||||
)
|
||||
from shared.routing import RouteBuilder
|
||||
from shared.auth.decorators import get_current_user_dep
|
||||
import structlog
|
||||
|
||||
logger = structlog.get_logger()
|
||||
@@ -368,6 +370,7 @@ async def create_delivery(
|
||||
po_id: str,
|
||||
delivery_data: DeliveryCreate,
|
||||
tenant_id: str = Path(..., description="Tenant ID"),
|
||||
current_user: dict = Depends(get_current_user_dep),
|
||||
service: PurchaseOrderService = Depends(get_po_service)
|
||||
):
|
||||
"""
|
||||
@@ -391,7 +394,7 @@ async def create_delivery(
|
||||
delivery = await service.create_delivery(
|
||||
tenant_id=uuid.UUID(tenant_id),
|
||||
delivery_data=delivery_data,
|
||||
created_by=uuid.uuid4() # TODO: Get from auth context
|
||||
created_by=uuid.UUID(current_user.get("user_id"))
|
||||
)
|
||||
|
||||
return DeliveryResponse.model_validate(delivery)
|
||||
@@ -411,6 +414,7 @@ async def update_delivery_status(
|
||||
delivery_id: str,
|
||||
status: str = Query(..., description="New delivery status"),
|
||||
tenant_id: str = Path(..., description="Tenant ID"),
|
||||
current_user: dict = Depends(get_current_user_dep),
|
||||
service: PurchaseOrderService = Depends(get_po_service)
|
||||
):
|
||||
"""
|
||||
@@ -431,7 +435,7 @@ async def update_delivery_status(
|
||||
tenant_id=uuid.UUID(tenant_id),
|
||||
delivery_id=uuid.UUID(delivery_id),
|
||||
status=status,
|
||||
updated_by=uuid.uuid4() # TODO: Get from auth context
|
||||
updated_by=uuid.UUID(current_user.get("user_id"))
|
||||
)
|
||||
|
||||
if not delivery:
|
||||
@@ -461,6 +465,7 @@ async def create_invoice(
|
||||
po_id: str,
|
||||
invoice_data: SupplierInvoiceCreate,
|
||||
tenant_id: str = Path(..., description="Tenant ID"),
|
||||
current_user: dict = Depends(get_current_user_dep),
|
||||
service: PurchaseOrderService = Depends(get_po_service)
|
||||
):
|
||||
"""
|
||||
@@ -482,7 +487,7 @@ async def create_invoice(
|
||||
invoice = await service.create_invoice(
|
||||
tenant_id=uuid.UUID(tenant_id),
|
||||
invoice_data=invoice_data,
|
||||
created_by=uuid.uuid4() # TODO: Get from auth context
|
||||
created_by=uuid.UUID(current_user.get("user_id"))
|
||||
)
|
||||
|
||||
return SupplierInvoiceResponse.model_validate(invoice)
|
||||
@@ -492,3 +497,77 @@ async def create_invoice(
|
||||
except Exception as e:
|
||||
logger.error("Error creating invoice", error=str(e), po_id=po_id)
|
||||
raise HTTPException(status_code=500, detail=str(e))
|
||||
|
||||
|
||||
# ================================================================
|
||||
# OVERDUE PO DETECTION
|
||||
# ================================================================
|
||||
|
||||
@router.get(
|
||||
route_builder.build_base_route("purchase-orders/overdue"),
|
||||
response_model=List[dict]
|
||||
)
|
||||
async def get_overdue_purchase_orders(
|
||||
tenant_id: str = Path(..., description="Tenant ID"),
|
||||
limit: int = Query(10, ge=1, le=100, description="Max results")
|
||||
):
|
||||
"""
|
||||
Get overdue purchase orders for dashboard display.
|
||||
|
||||
Returns POs that are past their estimated delivery date
|
||||
but not yet marked as delivered.
|
||||
|
||||
Args:
|
||||
tenant_id: Tenant UUID
|
||||
limit: Maximum number of results (default: 10)
|
||||
|
||||
Returns:
|
||||
List of overdue PO summaries with severity and days overdue
|
||||
"""
|
||||
try:
|
||||
detector = OverduePODetector()
|
||||
overdue_pos = await detector.get_overdue_pos_for_dashboard(
|
||||
tenant_id=uuid.UUID(tenant_id),
|
||||
limit=limit
|
||||
)
|
||||
|
||||
return overdue_pos
|
||||
|
||||
except Exception as e:
|
||||
logger.error("Error getting overdue POs", error=str(e), tenant_id=tenant_id)
|
||||
raise HTTPException(status_code=500, detail=str(e))
|
||||
|
||||
|
||||
@router.get(
|
||||
route_builder.build_resource_action_route("purchase-orders", "po_id", "overdue-status"),
|
||||
response_model=dict
|
||||
)
|
||||
async def check_po_overdue_status(
|
||||
po_id: str,
|
||||
tenant_id: str = Path(..., description="Tenant ID")
|
||||
):
|
||||
"""
|
||||
Check if a specific PO is overdue.
|
||||
|
||||
Args:
|
||||
tenant_id: Tenant UUID
|
||||
po_id: Purchase order UUID
|
||||
|
||||
Returns:
|
||||
Overdue status info or null if not overdue
|
||||
"""
|
||||
try:
|
||||
detector = OverduePODetector()
|
||||
overdue_info = await detector.check_single_po_overdue(
|
||||
po_id=uuid.UUID(po_id),
|
||||
tenant_id=uuid.UUID(tenant_id)
|
||||
)
|
||||
|
||||
if overdue_info:
|
||||
return overdue_info
|
||||
else:
|
||||
return {"overdue": False}
|
||||
|
||||
except Exception as e:
|
||||
logger.error("Error checking PO overdue status", error=str(e), po_id=po_id)
|
||||
raise HTTPException(status_code=500, detail=str(e))
|
||||
|
||||
Reference in New Issue
Block a user