Ошибка сохранения правила неверные данные для условия применения скидки

<?php

// local/php_interface/lib/eventhelpers/SaleActionCustomPrice.php

namespace ProjectNameEventHelpers;

use BitrixMainLoader;

class SaleActionCustomPrice  extends CSaleActionCtrlAction
{
    /**
     * Получение имени класса
     * @return string
     */
    public static function GetClassName()
    {
        return __CLASS__;
    }

    /**
     * Получение ID условия
     * @return array|string
     */
    public static function GetControlID()
    {
        return "DiscountPriceType";
    }

    /**
     * Добавление пункта в список условий с указанием отдельной группы
     * @param $arParams
     * @return array
     * @throws BitrixMainArgumentException
     * @throws BitrixMainLoaderException
     * @throws BitrixMainObjectPropertyException
     * @throws BitrixMainSystemException
     */
    public static function GetControlShow($arParams)
    {
        $arControls = static::GetAtomsEx();
        $arResult = array(
            'controlgroup' => true,
            'group' =>  false,
            'label' => 'Кастомные правила',
            'showIn' => static::GetShowIn($arParams['SHOW_IN_GROUPS']),
            'children' =>  [array(
                'controlId' => static::GetControlID(),
                'group' => false,
                'label' => "Если тип цены не",
                'showIn' => static::GetShowIn($arParams['SHOW_IN_GROUPS']),
                'control' => array(
                    "Если тип цены не",
                    $arControls["PT"]
                )
            )]
        );

        return $arResult;
    }

    /**
     * Формирование данных для визуального представления условия
     * @param bool $strControlID
     * @param bool $boolEx
     * @return array
     * @throws BitrixMainArgumentException
     * @throws BitrixMainLoaderException
     * @throws BitrixMainObjectPropertyException
     * @throws BitrixMainSystemException
     */
    public static function GetAtomsEx($strControlID = false, $boolEx = false)
    {
        $boolEx = (true === $boolEx ? true : false);
        $priceList = [];
        if (Loader::includeModule('main')) {
            // Получение типов цен
            $arGroupPrice = BitrixCatalogGroupTable::getList([
                'select' => ['ID', 'NAME'],
                'cache' => [
                    'ttl' => 60,
                    'cache_joins' => true,
                ]
            ]);

            while ($el = $arGroupPrice->fetch()) {
                $priceList[$el['ID']] = $el['NAME'] . " [" . $el['ID'] . "]";
            }
        }

        $arAtomList = [
            "PT" => [
                "JS" => [
                    "id" => "PT",
                    "name" => "extra",
                    "type" => "select",
                    "values" => $priceList,
                    "defaultText" => "...",
                    "defaultValue" => "",
                    "first_option" => "..."
                ],
                "ATOM" => [
                    "ID" => "PT",
                    "FIELD_TYPE" => "string",
                    "FIELD_LENGTH" => 255,
                    "MULTIPLE" => "N",
                    "VALIDATE" => "list"
                ]
            ],
        ];
        if (!$boolEx) {
            foreach ($arAtomList as &$arOneAtom)
            {
                $arOneAtom = $arOneAtom["JS"];
            }
            if (isset($arOneAtom))
            {
                unset($arOneAtom);
            }
        }

        return $arAtomList;
    }

    /**
     * Функция должна вернуть колбэк того, что должно быть выполнено при наступлении условий
     * @param $arOneCondition
     * @param $arParams
     * @param $arControl
     * @param bool $arSubs
     * @return string
     */
    public static function Generate($arOneCondition, $arParams, $arControl, $arSubs = false)
    {
        return __CLASS__ . '::applyProductDiscount($row,' . $arOneCondition["PT"] . ')';
    }

    /**
     * Логика кастомного условия
     * @param $row
     * @param $priceType
     * @return bool
     */
    public static function applyProductDiscount($row, $priceType)
    {
        return $priceType != $row['PRICE_TYPE_ID'];
    }
}

Реализовал отдельную страницу с формой для массового заказа. Соответственно ввод в форму надо как-то обрабатывать и сохранять в заказ.
Взял принцип отсюда dev.1c-bitrix.ru/support/forum/messages/forum6/top… В целом все устраивает и работает, но проблемы начались, когда потребовалось добавить скидку определенной группе пользователей.
Создал в админке скидки 10% для отдельной роли по моему типу цены.
Захожу, тестирую для данной роли.
Проблема в том, что при сохранении заказа теперь на Add2BasketByProductID валятся ошибки «Ошибка сохранения результатов применения скидок и правил корзины». Заказ при этом создается, но кривой. В админке он помечен как проблемный. Скидки то применяются ко всем товарам, то нет, то к какому-то рандомному, притом, что заказываю всегда одно и то же.
Как можно решить эту проблему?


  • Вопрос задан

    более трёх лет назад

  • 681 просмотр

Настройка скидки на товар

Рассмотрим форму настройки скидки на товары.

Например, создадим скидку 10% на раздел Пантолеты каталога Одежда. Пусть скидка действует в течении месяца.

Форма создания (редактирования) скидки находится на странице административного раздела Маркетинг > Товарный маркетинг > Скидки на товар > Скидки на товар нажмите Новая скидка:

Заполните поля на закладке Скидка:

  • Опция Активность должна быть отмечена, чтобы скидка применялась к товарам каталога.
  • Укажите название скидки в одноименном поле, в нашем случае это Скидка 10% на пантолеты.
  • В поле Сайт выберите сайт интернет-магазина, для товаров которого создаете скидку.
  • Период активности выберите как Интервал и с помощью календаря сделайте этот интервал равным месяцу.

    Важно! Будьте внимательны при настройке дат интервала действия скидки. Если в календаре у вас отключена установка времени, то в соответствующем поле будет установлена только

    дата без времени



    Например, если установлено, что скидка действует до 28.04.2015, то считается, что она действует до 28.04.2015 00:00:00. Таким образом, 28.04.2015 скидка действовать уже не будет.

  • В выпадающем списке Тип скидки можно выбрать одну из следующих форм задания скидки:
    • В процентах — скидка задается в процентах от стоимости товара (указывается в нашем примере);
    • Фиксированная сумма — можно указать определенную сумму скидки в валюте, определенной в поле Валюта скидки;
    • Установить цену на товар — можно указать фиксированную цену на товар после применения скидки в валюте, определенной в поле Валюта скидки.
  • В поле Величина скидки укажите величину скидки (в нашем примере это 10).
  • Поле Валюта скидки определяет, в какой валюте задана скидка (если она представлена в виде фиксированной суммы или цены), а также определяет валюту для Максимальной суммы скидки, если эта сумма задана. Поле Максимальная сумма скидки имеет смысл заполнять, если выбран тип скидки В процентах.

    Примечание: управление валютами, доступными для представления цен и скидок, осуществляется на страницах модуля Валюты (Настройки > Валюты).

  • Чем больше значение Приоритета применимости, тем раньше применится скидка. Помните о том, что приоритет применимости учитывается в рамках одного типа скидок (скидки на товары не будут скоординированы с правилами корзины).
  • Снимите галочку в поле Прекратить дальнейшее применение скидок, чтобы к товарам помимо данной скидки могли быть одновременно применены и другие (

    алгоритм применения

    Скидки применяются в порядке 1) Скидки на товар с учетом введенных купонов; 2) Накопительные программы; 3) Правила корзины
    Подробнее…



    ).
  • Поле Краткое описание служит для задания краткого описания скидки. Размер описания не должен превышать 255 символов.

На закладке Условия задаются условия применения скидки. Укажем, что данная скидка может применяться только для раздела Пантолеты каталога Одежда. Для этого с помощью ссылки Добавить условие задайте соответствующие значения для поле Инфоблок и поле Раздел, соединив данные условия логическим И (

все условия выполнены




):

Примечание: вы можете добавить

группу условий




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

На закладке

Ограничения




можно указать группы пользователей, которые могут воспользоваться данной скидкой, и типы цен, на которые эта скидка распространяется.

Оставим данные параметры неуказанными, что позволит применять скидку всем группам пользователей для всех типов цен товаров.

На закладке Купоны можно добавить купоны к скидке. Мы создаем скидку без купонов, поэтому опцию Создать купоны при сохранении параметров скидки оставляем

неотмеченной




.

Примечание: если для скидки нужно добавить купоны, то следует отметить опцию и указать

тип и число купонов



В результате скидка на товар будет показана в публичном разделе только в корзине после ввода купона.

Когда все параметры заданы, сохраните скидку. Она будет добавлена в общий список, а в публичном разделе созданная нами скидка будет отображаться сразу при просмотре товаров:

Документация по теме:

  • Создание и редактирование скидки на товар

Назад в раздел

Скидки в платформе Битрикс делятся на две большие группы: скидка на товар, скидка на заказ. Также существует множество различных комбинаций и сценариев. 

Чтобы создать систему скидок на сайте важно понимание скидочного механизма. Но прежде, чем мы перейдем к разбору наиболее популярных сценариев скидок, сначала рассмотрим процесс их создания. 

Как создать скидку на Битриксе

Для создания скидок в Битриксе используются правила работы с корзиной. Правила работы с корзиной позволяют задавать различные варианты условий применения скидок к товарам. 

Если в административной панели сайта перейти по пути Маркетинг > Товарный маркетинг > Правила работы с корзиной, то можно увидеть страницу со списком ранее созданных правил работы с корзиной. Для создания новой скидки нужно нажать кнопку Добавить правило.

Правила работы с корзиной

Страница Правила работы с корзиной в Битрикс

Еженедельные и ежемесячные скидки

Подробно рассмотрим создание скидки на примере акции, которая ограничена по времени. Такими акциями часто пользуются супермаркеты и крупные интернет ритейлеры. 

Например, мы хотим создать акцию: “Скидка 18% на чай Earl Gray с 12 по 18 августа”.

В окне создания нового правила в вкладке “Общие параметры” заполняются поля:

  • Активность: отмеченный чекбокс включит скидку рабочей на сайте. 

  • Сайт: оставляется по умолчанию. 

  • Название: вводится название скидки. 

  • Интервал периода активности: в нашем примере указывается время действия скидки с 12 по 18 августа.

  • Приоритет применимости: чем больше число, тем раньше применится скидка. Если к одному товару применяется одновременно несколько скидок, приоритет применимости устанавливает порядок применения скидок.

  • Индекс сортировки: если к одному товару применяются несколько скидок с одинаковым приоритетом применимости, индекс сортировки позволит установить порядок применения, чем меньше число, тем раньше применится скидка в рамках одного приоритета.

  • Прекратить применение скидок на текущем уровне приоритетов: при включенной функции у товара, к которому применяется эта скидка, другие скидки с таким же уровнем приоритета, но с большей сортировкой, чем у текущего правила, применяться к заказу не будут.

  • Прекратить дальнейшее применение правил: при включенном функционале скидки с меньшим приоритетом применимости, чем у текущей, применяться к товару не будут.

Заполнение вкладки Общие параметры Создание скидки на товар в определенный период времени

Во вкладке “Действия и условия” с помощью конструктора настраиваются условия, при которых скидка будет действовать. Условия выбираются через логические операторы (и, или и т. д.), которые меняются по клику на них.

В нашем случае нужно выбрать: Применить скидку 18% к товарам, в которых Поле Товар равно Earl Gray.

Настройка_скидки_на_конкретный_товар

Настройка дополнительных условий при создании скидки на товар

Праздничные скидки

Праздничные скидки всегда ограничены во времени, но посвящены какому-то событию, которое длится один день. 

К разновидностям таких скидок можно отнести “Черная пятница”, “Кибер-понедельник”, “Юбилей магазина” и др. Как правило, такие скидки назначаются сразу на весь ассортимент или отдельные разделы. 

Представим сценарий, когда мы хотим сделать “27 января 2020 года скидку 27% на всю электронику.

На вкладке Действия и условия настройки будут выглядеть как на рисунке. 

Применение скидки к разделам

Применение скидки к разделам

Цена всех товаров из вышеперечисленных разделов, которые окажутся в корзине, будет рассчитываться со скидкой. На остальные товары магазина скидка распространяться не будет действовать.

  Применение_скидки_к_товарам_из_раздела

Применение скидки к товарам из раздела “Электроника”

Товар дня

Однодневная скидка в сочетании с таймером в  карточке товара одна из самых эффективных и лучше других стимулирует к покупке. 

Поэтому мы встраиваем модуль “Товар дня” во все наши интернет магазины, где показываем ограничения не только по времени, но и по количеству оставшихся товаров по акции. Ограничения заставляют клиентов принимать решения быстро.

Пример_отображения_скидки_Товар

Пример отображения скидки “Товар дня” в карточке товара

Работа с модулем происходит в окне создания/редактирования товара.  В отдельной вкладке “Товара дня” указывается:

  • Активируется применение скидки к товару

  • Указывается временной диапазон применения скидки

  • Указывается величина скидки (фиксированная цена, или процент от стоимости)

  • Указывается количество товаров, которые участвуют в акции

  • Также есть возможность автоматического продления акции

Настройка скидки Товар дня

Настройка скидки “Товар дня” на Битрикс

После настройки скидки и ее применения в каталоге товар будет отмечен иконкой “Товар дня”

Лейбл_Товар_дня_в_карточке_товара

Список товаров с акцией “Товар дня”

В карточке товара появится таймер с отсчетом времени действия скидки на товар и доступное количество товара, которое участвует в акции.

Пример_отображения_скидки_Товар

Пример отображения скидки “Товар дня” в карточке товара

Бесплатная доставка 

Скидка может выражаться не только в снижении стоимости товара, но и предоставлению особых условий доставки такого товара. Например, “Бесплатная доставка при покупке свитера”

Настройка_бесплатной_доставки_при

Настройка бесплатной доставки при товара

Прогрессивные скидки

Скидка при достижении определенной суммы — классический прием, который используется как в оптовой, так и розничной торговле. 

Для того чтобы получить скидку, необходимо купить товар на сумму от… Предложение покупателю скидки при покупки товара на большую сумму, может повысить средний чек на 10-20%. Например, “Скидка 5% на сумму заказа от 8000 рублей”

Скидка на общую сумму заказа

Скидка на общую сумму заказа при заказе от…

Количественные скидки

Скидки предоставляемые за покупку определенного количества товаров. 

“Скидка 10% на платье при покупке двух и более аксессуаров»

Скидка_на_платье_при_покупке_от

Скидка на платье при покупке двух и более аксессуаров

Применение_скидки_на_платье_при

Применение скидки на платье при покупке двух разных

Скидки для групп пользователей

В платформе Битрикс можно настроить скидки для определенных групп пользователей (оптовая, клубная, скидка для постоянных клиентов, скидки VIP-клиентов). 

Чтобы настроить такие скидки сначала необходимо создать специальную группу пользователей, например “VIP клиенты” и поместить в нее клиентов. 

Создание группы пользователей

Создание группы пользователей в 1С-Битрикс

Затем при создании скидки в вкладке “Ограничения” указывается группа пользователей, к которой данная скидка будет применяться.

Ограничения скидки

Настройка скидок для определенной группы пользователей в Битрикс

Персональные скидки

Самый известный формат персональной скидки — скидка-купон. Купон привязан к конкретной скидке и представляет собой уникальную последовательность символов. 

Покупателю сообщается код купона, который он вводит в процессе оформления покупки, после чего в к заказу или товару применяется скидка. 

Рассмотрим механизм создания купона. 

На странице правил работы с корзиной открывается на редактирование скидка, к которой будет привязан купон. Во вкладке Купоны нажатием кнопки Добавить можно выбрать действие Добавить один купон или Добавить несколько купонов.

Добавление купона

Добавление купона

В окне создания купона:

  • Отмечается активность купона

  • Вводится название купона, либо генерируется случайная комбинация символов, нажатием кнопки “Сгенерировать купон”

  • Выбирается тип купона:

    • Купон на одну позицию заказа — купон можно применить только к одному товару и только один раз. Если в заказе несколько товаров, то купон применяется к самому дорогому товару;

    • Купон на один заказ — купон можно применить один раз на один любой заказ;

    • Многоразовый купон — купон может применяться к заказам неограниченное количество раз.

  • Отмечается период активности (указывается временной интервал действия купона, либо без ограничений)

  • Если вы хотите создать именной купон, для конкретного клиента, то укажите его из списка пользователей. Если поле оставить пустым воспользоваться купоном сможет любой пользователь

После сохранения купон появиться в общем списке на странице Купоны.

Окно создания купона

Окно создания купона

В результате, когда покупатель введет код купона на странице корзины, система автоматически пересчитает стоимость товара.

Применение купона в корзине

Применение купона в корзине готового решения Мегамарт

Как видите, создание скидок не представляет никакой сложности. Однако, следует придерживаться правила: чем проще, тем лучше. Лучше создать несколько простых скидок, чем в одной учитывать множество условий. Поскольку, если условий в настройках будет очень много, то высока вероятность того, что где-то что-то будет не учтено и может привести к “неожиданному” результату. 

0 / 0 / 0

Регистрация: 12.11.2018

Сообщений: 8

1

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

14.11.2018, 11:10. Показов 3671. Ответов 3


Беда вот в чем:
Созданы множественные скидки на каждый из товаров (при импорте товаров)
Приоритет 1
Сортировка 100

Затем делаю дополнительные правила по акции:

30% на ВСЮ новую коллекцию
Приоритет 5
Сортировка 10
Прекратить применение скидок на текущем уровне приоритетов V

50% на бренд CCC, новой коллекции
Приоритет 5
Сортировка 7
Прекратить применение скидок на текущем уровне приоритетов V

10% на бренд ААА и БББ, новой коллекции
Приоритет 5
Сортировка 5
Прекратить применение скидок на текущем уровне приоритетов V

При просмотре каталога и карточки товара — все ок, процент высчитывается верно.
НО если положить каждого товара из различных скидок в корзину — тут начинается диичь:

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

Те скидки, что стояли изначально у каждого товара (п 1 сорт 100) — ок
А вот остальные все сводятся к одной, естественно с наименьшим показателе сортировки.
Но какого хрена?!!
Как сделать чтобы в каталоге и корзине совпадали правила скидок?

__________________
Помощь в написании контрольных, курсовых и дипломных работ, диссертаций здесь

0

Programming

Эксперт

94731 / 64177 / 26122

Регистрация: 12.04.2006

Сообщений: 116,782

14.11.2018, 11:10

Ответы с готовыми решениями:

В корзине не отображаются скидки
На сайте есть самодельная шкала скидок. Но при добавлении в корзину, эти скидки не срабатывают.

Проклятые потоки.
Нахрена? я изучал и читал и не нашел плюсов. смотрите:
Я создал поток, подключил в него буфером…

Проклятые баннеры
Добрый день, столкнулся с неразрешимой для моего гуманитарного склада проблемой. На различных…

Проклятые функции
Доброго врмени суток, помогите найти ошибку!!!
/после выхода из этой функции func2 нужные мне…

3

436 / 404 / 111

Регистрация: 15.02.2012

Сообщений: 1,715

14.11.2018, 12:20

2

Увы все верно.

Прекратить применение скидок идет не на товар, а на все последующие скидки.
Т.е. как только появляется товар, на который есть скидка с пометкой «Прекратить применение скидок», то весь остальной список скидок больше рассматривается.

для того чтобы это обойти вам нужно правильно:
1. задублировать скидки
2. правильно проставить у всех скидок(и дублей и нет) приоритет и сортировку
3. правильно прописать ограничение «Были применены скидки» да/нет

другого варианта пока нет.

0

0 / 0 / 0

Регистрация: 12.11.2018

Сообщений: 8

14.11.2018, 12:34

 [ТС]

3

Цитата
Сообщение от tgarl
Посмотреть сообщение

2. правильно проставить у всех скидок(и дублей и нет) приоритет и сортировку
3. правильно прописать ограничение «Были применены скидки» да/нет

Вот тут поподробнее можно?
Что будет считаться правильной расстановкой сортировок и ограничений?
Как расставить в нашей ситуации уровни и сортировки?

0

436 / 404 / 111

Регистрация: 15.02.2012

Сообщений: 1,715

14.11.2018, 15:10

4

у вас скорее всего нужно
у 50% на бренд CCC, новой коллекции и 10% на бренд ААА и БББ, новой коллекции если они не пересекаются убрать ограничение «Прекратить применение скидок», если пересекаются задать более жесткие условия чтобы не пересекались, возможно разбив на несколько разных ограничений

у 30% на ВСЮ новую коллекцию убрать «Прекратить применение скидок», но добавить «Были применены скидки» = нет
тогда если не были применены скидки 10 и 50 будет 30

а у Созданы множественные скидки на каждый из товаров (при импорте товаров)
отдельно смотреть какие условия, возможно придется сдвинуть между новых коллекций…

примерно так. Но нужно проверять. У нас на сайте на треть из-за этого пришлось увеличить количество скидок потому как обойтись только старыми подправив правила не удалось

0

IT_Exp

Эксперт

87844 / 49110 / 22898

Регистрация: 17.06.2006

Сообщений: 92,604

14.11.2018, 15:10

4

Содержание

  • Примеры
    • Нарастающие скидки
    • Применение скидки / наценки при выборе точек самовывоза в форме заказа
    • Один купон на разные скидки
    • Одноразовый многоразовый купон

Примеры

В данной главе приведены наиболее яркие, распространенные примеры использования модуля.

Нарастающие скидки

Один из наиболее частых случаев применения модуля — реализация механизма Нарастающие скидки.

Решение данного примера вынесено в отдельный модуль, с возможностями которого можно познакомиться на странице модуля Покупай больше — плати меньше. Документация по модулю доступна на странице..

Применение скидки / наценки при выборе точек самовывоза в форме заказа

Механизм правил работы с корзиной в 1С-Битрикс дает возможность представлять скидки в зависимости от многих условий, таких как: тип плательщика, служба доставки, платежные системы и т.п. Но нет зависимости от выбранной точки самовывоза (склада). Но, как показывает практика, подобное очень часто требуется.

