Improve the frontend modals
This commit is contained in:
@@ -67,6 +67,83 @@ class RecipeService:
|
||||
logger.error(f"Error getting recipe statistics: {e}")
|
||||
return {"total_recipes": 0, "active_recipes": 0, "signature_recipes": 0, "seasonal_recipes": 0}
|
||||
|
||||
async def get_deletion_summary(self, recipe_id: UUID) -> Dict[str, Any]:
|
||||
"""Get summary of what will be affected by deleting this recipe"""
|
||||
try:
|
||||
from sqlalchemy import select, func
|
||||
from ..models.recipes import RecipeIngredient
|
||||
|
||||
# Get recipe info
|
||||
recipe = await self.recipe_repo.get_by_id(recipe_id)
|
||||
if not recipe:
|
||||
return {"success": False, "error": "Recipe not found"}
|
||||
|
||||
# Count recipe ingredients
|
||||
ingredients_result = await self.session.execute(
|
||||
select(func.count(RecipeIngredient.id))
|
||||
.where(RecipeIngredient.recipe_id == recipe_id)
|
||||
)
|
||||
ingredients_count = ingredients_result.scalar() or 0
|
||||
|
||||
# Count production batches using this recipe (if production tables exist)
|
||||
production_batches_count = 0
|
||||
try:
|
||||
# Try to import production models if they exist
|
||||
production_batches_result = await self.session.execute(
|
||||
select(func.count()).select_from(
|
||||
select(1).where(
|
||||
# This would need actual production_batches table reference
|
||||
# For now, set to 0
|
||||
).subquery()
|
||||
)
|
||||
)
|
||||
production_batches_count = 0 # Set to 0 for now
|
||||
except:
|
||||
production_batches_count = 0
|
||||
|
||||
# Count dependent recipes (recipes using this as ingredient) - future feature
|
||||
dependent_recipes_count = 0
|
||||
|
||||
# Count affected orders - would need orders service integration
|
||||
affected_orders_count = 0
|
||||
|
||||
# Determine if deletion is safe
|
||||
warnings = []
|
||||
can_delete = True
|
||||
|
||||
if production_batches_count > 0:
|
||||
warnings.append(f"Esta receta tiene {production_batches_count} lotes de producción asociados")
|
||||
can_delete = False
|
||||
|
||||
if affected_orders_count > 0:
|
||||
warnings.append(f"Esta receta está en {affected_orders_count} pedidos")
|
||||
can_delete = False
|
||||
|
||||
if dependent_recipes_count > 0:
|
||||
warnings.append(f"{dependent_recipes_count} recetas dependen de esta")
|
||||
|
||||
if recipe.status == RecipeStatus.ACTIVE:
|
||||
warnings.append("Esta receta está activa. Considera archivarla primero.")
|
||||
|
||||
return {
|
||||
"success": True,
|
||||
"data": {
|
||||
"recipe_id": str(recipe.id),
|
||||
"recipe_name": recipe.name,
|
||||
"recipe_code": recipe.recipe_code or "",
|
||||
"production_batches_count": production_batches_count,
|
||||
"recipe_ingredients_count": ingredients_count,
|
||||
"dependent_recipes_count": dependent_recipes_count,
|
||||
"affected_orders_count": affected_orders_count,
|
||||
"last_used_date": None,
|
||||
"can_delete": can_delete,
|
||||
"warnings": warnings
|
||||
}
|
||||
}
|
||||
except Exception as e:
|
||||
logger.error(f"Error getting deletion summary: {e}")
|
||||
return {"success": False, "error": str(e)}
|
||||
|
||||
async def create_recipe(
|
||||
self,
|
||||
recipe_data: Dict[str, Any],
|
||||
@@ -74,17 +151,35 @@ class RecipeService:
|
||||
created_by: UUID
|
||||
) -> Dict[str, Any]:
|
||||
"""Create a new recipe with ingredients"""
|
||||
from ..models.recipes import Recipe, RecipeIngredient, RecipeStatus
|
||||
|
||||
try:
|
||||
# Add metadata
|
||||
recipe_data["created_by"] = created_by
|
||||
recipe_data["created_at"] = datetime.utcnow()
|
||||
recipe_data["updated_at"] = datetime.utcnow()
|
||||
recipe_data["status"] = recipe_data.get("status", RecipeStatus.DRAFT)
|
||||
|
||||
# Use the shared repository's create method
|
||||
recipe_create = RecipeCreate(**recipe_data)
|
||||
recipe = await self.recipe_repo.create(recipe_create)
|
||||
# Create Recipe model directly (without ingredients)
|
||||
recipe = Recipe(**recipe_data)
|
||||
self.session.add(recipe)
|
||||
await self.session.flush() # Get the recipe ID
|
||||
|
||||
# Get the created recipe with ingredients (if the repository supports it)
|
||||
# Now create ingredients with the recipe_id and tenant_id
|
||||
for ing_data in ingredients_data:
|
||||
ingredient = RecipeIngredient(
|
||||
recipe_id=recipe.id,
|
||||
tenant_id=recipe.tenant_id, # Add tenant_id from recipe
|
||||
**ing_data
|
||||
)
|
||||
self.session.add(ingredient)
|
||||
|
||||
await self.session.flush()
|
||||
|
||||
# Commit the transaction to persist changes
|
||||
await self.session.commit()
|
||||
|
||||
# Get the created recipe with ingredients
|
||||
result = await self.recipe_repo.get_recipe_with_ingredients(recipe.id)
|
||||
|
||||
return {
|
||||
@@ -117,6 +212,45 @@ class RecipeService:
|
||||
"error": "Recipe not found"
|
||||
}
|
||||
|
||||
# Status transition business rules
|
||||
if "status" in recipe_data:
|
||||
from ..models.recipes import RecipeStatus
|
||||
new_status = recipe_data["status"]
|
||||
current_status = existing_recipe.status
|
||||
|
||||
# Cannot reactivate discontinued recipes
|
||||
if current_status == RecipeStatus.DISCONTINUED:
|
||||
if new_status != RecipeStatus.DISCONTINUED:
|
||||
return {
|
||||
"success": False,
|
||||
"error": "Cannot reactivate a discontinued recipe. Create a new version instead."
|
||||
}
|
||||
|
||||
# Can only archive active or testing recipes
|
||||
if new_status == RecipeStatus.ARCHIVED:
|
||||
if current_status not in [RecipeStatus.ACTIVE, RecipeStatus.TESTING]:
|
||||
return {
|
||||
"success": False,
|
||||
"error": "Can only archive active or testing recipes."
|
||||
}
|
||||
|
||||
# Cannot activate drafts without ingredients
|
||||
if new_status == RecipeStatus.ACTIVE and current_status == RecipeStatus.DRAFT:
|
||||
# Check if recipe has ingredients
|
||||
from sqlalchemy import select, func
|
||||
from ..models.recipes import RecipeIngredient
|
||||
|
||||
result = await self.session.execute(
|
||||
select(func.count(RecipeIngredient.id)).where(RecipeIngredient.recipe_id == recipe_id)
|
||||
)
|
||||
ingredient_count = result.scalar()
|
||||
|
||||
if ingredient_count == 0:
|
||||
return {
|
||||
"success": False,
|
||||
"error": "Cannot activate a recipe without ingredients."
|
||||
}
|
||||
|
||||
# Add metadata
|
||||
if updated_by:
|
||||
recipe_data["updated_by"] = updated_by
|
||||
|
||||
Reference in New Issue
Block a user