No empty ingredients
This commit is contained in:
parent
8a4616fb13
commit
a8f1050af9
3 changed files with 39 additions and 1 deletions
19
api/meals.py
19
api/meals.py
|
|
@ -233,6 +233,15 @@ async def create_meal_scoped(
|
|||
msg = meals.validate_meal(domain_meal)
|
||||
if msg:
|
||||
return error_response(request, 400, msg)
|
||||
# Disallow empty extra ingredients (no product and no textual content)
|
||||
for ing in domain_meal.extra_ingredients:
|
||||
name = (ing.name or "").strip()
|
||||
line = (ing.line or "").strip()
|
||||
has_product = getattr(ing, "product", None) is not None or (
|
||||
getattr(ing, "product_id", None) is not None and getattr(ing, "product_id") >= 0
|
||||
)
|
||||
if not has_product and name == "" and line == "":
|
||||
return error_response(request, 400, "Ingredient must include a name or line or a product")
|
||||
# Proactive validation via repositories
|
||||
hid = household["id"]
|
||||
# Validate members exist as users (do not require household membership here to preserve existing behavior/tests)
|
||||
|
|
@ -368,6 +377,16 @@ async def update_meal_scoped(
|
|||
400,
|
||||
f"Invalid recipe id(s): {', '.join(map(str, sorted(set(invalid_recipes))))}",
|
||||
)
|
||||
# Disallow empty extra ingredients on update as well
|
||||
for ing in domain_meal.extra_ingredients:
|
||||
name = (ing.name or "").strip()
|
||||
line = (ing.line or "").strip()
|
||||
has_product = getattr(ing, "product", None) is not None or (
|
||||
getattr(ing, "product_id", None) is not None and getattr(ing, "product_id") >= 0
|
||||
)
|
||||
if not has_product and name == "" and line == "":
|
||||
return error_response(request, 400, "Ingredient must include a name or line or a product")
|
||||
|
||||
await meals.update_meal(conn, domain_meal)
|
||||
# Return updated state
|
||||
updated = await meals.find_meal_by_id_scoped(conn, meal_id, hid)
|
||||
|
|
|
|||
|
|
@ -189,6 +189,15 @@ async def create_recipe(
|
|||
):
|
||||
if not recipe.ingredients:
|
||||
return error_response(None, 400, "Recipe must have at least one ingredient")
|
||||
# Disallow empty ingredients with neither product nor textual content
|
||||
for ing in recipe.ingredients:
|
||||
name = (ing.name or "").strip()
|
||||
line = (ing.line or "").strip()
|
||||
has_product = getattr(ing, "product", None) is not None or (
|
||||
getattr(ing, "product_id", None) is not None and getattr(ing, "product_id") >= 0
|
||||
)
|
||||
if not has_product and name == "" and line == "":
|
||||
return error_response(None, 400, "Ingredient must include a name or line or a product")
|
||||
hid = household["id"]
|
||||
# Build domain model and insert
|
||||
r = recipes.Recipe(
|
||||
|
|
@ -205,7 +214,10 @@ async def create_recipe(
|
|||
ingredient.recipe_id = r.id
|
||||
if ingredient.product:
|
||||
ingredient.product_id = ingredient.product.id
|
||||
await ingredients_mod.insert_ingredient(conn, ingredient)
|
||||
try:
|
||||
await ingredients_mod.insert_ingredient(conn, ingredient)
|
||||
except ValueError as e:
|
||||
return error_response(None, 400, str(e))
|
||||
response.headers["Location"] = f"/api/v1/households/{household['slug']}/recipes/{r.id}"
|
||||
created = MemberRef(id=user.id, display_name=user.display_name)
|
||||
out = RecipeOut(
|
||||
|
|
|
|||
|
|
@ -37,6 +37,13 @@ async def insert_ingredient(conn, ingredient: Ingredient):
|
|||
if ingredient.product_id is None or ingredient.product_id < 0:
|
||||
ingredient.product_id = None
|
||||
|
||||
# Disallow empty ingredients (no product and no textual content)
|
||||
name = (ingredient.name or "").strip()
|
||||
line = (ingredient.line or "").strip()
|
||||
has_product = ingredient.product_id is not None and ingredient.product_id >= 0
|
||||
if not has_product and name == "" and line == "":
|
||||
raise ValueError("Ingredient must include a name or line or a product")
|
||||
|
||||
async with conn.execute(
|
||||
"""
|
||||
INSERT INTO Ingredient (name, line, preparation, unit, quantity, product_id, recipe_id, meal_id)
|
||||
|
|
|
|||
Loading…
Reference in a new issue