Skip to content
ms3PromoCode
Промо-коды для MiniShop3 с гибкими правилами, генерацией по маске и интеграцией в позиции заказа
  1. Компоненты
  2. ms3PromoCode
  3. Разработка
  4. События плагина

События плагина

ms3PromoCode реализован как один MODX-плагин, подписанный на события MiniShop3 и системные события MODX.

Список подписок

СобытиеКогдаЧто делает плагин
OnLoadWebDocumentРендер страницы фронтаРегистрирует JS/CSS по пресету frontend_assets_preset
msOnAddToCartПокупатель добавил товар в корзинуsyncAfterCartChange — пересчитать или снять код
msOnChangeInCartИзменено количество позицииТо же
msOnRemoveFromCartУдалена позиция из корзиныТо же
msOnCreateOrderProductМенеджер добавил позицию в заказ через legacy-админТо же (для новой Vue-админки используется JS-перехватчик)
msOnUpdateOrderProductТо же — изменение позицииТо же
msOnRemoveOrderProductТо же — удаление позицииТо же
msOnCreateOrderПокупатель оформил заказrecordApplication — фиксация в ms3_promo_code_usages
msOnChangeOrderStatusИзменён статус заказаОткат / восстановление применения по cancel_statuses
msOnManagerCustomCssJsЗагрузка страницы редактирования заказаИнжект order-tab.js — вкладка «Промо-код»

syncAfterCartChange

Большинство кейсов с изменением состава корзины решается одним методом ApplicationService::syncAfterCartChange($order):

  1. Если в properties.promo_code нет применённого кода — no-op.
  2. Если есть — пытается заново применить:
    • restoreLineItems — восстановить оригинальные цены позиций.
    • findMatchingItems — пересобрать набор matching-позиций для текущего состава.
    • DiscountCalculator::calculate — пересчитать breakdown.
    • applyToLineItems — записать новые уценённые цены.
  3. Если на новом составе код стал невалидным (min_order_amount, exhausted и т.п.) — remove.

При автоматическом снятии кода с заказа (manager events) в msOrderLog пишется запись:

json
{
    "operation": "ms3promocode_auto_remove",
    "reason": "min_order",
    "message": "Сумма заказа меньше требуемого минимума (5 000 ₽)"
}

Какие события не используются

  • msOnGetCartCostне используется. При модели «уценка позиций» сумма корзины уже считается из msOrderProduct.cost, дополнительно вычитать скидку из агрегата означало бы двойную скидку. Hook был в ранних бета-версиях и удалён.
  • msOnGetProductPriceне используется. Скидки не применяются на уровне отдельных товаров вне контекста корзины.

Свои события компонента

Плагин также эмитит DOM-события для фронтенда (см. JS API):

СобытиеКогда
ms3promocode:readyHeadless-ядро инициализировано
ms3promocode:appliedКод успешно применён
ms3promocode:removedКод успешно снят
ms3promocode:auto-removedКод автоматически снят при изменении корзины
ms3promocode:errorОшибка операции

Подписаться можно стандартно:

js
document.addEventListener('ms3promocode:applied', (e) => {
    console.log(e.detail.code, e.detail.discount);
});

Подписка на события из своего плагина

Чтобы реагировать на применение кода в своём коде, подпишитесь на стандартные MS3-события — payload уже содержит всё нужное.

Пример: своя нотификация о применении

php
// elements/plugins/myplugin.php
$eventName = $modx->event->name;

if ($eventName === 'msOnCreateOrder') {
    /** @var \MiniShop3\Model\msOrder $order */
    $order = $scriptProperties['msOrder'];
    $properties = $order->get('properties');

    if (!empty($properties['promo_code'])) {
        $code = $properties['promo_code']['code'];
        $discount = $properties['promo_code']['discount_amount'];

        // ... отправить в Telegram, метрику и т.п.
        myNotifier()->send("Применён код {$code}, скидка {$discount}");
    }
}

Пример: запрет применения определённого кода

php
// Pre-validation на уровне плагина
if ($eventName === 'msOnCreateOrder') {
    $order = $scriptProperties['msOrder'];
    $properties = $order->get('properties');
    $code = $properties['promo_code']['code'] ?? null;

    if ($code === 'BANNED-CODE') {
        // Снять код принудительно
        /** @var \ms3PromoCode\Services\ApplicationService $svc */
        $svc = $modx->services->get('ms3promocode_application_service');
        $svc->remove($order);
    }
}

Внимание

ms3PromoCode не предоставляет своего pre-apply hook'а с возможностью отмены — только реактивные события после факта. Если такая логика нужна — обсудим в issue tracker.