2025-12-27 21:30:42 +01:00
|
|
|
"""
|
|
|
|
|
Onboarding Status API
|
|
|
|
|
Provides lightweight onboarding status checks by aggregating counts from multiple services
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
from fastapi import APIRouter, Depends, HTTPException
|
|
|
|
|
from sqlalchemy.ext.asyncio import AsyncSession
|
|
|
|
|
import structlog
|
|
|
|
|
import asyncio
|
|
|
|
|
import httpx
|
|
|
|
|
import os
|
|
|
|
|
|
|
|
|
|
from app.core.database import get_db
|
|
|
|
|
from app.core.config import settings
|
|
|
|
|
from shared.auth.decorators import get_current_tenant_id_dep
|
|
|
|
|
from shared.routing.route_builder import RouteBuilder
|
|
|
|
|
|
|
|
|
|
logger = structlog.get_logger()
|
|
|
|
|
router = APIRouter()
|
|
|
|
|
route_builder = RouteBuilder("tenants")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@router.get(route_builder.build_base_route("{tenant_id}/onboarding/status", include_tenant_prefix=False))
|
|
|
|
|
async def get_onboarding_status(
|
|
|
|
|
tenant_id: str,
|
|
|
|
|
db: AsyncSession = Depends(get_db)
|
|
|
|
|
):
|
|
|
|
|
"""
|
|
|
|
|
Get lightweight onboarding status by fetching counts from each service.
|
|
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
|
- ingredients_count: Number of active ingredients
|
|
|
|
|
- suppliers_count: Number of active suppliers
|
|
|
|
|
- recipes_count: Number of active recipes
|
|
|
|
|
- has_minimum_setup: Boolean indicating if minimum requirements are met
|
|
|
|
|
- progress_percentage: Overall onboarding progress (0-100)
|
|
|
|
|
"""
|
|
|
|
|
try:
|
|
|
|
|
# Service URLs from environment
|
|
|
|
|
inventory_url = os.getenv("INVENTORY_SERVICE_URL", "http://inventory-service:8000")
|
|
|
|
|
suppliers_url = os.getenv("SUPPLIERS_SERVICE_URL", "http://suppliers-service:8000")
|
|
|
|
|
recipes_url = os.getenv("RECIPES_SERVICE_URL", "http://recipes-service:8000")
|
|
|
|
|
|
2026-01-12 14:24:14 +01:00
|
|
|
|
2025-12-27 21:30:42 +01:00
|
|
|
# Fetch counts from all services in parallel
|
|
|
|
|
async with httpx.AsyncClient(timeout=10.0) as client:
|
|
|
|
|
results = await asyncio.gather(
|
|
|
|
|
client.get(
|
|
|
|
|
f"{inventory_url}/internal/count",
|
2026-01-12 14:24:14 +01:00
|
|
|
params={"tenant_id": tenant_id}
|
2025-12-27 21:30:42 +01:00
|
|
|
),
|
|
|
|
|
client.get(
|
|
|
|
|
f"{suppliers_url}/internal/count",
|
2026-01-12 14:24:14 +01:00
|
|
|
params={"tenant_id": tenant_id}
|
2025-12-27 21:30:42 +01:00
|
|
|
),
|
|
|
|
|
client.get(
|
|
|
|
|
f"{recipes_url}/internal/count",
|
2026-01-12 14:24:14 +01:00
|
|
|
params={"tenant_id": tenant_id}
|
2025-12-27 21:30:42 +01:00
|
|
|
),
|
|
|
|
|
return_exceptions=True
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
# Extract counts with fallback to 0
|
|
|
|
|
ingredients_count = 0
|
|
|
|
|
suppliers_count = 0
|
|
|
|
|
recipes_count = 0
|
|
|
|
|
|
|
|
|
|
if not isinstance(results[0], Exception) and results[0].status_code == 200:
|
|
|
|
|
ingredients_count = results[0].json().get("count", 0)
|
|
|
|
|
|
|
|
|
|
if not isinstance(results[1], Exception) and results[1].status_code == 200:
|
|
|
|
|
suppliers_count = results[1].json().get("count", 0)
|
|
|
|
|
|
|
|
|
|
if not isinstance(results[2], Exception) and results[2].status_code == 200:
|
|
|
|
|
recipes_count = results[2].json().get("count", 0)
|
|
|
|
|
|
|
|
|
|
# Calculate minimum setup requirements
|
|
|
|
|
# Minimum: 3 ingredients, 1 supplier, 1 recipe
|
|
|
|
|
has_minimum_ingredients = ingredients_count >= 3
|
|
|
|
|
has_minimum_suppliers = suppliers_count >= 1
|
|
|
|
|
has_minimum_recipes = recipes_count >= 1
|
|
|
|
|
|
|
|
|
|
has_minimum_setup = all([
|
|
|
|
|
has_minimum_ingredients,
|
|
|
|
|
has_minimum_suppliers,
|
|
|
|
|
has_minimum_recipes
|
|
|
|
|
])
|
|
|
|
|
|
|
|
|
|
# Calculate progress percentage
|
|
|
|
|
# Each requirement contributes 33.33%
|
|
|
|
|
progress = 0
|
|
|
|
|
if has_minimum_ingredients:
|
|
|
|
|
progress += 33
|
|
|
|
|
if has_minimum_suppliers:
|
|
|
|
|
progress += 33
|
|
|
|
|
if has_minimum_recipes:
|
|
|
|
|
progress += 34
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
"ingredients_count": ingredients_count,
|
|
|
|
|
"suppliers_count": suppliers_count,
|
|
|
|
|
"recipes_count": recipes_count,
|
|
|
|
|
"has_minimum_setup": has_minimum_setup,
|
|
|
|
|
"progress_percentage": progress,
|
|
|
|
|
"requirements": {
|
|
|
|
|
"ingredients": {
|
|
|
|
|
"current": ingredients_count,
|
|
|
|
|
"minimum": 3,
|
|
|
|
|
"met": has_minimum_ingredients
|
|
|
|
|
},
|
|
|
|
|
"suppliers": {
|
|
|
|
|
"current": suppliers_count,
|
|
|
|
|
"minimum": 1,
|
|
|
|
|
"met": has_minimum_suppliers
|
|
|
|
|
},
|
|
|
|
|
"recipes": {
|
|
|
|
|
"current": recipes_count,
|
|
|
|
|
"minimum": 1,
|
|
|
|
|
"met": has_minimum_recipes
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
except Exception as e:
|
|
|
|
|
logger.error("Failed to get onboarding status", tenant_id=tenant_id, error=str(e))
|
|
|
|
|
raise HTTPException(
|
|
|
|
|
status_code=500,
|
|
|
|
|
detail=f"Failed to get onboarding status: {str(e)}"
|
|
|
|
|
)
|