New enterprise feature

This commit is contained in:
Urtzi Alfaro
2025-11-30 09:12:40 +01:00
parent f9d0eec6ec
commit 972db02f6d
176 changed files with 19741 additions and 1361 deletions

View File

@@ -33,8 +33,8 @@ from shared.schemas.reasoning_types import create_batch_reasoning_forecast_deman
logger = structlog.get_logger()
# Base demo tenant IDs
DEMO_TENANT_SAN_PABLO = uuid.UUID("a1b2c3d4-e5f6-47a8-b9c0-d1e2f3a4b5c6") # Individual bakery
DEMO_TENANT_LA_ESPIGA = uuid.UUID("b2c3d4e5-f6a7-48b9-c0d1-e2f3a4b5c6d7") # Central bakery
DEMO_TENANT_PROFESSIONAL = uuid.UUID("a1b2c3d4-e5f6-47a8-b9c0-d1e2f3a4b5c6") # Individual bakery
DEMO_TENANT_ENTERPRISE_CHAIN = uuid.UUID("c3d4e5f6-a7b8-49c0-d1e2-f3a4b5c6d7e8") # Enterprise parent (Obrador)
# Base reference date for date calculations
# MUST match shared/utils/demo_dates.py for proper demo session cloning
@@ -145,7 +145,8 @@ async def seed_batches_for_tenant(
elif batch_data["status"] == "IN_PROGRESS":
# For IN_PROGRESS batches, set actual_start to a recent time to ensure valid progress calculation
# If planned_start is in the past, use it; otherwise, set to 30 minutes ago
now = datetime.now(timezone.utc)
# Use BASE_REFERENCE_DATE as "now" for consistent demo data
now = BASE_REFERENCE_DATE
if planned_start < now:
# If planned start was in the past, use a time that ensures batch is ~30% complete
elapsed_time_minutes = min(
@@ -160,7 +161,7 @@ async def seed_batches_for_tenant(
actual_end = None
# For San Pablo, use original IDs. For La Espiga, generate new UUIDs
if tenant_id == DEMO_TENANT_SAN_PABLO:
if tenant_id == DEMO_TENANT_PROFESSIONAL:
batch_id = uuid.UUID(batch_data["id"])
else:
# Generate deterministic UUID for La Espiga based on original ID
@@ -174,7 +175,7 @@ async def seed_batches_for_tenant(
current_stage = map_process_stage(batch_data.get("current_process_stage"))
# Create unique batch number for each tenant
if tenant_id == DEMO_TENANT_SAN_PABLO:
if tenant_id == DEMO_TENANT_PROFESSIONAL:
batch_number = batch_data["batch_number"]
else:
# For La Espiga, append tenant suffix to make batch number unique
@@ -268,22 +269,23 @@ async def seed_all(db: AsyncSession):
results = []
# Both tenants get the same production batches
result_san_pablo = await seed_batches_for_tenant(
# Seed Professional Bakery with production batches (single location)
result_professional = await seed_batches_for_tenant(
db,
DEMO_TENANT_SAN_PABLO,
"San Pablo - Individual Bakery",
DEMO_TENANT_PROFESSIONAL,
"Panadería Artesana Madrid (Professional)",
data["lotes_produccion"]
)
results.append(result_san_pablo)
results.append(result_professional)
result_la_espiga = await seed_batches_for_tenant(
# Seed Enterprise Parent (central production - Obrador) with scaled-up batches
result_enterprise_parent = await seed_batches_for_tenant(
db,
DEMO_TENANT_LA_ESPIGA,
"La Espiga - Central Bakery",
DEMO_TENANT_ENTERPRISE_CHAIN,
"Panadería Central - Obrador Madrid (Enterprise Parent)",
data["lotes_produccion"]
)
results.append(result_la_espiga)
results.append(result_enterprise_parent)
total_created = sum(r["batches_created"] for r in results)

View File

@@ -33,8 +33,8 @@ from shared.utils.demo_dates import BASE_REFERENCE_DATE
logger = structlog.get_logger()
# Base demo tenant IDs
DEMO_TENANT_SAN_PABLO = uuid.UUID("a1b2c3d4-e5f6-47a8-b9c0-d1e2f3a4b5c6") # Individual bakery
DEMO_TENANT_LA_ESPIGA = uuid.UUID("b2c3d4e5-f6a7-48b9-c0d1-e2f3a4b5c6d7") # Central bakery
DEMO_TENANT_PROFESSIONAL = uuid.UUID("a1b2c3d4-e5f6-47a8-b9c0-d1e2f3a4b5c6") # Individual bakery
DEMO_TENANT_ENTERPRISE_CHAIN = uuid.UUID("c3d4e5f6-a7b8-49c0-d1e2-f3a4b5c6d7e8") # Enterprise parent (Obrador)
def load_equipment_data():
@@ -109,9 +109,14 @@ async def seed_equipment_for_tenant(
}
equipment_type = type_mapping.get(equip_data["type"], EquipmentType.OTHER)
# Generate tenant-specific equipment ID using XOR transformation
base_equipment_id = uuid.UUID(equip_data["id"])
tenant_int = int(tenant_id.hex, 16)
equipment_id = uuid.UUID(int=tenant_int ^ int(base_equipment_id.hex, 16))
# Create equipment
equipment = Equipment(
id=uuid.UUID(equip_data["id"]),
id=equipment_id,
tenant_id=tenant_id,
name=equip_data["name"],
type=equipment_type,
@@ -156,23 +161,25 @@ async def seed_all(db: AsyncSession):
results = []
# Seed San Pablo (Individual Bakery)
result_san_pablo = await seed_equipment_for_tenant(
# Seed Professional Bakery with equipment (single location)
result_professional = await seed_equipment_for_tenant(
db,
DEMO_TENANT_SAN_PABLO,
"San Pablo - Individual Bakery",
DEMO_TENANT_PROFESSIONAL,
"Panadería Artesana Madrid (Professional)",
data["equipos_individual_bakery"]
)
results.append(result_san_pablo)
results.append(result_professional)
# Seed La Espiga (Central Bakery)
result_la_espiga = await seed_equipment_for_tenant(
# Seed Enterprise Parent (central production - Obrador) with scaled-up equipment
# Use enterprise equipment list if available, otherwise use individual bakery equipment
enterprise_equipment_key = "equipos_enterprise_chain" if "equipos_enterprise_chain" in data else "equipos_individual_bakery"
result_enterprise_parent = await seed_equipment_for_tenant(
db,
DEMO_TENANT_LA_ESPIGA,
"La Espiga - Central Bakery",
data["equipos_central_bakery"]
DEMO_TENANT_ENTERPRISE_CHAIN,
"Panadería Central - Obrador Madrid (Enterprise Parent)",
data[enterprise_equipment_key]
)
results.append(result_la_espiga)
results.append(result_enterprise_parent)
total_created = sum(r["equipment_created"] for r in results)

View File

@@ -33,8 +33,8 @@ from shared.utils.demo_dates import BASE_REFERENCE_DATE
logger = structlog.get_logger()
# Base demo tenant IDs
DEMO_TENANT_SAN_PABLO = uuid.UUID("a1b2c3d4-e5f6-47a8-b9c0-d1e2f3a4b5c6") # Individual bakery
DEMO_TENANT_LA_ESPIGA = uuid.UUID("b2c3d4e5-f6a7-48b9-c0d1-e2f3a4b5c6d7") # Central bakery
DEMO_TENANT_PROFESSIONAL = uuid.UUID("a1b2c3d4-e5f6-47a8-b9c0-d1e2f3a4b5c6") # Individual bakery
DEMO_TENANT_ENTERPRISE_CHAIN = uuid.UUID("c3d4e5f6-a7b8-49c0-d1e2-f3a4b5c6d7e8") # Enterprise parent (Obrador)
# System user ID (first admin user from auth service)
SYSTEM_USER_ID = uuid.UUID("50000000-0000-0000-0000-000000000004")
@@ -79,7 +79,7 @@ async def seed_quality_templates_for_tenant(
applicable_stages = template_data.get("applicable_stages", [])
# For San Pablo, use original IDs. For La Espiga, generate new UUIDs
if tenant_id == DEMO_TENANT_SAN_PABLO:
if tenant_id == DEMO_TENANT_PROFESSIONAL:
template_id = uuid.UUID(template_data["id"])
else:
# Generate deterministic UUID for La Espiga based on original ID
@@ -138,22 +138,23 @@ async def seed_all(db: AsyncSession):
results = []
# Both tenants get the same quality templates
result_san_pablo = await seed_quality_templates_for_tenant(
# Seed Professional Bakery with quality templates (single location)
result_professional = await seed_quality_templates_for_tenant(
db,
DEMO_TENANT_SAN_PABLO,
"San Pablo - Individual Bakery",
DEMO_TENANT_PROFESSIONAL,
"Panadería Artesana Madrid (Professional)",
data["plantillas_calidad"]
)
results.append(result_san_pablo)
results.append(result_professional)
result_la_espiga = await seed_quality_templates_for_tenant(
# Seed Enterprise Parent (central production - Obrador) with same quality templates
result_enterprise_parent = await seed_quality_templates_for_tenant(
db,
DEMO_TENANT_LA_ESPIGA,
"La Espiga - Central Bakery",
DEMO_TENANT_ENTERPRISE_CHAIN,
"Panadería Central - Obrador Madrid (Enterprise Parent)",
data["plantillas_calidad"]
)
results.append(result_la_espiga)
results.append(result_enterprise_parent)
total_created = sum(r["templates_created"] for r in results)