Skip to main content
All insights
Custom Software10 min readAugust 6, 2026

From Requisition to Inventory: Why Stock Needed Five Quantity States

The short answer

An inventory balance cannot answer every operational question. We modelled on-hand, reserved, delivered-pending-confirmation, deducted and available quantities separately, then made manager confirmation the only event that removes stock. The result is an auditable loop from request to shelf to delivery that still works when orders, receipts, invoices and handovers are partial.

By Timothy Indarsingh, Founder & CEO, Firelinkx

This is part of the engineering series behind our intranet platform case study. The visible workflow looks ordinary: an employee requests something, a manager approves it, Corporate Services buys it, the item arrives, and somebody delivers it. The engineering problem begins where that neat sentence stops. Two departments want the last box. The supplier sends half the order. The goods arrive before the invoice. The wrong item reaches the desk. Somebody asks what one legal entity spent, and the answer must not include the other's stock.

A form and a status field can automate the happy path. They cannot keep a cupboard, a purchase order and an approval history in agreement. To do that, we had to decide what every quantity meant, which event changes it, and how a correction remains visible after the number is right again.

The rule that anchors the loop

When stock moves

Stock increases when goods are received. It decreases only when the receiving manager confirms delivery—not when a request is submitted, approved, ordered or merely handed over.

Every earlier deduction point makes the system disagree with the physical world. Deduct at approval and an item vanishes from the record while it is still on the shelf. Deduct when a purchase order is raised and stock moves before the supplier has delivered anything. Deduct when Corporate Services hands over a package and a short or wrong delivery becomes indistinguishable from a correct one. The manager's confirmation is the first event that says the intended department received what the system says it received.

Confirmation is not forced into a yes-or-no shape. A manager can confirm part of a line, dispute it, or return it with notes. Ordering, receiving and delivery can all be partial at line-item level. That sounds like extra workflow until you compare it with the alternative: an official system showing a complete transaction while the real exceptions are explained in email.

Why one stock number became five

  • On hand: the quantity physically held by the organisation.
  • Reserved: on-hand stock promised to approved requisitions but not yet handed over.
  • Delivered pending confirmation: stock handed to a department whose manager has not yet accepted it.
  • Deducted: confirmed delivery already consumed from the stock layers.
  • Available: on hand minus reservations and deliveries awaiting confirmation.

Each figure answers a different question. A storekeeper asks what is physically present. A buyer asks what can still be promised. A department manager asks what is on the way. Finance asks what has actually left inventory. Collapsing those questions into one balance does not simplify the domain; it hides commitments until two people are promised the same unit.

Available quantity is calculated from the other states rather than typed or adjusted independently. A reservation therefore reduces what can be promised without pretending the item has left the shelf. If the requisition is cancelled, releasing the reservation restores availability without inventing a receipt. The state model describes what happened instead of making every change look like stock coming in or going out.

The movement log is the record; the balance is a cache

Goods are held in first-in-first-out layers, one layer per receipt, and deductions consume the oldest eligible layer first. Every receipt, reservation, transfer, deduction, adjustment and write-off creates an append-only movement. The current balance is maintained for fast screens and reports, but it is explicitly rebuildable from the layers and movements. If the cache and history disagree, the history wins.

This changes how errors are corrected. A confirmed movement is not edited until the audit trail looks tidy. A wrong-item delivery gets a compensating pair. A write-off is its own event. A post-confirmation reversal refers to the layer it reverses. The resulting quantity may match what an edit would have produced, but the path is different: an auditor can see the original event, the correction, the actor and the reason.

The two operating companies are isolated at this level, not only in a report filter. Every layer, movement, balance and delivery carries its cost entity. An inter-company transfer is an atomic outbound and inbound pair with a review step, inherited source cost and separate treatment on each side. The transfer cannot turn a shared catalog item into pooled stock or make one entity's cost history disappear inside the other's.

Concurrency has to be exercised by a database that can race

Two allocations competing for the last unit are not an exotic load test. They are a routine office event. The allocation path uses row-level locking and idempotency controls, and its dedicated tests run under real concurrent transactions against the production-class database engine. The fast test database is useful for most of the suite, but it cannot demonstrate every locking behaviour we rely on.

Marking those tests separately is important. A green test executed on an engine that cannot exhibit the failure is not evidence that the race is safe. It is evidence that the test environment was convenient. We keep the slower concurrency checks identifiable so nobody can run only the fast suite and mistake that for proof of allocation correctness.

