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

0035. Ассистируемая подача жалоб на отзывы (без хранения сессий ЛК)

Копия ADR из репозитория: backend/docs/adr/0035-complaint-assisted-submission.md. Канонический текст — в репозитории; портал обновляется командой npm run sync:adr.

  • Статус: accepted (2026-07-06)
  • Дата: 2026-07-06
  • Связанные задачи: OP-77 (эпик OP-13 · 5.5 Автоответы); реализует стратегию ADR-0026 (вариант E)

Контекст и проблема​

OP-75 подготавливает текст жалобы на отзыв (сущность ComplaintEntity, статусы draft/pending), но саму подачу оставляет отдельному тикету (OP-77). Исходная формулировка OP-77 («отправка жалоб через ЛК», «очередь отправки») подразумевала полную автоматизацию действия в ЛК продавца. Однако жалоба на отзыв — одна из двух UI-only операций, для которых ADR-0026 принял вариант E (ассистируемый ручной шаг) как базу MVP: полная автоматизация (вариант D через headless-браузер/неофициальные эндпоинты) отложена за фиче-флаг пост-MVP из-за риска блокировки аккаунта продавца (оферта WB) и стоимости хранения сессий ЛК. Нужно определить конкретную форму реализации подачи под вариант E.

Решение​

Подача реализуется как ассистируемый ручной шаг, полностью в рамках backend-API, без хранения сессий ЛК и без автоматической отправки:

  1. Диплинк вместо отправки. Для подготовленной жалобы формируется ссылка в экран отзывов ЛК продавца (seller.wildberries.ru), best-effort с подсказкой-фильтром по артикулу (nmId). Base-URL — единая константа WB_SELLER_FEEDBACKS_URL. Само действие «Пожаловаться» продавец выполняет в своём ЛК.
  2. Жизненный цикл статусов. К draft/pending добавлены терминальные submitted (продавец подтвердил подачу; фиксируется submitted_at) и dismissed (продавец отклонил кандидата).
  3. API. GET /autoreply/complaints — жалобы, ждущие действия (draft/pending), с диплинком; POST /autoreply/complaints/:id/submit — отметить поданной; POST /autoreply/complaints/:id/dismiss — отклонить. Scope — по кабинету; аудит (F6) на переходах.
  4. Защита факта подачи. Повторная prepare для уже поданной жалобы (submitted) отклоняется 409 Conflict — не затираем зафиксированную подачу (закрывает TODO OP-75).

Почему без очереди/отправки​

Под вариантом E внешней асинхронной отправки нет — нечего ретраить и незачем очередь (в отличие от отправки ответов OP-74 через официальный API). «Нотификация» продавца моделируется как API-поверхность «требует действия» + диплинк; реальный push-канал (email/Telegram/in-app) — отдельная поздняя история, не в scope [BE]-тикета.

Последствия​

  • Положительные: MVP не хранит сессии ЛК и не нарушает оферту WB → аккаунты клиентов не под угрозой блокировки; реализация дёшева (ломается только диплинк, не бизнес-логика); переиспользует подготовку жалоб OP-75 и аудит F6.
  • Границы: автоматическая подача в MVP не поставляется (осознанный отказ по ADR-0026); задел остаётся за фиче-флагом (вариант D). Диплинк best-effort — при изменении маршрутов ЛК WB его нужно перепроверять; при появлении официального метода «Пожаловаться» операция переезжает в вариант A.
  • Зависимость: фронтенд (OP-9x) отображает список ждущих действия жалоб с кнопкой «Открыть в ЛК» и фиксирует решение продавца через submit/dismiss.