Складской учёт
Назначение
Товарные запасы ресторана: приёмка (накладные), контроль (инвентаризации), списание (порча), ручная продажа (акты реализации), мониторинг остатков и лимитов. Полный цикл движения товара от прихода до списания.
6 контроллеров, ~40 эндпоинтов.
Сценарии
Накладные (приёмка товара)
Актор: Менеджер закупок / Кладовщик
Основной документ поступления товара.
Типы:
- INCOMING — приход от поставщика
- RETURN — возврат поставщику
- INTERNAL_TRANSFER — перемещение между складами
Жизненный цикл:
DRAFT ─── подтверждение ──► CONFIRMED ─── закрытие ──► CLOSED │ │ └── отмена ──► CANCELLED └── отмена (откат остатков) ──► CANCELLEDСоздание черновика:
- Склад (WAREHOUSE), юрлицо, контрагент (поставщик)
- Дата документа, опционально дата оплаты
- Строки: номенклатура, количество, цена, ставка НДС
Подтверждение:
- Статус DRAFT, минимум одна строка
- Расчёт сумм для каждой строки:
- Сумма без НДС = количество × цена
- НДС = сумма × ставка НДС
- Сумма с НДС = без НДС + НДС
- Итоги накладной (totalWithVat, totalWithoutVat, totalVat)
- Складские транзакции (INCOMING)
- Обновление остатков
- Статус → CONFIRMED
Бизнес-правила (агрегат InvoiceAggregate, static):
- Редактирование только в DRAFT (
ensureDraftStatus) - Минимум одна строка для подтверждения (
ensureHasItems) - Количество > 0, цена > 0
- НДС: 0–100% (
ensureValidVatRate) - Дата оплаты ≥ дата документа
- Склад принадлежит корпорации
- Дата не в заблокированном периоде (
ensureReasonableDocumentDate) - Для отмены подтверждённой: статус CONFIRMED (
ensurePostedStatus) - Нельзя подтвердить с существующими платежами (
ensureUnpaidForPost) - Фактическое количество ≤ общего (
ensureActualQuantityNotExceedTotal)
Доменное событие: invoice-changed
Инвентаризация
Актор: Управляющий / Кладовщик
Сверка фактических остатков с данными системы.
Процесс:
- Выбор склада, дата
- Для каждой номенклатуры: bookQuantity (автоматически из системы) vs factualQuantity (ввод вручную)
- При проведении:
- Факт > учёт → излишки (транзакция SURPLUS)
- Факт < учёт → недостачи (транзакция SHORTAGE)
- Остатки корректируются до фактических
DRAFT → POSTED / CANCELLEDБизнес-правила (агрегат InventoryAggregate, static):
- Редактирование только в DRAFT
- Минимум одна позиция
- Количество ≥ 0, себестоимость ≥ 0
- Дата не в заблокированном периоде
Поддерживает пересчёт (recount) отдельных позиций.
Доменное событие: inventory-changed
Акт списания
Актор: Управляющий / Повар
Удаление товара со склада (порча, просрочка, утеря).
DRAFT → POSTED / CANCELLED- Склад, причина, дата
- Позиции: номенклатура + количество
- При проведении: транзакции WRITE_OFF, уменьшение остатков
Бизнес-правила (агрегат WriteOffActAggregate, static):
- Количество > 0
- Минимум одна позиция
- Редактирование только в DRAFT
- Дата не в заблокированном периоде
Доменное событие: write-off-act-changed
Акт реализации
Актор: Управляющий
Ручная продажа (не через POS) — оптовые заказы, корпоративные и т.п.
DRAFT → POSTED / CANCELLED- Склад, метод оплаты, дата
- Позиции: номенклатура, количество, цена продажи, себестоимость
- При проведении: транзакции SALE
Бизнес-правила (агрегат SalesActAggregate, static):
- Сумма и количество > 0
- Скидка ≤ стоимость позиции
- Минимум одна позиция
- Редактирование только в DRAFT
Доменное событие: sales-act-changed
Складские остатки
WarehouseStock — текущее количество и средняя себестоимость каждой номенклатуры на каждом складе. Обновляется автоматически при подтверждении документов.
InventoryTransaction — полная история движения товара:
- Типы: INCOMING, OUTGOING, WRITE_OFF, SURPLUS, SHORTAGE, TRANSFER, SALE
- Каждая транзакция привязана к документу-источнику
Лимиты остатков
Для номенклатуры на складе — минимальный и максимальный остаток. Для мониторинга и оповещений.
Бизнес-правила (агрегат StockLimitAggregate, static):
- Минимум ≤ максимум, оба ≥ 0
Движение товара
ПОСТАВЩИК СКЛАД КЛИЕНТ │ │ │ │ ── Накладная (INCOMING) ──► │ │ │ ◄─ Накладная (RETURN) ──── │ │ │ │ ── Акт реализации ──────────►│ │ │ ── Акт списания (порча) ──► ∅ │ │ ── POS-чек (автосписание) ──►│ │ │ │ │ Склад A ───┤── Перемещение ──► Склад B │ │ │ │ │ Инвентаризация → коррекция остатков │Связи с другими контекстами
| Направление | Что | Зачем |
|---|---|---|
| Организация → Склад | Подразделения, юрлица, контрагенты | Склады, поставщики, даты блокировки |
| Меню → Склад | Номенклатура | Позиции документов, остатки |
| Склад → Бухгалтерия | Накладные | Основание для платежей |
| Закупки → Склад | Метод оплаты | В актах реализации |
Синхронизация с POS
При изменении накладных, инвентаризаций, списаний, актов реализации — события в Kafka.
Сущности
| Сущность | Описание |
|---|---|
| Накладная (Invoice) | Приход / возврат / перемещение. Строки, суммы, статус |
| Строка накладной (InvoiceItem) | Номенклатура, количество, цена, НДС, итоги |
| Складской остаток (WarehouseStock) | Количество и себестоимость на складе |
| Складская транзакция (InventoryTransaction) | Запись о движении: тип, количество, себестоимость, ссылка на документ |
| Инвентаризация (Inventory) | Сверка остатков. Привязка к счетам излишков/недостач |
| Позиция инвентаризации (InventoryItem) | Номенклатура, учётное vs фактическое количество |
| Акт списания (WriteOffAct) | Списание со склада с причиной |
| Акт реализации (SalesAct) | Ручная продажа с ценой и себестоимостью |
| Лимит остатков (StockLimit) | Мин/макс остаток на складе |
| Складской баланс (StockBalance) | Денормализованное представление остатков |