Skip to content
SKSuraj Kumar

Stock control

Inventory & Warehouse — Reference Build

Treats stock as a ledger of movements, not an editable number, so what the system says is on the shelf can be traced to why.

  • Business software
  • Operations
  • Inventory
  • Ledger
  • Next.js
Role
Sole engineer. Movement ledger design, allocation and reservation logic, batch picking rules and the operations interface.
Work type
Self-directed build — no client
Timeline
10 weeks build effort · 2026
Status
Case study published
Client
Independent build

Build effort, not elapsed calendar time. Engagements ran alongside study and employment, so this figure is the work itself rather than the span it sat in.

Interface built in code for this case study — not a client screen capture.

01Business problem

What was actually going wrong

Stock records stop matching the shelves within weeks, and once a business stops trusting the number it goes back to walking to the rack to check.

Who feels it

  • Warehouse and store teams reconciling by hand
  • Sales staff promising stock that is already allocated
  • Owners carrying dead stock they cannot see
  • Anyone handling batch-tracked or expiring goods

The usual inventory system stores a quantity and lets people edit it. Someone finds ten fewer units than the system claims and corrects the figure. The correction is silent, the cause is never found, and the same discrepancy reappears a month later. After enough of these, the quantity is treated as a rough guide and the business runs on physical checks.

Two consequences follow directly. Stockouts happen on items that appeared to be available, because a quantity on hand was already promised to three orders. And dead stock accumulates unnoticed, because nothing distinguishes a slow-moving item from one that has not moved at all.

For businesses handling batches or expiry dates, the problem is sharper. Stock is not fungible: a batch expiring in three weeks and one expiring in a year are different things, and picking the wrong one turns saleable stock into a write-off. A single quantity per item cannot express this.

02Product overview

What got built

An inventory system where every change in stock is an immutable movement entry and quantity is always derived, with explicit separation between on-hand, reserved and available-to-promise, and batch allocation that picks by expiry rather than convenience.

Engineering notes

  • Stock quantity derived from an append-only movement ledger
  • On-hand, reserved and available-to-promise as separate concepts
  • FEFO batch allocation with recorded overrides
  • Rollups maintained transactionally and verified by reconciliation

Nothing edits a quantity. Receipts, issues, transfers, adjustments and count variances are all movement entries with a reason code, a source document and an actor. Stock on hand at any location and for any batch is the sum of its movements. Every figure can therefore be explained by the entries behind it, and a discrepancy becomes a question with an answer.

Availability is three separate ideas kept separate. On-hand is what is physically there. Reserved is what has been promised to orders. Available-to-promise is on-hand less reserved plus inbound within a lead-time horizon. Sales sees available-to-promise, the warehouse sees on-hand, and the two are never conflated. Conflating them is the specific confusion behind most overselling.

Batch handling is first class. Stock is held per batch with its expiry, and picking allocates first-expiring-first-out by default with an override that must be justified. That single rule is the difference between rotating stock and writing it off.

Counting is a workflow, not an edit. A cycle count creates a task for a location, records counted quantities against the system position, and posts the difference as a variance movement with a reason. Variances are then reportable by location, item and counter — the reporting that turns a recurring discrepancy into a findable cause.

03Key features

What the software does, feature by feature

10 capabilities. Every one of them is deterministic software — there is no model in this build, and nothing here is described as AI.

  • 01

    Movement ledger

    Every stock change is an immutable entry with reason code, source document and actor. Quantity is derived, never stored as truth.

  • 02

    Location and bin structure

    Stock is tracked to bin level across warehouses, with zone and pick-sequence attributes that drive picking order.

  • 03

    Reservation and allocation

    Orders reserve stock explicitly, so available-to-promise reflects commitments, not raw shelf quantity.

  • 04

    Batch and expiry tracking

    Stock is held per batch with expiry dates, and allocation picks first-expiring-first-out unless overridden with a reason.

  • 05

    Cycle counting

    Counts are tasks against locations; variances post as movements with reasons, never as silent quantity edits.

  • 06

    Reorder points

    Reorder levels derived from consumption over a trailing period and supplier lead time, flagged before the stockout.

  • 07

    Transfer orders

    Inter-location transfers move stock through an in-transit state, so it is never counted at both ends or neither.

  • 08

    Pick lists

    Picking instructions ordered by bin sequence with batch specified per line, so the picker does not choose the batch.

  • 09

    Ageing and dead stock

    Stock by age bucket and days since last movement, so slow inventory surfaces while it can still be sold.

  • 10

    Valuation

    Weighted average cost maintained from receipt movements, with the calculation traceable to the entries behind it.

