403Webshell
Server IP : 80.87.202.40  /  Your IP : 216.73.216.169
Web Server : Apache
System : Linux rospirotorg.ru 5.14.0-539.el9.x86_64 #1 SMP PREEMPT_DYNAMIC Thu Dec 5 22:26:13 UTC 2024 x86_64
User : bitrix ( 600)
PHP Version : 8.2.27
Disable Function : NONE
MySQL : OFF |  cURL : ON |  WGET : ON |  Perl : ON |  Python : OFF |  Sudo : ON |  Pkexec : ON
Directory :  /home/bitrix/ext_www/rospirotorg.ru/bitrix/modules/wbs24.ozonapinew/lib/

Upload File :
current_dir [ Writeable] document_root [ Writeable]

 

Command :


[ Back ]     

Current File : /home/bitrix/ext_www/rospirotorg.ru/bitrix/modules/wbs24.ozonapinew/lib/Orders.php
<?php
namespace Wbs24\Ozonapinew;

use Bitrix\Main\SystemException;
use Bitrix\Main\Loader;
use Bitrix\Main\Localization\Loc;
use Bitrix\Main\Event;
use Bitrix\Main\EventResult;
use Bitrix\Sale\TradingPlatformTable;

// 02.11.2023
class Orders {
    use Exception; // trait

    protected const TRADING_PLATFORM_CODE = 'ozon_market';
    protected const OPTION_STATUSES_SUFFIX = '';

    protected $main;
    protected $moduleId;
    protected $wrappers;
    protected $Product;

    protected $xmlIdPrefix = 'OZON';
    protected $maxDuring = 30;
    protected $notLinkedProductId = 99999999;

    protected $siteId;
    protected $baseCurrency;
    protected $tradingPlatformCode;
    protected $deliveryServiceId;
    protected $paymentSystemId;
    protected $optionsOfCompletedStatuses = [];
    protected $userDescriptionTemplate;
    protected $templateFields = [
        '#SHIPMENT_ID#' => 'posting_number',
        '#CREATE_DATE#' => 'in_process_at',
    ];
    protected $changedCanBuyFlagProductIds = [];

    public function __construct($objects = [])
    {
        try {
            $this->main = $objects['Main'] ?? new Main();
            $this->moduleId = $this->main->getModuleId();
            $this->wrappers = new Wrappers($objects);

            if (!Loader::IncludeModule('sale')) {
                throw new SystemException("Sale module isn`t installed");
            }
            if (!Loader::IncludeModule('catalog')) {
                throw new SystemException("Catalog module isn`t installed");
            }
            if (!Loader::IncludeModule('iblock')) {
                throw new SystemException("Iblock module isn`t installed");
            }
            if (!Loader::IncludeModule('landing')) {
                throw new SystemException("Landing module isn`t installed");
            }

            $this->Product = $objects['Product'] ?? new Product($objects);
            $this->PackageRatio = $objects['PackageRatio'] ?? new PackageRatio($objects);
            $this->Db = $objects['Db'] ?? new Db($objects);

            $accountIndex = $this->wrappers->Option->getAccountIndex();
            $this->xmlIdPrefix .= ($accountIndex > 1 ? $accountIndex : '');

            $this->deadlineCreateOrdersHours = $this->wrappers->Option->get($this->moduleId, 'deadlineCreateOrdersHours');
            $this->expertMode = ($this->wrappers->Option->get($this->moduleId, 'expertMode') == 'Y');
            $this->siteId = $this->wrappers->Option->get($this->moduleId, 'siteId');
            $this->baseCurrency = \Bitrix\Currency\CurrencyManager::getBaseCurrency();
            $this->deliveryServiceId = intval($this->wrappers->Option->get($this->moduleId, 'deliveryServiceId'));
            $this->paymentSystemId = intval($this->wrappers->Option->get($this->moduleId, 'paymentSystemId'));
            $this->userDescriptionTemplate = $this->wrappers->Option->get($this->moduleId, 'userDescriptionTemplate');
            $this->notTransferCustomerInfoToOrder = ($this->wrappers->Option->get($this->moduleId, 'notTransferCustomerInfoToOrder') == 'Y');
            $this->allowCanBuyZero = ($this->wrappers->Option->get($this->moduleId, 'allowCanBuyZero') == 'Y');
            $this->recordShipmentDateWithTime = ($this->wrappers->Option->get($this->moduleId, 'recordShipmentDateWithTime') == 'Y');
            $this->verifyAndInstallTradingPlatform();
        } catch (SystemException $exception) {
            $this->exceptionHandler($exception);
        }
    }

