Задвоенный заказ появляется так. Обмен отправил в учётную систему заказ, та его создала, начала формировать ответ — и в этот момент связь оборвалась. Отправитель ответа не получил и теперь не знает, что произошло: заказ не доехал вовсе или доехал и был создан. Оба варианта одинаково правдоподобны, и отличить их изнутри невозможно.
Дальше отправитель обязан повторить попытку — именно обязан. Если он не повторит, то в половине случаев заказ будет потерян навсегда, и это хуже дубля. Он повторяет, учётная система получает второй такой же запрос и, не имея способа понять, что это тот же самый заказ, создаёт второй документ. Дубль родился не из ошибки, а из единственно правильного поведения при сбое.
Значит, чинить надо не повтор, а способность получателя узнавать повторы. Механизм называется идемпотентностью и стоит денег: 40 000–55 000 ₽, если заложить его в обмен сразу, и 58 000–90 000 ₽, если встраивать в уже работающий. Ниже — механика без жаргона, четыре источника дублей, расчёт того, во что они обходятся, три шага приёмки, которые вы проводите сами, и порядок склейки того, что уже накопилось.
Где именно рвётся связь
Важно понимать, что обрыв в опасном месте — это не редкость и не признак плохого канала. Между «запрос ушёл» и «ответ пришёл» проходит от долей секунды до нескольких минут, и всё это время окно уязвимости открыто. Учётная система может уйти на перезагрузку сразу после записи документа. Сеть может моргнуть. Ваш приёмник может быть перезапущен деплоем. Чем дольше принимающая сторона обрабатывает запрос, тем шире окно: при обработке в две минуты вероятность попасть в него на порядок выше, чем при обработке в две секунды.
Схема из трёх горизонтальных полос времени. Верхняя подписана «Отправитель (приёмник обмена)», нижняя — «Получатель (1С)», между ними стрелки. Первая стрелка вниз подписана «создать заказ A-10482: строки, количество, цена, контрагент, склад». В полосе получателя блок «Документ №1 создан, резерв поставлен». Обратная стрелка вверх нарисована пунктиром и оборвана посередине с зигзагом и подписью «ответ не дошёл — окно уязвимости». Вторая стрелка вниз с той же подписью помечена «повтор через 5 секунд». В полосе получателя второй блок «Документ №2 создан, резерв поставлен ещё раз», выделенный контрастно. Справа врезка: «отправитель не может отличить „не доехало“ от „доехало, но ответ потерян“». Чертёжный стиль, подписи по-русски.
Свойство операции, при котором повторное выполнение того же самого не меняет результат. Отправили заказ пять раз — документ создан один. Технически это делается так: получатель запоминает признак уже выполненной операции и на повтор отвечает не отказом, а тем же результатом, что и в первый раз, — «заказ создан, вот его номер». Отправитель при этом ничего не подозревает и спокойно закрывает свою часть работы.
Ключ операции: что это и кто его формирует
Ключ операции — короткая строка, которая едет вместе с заказом и отвечает на единственный вопрос: «это та же самая операция или новая?». Формирует её отправитель в момент первой отправки и потом подставляет во все повторы без изменений. Получатель хранит список уже виденных ключей — обычно 30–90 дней — и, встретив знакомый, возвращает результат первой обработки вместо создания второго документа.
Главная ошибка на этом месте — взять в качестве ключа что-нибудь уже существующее, потому что «зачем плодить сущности». Иногда это работает, чаще ломается через полгода в самый неудобный момент. Ниже — разбор кандидатов.
| Что берут за ключ | Годится | Почему |
|---|---|---|
| Номер заказа на сайте | Условно | Работает, пока номера присваивает одна система и заказ нельзя переоформить. Ломается, когда добавляется второй источник заказов или менеджер создаёт заказ вручную с тем же номером |
| Телефон клиента плюс сумма заказа | Нет | Два одинаковых заказа одного клиента в один день — обычное дело в опте и в доставке еды. Такой ключ будет глотать законные вторые заказы |
| Дата и время отправки | Нет | У повтора время другое, значит, и ключ другой. Такой ключ не защищает вообще ни от чего, но выглядит в смете убедительно |
| Внутренний идентификатор записи у отправителя | Да | Уникален, не меняется при редактировании заказа и не зависит от того, как считаются номера. Рабочий вариант, если отправитель один |
| Отдельный ключ операции, сформированный при первой отправке | Да, лучший вариант | Не связан ни с чем в бизнес-данных, живёт ровно столько, сколько нужно, и одинаково работает при любом числе источников и при повторной отправке отредактированного заказа |
Сравнение в две дорожки с одинаковым началом. Обе начинаются с одинакового блока «повтор отправки заказа A-10482 после обрыва». Верхняя дорожка подписана «Без ключа операции»: получатель видит новый запрос, создаёт «Документ №2», внизу итог «два заказа, два резерва, две отгрузки». Нижняя дорожка подписана «С ключом операции»: получатель видит знакомый ключ в списке за последние 90 дней, ничего не создаёт, отвечает «уже создано, документ №1», внизу итог «один заказ, один резерв». Сбоку врезка со списком ключей: три строки вида «ключ — номер документа — дата». Чертёжный стиль, подписи по-русски.
Четыре источника дублей
Обрыв связи — самый известный источник, но не единственный. Если закрыть только его, дубли станут реже, но не исчезнут, и это самая частая причина разочарования после доработки: «мы же заплатили за защиту».
- 1Повтор при обрыве связи — 60–70% дублей
Разобран выше. Лечится ключом операции на стороне получателя. Важная деталь: ключ должен проверяться до создания документа и в той же транзакции, иначе два одновременных повтора успеют проскочить оба.
- 2Двойное нажатие человеком
Менеджер нажал «отправить в учёт», ничего видимого не произошло за две секунды, нажал ещё раз. Формально это две разные операции, и ключ, сгенерированный на каждое нажатие заново, их не склеит. Лечится тем, что ключ привязывается к записи заказа, а не к нажатию кнопки, плюс блокировкой кнопки на время отправки.
- 3Повторная выгрузка периода
Классика: обмен встал на два дня, его починили и запустили выгрузку «за прошлую неделю, чтобы наверняка». Всё, что успело доехать раньше, создаётся заново. Лечится тем же списком ключей, но срок его хранения должен покрывать типичную глубину ручных перезаливок — отсюда требование хранить ключи 30–90 дней, а не сутки.
- 4Два обмена, работающих одновременно
Самый обидный вариант: подрядчик сделал новый обмен по событиям, а старая выгрузка по расписанию осталась включённой, потому что её никто не выключил и она была не в его зоне ответственности. Обе честно возят одни и те же заказы. Лечится не кодом, а списком действующих обменов, который кто-то в компании ведёт.
Как отличить дубль от законного повторного заказа
Прежде чем что-то чинить, стоит убедиться, что вы смотрите на дубли, а не на нормальную работу. Два одинаковых заказа одного клиента в один день — обычная ситуация в опте, в доставке и в рознице с самовывозом: клиент вспомнил, что забыл позицию, и оформил ещё раз. Автоматическая склейка «по клиенту и сумме за сутки» такие заказы съедает, и обходится это дороже самих дублей, потому что второй заказ просто не отгружают.
Настоящий дубль опознаётся по трём признакам сразу, а не по одному. Первый: разница во времени создания укладывается в интервал повторов — секунды или единицы минут, а не часы. Второй: состав совпадает построчно, включая количества и цены, а не только итоговую сумму. Третий: у второго документа нет собственной истории — его никто не открывал, не редактировал, к нему не привязана переписка или звонок. Законный второй заказ почти всегда нарушает хотя бы один из трёх признаков.
Практическое следствие простое: правило поиска дублей — не техническая настройка, а согласованный документ. Его формулирует подрядчик, а утверждает коммерческий отдел, потому что именно он потом объясняется с клиентом, чей второй заказ склеили. Полстраницы текста, десять минут обсуждения — и на выходе ясный критерий, по которому можно и разбирать накопившееся, и настраивать автоматику.
Сколько дубли стоят в месяц
Посчитаем на модельной оптовой компании: 900 заказов в месяц, средний чек 34 000 ₽, маржа 20%, ставка сотрудника с налогами 1 100 ₽ в час. Доля дублей в обмене без защиты по нашим наблюдениям укладывается в 0,8–1,5%; берём 1,2%.
Встроить защиту в уже работающий обмен — ключ операции, хранение списка ключей, проверка до создания документа, сценарии приёмки — стоит в модели 58 000 ₽. Окупается за 58 000 / 22 520 = 2,58 месяца, то есть на третьем. Это одна из самых быстро окупающихся доработок в интеграциях вообще: она не добавляет функций, она убирает регулярную работу, которую сейчас делают люди.
Столбчатая диаграмма с тремя столбцами по стоимости в рублях в месяц. Первый столбец «Замечены до отгрузки, 8 штук» — 6 600 ₽. Второй «Отгружены и вернулись, 3 штуки» — 13 650 ₽. Третий «Отказ клиента, 1 раз в квартал» — 2 270 ₽. Над диаграммой итог «22 520 ₽ в месяц, 270 240 ₽ в год». Справа отдельной горизонтальной линией отмечено «стоимость защиты 58 000 ₽ разово» с подписью «окупается на третьем месяце». Слева подпись исходных данных: «900 заказов в месяц, доля дублей 1,2%». Оси и подписи по-русски.
Приёмка: три шага, которые вы делаете сами
Проверить защиту от дублей может любой сотрудник за полчаса, без разработчика и без доступа к серверу. Эти три сценария стоит включить в приёмку до оплаты — и повторить их через месяц эксплуатации, потому что после доработок обмена защита иногда перестаёт работать незаметно.
- 1Отправьте один и тот же заказ в учёт дважды подряд. Правильный результат: второй документ не появился, в журнале обменов есть запись вида «ключ уже обработан, возвращён документ №такой-то». Если второй документ появился — защиты нет, что бы ни говорили на словах.
- 2Попросите выключить принимающую систему на 10–15 минут, оформите за это время три заказа, включите обратно. Правильный результат: приехало ровно три документа. Ноль означает, что нет очереди, шесть — что нет ключа операции.
- 3Запустите повторную выгрузку за вчерашний день. Правильный результат: новых документов не появилось, существующие могли обновиться. Появление вторых копий вчерашних заказов означает, что срок хранения ключей меньше суток и от ручных перезаливок вы не защищены.
Первый и третий сценарии по замыслу создают документы, и если защита не работает, они создадут их по-настоящему — с резервами и движениями. Поэтому приёмочные сценарии прогоняют на копии базы, а на боевой повторяют только после успешного прохождения на копии. Отсутствие тестового контура — само по себе повод не начинать проверку.
Что делать с уже возникшими дублями
Если дубли уже накопились, порядок разбора имеет значение: неправильная последовательность легко превращает 11 дублей в 11 потерянных оплат. Ключевое правило — дубли не удаляют, их закрывают.
- 1Шаг 1. Найти пары по составу, а не по сумме
Совпадение клиента, даты и суммы недостаточно: в опте два одинаковых заказа в один день — законная ситуация. Сравнивать надо построчно состав плюс время создания: настоящие дубли обычно отличаются на секунды или на время одного повтора.
- 2Шаг 2. Определить оригинал по времени создания
Оригинал — тот, что создан первым, а не тот, у которого номер красивее. Именно к первому обычно уже привязаны движения, и переносить проще к нему. Если к обоим что-то привязано, оригиналом назначается тот, у которого движений больше.
- 3Шаг 3. Перенести на оригинал всё, что успело прицепиться
Оплаты, отгрузки, документы, переписку, задачи менеджера. Это единственный ручной шаг, который нельзя автоматизировать целиком: часть привязок видна только человеку. Делать его до закрытия дубля, а не после.
- 4Шаг 4. Закрыть дубль служебным статусом, не удаляя
Отдельный статус вида «дубль, склеен с №такой-то» и снятые резервы. Документ остаётся в базе и в отчётности, но перестаёт участвовать в работе. Так сохраняется история и возможность разобраться, если через месяц выяснится, что склеили не то.
- 5Шаг 5. Записать факт склейки
Что склеено, когда, кем и по какому признаку. Через квартал этот список — единственный способ понять, стало ли дублей меньше после доработки, и посчитать её эффект честно.
Схема из пяти блоков со стрелками слева направо: «Найти пары по составу и времени», «Определить оригинал по времени создания», «Перенести оплаты, отгрузки, документы, переписку», «Закрыть дубль статусом „склеен с №…“, снять резерв», «Записать факт склейки в журнал». Под третьим блоком отвод к иконке человека с подписью «единственный ручной шаг». Под четвёртым блоком перечёркнутая красным врезка «удалить документ» с подписью «нельзя: движения и оплаты уже прошли». Справа итоговая рамка: «11 дублей в месяц, 22 520 ₽». Чертёжный стиль, подписи по-русски.
В учётных системах есть штатные механизмы поиска и удаления дублей справочников, и их регулярно применяют к документам. Если по документу прошли оплата, отгрузка или он попал в закрытый период, удаление разъезжает остатки, взаиморасчёты и отчётность, а восстанавливать это придётся из резервной копии. Документы с движениями всегда закрываются статусом, а не удаляются.
Когда защиту от дублей можно не покупать
Ключ операции нужен не везде, и есть три ситуации, в которых доработка не окупится. Общее у них одно: либо повтор безвреден по своей природе, либо цена разбора ниже цены защиты.
- Обмен только читает. Выгрузка остатков на сайт, загрузка данных в отчётность, обновление каталога — повтор здесь просто перезаписывает то же самое значение тем же самым. Такие операции идемпотентны сами по себе, и платить за защиту не нужно.
- Обмен обновляет по внешнему ключу, а не создаёт. Если правило звучит как «найти документ с таким идентификатором, а если нет — создать», защита уже встроена в саму логику. Проверить это можно вторым сценарием приёмки за десять минут.
- Меньше 100 операций в месяц и дубли единичны. При доле 1,2% это один дубль в месяц и около 2 000 ₽ потерь — доработка за 58 000 ₽ окупалась бы больше двух лет. Здесь дешевле раз в неделю просматривать список заказов глазами; правда, только до тех пор, пока объём не вырос.
Во всех остальных случаях защиту стоит закладывать сразу, при первой сборке обмена: тогда она стоит 40 000–55 000 ₽ в составе строки «повторные попытки» и не требует отдельного проекта. Разница между «заложить сразу» и «встроить потом» — примерно полторы цены и один разбор накопившихся дублей, которого можно было не делать. Как эта строка выглядит в общей смете на интеграцию и что ещё в ней должно быть, мы разбираем в материале про надёжную интеграцию.
