ms3PromoCode
Встречайте новый компонент экосистемы — ms3PromoCode. Промо-коды (скидочные купоны) для магазинов на MiniShop3: гибкие правила применения, ручная и пакетная генерация по маске, Vue-админка с аналитикой, готовая форма для покупателя.
Встроенной системы скидок в MiniShop3 нет. Все знают что в ms2 для этого был свой достаточно мощный компонент, который к слову, имел приличный набор ограничений в применении. Держа это в голове я выпустил систему скидок, встроенную в админку минишопа. Постарался учесть старый, всем известный функционал и одновременно избавиться от известных проблем
В шаблон корзины добавляется один сниппет:

В админке появляется раздел «Промо-коды» с двумя разделами:


Плюс — отдельная вкладка «Промо-код» прямо в карточке заказа. Можно применить или снять код на уже созданном заказе в пару кликов, стоимость пересчитается на лету. В определённых статусах (настраивается) вкладка блокируется от редактирования — защита от случайных правок по отгруженным заказам.

Скидка может действовать на всю корзину или только на подходящие позиции. Правила — шесть секций в редакторе:
Жизненный цикл кода тоже под контролем: период действия с датами старта и окончания, общий лимит применений, минимальная сумма заказа, выключатель. Компонент сам считает статус — scheduled, expired, exhausted, disabled. Отключённый код сообщает покупателю «не найден», чтобы не палить факт существования временно выключенной акции.

Для раздачи уникальных кодов (например, каждому подписчику рассылки — свой) — генератор по маске. Символы # (цифра), ? (буква), * (и то и другое), плюс литералы для префиксов-суффиксов. Например, маска SUMMER-**** выдаёт коды вида SUMMER-K3B9. Набор символов по умолчанию — без визуально неоднозначных (нет 0/O, 1/I/L), чтобы клиенты не гадали, что им прислали. Защита от коллизий, живое превью в админке.