    protected function verifyAndInstallTradingPlatform() {
        $result = TradingPlatformTable::getList([
            'filter' => [
                '=CODE' => self::TRADING_PLATFORM_CODE,
            ],
        ]);
        if (!$result->fetch()) {
            TradingPlatformTable::add([
                "CODE" => self::TRADING_PLATFORM_CODE,
                "NAME" => Loc::getMessage(strtoupper($this->moduleId).".TRADING_PLATFORM_NAME"),
                "ACTIVE" => "Y",
            ]);
        }
    }

    /**
     * Добавился параметр $ordersFromTradingPlatform, в котором передаются данные заказов с маркетплейса
     * Запрос к API вынесен в метод getOrders класса Api
     *
     * Вызов цепочки методов производится из класса Agents в методе getOrdersAgents
     *
     * Формат заказов:
     * $ordersFromTradingPlatform = [
     *     [
     *         'posting_number' => '123', // внешний номер заказа
     *         'shipment_date' => '2022-01-28T10:00:00Z', // планируемая дата отгрузки
     *         'products' => [
     *             [
     *                 'offer_id' => '456',
     *                 'name' => 'Product name',
     *                 'price' => 1000,
     *                 'discount_price' => 100, // опционально (если указано, то BASE_PRICE = price - discount_price)
     *                 'quantity' => 1,
     *             ],
     *         ],
     *     ],
     * ];
     */
    public function createNewOrders($ordersFromTradingPlatform)
    {
        $this->createReport('create_orders_log.txt', 'Start creating new orders');

        // проверить нет ли блокировки
        // если нет, поставить блокировку
        // если блокировка есть, прервать работу
        $started = ($this->wrappers->Option->get($this->moduleId, 'createOrdersStarted') == 'Y');
        if ($started) {
            $this->createReport('create_orders_log.txt', 'Creating of orders is blocked');
            $this->wrappers->Option->set($this->moduleId, 'createOrdersStarted', '');
            return;
        } else {
            $this->wrappers->Option->set($this->moduleId, 'createOrdersStarted', 'Y');
        }

        // начало выполнения скрипта по времени
        $startTime = time();

        $this->verifyAndConvertToTrueCharset($ordersFromTradingPlatform);

        foreach ($ordersFromTradingPlatform as $key => $resultOrder) {
            $this->createOrder($resultOrder);

            // Прерываем по таймеру
            if ((time() - $startTime) > $this->maxDuring) break;
        }

        // снимаем блокировку
        $this->wrappers->Option->set($this->moduleId, 'createOrdersStarted', '');
    }

    public function createOrder($resultOrder)
    {
        try {
            $success = false;
            $externalId = $resultOrder['posting_number'];
            $checkIs = $this->checkTheOrderForUniqueness($externalId);
            if ($checkIs) return $success;

            $userId = $this->getUserId();
            $eventResult = $this->callEvent('onBeforeCreateOrder', $resultOrder, $userId);
            if (!$eventResult) return $success;

            $order = $this->wrappers->Order->create($this->siteId, $userId);
            $order->setPersonTypeId(intval($this->wrappers->Option->get($this->moduleId, 'personTypeId')));
            $order->setField('XML_ID', $this->xmlIdPrefix.'_'.$externalId);

            $basket = $this->getBasket($order, $resultOrder['products']);
            $order->setBasket($basket);

            $this->createShipment($order, $basket, $resultOrder);
            $this->createPayment($order, $resultOrder);
            $this->initTradeBinding($order, $externalId);

            $shipmentDateTimestamp = strtotime($resultOrder['shipment_date']);

            $dateFormat = 'd.m.Y';
            if ($this->recordShipmentDateWithTime) {
                $dateFormat = 'd.m.Y H:i:s';
            }

            $shipmentDate = $shipmentDateTimestamp ? date($dateFormat, $shipmentDateTimestamp) : '';

            $orderPropertyValuesSetSuccess = $this->setOrderPropertyValues($order, [
                'shipmentDate' => $shipmentDate,
                'externalId' => $externalId,
                'createOrderDate' => $resultOrder['in_process_at'],
            ]);
            if (!$orderPropertyValuesSetSuccess) throw new SystemException("Order ${externalId} can`t be created because binding of properties is wrong");

            if (
                !empty($resultOrder['customer'])
                && !$this->notTransferCustomerInfoToOrder
            ) {
                $this->setCustomerData($order, $resultOrder['customer']);
            } else {
                $this->setDefaultCustomerData($order, $userId);
            }
            if (!empty($resultOrder['tracking_number'])) $this->setTrackNumber($order, $resultOrder['tracking_number']);
            $this->setUserDescription($order, $resultOrder);

            $eventResult = $this->callEvent('onBeforeSaveOrder', $resultOrder, $order);
            if (!$eventResult) return $success;

            $result = $order->save();
            if (!$result->isSuccess()) {
                $error = $result->getErrorMessages();
                $this->createReport('error_log.txt', $error);
            } else {
                // success
                $success = true;
                $this->createReport('create_orders_log.txt', 'Creating the order '.$externalId.' is success');

                // если включена опция, поменять дату создания заказа, в соотвествии с данными OZON
                if ($this->wrappers->Option->get($this->moduleId, 'useRealOrderDateCreating') == 'Y') {
                    $this->setOrderDateCreating($order->getId(), $resultOrder['in_process_at']);
                }
            }

            $this->returnBackChangesProductCanBuyFlags();

            return $success;
        } catch (SystemException $exception) {
            $this->exceptionHandler($exception);
        }
    }

