1
0
mirror of synced 2024-11-22 05:16:09 +03:00

Optimize generator (#215)

This commit is contained in:
Сергей Чазов 2021-09-08 16:31:17 +03:00 committed by GitHub
parent d06cb3c6e6
commit c3216f72d3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 342 additions and 209 deletions

View File

@ -1,3 +1,9 @@
## 2021-09-08 v.5.8.1
* Оптимизирована работа генератора icml каталога
* В генератор каталога добавлена возможность указывать свойства выгрузки одновременно для простых товаров и товаров с торговыми предложениями
* Исправлена ошибка выгрузки заказов из неподключенного к CRM магазина при использовании нескольких сайтов на одной лицензии
* Изменена логика обмена оплатами: для интеграционных оплат дата оплаты больше не передается из Битрикса
## 2021-08-19 v.5.8.0
* Добавлена синхронизация ответственного менеджера в заказе
* Исправлена ошибка выгрузки заказов с корпоративными клиентами, уже присутствующими в системе

View File

@ -1,3 +1,4 @@
- Добавлена синхронизация ответственного менеджера в заказе
- Исправлена ошибка выгрузки заказов с корпоративными клиентами, уже присутствующими в системе
- Исправлена ошибка выгрузки остатков при наличии более 100 складов в Битрикс
- Оптимизирована работа генератора icml каталога
- В генератор каталога добавлена возможность указывать свойства выгрузки одновременно для простых товаров и товаров с торговыми предложениями
- Исправлена ошибка выгрузки заказов из неподключенного к CRM магазина при использовании нескольких сайтов на одной лицензии
- Изменена логика обмена оплатами: для интеграционных оплат дата оплаты больше не передается из Битрикса

View File

@ -1,6 +1,6 @@
<?php
$arModuleVersion = [
'VERSION' => '5.8.0',
'VERSION_DATE' => '2021-08-19 16:00:00',
'VERSION' => '5.8.1',
'VERSION_DATE' => '2021-09-08 14:00:00',
];

View File

@ -23,52 +23,52 @@ class IcmlDirector
public const OFFERS_PART = 500;
public const FILE_LOG_NAME = 'i_crm_load_log';
public const DEFAULT_PRODUCT_PAGE_SIZE = 1;
/**
* @var IcmlWriter
*/
private $icmlWriter;
/**
* @var \Intaro\RetailCrm\Icml\XmlOfferDirector
*/
private $xmlOfferDirector;
/**
* @var \Intaro\RetailCrm\Model\Bitrix\Xml\XmlSetup
*/
private $setup;
/**
* @var \Intaro\RetailCrm\Repository\CatalogRepository
*/
private $catalogRepository;
/**
* @var string
*/
private $shopName;
/**
* @var \Intaro\RetailCrm\Icml\XmlCategoryDirector
*/
private $xmlCategoryDirector;
/**
* @var \Intaro\RetailCrm\Icml\QueryParamsMolder
*/
private $queryBuilder;
/**
* @var \Intaro\RetailCrm\Model\Bitrix\Xml\XmlData
*/
private $xmlData;
/**
* @var \Logger
*/
private $logger;
/**
* RetailCrmlXml constructor.
*
@ -87,7 +87,7 @@ class IcmlDirector
$this->xmlData = new XmlData();
$this->logger = $logger;
}
/**
* Основной метод. Генерирует icml файл католога товаров Битрикс
*/
@ -115,7 +115,7 @@ class IcmlDirector
self::FILE_LOG_NAME
);
}
/**
* @return void
*/
@ -126,21 +126,21 @@ class IcmlDirector
$this->xmlData->filePath = $this->setup->filePath;
$this->xmlData->categories = $this->xmlCategoryDirector->getXmlCategories();
}
/**
* записывает оферы всех торговых каталогов в xml файл
*/
private function writeOffers(): void
{
$this->icmlWriter->startOffersBlock();
foreach ($this->setup->iblocksForExport as $iblockId) {
$this->writeIblockOffers($iblockId);
}
$this->icmlWriter->endBlock();
}
/**
* записывает оферы конкретного торгового каталога товаров в xml файл
*
@ -149,7 +149,7 @@ class IcmlDirector
private function writeIblockOffers(int $productIblockId): void
{
$catalogIblockInfo = $this->catalogRepository->getCatalogIblockInfo($productIblockId);
//если нет торговых предложений
if ($catalogIblockInfo->skuIblockId === null) {
$selectParams
@ -157,20 +157,21 @@ class IcmlDirector
$this->setup->properties->products->names[$productIblockId],
$this->setup->basePriceId
);
$selectParams->pageNumber = 1;
$selectParams->nPageSize = self::OFFERS_PART;
$selectParams->parentId = null;
$selectParams->allParams = array_merge($selectParams->configurable, $selectParams->main);
while ($xmlOffers = $this->xmlOfferDirector->getXmlOffersPart($selectParams, $catalogIblockInfo)) {
$this->icmlWriter->writeOffers($xmlOffers);
$selectParams->pageNumber++;
}
return;
}
//если есть торговые предложения
$paramsForProduct
= $this->queryBuilder->getSelectParams(
@ -182,10 +183,10 @@ class IcmlDirector
$this->setup->properties->sku->names[$productIblockId],
$this->setup->basePriceId
);
$this->writeOffersAsOffersInXml($paramsForProduct, $paramsForOffer, $catalogIblockInfo);
}
/**
* Эта стратегия записи используется,
* когда в каталоге есть торговые предложения
@ -201,15 +202,16 @@ class IcmlDirector
): void {
$paramsForProduct->pageNumber = 1;
$paramsForProduct->nPageSize = $this->calculateProductPageSize();
$paramsForProduct->allParams = array_merge($paramsForProduct->configurable, $paramsForProduct->main);
do {
$productsPart = $this->xmlOfferDirector->getXmlOffersPart($paramsForProduct, $catalogIblockInfo);
$paramsForProduct->pageNumber++;
$this->writeProductsOffers($productsPart, $paramsForOffer, $catalogIblockInfo);
} while (!empty($productsPart));
}
/**
* Записывает в файл оферы всех товаров из $products
*
@ -223,12 +225,12 @@ class IcmlDirector
CatalogIblockInfo $catalogIblockInfo
): void {
$paramsForOffer->nPageSize = $this->calculateOffersPageSize();
foreach ($products as $product) {
$this->writeProductOffers($paramsForOffer, $catalogIblockInfo, $product);
}
}
/**
* Записывает оферы отдельного продукта в xml файл
*
@ -244,7 +246,8 @@ class IcmlDirector
$paramsForOffer->pageNumber = 1;
$writingOffersCount = 0;
$paramsForOffer->parentId = $product->id;
$paramsForOffer->allParams = array_merge($paramsForOffer->configurable, $paramsForOffer->main);
do {
$xmlOffersPart
= $this->xmlOfferDirector->getXmlOffersBySingleProduct($paramsForOffer, $catalogIblockInfo, $product);
@ -254,19 +257,19 @@ class IcmlDirector
$this->icmlWriter->writeOffers([$product]);
break;
}
if (!empty($xmlOffersPart)) {
$xmlOffersPart
= $this->trimOffersList($writingOffersCount, $xmlOffersPart);
$this->icmlWriter->writeOffers($xmlOffersPart);
$writingOffersCount += count($xmlOffersPart);
$paramsForOffer->pageNumber++;
}
} while ($this->shouldContinueWriting($writingOffersCount, $xmlOffersPart));
}
/**
* Проверяет,не достигнул ли лимит по записываемым оферам maxOffersValue
* и обрезает массив до лимита, если он достигнут
@ -283,10 +286,10 @@ class IcmlDirector
= count($xmlOffers) - ($writingOffers + count($xmlOffers) - $this->setup->maxOffersValue);
return array_slice($xmlOffers, 0, $sliceIndex);
}
return $xmlOffers;
}
/**
* Возвращает размер страницы для запроса товаров
*
@ -297,10 +300,10 @@ class IcmlDirector
if (empty($this->setup->maxOffersValue)) {
return self::DEFAULT_PRODUCT_PAGE_SIZE;
}
return (int) ceil(self::OFFERS_PART / $this->setup->maxOffersValue);
}
/**
* Возвращает размер страницы для офферов
*
@ -311,11 +314,11 @@ class IcmlDirector
if (empty($this->setup->maxOffersValue)) {
return self::OFFERS_PART;
}
return $this->setup->maxOffersValue < self::OFFERS_PART ?
$this->setup->maxOffersValue : self::OFFERS_PART;
}
/**
* Проверяет, нужно ли дальше записывать офферы
*
@ -329,7 +332,7 @@ class IcmlDirector
if (empty($this->setup->maxOffersValue)) {
return !empty($xmlOffers);
}
return !empty($xmlOffers) && $writingOffers < $this->setup->maxOffersValue;
}
}

View File

@ -21,26 +21,30 @@ class QueryParamsMolder
public function getSelectParams(?array $userProps, int $basePriceId): SelectParams
{
$catalogFields = ['catalog_length', 'catalog_width', 'catalog_height', 'catalog_weight'];
$params = new SelectParams();
foreach ($userProps as $key => $name) {
if ($name === '') {
unset($userProps[$key]);
continue;
}
if (in_array($name, $catalogFields, true)) {
$userProps[$key] = strtoupper($userProps[$key]);
} else {
$userProps[$key] = 'PROPERTY_' . $userProps[$key];
}
}
$params->configurable = $userProps ?? [];
$params->main = [
'LANG_DIR',
'CODE',
'IBLOCK_ID',
'IBLOCK_CODE',
'IBLOCK_SECTION_ID',
'IBLOCK_EXTERNAL_ID',
'NAME',
'DETAIL_PICTURE',
'PREVIEW_PICTURE',
@ -53,10 +57,10 @@ class QueryParamsMolder
'ID',
'LID',
];
return $params;
}
/**
* @param int|null $parentId
* @param \Intaro\RetailCrm\Model\Bitrix\Orm\CatalogIblockInfo $info
@ -70,7 +74,7 @@ class QueryParamsMolder
'ACTIVE' => 'Y',
];
}
return [
'IBLOCK_ID' => $info->skuIblockId,
'ACTIVE' => 'Y',

View File

@ -27,57 +27,57 @@ class XmlOfferBuilder
* @var \Intaro\RetailCrm\Model\Bitrix\Xml\XmlSetup
*/
private $setup;
/**
* @var bool|string|null
*/
private $purchasePriceNull;
/**
* @var array
*/
private $measures;
/**
* @var string|null
*/
private $defaultServerName;
/**
* @var array
*/
private $skuHlParams;
/**
* @var array
*/
private $productHlParams;
/**
* @var string
*/
private $productPicture;
/**
* @var \Intaro\RetailCrm\Model\Bitrix\Orm\CatalogIblockInfo
*/
private $catalogIblockInfo;
/**
* @var array
*/
private $productProps;
/**
* @var string
*/
private $barcode;
/**
* @var \Intaro\RetailCrm\Model\Bitrix\Xml\SelectParams
*/
private $selectParams;
/**
* @var \Intaro\RetailCrm\Model\Bitrix\Xml\XmlOffer
*/
@ -86,7 +86,7 @@ class XmlOfferBuilder
* @var array
*/
private $categories;
/**
* IcmlDataManager constructor.
*
@ -103,7 +103,7 @@ class XmlOfferBuilder
$this->measures = $this->prepareMeasures($measure);
$this->defaultServerName = $defaultServerName;
}
/**
* @return \Intaro\RetailCrm\Model\Bitrix\Xml\XmlOffer
*/
@ -112,13 +112,13 @@ class XmlOfferBuilder
$this->xmlOffer = new XmlOffer();
$this->xmlOffer->barcode = $this->barcode;
$this->xmlOffer->picture = $this->productPicture;
$this->addDataFromParams();
$this->addDataFromItem($this->productProps, $this->categories);
return $this->xmlOffer;
}
/**
* @param array $categories
*/
@ -126,7 +126,7 @@ class XmlOfferBuilder
{
$this->categories = $categories;
}
/**
* @param mixed $skuHlParams
*/
@ -134,7 +134,7 @@ class XmlOfferBuilder
{
$this->skuHlParams = $skuHlParams;
}
/**
* @param mixed $productHlParams
*/
@ -142,7 +142,7 @@ class XmlOfferBuilder
{
$this->productHlParams = $productHlParams;
}
/**
* @param \Intaro\RetailCrm\Model\Bitrix\Xml\SelectParams $selectParams
*/
@ -150,16 +150,16 @@ class XmlOfferBuilder
{
$this->selectParams = $selectParams;
}
/**
* @param array $productProps
*/
public function setOfferProps(array $productProps): void
{
$this->productProps = $productProps;
}
/**
* @param string $barcode
*/
@ -167,7 +167,7 @@ class XmlOfferBuilder
{
$this->barcode = $barcode;
}
/**
* @param \Intaro\RetailCrm\Model\Bitrix\Orm\CatalogIblockInfo $catalogIblockInfo
*/
@ -175,7 +175,7 @@ class XmlOfferBuilder
{
$this->catalogIblockInfo = $catalogIblockInfo;
}
/**
* @param string $getProductPicture
*/
@ -183,21 +183,21 @@ class XmlOfferBuilder
{
$this->productPicture = $getProductPicture;
}
/**
* Добавляет в XmlOffer значения настраиваемых параметров, производителя, вес и габариты
*/
private function addDataFromParams(): void
{
$resultParams = array_merge($this->productHlParams, $this->skuHlParams);
//достаем значения из обычных свойств
$resultParams = array_merge($resultParams, $this->getSimpleParams(
$resultParams,
$this->selectParams->configurable,
$this->productProps
));
[$resultParams, $this->xmlOffer->dimensions]
= $this->extractDimensionsFromParams(
$this->setup->properties,
@ -242,7 +242,7 @@ class XmlOfferBuilder
$this->xmlOffer->vatRate = $item['CATALOG_VAT'] ?? 'none';
$this->xmlOffer->unitCode = $this->getUnitCode($item['CATALOG_MEASURE'], $item['ID']);
}
/**
* Возвращает закупочную цену, если она требуется настройками
*
@ -257,15 +257,15 @@ class XmlOfferBuilder
if ($product['CATALOG_PURCHASING_PRICE']) {
return $product['CATALOG_PURCHASING_PRICE'];
}
if ($purchasePriceNull === 'Y') {
return 0;
}
}
return null;
}
/**
* Возвращает массив обычных свойств
*
@ -280,19 +280,19 @@ class XmlOfferBuilder
if (isset($resultParams[$key])) {
continue;
}
$codeWithValue = $params . '_VALUE';
if (isset($productProps[$codeWithValue])) {
$resultParams[$key] = $productProps[$codeWithValue];
} elseif (isset($productProps[$params])) {
$resultParams[$key] = $productProps[$params];
}
}
return $resultParams;
}
/**
* Удаляет параметры с пустыми и нулевыми значениями
*
@ -303,7 +303,7 @@ class XmlOfferBuilder
{
return array_diff($params, ['', 0, '0']);
}
/**
* Разделяем вендора и остальные параметры
*
@ -313,16 +313,16 @@ class XmlOfferBuilder
private function extractVendorFromParams(array $resultParams): array
{
$vendor = null;
if (isset($resultParams['manufacturer'])) {
$vendor = $resultParams['manufacturer'];
unset($resultParams['manufacturer']);
}
return [$resultParams, $vendor];
}
/**
* Преобразует вес товара в килограммы для ноды weight
*
@ -342,26 +342,26 @@ class XmlOfferBuilder
'kg' => 1,
];
$unit = '';
if (!empty($xmlSetupPropsCategories->products->names[$iblockId]['weight'])) {
$unit = $xmlSetupPropsCategories->products->units[$iblockId]['weight'];
} elseif (!empty($xmlSetupPropsCategories->sku->names[$iblockId]['weight'])) {
$unit = $xmlSetupPropsCategories->sku->units[$iblockId]['weight'];
}
if (isset($resultParams['weight'], $factors[$unit])) {
$weight = $resultParams['weight'] * $factors[$unit];
} else {
$weight = '';
}
if (isset($resultParams['weight'])) {
unset($resultParams['weight']);
}
return [$resultParams, $weight];
}
/**
* Получение данных для ноды dimensions
*
@ -385,34 +385,34 @@ class XmlOfferBuilder
'cm' => 1,
'm' => 100,
];
foreach ($dimensionsParams as $key => $param) {
$unit = '';
if (!empty($xmlSetupPropsCategories->products->names[$iblockId][$param])) {
$unit = $xmlSetupPropsCategories->products->units[$iblockId][$param];
} elseif (!empty($xmlSetupPropsCategories->sku->names[$iblockId][$param])) {
$unit = $xmlSetupPropsCategories->sku->units[$iblockId][$param];
}
if (isset($factors[$unit], $resultParams[$param])) {
$dimensions .= $resultParams[$param] * $factors[$unit];
} else {
$dimensions .= '0';
}
if (count($dimensionsParams) > $key + 1) {
$dimensions .= '/';
}
if (isset($resultParams[$param])) {
unset($resultParams[$param]);
}
}
return [$resultParams, $dimensions === '0/0/0' ? '' : $dimensions];
}
/**
* Собираем объект параметре заказа
*
@ -422,21 +422,21 @@ class XmlOfferBuilder
private function createParamObject(array $params): array
{
$offerParams = [];
foreach ($params as $code => $value) {
$paramName = GetMessage('PARAM_NAME_' . $code);
if (empty($paramName)) {
continue;
}
$offerParam = new OfferParam();
$offerParam->name = $paramName;
$offerParam->code = $code;
$offerParam->value = $value;
$offerParams[] = $offerParam;
}
return $offerParams;
}
@ -452,10 +452,10 @@ class XmlOfferBuilder
$unit->name = $this->measures[$measureIndex]['MEASURE_TITLE'] ?? '';
$unit->code = $this->measures[$measureIndex]['SYMBOL_INTL'] ?? '';
$unit->sym = $this->measures[$measureIndex]['SYMBOL_RUS'] ?? '';
return $unit;
}
/**
* Удаляет запрещенные в unit сode символы
*
@ -472,10 +472,10 @@ class XmlOfferBuilder
$measure['SYMBOL_INTL'] = preg_replace("/[^a-zA-Z_\-]/",'', $measure['SYMBOL_INTL']);
}
}
return $measures;
}
/**
* @param array $currentMeasure
*
@ -489,10 +489,10 @@ class XmlOfferBuilder
$unit->name = $clearCurrentMeasure['MEASURE']['MEASURE_TITLE'] ?? '';
$unit->code = $clearCurrentMeasure['MEASURE']['SYMBOL_INTL'] ?? '';
$unit->sym = $clearCurrentMeasure['MEASURE']['SYMBOL_RUS'] ?? '';
return $unit;
}
/**
* @param int|null $measureId
* @param int $itemId
@ -503,18 +503,18 @@ class XmlOfferBuilder
{
if (isset($measureId) && !empty($measureId)) {
return $this->createUnitFromCode($measureId);
} else {
try {
$currentMeasure = ProductTable::getCurrentRatioWithMeasure($itemId);
if (is_array($currentMeasure)) {
return $this->createUnitFromProductTable($currentMeasure);
}
} catch (ArgumentException $exception) {
Logger::getInstance()->write(GetMessage('UNIT_ERROR'), 'i_crm_load_log');
}
}
try {
$currentMeasure = ProductTable::getCurrentRatioWithMeasure($itemId);
if (is_array($currentMeasure)) {
return $this->createUnitFromProductTable($currentMeasure);
}
} catch (ArgumentException $exception) {
Logger::getInstance()->write(GetMessage('UNIT_ERROR'), 'i_crm_load_log');
}
return null;
}
}

View File

@ -2,6 +2,8 @@
namespace Intaro\RetailCrm\Icml;
use CIBlock;
use CIBlockSection;
use Intaro\RetailCrm\Model\Bitrix\Orm\CatalogIblockInfo;
use Intaro\RetailCrm\Model\Bitrix\Xml\SelectParams;
use Intaro\RetailCrm\Model\Bitrix\Xml\XmlOffer;
@ -22,22 +24,27 @@ class XmlOfferDirector
* @var \Intaro\RetailCrm\Model\Bitrix\Xml\XmlSetup
*/
private $setup;
/**
* @var \Intaro\RetailCrm\Repository\FileRepository
*/
private $fileRepository;
/**
* @var \Intaro\RetailCrm\Repository\CatalogRepository
*/
private $catalogRepository;
/**
* @var \Intaro\RetailCrm\Icml\XmlOfferBuilder
*/
private $xmlOfferBuilder;
private $xmlOfferBuilder;
/**
* @var array
*/
private $barcodes;
/**
* XmlOfferFactory constructor.
* @param \Intaro\RetailCrm\Model\Bitrix\Xml\XmlSetup $setup
@ -52,8 +59,9 @@ class XmlOfferDirector
MeasureRepository::getMeasures(),
SiteRepository::getDefaultServerName()
);
$this->barcodes = $this->catalogRepository->getBarcodes();
}
/**
* Возвращает страницу (массив) с товарами или торговыми предложениями (в зависимости от $param)
*
@ -64,19 +72,22 @@ class XmlOfferDirector
public function getXmlOffersPart(SelectParams $param, CatalogIblockInfo $catalogIblockInfo): array
{
$ciBlockResult = $this->catalogRepository->getProductPage($param, $catalogIblockInfo);
$barcodes = $this->catalogRepository->getProductBarcodesByIblockId($catalogIblockInfo->productIblockId);
$offers = [];
while ($offer = $ciBlockResult->GetNext()) {
$this->setXmlOfferParams($param, $offer, $catalogIblockInfo, $barcodes);
$this->xmlOfferBuilder->setCategories($this->catalogRepository->getProductCategoriesIds($offer['ID']));
while ($offer = $ciBlockResult->Fetch()) {
$categories = $this->catalogRepository->getProductCategories($offer['ID']);
$offer['DETAIL_PAGE_URL'] = $this->replaceUrlTemplate($offer, $categories);
$this->setXmlOfferParams($param, $offer, $catalogIblockInfo);
$this->xmlOfferBuilder
->setCategories(array_column($categories, 'IBLOCK_SECTION_ELEMENT_IBLOCK_SECTION_ID'));
$offers[] = $this->xmlOfferBuilder->build();
}
return $offers;
}
/**
* возвращает массив XmlOffers для конкретного продукта
*
@ -91,10 +102,10 @@ class XmlOfferDirector
XmlOffer $product
): array {
$xmlOffers = $this->getXmlOffersPart($paramsForOffer, $catalogIblockInfo);
return $this->addProductInfo($xmlOffers, $product);
}
/**
* Декорирует оферы информацией из товаров
*
@ -113,13 +124,15 @@ class XmlOfferDirector
$offer->picture = $offer->mergeValues($product->picture, $offer->picture);
$offer->weight = $offer->mergeValues($product->weight, $offer->weight);
$offer->dimensions = $offer->mergeValues($product->dimensions, $offer->dimensions);
$offer->barcode = $offer->mergeValues($product->barcode, $offer->barcode);
$offer->categoryIds = $product->categoryIds;
$offer->productName = $product->productName;
$offer->url = $this->mergeUrls($product->url, $offer->url);
}
return $xmlOffers;
}
/**
* Получение настраиваемых параметров, если они лежат в HL-блоке
*
@ -132,23 +145,23 @@ class XmlOfferDirector
private function getHlParams(int $iblockId, array $productProps, array $configurableParams, array $hls): array
{
$params = [];
foreach ($hls as $hlName => $hlBlockProduct) {
if (isset($hlBlockProduct[$iblockId])) {
reset($hlBlockProduct[$iblockId]);
$firstKey = key($hlBlockProduct[$iblockId]);
$hlRepository = new HlRepository($hlName);
if ($hlRepository->getHl() === null) {
continue;
}
$result = $hlRepository->getDataByXmlId($productProps[$configurableParams[$firstKey] . '_VALUE']);
if ($result === null) {
continue;
}
foreach ($hlBlockProduct[$iblockId] as $hlPropCodeKey => $hlPropCode) {
if (isset($result[$hlPropCode])) {
$params[$hlPropCodeKey] = $result[$hlPropCode];
@ -156,28 +169,26 @@ class XmlOfferDirector
}
}
}
return $params;
}
/**
* @param \Intaro\RetailCrm\Model\Bitrix\Xml\SelectParams $param
* @param array $product
* @param \Intaro\RetailCrm\Model\Bitrix\Orm\CatalogIblockInfo $catalogIblockInfo
* @param array $barcodes
*/
private function setXmlOfferParams(
SelectParams $param,
array $product,
CatalogIblockInfo $catalogIblockInfo,
array $barcodes
CatalogIblockInfo $catalogIblockInfo
): void {
if ($param->parentId === null) {
$pictureProperty = $this->setup->properties->products->pictures[$catalogIblockInfo->productIblockId];
} else {
$pictureProperty = $this->setup->properties->sku->pictures[$catalogIblockInfo->productIblockId];
}
//достаем значения из HL блоков товаров
$this->xmlOfferBuilder->setProductHlParams($this->getHlParams(
$catalogIblockInfo->productIblockId,
@ -185,7 +196,7 @@ class XmlOfferDirector
$param->configurable,
$this->setup->properties->highloadblockProduct
));
//достаем значения из HL блоков торговых предложений
$this->xmlOfferBuilder->setSkuHlParams($this->getHlParams(
$catalogIblockInfo->productIblockId,
@ -195,7 +206,7 @@ class XmlOfferDirector
));
$this->xmlOfferBuilder->setSelectParams($param);
$this->xmlOfferBuilder->setOfferProps($product);
$this->xmlOfferBuilder->setBarcode($barcodes[$product['ID']] ?? '');
$this->xmlOfferBuilder->setBarcode($this->barcodes[$product['ID']] ?? '');
$this->xmlOfferBuilder->setCatalogIblockInfo($catalogIblockInfo);
$this->xmlOfferBuilder->setPicturesPath(
$this
@ -203,7 +214,94 @@ class XmlOfferDirector
->getProductPicture($product, $pictureProperty ?? '')
);
}
/**
* @param array $offer
* @param array $categories
*
* @return string
*/
private function replaceUrlTemplate(array $offer, array $categories): string
{
if (strpos($offer['DETAIL_PAGE_URL'], '#PRODUCT_URL#')) {
return $offer['DETAIL_PAGE_URL'];
}
$replaceableUrlParts = [
'#SITE_DIR#'=> 'LANG_DIR',
'#ID#' => 'ID',
'#CODE#' => 'CODE',
'#EXTERNAL_ID#' => 'EXTERNAL_ID',
'#IBLOCK_TYPE_ID#' => 'IBLOCK_TYPE_ID',
'#IBLOCK_ID#' => 'IBLOCK_ID',
'#IBLOCK_CODE#' => 'IBLOCK_CODE',
'#IBLOCK_EXTERNAL_ID#' => 'IBLOCK_EXTERNAL_ID',
'#ELEMENT_ID#' => 'ID',
'#ELEMENT_CODE#' => 'CODE',
];
$resultUrl = $offer['DETAIL_PAGE_URL'];
foreach ($replaceableUrlParts as $key => $replaceableUrlPart) {
if (isset($offer[$replaceableUrlPart])) {
$resultUrl = str_replace($key, $offer[$replaceableUrlPart], $resultUrl);
}
}
if (
isset($categories[0]['IBLOCK_SECTION_ELEMENT_IBLOCK_SECTION_ID'])
&& strpos($offer['DETAIL_PAGE_URL'], '#SECTION_ID#') !== false
) {
$resultUrl = str_replace(
'#SECTION_ID#',
$categories[0]['IBLOCK_SECTION_ELEMENT_IBLOCK_SECTION_ID'],
$resultUrl
);
}
if (
isset($categories[0]['IBLOCK_SECTION_ELEMENT_IBLOCK_SECTION_CODE'])
&& strpos($offer['DETAIL_PAGE_URL'], '#SECTION_CODE#') !== false
) {
$resultUrl = str_replace(
'#SECTION_CODE#',
$categories[0]['IBLOCK_SECTION_ELEMENT_IBLOCK_SECTION_CODE'],
$resultUrl
);
}
if (
isset(
$categories[0]['IBLOCK_SECTION_ELEMENT_IBLOCK_SECTION_CODE'],
$categories[0]['IBLOCK_SECTION_ELEMENT_IBLOCK_SECTION_ID']
)
&& strpos($offer['DETAIL_PAGE_URL'], '#SECTION_CODE_PATH#') !== false
) {
$resultUrl = str_replace(
'#SECTION_CODE_PATH#',
CIBlockSection::getSectionCodePath($categories[0]['IBLOCK_SECTION_ELEMENT_IBLOCK_SECTION_ID']),
$resultUrl
);
}
return str_replace('//', '/', $resultUrl);
}
/**
* @param string $productUrl
* @param string $offerUrl
*
* @return string
*/
private function mergeUrls(string $productUrl, string $offerUrl): string
{
if (strpos($offerUrl, '#PRODUCT_URL#') !== false) {
return $productUrl;
}
return $offerUrl;
}
/**
* @param array $offerParams
* @param array $productParams
@ -211,7 +309,7 @@ class XmlOfferDirector
private function mergeParams(array $offerParams, array $productParams): array
{
$offerCodes = [];
/** @var \Intaro\RetailCrm\Model\Bitrix\Xml\OfferParam $offerParam */
foreach ($offerParams as $offerParam) {
$offerCodes[] = $offerParam->code;
@ -222,10 +320,10 @@ class XmlOfferDirector
if (in_array($productParam->code, $offerCodes, true)) {
continue;
}
$offerParams[] = $productParam;
}
return $offerParams;
}
}

