«Остатки должны быть в реальном времени» — строка, которая попадает в требования к интернет-магазину раньше всех остальных и почти никогда не расшифровывается. Под ней каждый участник встречи понимает своё: ИТ-служба — частоту обмена с 1С, коммерческий директор — отсутствие отмен, маркетолог — чтобы в рекламе не было товара, которого нет.
Разберём, что происходит с остатком на пути из учётной системы на сайт и в приложение, в какой момент товар перестаёт быть доступным другим покупателям, что показать человеку, когда данные всё-таки разошлись, и как считается остаток, когда точек продаж несколько. Про сами способы обмена — файл, прямой запрос, очередь событий, промежуточный слой — написано в отдельной статье, ссылка в конце; здесь речь не о том, как данные едут, а о том, как ведёт себя число, которое приехало.
Между тем, как вещь физически покинула полку, и тем, как это увидел покупатель на сайте, стоит цепочка, и обмен с 1С — только одно её звено. Сначала продажу нужно провести на кассе. Потом документ должен дойти до учётной системы — в рознице с несколькими точками это нередко отдельный обмен со своим расписанием. Потом измениться должен остаток в самой 1С. Потом сработать обмен с сайтом. Потом обновиться то, что сайт держит у себя для скорости. И только потом страница должна обновиться у человека, который держит её открытой уже десять минут.
Практический вывод один: сокращать имеет смысл самое длинное звено, а не то, которое проще сократить. Если продажи из бутиков попадают в 1С пакетом раз в несколько часов, обмен сайта с 1С хоть ежеминутный ничего не даст — витрина будет аккуратно показывать то же опоздание, которое есть внутри компании. Это первое, что мы просим измерить до оценки: не «как часто вы выгружаете», а «сколько проходит от продажи в точке до изменения числа в учёте».
Второе звено, о котором забывают, — страница, уже открытая у покупателя. Человек листает каталог полчаса, и его экран показывает данные момента загрузки. Ни один обмен этого не лечит; лечится это тем, что доступность перепроверяется в момент действия — при добавлении в корзину и при оформлении.
Прежде чем договариваться о скорости, стоит договориться о предмете. Физический остаток — то, что лежит на складе и в точках по данным учёта. Доступный к продаже — то же самое минус зарезервированное, минус брак и возвратный карантин, минус витринные образцы, минус позиции, отложенные для конкретного клиента. На витрину должно уходить второе число, а выгружается обычно первое — потому что в учётной системе оно лежит ближе и называется понятнее.
Третье число — товар в пути: отгружен поставщиком, но ещё не принят. Решение, показывать ли его, коммерческое: оно увеличивает видимый ассортимент и удлиняет срок, который вы потом обязаны выдержать. Решать это нужно один раз и записать, иначе каждая следующая группа товаров будет решаться заново и по-разному.
И отдельная строка — витринный образец в торговой точке. По учёту он есть, продать его онлайн обычно нельзя или нежелательно. Если признака «витрина» в учёте не заведено, на сайт он поедет как обычная единица товара, и половина историй про «заказал последний, а его нет» — про это, а не про скорость обмена.