    protected function setOrderDateCreating($orderId, $realDate)
    {
        if ($orderId && $realDate) {
            $realDateForDb = date('Y-m-d H:i:s', strtotime($realDate));
            $this->Db->query("UPDATE `b_sale_order` SET `DATE_INSERT` = '".$realDateForDb."' WHERE `ID` = ".$orderId);
        }
    }

    protected function verifyAndConvertToTrueCharset(&$array)
    {
        $charset = $this->getSiteCharset();

        if ($charset == 'windows-1251') {
            array_walk_recursive($array, function(&$item, $key) {
                $item = iconv('UTF-8', $charset, $item);
            });
        }
    }

    protected function getSiteCharset()
    {
        $charset = '';

        $result = \CSite::GetList(
            $by = "sort",
            $order="desc",
            ["LID" => $this->siteId]
        );
        if ($site = $result->fetch()) {
            $charset = $site['CHARSET'];
        }

        return $charset;
    }

    protected function getUserId()
    {
        $userId = intval($this->wrappers->Option->get($this->moduleId, 'userId'));
        if (!is_numeric($userId) || !$userId) $userId = 1;

        return $userId;
    }

    protected function getCustomerId()
    {
        $customerId = intval($this->wrappers->Option->get($this->moduleId, 'customerId'));
        if (!is_numeric($customerId) || !$customerId) $customerId = false;

        return $customerId;
    }

    protected function callEvent($eventName, &...$args)
    {
        $event = new Event($this->moduleId, $eventName, $args);
        $event->send();
        $eventResults = $event->getResults();
        $finalResult = true;

        foreach ($eventResults as $eventResult) {
            $eventParameters = $eventResult->getParameters();
            $disallowAction = $eventParameters['disallow'] ?: false;
            if ($disallowAction) $finalResult = false;
        }

        return $finalResult;
    }

    public function checkTheOrderForUniqueness($externalId)
    {
        return $this->getOrderIdByExternalId($externalId) ? true : false;
    }

    public function getOrderIdByExternalId($externalId)
    {
        $orderId = false;
        $orders = $this->wrappers->Order->getList([
            'select' => ['ID'],
            'filter' => [
                '=XML_ID' => $this->xmlIdPrefix.'_'.$externalId,
            ],
            'order' => ['ID' => 'DESC']
        ]);
        if ($orderInfo = $orders->fetch()) {
            $orderId = $orderInfo['ID'];
        }

        return $orderId;
    }

    protected function getBasket(&$order, $products)
    {
        $basket = \Bitrix\Sale\Basket::create($this->siteId);
        $this->addProductsToBasket($order, $basket, $products);

        return $basket;
    }

    protected function addProductsToBasket(&$order, &$basket, $products)
    {
        foreach ($products as $product) {
            $fields = $this->getProductFields($product);

            if (!$fields['CAN_BUY']) {
                $this->markOrderAsProblematic(
                    $order,
                    $fields,
                    $product
                );
                continue;
            }
            unset($fields['CAN_BUY']);

            $item = $basket->createItem("catalog", $fields['PRODUCT_ID']);
            unset($fields["PRODUCT_ID"]);
            $item->setFields($fields);
        }
    }

    protected function markOrderAsProblematic(&$order, $fields, $product)
    {
        $message = Loc::getMessage(strtoupper($this->moduleId).".ERROR_ADD_PRODUCT_TO_BASKET");
        $message = $this->replaceErrorMessage($message, $fields, $product['offer_id']);
        $code = str_replace('.', "_", $this->moduleId) . '_product_add_error_id_' . $fields['PRODUCT_ID'];
        $errorResult = new \Bitrix\Main\Error($message, $code);
        $result = new \Bitrix\Sale\Result();
        $result->addWarning($errorResult);
        \Bitrix\Sale\EntityMarker::addMarker($order, $order, $result);
    }

    protected function replaceErrorMessage($message, $fields, $offerId)
    {
        $patterns = [];
        $patterns[0] = '/#PRODUCT_ID#/';
        $patterns[1] = '/#OFFER_ID#/';

        $replacements = [];
        $replacements[0] = $fields['PRODUCT_ID'];
        $replacements[1] = is_array($offerId) ? implode(',', $offerId) : $offerId;

        return preg_replace($patterns, $replacements, $message);
    }

    protected function getProductFields($product)
    {
        $detail = $this->getProductDetail($product['offer_id']);
        $canBuy = $this->checkCanBuyProduct($detail);
        $fields = $this->getProductFieldsByDetailInfo($detail, $product);
        $fields['CAN_BUY'] = $canBuy;

        return $fields;
    }

    protected function checkCanBuyProduct($detail)
    {
        $canBuy = true;
        if (
            $detail
            && $detail['quantity_trace'] == 'Y'
            && $detail['can_buy_zero'] != 'Y'
            && !$detail['quantity']
        ) {
            $canBuy = false;
        }

        if (
            !$canBuy
            && $this->allowCanBuyZero
        ) {
            $productId = $detail['id'];
            $defaultCanBuyValue = $detail['can_buy_zero_raw'];

            $success = $this->updateProductCanBuyZero($productId, 'Y');
            if ($success) {
                $this->changedCanBuyFlagProductIds[$productId] = $defaultCanBuyValue;
                $canBuy = true;
            }
        }

        return $canBuy;
    }

    protected function updateProductCanBuyZero($productId, $flag)
    {
        return $this->wrappers->CCatalogProduct->Update(
            $productId,
            ['CAN_BUY_ZERO' => $flag]
        );
    }

    protected function returnBackChangesProductCanBuyFlags() {
        foreach ($this->changedCanBuyFlagProductIds as $productId => $defaultCanBuyValue) {
            $success = $this->updateProductCanBuyZero($productId, $defaultCanBuyValue);
            if (!$success) {
                $this->createReport(
                    'error_log.txt',
                    'error update product CAN_BUY_ZERO flag "'. $defaultCanBuyValue .'" for product_id = '.$productId
                );
            }
        }
        $this->changedCanBuyFlagProductIds = [];
    }

    protected function getProductDetail($offerId)
    {
        return $this->Product->getProductInfoByOfferId($offerId);
    }

    protected function getProductFieldsByDetailInfo($detailInfoAboutProduct, $product)
    {
        $product = $this->PackageRatio->calculatePriceAndQuantityWithPackageRatio($detailInfoAboutProduct, $product);

        $discountPrice = $product['discount_price'] ?? 0;
        $basePrice = $product['price'] - $discountPrice; // механизм не изменен вместе с обновлением класса

        $fields = [
            'PRODUCT_ID' => $detailInfoAboutProduct['id'] ?: $this->notLinkedProductId,
            'NAME' => $product['name'],
            'BASE_PRICE' => $basePrice, // механизм не изменен вместе с обновлением класса
            'DISCOUNT_PRICE' => $discountPrice,
            'PRICE' => $product['price'], // механизм не изменен вместе с обновлением класса
            'CURRENCY' => $this->baseCurrency,
            'QUANTITY' => $product['quantity'],
            'CUSTOM_PRICE' => 'Y',
            'LID' => $this->siteId,
            /* 'DIMENSIONS' => [
                "WIDTH" => $product['dimensions']['width'],
                "HEIGHT" => $product['dimensions']['height'],
                "LENGTH"=> $product['dimensions']['length'],
            ], */
        ];

        if (!empty($detailInfoAboutProduct['id'])) {
            $fields['PRODUCT_PROVIDER_CLASS'] = '\Bitrix\Catalog\Product\CatalogProvider';

            if (!empty($detailInfoAboutProduct['detail_page_url'])) {
                $fields['DETAIL_PAGE_URL'] = $detailInfoAboutProduct['detail_page_url'];
            }
        }

        $eventResult = $this->callEvent('onAfteGetProductFields', $fields);

        return $fields;
    }

