Когда в WooCommerce остаётся одна последняя единица товара, а два покупателя почти одновременно проходят checkout, магазин должен корректно определить, кому достанется товар. Для этого недостаточно просто показывать остаток в карточке: WooCommerce использует механизм управления запасами и временного резервирования для неоплаченных заказов.
Если логика резерва настроена неправильно, появляются типичные проблемы: две оплаты на одну единицу, слишком долгий «замороженный» остаток, преждевременное освобождение товара или расхождение между WooCommerce и внешней складской системой.
Как WooCommerce работает с резервом
В WooCommerce управление запасами включается в WooCommerce → Settings → Products → Inventory. Параметр Hold Stock (minutes) задаёт, сколько времени товар удерживается для неоплаченного заказа. После истечения срока pending-заказ может быть отменён, а удержанный остаток возвращён в доступное количество.
Официальная документация WooCommerce отдельно указывает, что stock reservation используется при checkout и связан с Hold Stock. Для block-based checkout резерв может действовать для Draft и Pending payment заказов, а затем освобождаться при изменении статуса или невозможности продолжить оформление.
Резерв — это не то же самое, что товар в корзине
Добавление товара в корзину само по себе не означает, что единица навсегда закреплена за покупателем. Это важно для популярных или лимитированных позиций: несколько людей могут одновременно видеть товар в корзине, но окончательная доступность проверяется ближе к checkout.
Именно поэтому нельзя строить собственную складскую логику только вокруг события add-to-cart. Если бизнесу нужно резервировать товар уже на этапе корзины, это отдельный сценарий, требующий дополнительной логики и аккуратного освобождения истёкших резервов.
Что делает Hold Stock
Hold Stock нужен прежде всего для заказов, которые созданы, но ещё не оплачены. Например, клиент выбрал оплату картой, перешёл на платёжный шлюз и не завершил платёж. Без временного удержания следующему покупателю можно было бы продать тот же последний экземпляр.
Слишком короткий интервал создаёт риск, что запас освободится до завершения нормальной оплаты. Слишком длинный — блокирует товар из-за брошенных заказов. Значение нужно выбирать исходя из реального среднего времени оплаты и особенностей платёжного метода.
Почему возникают двойные продажи
- глобальное управление запасами выключено;
- у конкретного товара или вариации не включён количественный учёт;
- внешняя ERP или склад перезаписывает остаток, не учитывая активные заказы;
- кастомный checkout обходит штатную логику WooCommerce;
- заказ создаётся нестандартно через API без корректного жизненного цикла статусов;
- кэширование или собственный код показывает устаревшее состояние.
Последняя единица товара — главный тест
Перед запуском магазина полезно провести простой сценарий. У товара оставляют количество 1 и открывают два независимых сеанса. Оба клиента доходят до checkout почти одновременно. Один завершает создание заказа, второй пытается сделать то же самое.
Правильный результат — система не должна молча принять два гарантированных заказа на одну физическую единицу, если backorder запрещён. После первого резерва или списания второй checkout должен получить актуальное состояние.
Вариативные товары проверяйте отдельно
Для размера, цвета или другой вариации остаток может храниться на уровне конкретной вариации. Если у размера M осталась одна единица, наличие размера L не должно влиять на его резерв. При тестировании проверяйте именно SKU и variation ID, а не только родительский товар.
Не путайте резерв и backorder
Backorder разрешает принимать заказ при недостаточном физическом остатке. Резерв, напротив, временно уменьшает доступность уже существующего запаса для других покупателей. Если backorder включён, отрицательное количество может быть нормальным бизнес-сценарием. Если backorder запрещён, отрицательный остаток — повод проверять интеграции и код.
Подробно про продажи под заказ: Backorder в WooCommerce.
Оплата банковским переводом и резерв
Заказы с ручной или отложенной оплатой могут долго находиться без подтверждения. Если Hold Stock одинаков для моментальной оплаты картой и банковского перевода, один из сценариев может стать неудобным.
Нужно заранее решить, должен ли товар оставаться зарезервированным до ручного подтверждения или заказ после определённого времени освобождает склад. Для дорогих и штучных товаров процесс полезно дополнить уведомлением менеджеру.
Интеграция с ERP и складом
Самая опасная архитектура — когда WooCommerce уменьшает остаток, а внешний импорт раз в несколько минут безусловно записывает старое число обратно. В этот момент резерв внутри магазина перестаёт отражать реальную доступность.
Определите единственный source of truth. Если главным является склад, он должен получать новые заказы и возвращать рассчитанный доступный остаток. Если главным является WooCommerce, внешний импорт не должен стирать изменения после оформления заказа.
Передачу заказов во внешнюю систему лучше делать идемпотентно и с журналом доставки событий. Практический подход описан в статье про WooCommerce webhooks и CRM.
Не кэшируйте динамический остаток как статический HTML
Каталог можно кэшировать, но checkout, корзина и критичные запросы доступности должны получать актуальное состояние. Само наличие надписи «1 в наличии» на закэшированной странице не гарантирует, что товар всё ещё доступен в момент заказа.
Проверяйте отмены и освобождение резерва
Нужно протестировать не только успешную оплату. Проверьте брошенный checkout, отменённый pending-заказ, ошибку платёжного шлюза, ручную отмену администратором и повторную попытку оплаты. После каждого сценария количество должно соответствовать реальному обязательству магазина.
Контрольный чек-лист
- включено глобальное Manage stock;
- количество ведётся у нужного товара или вариации;
- backorder настроен осознанно;
- Hold Stock соответствует реальному времени оплаты;
- два параллельных checkout не создают двойную продажу;
- неоплаченный заказ корректно освобождает резерв;
- ERP не перезаписывает доступный остаток устаревшими данными;
- checkout и API не ломают штатный жизненный цикл заказа.
Когда нужен кастомный механизм резерва
Стандартной логики WooCommerce обычно хватает для обычного интернет-магазина. Кастомизация нужна, когда товар должен блокироваться уже при добавлении в корзину, резерв зависит от пользователя или тарифа, есть несколько складов, требуется очередь покупателей либо резерв должен синхронно подтверждаться внешней ERP.
В таких проектах важно не просто «вычесть единицу», а сделать восстанавливаемую схему: создать резерв, дать ему срок жизни, подтвердить при заказе и гарантированно освободить при истечении.
Итог
Защита от двойной продажи в WooCommerce строится на согласованной работе количественного учёта, статусов заказа, Hold Stock и внешних интеграций. Главный практический тест — последняя единица товара и два параллельных checkout.
Если нужно настроить складскую логику WooCommerce, проверить гонки при оформлении заказа или связать магазин с ERP без расхождения остатков, A.S Groups может выполнить аудит и доработку. Связаться по проекту.
Обсуждение
Вопросы и комментарии
Можно уточнить детали статьи или поделиться своим опытом. Первый комментарий проходит проверку.