Заказ с сайта проходит через пять систем: витрину, платёжный сервис, учётную систему, склад и службу доставки. Ломается он не внутри них — каждая по отдельности работает годами, — а на четырёх стыках между ними. Заказ уходит в учёт дважды, потому что связь оборвалась на середине ответа. Не уходит вовсе, потому что учётная система была на обслуживании и никто не переслал запрос повторно. Приходит на позицию, которой нет в продаже, потому что товар переименовали, а сопоставление шло по названию. Висит неоплаченным при успешном платеже, потому что уведомление от платёжного сервиса не дошло.

Общее у всех четырёх случаев одно: они не выглядят как поломка. Сайт открывается, заказы принимаются, обмен в журнале успешен. Покупатель видит «заказ принят» и ждёт. Через два дня он звонит спросить, где заказ, и оказывается, что в учёте его нет вообще.

Дальше — маршрут заказа по шагам с указанием, кто на каждом владеет статусом; очередь повторов и что происходит, пока учёт недоступен; защита от повторной обработки по внешнему номеру; сопоставление номенклатуры по артикулу; отдельно оплаты и их подтверждения; и суточная сверка «создано — доехало», которая делает потерю заметной в тот же день. Общая механика связи витрины и учёта разобрана в опорной статье раздела; здесь мы разбираем один контур — самый дорогой в ошибках.

Маршрут заказа: пять систем и четыре стыка

Первое, что нужно нарисовать до начала работ, — таблица владения. В ней у каждого шага есть система, которая создаёт запись, и система, которая в этот момент имеет право менять статус. Если на каком-то шаге в колонке владельца оказывается две системы, вы уже нашли будущий баг.

ШагКто создаёт записьКто владеет статусомЧто ломается на этом стыке
Покупатель нажал «Оформить»СайтСайтДвойное нажатие создаёт два заказа с разными номерами и одинаковым составом
ОплатаПлатёжный сервисПлатёжный сервис до итогового ответаУведомление об успешной оплате не дошло — заказ висит неоплаченным
Заказ уехал в учётУчётная системаУчётная системаПовтор при обрыве связи даёт дубль; недоступность учёта — потерю заказа
Сборка и отгрузкаСкладУчётная система по документам складаСтатус меняется на складе, но не возвращается на сайт — покупатель звонит
Передача в доставкуСлужба доставкиСлужба доставкиТрек-номер есть у перевозчика, но не доехал до карточки заказа

Отдельно стоит зафиксировать порядок запуска. Направления «из учёта на витрину» — номенклатура, цены, остатки — безопасны: худшее последствие ошибки в них — неверная цифра на карточке, и мы разбирали этот контур в статье про обмен остатками и ценами. Направление «с витрины в учёт» создаёт в боевой базе документ, который пойдёт в отгрузку, в кассу и в отчётность, поэтому заказы всегда подключаются последними и всегда с защитой от повторной обработки. Обратный порядок — самая частая причина, по которой проект приходится останавливать на второй неделе и разбирать созданные документы вручную.

схема процессаzakazy-i-statusy-mezhdu-saytom-i-uchetom--01
Маршрут заказа через пять систем с указанием владельца статуса на каждом шаге

Горизонтальная схема из пяти блоков со стрелками: «Сайт» → «Платёжный сервис» → «Учётная система» → «Склад» → «Служба доставки». Под каждым блоком подпись «владелец статуса на этом шаге». На четырёх стыках между блоками нарисованы отметки-разрывы с подписями: «двойное нажатие», «уведомление об оплате не дошло», «повтор при обрыве или недоступность учёта», «статус не вернулся на сайт». Обратная стрелка от учёта к сайту подписана «статус покупателю». Чертёжная манера, подписи по-русски.

На каждом шаге ровно один владелец статуса — там, где их два, живёт будущий баг

Владелец статуса: правило одного хозяина

Что это значитВладелец статуса

Единственная система, которая на данном шаге имеет право изменить состояние заказа. Все остальные системы это состояние только читают и отображают. Правило нарушается, когда менеджер меняет статус в админке сайта, а кладовщик — в учётной системе: обе правки законны с точки зрения человека, но одна из них будет затёрта при следующем обмене, и предсказать, какая именно, невозможно.

