Inspiration

Industrial repair shops lose time and money because nobody knows what is on the shelf. A technician inspects a machine, discovers a missing bearing, and the part gets ordered days late. We wanted to close that loop: an inspection is approved, stock is reserved, the shortage is flagged, and the purchase is suggested, all automatically.

What it does

SMART-INV listens to the workshop's events in real time and keeps a live inventory:

  • Approved inspections reserve available parts for their work order, and whatever is missing becomes a shortage.
  • Purchases are matched to the catalog, enter the warehouse, and fill pending shortages automatically.
  • Reorder suggestions group shortages by part, listing which orders are waiting.
  • Issues, transfers, and cycle counts are recorded as immutable ledger movements with a full kardex.
  • Cancelled inspections and deleted orders release their reservations and close their shortages.
  • A REST API and web panels show stock, work-order materials, shortages, and the kardex.

How we built it

Python 3.12, FastAPI, SQLite in WAL mode, and Redpanda (Kafka API) through confluent-kafka. The consumer runs as a background thread inside the API process, and both share the database. Every event goes through one pipeline: a duplicate check, then a single transaction that records the event_id together with the business effect. Output events are written to an outbox in that same transaction and published afterwards. The frontend is vanilla JavaScript. Three of us split the backend (consumer and reservations, ledger and API, purchasing) and two the frontend.

Challenges we ran into

  • Disorder across topics. An inspection can arrive before its work order or part, so we park such events and retry them instead of dropping them.
  • Duplicates and concurrency. Delivery is at least once, and two approvals must never reserve the same last unit.
  • Deterministic rebuilds. Deleting the database and replaying must reproduce the same stock, so we always read from offset zero and always load the catalog first.
  • Messy real data. Parts without a SKU, repeated SKUs, missing quantities, kits, and purchases described only by free text.
  • Parallel work. Five people on shared tables meant agreeing on small, clear interfaces early.

Accomplishments that we're proud of

We replayed six simulated weeks of shop activity (1,742 events, duplicates included) end to end. Every distinct event was processed, nothing stayed stuck, and every output event in the database reached Kafka. A restart does nothing twice, and a wiped database rebuilds itself from the history.

What we learned

  • Idempotency belongs in the same transaction as the effect, not around it.
  • An outbox is safer than writing to the database and the broker separately.
  • It is easier to design for disorder than to try to prevent it.
  • Agreeing on the contract first is what made parallel work possible.

What's next for SMART-INV

  • Demand forecasting by model from parts lists and historical inspections.
  • Inventory valuation at average cost.
  • A rotation dashboard for critical and idle parts.
  • Consumer observability (lag and error rates).
  • Filling other orders' shortages automatically when cancellations free stock.
  • Scaling out with a multi-writer database and a partitioned consumer.

Built With

Share this project:

Updates

Submission history