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

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

Откуда берутся расхождения

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

  • Синхронизация работает с заданным интервалом. Маркетплейс принял заказ, а следующий обмен с сайтом ещё не начался. В этот промежуток старое число выглядит актуальным, хотя товар уже продан.
  • Резерв не равен физическому остатку. Товар лежит на полке, но уже есть в незавершённом заказе. Если канал видит только складское количество, он предлагает покупателю то, что фактически нельзя продавать.
  • Возвраты запаздывают. Посылку приняли обратно, но товар ещё не проверили или не вернули в доступный остаток. Другая крайность: возврат внесли на складе, но сайт о нём не узнал.
  • Ручная корректировка остаётся локальной. Кладовщик исправил пересорт, списал повреждённую пару или нашёл товар, но изменение осталось только в складской программе.
  • Офлайн-продажа не доходит до каталога. Последнюю единицу купили в физической точке, касса закрыла продажу, а онлайн-каналы продолжили показывать наличие.
  • Один товар выставлен в нескольких местах. Сайт, Rozetka и Prom.ua одновременно видят одну и ту же физическую единицу. Два заказа приходят раньше, чем любой канал получает новый остаток.
  • Поставщик живёт по собственному расписанию. Его CSV или XML-фид обновил количество в момент, не связанный с вашими продажами, резервами и возвратами. Свежий файл поставщика может перезаписать более новое состояние вашего склада.

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

Расхождение иногда маскируется само. Один канал ещё не списал продажу, другой уже добавил непроверенный возврат, и итоговые числа случайно совпадают. Ручная проверка видит одинаковое количество и заканчивается, хотя происхождение остатка уже разное. Следующее событие снова открывает проблему. Именно поэтому рабочая система сравнивает не только число в карточке товара, но и то, из каких подтверждённых операций оно сложилось. Для менеджера результат должен быть простым: единица свободна, зарезервирована, ожидает проверки после возврата или недоступна.

Когда готовый коннектор некорректно синхронизирует остатки

Проектируем синхронизацию остатков как часть магазина. Разработка стоит от $2500. В кейсе Safari Zbroia каталог интернет-магазина синхронизирован с 1С.

Оценить мой магазин

Три способа синхронизировать остатки

Ручной экспорт и импорт CSV/XML

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

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

Готовые коннекторы

Коннектор можно быстро включить и настроить без отдельного проекта интеграции. Для типового каталога он передаёт остатки через доступный XML-фид или API-обмен с сайтом, Rozetka или Prom.ua. Это практичный выбор, если правила магазина совпадают с тем, что уже заложено поставщиком коннектора.

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

Собственная интеграция

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

Собственный обмен особенно уместен, когда склад уже работает в 1С/BAS, WMS или отдельной учётной системе. Сначала здесь составляют карту ответственности за данные. Тот же принцип подробно объяснён в статье об интеграции 1С/BAS с CRM: для каждой сущности нужно знать, где она создаётся и кто имеет право её изменять.

Как устроена рабочая синхронизация

Одна система владеет остатком

Единый источник правды означает, что итоговое количество меняет одна система. Обычно это складской или учётный контур. Сайт и маркетплейсы не спорят с ним, а показывают рассчитанную доступность. Если оперативный остаток уже ведётся в WMS-системе, именно она может выполнять эту роль.

Сначала нужно договориться, что именно передавать. Физическое количество не подходит для прямой продажи. Из него вычитают активные резервы и при необходимости страховой буфер. Возврат добавляется только после того, как склад подтвердил, что товар снова можно продавать.

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

Резерв создаётся вместе с заказом

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

Передаются изменения, а не весь каталог

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

Масштаб каталога хорошо виден в кейсе интернет-магазина обуви Airstep: 6700+ SKU, автоматический XML-импорт от 4 поставщиков, Django 4.2, PostgreSQL, Meilisearch и собственное оформление заказа. Когда источников несколько, важно не позволить очередному фиду безусловно перезаписать резервы и локальные складские изменения.

Вебхуки реагируют, опрос проверяет

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

Повторное сообщение не повторяет списание

Сеть может повторно доставить то же событие, а система после задержки может не знать, прошла ли первая попытка. Идемпотентность здесь означает простое правило: одна и та же операция с тем же идентификатором меняет остаток только один раз. Без этого повтор заказа будет выглядеть как новая продажа.

Очередь переживает недоступность канала

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

Журнал показывает, какой канал ошибается

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

Что делать с последней единицей товара

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

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

Сколько это стоит и сколько длится

Отдельной честной цены «за синхронизацию» без схемы каналов нет. Узкий объём может означать обмен между готовым складом и одним сайтом. Более широкий охватывает маркетплейсы, офлайн-кассу, поставщиков, резервы и возвраты. Самый большой вариант включает создание системы, которая станет источником остатков.

Реальные стартовые цены Artbrain такие: WMS от $2500, интернет-магазин от $2500, CRM от $3000. Модуль обмена оценивается отдельно после описания потоков данных. Срок также зависит от количества каналов, качества артикулов и каталогов, правил резерва и возврата, доступности обмена в каждой системе и объёма тестирования. Называть календарный диапазон до этой проверки было бы догадкой.

Типичные ошибки

  • Разрешить всем системам менять остаток. После первого конфликта уже непонятно, какое число правильное и чьё изменение было последним.
  • Передавать физическое количество без резервов. Товар есть на полке, но уже обещан другому покупателю.
  • Полагаться только на полный импорт. Большой файл не решает проблему событий между двумя загрузками.
  • Резервировать при отгрузке. До этого момента сайт и маркетплейсы продолжают продавать ту же позицию.
  • Не защищаться от повторов. Повторно доставленный заказ второй раз вычитает количество, хотя новой продажи не было.
  • Молча пропускать ошибки API. Без очереди, повторных попыток и уведомления оператор узнаёт о сбое от покупателя.
  • Запускать без реальных сценариев. Нужно проверить отмену, возврат, офлайн-продажу, последнюю единицу, повтор события и временно недоступный канал.

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

Когда синхронизация не нужна

Собственная интеграция не нужна магазину с небольшим каталогом, одним каналом и редкими изменениями. Ручной CSV/XML или обычная сверка могут быть дешевле и понятнее. Нет смысла строить очередь и журналы, если один человек без напряжения контролирует всё движение товара.

Не стоит спешить и тогда, когда сам складской процесс ещё меняется. Сначала определите, кто создаёт резерв, когда возврат снова становится доступным и где фиксируется офлайн-продажа. Автоматизация нужна после появления повторяющегося правила, а не вместо него.

Для разговора о задаче достаточно подготовить список каналов, назвать систему, где сейчас ведётся склад, и показать путь одного заказа от оформления до отмены или отгрузки. По этой карте уже видно, хватит ли файла или готового коннектора, либо нужен собственный обмен. Мы можем спокойно разобрать этот процесс и определить объём без перестройки того, что уже работает.

Частые вопросы

Почему остатки на сайте и маркетплейсе не совпадают?

Разногласия возникают, когда каждый канал сохраняет свое количество, а обновление задерживается, отклоняется или привязывается к неправильному SKU или варианту. Бронирование, отмена, возврат и ручные изменения также могут учитываться на разных этапах. Требуется один источник правды для остатка и журнал обмена с повторной отправкой событий, завершившихся ошибкой.

Как часто нужно синхронизировать остатки между магазином и складом?

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

Хватит ли готового коннектора для синхронизации остатков?

Готового коннектора обычно достаточно, если системы имеют стабильные API, а бизнес использует стандартные правила для товаров, вариантов и складов. Кастомная интеграция необходима для нескольких складов, комплектов, резервов, офлайн-продаж, нестандартного сопоставления SKU или отдельных ограничений каналов. Решения следует принимать после проверки API и процессов, а не только по списку функций коннектора.

Как не продать последнюю единицу товара сразу на нескольких площадках?

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

Сколько стоит интеграция синхронизации остатков?

Цена зависит от объема работ, интеграции и сроков. Точную оценку готовим после бесплатного разбора задачи.

Anton Kunashenko, CEO & Lead Developer
CEO и ведущий разработчик Artbrain

Anton Kunashenko

Основатель Artbrain с 2018 года. Разрабатывает цифровые продукты для бизнеса: от лендингов до enterprise-систем.