from typing import Optional, List from datetime import datetime from decimal import Decimal from pydantic import Field from app.models.order import OrderStatus, PaymentMethod from app.schemas.base import BaseSchema, TimestampSchema from app.schemas.product import Product class OrderItemBase(BaseSchema): """Base schema for OrderItem data.""" product_id: int quantity: int = Field(..., gt=0) unit_price: Decimal = Field(..., ge=0, decimal_places=2) class OrderItemCreate(OrderItemBase): """Schema for creating a new order item.""" pass class OrderItemInDBBase(OrderItemBase, TimestampSchema): """Base schema for OrderItem in DB (with ID).""" id: int order_id: int class OrderItemInDB(OrderItemInDBBase): """Schema for OrderItem in DB.""" pass class OrderItemWithProduct(OrderItemInDBBase): """Schema for OrderItem with Product details.""" product: Product @property def subtotal(self) -> Decimal: """Calculate the subtotal for this order item.""" return self.unit_price * self.quantity class OrderBase(BaseSchema): """Base schema for Order data.""" user_id: int status: OrderStatus = OrderStatus.PENDING total_amount: Decimal = Field(..., ge=0, decimal_places=2) shipping_address: str payment_method: PaymentMethod notes: Optional[str] = None class OrderCreate(BaseSchema): """Schema for creating a new order.""" cart_id: int shipping_address: str payment_method: PaymentMethod notes: Optional[str] = None class OrderUpdate(BaseSchema): """Schema for updating an order.""" status: Optional[OrderStatus] = None tracking_number: Optional[str] = None notes: Optional[str] = None class OrderInDBBase(OrderBase, TimestampSchema): """Base schema for Order in DB (with ID).""" id: int tracking_number: Optional[str] = None payment_id: Optional[str] = None paid_at: Optional[datetime] = None class OrderInDB(OrderInDBBase): """Schema for Order in DB.""" pass class Order(OrderInDBBase): """Schema for Order response with items.""" items: List[OrderItemWithProduct] = [] model_config = { "json_schema_extra": { "examples": [ { "id": 1, "user_id": 1, "status": "pending", "total_amount": "39.98", "shipping_address": "123 Main St, City, Country", "tracking_number": None, "payment_method": "credit_card", "payment_id": None, "paid_at": None, "notes": "Please deliver during business hours", "created_at": "2023-07-24T12:00:00", "updated_at": "2023-07-24T12:00:00", "items": [ { "id": 1, "order_id": 1, "product_id": 1, "quantity": 2, "unit_price": "19.99", "product": { "id": 1, "name": "Product 1", "description": "Description of product 1", "price": "19.99", "sku": "PROD1", "stock_quantity": 100, "is_active": True } } ] } ] } } class OrderResponse(BaseSchema): """Schema for response after creating an order.""" order_id: int message: str status: str total_amount: Decimal