    protected function createShipment(&$order, &$basket, $resultOrder)
    {
        $shipmentCollection = $order->getShipmentCollection();
        $deliveryServiceId = $resultOrder['deliveryServiceId'] ?: $this->deliveryServiceId;
        $shipment = $shipmentCollection->createItem(
            \Bitrix\Sale\Delivery\Services\Manager::getObjectById($deliveryServiceId)
        );

        $this->setDeliveryNameWithParent($order, $shipment, $deliveryServiceId);

        $shipmentItemCollection = $shipment->getShipmentItemCollection();

        foreach ($basket as $basketItem) {
            $item = $shipmentItemCollection->createItem($basketItem);
            $item->setQuantity($basketItem->getQuantity());
        }
    }

    protected function setDeliveryNameWithParent(&$order, &$shipment, $deliveryServiceId)
    {
        $shipmentFields = [];
        $deliveryService = \Bitrix\Sale\Delivery\Services\Manager::getObjectById($deliveryServiceId);
        if (!$deliveryService) return;

        if ($deliveryService->isProfile()) {
            $shipmentFields['DELIVERY_NAME'] = $deliveryService->getNameWithParent();
        }
        if (empty($shipmentFields)) return;

        $setFieldsResult = $shipment->setFields($shipmentFields);
        if(!$setFieldsResult->isSuccess()) {
            $this->createReport('error_log.txt', $setFieldsResult->getErrors());
        }
    }

    protected function createPayment(&$order, $resultOrder)
    {
        $paymentCollection = $order->getPaymentCollection();
        $paymentSystemId = $resultOrder['paymentSystemId'] ?: $this->paymentSystemId;
        $payment = $paymentCollection->createItem(
            \Bitrix\Sale\PaySystem\Manager::getObjectById($paymentSystemId)
        );
        $payment->setField("SUM", $order->getPrice());
        $payment->setField("CURRENCY", $order->getCurrency());
    }

    protected function initTradeBinding(&$order, $externalId)
    {
        $platform = \Bitrix\Sale\TradingPlatform\Landing\Landing::getInstanceByCode(self::TRADING_PLATFORM_CODE);
        if (!$platform->isInstalled()) return;

        $collection = $order->getTradeBindingCollection();
        $collection->createItem($platform);
        foreach ($collection as $item) {
            $item->setField('EXTERNAL_ORDER_ID', $externalId);
        }
    }

    protected function payTheOrder(&$order, $paid = true)
    {
        $paymentCollection = $order->getPaymentCollection();
        foreach ($paymentCollection as $payment) {
            $payment->setPaid($paid ? "Y" : 'N');
        }
    }

    protected function shipTheOrder(&$order, $ship = true)
    {
        $shipmentCollection = $order->getShipmentCollection();
        foreach ($shipmentCollection as $shipment) {
            if ($shipment->isSystem()) continue;
            if ($ship) {
                $shipment->allowDelivery();
            } else {
                $shipment->disallowDelivery();
            }
            $shipment->setField('DEDUCTED', $ship ? 'Y' : 'N');
        }
    }

    protected function cancelledTheOrder(&$order)
    {
        $this->payTheOrder($order, false);
        $this->shipTheOrder($order, false);

        $order->setField("CANCELED", "Y");
    }

    protected function setOrderPropertyValues(&$order, $orderInfo)
    {
        $success = true;
        $externalId = $orderInfo['externalId'] ?? '';
        $shipmentDate = $orderInfo['shipmentDate'] ?? '';
        $createOrderDate = $orderInfo['createOrderDate'] ?? '';

        $propertyCollection = $order->getPropertyCollection();

        $externalIdProp = $propertyCollection->getItemByOrderPropertyId(intval($this->wrappers->Option->get($this->moduleId, 'propertyOfExternalOrderNumber')));
        if ($externalIdProp && $externalId) {
            $externalIdProp->setValue($externalId);
        } else {
            $success = false;
        }

        $shipmentDateProp = $propertyCollection->getItemByOrderPropertyId(intval($this->wrappers->Option->get($this->moduleId, 'propertyOfShipmentDate')));
        if ($shipmentDateProp) {
            if (
                $this->expertMode
                && $createOrderDate
                && $this->deadlineCreateOrdersHours
            ) {
                $realDateForDb = date('Y-m-d H:i:s', strtotime($createOrderDate));
                $preparedShipmentDate = $this->getPreparedDate($realDateForDb);
                $shipmentDateTimestamp = strtotime($preparedShipmentDate);
                $shipmentDate = $shipmentDateTimestamp ? date('d.m.Y', $shipmentDateTimestamp) : '';
                if ($shipmentDate) {
                    $shipmentDateProp->setValue($shipmentDate);
                }
            } else {
                $shipmentDateProp->setValue($shipmentDate);
            }
        }

        return $success;
    }

