Перейти к содержимому

Складской учёт

Назначение

Товарные запасы ресторана: приёмка (накладные), контроль (инвентаризации), списание (порча), ручная продажа (акты реализации), мониторинг остатков и лимитов. Полный цикл движения товара от прихода до списания.

6 контроллеров, ~40 эндпоинтов.


Сценарии

Накладные (приёмка товара)

Актор: Менеджер закупок / Кладовщик

Основной документ поступления товара.

Типы:

  • INCOMING — приход от поставщика
  • RETURN — возврат поставщику
  • INTERNAL_TRANSFER — перемещение между складами

Жизненный цикл:

DRAFT ─── подтверждение ──► CONFIRMED ─── закрытие ──► CLOSED
│ │
└── отмена ──► CANCELLED └── отмена (откат остатков) ──► CANCELLED

Создание черновика:

  1. Склад (WAREHOUSE), юрлицо, контрагент (поставщик)
  2. Дата документа, опционально дата оплаты
  3. Строки: номенклатура, количество, цена, ставка НДС

Подтверждение:

  1. Статус DRAFT, минимум одна строка
  2. Расчёт сумм для каждой строки:
    • Сумма без НДС = количество × цена
    • НДС = сумма × ставка НДС
    • Сумма с НДС = без НДС + НДС
  3. Итоги накладной (totalWithVat, totalWithoutVat, totalVat)
  4. Складские транзакции (INCOMING)
  5. Обновление остатков
  6. Статус → CONFIRMED

Бизнес-правила (агрегат InvoiceAggregate, static):

  • Редактирование только в DRAFT (ensureDraftStatus)
  • Минимум одна строка для подтверждения (ensureHasItems)
  • Количество > 0, цена > 0
  • НДС: 0–100% (ensureValidVatRate)
  • Дата оплаты ≥ дата документа
  • Склад принадлежит корпорации
  • Дата не в заблокированном периоде (ensureReasonableDocumentDate)
  • Для отмены подтверждённой: статус CONFIRMED (ensurePostedStatus)
  • Нельзя подтвердить с существующими платежами (ensureUnpaidForPost)
  • Фактическое количество ≤ общего (ensureActualQuantityNotExceedTotal)

Доменное событие: invoice-changed

Инвентаризация

Актор: Управляющий / Кладовщик

Сверка фактических остатков с данными системы.

Процесс:

  1. Выбор склада, дата
  2. Для каждой номенклатуры: bookQuantity (автоматически из системы) vs factualQuantity (ввод вручную)
  3. При проведении:
    • Факт > учёт → излишки (транзакция SURPLUS)
    • Факт < учёт → недостачи (транзакция SHORTAGE)
  4. Остатки корректируются до фактических
DRAFT → POSTED / CANCELLED

Бизнес-правила (агрегат InventoryAggregate, static):

  • Редактирование только в DRAFT
  • Минимум одна позиция
  • Количество ≥ 0, себестоимость ≥ 0
  • Дата не в заблокированном периоде

Поддерживает пересчёт (recount) отдельных позиций.

Доменное событие: inventory-changed

Акт списания

Актор: Управляющий / Повар

Удаление товара со склада (порча, просрочка, утеря).

DRAFT → POSTED / CANCELLED
  1. Склад, причина, дата
  2. Позиции: номенклатура + количество
  3. При проведении: транзакции WRITE_OFF, уменьшение остатков

Бизнес-правила (агрегат WriteOffActAggregate, static):

  • Количество > 0
  • Минимум одна позиция
  • Редактирование только в DRAFT
  • Дата не в заблокированном периоде

Доменное событие: write-off-act-changed

Акт реализации

Актор: Управляющий

Ручная продажа (не через POS) — оптовые заказы, корпоративные и т.п.

DRAFT → POSTED / CANCELLED
  1. Склад, метод оплаты, дата
  2. Позиции: номенклатура, количество, цена продажи, себестоимость
  3. При проведении: транзакции 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)Денормализованное представление остатков