Внимание: Решение задачи рассмотрено на примере дефолтного шаблона компонента sale.order.ajax. В кастомизированных шаблонах решение некоторых моментов может отличаться.

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

Например, имеется 2 склада:

  • Основной склад. (идентификатор склада равно 2)
  • Дополнительный склад. (идентификатор склада равно 3)

Склады

Требуется применить скидку на товары 10%, если покупатель выбрал точку самовывоза Основной склад.

Для этого необходимо:

1) Создать соответствующее
правило работы с корзиной.

Скидка 10%

Скидка 10% - условия применения

Как видно из скриншота, в качестве PHP-выражения указана обычная функция __scoder_check_stores(). Данная функция будет описана в файле
init.php, к ней мы еще вернемся

2) Необходимо определить, какая на данный момент выбрана точка самовывоза. Для этого понадобится обработчик события OnSaleComponentOrderUserResult, подробнее в
документации.

AddEventHandler("sale", "OnSaleComponentOrderUserResult", Array("CScoderClass", "OnSaleComponentOrderUserResultHandler"));
class CScoderClass
{
   const STORE_ID = 2;		//Ид точки самовывоза - Основной склад
   function OnSaleComponentOrderUserResultHandler(
	&$arUserResult,
	$request,
	&$arParams
   )
   {
         //если выбрана точка самовывоза - Основной склад
         if ($arUserResult['BUYER_STORE']==self::STORE_ID)
         {
               $_SESSION['IS_DISCOUNT'] = true;
         }
         else
         {
               $_SESSION['IS_DISCOUNT'] = false;
         }
   }
}

С помощью данного обработчика меняем признак сессии в зависимости от того какую точку самовывоза выбрал покупатель.

3. Описываем PHP-выражение — функцию __scoder_check_stores().

function __scoder_check_stores()
{
   $btrue = false;
   if ($_SESSION['IS_DISCOUNT']===true)
      $btrue = true;
   
   return $btrue;
}

Данная функция проверяет признак сессии и возвращает истину (true) или ложь (false), т.е. применять или нет скидку.

4) Остается доработать шаблон компонента формы заказа sale.order.ajax, чтобы покупатель видел скидку сразу после выбора точки самовывоза,
предварительно скопировав шаблон.

По умолчанию, при выборе точки самовывоза пересчета в форме заказа не происходит, как это, например происходит при смене местоположения или службы, доставки. Поэтому покупатель при выборе точки самовывоза не сразу увидит скидку.

Чтобы это изменить, необходимо внести изменения в js-код формы заказа — в order_ajax.js. Пересчет осуществляется командой BX.Sale.OrderAjaxComponent.sendRequest(). Вызов данной команды необходимо разместить в 2-х местах.

В методе editFadePickUpContent.и в методе initMaps

phpcondition_js1.jpg

phpcondition_js2.jpg

Если вы сделали все правильно, то настроенная вами скидка должна применяться при выборе нужной точки самовывоза.

Один купон на разные скидки

Внимание: В статье приведены фрагменты кода, описывающие принцип реализации. Для внедрения рекомендуется обратиться к разработчикам.

В зависимости от задач функция может быть более сложной. В данном материале описан принцип реализации.

Вопрос предоставления разной величины скидки с учетом стоимости всех товаров в корзине по одному купону не так тривиален.

Например, необходимо решить следующую задачу:

  • 5% — при сумме от 500 руб. до 1 000 руб.
  • 10% — при сумме от 1 000 руб. до 5 000 руб.
  • 15% — при сумме выше 5 000 руб.

Эта задача легко бы решалась, если не одно НО: они должны применяться только при активации купона, причем один купон на всех.

Для решения данной задачи необходимо создать 3 правила работы с корзиной с самими скидками (т.к. в нашем примере их 3) и еще одно правило под купон (назовем его служебным), последнее правило с нулевой скидкой.

В условиях 3-х правил указываем необходимые интервалы применения, а также дополнительное PHP-условие, которое будут доступно после установки модуля. В значении условия укажем функцию, например с названием __check_coupon(), к данной функции мы еще вернемся.
Произвольное PHP условие правил работы с корзиной

Выглядит все это следующим образом:

I. Скидка 5%

Один купон на все скидки - 5%

II. Скидка 10%

Один купон на все скидки - 10%

III. Скидка 15%

Один купон на все скидки - 15%

Также создаем 4-е (служебное) правило, скидку для неё указываем 0% и создаем нужный нам купон, например, SL-WI8UK-QU3ENAW

Служебное правило с купоном

Остается прописать функцию __check_coupon() в файле init.php. В данной функции будем проверять применен или нет наш купон и возвращать истину (true) или ложь (false).

function __check_coupon()
{
	$btrue = false;
	$coupon = "SL-WI8UK-QU3ENAW";	//TODO код купона
	
	//Проверяем примененные купону для текучего пользователя
	$arCoupons = BitrixSaleDiscountCouponsManager::get(true, array(), true, true);
	if (is_array($arCoupons) && array_key_exists($coupon, $arCoupons))
		$btrue = true;
	
	return $btrue;
}

Одноразовый многоразовый купон

В 1С-Битрикс имеются как одноразовые купоны, так и многоразовые.

Как быть, если многоразовый купон необходимо сделать одноразовым? Как это понимать?

Очень просто, бывает стоит задача создать какой то один купон с кодом, например СКИДКА и ограничить его использование одним и тем же пользователем много раз. Т.е. если покупатель уже воспользовался купоном и создал заказ, то чтобы более не мог его использовать. Деактивировать купон или сделать его одноразовым нельзя, т.к. этим же купоном должны иметь возможность воспользоваться другие покупатели.

Внимание: В статье приведены фрагменты кода, описывающие принцип реализации. Для внедрения рекомендуется обратиться к разработчикам.

В зависимости от задач функция может быть более сложной. В данном материале описан принцип реализации.

Конечно, задачу можно решить не одним способом. Но мы предлагаем воспользоваться модулем Произвольное PHP условие правил работы с корзиной.

Принцип реализации не сложен. Также необходимо создать правило для работы с корзиной, создать нужный многоразовый купон. На дополнительных условиях правила прописать произвольную PHP-функцию, которая будет проверять совершал ли покупатель с данным купоном заказ или нет, и возвращать ИСТИНУ (true) или ЛОЖЬ (false). Например функция __sc_check_multi_coupon() (это всего лишь пример, как может выглядеть функция, для внедрения рекомендуется обратиться к разработчикам.):

function __sc_check_multi_coupon()
{
	$btrue = true;
	$ar_orders = array();
	$arFilter = Array(
	   "USER_ID" => $GLOBALS["USER"]->GetID(),
	   "!CANCELED" => "Y",
	);

	$db_sales = CSaleOrder::GetList(
		array("DATE_INSERT" => "desc"), 
		$arFilter,
		false,
		false,
		array("ID")
	);
	while ($ar_sales = $db_sales->Fetch())
	{
		$ar_orders[] = $ar_sales["ID"];
		
	}
	if (count($ar_orders)>0)
	{
		$str_coupons = "КУПОН1,КУПОН2,...,КУПОНN";		//TODO заменить на свои купоны
		$ar = explode(",",$str_coupons);
		if (is_array($ar) && count($ar)>0)
		{
			$ar_coupons = array();
			foreach ($ar as $key => $coupon)
			{
				if (strlen(trim($coupon))>0)
					$ar_coupons[] = trim($coupon);
			}
		}
		if (is_array($ar_coupons))
		{
			$couponList = BitrixSaleInternalsOrderCouponsTable::getList(array(
				'select' => array('COUPON'),
				'filter' => array(
					'=ORDER_ID' => $ar_orders,
					'COUPON' => $ar_coupons
				)
			));
			if ($coupon = $couponList->fetch())
			{
				$btrue = false;
			}
		}
	}
	
	return $btrue;
}

Как известно, в 1С-Битрикс множество разновидностей скидок. Есть и «скидки на товары», и «скидки на заказ», и «купоны скидок», и даже «накопительные скидки». Но вместе они иногда работают не так, как нам нужно.

Рассмотрим пример

В интернет-магазине есть 2 типа скидок:

  • Скидка на товар.
  • Скидка по дисконтной карте, реализованная через купоны.

При оформлении заказа необходимо учитывать бОльшую скидку. Как это сделать?
Приоритеты и галочка «Прекратить дальнейшее применение скидок» здесь решением не являются. Например, скидка на товар 10%, а скидки по дисконтным картам от 5% до 20%.

То есть, если клиент кладет в корзину товар с 10% скидкой, вводит номер дисконтной карты (по ней скидка 20%) и карта не считается. Получается, применяется меньшая скидка.

Решим досадное недоразумение парочкой обработчиков событий.

CModule::IncludeModule('catalog');
 
AddEventHandler("catalog", "OnGetDiscount", 
    array("WeProductDiscountHandler", "OnGetDiscount"));
AddEventHandler("catalog", "OnGetDiscountResult", 
    array("WeProductDiscountHandler", "OnGetDiscountResult"));
 
 
class WeProductDiscountHandler{
 
    protected static $productPrice = null;
 
     @return 
    public function OnGetDiscount($intProductID, $intIBlockID, $arCatalogGroups, 
        $arUserGroups, $strRenewal, $siteID, $arDiscountCoupons, $boolSKU, $boolGetIDS){
 
        
        
        $curProductPrice = CPrice::GetBasePrice($intProductID, false, false, false);
        if($curProductPrice != false){
            self::$productPrice = $curProductPrice;
        }
 
        return true;
    }
 
     @return 
    public function OnGetDiscountResult(&$arResult){
 
        
        if(is_array(self::$productPrice) 
            && isset(self::$productPrice['PRICE']) 
            && self::$productPrice['PRICE'] > 0){
 
            $discounts = array();
            foreach($arResult as $key_discount => $discount){
 
                
                
                switch($discount['VALUE_TYPE']){
 
                    
                    case CCatalogDiscount::TYPE_PERCENT:
                        $discounts[$key_discount] = self::$productPrice['PRICE'] 
                            * ($discount['VALUE'] / 100);
                        break;
 
                    
                    case CCatalogDiscount::TYPE_SALE:
                        $discounts[$key_discount] = self::$productPrice['PRICE'] 
                            - $discount['VALUE'];
                        break;
 
                    
                    case CCatalogDiscount::TYPE_FIX:
                        $discounts[$key_discount] = $discount['VALUE'];
                        break;
 
                    default:
                        break;
                }
 
            }
 
            if(!empty($discounts)){
 
                
                $maxs_discounts = array_keys($discounts, max($discounts));
                if(isset($maxs_discounts[0], $arResult[$maxs_discounts[0]]) 
                    && is_array($arResult[$maxs_discounts[0]])){
 
                    
                    $neededDiscount = $arResult[$maxs_discounts[0]];
                    $arResult = array($neededDiscount);
 
                }
            }
 
        }
 
        self::$productPrice = null;
    }
 
}

На момент написания статьи, версия модуля «Торговый каталог» (catalog) была 14.0.5. Возможно, в поздних версиях это будет решено «из коробки». А пока довольствуемся тем, что есть.

Похожие записи

1C-Битрикс. Кастомизация нового шаблона компонента sale.order.ajax