    protected function getPreparedDate($dateString) {
        $date = new \DateTime($dateString);
        $hour = ltrim($date->format('H'), '0');
        if ((int) $hour >= (int) $this->deadlineCreateOrdersHours) {
            $date->modify('+1 day');
            $dateOnly = $date->format('Y-m-d');
        } else {
            $dateOnly = $date->format('Y-m-d');
        }
        return $dateOnly;
    }

    protected function setCustomerData(&$order, $customerData)
    {
        $phone = $customerData['phone'] ?? '';
        $email = $customerData['customer_email'] ?? '';
        $fullName = $customerData['name'] ?? '';
        $zipCode = $customerData['address']['zip_code'] ?? '';
        $city = $customerData['address']['city'] ?? '';
        $address = $customerData['address']['address_tail'] ?? '';

        $propertyCollection = $order->getPropertyCollection();

        $phoneProp = $propertyCollection->getPhone();
        if ($phoneProp) $phoneProp->setValue($phone);

        $emailProp = $propertyCollection->getUserEmail();
        if ($emailProp) $emailProp->setValue($email);

        $userProp = $propertyCollection->getProfileName();
        if ($userProp) $userProp->setValue($fullName);

        $zipProp = $propertyCollection->getItemByOrderPropertyCode('ZIP');
        if (!$zipProp) $zipProp = $propertyCollection->getDeliveryLocationZip();
        if ($zipProp && !empty($zipCode)) $zipProp->setValue($zipCode);

        $cityProp = $propertyCollection->getItemByOrderPropertyCode('CITY');
        if ($cityProp) $cityProp->setValue($city);

        $addressProp = $propertyCollection->getItemByOrderPropertyCode('ADDRESS');
        if (!$addressProp) $addressProp = $propertyCollection->getAddress();
        if ($addressProp) $addressProp->setValue($address);

        $locationCode = $this->getLocation($city);
        if ($locationCode) {
            $locationProp = $propertyCollection->getItemByOrderPropertyCode('LOCATION');
            if (!$locationProp) $locationProp = $propertyCollection->getDeliveryLocation();
            if ($locationProp) $locationProp->setValue($locationCode);
        }
    }

    protected function getLocation($city)
    {
        $query = \Bitrix\Sale\Location\LocationTable::getList(array(
            'filter' => array('NAME.NAME' => $city),
            'select' => array('CODE')
        ));
        if ($locationData = $query->fetch()) {
            return $locationData['CODE'] ?: false;
        }
    }

    protected function setDefaultCustomerData(&$order, $userId)
    {
        [$name, $phone, $email, $address] = $this->getUserData($userId);
        $propertyCollection = $order->getPropertyCollection();

        $phoneProp = $propertyCollection->getPhone();
        if ($phoneProp) $phoneProp->setValue($phone);

        $emailProp = $propertyCollection->getUserEmail();
        if ($emailProp) $emailProp->setValue($email);

        $userProp = $propertyCollection->getProfileName();;
        if ($userProp) $userProp->setValue($name);

        $addressProp = $propertyCollection->getAddress();
        if ($addressProp) $addressProp->setValue($address);
    }

    protected function getUserData($userId)
    {
        $customerId = $this->getCustomerId();

        if ($customerId) {
            $iterator = \CSaleOrderUserPropsValue::GetList(
                [],
                ["USER_PROPS_ID" => $customerId]
            );
            while ($field = $iterator->Fetch()) {
                if ($field['PROP_IS_PROFILE_NAME'] == 'Y') {
                    $name = $field['VALUE'];
                }
                if ($field['PROP_CODE'] == 'PHONE') {
                    $phone = $field['VALUE'];
                }
                if ($field['PROP_IS_EMAIL'] == 'Y') {
                    $email = $field['VALUE'];
                }
                if ($field['PROP_CODE'] == 'ADDRESS') {
                    $address = $field['VALUE'];
                }
            }
        } else {
            $userRes = \CUser::GetByID($userId ?: 1);
            $userFields = $userRes->Fetch();
            $name = ($userFields['NAME'] ?? '').' '.($userFields['LAST_NAME'] ?? '');
            $phone = $userFields['PERSONAL_PHONE'] ?? '';
            $email = $userFields['EMAIL'] ?? '';
            $address = '';
        }

        return [
            $name ?? '',
            $phone ?? '',
            $email ?? '',
            $address ?? '',
        ];
    }

