Files
bakery-ia/services/suppliers/app/api/deliveries.py

189 lines
7.0 KiB
Python
Raw Normal View History

# services/suppliers/app/api/deliveries.py
"""
2025-10-06 15:27:01 +02:00
Delivery CRUD API endpoints (ATOMIC)
"""
from fastapi import APIRouter, Depends, HTTPException, Query, Path
2025-10-06 15:27:01 +02:00
from typing import List, Optional, Dict, Any
from uuid import UUID
import structlog
from sqlalchemy.orm import Session
from app.core.database import get_db
from app.services.delivery_service import DeliveryService
from app.schemas.suppliers import (
DeliveryCreate, DeliveryUpdate, DeliveryResponse, DeliverySummary,
2025-10-06 15:27:01 +02:00
DeliverySearchParams
)
from app.models.suppliers import DeliveryStatus
2025-08-15 22:40:19 +02:00
from shared.auth.decorators import get_current_user_dep
2025-10-06 15:27:01 +02:00
from shared.routing import RouteBuilder
from shared.auth.access_control import require_user_role
2025-10-06 15:27:01 +02:00
# Create route builder for consistent URL structure
route_builder = RouteBuilder('suppliers')
router = APIRouter(tags=["deliveries"])
logger = structlog.get_logger()
2025-10-06 15:27:01 +02:00
@router.post(route_builder.build_base_route("deliveries"), response_model=DeliveryResponse)
@require_user_role(['admin', 'owner', 'member'])
async def create_delivery(
delivery_data: DeliveryCreate,
2025-08-15 22:40:19 +02:00
current_user: Dict[str, Any] = Depends(get_current_user_dep),
db: Session = Depends(get_db)
):
"""Create a new delivery"""
2025-08-15 22:40:19 +02:00
# require_permissions(current_user, ["deliveries:create"])
try:
service = DeliveryService(db)
delivery = await service.create_delivery(
2025-10-27 16:33:26 +01:00
tenant_id=current_user["tenant_id"],
delivery_data=delivery_data,
2025-10-27 16:33:26 +01:00
created_by=current_user["user_id"]
)
return DeliveryResponse.from_orm(delivery)
except ValueError as e:
raise HTTPException(status_code=400, detail=str(e))
except Exception as e:
logger.error("Error creating delivery", error=str(e))
raise HTTPException(status_code=500, detail="Failed to create delivery")
2025-10-06 15:27:01 +02:00
@router.get(route_builder.build_base_route("deliveries"), response_model=List[DeliverySummary])
async def list_deliveries(
supplier_id: Optional[UUID] = Query(None, description="Filter by supplier ID"),
status: Optional[str] = Query(None, description="Filter by status"),
date_from: Optional[str] = Query(None, description="Filter from date (YYYY-MM-DD)"),
date_to: Optional[str] = Query(None, description="Filter to date (YYYY-MM-DD)"),
search_term: Optional[str] = Query(None, description="Search term"),
limit: int = Query(50, ge=1, le=1000, description="Number of results to return"),
offset: int = Query(0, ge=0, description="Number of results to skip"),
2025-08-15 22:40:19 +02:00
current_user: Dict[str, Any] = Depends(get_current_user_dep),
db: Session = Depends(get_db)
):
"""List deliveries with optional filters"""
2025-08-15 22:40:19 +02:00
# require_permissions(current_user, ["deliveries:read"])
try:
from datetime import datetime
# Parse date filters
date_from_parsed = None
date_to_parsed = None
if date_from:
try:
date_from_parsed = datetime.fromisoformat(date_from)
except ValueError:
raise HTTPException(status_code=400, detail="Invalid date_from format")
if date_to:
try:
date_to_parsed = datetime.fromisoformat(date_to)
except ValueError:
raise HTTPException(status_code=400, detail="Invalid date_to format")
# Validate status
status_enum = None
if status:
try:
status_enum = DeliveryStatus(status.upper())
except ValueError:
raise HTTPException(status_code=400, detail="Invalid status")
service = DeliveryService(db)
search_params = DeliverySearchParams(
supplier_id=supplier_id,
status=status_enum,
date_from=date_from_parsed,
date_to=date_to_parsed,
search_term=search_term,
limit=limit,
offset=offset
)
deliveries = await service.search_deliveries(
2025-10-27 16:33:26 +01:00
tenant_id=current_user["tenant_id"],
search_params=search_params
)
return [DeliverySummary.from_orm(delivery) for delivery in deliveries]
except HTTPException:
raise
except Exception as e:
logger.error("Error listing deliveries", error=str(e))
raise HTTPException(status_code=500, detail="Failed to retrieve deliveries")
2025-10-06 15:27:01 +02:00
@router.get(route_builder.build_resource_detail_route("deliveries", "delivery_id"), response_model=DeliveryResponse)
async def get_delivery(
delivery_id: UUID = Path(..., description="Delivery ID"),
2025-08-15 22:40:19 +02:00
current_user: Dict[str, Any] = Depends(get_current_user_dep),
db: Session = Depends(get_db)
):
"""Get delivery by ID with items"""
2025-08-15 22:40:19 +02:00
# require_permissions(current_user, ["deliveries:read"])
try:
service = DeliveryService(db)
delivery = await service.get_delivery(delivery_id)
if not delivery:
raise HTTPException(status_code=404, detail="Delivery not found")
# Check tenant access
2025-10-27 16:33:26 +01:00
if delivery.tenant_id != current_user["tenant_id"]:
raise HTTPException(status_code=403, detail="Access denied")
return DeliveryResponse.from_orm(delivery)
except HTTPException:
raise
except Exception as e:
logger.error("Error getting delivery", delivery_id=str(delivery_id), error=str(e))
raise HTTPException(status_code=500, detail="Failed to retrieve delivery")
2025-10-06 15:27:01 +02:00
@router.put(route_builder.build_resource_detail_route("deliveries", "delivery_id"), response_model=DeliveryResponse)
@require_user_role(['admin', 'owner', 'member'])
async def update_delivery(
delivery_data: DeliveryUpdate,
delivery_id: UUID = Path(..., description="Delivery ID"),
2025-08-15 22:40:19 +02:00
current_user: Dict[str, Any] = Depends(get_current_user_dep),
db: Session = Depends(get_db)
):
"""Update delivery information"""
2025-08-15 22:40:19 +02:00
# require_permissions(current_user, ["deliveries:update"])
try:
service = DeliveryService(db)
# Check delivery exists and belongs to tenant
existing_delivery = await service.get_delivery(delivery_id)
if not existing_delivery:
raise HTTPException(status_code=404, detail="Delivery not found")
2025-10-27 16:33:26 +01:00
if existing_delivery.tenant_id != current_user["tenant_id"]:
raise HTTPException(status_code=403, detail="Access denied")
delivery = await service.update_delivery(
delivery_id=delivery_id,
delivery_data=delivery_data,
2025-10-27 16:33:26 +01:00
updated_by=current_user["user_id"]
)
if not delivery:
raise HTTPException(status_code=404, detail="Delivery not found")
return DeliveryResponse.from_orm(delivery)
except HTTPException:
raise
except ValueError as e:
raise HTTPException(status_code=400, detail=str(e))
except Exception as e:
logger.error("Error updating delivery", delivery_id=str(delivery_id), error=str(e))
raise HTTPException(status_code=500, detail="Failed to update delivery")