Скидка от суммы корзины в MiniShop3: плагин на msOnGetCartCost за 20 строк

Клиент просит скидку 5% от 5 000 ₽, 10% от 10 000 ₽ или фикс 500 ₽ от 3 000 ₽. В miniShop2 вы, скорее всего, лезли в msOnGetOrderCost. В MiniShop3 расчёт разбит на три события: корзина, доставка, комиссия оплаты. Скидку на товары вешаем на msOnGetCartCost.

Документация: События стоимости.

Что делает msOnGetCartCost


MiniShop3 считает сумму корзины и вызывает плагины на msOnGetCartCost. В $scriptProperties['cost'] приходит текущая сумма. Новую сумму задаём через $modx->event->returnedValues['cost']. Значение подхватится в корзине, на оформлении и в API.

События с префиксом Before умеют остановить операцию через output(). msOnGetCartCost только меняет цифру.

MS2: msOnGetOrderCost заменили на msOnGetCartCost, msOnGetDeliveryCost, msOnGetPaymentCost.

Плагин: скидка от суммы корзины



Один плагин, правила в массиве $config вверху файла. Фикс применяется первым, процент считается от остатка. Данные для витрины кладём в $modx->eventData['ms3CartDiscount'].

<?php
/**
 * Cart discount by order amount.
 * Event: msOnGetCartCost
 */

if ($modx->event->name !== 'msOnGetCartCost') {
    return;
}

$cartCost = (float) ($scriptProperties['cost'] ?? 0);
if ($cartCost <= 0) {
    return;
}

$config = [
    'fixed' => [
        'enabled'   => true,
        'threshold' => 3000,
        'amount'    => 500,
    ],
    'percent_tiers' => [
        10000 => 10,
        5000  => 5,
    ],
];

$discountParts = [];
$costAfterFixed = $cartCost;

if (
    $config['fixed']['enabled']
    && $cartCost >= $config['fixed']['threshold']
) {
    $fixedAmount = min($config['fixed']['amount'], $cartCost);
    $discountParts['fixed'] = $fixedAmount;
    $costAfterFixed = $cartCost - $fixedAmount;
}

$appliedPercent = 0;

if ($costAfterFixed > 0) {
    foreach ($config['percent_tiers'] as $threshold => $percent) {
        if ($costAfterFixed < $threshold) {
            continue;
        }

        $discountParts['percent'] = round($costAfterFixed * $percent / 100, 2);
        $appliedPercent = $percent;
        break;
    }
}

$totalDiscount = array_sum($discountParts);

if ($totalDiscount <= 0) {
    return;
}

$returnedValues = &$modx->event->returnedValues;
$returnedValues['cost'] = max(0.0, $cartCost - $totalDiscount);

$modx->eventData['ms3CartDiscount'] = [
    'total'   => $totalDiscount,
    'parts'   => $discountParts,
    'percent' => $appliedPercent,
];

Только процент или только фикс

Меняете $config, второй плагин не нужен.

  • Только процент: 'fixed' => ['enabled' => false, 'threshold' => 0, 'amount' => 0]
  • Только фикс: 'percent_tiers' => []

Установка


  1. Элементы → Плагины → Создать. Имя: MS3 Cart Discount.
  2. Вставьте код выше.
  3. Системные событияmsOnGetCartCost.
  4. Сохраните, очистите кэш.
  5. Проверьте корзину.
Плагин включён, priority по умолчанию 0. Несколько плагинов на одном событии: меньший priority выполняется раньше, второй видит уже уменьшенную сумму.

Проверка


  • 3 500 ₽ → 3 000 ₽ (минус 500 ₽ фикс)
  • 6 000 ₽ → 5 700 ₽ (минус 5%)
  • 10 500 ₽ → 9 450 ₽ (минус 10%)
  • 12 000 ₽ → 10 950 ₽ (500 ₽ + 10% от 11 500 ₽)
Отладка на один запрос:

$modx->log(
    modX::LOG_LEVEL_ERROR,
    '[MS3CartDiscount] cost=' . $cartCost . ' discount=' . $totalDiscount
);

Лог: core/cache/logs/error.log. Строку удалите после проверки.

Показать скидку в корзине



Отдельный плагин на msOnGetStatusCart. Читает тот же ключ ms3CartDiscount.

<?php
if ($modx->event->name !== 'msOnGetStatusCart') {
    return;
}

$discount = $modx->eventData['ms3CartDiscount'] ?? null;

if ($discount === null || ($discount['total'] ?? 0) <= 0) {
    return;
}

$labelParts = [];

if (!empty($discount['parts']['fixed'])) {
    $labelParts[] = '−' . number_format($discount['parts']['fixed'], 0, '', ' ') . ' ₽';
}

if (!empty($discount['parts']['percent']) && !empty($discount['percent'])) {
    $labelParts[] = $discount['percent'] . '%';
}

$label = 'Скидка ' . implode(' + ', $labelParts);

$status = $scriptProperties['status'];
$status['discount_label'] = $label;

$returnedValues = &$modx->event->returnedValues;
$returnedValues['status'] = $status;

В чанке корзины (Fenom): {$status.discount_label}.

Три частые ошибки


  1. Без ссылки на returnedValues. $values = $modx->event->returnedValues; — не сработает. Нужно: $returnedValues = &$modx->event->returnedValues;
  2. Пустая корзина. $cartCost === 0 — плагин выходит, это нормально.
  3. Три плагина на одном событии. Лучше один плагин и $config, чем три файла с разными ключами в eventData.

Дальше


  • Скидка на доставку → msOnGetDeliveryCost
  • Комиссия оплаты → msOnGetPaymentCost
  • Блокировка без остатка → msOnBeforeAddToCart
Иван Бочкарев
Сегодня в 09:10
modx.pro
45
0
Поблагодарить автора Отправить деньги

Комментарии: 0

Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.
0