Skip to content
PMPaulo Mota
Back to the demo

How it was built

Parts and stock, under the hood

How each outgoing part is tied to a repair and how orders are grouped by supplier.

01

The problem

Parts that leave without paperwork are parts that never get charged. And you only find out stock ran out when the car is already up on the lift.

02

The model

Parts with stock, minimum, cost and price. Every stock change is a movement: out to a repair, or in from an order.

TableWhat it holds
partsReference, supplier, stock, minimum, cost, price and bin.
movementsEvery stock change: out to a repair or in from an order.
purchase_ordersOrder per supplier, with its lines and whether it has arrived.
03

Orders

Whatever is below minimum is grouped by supplier, with enough to get back to twice the minimum. On receipt, stock goes up and an incoming movement is logged.

ts
// O que está abaixo do mínimo agrupa-se por fornecedor,
// com quantidade para voltar ao dobro do mínimo.
for (const p of parts.filter(p => p.stock < p.min)) {
  const lines = bySupplier.get(p.supplier) ?? [];
  lines.push({ ref: p.ref, qty: p.min * 2 - p.stock });
  bySupplier.set(p.supplier, lines);
}
04

What I'd do differently in production

Stock would be the sum of the movements rather than an editable number, so the system and the history can never disagree.

sql
-- Em produção o stock é a soma dos movimentos,
-- nunca um número que se edita à mão.
create view part_stock as
select ref, sum(case kind when 'in' then qty else -qty end) as stock
  from movements
 group by ref;