MukeshKapoor25's picture
fix(order): Add UUID validation to order retrieval endpoint
a65b141
"""
Order API endpoints for customer order management.
"""
from fastapi import APIRouter, Depends, HTTPException, status
from insightfy_utils.logging import get_logger
from uuid import UUID
from app.dependencies.auth import get_current_customer, CustomerToken
from app.order.services.service import OrderService
from app.order.schemas.schema import (
CreateOrderRequest,
OrderResponse,
OrderListRequest,
OrderListResponse
)
logger = get_logger(__name__)
router = APIRouter(
prefix="/orders",
tags=["Orders"]
)
@router.post(
"/create",
response_model=dict,
status_code=status.HTTP_201_CREATED,
summary="Create a new order",
description="Create a new order from cart items. Requires customer authentication."
)
async def create_order(
request: CreateOrderRequest,
current_customer: CustomerToken = Depends(get_current_customer)
):
"""
Create a new order for the authenticated customer.
- Validates all products exist and are available
- Ensures all items are from the same merchant
- Calculates totals including tax
- Persists order to PostgreSQL trans schema
- Returns complete order details
"""
result = await OrderService.create_order(
customer_id=current_customer.customer_id,
request=request
)
if not result["success"]:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail=result["message"]
)
return {
"success": True,
"message": result["message"],
"data": result["order"]
}
@router.get(
"/{order_id}",
response_model=dict,
summary="Get order details",
description="Get detailed information about a specific order"
)
async def get_order(
order_id: str,
current_customer: CustomerToken = Depends(get_current_customer)
):
"""
Get order details by ID.
Only returns orders belonging to the authenticated customer.
"""
# Validate UUID format
try:
UUID(order_id)
except (ValueError, AttributeError):
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail=f"Invalid order ID format: '{order_id}'. Must be a valid UUID."
)
order = await OrderService.get_order(
customer_id=current_customer.customer_id,
order_id=order_id
)
if not order:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="Order not found"
)
return {
"success": True,
"data": order
}
@router.post(
"/list",
response_model=OrderListResponse,
summary="List customer orders",
description="List all orders for the authenticated customer with optional filtering and projection"
)
async def list_orders(
request: OrderListRequest,
current_customer: CustomerToken = Depends(get_current_customer)
):
"""
List orders for the authenticated customer.
Supports:
- Filtering by status, payment_status, fulfillment_status
- Pagination with skip/limit
- Sorting by any field
- Field projection for optimized responses
Following API list endpoint standard with projection_list support.
"""
result = await OrderService.list_orders(
customer_id=current_customer.customer_id,
filters=request.filters,
skip=request.skip,
limit=request.limit,
projection_list=request.projection_list,
sort_by=request.sort_by,
sort_order=request.sort_order
)
return OrderListResponse(
total=result["total"],
skip=result["skip"],
limit=result["limit"],
orders=result["orders"]
)
@router.get(
"/",
response_model=dict,
summary="Get customer orders (simple)",
description="Simple GET endpoint to list customer orders"
)
async def get_orders_simple(
skip: int = 0,
limit: int = 100,
current_customer: CustomerToken = Depends(get_current_customer)
):
"""
Simple GET endpoint to list customer orders.
For advanced filtering and projection, use POST /orders/list instead.
"""
result = await OrderService.list_orders(
customer_id=current_customer.customer_id,
skip=skip,
limit=limit
)
return {
"success": True,
"data": {
"total": result["total"],
"orders": result["orders"]
}
}