diff --git a/CHANGELOG.md b/CHANGELOG.md
index 1a63b23d..bbf400e9 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,6 @@
+## 2025-09-26 v6.7.5
+- Добавлена опция обновления участий программы лояльности
+
## 2025-08-29 v6.7.4
- Обновлен тип данных у стоимости доставки
diff --git a/intaro.retailcrm/classes/general/user/RetailCrmUser.php b/intaro.retailcrm/classes/general/user/RetailCrmUser.php
index dc454941..28581211 100644
--- a/intaro.retailcrm/classes/general/user/RetailCrmUser.php
+++ b/intaro.retailcrm/classes/general/user/RetailCrmUser.php
@@ -12,6 +12,8 @@
IncludeModuleLangFile(__FILE__);
use Bitrix\Main\UserTable;
+use Retailcrm\ApiClient;
+use Throwable;
/**
* Class RetailCrmUser
@@ -207,7 +209,7 @@ public static function fixDateCustomer(): void
COption::SetOptionString(RetailcrmConstants::MODULE_ID, RetailcrmConstants::OPTION_FIX_DATE_CUSTOMER, 'Y');
$startId = COption::GetOptionInt(RetailcrmConstants::MODULE_ID, RetailcrmConstants::OPTION_FIX_DATE_CUSTOMER_LAST_ID, 0);
- $api = new RetailCrm\ApiClient(RetailcrmConfigProvider::getApiUrl(), RetailcrmConfigProvider::getApiKey());
+ $api = new ApiClient(RetailcrmConfigProvider::getApiUrl(), RetailcrmConfigProvider::getApiKey());
$optionsSitesList = RetailcrmConfigProvider::getSitesList();
$limit = 50;
$offset = 0;
@@ -221,7 +223,7 @@ public static function fixDateCustomer(): void
'limit' => $limit,
'offset' => $offset,
]);
- } catch (\Throwable $exception) {
+ } catch (Throwable $exception) {
Logger::getInstance()->write($exception->getMessage(), 'fixDateCustomers');
break;
@@ -234,14 +236,10 @@ public static function fixDateCustomer(): void
}
foreach ($users as $user) {
- $site = null;
-
- if ($optionsSitesList) {
- if (isset($user['LID']) && array_key_exists($user['LID'], $optionsSitesList) && $optionsSitesList[$user['LID']] !== null) {
- $site = $optionsSitesList[$user['LID']];
- } else {
- continue;
- }
+ $site = RetailcrmConfigProvider::getUserSite($user, $optionsSitesList);
+
+ if ($optionsSitesList && $site === null) {
+ continue;
}
$customer['externalId'] = $user['ID'];
@@ -251,7 +249,7 @@ public static function fixDateCustomer(): void
$customer['createdAt'] = $date->format('Y-m-d H:i:s');
RCrmActions::apiMethod($api, 'customersEdit', __METHOD__, $customer, $site);
- } catch (\Throwable $exception) {
+ } catch (Throwable $exception) {
Logger::getInstance()->write($exception->getMessage(), 'fixDateCustomers');
continue;
}
@@ -264,4 +262,102 @@ public static function fixDateCustomer(): void
$offset += $limit;
}
}
+
+ public static function updateLoyaltyAccountIds(): bool
+ {
+ $api = new ApiClient(RetailcrmConfigProvider::getApiUrl(), RetailcrmConfigProvider::getApiKey());
+ $offset = 0;
+ $limit = 50;
+ $optionsSitesList = RetailcrmConfigProvider::getSitesList();
+ $status = true;
+
+ while (true) {
+ try {
+ $usersResult = UserTable::getList([
+ 'select' => ['ID', 'UF_REG_IN_PL_INTARO', 'LID', 'UF_LP_ID_INTARO'],
+ 'filter' => ['=UF_REG_IN_PL_INTARO' => true],
+ 'order' => ['ID'],
+ 'limit' => $limit,
+ 'offset' => $offset
+ ]);
+ } catch (Throwable $exception) {
+ Logger::getInstance()->write($exception->getMessage(), 'loyaltyIdsUpdate');
+
+ $status = false;
+
+ break;
+ }
+
+ $users = $usersResult->fetchAll();
+
+ if ($users === []) {
+ break;
+ }
+
+ $offset += $limit;
+
+ foreach ($users as $user) {
+ $site = RetailcrmConfigProvider::getUserSite($user, $optionsSitesList);
+
+ if ($optionsSitesList && $site === null) {
+ continue;
+ }
+
+ $filter['customerExternalId'] = $user['ID'];
+
+ try {
+ $actualLoyalty = null;
+ $crmAccounts = RCrmActions::apiMethod($api, 'getLoyaltyAccounts', __METHOD__, $filter, $site);
+
+ foreach ($crmAccounts['loyaltyAccounts'] as $crmAccount) {
+ $loyalty = $crmAccounts = RCrmActions::apiMethod(
+ $api,
+ 'getLoyaltyLoyalty',
+ __METHOD__,
+ $crmAccount['loyalty']['id'],
+ $site
+ );
+
+ if ($loyalty['loyalty']['active'] === true) {
+ $actualLoyalty = $crmAccount;
+
+ break;
+ }
+ }
+
+ if ($actualLoyalty !== null && $user['UF_LP_ID_INTARO'] != $actualLoyalty['id']) {
+ $updateUser = new CUser;
+ $cardNumber = isset($actualLoyalty['cardNumber']) ? $actualLoyalty['cardNumber'] : '';
+
+ $fields = [
+ 'UF_LP_ID_INTARO' => $actualLoyalty['id'],
+ 'UF_CARD_NUM_INTARO' => $cardNumber
+ ];
+
+ if ($updateUser->Update($user['ID'], $fields)) {
+ Logger::getInstance()->write(
+ sprintf('Обновлен идентификатор участия ПЛ для пользователя с ID %s', $user['ID']),
+ 'loyaltyIdsUpdate'
+ );
+ }
+ }
+ } catch (Throwable $exception) {
+ Logger::getInstance()->write($exception->getMessage(), 'loyaltyIdsUpdate');
+
+ continue;
+ }
+
+ time_nanosleep(0, 550000000);
+ }
+ }
+
+ return $status;
+ }
+
+ public static function updateLoyaltyAccountIdsAgent()
+ {
+ self::updateLoyaltyAccountIds();
+
+ return '';
+ }
}
diff --git a/intaro.retailcrm/description.ru b/intaro.retailcrm/description.ru
index 151d099d..2ffb24a1 100644
--- a/intaro.retailcrm/description.ru
+++ b/intaro.retailcrm/description.ru
@@ -1 +1 @@
-- Обновлен тип данных у стоимости доставки
+- Добавлена опция обновления участий программы лояльности
diff --git a/intaro.retailcrm/install/version.php b/intaro.retailcrm/install/version.php
index 07212f76..d9d0bf8d 100644
--- a/intaro.retailcrm/install/version.php
+++ b/intaro.retailcrm/install/version.php
@@ -1,6 +1,6 @@
'6.7.4',
- 'VERSION_DATE' => '2025-08-29 9:30:00'
+ 'VERSION' => '6.7.5',
+ 'VERSION_DATE' => '2025-09-26 9:30:00'
];
diff --git a/intaro.retailcrm/lang/en/options.php b/intaro.retailcrm/lang/en/options.php
index 3a7912c6..8db35ff2 100644
--- a/intaro.retailcrm/lang/en/options.php
+++ b/intaro.retailcrm/lang/en/options.php
@@ -23,6 +23,9 @@
$MESS ['COUPON_CUSTOM_FIELD'] = 'Select a custom field in the CRM to transfer the applied coupon in the Bitrix order';
$MESS ['SELECT_VALUE'] = '-- Select a value --';
$MESS ['ORDER_UPLOAD'] = 'Re-upload orders';
+$MESS ['LP_IDS_UPDATE'] = 'Update participations';
+$MESS ['IDS_UPDATED'] = 'Task successfully created';
+$MESS ['IDS_NOT_UPDATED'] = 'Task not created. Error';
$MESS ['LP_WARNING'] = 'Loyalty program of RetailCRM is available only with the “Uploading orders by event” options active';
$MESS ['ORDER_NUMBER'] = 'Order numbers: ';
$MESS ['ORDER_UPLOAD_INFO'] = 'Click "Start uploading" to upload all the orders . Or list the required order IDs separated by commas, intervals or dashes. For example: 1, 3, 5-10, 12, 13... etc.';
diff --git a/intaro.retailcrm/lang/ru/options.php b/intaro.retailcrm/lang/ru/options.php
index 92797a91..5f388882 100644
--- a/intaro.retailcrm/lang/ru/options.php
+++ b/intaro.retailcrm/lang/ru/options.php
@@ -160,6 +160,8 @@
$MESS ['LP_DEF_TEMP_CREATE_MSG'] = 'Заменить шаблон .default компонента sale.order.ajax шаблоном с функциями Программы лояльности.
Если в папке .local уже есть шаблон .default для sale.order.ajax, то он будет скопирован в папку .default_backup';
$MESS ['LOYALTY_PROGRAM_TITLE'] = 'Программа лояльности';
+$MESS ['IDS_UPDATED'] = 'Агент для обновления участий ПЛ создан';
+$MESS ['IDS_NOT_UPDATED'] = 'Ошибка при добавлении агента';
$MESS ['LOYALTY_PROGRAM_TOGGLE_MSG'] = 'Активность программы лояльности';
$MESS ['LP_CUSTOM_TEMP_CREATE_MSG'] = 'Создать шаблон intaro.retailCRM для компонента оформления заказа sale.order.ajax c функциями Программы лояльности.
Внимение: если шаблон уже существует, то он будет перезаписан';
$MESS ['LP_DEF_TEMP_CREATE_MSG'] = 'Заменить шаблон .default компонента sale.order.ajax шаблоном с функциями Программы лояльности.
Если в папке .local уже есть шаблон .default для sale.order.ajax, то он будет скопирован в папку .default_backup';
@@ -169,6 +171,7 @@
$MESS ['LP_CUSTOM_TEMP_CREATE_MSG'] = 'Создать шаблон default_loyalty для компонента регистрации %s c функциями Программы лояльности.
Внимание: если шаблон уже существует, то он будет перезаписан';
$MESS ['LP_DEF_TEMP_CREATE_MSG'] = 'Заменить шаблон .default компонента %s шаблоном с функциями Программы лояльности.
Если в папке шаблонов компонента уже будет .default, то он будет скопирован в папку .default_backup';
$MESS ['LP_CREATE_TEMPLATE'] = 'Создать шаблон';
+$MESS ['LP_IDS_UPDATE'] = 'Обновить участия';
$MESS ['LP_REPLACE_TEMPLATE'] = 'Заменить шаблон';
$MESS ['LP_SALE_ORDER_AJAX_HEAD'] = ' Управление компонентом Оформление заказа (sale.order.ajax)';
$MESS ['LP_TEMP_CHOICE_MSG'] = 'Выберите, в каких шаблонах сайта будет доступен шаблон компонента с функциями Программы лояльности:';
diff --git a/intaro.retailcrm/lib/component/configprovider.php b/intaro.retailcrm/lib/component/configprovider.php
index 2102d923..cda06eeb 100644
--- a/intaro.retailcrm/lib/component/configprovider.php
+++ b/intaro.retailcrm/lib/component/configprovider.php
@@ -1320,4 +1320,24 @@ public static function getStatusCollector()
{
return static::getOption(Constants::CRM_COLLECTOR, 'N');
}
+
+ /**
+ * @param array|null $optionsSitesList
+ * @return string|null
+ */
+ public static function getUserSite(array $user, array $optionsSitesList): ?string
+ {
+ if (!$optionsSitesList) {
+ return null;
+ }
+
+ if (isset($user['LID']) &&
+ array_key_exists($user['LID'], $optionsSitesList) &&
+ $optionsSitesList[$user['LID']] !== null
+ ) {
+ return $optionsSitesList[$user['LID']];
+ }
+
+ return null;
+ }
}
diff --git a/intaro.retailcrm/lib/component/constants.php b/intaro.retailcrm/lib/component/constants.php
index c0ece108..917e4f58 100644
--- a/intaro.retailcrm/lib/component/constants.php
+++ b/intaro.retailcrm/lib/component/constants.php
@@ -18,7 +18,7 @@
*/
class Constants
{
- public const MODULE_VERSION = '6.7.4';
+ public const MODULE_VERSION = '6.7.5';
public const CRM_PURCHASE_PRICE_NULL = 'purchasePrice_null';
public const BITRIX_USER_ID_PREFIX = 'bitrixUserId-';
public const CRM_USERS_MAP = 'crm_users_map';
diff --git a/intaro.retailcrm/lib/controller/adminpanel.php b/intaro.retailcrm/lib/controller/adminpanel.php
index 49f02c9c..959f5e7c 100644
--- a/intaro.retailcrm/lib/controller/adminpanel.php
+++ b/intaro.retailcrm/lib/controller/adminpanel.php
@@ -6,7 +6,7 @@
use Bitrix\Main\Engine\Controller;
use Intaro\RetailCrm\Component\ConfigProvider;
use Intaro\RetailCrm\Component\Constants;
-
+use CAgent;
/**
* @category Integration
* @package Intaro\RetailCrm\Controller
@@ -88,6 +88,29 @@ public function createTemplateAction(array $templates, string $donor, string $re
];
}
+ /**
+ * @return array
+ */
+ public function updateIdsAction(): array
+ {
+ $agentName = 'RetailCrmUser::updateLoyaltyAccountIdsAgent();';
+
+ CAgent::RemoveAgent($agentName, 'intaro.retailcrm');
+
+ $agentId = CAgent::AddAgent(
+ $agentName,
+ 'intaro.retailcrm',
+ 'N',
+ 20,
+ '',
+ 'Y',
+ date('d.m.Y H:i:s', time() + 10),
+ 30
+ );
+
+ return ['success' => $agentId !== false];
+ }
+
/**
* @return string[]
* @throws \Bitrix\Main\ArgumentOutOfRangeException
diff --git a/intaro.retailcrm/options.php b/intaro.retailcrm/options.php
index 8023da3a..925d167f 100644
--- a/intaro.retailcrm/options.php
+++ b/intaro.retailcrm/options.php
@@ -1514,6 +1514,27 @@ function createTemplates(donor) {
});
}
+ function updateIds() {
+ BX.ajax.runAction('intaro:retailcrm.api.adminpanel.updateIds',
+ {
+ data: {
+ sessid: BX.bitrix_sessid()
+ }
+ }
+ ).then(result => {
+ if (result.data.success === true) {
+ BX.UI.Notification.Center.notify({
+ content: "= GetMessage('IDS_UPDATED') ?>"
+ });
+ } else {
+ BX.UI.Notification.Center.notify({
+ content: "= GetMessage('IDS_NOT_UPDATED') ?>"
+ });
+ }
+
+ });
+ }
+
function replaceDefaultTemplates(donor) {
let templates = [];
let i = 0;
@@ -2371,6 +2392,13 @@ function updateAddressList()
+