2022-03-02 15:40:53 +03:00
|
|
|
|
<?php
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @category Integration
|
|
|
|
|
* @package Intaro\RetailCrm\Component\Loyalty
|
|
|
|
|
* @author RetailCRM <integration@retailcrm.ru>
|
|
|
|
|
* @license MIT
|
|
|
|
|
* @link http://retailcrm.ru
|
|
|
|
|
* @see http://retailcrm.ru/docs
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
namespace Intaro\RetailCrm\Component\Handlers;
|
|
|
|
|
|
|
|
|
|
IncludeModuleLangFile(__FILE__);
|
|
|
|
|
|
|
|
|
|
use Bitrix\Main\Event;
|
|
|
|
|
use Bitrix\Main\HttpRequest;
|
|
|
|
|
use Bitrix\Sale\Order;
|
|
|
|
|
use Intaro\RetailCrm\Component\Builder\Bitrix\LoyaltyDataBuilder;
|
|
|
|
|
use Intaro\RetailCrm\Component\ConfigProvider;
|
|
|
|
|
use Intaro\RetailCrm\Component\ServiceLocator;
|
|
|
|
|
use Intaro\RetailCrm\Model\Api\Response\Order\Loyalty\OrderLoyaltyApplyResponse;
|
|
|
|
|
use Intaro\RetailCrm\Repository\UserRepository;
|
|
|
|
|
use Intaro\RetailCrm\Service\LoyaltyService;
|
|
|
|
|
use Intaro\RetailCrm\Service\LoyaltyAccountService;
|
|
|
|
|
use Intaro\RetailCrm\Service\CustomerService;
|
|
|
|
|
use Intaro\RetailCrm\Service\OrderLoyaltyDataService;
|
|
|
|
|
use Intaro\RetailCrm\Service\Utils;
|
|
|
|
|
use Logger;
|
|
|
|
|
use RetailCrmEvent;
|
|
|
|
|
use Throwable;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Class EventsHandlers
|
|
|
|
|
*
|
|
|
|
|
* @package Intaro\RetailCrm\Component\Loyalty
|
|
|
|
|
*/
|
|
|
|
|
class EventsHandlers
|
|
|
|
|
{
|
|
|
|
|
public static $disableSaleHandler = false;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* EventsHandlers constructor.
|
|
|
|
|
*/
|
|
|
|
|
public function __construct()
|
|
|
|
|
{
|
|
|
|
|
IncludeModuleLangFile(__FILE__);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Обработчик события, вызываемого при обновлении еще не сохраненного заказа
|
|
|
|
|
*
|
|
|
|
|
* Модифицирует данные $arResult с учетом привилегий покупателя по Программе лояльности
|
|
|
|
|
*
|
|
|
|
|
* @param \Bitrix\Sale\Order $order
|
|
|
|
|
* @param array $arUserResult
|
|
|
|
|
* @param \Bitrix\Main\HttpRequest $request
|
|
|
|
|
* @param array $arParams
|
|
|
|
|
* @param array $arResult
|
|
|
|
|
*/
|
2023-03-15 11:55:04 +03:00
|
|
|
|
public static function OnSaleComponentOrderResultPreparedHandler(
|
2022-03-02 15:40:53 +03:00
|
|
|
|
Order $order,
|
|
|
|
|
array $arUserResult,
|
|
|
|
|
HttpRequest $request,
|
|
|
|
|
array $arParams,
|
|
|
|
|
array &$arResult
|
|
|
|
|
): void {
|
|
|
|
|
if (ConfigProvider::getLoyaltyProgramStatus() === 'Y') {
|
|
|
|
|
$bonusInput = (float) $request->get('bonus-input');
|
|
|
|
|
$availableBonuses = (float) $request->get('available-bonuses');
|
|
|
|
|
$chargeRate = (float) $request->get('charge-rate');
|
|
|
|
|
$loyaltyDiscountInput = (float) $request->get('loyalty-discount-input');
|
|
|
|
|
$calculateItemsInput = $request->get('calculate-items-input');
|
|
|
|
|
$bonusDiscount = round($bonusInput * $chargeRate, 2);
|
|
|
|
|
|
|
|
|
|
if ($bonusInput > $availableBonuses) {
|
|
|
|
|
$arResult['LOYALTY']['ERROR'] = GetMessage('BONUS_ERROR_MSG');
|
|
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$jsDataTotal = &$arResult['JS_DATA']['TOTAL'];
|
|
|
|
|
|
|
|
|
|
$isWriteOffAvailable = $bonusInput > 0
|
|
|
|
|
&& $availableBonuses > 0
|
|
|
|
|
&& $jsDataTotal['ORDER_TOTAL_PRICE'] >= $bonusDiscount + $loyaltyDiscountInput;
|
|
|
|
|
|
|
|
|
|
if ($isWriteOffAvailable || $loyaltyDiscountInput > 0) {
|
|
|
|
|
$jsDataTotal['ORDER_TOTAL_PRICE']
|
|
|
|
|
-= round($bonusDiscount + $loyaltyDiscountInput, 2);
|
|
|
|
|
$jsDataTotal['ORDER_TOTAL_PRICE_FORMATED']
|
|
|
|
|
= number_format($jsDataTotal['ORDER_TOTAL_PRICE'], 0, ',', ' ')
|
|
|
|
|
. ' ' . GetMessage('RUB');
|
|
|
|
|
$jsDataTotal['BONUS_PAYMENT'] = $bonusDiscount;
|
|
|
|
|
$jsDataTotal['DISCOUNT_PRICE'] += $bonusDiscount + $loyaltyDiscountInput;
|
|
|
|
|
$jsDataTotal['DISCOUNT_PRICE_FORMATED'] = $jsDataTotal['DISCOUNT_PRICE'] . ' ' . GetMessage('RUB');
|
|
|
|
|
$jsDataTotal['ORDER_PRICE_FORMATED']
|
|
|
|
|
= $jsDataTotal['ORDER_PRICE'] - $loyaltyDiscountInput . ' ' . GetMessage('RUB');
|
|
|
|
|
$oldItems = json_decode(htmlspecialchars_decode($calculateItemsInput), true);
|
|
|
|
|
|
|
|
|
|
/** @var LoyaltyService $service */
|
|
|
|
|
$service = ServiceLocator::get(LoyaltyService::class);
|
|
|
|
|
$calculate = $service->getLoyaltyCalculate($arResult['BASKET_ITEMS'], $bonusInput);
|
|
|
|
|
|
|
|
|
|
if ($calculate->success) {
|
|
|
|
|
$jsDataTotal['WILL_BE_CREDITED'] = $calculate->order->bonusesCreditTotal;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ($calculateItemsInput !== null) {
|
|
|
|
|
foreach ($arResult['JS_DATA']['GRID']['ROWS'] as $key => &$item) {
|
|
|
|
|
$item['data']['SUM_NUM'] = $oldItems[$key]['SUM_NUM'];
|
|
|
|
|
$item['data']['SUM'] = $item['data']['SUM_NUM'] . GetMessage('RUB');
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
unset($item);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Обработчик события, вызываемого ПОСЛЕ сохранения заказа (OnSaleOrderSaved)
|
|
|
|
|
*
|
|
|
|
|
* @param \Bitrix\Main\Event $event
|
|
|
|
|
*/
|
2023-03-15 11:55:04 +03:00
|
|
|
|
public static function OnSaleOrderSavedHandler(Event $event): void
|
2022-03-02 15:40:53 +03:00
|
|
|
|
{
|
2023-01-24 15:54:48 +03:00
|
|
|
|
if (self::$disableSaleHandler === true) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2022-03-02 15:40:53 +03:00
|
|
|
|
try {
|
2023-01-24 15:54:48 +03:00
|
|
|
|
/** @var Order $order */
|
|
|
|
|
$order = $event->getParameter('ENTITY');
|
2024-10-03 12:46:41 +03:00
|
|
|
|
|
|
|
|
|
$saveResult = RetailCrmEvent::orderSave($order);
|
|
|
|
|
Utils::handleApiErrors($saveResult);
|
2023-01-24 15:54:48 +03:00
|
|
|
|
|
2023-01-16 11:05:29 +03:00
|
|
|
|
$isBonusInput = (
|
|
|
|
|
!empty($_POST['bonus-input'])
|
|
|
|
|
&& !empty($_POST['available-bonuses'])
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
$isDataForLoyaltyDiscount = isset($_POST['calculate-items-input'], $_POST['loyalty-discount-input']);
|
|
|
|
|
|
2023-01-24 15:54:48 +03:00
|
|
|
|
if (!($isDataForLoyaltyDiscount || $isBonusInput) ) {
|
2023-01-16 11:05:29 +03:00
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2022-03-02 15:40:53 +03:00
|
|
|
|
/* @var LoyaltyService $loyaltyService */
|
|
|
|
|
$loyaltyService = ServiceLocator::get(LoyaltyService::class);
|
|
|
|
|
|
|
|
|
|
/* @var OrderLoyaltyDataService $orderLoyaltyDataService */
|
|
|
|
|
$orderLoyaltyDataService = ServiceLocator::get(OrderLoyaltyDataService::class);
|
|
|
|
|
|
|
|
|
|
$bonusFloat = (float) $_POST['bonus-input'];
|
|
|
|
|
|
|
|
|
|
/** @var bool $isNewOrder */
|
|
|
|
|
$isNewOrder = $event->getParameter('IS_NEW');
|
|
|
|
|
$isLoyaltyOn = ConfigProvider::getLoyaltyProgramStatus() === 'Y';
|
|
|
|
|
$isBonusesIssetAndAvailable = $isBonusInput && (float) $_POST['available-bonuses'] >= $bonusFloat;
|
|
|
|
|
|
|
|
|
|
/** @var array $calculateItemsInput */
|
|
|
|
|
$calculateItemsInput = $isDataForLoyaltyDiscount
|
|
|
|
|
? json_decode(htmlspecialchars_decode($_POST['calculate-items-input']), true)
|
|
|
|
|
: [];
|
|
|
|
|
|
2022-06-28 15:28:28 +03:00
|
|
|
|
if ($isNewOrder && $isLoyaltyOn && ($isDataForLoyaltyDiscount || $isBonusInput)) {
|
2022-03-02 15:40:53 +03:00
|
|
|
|
self::$disableSaleHandler = true;
|
|
|
|
|
|
|
|
|
|
$hlInfoBuilder = new LoyaltyDataBuilder();
|
|
|
|
|
$hlInfoBuilder->setOrder($order);
|
|
|
|
|
|
|
|
|
|
$discountInput = isset($_POST['loyalty-discount-input'])
|
|
|
|
|
? (float) $_POST['loyalty-discount-input']
|
|
|
|
|
: 0;
|
|
|
|
|
|
|
|
|
|
$loyaltyBonusMsg = 0;
|
|
|
|
|
$applyBonusResponse = null;
|
|
|
|
|
|
|
|
|
|
//Если есть бонусы
|
|
|
|
|
if ($isBonusesIssetAndAvailable) {
|
2024-06-18 09:21:06 +03:00
|
|
|
|
$hlInfoBuilder->setApplyResponse($loyaltyService->applyBonusesInOrder($order, $bonusFloat));
|
2022-03-02 15:40:53 +03:00
|
|
|
|
$loyaltyBonusMsg = $bonusFloat;
|
2022-06-28 15:28:28 +03:00
|
|
|
|
$hlInfoBuilder->setBonusCountTotal($bonusFloat);
|
2022-03-02 15:40:53 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//Если бонусов нет, но скидка по ПЛ есть
|
|
|
|
|
if (
|
|
|
|
|
($isDataForLoyaltyDiscount && !$isBonusInput)
|
|
|
|
|
) {
|
|
|
|
|
$loyaltyService->saveDiscounts($order, $calculateItemsInput);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$orderLoyaltyDataService->saveBonusAndDiscToOrderProps(
|
|
|
|
|
$order->getPropertyCollection(),
|
|
|
|
|
$discountInput,
|
|
|
|
|
$loyaltyBonusMsg
|
|
|
|
|
);
|
2023-01-16 11:05:29 +03:00
|
|
|
|
|
2022-03-02 15:40:53 +03:00
|
|
|
|
$hlInfoBuilder->setCalculateItemsInput($calculateItemsInput);
|
|
|
|
|
$orderLoyaltyDataService->saveLoyaltyInfoToHl($hlInfoBuilder->build()->getResult());
|
2023-01-16 11:05:29 +03:00
|
|
|
|
$order->save();
|
2022-03-02 15:40:53 +03:00
|
|
|
|
|
|
|
|
|
self::$disableSaleHandler = false;
|
|
|
|
|
}
|
|
|
|
|
} catch (Throwable $exception) {
|
|
|
|
|
Logger::getInstance()->write(GetMessage('CAN_NOT_SAVE_ORDER') . $exception->getMessage(), 'uploadApiErrors');
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|