04User flow

How a person moves through it

The path from the trigger to the finished record, with each step attributed to whoever performs it — a person or the system.

  1. 01Store keeperReceives goods against a purchase order and puts them away into specific bins with batch details.
  2. 02SystemWrites receipt movements, updates derived on-hand per bin and batch, and recalculates weighted average cost.
  3. 03SalesChecks available-to-promise, which nets existing reservations and counts inbound within the lead-time horizon.
  4. 04SystemReserves stock on order confirmation and allocates specific batches first-expiring-first-out.
  5. 05PickerWorks a pick list ordered by bin sequence with the batch specified per line.
  6. 06SystemPosts issue movements on dispatch and releases the corresponding reservations.
  7. 07SupervisorRuns cycle counts by location; variances post as movements with reasons and appear in variance reporting.

05Architecture

How it is put together

The processing path first, then the layers it runs on, then the constraints that shaped both.

Path through the system

6 stages

  1. 01

    Receive

    Goods receipt against order; put-away to bin with batch and expiry.

  2. 02

    Store

    Derived on-hand per item, bin and batch from movement entries.

  3. 03

    Reserve

    Order commitments held against stock; available-to-promise recalculated.

  4. 04

    Allocate

    Batch selection by first-expiring-first-out with justified overrides.

  5. 05

    Issue

    Pick and dispatch post issue movements and release reservations.

  6. 06

    Verify

    Cycle counts post variances with reason codes for root-cause reporting.

Layers

Interface
Stock position by item, location and batchMovement history with reason codesPick list ordered by bin sequenceCycle count entryAgeing and reorder dashboards
Application
Movement posting with validationDerived position calculationsReservation and available-to-promise logicFEFO allocation with override recording
Services
Order integration for reservationsPurchase receipt integrationWeighted average cost recalculationBarcode input handling
Data
Immutable movement entriesItem, location and bin master dataBatches with expiryReservations with order references

Why it is shaped this way

  • Position is derived from movements, with maintained rollups per item, location and batch for read performance. The rollups are explicitly caches and a reconciliation job verifies them against the ledger.
  • Reservations are entries too, not a decremented quantity. That keeps on-hand physically accurate while availability reflects commitments; without the separation, overselling is only a matter of time.
  • Transfers post an out movement to in-transit and an in movement on receipt. Stock in transit belongs to a location, so it is never double counted or invisible.

06Technical decisions

The choices that mattered, and what each one cost

Every decision here was contested by a reasonable alternative. The trade-off column is the part usually left out.

01

Make stock quantity a derived value over an immutable movement ledger.

Why

An editable quantity destroys the audit trail exactly where it is most needed. Deriving the number means every unit of stock can be explained by the movements that created it, and a discrepancy becomes traceable, not something to be papered over.

Trade-off

Reads require aggregation, so rollups are maintained per item, location and batch. The rollups are treated as caches with reconciliation, not as the source of truth.

02

Separate on-hand, reserved and available-to-promise as distinct concepts.

Why

Overselling comes from one number serving two purposes. The warehouse needs physical truth; sales needs what can still be promised. Conflating them guarantees one of the two audiences is misled.

Trade-off

Three numbers on a screen instead of one, so the interface has to label all three clearly and consistently, with no single "stock" figure anywhere.

03

Allocate batches first-expiring-first-out by default with a justified override.

Why

Expiry write-offs are almost entirely a picking-discipline problem. Making the system choose the batch — and requiring a reason to deviate — moves the decision out of a picker’s convenience.

Trade-off

Occasionally the nearest bin holds a later batch, so the override exists. Overrides are reported, which keeps them exceptional.

04

Post count variances as movements with reason codes, never as quantity adjustments.

Why

A variance is information. Posting it as a movement preserves both the count and the difference, so variance can be analysed by location, item and cause instead of disappearing into a series of silent corrections.

Trade-off

The ledger accumulates variance entries. That growth is the price of having the reporting at all.

05

Model in-transit as a location.

Why

Two-step transfers otherwise leave stock either counted twice or missing during the gap. Treating in-transit as a real location keeps the ledger balanced at every moment.

Trade-off

One more location type to handle in reporting — cheap next to reconciling phantom stock.

07Challenges

What was genuinely difficult

Not the setup work. These are the problems where the first implementation was wrong and had to be reconsidered.

01

Concurrent allocation of the same stock to two orders.

Approach

Reservation insertion takes a lock on the item-location rollup, recomputes available from the ledger and existing reservations, and only then writes the reservation. The second request either allocates from another batch or fails with the actual available quantity. Both cannot succeed against the same units.

Outcome

