В большинстве движков интернет-магазинов цена товара — это одно число в одном поле базы данных. Работает безупречно, пока магазин имеет один склад и продаёт всем по одной цене. Проблема возникает, как только появляется второй склад со своей закупочной стоимостью или оптовый покупатель, которому нужна другая цена за тот же товар.
Эта статья о том, почему «один товар — одна цена» ломается именно в этой точке, и что пришлось посчитать в ядре собственного движка LiteShop, чтобы этого избежать.
Где именно ломается модель с одной ценой
Представим магазин с двумя складами: один в Киеве, товар туда завезли по старой закупочной цене, второй во Львове — та же позиция, но завезённая позже и дороже. Классический движок, в котором цена привязана к товару, а не к паре «товар + склад», заставляет выбирать: либо держать две разные товарные записи для одной и той же позиции (и путать покупателя выбором «одинакового» товара дважды), либо продавать с одного склада себе в убыток, пока не выровняется средняя закупочная.
Та же проблема с оптовыми уровнями: постоянный клиент с заказами на сумму выше определённого порога должен получать другую цену за тот же артикул, чем розничный покупатель. Если цена — одно поле, это требует либо ручной системы скидок поверх стандартного движка, либо отдельного прайса, который синхронизируется вручную и расходится с основным каталогом за первую же неделю.
Что это значит для архитектуры, а не только для интерфейса
Правильное решение — не косметическое (добавить поле «скидка» в карточку товара), а структурное: цена должна принадлежать паре «товар + склад» и дополнительно модифицироваться уровнем покупателя. Это означает отдельную таблицу цен, а не одно поле, и логику выбора правильной строки цены при каждом просмотре карточки товара и каждом расчёте корзины — без замедления страницы, потому что этот расчёт происходит на каждом запросе.
Мы строили эту логику в ядре собственного движка LiteShop: несколько складов с разной закупочной ценой одного товара, уровни оптовых цен и складской учёт — не надстройка поверх типового движка, а часть того, как построена модель товара с самого начала. 42 модуля ядра (доставка, оплата, склад, лояльность, SEO) включаются переключателем в админке, а не устанавливаются отдельными плагинами, которые потом конфликтуют друг с другом.
Не замедляет ли это магазин
Дополнительная логика расчёта цены на каждый просмотр — естественный вопрос о скорости. На проде одного из магазинов, построенных на этом движке (Hetzner cx43), первый ответ главной страницы холодный равен тёплому — 167 мс, замер 19.05.2026. Это возможно именно потому, что расчёт цены по складу и уровню клиента кешируется в Redis: замеры 12.06.2026 показали 98,3% попаданий в кеш при нуле вытесненных ключей — то есть кеш не успевает переполняться и удалять актуальные данные даже под живой нагрузкой.
Чего движок пока не делает — честно
Резервирование товара с таймером в корзине отсутствует: остаток списывается во время оформления заказа, не в момент добавления в корзину. Импорта каталога напрямую из OpenCart нет. Интеграции с Rozetka Delivery и Meest пока заглушки, не рабочая функция. Эти ограничения — не спрятаны мелким шрифтом, а прямо озвучены: движок молодой, и множественные склады с оптовыми уровнями — это та часть, которую сделали крепкой с первого дня, а остальное достраивают последовательно.
Кому это вообще нужно
Если у вас один склад, несколько сотен товаров и нет планов на оптовые уровни или доработки — типовой движок или аренда конструктора обойдутся дешевле, и честный разбор задачи скажет это первым письмом, а не после оплаты. Потребность в структурном решении возникает от двух складов или поставщиков, от необходимости в оптовых уровнях цен, или когда типовой конструктор уже упирается в собственные ограничения.