Практическая трудность в том, что статусов в учётной системе обычно втрое больше, чем нужно покупателю. «Заказ клиента проведён», «резерв установлен», «отбор выполнен», «реализация проведена» — это внутренние состояния склада и бухгалтерии. Покупателю нужно пять: принят, собран, передан в доставку, прибыл в пункт выдачи, вручён. Между двумя наборами должна лежать явная таблица соответствия, а не логика в голове программиста.

  • Внутренних статусов может быть сколько угодно — это дело учётной системы. Наружу выходят пять, и таблица соответствия согласуется с тем, кто отвечает за магазин, а не пишется подрядчиком по своему усмотрению.
  • Каждое изменение статуса возвращается на сайт по событию, а не подбирается ночной выгрузкой. Статус, который приезжает раз в сутки, покупателю бесполезен: он успевает позвонить раньше.
  • Статусы «отменён» и «частично отгружен» проектируются отдельно и заранее. Они редкие, поэтому их обычно забывают, и именно на них потом приходятся самые тяжёлые обращения в поддержку.
  • Изменение статуса руками в админке сайта либо запрещено, либо ограничено списком состояний, которых нет в учёте. Иначе обмен будет затирать правки менеджера, а менеджер — терять доверие к системе.

Очередь и повторы: что происходит, пока учёт недоступен

Учётная система бывает недоступна регулярно и по нормальным причинам: обновление конфигурации, выгрузка отчётности, ночное обслуживание, обрыв канала. Вопрос не в том, случится ли это, а в том, что произойдёт с заказом, который оформили именно в эту минуту. Правильный ответ — ничего страшного: заказ уже записан на вашей стороне и ждёт в очереди.

  1. 1
    Шаг 1. Сначала записать у себя

    Заказ сохраняется в базе сайта или в промежуточном хранилище до всякой попытки передать его дальше. Это главное архитектурное решение всего контура: система, недоступная в момент оформления, не должна приводить к потере заказа ни при каких обстоятельствах.

  2. 2
    Шаг 2. Поставить в очередь на передачу

    Передача — отдельная задача со своим состоянием: «ожидает», «отправляется», «доставлено», «ошибка». Пока задача не перешла в «доставлено», заказ считается непереданным, и это видно в интерфейсе, а не только в логах.

  3. 3
    Шаг 3. Повторять с нарастающей паузой

    Первый повтор через минуту, второй через пять, третий через пятнадцать и так далее. Повторы без пауз добивают систему, которая и так на обслуживании, и превращают короткую недоступность в долгую.

  4. 4
    Шаг 4. Сдаться заметно

    После нескольких неудачных попыток задача помечается как требующая внимания, и уходит алерт живому человеку. Тихое исчезновение заказа из очереди — самый дорогой сценарий: заказ не потерян технически, но о нём никто не знает.

  5. 5
    Шаг 5. Уметь отправить повторно вручную

    Кнопка «отправить в учёт ещё раз» рядом с заказом. Она нужна не для регулярной работы, а для того, чтобы разбор инцидента занимал минуты, а не звонок подрядчику. Работать она обязана безопасно — за это отвечает защита от повторной обработки из следующего раздела.

схема процессаzakazy-i-statusy-mezhdu-saytom-i-uchetom--02
Схема очереди передачи заказа: запись у себя, повторы с нарастающей паузой, алерт при отказе

Схема слева направо: «Покупатель оформил» → «Запись в своей базе» (блок выделен как обязательный) → «Очередь передачи» с четырьмя состояниями «ожидает / отправляется / доставлено / ошибка» → «Учётная система». От блока очереди вниз ветка повторов с подписями «1 минута», «5 минут», «15 минут» и далее блок «алерт человеку». Сбоку кнопка-блок «отправить повторно вручную» со стрелкой в очередь. Чертёжная манера, подписи по-русски.

Заказ сначала записывается у вас и только потом уходит дальше — это главное решение контура

Защита от повторов: внешний номер, а не состав

Дубль возникает не из-за плохого кода, а из-за физики связи. Сайт отправил заказ, учётная система его создала, и в этот момент оборвался канал — ответ не дошёл. Сайт не знает, дошёл заказ или нет, и по правилам надёжности повторяет отправку. Учёт создаёт второй документ. Оба документа корректны, оба пойдут в отгрузку.

Правильное лечение — внешний номер: сайт присваивает заказу собственный неизменяемый идентификатор и передаёт его вместе с заказом, а учётная система перед созданием документа проверяет, нет ли уже документа с таким внешним номером. Есть — возвращает существующий, а не создаёт новый. Это делает повторную отправку безопасной, и именно поэтому кнопка «отправить ещё раз» из предыдущего раздела не превращается в генератор дублей.

Сравнивать по составу заказа нельзя

Соблазн сравнить «клиент, сумма, состав, дата» и считать совпадение дублем понятен, но он ломает нормальную работу: постоянный покупатель, заказывающий один и тот же товар два раза за день, получит отказ во втором заказе. Единственный корректный признак дубля — совпадение внешнего номера, потому что он присвоен один раз и не меняется. Подробный разбор источников задвоений и процедуру разбора уже возникших дублей мы вынесли в отдельную статью.

Сопоставление номенклатуры: артикул как ключ

