Задача: после того как заказ, в интернет-магазине, перешел в статус "Выполнен" начислить пользователю 5% от стоимости заказа, на накопительный счет - с которого можно оплатить будущие заказы.
Для этого нам нужно событие смены статуса заказа OnSaleStatusOrder или (вариант в новом ядре) OnSaleStatusOrderChange и метод CSaleUserAccount::UpdateAccount изменяющий сумму на счете пользователя
Добавим следующий код в init.php, пояснения ниже
use Bitrix\Main\Loader;
AddEventHandler("sale", "OnSaleStatusOrder", "OrderComplete");
function OrderComplete($orderID, &$arFields)
{
Loader::includeModule("sale");
if ($arFields == 'F') {
$order = \Bitrix\Sale\Order::load($orderID);
$orderUser = $order->getUserId();
$orderSumm = $order->getPrice();
$bonusPercent = orderSumm * 5 / 100;
CSaleUserAccount::UpdateAccount(
$orderUser,
$bonusPercent,
"RUB",
false,
$orderID,
false
);
}
}
- Подключили модуль sale Loader::includeModule("sale");;
- Проверили, что статус заказ перешел в выполнен if ($arFields == 'F') ;
- Зная id заказа, из переменной $orderID, получили ID пользователя $orderUser = $order->getUserId(); и сумму заказа $orderSumm = $order->getPrice();;
- Высчитали 5% из стоимости заказа $bonusPercent;
- Методом CSaleUserAccount::UpdateAccount начислил пользователю сумму бонуса, основанием сделали ID заказа;
В личном кабинете можно вывести историю начислений и списаний, например так:

Начислить процент без учета стоимости доставки и без учета оплаты с накопительного счета
Расширяем задачу: нужно начислять 10% но при этом учитывать только стоимость товаров, без учета стоимости доставки. Дополнительно, не учитываем полную или частичную оплату с внутреннего счета. То есть: начисляем бонус, только на реально потраченные деньги.
use Bitrix\Main\Loader;
AddEventHandler("sale", "OnSaleStatusOrder", "OrderComplete");
function OrderComplete($orderID, &$arFields)
{
Loader::includeModule("sale");
if ($arFields == 'F') {
$order = \Bitrix\Sale\Order::load($orderID);
$orderUser = $order->getUserId();
$orderSumm = $order->getPrice();
$orderDeliveryPrice = $order->getDeliveryPrice();
$orderPayments = \Bitrix\Sale\PaymentCollection::getList([
'select' => ['SUM'],
'filter' => [
'=ORDER_ID' => $orderID,
'=PAY_SYSTEM_ID' => 13,
'=PAID' => 'Y']
]);
while ($orderPayment = $orderPayments->fetch()) {
$orderPayid = $orderPayment['SUM'];
}
// Общая сумма минус доставка и минус накопительный счет
if (empty($orderPayid)) {
$realOrderPrice = $orderSumm - $orderDeliveryPrice;
} else {
$realOrderPrice = $orderSumm - $orderDeliveryPrice - $orderPayId;
}
$bonusPercent = $realOrderPrice * 10 / 100;
CSaleUserAccount::UpdateAccount(
$orderUser,
$bonusPercent,
"RUB",
false,
$orderID,
false
);
}
}
}
}
Дополнительно, к коду из первого варианта добавили:
- Получили стоимость доставки $orderDeliveryPrice = $order->getDeliveryPrice();;
- Получили коллекцию оплат для заказа $orderPayments = \Bitrix\Sale\PaymentCollection::getList, отфильтровав только оплату с внутреннего счета с 'select' => ['SUM'], - так как нам нужн только сумма оплаты;
- В переменной $realOrderPrice высчитали сумму заказа за минусом стоимости доставки и оплаты с накопительного счета;
Усложнение. Процент для начисления в зависимости от суммы заказа
Расширяем задачу, дальше: начислять разный процент, на внутренний счет, в зависимости от стоимости заказа.
Создаем и заполняем HL инфоблок с пользовательскими полями:
- 'UF_BONUS_FROM' - Стоимость заказа от
- UF_BONUS_TO' - Стоимость заказа до
- UF_BONUS_PRICE' - Величина процента начисления
После наполнения:

И расширяем код из примеров выше:
use Bitrix\Main\Loader;
use Bitrix\Highloadblock as HL;
use Bitrix\Main\Entity;
AddEventHandler("sale", "OnSaleStatusOrder", "OrderComplete");
function OrderComplete($orderID, &$arFields)
{
Loader::includeModule("sale");
Loader::includeModule("highloadblock");
if ($arFields == 'F') {
$order = \Bitrix\Sale\Order::load($orderID); // 123 - ID заказа
$orderUser = $order->getUserId();
$orderSumm = $order->getPrice();
$orderDeliveryPrice = $order->getDeliveryPrice();
$orderPayments = \Bitrix\Sale\PaymentCollection::getList([
'select' => ['SUM'],
'filter' => [
'=ORDER_ID' => $orderID,
'=PAY_SYSTEM_ID' => 13,
'=PAID' => 'Y']
]);
while ($orderPayment = $orderPayments->fetch()) {
$orderPayid = $orderPayment['SUM'];
}
if (empty($orderPayid)) {
$orderPriceBonus = $orderSumm - $orderDeliveryPrice;
} else {
$orderPriceBonus = $orderSumm - $orderDeliveryPrice - $orderPayid;
}
$hlblockDatas = HL\HighloadBlockTable::getById(5)->fetch();
$entityHlBonus = HL\HighloadBlockTable::compileEntity($hlblockDatas);
$entityDataClassBonus = $entityHlBonus->getDataClass();
$bonusData = $entityDataClassBonus::getList(array(
'select' => array('UF_BONUS_FROM', 'UF_BONUS_TO', 'UF_BONUS_PRICE'),
));
while ($arBonusData = $bonusData->Fetch()) {
$priceFrom = $arBonusData['UF_BONUS_FROM'];
$priceTo = $arBonusData['UF_BONUS_TO'];
if (($orderPriceBonus > $priceFrom) && ($orderPriceBonus < $priceTo)) {
$priceBonus = $arBonusData['UF_BONUS_PRICE'];
$summToAddBonus = $orderPriceBonus * $priceBonus / 100;
CSaleUserAccount::UpdateAccount(
$orderUser,
$summToAddBonus,
"RUB",
false,
$orderID,
false
);
}
}
}
}
- Подключили модуль Hl инфоблоков Loader::includeModule("highloadblock");
- Минимальное и максимальное значения, из HLблока загоняем в переменные $priceFrom и $priceTo
- Получили значения пользовательских полей инфоблока и отсекли диапазаон подпадающий под условия начисления
if (($orderPriceBonus > $priceFrom) && ($orderPriceBonus < $priceTo))
Поддержать выпуски видео уроков, поблагодарить за полезную инструкцию или заметку можно через:
Юманей

Цитата |
---|
Ksyusha Darovykh написал: Здравствуйте, можете дать наводку/пример, как Вы вывели историю начислений и списаний? Пыталась написать это в комментариях к теме, не получилось |
История уже есть в компоненте sale.personal.account (Счета текущего пользователя)
Распечатайте массив $arResult этого компонента и увидите все данные, которыми можно манипулировать
Недостающие данные можно получить методом GetByUserID
Код |
---|
Метод возвращает ассоциативный массив параметров счета с валютой currency для пользователя с кодом userID. Нестатический метод. |

Код |
---|
use Bitrix\Main\Loader; |
Parse error: syntax error, unexpected 'use' (T_USE) in /var/www/u0972962/data/www/noutland.ru/mini1c/web/reports/index.php on line 234?

Цитата |
---|
Ольга Стафиевская пишет: Скажите, почему строка [CODE] use Bitrix\Main\Loader; [/CODE] мне выдает ошибку Parse error: syntax error, unexpected 'use' (T_USE) in /var/www/u0972962/data/www/noutland.ru/mini1c/web/reports/index.php on line 234? |
Код |
---|
noutland.ru/mini1c/web/reports/index.php |

Цитата |
---|
Guest пишет: Здравствуйте. Вставляю ваш код, но сайт становится не доступным. Можете подсказать? спасибо большое! |
Цитата |
---|
Михаил Базаров пишет: [QUOTE]Guest пишет: Здравствуйте. Вставляю ваш код, но сайт становится не доступным. Можете подсказать? спасибо большое![/QUOTE] Включите вывод ошибок и скопируйте ее сюда |
/home/b/bazaklfm/bazaklfm.beget.tech/public_html/local/php_interface/init.php:61
#0: require_once
/home/b/bazaklfm/bazaklfm.beget.tech/public_html/bitrix/modules/main/include/prolog_before.php:14
#1: require_once(string)
/home/b/bazaklfm/bazaklfm.beget.tech/public_html/bitrix/modules/main/include/prolog.php:10
#2: require_once(string)
/home/b/bazaklfm/bazaklfm.beget.tech/public_html/bitrix/header.php:1
#3: require(string)
/home/b/bazaklfm/bazaklfm.beget.tech/public_html/refer/tech.php:2

Цитата |
---|
expecting end of file (0) /home/b/bazaklfm/bazaklfm.beget.tech/public_html/local/php_interface/init.php:61 #0: require_once /home/b/bazaklfm/bazaklfm.beget.tech/public_html/bitrix/modules/main/include/prolog_before.php:14 #1: require_once(string) /home/b/bazaklfm/bazaklfm.beget.tech/public_html/bitrix/modules/main/include/prolog.php:10 #2: require_once(string) /home/b/bazaklfm/bazaklfm.beget.tech/public_html/bitrix/header.php:1 #3: require(string) /home/b/bazaklfm/bazaklfm.beget.tech/public_html/refer/tech.php:2 |
Проверьте 61-ую строчку, не хватает или лишняя скобка }