Главный вопрос мультиканальной торговли звучит не «как часто обновляются остатки», а «в какой момент единица товара закрепляется за покупателем». Пока ответа нет, частота обмена не имеет значения: два человека в разных каналах могут видеть одно и то же правдивое число и одновременно начать его покупать.
Разумная точка закрепления — начало оформления заказа, а не факт оплаты. Между нажатием кнопки и приходом денег проходят минуты: человек вводит данные, уходит в приложение банка, возвращается. Всё это время единица должна быть вынута из общего остатка, иначе окно уязвимости равно длительности оплаты, помноженной на число одновременных покупателей.
Закрепление обязано быть временным. У резерва есть срок жизни, и он разный для разных способов оплаты: карта — минуты, счёт юридическому лицу — дни. Слишком короткий срок теряет уже начатые заказы, слишком длинный прячет ходовые позиции от всех остальных. Это настройка, а не константа, и её стоит иметь в админке, чтобы менять без разработчика.
И важная граница: корзина — не резерв. Вещь, лежащая в корзине неделю, не должна быть заблокирована, иначе самые востребованные позиции исчезают из продажи, физически оставаясь на складе. Корзина — это намерение, резерв — обязательство.
Двойная продажа происходит в окне между моментом, когда покупатель увидел число, и моментом, когда единица закрепилась за кем-то другим. Величина окна считается на своих цифрах, и считается за один вечер — для этого не нужен подрядчик.
Возьмите позиции, у которых остаток — одна-две единицы: в премиальном сегменте и в товарах с размерной сеткой это обычно заметная часть каталога. Посмотрите, сколько заказов в час проходит в пиковый день, и какая доля приходится на эти позиции. Умножьте частоту на длительность окна — и вы получите ожидаемое число столкновений. Дальше сравните его с тем, что у вас уже происходит: число отменённых по вине магазина заказов за месяц обычно известно службе поддержки, даже если его никто не считал отдельно.
Это сравнение и есть ответ на вопрос, что чинить первым. Если расчётные столкновения объясняют большую часть отмен — чинится резерв. Если отмен заметно больше — дело не в обмене, а в том, что физический остаток в учёте не совпадает с полкой, и первым идёт инвентаризация и дисциплина ввода, а не интеграция.
Расхождения будут всегда: пересорт, потеря на кассе, возврат, который не успели провести. Поэтому вопрос не «как не допустить», а «как это выглядит для человека» — и ответов должно быть три, по числу моментов, в которые это вскрывается.
В каталоге и карточке — честный набор доступного и возможность оставить след. Если размера нет, пустое место хуже, чем явная недоступность с подпиской на возврат размера: во втором случае вы получаете контакт заинтересованного покупателя вместо ушедшего. Технически это тот же поток остатков, просто с обратной стороны.
В корзине и при оформлении — проверка в момент действия и внятное сообщение. Самый частый промах здесь не в технике, а в формулировке: «Ошибка оформления» заставляет человека написать в поддержку, а «Размер M закончился, пока вы оформляли заказ; остальные позиции в заказе сохранены» позволяет ему продолжить самому.
И после оплаты — худший случай, который всё равно случится. Здесь работает не интерфейс, а процедура: кто и за какое время связывается с покупателем, что предлагает взамен, как и когда возвращаются деньги, и видит ли менеджер такой заказ отдельным списком в админке. Этот список — такая же часть работы по обмену, как сам обмен, и в требованиях его почти никогда нет.