Two orders cannot be allocated the same physical stock, so a pick list never sends a picker to an empty bin.

02

Position queries slowing down as the movement ledger grew.

Approach

Rollups are maintained per item, location and batch inside the same transaction as the movement, so reads never aggregate the full history. A scheduled reconciliation recomputes rollups from the ledger and reports any divergence, which keeps the cache honest and not merely fast.

Outcome

Position reads stay constant-time as history grows, and a divergence shows up in a report before it can show up as a wrong number on a screen.

03

Making cycle counting practical for staff working with a phone in a warehouse aisle.

Approach

The count screen is a single-column, large-target layout that accepts barcode input, works through one bin at a time, and shows the system position only after a count is entered to avoid anchoring the counter. Entries are queued locally and posted when connectivity returns.

Outcome

Counts got done in the aisle instead of transcribed later, and the anchoring problem — counters confirming the system number — largely disappeared.

08Business value

What it changes for the business

Stated qualitatively on purpose. Invented percentages are the easiest thing to put on a portfolio and the easiest thing to see through.

Operational effect

  • Restores trust in the stock number by making every quantity explainable from the movements behind it.
  • Prevents overselling by separating what is physically present from what is still promisable.
  • Reduces expiry write-offs by taking batch choice out of the picker’s hands.
  • Turns count discrepancies into analysable data instead of silent corrections, so root causes get found.
  • Makes dead and slow-moving stock visible while it can still be sold rather than written off.
  • Gives a traceable cost basis for valuation, sourced from the same entries as the quantities.

What would change at scale

  • Partition the movement ledger by period and archive closed periods, since the ledger is append-only and grows monotonically.
  • Add wave picking and pick-path optimisation across orders rather than sequencing within a single pick list.
  • Introduce serial number tracking for items requiring individual traceability: a stronger constraint than batches, and one that changes how allocation works.
  • Support consignment and owned-but-remote stock as distinct ownership states, because they behave differently for valuation.
  • Add demand-based reorder point recalculation with seasonality; a trailing average under-orders ahead of a known peak.

09Interface

The screens where the work happens

Dense operational views rather than dashboards. These are used for hours at a time, so the priorities are legibility, keyboard flow and state that is never ambiguous.

Stock position

On-hand, reserved and available by item, location and batch, with expiry dates shown per batch.

Movement history

Every entry with reason code, source document, actor and resulting position — the audit trail as the primary view.

Pick list

Lines ordered by bin sequence with the batch specified, so the picker follows a route and makes no choices.

Cycle count

Single-bin count entry that reveals the system position only after a quantity is entered.

The screen above is built in HTML and CSS for this case study. It reproduces the layout, states and vocabulary of the real build without exposing client data, which is why it exists rather than a screenshot. It is evidence of design and of the decisions behind it. It is not a photograph of a deployed system, and no part of it is a capture of anyone else’s product.

10Technologies

What it is built with

Chosen for the shape of the problem, not for novelty. Anything unusual is justified in the decisions section above.

Frontend
  • Next.js App Router
  • TypeScript
  • Tailwind CSS
  • Offline-tolerant count entry
Application
  • Immutable movement posting
  • Locked reservation allocation
  • FEFO batch selection
  • Rollup reconciliation
Data
  • PostgreSQL
  • Append-only movement entries
  • Maintained position rollups
Operations
  • Barcode input
  • Bin sequence pick ordering
  • Weighted average costing

11Technical preview

Structure, models and annotated excerpts

There is no repository link on this site. What is available instead is the module structure, the data model, the interface contracts and annotated excerpts written for this case study — enough for a technical reviewer to judge the engineering.

Technical preview

Implementation detail for this build

Selected implementation details are available for technical review: component structure, data models, architecture notes and sanitized code excerpts. Some client-specific source material stays private because of confidentiality. Enter the project access keyword if you have been given one — the same one works across every case study.

A presentation convenience, not authentication. This is a static site, so the keyword ships to your browser with the page and anyone reading the bundle can find it — worth saying plainly rather than dressing it up. Nothing confidential is stored behind it.

Inside this section

  • Module and folder structure for the build
  • Data models and the interface contracts between layers
  • 2 annotated implementation excerpts
  • Design notes covering the decisions the excerpts imply
  • The same keyword opens every case study on the site

For private client work, contact me for a walkthrough.

Next step

Need something along these lines?

Send the process, the constraints and the deadline. You will get an honest scope, an architecture sketch and a timeline before any commitment.

Email
surajk86808@gmail.com
Based in
Bengaluru, India
Working hours
IST (UTC+5:30)
Availability
Taking new engagements