Procurement — getting stock in the door, before it hits the books¶
What this covers. Everything that happens before goods are physically in your warehouse: deciding what to buy, how much, and from whom — and then checking that what arrived, at the price it was charged, matches what you ordered. The central idea is that a purchase order is a promise, not a stock fact: flour you have ordered but not received is not on hand, cannot be cooked, and has no cost yet. This chapter explains the suppliers you buy from, the units goods come in, and the supplier products that price them; the per-place minimum and maximum stock levels that decide when to reorder; the goods receipt, whose one job is to put goods into stock with a quantity and a cost, and the supplier's papers it can be read from so nobody types them — and the lightest case of all, a no-supplier market run that posts stock from just an item, a quantity, and a cost; the match between what was ordered and what was received; and the stock-aware plan that subtracts what you already have (and have already ordered) from what you need, so you never double-buy. Everything you buy rides this same path — ingredients, packaging, expensed supplies, even a €4,500 oven.
1. Buying is intent; the ledger is reality¶
A warehouse's stock ledger is the dated record of what physically happened to stock — what was received, consumed, transferred, wasted, counted — and its figures stay settled while the governing close remains in force. (Perpetual inventory means the on-hand count is kept live, move by move, rather than discovered once a month at a stocktake.) Procurement sits in front of that ledger. It is the layer of intent: a decision to buy 20 kg of flour next Tuesday.
That decision is a commitment, not a stock movement. A stock movement is the ledger's unit of physical change — value moving from one place to another. A commitment changes nothing physical. Flour you have ordered but not received:
- is not on hand — you can't cook with a promise,
- has no cost in the books yet — its weighted-average cost (the blended price its deliveries strike) is unaffected,
- and is not in the ledger at all — no movement, no entry.
So the single most important rule of this whole chapter is:
A purchase order never moves stock. It is a commitment document, full stop. Stock and value enter the books at exactly one moment — receipt, when goods physically arrive and a goods receipt is recorded. The order and the receipt are two different things, deliberately kept apart, and reconciled by the match (§6).
Why keep them apart at all? Because they answer different questions and change for different reasons. The order is what we intend to spend; the receipt is what we actually got and what it actually cost. If you let the order touch the ledger, your on-hand count would inflate the instant you placed an order — long before the truck arrives, and even if it never does. The order's money is committed but not yet spent: it's the difference between "we have 5 kg of flour" and "we'll have 25 kg by Friday." Both numbers are true, and the plan in §8 needs both — but only one of them is stock.
This is the classic separation a large ERP draws between three roles: purchasing (the commitment), receiving (the goods actually showing up), and paying the supplier (the invoice). A big SAP-or-Odoo-style system keeps three separate documents wired together through a clearing account, and matches invoices to receipts many to many. For a small food-and-beverage operator that's ceremony with no payoff — so this domain keeps exactly one document, the goods receipt, and gives it one job: to put the goods into stock with a quantity and a cost. Paying the supplier is the business of the operator's accounting (Financial boundary).
An invoice, a till receipt, a delivery note — any supplier paper that lists the goods with their quantities and prices — is what a receipt's lines can be read from, so nobody has to type them (§6); the invoice and the till receipt are the supplier's bill, the paper that charges for the goods. The receipt records the goods at the quantities and prices of the paper it is entered from. What the paper printed stays beside the receipt as evidence, and comparing the two catches a misread line: it checks the reading; the receipt is the record.
A receipt answers to one supplier paper, and there is no clearing account between receiving and paying. A delivery that comes with two papers — two orders on one truck billed apart, a second till receipt rung up a minute later for something forgotten — is two receipts. Each paper states its own freight, discounts and taxes, and a cost belongs to the goods it was incurred for: the delivery charge printed on one paper is no part of what the goods on the other cost. What matters is the match: did we get what we ordered, at the price we agreed?
The market run: a goods receipt with no supplier at all¶
There is an even lighter rhythm, and it is first-class, not a workaround: the cash run to the market or the bazaar, where the cook buys a crate of tomatoes from a stall that hands over no paper and is no one's catalogued supplier. A goods receipt does not need a supplier or a supplier product to bring that stock in. The minimum to post a movement is genuinely small: an item, a quantity in a plain measure, a cost, a warehouse, and a date. That cost is all weighted-average costing needs; the stock lands and is valued exactly like any other receipt.
Everything supplier-shaped is optional on top of that floor. When a supplier is named, the match (§6) and the price-history learning kick in; when one isn't, they simply don't apply — there is no order to match against and no supplier product whose price to record, and that is fine. The market buy is the everyday reality a food operation runs on, so the receipt is built to accept it with no ceremony.
A saved list carrying the Shopping label is the lightweight prep document for that run. It can mix catalog items with unresolved free text and keep quantities, unit hints, notes, and supporting attachments only where they help. When a walk-in goods receipt starts from it, the receipt may retain that link as provenance, but the receipt still records only what was actually bought. The saved list never moves stock and has no open, closed, or cancelled lifecycle, so it can remain useful for the next market run until it is soft-deleted. Deleting it later does not erase the provenance already kept by a receipt.
2. Who you buy from: suppliers and the product that prices an item¶
Procurement has to know what unit the goods come in, who sells it, and at what
price, with what lead time. Two ideas carry this: a supplier (who you buy from)
and a supplier product (how one supplier prices one item, in a chosen unit).
There is no separate "bundle" record between them — the bundle a thing arrives in is
just one of the item's units (a 25 kg sack, a case of 6 × 2 kg), exactly like
kg or each, taught in Units of measure. You order
in whatever unit you buy in ("2 sacks"); your stock is held in the base measure
(grams, once it lands); the unit's ratio turns the one into the other without anyone
doing the arithmetic twice.
The supplier¶
A supplier is a vendor you buy from: a name, a contact person, phone, email, address, and any attached paperwork (a signed contract, a price list). It is scoped to your company — your suppliers are yours. A supplier owns no prices itself. Price lives on the supplier product, because the same vendor sells flour, sugar, and oil at three different prices in three different units.
The supplier product¶
A supplier product is one supplier's catalogue line for one item, bought in a
chosen unit — how you buy this item from this vendor, and at what. It points at the
item and the unit it is priced in: a per-item bundle (a 25 kg sack), or a
plain measure (kg, for loose produce). The same item from two vendors is two
lines; the same item priced two ways by one vendor — per sack and per pallet — is
two lines too. Each carries the commercial terms and the recognition keys for that
line:
- the price in that unit — what this supplier charges per sack, per case, per kg,
- the price per base measure — the same price expressed per kilogram or per liter, so you can compare two suppliers like-for-like even when one prices a 25 kg sack and the other a 10 kg bag,
- the lead time — how many days from order to delivery, used to decide when to place the order so it lands in time (§8),
- the minimum order quantity (MOQ) — the smallest amount the vendor will sell; you can't order half a sack,
- the recorded price history — what this product has actually cost over its recent receipts, feeding the anomaly checks (§6). The history also yields the product's typical price: the middle value of its recent history, not the average, so one box misread as a single piece at ten times the price cannot poison the very figure used to catch that mistake,
- and the codes and descriptions that let a line on the supplier's paper be recognized as this line: the supplier's printed code (their article number), and the free-text line descriptions it has used before, learned over time — plus a shop link and photos of the goods and the supplier's label.
The supplier product is optional, and entirely a purchasing-side concept: it exists to power purchase-order creation, the order ↔ receipt match, recognizing lines read off a supplier's paper, and price memory. Bringing stock in needs none of it — a goods receipt posts from an item, a unit, a quantity, and a price (the market run, §1). A catalogue line can even sit unresolved, naming a supplier and a code but no item or unit yet, until someone matches it — and that match is yours to change. Which item a supplier's line points at is a bookkeeping decision, not a fixed fact: re-aim it whenever you learn the line meant a different item, or fix one you mapped wrong. That never disturbs what you already received — every goods receipt froze its own item and unit the moment it posted — so a catalogue line only guides the next delivery, it never rewrites the last.
Worked example. Flour from "Baker's Supply": you buy it as a 25 kg sack (a per-item unit, ratio 25 000, since 25 kg = 25 000 g), and a supplier product prices that item-in-that-unit at €18.00 a sack, 2-day lead time, MOQ 1 sack. The price per base measure is 18.00 ÷ 25 000 = €0.00072 per gram, i.e. €0.72 per kg — the number you'd line up against a rival vendor's own product for the same flour. Order 2 sacks and that's 50 kg = 50 000 g feeding the plan's base-unit math; the committed cost is 2 × 18.00 = €36.00.
Variable-weight goods (catch-weight). Some goods are sold by a weight that isn't fixed per package — a side of beef, a wheel of cheese, loose fruit weighed at the counter. The supplier prices them per measure (per kilogram), and each delivery's actual weight is whatever the scale read that day. The unit for these is that measure — one kilogram, priced per kilogram — and the received line carries the weight that arrived (5.945 kg, not "1 case"). The ledger books exactly that weight: there is no fixed bundle to convert, because the weight is the quantity.
3. How much to keep: minimum and maximum per place¶
A par level answers a simple question: how much of this should I keep on hand here? It comes as a pair of numbers — a minimum and a maximum — set per item, per warehouse — a warehouse being one place the business actually holds stock.
- Minimum (the reorder point). When the projected on-hand for this item at this warehouse falls to or below the minimum, it's time to reorder. This is the everyday, demand-agnostic trigger that keeps you from running out.
- Maximum (the order-up-to level). The target you replenish back to. The
baseline order quantity is simply
maximum − projected on-hand, before any rounding for unit size or MOQ.
Why per-item-per-warehouse, and not just per item? Because the warehouse is the grain at which stock actually lives and is valued — on-hand and weighted-average cost are both warehouse-level facts (see Scope & locations and Costing & valuation). The bar and the dry store, run as two warehouses, hold what is, on paper, the same item, but they're different pools that run down at different rates and reorder on different cadences. A commissary warehouse that supplies three restaurants pars high; a single outlet's own warehouse pars low. A par level is a property of stock held at a place — exactly like on-hand and cost — so it belongs at the same grain.
Don't confuse the maximum with the supplier's MOQ (§2). They're different numbers from different sides of the table: MOQ is "the smallest the vendor will sell you"; the maximum is "the most you want to hold." Both feed the plan, and they're not interchangeable — a vendor might force a 1-sack minimum on an item you'd happily hold only 5 kg of.
Par only applies to a quantity book¶
A par level needs a countable on-hand balance to compare with its minimum. Both stock and counted consumables keep that quantity book; the first also carries value, while the second is always worth zero. Category never decides either case (see Item model & policies).
Everything that materializes, though, is orderable — any such item can be a purchase-order line and a goods-receipt line, and only the phantom is refused, since nothing of one ever arrives to be ordered or received. What the par gate decides is only whether the plan can propose an item automatically:
- Stock items can be par'd, and the plan can propose orders automatically from their minimum and maximum.
- Counted consumables can also be par'd from their zero-value quantity book.
- Plain consumables — cooking oil, salt, a cleaning supply — are expensed when received and never counted or valued. They have no on-hand quantity, so there is nothing for a minimum to watch and nothing for a maximum to refill toward. The operator can still put oil on an order by hand whenever they like, but the plan will not auto-propose it. Manual-add only.
- Fixed assets — an oven, a mixer, a walk-in fridge — are likewise orderable, manual-add only (nobody auto-reorders ovens off a par level). They ride a purchase order and a goods receipt like anything else; the difference shows at receiving, where the receipt creates an entry in the asset register instead of a stock movement (see Fixed assets) — and the line still participates in the match. A €4,500 oven is exactly the line worth matching.
4. The purchase list: capturing intent before it's resolved¶
Everything from here down assumes a buying decision is already resolved — you know the supplier, the unit, the price, the exact item. But that is rarely where buying actually starts. It starts with a scribble:
"I need 101 eggs, 5 kg of flour, and some cling film."
No supplier chosen. No unit chosen. Quantities in whatever unit is natural — and maybe not even a firm catalog item yet ("some cling film"). Forcing the operator to pick a supplier, a unit, and a price before they can even jot down "eggs" is exactly the kind of friction that stops a busy kitchen from starting at all. So the domain gives that scribble a home of its own: the purchase list.
A purchase list is loose buying intent, captured early — the everyday request that precedes the order. Like the order it is pure intent: it never moves stock and never touches the books. Unlike the order it is deliberately unresolved:
- a line may be a real catalog item or just free text ("cling film") — it only has to name something;
- the quantity, the unit, the needed-by date, and the warehouse are all optional — "some cling film" is a perfectly valid line. A warehouse a line does name is one that holds operating stock: a list nets against a pool and ends as goods on a storage location, so it never plans against the books that carry the asset register;
- there is no supplier and no price on it at all.
The kitchen adds to one list across the week; it can be printed and shopped; and when the buying decisions firm up, each line is resolved — bound to a catalog item (with a suggestion the operator applies, never an automatic guess) — and then fulfilled. The whole arc is capture → resolve → fulfill, and there are two ways to fulfill a list:
capture ┌─ Plan it ─▶ supplier + unit chosen, rounded to units ─▶ draft order(s) ─▶ receipt
purchase list ─▶ per line (your quantities at face value; optionally net out stock)
(loose lines) └─ Print ──▶ shop ─▶ keep the till check ─▶ scan the check ─▶ goods receipt
Plan it turns the list into actual orders. It does the same order-shaping the stock-aware plan does (§8): it resolves each line to a supplier and a unit, rounds the quantity up to whole units and the supplier's minimum, and groups the result one draft order per supplier. What it deliberately does not do by default is netting — subtracting what you already have. A hand-written list is an explicit statement of intent, so Plan it takes your quantities at face value: ask for 101 eggs and it orders enough whole units for 101 eggs, even if some are already in the fridge. Subtracting on-hand is offered as a deliberate opt-in: turn it on and a line is reduced by what's already on hand and already on order, and a line that's already fully covered is marked as such and ordered as nothing. (Contrast the automatic plan in §8, where netting is always on — that is the whole point of a reorder-point. The difference between the two is exactly the difference between "keep the stock topped up" and "I, a human, want these things.")
A line that can't be planned — no firm item, no quantity, a unit that can't be converted, or no warehouse whose shortage it is answering — is surfaced, not silently dropped; so is a plannable line with no supplier or unit to source it from ("pick a supplier"). The operator fixes it and plans again. Lines they decide they don't want are dropped. Whatever is left can simply be lived with: an unresolved "cling film" line may linger — that is the point of a low-friction front door — until the operator closes the list, or cancels it to abandon it.
The other path needs no orders at all. The operator prints the list, shops, keeps the till check, and records a goods receipt from that check — the same photo-to-receipt flow used for any walk-in purchase (§6). The list and the receipt aren't wired together; the list was just the shopping memo. When the trip is done, the operator closes the list.
Why a separate thing, and not just a loose order? Because an order carries invariants a loose list would break — above all one supplier per order, the very thing the match (§6) reconciles against. A list that mixes eggs from one vendor and flour from another can't be a single order. Keeping the loose, multi-supplier, pre-resolution stage as its own artifact lets the order stay strict and matchable, and lets capture stay effortless. The purchase list is the third source of demand in this domain — the manual one — beside the two automatic feeders the plan already has (§8); it is the one a human authors by hand, and the only one that is stored, printed, and shopped.
5. The purchase order: a commitment to one supplier¶
A purchase order is a commitment to one supplier for specific items, at specific quantities, in chosen units, at agreed prices, expected by a date. It has:
- a header — your company, the supplier, the order date and the expected-by date, a status (§7), a note, any reference documents (a supplier quote, the emailed order confirmation, a signed copy of the order), and optionally a pointer back to the plan run that proposed it. These documents are filing-cabinet material — the supplier's bill is never one of them; it is kept with the goods receipt (§6);
- lines — one per item ordered: the item, the unit ordered, the ordered quantity (in those units), the agreed price per unit, and a derived base-unit quantity and committed amount.
An order names no destination. It is a commercial fact: this supplier, these goods, these quantities, this money. Where the goods end up is decided when they physically arrive, line by line, on the goods receipt — because that is when somebody is standing in the building with a box, and only then is the answer real. Ordering flour a fortnight before a delivery van picks a door is a guess, and a guess written on the order would either be re-typed at the door anyway or, worse, quietly believed.
What the order does remember is the other half of that question: whose shortage a line was raised to cover. When a par level or a purchase list drafts a line, the line keeps the warehouse whose gap it answers. Nothing is placed by it and no operator is asked for it — a line typed by hand carries none — but the next plan reads it, which is the whole reason it is kept (§8).
By construction the order is pre-ledger: no stock movement or effect on weighted-average cost. Its only money figure is a commitment — the sum of line price × quantity — and that number is used for two things only: forecasting how much you'll owe suppliers, and the match (§6). It is never fed to valuation. What feeds cost is the receipt's actual net cost, not the order's promise (see Costing & valuation).
Why one supplier per order? Because an order is a thing you send to a vendor and then match against what that vendor delivers. The plan in §8 may work out demand across many items sourced from many suppliers — but it then groups the result one order per supplier, so each order is a single thing you can send, receive, and reconcile against that supplier's receipts.
6. The match: ordered vs received¶
When goods arrive, the operator records a goods receipt — the document that brings stock into the books (what it does to stock and cost is covered in Stock ledger). It says what came in, how much of it, and what it cost; the supplier's paper is only where those figures were read from (§1). The match sets the order, which says what was promised, against the receipt, which says what arrived and what it was charged, and answers: did we receive what we ordered, at the price we agreed?
The link is per line, and it's optional¶
The connection from an order to a receipt is drawn line by line, and it is allowed to be absent. Two properties, both deliberate:
- Line-level, not document-level. One order can be received across several deliveries — the produce vendor ships what's fresh today and back-orders the rest; one sack is damaged and refused at the door. And one delivery can fulfill lines from more than one order. Matching at the item grain is the only way to support that fan-out honestly.
- Optional — walk-in receipts are first-class. A receipt line can point at no order at all, and that is completely normal: the chef drove to the market and bought tomatoes; a vendor dropped off a substitution nobody ordered. Food-and-beverage runs on these. The match never requires an order; an un-linked receipt line is the rule for spontaneous buys, not an error.
Sitting above those per-line links, a receipt also names — at its header — the set of orders it fulfills: a multiselect of one or more purchase orders the operator declares this delivery to be against. The submitted set is authoritative, and it stays in step with the line links automatically: linking any receipt line to an order's line auto-declares that order (the declared set is every order explicitly chosen plus every order a line points at), and dropping an order from the set detaches — unlinks — its lines. A declared order is checked two ways: it must belong to the same supplier as the receipt, and it must still be open to receive against — only an Ordered or Partially received order can be declared, never a finished (received/over-received) or cancelled one. Re-reading a receipt's paper re-derives the lines as unlinked, and if the supplier changed it clears the declared set (those orders belonged to a different vendor). The header set is the operator's statement of intent; the per-line links above remain optional and per-item beneath it.
Checking the money: the price promised against the price charged¶
The financial half of the match compares like with like: the order line's committed amount — its price × quantity — against what the receipt says the supplier charged for those same goods, after any discount and before tax and freight. Tax and freight stay out of the comparison because the order never promised them: an order commits to a price for goods, while tax follows from the law and freight from the delivery, and neither says whether the supplier kept to the price agreed. A $100.00 order line received as $100.00 of goods with $8.88 of sales tax is a kept promise, not a price change. (What tax and freight do to the cost of the goods is a separate concern, explained in Costing & valuation.)
A small tolerance absorbs honest penny-drift — a unit price rounded differently, a fractional cent here or there. The tolerance is a per-currency configuration default of 0.05, not a hard constant: what counts as penny-drift depends on the currency the company keeps its books in.
The match doesn't just answer matched-or-not; it classifies each order line with one verdict from a fixed, ordered set, and quantity is decided before price:
not-received → nothing arrived against this line
short-received → less arrived than was ordered
over-received → more arrived than was ordered
unpriced → no expected price to compare against
price-mismatch → quantity is right, but the goods were charged beyond tolerance of the order
matched → right quantity, right money
The quantity verdicts come first because a line that under- or over-delivered is a quantity story regardless of price; only once the quantity lines up does the money get compared against the tolerance. This is exactly the per-line classification that makes the order's own status derivable — a line's over-received verdict is what lifts the whole order to over-received in §7. The same verdict rule serves a receipt-side preview too: before a draft is posted, the operator can see what posting this receipt would do to each declared order's lines and status, computed against a received baseline of the already-posted lines plus this receipt's own (other open drafts don't count).
The receipt's own money: what was charged, and whether it adds up¶
Taxes belong to the document, not to its lines. A supplier charges a tax on goods, and usually on several at once: one sales-tax figure at the foot of a US receipt, one VAT figure for each rate on a Portuguese invoice. A receipt therefore holds its taxes as they were charged, each naming the goods it was charged on; a tax that names none was charged on the whole purchase. Goods taxed at the same rate bear one tax however the operator enters it: a rate set against each line is still the receipt's one figure for that rate, worked out once over all those goods, since rounding it line by line drifts from the bill by cents. The amount the bill prints is the tax — cost is what was actually incurred, and a supplier rounds its tax in its own way — so a rate printed beside the amount only describes it. A tax is known by its amount or by its rate; one the bill gives neither for is not yet a tax of the receipt, and a scan says what it could not read rather than booking it. What any one line bears is worked out from these taxes (Costing & valuation §3); it is a result. And a tax stays with its goods: it is a charge on those goods and on no others, whatever else the purchase holds.
A discount on the whole purchase or on promoted goods, and savings that are only information. Beyond a discount on a single line, a supplier may take one overall discount off the whole purchase; it lowers what every good cost (the same §3). A promotion discount that names the goods it was earned on — €0.66 off for three almond and three coconut drinks — is neither: it lowers what those goods cost and nothing else, shared between them by what each cost (€0.33 each here), and it falls on the whole purchase only when the bill does not say which goods earned it. "Coupon savings" printed on a receipt are a different thing — a note of how much the prices above have already come down. A receipt whose goods come to $602.37, with $13.65 of tax and $616.02 to pay, and which also prints "Coupon savings $3.00", cost $616.02: the $3.00 is already inside the $602.37, and is never taken off a second time. Coupon savings are the line discounts over again, so a receipt does not keep them; a scan only checks them against its line discounts and says when the two differ.
Checking the receipt against its paper. A second, lighter check sits beside the match, and it asks something else: was the paper read right? A receipt read from a supplier's paper keeps what that paper printed — its subtotal, its taxes and the amount they were charged on, its total and any discount — and each line read from it keeps the amount printed for that line. Beside them the receipt holds the totals its operator expects it to add up to — the printed ones to begin with, or the amount paid on a market purchase that had nothing to scan. A disagreement points at a line worth a second look: a quantity read as 1 where the paper says 10, a price taken from the wrong column, a line read twice.
The goods arrived whether or not the paperwork balances, so money that does not add up is a question, never a stop. When the receipt's own sums disagree with the expected totals — or cannot be finished at all — the goods are stock all the same: received, costed and counted like any other delivery. This catches a misread line; the order ↔ receipt match catches a mis-delivery or a price change. They are different questions asked of the same receipt.
A receipt need not repeat its paper: one bill may be split across several receipts, and goods the company does not keep in stock are left off. A receipt that differs from its paper — in its totals, or in a line against the amount printed for it — is as complete as its own figures are.
Reading a paper: from a photo to a draft receipt¶
Typing a supplier's paper in by hand is the chore an operator most wants to skip, so a receipt can also be read straight off a photo or PDF of any paper that lists the goods with their quantities and prices — an invoice, a till receipt, a delivery note. The reading produces a draft goods receipt, never a posted one — a starting point the operator reviews, corrects, and only then posts. Three things happen in that read, in order, and each is deliberately conservative: the system would rather leave a line for a human than guess wrong and quietly book the wrong stock.
- Identify the supplier. The vendor on the paper is matched to one of your existing suppliers by name, across language and script — a bill that prints "Макро" is recognized as your "Makro." If no existing supplier is clearly the vendor, a new supplier is created from the name and contact details printed on the bill, so the draft always lands against a real supplier. Supplier identification is fully automatic; there is no separate "is this the right vendor?" step.
- Auto-fill the lines the system already knows. Every supplier product remembers the codes and descriptions that supplier has used for it on past papers (the recognition keys of §2). A line whose printed code or description exactly matches one of those learned keys is bound straight to its item and unit and becomes a real, postable receipt line — and the match is learned, so this supplier's papers get easier to read every time. Only an exact, deterministic match auto-fills; nothing is bound on a fuzzy resemblance.
- Set the rest aside for review. Every other line — a product the system can't confidently place, a line it has never seen from this supplier, a credit or return — is set aside as an extracted line awaiting review, not silently dropped and not guessed into a binding. Each carries what was read (the description, quantity, price, and which file, page, and exact place on that page it came from, so the operator can jump back to the source) plus, where the read was confident enough, a suggestion: "this looks like your existing Olive Oil 5L — confirm it," or "this looks new — create it as a new item." A suggestion is only ever a prompt for a human; it never binds the line on its own.
The operator then works the review list down. Applying a line turns it into a real receipt line (creating the item or unit first if it's genuinely new); dismissing a line drops it — a duplicate, a header row the reader mistook for a product. Either way the line leaves the review list. A line proposed as new is the operator's chance to tidy the inventory name, the unit name, and the unit's conversion ratio before committing — exactly the moment those are still editable.
Reading a line at the right grain. One printed line often states the same goods two ways — a coarse "1 box" alongside a finer "10 × 1 kg @ €0.99," or a weighed "5.945 kg @ €2.20/kg." The read takes the finest grain the bill actually prices, so the quantity that lands is the real one: ten kilograms from that box, the weighed kilograms from the scale — never "1" when the box holds ten. It only copies numbers the bill prints and checks they reconcile to the line's total; if the only price shown is per box, it reads one box and leaves the unit size to the item's known ratio. Rows that aren't goods at all — a delivery fee, an included tax or levy memo, a returnable-container deposit — are recognized by their role and kept out of the product lines, never read as stock.
A draft can't be posted while lines are still awaiting review. Posting brings stock and cost into the books, and a half-reviewed scan would silently drop the stock on every un-applied line. So a receipt read from a paper cannot post until every extracted line has been applied or dismissed — the review list must be empty. This is the one gate the photo path adds; it exists precisely so a readable-but-unplaced line can never vanish into a posted document.
A draft receipt says everything that stops it posting, all at once — rows still awaiting review, rows nobody has placed, a contour sealed over the document's date, an item that has since stopped being purchasable — and posting refuses on exactly that list, never on a reason the draft did not show. Why: the operator fixes three things in one pass instead of discovering them one attempt at a time, and no screen or agent has to guess the posting rules to know whether to offer the button.
A receipt's files: its supplier paper and its attachments. Not every file kept with a delivery is a priced paper. The supplier's invoice, till receipt or delivery note is the receipt's supplier paper — what its lines are read from; a photo of the goods on the table, the boxes, a damaged pallet or a label printing no prices is an attachment, kept with the receipt as evidence and never read. When files are read, a badly photographed bill is still a supplier paper; a file is sorted as an attachment only when it is certainly no priced paper. A delivery whose files hold no priced paper at all is still recorded: a draft with its attachments and no lines, keyed by hand.
A receipt is read from all its pages at once. A paper often runs over several pages — the goods on the first, the totals, the tax breakdown and the promotion summary on the last. Read apart, each page loses what the others say, so the pages a receipt's lines come from are always read together, as one set. A page added later means the whole set is read again, and the new reading replaces everything the earlier one produced on the same receipt — its lines, its review list, what the paper printed — a clean re-do, not a merge. A file the new reading leaves out stays with the receipt as an attachment, and a file added without a reading is one too. A posted receipt is no exception: its booking is taken back and it returns to a draft to be reviewed and posted again, because the stock and cost it books must come from what the whole set says. A page taken away without a reading leaves the lines read from it standing. A receipt keyed by hand keeps its lines when a file joins it: they are the stockkeeper's statement, and the file is kept as an attachment. Only a read the operator asks for rebuilds it from its paper. The read is a convenience that produces a draft for a human to finish, never an authority that posts on its own.
Worked example. - Order line: 2 sacks of flour @ €18.00 = €36.00 committed. - Goods arrive: 2 sacks, and the bill charges €36.03 for them before tax (the supplier's price rounds 3 cents differently). - Right quantity, difference = 0.03 ≤ 0.05 ⇒ matched, no operator action. - Counter-case: the bill's line reads €38.50 (the price went up). Right quantity, difference = 2.50 > 0.05 ⇒ price-mismatch, flagged for resolution. The receipt still records the goods at their real cost — the ledger always books what actually arrived — while the match is what surfaces the price drift so a human sees it.
Why the receipt, not the order, drives stock and cost. The order said €36.00; the truck might bring 1.9 sacks at another price. The ledger and the weighted-average cost must reflect what physically arrived and what it actually cost — that's the receipt, valued at its net landed cost. The order is the expectation the actual is checked against; it is never the source of the stock fact. That, in one sentence, is the entire reason the two are separate documents.
7. The life of a purchase order¶
An order moves through six states:
Draft ──▶ Ordered ──▶ Partially received ──┬──▶ Received
│ │ │ └──▶ Over-received
└───────────┴────────────────┴───────────────▶ Cancelled
| State | What it means | Effect on stock |
|---|---|---|
| Draft | being assembled — by the operator, or proposed by the plan; freely editable; counts as an open order in the netting engine (§8) so a re-run while a proposal stands does not generate duplicates | none |
| Ordered | committed and sent to the supplier; counts as an open order in the plan (§8) | none — still pre-ledger |
| Partially received | some lines or quantities have arrived and been received; the rest is still outstanding | the arrived portion enters the books via its goods receipt; the order itself, still none |
| Received | fully fulfilled — every line arrived, each within tolerance of what was ordered | none of its own (all stock effects belonged to the receipts) |
| Over-received | fully fulfilled, but at least one line arrived above its ordered quantity (beyond tolerance) — the supplier sent more than the order called for | none of its own (the surplus entered the books with its goods receipt) |
| Cancelled | abandoned before or partway through fulfillment; stops counting as open | none |
Why "partially received" is a real state, not an edge case. In food-and-beverage, partial deliveries are normal: the produce vendor ships what's fresh and back-orders the rest; a damaged sack is rejected at the door. Modeling "partly here" as an explicit state — rather than forcing the operator to cancel and re-order, or to pretend the whole thing arrived — keeps the open-order math honest. The still-outstanding quantity is exactly what the plan must keep counting as on-order (§8).
Received, over-received, and the rule when lines disagree. An order is fully delivered once every line has arrived. If each line landed within tolerance of what was ordered, the order is received — a clean fulfillment. If nothing is short but at least one line came in above its order (beyond tolerance), it is over-received instead: a distinct outcome so the operator sees "the supplier sent more than we asked" at a glance, rather than having it hide inside a plain "received." One rule settles the mixed case — still-short always wins. If even one line is under-delivered, the order stays partially received no matter how far another line ran over, because that short line is genuinely still on-order and the plan must keep counting it (§8). Over-received is reached only when nothing is short and something is over. Correcting the over-delivery later — cancelling the goods receipt that carried the surplus, or editing its quantity down — rolls the order back to whatever its remaining receipts justify.
Who approves an order. There's no separate approval workflow. The human confirmation is the approval: when the plan proposes a draft order, an operator — often through the Dough agent — reviews it and confirms it into Ordered. The person is the gate. The agent proposes and explains; the operator decides; the deterministic path then does the work.
8. The stock-aware plan: what to buy, and when¶
The plan answers the operator's real question — "what do I actually need to buy, and when do I place the order?" — by combining demand (what we'll need) with coverage (what we already have or have already ordered). It draws demand from two automatic sources and runs them through one netting engine. (The third source of demand — the hand-authored purchase list of §4 — is manual: it reuses the shaping half of this engine but skips the netting by default, since a human typing "101 eggs" means 101, not "101 minus whatever's in the fridge.")
Two automatic sources of demand¶
- The reorder point (everyday). From the minimum/maximum par levels (§3): if projected on-hand has fallen to or below the minimum, top back up to the maximum. This is the demand-agnostic baseline that simply keeps you stocked.
- The forecast cascade (planning). A forward-looking, menu-driven chain: a weekly sales plan → a daily distribution → per-restaurant ingredient demand (obtained by exploding each dish's recipe — walking the bill of materials down to raw ingredients, the same explosion described in Recipes & production) → logistics dates → a prep plan → procurement demand. This is the source for "we expect to sell N of dish X next week, so we'll need M kg of ingredient Y by Tuesday."
Demand combines across restaurants on the way down. In a group fed by a central commissary, each restaurant's forecast explodes separately, and the demand for shared prep items lands together at the warehouse that makes them.
Worked example. Restaurant A's Tuesday plan needs 45 kg of dough; Restaurant B's needs 30 kg. The prep plan therefore calls for 75 kg of dough at the commissary by Tuesday — and because dough is a prep item, its recipe explodes onward: 75 kg of dough at a 60% flour ratio becomes 45 kg of flour demand at the commissary's store, dated early enough to produce. That single flour figure — not two restaurant-sized ones — is what enters the netting engine below, gets the commissary's on-hand and open orders subtracted, and lands on one supplier's draft order.
The netting engine, step by step¶
"Netting" just means subtracting what you already have from what you need, so you only buy the gap. In business terms the engine does this:
- Total up gross demand per item and demand-date, from the logistics plan plus the raw materials exploded out of each prep item line (a prep item — formally, a semi-finished good — is something you make in-house and stock: a batch of dough, a base sauce; its own recipe is exploded to find the raw materials it consumes). This total is "raw need, before subtracting anything we have."
- Keep only what can be sourced. Items with a known supplier product or default supplier proceed; an item with neither is skipped with a warning — surfaced for a human, never silently dropped. (Recall §3: par-driven auto-proposals are limited to stock and counted consumables; plain consumables and fixed assets can still ride along if added by hand.)
- Net against coverage — subtract what's already covered. This is the heart of a stock-aware plan. From gross demand, subtract:
- real on-hand — the live ledger quantity at the relevant warehouse (the running sum of stock movements; see Stock ledger), and
-
open orders — the sum of
max(ordered − received, 0)across the lines of every purchase order that is not yet finished: Draft, Ordered, or Partially received. Both Received and Over-received are finished and excluded — an over-received order has nothing still outstanding, so it contributes zero coverage, and the per-linemax(… , 0)means an over-delivered line never subtracts more than was ordered. A draft proposal created in an earlier run of the netting engine is counted as coverage, so that a second run — before that draft is confirmed — does not generate duplicate orders for the same item.Which open lines count here is decided by the warehouse each was raised for (§5): a line planned for this warehouse counts, and so does a line planned for nowhere at all — the hand-typed order that answered no plan. A line raised for a different warehouse does not. The blank case is deliberate: goods are already on their way, and treating them as coverage risks proposing a little too little, while ignoring them risks buying the same sack twice. Under-ordering is the cheaper mistake — the next run sees the shortfall and fixes it, whereas a second sack has already been paid for.
There's also a within-this-run carry-forward: if rounding up to whole units on an earlier date over-buys, that surplus rolls forward and reduces a later date's need in the same run.
net need = gross demand − on-hand − open-order quantity − surplus carried forward
If net need comes out ≤ 0, order nothing and carry any surplus forward. 4. Round up for MOQ and unit size. Convert the net need (in base units) into whole units using the unit's ratio, take at least the product's MOQ, and round up — you cannot buy 1.3 sacks. 5. Back-date the order by the lead time. The recommended order date is the demand date minus the supplier's lead time, then snapped to the nearest valid ordering day on or before it. This is when to place the order so it arrives in time. 6. Group one order per supplier. Each line is resolved to its vendor (via the item's supplier product, or the item's default supplier), and the proposed lines are grouped one purchase order per supplier — one sendable, matchable document each.
The output is a set of draft purchase orders, one per supplier, each with lines carrying the supplier, item, order date, demand date, base-unit quantity, the unit, and the unit quantity.
One boundary worth stating: the engine buys from vendors — it does not move stock between your own warehouses, and it does not schedule production. In a group with a central commissary, "Restaurant B is low on dough" is answered by an explicit transfer from the commissary (see Scope & locations §5), not by a purchase order — and the netting engine does not propose those transfers. Likewise the prep plan stage of the forecast cascade (§8) tells the engine how much prep-item demand to explode into raw-material purchases, but the engine never emits "produce 60 kg of dough on Tuesday" — production runs record what the kitchen actually made; they are not proposed. Make-side and move-side suggestions are the same subtraction pointed at different sources and a natural later extension; today the commissary's production and dispatch rhythm is the operator's call.
Worked example (the subtraction that earns its keep)¶
Suppose next Tuesday's forecast needs 40 kg of flour at the dry store, the supplier's lead time is 2 days, the unit is a 25 kg sack, MOQ 1 sack, price €18.00 a sack.
- Gross demand (Tue) = 40 kg.
- On-hand now (the live ledger quantity at that warehouse) = 12 kg.
- An open order, already Ordered, arriving Monday = 25 kg (1 sack).
- Net need = 40 − 12 − 25 = 3 kg.
- Units = ceil(3 ÷ 25) = ceil(0.12) → bumped up to the MOQ = 1 sack (25 kg).
- Surplus carried forward = 25 − 3 = 22 kg (it'll trim any later demand in the same run).
- Order date = Tuesday − 2 days = Sunday, snapped to the ordering calendar.
- Committed amount = 1 × 18.00 = €18.00, grouped into the "Baker's Supply" draft order.
Without the on-hand-plus-open-order subtraction in step 3, the naïve plan would have ordered 2 sacks (ceil(40 ÷ 25)) and over-bought about 35 kg of flour you either already had or already had on the way. That subtraction is the whole point of a stock-aware plan.
The human stays in the loop¶
The plan never auto-sends. It produces draft orders and surfaces them to the operator — through the Dough agent — for review and confirm-to-Ordered. The agent proposes and explains its reasoning ("12 kg on hand, 25 more on order, so one extra sack covers Tuesday"); the operator approves; only then does the deterministic engine turn the draft into a sent order. Warnings — a missing supplier, a zero lead time — ride along as findings for the operator to see, rather than failing the whole run.
9. The whole flow, in one pass¶
- Optionally, a human jots a purchase list — loose, low-friction intent: items or free text, quantities maybe, no supplier or price. They resolve its lines to catalog items, then Plan it (order-shaping at face value, on-hand netting only if asked) into draft orders, or print it and shop, recording a goods receipt from the till check. This is the manual, third source of demand.
- Minimum/maximum par levels (per item, per warehouse, only items with a countable book) plus the forecast cascade produce demand automatically.
- The netting engine subtracts real on-hand and open orders, rounds up for MOQ and unit size, back-dates by the lead time, and groups one draft order per supplier.
- An operator (through the Dough agent) confirms a draft into Ordered — now an open commitment, still pre-ledger.
- Goods arrive → a goods receipt is recorded and posted — typed by hand or read from a photo of the supplier's paper into a draft the operator reviews (§6) — at the quantities and prices that paper states — linked line by line to the order's lines, or left un-linked for a walk-in buy. A receipt read from a paper can't post until every extracted line has been applied or dismissed. A capitalized line lands in the asset register instead of stock.
- The match compares each order line's committed amount with what the receipt says those goods were charged, before tax and freight, within the configured tolerance (default 0.05, per currency): in tolerance is matched, out of tolerance is a discrepancy to resolve.
- The order advances Ordered → Partially received → Received — or to Over-received instead of Received, when a line arrived above its order — as its lines are fulfilled (§7); Received and Over-received are both finished outcomes. Throughout, only the goods receipt ever moves stock and cost — at the goods' actual net landed cost, which is what blends into weighted-average cost. The order itself moves nothing, ever.
Use-by date¶
A receiving line can state a use-by date. When no date is stated, the receipt date plus the item's shelf-life at receipt entry provides an estimate for that delivery. Later changes to the item's usual shelf-life concern later deliveries. Correcting the receipt date shifts a calculated estimate by the same number of days; a stated use-by date remains the supplier's date.
For example, milk received on June 1 with a stated use-by date of June 8 keeps that date even when the item's usual shelf-life estimate changes.
See also¶
- Stock ledger — the goods receipt that brings stock in: the landed-cost build-up and its gross-vs-net totals; plus the journal of stock movements whose running sum the plan subtracts as on-hand.
- Period close — the month-end close, the settled period it establishes, and controlled return to reconciliation.
- Costing & valuation — weighted-average cost, the gross (what the purchase was charged) vs net (valuation) split, why cost reads the net figure, and what a corrected receipt price does to stock's worth.
- Item model & policies — the stocked gate that par levels and the plan's filter rely on, and the five treatments (stock, small tools, consumable, counted consumable, fixed asset) a receipt line routes by.
- Fixed assets — the asset register a capitalized receipt line lands in, and what happens to an asset after it's received.
- Scope & locations — the warehouse as the stock and valuation grain that par levels are keyed to.
- Units of measure — base measures, the units you buy in, and the ratio that converts a unit into a base-unit quantity.
- Recipes & production — the recipe explosion that turns the menu forecast into ingredient demand, and the prep items whose own recipes the plan explodes.
- Sales & consumption — the depletion side that draws stock down, against which reorder levels are set.
- Financial boundary — the conceptual accounts this in-flow feeds for export to the operator's accounting system, including the input-VAT receivable.