На фронте — headless JS-ядро window.ms3PromoCode. Можно писать свой UI поверх, если стандартная форма не подходит:
Web API на случай полностью своего фронта:
Отдельно — override-директория. Любой файл, положенный в assets/components/ms3promocode-overrides/, прозрачно подменяет аналогичный файл пакета. Можно переопределить CSS, JS, чанки — без правок самого компонента, обновления не затрут ваши изменения.
Компонент не патчит ядро MS3 — только подписывается на официальные события:
В MiniShop3 1.10 карточка заказа окончательно переехала на Vue (писал о этом в посте про релизы MS3). ms3PromoCode корректно работает и там: ручное добавление, изменение или удаление позиции в Vue-админке автоматически перераспределяет скидку. Нативных событий для таких действий в MS3 пока нет (вопрос висит в issue #207), поэтому временно используется JS-интерсептор, который после каждого запроса на изменение позиции дёргает processor Mgr/Order/Resync. Как только в MS3 появятся штатные события — перейду на них, текущая реализация рассчитана на этот переход.
Релиз — 1.0.0-beta1, статус открытой беты. В планах: интеграция с накопительными скидками клиентов, поддержка стеков кодов (можно ли применять два сразу — и если да, как), UI-виджет выбора кода из списка собственных сохранённых. Обратная связь, баг-репорты и feature-requests — через issue-трекер.
Готов услышать — что ещё хочется видеть в v1.0 стабильной, какие сценарии из вашей практики не покрываются текущими правилами, и где интеграция с корзиной ведёт себя неочевидно.
Зачем он нужен
Встроенной системы скидок в MiniShop3 нет. Все знают что в ms2 для этого был свой достаточно мощный компонент, который к слову, имел приличный набор ограничений в применении. Держа это в голове я выпустил систему скидок, встроенную в админку минишопа. Постарался учесть старый, всем известный функционал и одновременно избавиться от известных проблем
Для покупателя
В шаблон корзины добавляется один сниппет:
{'!ms3PromoCodeForm' | snippet}Это классическая форма, которая рендерит себя еще на сервере без «мигания» при загрузке страницы. В наличии поле для ввода и Кнопки «Применить» и «Снять». После любого изменения корзины скидка автоматически пересчитывается, код тихо снимается, если новые позиции под его правила больше не подходят — с записью в msOrderLog.
Для менеджера магазина
В админке появляется раздел «Промо-коды» с двумя разделами:
- Управление кодами — таблица со всеми фильтрами и сортировками, редактор кода с тремя вкладками (Основное / Правила / Стастистика), массовые действия.
- Аналитика — KPI (количество применений, суммарная скидка) и детальный лог использования с фильтром по датам, заказам и клиентам.


Плюс — отдельная вкладка «Промо-код» прямо в карточке заказа. Можно применить или снять код на уже созданном заказе в пару кликов, стоимость пересчитается на лету. В определённых статусах (настраивается) вкладка блокируется от редактирования — защита от случайных правок по отгруженным заказам.

Правила применения — гибкий таргетинг
Скидка может действовать на всю корзину или только на подходящие позиции. Правила — шесть секций в редакторе:
- Разрешённые товары и исключения.
- Категории и исключения категорий.
- Бренды.
- Универсальный фильтр по любому полю таблицы modx_ms3_products — с операторами =, !=, <, >, IN, BETWEEN, LIKE, CONTAINS.
- Фильтр по опции товара (варианты, цвета, размеры).
Жизненный цикл кода тоже под контролем: период действия с датами старта и окончания, общий лимит применений, минимальная сумма заказа, выключатель. Компонент сам считает статус — scheduled, expired, exhausted, disabled. Отключённый код сообщает покупателю «не найден», чтобы не палить факт существования временно выключенной акции.

Пакетная генерация по маске
Для раздачи уникальных кодов (например, каждому подписчику рассылки — свой) — генератор по маске. Символы # (цифра), ? (буква), * (и то и другое), плюс литералы для префиксов-суффиксов. Например, маска SUMMER-**** выдаёт коды вида SUMMER-K3B9. Набор символов по умолчанию — без визуально неоднозначных (нет 0/O, 1/I/L), чтобы клиенты не гадали, что им прислали. Защита от коллизий, живое превью в админке.


Для разработчика
На фронте — headless JS-ядро window.ms3PromoCode. Можно писать свой UI поверх, если стандартная форма не подходит:
await window.ms3PromoCode.init();
const result = await window.ms3PromoCode.apply('SALE10');
if (result.success) {
console.log('Скидка:', result.data.discount);
}
window.ms3PromoCode.on('applied', (data) => { /* ... */ });
window.ms3PromoCode.on('auto-removed', (data) => { /* ... */ });Всё что нужно для интеграции с React, Vue, Alpine или просто своим ванильным JS — init, apply, remove, validate, getCurrent, refresh, подписка на события applied / auto-removed.Web API на случай полностью своего фронта:
- POST /api/v1/promo/apply — применить код к корзине.
- POST /api/v1/promo/remove — снять применённый код.
- POST /api/v1/promo/validate — проверить без записи (можно с пустой корзиной).
- GET /api/v1/promo/current — текущий применённый код.
Отдельно — override-директория. Любой файл, положенный в assets/components/ms3promocode-overrides/, прозрачно подменяет аналогичный файл пакета. Можно переопределить CSS, JS, чанки — без правок самого компонента, обновления не затрут ваши изменения.
Интеграция с MiniShop3
Компонент не патчит ядро MS3 — только подписывается на официальные события:
- msOnAddToCart / msOnChangeInCart / msOnRemoveFromCart — любое изменение корзины триггерит восстановление исходных цен, пересчёт скидки и повторное применение. Если корзина больше не удовлетворяет условиям — код автоматически снимается, событие логируется.
- msOnCreateOrder — при сабмите заказа применение записывается в ms3_promo_code_usages с полным breakdown по позициям и счётчиком кода инкрементируется.
- msOnChangeOrderStatus — переход в один из статусов из настройки ms3promocode.cancel_statuses (обычно — «отменён») помечает применение как cancelled и декрементирует счётчик кода. Возврат заказа из отменённого состояния — восстанавливает.
Работа в новой Vue-админке MS3
В MiniShop3 1.10 карточка заказа окончательно переехала на Vue (писал о этом в посте про релизы MS3). ms3PromoCode корректно работает и там: ручное добавление, изменение или удаление позиции в Vue-админке автоматически перераспределяет скидку. Нативных событий для таких действий в MS3 пока нет (вопрос висит в issue #207), поэтому временно используется JS-интерсептор, который после каждого запроса на изменение позиции дёргает processor Mgr/Order/Resync. Как только в MS3 появятся штатные события — перейду на них, текущая реализация рассчитана на этот переход.
Установка и совместимость
- MODX Revolution 3.0+
- MiniShop3 1.10+
- PHP 8.2+
- pdoTools (для Fenom-чанков фронтенд-формы)
- VueTools (для админ-панели)
Что дальше
Релиз — 1.0.0-beta1, статус открытой беты. В планах: интеграция с накопительными скидками клиентов, поддержка стеков кодов (можно ли применять два сразу — и если да, как), UI-виджет выбора кода из списка собственных сохранённых. Обратная связь, баг-репорты и feature-requests — через issue-трекер.
Готов услышать — что ещё хочется видеть в v1.0 стабильной, какие сценарии из вашей практики не покрываются текущими правилами, и где интеграция с корзиной ведёт себя неочевидно.
Поблагодарить автора
Отправить деньги
0