Заказ доехал, документ создался, но в нём не тот товар или пустая строка. Причина почти всегда одна: сопоставление позиций шло по названию. Названия меняют постоянно и без всякого злого умысла — маркетолог добавил в наименование цвет, контент-редактор убрал лишнее слово, менеджер поправил опечатку. Для человека это тот же товар, для обмена — новый.

  • Ключ сопоставления — артикул или внутренний код номенклатуры, и он не меняется никогда. Название, штрихкод и цена меняться могут; ключ — нет. Если артикулы у вас исторически задвоены, это чинится до интеграции, а не во время неё.
  • Товар с характеристиками — отдельная сложность. Ключом становится пара «артикул позиции плюс характеристика», иначе футболка размера M приедет в документ как футболка вообще, и склад соберёт наугад.
  • Позиция, которую не удалось сопоставить, не молчит. Она попадает в отчёт несопоставленных с указанием заказа и строки, а заказ помечается как требующий внимания — но не отбрасывается.
  • Отчёт несопоставленных смотрит человек со стороны магазина, а не подрядчик. Обычно там пять-десять строк в месяц, и разбираются они за пятнадцать минут; без ответственного он превращается в свалку через две недели.
сравнениеzakazy-i-statusy-mezhdu-saytom-i-uchetom--03
Сравнение сопоставления по названию и по артикулу при переименовании товара

Сравнение в две колонки на одном примере. Слева «Ключ — название»: строка заказа «Футболка синяя хлопок» не находит карточку «Футболка хлопковая, синяя», создаётся вторая карточка с остатком 0, заказ приходит на позицию, которой нет в продаже. Справа «Ключ — артикул»: строка заказа с артикулом FT-1042 находит ту же карточку независимо от названия. Внизу отдельная плашка «Товар с характеристиками: ключ — артикул + характеристика». Чертёжная манера, подписи по-русски.

Название меняют раз в квартал, артикул — никогда. Ключом должен быть артикул

Оплаты: почему заказ висит неоплаченным при успешном платеже

Покупатель заплатил, деньги списались, банк прислал ему уведомление — а в магазине заказ по-прежнему в статусе «ожидает оплаты», и склад его не собирает. Механика этой ситуации всегда одна и та же и не зависит от платёжного сервиса.

  1. 1Покупатель уходит на страницу оплаты платёжного сервиса и там платит. Ваш сайт в этот момент в процессе не участвует — он только ждёт.
  2. 2После списания платёжный сервис отправляет на ваш сайт служебное уведомление об успешной оплате. Это отдельный запрос от сервиса к вам, и именно он меняет статус заказа.
  3. 3Возврат покупателя на сайт после оплаты — это не подтверждение платежа. Покупатель мог закрыть вкладку, потерять связь или уйти по кнопке «назад»; на статус заказа это влиять не должно.
  4. 4Если служебное уведомление не дошло — упал ваш сервер, сработала блокировка на стороне защиты сайта, случился обрыв, — заказ остаётся неоплаченным при списанных деньгах. Платёжные сервисы обычно повторяют уведомление несколько раз, но полагаться только на это нельзя.
  5. 5Поэтому нужен второй контур: регламентная сверка неоплаченных заказов старше 15–30 минут напрямую через запрос статуса платежа в сервисе. Она ловит все уведомления, которые не дошли, и стоит нескольких часов работы.

И отдельное правило безопасности, которое стоит проверить на приёмке: сумма и валюта платежа сверяются с суммой заказа до перевода его в оплаченные, а само уведомление проверяется на подлинность подписью от платёжного сервиса. Заказ, который переводится в оплаченные по факту получения любого запроса на нужный адрес, — это не интеграция, а открытая дверь.

Суточная сверка: создано N — доехало N

Всё описанное выше работает, только если кто-то ежедневно смотрит одну цифру: сколько заказов создано на сайте за сутки и сколько документов появилось в учёте. Расхождение — это либо потеря, либо дубль, и разбирается оно в тот же день, а не через неделю по звонку покупателя.

ПоказательГде смотримНормаЧто означает отклонение
Создано заказов на сайте за суткиБаза сайтаБазовая цифра для сравнения
Создано документов в учёте за суткиУчётная система, отбор по внешнему номеруСовпадает с первой цифройМеньше — потеря, больше — дубли
Задач в очереди со статусом «ошибка»Интерфейс очереди передачи0Учёт был недоступен или отклонил заказ по содержанию
Строк в отчёте несопоставленных позицийОтчёт обменаЕдиницы в месяцПереименование товара или расхождение артикулов
Заказов «ожидает оплаты» старше 30 минут при успешном платежеСверка с платёжным сервисом0Не дошло служебное уведомление об оплате

