Skip to content
All case studies
EnterpriseDelivered2025

Multi-Product Inventory & Procurement System

A building materials distributor carrying hundreds of SKUs across multiple units of measure and several storage locations needed procurement and stock to stop being two separate, contradictory sets of numbers.

Client
Building Materials Distributor
Region
India
Discipline
Enterprise Systems
inventory.internal / stock
Stock by location
2 below reorder
OPC 53 Cement
68 bag
WH-1
TMT Bar 12mmReorder
22 tonne
WH-2
Aggregate 20mm
84 cu.m
WH-1
Plywood 18mm
41 sheet
WH-3
PO-2025-0418
TMT Bar 12mm — 40 tonne
Awaiting approval
Raised by Store›Approval limit ₹ 5,00,000

Interface recreated from the delivered system. Client data is illustrative and non-identifying.

The problem

Building materials are an awkward inventory problem: the same product is bought by the tonne, stored by the bag and sold by the piece, from more than one location, at prices that move with each supplier quote.

Purchasing worked from one view of stock and the warehouse worked from another. The gap between them showed up as emergency purchases of material already sitting in a yard, and as stockouts on items the system claimed were available.

  • Unit-of-measure conversions were done mentally and inconsistently, so quantities disagreed across teams.
  • Stock levels were location-blind — the total looked healthy while a specific site had nothing.
  • Purchase orders lived in email threads with no approval record and no link to received goods.
  • Supplier price history was not retained, so negotiation ran on recollection.

The approach

We treated the unit-of-measure problem as the foundation rather than a formatting detail. Every product carries a base unit and declared conversion factors, and all stock math happens in base units — the interface converts for display only.

On top of that, stock became a single append-only ledger. Receipts, issues, transfers and adjustments are all entries; current stock is derived, never directly edited. That is what makes the numbers reconcilable.

  • Defined a product master with base units and explicit conversion factors for purchase, storage and sale units.
  • Made every stock movement a ledger entry, with on-hand quantity computed rather than stored and overwritten.
  • Modelled locations as first-class, so availability is always answered per warehouse as well as in total.
  • Tied the purchase order lifecycle — raise, approve, receive, invoice — to the same ledger that the warehouse writes to.

What we built

One procurement-to-stock system where a received purchase order and a warehouse receipt are the same event.

  • Product master with categories, base units, multi-unit conversions and per-supplier codes.
  • Multi-warehouse stock ledger with per-location on-hand, in-transit and reserved quantities.
  • Purchase order workflow — draft, approval, partial and full goods receipt, invoice matching.
  • Supplier registry with quotation and price history per product, so rate changes are visible over time.
  • Reorder-level alerts calculated per product per location, not on the misleading global total.
  • Stock transfer between warehouses with in-transit state and receiving confirmation.
  • Role-based approval limits — who can approve a PO, and up to what value.
  • Valuation and movement reports exportable for the accountant.

Tech stack

Frontend

Next.jsTypeScriptTailwind CSS

Backend

Node.jsREST APITransactional service layer

Data

PostgreSQLAppend-only stock ledgerMaterialised report views

Infra

DockerRole-based authExcel/PDF export pipeline

Outcome

Purchasing and the warehouse now argue from the same ledger, which mostly means they stop arguing.

  • Stock is answerable per location and per unit without manual conversion.
  • Every purchase order carries its approval record and links to the goods actually received.
  • Reorder alerts fire against real per-location availability instead of a flattering total.
  • Supplier price history is retained, so procurement negotiates from record rather than memory.

Building something like this?

Most of these started as one module solving one painful process. Tell us which process is yours.

We reply within 24 hours, Mon–Sat.