Open source · MIT

Crate

Складской учёт с настоящим FIFO: остаток — очередь партий, а себестоимость каждой отгрузки разобрана построчно.

v1.0.0 Себестоимость, которую можно предъявить
Laravel 13PHP 8.5PostgreSQL 18BladeTailwind 4Vite 8
Crate

Средняя цена врёт

Большинство складских программ отвечают на вопрос «сколько» и пожимают плечами на вопрос «почём». Они держат одну среднюю цену на товар, и как только закупочные цены расходятся, средняя тихо перестаёт совпадать с реальностью: маржа каждого заказа врёт на несколько процентов, и объяснить это некому.

Crate хранит слои. Приёмка создаёт партию со своей ценой, отгрузка ест очередь со старого конца и записывает, что именно взяла. Откройте любой заказ — и увидите арифметику: четыре штуки из июньской партии по 333,42 ₽, одна из конца июня, восемь из июльской, и рядом — во что обошлась бы та же строка по средней цене.

Что внутри

Настоящий FIFO

Партии читаются с блокировкой строк и расходуются в порядке прихода, поэтому два одновременных заказа не спишут один остаток дважды. Отгрузка сверх остатка не проводится наполовину — документ откатывается целиком.

Себестоимость построчно

Каждая строка отгрузки хранит свои слои: партия, дата, сколько взято, цена закупки. Рядом лежит альтернатива по средневзвешенной оценке и разница между ними — видно, на сколько соврала бы средняя цена.

Книга не редактируется

Проведённый документ неизменяем. Ошибка исправляется сторнированием, которое возвращает товар ровно в те партии, из которых он ушёл. Приёмку, из партии которой уже отгружали, сторнировать нельзя — это соврало бы о себестоимости.

Переезд не старит товар

Перемещение между складами воссоздаёт на новом месте те же слои с их ценой и датой прихода. Иначе очередь FIFO обнулялась бы переездом, а полугодовой остаток выглядел бы свежим.

Осмысленная инвентаризация

Лист запоминает ожидаемое количество в момент открытия: склад работает, пока человек ходит по стеллажам. Излишки приходуются по средней цене остатка, недостача списывается по очереди партий — два разных документа, а не один со знаком.

Целые числа и сверка

Деньги в копейках, количество в тысячных долях единицы — никаких float там, где вся работа в том, чтобы цифры сходились. Команда crate:verify пересчитывает остатки из книги и сверяет с партиями каждую ночь.

Скриншоты

Остатки: каждая полоса — очередь партий, слева самое старое
Остатки: каждая полоса — очередь партий, слева самое старое
Разбор заказа: из каких партий собрана себестоимость
Разбор заказа: из каких партий собрана себестоимость
Карточка товара: слои по складам и история движений
Карточка товара: слои по складам и история движений
Книга: приёмки, отгрузки, перемещения и сторно
Книга: приёмки, отгрузки, перемещения и сторно
Инвентаризация: ожидалось, посчитано, расхождение
Инвентаризация: ожидалось, посчитано, расхождение
Прибыль: выручка минус себестоимость по партиям
Прибыль: выручка минус себестоимость по партиям

Установка

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

Есть проект или идея?

Напишите мне, обсудим задачу.