Improve the frontend and fix TODOs

This commit is contained in:
Urtzi Alfaro
2025-10-24 13:05:04 +02:00
parent 07c33fa578
commit 61376b7a9f
100 changed files with 8284 additions and 3419 deletions

View File

@@ -100,6 +100,9 @@ class DashboardService:
stock_value_trend = await self._get_stock_value_trend(db, tenant_id, days=30)
alert_trend = await dashboard_repo.get_alert_trend(tenant_id, days=30)
# Get stock summary for total stock items
stock_summary = await repos['stock_repo'].get_stock_summary_by_tenant(tenant_id)
# Recent activity
recent_activity = await self.get_recent_activity(db, tenant_id, limit=10)
@@ -108,7 +111,7 @@ class DashboardService:
total_ingredients=inventory_summary.total_ingredients,
active_ingredients=inventory_summary.total_ingredients, # Assuming all are active
total_stock_value=inventory_summary.total_stock_value,
total_stock_items=await self._get_total_stock_items(db, tenant_id),
total_stock_items=stock_summary.get('total_stock_items', 0),
# Stock status breakdown
in_stock_items=await self._get_in_stock_count(db, tenant_id),
@@ -872,6 +875,201 @@ class DashboardService:
"temperature_compliance_rate": Decimal("100")
}
async def _get_in_stock_count(self, db, tenant_id: UUID) -> int:
"""Get count of items currently in stock"""
try:
repos = self._get_repositories(db)
stock_repo = repos['stock_repo']
# Get stock summary and extract in-stock count
stock_summary = await stock_repo.get_stock_summary_by_tenant(tenant_id)
return stock_summary.get('in_stock_items', 0)
except Exception as e:
logger.error("Failed to get in-stock count", error=str(e))
return 0
async def _get_ingredient_metrics(self, db, tenant_id: UUID) -> Dict[str, Any]:
"""Get ingredient metrics for business model analysis"""
try:
repos = self._get_repositories(db)
ingredient_repo = repos['ingredient_repo']
# Get all ingredients for the tenant
ingredients = await ingredient_repo.get_ingredients_by_tenant(tenant_id, limit=1000)
if not ingredients:
return {
"total_types": 0,
"avg_stock": 0.0,
"finished_product_ratio": 0.0,
"supplier_count": 0
}
# Calculate metrics
total_types = len(ingredients)
# Calculate average stock per ingredient
total_stock = sum(float(i.current_stock_level or 0) for i in ingredients)
avg_stock = total_stock / total_types if total_types > 0 else 0
# Calculate finished product ratio
finished_products = len([i for i in ingredients if hasattr(i, 'product_type') and i.product_type and i.product_type.value == 'finished_product'])
finished_ratio = finished_products / total_types if total_types > 0 else 0
# Estimate supplier diversity (simplified)
supplier_count = len(set(str(i.supplier_id) for i in ingredients if hasattr(i, 'supplier_id') and i.supplier_id)) or 1
return {
"total_types": total_types,
"avg_stock": avg_stock,
"finished_product_ratio": finished_ratio,
"supplier_count": supplier_count
}
except Exception as e:
logger.error("Failed to get ingredient metrics", error=str(e))
return {
"total_types": 0,
"avg_stock": 0.0,
"finished_product_ratio": 0.0,
"supplier_count": 0
}
async def _analyze_operational_patterns(self, db, tenant_id: UUID) -> Dict[str, Any]:
"""Analyze operational patterns for business model insights"""
try:
repos = self._get_repositories(db)
# Get ingredients to analyze patterns
ingredients = await repos['ingredient_repo'].get_ingredients_by_tenant(tenant_id, limit=1000)
if not ingredients:
return {
"order_frequency": "unknown",
"seasonal_variation": "low",
"bulk_indicator": "unknown",
"scale_indicator": "small"
}
# Analyze order frequency based on reorder patterns
frequent_reorders = len([i for i in ingredients if hasattr(i, 'reorder_frequency') and i.reorder_frequency and i.reorder_frequency > 5])
infrequent_reorders = len([i for i in ingredients if hasattr(i, 'reorder_frequency') and i.reorder_frequency and i.reorder_frequency <= 2])
if frequent_reorders > len(ingredients) * 0.3:
order_frequency = "high"
elif infrequent_reorders > len(ingredients) * 0.4:
order_frequency = "low"
else:
order_frequency = "moderate"
# Analyze seasonal variation (simplified estimation)
seasonal_variation = "moderate" # Default assumption for bakery business
# Analyze bulk purchasing indicator
bulk_items = len([i for i in ingredients if hasattr(i, 'bulk_order_quantity') and i.bulk_order_quantity and i.bulk_order_quantity > 100])
if bulk_items > len(ingredients) * 0.2:
bulk_indicator = "high"
elif bulk_items < len(ingredients) * 0.05:
bulk_indicator = "low"
else:
bulk_indicator = "moderate"
# Analyze production scale
total_ingredients = len(ingredients)
if total_ingredients > 500:
scale_indicator = "large"
elif total_ingredients > 100:
scale_indicator = "medium"
else:
scale_indicator = "small"
return {
"order_frequency": order_frequency,
"seasonal_variation": seasonal_variation,
"bulk_indicator": bulk_indicator,
"scale_indicator": scale_indicator
}
except Exception as e:
logger.error("Failed to analyze operational patterns", error=str(e))
return {
"order_frequency": "unknown",
"seasonal_variation": "low",
"bulk_indicator": "unknown",
"scale_indicator": "small"
}
async def _generate_model_recommendations(
self,
model: str,
ingredient_metrics: Dict[str, Any],
operational_patterns: Dict[str, Any]
) -> Dict[str, Any]:
"""Generate business model specific recommendations"""
try:
recommendations = {
"specific": [],
"optimization": []
}
# Model-specific recommendations
if model == "central_bakery":
recommendations["specific"].extend([
"Optimize distribution network for multi-location delivery",
"Implement centralized procurement for bulk discounts",
"Standardize recipes across all production facilities"
])
if operational_patterns.get("scale_indicator") == "large":
recommendations["optimization"].extend([
"Automate inter-facility transfers",
"Implement predictive demand forecasting",
"Optimize fleet routing for distribution"
])
elif model == "individual_bakery":
recommendations["specific"].extend([
"Focus on local sourcing to reduce costs",
"Implement just-in-time production scheduling",
"Optimize single-location workflow efficiency"
])
recommendations["optimization"].extend([
"Reduce waste through better portion control",
"Implement daily production planning",
"Optimize oven scheduling for energy efficiency"
])
elif model == "mixed":
recommendations["specific"].extend([
"Balance centralized and decentralized operations",
"Implement hybrid sourcing strategy",
"Maintain flexibility in production planning"
])
recommendations["optimization"].extend([
"Optimize batch sizes for efficiency",
"Implement cross-training for staff flexibility",
"Balance inventory across multiple locations"
])
# Generic recommendations based on metrics
if ingredient_metrics.get("finished_product_ratio", 0) > 0.5:
recommendations["optimization"].append("Focus on finished product quality control")
if operational_patterns.get("order_frequency") == "high":
recommendations["optimization"].append("Streamline ordering process with automated reordering")
return recommendations
except Exception as e:
logger.error("Failed to generate model recommendations", error=str(e))
return {
"specific": ["Review business model configuration"],
"optimization": ["Analyze operational data for insights"]
}
async def _analyze_inventory_performance(self, db, tenant_id: UUID, days_back: int) -> Dict[str, Any]:
"""Analyze overall inventory performance metrics using real data"""
try: