Как суммировать опции к старой цене в minishop2

    При работе с интернет-магазином на MODX Revolution и компонентом miniShop2 часто возникает ситуация, когда новая цена товара корректно суммируется с выбранными опциями, а старая цена остаётся без изменений. Это приводит к некорректному отображению скидки. В этой статье мы подробно разберём, как настроить чанк вывода цен так, чтобы старая цена также учитывала надбавки от опций.

    Почему старая цена не суммируется с опциями?

    Стандартный чанк вывода цен в miniShop2 использует плейсхолдеры {$price} и {$old_price}. При этом опции (например, выбор размера, цвета или дополнительной услуги) добавляются к цене через JavaScript-сниппет msOptionsPrice, который обновляет только msoptionsprice-cost - элемент с текущей ценой. Для старой цены (msoptionsprice-old-cost) аналогичный механизм не предусмотрен по умолчанию.

    Таким образом, при выборе опции новая цена увеличивается, а старая остаётся прежней, что визуально искажает скидку. Чтобы это исправить, нужно модифицировать JS-обработчик и добавить в чанк правильные классы.

    Пошаговая инструкция по исправлению

    1. Модифицируем чанк вывода цен

    Найдите чанк, который вы используете для отображения цен (например, tpl.msProducts.row или кастомный). Замените блок со старой ценой на следующий код:

    {if $price}
        <div class="product__block-price mb-4">
            <div class="product__price">
                {if $_modx->resource.parent == 12}От {/if}
                <span class="msoptionsprice-cost msoptionsprice-{$_modx->resource.id}">{$price}</span> {'ms2_frontend_currency' | lexicon}
            </div>
            {if $old_price}
                <div class="product__price old-price">
                    <span class="msoptionsprice-old-cost msoptionsprice-{$_modx->resource.id}">{$old_price}</span> {'ms2_frontend_currency' | lexicon}
                </div>
            {/if}
        </div>
    {/if}

    Обратите внимание, что у старой цены должен быть класс msoptionsprice-old-cost и идентификатор товара msoptionsprice-{$_modx->resource.id}. Это позволит JS-сценариям обращаться к этому элементу.

    2. Добавляем поддержку old_cost в JavaScript

    Сниппет msOptionsPrice обычно подключается через файл msoptionsprice.js. Откройте его и найдите функцию, которая обновляет цену при выборе опции. Внутри неё нужно добавить расчёт старой цены с опциями. Примерный код:

    // Находим элемент старой цены
    var oldCostElement = $('.msoptionsprice-old-cost.msoptionsprice-' + resourceId);
    if (oldCostElement.length) {
        // Старая цена = базовая старая цена + сумма опций
        var oldPrice = parseFloat(oldCostElement.data('old-price')) || 0;
        var optionsSum = 0;
        // Суммируем выбранные опции (логика аналогична расчёту новой цены)
        // ...
        oldCostElement.text(formatPrice(oldPrice + optionsSum));
    }

    В этом коде мы получаем базовую старую цену из data-атрибута data-old-price, который нужно заранее задать в HTML. Затем прибавляем сумму выбранных опций и обновляем отображение.

    3. Добавляем data-атрибут в чанк

    Чтобы хранить базовую старую цену (без опций), добавьте к элементу msoptionsprice-old-cost атрибут data-old-price:

    <span class="msoptionsprice-old-cost msoptionsprice-{$_modx->resource.id}" data-old-price="{$old_price|default:0}">{$old_price}</span>

    Теперь при загрузке страницы в этом атрибуте будет храниться исходная старая цена, и JS сможет её использовать для расчётов.

    Альтернативный способ: использовать готовое расширение

    Если вы не хотите править JS-файлы вручную, можно установить дополнение msOptionsPrice2 или msPriceCorrection. Они уже включают функционал суммирования опций как к новой, так и к старой цене. Однако учтите, что такие решения могут конфликтовать с кастомными доработками.

    Часто задаваемые вопросы

    Что делать, если после изменений старая цена перестала отображаться?

    Проверьте, что в чанке присутствует условие {if $old_price} - если старая цена равна 0 или не задана, блок не выведется. Убедитесь, что в товаре заполнено поле old_price.

    Можно ли обновлять старую цену без перезагрузки страницы?

    Да, описанный выше метод с JavaScript обновляет старую цену динамически, без перезагрузки. Главное - правильно привязать обработчики к событиям выбора опций.

    Почему в некоторых темах старую цену не суммируют?

    Это связано с тем, что разработчики шаблонов часто копируют стандартный чанк miniShop2, где старая цена выводится без класса msoptionsprice-old-cost. JS-скрипт не видит элемент и не обновляет его. Решение - добавить правильный класс и data-атрибут.

    Часто задаваемые вопросы