Клиент передал товар в пункт выдачи, но склад и учетная система не видят возврат. В такой цепочке участвуют ПВЗ, перевозчик, marketplace, интеграционный сервис и учет. Потеря может быть как недоставленным событием, так и неверной привязкой к заказу или неподдерживаемым статусом.
Нужно проследить один возврат по сквозным идентификаторам: return id, shipment id, order id и внешнему event id. После восстановления события важно сделать обработку идемпотентной и добавить регулярную сверку, иначе ручной повтор создаст дубликаты.
Что проверить в первую очередь
Сначала зафиксируйте точный сценарий, время ошибки и последнее известное рабочее состояние. Не меняйте несколько настроек одновременно: один контролируемый шаг должен подтверждать или исключать одну гипотезу. Перед работой с данными и конфигурацией подготовьте резервную копию и понятный способ отката.
- Получите квитанцию/return id ПВЗ и время фактического приема.
- Сопоставьте возврат с исходным заказом, отправлением, позицией и продавцом.
- Проверьте журнал webhook/API, очередь и dead-letter за этот период.
- Сравните таблицу соответствия внешних и внутренних статусов.
Почему возникает проблема
Внешний симптом обычно появляется на границе нескольких компонентов: интерфейса, backend, базы, фоновой очереди или внешнего сервиса. Поэтому важно найти первое место, где состояние становится неверным, а не исправлять последнее сообщение об ошибке.
- ПВЗ передает статус, которого нет в mapping интеграции.
- Webhook получил timeout и провайдер не повторил событие либо повтор был отклонен.
- Возврат ищется по order id, хотя частичный возврат имеет отдельный shipment/return id.
- Сообщение попало в dead-letter из-за временно отсутствующей позиции заказа.
- Обмен выгружает только новые записи и пропускает событие с более старым created_at.
Пошаговая диагностика
Диагностику проводите на тестовой записи или отдельном окружении. В журналах скрывайте токены, пароли и персональные данные. Для каждого шага сохраняйте измеримый результат: идентификатор события, код ответа, версию записи, состояние процесса или контрольную сумму.
- Запросите текущий возврат напрямую в API провайдера по внешнему ID.
- Найдите входящее событие, его подпись, код ответа и correlation id.
- Проверьте состояние очереди, retries и текст первой ошибки обработки.
- Сравните payload рабочего и потерянного возврата, включая позиции и статусы.
- Проверьте timezone и окна инкрементальной выгрузки.
Сквозная модель статусов возврата
Физический прием, доставка на склад, проверка качества, финансовый возврат и закрытие учета — разные этапы. Один флаг returned скрывает причину задержки.
- accepted_at_pickup подтверждает прием ПВЗ, но не приход на склад.
- in_transit и received_at_warehouse описывают логистический этап.
- inspection_result определяет доступность возврата денег или обмена.
- accounting_posted фиксирует документ в учете отдельно от клиентского статуса.
- Каждый переход хранит источник, время события и внешний идентификатор.
Как исправить проблему
Исправление лучше разбить на небольшие обратимые изменения. Сначала устраните подтвержденную причину, затем повторите исходный сценарий и проверьте соседние функции. Массовую обработку данных запускайте на ограниченной выборке с отчетом и только после сверки расширяйте на весь объем.
- Добавьте отсутствующий mapping статуса и обработку неизвестного значения без потери сообщения.
- Сделайте upsert по provider + return id и отдельную историю событий.
- Настройте надежные retries и ручное безопасное переигрывание dead-letter.
- Добавьте периодический pull/reconciliation возвратов за перекрывающееся окно.
- Отображайте менеджеру этап и причину блокировки, а не общий статус ошибки.
Безопасный порядок внедрения
- Сохраните затрагиваемые данные, конфигурацию и текущие журналы, заранее проверив способ отката.
- Повторите проблему на тестовом объекте без реальных списаний, рассылок и изменений клиентских данных.
- Внесите одно логическое изменение и зафиксируйте его в системе контроля версий или журнале работ.
- Не отключайте авторизацию, валидацию, шифрование и другие защитные механизмы ради быстрого исчезновения ошибки.
- После выкладки контролируйте логи, метрики и полный пользовательский сценарий, а не только один успешный запрос.
Как проверить результат
Разовый успешный тест недостаточен. Повторите операцию, проверьте крайние значения, параллельные действия и восстановление после перезапуска или временного сбоя. Для важного сценария сохраните автоматический тест либо короткий регрессионный чек-лист.
- Потерянный возврат появляется один раз и связан с правильными позициями.
- Повтор webhook/pull не создает второй документ.
- Частичный возврат не меняет невозвращенные товары.
- Сверка ПВЗ, логистики и учета показывает одинаковое количество по контрольному периоду.
Типичные ошибки при исправлении
- Создавать возврат вручную без внешнего ID и затем получать дубль.
- Считать прием в ПВЗ окончательным финансовым возвратом.
- Удалять ошибочное сообщение из очереди без сохранения payload и причины.
- Использовать только order id для нескольких отправлений и продавцов.
Как предотвратить повторение
Профилактика строится вокруг явных контрактов, повторяемых релизов и наблюдаемости. Система должна не только работать сейчас, но и позволять быстро увидеть нарушение инварианта при следующем обновлении, росте нагрузки или сбое внешнего сервиса.
- Ежедневно сверяйте возвраты по статусам и возрасту этапа.
- Храните необработанные события ограниченный срок для повторного разбора.
- Алертируйте неизвестные статусы и рост dead-letter.
- Тестируйте частичные возвраты, обмен и задержанный порядок событий.
Что подготовить для технического разбора
- Описание ожидаемого и фактического поведения, а также точную последовательность действий.
- Время проблемы, идентификатор тестового объекта и версии затронутых компонентов.
- Фрагменты журналов до и после ошибки без секретов и персональных данных.
- Перечень последних изменений и уже выполненных проверок.
- Безопасный доступ к тестовой среде или способ воспроизвести сбой без влияния на клиентов.
Частые вопросы
Можно ли просто повторно запросить все возвраты?
Можно через перекрывающееся окно, если запись идемпотентна по внешнему ID. Без unique/upsert повторная выгрузка создаст дубли.
Когда показывать клиенту возврат принятым?
Можно сразу после подтверждения ПВЗ, но интерфейс должен отличать прием товара от проверки и фактического возврата денег.
Когда нужна помощь специалиста
Если возвраты теряются между ПВЗ и учетом, я могу восстановить цепочку по идентификаторам, исправить mapping и очередь, добавить идемпотентный повтор и автоматическую сверку.