Skip to content

Capstone 8 — Inventory Management System

Scope: a term's work · Prerequisites: Modules 1–15


1. Problem statement

A warehouse holds stock of thousands of items and records every movement: receipts from suppliers, issues to customers, transfers between locations, returns, and adjustments after a stock count.

The requirement that shapes the whole design is that stock is never negative and the recorded level always matches the movements. Every movement is appended to a log; the current level is derived from it, or maintained alongside with the log as truth — but whichever you choose, a reconciliation command must be able to recompute every level from the log and find no disagreement.

Items also differ: a serialised item is tracked one unit at a time, a batch item has an expiry date, and a bulk item is measured in kilograms. Reordering depends on a reorder point and a supplier lead time, and the system must report what to order today.


2. Actors

Actor What they do What the system owes them
Warehouse operative Receives, issues, transfers, counts Fast operations that cannot produce a negative level, and a refusal when one would
Purchasing officer Sees what to reorder and places orders A reorder report that reflects real levels and lead times
Stock controller Counts stock, records adjustments An adjustment that says who changed what, and why
Auditor Reconciles levels against the movement log A derivable answer, and an append-only log

3. Use cases

  1. Add items: serialised, batch-tracked and bulk.
  2. Receive stock from a supplier, with a reference and a date.
  3. Issue stock to a customer, refusing to go below zero.
  4. Transfer stock between locations.
  5. Record a stock count, and adjust the level with a reason.
  6. Compute the current level for an item at a location.
  7. Reconcile: recompute every level from the movement log and report any disagreement.
  8. Report items at or below their reorder point, with a suggested order quantity.
  9. Show an item's movement history in order.
  10. Save and load everything; refuse a corrupted file with a line number and no partial state.

4. Suggested classes

Class Responsibility, in one sentence Notes
Quantity An amount with a unit, so kilograms and units cannot be added carelessly A value type; the reason bulk items do not produce nonsense
ItemKind What differs between serialised, batch and bulk items An interface, or a composed policy
Item A stock-keeping identity: code, description, unit, reorder point Shared by all kinds
SerialisedItem An item tracked one unit at a time Holds serial numbers
BatchItem An item tracked by batch with expiry dates Holds batches
BulkItem An item measured in kilograms Holds a quantity, not units
Location A place stock is held: a bin, a rack, a warehouse Owns no items; holds levels
Movement One appended record of stock changing, with a kind and a reason Immutable once constructed
MovementLog The append-only sequence of movements Owns its movements; the source of truth
StockLevels The current level per item and location Derived from, or reconciled against, the log
ReorderPolicy Turns a level, a lead time and a demand rate into a suggestion Injected; the thing that varies
Warehouse Coordinates operations and owns the log and the levels Where a movement becomes a transaction

The class worth the most marks is MovementLog together with the reconciliation command. Every other project in this list has an append-only log, but this one measures it: the reconciliation recomputes every level from the movements and reports disagreements. That command is both a feature and the strongest possible test of your invariants — if the levels are maintained separately, this is what catches it.


5. Relationships

   Warehouse ◆── MovementLog         composition
   MovementLog ◆── vector<Movement>  composition, and append-only
   Movement ────> Item               association: refers to, does not own
   Movement ────> Location           association
   Warehouse ◆── StockLevels         composition
   StockLevels ◇── Item              aggregation: a level refers to an item it does not own
   Item <|── SerialisedItem          inheritance for substitution
   Item <|── BatchItem
   Item <|── BulkItem
   BatchItem ◆── vector<Batch>       composition
   Warehouse ┈┈> ReorderPolicy       dependency, injected

6. Design constraints

  • A level is never negative, and the rule is enforced in one place — the operation that would go negative is refused with the amount available and the amount requested.
  • Movements are append-only. A correction is a compensating movement, and both remain visible: the log is what an auditor reads.
  • One source of truth for levels. Either the level is computed from the log (and you state the cost of that on every query) or it is maintained alongside it (and you reconcile). Say which, and why.
  • The reconciliation is a feature you build and run, not an intention.
  • Units cannot be mixed. A Quantity carrying its unit is the design that makes adding kilograms to units a compile error or an explicit refusal — pick one and state it.
  • Reorder suggestions come from an injected policy, so a rule change is configuration.
  • Every adjustment carries a reason and an author — the audit requirement that shapes the movement type.
  • Format: documented text format with a version marker and an escape rule; the log's order preserved exactly on a round trip; a later-version file refused, not misread.

7. Milestones

