Задача: 1С-Предприятие каждый день выгружает HL справочник на сайт с количеством бонусов контрагента в виде "XML-ID контрагента = Количество бонусов"
Нужно копировать бонусы на внутренний счет пользователя, для возможности дальнейшей оплаты заказов.
В моем случае перерасчет бонусов происходит каждую ночь, с помощью скрипта запускаемого на cron. В течении дня пользователи тратят бонусы, а в 00:00 внутренний счет обновляется согласно HL справочнику.
Таким образом не важно что происходит с бонусами на стороне 1С, в любом случае учтется последнее обновление HL справочника по информации из 1С.
Получаем информацию из HL блока в 1С-Битрикс
Для начала получим информацию из справочника. По XML-ID пользователя найдем его внутренний (Битриксовый) ID и просто выведем на экран:
use Bitrix\Main\Loader;
use Bitrix\Highloadblock as HL;
use Bitrix\Main\UserTable;
Loader::includeModule('highloadblock');
Loader::includeModule('sale');
$hlblockDatas = HL\HighloadBlockTable::getById(5)->fetch();
$entityHlBonus = HL\HighloadBlockTable::compileEntity($hlblockDatas);
$entityDataClassBonus = $entityHlBonus->getDataClass();
// Получаем данные из HL блока с бонусами
$bonusData = $entityDataClassBonus::getList(array(
'select' => array(
'UF_KONTRAGENT',
'UF_SUMMABONUSOV'
),
));
while ($arBonusData = $bonusData->Fetch()) {
// Находим ID пользователя по XML-ID
$userId = UserTable::getList([
'filter' => [
'XML_ID' => $arBonusData['UF_KONTRAGENT']
],
'select' => [
'ID'
]
])->fetch();
echo 'У пользователя с ID ' . $userId['ID') . ' ' . $arBonusData['UF_SUMMABONUSOV'] . ' бонуса';
}
- Подключили модуль HL блоков и из справочника с ID 5 получили поля UF_KONTRAGENT и UF_SUMMABONUSOV.
- Далее, в цикле, с помощью Bitrix\Main\UserTable получлил ID пользователя с переданным в фильтр XML-ID (поле UF_KONTRAGENT). И вывели на экран информацию по бонусам этого пользователя.
Начисление суммы на внутренний счет пользователя через API
Дальше все просто: нам нужно получить внутренний счет пользователя и обновить его баланс суммой полученной из HL справочника.
Замечание по получению информации о счете: для ситуации, когда в HL блоке появляется новый контрагент, у которого еще нет внутреннего счета на сайте. Счет нужно сначала создать, с нулем на балансе, а дальше можно обновлять.
$_SERVER['DOCUMENT_ROOT'] = realpath(dirname(__FILE__) . '/../..');
define('NO_KEEP_STATISTIC', true);
define('NOT_CHECK_PERMISSIONS', true);
define('BX_NO_ACCELERATOR_RESET', true);
require($_SERVER['DOCUMENT_ROOT'] . '/bitrix/modules/main/include/prolog_before.php');
@set_time_limit(0);
@ignore_user_abort(true);
use Bitrix\Main\Loader;
use Bitrix\Highloadblock as HL;
use Bitrix\Main\UserTable;
Loader::includeModule('highloadblock');
Loader::includeModule('sale');
$hlblockDatas = HL\HighloadBlockTable::getById(5)->fetch();
$entityHlBonus = HL\HighloadBlockTable::compileEntity($hlblockDatas);
$entityDataClassBonus = $entityHlBonus->getDataClass();
// Получаем данные из HL блока с бонусами
$bonusData = $entityDataClassBonus::getList(array(
'select' => array(
'UF_KONTRAGENT',
'UF_SUMMABONUSOV'
),
));
while ($arBonusData = $bonusData->Fetch()) {
if (!empty($arBonusData['UF_KONTRAGENT'])) {
// Получаем ID пользователя зная его XML_ID из HL
$userId = UserTable::getList([
'filter' => [
'XML_ID' => $arBonusData['UF_KONTRAGENT']
],
'select' => [
'ID'
]
])->fetch();
if (!empty($userId['ID'])) {
// Получаем информацию о текущем счете пользователя
$userCurrentAccount = CSaleUserAccount::GetByUserID(
$userId['ID'],
"RUB"
);
// Если у пользователя еще нет счета создаем с нулем на балансе
if (empty($userCurrentAccount)) {
CSaleUserAccount::add(array(
'USER_ID' => $userId['ID'],
'CURRENCY' => 'RUB',
'CURRENT_BUDGET' => '0'
));
$userCurrentAccount = CSaleUserAccount::GetByUserID(
$userId['ID'],
"RUB"
);
}
// Обновляем сумму на счете из HL
CSaleUserAccount::update($userCurrentAccount['ID'], array(
'CURRENT_BUDGET' => $arBonusData['UF_SUMMABONUSOV']
));
unset($userId, $userCurrentAccount);
}
}
}
require($_SERVER['DOCUMENT_ROOT'] . '/bitrix/modules/main/include/epilog_after.php');
Привел готовый код для запуска его на crontab задании, если у вас пользователей не много, можно сделать агента. В моем случае более 100 тыс. пользователей и crontab задание более приемлимо - отрабатывает минут за 10
Суть проста: не важно какая сумма на счету пользователя до запуска скрипта, она обновиться суммой указанной в $arBonusData['UF_SUMMABONUSOV'] с помощью метода CSaleUserAccount::update