1
0
mirror of synced 2024-11-30 09:16:06 +03:00
bitrix-module/intaro.retailcrm/classes/general/order/RetailCrmOrder_v5.php

1043 lines
38 KiB
PHP
Raw Normal View History

2016-09-15 16:42:10 +03:00
<?php
2021-05-31 11:14:02 +03:00
/**
* @category RetailCRM
* @package RetailCRM\Order
* @author RetailCRM <integration@retailcrm.ru>
* @license MIT
* @link http://retailcrm.ru
* @see http://retailcrm.ru/docs
*/
use Bitrix\Main\Context;
use Bitrix\Main\Context\Culture;
2021-07-08 16:29:34 +03:00
use Bitrix\Main\UserTable;
use Bitrix\Sale\Delivery\Services\Manager;
2021-05-31 11:14:02 +03:00
use Bitrix\Sale\Internals\Fields;
2021-09-08 10:19:29 +03:00
use Bitrix\Sale\Internals\OrderTable;
use Bitrix\Sale\Location\LocationTable;
2021-07-08 16:29:34 +03:00
use Bitrix\Sale\Order;
use Intaro\RetailCrm\Component\ApiClient\ClientAdapter;
use Intaro\RetailCrm\Component\Constants;
use Intaro\RetailCrm\Component\Factory\ClientFactory;
use Intaro\RetailCrm\Component\ServiceLocator;
use Intaro\RetailCrm\Service\LoyaltyService;
2021-07-08 16:29:34 +03:00
use RetailCrm\ApiClient;
use Intaro\RetailCrm\Service\ManagerService;
use Intaro\RetailCrm\Service\LoyaltyAccountService;
use RetailCrm\Response\ApiResponse;
use Intaro\RetailCrm\Component\ConfigProvider;
use Intaro\RetailCrm\Model\Api\Response\OrdersCreateResponse;
2021-05-31 11:14:02 +03:00
2016-09-15 16:42:10 +03:00
IncludeModuleLangFile(__FILE__);
/**
* Class RetailCrmOrder
*
* @category RetailCRM
* @package RetailCRM\Order
*/
2016-09-15 16:42:10 +03:00
class RetailCrmOrder
{
/**
* Creates order or returns order for mass upload
*
* @param array $arOrder
* @param $api
* @param $arParams
* @param bool $send
* @param null $site
* @param string $methodApi
*
* @return array|false|\Intaro\RetailCrm\Model\Api\Response\OrdersCreateResponse|\Intaro\RetailCrm\Model\Api\Response\OrdersEditResponse|null
* @throws \Bitrix\Main\ArgumentException
* @throws \Bitrix\Main\ObjectPropertyException
* @throws \Bitrix\Main\SystemException
2016-09-15 16:42:10 +03:00
*/
public static function orderSend(
array $arOrder,
$api,
$arParams,
bool $send = false,
$site = null,
string $methodApi = 'ordersEdit'
) {
2016-10-04 17:57:39 +03:00
if (!$api || empty($arParams)) { // add cond to check $arParams
return null;
2016-09-15 16:42:10 +03:00
}
if (empty($arOrder)) {
2016-09-15 16:42:10 +03:00
RCrmActions::eventLog('RetailCrmOrder::orderSend', 'empty($arFields)', 'incorrect order');
return null;
2016-09-15 16:42:10 +03:00
}
2020-04-24 13:18:18 +03:00
$dimensionsSetting = RetailcrmConfigProvider::getOrderDimensions();
$currency = RetailcrmConfigProvider::getCurrencyOrDefault();
2018-05-23 12:19:59 +03:00
$order = [
'number' => $arOrder['NUMBER'],
'externalId' => $arOrder['ID'],
'createdAt' => $arOrder['DATE_INSERT'],
'customer' => isset($arParams['customerCorporate'])
? ['id' => $arParams['customerCorporate']['id']]
: ['externalId' => $arOrder['USER_ID']],
'orderType' => $arParams['optionsOrderTypes'][$arOrder['PERSON_TYPE_ID']] ?? '',
'status' => $arParams['optionsPayStatuses'][$arOrder['STATUS_ID']] ?? '',
'customerComment' => $arOrder['USER_DESCRIPTION'],
'managerComment' => $arOrder['COMMENTS'],
'managerId' => $arParams['managerId'] ?? null,
'delivery' => ['cost' => $arOrder['PRICE_DELIVERY']],
];
2020-04-24 13:18:18 +03:00
$orderCouponField = ConfigProvider::getOrderCouponField();
if ($orderCouponField !== '__default_empty_value__') {
$couponList = \Bitrix\Sale\Internals\OrderCouponsTable::getList([
'select' => ['COUPON'],
'filter' => ['=ORDER_ID' => $arOrder['ID']],
]);
$appliedCoupons = [];
while ($coupon = $couponList->fetch())
{
$appliedCoupons[] = $coupon['COUPON'];
}
if (!empty($orderCouponField) && $appliedCoupons !== []) {
$order['customFields'][$orderCouponField] = implode('; ', $appliedCoupons);
}
}
if (!empty($arOrder['REASON_CANCELED'])) {
$order['statusComment'] = $arOrder['REASON_CANCELED'];
}
2020-04-24 13:18:18 +03:00
if (isset($arParams['contactExId'])) {
$order['contact']['externalId'] = $arParams['contactExId'];
}
if (isset($arParams['orderCompany']) && !empty($arParams['orderCompany'])) {
$company = $arParams['orderCompany'];
if (isset($company['id'])) {
$order['company']['id'] = $company['id'];
}
if (isset($company['name'])) {
$order['contragent']['legalName'] = $company['name'];
}
}
2017-09-04 11:36:04 +03:00
if ($send && isset($_COOKIE['_rc']) && $_COOKIE['_rc'] != '') {
2016-09-15 16:42:10 +03:00
$order['customer']['browserId'] = $_COOKIE['_rc'];
}
2020-04-24 13:18:18 +03:00
$order['contragent']['contragentType'] = $arParams['optionsContragentType'][$arOrder['PERSON_TYPE_ID']];
2016-09-15 16:42:10 +03:00
$countryList = BitrixOrderService::getCountryList();
$isSendCustomFields = 'N';
if (method_exists(RCrmActions::class, 'convertCmsFieldToCrmValue')) {
$isSendCustomFields = RetailcrmConfigProvider::getCustomFieldsStatus();
}
//Order fields
foreach ($arOrder['PROPS']['properties'] as $prop) {
2018-06-13 13:05:58 +03:00
if (!empty($arParams['optionsLegalDetails'])
&& is_array($arParams['optionsLegalDetails'][$arOrder['PERSON_TYPE_ID']])
&& $search = array_search($prop['CODE'], $arParams['optionsLegalDetails'][$arOrder['PERSON_TYPE_ID']])
2018-06-13 13:05:58 +03:00
) {
2017-09-04 11:36:04 +03:00
$order['contragent'][$search] = $prop['VALUE'][0];//legal order data
} elseif ($isSendCustomFields === 'Y'
&& !empty($arParams['customOrderProps'])
&& isset($arParams['customOrderProps'][$prop['ID'] . '#' . $prop['CODE']])
2018-06-13 13:05:58 +03:00
) {
$order['customFields'][$arParams['customOrderProps'][$prop['ID'] . '#' . $prop['CODE']]] = RCrmActions::convertCmsFieldToCrmValue($prop['VALUE'][0], $prop['TYPE']);
} elseif (is_array($arParams['optionsOrderProps'][$arOrder['PERSON_TYPE_ID']])
&& $search = array_search($prop['CODE'], $arParams['optionsOrderProps'][$arOrder['PERSON_TYPE_ID']])) {//other
2021-09-08 10:19:29 +03:00
if (in_array($search, ['fio', 'phone', 'email'])) {//fio, phone, email
if ($search === 'fio') {
$order = array_merge($order, RCrmActions::explodeFio($prop['VALUE'][0]));//add fio fields
2021-09-08 10:19:29 +03:00
} elseif ($search === 'email' && mb_strlen($prop['VALUE'][0]) > 100) {
2020-12-22 13:03:32 +03:00
continue;
2016-09-15 16:42:10 +03:00
} else {
// ignoring a property with a non-set group if the field value is already set
if (!empty($order[$search]) && $prop['PROPS_GROUP_ID'] == 0) {
continue;
}
2017-09-04 11:36:04 +03:00
$order[$search] = $prop['VALUE'][0];//phone, email
2016-09-15 16:42:10 +03:00
}
} else {
if ($prop['TYPE'] === 'LOCATION' && isset($prop['VALUE'][0]) && $prop['VALUE'][0] != '') {
$arLoc = LocationTable::getByCode($prop['VALUE'][0])->fetch();
if ($arLoc) {
$deliveryLocation = CSaleLocation::GetByID($arLoc['ID']);
$order['delivery']['address']['region'] = $deliveryLocation['REGION_NAME'] ?? '';
$city = $deliveryLocation['CITY_NAME'] ?? null;
if (count($countryList) > 0 && isset($countryList[$deliveryLocation['COUNTRY_NAME']])) {
$order['countryIso'] = $countryList[$deliveryLocation['COUNTRY_NAME']];
}
}
$prop['VALUE'][0] = null;
}
if (!empty($prop['VALUE'][0])) {
$order['delivery']['address'][$search] = $prop['VALUE'][0];
}
}
}
}
//Перезапись города при его наличии в свойстве типа LOCATION
if (isset($city)) {
$order['delivery']['address']['city'] = $city;
}
// Пункт самовывоза
$pickupPointAddress = '';
if (RetailcrmConfigProvider::needSendPickupPointAddress() === 'Y') {
$pickupPointAddress = BitrixOrderService::getPickupPointAddress($arOrder);
}
if ($pickupPointAddress !== '') {
$order['delivery']['address']['text'] = $pickupPointAddress;
2016-09-15 16:42:10 +03:00
}
//Deliverys
if (array_key_exists($arOrder['DELIVERYS'][0]['id'], $arParams['optionsDelivTypes'])) {
$order['delivery']['code'] = $arParams['optionsDelivTypes'][$arOrder['DELIVERYS'][0]['id']];
if (isset($arOrder['DELIVERYS'][0]['service']) && $arOrder['DELIVERYS'][0]['service'] != '') {
$order['delivery']['service']['code'] = $arOrder['DELIVERYS'][0]['service'];
2016-09-15 16:42:10 +03:00
}
}
2018-02-27 15:29:43 +03:00
$weight = 0;
$width = 0;
$height = 0;
$length = 0;
2021-09-08 10:19:29 +03:00
if ('ordersEdit' === $methodApi) {
$response = RCrmActions::apiMethod($api, 'ordersGet', __METHOD__, $order['externalId'], $site);
if (isset($response['order'])) {
2019-12-24 15:41:12 +03:00
foreach ($response['order']['items'] as $k => $item) {
$externalId = $k .'_'. $item['offer']['externalId'];
2019-12-24 15:41:12 +03:00
$orderItems[$externalId] = $item;
}
}
}
2017-09-04 11:36:04 +03:00
//basket
foreach ($arOrder['BASKET'] as $position => $product) {
$itemId = null;
2021-09-08 10:19:29 +03:00
$externalId = $position . '_' . $product['PRODUCT_ID'];
2019-12-24 15:41:12 +03:00
if (isset($orderItems[$externalId])) { //update
$externalIds = $orderItems[$externalId]['externalIds'];
2020-04-30 11:56:43 +03:00
$itemId = $orderItems[$externalId]['id'];
$key = null;
$keyBasketId = null;
if (is_array($externalIds)) {
$key = array_search('bitrix', array_column($externalIds, 'code'));
$keyBasketId = array_search('bitrixBasketId', array_column($externalIds, 'code'));
}
if (isset($externalIds[$key]['code']) && $externalIds[$key]['code'] === 'bitrix') {
2021-09-08 10:19:29 +03:00
$externalIds[$key] = [
2019-12-24 15:41:12 +03:00
'code' => 'bitrix',
'value' => $externalId,
2021-09-08 10:19:29 +03:00
];
2019-12-24 15:41:12 +03:00
} else {
2021-09-08 10:19:29 +03:00
$externalIds[] = [
2019-12-24 15:41:12 +03:00
'code' => 'bitrix',
'value' => $externalId,
2021-09-08 10:19:29 +03:00
];
}
if (isset($externalIds[$keyBasketId]['code'])
&& $externalIds[$keyBasketId]['code'] === 'bitrixBasketId'
) {
$externalIds[$keyBasketId] = [
'code' => 'bitrixBasketId',
'value' => $product['ID'] . '#' . $externalId,
];
} else {
$externalIds[] = [
'code' => 'bitrixBasketId',
'value' => $product['ID'] . '#' . $externalId,
];
}
} else { //create
2021-09-08 10:19:29 +03:00
$externalIds = [
[
2019-12-24 15:41:12 +03:00
'code' => 'bitrix',
'value' => $externalId,
],
[
'code' => 'bitrixBasketId',
'value' => $product['ID'] . '#' . $externalId,
],
2021-09-08 10:19:29 +03:00
];
}
$item = [
'externalIds' => $externalIds,
'quantity' => $product['QUANTITY'],
'offer' => [
'externalId' => $product['PRODUCT_ID'],
'xmlId' => $product['PRODUCT_XML_ID'],
],
'productName' => $product['NAME'],
];
2016-09-15 16:42:10 +03:00
2020-04-30 11:56:43 +03:00
if (isset($itemId)) {
$item['id'] = $itemId;
}
2021-09-08 10:19:29 +03:00
$catalogProduct = CCatalogProduct::GetByID($product['PRODUCT_ID']);
2021-09-08 10:19:29 +03:00
if (is_null($catalogProduct['PURCHASING_PRICE']) === false) {
if ($catalogProduct['PURCHASING_CURRENCY'] && $currency != $catalogProduct['PURCHASING_CURRENCY']) {
2018-12-26 11:41:06 +03:00
$purchasePrice = CCurrencyRates::ConvertCurrency(
2021-09-08 10:19:29 +03:00
(double) $catalogProduct['PURCHASING_PRICE'],
$catalogProduct['PURCHASING_CURRENCY'],
2018-12-26 11:41:06 +03:00
$currency
);
} else {
2021-09-08 10:19:29 +03:00
$purchasePrice = $catalogProduct['PURCHASING_PRICE'];
2018-12-26 11:41:06 +03:00
}
$item['purchasePrice'] = $purchasePrice;
2016-09-15 16:42:10 +03:00
}
2018-07-16 16:01:19 +03:00
$discount = (double) $product['DISCOUNT_PRICE'];
$dpItem = $product['BASE_PRICE'] - $product['PRICE'];
if ( $dpItem > 0 && $discount <= 0) {
$discount = $dpItem;
}
2017-09-04 11:36:04 +03:00
$item['discountManualPercent'] = 0;
$item['initialPrice'] = (double) $product['BASE_PRICE'];
if (
$product['BASE_PRICE'] >= $product['PRICE']
&& $methodApi === 'ordersEdit'
&& ConfigProvider::getLoyaltyProgramStatus() === 'Y'
) {
/** @var LoyaltyService $service */
$service = ServiceLocator::get(LoyaltyService::class);
$item['discountManualAmount'] = $service->getInitialDiscount((int) $product['ID']) ?? $discount;
} elseif ($product['BASE_PRICE'] >= $product['PRICE']) {
2021-05-31 11:14:02 +03:00
$item['discountManualAmount'] = self::getDiscountManualAmount($product);
$item['initialPrice'] = (double) $product['BASE_PRICE'];
$order['discountManualAmount'] = 0;
$order['discountManualPercent'] = 0;
2021-05-31 11:14:02 +03:00
} else {
$item['discountManualAmount'] = 0;
$item['initialPrice'] = $product['PRICE'];
}
2016-09-15 16:42:10 +03:00
if (
!empty($product['VAT_INCLUDED'])
&& $product['VAT_INCLUDED'] === 'Y'
&& RetailcrmConfigProvider::getOrderVat() === 'Y'
) {
$item['vatRate'] = $product['VAT_RATE'] * 100;
}
2016-09-15 16:42:10 +03:00
$order['items'][] = $item;
2018-02-27 15:29:43 +03:00
2021-09-08 10:19:29 +03:00
if ($send && $dimensionsSetting === 'Y') {
2018-03-22 16:11:04 +03:00
$dimensions = RCrmActions::unserializeArrayRecursive($product['DIMENSIONS']);
2018-07-16 16:01:19 +03:00
if ($dimensions !== false) {
$width += $dimensions['WIDTH'];
$height += $dimensions['HEIGHT'];
$length += $dimensions['LENGTH'];
2018-11-02 16:51:13 +03:00
$weight += $product['WEIGHT'] * $product['QUANTITY'];
2018-07-16 16:01:19 +03:00
}
2018-03-22 16:11:04 +03:00
}
2016-09-15 16:42:10 +03:00
}
2018-02-27 15:29:43 +03:00
2021-09-08 10:19:29 +03:00
if ($send && $dimensionsSetting === 'Y') {
2018-03-22 16:11:04 +03:00
$order['width'] = $width;
$order['height'] = $height;
$order['length'] = $length;
$order['weight'] = $weight;
}
2018-02-27 15:29:43 +03:00
2017-09-04 11:36:04 +03:00
//payments
$payments = [];
foreach ($arOrder['PAYMENTS'] as $payment) {
if (!empty($payment['PAY_SYSTEM_ID']) && isset($arParams['optionsPayTypes'][$payment['PAY_SYSTEM_ID']])) {
$crmPayment = [];
if (!empty($payment['DATE_PAID'])) {
$crmPayment['paidAt'] = new \DateTime($payment['DATE_PAID']);
}
if (!empty($arParams['optionsPayment'][$payment['PAID']])) {
$crmPayment['status'] = $arParams['optionsPayment'][$payment['PAID']];
}
if (!empty($payment['ID'])) {
$crmPayment['externalId'] = RCrmActions::generatePaymentExternalId($payment['ID']);
}
if (RetailcrmConfigProvider::shouldSendPaymentAmount()) {
$crmPayment['amount'] = $payment['SUM'];
}
$crmPayment = RetailCrmService::preparePayment($crmPayment, $payment, $arParams['optionsPayTypes']);
$payments[] = $crmPayment;
} else {
2018-10-04 16:28:14 +03:00
RCrmActions::eventLog(
'RetailCrmOrder::orderSend',
'payments',
'OrderID = ' . $arOrder['ID'] . '. Payment not found.'
2018-10-04 16:28:14 +03:00
);
2017-09-04 11:36:04 +03:00
}
}
2017-09-04 11:36:04 +03:00
if (count($payments) > 0) {
$order['payments'] = $payments;
}
2018-10-04 16:28:14 +03:00
2017-09-04 11:36:04 +03:00
//send
2016-09-15 16:42:10 +03:00
if (function_exists('retailCrmBeforeOrderSend')) {
$newResOrder = retailCrmBeforeOrderSend($order, $arOrder);
2016-09-15 16:42:10 +03:00
if (is_array($newResOrder) && !empty($newResOrder)) {
$order = $newResOrder;
2017-09-04 11:36:04 +03:00
} elseif ($newResOrder === false) {
2018-10-04 16:28:14 +03:00
RCrmActions::eventLog(
'RetailCrmOrder::orderSend',
'retailCrmBeforeOrderSend()',
'OrderID = ' . $arOrder['ID'] . '. Sending canceled after retailCrmBeforeOrderSend'
2018-10-04 16:28:14 +03:00
);
2017-11-13 11:05:11 +03:00
2017-09-04 11:36:04 +03:00
return false;
2016-09-15 16:42:10 +03:00
}
}
if ('ordersEdit' === $methodApi) {
$order = RetailCrmService::unsetIntegrationDeliveryFields($order);
}
2016-09-15 16:42:10 +03:00
$normalizer = new RestNormalizer();
$order = $normalizer->normalize($order, 'orders');
2016-09-15 16:42:10 +03:00
2020-04-24 13:18:18 +03:00
Logger::getInstance()->write($order, 'orderSend');
2016-09-15 16:42:10 +03:00
/** @var ClientAdapter $client */
$client = ClientFactory::createClientAdapter();
$userId = $arOrder['USER_ID'];
$arUser = UserTable::getById($userId)->fetch();
// Check and set privilegeType
$order['privilegeType'] = LoyaltyAccountService::getPrivilegeType($client, $userId, $arParams);
$fioCrm = [$order['firstName'] ?? null, $order['lastName'] ?? null, $order['patronymic'] ?? null];
if (!empty($arUser['NAME']) && in_array($arUser['NAME'], $fioCrm)) {
$order['firstName'] = $arUser['NAME'];
}
if (!empty($arUser['LAST_NAME']) && in_array($arUser['LAST_NAME'], $fioCrm)) {
$order['lastName'] = $arUser['LAST_NAME'];
}
if ($send) {
if ($methodApi === 'ordersCreate') {
if (isset($arParams['customerCorporate']) && !empty($order['contact']['externalId'])) {
$externalId = $order['contact']['externalId'];
} else {
$externalId = $order['customer']['externalId'];
}
if ($site === null) {
$site = RetailcrmConfigProvider::getSitesAvailable();
}
$crmBasket = RCrmActions::apiMethod($api, 'cartGet', __METHOD__, $externalId, $site);
$orderResponse = $client->createOrder($order, $site);
if ($orderResponse instanceof OrdersCreateResponse && !$orderResponse->success) {
Logger::getInstance()->write([
'methodApi' => 'orderCreate',
'errorMsg' => $orderResponse->errorMsg ?? '',
'errors' => $orderResponse->errors ?? '',
'params' => ['number' => $order['number'], 'externalId' => $order['externalId']]
], 'apiErrors');
}
if (!empty($crmBasket['cart']) && $orderResponse instanceof OrdersCreateResponse && !empty($orderResponse->id) ) {
RCrmActions::apiMethod(
$api,
'cartClear',
__METHOD__,
[
'clearedAt' => date('Y-m-d H:i:sP'),
'customer' => [
'externalId' => $externalId
],
'order' => [
'id' => $orderResponse->id
]
],
$site
);
}
return $orderResponse;
}
if ($methodApi === 'ordersEdit') {
return $client->editOrder($order, $site);
}
2016-09-15 16:42:10 +03:00
}
return $order;
}
2018-10-04 16:28:14 +03:00
2016-09-15 16:42:10 +03:00
/**
* Mass order uploading, without repeating; always returns true, but writes error log
*
* @param int $pSize
* @param bool $failed -- flag to export failed orders
* @param array|null $orderList
*
* @return bool
* @throws \Bitrix\Main\ArgumentException
* @throws \Bitrix\Main\ArgumentNullException
* @throws \Bitrix\Main\ObjectPropertyException
* @throws \Bitrix\Main\SystemException
2016-09-15 16:42:10 +03:00
*/
public static function uploadOrders(int $pSize = 50, bool $failed = false, array $orderList = []): bool
2016-10-04 17:57:39 +03:00
{
2020-04-24 13:18:18 +03:00
if (!RetailcrmDependencyLoader::loadDependencies()) {
2016-09-15 16:42:10 +03:00
return true;
}
2021-07-08 16:29:34 +03:00
$ordersPack = [];
$resCustomers = [];
$resCustomersAdded = [];
$resCustomersCorporate = [];
$orderIds = [];
2016-09-15 16:42:10 +03:00
2020-04-24 13:18:18 +03:00
$lastUpOrderId = RetailcrmConfigProvider::getLastOrderId();
$failedIds = RetailcrmConfigProvider::getFailedOrdersIds();
2016-09-15 16:42:10 +03:00
if ($failed == true && $failedIds !== false && count($failedIds) > 0) {
$orderIds = $failedIds;
} elseif (count($orderList) > 0) {
2016-09-15 16:42:10 +03:00
$orderIds = $orderList;
} else {
$dbOrder = OrderTable::GetList([
'order' => ['ID' => 'ASC'],
'filter' => ['>ID' => $lastUpOrderId],
'limit' => $pSize,
'select' => ['ID'],
]);
2020-04-24 13:18:18 +03:00
2016-10-04 17:57:39 +03:00
while ($arOrder = $dbOrder->fetch()) {
2016-09-15 16:42:10 +03:00
$orderIds[] = $arOrder['ID'];
}
}
2017-09-04 11:36:04 +03:00
if (count($orderIds) <= 0) {
2016-09-15 16:42:10 +03:00
return false;
}
2020-04-24 13:18:18 +03:00
$optionsOrderTypes = RetailcrmConfigProvider::getOrderTypes();
$optionsDelivTypes = RetailcrmConfigProvider::getDeliveryTypes();
$optionsPayTypes = RetailcrmConfigProvider::getPaymentTypes();
$optionsPayStatuses = RetailcrmConfigProvider::getPaymentStatuses(); // --statuses
$optionsPayment = RetailcrmConfigProvider::getPayment();
$optionsOrderProps = RetailcrmConfigProvider::getOrderProps();
$optionsLegalDetails = RetailcrmConfigProvider::getLegalDetails();
$optionsContragentType = RetailcrmConfigProvider::getContragentTypes();
$optionsCustomFields = RetailcrmConfigProvider::getCustomFields();
2021-09-08 10:19:29 +03:00
$api = new ApiClient(RetailcrmConfigProvider::getApiUrl(), RetailcrmConfigProvider::getApiKey());
2016-09-15 16:42:10 +03:00
2021-09-08 10:19:29 +03:00
$arParams = [
2016-09-15 16:42:10 +03:00
'optionsOrderTypes' => $optionsOrderTypes,
'optionsDelivTypes' => $optionsDelivTypes,
'optionsPayTypes' => $optionsPayTypes,
'optionsPayStatuses' => $optionsPayStatuses,
'optionsPayment' => $optionsPayment,
'optionsOrderProps' => $optionsOrderProps,
'optionsLegalDetails' => $optionsLegalDetails,
'optionsContragentType' => $optionsContragentType,
2021-09-08 10:19:29 +03:00
'optionsSitesList' => RetailcrmConfigProvider::getSitesList(),
2016-09-15 16:42:10 +03:00
'optionsCustomFields' => $optionsCustomFields,
'customOrderProps' => RetailcrmConfigProvider::getMatchedOrderProps(),
2021-09-08 10:19:29 +03:00
];
2016-09-15 16:42:10 +03:00
2021-09-08 10:19:29 +03:00
$recOrders = [];
2020-04-24 13:18:18 +03:00
2016-10-04 17:57:39 +03:00
foreach ($orderIds as $orderId) {
2021-09-08 10:19:29 +03:00
$bitrixOrder = Order::load($orderId);
2020-04-24 13:18:18 +03:00
2021-09-08 10:19:29 +03:00
if (!$bitrixOrder) {
2016-09-15 16:42:10 +03:00
continue;
}
2020-04-24 13:18:18 +03:00
2021-07-08 16:29:34 +03:00
$arCustomer = [];
$arCustomerCorporate = [];
2021-09-08 10:19:29 +03:00
$order = self::orderObjToArr($bitrixOrder);
$site = self::getCrmShopCodeByLid($order['LID'], $arParams['optionsSitesList']);
2020-04-24 13:18:18 +03:00
2021-09-08 10:19:29 +03:00
if (null === $site && count($arParams['optionsSitesList']) > 0) {
2020-04-24 13:18:18 +03:00
continue;
}
if (empty($order['USER_ID'])) {
RCrmActions::eventLog(
'RetailCrmOrder::uploadOrders',
'Order::load',
'The user does not exist in order: ' . $order['ID']
);
continue;
}
2021-07-08 16:29:34 +03:00
self::createCustomerForOrder($api, $arCustomer, $arCustomerCorporate,$arParams, $order, $site);
2017-09-04 11:36:04 +03:00
if (isset($order['RESPONSIBLE_ID']) && !empty($order['RESPONSIBLE_ID'])) {
$managerService = ManagerService::getInstance();
$arParams['managerId'] = $managerService->getManagerCrmId((int) $order['RESPONSIBLE_ID']);
}
$arOrders = self::orderSend($order, $api, $arParams, false, $site,'ordersCreate');
2016-09-15 16:42:10 +03:00
2020-04-24 13:18:18 +03:00
if (!$arCustomer || !$arOrders) {
2016-09-15 16:42:10 +03:00
continue;
}
2018-10-04 16:28:14 +03:00
2020-04-24 13:18:18 +03:00
if (!empty($arCustomerCorporate) && !empty($arCustomerCorporate['nickName'])) {
$resCustomersCorporate[$arCustomerCorporate['nickName']] = $arCustomerCorporate;
}
if (
array_key_exists('externalId', $arCustomer)
&& !in_array($arCustomer['externalId'], $resCustomersAdded, true)
) {
$resCustomersAdded[] = $arCustomer['externalId'];
2020-04-24 13:18:18 +03:00
$resCustomers[$order['LID']][] = $arCustomer;
}
2021-07-08 16:29:34 +03:00
$ordersPack[$order['LID']][] = $arOrders;
2016-09-15 16:42:10 +03:00
$recOrders[] = $orderId;
}
2018-10-04 16:28:14 +03:00
2021-07-08 16:29:34 +03:00
if (count($ordersPack) > 0) {
2021-09-08 10:19:29 +03:00
if (false === RetailCrmOrder::uploadCustomersList($resCustomers, $api, $arParams['optionsSitesList'])) {
2020-04-24 13:18:18 +03:00
return false;
2016-09-15 16:42:10 +03:00
}
2020-04-24 13:18:18 +03:00
if ('Y' === RetailcrmConfigProvider::getCorporateClientStatus()) {
2021-07-08 16:29:34 +03:00
$cachedCorporateIds = [];
foreach ($ordersPack as $lid => $lidOrdersList) {
$site = self::getCrmShopCodeByLid($lid, $arParams['optionsSitesList']);
2021-07-08 16:29:34 +03:00
foreach ($lidOrdersList as $key => $orderData) {
$lidOrdersList[$key] = self::addCorporateCustomerToOrder(
$orderData,
$api,
$resCustomersCorporate,
$cachedCorporateIds,
$site
2021-07-08 16:29:34 +03:00
);
2017-11-13 11:05:11 +03:00
}
2020-04-24 13:18:18 +03:00
2021-07-08 16:29:34 +03:00
$ordersPack[$lid] = $lidOrdersList;
2016-09-15 16:42:10 +03:00
}
}
2020-04-24 13:18:18 +03:00
2021-09-08 10:19:29 +03:00
if (false === RetailCrmOrder::uploadOrdersList($ordersPack, $api, $arParams['optionsSitesList'])) {
2020-04-24 13:18:18 +03:00
return false;
}
2016-09-15 16:42:10 +03:00
if ($failed == true && $failedIds !== false && count($failedIds) > 0) {
2020-04-24 13:18:18 +03:00
RetailcrmConfigProvider::setFailedOrdersIds(array_diff($failedIds, $recOrders));
} elseif (count($orderList) === 0 && $lastUpOrderId < max($recOrders)) {
2020-04-24 13:18:18 +03:00
RetailcrmConfigProvider::setLastOrderId(max($recOrders));
2016-09-15 16:42:10 +03:00
}
}
return true;
}
2018-02-27 15:29:43 +03:00
2021-07-08 16:29:34 +03:00
/**
* @param \RetailCrm\ApiClient $api
* @param array $arCustomer
* @param array $arCustomerCorporate
* @param array $arParams
* @param array $order
* @param $site
*
* @throws \Bitrix\Main\ArgumentException
* @throws \Bitrix\Main\ObjectPropertyException
* @throws \Bitrix\Main\SystemException
* @throws \Exception
2021-07-08 16:29:34 +03:00
*/
public static function createCustomerForOrder(
ApiClient $api,
array &$arCustomer,
array &$arCustomerCorporate,
array &$arParams,
array $order,
$site
): void {
$optionsContragentType = RetailcrmConfigProvider::getContragentTypes();
$user = UserTable::getById($order['USER_ID'])->fetch();
if (!$user) {
RCrmActions::eventLog(
'RetailCrmOrder::createCustomerForOrder',
'UserTable::getById',
'Error find user: ' . $order['USER_ID'] . ' in order: ' . $order['ID']
);
return;
}
2021-07-08 16:29:34 +03:00
if ('Y' === RetailcrmConfigProvider::getCorporateClientStatus()) {
if (true === RetailCrmCorporateClient::isCorpTookExternalId((string) $user['ID'], $api, $site)) {
RetailCrmCorporateClient::setPrefixForExternalId((string) $user['ID'], $api, $site);
2021-07-08 16:29:34 +03:00
}
}
if (
'Y' === RetailcrmConfigProvider::getCorporateClientStatus()
&& in_array($optionsContragentType[$order['PERSON_TYPE_ID']], ['legal-entity', 'enterpreneur'])
2021-07-08 16:29:34 +03:00
) {
// TODO check if order is corporate, and if it IS - make corporate order
$arCustomer = RetailCrmUser::customerSend(
$user,
$api,
'individual',
false,
$site
);
$arCustomerCorporate = RetailCrmCorporateClient::clientSend(
$order,
$api,
$optionsContragentType[$order['PERSON_TYPE_ID']],
2021-07-08 16:29:34 +03:00
false,
true,
$site
);
$arParams['orderCompany'] = isset($arCustomerCorporate['companies'])
? reset($arCustomerCorporate['companies'])
: null;
$arParams['contactExId'] = $user['ID'];
return;
}
$arCustomer = RetailCrmUser::customerSend(
$user,
$api,
$optionsContragentType[$order['PERSON_TYPE_ID']],
false,
$site
);
if (isset($arParams['contactExId'])) {
unset($arParams['contactExId']);
}
}
/**
* @param array $orderData
* @param \RetailCrm\ApiClient $api
* @param array $resCustomersCorporate
* @param array $cachedCorporateIds
*
* @return array
*/
public static function addCorporateCustomerToOrder(
array $orderData,
ApiClient $api,
array $resCustomersCorporate,
array &$cachedCorporateIds,
$site = null
2021-07-08 16:29:34 +03:00
): array {
$customerLegalName = $orderData['contragent']['legalName'];
if (
isset($orderData['contragent']['contragentType'])
&& in_array($orderData['contragent']['contragentType'], ['legal-entity', 'enterpreneur'])
2021-07-08 16:29:34 +03:00
&& !empty($customerLegalName)
) {
if (isset($cachedCorporateIds[$customerLegalName])) {
$orderData['customer'] = ['id' => $cachedCorporateIds[$customerLegalName]];
} else {
$corpListResponse = $api->customersCorporateList(['nickName' => [$customerLegalName]]);
if (
$corpListResponse
&& $corpListResponse->isSuccessful()
&& $corpListResponse->offsetExists('customersCorporate')
&& !empty($corpListResponse['customersCorporate'])
) {
$corpListResponse = $corpListResponse['customersCorporate'];
$corpListResponse = reset($corpListResponse);
$orderData['customer'] = ['id' => $corpListResponse['id']];
$cachedCorporateIds[$customerLegalName] = $corpListResponse['id'];
RetailCrmCorporateClient::addCustomersCorporateAddresses(
$orderData['customer']['id'],
$customerLegalName,
$orderData['delivery']['address']['text'],
$api,
null
2021-07-08 16:29:34 +03:00
);
} elseif (array_key_exists($customerLegalName, $resCustomersCorporate)) {
$createResponse = $api->customersCorporateCreate(
$resCustomersCorporate[$customerLegalName],
$site
2021-07-08 16:29:34 +03:00
);
if ($createResponse && $createResponse->isSuccessful()) {
$orderData['customer'] = ['id' => $createResponse['id']];
$cachedCorporateIds[$customerLegalName] = $createResponse['id'];
}
}
time_nanosleep(0, 250000000);
}
}
return $orderData;
}
/**
* @param array $resCustomers
* @param RetailCrm\ApiClient $api
* @param array $optionsSitesList
*
* @return array|false
*/
2021-09-08 10:19:29 +03:00
public static function uploadCustomersList(array $resCustomers, ApiClient $api, array $optionsSitesList)
{
2021-09-08 10:19:29 +03:00
return self::uploadItems(
$resCustomers,
'customersUpload',
'uploadedCustomers',
$api,
$optionsSitesList
);
}
/**
* @param array $resOrders
* @param RetailCrm\ApiClient $api
* @param array $optionsSitesList
*
* @return array|false
*/
2021-09-08 10:19:29 +03:00
public static function uploadOrdersList(array $resOrders, ApiClient $api, array $optionsSitesList)
{
2021-09-08 10:19:29 +03:00
return self::uploadItems(
$resOrders,
'ordersUpload',
'uploadedOrders',
$api,
$optionsSitesList
);
}
/**
2021-09-08 10:19:29 +03:00
* @param string $orderLid
* @param array $optionsSitesList
*
2021-09-08 10:19:29 +03:00
* @return string|null
*/
2021-09-08 10:19:29 +03:00
public static function getCrmShopCodeByLid(string $orderLid, array $optionsSitesList): ?string
{
2021-09-08 10:19:29 +03:00
return $optionsSitesList[$orderLid] ?? null;
}
/**
2021-09-08 10:19:29 +03:00
* @param array $pack
* @param string $method
* @param string $keyResponse
* @param RetailCrm\ApiClient $api
2021-09-08 10:19:29 +03:00
* @param array $optionsSitesList
*
* @return array|false
*/
2021-09-08 10:19:29 +03:00
public static function uploadItems(
array $pack,
string $method,
string $keyResponse,
ApiClient $api,
array $optionsSitesList
) {
$uploaded = [];
$sizePack = 50;
foreach ($pack as $key => $itemLoad) {
2021-09-08 10:19:29 +03:00
$site = self::getCrmShopCodeByLid($key, $optionsSitesList);
2021-09-08 10:19:29 +03:00
if (null === $site && count($optionsSitesList) > 0) {
continue;
}
$chunkList = array_chunk($itemLoad, $sizePack, true);
foreach ($chunkList as $chunk) {
time_nanosleep(0, 250000000);
/** @var \RetailCrm\Response\ApiResponse|bool $response */
$response = RCrmActions::apiMethod(
$api,
$method,
__METHOD__,
$chunk,
$site
);
if ($response === false) {
return false;
}
2021-09-08 10:19:29 +03:00
if (($response instanceof ApiResponse) && $response->offsetExists($keyResponse)) {
$uploaded = array_merge($uploaded, $response[$keyResponse]);
}
}
}
return $uploaded;
}
2020-04-24 13:18:18 +03:00
/**
* Returns true if provided order array is corporate order data
*
* @param array|\ArrayAccess $order
*
* @return bool
*/
2021-07-08 16:29:34 +03:00
public static function isOrderCorporate($order): bool
2020-04-24 13:18:18 +03:00
{
2021-09-08 10:19:29 +03:00
return isset($order['customer'], $order['customer']['type'])
&& (is_array($order) || $order instanceof ArrayAccess)
2021-07-08 16:29:34 +03:00
&& $order['customer']['type'] === 'customer_corporate';
2020-04-24 13:18:18 +03:00
}
/**
* Converts order object to array
*
* @param \Bitrix\Sale\Order $obOrder
*
* @return array
* @throws \Bitrix\Main\SystemException
*/
public static function orderObjToArr(Order $obOrder): array
2016-10-04 17:57:39 +03:00
{
$culture = new Culture(['FORMAT_DATETIME' => 'Y-m-d HH:i:s']);
$arOrder = [
2016-09-15 16:42:10 +03:00
'ID' => $obOrder->getId(),
'NUMBER' => $obOrder->getField('ACCOUNT_NUMBER'),
'LID' => $obOrder->getSiteId(),
2018-10-04 16:28:14 +03:00
'DATE_INSERT' => $obOrder->getDateInsert()->toString($culture),
2016-09-15 16:42:10 +03:00
'STATUS_ID' => $obOrder->getField('STATUS_ID'),
'USER_ID' => $obOrder->getUserId(),
'PERSON_TYPE_ID' => $obOrder->getPersonTypeId(),
'CURRENCY' => $obOrder->getCurrency(),
'PAYMENTS' => [],
'DELIVERYS' => [],
2016-09-15 16:42:10 +03:00
'PRICE_DELIVERY' => $obOrder->getDeliveryPrice(),
'PROPS' => $obOrder->getPropertyCollection()->getArray(),
'DISCOUNTS' => $obOrder->getDiscount()->getApplyResult(),
'BASKET' => [],
2016-09-15 16:42:10 +03:00
'USER_DESCRIPTION' => $obOrder->getField('USER_DESCRIPTION'),
'COMMENTS' => $obOrder->getField('COMMENTS'),
'REASON_CANCELED' => $obOrder->getField('REASON_CANCELED'),
'RESPONSIBLE_ID' => $obOrder->getField('RESPONSIBLE_ID'),
];
2018-02-27 15:29:43 +03:00
2016-09-15 16:42:10 +03:00
$shipmentList = $obOrder->getShipmentCollection();
2020-04-24 13:18:18 +03:00
2016-10-04 17:57:39 +03:00
foreach ($shipmentList as $shipmentData) {
2018-06-13 13:05:58 +03:00
if ($shipmentData->isSystem()) {
continue;
}
2016-10-04 17:57:39 +03:00
if ($shipmentData->getDeliveryId()) {
$delivery = Manager::getById($shipmentData->getDeliveryId());
$siteDeliverys = RCrmActions::DeliveryList();
foreach ($siteDeliverys as $siteDelivery) {
if ($siteDelivery['ID'] == $delivery['ID'] && $siteDelivery['PARENT_ID'] == 0) {
unset($delivery['PARENT_ID']);
}
}
2016-10-04 17:57:39 +03:00
if ($delivery['PARENT_ID']) {
$service = explode(':', $delivery['CODE']);
$shipment = ['id' => $delivery['PARENT_ID'], 'service' => $service[1]];
2016-10-04 17:57:39 +03:00
} else {
$shipment = ['id' => $delivery['ID']];
2016-09-15 16:42:10 +03:00
}
$arOrder['DELIVERYS'][] = $shipment;
}
}
2018-02-27 15:29:43 +03:00
2017-09-04 11:36:04 +03:00
$paymentList = $obOrder->getPaymentCollection();
2020-04-24 13:18:18 +03:00
2017-09-04 11:36:04 +03:00
foreach ($paymentList as $paymentData) {
$arOrder['PAYMENTS'][] = $paymentData->getFields()->getValues();
}
2016-09-15 16:42:10 +03:00
$basketItems = $obOrder->getBasket();
2020-04-24 13:18:18 +03:00
2016-10-04 17:57:39 +03:00
foreach ($basketItems as $item) {
2016-09-15 16:42:10 +03:00
$arOrder['BASKET'][] = $item->getFields();
}
2018-02-27 15:29:43 +03:00
2016-09-15 16:42:10 +03:00
return $arOrder;
}
2021-05-31 11:14:02 +03:00
/**
* @param \Bitrix\Sale\Internals\Fields $product
*
* @return float
*/
public static function getDiscountManualAmount(Fields $product): float
{
if ($product->get('CUSTOM_PRICE') === 'Y') {
$sumDifference = $product->get('BASE_PRICE') - $product->get('PRICE');
return $sumDifference > 0 ? $sumDifference : 0.0;
}
2021-05-31 11:14:02 +03:00
$discount = (double) $product->get('DISCOUNT_PRICE');
$dpItem = $product->get('BASE_PRICE') - $product->get('PRICE');
2021-05-31 11:14:02 +03:00
if ($dpItem > 0 && $discount <= 0) {
return $dpItem;
}
2021-05-31 11:14:02 +03:00
return $discount;
}
2016-09-15 16:42:10 +03:00
}