# ================================================================ # services/orders/app/schemas/order_schemas.py # ================================================================ """ Order-related Pydantic schemas for Orders Service """ from datetime import datetime, date from decimal import Decimal from typing import Optional, List, Dict, Any from uuid import UUID from pydantic import BaseModel, Field, validator from app.models.enums import ( CustomerType, DeliveryMethod, PaymentTerms, PaymentMethod, PaymentStatus, CustomerSegment, PriorityLevel, OrderType, OrderStatus, OrderSource, SalesChannel, BusinessModel, DeliveryStatus ) # ===== Customer Schemas ===== class CustomerBase(BaseModel): name: str = Field(..., min_length=1, max_length=200) business_name: Optional[str] = Field(None, max_length=200) customer_type: CustomerType = Field(default=CustomerType.INDIVIDUAL) email: Optional[str] = Field(None, max_length=255) phone: Optional[str] = Field(None, max_length=50) address_line1: Optional[str] = Field(None, max_length=255) address_line2: Optional[str] = Field(None, max_length=255) city: Optional[str] = Field(None, max_length=100) state: Optional[str] = Field(None, max_length=100) postal_code: Optional[str] = Field(None, max_length=20) country: str = Field(default="US", max_length=100) is_active: bool = Field(default=True) preferred_delivery_method: DeliveryMethod = Field(default=DeliveryMethod.DELIVERY) payment_terms: PaymentTerms = Field(default=PaymentTerms.IMMEDIATE) credit_limit: Optional[Decimal] = Field(None, ge=0) discount_percentage: Decimal = Field(default=Decimal("0.00"), ge=0, le=100) customer_segment: CustomerSegment = Field(default=CustomerSegment.REGULAR) priority_level: PriorityLevel = Field(default=PriorityLevel.NORMAL) special_instructions: Optional[str] = None delivery_preferences: Optional[Dict[str, Any]] = None product_preferences: Optional[Dict[str, Any]] = None class Config: from_attributes = True use_enum_values = True class CustomerCreate(CustomerBase): customer_code: str = Field(..., min_length=1, max_length=50) class CustomerUpdate(BaseModel): name: Optional[str] = Field(None, min_length=1, max_length=200) business_name: Optional[str] = Field(None, max_length=200) customer_type: Optional[CustomerType] = None email: Optional[str] = Field(None, max_length=255) phone: Optional[str] = Field(None, max_length=50) address_line1: Optional[str] = Field(None, max_length=255) address_line2: Optional[str] = Field(None, max_length=255) city: Optional[str] = Field(None, max_length=100) state: Optional[str] = Field(None, max_length=100) postal_code: Optional[str] = Field(None, max_length=20) country: Optional[str] = Field(None, max_length=100) is_active: Optional[bool] = None preferred_delivery_method: Optional[DeliveryMethod] = None payment_terms: Optional[PaymentTerms] = None credit_limit: Optional[Decimal] = Field(None, ge=0) discount_percentage: Optional[Decimal] = Field(None, ge=0, le=100) customer_segment: Optional[CustomerSegment] = None priority_level: Optional[PriorityLevel] = None special_instructions: Optional[str] = None delivery_preferences: Optional[Dict[str, Any]] = None product_preferences: Optional[Dict[str, Any]] = None class Config: from_attributes = True use_enum_values = True class CustomerResponse(CustomerBase): id: UUID tenant_id: UUID customer_code: str total_orders: int total_spent: Decimal average_order_value: Decimal last_order_date: Optional[datetime] created_at: datetime updated_at: datetime class Config: from_attributes = True # ===== Order Item Schemas ===== class OrderItemBase(BaseModel): product_id: UUID product_name: str = Field(..., min_length=1, max_length=200) product_sku: Optional[str] = Field(None, max_length=100) product_category: Optional[str] = Field(None, max_length=100) quantity: Decimal = Field(..., gt=0) unit_of_measure: str = Field(default="each", max_length=50) weight: Optional[Decimal] = Field(None, ge=0) unit_price: Decimal = Field(..., ge=0) line_discount: Decimal = Field(default=Decimal("0.00"), ge=0) product_specifications: Optional[Dict[str, Any]] = None customization_details: Optional[str] = None special_instructions: Optional[str] = None recipe_id: Optional[UUID] = None class OrderItemCreate(OrderItemBase): pass class OrderItemUpdate(BaseModel): quantity: Optional[Decimal] = Field(None, gt=0) unit_price: Optional[Decimal] = Field(None, ge=0) line_discount: Optional[Decimal] = Field(None, ge=0) product_specifications: Optional[Dict[str, Any]] = None customization_details: Optional[str] = None special_instructions: Optional[str] = None class OrderItemResponse(OrderItemBase): id: UUID order_id: UUID line_total: Decimal status: str created_at: datetime updated_at: datetime class Config: from_attributes = True # ===== Order Schemas ===== class OrderBase(BaseModel): customer_id: UUID order_type: OrderType = Field(default=OrderType.STANDARD) priority: PriorityLevel = Field(default=PriorityLevel.NORMAL) requested_delivery_date: datetime delivery_method: DeliveryMethod = Field(default=DeliveryMethod.DELIVERY) delivery_address: Optional[Dict[str, Any]] = None delivery_instructions: Optional[str] = None delivery_window_start: Optional[datetime] = None delivery_window_end: Optional[datetime] = None discount_percentage: Decimal = Field(default=Decimal("0.00"), ge=0, le=100) delivery_fee: Decimal = Field(default=Decimal("0.00"), ge=0) payment_method: Optional[PaymentMethod] = None payment_terms: PaymentTerms = Field(default=PaymentTerms.IMMEDIATE) special_instructions: Optional[str] = None custom_requirements: Optional[Dict[str, Any]] = None allergen_warnings: Optional[Dict[str, Any]] = None order_source: OrderSource = Field(default=OrderSource.MANUAL) sales_channel: SalesChannel = Field(default=SalesChannel.DIRECT) order_origin: Optional[str] = Field(None, max_length=100) communication_preferences: Optional[Dict[str, Any]] = None class Config: from_attributes = True use_enum_values = True class OrderCreate(OrderBase): tenant_id: UUID items: List[OrderItemCreate] = Field(..., min_items=1) class OrderUpdate(BaseModel): status: Optional[OrderStatus] = None priority: Optional[PriorityLevel] = None requested_delivery_date: Optional[datetime] = None confirmed_delivery_date: Optional[datetime] = None delivery_method: Optional[DeliveryMethod] = None delivery_address: Optional[Dict[str, Any]] = None delivery_instructions: Optional[str] = None delivery_window_start: Optional[datetime] = None delivery_window_end: Optional[datetime] = None payment_method: Optional[PaymentMethod] = None payment_status: Optional[PaymentStatus] = None special_instructions: Optional[str] = None custom_requirements: Optional[Dict[str, Any]] = None allergen_warnings: Optional[Dict[str, Any]] = None class Config: from_attributes = True use_enum_values = True class OrderResponse(OrderBase): id: UUID tenant_id: UUID order_number: str status: str order_date: datetime confirmed_delivery_date: Optional[datetime] actual_delivery_date: Optional[datetime] subtotal: Decimal discount_amount: Decimal tax_amount: Decimal total_amount: Decimal payment_status: str business_model: Optional[str] estimated_business_model: Optional[str] production_batch_id: Optional[UUID] quality_score: Optional[Decimal] customer_rating: Optional[int] created_at: datetime updated_at: datetime items: List[OrderItemResponse] = [] class Config: from_attributes = True # ===== Dashboard and Analytics Schemas ===== class OrdersDashboardSummary(BaseModel): """Summary data for orders dashboard""" # Current period metrics total_orders_today: int total_orders_this_week: int total_orders_this_month: int # Revenue metrics revenue_today: Decimal revenue_this_week: Decimal revenue_this_month: Decimal # Order status breakdown pending_orders: int confirmed_orders: int in_production_orders: int ready_orders: int delivered_orders: int # Customer metrics total_customers: int new_customers_this_month: int repeat_customers_rate: Decimal # Performance metrics average_order_value: Decimal order_fulfillment_rate: Decimal on_time_delivery_rate: Decimal # Business model detection business_model: Optional[str] business_model_confidence: Optional[Decimal] # Recent activity recent_orders: List[OrderResponse] high_priority_orders: List[OrderResponse] class DemandRequirements(BaseModel): """Demand requirements for production planning""" date: date tenant_id: UUID # Product demand breakdown product_demands: List[Dict[str, Any]] # Aggregate metrics total_orders: int total_quantity: Decimal total_value: Decimal # Business context business_model: Optional[str] rush_orders_count: int special_requirements: List[str] # Timing requirements earliest_delivery: datetime latest_delivery: datetime average_lead_time_hours: int