mirror of
https://github.com/mealie-recipes/mealie.git
synced 2026-05-13 13:27:29 -04:00
feat: Add recipe as ingredient (#4800)
Co-authored-by: Michael Genson <71845777+michael-genson@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
parent
ff42964537
commit
60d9294861
@@ -20,6 +20,7 @@ from mealie.schema.household.group_shopping_list import (
|
||||
ShoppingListOut,
|
||||
ShoppingListSave,
|
||||
)
|
||||
from mealie.schema.recipe.recipe import Recipe
|
||||
from mealie.schema.recipe.recipe_ingredient import (
|
||||
IngredientFood,
|
||||
IngredientUnit,
|
||||
@@ -315,10 +316,22 @@ class ShoppingListService:
|
||||
|
||||
list_items: list[ShoppingListItemCreate] = []
|
||||
for ingredient in recipe_ingredients:
|
||||
if isinstance(ingredient.referenced_recipe, Recipe):
|
||||
# Recursively process sub-recipe ingredients
|
||||
sub_recipe = ingredient.referenced_recipe
|
||||
sub_scale = (ingredient.quantity or 1) * scale
|
||||
sub_items = self.get_shopping_list_items_from_recipe(
|
||||
list_id,
|
||||
sub_recipe.id,
|
||||
sub_scale,
|
||||
sub_recipe.recipe_ingredient,
|
||||
)
|
||||
list_items.extend(sub_items)
|
||||
continue
|
||||
|
||||
if isinstance(ingredient.food, IngredientFood):
|
||||
food_id = ingredient.food.id
|
||||
label_id = ingredient.food.label_id
|
||||
|
||||
else:
|
||||
food_id = None
|
||||
label_id = None
|
||||
|
||||
@@ -369,6 +369,27 @@ class RecipeService(RecipeServiceBase):
|
||||
|
||||
return new_recipe
|
||||
|
||||
def has_recursive_recipe_link(self, recipe: Recipe, visited: set[str] | None = None):
|
||||
"""Recursively checks if a recipe links to itself through its ingredients."""
|
||||
|
||||
if visited is None:
|
||||
visited = set()
|
||||
recipe_id = str(getattr(recipe, "id", None))
|
||||
if recipe_id in visited:
|
||||
return True
|
||||
|
||||
visited.add(recipe_id)
|
||||
ingredients = getattr(recipe, "recipe_ingredient", [])
|
||||
for ing in ingredients:
|
||||
try:
|
||||
sub_recipe = self.get_one(ing.referenced_recipe.id)
|
||||
except (AttributeError, exceptions.NoEntryFound):
|
||||
continue
|
||||
|
||||
if self.has_recursive_recipe_link(sub_recipe, visited):
|
||||
return True
|
||||
return False
|
||||
|
||||
def _pre_update_check(self, slug_or_id: str | UUID, new_data: Recipe) -> Recipe:
|
||||
"""
|
||||
gets the recipe from the database and performs a check to see if the user can update the recipe.
|
||||
@@ -399,6 +420,9 @@ class RecipeService(RecipeServiceBase):
|
||||
if setting_lock and not self.can_lock_unlock(recipe):
|
||||
raise exceptions.PermissionDenied("You do not have permission to lock/unlock this recipe.")
|
||||
|
||||
if self.has_recursive_recipe_link(new_data):
|
||||
raise exceptions.RecursiveRecipe("Recursive recipe link detected. Update aborted.")
|
||||
|
||||
return recipe
|
||||
|
||||
def update_one(self, slug_or_id: str | UUID, update_data: Recipe) -> Recipe:
|
||||
|
||||
Reference in New Issue
Block a user