Improve the inventory page
This commit is contained in:
@@ -10,7 +10,7 @@ from pydantic import BaseModel, Field, validator
|
||||
from typing import Generic, TypeVar
|
||||
from enum import Enum
|
||||
|
||||
from app.models.inventory import UnitOfMeasure, IngredientCategory, StockMovementType, ProductType, ProductCategory
|
||||
from app.models.inventory import UnitOfMeasure, IngredientCategory, StockMovementType, ProductType, ProductCategory, ProductionStage
|
||||
|
||||
T = TypeVar('T')
|
||||
|
||||
@@ -172,17 +172,26 @@ class StockCreate(InventoryBaseSchema):
|
||||
batch_number: Optional[str] = Field(None, max_length=100, description="Batch number")
|
||||
lot_number: Optional[str] = Field(None, max_length=100, description="Lot number")
|
||||
supplier_batch_ref: Optional[str] = Field(None, max_length=100, description="Supplier batch reference")
|
||||
|
||||
|
||||
# Production stage tracking
|
||||
production_stage: ProductionStage = Field(ProductionStage.RAW_INGREDIENT, description="Production stage of the stock")
|
||||
transformation_reference: Optional[str] = Field(None, max_length=100, description="Transformation reference ID")
|
||||
|
||||
current_quantity: float = Field(..., ge=0, description="Current quantity")
|
||||
received_date: Optional[datetime] = Field(None, description="Date received")
|
||||
expiration_date: Optional[datetime] = Field(None, description="Expiration date")
|
||||
best_before_date: Optional[datetime] = Field(None, description="Best before date")
|
||||
|
||||
|
||||
# Stage-specific expiration fields
|
||||
original_expiration_date: Optional[datetime] = Field(None, description="Original batch expiration (for par-baked items)")
|
||||
transformation_date: Optional[datetime] = Field(None, description="Date when product was transformed")
|
||||
final_expiration_date: Optional[datetime] = Field(None, description="Final expiration after transformation")
|
||||
|
||||
unit_cost: Optional[Decimal] = Field(None, ge=0, description="Unit cost")
|
||||
storage_location: Optional[str] = Field(None, max_length=100, description="Storage location")
|
||||
warehouse_zone: Optional[str] = Field(None, max_length=50, description="Warehouse zone")
|
||||
shelf_position: Optional[str] = Field(None, max_length=50, description="Shelf position")
|
||||
|
||||
|
||||
quality_status: str = Field("good", description="Quality status")
|
||||
|
||||
|
||||
@@ -191,18 +200,27 @@ class StockUpdate(InventoryBaseSchema):
|
||||
batch_number: Optional[str] = Field(None, max_length=100, description="Batch number")
|
||||
lot_number: Optional[str] = Field(None, max_length=100, description="Lot number")
|
||||
supplier_batch_ref: Optional[str] = Field(None, max_length=100, description="Supplier batch reference")
|
||||
|
||||
|
||||
# Production stage tracking
|
||||
production_stage: Optional[ProductionStage] = Field(None, description="Production stage of the stock")
|
||||
transformation_reference: Optional[str] = Field(None, max_length=100, description="Transformation reference ID")
|
||||
|
||||
current_quantity: Optional[float] = Field(None, ge=0, description="Current quantity")
|
||||
reserved_quantity: Optional[float] = Field(None, ge=0, description="Reserved quantity")
|
||||
received_date: Optional[datetime] = Field(None, description="Date received")
|
||||
expiration_date: Optional[datetime] = Field(None, description="Expiration date")
|
||||
best_before_date: Optional[datetime] = Field(None, description="Best before date")
|
||||
|
||||
|
||||
# Stage-specific expiration fields
|
||||
original_expiration_date: Optional[datetime] = Field(None, description="Original batch expiration (for par-baked items)")
|
||||
transformation_date: Optional[datetime] = Field(None, description="Date when product was transformed")
|
||||
final_expiration_date: Optional[datetime] = Field(None, description="Final expiration after transformation")
|
||||
|
||||
unit_cost: Optional[Decimal] = Field(None, ge=0, description="Unit cost")
|
||||
storage_location: Optional[str] = Field(None, max_length=100, description="Storage location")
|
||||
warehouse_zone: Optional[str] = Field(None, max_length=50, description="Warehouse zone")
|
||||
shelf_position: Optional[str] = Field(None, max_length=50, description="Shelf position")
|
||||
|
||||
|
||||
is_available: Optional[bool] = Field(None, description="Is available")
|
||||
quality_status: Optional[str] = Field(None, description="Quality status")
|
||||
|
||||
@@ -215,12 +233,23 @@ class StockResponse(InventoryBaseSchema):
|
||||
batch_number: Optional[str]
|
||||
lot_number: Optional[str]
|
||||
supplier_batch_ref: Optional[str]
|
||||
|
||||
# Production stage tracking
|
||||
production_stage: ProductionStage
|
||||
transformation_reference: Optional[str]
|
||||
|
||||
current_quantity: float
|
||||
reserved_quantity: float
|
||||
available_quantity: float
|
||||
received_date: Optional[datetime]
|
||||
expiration_date: Optional[datetime]
|
||||
best_before_date: Optional[datetime]
|
||||
|
||||
# Stage-specific expiration fields
|
||||
original_expiration_date: Optional[datetime]
|
||||
transformation_date: Optional[datetime]
|
||||
final_expiration_date: Optional[datetime]
|
||||
|
||||
unit_cost: Optional[float]
|
||||
total_cost: Optional[float]
|
||||
storage_location: Optional[str]
|
||||
@@ -231,7 +260,7 @@ class StockResponse(InventoryBaseSchema):
|
||||
quality_status: str
|
||||
created_at: datetime
|
||||
updated_at: datetime
|
||||
|
||||
|
||||
# Related data
|
||||
ingredient: Optional[IngredientResponse] = None
|
||||
|
||||
@@ -278,6 +307,60 @@ class StockMovementResponse(InventoryBaseSchema):
|
||||
ingredient: Optional[IngredientResponse] = None
|
||||
|
||||
|
||||
# ===== PRODUCT TRANSFORMATION SCHEMAS =====
|
||||
|
||||
class ProductTransformationCreate(InventoryBaseSchema):
|
||||
"""Schema for creating product transformations"""
|
||||
source_ingredient_id: str = Field(..., description="Source ingredient ID")
|
||||
target_ingredient_id: str = Field(..., description="Target ingredient ID")
|
||||
source_stage: ProductionStage = Field(..., description="Source production stage")
|
||||
target_stage: ProductionStage = Field(..., description="Target production stage")
|
||||
|
||||
source_quantity: float = Field(..., gt=0, description="Input quantity")
|
||||
target_quantity: float = Field(..., gt=0, description="Output quantity")
|
||||
conversion_ratio: Optional[float] = Field(None, gt=0, description="Conversion ratio (auto-calculated if not provided)")
|
||||
|
||||
# Expiration handling
|
||||
expiration_calculation_method: str = Field("days_from_transformation", description="How to calculate expiration")
|
||||
expiration_days_offset: Optional[int] = Field(1, description="Days from transformation date for expiration")
|
||||
|
||||
# Process details
|
||||
process_notes: Optional[str] = Field(None, description="Process notes")
|
||||
target_batch_number: Optional[str] = Field(None, max_length=100, description="Target batch number")
|
||||
|
||||
# Source stock selection (optional - if not provided, uses FIFO)
|
||||
source_stock_ids: Optional[List[str]] = Field(None, description="Specific source stock IDs to transform")
|
||||
|
||||
|
||||
class ProductTransformationResponse(InventoryBaseSchema):
|
||||
"""Schema for product transformation responses"""
|
||||
id: str
|
||||
tenant_id: str
|
||||
transformation_reference: str
|
||||
source_ingredient_id: str
|
||||
target_ingredient_id: str
|
||||
source_stage: ProductionStage
|
||||
target_stage: ProductionStage
|
||||
source_quantity: float
|
||||
target_quantity: float
|
||||
conversion_ratio: float
|
||||
expiration_calculation_method: str
|
||||
expiration_days_offset: Optional[int]
|
||||
transformation_date: datetime
|
||||
process_notes: Optional[str]
|
||||
performed_by: Optional[str]
|
||||
source_batch_numbers: Optional[str]
|
||||
target_batch_number: Optional[str]
|
||||
is_completed: bool
|
||||
is_reversed: bool
|
||||
created_at: datetime
|
||||
created_by: Optional[str]
|
||||
|
||||
# Related data
|
||||
source_ingredient: Optional[IngredientResponse] = None
|
||||
target_ingredient: Optional[IngredientResponse] = None
|
||||
|
||||
|
||||
# ===== ALERT SCHEMAS =====
|
||||
|
||||
class StockAlertResponse(InventoryBaseSchema):
|
||||
@@ -379,6 +462,8 @@ class InventoryFilter(BaseModel):
|
||||
class StockFilter(BaseModel):
|
||||
"""Stock filtering parameters"""
|
||||
ingredient_id: Optional[str] = None
|
||||
production_stage: Optional[ProductionStage] = None
|
||||
transformation_reference: Optional[str] = None
|
||||
is_available: Optional[bool] = None
|
||||
is_expired: Optional[bool] = None
|
||||
expiring_within_days: Optional[int] = None
|
||||
|
||||
Reference in New Issue
Block a user