Disallow empty ingredients
This commit is contained in:
parent
a8f1050af9
commit
ec9fbc071d
4 changed files with 38 additions and 0 deletions
13
api/meals.py
13
api/meals.py
|
|
@ -242,6 +242,13 @@ async def create_meal_scoped(
|
||||||
)
|
)
|
||||||
if not has_product and name == "" and line == "":
|
if not has_product and name == "" and line == "":
|
||||||
return error_response(request, 400, "Ingredient must include a name or line or a product")
|
return error_response(request, 400, "Ingredient must include a name or line or a product")
|
||||||
|
# quantity must be > 0
|
||||||
|
try:
|
||||||
|
q = float(getattr(ing, "quantity", 0))
|
||||||
|
except Exception:
|
||||||
|
q = getattr(ing, "quantity", 0)
|
||||||
|
if isinstance(q, (int, float)) and q <= 0:
|
||||||
|
return error_response(request, 400, "Ingredient quantity must be greater than 0")
|
||||||
# Proactive validation via repositories
|
# Proactive validation via repositories
|
||||||
hid = household["id"]
|
hid = household["id"]
|
||||||
# Validate members exist as users (do not require household membership here to preserve existing behavior/tests)
|
# Validate members exist as users (do not require household membership here to preserve existing behavior/tests)
|
||||||
|
|
@ -386,6 +393,12 @@ async def update_meal_scoped(
|
||||||
)
|
)
|
||||||
if not has_product and name == "" and line == "":
|
if not has_product and name == "" and line == "":
|
||||||
return error_response(request, 400, "Ingredient must include a name or line or a product")
|
return error_response(request, 400, "Ingredient must include a name or line or a product")
|
||||||
|
try:
|
||||||
|
q = float(getattr(ing, "quantity", 0))
|
||||||
|
except Exception:
|
||||||
|
q = getattr(ing, "quantity", 0)
|
||||||
|
if isinstance(q, (int, float)) and q <= 0:
|
||||||
|
return error_response(request, 400, "Ingredient quantity must be greater than 0")
|
||||||
|
|
||||||
await meals.update_meal(conn, domain_meal)
|
await meals.update_meal(conn, domain_meal)
|
||||||
# Return updated state
|
# Return updated state
|
||||||
|
|
|
||||||
|
|
@ -198,6 +198,13 @@ async def create_recipe(
|
||||||
)
|
)
|
||||||
if not has_product and name == "" and line == "":
|
if not has_product and name == "" and line == "":
|
||||||
return error_response(None, 400, "Ingredient must include a name or line or a product")
|
return error_response(None, 400, "Ingredient must include a name or line or a product")
|
||||||
|
# quantity must be > 0
|
||||||
|
try:
|
||||||
|
q = float(getattr(ing, "quantity", 0))
|
||||||
|
except Exception:
|
||||||
|
q = getattr(ing, "quantity", 0)
|
||||||
|
if isinstance(q, (int, float)) and q <= 0:
|
||||||
|
return error_response(None, 400, "Ingredient quantity must be greater than 0")
|
||||||
hid = household["id"]
|
hid = household["id"]
|
||||||
# Build domain model and insert
|
# Build domain model and insert
|
||||||
r = recipes.Recipe(
|
r = recipes.Recipe(
|
||||||
|
|
|
||||||
|
|
@ -47,6 +47,16 @@ class Ingredient(ApiModel):
|
||||||
return v
|
return v
|
||||||
return v
|
return v
|
||||||
|
|
||||||
|
# Quantity must be > 0
|
||||||
|
@field_validator("quantity")
|
||||||
|
@classmethod
|
||||||
|
def _positive_quantity(cls, v: float) -> float:
|
||||||
|
if v is None:
|
||||||
|
return v
|
||||||
|
if isinstance(v, (int, float)) and v <= 0:
|
||||||
|
raise ValueError("Ingredient quantity must be greater than 0")
|
||||||
|
return v
|
||||||
|
|
||||||
# Backward compatibility: DB may contain NULL preparation; normalize to empty string
|
# Backward compatibility: DB may contain NULL preparation; normalize to empty string
|
||||||
@field_validator("preparation", mode="before")
|
@field_validator("preparation", mode="before")
|
||||||
@classmethod
|
@classmethod
|
||||||
|
|
|
||||||
|
|
@ -44,6 +44,14 @@ async def insert_ingredient(conn, ingredient: Ingredient):
|
||||||
if not has_product and name == "" and line == "":
|
if not has_product and name == "" and line == "":
|
||||||
raise ValueError("Ingredient must include a name or line or a product")
|
raise ValueError("Ingredient must include a name or line or a product")
|
||||||
|
|
||||||
|
# Enforce positive quantity at repository layer as well
|
||||||
|
try:
|
||||||
|
q = float(ingredient.quantity)
|
||||||
|
except Exception:
|
||||||
|
q = ingredient.quantity
|
||||||
|
if isinstance(q, (int, float)) and q <= 0:
|
||||||
|
raise ValueError("Ingredient quantity must be greater than 0")
|
||||||
|
|
||||||
async with conn.execute(
|
async with conn.execute(
|
||||||
"""
|
"""
|
||||||
INSERT INTO Ingredient (name, line, preparation, unit, quantity, product_id, recipe_id, meal_id)
|
INSERT INTO Ingredient (name, line, preparation, unit, quantity, product_id, recipe_id, meal_id)
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue