new

ms3PromoCode

Модуль промо-кодов для MiniShop3
Автор дополнения
Николай Савин
Пакетов
20
Закачек
32 679
Обычно отвечает в течение суток
Автор дополнения
Пакетов
20
Закачек
32 679
Обычно отвечает в течение суток
Версия 1.0.1-beta1
Дата выпуска 29.05.2026
Загрузки 0
Просмотры 345
Внимание, этот компонент требует PHP 8.2 или выше!
Внимание, этот компонент требует MODX 3 или выше.

О компоненте


Полнофункциональная система промо-кодов для магазинов на MiniShop3: гибкие правила применения, ручная и пакетная генерация, современная админка на Vue 3 + PrimeVue 4, готовая фронтенд-форма для покупателя. Скидка учитывается прямо в позициях заказа — чек 54-ФЗ, email-уведомления и личный кабинет показывают правильные суммы без каких-либо доработок шаблонов.



Скидки


  • Тип: процент или фиксированная сумма в рублях.
  • Область применения: вся корзина или только подпадающие под правила позиции.
  • Корректный учёт в позициях. Цена со скидкой прописывается в каждой позиции заказа, поэтому сумма в чеке ОФД, в email-уведомлении и в личном кабинете покупателя всегда совпадает с оплаченной — никаких правок шаблонов не требуется.
  • Точная сумма скидки. При распределении по нескольким товарам копейки автоматически компенсируются, чтобы итог совпадал с заявленной суммой до рубля.

Условия применения (правила)


  • Включить или исключить конкретные товары.
  • Ограничить категориями или брендами.
  • Универсальный фильтр по любому полю карточки товара (цена, остаток, артикул, вес, собственные поля и т.д.) с разными операторами сравнения: равно, не равно, больше, меньше, диапазон, содержит и др.
  • Фильтр по опциям товара — цвет, размер, вариант и другие.
  • Несколько правил объединяются по «И», значения внутри одного правила — по «ИЛИ».

Жизненный цикл кода


  • Период действия — даты начала и окончания.
  • Общий лимит применений.
  • Минимальная сумма заказа для применения.
  • Включён / выключен.
  • Автоматические статусы: запланирован, истёк, исчерпан, отключён. Отключённый код для покупателя выглядит как «не найден» — факт его существования не раскрывается.

Генерация кодов


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

Админ-панель


Современный интерфейс на Vue 3 + PrimeVue 4.


  • Список промо-кодов с постраничной выборкой, сортировкой, фильтрами и групповыми действиями (включить / выключить / удалить сразу несколько кодов).
  • Редактор кода с тремя вкладками: основные параметры, правила применения, статистика.
  • Раздел «Аналитика»: ключевые показатели (количество применений, общая сумма скидки) и детальный журнал использований с фильтрами по датам и статусу.
  • Вкладка «Промо-код» прямо в карточке заказа — менеджер может применить или снять код у конкретного заказа.

Фронтенд для покупателя


  • Готовая форма ввода кода через сниппет ms3PromoCodeForm. Состояние «код применён» рендерится сразу на сервере — нет «мигания» при загрузке страницы.
  • Шаблон формы легко переопределяется через собственный чанк.
  • Headless JS-API для собственных интеграций (SPA, кастомные темы).
  • Автоматический перерасчёт итогов корзины после применения или снятия кода.
  • Папка переопределений assets/components/ms3promocode-overrides/ — можно заменить любой JS- или CSS-файл пакета своей версией без правок исходников.

Ручное редактирование заказа в админке


  • Если менеджер добавил, изменил или удалил позицию в заказе, к которому уже применён промо-код — скидка автоматически пересчитается и распределится заново.
  • Если новый состав заказа больше не подходит под условия кода (например, сумма стала меньше минимальной) — код автоматически снимается, а факт снятия записывается в историю заказа.

Учёт и статистика


  • Каждое применение фиксируется в базе с привязкой к заказу, покупателю и подробной разбивкой скидки по позициям.
  • Отмена заказа откатывает применение кода и уменьшает счётчик использований. Возврат заказа из отменённого статуса — восстанавливает.
  • Данные учёта доступны в разделе «Аналитика» с возможностью фильтрации и экспорта.

Требования


  • MODX Revolution 3.0 и выше
  • MiniShop3 1.10 и выше
  • PHP 8.2 и выше
  • VueTools — для админки
  • pdoTools — для шаблонов фронтенд-формы

1.0.1-beta1 — 2026-05-29

Багфикс-релиз. Закрыта дыра в синхронизации скидки при изменении опций позиции в корзине и при ручной правке цены позиции в админке.

Исправлено

Snapshot цены позиции теперь валидируется, а не доверяется слепо. msOrderProduct.properties.ms3promocode.original_price хранит исходную цену позиции до применения кода. Раньше ApplicationService::originalPriceCost() всегда читал snapshot, если он есть. Если между apply() и следующим syncAfterCartChange() цена позиции была переписана внешней силой — snapshot устаревал, и скидка пересчитывалась от старой «оригинальной», а не от актуальной цены.

Известные внешние силы, которые переписывают msOrderProduct.price:

  • ms3AddOptions (и аналоги) при смене или удалении опции уже добавленной позиции.
  • Менеджер в админке при ручном редактировании цены позиции.
  • Сторонние плагины на msOnGetProductPrice, msOnBeforeChangeOptionsInCart.

Новый инвариант, проверяемый перед чтением snapshot:

live_price + (discount_amount / count) ≈ snapshot.original_price   (допуск ≤ 0.01 на единицу)

Если инвариант сломан — snapshot игнорируется, новый baseline = live price. Это же правило применяется в restoreLineItems(): stale snapshot чистится из properties без перезаписи live price (раньше при remove() восстанавливалась устаревшая «оригинальная» цена поверх актуальной).

Добавлено

Подписка на msOnChangeOptionInCart. Теперь плагин ловит и фронтовое изменение опции (Cart::changeOption()), включая её удаление. Сценарий «применил код → убрал платную опцию → ушёл оплачивать» больше не оставляет скидку, посчитанную от старой цены. Merge-сценарий (новый product_key совпадает с другой позицией) шёл через msOnChangeInCart и работал, теперь он покрыт и второй веткой.

Последние обсуждения в сообществе MODX.pro