Разработка системы управления складскими остатками для e-commerce

Когда два покупателя одновременно оформляют последний экземпляр товара, без надёжной системы остатков один из них узнает об отсутствии после оплаты. Мы разрабатываем систему управления складскими остатками, которая исключает overselling, автоматизирует резервирование и синхронизацию с учётными системами. Реализуем проект под ключ — от аудита до внедрения и последующей поддержки, обеспечивая стабильную работу вашего e-commerce.

Разработка и обслуживание любых видов сайтов:

Информационные сайты или веб-приложения
Сайты визитки, landing page, корпоративные сайты, онлайн каталоги, квиз, промо-сайты, блоги, новостные ресурсы, информационные порталы, форумы, агрегаторы
Сайты или веб-приложения электронной коммерции
Интернет-магазины, B2B-порталы, маркетплейсы, онлайн-обменники, кэшбэк-сайты, биржи, дропшиппинг-платформы, парсеры товаров
Веб-приложения для управления бизнес-процессами
CRM-системы, ERP-системы, корпоративные порталы, системы управления производством, парсеры информации
Сайты или веб-приложения электронных услуг
Доски объявлений, онлайн-школы, онлайн-кинотеатры, конструкторы сайтов, порталы предоставления электронных услуг, видеохостинги, тематические порталы

Это лишь некоторые из технических типов сайтов, с которыми мы работаем, и каждый из них может иметь свои специфические особенности и функциональность, а также быть адаптированным под конкретные потребности и цели клиента

Услуги, которые мы предлагаем
Показано 1 из 1Все 2062 услуг
Разработка системы управления складскими остатками для e-commerce
Средний
~5 дней
Часто задаваемые вопросы

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

Проблемы, которые решает система

Первая — конкурентное резервирование. Если в момент оформления заказа не заблокировать единицу, два пользователя могут купить один товар. Вторая — зависшие резервы. Брошенные корзины — не редкость, и если не освобождать резервы, через неделю половина остатков будет недоступна. Третья — рассинхронизация с внешними учётными системами. Когда 1С или МойСклад обновляют количество, а магазин продолжает продавать по старым данным, возникают задолженности.

Схема данных

Базовая структура для PostgreSQL:

CREATE TABLE product_variants (
    id BIGSERIAL PRIMARY KEY,
    product_id BIGINT NOT NULL REFERENCES products(id),
    sku VARCHAR(100) NOT NULL UNIQUE,
    attributes JSONB NOT NULL DEFAULT '{}',
    stock_qty INTEGER NOT NULL DEFAULT 0,
    reserved_qty INTEGER NOT NULL DEFAULT 0,
    low_stock_threshold INTEGER NOT NULL DEFAULT 5,
    CHECK (stock_qty >= 0),
    CHECK (reserved_qty >= 0),
    CHECK (stock_qty >= reserved_qty)
);

CREATE TABLE stock_movements (
    id BIGSERIAL PRIMARY KEY,
    variant_id BIGINT NOT NULL REFERENCES product_variants(id),
    delta INTEGER NOT NULL,
    type VARCHAR(50) NOT NULL,
    reference VARCHAR(255),
    created_at TIMESTAMP NOT NULL DEFAULT NOW()
);

available_qty = stock_qty - reserved_qty вычисляется на лету. Лог stock_movements фиксирует каждую операцию для аудита. Индексы на (product_id, sku) и (variant_id, created_at) ускоряют поиск и отчётность.

Атомарное резервирование без гонок

Атомарность обеспечивается через UPDATE ... RETURNING:

UPDATE product_variants
SET reserved_qty = reserved_qty + :qty
WHERE id = :variant_id
  AND (stock_qty - reserved_qty) >= :qty
RETURNING id, stock_qty, reserved_qty;

Если строка не вернулась — товара недостаточно. В Laravel это оборачивается в транзакцию с lockForUpdate(). Для высоконагруженных сценариев используйте пессимистичную блокировку строки, чтобы избежать взаимоблокировок.

Почему важно освобождать резервы?

Брошенная корзина — потерянный остаток. Два подхода: TTL через очередь (точность до минуты) и scheduled cleanup (проще, но ±5 минут). Для магазинов до 1000 заказов в день достаточно cron-задачи каждые 5 минут. Сравнение методов:

Характеристика TTL через очередь Scheduled cleanup
Точность освобождения ±1 минута ±5 минут
Зависимость от инфраструктуры Нужна очередь (Redis/Beanstalkd) Только cron
Нагрузка при 1000 заказов/день Низкая Низкая
Как настроить TTL в Laravel?
// В сервис-провайдере регистрируем job
use App\Jobs\ReleaseReservation;

$ttl = Carbon::now()->addMinutes(30);
ReleaseReservation::dispatch($variantId, $qty)->delay($ttl);

Если заказ оформлен, job удаляется. Если нет — резерв автоматически снижается.

Интеграция с 1С и МойСклад

Остатки приходят из внешних систем двумя способами:

Режим Описание Когда выбрать
Webhook Склад вызывает ваш endpoint при изменении Высокая частота обновлений
Pull Магазин опрашивает систему раз в N минут Ограничения по безопасности

Важное правило: при импорте обновляйте только stock_qty, не трогая reserved_qty. Иначе активные резервы слетят.

Как отображать статус на витрине?

Для покупателя важно видеть реальное наличие. Мы вычисляем доступное количество и отображаем:

  • Если available_qty > low_stock_threshold — «В наличии».
  • Если 0 < available_qty ≤ low_stock_threshold — «Осталось N шт.».
  • Если available_qty = 0 — «Нет в наличии».
  • Если настроен предзаказ — «Под заказ, 5–7 дней».

Для высоконагруженных страниц статус кешируется в Redis с TTL 60 секунд.

Как настроить уведомления о низком остатке?

Оповещение менеджера закупок триггерится при обновлении stock_qty ниже порога. В Laravel это observer:

class ProductVariantObserver {
    public function updated(ProductVariant $variant): void {
        if ($variant->wasChanged('stock_qty') && $variant->isLowStock()) {
            LowStockAlert::dispatch($variant);
        }
    }
}

Алерт отправляется в email, Telegram или Slack. Дополнительно можно настроить SMS для критичных позиций.

Как оптимизировать запросы для отображения остатков?

При выводе списка товаров типичная ошибка — N+1 запрос: для каждого варианта выбираем остаток отдельно. Используйте withCount или оконные функции. Например, для PostgreSQL:

SELECT p.*, SUM(sm.delta) OVER (PARTITION BY sm.variant_id) AS current_stock
FROM products p
LEFT JOIN stock_movements sm ON sm.variant_id = p.id
WHERE ...

Этот запрос выполняется за один проход. Для больших каталогов агрегируйте данные в Redis через scheduled job.

Процесс внедрения

  1. Проектирование схемы данных и выбор методов резервирования.
  2. Реализация атомарных операций с тестированием на конкурентность.
  3. Настройка освобождения резервов (TTL или cron).
  4. Интеграция с внешними учётными системами (1С, МойСклад).
  5. Разработка панели администрирования с фильтрами и экспортом.
  6. Нагрузочное тестирование и деплой.

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

Сроки реализации

Этап Время
Базовое резервирование + лог 3–5 дней
Интеграция с учётной системой +3–5 дней
Кеширование и отображение на витрине +2 дня
Панель остатков в админке +2–3 дня
Итого 1–2 недели

Правильно спроектированная система остатков снижает потери от overselling на 15–20% и исключает ручной контроль. Например, для магазина с 5000 заказов в месяц устранение overselling сохраняет до $1.4k–1.9k выручки ежемесячно. Дополнительно автоматизация закупок экономит до $900–1.3k в месяц на зарплате логиста.

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

Наши компетенции:

Последние работы

  • Разработка сайта компании B2B ADVANCE
    Разработка сайта компании B2B ADVANCE
    1542
  • Разработка веб-приложения для компании FEEDME
    Разработка веб-приложения для компании FEEDME
    1394
  • Разработка веб-сайта для компании БЕЛФИНГРУПП
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    1081
  • Разработка интернет магазина для компании FURNORO
    Разработка интернет магазина для компании FURNORO
    1369
  • Разработка веб-приложения для компании Enviok
    Разработка веб-приложения для компании Enviok
    1142
  • Разработка веб-сайта для компании ФИКСПЕР
    Разработка веб-сайта для компании ФИКСПЕР
    1060