Настройка мультисклада OpenCart
Мультисклад в OpenCart позволяет разделить товарные запасы по нескольким физическим или логическим точкам хранения — офис, склад поставщика, дропшиппинг-партнёр, региональный хаб. Без этой настройки магазин с несколькими источниками поставок теряет точность остатков и усложняет логистику.
Что такое мультисклад в OpenCart
Стандартная установка OpenCart хранит остатки в единой таблице oc_product (quantity + subtract). Для работы с несколькими складами нужен модуль, добавляющий таблицы вида oc_location, oc_product_location, и логику списания при заказе.
Популярные решения:
- Journal3 Warehouse — встроен в тему Journal3
- Multi Warehouse Pro от Opencart.com — официальный extension
- модуль XLDevelopment — гибкая настройка приоритетов склада
- Кастомная разработка через Events + Model override
Архитектура решения
Базовая схема при кастомной реализации:
CREATE TABLE oc_location (
location_id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(128),
address TEXT,
status TINYINT(1)
);
CREATE TABLE oc_product_to_location (
product_id INT,
location_id INT,
quantity INT DEFAULT 0,
PRIMARY KEY (product_id, location_id)
);
При оформлении заказа событие catalog/model/checkout/order/addOrder/after триггерит кастомный observer, который списывает остатки с нужного склада по правилу приоритета (ближайший к покупателю, первый непустой, конкретный склад для товара).
Настройка через extension
Шаг 1 — установка модуля
Загрузка через admin > Extensions > Installer. Модуль регистрирует события через oc_event:
// install.php модуля
$this->model_setting_event->addEvent([
'code' => 'multi_warehouse',
'trigger' => 'catalog/model/checkout/order/addOrder/after',
'action' => 'extension/multi_warehouse/model/warehouse/subtractStock',
'status' => 1,
'sort_order' => 1
]);
Шаг 2 — создание складов
В разделе Extensions > Multi Warehouse > Locations создаются склады с атрибутами: название, адрес, приоритет, привязка к зонам доставки.
Шаг 3 — распределение товаров
В карточке товара появляется вкладка «Склады». Для каждого склада указывается доступное количество. При включённом subtract система работает с агрегированным остатком.
Шаг 4 — правила выбора склада
Стратегии списания:
-
FIFO по приоритету — берёт со склада с наименьшим
priority - Ближайший к покупателю — по shipping zone mapping
- Специфичный для товара — жёсткая привязка товара к складу
- Смешанный — списывает с нескольких складов при дефиците на одном (split fulfillment)
Интеграция с поставщиками
Для дропшиппинга или VMI (vendor-managed inventory) остатки обновляются по API:
// Обновление остатков склада через кастомный API endpoint
// admin/controller/api/warehouse.php
public function updateStock(): void {
$json = [];
$location_id = (int)$this->request->post['location_id'];
$updates = $this->request->post['products']; // [{product_id, quantity}]
foreach ($updates as $item) {
$this->model_extension_warehouse->setLocationStock(
(int)$item['product_id'],
$location_id,
(int)$item['quantity']
);
}
$json['success'] = count($updates) . ' товаров обновлено';
$this->response->addHeader('Content-Type: application/json');
$this->response->setOutput(json_encode($json));
}
Поставщик делает POST /index.php?route=api/warehouse/updateStock с токеном в заголовке — остатки обновляются без доступа в админку.
Отображение на фронте
По умолчанию покупатель видит суммарный остаток. Можно вывести доступность по складу:
{% if product.locations %}
<ul class="warehouse-availability">
{% for loc in product.locations %}
<li>{{ loc.name }}:
{% if loc.quantity > 0 %}в наличии ({{ loc.quantity }} шт.)
{% else %}нет в наличии{% endif %}
</li>
{% endfor %}
</ul>
{% endif %}
Это актуально для B2B-магазинов, где покупатель выбирает склад самовывоза.
Резервирование и возвраты
Важный момент — резервирование остатков при оплате заказа, а не при его создании. Модуль должен обрабатывать статусы:
| Статус заказа | Действие с остатком |
|---|---|
| Pending | Без изменений или мягкое резервирование |
| Processing | Жёсткое списание |
| Shipped | Подтверждение отгрузки |
| Cancelled | Возврат на склад |
| Refunded | Возврат по правилу склада возвратов |
Для этого настраиваются события на catalog/model/checkout/order/addOrderHistory/after.
Отчётность
Полезные SQL-запросы для контроля остатков:
-- Остатки по складам
SELECT l.name AS location, p.model, ptl.quantity
FROM oc_product_to_location ptl
JOIN oc_location l ON l.location_id = ptl.location_id
JOIN oc_product p ON p.product_id = ptl.product_id
WHERE ptl.quantity < 5
ORDER BY l.name, p.model;
-- Движение по складу за период
SELECT DATE(oh.date_added), SUM(op.quantity)
FROM oc_order_history oh
JOIN oc_order_product op ON op.order_id = oh.order_id
WHERE oh.order_status_id = 2 -- Processing
AND oh.date_added BETWEEN '2025-01-01' AND '2025-01-31'
GROUP BY DATE(oh.date_added);
Сроки и трудозатраты
Настройка готового модуля с 2–3 складами: 2–3 дня. Кастомная разработка с нуля (приоритеты, API поставщика, split fulfillment): 1–2 недели. Интеграция с внешней WMS (1C, МойСклад) добавляет ещё 3–5 дней на маппинг данных и тестирование.







