BUG-024: Декомпозиция

Код

Warehouse Service

  • В IngredientService.deleteIngredient(id, franchiseId) перед физическим удалением:
    • Проверка компонентного использования (isIngredientInUse → 422 INGREDIENT_IN_USE) уже была
    • Добавлено: найти собственные техкарты через techCardRepository.findByIngredientId(id). Если есть — удалить techCardRepository.deleteAll(...). Каскад на recipe_items — через ON DELETE CASCADE FK fk_recipe_items_tech_card в БД. Всё в одной транзакции.
  • Глобальный @ExceptionHandler({DataIntegrityViolationException, ConstraintViolationException}) в GlobalExceptionHandler409 DB_CONSTRAINT как safety net вместо 500

Admin Franchise (web)

  • Карточка ингредиента: показывать блок «Техкарта» если ингредиент — полуфабрикат (у него есть tech_cards c ingredient_id = :id)
  • При клике «Удалить ингредиент» с ненулевой техкартой — модалка подтверждения: «У ингредиента есть техкарта. Удалить вместе?» Yes → DELETE, No → cancel
  • Обработка 409 INGREDIENT_IN_USE от API — показать список затронутых продуктов/ингредиентов с ссылками в тосте/модалке

Спеки

  • 08-Specs/Админка Франшизы/Ингредиенты.md (или Техкарты.md) — добавить правило: «Удаление ингредиента-полуфабриката каскадно удаляет его техкарту. Удаление ингредиента, используемого как компонент в чужих техкартах, блокируется (409 с перечнем)»
  • 03-Services/Warehouse Service/API.md — у DELETE /ingredients/{id} добавить в Errors: 409 INGREDIENT_IN_USE с форматом details.usages[]
  • Пометить обновление в спеках *(Исправлено в [[07-Tasks/Bugs/BUG-024 500 при удалении ингредиента-полуфабриката с техкартой/Баг|BUG-024]])*