Теперь цена вопроса. Модельный магазин: 900 заказов в месяц, средний чек 6 200 ₽, валовая маржа 24 % — 1 488 ₽ с заказа, ставка сотрудника 700 ₽ в час. Обмен настроен «в лоб»: без очереди повторов, без защиты от дублей и без сверки.

Что стоит месяц без очереди, защиты от дублей и сверки
Не доехало в учёт: 2 % от 900 заказов18 заказов
Из них потеряны совсем — 9 заказов × 1 488 ₽ маржи13 392 ₽
Найдены с опозданием: 9 заказов × 30 мин разбора × 700 ₽/час3 150 ₽
Дубли: 1,2 % от 900 = 11 заказов × 20 мин разбора × 700 ₽/час2 567 ₽
Два дубля дошли до отгрузки: обратная логистика 450 ₽ × 2900 ₽
Обращения «где мой заказ» из-за зависших статусов: 8 % от 900 = 72 × 6 мин × 700 ₽/час5 040 ₽
Итого25 049 ₽ в месяц — и большая часть этой суммы никогда не попадает ни в один отчёт

Лечится это пятью работами, и все они делаются на уже существующем обмене — переписывать его не нужно.

Смета: контур заказов, который не теряет
Внешний номер и защита от повторной обработки, 10 ч × 3 000 ₽30 000 ₽
Очередь передачи, повторы с нарастающей паузой, ручная переотправка, 12 ч36 000 ₽
Возврат статусов на сайт по событию и уведомление покупателю, 14 ч42 000 ₽
Сопоставление по артикулу и отчёт несопоставленных позиций, 8 ч24 000 ₽
Суточная сверка «создано — доехало» и алерты, 6 ч18 000 ₽
Итого150 000 ₽ разово. Окупаемость: 150 000 ÷ 25 049 = 6 месяцев
графикzakazy-i-statusy-mezhdu-saytom-i-uchetom--04
Диаграмма потерь за месяц: 25 049 рублей по пяти причинам и смета на 150 000 рублей

Столбиковая диаграмма из пяти частей с подписями в рублях за месяц: «Потерянная маржа 9 заказов — 13 392», «Обращения «где мой заказ» — 5 040», «Разбор опоздавших заказов — 3 150», «Разбор дублей — 2 567», «Обратная логистика — 900». Итог справа «25 049 ₽ в месяц». Ниже горизонтальная плашка «Смета устранения — 150 000 ₽, окупаемость 6 месяцев». Ось подписана в рублях, все значения проставлены. Чертёжная манера, подписи по-русски.

Две трети потерь — это маржа заказов, которые просто не доехали до учёта

Ответственный за сверку должен быть со стороны магазина, а не подрядчика. Подрядчик видит техническую сторону: очередь пуста, ошибок нет. Расхождение на два заказа означает, что двум конкретным покупателям надо позвонить сегодня, и это решение принимает тот, кто отвечает за магазин. В договоре на поддержку эта роль описывается отдельно — вместе со сроком реакции на алерт; что должно быть в такой поддержке и чем она отличается от абонентской платы, разобрано на нашей странице о поддержке. Заказы с маркетплейсов при этом сверяются отдельным потоком: там внешним номером служит идентификатор отправления, а не номер заказа сайта, и контур площадок мы разбирали в отдельной статье.

Когда всё это делать не надо

Есть три ситуации, в которых полный контур заказов не окупается, и признать это честнее, чем продать проект.

  • Меньше 90–120 заказов в месяц. Потери составят один-два заказа, то есть 1 500–3 000 ₽, против 150 000 ₽ вложений. Рабочий вариант — суточная сверка вручную по двум цифрам и письменный регламент, кто её делает и что происходит в его отпуск. Это пятнадцать минут в день и ноль рублей.
  • Заказ и так подтверждается менеджером звонком. Если каждый заказ перед сборкой проходит через живого человека, потеря обнаруживается в тот же день сама собой. Здесь дешевле автоматизировать не передачу, а подготовку звонка — подсказку менеджеру и заполнение карточки.
  • Учётная система пока не готова принимать документы автоматически. Если конфигурация в активной доработке или в ней нет заказа клиента как документа, контур передачи придётся переделывать через два месяца вместе с доработкой. Правильный порядок — сначала торговый контур в учёте, потом обмен.

И один вывод, который важнее всех расчётов. Контур заказов проектируется от предположения, что каждая система в цепочке рано или поздно будет недоступна, и в этот момент заказ не должен исчезнуть. Всё остальное — очередь, повторы, внешний номер, сверка — это лишь способы выполнить одно требование: заказ, за который покупатель уже заплатил, обязан быть найден и обработан, даже если в момент оформления половина систем лежала.

Заказ, за который уже заплатили, не имеет права зависеть от того, была ли доступна учётная система в ту минуту, когда его оформили.