Idempotency protects the retry path

Locking decides which allocation wins. Idempotency handles a different problem: the same successful instruction arriving twice because a user double-clicked, a client retried after a timeout, or a worker restarted before it recorded completion. The movement carries the identity of the operation that created it, and repeating that operation returns the existing result rather than consuming another layer.

That distinction matters whenever the caller cannot tell whether a timeout happened before or after commit. Telling users never to retry is not an operational design. The server has to make the retry safe. Our concurrency tests therefore exercise both competing operations and duplicate delivery of the same operation: one must serialize correctly, while the other must collapse to one effect.

An off-catalog request is data, not a failure

Procurement catalogs usually decay in one of two ways. Force every request through a catalog item and hurried users create vague duplicates to get their work done. Permit unrestricted free text and the catalog becomes optional, leaving no stable basis for comparison or pricing. We made a requisition line explicitly catalog-linked or off-catalog. The second state is visible and reportable rather than represented by a missing relationship nobody can interpret later.

The normal path still has to be pleasant, so the picker uses fuzzy typeahead search. When somebody genuinely needs an unlisted item, that line enters a promotion queue. Approval atomically creates a catalog item and its first supplier offer, while a database constraint prevents two open promotion requests for the same candidate. The catalog improves from observed demand instead of being designed once and slowly bypassed.

The item can be real while its cost is uncertain

A delivery can arrive days or weeks before its invoice. Physically, that stock exists and may be needed immediately. Financially, its final cost is not yet known. The layer therefore carries a cost state—pending, proposed or confirmed—separately from its drawable quantity. Confirmed cost is immutable, but pending layers are not fictional stock and remain available for use.

Invoice matching writes the confirmed cost back to the receipt and refreshes catalog pricing from the invoice only. A quote can help make a purchasing decision; it does not become historical cost merely because the invoice is late. The boundary is also explicit: the platform tracks invoices for provenance and matching, but it is not an accounts-payable ledger.

Emergency receipts without a purchase order and standalone purchase orders are supported behind extra authority and a mandatory justification. Refusing to model an exceptional purchase does not prevent it. It moves the event into email and makes the official history less accurate. The safer choice is a narrower, more visible route through the system.

The exception surface is the product

The implementation includes adjustments, graded returns, write-offs, wrong-item corrections, lost-in-transit handling, post-confirmation reversals and reviewed transfers. These are not embellishments around a requisition form. They are the points where the record is most likely to split from the shelf, and therefore the places an inventory system earns trust.

We even shipped the ledger in two deliberately incomplete stages. The first release accepted receipts but had no deduction path. Reservation, delivery, manager confirmation and FIFO drawdown came in the next increment. That intermediate state was documented and safe: inventory could enter the new record, but nobody could accidentally consume it through an unfinished flow. Building both halves simultaneously would have produced a more complete demo sooner and a less certain accounting boundary.

What the workflow contributes

Requisitions belong to departments rather than individual employees, so several staff members can contribute line items to the same open request. Approvers can return a request with notes at each review point instead of choosing only approve or reject. Those two choices remove common reasons for leaving the platform: duplicate individual orders and approval conversations that have to restart in email.

The approval chain follows the evidence being created: department review confirms the need, Corporate Services review controls sourcing, the purchase order records the commitment, goods receipt establishes what arrived, and the department manager confirms the handover. A line can advance partially without pretending the rest arrived with it. That lets one requisition contain items supplied on different dates without cloning the request or marking incomplete work complete.

The completed loop connects intent, authority and physical evidence. A request explains why stock was reserved. The purchase order and receipt explain how it arrived. Delivery confirmation explains why it left. The layer identifies which cost was consumed. Corrections remain events. When somebody asks how many items exist, what is still available, who has been promised one, what it cost and who approved it, the answers come from the same history.

The takeaway

Inventory software fails at the join between a clean workflow and an untidy physical world. The durable design was not a clever requisition form. It was refusing to let one number stand for five different states, refusing to erase corrections, and choosing one unambiguous event that removes stock. Once those rules were fixed, the exceptions became modelled events instead of spreadsheet footnotes.

Want your stock and orders easier to manage?

Firelinkx helps Guyanese businesses get this right. Get a clear scope, timeline, and price, or just ask a question. We respond within 24 hours on business days.

WhatsApp Us