Improve te panel de control logic

This commit is contained in:
Urtzi Alfaro
2025-11-21 16:15:09 +01:00
parent 2ee94fb4b1
commit 3242c8d837
21 changed files with 2805 additions and 696 deletions

View File

@@ -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 = []