BR 2.5 — Catalog Service

Источник

Задачи

Миграция БД

  • Liquibase changeset XXX-br-2-5-kitchen-stations:
    • Создать таблицу kitchen_stations (id, franchise_id, name, description, is_default, deleted_at, created_at, updated_at)
    • Индекс idx_kitchen_stations_franchise (franchise_id) WHERE deleted_at IS NULL
    • Unique uq_kitchen_stations_franchise_name (franchise_id, LOWER(name)) WHERE deleted_at IS NULL
  • Liquibase changeset XXX-br-2-5-products-kitchen-fields:
    • ALTER TABLE products ADD COLUMN requires_kitchen BOOLEAN NOT NULL DEFAULT false
    • ALTER TABLE products ADD COLUMN kitchen_station_id UUID NULL
    • ADD CONSTRAINT fk_products_kitchen_station FK kitchen_station_id REFERENCES kitchen_stations(id) ON DELETE RESTRICT
    • ADD CONSTRAINT chk_products_kitchen CHECK (requires_kitchen = false OR kitchen_station_id IS NOT NULL)
    • Индекс idx_products_kitchen_station (kitchen_station_id) WHERE kitchen_station_id IS NOT NULL

Entity + Repository

  • KitchenStation — JPA entity
  • KitchenStationRepository — Spring Data JPA (findByFranchiseIdAndDeletedAtIsNull, existsByFranchiseIdAndNameIgnoreCase, etc.)
  • Product entity — добавить поля requiresKitchen, kitchenStationId (FK-relation through @ManyToOne)
  • ProductRepository — query для countByKitchenStationId (для правила STATION_IN_USE)

DTO

  • KitchenStationResponse, CreateKitchenStationRequest, UpdateKitchenStationRequest
  • Расширить ProductResponse / CreateProductRequest / UpdateProductRequest новыми полями

Service

  • KitchenStationService — CRUD + soft delete с защитой STATION_IN_USE
  • ProductService.validateKitchen(request):
    • requires_kitchen=true + kitchen_station_id IS NULL → 422 MISSING_KITCHEN_STATION
    • requires_kitchen=false + kitchen_station_id != null → автоматически сбрасывать на NULL
    • kitchen_station_id указывает на soft-deleted или несуществующую станцию → 422 STATION_NOT_FOUND

Controllers

  • KitchenStationController/kitchen-stations (GET, POST, PATCH, DELETE) — все с permission catalog.edit / catalog.read
  • ProductController — расширить DTO (ничего не создавать, апдейт existing endpoint’ов)

Events

  • product.updated и catalog.product.availability.changed — проверить что новые поля requires_kitchen / kitchen_station_id попадают в payload (для консьюмеров Aggregator Service)

Verification

  1. mvn compile зелёный локально
  2. Миграции применяются на пустую БД и на существующую БД с товарами (старые товары получают requires_kitchen=false, kitchen_station_id=NULL по дефолту — OK)
  3. Smoke:
    • POST /kitchen-stations { name: "Горячая кухня" } → 201
    • POST /kitchen-stations { name: "горячая кухня" } → 409 DUPLICATE_STATION (case-insensitive)
    • POST /products { ..., requires_kitchen: true } без kitchen_station_id → 422 MISSING_KITCHEN_STATION
    • POST /products { ..., requires_kitchen: true, kitchen_station_id: X } → 201
    • DELETE /kitchen-stations/X когда на X ссылается товар → 422 STATION_IN_USE с details