View File

@ -23,14 +23,14 @@ class SelectParams
* @var array
*/
public $configurable;
/**
* обязательные свойства
*
* @var array
*/
public $main;
/**
* номер запрашиваемой страницы
*
@ -44,11 +44,16 @@ class SelectParams
* @var int
*/
public $nPageSize;
/**
* id товара у торогового предложения, если запрашивается SKU
*
* @var int
*/
public $parentId;
/**
* @var array
*/
public $allParams;
}

View File

@ -2,7 +2,9 @@
namespace Intaro\RetailCrm\Repository;
use Bitrix\Catalog\StoreBarcodeTable;
use Bitrix\Iblock\IblockTable;
use Bitrix\Iblock\SectionElementTable;
use Bitrix\Iblock\SectionTable;
use Bitrix\Main\ArgumentException;
use Bitrix\Main\ObjectPropertyException;
@ -28,7 +30,7 @@ class CatalogRepository
* @var \Intaro\RetailCrm\Icml\QueryParamsMolder
*/
private $builder;
/**
* CatalogRepository constructor.
*/
@ -36,52 +38,53 @@ class CatalogRepository
{
$this->builder = new QueryParamsMolder();
}
/**
* Получение категорий, к которым относится товар
*
* @param int $offerId
* @return array
*/
public function getProductCategoriesIds(int $offerId): array
public function getProductCategories(int $offerId): array
{
$query = CIBlockElement::GetElementGroups($offerId, false, ['ID']);
$ids = [];
while ($category = $query->GetNext()) {
$ids[] = $category['ID'];
try {
$categories = SectionElementTable::query()
->addSelect('IBLOCK_SECTION.ID')
->addSelect('IBLOCK_SECTION.CODE')
->where('IBLOCK_ELEMENT_ID', $offerId)
->fetchAll();
} catch (ObjectPropertyException | ArgumentException | SystemException $exception) {
return [];
}
return $ids;
return $categories;
}
/**
* Returns products IDs with barcodes by infoblock id
*
* @param int $iblockId
*
* @return array
*/
public function getProductBarcodesByIblockId(int $iblockId): array
public function getBarcodes(): array
{
$barcodes = [];
$dbBarCode = CCatalogStoreBarCode::getList(
[],
['IBLOCK_ID' => $iblockId],
false,
false,
['PRODUCT_ID', 'BARCODE']
);
while ($arBarCode = $dbBarCode->GetNext()) {
if (!empty($arBarCode)) {
$barcodes[$arBarCode['PRODUCT_ID']] = $arBarCode['BARCODE'];
}
try {
$arBarCodes = StoreBarcodeTable::query()
->addSelect('PRODUCT_ID')
->addSelect('BARCODE')
->fetchAll();
} catch (ObjectPropertyException | ArgumentException | SystemException $exception) {
return [];
}
foreach ($arBarCodes as $arBarCode){
$barcodes[$arBarCode['PRODUCT_ID']] = $arBarCode['BARCODE'];
}
return $barcodes;
}
/**
* @param \Intaro\RetailCrm\Model\Bitrix\Xml\SelectParams $param
* @param \Intaro\RetailCrm\Model\Bitrix\Orm\CatalogIblockInfo $catalogIblockInfo
@ -94,10 +97,10 @@ class CatalogRepository
$this->builder->getWhereForOfferPart($param->parentId, $catalogIblockInfo),
false,
['nPageSize' => $param->nPageSize, 'iNumPage' => $param->pageNumber, 'checkOutOfRange' => true],
array_merge($param->configurable, $param->main)
$param->allParams
);
}
/**
* @param int $iblockId
* @return \Bitrix\Main\ORM\Objectify\Collection|null
@ -113,7 +116,7 @@ class CatalogRepository
return null;
}
}
/**
* @param $iblockId
* @return EntityObject|null
@ -128,7 +131,7 @@ class CatalogRepository
return null;
}
}
/**
* Возвращает информацию об инфоблоке торговых предложений по ID инфоблока товаров
*
@ -139,20 +142,20 @@ class CatalogRepository
{
$catalogIblockInfo = new CatalogIblockInfo();
$info = CCatalogSKU::GetInfoByProductIBlock($productIblockId);
if ($info === false) {
$catalogIblockInfo->productIblockId = $productIblockId;
return $catalogIblockInfo;
}
$catalogIblockInfo->skuIblockId = $info['IBLOCK_ID'];
$catalogIblockInfo->productIblockId = $info['PRODUCT_IBLOCK_ID'];
$catalogIblockInfo->skuPropertyId = $info['SKU_PROPERTY_ID'];
return $catalogIblockInfo;
}
/**
* @param int|null $profileId
* @return int
@ -160,7 +163,7 @@ class CatalogRepository
public static function getBasePriceId(?int $profileId): int
{
$basePriceId = RetailcrmConfigProvider::getCatalogBasePriceByProfile($profileId);
if (!$basePriceId) {
$dbPriceType = CCatalogGroup::GetList(
[],
@ -169,11 +172,11 @@ class CatalogRepository
false,
['ID']
);
$result = $dbPriceType->GetNext();
return $result['ID'];
}
return $basePriceId;
}
}

View File

@ -2,7 +2,10 @@
namespace Intaro\RetailCrm\Repository;
use CCatalogMeasure;
use Bitrix\Catalog\MeasureTable;
use Bitrix\Main\ArgumentException;
use Bitrix\Main\ObjectPropertyException;
use Bitrix\Main\SystemException;
/**
* Class MeasureRepository
@ -18,12 +21,22 @@ class MeasureRepository
public static function getMeasures(): array
{
$measures = [];
$resMeasure = CCatalogMeasure::getList();
while ($measure = $resMeasure->Fetch()) {
$measures[$measure['ID']] = $measure;
try {
$resMeasures = MeasureTable::query()
->addSelect('ID')
->addSelect('MEASURE_TITLE')
->addSelect('SYMBOL_INTL')
->addSelect('SYMBOL')
->fetchAll();
} catch (ObjectPropertyException | ArgumentException | SystemException $exception) {
return [];
}
foreach ($resMeasures as $resMeasure) {
$measures[$resMeasure['ID']] = $resMeasure;
}
return $measures;
}
}