# hospitality.recipe-cost Costs a recipe the way a kitchen costing sheet does: what each ingredient costs in the recipe, the total, and the cost of one portion. For each ingredient: 1. **Convert** the quantity the recipe needs into the unit the pack is sold in, with `units.convert` (250 g of a 1.5 kg bag is 0.25 kg). Count items use the unit `each`, which only converts to `each` (3 eggs from a tray of 12). 2. **Gross up for yield.** `quantity` is the usable amount the recipe needs after trimming and peeling. `yieldBasisPoints` is the usable share of what is bought: 400 g of peeled carrots at an 8000 (80%) yield means buying 500 g. A common mistake multiplies by the yield instead, costing 320 g. 3. **Price it** as that share of the pack price, in one exact division, rounded half-up to the minor unit. The total is the sum of the rounded line costs, so the sheet adds up, and the portion cost is the total divided by `portions`, rounded half-up. ## Precision Quantities and pack sizes are decimal text (`"0.75"`), never floats. The converted quantity is carried to 9 decimal places of the pack unit, a microgram of a kilogram pack, and everything after that is exact integer arithmetic. Pack sizes may have at most 6 decimal places and 15 digits. An ingredient whose cost cannot be held exactly (beyond 2^53 minor units) is an error rather than a rounded guess. A line under half a penny (a pinch of salt) costs 0. Kitchens that want those counted usually add a "sundries" line as a fixed amount. ## Errors - Units must be ones `units.convert` knows (`g`, `kg`, `mL`, `L`, `oz`, `lb`, `floz_imp`...) or `each`, and a quantity and its pack must be the same dimension: oil costed in grams but bought by the litre needs a density, which this does not guess. - `yieldBasisPoints` is 1 to 10000, `portions` at least 1, pack prices not negative, and every pack price in `currency`. 1.0.1 fixes Python accepting a trailing newline in quantity and packSize; adds tests.