1
0
mirror of synced 2024-11-29 00:36:07 +03:00

Исправление работы со скидками (#258)

This commit is contained in:
Vlad 2022-06-28 15:28:28 +03:00 committed by GitHub
parent 9b1e641b16
commit 96e5bce336
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 436 additions and 76 deletions

View File

@ -1,3 +1,9 @@
## 2022-06-28 v.6.1.0
- Исправлены ошибки дублирования скидок при обмене данными
- Скорректирована работа с общей скидкой по заказу, она более не переносится в скидку по товару в CRM
- Скорректирована передача бонусов и персональных скидок
- Исправлены типы полей скидок в HL-блоке программы лояльности
## 2022-06-17 v.6.0.6 ## 2022-06-17 v.6.0.6
- Замена устаревшего jQuery метода - Замена устаревшего jQuery метода

View File

@ -81,6 +81,8 @@
<field id="order_product.quantity" group="item">quantity</field> <field id="order_product.quantity" group="item">quantity</field>
<field id="order_product.status" group="item">status</field> <field id="order_product.status" group="item">status</field>
<field id="order_product.discount_total" group="item">discountTotal</field> <field id="order_product.discount_total" group="item">discountTotal</field>
<field id="order_product.bonuses_charge" group="item">bonusesCharge</field>
<field id="order_product.bonuses_credit" group="item">bonusesCredit</field>
<field id="payments.status" group="payment">status</field> <field id="payments.status" group="payment">status</field>
<field id="payments.type" group="payment">type</field> <field id="payments.type" group="payment">type</field>

View File

@ -564,6 +564,9 @@
}, },
"content": { "content": {
"type": "string" "type": "string"
},
"privilegeType": {
"type": "string"
} }
} }
} }

View File

