How a market run gets into stock the moment it's bought, and how somebody other than the buyer confirms afterwards that the spend was real.
Why this exists
Most fresh produce in a Kenyan kitchen is bought with cash from a trader: sukuma wiki from Marikiti at six in the morning, tomatoes from the mama mboga on the corner, fish straight off the beach. No order, no supplier account, no invoice. If those crates never reach the ledger, every variance figure is wrong by exactly the value of everything bought at a market, which is the place a stock system is supposed to earn its keep.
So a cash purchase is a purchase and a receipt of goods, captured on the phone in well under a minute. It is not a payment. The cash left somebody's pocket in a system Bohari knows nothing about, and nothing here moves money.
Capturing one on the phone
The mobile Market purchase screen needs capture_cash_purchase, which the Storekeeper, Chef, Bar Manager and Outlet Manager roles all hold. Everything about it is built for speed:
- Who did you buy from? is free text. A market trader has no supplier record and shouldn't need one.
- The outlet and storage location default to the first available; chips to choose only appear when there's more than one.
- Each line is an item picked from the catalogue, a Quantity in the item's own stock unit (kilos of tomatoes, not "a crate at the crate price"), and a Price per unit. Add another item as you go, with the KES total updating underneath.
- A photo of the receipt is optional. A trader's receipt is often a torn page or nothing at all, and refusing the capture without one would push the spend straight back out of the system.
Save purchase writes it to the phone's outbox first ("Purchase saved on this phone. It will send when you have signal.") and it syncs when there's a network, photo included. Each capture carries its own operation id, so one that syncs twice posts once. The footnote under the button says what matters: the stock is counted from now, and Finance reviews the record later.
Capture is a phone job. The web lists and reviews cash purchases; it doesn't create them.
Stock posts on capture, not on review
The tomatoes are in the kitchen the moment they're bought. Holding the ledger entry until somebody in an office reviews the paperwork would leave the system knowingly wrong for however long that takes, and "the stock is there but the screen says it isn't" is the one state a stock-control product must never be in.
Each line therefore posts a receipt movement to the chosen location at the price paid, tagged as a cash purchase rather than a manual adjustment, so any report that splits spend by channel doesn't misfile most of the produce budget. The rows show up on the Movements screen described in Stock on Hand, and the purchase itself gets a number like CP-000123.
A few things the server refuses at capture:
- No vendor: "Who the goods came from is required".
- An item that isn't stock-tracked: "Item is not stock-tracked and has no ledger".
- A quantity at or below zero, or a negative unit cost. Zero cost is fine; a free bunch thrown in by the trader is a real thing.
- A purchase time more than a day in the future.
Review: somebody else confirms the spend
The web's Cash and market purchases screen (needs view_procurement or capture_cash_purchase) sorts them into Awaiting review (oldest first, since it's a queue), Ratified, Rejected and All. Open one and you get the vendor, the moment it was bought, the lines in stock units with unit cost and line total, and the server's own total in KES.
Anyone holding review_cash_purchase (Finance and the Outlet Manager) sees Ratify and Reject. Review examines the record, not the goods:
- Ratify changes nothing about stock. It says the spend was real. A note is optional.
- Reject reverses every stock movement the purchase posted, appending an opposing row to each, so the quantities come back off the ledger. The purchase and its reversal both stay visible; nothing is deleted. The note is required ("A rejection must say why.") and it's written into the ledger reversal, so whoever reads the stock history later sees why the tomatoes moved back.
The dialog spells this out before you press Reject and reverse, because a reviewer who believes the stock is still pending will treat rejection as a harmless cancellation and then wonder where the produce went.
The buyer can't review their own capture. This is the flow with the least paper behind it, so one person inventing a purchase and signing it off is exactly what the rule exists to stop, and no permission can express it; the server answers "You captured this purchase; it must be reviewed by somebody else." An Outlet Manager who did the market run personally still needs a second pair of eyes. Reviewers also need access to the purchase's outlet, so a manager pinned to Westlands can't rule on Karen's market runs.
A purchase is reviewed once. Try again and you get "This purchase has already been ratified." The same review works from the phone's approvals list, with the same two outcomes.
What a rejection is for
Reject when the record is wrong: captured twice, wrong item, a price that can't be right, or a purchase that never happened. The note is the place to say which, something like "Captured twice, the same crates were already recorded on CP-0114."
Don't reject to fix the shelf. If the produce was bought and then went bad, that's a write-off through Waste, which leaves the purchase intact and records the loss where it belongs. If a quantity was miscounted, a stocktake corrects it. Rejecting says the spend wasn't real, and that's a different claim.
Checking the till against the record
Cash leaves an M-Pesa till or a float, and sooner or later a manager asks whether every shilling that left became stock. The Statement check screen (needs record_settlement, so it's Finance's) takes an exported statement and matches its outgoing rows against cash purchases and recorded settlements. Rows nothing explains add up to an unrecorded-spend figure, which is the headline. The file is analysed and never stored. The full walkthrough is in Suppliers, since the same check covers supplier payments.
One detail worth knowing here: rejected purchases are excluded from that matching. A rejected capture whose cash genuinely left the till will surface as unrecorded spend, which is the right answer.
FAQ
I bought the produce myself and I'm the outlet manager. Why can't I ratify it?
Because you captured it. The rule is about this document's history, not your role, and the server refuses the capturer whatever they hold. Hand it to Finance or a colleague with review_cash_purchase. See Roles & Permissions.
The stock is on the shelf but the purchase still says Awaiting review. Is something stuck? No, that's the design. Stock posted when the purchase was captured; the review is about the spend, not the goods. The status badge's own tooltip says the same thing.
I rejected a purchase by mistake. Can I un-reject it? No; a purchase is reviewed once. Capture it again on the phone. The rejected record, its reversal and the new capture all stay visible, which is the honest history of what happened.
Why is there no supplier picker on the capture screen? Because a market trader isn't a supplier in the register sense: no code, no KRA PIN, no agreed price list. A cash purchase carries the vendor as free text. If you're buying from the same trader on credit every week, that's a supplier, and they belong in Suppliers with a purchase order behind each delivery.
Does the KES total on a purchase affect anything else? It's the cost the stock was received at, so it feeds valuation and the purchases-by-supplier report, where cash purchases appear as one separate total beside the supplier table rather than being blended into per-item prices. It is not a payable, and nothing here will ever ask you to settle it.