Compare commits
12 commits
Author | SHA1 | Date | |
---|---|---|---|
|
e61259ded9 | ||
|
0359315c79 | ||
|
08ff21ce04 | ||
|
de7ecd4100 | ||
|
54692c50d4 | ||
|
61044988d5 | ||
|
7a36fa5de7 | ||
|
8cf4420592 | ||
|
84c7d10146 | ||
|
8c38d21477 | ||
|
115cf33423 | ||
|
3162031b65 |
26 changed files with 1033 additions and 1374 deletions
2
.github/workflows/ci.yml
vendored
2
.github/workflows/ci.yml
vendored
|
@ -49,7 +49,7 @@ jobs:
|
||||||
run: composer validate
|
run: composer validate
|
||||||
- name: Cache Composer packages
|
- name: Cache Composer packages
|
||||||
id: composer-cache
|
id: composer-cache
|
||||||
uses: actions/cache@v2
|
uses: actions/cache@v3
|
||||||
with:
|
with:
|
||||||
path: vendor
|
path: vendor
|
||||||
key: ${{ runner.os }}-php-${{ hashFiles('**/composer.lock') }}
|
key: ${{ runner.os }}-php-${{ hashFiles('**/composer.lock') }}
|
||||||
|
|
37
CHANGELOG.md
37
CHANGELOG.md
|
@ -1,3 +1,40 @@
|
||||||
|
|
||||||
|
## 2025-03-26 v6.6.11
|
||||||
|
- Исправлена передача габаритов при выгрузке заказов по агенту
|
||||||
|
|
||||||
|
## 2025-03-25 v6.6.10
|
||||||
|
- Исправлено некорректное изменение статуса оплаты отмененных заказов
|
||||||
|
|
||||||
|
## 2025-03-04 v6.6.9
|
||||||
|
- Исправлено обновление модуля
|
||||||
|
|
||||||
|
## 2025-03-03 v6.6.8
|
||||||
|
- Исправлена ошибка экспорта дополнительных свойств товаров
|
||||||
|
|
||||||
|
## 2025-02-04 v6.6.7
|
||||||
|
- Исправлена ошибка установки модуля на PHP 8.0
|
||||||
|
|
||||||
|
## 2025-01-29 v6.6.6
|
||||||
|
- Поддержка нулевой закупочной стоимости при генерации каталога
|
||||||
|
|
||||||
|
## 2025-01-28 v6.6.5
|
||||||
|
- Исправлена ошибка редактирования интеграционных доставок при активации опции передачи статусов интеграционных оплат
|
||||||
|
|
||||||
|
## 2025-01-27 v6.6.4
|
||||||
|
- Исправлено некорректное удаление признака применения промокода при изменении состава заказа в CRM
|
||||||
|
|
||||||
|
## 2025-01-14 v6.6.3
|
||||||
|
- Исправлены ошибки при обновлении модуля
|
||||||
|
|
||||||
|
## 2025-01-14 v6.6.2
|
||||||
|
- Исправлена выгрузка архива заказов при установке модуля
|
||||||
|
|
||||||
|
## 2024-12-17 v6.6.1
|
||||||
|
- Исправлены API методы по взаимодействию с пользовательскими полями и справочниками
|
||||||
|
|
||||||
|
## 2024-12-09 v6.6.0
|
||||||
|
- Добавлено динамическое изменение свойств товаров при настройке экспорта
|
||||||
|
|
||||||
## 2024-12-08 v6.5.39
|
## 2024-12-08 v6.5.39
|
||||||
- Исправлена поломка заказов с промокодом Maxma при включенной передаче корзины в CRM
|
- Исправлена поломка заказов с промокодом Maxma при включенной передаче корзины в CRM
|
||||||
|
|
||||||
|
|
|
@ -1508,7 +1508,7 @@ class ApiClient
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->client->makeRequest(
|
return $this->client->makeRequest(
|
||||||
"/custom-fields/$entity/edit/{$customField['code']}",
|
"/custom-fields/$entity/{$customField['code']}/edit",
|
||||||
Client::METHOD_POST,
|
Client::METHOD_POST,
|
||||||
array('customField' => json_encode($customField))
|
array('customField' => json_encode($customField))
|
||||||
);
|
);
|
||||||
|
@ -1591,7 +1591,7 @@ class ApiClient
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->client->makeRequest(
|
return $this->client->makeRequest(
|
||||||
"/custom-fields/dictionaries/{$customDictionary['code']}/create",
|
"/custom-fields/dictionaries/create",
|
||||||
Client::METHOD_POST,
|
Client::METHOD_POST,
|
||||||
array('customDictionary' => json_encode($customDictionary))
|
array('customDictionary' => json_encode($customDictionary))
|
||||||
);
|
);
|
||||||
|
|
|
@ -1226,7 +1226,6 @@ class RetailCrmHistory
|
||||||
}
|
}
|
||||||
|
|
||||||
if (array_key_exists('discountTotal_sum', $collectItems[$product['offer']['externalId']])) {
|
if (array_key_exists('discountTotal_sum', $collectItems[$product['offer']['externalId']])) {
|
||||||
$item->setField('CUSTOM_PRICE', 'Y');
|
|
||||||
$item->setField('DISCOUNT_NAME', '');
|
$item->setField('DISCOUNT_NAME', '');
|
||||||
$item->setField('DISCOUNT_VALUE', '');
|
$item->setField('DISCOUNT_VALUE', '');
|
||||||
|
|
||||||
|
@ -1240,6 +1239,7 @@ class RetailCrmHistory
|
||||||
$price = self::truncate($price, 2);
|
$price = self::truncate($price, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$item->markFieldCustom('PRICE');
|
||||||
$item->setField('PRICE', $price);
|
$item->setField('PRICE', $price);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2062,7 +2062,7 @@ class RetailCrmHistory
|
||||||
$payment->delete();
|
$payment->delete();
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($paymentsCrm['totalSumm'] == $paySumm) {
|
if ($paymentsCrm['totalSumm'] == $paySumm && $order->getField('CANCELED') !== 'Y') {
|
||||||
$order->setFieldNoDemand('PAYED', 'Y');
|
$order->setFieldNoDemand('PAYED', 'Y');
|
||||||
} else {
|
} else {
|
||||||
$order->setFieldNoDemand('PAYED', 'N');
|
$order->setFieldNoDemand('PAYED', 'N');
|
||||||
|
|
|
@ -358,7 +358,7 @@ class RetailCrmOrder
|
||||||
|
|
||||||
$order['items'][] = $item;
|
$order['items'][] = $item;
|
||||||
|
|
||||||
if ($send && $dimensionsSetting === 'Y') {
|
if ($dimensionsSetting === 'Y') {
|
||||||
$dimensions = RCrmActions::unserializeArrayRecursive($product['DIMENSIONS']);
|
$dimensions = RCrmActions::unserializeArrayRecursive($product['DIMENSIONS']);
|
||||||
|
|
||||||
if ($dimensions !== false) {
|
if ($dimensions !== false) {
|
||||||
|
@ -370,7 +370,7 @@ class RetailCrmOrder
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($send && $dimensionsSetting === 'Y') {
|
if ($dimensionsSetting === 'Y') {
|
||||||
$order['width'] = $width;
|
$order['width'] = $width;
|
||||||
$order['height'] = $height;
|
$order['height'] = $height;
|
||||||
$order['length'] = $length;
|
$order['length'] = $length;
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
- Исправлена поломка заказов с промокодом Maxma при включенной передаче корзины в CRM
|
- Исправлена передача габаритов при выгрузке заказов по агенту
|
|
@ -38,7 +38,8 @@ if (file_exists($_SERVER['DOCUMENT_ROOT'] . '/bitrix/php_interface/retailcrm/exp
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$settingService = SettingsService::getInstance([], '');
|
global $PROFILE_ID;
|
||||||
|
$settingService = SettingsService::getInstance([], '', $PROFILE_ID ?? $profile_id);
|
||||||
$iblockPropertySku = [];
|
$iblockPropertySku = [];
|
||||||
$iblockPropertySkuHl = [];
|
$iblockPropertySkuHl = [];
|
||||||
$iblockPropertyUnitSku = [];
|
$iblockPropertyUnitSku = [];
|
||||||
|
@ -46,7 +47,7 @@ if (file_exists($_SERVER['DOCUMENT_ROOT'] . '/bitrix/php_interface/retailcrm/exp
|
||||||
$iblockPropertyProductHl = [];
|
$iblockPropertyProductHl = [];
|
||||||
$iblockPropertyUnitProduct = [];
|
$iblockPropertyUnitProduct = [];
|
||||||
|
|
||||||
foreach (array_keys($settingService->actrualPropList) as $prop) {
|
foreach (array_keys($settingService->actualPropList) as $prop) {
|
||||||
$skuUnitProps = ('iblockPropertyUnitSku_' . $prop);
|
$skuUnitProps = ('iblockPropertyUnitSku_' . $prop);
|
||||||
$skuUnitProps = $$skuUnitProps;
|
$skuUnitProps = $$skuUnitProps;
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,8 @@ CModule::IncludeModule('intaro.retailcrm');
|
||||||
//TODO заменить вызов на сервис-локатор, когда он приедет
|
//TODO заменить вызов на сервис-локатор, когда он приедет
|
||||||
$settingsService = SettingsService::getInstance(
|
$settingsService = SettingsService::getInstance(
|
||||||
$arOldSetupVars ?? [],
|
$arOldSetupVars ?? [],
|
||||||
$ACTION
|
$ACTION,
|
||||||
|
$PROFILE_ID
|
||||||
);
|
);
|
||||||
|
|
||||||
$isSetupModulePage = $settingsService->isSetupModulePage();
|
$isSetupModulePage = $settingsService->isSetupModulePage();
|
||||||
|
@ -110,7 +111,7 @@ if ($STEP === 1) {
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<form method="post" action="<?=$APPLICATION->GetCurPage()?>">
|
<form method="post" id="submit-form" action="<?=$APPLICATION->GetCurPage()?>">
|
||||||
<?php
|
<?php
|
||||||
if ($ACTION === 'EXPORT_EDIT' || $ACTION === 'EXPORT_COPY') {
|
if ($ACTION === 'EXPORT_EDIT' || $ACTION === 'EXPORT_COPY') {
|
||||||
?>
|
?>
|
||||||
|
@ -190,8 +191,7 @@ if ($STEP === 1) {
|
||||||
<tbody>
|
<tbody>
|
||||||
|
|
||||||
<?php
|
<?php
|
||||||
foreach ($settingsService->actrualPropList as $propertyKey => $property) {
|
foreach ($settingsService->defaultPropList as $propertyKey => $property) { ?>
|
||||||
$productSelected = false; ?>
|
|
||||||
|
|
||||||
<tr class="adm-list-table-row">
|
<tr class="adm-list-table-row">
|
||||||
<td class="adm-list-table-cell">
|
<td class="adm-list-table-cell">
|
||||||
|
@ -215,14 +215,14 @@ if ($STEP === 1) {
|
||||||
if ($keyField === $propertyKey) { ?>
|
if ($keyField === $propertyKey) { ?>
|
||||||
<option value="<?=$field['CODE']?>"
|
<option value="<?=$field['CODE']?>"
|
||||||
<?php
|
<?php
|
||||||
$productSelected = $settingsService->isOptionSelected(
|
$isSelected = $settingsService->isOptionSelected(
|
||||||
$field,
|
$field,
|
||||||
$arIBlock['OLD_PROPERTY_PRODUCT_SELECT'],
|
$arIBlock['OLD_PROPERTY_PRODUCT_SELECT'],
|
||||||
$propertyKey
|
$propertyKey
|
||||||
);
|
);
|
||||||
?>
|
?>
|
||||||
|
|
||||||
<?= $productSelected ? ' selected' : ''?>
|
<?= $isSelected ? ' selected' : ''?>
|
||||||
>
|
>
|
||||||
<?=$field['name']?>
|
<?=$field['name']?>
|
||||||
</option>
|
</option>
|
||||||
|
@ -241,7 +241,7 @@ if ($STEP === 1) {
|
||||||
<?php
|
<?php
|
||||||
echo $settingsService->getOptionClass($prop, true);
|
echo $settingsService->getOptionClass($prop, true);
|
||||||
|
|
||||||
$productSelected = $settingsService->isOptionSelected(
|
$isSelected = $settingsService->isOptionSelected(
|
||||||
$prop,
|
$prop,
|
||||||
$arIBlock['OLD_PROPERTY_PRODUCT_SELECT'],
|
$arIBlock['OLD_PROPERTY_PRODUCT_SELECT'],
|
||||||
$propertyKey
|
$propertyKey
|
||||||
|
@ -251,7 +251,7 @@ if ($STEP === 1) {
|
||||||
= $settingsService->getHlTableName($prop)
|
= $settingsService->getHlTableName($prop)
|
||||||
?? $productHlTableName;
|
?? $productHlTableName;
|
||||||
|
|
||||||
echo $productSelected ? ' selected' : '';
|
echo $isSelected ? ' selected' : '';
|
||||||
?>
|
?>
|
||||||
>
|
>
|
||||||
<?=$prop['NAME']?>
|
<?=$prop['NAME']?>
|
||||||
|
@ -376,19 +376,18 @@ if ($STEP === 1) {
|
||||||
<option value="<?=$prop['CODE']?>"
|
<option value="<?=$prop['CODE']?>"
|
||||||
<?php
|
<?php
|
||||||
echo $settingsService->getOptionClass($prop, false);
|
echo $settingsService->getOptionClass($prop, false);
|
||||||
if (!$productSelected) {
|
|
||||||
$isSelected = $settingsService->isOptionSelected(
|
|
||||||
$prop,
|
|
||||||
$arIBlock['OLD_PROPERTY_SKU_SELECT'],
|
|
||||||
$propertyKey
|
|
||||||
);
|
|
||||||
|
|
||||||
$skuHlTableName
|
$isSelected = $settingsService->isOptionSelected(
|
||||||
= $settingsService->getHlTableName($prop)
|
$prop,
|
||||||
?? $skuHlTableName;
|
$arIBlock['OLD_PROPERTY_SKU_SELECT'],
|
||||||
|
$propertyKey
|
||||||
|
);
|
||||||
|
|
||||||
echo $isSelected ? ' selected' : '';
|
$skuHlTableName
|
||||||
}
|
= $settingsService->getHlTableName($prop)
|
||||||
|
?? $skuHlTableName;
|
||||||
|
|
||||||
|
echo $isSelected ? ' selected' : '';
|
||||||
?>
|
?>
|
||||||
>
|
>
|
||||||
<?=$prop['NAME']?>
|
<?=$prop['NAME']?>
|
||||||
|
@ -473,9 +472,97 @@ if ($STEP === 1) {
|
||||||
</tr>
|
</tr>
|
||||||
<?php
|
<?php
|
||||||
} ?>
|
} ?>
|
||||||
|
|
||||||
|
<?php
|
||||||
|
$catalogId = $arIBlock['ID'];
|
||||||
|
$catalogCustomProps = $settingsService->customPropList[$catalogId];
|
||||||
|
|
||||||
|
if (!empty($catalogCustomProps)) {
|
||||||
|
foreach ($catalogCustomProps as $catalogCustomPropCode => $catalogCustomPropValue) { ?>
|
||||||
|
<tr class="adm-list-table-row custom-property-row">
|
||||||
|
<td class="adm-list-table-cell custom-property-title">
|
||||||
|
<?=htmlspecialcharsex($catalogCustomPropValue)?>
|
||||||
|
</td>
|
||||||
|
<td class="adm-list-table-cell">
|
||||||
|
<select
|
||||||
|
name="iblockPropertyProduct_<?=$catalogCustomPropCode?>[<?= $catalogId ?>]"
|
||||||
|
id="iblockPropertyProduct_<?=$catalogCustomPropCode . $catalogId ?>"
|
||||||
|
class="property-export"
|
||||||
|
data-type="<?= $catalogCustomPropCode ?>"
|
||||||
|
onchange="propertyChange(this)"
|
||||||
|
style="width: 200px">
|
||||||
|
|
||||||
|
<option value=""></option>
|
||||||
|
<?php foreach ($arIBlock['PROPERTIES_PRODUCT'] as $prop) {
|
||||||
|
$productHlTableName = ''; ?>
|
||||||
|
<option value="<?=$prop['CODE']?>"
|
||||||
|
<?php
|
||||||
|
echo $settingsService->getOptionClass($prop, true);
|
||||||
|
|
||||||
|
$isSelected = $settingsService->isOptionSelected(
|
||||||
|
$prop,
|
||||||
|
$arIBlock['OLD_PROPERTY_PRODUCT_SELECT'],
|
||||||
|
$catalogCustomPropCode
|
||||||
|
);
|
||||||
|
|
||||||
|
$productHlTableName
|
||||||
|
= $settingsService->getHlTableName($prop)
|
||||||
|
?? $productHlTableName;
|
||||||
|
|
||||||
|
echo $isSelected ? ' selected' : '';
|
||||||
|
?>
|
||||||
|
>
|
||||||
|
<?=$prop['NAME']?>
|
||||||
|
</option>
|
||||||
|
<?php } ?>
|
||||||
|
</select>
|
||||||
|
</td>
|
||||||
|
|
||||||
|
<?php if ($arIBlock['PROPERTIES_SKU'] !== null) { ?>
|
||||||
|
<td class="adm-list-table-cell">
|
||||||
|
<select
|
||||||
|
name="iblockPropertySku_<?=$catalogCustomPropCode?>[<?= $catalogId ?>]"
|
||||||
|
id="iblockPropertySku_<?=$catalogCustomPropCode . $catalogId ?>"
|
||||||
|
class="property-export"
|
||||||
|
data-type="<?= $catalogCustomPropCode ?>"
|
||||||
|
onchange="propertyChange(this)"
|
||||||
|
style="width: 200px">
|
||||||
|
|
||||||
|
<option value=""></option>
|
||||||
|
<?php foreach ($arIBlock['PROPERTIES_SKU'] as $prop) {
|
||||||
|
$skuHlTableName = ''; ?>
|
||||||
|
<option value="<?=$prop['CODE']?>"
|
||||||
|
<?php
|
||||||
|
echo $settingsService->getOptionClass($prop, false);
|
||||||
|
|
||||||
|
$isSelected = $settingsService->isOptionSelected(
|
||||||
|
$prop,
|
||||||
|
$arIBlock['OLD_PROPERTY_SKU_SELECT'],
|
||||||
|
$catalogCustomPropCode
|
||||||
|
);
|
||||||
|
|
||||||
|
$skuHlTableName
|
||||||
|
= $settingsService->getHlTableName($prop)
|
||||||
|
?? $skuHlTableName;
|
||||||
|
|
||||||
|
echo $isSelected ? ' selected' : '';
|
||||||
|
?>
|
||||||
|
>
|
||||||
|
<?=$prop['NAME']?>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<?php } ?>
|
||||||
|
</select>
|
||||||
|
<button id="delete-custom-row" class="adm-btn-save" type="button" style="margin-left: 10px"><?= GetMessage('DELETE_PROPERTY');?></button>
|
||||||
|
</td>
|
||||||
|
<?php } ?>
|
||||||
|
</tr>
|
||||||
|
<?php }
|
||||||
|
}
|
||||||
|
?>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
<br>
|
<button class="adm-btn-save add-custom-row" type="button" style="margin-top: 20px;"><?= GetMessage('ADD_PROPERTY');?></button>
|
||||||
<br>
|
<br>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -484,6 +571,20 @@ if ($STEP === 1) {
|
||||||
</div>
|
</div>
|
||||||
<input type="hidden" name="count_checked" id="count_checked" value="<?=$intCountChecked?>">
|
<input type="hidden" name="count_checked" id="count_checked" value="<?=$intCountChecked?>">
|
||||||
<br>
|
<br>
|
||||||
|
<template id="custom-property-template-row">
|
||||||
|
<tr class="adm-list-table-row custom-property-row">
|
||||||
|
<td class="adm-list-table-cell">
|
||||||
|
<input type="text" title="Название нового свойства" name="custom-property-title" style="width: 200px">
|
||||||
|
</td>
|
||||||
|
<td class="adm-list-table-cell">
|
||||||
|
<select name="iblockPropertyProduct_" id="iblockPropertyProduct_" class="property-export" onchange="propertyChange(this)" style="width: 200px"></select>
|
||||||
|
</td>
|
||||||
|
<td class="adm-list-table-cell">
|
||||||
|
<select name="iblockPropertySku_" id="iiblockPropertySku_" class="property-export" onchange="propertyChange(this)" style="width: 200px"></select>
|
||||||
|
<button id="delete-new-custom-row" class="adm-btn-save" type="button" style="margin-left: 10px"><?= GetMessage('DELETE_PROPERTY');?></button>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</template>
|
||||||
<h3><?=GetMessage('SETTINGS_EXPORT')?></h3>
|
<h3><?=GetMessage('SETTINGS_EXPORT')?></h3>
|
||||||
<span class="text"><?=GetMessage('FILENAME')?><br><br></span>
|
<span class="text"><?=GetMessage('FILENAME')?><br><br></span>
|
||||||
<input type="text" name="SETUP_FILE_NAME" value="<?=htmlspecialcharsbx(strlen($SETUP_FILE_NAME) > 0 ?
|
<input type="text" name="SETUP_FILE_NAME" value="<?=htmlspecialcharsbx(strlen($SETUP_FILE_NAME) > 0 ?
|
||||||
|
@ -566,7 +667,7 @@ if ($STEP === 1) {
|
||||||
<input type="hidden" name="STEP" value="<?=$STEP + 1?>">
|
<input type="hidden" name="STEP" value="<?=$STEP + 1?>">
|
||||||
<input type="hidden" name="SETUP_FIELDS_LIST" value="<?=
|
<input type="hidden" name="SETUP_FIELDS_LIST" value="<?=
|
||||||
$settingsService->getSetupFieldsString(
|
$settingsService->getSetupFieldsString(
|
||||||
array_keys($settingsService->actrualPropList) ?? [],
|
array_keys($settingsService->actualPropList) ?? [],
|
||||||
$hlblockModule === true,
|
$hlblockModule === true,
|
||||||
$hlBlockList ?? []
|
$hlBlockList ?? []
|
||||||
)
|
)
|
||||||
|
@ -577,8 +678,109 @@ if ($STEP === 1) {
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
<?php CJSCore::Init(['jquery']);?>
|
<?php CJSCore::Init(['jquery']);?>
|
||||||
|
<?php CUtil::InitJSCore(['intaro_custom_props']); ?>
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
|
BX.ready(function() {
|
||||||
|
if (typeof createCustomPropsRaw !== 'function') {
|
||||||
|
$('.add-custom-row').hide();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$('.add-custom-row').click(function () {
|
||||||
|
if (typeof createCustomPropsRaw === 'function') {
|
||||||
|
createCustomPropsRaw($(this));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$(document).on('click', '#delete-new-custom-row', function () {
|
||||||
|
if (typeof deleteCustomPropRow === 'function') {
|
||||||
|
deleteCustomPropRow($(this));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$(document).on('click', '#delete-custom-row', function () {
|
||||||
|
let buttonElem = $(this);
|
||||||
|
|
||||||
|
if (typeof addCustomPropToDelete === 'function' && typeof deleteCustomPropRow === 'function') {
|
||||||
|
addCustomPropToDelete(buttonElem);
|
||||||
|
deleteCustomPropRow(buttonElem);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$(document).on('blur', 'input[name="custom-property-title"]', function () {
|
||||||
|
|
||||||
|
if (typeof getUniquePropertyCode === 'function' && typeof addCustomPropCodeToSelectAttributes === 'function') {
|
||||||
|
let inputElem = $(this);
|
||||||
|
let newPropertyTitle = inputElem.val();
|
||||||
|
|
||||||
|
if (!newPropertyTitle) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let newPropertyCode = getUniquePropertyCode(newPropertyTitle);
|
||||||
|
addCustomPropCodeToSelectAttributes(newPropertyCode, inputElem);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$('#submit-form').submit(function (formEvent) {
|
||||||
|
if (typeof setCustomProperties !== "function") {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
formEvent.preventDefault();
|
||||||
|
let savePromise = null;
|
||||||
|
let deletePromise = null;
|
||||||
|
let formElem = formEvent.currentTarget;
|
||||||
|
let profileId = $($('input[name="PROFILE_ID"]')).val();
|
||||||
|
|
||||||
|
setCustomProperties();
|
||||||
|
|
||||||
|
if (Object.keys(customProps).length > 0) {
|
||||||
|
savePromise = BX.ajax.runAction('intaro:retailcrm.api.customexportprops.save', {
|
||||||
|
json: {
|
||||||
|
properties: customProps,
|
||||||
|
profileId: profileId
|
||||||
|
},
|
||||||
|
}).then(addParamsToSetupFieldsList());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Object.keys(customPropsToDelete).length > 0) {
|
||||||
|
deletePromise = BX.ajax.runAction('intaro:retailcrm.api.customexportprops.delete', {
|
||||||
|
json: {
|
||||||
|
properties: customPropsToDelete,
|
||||||
|
profileId: profileId
|
||||||
|
},
|
||||||
|
}).then(deleteParamsFromSetupFieldsList());
|
||||||
|
}
|
||||||
|
|
||||||
|
const promises = [savePromise, deletePromise].filter(Boolean);
|
||||||
|
|
||||||
|
if (promises.length > 0) {
|
||||||
|
Promise.all(promises)
|
||||||
|
.finally(() => {
|
||||||
|
formElem.submit();
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
formElem.submit();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const setupFieldsListElement = $('input[name="SETUP_FIELDS_LIST"]');
|
||||||
|
let customProps = {};
|
||||||
|
let customPropsToDelete = {};
|
||||||
|
const setupFieldsParamsToFill = [
|
||||||
|
'iblockPropertySku_',
|
||||||
|
'iblockPropertyUnitSku_',
|
||||||
|
'iblockPropertyProduct_',
|
||||||
|
'iblockPropertyUnitProduct_',
|
||||||
|
'highloadblockb_hlsys_marking_code_group_',
|
||||||
|
'highloadblock_productb_hlsys_marking_code_group_',
|
||||||
|
'highloadblockeshop_color_reference_',
|
||||||
|
'highloadblock_producteshop_color_reference_',
|
||||||
|
'highloadblockeshop_brand_reference_',
|
||||||
|
'highloadblock_producteshop_brand_reference_'
|
||||||
|
];
|
||||||
|
|
||||||
function checkLoadStatus(object)
|
function checkLoadStatus(object)
|
||||||
{
|
{
|
||||||
if (object.checked) {
|
if (object.checked) {
|
||||||
|
|
|
@ -50,6 +50,10 @@ $arJsConfig = [
|
||||||
'js' => '/bitrix/js/intaro/sms.js',
|
'js' => '/bitrix/js/intaro/sms.js',
|
||||||
'rel' => [],
|
'rel' => [],
|
||||||
],
|
],
|
||||||
|
'intaro_custom_props' => [
|
||||||
|
'js' => '/bitrix/js/intaro/export/custom-props-export.js',
|
||||||
|
'rel' => [],
|
||||||
|
],
|
||||||
];
|
];
|
||||||
|
|
||||||
foreach ($arJsConfig as $ext => $arExt) {
|
foreach ($arJsConfig as $ext => $arExt) {
|
||||||
|
|
|
@ -0,0 +1,228 @@
|
||||||
|
|
||||||
|
function deleteCustomPropRow(deleteButton)
|
||||||
|
{
|
||||||
|
deleteButton.closest('tr').remove();
|
||||||
|
}
|
||||||
|
|
||||||
|
function addCustomPropToDelete(deleteButton)
|
||||||
|
{
|
||||||
|
let deletedPropTitle = deleteButton.closest('td').siblings().filter('.custom-property-title').text().trim();
|
||||||
|
let deletedPropCode = deleteButton.siblings().filter('select').first().data('type');
|
||||||
|
let customPropCatalogId = deleteButton.closest('.iblockExportTable').data('type');
|
||||||
|
|
||||||
|
let values = {
|
||||||
|
'code': deletedPropCode,
|
||||||
|
'title': deletedPropTitle,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (customPropsToDelete.hasOwnProperty(customPropCatalogId)) {
|
||||||
|
customPropsToDelete[customPropCatalogId].push(values);
|
||||||
|
} else {
|
||||||
|
customPropsToDelete[customPropCatalogId] = [values];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function addCustomPropCodeToSelectAttributes(customPropCode, customPropTitleElem)
|
||||||
|
{
|
||||||
|
let selectElements = customPropTitleElem.closest('.custom-property-row').find('td select');
|
||||||
|
let catalogId = customPropTitleElem.closest('.iblockExportTable').data('type');
|
||||||
|
|
||||||
|
selectElements.each(function (index, element) {
|
||||||
|
let selectElem = $(element);
|
||||||
|
let newSelectIdValue = selectElem.attr('id').match(/^[^_]*_/)[0] + customPropCode + catalogId;
|
||||||
|
let newSelectNameValue = selectElem.attr('name').match(/^[^_]*_/)[0] + customPropCode + `[${catalogId}]`;
|
||||||
|
|
||||||
|
selectElem.attr('id', newSelectIdValue);
|
||||||
|
selectElem.attr('name', newSelectNameValue);
|
||||||
|
selectElem.data('type', customPropCode);
|
||||||
|
triggerSelectChange(selectElem);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function triggerSelectChange(selectElem)
|
||||||
|
{
|
||||||
|
if (selectElem.val().length > 0) {
|
||||||
|
selectElem.trigger('change', [self]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function setCustomProperties()
|
||||||
|
{
|
||||||
|
let customPropertiesRows = $('.custom-property-row');
|
||||||
|
|
||||||
|
if (customPropertiesRows.length === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let customPropertyCatalogId;
|
||||||
|
let customPropertyTitle = '';
|
||||||
|
let customPropertyCode = '';
|
||||||
|
let productPropertyMatch = '';
|
||||||
|
let offerPropertyMatch = '';
|
||||||
|
|
||||||
|
let catalogIds = [];
|
||||||
|
customPropertiesRows.each(function (index, propertyRow) {
|
||||||
|
let propertyRowObj = $(propertyRow);
|
||||||
|
customPropertyCatalogId = propertyRowObj.closest('.iblockExportTable').data('type');
|
||||||
|
customPropertyTitle = propertyRowObj.find('input[name="custom-property-title"]').val();
|
||||||
|
|
||||||
|
if (!customPropertyTitle) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
customPropertyCode = getUniquePropertyCode(customPropertyTitle);
|
||||||
|
productPropertyMatch = propertyRowObj.find('select[name=custom-product-property-select]').val();
|
||||||
|
offerPropertyMatch = propertyRowObj.find('select[name=custom-offer-property-select]').val();
|
||||||
|
|
||||||
|
let values = {
|
||||||
|
'title': customPropertyTitle,
|
||||||
|
'code': customPropertyCode,
|
||||||
|
'productProperty': productPropertyMatch,
|
||||||
|
'offerProperty': offerPropertyMatch
|
||||||
|
};
|
||||||
|
|
||||||
|
if (catalogIds.indexOf(customPropertyCatalogId) === -1) {
|
||||||
|
customProps[customPropertyCatalogId] = [values];
|
||||||
|
} else {
|
||||||
|
customProps[customPropertyCatalogId].push(values);
|
||||||
|
}
|
||||||
|
|
||||||
|
catalogIds.push(customPropertyCatalogId);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function getUniquePropertyCode(customPropertyTitle)
|
||||||
|
{
|
||||||
|
let uniqueValue = transliterate(customPropertyTitle).replace(/ /g, '_');
|
||||||
|
let counter = 0;
|
||||||
|
const setupFieldsListValues = setupFieldsListElement.val().split(',');
|
||||||
|
|
||||||
|
while (setupFieldsListValues.includes(uniqueValue)) {
|
||||||
|
uniqueValue = `${customPropertyTitle}${++counter}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
return uniqueValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
function addParamsToSetupFieldsList()
|
||||||
|
{
|
||||||
|
let newParams = '';
|
||||||
|
|
||||||
|
if (Object.keys(customProps).length === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let propertiesByCatalogId of Object.values(customProps)) {
|
||||||
|
propertiesByCatalogId.forEach(function (values) {
|
||||||
|
setupFieldsParamsToFill.forEach(function (param) {
|
||||||
|
newParams += ',' + param + values.code;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
let newValue = setupFieldsListElement.val() + newParams;
|
||||||
|
setupFieldsListElement.val(newValue);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function deleteParamsFromSetupFieldsList()
|
||||||
|
{
|
||||||
|
let setupFields = setupFieldsListElement.val();
|
||||||
|
|
||||||
|
if (Object.keys(customPropsToDelete).length === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let propsByCatalogId of Object.values(customPropsToDelete)) {
|
||||||
|
propsByCatalogId.forEach(function (propValues) {
|
||||||
|
setupFieldsParamsToFill.forEach(function (param) {
|
||||||
|
let paramToDelete = ',' + param + propValues.code;
|
||||||
|
setupFields = setupFields.replace(paramToDelete, '');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
setupFieldsListElement.val(setupFields);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function createCustomPropsRaw(addRowButton)
|
||||||
|
{
|
||||||
|
let templateRow = $($('#custom-property-template-row').html());
|
||||||
|
let templateSelectElements = templateRow.find('select');
|
||||||
|
|
||||||
|
let prevTableRow = $(addRowButton).prev('table').find('tbody tr:last-child');
|
||||||
|
let lastRawSelectElements = prevTableRow.find('td select');
|
||||||
|
|
||||||
|
lastRawSelectElements.each(function (index, element) {
|
||||||
|
let selectElement = $(element);
|
||||||
|
let templateSelectElement = templateSelectElements[index];
|
||||||
|
fillTemplateSelect(selectElement, templateSelectElement);
|
||||||
|
prevTableRow.after(templateRow);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function fillTemplateSelect(sourceSelectElement, templateSelectElement)
|
||||||
|
{
|
||||||
|
let selectOptions = sourceSelectElement.find('option');
|
||||||
|
|
||||||
|
selectOptions.each(function (index, element) {
|
||||||
|
let optionElem = $(element);
|
||||||
|
let value = $(optionElem).val();
|
||||||
|
let text = $(optionElem).text();
|
||||||
|
|
||||||
|
$('<option>', { value: value, text: text }).appendTo(templateSelectElement);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function transliterate(titleToTransliterate)
|
||||||
|
{
|
||||||
|
const hasCyrillicChars = /[\u0400-\u04FF]/.test(titleToTransliterate);
|
||||||
|
|
||||||
|
if (!hasCyrillicChars) {
|
||||||
|
return titleToTransliterate;
|
||||||
|
}
|
||||||
|
|
||||||
|
translitedText = '';
|
||||||
|
for (var i = 0; i < titleToTransliterate.length; i++) {
|
||||||
|
switch (titleToTransliterate[i]) {
|
||||||
|
case 'а': case 'А': translitedText += 'a'; break;
|
||||||
|
case 'б': case 'Б': translitedText += 'b'; break;
|
||||||
|
case 'в': case 'В': translitedText += 'v'; break;
|
||||||
|
case 'г': case 'Г': translitedText += 'g'; break;
|
||||||
|
case 'д': case 'Д': translitedText += 'd'; break;
|
||||||
|
case 'е': case 'Е': translitedText += 'e'; break;
|
||||||
|
case 'ё': case 'Ё': translitedText += 'yo'; break;
|
||||||
|
case 'ж': case 'Ж': translitedText += 'zh'; break;
|
||||||
|
case 'з': case 'З': translitedText += 'z'; break;
|
||||||
|
case 'и': case 'И': translitedText += 'i'; break;
|
||||||
|
case 'й': case 'Й': translitedText += 'y'; break;
|
||||||
|
case 'к': case 'К': translitedText += 'k'; break;
|
||||||
|
case 'л': case 'Л': translitedText += 'l'; break;
|
||||||
|
case 'м': case 'М': translitedText += 'm'; break;
|
||||||
|
case 'н': case 'Н': translitedText += 'n'; break;
|
||||||
|
case 'о': case 'О': translitedText += 'o'; break;
|
||||||
|
case 'п': case 'П': translitedText += 'p'; break;
|
||||||
|
case 'р': case 'Р': translitedText += 'r'; break;
|
||||||
|
case 'с': case 'С': translitedText += 's'; break;
|
||||||
|
case 'т': case 'Т': translitedText += 't'; break;
|
||||||
|
case 'у': case 'У': translitedText += 'u'; break;
|
||||||
|
case 'ф': case 'Ф': translitedText += 'f'; break;
|
||||||
|
case 'х': case 'Х': translitedText += 'h'; break;
|
||||||
|
case 'ц': case 'Ц': translitedText += 'c'; break;
|
||||||
|
case 'ч': case 'Ч': translitedText += 'ch'; break;
|
||||||
|
case 'ш': case 'Ш': translitedText += 'sh'; break;
|
||||||
|
case 'щ': case 'Щ': translitedText += 'sch'; break;
|
||||||
|
case 'ъ': case 'Ъ': translitedText += ''; break;
|
||||||
|
case 'ы': case 'Ы': translitedText += 'y'; break;
|
||||||
|
case 'ь': case 'Ь': translitedText += ''; break;
|
||||||
|
case 'э': case 'Э': translitedText += 'e'; break;
|
||||||
|
case 'ю': case 'Ю': translitedText += 'yu'; break;
|
||||||
|
case 'я': case 'Я': translitedText += 'ya'; break;
|
||||||
|
default: translitedText += titleToTransliterate[i]; break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return translitedText;
|
||||||
|
}
|
|
@ -31,7 +31,7 @@ if (class_exists('intaro_retailcrm')) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
include (__DIR__ . '/../lib/component/advanced/installertrait.php');
|
require_once(__DIR__ . '/../lib/component/advanced/installertrait.php');
|
||||||
|
|
||||||
class intaro_retailcrm extends CModule
|
class intaro_retailcrm extends CModule
|
||||||
{
|
{
|
||||||
|
@ -58,6 +58,7 @@ class intaro_retailcrm extends CModule
|
||||||
$this->INSTALL_PATH = $path;
|
$this->INSTALL_PATH = $path;
|
||||||
|
|
||||||
include($path . '/version.php');
|
include($path . '/version.php');
|
||||||
|
|
||||||
$this->MODULE_VERSION = $arModuleVersion['VERSION'];
|
$this->MODULE_VERSION = $arModuleVersion['VERSION'];
|
||||||
$this->MODULE_VERSION_DATE = $arModuleVersion['VERSION_DATE'];
|
$this->MODULE_VERSION_DATE = $arModuleVersion['VERSION_DATE'];
|
||||||
$this->MODULE_NAME = GetMessage('RETAIL_MODULE_NAME');
|
$this->MODULE_NAME = GetMessage('RETAIL_MODULE_NAME');
|
||||||
|
@ -87,6 +88,18 @@ class intaro_retailcrm extends CModule
|
||||||
*/
|
*/
|
||||||
function DoInstall()
|
function DoInstall()
|
||||||
{
|
{
|
||||||
|
try {
|
||||||
|
require_once('install_deps.php');
|
||||||
|
} catch (Error $exception) {
|
||||||
|
RCrmActions::eventLog(
|
||||||
|
'RetailCRM module install error',
|
||||||
|
'intaro.retailcrm',
|
||||||
|
$exception->getCode() . ': ' . $exception->getMessage()
|
||||||
|
);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
global $APPLICATION, $step, $arResult;
|
global $APPLICATION, $step, $arResult;
|
||||||
|
|
||||||
if (!in_array('curl', get_loaded_extensions(), true)) {
|
if (!in_array('curl', get_loaded_extensions(), true)) {
|
||||||
|
@ -112,57 +125,6 @@ class intaro_retailcrm extends CModule
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
include($this->INSTALL_PATH . '/../lib/component/apiclient/traits/baseclienttrait.php');
|
|
||||||
include($this->INSTALL_PATH . '/../lib/component/apiclient/traits/customerstrait.php');
|
|
||||||
include($this->INSTALL_PATH . '/../lib/component/apiclient/traits/customerscorporatetrait.php');
|
|
||||||
include($this->INSTALL_PATH . '/../lib/component/apiclient/traits/loyaltytrait.php');
|
|
||||||
include($this->INSTALL_PATH . '/../lib/component/apiclient/traits/ordertrait.php');
|
|
||||||
include($this->INSTALL_PATH . '/../lib/component/apiclient/traits/carttrait.php');
|
|
||||||
include($this->INSTALL_PATH . '/../classes/general/Http/Client.php');
|
|
||||||
include($this->INSTALL_PATH . '/../classes/general/Response/ApiResponse.php');
|
|
||||||
include($this->INSTALL_PATH . '/../classes/general/RCrmActions.php');
|
|
||||||
include($this->INSTALL_PATH . '/../classes/general/user/RetailCrmUser.php');
|
|
||||||
include($this->INSTALL_PATH . '/../classes/general/events/RetailCrmEvent.php');
|
|
||||||
require_once $this->INSTALL_PATH . '/../classes/general/RetailcrmConfigProvider.php';
|
|
||||||
include($this->INSTALL_PATH . '/../lib/model/bitrix/xml/offerparam.php');
|
|
||||||
include($this->INSTALL_PATH . '/../lib/icml/settingsservice.php');
|
|
||||||
include($this->INSTALL_PATH . '/../lib/component/agent.php');
|
|
||||||
include($this->INSTALL_PATH . '/../lib/model/bitrix/xml/selectparams.php');
|
|
||||||
include($this->INSTALL_PATH . '/../lib/model/bitrix/xml/unit.php');
|
|
||||||
include($this->INSTALL_PATH . '/../lib/model/bitrix/xml/xmlcategory.php');
|
|
||||||
include($this->INSTALL_PATH . '/../lib/model/bitrix/xml/xmldata.php');
|
|
||||||
include($this->INSTALL_PATH . '/../lib/model/bitrix/xml/xmloffer.php');
|
|
||||||
include($this->INSTALL_PATH . '/../lib/model/bitrix/xml/xmlsetup.php');
|
|
||||||
include($this->INSTALL_PATH . '/../lib/model/bitrix/xml/xmlsetupprops.php');
|
|
||||||
include($this->INSTALL_PATH . '/../lib/model/bitrix/xml/xmlsetuppropscategories.php');
|
|
||||||
include($this->INSTALL_PATH . '/../lib/icml/icmldirector.php');
|
|
||||||
include($this->INSTALL_PATH . '/../lib/icml/icmlwriter.php');
|
|
||||||
include($this->INSTALL_PATH . '/../lib/icml/queryparamsmolder.php');
|
|
||||||
include($this->INSTALL_PATH . '/../lib/icml/xmlcategorydirector.php');
|
|
||||||
include($this->INSTALL_PATH . '/../lib/icml/xmlcategoryfactory.php');
|
|
||||||
include($this->INSTALL_PATH . '/../lib/icml/xmlofferdirector.php');
|
|
||||||
include($this->INSTALL_PATH . '/../lib/icml/xmlofferbuilder.php');
|
|
||||||
include($this->INSTALL_PATH . '/../lib/icml/utils/icmlutils.php');
|
|
||||||
include($this->INSTALL_PATH . '/../lib/repository/catalogrepository.php');
|
|
||||||
include($this->INSTALL_PATH . '/../lib/repository/filerepository.php');
|
|
||||||
include($this->INSTALL_PATH . '/../lib/repository/hlrepository.php');
|
|
||||||
include($this->INSTALL_PATH . '/../lib/repository/measurerepository.php');
|
|
||||||
include($this->INSTALL_PATH . '/../lib/repository/siterepository.php');
|
|
||||||
include($this->INSTALL_PATH . '/../lib/service/hl.php');
|
|
||||||
include($this->INSTALL_PATH . '/../lib/model/bitrix/orm/catalogiblockinfo.php');
|
|
||||||
include($this->INSTALL_PATH . '/../lib/model/bitrix/orm/iblockcatalog.php');
|
|
||||||
include($this->INSTALL_PATH . '/../classes/general/Exception/InvalidJsonException.php');
|
|
||||||
include($this->INSTALL_PATH . '/../classes/general/Exception/CurlException.php');
|
|
||||||
include($this->INSTALL_PATH . '/../classes/general/RestNormalizer.php');
|
|
||||||
include($this->INSTALL_PATH . '/../classes/general/Logger.php');
|
|
||||||
include($this->INSTALL_PATH . '/../classes/general/services/RetailCrmService.php');
|
|
||||||
include($this->INSTALL_PATH . '/../lib/component/constants.php');
|
|
||||||
$version = COption::GetOptionString($this->MODULE_ID, Constants::CRM_API_VERSION, 0);
|
|
||||||
include($this->INSTALL_PATH . '/../classes/general/ApiClient_v5.php');
|
|
||||||
include($this->INSTALL_PATH . '/../classes/general/order/RetailCrmOrder_v5.php');
|
|
||||||
include($this->INSTALL_PATH . '/../classes/general/history/RetailCrmHistory_v5.php');
|
|
||||||
include($this->INSTALL_PATH . '/../classes/general/cart/RetailCrmCart_v5.php');
|
|
||||||
|
|
||||||
$step = (int) $_REQUEST['step'];
|
$step = (int) $_REQUEST['step'];
|
||||||
|
|
||||||
if (file_exists($this->INSTALL_PATH . '/../classes/general/config/options.xml')) {
|
if (file_exists($this->INSTALL_PATH . '/../classes/general/config/options.xml')) {
|
||||||
|
@ -191,22 +153,6 @@ class intaro_retailcrm extends CModule
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
include($this->INSTALL_PATH . '/../lib/model/bitrix/abstractmodelproxy.php');
|
|
||||||
include($this->INSTALL_PATH . '/../lib/model/bitrix/orderprops.php');
|
|
||||||
include($this->INSTALL_PATH . '/../lib/model/bitrix/tomodule.php');
|
|
||||||
include($this->INSTALL_PATH . '/../lib/repository/abstractrepository.php');
|
|
||||||
include($this->INSTALL_PATH . '/../lib/repository/orderpropsrepository.php');
|
|
||||||
include($this->INSTALL_PATH . '/../lib/repository/persontyperepository.php');
|
|
||||||
include($this->INSTALL_PATH . '/../lib/repository/tomodulerepository.php');
|
|
||||||
include($this->INSTALL_PATH . '/../lib/model/bitrix/orm/tomodule.php');
|
|
||||||
include($this->INSTALL_PATH . '/../lib/model/bitrix/agreement.php');
|
|
||||||
include($this->INSTALL_PATH . '/../lib/repository/agreementrepository.php');
|
|
||||||
include($this->INSTALL_PATH . '/../lib/service/orderloyaltydataservice.php');
|
|
||||||
include($this->INSTALL_PATH . '/../lib/service/currencyservice.php');
|
|
||||||
include($this->INSTALL_PATH . '/../lib/component/factory/clientfactory.php');
|
|
||||||
include($this->INSTALL_PATH . '/../lib/component/apiclient/clientadapter.php');
|
|
||||||
include($this->INSTALL_PATH . '/../lib/component/advanced/loyaltyinstaller.php');
|
|
||||||
|
|
||||||
$this->installExport();
|
$this->installExport();
|
||||||
$this->subscriptionSetup();
|
$this->subscriptionSetup();
|
||||||
|
|
||||||
|
|
70
intaro.retailcrm/install/install_deps.php
Normal file
70
intaro.retailcrm/install/install_deps.php
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
require_once($this->INSTALL_PATH . '/../lib/component/apiclient/traits/baseclienttrait.php');
|
||||||
|
require_once($this->INSTALL_PATH . '/../lib/component/apiclient/traits/customerstrait.php');
|
||||||
|
require_once($this->INSTALL_PATH . '/../lib/component/apiclient/traits/customerscorporatetrait.php');
|
||||||
|
require_once($this->INSTALL_PATH . '/../lib/component/apiclient/traits/loyaltytrait.php');
|
||||||
|
require_once($this->INSTALL_PATH . '/../lib/component/apiclient/traits/ordertrait.php');
|
||||||
|
require_once($this->INSTALL_PATH . '/../lib/component/apiclient/traits/carttrait.php');
|
||||||
|
require_once($this->INSTALL_PATH . '/../classes/general/Http/Client.php');
|
||||||
|
require_once($this->INSTALL_PATH . '/../classes/general/Response/ApiResponse.php');
|
||||||
|
require_once($this->INSTALL_PATH . '/../classes/general/RCrmActions.php');
|
||||||
|
require_once($this->INSTALL_PATH . '/../classes/general/user/RetailCrmUser.php');
|
||||||
|
require_once($this->INSTALL_PATH . '/../classes/general/events/RetailCrmEvent.php');
|
||||||
|
require_once $this->INSTALL_PATH . '/../classes/general/RetailcrmConfigProvider.php';
|
||||||
|
require_once($this->INSTALL_PATH . '/../lib/model/bitrix/xml/offerparam.php');
|
||||||
|
require_once($this->INSTALL_PATH . '/../lib/icml/settingsservice.php');
|
||||||
|
require_once($this->INSTALL_PATH . '/../lib/component/agent.php');
|
||||||
|
require_once($this->INSTALL_PATH . '/../lib/model/bitrix/xml/selectparams.php');
|
||||||
|
require_once($this->INSTALL_PATH . '/../lib/model/bitrix/xml/unit.php');
|
||||||
|
require_once($this->INSTALL_PATH . '/../lib/model/bitrix/xml/xmlcategory.php');
|
||||||
|
require_once($this->INSTALL_PATH . '/../lib/model/bitrix/xml/xmldata.php');
|
||||||
|
require_once($this->INSTALL_PATH . '/../lib/model/bitrix/xml/xmloffer.php');
|
||||||
|
require_once($this->INSTALL_PATH . '/../lib/model/bitrix/xml/xmlsetup.php');
|
||||||
|
require_once($this->INSTALL_PATH . '/../lib/model/bitrix/xml/xmlsetupprops.php');
|
||||||
|
require_once($this->INSTALL_PATH . '/../lib/model/bitrix/xml/xmlsetuppropscategories.php');
|
||||||
|
require_once($this->INSTALL_PATH . '/../lib/icml/icmldirector.php');
|
||||||
|
require_once($this->INSTALL_PATH . '/../lib/icml/icmlwriter.php');
|
||||||
|
require_once($this->INSTALL_PATH . '/../lib/icml/queryparamsmolder.php');
|
||||||
|
require_once($this->INSTALL_PATH . '/../lib/icml/xmlcategorydirector.php');
|
||||||
|
require_once($this->INSTALL_PATH . '/../lib/icml/xmlcategoryfactory.php');
|
||||||
|
require_once($this->INSTALL_PATH . '/../lib/icml/xmlofferdirector.php');
|
||||||
|
require_once($this->INSTALL_PATH . '/../lib/icml/xmlofferbuilder.php');
|
||||||
|
require_once($this->INSTALL_PATH . '/../lib/repository/catalogrepository.php');
|
||||||
|
require_once($this->INSTALL_PATH . '/../lib/repository/filerepository.php');
|
||||||
|
require_once($this->INSTALL_PATH . '/../lib/repository/hlrepository.php');
|
||||||
|
require_once($this->INSTALL_PATH . '/../lib/repository/measurerepository.php');
|
||||||
|
require_once($this->INSTALL_PATH . '/../lib/repository/siterepository.php');
|
||||||
|
require_once($this->INSTALL_PATH . '/../lib/service/hl.php');
|
||||||
|
require_once($this->INSTALL_PATH . '/../lib/model/bitrix/orm/catalogiblockinfo.php');
|
||||||
|
require_once($this->INSTALL_PATH . '/../lib/model/bitrix/orm/iblockcatalog.php');
|
||||||
|
require_once($this->INSTALL_PATH . '/../classes/general/Exception/InvalidJsonException.php');
|
||||||
|
require_once($this->INSTALL_PATH . '/../classes/general/Exception/CurlException.php');
|
||||||
|
require_once($this->INSTALL_PATH . '/../classes/general/RestNormalizer.php');
|
||||||
|
require_once($this->INSTALL_PATH . '/../classes/general/Logger.php');
|
||||||
|
require_once($this->INSTALL_PATH . '/../classes/general/services/RetailCrmService.php');
|
||||||
|
require_once($this->INSTALL_PATH . '/../lib/component/constants.php');
|
||||||
|
require_once($this->INSTALL_PATH . '/../classes/general/ApiClient_v5.php');
|
||||||
|
require_once($this->INSTALL_PATH . '/../classes/general/order/RetailCrmOrder_v5.php');
|
||||||
|
require_once($this->INSTALL_PATH . '/../classes/general/history/RetailCrmHistory_v5.php');
|
||||||
|
require_once($this->INSTALL_PATH . '/../classes/general/cart/RetailCrmCart_v5.php');
|
||||||
|
require_once($this->INSTALL_PATH . '/../lib/service/managerservice.php');
|
||||||
|
require_once($this->INSTALL_PATH . '/../lib/service/loyaltyservice.php');
|
||||||
|
require_once($this->INSTALL_PATH . '/../lib/service/loyaltyaccountservice.php');
|
||||||
|
require_once($this->INSTALL_PATH . '/../lib/repository/managerrepository.php');
|
||||||
|
require_once($this->INSTALL_PATH . '/../classes/general/services/BitrixOrderService.php');
|
||||||
|
require_once($this->INSTALL_PATH . '/../lib/model/bitrix/abstractmodelproxy.php');
|
||||||
|
require_once($this->INSTALL_PATH . '/../lib/model/bitrix/orderprops.php');
|
||||||
|
require_once($this->INSTALL_PATH . '/../lib/model/bitrix/tomodule.php');
|
||||||
|
require_once($this->INSTALL_PATH . '/../lib/repository/abstractrepository.php');
|
||||||
|
require_once($this->INSTALL_PATH . '/../lib/repository/orderpropsrepository.php');
|
||||||
|
require_once($this->INSTALL_PATH . '/../lib/repository/persontyperepository.php');
|
||||||
|
require_once($this->INSTALL_PATH . '/../lib/repository/tomodulerepository.php');
|
||||||
|
require_once($this->INSTALL_PATH . '/../lib/model/bitrix/orm/tomodule.php');
|
||||||
|
require_once($this->INSTALL_PATH . '/../lib/model/bitrix/agreement.php');
|
||||||
|
require_once($this->INSTALL_PATH . '/../lib/repository/agreementrepository.php');
|
||||||
|
require_once($this->INSTALL_PATH . '/../lib/service/orderloyaltydataservice.php');
|
||||||
|
require_once($this->INSTALL_PATH . '/../lib/service/currencyservice.php');
|
||||||
|
require_once($this->INSTALL_PATH . '/../lib/component/factory/clientfactory.php');
|
||||||
|
require_once($this->INSTALL_PATH . '/../lib/component/apiclient/clientadapter.php');
|
||||||
|
require_once($this->INSTALL_PATH . '/../lib/component/advanced/loyaltyinstaller.php');
|
|
@ -1,6 +1,6 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
$arModuleVersion = [
|
$arModuleVersion = [
|
||||||
'VERSION' => '6.5.39',
|
'VERSION' => '6.6.11',
|
||||||
'VERSION_DATE' => '2024-12-08 18:30:00'
|
'VERSION_DATE' => '2025-03-26 16:00:00'
|
||||||
];
|
];
|
||||||
|
|
|
@ -47,3 +47,5 @@ $MESS['BASE_PRICE'] = 'Base price';
|
||||||
$MESS['WAIT'] = 'Loading...';
|
$MESS['WAIT'] = 'Loading...';
|
||||||
$MESS["OFFERS_VALUE"] = "Maximum number of trade offers for a product";
|
$MESS["OFFERS_VALUE"] = "Maximum number of trade offers for a product";
|
||||||
$MESS["LOAD_NON_ACTIVITY"] = "Unload inactive products, services and trade offers";
|
$MESS["LOAD_NON_ACTIVITY"] = "Unload inactive products, services and trade offers";
|
||||||
|
$MESS["ADD_PROPERTY"] = "Add property";
|
||||||
|
$MESS["DELETE_PROPERTY"] = "Delete";
|
||||||
|
|
|
@ -148,7 +148,7 @@ $MESS ['NO_INTEGRATION_PAYMENT'] = '(Non-integrated)';
|
||||||
$MESS ['ERR_CHECK_JOURNAL'] = 'Error while saving. Details in the event log';
|
$MESS ['ERR_CHECK_JOURNAL'] = 'Error while saving. Details in the event log';
|
||||||
$MESS ['ERROR_LINK_INTEGRATION_PAYMENT'] = 'Error in comparing integration payments';
|
$MESS ['ERROR_LINK_INTEGRATION_PAYMENT'] = 'Error in comparing integration payments';
|
||||||
$MESS ['ERROR_UPDATE_PAYMENT_TYPES_DELIVERY'] = 'Error when updating payment methods for deliveries';
|
$MESS ['ERROR_UPDATE_PAYMENT_TYPES_DELIVERY'] = 'Error when updating payment methods for deliveries';
|
||||||
$MESS ['INTEGRATION_PAYMENT_LABEL'] = 'When correlating CMS and CRM integration payments, a regular payment is created on the system side to which orders will be linked.';
|
$MESS ['INTEGRATION_PAYMENT_LABEL'] = 'When correlating CMS and CRM integration payments, a regular payment is created on the system side to which orders will be linked. <br> If you have integration deliveries in your CRM, then you need to enable the new payment method in the integration settings';
|
||||||
$MESS ['NEED_PERMISSIONS_REFERENCE_LABEL'] = 'For this option to work correctly, the api key needs access to receive and edit reference book';
|
$MESS ['NEED_PERMISSIONS_REFERENCE_LABEL'] = 'For this option to work correctly, the api key needs access to receive and edit reference book';
|
||||||
|
|
||||||
$MESS ['FIX_UPLOAD_CUSTOMER_HEADER'] = 'Fix customer registration date in CRM';
|
$MESS ['FIX_UPLOAD_CUSTOMER_HEADER'] = 'Fix customer registration date in CRM';
|
||||||
|
|
|
@ -47,3 +47,5 @@ $MESS["UNIT_MEASUREMENT_KG"] = "кг.";
|
||||||
$MESS['BASE_PRICE'] = 'Базовая цена';
|
$MESS['BASE_PRICE'] = 'Базовая цена';
|
||||||
$MESS['WAIT'] = 'Загрузка...';
|
$MESS['WAIT'] = 'Загрузка...';
|
||||||
$MESS["OFFERS_VALUE"] = "Максимальное количество торговых предложений у товара";
|
$MESS["OFFERS_VALUE"] = "Максимальное количество торговых предложений у товара";
|
||||||
|
$MESS["ADD_PROPERTY"] = "Добавить свойство";
|
||||||
|
$MESS["DELETE_PROPERTY"] = "Удалить";
|
||||||
|
|
|
@ -213,7 +213,7 @@ $MESS ['NO_INTEGRATION_PAYMENT'] = '(Не интеграционная)';
|
||||||
$MESS ['ERR_CHECK_JOURNAL'] = 'Ошибка при сохранении. Подробности в журнале событий';
|
$MESS ['ERR_CHECK_JOURNAL'] = 'Ошибка при сохранении. Подробности в журнале событий';
|
||||||
$MESS ['ERROR_LINK_INTEGRATION_PAYMENT'] = 'Ошибка при сопоставлении интеграционных оплат';
|
$MESS ['ERROR_LINK_INTEGRATION_PAYMENT'] = 'Ошибка при сопоставлении интеграционных оплат';
|
||||||
$MESS ['ERROR_UPDATE_PAYMENT_TYPES_DELIVERY'] = 'Ошибка при обновлении способов оплаты для доставок';
|
$MESS ['ERROR_UPDATE_PAYMENT_TYPES_DELIVERY'] = 'Ошибка при обновлении способов оплаты для доставок';
|
||||||
$MESS ['INTEGRATION_PAYMENT_LABEL'] = 'При сопоставлении интеграционных оплат CRM, на стороне системы создаётся обычная оплата, к которой будут привязываться заказы.';
|
$MESS ['INTEGRATION_PAYMENT_LABEL'] = 'При сопоставлении интеграционных оплат CRM, на стороне системы создаётся обычная оплата, к которой будут привязываться заказы. <br> Если в вашей CRM используются интеграционные доставки, новый способ оплаты необходимо вручную активировать в настройках интеграций.';
|
||||||
$MESS ['NEED_PERMISSIONS_REFERENCE_LABEL'] = 'Для корректной работы опции апи-ключу необходимы доступы на получение и редактирование справочников';
|
$MESS ['NEED_PERMISSIONS_REFERENCE_LABEL'] = 'Для корректной работы опции апи-ключу необходимы доступы на получение и редактирование справочников';
|
||||||
|
|
||||||
$MESS ['FIX_UPLOAD_CUSTOMER_HEADER'] = 'Исправление даты регистрации клиентов в CRM';
|
$MESS ['FIX_UPLOAD_CUSTOMER_HEADER'] = 'Исправление даты регистрации клиентов в CRM';
|
||||||
|
|
|
@ -24,15 +24,19 @@ trait InstallerTrait
|
||||||
false
|
false
|
||||||
);
|
);
|
||||||
|
|
||||||
$path = $_SERVER['DOCUMENT_ROOT'] . '/local/';
|
$pathFrom = $_SERVER['DOCUMENT_ROOT'] .
|
||||||
|
'/bitrix/modules/' .
|
||||||
|
Constants::MODULE_ID .
|
||||||
|
'/install/export/bitrix/js/intaro/export'
|
||||||
|
;
|
||||||
|
|
||||||
CheckDirPath($path);
|
CopyDirFiles(
|
||||||
|
$pathFrom,
|
||||||
$file = new \Bitrix\Main\IO\File($path . 'icml_property_retailcrm.txt', $siteId = null);
|
$_SERVER['DOCUMENT_ROOT'] . '/bitrix/js/intaro/export/',
|
||||||
|
true,
|
||||||
if (!$file->isExists()) {
|
true,
|
||||||
$file->putContents("");
|
false
|
||||||
}
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function subscriptionSetup()
|
public function subscriptionSetup()
|
||||||
|
|
|
@ -18,7 +18,7 @@ namespace Intaro\RetailCrm\Component;
|
||||||
*/
|
*/
|
||||||
class Constants
|
class Constants
|
||||||
{
|
{
|
||||||
public const MODULE_VERSION = '6.5.39';
|
public const MODULE_VERSION = '6.6.11';
|
||||||
public const CRM_PURCHASE_PRICE_NULL = 'purchasePrice_null';
|
public const CRM_PURCHASE_PRICE_NULL = 'purchasePrice_null';
|
||||||
public const BITRIX_USER_ID_PREFIX = 'bitrixUserId-';
|
public const BITRIX_USER_ID_PREFIX = 'bitrixUserId-';
|
||||||
public const CRM_USERS_MAP = 'crm_users_map';
|
public const CRM_USERS_MAP = 'crm_users_map';
|
||||||
|
|
95
intaro.retailcrm/lib/controller/customexportprops.php
Normal file
95
intaro.retailcrm/lib/controller/customexportprops.php
Normal file
|
@ -0,0 +1,95 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Intaro\RetailCrm\Controller;
|
||||||
|
|
||||||
|
use Bitrix\Main\Engine\Controller;
|
||||||
|
use Bitrix\Main\Result;
|
||||||
|
use Bitrix\Main\Error;
|
||||||
|
use Bitrix\Main\Application;
|
||||||
|
use Intaro\RetailCrm\Icml\SettingsService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @category Integration
|
||||||
|
* @package Intaro\RetailCrm\Controller
|
||||||
|
* @author RetailCRM <integration@retailcrm.ru>
|
||||||
|
* @license MIT
|
||||||
|
* @link http://retailcrm.ru
|
||||||
|
* @see http://retailcrm.ru/docs
|
||||||
|
*/
|
||||||
|
class CustomExportProps extends Controller
|
||||||
|
{
|
||||||
|
private function getRequestData(): array
|
||||||
|
{
|
||||||
|
$data = $this->getRequest()->getInput();
|
||||||
|
|
||||||
|
if ($data === null) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return json_decode($data, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function saveAction()
|
||||||
|
{
|
||||||
|
$requestData = $this->getRequestData();
|
||||||
|
$props = $requestData['properties'];
|
||||||
|
$profileId = $requestData['profileId'];
|
||||||
|
|
||||||
|
$settingsService = SettingsService::getInstance(
|
||||||
|
[],
|
||||||
|
null,
|
||||||
|
$profileId
|
||||||
|
);
|
||||||
|
|
||||||
|
$idCategories = array_keys($props);
|
||||||
|
|
||||||
|
if ($idCategories !== []) {
|
||||||
|
$settingsService->setProfileCatalogs($idCategories);//сразу заменяет и create и update
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($props as $catalogId => $propsArray) {
|
||||||
|
$catalogCustomProps = [];
|
||||||
|
|
||||||
|
foreach ($propsArray as $property) {
|
||||||
|
$catalogCustomProps[] = [
|
||||||
|
'code' => $property['code'],
|
||||||
|
'title' => $property['title']
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
$settingsService
|
||||||
|
->setCatalogCustomPropsOptionName($catalogId)
|
||||||
|
->saveCustomProps($catalogCustomProps)
|
||||||
|
;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function deleteAction()
|
||||||
|
{
|
||||||
|
$requestData = $this->getRequestData();
|
||||||
|
$props = $requestData['properties'];
|
||||||
|
$profileId = $requestData['profileId'];
|
||||||
|
|
||||||
|
$settingsService = SettingsService::getInstance(
|
||||||
|
[],
|
||||||
|
null,
|
||||||
|
$profileId
|
||||||
|
);
|
||||||
|
|
||||||
|
foreach ($props as $catalogId => $propsArray) {
|
||||||
|
$catalogCustomProps = [];
|
||||||
|
|
||||||
|
foreach ($propsArray as $property) {
|
||||||
|
$catalogCustomProps[] = [
|
||||||
|
'code' => $property['code'],
|
||||||
|
'title' => $property['title']
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
$settingsService
|
||||||
|
->setCatalogCustomPropsOptionName($catalogId)
|
||||||
|
->removeCustomProps($catalogCustomProps, $catalogId)
|
||||||
|
;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -163,7 +163,7 @@ class IcmlWriter
|
||||||
$this->writeOptionalSimpleElement('vatRate', $offer->vatRate);
|
$this->writeOptionalSimpleElement('vatRate', $offer->vatRate);
|
||||||
$this->writeOptionalSimpleElement('weight', $offer->weight);
|
$this->writeOptionalSimpleElement('weight', $offer->weight);
|
||||||
$this->writeOptionalSimpleElement('dimensions', $offer->dimensions);
|
$this->writeOptionalSimpleElement('dimensions', $offer->dimensions);
|
||||||
$this->writeOptionalSimpleElement('purchasePrice', $offer->purchasePrice);
|
$this->writeOptionalPurchasePrice($offer->purchasePrice);
|
||||||
$this->writer->endElement();
|
$this->writer->endElement();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -180,6 +180,16 @@ class IcmlWriter
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Запись закупочной стоимости
|
||||||
|
*
|
||||||
|
* @param $value
|
||||||
|
*/
|
||||||
|
private function writeOptionalPurchasePrice($value): void
|
||||||
|
{
|
||||||
|
$this->writeSimpleElement('purchasePrice', !empty($value) ? $value : 0);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $name
|
* @param string $name
|
||||||
* @param $value
|
* @param $value
|
||||||
|
|
|
@ -8,14 +8,19 @@ use CCatalogGroup;
|
||||||
use CCatalogSku;
|
use CCatalogSku;
|
||||||
use CCatalogVat;
|
use CCatalogVat;
|
||||||
use CIBlock;
|
use CIBlock;
|
||||||
|
use COption;
|
||||||
|
use Bitrix\Main\Config\Option;
|
||||||
use Intaro\RetailCrm\Service\Hl;
|
use Intaro\RetailCrm\Service\Hl;
|
||||||
use RetailcrmConfigProvider;
|
use RetailcrmConfigProvider;
|
||||||
|
use Bitrix\Main\Application;
|
||||||
|
use Bitrix\Main\Entity\Query;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Отвечает за управление настройками выгрузки icml каталога
|
* Отвечает за управление настройками выгрузки icml каталога
|
||||||
*
|
* @var $PROFILE_ID - зачем если получаем в в конструкторе инстансе
|
||||||
* Class SettingsService
|
* Class SettingsService
|
||||||
*
|
*
|
||||||
|
*
|
||||||
* @package Intaro\RetailCrm\Icml
|
* @package Intaro\RetailCrm\Icml
|
||||||
*/
|
*/
|
||||||
class SettingsService
|
class SettingsService
|
||||||
|
@ -32,6 +37,14 @@ class SettingsService
|
||||||
*/
|
*/
|
||||||
public const INFOBLOCK_WITH_SKU = 'P';
|
public const INFOBLOCK_WITH_SKU = 'P';
|
||||||
|
|
||||||
|
private const MODULE_ID = 'intaro.retailcrm';
|
||||||
|
|
||||||
|
private string $catalogCustomPropsOptionName;
|
||||||
|
|
||||||
|
private string $profileCatalogsOptionName;
|
||||||
|
|
||||||
|
private string $exportProfileId;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var array
|
* @var array
|
||||||
*/
|
*/
|
||||||
|
@ -98,7 +111,13 @@ class SettingsService
|
||||||
public $loadNonActivity;
|
public $loadNonActivity;
|
||||||
|
|
||||||
/** @var array */
|
/** @var array */
|
||||||
public $actrualPropList = [];
|
public $actualPropList = [];
|
||||||
|
|
||||||
|
/** @var array */
|
||||||
|
public $customPropList = [];
|
||||||
|
|
||||||
|
/** @var array */
|
||||||
|
public $defaultPropList = [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var \Intaro\RetailCrm\Icml\SettingsService|null
|
* @var \Intaro\RetailCrm\Icml\SettingsService|null
|
||||||
|
@ -112,7 +131,7 @@ class SettingsService
|
||||||
* @param array $arOldSetupVars
|
* @param array $arOldSetupVars
|
||||||
* @param string|null $action
|
* @param string|null $action
|
||||||
*/
|
*/
|
||||||
private function __construct(array $arOldSetupVars, ?string $action)
|
private function __construct(array $arOldSetupVars, ?string $action, ?string $profileId)
|
||||||
{
|
{
|
||||||
$this->arOldSetupVars = $arOldSetupVars;
|
$this->arOldSetupVars = $arOldSetupVars;
|
||||||
$this->action = $action;
|
$this->action = $action;
|
||||||
|
@ -128,7 +147,15 @@ class SettingsService
|
||||||
$this->getPriceTypes();
|
$this->getPriceTypes();
|
||||||
$this->getVatRates();
|
$this->getVatRates();
|
||||||
|
|
||||||
$this->actrualPropList = array_merge($this->getIblockPropsPreset(), $this->parseNewProps());
|
$this->exportProfileId = $profileId ?? '0';
|
||||||
|
$this->profileCatalogsOptionName = sprintf('exportProfileId_%s_catalogs', $this->exportProfileId);
|
||||||
|
|
||||||
|
$this->linkNewProfile();
|
||||||
|
$this->deleteEmptyProfileCatalogs();
|
||||||
|
|
||||||
|
$this->customPropList = $this->getNewProps();
|
||||||
|
$this->defaultPropList = $this->getIblockPropsPreset();
|
||||||
|
$this->actualPropList = $this->getActualPropList();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -137,16 +164,29 @@ class SettingsService
|
||||||
*
|
*
|
||||||
* @return \Intaro\RetailCrm\Icml\SettingsService|null
|
* @return \Intaro\RetailCrm\Icml\SettingsService|null
|
||||||
*/
|
*/
|
||||||
public static function getInstance(array $arOldSetupVars, ?string $action): ?SettingsService
|
public static function getInstance(array $arOldSetupVars, ?string $action, ?string $profileId): ?SettingsService
|
||||||
{
|
{
|
||||||
if (is_null(self::$instance)) {
|
if (is_null(self::$instance)) {
|
||||||
self::$instance = new self($arOldSetupVars, $action);
|
self::$instance = new self($arOldSetupVars, $action, $profileId);
|
||||||
}
|
}
|
||||||
|
|
||||||
return self::$instance;
|
return self::$instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getPriceTypes()
|
private function getActualPropList(): array
|
||||||
|
{
|
||||||
|
$customProps = [];
|
||||||
|
|
||||||
|
foreach ($this->customPropList as $propsByCatalog) {
|
||||||
|
foreach ($propsByCatalog as $code => $value) {
|
||||||
|
$customProps[$code] = $value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return array_merge($this->defaultPropList, $customProps);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getPriceTypes()
|
||||||
{
|
{
|
||||||
$dbPriceType = CCatalogGroup::GetList(['SORT' => 'ASC'], [], [], [], ['ID', 'NAME', 'BASE']);
|
$dbPriceType = CCatalogGroup::GetList(['SORT' => 'ASC'], [], [], [], ['ID', 'NAME', 'BASE']);
|
||||||
|
|
||||||
|
@ -155,7 +195,7 @@ class SettingsService
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getVatRates()
|
private function getVatRates()
|
||||||
{
|
{
|
||||||
$dbVatRate = CCatalogVat::GetListEx(['SORT' => 'ASC'], ['ACTIVE' => 'Y'], false, false, ['ID', 'NAME', 'RATE']);
|
$dbVatRate = CCatalogVat::GetListEx(['SORT' => 'ASC'], ['ACTIVE' => 'Y'], false, false, ['ID', 'NAME', 'RATE']);
|
||||||
|
|
||||||
|
@ -230,7 +270,9 @@ class SettingsService
|
||||||
private function setProperties(array &$properties, string $propName): void
|
private function setProperties(array &$properties, string $propName): void
|
||||||
{
|
{
|
||||||
foreach ($this->arOldSetupVars[$propName] as $iblock => $val) {
|
foreach ($this->arOldSetupVars[$propName] as $iblock => $val) {
|
||||||
$properties[$iblock][$propName] = $val;
|
if (!empty($val)) {
|
||||||
|
$properties[$iblock][$propName] = $val;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -260,27 +302,22 @@ class SettingsService
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
private function parseNewProps(): array
|
private function getNewProps(): array
|
||||||
{
|
{
|
||||||
global $APPLICATION;
|
|
||||||
|
|
||||||
$result = [];
|
$result = [];
|
||||||
$text = $APPLICATION->GetFileContent($_SERVER["DOCUMENT_ROOT"] . "/local/icml_property_retailcrm.txt");
|
$currentProfileCatalogIds = $this->getProfileCatalogs();
|
||||||
|
|
||||||
if ($text === false) {
|
if (!is_null($currentProfileCatalogIds)) {
|
||||||
return $result;
|
foreach ($currentProfileCatalogIds as $catalogId) {
|
||||||
}
|
$catalogCustomProps = $this
|
||||||
|
->setCatalogCustomPropsOptionName($catalogId)
|
||||||
|
->getCustomProps()
|
||||||
|
;
|
||||||
|
|
||||||
preg_match_all('/\w+\s*=\s*\w+[ *\w+]*/mu', $text, $matches);
|
foreach ($catalogCustomProps as $prop) {
|
||||||
|
$result[$catalogId][$prop['code']] = $prop['title'];
|
||||||
foreach ($matches[0] as $newProp) {
|
}
|
||||||
$elements = explode("=", $newProp);
|
|
||||||
|
|
||||||
if (empty($elements[0]) || empty($elements[1])) {
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$result[trim($elements[0])] = trim($elements[1]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return $result;
|
return $result;
|
||||||
|
@ -289,7 +326,7 @@ class SettingsService
|
||||||
/**
|
/**
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
public function getHintProps(): array
|
private function getHintProps(): array
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'article' => ['ARTICLE', 'ART', 'ARTNUMBER', 'ARTICUL', 'ARTIKUL'],
|
'article' => ['ARTICLE', 'ART', 'ARTNUMBER', 'ARTICUL', 'ARTIKUL'],
|
||||||
|
@ -365,7 +402,7 @@ class SettingsService
|
||||||
|
|
||||||
public function setProps(): void
|
public function setProps(): void
|
||||||
{
|
{
|
||||||
foreach (array_keys($this->actrualPropList) as $prop) {
|
foreach (array_keys($this->actualPropList) as $prop) {
|
||||||
$this->setProperties($this->iblockPropertySku, 'iblockPropertySku_' . $prop);
|
$this->setProperties($this->iblockPropertySku, 'iblockPropertySku_' . $prop);
|
||||||
$this->setProperties($this->iblockPropertyUnitSku, 'iblockPropertyUnitSku_' . $prop);
|
$this->setProperties($this->iblockPropertyUnitSku, 'iblockPropertyUnitSku_' . $prop);
|
||||||
$this->setProperties($this->iblockPropertyProduct, 'iblockPropertyProduct_' . $prop);
|
$this->setProperties($this->iblockPropertyProduct, 'iblockPropertyProduct_' . $prop);
|
||||||
|
@ -548,7 +585,7 @@ class SettingsService
|
||||||
*
|
*
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
public function getSiteList(int $iblockId): array
|
private function getSiteList(int $iblockId): array
|
||||||
{
|
{
|
||||||
$siteList = [];
|
$siteList = [];
|
||||||
|
|
||||||
|
@ -576,7 +613,9 @@ class SettingsService
|
||||||
$dbSkuProperties = CIBlock::GetProperties($iblockOffer['IBLOCK_ID'], [], ['MULTIPLE' => 'N']);
|
$dbSkuProperties = CIBlock::GetProperties($iblockOffer['IBLOCK_ID'], [], ['MULTIPLE' => 'N']);
|
||||||
|
|
||||||
while ($prop = $dbSkuProperties->Fetch()) {
|
while ($prop = $dbSkuProperties->Fetch()) {
|
||||||
$propertiesSKU[] = $prop;
|
if ($prop['CODE'] !== '') {
|
||||||
|
$propertiesSKU[] = $prop;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -597,7 +636,7 @@ class SettingsService
|
||||||
$props = [];
|
$props = [];
|
||||||
|
|
||||||
if (isset($oldValues[$iblockId])) {
|
if (isset($oldValues[$iblockId])) {
|
||||||
foreach (array_keys($this->actrualPropList) as $prop) {
|
foreach (array_keys($this->actualPropList) as $prop) {
|
||||||
$fullKey = $keyGroup . '_' . $prop;
|
$fullKey = $keyGroup . '_' . $prop;
|
||||||
$props[$prop] = $oldValues[$iblockId][$fullKey];
|
$props[$prop] = $oldValues[$iblockId][$fullKey];
|
||||||
}
|
}
|
||||||
|
@ -623,14 +662,16 @@ class SettingsService
|
||||||
*
|
*
|
||||||
* @return array|null
|
* @return array|null
|
||||||
*/
|
*/
|
||||||
public function getProductProps(int $iblockId): ?array
|
private function getProductProps(int $iblockId): ?array
|
||||||
{
|
{
|
||||||
$propertiesProduct = null;
|
$propertiesProduct = null;
|
||||||
|
|
||||||
$iblockResult = CIBlock::GetProperties($iblockId, [], ['MULTIPLE' => 'N']);
|
$iblockResult = CIBlock::GetProperties($iblockId, [], ['MULTIPLE' => 'N']);
|
||||||
|
|
||||||
while ($prop = $iblockResult->Fetch()) {
|
while ($prop = $iblockResult->Fetch()) {
|
||||||
$propertiesProduct[] = $prop;
|
if ($prop['CODE'] !== '') {
|
||||||
|
$propertiesProduct[] = $prop;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $propertiesProduct;
|
return $propertiesProduct;
|
||||||
|
@ -642,7 +683,7 @@ class SettingsService
|
||||||
*
|
*
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
public function isExport($iblockId, $iblockExport): bool
|
private function isExport($iblockId, $iblockExport): bool
|
||||||
{
|
{
|
||||||
if (is_array($iblockExport) && count($iblockExport) !== 0) {
|
if (is_array($iblockExport) && count($iblockExport) !== 0) {
|
||||||
return (in_array($iblockId, $iblockExport));
|
return (in_array($iblockId, $iblockExport));
|
||||||
|
@ -747,4 +788,152 @@ class SettingsService
|
||||||
|
|
||||||
return [$arIBlockList, $intCountChecked, $intCountAvailIBlock, $arIBlockList['iblockExport'] ?? false];
|
return [$arIBlockList, $intCountChecked, $intCountAvailIBlock, $arIBlockList['iblockExport'] ?? false];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function setCatalogCustomPropsOptionName(string $catalogId): self
|
||||||
|
{
|
||||||
|
$this->catalogCustomPropsOptionName = sprintf(
|
||||||
|
'exportCustomProps_ProfileId_%s_catalogId_%s',
|
||||||
|
$this->exportProfileId,
|
||||||
|
$catalogId
|
||||||
|
);
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getCustomProps(): ?array
|
||||||
|
{
|
||||||
|
$props = unserialize(COption::GetOptionString(self::MODULE_ID, $this->catalogCustomPropsOptionName));
|
||||||
|
|
||||||
|
if (!$props) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $props;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function removeCustomProps(array $propsToDelete, string $catalogId): void
|
||||||
|
{
|
||||||
|
$currentCatalogProps = $this->getCustomProps();
|
||||||
|
$updatedCatalogProps = array_values(
|
||||||
|
array_filter(
|
||||||
|
$currentCatalogProps,
|
||||||
|
fn ($currentProp) => !in_array($currentProp, $propsToDelete)
|
||||||
|
));
|
||||||
|
|
||||||
|
if (empty($updatedCatalogProps)) {
|
||||||
|
$this->deleteOptionEntry($this->catalogCustomPropsOptionName);
|
||||||
|
$this->deleteProfileCatalog($catalogId);
|
||||||
|
} else {
|
||||||
|
$this->updateCustomProps($updatedCatalogProps);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function updateCustomProps(array $updatedProps)
|
||||||
|
{
|
||||||
|
$serializedProps = serialize($updatedProps);
|
||||||
|
$this->updateOptionEntry($this->catalogCustomPropsOptionName, $serializedProps);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function setCustomProps(array $props)
|
||||||
|
{
|
||||||
|
$propsString = serialize($props);
|
||||||
|
$this->setOptionEntry($this->catalogCustomPropsOptionName, $propsString);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function saveCustomProps(array $newProps): void
|
||||||
|
{
|
||||||
|
$currentProps = $this->getCustomProps();
|
||||||
|
|
||||||
|
if (is_null($currentProps)) {
|
||||||
|
$this->setCustomProps($newProps);
|
||||||
|
} else {
|
||||||
|
$updatedProps = array_merge($currentProps, $newProps);
|
||||||
|
$this->updateCustomProps($updatedProps);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getProfileCatalogs(): ?array
|
||||||
|
{
|
||||||
|
$catalogs = unserialize(COption::GetOptionString(self::MODULE_ID, $this->profileCatalogsOptionName));
|
||||||
|
|
||||||
|
if (!$catalogs) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $catalogs;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setProfileCatalogs(array $catalogsId): void
|
||||||
|
{
|
||||||
|
$catalogs = serialize($catalogsId);
|
||||||
|
$this->setOptionEntry($this->profileCatalogsOptionName, $catalogs);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function deleteProfileCatalog(string $catalogId): void
|
||||||
|
{
|
||||||
|
$currentCatalogs = $this->getProfileCatalogs();
|
||||||
|
$catalogIdIndex = array_search($catalogId, $currentCatalogs);
|
||||||
|
|
||||||
|
if ($catalogIdIndex !== false) {
|
||||||
|
unset($currentCatalogs[$catalogIdIndex]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$updatedCatalogs = serialize($currentCatalogs);
|
||||||
|
$this->updateOptionEntry($this->profileCatalogsOptionName, $updatedCatalogs);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function deleteEmptyProfileCatalogs(): void
|
||||||
|
{
|
||||||
|
$currentCatalogs = $this->getProfileCatalogs();
|
||||||
|
|
||||||
|
if (is_null($currentCatalogs)) {
|
||||||
|
$this->deleteOptionEntry($this->profileCatalogsOptionName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function setOptionEntry(string $name, string $value)
|
||||||
|
{
|
||||||
|
COption::SetOptionString(self::MODULE_ID, $name, $value);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function updateOptionEntry(string $name, string $value)
|
||||||
|
{
|
||||||
|
COption::SetOptionString(self::MODULE_ID, $name, '');
|
||||||
|
COption::SetOptionString(self::MODULE_ID, $name, $value);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function deleteOptionEntry(string $name)
|
||||||
|
{
|
||||||
|
COption::RemoveOption(self::MODULE_ID, $name);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function linkNewProfile(): void
|
||||||
|
{
|
||||||
|
$currentProfileCatalogs = unserialize(COption::GetOptionString(self::MODULE_ID, $this->profileCatalogsOptionName));
|
||||||
|
|
||||||
|
if (!$currentProfileCatalogs) {
|
||||||
|
$tmpProfileName = 'exportProfileId_0_catalogs';
|
||||||
|
$currentProfileCatalogs = unserialize(COption::GetOptionString(self::MODULE_ID, $tmpProfileName));
|
||||||
|
|
||||||
|
if ($currentProfileCatalogs) {
|
||||||
|
$this->setOptionEntry($this->profileCatalogsOptionName, serialize($currentProfileCatalogs));
|
||||||
|
$this->deleteOptionEntry($tmpProfileName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($currentProfileCatalogs as $catalogId) {
|
||||||
|
$optionName = sprintf('exportCustomProps_ProfileId_%s_catalogId_%s', $this->exportProfileId, $catalogId);
|
||||||
|
$propsCatalog = unserialize(COption::GetOptionString(self::MODULE_ID, $optionName));
|
||||||
|
|
||||||
|
if (!$propsCatalog) {
|
||||||
|
$tmpOptionName = sprintf('exportCustomProps_ProfileId_%s_catalogId_%s', '0', $catalogId);
|
||||||
|
$propsCatalog = unserialize(COption::GetOptionString(self::MODULE_ID, $tmpOptionName));
|
||||||
|
|
||||||
|
if ($propsCatalog) {
|
||||||
|
$this->setOptionEntry($optionName, serialize($propsCatalog));
|
||||||
|
$this->deleteOptionEntry($tmpOptionName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -115,8 +115,8 @@ class XmlOfferBuilder
|
||||||
public function __construct(XmlSetup $setup, array $measure, ?string $serverName)
|
public function __construct(XmlSetup $setup, array $measure, ?string $serverName)
|
||||||
{
|
{
|
||||||
$this->setup = $setup;
|
$this->setup = $setup;
|
||||||
|
$this->setSettingsService();
|
||||||
$this->purchasePriceNull = RetailcrmConfigProvider::getCrmPurchasePrice();
|
$this->purchasePriceNull = RetailcrmConfigProvider::getCrmPurchasePrice();
|
||||||
$this->settingsService = SettingsService::getInstance([], '');
|
|
||||||
$this->vatRates = $this->settingsService->vatRates;
|
$this->vatRates = $this->settingsService->vatRates;
|
||||||
$this->measures = $this->prepareMeasures($measure);
|
$this->measures = $this->prepareMeasures($measure);
|
||||||
$this->serverName = $serverName;
|
$this->serverName = $serverName;
|
||||||
|
@ -141,6 +141,12 @@ class XmlOfferBuilder
|
||||||
return $this->xmlOffer;
|
return $this->xmlOffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function setSettingsService(): void
|
||||||
|
{
|
||||||
|
global $PROFILE_ID;
|
||||||
|
$this->settingsService = SettingsService::getInstance([], '', $PROFILE_ID);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param array $categories
|
* @param array $categories
|
||||||
*/
|
*/
|
||||||
|
@ -479,7 +485,7 @@ class XmlOfferBuilder
|
||||||
private function createParamObject(array $params): array
|
private function createParamObject(array $params): array
|
||||||
{
|
{
|
||||||
$offerParams = [];
|
$offerParams = [];
|
||||||
$names = $this->settingsService->actrualPropList;
|
$names = $this->settingsService->actualPropList;
|
||||||
|
|
||||||
foreach ($params as $code => $value) {
|
foreach ($params as $code => $value) {
|
||||||
|
|
||||||
|
|
|
@ -877,7 +877,9 @@ if (isset($_POST['Update']) && ($_POST['Update'] === 'Y')) {
|
||||||
$substitutionPaymentList[$integrationPayment] = $codePayment;
|
$substitutionPaymentList[$integrationPayment] = $codePayment;
|
||||||
|
|
||||||
foreach ($originalPayment['deliveryTypes'] as $codeDelivery) {
|
foreach ($originalPayment['deliveryTypes'] as $codeDelivery) {
|
||||||
if (!isset($arResult['deliveryTypesList'][$codeDelivery])) {
|
if (!isset($arResult['deliveryTypesList'][$codeDelivery]) ||
|
||||||
|
isset($arResult['deliveryTypesList'][$codeDelivery]['integrationCode'])
|
||||||
|
) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
1290
intaro.retailcrm/updater.php
Normal file → Executable file
1290
intaro.retailcrm/updater.php
Normal file → Executable file
File diff suppressed because it is too large
Load diff
|
@ -17,25 +17,6 @@ class SettingServiceTest extends \BitrixTestCase
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testConstruct(): SettingsService
|
|
||||||
{
|
|
||||||
$path = $_SERVER['DOCUMENT_ROOT'] . '/local/';
|
|
||||||
|
|
||||||
CheckDirPath($path);
|
|
||||||
|
|
||||||
$file = new \Bitrix\Main\IO\File($path . '/icml_property_retailcrm.txt', $siteId = null);
|
|
||||||
|
|
||||||
$file->putContents("property1 = test prop \n property2 = test prop 2");
|
|
||||||
|
|
||||||
$settingService = SettingsService::getInstance($this->getSetupVars(), "");
|
|
||||||
|
|
||||||
$this->assertInstanceOf(SettingsService::class, $settingService);
|
|
||||||
$this->assertArrayHasKey('property1', $settingService->actrualPropList);
|
|
||||||
$this->assertArrayHasKey('property2', $settingService->actrualPropList);
|
|
||||||
|
|
||||||
return $settingService;
|
|
||||||
}
|
|
||||||
|
|
||||||
private function getSetupVars()
|
private function getSetupVars()
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
|
|
Loading…
Add table
Reference in a new issue