REFACTOR ALL APIs fix 1
This commit is contained in:
@@ -107,3 +107,166 @@ class MultiDayForecastResponse(BaseModel):
|
||||
processing_time_ms: int = Field(..., description="Total processing time")
|
||||
|
||||
|
||||
# ================================================================
|
||||
# SCENARIO SIMULATION SCHEMAS - PROFESSIONAL/ENTERPRISE ONLY
|
||||
# ================================================================
|
||||
|
||||
class ScenarioType(str, Enum):
|
||||
"""Types of scenarios available for simulation"""
|
||||
WEATHER = "weather" # Weather impact (heatwave, cold snap, rain, etc.)
|
||||
COMPETITION = "competition" # New competitor opening nearby
|
||||
EVENT = "event" # Local event (festival, sports, concert, etc.)
|
||||
PRICING = "pricing" # Price changes
|
||||
PROMOTION = "promotion" # Promotional campaigns
|
||||
HOLIDAY = "holiday" # Holiday periods
|
||||
SUPPLY_DISRUPTION = "supply_disruption" # Supply chain issues
|
||||
CUSTOM = "custom" # Custom user-defined scenario
|
||||
|
||||
|
||||
class WeatherScenario(BaseModel):
|
||||
"""Weather scenario parameters"""
|
||||
temperature_change: Optional[float] = Field(None, ge=-30, le=30, description="Temperature change in °C")
|
||||
precipitation_change: Optional[float] = Field(None, ge=0, le=100, description="Precipitation change in mm")
|
||||
weather_type: Optional[str] = Field(None, description="Weather type (heatwave, cold_snap, rainy, etc.)")
|
||||
|
||||
|
||||
class CompetitionScenario(BaseModel):
|
||||
"""Competition scenario parameters"""
|
||||
new_competitors: int = Field(1, ge=1, le=10, description="Number of new competitors")
|
||||
distance_km: float = Field(0.5, ge=0.1, le=10, description="Distance from location in km")
|
||||
estimated_market_share_loss: float = Field(0.1, ge=0, le=0.5, description="Estimated market share loss (0-50%)")
|
||||
|
||||
|
||||
class EventScenario(BaseModel):
|
||||
"""Event scenario parameters"""
|
||||
event_type: str = Field(..., description="Type of event (festival, sports, concert, etc.)")
|
||||
expected_attendance: int = Field(..., ge=0, description="Expected attendance")
|
||||
distance_km: float = Field(0.5, ge=0, le=50, description="Distance from location in km")
|
||||
duration_days: int = Field(1, ge=1, le=30, description="Duration in days")
|
||||
|
||||
|
||||
class PricingScenario(BaseModel):
|
||||
"""Pricing scenario parameters"""
|
||||
price_change_percent: float = Field(..., ge=-50, le=100, description="Price change percentage")
|
||||
affected_products: Optional[List[str]] = Field(None, description="List of affected product IDs")
|
||||
|
||||
|
||||
class PromotionScenario(BaseModel):
|
||||
"""Promotion scenario parameters"""
|
||||
discount_percent: float = Field(..., ge=0, le=75, description="Discount percentage")
|
||||
promotion_type: str = Field(..., description="Type of promotion (bogo, discount, bundle, etc.)")
|
||||
expected_traffic_increase: float = Field(0.2, ge=0, le=2, description="Expected traffic increase (0-200%)")
|
||||
|
||||
|
||||
class ScenarioSimulationRequest(BaseModel):
|
||||
"""Request schema for scenario simulation - PROFESSIONAL/ENTERPRISE ONLY"""
|
||||
scenario_name: str = Field(..., min_length=3, max_length=200, description="Name for this scenario")
|
||||
scenario_type: ScenarioType = Field(..., description="Type of scenario to simulate")
|
||||
inventory_product_ids: List[str] = Field(..., min_items=1, description="Products to simulate")
|
||||
start_date: date = Field(..., description="Simulation start date")
|
||||
duration_days: int = Field(7, ge=1, le=30, description="Simulation duration in days")
|
||||
|
||||
# Scenario-specific parameters (one should be provided based on scenario_type)
|
||||
weather_params: Optional[WeatherScenario] = None
|
||||
competition_params: Optional[CompetitionScenario] = None
|
||||
event_params: Optional[EventScenario] = None
|
||||
pricing_params: Optional[PricingScenario] = None
|
||||
promotion_params: Optional[PromotionScenario] = None
|
||||
|
||||
# Custom scenario parameters
|
||||
custom_multipliers: Optional[Dict[str, float]] = Field(
|
||||
None,
|
||||
description="Custom multipliers for baseline forecast (e.g., {'demand': 1.2, 'traffic': 0.8})"
|
||||
)
|
||||
|
||||
# Comparison settings
|
||||
include_baseline: bool = Field(True, description="Include baseline forecast for comparison")
|
||||
|
||||
@validator('start_date')
|
||||
def validate_start_date(cls, v):
|
||||
if v < date.today():
|
||||
raise ValueError("Simulation start date cannot be in the past")
|
||||
return v
|
||||
|
||||
|
||||
class ScenarioImpact(BaseModel):
|
||||
"""Impact of scenario on a specific product"""
|
||||
inventory_product_id: str
|
||||
baseline_demand: float
|
||||
simulated_demand: float
|
||||
demand_change_percent: float
|
||||
confidence_range: tuple[float, float]
|
||||
impact_factors: Dict[str, Any] # Breakdown of what drove the change
|
||||
|
||||
|
||||
class ScenarioSimulationResponse(BaseModel):
|
||||
"""Response schema for scenario simulation"""
|
||||
id: str = Field(..., description="Simulation ID")
|
||||
tenant_id: str
|
||||
scenario_name: str
|
||||
scenario_type: ScenarioType
|
||||
|
||||
# Simulation parameters
|
||||
start_date: date
|
||||
end_date: date
|
||||
duration_days: int
|
||||
|
||||
# Results
|
||||
baseline_forecasts: Optional[List[ForecastResponse]] = Field(
|
||||
None,
|
||||
description="Baseline forecasts (if requested)"
|
||||
)
|
||||
scenario_forecasts: List[ForecastResponse] = Field(..., description="Forecasts with scenario applied")
|
||||
|
||||
# Impact summary
|
||||
total_baseline_demand: float
|
||||
total_scenario_demand: float
|
||||
overall_impact_percent: float
|
||||
product_impacts: List[ScenarioImpact]
|
||||
|
||||
# Insights and recommendations
|
||||
insights: List[str] = Field(..., description="AI-generated insights about the scenario")
|
||||
recommendations: List[str] = Field(..., description="Actionable recommendations")
|
||||
risk_level: str = Field(..., description="Risk level: low, medium, high")
|
||||
|
||||
# Metadata
|
||||
created_at: datetime
|
||||
processing_time_ms: int
|
||||
|
||||
class Config:
|
||||
json_schema_extra = {
|
||||
"example": {
|
||||
"id": "scenario_123",
|
||||
"tenant_id": "tenant_456",
|
||||
"scenario_name": "Summer Heatwave Impact",
|
||||
"scenario_type": "weather",
|
||||
"overall_impact_percent": 15.5,
|
||||
"insights": [
|
||||
"Cold beverages expected to increase by 45%",
|
||||
"Bread products may decrease by 8% due to reduced appetite",
|
||||
"Ice cream demand projected to surge by 120%"
|
||||
],
|
||||
"recommendations": [
|
||||
"Increase cold beverage inventory by 40%",
|
||||
"Reduce bread production by 10%",
|
||||
"Stock additional ice cream varieties"
|
||||
],
|
||||
"risk_level": "medium"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class ScenarioComparisonRequest(BaseModel):
|
||||
"""Request to compare multiple scenarios"""
|
||||
scenario_ids: List[str] = Field(..., min_items=2, max_items=5, description="Scenario IDs to compare")
|
||||
|
||||
|
||||
class ScenarioComparisonResponse(BaseModel):
|
||||
"""Response comparing multiple scenarios"""
|
||||
scenarios: List[ScenarioSimulationResponse]
|
||||
comparison_matrix: Dict[str, Dict[str, Any]]
|
||||
best_case_scenario_id: str
|
||||
worst_case_scenario_id: str
|
||||
recommended_action: str
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user