Public Access
feat: planner cost+savings estimator against ingredient_grocery_match
This commit is contained in:
@@ -0,0 +1,80 @@
|
||||
from decimal import Decimal
|
||||
from uuid import uuid4
|
||||
|
||||
import pytest
|
||||
|
||||
from app.services.planner.cost import compute_recipe_cost
|
||||
from app.services.planner.types import RecipeCost
|
||||
|
||||
|
||||
def _ingredient(ing_id, qty=1.0, unit=None):
|
||||
return {"ingredient_id": ing_id, "qty": qty, "unit": unit}
|
||||
|
||||
|
||||
def _match(grocery_id, name, current, regular, is_on_sale, confidence=0.9):
|
||||
return {
|
||||
"grocery_item_id": grocery_id,
|
||||
"grocery_item_name": name,
|
||||
"current_price": Decimal(str(current)),
|
||||
"regular_price": Decimal(str(regular)),
|
||||
"is_on_sale": is_on_sale,
|
||||
"confidence": Decimal(str(confidence)),
|
||||
}
|
||||
|
||||
|
||||
def test_compute_recipe_cost_sums_ingredient_costs():
|
||||
recipe_id = uuid4()
|
||||
i1, i2 = uuid4(), uuid4()
|
||||
g1, g2 = uuid4(), uuid4()
|
||||
matches = {
|
||||
i1: [_match(g1, "Chicken", current=4.00, regular=5.00, is_on_sale=True)],
|
||||
i2: [_match(g2, "Olive Oil", current=8.00, regular=8.00, is_on_sale=False)],
|
||||
}
|
||||
pantry_ingredient_ids = set()
|
||||
|
||||
result = compute_recipe_cost(
|
||||
recipe_id=recipe_id,
|
||||
ingredients=[_ingredient(i1, qty=2.0), _ingredient(i2, qty=1.0)],
|
||||
match_index=matches,
|
||||
pantry_ingredient_ids=pantry_ingredient_ids,
|
||||
)
|
||||
|
||||
assert isinstance(result, RecipeCost)
|
||||
assert result.recipe_id == recipe_id
|
||||
assert result.total_ingredient_count == 2
|
||||
assert result.matched_ingredient_count == 2
|
||||
assert result.sale_ingredient_count == 1
|
||||
assert result.total_cost == Decimal("16.00") # 2*4 + 1*8
|
||||
assert result.total_savings == Decimal("2.00") # 2*(5-4)
|
||||
|
||||
|
||||
def test_unmatched_ingredient_zero_cost_and_savings():
|
||||
recipe_id = uuid4()
|
||||
i1 = uuid4()
|
||||
result = compute_recipe_cost(
|
||||
recipe_id=recipe_id,
|
||||
ingredients=[_ingredient(i1, qty=1.0)],
|
||||
match_index={},
|
||||
pantry_ingredient_ids=set(),
|
||||
)
|
||||
assert result.matched_ingredient_count == 0
|
||||
assert result.total_cost == Decimal("0.00")
|
||||
assert result.total_savings == Decimal("0.00")
|
||||
|
||||
|
||||
def test_pantry_hits_counted():
|
||||
recipe_id = uuid4()
|
||||
i1, i2 = uuid4(), uuid4()
|
||||
g1, g2 = uuid4(), uuid4()
|
||||
matches = {
|
||||
i1: [_match(g1, "X", current=2.00, regular=2.00, is_on_sale=False)],
|
||||
i2: [_match(g2, "Y", current=3.00, regular=3.00, is_on_sale=False)],
|
||||
}
|
||||
result = compute_recipe_cost(
|
||||
recipe_id=recipe_id,
|
||||
ingredients=[_ingredient(i1), _ingredient(i2)],
|
||||
match_index=matches,
|
||||
pantry_ingredient_ids={i1},
|
||||
)
|
||||
assert result.pantry_hit_count == 1
|
||||
assert result.pantry_hit_pct == 0.5
|
||||
Reference in New Issue
Block a user