С выходом нового шаблона компонента sale.order.ajax на форумах битрикса разгораются возмущения и недомения. Мол, теперь код всего шаблона на JavaScript и как его кастомизировать непонятно. На самом деле да, код js-скрипта составляет почти семь тысяч строк. Сходу в таком количестве кода, даже хорошо написанного (к сожалению, битрикс этим не балует), соблюдая паттерны программирования, будет непросто.

В этой заметке я покажу способ, как можно кастомизировать основной скрипт логики шаблона оформления заказа (order_ajax.js), не прибегая к его правке. Что нам это даёт? Когда прилетят очередные обновления шаблона, мы просто заменим его и всё. Все наши кастомизации будут работать (в теории).

Итак, поехали!

1С-Битрикс. Пишем человеческий шаблон многоуровнего меню каталога

Не буду писать про боль при интегации дефотного шаблона. Давайте просто напишем свой, с блекджеком и вот этим всем.

В заметке будет (интересного):

  • построение древовидного массива без рекурсии (неограниченной вложенности)
  • анонимная рекурсивная функция
  • формирование урлов для секций супер-быстрым способом
  • поработаем с сущностями инфоблока через ORM D7

Дальше много кода.

Добавить комментарий

Доброго времени суток! Есть св-во у товаров, правязанное к инфоблоку. Не множественное. По-факту типа бренд. Как мне создать правило корзины чтобы если покупатель положит 7 товаров одного производителя в корзину и 10 товаров другого, то предлагать подарок. То есть нужно чтобы если в корзине 12+ товаров выбранных брендов — предлагать подарок

Это

http://prntscr.com/l4qjpu

правило возвращает ошибку Неверные данные для условия применения скидки
А это

http://prntscr.com/l4qk9t

по понятным причинам применяется только если 12 товаров определённого бренда находится в корзине. Мне же надо чтобы 12 товаров любого из указанных брендов предлагали подарок. Спасибо!


<?php

// local/php_interface/lib/eventhelpers/SaleActionCustomPrice.php

namespace ProjectNameEventHelpers;

use BitrixMainLoader;

class SaleActionCustomPrice  extends CSaleActionCtrlAction
{
    /**
     * Получение имени класса
     * @return string
     */
    public static function GetClassName()
    {
        return __CLASS__;
    }

    /**
     * Получение ID условия
     * @return array|string
     */
    public static function GetControlID()
    {
        return "DiscountPriceType";
    }

    /**
     * Добавление пункта в список условий с указанием отдельной группы
     * @param $arParams
     * @return array
     * @throws BitrixMainArgumentException
     * @throws BitrixMainLoaderException
     * @throws BitrixMainObjectPropertyException
     * @throws BitrixMainSystemException
     */
    public static function GetControlShow($arParams)
    {
        $arControls = static::GetAtomsEx();
        $arResult = array(
            'controlgroup' => true,
            'group' =>  false,
            'label' => 'Кастомные правила',
            'showIn' => static::GetShowIn($arParams['SHOW_IN_GROUPS']),
            'children' =>  [array(
                'controlId' => static::GetControlID(),
                'group' => false,
                'label' => "Если тип цены не",
                'showIn' => static::GetShowIn($arParams['SHOW_IN_GROUPS']),
                'control' => array(
                    "Если тип цены не",
                    $arControls["PT"]
                )
            )]
        );

        return $arResult;
    }

    /**
     * Формирование данных для визуального представления условия
     * @param bool $strControlID
     * @param bool $boolEx
     * @return array
     * @throws BitrixMainArgumentException
     * @throws BitrixMainLoaderException
     * @throws BitrixMainObjectPropertyException
     * @throws BitrixMainSystemException
     */
    public static function GetAtomsEx($strControlID = false, $boolEx = false)
    {
        $boolEx = (true === $boolEx ? true : false);
        $priceList = [];
        if (Loader::includeModule('main')) {
            // Получение типов цен
            $arGroupPrice = BitrixCatalogGroupTable::getList([
                'select' => ['ID', 'NAME'],
                'cache' => [
                    'ttl' => 60,
                    'cache_joins' => true,
                ]
            ]);

            while ($el = $arGroupPrice->fetch()) {
                $priceList[$el['ID']] = $el['NAME'] . " [" . $el['ID'] . "]";
            }
        }

        $arAtomList = [
            "PT" => [
                "JS" => [
                    "id" => "PT",
                    "name" => "extra",
                    "type" => "select",
                    "values" => $priceList,
                    "defaultText" => "...",
                    "defaultValue" => "",
                    "first_option" => "..."
                ],
                "ATOM" => [
                    "ID" => "PT",
                    "FIELD_TYPE" => "string",
                    "FIELD_LENGTH" => 255,
                    "MULTIPLE" => "N",
                    "VALIDATE" => "list"
                ]
            ],
        ];
        if (!$boolEx) {
            foreach ($arAtomList as &$arOneAtom)
            {
                $arOneAtom = $arOneAtom["JS"];
            }
            if (isset($arOneAtom))
            {
                unset($arOneAtom);
            }
        }

        return $arAtomList;
    }

    /**
     * Функция должна вернуть колбэк того, что должно быть выполнено при наступлении условий
     * @param $arOneCondition
     * @param $arParams
     * @param $arControl
     * @param bool $arSubs
     * @return string
     */
    public static function Generate($arOneCondition, $arParams, $arControl, $arSubs = false)
    {
        return __CLASS__ . '::applyProductDiscount($row,' . $arOneCondition["PT"] . ')';
    }

    /**
     * Логика кастомного условия
     * @param $row
     * @param $priceType
     * @return bool
     */
    public static function applyProductDiscount($row, $priceType)
    {
        return $priceType != $row['PRICE_TYPE_ID'];
    }
}