Пока склад один, остаток — число. Как только к нему добавляются торговые точки, это уже таблица, и почти все дорогие решения в проекте связаны именно с ней.
Первое решение — что считается доступным для онлайн-заказа. Варианты: только склад интернет-магазина; склад плюс точки с ежедневной перевозкой между ними; всё, что есть в компании. Чем шире, тем больше видимый ассортимент и тем больше отмен из-за расхождений в точках, где товар трогают руками.
Второе — самовывоз. Самый простой с виду способ доставки требует самого точного знания: не «есть ли вообще», а «есть ли в этом конкретном магазине прямо сейчас». Обещание «заберите сегодня в ТЦ» дороже любого другого, потому что покупатель за ним поедет.
В перезапуске GrandeBoutique.ru это видно прямо на витрине: сеть мультибрендовых бутиков из Уфы, свыше 35 000 товарных позиций и более тридцати интеграций, а в каталоге есть фильтр по конкретному магазину. В тексте кейса сказано, что практически по каждой позиции в ежедневном режиме идёт обмен и актуализация — изменение цены, остатков, наличия в магазинах, — и что в премиальном сегменте с ограниченным ассортиментом и мультиканальными продажами мгновенное обновление остатков критично: информация о наличии обновляется в режиме реального времени, исключая ситуацию, когда покупатель заказывает то, чего уже нет на складе. По нашим данным о проекте весь перезапуск занял менее двенадцати месяцев — с миграцией со старой платформы и всеми тридцатью с лишним обменами.
Когда к сайту добавляется мобильное приложение, остаток чаще всего ломается не в обмене с 1С, а на стыке каналов: у приложения заводят собственный кэш, собственную частоту обновления, иногда собственный справочник товаров. Снаружи это выглядит как два магазина с разными данными, и покупатель, у которого в приложении размер есть, а на сайте нет, пишет в поддержку именно об этом.
Правильная схема простая на словах и требует дисциплины в работе: источник остатка один, каналы — только представления. У нас так сделано в проекте SHI TRENDY, московского концепт-стора: приложение собрано на Flutter сразу под iOS и Android и глубоко интегрировано с административной системой сайта, а обмен каталогом и товарными остатками, как сказано в кейсе, происходит полностью в автоматическом режиме. Третьего справочника и третьей частоты обновления там не появляется.
Вопрос подрядчику формулируется соответственно: откуда приложение берёт остаток — из того же места, что и сайт, или из своей копии. Ответ «из своей, так быстрее» означает, что расхождение между каналами запрограммировано заранее.
Это общая практика рынка, а не замер по конкретному нашему клиенту. Внешние площадки отличаются от собственных каналов одним: цена ошибки там не ваша. Отмена по вине продавца на площадке бьёт по карточке и по условиям работы, и восстанавливается это дольше, чем приносит одна недополученная продажа.
Отсюда два приёма, которые применяют почти все, кто торгует и у себя, и на площадках. Первый — квота: площадке отдаётся не весь остаток, а его часть, и эта часть не трогается собственными каналами. Второй — порог: позиции с остатком в одну-две единицы на внешние витрины не отдаются вовсе. Оба приёма сознательно жертвуют частью продаж ради предсказуемости, и оба — коммерческое решение, которое принимается до разработки, потому что от него зависит устройство выгрузки.
Та же логика работает для рекламных фидов и товарных витрин поисковиков: фид обязан пересобираться вместе с остатком, иначе вы платите за переходы на отсутствующий товар. Проверяется это одним вопросом к подрядчику: от чего обновляется фид — от изменения остатка или от расписания. Второй ответ означает, что между витриной и объявлением всегда будет разрыв длиной в интервал выгрузки.
Непрерывное обновление оправдано там, где позиции малочисленны и невосполнимы: единичные вещи, ограниченные коллекции, премиальный сегмент. Там каждое столкновение — личный разговор с человеком, который ждал именно эту вещь. Если же у вас глубокий запас по каждой позиции и остаток исчисляется десятками, достаточно периодического обмена плюс резерва: такая схема дешевле в разработке и, что важнее, восстанавливается после сбоя простым повторным обменом.
Порядок действий из этого следует понятный: сначала резерв, потом частота. Ускорять обмен, не закрепляя товар за покупателем, — это уменьшать окно, не убирая его; закрепление же убирает само явление для всех каналов разом.
Чего мы не обещаем. Что отмен не станет ноль: пересорт и ошибки на кассе живут вне сайта, и никакая интеграция их не видит. Что проблему решит скорость обмена: если остаток в учёте не совпадает с полкой, витрина будет быстро показывать неверное число. И что срок можно назвать до доступов — пока нет тестового контура учётной системы и живой выгрузки, любая оценка обмена остатками остаётся предположением, включая нашу.
Пришлите пять чисел из списка выше: задержку от продажи в точке до учёта, долю позиций с остатком в одну-две единицы, пик заказов в час, число отмен «товара не оказалось» за месяц и количество точек, с которых отгружают онлайн-заказы. По ним мы посчитаем ваше окно уязвимости и скажем, что в вашем случае даёт больший эффект — резерв, разрез остатка по складам или дисциплина ввода в рознице. Нередко третье, и это самый дешёвый из трёх ответов.
А если у вас уже есть техническое задание на магазин — пришлите из него страницу про остатки и резерв. Разберём, какие решения в нём не приняты: что считается доступным к продаже, когда возникает и когда снимается закрепление, что видит покупатель в каждом из трёх моментов расхождения и кто отвечает за заказы, оплаченные на отсутствующий товар.
Посмотрим ваш сайт, скажем, что мешает ему приводить клиентов, и какие каналы дадут результат в вашей практике. Без обязательств, отвечаем в течение рабочего дня.