Решение протестировано на Bitrix 18.1.8 и позволяет создать новое действие в Правилах работы с корзиной.
У текущей версии сайта есть стандартный набор действий:
- Изменить стоимость товаров в корзине
- Изменить стоимость доставки
- Предоставить подарок
Мы же добавим новое действие в рамках API Bitrix и назовём его Изменить бонусный баланс
Данное действие будет начислять дополнительные бонусны баллы на личный счёт покупателя Битрикс.
1. Создадим отдельный класс по образу и подобию Bitrix но где нибудь в отдельном месте
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 |
<?php //bitrix/php_interface/Sale/Salebonus.php /** * Добавляет новое действие в правила работы корзины для Маркетинга */ use Bitrix\Main\Loader, Bitrix\Main\Localization\Loc, Bitrix\Sale; if (!Loader::includeModule('catalog')) return; class CSaleActionCtrlBonusUser extends CSaleActionCtrl { public static function GetControlDescr() { $description = parent::GetControlDescr(); $description['EXECUTE_MODULE'] = 'all';//Для сохранения в таблицу $description['SORT'] = 500; return $description; } public static function GetControlID() { return 'ActSaleBonusUser';//Уникальный идентификатор } public static function GetControlShow($arParams) { $arAtoms = static::GetAtomsEx(false, false); $boolCurrency = false; if (static::$boolInit) { if (isset(static::$arInitParams['CURRENCY'])) { $arAtoms['Unit']['values']['Cur'] = static::$arInitParams['CURRENCY']; $boolCurrency = true; } elseif (isset(static::$arInitParams['SITE_ID'])) { $strCurrency = Sale\Internals\SiteCurrencyTable::getSiteCurrency(static::$arInitParams['SITE_ID']); if (!empty($strCurrency)) { $arAtoms['Unit']['values']['Cur'] = $strCurrency; $boolCurrency = true; } } } if (!$boolCurrency) { unset($arAtoms['Unit']['values']['Cur']); } $arResult = array( 'controlId' => static::GetControlID(), 'group' => false, 'label' => 'Изменить бонусный баланс', 'defaultText' => 'Бонусный баланс', 'showIn' => static::GetShowIn($arParams['SHOW_IN_GROUPS']), 'control' => array( 'Применить к бонусному балансу', $arAtoms['Type'], $arAtoms['Value'], $arAtoms['Unit'] ) ); return $arResult; } public static function GetAtoms() { return static::GetAtomsEx(false, false); } public static function GetAtomsEx($strControlID = false, $boolEx = false) { $boolEx = (true === $boolEx ? true : false); $arAtomList = array( 'Type' => array( 'JS' => array( 'id' => 'Type', 'name' => 'extra', 'type' => 'select', 'values' => array( 'Discount' => Loc::getMessage('BT_SALE_ACT_DELIVERY_SELECT_TYPE_DISCOUNT'), 'DiscountZero' => Loc::getMessage('BT_SALE_ACT_DELIVERY_SELECT_TYPE_DISCOUNT_ZERO'), 'Extra' => Loc::getMessage('BT_SALE_ACT_DELIVERY_SELECT_TYPE_EXTRA'), ), 'defaultText' => Loc::getMessage('BT_SALE_ACT_DELIVERY_SELECT_TYPE_DEF'), 'defaultValue' => 'Discount', 'first_option' => '...' ), 'ATOM' => array( 'ID' => 'Type', 'FIELD_TYPE' => 'string', 'FIELD_LENGTH' => 255, 'MULTIPLE' => 'N', 'VALIDATE' => 'list' ) ), 'Value' => array( 'JS' => array( 'id' => 'Value', 'name' => 'extra_size', 'type' => 'input' ), 'ATOM' => array( 'ID' => 'Value', 'FIELD_TYPE' => 'double', 'MULTIPLE' => 'N', 'VALIDATE' => '' ) ), 'Unit' => array( 'JS' => array( 'id' => 'Unit', 'name' => 'extra_unit', 'type' => 'select', 'values' => array( 'Perc' => Loc::getMessage('BT_SALE_ACT_DELIVERY_SELECT_PERCENT'), 'Cur' => Loc::getMessage('BT_SALE_ACT_DELIVERY_SELECT_CUR') ), 'defaultText' => Loc::getMessage('BT_SALE_ACT_DELIVERY_SELECT_UNIT_DEF'), 'defaultValue' => 'Perc', 'first_option' => '...' ), 'ATOM' => array( 'ID' => 'Unit', 'FIELD_TYPE' => 'string', 'FIELD_LENGTH' => 255, 'MULTIPLE' => 'N', 'VALIDATE' => '' ) ) ); if (!$boolEx) { foreach ($arAtomList as &$arOneAtom) { $arOneAtom = $arOneAtom['JS']; } if (isset($arOneAtom)) unset($arOneAtom); } return $arAtomList; } public static function GetShowIn($arControls) { return array(CSaleActionCtrlGroup::GetControlID()); } /** * Функция должна вернуть колбэк того что должно быть выполнено при наступлении условий * @param type $arOneCondition * @param type $arParams * @param type $arControl * @param type $arSubs * @return string */ public static function Generate($arOneCondition, $arParams, $arControl, $arSubs = false) { $mxResult = ''; if (is_string($arControl)) { if ($arControl == static::GetControlID()) { $arControl = array( 'ID' => static::GetControlID(), 'ATOMS' => static::GetAtoms() ); } } $boolError = !is_array($arControl); if (!$boolError) { $arOneCondition['Value'] = (float) $arOneCondition['Value']; $actionParams = array( 'VALUE' => ($arOneCondition['Type'] == 'Extra' ? $arOneCondition['Value'] : -$arOneCondition['Value']), 'UNIT' => ($arOneCondition['Unit'] == 'Cur' ? Sale\Discount\Actions::VALUE_TYPE_FIX : Sale\Discount\Actions::VALUE_TYPE_PERCENT) ); if ($arOneCondition['Type'] == 'DiscountZero' && $arOneCondition['Unit'] == 'Cur') $actionParams['MAX_BOUND'] = 'Y'; //Описываем колбэк $mxResult .= 'include_once($_SERVER[\'DOCUMENT_ROOT\'].\'/bitrix/modules/zixnru.framework/classes/general/_testaction.php\');' . PHP_EOL; $mxResult .= '\Zixnru\Framework\ActionsUserBonusBalans::applyToBonus(' . $arParams['ORDER'] . ', ' . var_export($actionParams, true) . ')'; unset($actionParams); } return $mxResult; } } |
За образец класса взят исходный код Bitrix действия для изменения стоимости доставки, но изменены лишь некоторые методы, которые прокомментированы.
Суть основной функции Generate этого класса в том что формируется PHP код, который затем будет обёрнут в callable функцию и сохранён в таблицу b_sale_discount в столбец APPLICATION. По этому в этой функции мы добавляем подключение файла с классом обработчиком и затем вызов этого обработчика который уже должен выполнить какие либо действия. В обработчик по ссылке передаётся массив заказа и параметры сохранённого действия.
2. Об созданном классе должен узать модуль Bitrix — Sale, по этому в файл init.php нужно добавить строчку
1 2 3 4 5 |
include_once($_SERVER["DOCUMENT_ROOT"] .'/bitrix/php_interface/Sale/Salebonus.php'); $eventManager = \Bitrix\Main\EventManager::getInstance(); $eventManager->addEventHandler('sale', 'OnCondSaleActionsControlBuildList', ['CSaleActionCtrlBonusUser','GetControlDescr'],600); |
В обработчике вы уже вольны сделать любые манипуляции с массивом заказа, в нашем случае мы просто дописываем туда некоторый ключ массива что бы его потом обработать в компоненте заказа.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
<?php //bitrix/modules/zixnru.framework/classes/general/_testaction.php namespace Zixnru\Framework; class ActionsUserBonusBalans { public static function applyToBonus(array &$order, array $action) { if ($action['UNIT'] !== 'F') { return; } $action['VALUE'] = intval($action['VALUE']); if (!isset($order['BONUS_FROM_BALANS_USER'])) { $order['BONUS_FROM_BALANS_USER'] = $action['VALUE']; } else { $order['BONUS_FROM_BALANS_USER'] += $action['VALUE']; } } } |
Если вы так же хотите отловить применённое действие в компоненте заказа, то достаточно обратится к объекту заказа следующим образом:
1 2 3 4 |
$order = $basket->getOrder(); $calcResults = $order->getDiscount()->getApplyResult(true); |
В результате получите список применёных правил корзины к заказу до момента его сохранения.
Как создать действие запрета на заказ для отдельный группы пользователей, если доступное количество торгового предложения равно 1