Open source · MIT

Crate

Stock control with real FIFO: a balance is a queue of lots, and the cost of every shipment is broken down line by line.

v1.0.0 A cost of goods you can prove
Laravel 13PHP 8.5PostgreSQL 18BladeTailwind 4Vite 8
Crate

The average price lies

Most stock systems answer «how many» and shrug at «how much». They keep one average price per item, and the moment purchase prices drift, that average quietly stops matching reality. The margin on every order is off by a few percent and nobody can say why.

Crate keeps the layers. A receipt creates a lot with its own price; a shipment eats the queue from the oldest end and writes down which lots it took. Open any order and you see the arithmetic: four screws from the June lot, one from late June, eight from July, and what the same line would have cost under a weighted average.

What is inside

Real FIFO

Lots are read with row locks and consumed in receipt order, so two simultaneous orders can never spend the same stock twice. A shipment beyond the balance is never half-posted: the whole document rolls back.

Cost, line by line

Every shipment line stores its layers: lot, date, quantity taken, purchase price. Beside it sits the weighted-average alternative and the difference between them, so you can see exactly how much the average would have lied.

An immutable ledger

A posted document is never edited. A mistake is fixed by a reversal that returns the goods to the very lots they came from. A receipt whose lot has already been shipped cannot be reversed: that would be a lie about the cost of orders already made.

Transfers keep the age

Moving stock between warehouses recreates the same layers with their price and receipt date. Otherwise the FIFO queue would reset on every transfer and six-month-old stock would look fresh.

Stock counts that mean something

The sheet snapshots the expected quantity when it opens, because the warehouse keeps working while somebody walks the aisles. Surplus is received at the average cost of the remainder, shortage is written off through the queue. Two documents instead of one with a sign.

Integers and verification

Money in kopecks, quantity in thousandths of a unit, with no floats in a system whose whole job is that the numbers add up. The crate:verify command recomputes balances from the ledger and compares them with the lots every night.

Screenshots

Stock: every bar is a queue of lots, oldest on the left
Stock: every bar is a queue of lots, oldest on the left
One order taken apart: which lots the cost came from
One order taken apart: which lots the cost came from
Product card: layers per warehouse and the movement history
Product card: layers per warehouse and the movement history
The ledger: receipts, shipments, transfers and reversals
The ledger: receipts, shipments, transfers and reversals
Stock count: expected, counted, difference
Stock count: expected, counted, difference
Profit: revenue minus the cost of the lots that left
Profit: revenue minus the cost of the lots that left

Installation

git clone https://github.com/dripips/crate.git cd crate docker compose up --build

Have a project or idea?

Write to me and we will talk the task through.