Improve te panel de control logic
This commit is contained in:
@@ -54,6 +54,74 @@ DEMO_TENANT_LA_ESPIGA = uuid.UUID("b2c3d4e5-f6a7-48b9-c0d1-e2f3a4b5c6d7")
|
||||
# Base reference date for demo data (all relative dates calculated from this)
|
||||
BASE_REFERENCE_DATE = datetime(2025, 1, 15, 12, 0, 0, tzinfo=timezone.utc)
|
||||
|
||||
# Daily consumption rates (kg/day) - aligned with procurement seed script
|
||||
# Used to create realistic stock levels that trigger appropriate PO scenarios
|
||||
DAILY_CONSUMPTION_RATES = {
|
||||
"HAR-T55-001": 50.0, # Harina de Trigo T55
|
||||
"HAR-INT-001": 15.0, # Harina Integral Ecológica
|
||||
"MAN-SAL-001": 8.0, # Mantequilla sin Sal 82% MG
|
||||
"HUE-FRE-001": 100.0, # Huevos Frescos (units, modeled as kg)
|
||||
"LEV-SEC-001": 2.5, # Levadura Seca
|
||||
"SAL-FIN-001": 3.0, # Sal Fina
|
||||
"ACE-OLI-001": 5.0, # Aceite de Oliva Virgen
|
||||
"AZU-MOR-001": 6.0, # Azúcar Moreno
|
||||
"SEM-GIR-001": 2.0, # Semillas de Girasol
|
||||
"MIE-AZA-001": 1.5, # Miel de Azahar
|
||||
"CHO-NEG-001": 4.0, # Chocolate Negro 70%
|
||||
"NUE-PEL-001": 3.5, # Nueces Peladas
|
||||
"PAS-SUL-001": 2.5 # Pasas Sultanas
|
||||
}
|
||||
|
||||
# Reorder points (kg) - when to trigger PO
|
||||
REORDER_POINTS_BY_SKU = {
|
||||
"HAR-T55-001": 150.0, # Critical ingredient
|
||||
"HAR-INT-001": 50.0,
|
||||
"MAN-SAL-001": 25.0,
|
||||
"HUE-FRE-001": 300.0,
|
||||
"LEV-SEC-001": 10.0,
|
||||
"SAL-FIN-001": 20.0,
|
||||
"ACE-OLI-001": 15.0,
|
||||
"AZU-MOR-001": 20.0,
|
||||
"SEM-GIR-001": 10.0,
|
||||
"MIE-AZA-001": 5.0,
|
||||
"CHO-NEG-001": 15.0,
|
||||
"NUE-PEL-001": 12.0,
|
||||
"PAS-SUL-001": 10.0
|
||||
}
|
||||
|
||||
def calculate_realistic_stock_level(
|
||||
ingredient_sku: str,
|
||||
make_critical: bool = False,
|
||||
variability_factor: float = 0.2
|
||||
) -> float:
|
||||
"""
|
||||
Calculate realistic stock level based on consumption rates
|
||||
|
||||
Args:
|
||||
ingredient_sku: SKU of the ingredient
|
||||
make_critical: If True, create critically low stock (< 1 day supply)
|
||||
variability_factor: Random variation (default 20%)
|
||||
|
||||
Returns:
|
||||
Realistic stock level in kg
|
||||
"""
|
||||
daily_consumption = DAILY_CONSUMPTION_RATES.get(ingredient_sku, 5.0)
|
||||
|
||||
if make_critical:
|
||||
# Critical: 0.5-6 hours worth of stock
|
||||
days_of_supply = random.uniform(0.02, 0.25)
|
||||
else:
|
||||
# Normal: 5-15 days worth of stock (healthy inventory levels)
|
||||
# This prevents all ingredients from triggering alerts
|
||||
days_of_supply = random.uniform(5.0, 15.0)
|
||||
|
||||
stock_level = daily_consumption * days_of_supply
|
||||
|
||||
# Add realistic variability
|
||||
stock_level *= random.uniform(1 - variability_factor, 1 + variability_factor)
|
||||
|
||||
return max(0.1, stock_level) # Minimum 0.1 kg
|
||||
|
||||
# Load configuration from JSON
|
||||
def load_stock_config():
|
||||
"""Load stock configuration from JSON file"""
|
||||
@@ -126,13 +194,25 @@ async def create_stock_batches_for_ingredient(
|
||||
stocks = []
|
||||
num_batches = random.randint(1, 2) # Reduced from 3-5 for faster demo loading
|
||||
|
||||
# Calculate target total stock for this ingredient
|
||||
# Use 40-80% of max_stock_level to allow for realistic variation
|
||||
# If max_stock_level is not set, use reorder_point * 3 as a reasonable target
|
||||
if ingredient.max_stock_level:
|
||||
target_total_stock = float(ingredient.max_stock_level) * random.uniform(0.4, 0.8)
|
||||
# CRITICAL DEMO SCENARIO: Create consumption-aware stock levels
|
||||
# This creates realistic scenarios that trigger intelligent PO reasoning
|
||||
critical_low_stock_skus = ["HAR-T55-001", "LEV-SEC-001", "MAN-SAL-001"]
|
||||
is_critical_low = ingredient.sku in critical_low_stock_skus
|
||||
|
||||
# Calculate target total stock using consumption-aware logic
|
||||
if is_critical_low:
|
||||
# Critical low: < 1 day supply (triggers urgent/critical PO reasoning)
|
||||
target_total_stock = calculate_realistic_stock_level(
|
||||
ingredient.sku,
|
||||
make_critical=True
|
||||
)
|
||||
num_batches = 1 # Single nearly-empty batch for critical items
|
||||
else:
|
||||
target_total_stock = float(ingredient.reorder_point or 50.0) * 3.0
|
||||
# Normal low stock: 1-4 days supply (creates urgency but not critical)
|
||||
target_total_stock = calculate_realistic_stock_level(
|
||||
ingredient.sku,
|
||||
make_critical=False
|
||||
)
|
||||
|
||||
# Distribute total stock across batches
|
||||
batch_quantities = []
|
||||
|
||||
Reference in New Issue
Block a user