    protected function setTrackNumber(&$order, $trackNumber)
    {
        $propertyCollection = $order->getPropertyCollection();
        $trackNumberProp = $propertyCollection->getItemByOrderPropertyId($this->wrappers->Option->get($this->moduleId, 'propertyOfTrackNumber'));
        if ($trackNumberProp && !empty($trackNumber)) $trackNumberProp->setValue($trackNumber);
    }

    protected function setUserDescription(&$order, $resultOrder)
    {
        $descriptions = [];

        if ($this->userDescriptionTemplate) {
            $descriptions[] = $this->applyTemplate($this->userDescriptionTemplate, $resultOrder);
        }
        $comment = $resultOrder['customer']['address']['comment'] ?? false;
        if ($comment) $descriptions[] = $comment;

        if ($descriptions) $order->setField('USER_DESCRIPTION', implode(', ', $descriptions));
    }

    protected function applyTemplate($template, $resultOrder)
    {
        $result = $template;

        foreach ($this->templateFields as $mark => $field) {
            $value = $resultOrder[$field] ?? '';
            $result = str_replace($mark, $value, $result);
        }

        return $result;
    }

    /**
     * Метод changeOrderStatuses расформирован на 3 части (вызов из класса Agents в методе getStatusesAgent):
     * 1) getOrderIdsToExternalIds в текущем классе - получение id и связанных externalId
     * 2) getStatusByExternalId в классе Api - получение статуса по externalId
     * 3) changeOrderStatus в текущем классе - конвертация и сохранение нового статуса в заказ
     *
     * Вызов цепочки методов произвадится из класса Agents в методе getStatusesAgent
     */
    public function getOrderIdsToExternalIds($flagOfAllOrders = false, $orderId = false)
    {
        $today = date('Y-m-d');
        global $DB;

        $filter = [
            '%=XML_ID' => $this->xmlIdPrefix.'_%',
            ">=DATE_INSERT" => date($DB->DateFormatToPHP(\CSite::GetDateFormat("SHORT")),  strtotime($today.' -'. $this->wrappers->Option->get($this->moduleId, 'numberOfDaysToProcessOrders') .' days')),
        ];

        if ($orderId > 0) {
            $filter['>ID'] = $orderId;
        }

        if ($flagOfAllOrders == false){
            $filter['!=CANCELED'] = 'Y';
        }

        if ($statusesFilter = $this->getFilterByCompletedStatuses()) {
            foreach ($statusesFilter as $keyFilter => $valueFilter) {
                $filter[$keyFilter] = $valueFilter;
            }
        }

        $orders = $this->wrappers->Order->getList([
            'select' => ['ID', 'STATUS_ID', 'XML_ID'],
            'filter' => $filter,
            'order' => ['ID' => 'ASC'],
        ]);
        $orderIdsToExternalIds = [];

        while ($orderResult = $orders->fetch()) {
            if (strpos($orderResult['XML_ID'], $this->xmlIdPrefix.'_') === false) continue;

            $externalId = $this->getExternalId($orderResult['ID']);
            if (!$externalId) continue;
            $orderIdsToExternalIds[$orderResult['ID']] = $externalId;
        }

        return $orderIdsToExternalIds;
    }

    public function changeOrderStatus($orderId, $statusOnTradingPlatform)
    {
        $eventResult = $this->callEvent('onBeforeChangeOrderStatus', $orderId, $statusOnTradingPlatform);
        if (!$eventResult) return;

        $success = false;
        $needSave = false;
        $statusOnBitrix = $this->convertStatusToBitrixSimilar($statusOnTradingPlatform);
        $order = $this->wrappers->Order->load($orderId);

        if ($statusOnBitrix) {
            $oldStatusOnBitrix = $order->getField('STATUS_ID');

            if ($statusOnBitrix !== $oldStatusOnBitrix) {
                // change order status
                $order->setField('STATUS_ID', $statusOnBitrix);
                $needSave = true;
            }
        }

        // change order flags
        $flagIsChanged = $this->setOrderFlags($order, $statusOnTradingPlatform);
        if (!$needSave && $flagIsChanged) $needSave = true;

        if ($needSave) {
            $result = $order->save();
            if ($result->isSuccess()) {
                $success = true;
            } else {
                $this->createReport('error_log.txt', $result->getErrors());
            }
        }

        return $success;
    }

    public function setCompletedStatuses($statuses)
    {
        $this->optionsOfCompletedStatuses = $statuses;
    }

