Improve demo seed

This commit is contained in:
Urtzi Alfaro
2025-10-17 07:31:14 +02:00
parent b6cb800758
commit d4060962e4
56 changed files with 8235 additions and 339 deletions

View File

@@ -1,6 +1,6 @@
"""
Internal Demo Cloning API for Inventory Service
Service-to-service endpoint for cloning inventory data
Service-to-service endpoint for cloning inventory data with date adjustment
"""
from fastapi import APIRouter, Depends, HTTPException, Header
@@ -11,9 +11,15 @@ import uuid
from datetime import datetime, timezone
from typing import Optional
import os
import sys
from pathlib import Path
# Add shared path
sys.path.insert(0, str(Path(__file__).parent.parent.parent.parent.parent))
from app.core.database import get_db
from app.models.inventory import Ingredient
from app.models.inventory import Ingredient, Stock
from shared.utils.demo_dates import adjust_date_for_demo, BASE_REFERENCE_DATE
logger = structlog.get_logger()
router = APIRouter(prefix="/internal/demo", tags=["internal"])
@@ -48,7 +54,8 @@ async def clone_demo_data(
Clones:
- Ingredients from template tenant
- (Future: recipes, stock data, etc.)
- Stock batches with date-adjusted expiration dates
- Generates inventory alerts based on stock status
Args:
base_tenant_id: Template tenant UUID to clone from
@@ -60,13 +67,15 @@ async def clone_demo_data(
Cloning status and record counts
"""
start_time = datetime.now(timezone.utc)
session_created_at = datetime.now(timezone.utc)
logger.info(
"Starting inventory data cloning",
"Starting inventory data cloning with date adjustment",
base_tenant_id=base_tenant_id,
virtual_tenant_id=virtual_tenant_id,
demo_account_type=demo_account_type,
session_id=session_id
session_id=session_id,
session_created_at=session_created_at.isoformat()
)
try:
@@ -77,9 +86,13 @@ async def clone_demo_data(
# Track cloning statistics
stats = {
"ingredients": 0,
# Add other entities here in future
"stock_batches": 0,
"alerts_generated": 0
}
# Mapping from base ingredient ID to virtual ingredient ID
ingredient_id_mapping = {}
# Clone Ingredients
result = await db.execute(
select(Ingredient).where(Ingredient.tenant_id == base_uuid)
@@ -94,8 +107,9 @@ async def clone_demo_data(
for ingredient in base_ingredients:
# Create new ingredient with same attributes but new ID and tenant
new_ingredient_id = uuid.uuid4()
new_ingredient = Ingredient(
id=uuid.uuid4(),
id=new_ingredient_id,
tenant_id=virtual_uuid,
name=ingredient.name,
sku=ingredient.sku,
@@ -116,21 +130,123 @@ async def clone_demo_data(
reorder_quantity=ingredient.reorder_quantity,
max_stock_level=ingredient.max_stock_level,
shelf_life_days=ingredient.shelf_life_days,
display_life_hours=ingredient.display_life_hours,
best_before_hours=ingredient.best_before_hours,
storage_instructions=ingredient.storage_instructions,
is_perishable=ingredient.is_perishable,
is_active=ingredient.is_active,
allergen_info=ingredient.allergen_info
allergen_info=ingredient.allergen_info,
nutritional_info=ingredient.nutritional_info
)
db.add(new_ingredient)
stats["ingredients"] += 1
# Store mapping for stock cloning
ingredient_id_mapping[ingredient.id] = new_ingredient_id
await db.flush() # Ensure ingredients are persisted before stock
# Clone Stock batches with date adjustment
result = await db.execute(
select(Stock).where(Stock.tenant_id == base_uuid)
)
base_stocks = result.scalars().all()
logger.info(
"Found stock batches to clone",
count=len(base_stocks),
base_tenant=str(base_uuid)
)
for stock in base_stocks:
# Map ingredient ID
new_ingredient_id = ingredient_id_mapping.get(stock.ingredient_id)
if not new_ingredient_id:
logger.warning(
"Stock references non-existent ingredient, skipping",
stock_id=str(stock.id),
ingredient_id=str(stock.ingredient_id)
)
continue
# Adjust dates relative to session creation
adjusted_expiration = adjust_date_for_demo(
stock.expiration_date,
session_created_at,
BASE_REFERENCE_DATE
)
adjusted_received = adjust_date_for_demo(
stock.received_date,
session_created_at,
BASE_REFERENCE_DATE
)
adjusted_best_before = adjust_date_for_demo(
stock.best_before_date,
session_created_at,
BASE_REFERENCE_DATE
)
adjusted_created = adjust_date_for_demo(
stock.created_at,
session_created_at,
BASE_REFERENCE_DATE
) or session_created_at
# Create new stock batch
new_stock = Stock(
id=uuid.uuid4(),
tenant_id=virtual_uuid,
ingredient_id=new_ingredient_id,
supplier_id=stock.supplier_id,
batch_number=stock.batch_number,
lot_number=stock.lot_number,
supplier_batch_ref=stock.supplier_batch_ref,
production_stage=stock.production_stage,
current_quantity=stock.current_quantity,
reserved_quantity=stock.reserved_quantity,
available_quantity=stock.available_quantity,
received_date=adjusted_received,
expiration_date=adjusted_expiration,
best_before_date=adjusted_best_before,
unit_cost=stock.unit_cost,
total_cost=stock.total_cost,
storage_location=stock.storage_location,
warehouse_zone=stock.warehouse_zone,
shelf_position=stock.shelf_position,
requires_refrigeration=stock.requires_refrigeration,
requires_freezing=stock.requires_freezing,
storage_temperature_min=stock.storage_temperature_min,
storage_temperature_max=stock.storage_temperature_max,
storage_humidity_max=stock.storage_humidity_max,
shelf_life_days=stock.shelf_life_days,
storage_instructions=stock.storage_instructions,
is_available=stock.is_available,
is_expired=stock.is_expired,
quality_status=stock.quality_status,
created_at=adjusted_created,
updated_at=session_created_at
)
db.add(new_stock)
stats["stock_batches"] += 1
# Commit all changes
await db.commit()
# Generate inventory alerts
try:
from shared.utils.alert_generator import generate_inventory_alerts
alerts_count = await generate_inventory_alerts(db, virtual_uuid, session_created_at)
stats["alerts_generated"] = alerts_count
await db.commit() # Commit alerts
logger.info(f"Generated {alerts_count} inventory alerts", virtual_tenant_id=virtual_tenant_id)
except Exception as e:
logger.warning(f"Failed to generate alerts: {str(e)}", exc_info=True)
stats["alerts_generated"] = 0
total_records = sum(stats.values())
duration_ms = int((datetime.now(timezone.utc) - start_time).total_seconds() * 1000)
logger.info(
"Inventory data cloning completed",
"Inventory data cloning completed with date adjustment",
virtual_tenant_id=virtual_tenant_id,
total_records=total_records,
stats=stats,

View File

@@ -303,6 +303,7 @@ class Stock(Base):
'id': str(self.id),
'tenant_id': str(self.tenant_id),
'ingredient_id': str(self.ingredient_id),
'supplier_id': str(self.supplier_id) if self.supplier_id else None,
'batch_number': self.batch_number,
'lot_number': self.lot_number,
'supplier_batch_ref': self.supplier_batch_ref,