diff --git a/mealie/schema/recipe/recipe_ingredient.py b/mealie/schema/recipe/recipe_ingredient.py index cafdd58d8..4a32f0ff9 100644 --- a/mealie/schema/recipe/recipe_ingredient.py +++ b/mealie/schema/recipe/recipe_ingredient.py @@ -303,6 +303,11 @@ class RecipeIngredient(RecipeIngredientBase): reference_id: UUID = Field(default_factory=uuid4) model_config = ConfigDict(from_attributes=True) + @field_validator("reference_id", mode="before") + @classmethod + def ensure_reference_id(cls, value) -> UUID: + return value or uuid4() + @field_validator("quantity", mode="before") @classmethod def validate_quantity(cls, value) -> NoneFloat: 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 0370dbbaf..7203527df 100644 --- a/tests/integration_tests/user_recipe_tests/test_recipe_crud.py +++ b/tests/integration_tests/user_recipe_tests/test_recipe_crud.py @@ -19,6 +19,7 @@ from recipe_scrapers._schemaorg import SchemaOrg from recipe_scrapers.plugins import SchemaOrgFillPlugin from slugify import slugify +from mealie.db.models.recipe import RecipeModel from mealie.pkgs.safehttp.transport import AsyncSafeTransport from mealie.schema.cookbook.cookbook import SaveCookBook from mealie.schema.recipe.recipe import Recipe, RecipeCategory, RecipeSummary, RecipeTag @@ -1252,6 +1253,25 @@ def test_get_recipe_by_slug_or_id(api_client: TestClient, unique_user: utils.Tes assert recipe_data["id"] == recipe_id +def test_get_recipe_ingredient_missing_reference_id(api_client: TestClient, unique_user: utils.TestUser): + slug = random_string() + response = api_client.post(api_routes.recipes, json={"name": slug}, headers=unique_user.token) + assert response.status_code == 201 + + # Manually edit the database to remove the reference id from the ingredient + session = unique_user.repos.session + recipe = session.query(RecipeModel).filter(RecipeModel.slug == slug).first() + recipe.recipe_ingredient[0].reference_id = None + session.commit() + + # Make sure we can fetch the recipe and generate a new reference id + response = api_client.get(api_routes.recipes_slug(slug), headers=unique_user.token) + assert response.status_code == 200 + recipe_data = response.json() + assert len(recipe_data["recipeIngredient"]) == 1 + assert recipe_data["recipeIngredient"][0].get("referenceId") + + @pytest.mark.parametrize("organizer_type", ["tags", "categories", "tools"]) def test_get_recipes_organizer_filter(api_client: TestClient, unique_user: utils.TestUser, organizer_type: str): database = unique_user.repos