1
0
mirror of synced 2024-11-28 16:26:07 +03:00
bitrix-module/intaro.retailcrm/lib/service/orderloyaltydataservice.php

579 lines
21 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
/**
* @category Integration
* @package Intaro\RetailCrm\Service
* @author retailCRM <integration@retailcrm.ru>
* @license MIT
* @link http://retailcrm.ru
* @see http://retailcrm.ru/docs
*/
namespace Intaro\RetailCrm\Service;
use Bitrix\Highloadblock as HL;
use Bitrix\Main\ArgumentException;
use Bitrix\Main\Loader;
use Bitrix\Main\Localization\Loc;
use Bitrix\Main\ObjectPropertyException;
use Bitrix\Main\SystemException;
use Bitrix\Sale\Internals\OrderPropsGroupTable;
use Bitrix\Sale\Order;
use Bitrix\Sale\PropertyValue;
use Bitrix\Sale\PropertyValueCollectionBase;
use CSaleOrderProps;
use CUserTypeEntity;
use Exception;
use Intaro\RetailCrm\Component\Constants;
use Intaro\RetailCrm\Component\Factory\ClientFactory;
use Intaro\RetailCrm\Component\Handlers\EventsHandlers;
use Intaro\RetailCrm\Component\Json\Serializer;
use Intaro\RetailCrm\Model\Api\CodeValueModel;
use Intaro\RetailCrm\Model\Api\Order\OrderProduct;
use Intaro\RetailCrm\Model\Bitrix\OrderLoyaltyData;
use Intaro\RetailCrm\Repository\OrderLoyaltyDataRepository;
use Intaro\RetailCrm\Repository\OrderPropsRepository;
use Intaro\RetailCrm\Repository\PersonTypeRepository;
use Logger;
/**
* Class OrderLoyaltyDataService
* @package Intaro\RetailCrm\Service
*/
class OrderLoyaltyDataService
{
/**
* @var \Logger
*/
private $logger;
/**
* OrderLoyaltyDataService constructor.
*/
public function __construct()
{
$this->logger = Logger::getInstance();
}
/**
* add LP Order Props
*
* @throws \Bitrix\Main\ArgumentException
* @throws \Bitrix\Main\ObjectPropertyException
* @throws \Bitrix\Main\SystemException
*/
public function addCustomersLoyaltyFields(): void
{
$persons = PersonTypeRepository::getCollectionByWhere(['ID']);
foreach ($persons as $person) {
$personId = $person->getID();
$groupId = $this->getGroupId($personId);
if (isset($groupId)) {
$this->addBonusField($personId, $groupId);
}
}
}
/**
* Создает HL блок для хранения информации о бонусах и скидках
*
* @throws \Bitrix\Main\SystemException
* @throws \Exception
*/
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,
]);
$arLangs = [
'ru' => Loc::GetMessage('LP_ORDER_GROUP_NAME', null, 'ru'),
'en' => Loc::GetMessage('LP_ORDER_GROUP_NAME', null, 'en'),
];
if ($result->isSuccess()) {
$hlId = $result->getId();
foreach ($arLangs as $langKey => $langVal) {
HL\HighloadBlockLangTable::add([
'ID' => $hlId,
'LID' => $langKey,
'NAME' => $langVal,
]);
}
} else {
foreach ($result->getErrorMessages() as $error) {
Logger::getInstance()->write($error);
}
}
if (!isset($hlId)) {
return;
}
$ufObject = 'HLBLOCK_' . $hlId;
$arCartFields = self::getHlFields($ufObject);
foreach ($arCartFields as $arCartField) {
$obUserField = new CUserTypeEntity();
$obUserField->Add($arCartField);
}
}
/**
* Добавляет информацию о списанных бонусах и скидках программы лояльности в св-ва заказа
*
* @param \Bitrix\Sale\PropertyValueCollectionBase $props
* @param float|null $loyaltyDiscountInput
* @param float|null $loyaltyBonus
*/
public function saveBonusAndDiscToOrderProps(
PropertyValueCollectionBase $props,
?float $loyaltyDiscountInput = 0,
?float $loyaltyBonus = 0
): void {
/** @var \Bitrix\Sale\PropertyValue $prop */
foreach ($props as $prop) {
if ($prop->getField('CODE') === 'LP_DISCOUNT_INFO') {
$this->saveLpInfoToField($prop, $loyaltyDiscountInput);
break;
}
}
foreach ($props as $prop) {
if ($prop->getField('CODE') === 'LP_BONUS_INFO') {
$this->saveLpInfoToField($prop, $loyaltyBonus);
break;
}
}
}
/**
* @param int $orderId
*
* @throws \Bitrix\Main\LoaderException
*/
public function updateOrderFromCrm(int $orderId): void
{
if (!Loader::includeModule('sale')) {
return;
}
/** @var \Intaro\RetailCrm\Component\ApiClient\ClientAdapter $client */
$client = ClientFactory::createClientAdapter();
$response = $client->getOrder($orderId);
if ($response === null || !is_array($response->order->items)) {
return;
}
try {
$order = Order::load($orderId);
if ($order === null) {
return;
}
$basket = $order->getBasket();
/** @var OrderProduct $item */
foreach ($response->order->items as $item) {
$itemArray = Serializer::serializeArray($item);
$basketIdKey = array_search(
'bitrixBasketId',
array_column($itemArray['externalIds'], 'code'),
true
);
$basketId = explode('#', $item->externalIds[$basketIdKey]->value)[0] ?? null;
$basketItem = $basket->getItemById($basketId);
if ($basketItem === null) {
continue;
}
$basketItem->setField('CUSTOM_PRICE', 'Y');
$basketItem->setField('DISCOUNT_PRICE', $item->initialPrice - $item->discountTotal);
$basketItem->setField('PRICE', $item->initialPrice - $item->discountTotal);
}
EventsHandlers::$disableSaleHandler = true;
$order->save();
EventsHandlers::$disableSaleHandler = false;
} catch (Exception $exception) {
$this->logger->write($exception->getMessage(), Constants::LOYALTY_ERROR);
}
}
/**
* Записывает данные о ПЛ в HL-блок
*
* @param OrderLoyaltyData[] $loyaltyHls
* @return void
*/
public function saveLoyaltyInfoToHl(array $loyaltyHls): void
{
$repository = new OrderLoyaltyDataRepository();
foreach ($loyaltyHls as $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);
}
}
}
/**
* @param $personId
* @param $groupId
*/
private function addBonusField($personId, $groupId): void
{
try {
$bonusProp = OrderPropsRepository::getFirstByWhere(['ID'],
[
['PERSON_TYPE_ID', '=', $personId],
['PROPS_GROUP_ID', '=', $groupId],
]
);
if ($bonusProp === null) {
$fields = [
[
'REQUIRED' => 'N',
'NAME' => GetMessage('LP_BONUS_INFO'),
'TYPE' => 'TEXTAREA',
'CODE' => 'LP_BONUS_INFO',
'USER_PROPS' => 'Y',
'IS_LOCATION' => 'N',
'IS_LOCATION4TAX' => 'N',
'IS_EMAIL' => 'N',
'IS_PROFILE_NAME' => 'N',
'IS_PAYER' => 'N',
'IS_FILTERED' => 'Y',
'PERSON_TYPE_ID' => $personId,
'PROPS_GROUP_ID' => $groupId,
'DEFAULT_VALUE' => '',
'DESCRIPTION' => GetMessage('LP_BONUS_INFO'),
'UTIL' => 'Y',
],
[
'REQUIRED' => 'N',
'NAME' => GetMessage('LP_DISCOUNT_INFO'),
'TYPE' => 'TEXTAREA',
'CODE' => 'LP_DISCOUNT_INFO',
'USER_PROPS' => 'Y',
'IS_LOCATION' => 'N',
'IS_LOCATION4TAX' => 'N',
'IS_EMAIL' => 'N',
'IS_PROFILE_NAME' => 'N',
'IS_PAYER' => 'N',
'IS_FILTERED' => 'Y',
'PERSON_TYPE_ID' => $personId,
'PROPS_GROUP_ID' => $groupId,
'DEFAULT_VALUE' => '',
'DESCRIPTION' => GetMessage('LP_DISCOUNT_INFO'),
'UTIL' => 'Y',
],
];
foreach ($fields as $field) {
CSaleOrderProps::Add($field);
}
}
} catch (ObjectPropertyException | ArgumentException | SystemException $exception) {
$this->logger->write($exception->getMessage(), Constants::LOYALTY_ERROR);
}
}
/**
* @param $personId
* @return int
*/
private function getGroupId($personId): ?int
{
try {
$lpGroup = OrderPropsGroupTable::query()
->setSelect(['ID'])
->where(
[
['PERSON_TYPE_ID', '=', $personId],
['NAME', '=', GetMessage('LP_ORDER_GROUP_NAME')],
]
)
->fetch();
if (is_array($lpGroup)) {
return $lpGroup['ID'];
}
if ($lpGroup === false) {
return OrderPropsGroupTable::add([
'PERSON_TYPE_ID' => $personId,
'NAME' => GetMessage('LP_ORDER_GROUP_NAME'),
])->getId();
}
} catch (Exception $exception) {
$this->logger->write($exception->getMessage(), Constants::LOYALTY_ERROR);
return null;
}
return null;
}
/**
* Возвращает настройки для генерации полей HL блока
*
* @param string $ufObject
* @return array[]
*/
private static function getHlFields(string $ufObject): array
{
return [
'UF_ORDER_ID' => [
'ENTITY_ID' => $ufObject,
'FIELD_NAME' => 'UF_ORDER_ID',
'USER_TYPE_ID' => 'integer',
'MANDATORY' => 'Y',
'EDIT_FORM_LABEL' => [
'ru' => Loc::GetMessage('UF_ORDER_ID', null, 'ru'),
'en' => Loc::GetMessage('UF_ORDER_ID', null, 'en'),
],
'LIST_COLUMN_LABEL' => [
'ru' => Loc::GetMessage('UF_ORDER_ID', null, 'ru'),
'en' => Loc::GetMessage('UF_ORDER_ID', null, 'en'),
],
'LIST_FILTER_LABEL' => [
'ru' => Loc::GetMessage('UF_ORDER_ID', null, 'ru'),
'en' => Loc::GetMessage('UF_ORDER_ID', null, 'en'),
],
],
'UF_ITEM_ID' => [
'ENTITY_ID' => $ufObject,
'FIELD_NAME' => 'UF_ITEM_ID',
'USER_TYPE_ID' => 'integer',
'MANDATORY' => 'Y',
'EDIT_FORM_LABEL' => [
'ru' => Loc::GetMessage('UF_ITEM_ID', null, 'ru'),
'en' => Loc::GetMessage('UF_ITEM_ID', null, 'en'),
],
'LIST_COLUMN_LABEL' => [
'ru' => Loc::GetMessage('UF_ITEM_ID', null, 'ru'),
'en' => Loc::GetMessage('UF_ITEM_ID', null, 'en'),
],
'LIST_FILTER_LABEL' => [
'ru' => Loc::GetMessage('UF_ITEM_ID', null, 'ru'),
'en' => Loc::GetMessage('UF_ITEM_ID', null, 'en'),
],
],
'UF_ITEM_POS_ID' => [
'ENTITY_ID' => $ufObject,
'FIELD_NAME' => 'UF_ITEM_POS_ID',
'USER_TYPE_ID' => 'integer',
'MANDATORY' => 'Y',
'EDIT_FORM_LABEL' => [
'ru' => Loc::GetMessage('UF_ITEM_POS_ID', null, 'ru'),
'en' => Loc::GetMessage('UF_ITEM_POS_ID', null, 'en'),
],
'LIST_COLUMN_LABEL' => [
'ru' => Loc::GetMessage('UF_ITEM_POS_ID', null, 'ru'),
'en' => Loc::GetMessage('UF_ITEM_POS_ID', null, 'en'),
],
'LIST_FILTER_LABEL' => [
'ru' => Loc::GetMessage('UF_ITEM_POS_ID', null, 'ru'),
'en' => Loc::GetMessage('UF_ITEM_POS_ID', null, 'en'),
],
],
'UF_NAME' => [
'ENTITY_ID' => $ufObject,
'FIELD_NAME' => 'UF_NAME',
'USER_TYPE_ID' => 'string',
'MANDATORY' => 'N',
'EDIT_FORM_LABEL' => [
'ru' => Loc::GetMessage('UF_NAME', null, 'ru'),
'en' => Loc::GetMessage('UF_NAME', null, 'en'),
],
'LIST_COLUMN_LABEL' => [
'ru' => Loc::GetMessage('UF_NAME', null, 'ru'),
'en' => Loc::GetMessage('UF_NAME', null, 'en'),
],
'LIST_FILTER_LABEL' => [
'ru' => Loc::GetMessage('UF_NAME', null, 'ru'),
'en' => Loc::GetMessage('UF_NAME', null, 'en'),
],
],
'UF_DEF_DISCOUNT' => [
'ENTITY_ID' => $ufObject,
'FIELD_NAME' => 'UF_DEF_DISCOUNT',
'USER_TYPE_ID' => 'double',
'MANDATORY' => 'N',
'EDIT_FORM_LABEL' => [
'ru' => Loc::GetMessage('UF_DEF_DISCOUNT', null, 'ru'),
'en' => Loc::GetMessage('UF_DEF_DISCOUNT', null, 'en'),
],
'LIST_COLUMN_LABEL' => [
'ru' => Loc::GetMessage('UF_DEF_DISCOUNT', null, 'ru'),
'en' => Loc::GetMessage('UF_DEF_DISCOUNT', null, 'en'),
],
'LIST_FILTER_LABEL' => [
'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,
'FIELD_NAME' => 'UF_CHECK_ID',
'USER_TYPE_ID' => 'string',
'MANDATORY' => 'N',
'EDIT_FORM_LABEL' => [
'ru' => Loc::GetMessage('UF_CHECK_ID', null, 'ru'),
'en' => Loc::GetMessage('UF_CHECK_ID', null, 'en'),
],
'LIST_COLUMN_LABEL' => [
'ru' => Loc::GetMessage('UF_CHECK_ID', null, 'ru'),
'en' => Loc::GetMessage('UF_CHECK_ID', null, 'en'),
],
'LIST_FILTER_LABEL' => [
'ru' => Loc::GetMessage('UF_CHECK_ID', null, 'ru'),
'en' => Loc::GetMessage('UF_CHECK_ID', null, 'en'),
],
],
'UF_IS_DEBITED' => [
'ENTITY_ID' => $ufObject,
'FIELD_NAME' => 'UF_IS_DEBITED',
'USER_TYPE_ID' => 'boolean',
'MANDATORY' => 'N',
'EDIT_FORM_LABEL' => [
'ru' => Loc::GetMessage('UF_IS_DEBITED', null, 'ru'),
'en' => Loc::GetMessage('UF_IS_DEBITED', null, 'en'),
],
'LIST_COLUMN_LABEL' => [
'ru' => Loc::GetMessage('UF_IS_DEBITED', null, 'ru'),
'en' => Loc::GetMessage('UF_IS_DEBITED', null, 'en'),
],
'LIST_FILTER_LABEL' => [
'ru' => Loc::GetMessage('UF_IS_DEBITED', null, 'ru'),
'en' => Loc::GetMessage('UF_IS_DEBITED', null, 'en'),
],
],
'UF_QUANTITY' => [
'ENTITY_ID' => $ufObject,
'FIELD_NAME' => 'UF_QUANTITY',
'USER_TYPE_ID' => 'integer',
'MANDATORY' => 'Y',
'EDIT_FORM_LABEL' => [
'ru' => Loc::GetMessage('UF_QUANTITY', null, 'ru'),
'en' => Loc::GetMessage('UF_QUANTITY', null, 'en'),
],
'LIST_COLUMN_LABEL' => [
'ru' => Loc::GetMessage('UF_QUANTITY', null, 'ru'),
'en' => Loc::GetMessage('UF_QUANTITY', null, 'en'),
],
'LIST_FILTER_LABEL' => [
'ru' => Loc::GetMessage('UF_QUANTITY', null, 'ru'),
'en' => Loc::GetMessage('UF_QUANTITY', null, 'en'),
],
],
'UF_BONUS_COUNT' => [
'ENTITY_ID' => $ufObject,
'FIELD_NAME' => 'UF_BONUS_COUNT',
'USER_TYPE_ID' => 'double',
'MANDATORY' => 'N',
'EDIT_FORM_LABEL' => [
'ru' => Loc::GetMessage('UF_BONUS_COUNT', null, 'ru'),
'en' => Loc::GetMessage('UF_BONUS_COUNT', null, 'en'),
],
'LIST_COLUMN_LABEL' => [
'ru' => Loc::GetMessage('UF_BONUS_COUNT', null, 'ru'),
'en' => Loc::GetMessage('UF_BONUS_COUNT', null, 'en'),
],
'LIST_FILTER_LABEL' => [
'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' => 'double',
'MANDATORY' => 'N',
'EDIT_FORM_LABEL' => [
'ru' => Loc::GetMessage('UF_BONUS_COUNT_TOTAL', null, 'ru'),
'en' => Loc::GetMessage('UF_BONUS_COUNT_TOTAL', null, 'en'),
],
'LIST_COLUMN_LABEL' => [
'ru' => Loc::GetMessage('UF_BONUS_COUNT_TOTAL', null, 'ru'),
'en' => Loc::GetMessage('UF_BONUS_COUNT_TOTAL', null, 'en'),
],
'LIST_FILTER_LABEL' => [
'ru' => Loc::GetMessage('UF_BONUS_COUNT_TOTAL', null, 'ru'),
'en' => Loc::GetMessage('UF_BONUS_COUNT_TOTAL', null, 'en'),
],
'SETTINGS' => [
'PRECISION' => 2,
],
],
];
}
/**
* @param \Bitrix\Sale\PropertyValue $prop
* @param float|null $loyaltyBonus
*/
private function saveLpInfoToField(PropertyValue $prop, ?float $loyaltyBonus = 0): void
{
try {
$result = $prop->setField('VALUE', (string) $loyaltyBonus);
if (!$result->isSuccess()) {
$this->logger->write($result->getErrorMessages(), Constants::LOYALTY_ERROR);
}
} catch (Exception $exception) {
$this->logger->write($exception->getMessage(), Constants::LOYALTY_ERROR);
}
}
}