Costing & Pricing¶
Costing a recipe¶
Provide purchase data — any object satisfying the PurchasedItem protocol
works. Purchase is a built-in Pydantic model for convenience.
from decimal import Decimal
from wright import Purchase, calculate_recipe_cost, get_top_cost_drivers
groceries = [
Purchase(name="Flour", quantity=1000, unit="g", price=Decimal("3.99")),
Purchase(name="Butter", quantity=500, unit="g", price=Decimal("5.49")),
]
cost = calculate_recipe_cost(recipe, groceries)
calculate_recipe_cost returns a RecipeCost with:
| Attribute | Type | Description |
|---|---|---|
.total_cost_range |
PriceRange |
min/max total cost for the recipe |
.cost_per_serving_range |
PriceRange |
min/max cost divided by servings |
.ingredient_costs |
list[IngredientCost] |
per-ingredient cost breakdown |
print(cost.total_cost_range)
# → PriceRange(min_price=Decimal('1.99'), max_price=Decimal('1.99'))
print(cost.cost_per_serving_range.midpoint)
# → Decimal('0.20')
Top cost drivers¶
drivers = get_top_cost_drivers(cost, n=3)
# → list[IngredientCost] sorted by price_descending
for d in drivers:
print(f"{d.ingredient_name}: ${d.price_range.midpoint}")
Unit conversion¶
Recipes use grams. Purchases use pounds. wc_right handles conversion
transparently:
For volume-to-weight conversions (e.g., olive oil), provide density data:
density_data = {"liquids": {"Olive Oil": 0.91}} # 0.91 g/ml
cost = calculate_recipe_cost(recipe, groceries, density_data=density_data)
For dry ingredients (spices, sugar), use volume weights:
density_data = {
"volume_weights": {
"Cinnamon": {"tsp": 2.6, "tbsp": 7.8},
"Sugar": {"tsp": 4.2, "tbsp": 12.5, "cup": 200.0},
}
}
Pricing¶
Two strategies, one idea: cover costs and leave margin.
from wright import margin_price, multiplier_price
cost = Decimal("2.00")
margin_price(cost, Decimal("0.67")) # → Decimal('6.06') — 67% margin
margin_price(cost, 0.67) # → Decimal('6.06') — float also works
multiplier_price(cost, 3) # → Decimal('6.00') — 3× cost
Every pricing function returns a Decimal. No formatting or rounding inside
the library — do that at your UI layer.