# Milestone Done when
1 Design Diagram; the level/log relationship decided and justified; the non-negative rule located in one place
2 Items and units Three item kinds with their differences in types; Quantity preventing unit nonsense
3 Movements Receive, issue, transfer and adjust, all appended to the log, with refusals that name the numbers
4 Levels and reconciliation Levels correct and the reconciliation command finds no disagreement — demonstrated by a scripted sequence
5 Persistence Documented format; round trip preserving the log's order and content; three hand-edited corruptions rejected with line numbers
6 Tests and report Invariants, boundaries and failures asserted; a deliberate bug caught; the reconciliation report in the design report; the reversal named with its cost

8. Minimum requirements

  • [ ] Three item kinds, differing in tracked units and expiry, with the difference in types
  • [ ] A Quantity that cannot silently mix kilograms and units
  • [ ] Receive, issue, transfer and adjust, each appending a movement
  • [ ] A refusal that names the available and requested amounts when stock would go negative — demonstrated
  • [ ] An append-only movement log with a reason and author on every adjustment
  • [ ] Levels per item and location, with the level/log relationship documented and justified
  • [ ] A reconciliation command that recomputes every level and reports disagreements, run and demonstrated clean
  • [ ] Reorder suggestions from an injected policy, with lead times
  • [ ] An item's movement history, in order
  • [ ] Persistence with a version marker and escape rule; a round trip preserving the log's order and content, including an empty log
  • [ ] Three hand-edited corruptions rejected with line numbers, leaving the loaded state untouched
  • [ ] At least two patterns, each justified by a named requirement; one declined, with the reason
  • [ ] Tests with assertions covering invariants, boundaries and failure paths
  • [ ] No warnings with -Wall -Wextra -Werror

9. Advanced requirements

  • [ ] Expiry-aware issuing: batches are issued soonest-expiring first, with the rule stated and tested
  • [ ] A fourth item kind added with no edits to existing operations — the file count in the report
  • [ ] Demand-based reorder points, from an injected policy that reads movement history
  • [ ] Reconciliation under a deliberately corrupted level, showing the command finds and reports it
  • [ ] Query cost stated and measured: level lookup and history lookup, at two sizes, in the report
  • [ ] Transfers in transit, with a location that holds stock between two sites
  • [ ] A count sheet export to CSV behind the same interface as the console report

10. Testing requirements

  • Invariants: levels never negative; every level agrees with the log; a movement is never mutated; the total of a transfer is zero across the two locations; units never mix
  • Boundaries: issuing exactly the available quantity; one unit more; receiving zero; a bulk quantity at a fractional kilogram; a reorder point exactly at the current level; an empty log
  • Failure paths: issuing more than available; transferring from a location with no stock; adjusting with no reason; loading a truncated file; a movement referring to an unknown item
  • Round trip: the log's content and order preserved exactly, including an empty log and an item code containing the separator
  • One deliberate bug (for example, applying a level update before validating the movement), caught by the reconciliation or by a test, with the failing assertion kept

11. Extension ideas

  • Supplier records with lead times and reliability, and a suggestion that accounts for both.
  • Cycle counting: a schedule that counts a subset of items each week, with an adjustment per count.
  • Stock valuation by a cost method (FIFO or average), and the design decision about where cost lives.
  • A "days of stock remaining" report, with the complexity of computing it from the log.
  • Barcode-driven operations, with a parser at the boundary and validation on every scanned code.
  • Multiple warehouses with inter-warehouse transfers in transit, and a measure of how expensive the change was.

12. Evaluation checklist

  • [ ] The diagram matches the declarations, including multiplicities
  • [ ] One source of truth for levels is named, and the other is derived or reconciled
  • [ ] The reconciliation runs clean on a scripted sequence — output pasted
  • [ ] The reconciliation detects a deliberately corrupted level — demonstrated
  • [ ] Stock cannot go negative — demonstrated by a test that tries
  • [ ] Units cannot be silently mixed — demonstrated by a compile error or a documented refusal
  • [ ] The log is append-only, and a correction is a compensating movement
  • [ ] Every adjustment names a reason and an author
  • [ ] The round trip preserves the log's order and content, including an empty log — output pasted
  • [ ] Three corruptions rejected with line numbers, leaving the loaded state untouched
  • [ ] The suite fails when a deliberate bug is introduced
  • [ ] One pattern considered and declined, in writing
  • [ ] The report names the decision I would reverse and the cost of reversing it

Related: Capstone options · Projects and the rubric · Module 16 — Capstone · Module 4 — Encapsulation