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¶
- Add items: serialised, batch-tracked and bulk.
- Receive stock from a supplier, with a reference and a date.
- Issue stock to a customer, refusing to go below zero.
- Transfer stock between locations.
- Record a stock count, and adjust the level with a reason.
- Compute the current level for an item at a location.
- Reconcile: recompute every level from the movement log and report any disagreement.
- Report items at or below their reorder point, with a suggested order quantity.
- Show an item's movement history in order.
- 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
Quantitycarrying 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
Quantitythat 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