# services/recipes/app/api/recipe_quality_configs.py """ Recipe Quality Configuration API - Atomic CRUD operations on RecipeQualityConfiguration """ from fastapi import APIRouter, Depends, HTTPException, Header from sqlalchemy.ext.asyncio import AsyncSession from typing import List from uuid import UUID import logging from ..core.database import get_db from ..services.recipe_service import RecipeService from ..schemas.recipes import ( RecipeQualityConfiguration, RecipeQualityConfigurationUpdate ) from shared.routing import RouteBuilder, RouteCategory from shared.auth.access_control import require_user_role route_builder = RouteBuilder('recipes') logger = logging.getLogger(__name__) router = APIRouter(tags=["recipe-quality-configs"]) def get_user_id(x_user_id: str = Header(...)) -> UUID: """Extract user ID from header""" try: return UUID(x_user_id) except ValueError: raise HTTPException(status_code=400, detail="Invalid user ID format") @router.get( route_builder.build_custom_route(RouteCategory.BASE, ["{recipe_id}", "quality-configuration"]), response_model=RecipeQualityConfiguration ) async def get_recipe_quality_configuration( tenant_id: UUID, recipe_id: UUID, db: AsyncSession = Depends(get_db) ): """Get quality configuration for a specific recipe""" try: recipe_service = RecipeService(db) recipe = await recipe_service.get_recipe(tenant_id, recipe_id) if not recipe: raise HTTPException(status_code=404, detail="Recipe not found") quality_config = recipe.get("quality_check_configuration") if not quality_config: quality_config = { "stages": {}, "overall_quality_threshold": 7.0, "critical_stage_blocking": True, "auto_create_quality_checks": True, "quality_manager_approval_required": False } return quality_config except HTTPException: raise except Exception as e: logger.error(f"Error getting recipe quality configuration: {e}") raise HTTPException(status_code=500, detail="Internal server error") @router.put( route_builder.build_custom_route(RouteCategory.BASE, ["{recipe_id}", "quality-configuration"]), response_model=RecipeQualityConfiguration ) @require_user_role(['admin', 'owner', 'member']) async def update_recipe_quality_configuration( tenant_id: UUID, recipe_id: UUID, quality_config: RecipeQualityConfigurationUpdate, user_id: UUID = Depends(get_user_id), db: AsyncSession = Depends(get_db) ): """Update quality configuration for a specific recipe""" try: recipe_service = RecipeService(db) recipe = await recipe_service.get_recipe(tenant_id, recipe_id) if not recipe: raise HTTPException(status_code=404, detail="Recipe not found") updated_recipe = await recipe_service.update_recipe_quality_configuration( tenant_id, recipe_id, quality_config.dict(exclude_unset=True), user_id ) return updated_recipe["quality_check_configuration"] except HTTPException: raise except Exception as e: logger.error(f"Error updating recipe quality configuration: {e}") raise HTTPException(status_code=500, detail="Internal server error") @router.post( route_builder.build_custom_route(RouteCategory.BASE, ["{recipe_id}", "quality-configuration", "stages", "{stage}", "templates"]) ) @require_user_role(['admin', 'owner', 'member']) async def add_quality_templates_to_stage( tenant_id: UUID, recipe_id: UUID, stage: str, template_ids: List[UUID], user_id: UUID = Depends(get_user_id), db: AsyncSession = Depends(get_db) ): """Add quality templates to a specific recipe stage""" try: recipe_service = RecipeService(db) recipe = await recipe_service.get_recipe(tenant_id, recipe_id) if not recipe: raise HTTPException(status_code=404, detail="Recipe not found") await recipe_service.add_quality_templates_to_stage( tenant_id, recipe_id, stage, template_ids, user_id ) return {"message": f"Added {len(template_ids)} templates to {stage} stage"} except HTTPException: raise except Exception as e: logger.error(f"Error adding quality templates to recipe stage: {e}") raise HTTPException(status_code=500, detail="Internal server error") @router.delete( route_builder.build_custom_route(RouteCategory.BASE, ["{recipe_id}", "quality-configuration", "stages", "{stage}", "templates", "{template_id}"]) ) @require_user_role(['admin', 'owner']) async def remove_quality_template_from_stage( tenant_id: UUID, recipe_id: UUID, stage: str, template_id: UUID, user_id: UUID = Depends(get_user_id), db: AsyncSession = Depends(get_db) ): """Remove a quality template from a specific recipe stage""" try: recipe_service = RecipeService(db) recipe = await recipe_service.get_recipe(tenant_id, recipe_id) if not recipe: raise HTTPException(status_code=404, detail="Recipe not found") await recipe_service.remove_quality_template_from_stage( tenant_id, recipe_id, stage, template_id, user_id ) return {"message": f"Removed template from {stage} stage"} except HTTPException: raise except Exception as e: logger.error(f"Error removing quality template from recipe stage: {e}") raise HTTPException(status_code=500, detail="Internal server error")