From 6e485060e086954e0d1decd8ae930ed8ab44c6b0 Mon Sep 17 00:00:00 2001 From: Cameron Wyatt Date: Tue, 31 Dec 2024 23:13:05 +0000 Subject: [PATCH] Fixed food seed file to remove duplicate item. Added logic to food, label, and unit seeding to query all existing items and then only seed new ones, making it less likely to get duplicates from seeding. Updated messages on group data management page. Updated tests --- frontend/lang/messages/en-US.json | 4 +-- .../seed/resources/foods/locales/en-US.json | 6 ---- mealie/repos/seed/seeders.py | 29 +++++++++++++++---- .../user_group_tests/test_group_seeder.py | 2 +- 4 files changed, 27 insertions(+), 14 deletions(-) diff --git a/frontend/lang/messages/en-US.json b/frontend/lang/messages/en-US.json index 154a470e4..c979d17bf 100644 --- a/frontend/lang/messages/en-US.json +++ b/frontend/lang/messages/en-US.json @@ -1048,8 +1048,8 @@ "foods": { "merge-dialog-text": "Combining the selected foods will merge the source food and target food into a single food. The source food will be deleted and all of the references to the source food will be updated to point to the target food.", "merge-food-example": "Merging {food1} into {food2}", - "seed-dialog-text": "Seed the database with foods based on your local language. This will create 200+ common foods that can be used to organize your database. Foods are translated via a community effort.", - "seed-dialog-warning": "You have already have some items in your database. This action will not reconcile duplicates, you will have to manage them manually.", + "seed-dialog-text": "Seed the database with foods based on your local language. This will create ~2700 common foods that can be used to organize your database. Foods are translated via a community effort.", + "seed-dialog-warning": "You already have some items in your database. A new item will not be added if an item with the same name already exists.", "combine-food": "Combine Food", "source-food": "Source Food", "target-food": "Target Food", diff --git a/mealie/repos/seed/resources/foods/locales/en-US.json b/mealie/repos/seed/resources/foods/locales/en-US.json index cc80bd46c..4b97d32aa 100644 --- a/mealie/repos/seed/resources/foods/locales/en-US.json +++ b/mealie/repos/seed/resources/foods/locales/en-US.json @@ -10567,12 +10567,6 @@ "name": "wasabi pea", "pluralName": "wasabi peas" }, - { - "aliases": [], - "description": "", - "name": null, - "pluralName": "achiote seeds" - }, { "aliases": [], "description": "", diff --git a/mealie/repos/seed/seeders.py b/mealie/repos/seed/seeders.py index 2f7a3acba..033abe79b 100644 --- a/mealie/repos/seed/seeders.py +++ b/mealie/repos/seed/seeders.py @@ -4,7 +4,12 @@ from collections.abc import Generator from functools import cached_property from mealie.schema.labels import MultiPurposeLabelOut, MultiPurposeLabelSave -from mealie.schema.recipe.recipe_ingredient import SaveIngredientFood, SaveIngredientUnit +from mealie.schema.recipe.recipe_ingredient import ( + IngredientFood, + IngredientUnit, + SaveIngredientFood, + SaveIngredientUnit, +) from mealie.services.group_services.labels_service import MultiPurposeLabelService from ._abstract_seeder import AbstractSeeder @@ -21,11 +26,17 @@ class MultiPurposeLabelSeeder(AbstractSeeder): locale_path = self.resources / "foods" / "locales" / f"{locale}.json" return locale_path if locale_path.exists() else foods.en_US + def get_all_labels(self) -> list[MultiPurposeLabelOut]: + return self.repos.group_multi_purpose_labels.get_all() + def load_data(self, locale: str | None = None) -> Generator[MultiPurposeLabelSave, None, None]: file = self.get_file(locale) - label_names = set(json.loads(file.read_text(encoding="utf-8")).keys()) - for label in label_names: + current_label_names = {label.name for label in self.get_all_labels()} + seed_label_names = set(json.loads(file.read_text(encoding="utf-8")).keys()) + # only seed new labels + to_seed_labels = seed_label_names - current_label_names + for label in to_seed_labels: yield MultiPurposeLabelSave( name=label, group_id=self.repos.group_id, @@ -45,10 +56,13 @@ class IngredientUnitsSeeder(AbstractSeeder): locale_path = self.resources / "units" / "locales" / f"{locale}.json" return locale_path if locale_path.exists() else units.en_US + def get_all_units(self) -> list[IngredientUnit]: + return self.repos.ingredient_units.get_all() + def load_data(self, locale: str | None = None) -> Generator[SaveIngredientUnit, None, None]: file = self.get_file(locale) - seen_unit_names = set() + seen_unit_names = {unit.name for unit in self.get_all_units()} for unit in json.loads(file.read_text(encoding="utf-8")).values(): if unit["name"] in seen_unit_names: continue @@ -80,14 +94,19 @@ class IngredientFoodsSeeder(AbstractSeeder): def get_label(self, value: str) -> MultiPurposeLabelOut | None: return self.repos.group_multi_purpose_labels.get_one(value, "name") + def get_all_foods(self) -> list[IngredientFood]: + return self.repos.ingredient_foods.get_all() + def load_data(self, locale: str | None = None) -> Generator[SaveIngredientFood, None, None]: file = self.get_file(locale) - seed_foods_names = set() + # get all current unique foods + seed_foods_names = {food.name for food in self.get_all_foods()} for label, value in json.loads(file.read_text(encoding="utf-8")).items(): label_out = self.get_label(label) for food in value["foods"]: + # don't seed foods that already exist, matched on food name if food["name"] in seed_foods_names: continue diff --git a/tests/integration_tests/user_group_tests/test_group_seeder.py b/tests/integration_tests/user_group_tests/test_group_seeder.py index 91df8ab6e..9e7d5b137 100644 --- a/tests/integration_tests/user_group_tests/test_group_seeder.py +++ b/tests/integration_tests/user_group_tests/test_group_seeder.py @@ -12,7 +12,7 @@ def test_seed_invalid_locale(api_client: TestClient, unique_user: TestUser): def test_seed_foods(api_client: TestClient, unique_user: TestUser): - CREATED_FOODS = 2694 + CREATED_FOODS = 2687 database = unique_user.repos # Check that the foods was created