Recipe-Derived Stock

For dishes cooked to order — showing how many portions the ingredients still cover instead of a quantity nobody counted, and why it never stops a sale.

7 min read · Updated 10 Sep 2026

On this page

Some things you sell have no stock of their own. Nobody counts adobo; there is pork, soy sauce and rice, and a cook. Counting the dish is meaningless, and leaving it untracked tells a cashier nothing.

Stock from Recipe is the third option: Kassly works out how many portions the ingredients still cover and shows that instead. It is opt-in per item, and it is advisory — a number to inform a promise, never a limit.

Needs the Recipe Costing add-on (₱350 per branch each month), or any bundle that includes it — because it needs a recipe to derive from, and recipes live behind that add-on.

Switching it on

The tick is on the product form, in the Options card: Stock from Recipe. Three rules govern when you can use it.

It is edit-only. A product created a moment ago cannot have a recipe yet, so the option does not appear on the create form. Save the product, write its recipe, then come back and tick it.

It needs a recipe first. Until the item has one the checkbox is visible but greyed out, with the reason on hover: "Add a recipe for this item under Compositions first, then its stock can be derived from the ingredients."

It cannot coexist with Track Stock. An item counts its own units or derives them, never both — two disagreeing numbers for the same dish is worse than one. Ticking either box clears the other, and the server refuses the combination outright: "An item cannot both track its own stock and take its stock from a recipe. Turn off Track Stock to derive availability from ingredients."

How the number is worked out

For each line of the recipe that can constrain anything, Kassly asks how many portions that one ingredient covers, and the answer for the dish is the smallest of those.

Per line:

  1. Per portion = the line's quantity ÷ the recipe's yield.
  2. Converted into the ingredient's own stock unit, using the item's packaging conversions.
  3. Scaled up by the line's waste factor.
  4. Portions = the ingredient's on-hand quantity at this branch ÷ that figure, rounded down. Two point nine portions' worth of mince is two portions.

The dish reports the lowest figure across all its lines, and remembers which ingredient produced it — that is the limiting ingredient, and hovering the figure names it: "Limited by Pork Belly — 1800g on hand, 262.5g per portion".

An ingredient with no stock row at this branch counts as zero, not as unknown. An ingredient that tracks stock but has never been received here genuinely has none.

Waste is applied, and it makes the number smaller

A recipe line with w percent waste consumes quantity ÷ (1 − w ÷ 100) — you have to buy more than a kilo of fish to serve a kilo of fish. A line with 20% waste therefore covers fewer portions, not more.

Waste on the line 1,000 g of ingredient really consumes
0% 1,000 g
10% 1,111 g
20% 1,250 g

The same factor is used for the portion count, for the deduction a sale makes, and for the saved food cost, so the three always agree.

The live cost preview inside the Add Composition dialog is wrong. As you type a recipe, the Total ingredient cost and Cost per serving shown at the bottom of the dialog scale waste the other way — multiplying by (1 + waste ÷ 100) instead of dividing by (1 − waste ÷ 100). On a line with waste it understates the cost. The saved recipe, the Compositions list, the food cost reports, the stock deduction and this portion count all use the correct factor. Trust the list, not the dialog's running total.

Two rules that keep it in step with what a sale takes

Every line that a sale would skip is also skipped here, on purpose. Otherwise a line that never deducts anything would pin a dish at zero portions while it carried on selling.

A line is skipped when:

  • the ingredient has Track Stock off, or
  • the ingredient has been deleted, or
  • its unit cannot be converted to the ingredient's stock unit, or
  • its quantity works out as zero or less.

That first rule is also why this is never a cascade. If one of your ingredients is itself a recipe-derived item, it has Track Stock off — so its line is skipped rather than recursed into. Kassly only ever looks one level down, at counted ingredient stock.

Producible recipes — the ones a commissary makes in batches — are excluded from this entirely. They are consumed by a production run, not by a sale.

What you see

On Catalog → Products, an item with Stock from Recipe on shows its portion count in the stock column as 24 served, with a status badge.

On the POS, the card carries a badge reading 24 left.

Portions Reads as
Above 5 In stock
1 to 5 Low
0 Out of stock

That threshold of five portions is a flat default, deliberately provisional — whether it should be something you set per dish is still an open question.

A dash is not "sold out"

Sometimes there is no honest figure to give, and Kassly shows -- rather than guessing. A dash never means the dish has run out. Hover it and the reason is there:

Reason Hover text
No recipe attached No recipe attached yet, so there is nothing to derive portions from
No tracked ingredients None of this recipe's ingredients track stock, so no portion count can be derived
Yield missing or invalid This recipe has no yield set, so portions cannot be worked out
No branch chosen Pick a branch to see how many portions the ingredients cover

The last one catches most cases: ingredients are held per branch, so a portion count with no branch selected would be a number about nowhere. Pick a branch at the top of the app.

On the POS a dish with no figure synced is treated as unconstrained rather than sold out — showing "sold out" for a dish nobody measured would take it off the menu for no reason.

It never blocks a sale

This is the design, not a gap.

A dish showing 0 portions can still be sold. The card stays tappable, the cashier can ring it up, and nothing warns or asks for an override. Compare counted stock, where a tracked item at zero disables the card.

The reason is that a derived figure is never quite true:

  • it is a snapshot of one branch at one moment, stale the instant another till rings the same dish;
  • an offline terminal cannot see the sales that have not synced yet;
  • it is only as good as the ingredient on-hand behind it, which drifts every time spoilage or a delivery goes unrecorded.

A POS that refuses a dish the kitchen can actually cook is worse than one showing a stale count. So treat the number as what it is: a good enough answer to "can I promise this to the table", checked by the person who can see the kitchen.

Because that is the point, cashiers can see the figure too — not just owners and managers.

Variants

The catalogue list and the POS grid use the item's product-level recipe — the one that applies to all variants. A dish whose only recipes are variant-specific therefore reads as having no recipe on the list, even though selling it deducts correctly.

Per-variant portion counts are available when Kassly asks about one specific item and variant, which is what happens when you open the item itself.

When the figure looks wrong

Symptom Usual cause
-- on every dish No branch selected
-- on one dish No recipe, an inactive recipe, or all its recipes are variant-specific
Far fewer portions than expected The yield is wrong, or an ingredient's cost/unit was entered per pack instead of per stock unit
Far more portions than expected An ingredient that should constrain it has Track Stock off, so its line is being skipped
A dish that should be out still shows portions The ingredient's on-hand figure is overstated — count it

Where to go next