BR 1.14 — Warehouse Service

Миграция

  • Создать таблицу warehouses (id, franchise_id, store_id, name, status, created_at)
  • UNIQUE constraint (franchise_id, store_id)
  • Индекс idx_warehouses_franchise_id на franchise_id
  • Создать таблицу stock_batches (id, warehouse_id FK, ingredient_id FK, purchase_price, quantity, unit_of_measure, received_date, shelf_life_date, status, created_at)
  • Индекс idx_stock_batches_warehouse_ingredient на (warehouse_id, ingredient_id)
  • Создать таблицу stock_balances (id, warehouse_id FK, ingredient_id FK, current_quantity, average_cost, unit_of_measure, updated_at)
  • UNIQUE constraint (warehouse_id, ingredient_id)
  • Создать таблицу receipt_acts (id, franchise_id, warehouse_id FK, document_number, receipt_date, comment, status, total_amount, created_by, timestamps)
  • Индекс idx_receipt_acts_franchise_status на (franchise_id, status)
  • Создать таблицу receipt_act_lines (id, receipt_act_id FK CASCADE, ingredient_id FK, quantity, unit_of_measure, unit_price, line_total, shelf_life_date)
  • Создать таблицу write_off_acts (id, franchise_id, warehouse_id FK, document_number, write_off_date, reason, status, total_cost, created_by, timestamps)
  • Индекс idx_write_off_acts_franchise_status на (franchise_id, status)
  • Создать таблицу write_off_act_lines (id, write_off_act_id FK CASCADE, ingredient_id FK, quantity, unit_cost, line_cost)

Entity / DTO

  • Создать Warehouse entity
  • Создать WarehouseResponse DTO
  • Создать StockBatch entity
  • Создать StockBalance entity
  • Создать StockBalanceResponse DTO
  • Создать ReceiptAct entity
  • Создать ReceiptActLine entity
  • Создать ReceiptActResponse, ReceiptActLineResponse DTO
  • Создать CreateReceiptActRequest, UpdateReceiptActRequest DTO
  • Создать CreateReceiptActLineRequest, UpdateReceiptActLineRequest DTO
  • Создать WriteOffAct entity
  • Создать WriteOffActLine entity
  • Создать WriteOffActResponse, WriteOffActLineResponse DTO
  • Создать CreateWriteOffActRequest, UpdateWriteOffActRequest DTO
  • Создать CreateWriteOffActLineRequest DTO
  • Создать AverageCostResponse DTO

Repository

  • Создать WarehouseRepository (findByFranchiseId, findByFranchiseIdAndStoreId)
  • Создать StockBatchRepository (findByWarehouseIdAndIngredientId с qty > 0, сортировка по received_date ASC для FIFO)
  • Создать StockBalanceRepository (findByWarehouseId, findByWarehouseIdAndIngredientId)
  • Создать ReceiptActRepository (findByFranchiseId с фильтрами warehouse_id, status, пагинация)
  • Создать ReceiptActLineRepository (findByReceiptActId)
  • Создать WriteOffActRepository (findByFranchiseId с фильтрами)
  • Создать WriteOffActLineRepository (findByWriteOffActId)

Service

  • Создать WarehouseService — автоматическое создание склада при событии store.created, получение складов по franchise_id с ролевой фильтрацией
  • Создать StockService — управление балансами, расчёт средневзвешенной цены, FIFO-логика списания партий
  • Создать ReceiptActService — CRUD draft-документов, проводка (создание партий, обновление балансов, пересчёт average_cost), генерация document_number
  • Создать WriteOffActService — CRUD draft-документов, проводка (валидация остатков, FIFO-списание, обновление балансов), расчёт unit_cost из средневзвешенной
  • Обновить CostCalculationService — получение average_cost из stock_batches вместо статического значения

Controller

  • Создать WarehouseController (GET /warehouses)
  • Создать StockController (GET /stock-balances, GET /stock-balances/{wId}/{iId}, GET /ingredients/{id}/average-cost)
  • Создать ReceiptActController (GET/POST /receipt-acts, GET/PATCH /receipt-acts/{id}, POST /receipt-acts/{id}/post, POST/PATCH/DELETE /receipt-acts/{id}/lines)
  • Создать WriteOffActController (GET/POST /write-off-acts, GET/PATCH /write-off-acts/{id}, POST /write-off-acts/{id}/post, POST/DELETE /write-off-acts/{id}/lines)

Kafka Consumer

  • Добавить consumer для store.created → автоматическое создание склада (WarehouseService.createForStore)

Тестирование

  • Unit-тесты: FIFO-логика в StockService
  • Unit-тесты: средневзвешенная цена
  • Unit-тесты: проводка приёмки (создание партий + обновление балансов)
  • Unit-тесты: проводка списания (валидация остатков + FIFO)
  • Integration-тесты: полный цикл приёмка → списание → проверка остатков