@ -15,7 +15,10 @@ use Bitrix\Sale\Location\Search\Finder;
use Bitrix\Sale\Order; use Bitrix\Sale\Order;
use Bitrix\Sale\OrderUserProperties; use Bitrix\Sale\OrderUserProperties;
use Bitrix\Sale\Payment; 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\ManagerService;
use Intaro\RetailCrm\Service\OrderLoyaltyDataService;
use Intaro\RetailCrm\Component\ConfigProvider; use Intaro\RetailCrm\Component\ConfigProvider;
use Intaro\RetailCrm\Component\Constants; use Intaro\RetailCrm\Component\Constants;
use Intaro\RetailCrm\Component\Handlers\EventsHandlers; use Intaro\RetailCrm\Component\Handlers\EventsHandlers;
@ -251,6 +254,9 @@ class RetailCrmHistory
$api = new RetailCrm\ApiClient(RetailcrmConfigProvider::getApiUrl(), RetailcrmConfigProvider::getApiKey()); $api = new RetailCrm\ApiClient(RetailcrmConfigProvider::getApiUrl(), RetailcrmConfigProvider::getApiKey());
/* @var OrderLoyaltyDataService $orderLoyaltyDataService */
$orderLoyaltyDataService = ServiceLocator::get(OrderLoyaltyDataService::class);
$historyFilter = array(); $historyFilter = array();
$historyStart = COption::GetOptionString(self::$MODULE_ID, self::$CRM_ORDER_HISTORY); $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); $optionDiscRound = COption::GetOptionString(self::$MODULE_ID, self::$CRM_DISCOUNT_ROUND, 0);
$editBasketInfo = [];
$deleteBasketInfo = [];
$bonusesChargeTotal = null;
foreach ($order['items'] as $product) { foreach ($order['items'] as $product) {
if ($collectItems[$product['offer']['externalId']]['quantity']) { if ($collectItems[$product['offer']['externalId']]['quantity']) {
$product['quantity'] = $collectItems[$product['offer']['externalId']]['quantity']; $product['quantity'] = $collectItems[$product['offer']['externalId']]['quantity'];
@ -1029,12 +1039,11 @@ class RetailCrmHistory
} }
} }
if ($product['delete']) { if ($product['delete'] && $collectItems[$product['offer']['externalId']]['quantity'] <= 0) {
if ($collectItems[$product['offer']['externalId']]['quantity'] <= 0) { $deleteBasketInfo[] = $item->getBasketCode();
$item->delete(); $item->delete();
continue; continue;
}
} }
if ($product['quantity']) { if ($product['quantity']) {
@ -1065,6 +1074,25 @@ class RetailCrmHistory
$item->setField('PRICE', $price); $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); 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)) { if (!empty($newHistoryPayments)) {
foreach ($newOrder->getPaymentCollection() as $orderPayment) { foreach ($newOrder->getPaymentCollection() as $orderPayment) {
if (array_key_exists($orderPayment->getField('XML_ID'), $newHistoryPayments)) { if (array_key_exists($orderPayment->getField('XML_ID'), $newHistoryPayments)) {

View File

@ -98,11 +98,6 @@ class RetailCrmOrder
$order['contragent']['contragentType'] = $arParams['optionsContragentType'][$arOrder['PERSON_TYPE_ID']]; $order['contragent']['contragentType'] = $arParams['optionsContragentType'][$arOrder['PERSON_TYPE_ID']];
if ($methodApi === 'ordersEdit') {
$order['discountManualAmount'] = 0;
$order['discountManualPercent'] = 0;
}
//fields //fields
foreach ($arOrder['PROPS']['properties'] as $prop) { foreach ($arOrder['PROPS']['properties'] as $prop) {
if (!empty($arParams['optionsLegalDetails']) if (!empty($arParams['optionsLegalDetails'])
@ -284,7 +279,7 @@ class RetailCrmOrder
) { ) {
/** @var LoyaltyService $service */ /** @var LoyaltyService $service */
$service = ServiceLocator::get(LoyaltyService::class); $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']) { } elseif ($product['BASE_PRICE'] >= $product['PRICE']) {
$item['discountManualAmount'] = self::getDiscountManualAmount($product); $item['discountManualAmount'] = self::getDiscountManualAmount($product);
$item['initialPrice'] = (double) $product['BASE_PRICE']; $item['initialPrice'] = (double) $product['BASE_PRICE'];
@ -355,6 +350,14 @@ class RetailCrmOrder
$order['payments'] = $payments; $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 //send
if (function_exists('retailCrmBeforeOrderSend')) { if (function_exists('retailCrmBeforeOrderSend')) {
$newResOrder = retailCrmBeforeOrderSend($order, $arOrder); $newResOrder = retailCrmBeforeOrderSend($order, $arOrder);
@ -380,10 +383,6 @@ class RetailCrmOrder
Logger::getInstance()->write($order, 'orderSend'); Logger::getInstance()->write($order, 'orderSend');
if (ConfigProvider::getLoyaltyProgramStatus() === 'Y' && LoyaltyAccountService::getLoyaltyPersonalStatus()) {
$order['privilegeType'] = 'loyalty_level';
}
/** @var \Intaro\RetailCrm\Component\ApiClient\ClientAdapter $client */ /** @var \Intaro\RetailCrm\Component\ApiClient\ClientAdapter $client */
$client = ClientFactory::createClientAdapter(); $client = ClientFactory::createClientAdapter();

View File

@ -1 +1,4 @@
- Замена устаревшего jQuery метода - Исправлены ошибки задвоения скидок при обмене данными
- Скорректирована работа с общей скидкой по заказу, она более не переносится в скидку по товару в CRM
- Скорректирована передача бонусов и персональных скидок
- Исправлены типы полей скидок в HL-блоке программы лояльности

View File

@ -1,6 +1,6 @@
<?php <?php
$arModuleVersion = [ $arModuleVersion = [
'VERSION' => '6.0.6', 'VERSION' => '6.1.0',
'VERSION_DATE' => '2022-06-17 12:00:00' 'VERSION_DATE' => '2022-06-28 11:00:00'
]; ];

View File

@ -24,8 +24,6 @@ use Intaro\RetailCrm\Model\Api\OrderProduct;
use Intaro\RetailCrm\Model\Api\Response\Order\Loyalty\OrderLoyaltyApplyResponse; use Intaro\RetailCrm\Model\Api\Response\Order\Loyalty\OrderLoyaltyApplyResponse;
use Intaro\RetailCrm\Model\Bitrix\OrderLoyaltyData; use Intaro\RetailCrm\Model\Bitrix\OrderLoyaltyData;
use Intaro\RetailCrm\Service\CookieService; use Intaro\RetailCrm\Service\CookieService;
use Intaro\RetailCrm\Service\LoyaltyService;
use Intaro\RetailCrm\Service\OrderLoyaltyDataService;
use Logger; use Logger;
/** /**
@ -50,9 +48,7 @@ class LoyaltyDataBuilder implements BuilderInterface
/** @var OrderLoyaltyData[] $data */ /** @var OrderLoyaltyData[] $data */
private $data; private $data;
/** /** @var float|null */
* @var float
*/
private $bonusCountTotal; private $bonusCountTotal;
/** /**
@ -64,13 +60,19 @@ class LoyaltyDataBuilder implements BuilderInterface
} }
/** /**
* @param int[] $basketItemIds
*
* @return \Intaro\RetailCrm\Component\Builder\BuilderInterface * @return \Intaro\RetailCrm\Component\Builder\BuilderInterface
*/ */
public function build(): BuilderInterface public function build(array $basketItemIds = []): BuilderInterface
{ {
try { try {
/** @var BasketItemBase $basketItem */ /** @var BasketItemBase $basketItem */
foreach ($this->order->getBasket() as $key => $basketItem) { foreach ($this->order->getBasket() as $key => $basketItem) {
if (!empty($basketItemIds) && !in_array($basketItem->getId(), $basketItemIds)) {
continue;
}
$loyaltyHl = new OrderLoyaltyData(); $loyaltyHl = new OrderLoyaltyData();
$loyaltyHl->orderId = $this->order->getId(); $loyaltyHl->orderId = $this->order->getId();
$loyaltyHl->itemId= $basketItem->getProductId(); $loyaltyHl->itemId= $basketItem->getProductId();
@ -82,6 +84,9 @@ class LoyaltyDataBuilder implements BuilderInterface
$loyaltyHl->defaultDiscount $loyaltyHl->defaultDiscount
= $this->calculateItemsInput[$loyaltyHl->basketItemPositionId]['SHOP_ITEM_DISCOUNT'] ?? null; = $this->calculateItemsInput[$loyaltyHl->basketItemPositionId]['SHOP_ITEM_DISCOUNT'] ?? null;
$loyaltyHl->bonusCount
= $this->calculateItemsInput[$loyaltyHl->basketItemPositionId]['BONUSES_CHARGE'] ?? null;
$this->addBonusInfo($loyaltyHl, $key); $this->addBonusInfo($loyaltyHl, $key);
$this->data[] = $loyaltyHl; $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; $this->bonusCountTotal = $bonusCountTotal;
} }

View File

@ -185,7 +185,7 @@ class EventsHandlers
? json_decode(htmlspecialchars_decode($_POST['calculate-items-input']), true) ? json_decode(htmlspecialchars_decode($_POST['calculate-items-input']), true)
: []; : [];
if ($isNewOrder && $isLoyaltyOn) { if ($isNewOrder && $isLoyaltyOn && ($isDataForLoyaltyDiscount || $isBonusInput)) {
self::$disableSaleHandler = true; self::$disableSaleHandler = true;
$hlInfoBuilder = new LoyaltyDataBuilder(); $hlInfoBuilder = new LoyaltyDataBuilder();
@ -204,7 +204,7 @@ class EventsHandlers
$hlInfoBuilder->setApplyResponse($applyBonusResponse); $hlInfoBuilder->setApplyResponse($applyBonusResponse);
$loyaltyBonusMsg = $bonusFloat; $loyaltyBonusMsg = $bonusFloat;
$hlInfoBuilder->setBonusInputTotal($bonusFloat); $hlInfoBuilder->setBonusCountTotal($bonusFloat);
} }
//Если бонусов нет, но скидка по ПЛ есть //Если бонусов нет, но скидка по ПЛ есть

View File

@ -4,7 +4,7 @@ $MESS ['UF_ITEM_ID'] = 'Product ID';
$MESS ['UF_DEF_DISCOUNT'] = 'Shop discount'; $MESS ['UF_DEF_DISCOUNT'] = 'Shop discount';
$MESS ['UF_ITEM_POS_ID'] = 'Basket position ID'; $MESS ['UF_ITEM_POS_ID'] = 'Basket position ID';
$MESS ['UF_CHECK_ID'] = 'Verification code 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_DISCOUNT_INFO'] = 'Personal discount';
$MESS ['LP_ORDER_GROUP_NAME'] = 'Loyalty program'; $MESS ['LP_ORDER_GROUP_NAME'] = 'Loyalty program';
$MESS ['UF_QUANTITY'] = 'Quantity in the basket'; $MESS ['UF_QUANTITY'] = 'Quantity in the basket';

View File

@ -4,7 +4,7 @@ $MESS ['UF_ITEM_ID'] = 'ID товара';
$MESS ['UF_DEF_DISCOUNT'] = 'Скидка магазина'; $MESS ['UF_DEF_DISCOUNT'] = 'Скидка магазина';
$MESS ['UF_ITEM_POS_ID'] = 'ID позиции в корзине'; $MESS ['UF_ITEM_POS_ID'] = 'ID позиции в корзине';
$MESS ['UF_CHECK_ID'] = 'ID проверочного кода'; $MESS ['UF_CHECK_ID'] = 'ID проверочного кода';
$MESS ['LP_BONUS_INFO'] = 'Бонусов начислено'; $MESS ['LP_BONUS_INFO'] = 'Бонусов списано';
$MESS ['LP_DISCOUNT_INFO'] = 'Персональная скидка'; $MESS ['LP_DISCOUNT_INFO'] = 'Персональная скидка';
$MESS ['LP_ORDER_GROUP_NAME'] = 'Программа лояльности'; $MESS ['LP_ORDER_GROUP_NAME'] = 'Программа лояльности';
$MESS ['UF_QUANTITY'] = 'Количество в корзине'; $MESS ['UF_QUANTITY'] = 'Количество в корзине';

View File

@ -73,6 +73,16 @@ class OrderProduct extends AbstractApiModel
*/ */
public $quantity; public $quantity;
/**
* Набор итоговых скидок на товарную позицию
*
* @var array $discounts
*
* @Mapping\Type("array<Intaro\RetailCrm\Model\Api\Order\OrderProductDiscountItem>")
* @Mapping\SerializedName("discounts")
*/
public $discounts;
/** /**
* Итоговая денежная скидка на единицу товара c учетом всех скидок на товар и заказ * Итоговая денежная скидка на единицу товара c учетом всех скидок на товар и заказ
* *

View File

@ -0,0 +1,44 @@
<?php
/**
* PHP version 7.1
*
* @category Integration
* @package Intaro\RetailCrm\Model\Api
* @author RetailCRM <integration@retailcrm.ru>
* @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;
}

View File

@ -77,7 +77,7 @@ class OrderLoyaltyData
/** /**
* Количество в корзине * Количество в корзине
* *
* @var float * @var integer
* *
* @Mapping\Type("integer") * @Mapping\Type("integer")
* @Mapping\SerializedName("UF_QUANTITY") * @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") * @Mapping\SerializedName("UF_BONUS_COUNT")
*/ */
public $bonusCount; public $bonusCount;
@ -129,9 +129,9 @@ class OrderLoyaltyData
/** /**
* Количество списываемых бонусов по всему заказу * Количество списываемых бонусов по всему заказу
* *
* @var integer * @var float
* *
* @Mapping\Type("integer") * @Mapping\Type("float")
* @Mapping\SerializedName("UF_BONUS_COUNT_TOTAL") * @Mapping\SerializedName("UF_BONUS_COUNT_TOTAL")
*/ */
public $bonusCountTotal; public $bonusCountTotal;

View File

@ -97,7 +97,10 @@ class OrderLoyaltyDataRepository extends AbstractRepository
->where('UF_ITEM_POS_ID', '=', $positionId) ->where('UF_ITEM_POS_ID', '=', $positionId)
->fetch(); ->fetch();
/** @var OrderLoyaltyData $result */ if (false === $product) {
return null;
}
return Deserializer::deserializeArray($product, OrderLoyaltyData::class); return Deserializer::deserializeArray($product, OrderLoyaltyData::class);
} catch (ObjectPropertyException | ArgumentException | SystemException $exception) { } catch (ObjectPropertyException | ArgumentException | SystemException $exception) {
$this->logger->write($exception->getMessage(), Constants::LOYALTY_ERROR); $this->logger->write($exception->getMessage(), Constants::LOYALTY_ERROR);
@ -166,6 +169,12 @@ class OrderLoyaltyDataRepository extends AbstractRepository
unset($productAr['ID']); unset($productAr['ID']);
foreach ($productAr as $key => $value) {
if (null === $value) {
unset($productAr[$key]);
}
}
$result = $this->dataManager::update($position->id, $productAr); $result = $this->dataManager::update($position->id, $productAr);
if ($result->isSuccess()) { if ($result->isSuccess()) {
@ -179,6 +188,31 @@ class OrderLoyaltyDataRepository extends AbstractRepository
return false; 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 * @param int $externalId
* @return float|null * @return float|null
@ -195,12 +229,11 @@ class OrderLoyaltyDataRepository extends AbstractRepository
->where([ ->where([
['UF_ITEM_POS_ID', '=', $externalId] ['UF_ITEM_POS_ID', '=', $externalId]
]) ])
->fetch(); ->fetch();
if ($result !== false) { if ($result !== false) {
return (float) $result['UF_DEF_DISCOUNT']; return (float) $result['UF_DEF_DISCOUNT'];
} }
} catch (SystemException | Exception $exception) { } catch (SystemException | Exception $exception) {
$this->logger->write($exception->getMessage(), Constants::LOYALTY_ERROR); $this->logger->write($exception->getMessage(), Constants::LOYALTY_ERROR);
} }

View File

@ -85,6 +85,17 @@ class OrderLoyaltyDataService
*/ */
public static function createLoyaltyHlBlock(): void 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([ $result = HL\HighloadBlockTable::add([
'NAME' => Constants::HL_LOYALTY_CODE, 'NAME' => Constants::HL_LOYALTY_CODE,
'TABLE_NAME' => Constants::HL_LOYALTY_TABLE_NAME, 'TABLE_NAME' => Constants::HL_LOYALTY_TABLE_NAME,
@ -170,18 +181,15 @@ class OrderLoyaltyDataService
return; return;
} }
$repository = new OrderLoyaltyDataRepository();
$bitrixItems = $repository->getProductsByOrderId($orderId);
$loyaltyDiscount = 0; $loyaltyDiscount = 0;
/** @var OrderProduct $item */ /** @var OrderProduct $item */
foreach ($response->order->items as $item) { foreach ($response->order->items as $item) {
/** @var CodeValueModel $itemBitrixId */ foreach ($item->discounts as $discount) {
$itemBitrixId = $item->externalIds[0]; if (in_array($discount->type, ['personal', 'loyalty_level'])) {
/** @var OrderLoyaltyData $bitrixItem */ $loyaltyDiscount += $discount->amount;
$bitrixItem = $bitrixItems[$itemBitrixId->value]; }
}
$loyaltyDiscount += ($item->discountTotal - $bitrixItem->defaultDiscount) * $item->quantity;
} }
$this->saveBonusAndDiscToOrderProps( $this->saveBonusAndDiscToOrderProps(
@ -264,7 +272,33 @@ class OrderLoyaltyDataService
$repository = new OrderLoyaltyDataRepository(); $repository = new OrderLoyaltyDataRepository();
foreach ($loyaltyHls as $loyaltyData) { 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'), 'ru' => Loc::GetMessage('UF_DEF_DISCOUNT', null, 'ru'),
'en' => Loc::GetMessage('UF_DEF_DISCOUNT', null, 'en'), 'en' => Loc::GetMessage('UF_DEF_DISCOUNT', null, 'en'),
], ],
'SETTINGS' => [
'PRECISION' => 2,
],
], ],
'UF_CHECK_ID' => [ 'UF_CHECK_ID' => [
'ENTITY_ID' => $ufObject, 'ENTITY_ID' => $ufObject,
@ -537,11 +574,14 @@ class OrderLoyaltyDataService
'ru' => Loc::GetMessage('UF_BONUS_COUNT', null, 'ru'), 'ru' => Loc::GetMessage('UF_BONUS_COUNT', null, 'ru'),
'en' => Loc::GetMessage('UF_BONUS_COUNT', null, 'en'), 'en' => Loc::GetMessage('UF_BONUS_COUNT', null, 'en'),
], ],
'SETTINGS' => [
'PRECISION' => 2,
],
], ],
'UF_BONUS_COUNT_TOTAL' => [ 'UF_BONUS_COUNT_TOTAL' => [
'ENTITY_ID' => $ufObject, 'ENTITY_ID' => $ufObject,
'FIELD_NAME' => 'UF_BONUS_COUNT_TOTAL', 'FIELD_NAME' => 'UF_BONUS_COUNT_TOTAL',
'USER_TYPE_ID' => 'integer', 'USER_TYPE_ID' => 'double',
'MANDATORY' => 'N', 'MANDATORY' => 'N',
'EDIT_FORM_LABEL' => [ 'EDIT_FORM_LABEL' => [
'ru' => Loc::GetMessage('UF_BONUS_COUNT_TOTAL', null, 'ru'), 'ru' => Loc::GetMessage('UF_BONUS_COUNT_TOTAL', null, 'ru'),
@ -555,6 +595,9 @@ class OrderLoyaltyDataService
'ru' => Loc::GetMessage('UF_BONUS_COUNT_TOTAL', null, 'ru'), 'ru' => Loc::GetMessage('UF_BONUS_COUNT_TOTAL', null, 'ru'),
'en' => Loc::GetMessage('UF_BONUS_COUNT_TOTAL', null, 'en'), 'en' => Loc::GetMessage('UF_BONUS_COUNT_TOTAL', null, 'en'),
], ],
'SETTINGS' => [
'PRECISION' => 2,
],
], ],
]; ];
} }

View File

@ -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'); Loader::includeModule('highloadblock');
(new LoyaltyProgramUpdater()) (new LoyaltyProgramUpdater())
->tryReplaceExportVars() ->updateBonusInfoFieldForLp()
->addLoyaltyProgramEvents() ->updateBonusFieldsTypeInHl()
->CopyFiles() ->updateDefDiscountFieldTypeInHl();
->addLpUserFields()
->addAgreement()
->createLoyaltyHlBlock()
->addCustomersLoyaltyFields();
} }
try { try {