From 543a53cab4cc3e185d095b227d86854fd6d4a238 Mon Sep 17 00:00:00 2001 From: Michael Genson <71845777+michael-genson@users.noreply.github.com> Date: Sat, 19 Oct 2024 15:36:34 -0500 Subject: [PATCH] fix: Bulk Update Owner Removes Some Recipe Data (#4393) --- frontend/lib/api/user/recipes/recipe.ts | 4 +++ frontend/pages/group/data/recipes.vue | 2 +- mealie/routes/recipe/recipe_crud_routes.py | 25 +++++++++++++++++++ .../user_recipe_tests/test_recipe_crud.py | 9 +++++-- 4 files changed, 37 insertions(+), 3 deletions(-) diff --git a/frontend/lib/api/user/recipes/recipe.ts b/frontend/lib/api/user/recipes/recipe.ts index dd7fcc7d0..87288814c 100644 --- a/frontend/lib/api/user/recipes/recipe.ts +++ b/frontend/lib/api/user/recipes/recipe.ts @@ -182,6 +182,10 @@ export class RecipeAPI extends BaseCRUDAPI { return await this.requests.put(routes.recipesBase, payload); } + async patchMany(payload: Recipe[]) { + return await this.requests.patch(routes.recipesBase, payload); + } + async updateLastMade(recipeSlug: string, timestamp: string) { return await this.requests.patch(routes.recipesSlugLastMade(recipeSlug), { timestamp }) } diff --git a/frontend/pages/group/data/recipes.vue b/frontend/pages/group/data/recipes.vue index 5fb57d408..94d2f245b 100644 --- a/frontend/pages/group/data/recipes.vue +++ b/frontend/pages/group/data/recipes.vue @@ -377,7 +377,7 @@ export default defineComponent({ }); loading.value = true; - await api.recipes.updateMany(selected.value); + await api.recipes.patchMany(selected.value); await refreshRecipes(); resetAll(); diff --git a/mealie/routes/recipe/recipe_crud_routes.py b/mealie/routes/recipe/recipe_crud_routes.py index 997052437..302ae1f40 100644 --- a/mealie/routes/recipe/recipe_crud_routes.py +++ b/mealie/routes/recipe/recipe_crud_routes.py @@ -516,6 +516,31 @@ class RecipeController(BaseRecipeController): return recipe + @router.patch("") + def patch_many(self, data: list[Recipe]): + updated_by_group_and_household: defaultdict[UUID4, defaultdict[UUID4, list[Recipe]]] = defaultdict( + lambda: defaultdict(list) + ) + for recipe in data: + r = self.service.patch_one(recipe.id, recipe) # type: ignore + updated_by_group_and_household[r.group_id][r.household_id].append(r) + + all_updated: list[Recipe] = [] + if updated_by_group_and_household: + for group_id, household_dict in updated_by_group_and_household.items(): + for household_id, updated_recipes in household_dict.items(): + all_updated.extend(updated_recipes) + self.publish_event( + event_type=EventTypes.recipe_updated, + document_data=EventRecipeBulkData( + operation=EventOperation.update, recipe_slugs=[r.slug for r in updated_recipes] + ), + group_id=group_id, + household_id=household_id, + ) + + return all_updated + @router.patch("/{slug}/last-made") def update_last_made(self, slug: str, data: RecipeLastMade): """Update a recipe's last made timestamp""" diff --git a/tests/integration_tests/user_recipe_tests/test_recipe_crud.py b/tests/integration_tests/user_recipe_tests/test_recipe_crud.py index ebd156e61..f675d6da2 100644 --- a/tests/integration_tests/user_recipe_tests/test_recipe_crud.py +++ b/tests/integration_tests/user_recipe_tests/test_recipe_crud.py @@ -483,7 +483,8 @@ def test_read_update( assert cats[0]["name"] in test_name -def test_update_many(api_client: TestClient, unique_user: TestUser): +@pytest.mark.parametrize("use_patch", [True, False]) +def test_update_many(api_client: TestClient, unique_user: TestUser, use_patch: bool): recipe_slugs = [random_string() for _ in range(3)] for slug in recipe_slugs: api_client.post(api_routes.recipes, json={"name": slug}, headers=unique_user.token) @@ -498,7 +499,11 @@ def test_update_many(api_client: TestClient, unique_user: TestUser): recipe_data["name"] = new_slug_by_id[recipe_data["id"]] recipe_data["slug"] = new_slug_by_id[recipe_data["id"]] - response = api_client.put(api_routes.recipes, json=recipes_data, headers=unique_user.token) + if use_patch: + api_client_func = api_client.patch + else: + api_client_func = api_client.put + response = api_client_func(api_routes.recipes, json=recipes_data, headers=unique_user.token) assert response.status_code == 200 for updated_recipe_data in response.json(): assert updated_recipe_data["slug"] == new_slug_by_id[updated_recipe_data["id"]]