48 lines
1.4 KiB
Python
48 lines
1.4 KiB
Python
"""
|
|
Shared kitchen helpers used by both the DRF API views (views.py) and the
|
|
HTMX views (views_htmx.py). Consolidated here to avoid cross-module
|
|
duplication and the views_htmx -> views runtime coupling.
|
|
"""
|
|
from decimal import Decimal
|
|
|
|
from .models import Ingredient, PantryItem
|
|
|
|
|
|
def find_ingredient(name):
|
|
"""Find ingredient by name or alias (case-insensitive)."""
|
|
# Exact name match
|
|
try:
|
|
return Ingredient.objects.get(name__iexact=name)
|
|
except Ingredient.DoesNotExist:
|
|
pass
|
|
|
|
# Search aliases (JSONField contains). Guard against a falsy aliases value.
|
|
for ingredient in Ingredient.objects.all():
|
|
if ingredient.aliases and any(a.lower() == name.lower() for a in ingredient.aliases):
|
|
return ingredient
|
|
|
|
return None
|
|
|
|
|
|
def get_pantry_total(ingredient_id):
|
|
"""Get total quantity of an ingredient across all pantry locations."""
|
|
total = Decimal("0")
|
|
for item in PantryItem.objects.filter(ingredient_id=ingredient_id, quantity__gt=0):
|
|
total += item.quantity
|
|
return total
|
|
|
|
|
|
def get_section_key(ingredient):
|
|
"""Determine the canonical (lowercase) shopping section key from an
|
|
ingredient's tags."""
|
|
tag_names = set(ingredient.tags.values_list("name", flat=True))
|
|
if "protein" in tag_names:
|
|
return "protein"
|
|
if "veg" in tag_names:
|
|
return "veg"
|
|
if "carb" in tag_names:
|
|
return "carbs"
|
|
if "dairy" in tag_names:
|
|
return "dairy"
|
|
return "other"
|