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

@@ -5,7 +5,7 @@ Service-to-service endpoint for cloning recipe and production data
from fastapi import APIRouter, Depends, HTTPException, Header
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select
from sqlalchemy import select, delete, func
import structlog
import uuid
from datetime import datetime, timezone, timedelta
@@ -375,3 +375,83 @@ async def clone_health_check(_: bool = Depends(verify_internal_api_key)):
"clone_endpoint": "available",
"version": "2.0.0"
}
@router.delete("/tenant/{virtual_tenant_id}")
async def delete_demo_data(
virtual_tenant_id: str,
db: AsyncSession = Depends(get_db),
_: bool = Depends(verify_internal_api_key)
):
"""
Delete all recipe data for a virtual demo tenant
Called by demo session cleanup service to remove ephemeral data
when demo sessions expire or are destroyed.
"""
logger.info(
"Deleting recipe data for virtual tenant",
virtual_tenant_id=virtual_tenant_id
)
start_time = datetime.now(timezone.utc)
try:
virtual_uuid = uuid.UUID(virtual_tenant_id)
# Count records before deletion
recipe_count = await db.scalar(
select(func.count(Recipe.id)).where(Recipe.tenant_id == virtual_uuid)
)
ingredient_count = await db.scalar(
select(func.count(RecipeIngredient.id)).where(RecipeIngredient.tenant_id == virtual_uuid)
)
# Delete in correct order (RecipeIngredient references Recipe)
await db.execute(
delete(RecipeIngredient).where(RecipeIngredient.tenant_id == virtual_uuid)
)
await db.execute(
delete(Recipe).where(Recipe.tenant_id == virtual_uuid)
)
await db.commit()
duration_ms = int((datetime.now(timezone.utc) - start_time).total_seconds() * 1000)
logger.info(
"Recipe data deleted successfully",
virtual_tenant_id=virtual_tenant_id,
recipes_deleted=recipe_count,
ingredients_deleted=ingredient_count,
duration_ms=duration_ms
)
return {
"service": "recipes",
"status": "deleted",
"virtual_tenant_id": virtual_tenant_id,
"records_deleted": {
"recipes": recipe_count,
"recipe_ingredients": ingredient_count,
"total": recipe_count + ingredient_count
},
"duration_ms": duration_ms
}
except ValueError as e:
logger.error("Invalid UUID format", error=str(e))
raise HTTPException(status_code=400, detail=f"Invalid UUID: {str(e)}")
except Exception as e:
logger.error(
"Failed to delete recipe data",
virtual_tenant_id=virtual_tenant_id,
error=str(e),
exc_info=True
)
await db.rollback()
raise HTTPException(
status_code=500,
detail=f"Failed to delete recipe data: {str(e)}"
)

View File

@@ -111,6 +111,34 @@ async def search_recipes(
raise HTTPException(status_code=500, detail="Internal server error")
@router.get(
route_builder.build_custom_route(RouteCategory.BASE, ["count"]),
response_model=dict
)
async def count_recipes(
tenant_id: UUID,
db: AsyncSession = Depends(get_db)
):
"""Get count of recipes for a tenant"""
try:
recipe_service = RecipeService(db)
# Use the search method with limit 0 to just get the count
recipes = await recipe_service.search_recipes(
tenant_id=tenant_id,
limit=10000 # High limit to get all
)
count = len(recipes)
logger.info(f"Retrieved recipe count for tenant {tenant_id}: {count}")
return {"count": count}
except Exception as e:
logger.error(f"Error counting recipes for tenant {tenant_id}: {e}")
raise HTTPException(status_code=500, detail="Internal server error")
@router.get(
route_builder.build_custom_route(RouteCategory.BASE, ["{recipe_id}"]),
response_model=RecipeResponse
@@ -188,34 +216,6 @@ async def update_recipe(
raise HTTPException(status_code=500, detail="Internal server error")
@router.get(
route_builder.build_custom_route(RouteCategory.BASE, ["count"]),
response_model=dict
)
async def count_recipes(
tenant_id: UUID,
db: AsyncSession = Depends(get_db)
):
"""Get count of recipes for a tenant"""
try:
recipe_service = RecipeService(db)
# Use the search method with limit 0 to just get the count
recipes = await recipe_service.search_recipes(
tenant_id=tenant_id,
limit=10000 # High limit to get all
)
count = len(recipes)
logger.info(f"Retrieved recipe count for tenant {tenant_id}: {count}")
return {"count": count}
except Exception as e:
logger.error(f"Error counting recipes for tenant {tenant_id}: {e}")
raise HTTPException(status_code=500, detail="Internal server error")
@router.delete(
route_builder.build_custom_route(RouteCategory.BASE, ["{recipe_id}"])
)