Как отменить правила работы корзины при работающей скидки на товар?

Привет!

Есть скидки на товар. Например, синие платье на этой неделе будет со скидкой 10%.
Так же существует правило работы с корзиной, где имеется скидка 20% на два товара в корзине.

Как отменить применение правила, если у товара есть конкретная скидка? Чтобы не получилось 30% за каждое, а только по 10%.


  • Вопрос задан

    более трёх лет назад

  • 815 просмотров

Пригласить эксперта

Если Битрикс 18 версии и старше и скидки сконвертированы в правила работы с корзиной

В настройках правила работы с корзиной, устанавливающего 20% на два товара укажите
Приоритет применимости больше чем у правила с обычной скидкой
Установите галочку «Прекратить дальнейшее применение правил»


  • Показать ещё
    Загружается…

25 июн. 2023, в 10:30

6000 руб./за проект

25 июн. 2023, в 10:26

15000 руб./за проект

25 июн. 2023, в 09:57

7000 руб./за проект

Минуточку внимания

0 / 0 / 0

Регистрация: 12.11.2018

Сообщений: 8

1

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

14.11.2018, 11:10. Показов 4122. Ответов 3


Студворк — интернет-сервис помощи студентам

Беда вот в чем:
Созданы множественные скидки на каждый из товаров (при импорте товаров)
Приоритет 1
Сортировка 100

Затем делаю дополнительные правила по акции:

30% на ВСЮ новую коллекцию
Приоритет 5
Сортировка 10
Прекратить применение скидок на текущем уровне приоритетов V

50% на бренд CCC, новой коллекции
Приоритет 5
Сортировка 7
Прекратить применение скидок на текущем уровне приоритетов V

10% на бренд ААА и БББ, новой коллекции
Приоритет 5
Сортировка 5
Прекратить применение скидок на текущем уровне приоритетов V

При просмотре каталога и карточки товара — все ок, процент высчитывается верно.
НО если положить каждого товара из различных скидок в корзину — тут начинается диичь:

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

Те скидки, что стояли изначально у каждого товара (п 1 сорт 100) — ок
А вот остальные все сводятся к одной, естественно с наименьшим показателе сортировки.
Но какого хрена?!!
Как сделать чтобы в каталоге и корзине совпадали правила скидок?



0



Programming

Эксперт

94731 / 64177 / 26122

Регистрация: 12.04.2006

Сообщений: 116,782

14.11.2018, 11:10

Ответы с готовыми решениями:

В корзине не отображаются скидки
На сайте есть самодельная шкала скидок. Но при добавлении в корзину, эти скидки не срабатывают.

Проклятые потоки.
Нахрена? я изучал и читал и не нашел плюсов. смотрите:
Я создал поток, подключил в него буфером…

Проклятые баннеры
Добрый день, столкнулся с неразрешимой для моего гуманитарного склада проблемой. На различных…

Проклятые функции
Доброго врмени суток, помогите найти ошибку!!!
/после выхода из этой функции func2 нужные мне…

3

439 / 406 / 113

Регистрация: 15.02.2012

Сообщений: 1,763

14.11.2018, 12:20

2

Увы все верно.

Прекратить применение скидок идет не на товар, а на все последующие скидки.
Т.е. как только появляется товар, на который есть скидка с пометкой «Прекратить применение скидок», то весь остальной список скидок больше рассматривается.

для того чтобы это обойти вам нужно правильно:
1. задублировать скидки
2. правильно проставить у всех скидок(и дублей и нет) приоритет и сортировку
3. правильно прописать ограничение «Были применены скидки» да/нет

другого варианта пока нет.



0



0 / 0 / 0

Регистрация: 12.11.2018

Сообщений: 8

14.11.2018, 12:34

 [ТС]

3

Цитата
Сообщение от tgarl
Посмотреть сообщение

2. правильно проставить у всех скидок(и дублей и нет) приоритет и сортировку
3. правильно прописать ограничение «Были применены скидки» да/нет

Вот тут поподробнее можно?
Что будет считаться правильной расстановкой сортировок и ограничений?
Как расставить в нашей ситуации уровни и сортировки?



0



439 / 406 / 113

Регистрация: 15.02.2012

Сообщений: 1,763

14.11.2018, 15:10

4

у вас скорее всего нужно
у 50% на бренд CCC, новой коллекции и 10% на бренд ААА и БББ, новой коллекции если они не пересекаются убрать ограничение «Прекратить применение скидок», если пересекаются задать более жесткие условия чтобы не пересекались, возможно разбив на несколько разных ограничений

у 30% на ВСЮ новую коллекцию убрать «Прекратить применение скидок», но добавить «Были применены скидки» = нет
тогда если не были применены скидки 10 и 50 будет 30

а у Созданы множественные скидки на каждый из товаров (при импорте товаров)
отдельно смотреть какие условия, возможно придется сдвинуть между новых коллекций…

примерно так. Но нужно проверять. У нас на сайте на треть из-за этого пришлось увеличить количество скидок потому как обойтись только старыми подправив правила не удалось



0



IT_Exp

Эксперт

87844 / 49110 / 22898

Регистрация: 17.06.2006

Сообщений: 92,604

14.11.2018, 15:10

4

  • Ошибка сохранения параметров записи dvr
  • Ошибка сохранения объекта нарушено ограничение уникальности параметра name
  • Ошибка сохранения объекта нарушено ограничение уникальности параметра code
  • Ошибка сохранения неправильный шаблон для сайта битрикс
  • Ошибка сохранения неверное подтверждение пароля