From 96e5bce336723f2f98df73633b71bdbaaa2e569f Mon Sep 17 00:00:00 2001 From: Vlad <48670792+Mozgito@users.noreply.github.com> Date: Tue, 28 Jun 2022 15:28:28 +0300 Subject: [PATCH] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D0=B8=D0=B5=20=D1=80=D0=B0=D0=B1=D0=BE=D1=82=D1=8B?= =?UTF-8?q?=20=D1=81=D0=BE=20=D1=81=D0=BA=D0=B8=D0=B4=D0=BA=D0=B0=D0=BC?= =?UTF-8?q?=D0=B8=20(#258)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 6 + .../classes/general/config/objects.xml | 2 + .../classes/general/config/retailcrm.json | 3 + .../general/history/RetailCrmHistory_v5.php | 60 +++++- .../general/order/RetailCrmOrder_v5.php | 19 +- intaro.retailcrm/description.ru | 5 +- intaro.retailcrm/install/version.php | 4 +- .../builder/bitrix/loyaltydatabuilder.php | 21 ++- .../lib/component/handlers/eventshandlers.php | 4 +- .../en/service/orderloyaltydataservice.php | 2 +- .../ru/service/orderloyaltydataservice.php | 2 +- .../lib/model/api/order/orderproduct.php | 10 + .../api/order/orderproductdiscountitem.php | 44 +++++ .../lib/model/bitrix/orderloyaltydata.php | 10 +- .../repository/orderloyaltydatarepository.php | 85 ++++++--- .../lib/service/orderloyaltydataservice.php | 63 ++++++- intaro.retailcrm/updater.php | 172 +++++++++++++++++- 17 files changed, 436 insertions(+), 76 deletions(-) create mode 100644 intaro.retailcrm/lib/model/api/order/orderproductdiscountitem.php diff --git a/CHANGELOG.md b/CHANGELOG.md index fe0fc214..cde84522 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## 2022-06-28 v.6.1.0 +- Исправлены ошибки дублирования скидок при обмене данными +- Скорректирована работа с общей скидкой по заказу, она более не переносится в скидку по товару в CRM +- Скорректирована передача бонусов и персональных скидок +- Исправлены типы полей скидок в HL-блоке программы лояльности + ## 2022-06-17 v.6.0.6 - Замена устаревшего jQuery метода diff --git a/intaro.retailcrm/classes/general/config/objects.xml b/intaro.retailcrm/classes/general/config/objects.xml index 564883a6..82210e9a 100644 --- a/intaro.retailcrm/classes/general/config/objects.xml +++ b/intaro.retailcrm/classes/general/config/objects.xml @@ -81,6 +81,8 @@ quantity status discountTotal + bonusesCharge + bonusesCredit status type diff --git a/intaro.retailcrm/classes/general/config/retailcrm.json b/intaro.retailcrm/classes/general/config/retailcrm.json index ff2c144f..a0708826 100644 --- a/intaro.retailcrm/classes/general/config/retailcrm.json +++ b/intaro.retailcrm/classes/general/config/retailcrm.json @@ -564,6 +564,9 @@ }, "content": { "type": "string" + }, + "privilegeType": { + "type": "string" } } } diff --git a/intaro.retailcrm/classes/general/history/RetailCrmHistory_v5.php b/intaro.retailcrm/classes/general/history/RetailCrmHistory_v5.php index 12af716a..e7f3c92e 100644 --- a/intaro.retailcrm/classes/general/history/RetailCrmHistory_v5.php +++ b/intaro.retailcrm/classes/general/history/RetailCrmHistory_v5.php @@ -15,7 +15,10 @@ use Bitrix\Sale\Location\Search\Finder; use Bitrix\Sale\Order; use Bitrix\Sale\OrderUserProperties; use Bitrix\Sale\Payment; +use Intaro\RetailCrm\Component\ServiceLocator; +use Intaro\RetailCrm\Component\Builder\Bitrix\LoyaltyDataBuilder; use Intaro\RetailCrm\Service\ManagerService; +use Intaro\RetailCrm\Service\OrderLoyaltyDataService; use Intaro\RetailCrm\Component\ConfigProvider; use Intaro\RetailCrm\Component\Constants; use Intaro\RetailCrm\Component\Handlers\EventsHandlers; @@ -251,6 +254,9 @@ class RetailCrmHistory $api = new RetailCrm\ApiClient(RetailcrmConfigProvider::getApiUrl(), RetailcrmConfigProvider::getApiKey()); + /* @var OrderLoyaltyDataService $orderLoyaltyDataService */ + $orderLoyaltyDataService = ServiceLocator::get(OrderLoyaltyDataService::class); + $historyFilter = array(); $historyStart = COption::GetOptionString(self::$MODULE_ID, self::$CRM_ORDER_HISTORY); @@ -988,6 +994,10 @@ class RetailCrmHistory $optionDiscRound = COption::GetOptionString(self::$MODULE_ID, self::$CRM_DISCOUNT_ROUND, 0); + $editBasketInfo = []; + $deleteBasketInfo = []; + $bonusesChargeTotal = null; + foreach ($order['items'] as $product) { if ($collectItems[$product['offer']['externalId']]['quantity']) { $product['quantity'] = $collectItems[$product['offer']['externalId']]['quantity']; @@ -1029,12 +1039,11 @@ class RetailCrmHistory } } - if ($product['delete']) { - if ($collectItems[$product['offer']['externalId']]['quantity'] <= 0) { + if ($product['delete'] && $collectItems[$product['offer']['externalId']]['quantity'] <= 0) { + $deleteBasketInfo[] = $item->getBasketCode(); $item->delete(); continue; - } } if ($product['quantity']) { @@ -1065,6 +1074,25 @@ class RetailCrmHistory $item->setField('PRICE', $price); } + + $manualProductDiscount = 0; + $bonusesChargeProduct = $product['bonusesCharge'] ?? null; + + foreach ($product['discounts'] as $productDiscount) { + if ('manual_product' === $productDiscount['type']) { + $manualProductDiscount = $productDiscount['amount']; + } + } + + $editBasketInfo[] = [ + 'productId' => $item->getProductId(), + 'productDiscount' => $manualProductDiscount / $item->getQuantity(), + 'bonusesCharge' => $bonusesChargeProduct, + ]; + + if (null !== $bonusesChargeProduct) { + $bonusesChargeTotal += $bonusesChargeProduct; + } } } @@ -1152,6 +1180,32 @@ class RetailCrmHistory self::orderSave($newOrder); } + //items loyalty info to HL + if (!empty($editBasketInfo)) { + $newBasket = $newOrder->getBasket(); + $calculateItemsInput = []; + $basketItemIds = []; + + foreach ($editBasketInfo as $itemInfo) { + $basketItem = self::getExistsItem($newBasket, 'catalog', $itemInfo['productId']); + if (false !== $basketItem) { + $calculateItemsInput[$basketItem->getId()]['SHOP_ITEM_DISCOUNT'] = $itemInfo['productDiscount']; + $calculateItemsInput[$basketItem->getId()]['BONUSES_CHARGE'] = $itemInfo['bonusesCharge']; + $basketItemIds[] = $basketItem->getId(); + } + } + + $hlInfoBuilder = new LoyaltyDataBuilder(); + $hlInfoBuilder->setOrder($newOrder); + $hlInfoBuilder->setCalculateItemsInput($calculateItemsInput); + $hlInfoBuilder->setBonusCountTotal($bonusesChargeTotal); + $orderLoyaltyDataService->saveLoyaltyInfoToHl($hlInfoBuilder->build($basketItemIds)->getResult()); + } + + if (!empty($deleteBasketInfo)) { + $orderLoyaltyDataService->deleteLoyaltyInfoFromHl($deleteBasketInfo); + } + if (!empty($newHistoryPayments)) { foreach ($newOrder->getPaymentCollection() as $orderPayment) { if (array_key_exists($orderPayment->getField('XML_ID'), $newHistoryPayments)) { diff --git a/intaro.retailcrm/classes/general/order/RetailCrmOrder_v5.php b/intaro.retailcrm/classes/general/order/RetailCrmOrder_v5.php index cf2ad645..ca1b61d9 100644 --- a/intaro.retailcrm/classes/general/order/RetailCrmOrder_v5.php +++ b/intaro.retailcrm/classes/general/order/RetailCrmOrder_v5.php @@ -98,11 +98,6 @@ class RetailCrmOrder $order['contragent']['contragentType'] = $arParams['optionsContragentType'][$arOrder['PERSON_TYPE_ID']]; - if ($methodApi === 'ordersEdit') { - $order['discountManualAmount'] = 0; - $order['discountManualPercent'] = 0; - } - //fields foreach ($arOrder['PROPS']['properties'] as $prop) { if (!empty($arParams['optionsLegalDetails']) @@ -284,7 +279,7 @@ class RetailCrmOrder ) { /** @var LoyaltyService $service */ $service = ServiceLocator::get(LoyaltyService::class); - $item['discountManualAmount'] = $service->getInitialDiscount((int) $externalId) ?? $discount; + $item['discountManualAmount'] = $service->getInitialDiscount((int) $product['ID']) ?? $discount; } elseif ($product['BASE_PRICE'] >= $product['PRICE']) { $item['discountManualAmount'] = self::getDiscountManualAmount($product); $item['initialPrice'] = (double) $product['BASE_PRICE']; @@ -355,6 +350,14 @@ class RetailCrmOrder $order['payments'] = $payments; } + if (!empty($arParams['crmOrder']['privilegeType'])) { + $order['privilegeType'] = $arParams['crmOrder']['privilegeType']; + } elseif (ConfigProvider::getLoyaltyProgramStatus() === 'Y' && LoyaltyAccountService::getLoyaltyPersonalStatus()) { + $order['privilegeType'] = 'loyalty_level'; + } else { + $order['privilegeType'] = 'none'; + } + //send if (function_exists('retailCrmBeforeOrderSend')) { $newResOrder = retailCrmBeforeOrderSend($order, $arOrder); @@ -380,10 +383,6 @@ class RetailCrmOrder Logger::getInstance()->write($order, 'orderSend'); - if (ConfigProvider::getLoyaltyProgramStatus() === 'Y' && LoyaltyAccountService::getLoyaltyPersonalStatus()) { - $order['privilegeType'] = 'loyalty_level'; - } - /** @var \Intaro\RetailCrm\Component\ApiClient\ClientAdapter $client */ $client = ClientFactory::createClientAdapter(); diff --git a/intaro.retailcrm/description.ru b/intaro.retailcrm/description.ru index c83d006f..8941ef9b 100644 --- a/intaro.retailcrm/description.ru +++ b/intaro.retailcrm/description.ru @@ -1 +1,4 @@ -- Замена устаревшего jQuery метода \ No newline at end of file +- Исправлены ошибки задвоения скидок при обмене данными +- Скорректирована работа с общей скидкой по заказу, она более не переносится в скидку по товару в CRM +- Скорректирована передача бонусов и персональных скидок +- Исправлены типы полей скидок в HL-блоке программы лояльности \ No newline at end of file diff --git a/intaro.retailcrm/install/version.php b/intaro.retailcrm/install/version.php index ad883cb8..61f71d4b 100644 --- a/intaro.retailcrm/install/version.php +++ b/intaro.retailcrm/install/version.php @@ -1,6 +1,6 @@ '6.0.6', - 'VERSION_DATE' => '2022-06-17 12:00:00' + 'VERSION' => '6.1.0', + 'VERSION_DATE' => '2022-06-28 11:00:00' ]; diff --git a/intaro.retailcrm/lib/component/builder/bitrix/loyaltydatabuilder.php b/intaro.retailcrm/lib/component/builder/bitrix/loyaltydatabuilder.php index 600a2145..4f65aae6 100644 --- a/intaro.retailcrm/lib/component/builder/bitrix/loyaltydatabuilder.php +++ b/intaro.retailcrm/lib/component/builder/bitrix/loyaltydatabuilder.php @@ -24,8 +24,6 @@ use Intaro\RetailCrm\Model\Api\OrderProduct; use Intaro\RetailCrm\Model\Api\Response\Order\Loyalty\OrderLoyaltyApplyResponse; use Intaro\RetailCrm\Model\Bitrix\OrderLoyaltyData; use Intaro\RetailCrm\Service\CookieService; -use Intaro\RetailCrm\Service\LoyaltyService; -use Intaro\RetailCrm\Service\OrderLoyaltyDataService; use Logger; /** @@ -50,9 +48,7 @@ class LoyaltyDataBuilder implements BuilderInterface /** @var OrderLoyaltyData[] $data */ private $data; - /** - * @var float - */ + /** @var float|null */ private $bonusCountTotal; /** @@ -64,13 +60,19 @@ class LoyaltyDataBuilder implements BuilderInterface } /** + * @param int[] $basketItemIds + * * @return \Intaro\RetailCrm\Component\Builder\BuilderInterface */ - public function build(): BuilderInterface + public function build(array $basketItemIds = []): BuilderInterface { try { /** @var BasketItemBase $basketItem */ foreach ($this->order->getBasket() as $key => $basketItem) { + if (!empty($basketItemIds) && !in_array($basketItem->getId(), $basketItemIds)) { + continue; + } + $loyaltyHl = new OrderLoyaltyData(); $loyaltyHl->orderId = $this->order->getId(); $loyaltyHl->itemId= $basketItem->getProductId(); @@ -82,6 +84,9 @@ class LoyaltyDataBuilder implements BuilderInterface $loyaltyHl->defaultDiscount = $this->calculateItemsInput[$loyaltyHl->basketItemPositionId]['SHOP_ITEM_DISCOUNT'] ?? null; + $loyaltyHl->bonusCount + = $this->calculateItemsInput[$loyaltyHl->basketItemPositionId]['BONUSES_CHARGE'] ?? null; + $this->addBonusInfo($loyaltyHl, $key); $this->data[] = $loyaltyHl; @@ -150,9 +155,9 @@ class LoyaltyDataBuilder implements BuilderInterface } /** - * @param float $bonusCountTotal + * @param float|null $bonusCountTotal */ - public function setBonusInputTotal(float $bonusCountTotal): void + public function setBonusCountTotal(?float $bonusCountTotal): void { $this->bonusCountTotal = $bonusCountTotal; } diff --git a/intaro.retailcrm/lib/component/handlers/eventshandlers.php b/intaro.retailcrm/lib/component/handlers/eventshandlers.php index aead029f..d99ec5b5 100644 --- a/intaro.retailcrm/lib/component/handlers/eventshandlers.php +++ b/intaro.retailcrm/lib/component/handlers/eventshandlers.php @@ -185,7 +185,7 @@ class EventsHandlers ? json_decode(htmlspecialchars_decode($_POST['calculate-items-input']), true) : []; - if ($isNewOrder && $isLoyaltyOn) { + if ($isNewOrder && $isLoyaltyOn && ($isDataForLoyaltyDiscount || $isBonusInput)) { self::$disableSaleHandler = true; $hlInfoBuilder = new LoyaltyDataBuilder(); @@ -204,7 +204,7 @@ class EventsHandlers $hlInfoBuilder->setApplyResponse($applyBonusResponse); $loyaltyBonusMsg = $bonusFloat; - $hlInfoBuilder->setBonusInputTotal($bonusFloat); + $hlInfoBuilder->setBonusCountTotal($bonusFloat); } //Если бонусов нет, но скидка по ПЛ есть diff --git a/intaro.retailcrm/lib/lang/en/service/orderloyaltydataservice.php b/intaro.retailcrm/lib/lang/en/service/orderloyaltydataservice.php index 1da3d02d..df4b2f64 100644 --- a/intaro.retailcrm/lib/lang/en/service/orderloyaltydataservice.php +++ b/intaro.retailcrm/lib/lang/en/service/orderloyaltydataservice.php @@ -4,7 +4,7 @@ $MESS ['UF_ITEM_ID'] = 'Product ID'; $MESS ['UF_DEF_DISCOUNT'] = 'Shop discount'; $MESS ['UF_ITEM_POS_ID'] = 'Basket position ID'; $MESS ['UF_CHECK_ID'] = 'Verification code ID'; -$MESS ['LP_BONUS_INFO'] = 'Bonus info'; +$MESS ['LP_BONUS_INFO'] = 'Bonuses charged'; $MESS ['LP_DISCOUNT_INFO'] = 'Personal discount'; $MESS ['LP_ORDER_GROUP_NAME'] = 'Loyalty program'; $MESS ['UF_QUANTITY'] = 'Quantity in the basket'; diff --git a/intaro.retailcrm/lib/lang/ru/service/orderloyaltydataservice.php b/intaro.retailcrm/lib/lang/ru/service/orderloyaltydataservice.php index 59b820cc..f3fbc35a 100644 --- a/intaro.retailcrm/lib/lang/ru/service/orderloyaltydataservice.php +++ b/intaro.retailcrm/lib/lang/ru/service/orderloyaltydataservice.php @@ -4,7 +4,7 @@ $MESS ['UF_ITEM_ID'] = 'ID товара'; $MESS ['UF_DEF_DISCOUNT'] = 'Скидка магазина'; $MESS ['UF_ITEM_POS_ID'] = 'ID позиции в корзине'; $MESS ['UF_CHECK_ID'] = 'ID проверочного кода'; -$MESS ['LP_BONUS_INFO'] = 'Бонусов начислено'; +$MESS ['LP_BONUS_INFO'] = 'Бонусов списано'; $MESS ['LP_DISCOUNT_INFO'] = 'Персональная скидка'; $MESS ['LP_ORDER_GROUP_NAME'] = 'Программа лояльности'; $MESS ['UF_QUANTITY'] = 'Количество в корзине'; diff --git a/intaro.retailcrm/lib/model/api/order/orderproduct.php b/intaro.retailcrm/lib/model/api/order/orderproduct.php index d079eeef..a1b3c8f0 100644 --- a/intaro.retailcrm/lib/model/api/order/orderproduct.php +++ b/intaro.retailcrm/lib/model/api/order/orderproduct.php @@ -73,6 +73,16 @@ class OrderProduct extends AbstractApiModel */ public $quantity; + /** + * Набор итоговых скидок на товарную позицию + * + * @var array $discounts + * + * @Mapping\Type("array") + * @Mapping\SerializedName("discounts") + */ + public $discounts; + /** * Итоговая денежная скидка на единицу товара c учетом всех скидок на товар и заказ * diff --git a/intaro.retailcrm/lib/model/api/order/orderproductdiscountitem.php b/intaro.retailcrm/lib/model/api/order/orderproductdiscountitem.php new file mode 100644 index 00000000..48ba1f51 --- /dev/null +++ b/intaro.retailcrm/lib/model/api/order/orderproductdiscountitem.php @@ -0,0 +1,44 @@ + + * @license MIT + * @link http://retailcrm.ru + * @see http://retailcrm.ru/docs + */ + +namespace Intaro\RetailCrm\Model\Api\Order; + +use Intaro\RetailCrm\Model\Api\AbstractApiModel; +use Intaro\RetailCrm\Component\Json\Mapping; + +/** + * Class OrderProductPriceItem + * @package Intaro\RetailCrm\Model\Api\Order + */ +class OrderProductDiscountItem extends AbstractApiModel +{ + /** + * Тип скидки + * + * @var string + * + * @Mapping\Type("string") + * @Mapping\SerializedName("type") + */ + public $type; + + /** + * Денежная величина скидки на товарную позицию + * + * @var float $amount + * + * @Mapping\Type("float") + * @Mapping\SerializedName("amount") + */ + public $amount; +} diff --git a/intaro.retailcrm/lib/model/bitrix/orderloyaltydata.php b/intaro.retailcrm/lib/model/bitrix/orderloyaltydata.php index b893733f..0125fd97 100644 --- a/intaro.retailcrm/lib/model/bitrix/orderloyaltydata.php +++ b/intaro.retailcrm/lib/model/bitrix/orderloyaltydata.php @@ -77,7 +77,7 @@ class OrderLoyaltyData /** * Количество в корзине * - * @var float + * @var integer * * @Mapping\Type("integer") * @Mapping\SerializedName("UF_QUANTITY") @@ -119,9 +119,9 @@ class OrderLoyaltyData /** * Количество списываемых бонусов по позиции * - * @var integer + * @var float * - * @Mapping\Type("integer") + * @Mapping\Type("float") * @Mapping\SerializedName("UF_BONUS_COUNT") */ public $bonusCount; @@ -129,9 +129,9 @@ class OrderLoyaltyData /** * Количество списываемых бонусов по всему заказу * - * @var integer + * @var float * - * @Mapping\Type("integer") + * @Mapping\Type("float") * @Mapping\SerializedName("UF_BONUS_COUNT_TOTAL") */ public $bonusCountTotal; diff --git a/intaro.retailcrm/lib/repository/orderloyaltydatarepository.php b/intaro.retailcrm/lib/repository/orderloyaltydatarepository.php index c1759110..12edbad8 100644 --- a/intaro.retailcrm/lib/repository/orderloyaltydatarepository.php +++ b/intaro.retailcrm/lib/repository/orderloyaltydatarepository.php @@ -35,12 +35,12 @@ class OrderLoyaltyDataRepository extends AbstractRepository * @var \Bitrix\Main\Entity\DataManager|string|null */ private $dataManager; - + /** * @var \Logger */ private $logger; - + /** * OrderLoyaltyDataRepository constructor. * @throws \Bitrix\Main\LoaderException @@ -51,7 +51,7 @@ class OrderLoyaltyDataRepository extends AbstractRepository $this->logger = Logger::getInstance(); $this->dataManager = Utils::getHlClassByName(Constants::HL_LOYALTY_CODE); } - + /** * @param \Intaro\RetailCrm\Model\Bitrix\OrderLoyaltyData $loyaltyHl * @return int|null @@ -62,25 +62,25 @@ class OrderLoyaltyDataRepository extends AbstractRepository if ($this->dataManager === null) { return null; } - + $result = Serializer::serializeArray($loyaltyHl, OrderLoyaltyData::class); - + unset($result['ID']); - + $result = $this->dataManager::add($result); - + if ($result->isSuccess()) { return $result->getId(); } - + return null; } catch (Exception $exception) { $this->logger->write($exception->getMessage(), Constants::LOYALTY_ERROR); } - + return null; } - + /** * @param int $positionId * @return \Intaro\RetailCrm\Model\Bitrix\OrderLoyaltyData|null @@ -90,20 +90,23 @@ class OrderLoyaltyDataRepository extends AbstractRepository if ($this->dataManager === null) { return null; } - + try { $product = $this->dataManager::query() ->setSelect(['*']) ->where('UF_ITEM_POS_ID', '=', $positionId) ->fetch(); - - /** @var OrderLoyaltyData $result */ + + if (false === $product) { + return null; + } + return Deserializer::deserializeArray($product, OrderLoyaltyData::class); } catch (ObjectPropertyException | ArgumentException | SystemException $exception) { $this->logger->write($exception->getMessage(), Constants::LOYALTY_ERROR); } } - + /** * @param $orderId * @@ -161,24 +164,55 @@ class OrderLoyaltyDataRepository extends AbstractRepository if ($this->dataManager === null) { return false; } - + $productAr = Serializer::serializeArray($position, OrderLoyaltyData::class); - + unset($productAr['ID']); - + + foreach ($productAr as $key => $value) { + if (null === $value) { + unset($productAr[$key]); + } + } + $result = $this->dataManager::update($position->id, $productAr); - + if ($result->isSuccess()) { return true; } - + } catch (Exception $exception) { $this->logger->write($exception->getMessage(), Constants::LOYALTY_ERROR); } - + return false; } - + + /** + * @param mixed $primary + * @return bool + */ + public function delete($primary): bool + { + try { + if ($this->dataManager === null) { + return false; + } + + $result = $this->dataManager::delete($primary); + + if ($result->isSuccess()) { + return true; + } + + } catch (Exception $exception) { + $this->logger->write($exception->getMessage(), Constants::LOYALTY_ERROR); + } + + return false; + + } + /** * @param int $externalId * @return float|null @@ -189,22 +223,21 @@ class OrderLoyaltyDataRepository extends AbstractRepository if ($this->dataManager === null) { return null; } - + $result = $this->dataManager::query() ->setSelect(['UF_DEF_DISCOUNT']) ->where([ ['UF_ITEM_POS_ID', '=', $externalId] ]) - ->fetch(); - + ->fetch(); + if ($result !== false) { return (float) $result['UF_DEF_DISCOUNT']; } - } catch (SystemException | Exception $exception) { $this->logger->write($exception->getMessage(), Constants::LOYALTY_ERROR); } - + return null; } } diff --git a/intaro.retailcrm/lib/service/orderloyaltydataservice.php b/intaro.retailcrm/lib/service/orderloyaltydataservice.php index 02fc9051..1d3bee45 100644 --- a/intaro.retailcrm/lib/service/orderloyaltydataservice.php +++ b/intaro.retailcrm/lib/service/orderloyaltydataservice.php @@ -85,6 +85,17 @@ class OrderLoyaltyDataService */ public static function createLoyaltyHlBlock(): void { + $checkHl = HL\HighloadBlockTable::query() + ->addSelect('*') + ->addFilter('NAME', Constants::HL_LOYALTY_CODE) + ->addFilter('TABLE_NAME', Constants::HL_LOYALTY_TABLE_NAME) + ->exec() + ->fetch(); + + if (false !== $checkHl) { + return; + } + $result = HL\HighloadBlockTable::add([ 'NAME' => Constants::HL_LOYALTY_CODE, 'TABLE_NAME' => Constants::HL_LOYALTY_TABLE_NAME, @@ -170,18 +181,15 @@ class OrderLoyaltyDataService return; } - $repository = new OrderLoyaltyDataRepository(); - $bitrixItems = $repository->getProductsByOrderId($orderId); $loyaltyDiscount = 0; /** @var OrderProduct $item */ foreach ($response->order->items as $item) { - /** @var CodeValueModel $itemBitrixId */ - $itemBitrixId = $item->externalIds[0]; - /** @var OrderLoyaltyData $bitrixItem */ - $bitrixItem = $bitrixItems[$itemBitrixId->value]; - - $loyaltyDiscount += ($item->discountTotal - $bitrixItem->defaultDiscount) * $item->quantity; + foreach ($item->discounts as $discount) { + if (in_array($discount->type, ['personal', 'loyalty_level'])) { + $loyaltyDiscount += $discount->amount; + } + } } $this->saveBonusAndDiscToOrderProps( @@ -264,7 +272,33 @@ class OrderLoyaltyDataService $repository = new OrderLoyaltyDataRepository(); foreach ($loyaltyHls as $loyaltyData) { - $repository->add($loyaltyData); + $positionLpData = $repository->getOrderLpDataByPosition($loyaltyData->basketItemPositionId); + + if (null !== $positionLpData) { + $loyaltyData->id = $positionLpData->id; + $repository->edit($loyaltyData); + } else { + $repository->add($loyaltyData); + } + } + } + + /** + * Удаляет данные о ПЛ из HL-блока + * + * @param int[] $basketItemIds + * @return void + */ + public function deleteLoyaltyInfoFromHl(array $basketItemIds): void + { + $repository = new OrderLoyaltyDataRepository(); + + foreach ($basketItemIds as $basketItemId) { + $positionLpData = $repository->getOrderLpDataByPosition($basketItemId); + + if (null !== $positionLpData) { + $repository->delete($positionLpData->id); + } } } @@ -465,6 +499,9 @@ class OrderLoyaltyDataService 'ru' => Loc::GetMessage('UF_DEF_DISCOUNT', null, 'ru'), 'en' => Loc::GetMessage('UF_DEF_DISCOUNT', null, 'en'), ], + 'SETTINGS' => [ + 'PRECISION' => 2, + ], ], 'UF_CHECK_ID' => [ 'ENTITY_ID' => $ufObject, @@ -537,11 +574,14 @@ class OrderLoyaltyDataService 'ru' => Loc::GetMessage('UF_BONUS_COUNT', null, 'ru'), 'en' => Loc::GetMessage('UF_BONUS_COUNT', null, 'en'), ], + 'SETTINGS' => [ + 'PRECISION' => 2, + ], ], 'UF_BONUS_COUNT_TOTAL' => [ 'ENTITY_ID' => $ufObject, 'FIELD_NAME' => 'UF_BONUS_COUNT_TOTAL', - 'USER_TYPE_ID' => 'integer', + 'USER_TYPE_ID' => 'double', 'MANDATORY' => 'N', 'EDIT_FORM_LABEL' => [ 'ru' => Loc::GetMessage('UF_BONUS_COUNT_TOTAL', null, 'ru'), @@ -555,6 +595,9 @@ class OrderLoyaltyDataService 'ru' => Loc::GetMessage('UF_BONUS_COUNT_TOTAL', null, 'ru'), 'en' => Loc::GetMessage('UF_BONUS_COUNT_TOTAL', null, 'en'), ], + 'SETTINGS' => [ + 'PRECISION' => 2, + ], ], ]; } diff --git a/intaro.retailcrm/updater.php b/intaro.retailcrm/updater.php index 25903681..ede8cddc 100644 --- a/intaro.retailcrm/updater.php +++ b/intaro.retailcrm/updater.php @@ -910,6 +910,168 @@ class LoyaltyProgramUpdater } } } + + + public function updateBonusInfoFieldForLp(): self + { + $bonusProps = CSaleOrderProps::GetList([], ['CODE' => 'LP_BONUS_INFO']); + $lang = Context::getCurrent()->getLanguage(); + $lpBonusInfo = [ + 'ru' => 'Бонусов списано', + 'en' => 'Bonuses charged' + ][$lang]; + $updateInfo = [ + 'NAME' => $lpBonusInfo, + 'DESCRIPTION' => $lpBonusInfo, + ]; + + while ($bonusProp = $bonusProps->Fetch()) + { + CSaleOrderProps::Update($bonusProp['ID'], $updateInfo); + } + + return $this; + } + + /** + * Обновление типов полей с бонусами и перенос информации + * + * @throws Main\ArgumentException + * @throws Main\ObjectPropertyException + * @throws Main\SystemException + */ + public function updateBonusFieldsTypeInHl(): self + { + $hlblock = HL\HighloadBlockTable::query() + ->addSelect('*') + ->addFilter('NAME', 'LoyaltyProgramRetailCRM') + ->exec() + ->fetch(); + + if (isset($hlblock['ID'])) { + $ufObject = 'HLBLOCK_' . $hlblock['ID']; + $bonusCountField = CUserTypeEntity::GetList([], [ + "ENTITY_ID" => $ufObject, + "FIELD_NAME" => 'UF_BONUS_COUNT', + ])->fetch(); + $bonusTotalCountField = CUserTypeEntity::GetList([], [ + "ENTITY_ID" => $ufObject, + "FIELD_NAME" => 'UF_BONUS_COUNT_TOTAL', + ])->fetch(); + + if ('integer' === $bonusCountField['USER_TYPE_ID'] && 'integer' === $bonusTotalCountField['USER_TYPE_ID']) { + $hlblockEntity = HL\HighloadBlockTable::compileEntity($hlblock); + $manager = $hlblockEntity->getDataClass(); + + $bonusHlblockData = $manager::query() + ->setSelect(['ID', 'UF_BONUS_COUNT', 'UF_BONUS_COUNT_TOTAL']) + ->setFilter(['!=UF_BONUS_COUNT' => 'NULL', 'LOGIC' => 'OR', '!=UF_BONUS_COUNT_TOTAL' => 'NULL']) + ->fetchAll(); + + $obUserField = new CUserTypeEntity(); + $obUserField->Delete($bonusCountField['ID']); + $obUserField->Delete($bonusTotalCountField['ID']); + + $newBonusFields = $this->getNewBonusHlFields($ufObject); + + foreach ($newBonusFields as $newBonusField) { + $obUserField->Add($newBonusField); + } + + foreach ($bonusHlblockData as $field) { + $manager::update($field['ID'], ['fields' => [ + 'UF_BONUS_COUNT' => $field['UF_BONUS_COUNT'], + 'UF_BONUS_COUNT_TOTAL' => $field['UF_BONUS_COUNT_TOTAL'], + ],]); + } + } + } + + return $this; + } + + /** + * Обновление поля скидки по товару + * + * @throws Main\ArgumentException + * @throws Main\ObjectPropertyException + * @throws Main\SystemException + */ + public function updateDefDiscountFieldTypeInHl(): self + { + $hlblock = HL\HighloadBlockTable::query() + ->addSelect('*') + ->addFilter('NAME', 'LoyaltyProgramRetailCRM') + ->exec() + ->fetch(); + + if (isset($hlblock['ID'])) { + $ufObject = 'HLBLOCK_' . $hlblock['ID']; + $defDiscountField = CUserTypeEntity::GetList([], [ + "ENTITY_ID" => $ufObject, + "FIELD_NAME" => 'UF_DEF_DISCOUNT', + ])->fetch(); + + if (false !== $defDiscountField) { + $obUserField = new CUserTypeEntity(); + $obUserField->Update($defDiscountField['ID'], [ + 'SETTINGS' => [ + 'PRECISION' => 2, + ], + ]); + } + } + + return $this; + } + + public function getNewBonusHlFields(string $ufObject): array + { + return [ + 'UF_BONUS_COUNT' => [ + 'ENTITY_ID' => $ufObject, + 'FIELD_NAME' => 'UF_BONUS_COUNT', + 'USER_TYPE_ID' => 'double', + 'MANDATORY' => 'N', + 'EDIT_FORM_LABEL' => [ + 'ru' => 'Количество списываемых бонусов в позиции', + 'en' => 'Bonuses for writing off in position', + ], + 'LIST_COLUMN_LABEL' => [ + 'ru' => 'Количество списываемых бонусов в позиции', + 'en' => 'Bonuses for writing off in position', + ], + 'LIST_FILTER_LABEL' => [ + 'ru' => 'Количество списываемых бонусов в позиции', + 'en' => 'Bonuses for writing off in position', + ], + 'SETTINGS' => [ + 'PRECISION' => 2, + ], + ], + 'UF_BONUS_COUNT_TOTAL' => [ + 'ENTITY_ID' => $ufObject, + 'FIELD_NAME' => 'UF_BONUS_COUNT_TOTAL', + 'USER_TYPE_ID' => 'double', + 'MANDATORY' => 'N', + 'EDIT_FORM_LABEL' => [ + 'ru' => 'Количество списываемых бонусов в заказе', + 'en' => 'Bonuses for writing off in order', + ], + 'LIST_COLUMN_LABEL' => [ + 'ru' => 'Количество списываемых бонусов в заказе', + 'en' => 'Bonuses for writing off in order', + ], + 'LIST_FILTER_LABEL' => [ + 'ru' => 'Количество списываемых бонусов в заказе', + 'en' => 'Bonuses for writing off in order', + ], + 'SETTINGS' => [ + 'PRECISION' => 2, + ], + ], + ]; + } } /** @@ -924,13 +1086,9 @@ function update() Loader::includeModule('highloadblock'); (new LoyaltyProgramUpdater()) - ->tryReplaceExportVars() - ->addLoyaltyProgramEvents() - ->CopyFiles() - ->addLpUserFields() - ->addAgreement() - ->createLoyaltyHlBlock() - ->addCustomersLoyaltyFields(); + ->updateBonusInfoFieldForLp() + ->updateBonusFieldsTypeInHl() + ->updateDefDiscountFieldTypeInHl(); } try {