Механизм индивидуальной скидки

В CMS 1С-Битрикс есть очень мощная система установки скидок на товары и на заказы. С помощью этой системы можно, в принципе, построить почти любые правила. Почти! Чего не хватает - это возможность персональной установки скидок для каждого конкретного пользователя... Разработанный мной несколько лет назад алгоритм позволяет решить эту задачу.

В CMS 1С-Битрикс есть очень мощная система установки скидок на товары и на заказы. С помощью этой системы можно, в принципе, построить почти любые правила. Почти! Чего не хватает - это возможность персональной установки скидок для каждого конкретного пользователя... Разработанный мной несколько лет назад алгоритм позволяет решить эту задачу.

Итак, небольшое описание логики алгоритма.

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

Конечно, в таком случае нужно еще и параметры кеширования компонентов править, чтобы пользователю показывалась правильная цена.

Итак, обработчики. Создаем обработчик определения минимальной цены:

AddEventHandler("catalog", "OnGetOptimalPrice", "OnGetOptimalPriceHandler");
function OnGetOptimalPriceHandler($ProductID, $quantity, $arUserGroups, $reneval, $arPrices, $site_id, $arDiscountCoupons)
{
    // если пользователь авторизован - оставляем механизм определения минимальной цены по умолчанию:
    if ($GLOBALS['USER']->GetID() <= 0) return true;

    // получаем информацию о пользовательской скидке:
    $USER_DISCOUNT = GetUserDiscounts();

    // дальше у меня у товара есть привязка к ценовой группе - некий тип товара.
    // получаем значение свойства ценовой группы:
    $db_props = CIBlockElement::GetProperty(CATALOG_IBLOCK_ID, $ProductID, array("sort" => "asc"),
        Array("CODE" => "TSENOVAYA_GRUPPA"));
    if ($ar_props = $db_props->Fetch()) {
        if (strlen($ar_props['VALUE']) > 0) {
            // тут проверяем, привязан ли текущий пользователь к данной ценовой группе:
            $DISCVALUES = $USER_DISCOUNT['VALUES'][$ar_props['VALUE_ENUM']];
            $arPrices = array();
            if (is_array($DISCVALUES) && intval($DISCVALUES['PROPERTY_DISCOUNT_VALUE']) > 0) {
                // если применима пользователю скидка на данный товар, то получаем информацию по ценам на товар:
                $dbProductPrice = CPrice::GetListEx(
                    array(),
                    array("PRODUCT_ID" => $ProductID),
                    false,
                    false,
                    array("*")
                );
                while ($arProducPrice = $dbProductPrice->GetNext()) {
                    $arPrices[$arProducPrice['ID']] = $arProducPrice;

                }

                // опеределяем самостоятельно наименьшую цену:
                $MIN_PRICE_VALUE = false;
                $MIN_PRICE_KEY = false;
                foreach ($arPrices as $PriceKey => $arPrice) {
                    if ($arPrice['GROUP_BUY'] == 'N') continue;

                    if ($MIN_PRICE_VALUE == false) {
                        $MIN_PRICE_KEY = $PriceKey;
                        $MIN_PRICE_VALUE = $arPrice['DISCOUNT_VALUE'];
                    } elseif ($arPrice['DISCOUNT_VALUE'] < $MIN_PRICE_VALUE) {
                        $MIN_PRICE_KEY = $PriceKey;
                        $MIN_PRICE_VALUE = $arPrice['DISCOUNT_VALUE'];
                    }
                }

                if ($MIN_PRICE_KEY !== false) {
                    $arPrices = array($MIN_PRICE_KEY => $arPrices[$MIN_PRICE_KEY]);
                }

                // получаем значение скидки:
                $PersonalDiscount = intval($DISCVALUES['PROPERTY_DISCOUNT_VALUE']);

                // берем цену, с которой нужно работать:
                $BASEPrice = current($arPrices);

                // формируем массив минимальной цены с коррекцией цены на персональную скидку
                $arBASE_PRICE = array(
                    'PRICE' => array(
                        'ID' => $BASEPrice['ID'],
                        'CATALOG_GROUP_ID' => $BASEPrice['CATALOG_GROUP_ID'],
                        'PRICE' => $BASEPrice['PRICE'] * (100 - $PersonalDiscount) / 100,
                        'CURRENCY' => $BASEPrice['CURRENCY'],
                        'ELEMENT_IBLOCK_ID' => $BASEPrice['PRODUCT_ID'],
                    ),
                    'DISCOUNT_PRICE' => $BASEPrice['PRICE'] * (100 - $PersonalDiscount) / 100,
                    'DISCOUNT' => array()
                );
                return $arBASE_PRICE;

            } else return true;

        } else return true;
    } else return true;
}

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

function GetUserDiscounts()
{
    if (CModule::IncludeModule('iblock')) {
        $arResult = array('ENUM' => array(),'VALUES' => array());

        // выбибраем из инфоблока со скидками все правила для текущего пользователя:
        $arSelect = Array("ID", "NAME", "DATE_ACTIVE_FROM", "PROPERTY_USERS", "PROPERTY_DISCOUNT",
            "PROPERTY_TSENOVAYA_GRUPPA");
        $arFilter = Array(
            "IBLOCK_ID" => DISCOUNT_IBLOCK_ID, "ACTIVE_DATE" => "Y",
            "ACTIVE" => "Y", "PROPERTY_USERS" => $GLOBALS['USER']->GetID()
        );
        $res = CIBlockElement::GetList(Array(), $arFilter, false, false, $arSelect);
        while ($arFields = $res->GetNext()) {
            $arResult['ENUM'][$arFields['PROPERTY_TSENOVAYA_GRUPPA_ENUM_ID']] = $arFields;
            $arResult['VALUES'][$arFields['PROPERTY_TSENOVAYA_GRUPPA_VALUE']] = $arFields;
        }

        return $arResult;
    }
}

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

Количество показов: 7897
19.07.2016

Возврат к списку

Если вам была полезна статья можете отблагодарить автора:
Ethereum:

0x16Df809287333C49D3A237296C6248A6c08702Bc

Разработка сайта

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

Сопровождение сайта

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

Работы по сайту

Вы можете подать заявку на выполнение определенного объема работ по сайту. Опишите в заявке объем работ. Это может быть разработка какого-то нового функционала, доработки по имеющемуся функционалу, доработки под требования сео-специалистов. На основании заявки вам будет сформирован бюджет работ, а также названы сроки на выполнение тех или иных работ.