# services/recipes/app/schemas/production.py """ Pydantic schemas for production-related API requests and responses """ from pydantic import BaseModel, Field from typing import List, Optional, Dict, Any from uuid import UUID from datetime import datetime, date from enum import Enum from ..models.recipes import ProductionStatus, ProductionPriority, MeasurementUnit class ProductionIngredientConsumptionCreate(BaseModel): """Schema for creating production ingredient consumption""" recipe_ingredient_id: UUID ingredient_id: UUID stock_id: Optional[UUID] = None planned_quantity: float = Field(..., gt=0) actual_quantity: float = Field(..., gt=0) unit: MeasurementUnit consumption_notes: Optional[str] = None staff_member: Optional[UUID] = None ingredient_condition: Optional[str] = None quality_impact: Optional[str] = None substitution_used: bool = False substitution_details: Optional[str] = None class ProductionIngredientConsumptionResponse(BaseModel): """Schema for production ingredient consumption responses""" id: UUID tenant_id: UUID production_batch_id: UUID recipe_ingredient_id: UUID ingredient_id: UUID stock_id: Optional[UUID] = None planned_quantity: float actual_quantity: float unit: str variance_quantity: Optional[float] = None variance_percentage: Optional[float] = None unit_cost: Optional[float] = None total_cost: Optional[float] = None consumption_time: datetime consumption_notes: Optional[str] = None staff_member: Optional[UUID] = None ingredient_condition: Optional[str] = None quality_impact: Optional[str] = None substitution_used: bool substitution_details: Optional[str] = None class Config: from_attributes = True class ProductionBatchCreate(BaseModel): """Schema for creating production batches""" recipe_id: UUID batch_number: str = Field(..., min_length=1, max_length=100) production_date: date planned_start_time: Optional[datetime] = None planned_end_time: Optional[datetime] = None planned_quantity: float = Field(..., gt=0) batch_size_multiplier: float = Field(default=1.0, gt=0) priority: ProductionPriority = ProductionPriority.NORMAL assigned_staff: Optional[List[UUID]] = None production_notes: Optional[str] = None customer_order_reference: Optional[str] = None pre_order_quantity: Optional[float] = Field(None, ge=0) shelf_quantity: Optional[float] = Field(None, ge=0) class ProductionBatchUpdate(BaseModel): """Schema for updating production batches""" batch_number: Optional[str] = Field(None, min_length=1, max_length=100) production_date: Optional[date] = None planned_start_time: Optional[datetime] = None actual_start_time: Optional[datetime] = None planned_end_time: Optional[datetime] = None actual_end_time: Optional[datetime] = None planned_quantity: Optional[float] = Field(None, gt=0) actual_quantity: Optional[float] = Field(None, ge=0) batch_size_multiplier: Optional[float] = Field(None, gt=0) status: Optional[ProductionStatus] = None priority: Optional[ProductionPriority] = None assigned_staff: Optional[List[UUID]] = None production_notes: Optional[str] = None quality_score: Optional[float] = Field(None, ge=1, le=10) quality_notes: Optional[str] = None defect_rate: Optional[float] = Field(None, ge=0, le=100) rework_required: Optional[bool] = None labor_cost: Optional[float] = Field(None, ge=0) overhead_cost: Optional[float] = Field(None, ge=0) production_temperature: Optional[float] = None production_humidity: Optional[float] = Field(None, ge=0, le=100) oven_temperature: Optional[float] = None baking_time_minutes: Optional[int] = Field(None, ge=0) waste_quantity: Optional[float] = Field(None, ge=0) waste_reason: Optional[str] = None customer_order_reference: Optional[str] = None pre_order_quantity: Optional[float] = Field(None, ge=0) shelf_quantity: Optional[float] = Field(None, ge=0) class ProductionBatchResponse(BaseModel): """Schema for production batch responses""" id: UUID tenant_id: UUID recipe_id: UUID batch_number: str production_date: date planned_start_time: Optional[datetime] = None actual_start_time: Optional[datetime] = None planned_end_time: Optional[datetime] = None actual_end_time: Optional[datetime] = None planned_quantity: float actual_quantity: Optional[float] = None yield_percentage: Optional[float] = None batch_size_multiplier: float status: str priority: str assigned_staff: Optional[List[UUID]] = None production_notes: Optional[str] = None quality_score: Optional[float] = None quality_notes: Optional[str] = None defect_rate: Optional[float] = None rework_required: bool planned_material_cost: Optional[float] = None actual_material_cost: Optional[float] = None labor_cost: Optional[float] = None overhead_cost: Optional[float] = None total_production_cost: Optional[float] = None cost_per_unit: Optional[float] = None production_temperature: Optional[float] = None production_humidity: Optional[float] = None oven_temperature: Optional[float] = None baking_time_minutes: Optional[int] = None waste_quantity: float waste_reason: Optional[str] = None efficiency_percentage: Optional[float] = None customer_order_reference: Optional[str] = None pre_order_quantity: Optional[float] = None shelf_quantity: Optional[float] = None created_at: datetime updated_at: datetime created_by: Optional[UUID] = None completed_by: Optional[UUID] = None ingredient_consumptions: Optional[List[ProductionIngredientConsumptionResponse]] = None class Config: from_attributes = True class ProductionBatchSearchRequest(BaseModel): """Schema for production batch search requests""" search_term: Optional[str] = None status: Optional[ProductionStatus] = None priority: Optional[ProductionPriority] = None start_date: Optional[date] = None end_date: Optional[date] = None recipe_id: Optional[UUID] = None limit: int = Field(default=100, ge=1, le=1000) offset: int = Field(default=0, ge=0) class ProductionScheduleCreate(BaseModel): """Schema for creating production schedules""" schedule_date: date schedule_name: Optional[str] = Field(None, max_length=255) estimated_production_hours: Optional[float] = Field(None, gt=0) estimated_material_cost: Optional[float] = Field(None, ge=0) available_staff_hours: Optional[float] = Field(None, gt=0) oven_capacity_hours: Optional[float] = Field(None, gt=0) production_capacity_limit: Optional[float] = Field(None, gt=0) schedule_notes: Optional[str] = None preparation_instructions: Optional[str] = None special_requirements: Optional[Dict[str, Any]] = None class ProductionScheduleUpdate(BaseModel): """Schema for updating production schedules""" schedule_name: Optional[str] = Field(None, max_length=255) total_planned_batches: Optional[int] = Field(None, ge=0) total_planned_items: Optional[float] = Field(None, ge=0) estimated_production_hours: Optional[float] = Field(None, gt=0) estimated_material_cost: Optional[float] = Field(None, ge=0) is_published: Optional[bool] = None is_completed: Optional[bool] = None completion_percentage: Optional[float] = Field(None, ge=0, le=100) available_staff_hours: Optional[float] = Field(None, gt=0) oven_capacity_hours: Optional[float] = Field(None, gt=0) production_capacity_limit: Optional[float] = Field(None, gt=0) schedule_notes: Optional[str] = None preparation_instructions: Optional[str] = None special_requirements: Optional[Dict[str, Any]] = None class ProductionScheduleResponse(BaseModel): """Schema for production schedule responses""" id: UUID tenant_id: UUID schedule_date: date schedule_name: Optional[str] = None total_planned_batches: int total_planned_items: float estimated_production_hours: Optional[float] = None estimated_material_cost: Optional[float] = None is_published: bool is_completed: bool completion_percentage: Optional[float] = None available_staff_hours: Optional[float] = None oven_capacity_hours: Optional[float] = None production_capacity_limit: Optional[float] = None schedule_notes: Optional[str] = None preparation_instructions: Optional[str] = None special_requirements: Optional[Dict[str, Any]] = None created_at: datetime updated_at: datetime created_by: Optional[UUID] = None published_by: Optional[UUID] = None published_at: Optional[datetime] = None class Config: from_attributes = True class ProductionStatisticsResponse(BaseModel): """Schema for production statistics responses""" total_batches: int completed_batches: int failed_batches: int success_rate: float average_yield_percentage: float average_quality_score: float total_production_cost: float status_breakdown: List[Dict[str, Any]] class StartProductionRequest(BaseModel): """Schema for starting production batch""" staff_member: Optional[UUID] = None production_notes: Optional[str] = None ingredient_consumptions: List[ProductionIngredientConsumptionCreate] class CompleteProductionRequest(BaseModel): """Schema for completing production batch""" actual_quantity: float = Field(..., gt=0) quality_score: Optional[float] = Field(None, ge=1, le=10) quality_notes: Optional[str] = None defect_rate: Optional[float] = Field(None, ge=0, le=100) waste_quantity: Optional[float] = Field(None, ge=0) waste_reason: Optional[str] = None production_notes: Optional[str] = None staff_member: Optional[UUID] = None