    protected function getFilterByCompletedStatuses()
    {
        $filter = [];

        foreach ($this->optionsOfCompletedStatuses as $option) {
            $status = $this->wrappers->Option->get($this->moduleId, self::OPTION_STATUSES_SUFFIX.$option);
            if ($status && !in_array($status, $filter)) {
                $filter[] = $status;
            }
        }

        $disallowStatuses = $this->getBitrixDisallowStatuses();
        foreach ($disallowStatuses as $status) {
            if ($status == 'nothing') continue;
            $filter[] = $status;
        }

        $filter = array_unique($filter);

        return $filter ? ['!=STATUS_ID' => $filter] : [];
    }

    protected function getBitrixDisallowStatuses()
    {
        $statusesList = $this->wrappers->Option->get($this->moduleId, 'disallowStatuses');

        return explode(",", $statusesList);
    }

    protected function getExternalId($orderId)
    {
        $externalId = '';
        $order = $this->wrappers->Order->load($orderId);
        if ($order) {
            $xmlId = $order->getField("XML_ID");
            $externalId = str_replace($this->xmlIdPrefix.'_', '', $xmlId);
        }

        return $externalId;
    }

    public function convertStatusToBitrixSimilar($statusOnTradingPlatform)
    {
        $statusWithBitrix = $this->wrappers->Option->get($this->moduleId, self::OPTION_STATUSES_SUFFIX.$statusOnTradingPlatform);

        // если соответствие не выбрано
        if (!$statusWithBitrix || $statusWithBitrix == 'nothing') {
            $statusWithBitrix = null;
        }

        return $statusWithBitrix;
    }

    // need - не используется, удалить (проверить)
    public function getBitrixStatusInfo($orderId)
    {
        $order = \Bitrix\Sale\Order::load($orderId);
        if ($order) {
            $oldStatusInBitrix = $order->getField('STATUS_ID');

            $query = \Bitrix\Sale\Internals\OrderChangeTable::getList(
                [
                    'order' => array('DATE_CREATE' => 'DESC', 'ID' => 'DESC'),
                    'filter' => array('ORDER_ID' => $orderId, 'TYPE' => 'ORDER_STATUS_CHANGED'),
                    'select' => array('DATE_MODIFY'),
                ]
            );

            if ($historyItem = $query->fetch()) {
                $date = $historyItem['DATE_MODIFY'];
                $bitrixStatusChangeTime = strtotime($date->toString(new \Bitrix\Main\Context\Culture(array("FORMAT_DATETIME" => "Y-m-d HH:i:s"))));
            }
        }

        return [
            'status' => $oldStatusInBitrix ?? false,
            'modifed' => $bitrixStatusChangeTime ?? 0,
        ];
    }

    public function getStatus($orderId)
    {
        $order = $this->wrappers->Order->load($orderId);

        return $order->getField('STATUS_ID');
    }

    public function setStatus(int $orderId, string $status): bool
    {
        $success = false;
        $order = $this->wrappers->Order->load($orderId);
        $order->setField('STATUS_ID', $status);
        $result = $order->save();
        if ($result->isSuccess()) {
            $success = true;
        } else {
            $this->createReport('error_log.txt', $result->getErrors());
        }

        return $success;
    }

    protected function setOrderFlags(&$order, $statusOnTradingPlatform)
    {
        $paid = false;
        $ship = false;
        $flagIsChanged = false;
        $statusOnTradingPlatform = self::OPTION_STATUSES_SUFFIX.$statusOnTradingPlatform;

        // payment
        if (!$order->isPaid()) {
            $paymentFlagData = $this->wrappers->Option->get($this->moduleId, 'paymentFlag');
            $paymentFlags = explode(",", $paymentFlagData);
            if (in_array($statusOnTradingPlatform, $paymentFlags)) {
                $this->payTheOrder($order);
                $paid = true;
                $flagIsChanged = true;
            }
        }

        // shipment
        if (!$order->isShipped()) {
            $shippingFlagData = $this->wrappers->Option->get($this->moduleId, 'shippingFlag');
            $shippingFlags = explode(",", $shippingFlagData);
            if (in_array($statusOnTradingPlatform, $shippingFlags)) {
                $this->shipTheOrder($order);
                $ship = true;
                $flagIsChanged = true;
            }
        }

        // cancelled
        if (
            !$paid
            && !$ship
            && !$order->isCanceled()
        ) {
            $cancelledFlagData = $this->wrappers->Option->get($this->moduleId, 'cancelledFlag');
            $cancelledFlags = explode(",", $cancelledFlagData);
            if (in_array($statusOnTradingPlatform, $cancelledFlags)) {
                $this->cancelledTheOrder($order);
                $flagIsChanged = true;
            }
        }

        return $flagIsChanged;
    }
}

Youez - 2016 - github.com/yon3zu
LinuXploit