mirror of
https://github.com/mealie-recipes/mealie.git
synced 2026-04-09 22:45:36 -04:00
fix: Removing a recipe ingredient doesn't remove its links to steps (#6896)
Co-authored-by: Michael Genson <genson.michael@gmail.com> Co-authored-by: Michael Genson <71845777+michael-genson@users.noreply.github.com>
This commit is contained in:
@@ -463,6 +463,24 @@ class RecipeService(RecipeServiceBase):
|
|||||||
|
|
||||||
return recipe
|
return recipe
|
||||||
|
|
||||||
|
def _remove_non_existent_ingredient_references(self, update_data: Recipe) -> Recipe:
|
||||||
|
"""Removes the references of ingredients from steps that no longer exist."""
|
||||||
|
|
||||||
|
current_ingredient_reference_ids = set() # set of current ingredient(s) reference id's
|
||||||
|
for ingredient in update_data.recipe_ingredient:
|
||||||
|
current_ingredient_reference_ids.add(ingredient.reference_id)
|
||||||
|
|
||||||
|
recipe_instructions = update_data.recipe_instructions
|
||||||
|
if recipe_instructions is not None:
|
||||||
|
for instruction in recipe_instructions:
|
||||||
|
instruction.ingredient_references = [
|
||||||
|
ref
|
||||||
|
for ref in instruction.ingredient_references
|
||||||
|
if ref.reference_id in current_ingredient_reference_ids
|
||||||
|
]
|
||||||
|
|
||||||
|
return update_data
|
||||||
|
|
||||||
def _resolve_ingredient_sub_recipes(self, update_data: Recipe) -> Recipe:
|
def _resolve_ingredient_sub_recipes(self, update_data: Recipe) -> Recipe:
|
||||||
"""Resolve all referenced_recipe slugs to IDs within the current group."""
|
"""Resolve all referenced_recipe slugs to IDs within the current group."""
|
||||||
if not update_data.recipe_ingredient:
|
if not update_data.recipe_ingredient:
|
||||||
@@ -488,7 +506,7 @@ class RecipeService(RecipeServiceBase):
|
|||||||
def update_one(self, slug_or_id: str | UUID, update_data: Recipe) -> Recipe:
|
def update_one(self, slug_or_id: str | UUID, update_data: Recipe) -> Recipe:
|
||||||
recipe = self._pre_update_check(slug_or_id, update_data)
|
recipe = self._pre_update_check(slug_or_id, update_data)
|
||||||
|
|
||||||
# Resolve sub-recipe references before passing to repository
|
update_data = self._remove_non_existent_ingredient_references(update_data)
|
||||||
update_data = self._resolve_ingredient_sub_recipes(update_data)
|
update_data = self._resolve_ingredient_sub_recipes(update_data)
|
||||||
|
|
||||||
new_data = self.group_recipes.update(recipe.slug, update_data)
|
new_data = self.group_recipes.update(recipe.slug, update_data)
|
||||||
|
|||||||
@@ -1127,6 +1127,66 @@ def test_sub_recipe_not_found_in_other_group(api_client: TestClient, unique_user
|
|||||||
assert response.json()["detail"]["message"] == "No Entry Found"
|
assert response.json()["detail"]["message"] == "No Entry Found"
|
||||||
|
|
||||||
|
|
||||||
|
def test_update_with_non_existent_ingredient_references(api_client: TestClient, unique_user: TestUser):
|
||||||
|
"""Test that the non-existent ingredient references are removed"""
|
||||||
|
|
||||||
|
database = unique_user.repos
|
||||||
|
|
||||||
|
# Create a food
|
||||||
|
food = database.ingredient_foods.create(
|
||||||
|
SaveIngredientFood(
|
||||||
|
name=random_string(10),
|
||||||
|
group_id=unique_user.group_id,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
# Create a recipe_a
|
||||||
|
recipe_a: Recipe = database.recipes.create(
|
||||||
|
Recipe(
|
||||||
|
name=random_string(10),
|
||||||
|
user_id=unique_user.user_id,
|
||||||
|
group_id=unique_user.group_id,
|
||||||
|
recipe_ingredient=[
|
||||||
|
RecipeIngredient(note="", food=food),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
recipe_url = api_routes.recipes_slug(recipe_a.slug)
|
||||||
|
response = api_client.get(recipe_url, headers=unique_user.token)
|
||||||
|
assert response.status_code == 200
|
||||||
|
recipe_data = json.loads(response.text)
|
||||||
|
|
||||||
|
"""
|
||||||
|
Updating the recipe with some references of non-exisitent ingredient(s),
|
||||||
|
mimicking the behaviour observed from the screen
|
||||||
|
"""
|
||||||
|
food_ingredient_ref_id = recipe_data["recipeIngredient"][0]["referenceId"]
|
||||||
|
recipe_data["recipeInstructions"].append(
|
||||||
|
{
|
||||||
|
"title": "Step One",
|
||||||
|
"text": "Mash the Peas to form a paste.",
|
||||||
|
"ingredientReferences": [
|
||||||
|
{"referenceId": food_ingredient_ref_id},
|
||||||
|
{"referenceId": "5fb334fe-00b7-43d6-bb75-355977852543"},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
# Call the put API end point
|
||||||
|
response = api_client.put(recipe_url, json=recipe_data, headers=unique_user.token)
|
||||||
|
assert response.status_code == 200
|
||||||
|
recipe_data = json.loads(response.text)
|
||||||
|
|
||||||
|
"""
|
||||||
|
Assert the result to verify that the resulting recipe instruction has reference
|
||||||
|
to only valid id i.e. food_ingredient_ref_id
|
||||||
|
"""
|
||||||
|
step_one_ingr_refs = recipe_data["recipeInstructions"][0]["ingredientReferences"]
|
||||||
|
assert len(step_one_ingr_refs) == 1
|
||||||
|
assert step_one_ingr_refs[0]["referenceId"] == food_ingredient_ref_id
|
||||||
|
|
||||||
|
|
||||||
def test_duplicate(api_client: TestClient, unique_user: TestUser):
|
def test_duplicate(api_client: TestClient, unique_user: TestUser):
|
||||||
recipe_data = recipe_test_data[0]
|
recipe_data = recipe_test_data[0]
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user