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