Обратная логистика использует другие ограничения, чем обычная доставка: точка старта может быть у клиента или в ПВЗ, склад приёма зависит от типа товара, а временное окно и вместимость транспорта уже частично заняты прямыми заказами. Молчаливый отказ оптимизатора оставляет операцию без владельца.
Возьмите одну заявку и проверьте её путь от статуса approved до появления stop в маршруте. Зафиксируйте координаты, склад назначения, окно, габариты, тип груза, доступного курьера и ответ планировщика. Не меняйте адрес вручную до сохранения исходной причины исключения.
Что проверить в первую очередь
Для проблемы «система не создаёт маршрут возврата товара на склад» сначала зафиксируйте один воспроизводимый пример: точное время, идентификатор объекта, пользователя или операции, входные данные, версию приложения и фактический результат. Отдельно запишите ожидаемое поведение: подтверждённая заявка создаёт допустимую pickup-точку, назначение склада и маршрутное задание либо понятную причину, почему автоматическое планирование невозможно. Это не формальность. Без исходной точки легко принять временное совпадение за исправление, изменить сразу несколько условий и потерять возможность доказать настоящую причину сбоя.
Проверку начинайте с чтения состояния и журналов. Не запускайте массовый перерасчёт, повторную отправку, удаление записей или изменение прав на рабочей системе, пока не подготовлены резервная копия и способ отката. Секреты, токены, персональные данные и содержимое заказов в диагностические выгрузки не включайте.
- Проверьте статус возврата и флаг готовности товара к забору.
- Убедитесь, что адрес клиента и склада успешно геокодированы и попадают в обслуживаемую зону.
- Сверьте рабочее время склада и допустимое окно возврата.
- Проверьте вес, объём, температурный режим и ограничения транспорта.
- Уточните cutoff планирования и необходимость ручного подтверждения приёмки.
Почему возникает проблема
Видимый симптом обычно находится в конце цепочки. Пользователь видит неверный статус или отказ, хотя первичная ошибка могла произойти в API, фоновой задаче, кеше, очереди, внешнем сервисе либо при проверке доступа. Основной риск этого сценария: товар зависает у курьера или клиента, склад не ожидает приёмку, а остатки и сроки возврата становятся недостоверными. Поэтому исправление только интерфейса или ручная правка итоговой записи часто скрывает проблему, но не устраняет её.
Разбирайте события по хронологии и ищите первую точку, где фактические данные перестают соответствовать бизнес-правилу. В распределённой системе одинаково важны успешный ответ, повтор запроса, задержка события, параллельное выполнение и восстановление после временного отказа.
- Заявка имеет бизнес-статус approved, но не публикует событие route_ready.
- Склад назначения закрыт, не поддерживает категорию товара или не имеет координат.
- Оптимизатор исключает stop из-за невозможного окна и не сохраняет объяснение.
- Возврат имеет отрицательный или нулевой объём из-за ошибки единиц.
- Маршрут построен, но интеграция с приложением курьера отфильтровала обратную точку.
Пошаговая диагностика
Создайте безопасный тестовый сценарий, максимально похожий на проблемный, но не затрагивающий реальные списания, рассылки и клиентские данные. Присвойте операции единый correlation ID и проследите его через входящий запрос, бизнес-логику, базу, очередь и внешние интеграции. Для каждого этапа фиксируйте вход, результат, код ответа, время выполнения и номер версии записи.
Сначала подтвердите сам факт расхождения, затем последовательно исключайте уровни. Сравните рабочий и ошибочный случаи по одним и тем же полям. Проверьте часовой пояс, формат идентификаторов, порядок событий, права сервисной учётной записи и актуальность конфигурации на каждом экземпляре приложения. Если результат зависит от повторного запроса, задержки или конкретного узла, это важная часть причины, а не случайный шум.
- Сопоставьте return ID, logistics task ID, route plan ID и courier job ID.
- Проверьте результат геокодирования и версию справочника зон.
- Запустите dry-run оптимизатора только для одной заявки с выводом нарушенных ограничений.
- Сравните прямую доставку и возврат для того же адреса и транспорта.
- Проследите публикацию маршрута и подтверждение получения мобильным приложением.
Как устроить возвратную логистическую задачу
Возврат должен становиться отдельной logistics task с местом забора, местом приёмки, грузовыми параметрами, временными окнами, приоритетом и собственным жизненным циклом.
Надёжная реализация хранит бизнес-состояние явно и не пытается восстановить его только по экрану, случайному логу или последнему webhook. У каждого значимого действия должен быть стабильный идентификатор, понятный владелец, версия правила и проверяемый переход статуса. Повторная доставка одного события не должна создавать второе действие, а запоздавшее событие не должно возвращать объект в невозможное состояние.
- Склад выбирается детерминированным правилом по продавцу, категории, региону и возможности приёмки.
- Каждая точка хранит исходный адрес, координаты, качество геокодирования и временную зону.
- Оптимизатор возвращает не только маршрут, но и объяснимую причину исключения.
- Нераспределённые задачи попадают в очередь ручного решения с ответственным.
- Приёмка на складе закрывает маршрут и запускает дальнейшее складское движение.
Как исправить проблему
Исправление разделите на небольшие обратимые изменения. Сначала устраните подтверждённую первопричину, затем восстановите повреждённые данные отдельной контролируемой процедурой. Не смешивайте выпуск нового кода и массовую коррекцию истории в одном непрозрачном запуске: для них нужны разные отчёты, критерии успеха и планы отката.
Если затронуты существующие записи, сначала сформируйте dry-run: список объектов, старое значение, предлагаемое новое значение и основание для изменения. Обновление должно быть идемпотентным, ограниченным точной выборкой и сопровождаться аудитом. Для финансовых данных, прав доступа и персональной информации предпочтительны компенсирующие записи, а не переписывание истории.
- Добавьте явное событие готовности возврата и идемпотентное создание logistics task.
- Валидируйте адреса, окна и грузовые параметры до отправки в оптимизатор.
- Сохраняйте violated constraints и показывайте их диспетчеру.
- Настройте fallback на следующий рейс или ручное назначение без потери исходных данных.
- Унифицируйте схему прямых и обратных stop в API приложения курьера.
Безопасный порядок внедрения
- Сохраните конфигурацию, связанные записи и необходимые журналы; отдельно проверьте, что резервную копию действительно можно восстановить.
- Воспроизведите проблему на тестовом объекте и сохраните результат до изменения, чтобы после выпуска сравнить одинаковые сценарии.
- Внесите минимальное изменение под системой контроля версий, опишите причину, ожидаемый эффект, ограничения и точный способ отката.
- Прогоните нормальный сценарий, ошибочный ввод, повтор одного запроса, два параллельных запроса и временную недоступность зависимости.
- Выпустите изменение на ограниченную долю трафика или один процесс, если архитектура это позволяет, и сравните метрики со старой версией.
- Только после стабильного наблюдения выполните контролируемое исправление исторических данных и сохраните итоговый отчёт.
Как проверить результат
Один успешный пример недостаточен. Проверьте основную операцию повторно, крайние значения, одновременные действия, перезапуск процесса и восстановление после краткого сбоя сети. Результат подтверждайте не только экраном пользователя, но и состоянием базы, очереди, внешнего сервиса и журналом аудита. Особое внимание уделите тому, что система делает при повторной доставке уже обработанного события.
Критерии приёмки сформулируйте до выпуска. Каждый пункт должен давать однозначный ответ «выполнено» или «не выполнено», а не субъективную оценку. Если тест невозможно повторить автоматически, оставьте короткий регрессионный чек-лист с тестовыми данными и ожидаемыми статусами.
- Обычный возврат создаёт точку забора и склад назначения.
- Невозможное окно даёт понятную причину и попадает в рабочую очередь.
- Повтор события не создаёт дублирующую logistics task.
- Смена склада пересчитывает маршрут и сохраняет аудит решения.
- После приёмки курьерская задача закрывается, а товар появляется в нужном складском статусе.
Типичные ошибки при исправлении
- Назначать ближайший склад без проверки возможности приёмки категории.
- Игнорировать часовой пояс клиента и склада.
- Считать отсутствие маршрута допустимым пустым результатом без алерта.
- Создавать новую заявку при каждом повторе планировщика.
- Закрывать возврат сразу после забора, не дожидаясь складской приёмки.
Опаснее всего исправление, которое убирает заметный симптом ценой отключения проверки, ослабления прав или потери аудита. Такое изменение может сделать интерфейс «зелёным», но увеличить ущерб при следующем сбое. Если временный обход всё же необходим, ограничьте его срок, пользователей и область действия, добавьте мониторинг и заранее назначьте дату удаления.
Как предотвратить повторение
Профилактика строится вокруг явных контрактов, идемпотентных обработчиков, наблюдаемости и повторяемых релизов. Система должна не только корректно работать сейчас, но и быстро показывать нарушение правила после обновления, роста нагрузки или отказа интеграции. Ошибку, которая уже привела к потере времени, денег, данных или заявок, стоит закрепить автоматическим тестом.
Настройте мониторинг полного пользовательского пути, а не только доступности отдельных серверов. Техническая метрика должна быть связана с бизнес-результатом: заказ завершён, доступ выдан, файл восстановлен, событие обработано один раз, данные изолированы. Порог оповещения задавайте по нормальному профилю нагрузки и проверяйте, что уведомление содержит достаточно контекста для первого решения.
- Возраст возвратов без logistics task и без назначенного владельца.
- Доля точек, исключённых оптимизатором по каждой причине.
- Ошибки геокодирования и выход адресов за обслуживаемую зону.
- Время от approval до забора и от забора до приёмки на складе.
- Расхождение статусов возврата, маршрута и складского движения.
Что подготовить для технического разбора
- Короткое описание ожидаемого и фактического поведения с точной последовательностью действий.
- Время возникновения, идентификатор тестового объекта и версии всех затронутых компонентов.
- Обезличенные фрагменты журналов до и после ошибки с единым correlation ID.
- Список последних изменений, результаты уже выполненных проверок и условия, при которых симптом исчезает.
- Безопасный доступ к тестовой среде либо минимальный пример, не содержащий паролей, токенов и персональных данных.
Частые вопросы
Почему обычная доставка строится, а возврат нет?
Для возврата часто действуют другой склад, окно, тип stop и дополнительные ограничения приёмки. Нужно сравнить вход планировщика.
Можно ли назначить маршрут вручную?
Да, как контролируемый fallback с аудитом, но причина автоматического исключения всё равно должна быть сохранена.
Когда товар считать возвращённым?
Обычно после подтверждённой приёмки в согласованной точке, а не только после создания маршрута или забора курьером.
Когда нужна помощь специалиста
Если возвраты не попадают в маршруты, я могу проверить события, геокодирование, зоны, ограничения оптимизатора и мобильное приложение курьера. Для оценки нужны обезличенный return ID, вход планировщика и его ответ.