diff --git a/.gitignore b/.gitignore index 3a7f1021..73dc1cb0 100644 --- a/.gitignore +++ b/.gitignore @@ -8,7 +8,7 @@ /.idea /.idea/* - +/intaro.retailcrm/log/* /vendor/ .env .phpunit.result.cache diff --git a/CHANGELOG.md b/CHANGELOG.md index f732a6d4..7dfe7939 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,6 @@ +## 2020-04-23 v.5.3.0 +* Добавлена поддержка корпоративных клиентов + ## 2020-01-09 v.5.2.5 * Добавлена передача "externalIds" у позиций товаров в заказе * Добавлено разделение поля строение/корпус на два отдельных diff --git a/intaro.retailcrm/classes/general/ApiClient_v5.php b/intaro.retailcrm/classes/general/ApiClient_v5.php index 90f519f4..9f4add4f 100644 --- a/intaro.retailcrm/classes/general/ApiClient_v5.php +++ b/intaro.retailcrm/classes/general/ApiClient_v5.php @@ -200,6 +200,662 @@ class ApiClient ); } + /* + * Create customers corporate + * + * @param array $customer customer corporate data + * @param string $site (default: null) + * + * @throws \InvalidArgumentException + * @throws \RetailCrm\Exception\CurlException + * @throws \RetailCrm\Exception\InvalidJsonException + * + * @return ApiResponse + */ + public function customersCorporateCreate(array $customer, $site = null) + { + if (! count($customer)) { + throw new \InvalidArgumentException( + 'Parameter `customer` must contains a data' + ); + } + + return $this->client->makeRequest( + '/customers-corporate/create', + Client::METHOD_POST, + $this->fillSite($site, array('customerCorporate' => json_encode($customer))) + ); + } + + /* + * Save customer corporate IDs' (id and externalId) association in the CRM + * + * @param array $ids ids mapping + * + * @throws \InvalidArgumentException + * @throws \RetailCrm\Exception\CurlException + * @throws \RetailCrm\Exception\InvalidJsonException + * + * @return ApiResponse + */ + public function customersСorporateFixExternalIds(array $ids) + { + if (! count($ids)) { + throw new \InvalidArgumentException( + 'Method parameter must contains at least one IDs pair' + ); + } + + return $this->client->makeRequest( + '/customers-corporate/fix-external-ids', + Client::METHOD_POST, + array('customerCorporate' => json_encode($ids)) + ); + } + + /* + * Upload array of the customers corporate + * + * @param array $customers array of customers + * @param string $site (default: null) + * + * @throws \InvalidArgumentException + * @throws \RetailCrm\Exception\CurlException + * @throws \RetailCrm\Exception\InvalidJsonException + * + * @return ApiResponse + */ + public function customersCorporateUpload(array $customers, $site = null) + { + if (! count($customers)) { + throw new \InvalidArgumentException( + 'Parameter `customers` must contains array of the customers' + ); + } + + return $this->client->makeRequest( + '/customers-corporate/upload', + Client::METHOD_POST, + $this->fillSite($site, array('customersCorporate' => json_encode($customers))) + ); + } + + /** + * Get customer corporate by id or externalId + * + * @param string $id customers-corporate identificator + * @param string $by (default: 'externalId') + * @param string $site (default: null) + * + * @throws \InvalidArgumentException + * @throws \RetailCrm\Exception\CurlException + * @throws \RetailCrm\Exception\InvalidJsonException + * + * @return ApiResponse + */ + public function customersСorporateGet($id, $by = 'externalId', $site = null) + { + $this->checkIdParameter($by); + + return $this->client->makeRequest( + "/customers-corporate/$id", + Client::METHOD_GET, + $this->fillSite($site, array('by' => $by)) + ); + } + + /** + * Get corporate customer companies by id or externalId + * + * @param string $id corporate customer identifier + * @param array $filter (default: array()) + * @param int $page (default: null) + * @param int $limit (default: null) + * @param string $by (default: 'externalId') + * @param string $site (default: null) + * + * @throws \InvalidArgumentException + * @throws \RetailCrm\Exception\CurlException + * @throws \RetailCrm\Exception\InvalidJsonException + * + * @return \RetailCrm\Response\ApiResponse + */ + public function customersCorporateCompanies( + $id, + array $filter = [], + $page = null, + $limit = null, + $by = 'externalId', + $site = null + ) { + + $this->checkIdParameter($by); + + $parameters = ['by' => $by]; + if (count($filter)) { + $parameters['filter'] = $filter; + } + if (null !== $page) { + $parameters['page'] = (int) $page; + } + if (null !== $limit) { + $parameters['limit'] = (int) $limit; + } + /* @noinspection PhpUndefinedMethodInspection */ + return $this->client->makeRequest( + "/customers-corporate/$id/companies", + Client::METHOD_GET, + $this->fillSite($site, $parameters) + ); + } + + /** + * Edit a customer corporate + * + * @param array $customer customer data + * @param string $by (default: 'externalId') + * @param string $site (default: null) + * + * @throws \InvalidArgumentException + * @throws \RetailCrm\Exception\CurlException + * @throws \RetailCrm\Exception\InvalidJsonException + * + * @return ApiResponse + */ + public function customersСorporateEdit(array $customer, $by = 'externalId', $site = null) + { + if (!count($customer)) { + throw new \InvalidArgumentException( + 'Parameter `customer` must contains a data' + ); + } + + $this->checkIdParameter($by); + + if (!array_key_exists($by, $customer)) { + throw new \InvalidArgumentException( + sprintf('Customer array must contain the "%s" parameter.', $by) + ); + } + + return $this->client->makeRequest( + sprintf('/customers-corporate/%s/edit', $customer[$by]), + Client::METHOD_POST, + $this->fillSite( + $site, + array('customerCorporate' => json_encode($customer), 'by' => $by) + ) + ); + } + + /* + * Get customers corporate history + * + * @param array $filter + * @param null $page + * @param null $limit + * + * @return ApiResponse + * + */ + public function customersСorporateHistory(array $filter = array(), $page = null, $limit = null) + { + $parameters = array(); + + if (count($filter)) { + $parameters['filter'] = $filter; + } + if (null !== $page) { + $parameters['page'] = (int) $page; + } + if (null !== $limit) { + $parameters['limit'] = (int) $limit; + } + + return $this->client->makeRequest( + '/customers-corporate/history', + Client::METHOD_GET, + $parameters + ); + } + + /** + * Create corporate customer contact + * + * @param string $id corporate customer identifier + * @param array $contact (default: array()) + * @param string $by (default: 'externalId') + * @param string $site (default: null) + * + * @return \RetailCrm\Response\ApiResponse + * @throws \RetailCrm\Exception\CurlException + * @throws \RetailCrm\Exception\InvalidJsonException + * + * @throws \InvalidArgumentException + */ + public function customersCorporateContactsCreate($id, array $contact = [], $by = 'externalId', $site = null) + { + if (! count($contact)) { + throw new \InvalidArgumentException( + 'Parameter `contact` must contains a data' + ); + } + + /* @noinspection PhpUndefinedMethodInspection */ + return $this->client->makeRequest( + "/customers-corporate/$id/contacts/create", + Client::METHOD_POST, + $this->fillSite($site, ['contact' => json_encode($contact), 'by' => $by]) + ); + } + + /** + * Get corporate customer contacts by id or externalId + * + * @param string $id corporate customer identifier + * @param array $filter (default: array()) + * @param int $page (default: null) + * @param int $limit (default: null) + * @param string $by (default: 'externalId') + * @param string $site (default: null) + * + * @throws \InvalidArgumentException + * @throws \RetailCrm\Exception\CurlException + * @throws \RetailCrm\Exception\InvalidJsonException + * + * @return \RetailCrm\Response\ApiResponse + */ + public function customersCorporateContacts( + $id, + array $filter = [], + $page = null, + $limit = null, + $by = 'externalId', + $site = null + ) { + $this->checkIdParameter($by); + $parameters = ['by' => $by]; + if (count($filter)) { + $parameters['filter'] = $filter; + } + if (null !== $page) { + $parameters['page'] = (int) $page; + } + if (null !== $limit) { + $parameters['limit'] = (int) $limit; + } + /* @noinspection PhpUndefinedMethodInspection */ + return $this->client->makeRequest( + "/customers-corporate/$id/contacts", + Client::METHOD_GET, + $this->fillSite($site, $parameters) + ); + } + + /** + * Returns filtered corporate customers list + * + * @param array $filter (default: array()) + * @param int $page (default: null) + * @param int $limit (default: null) + * + * @throws \InvalidArgumentException + * @throws \RetailCrm\Exception\CurlException + * @throws \RetailCrm\Exception\InvalidJsonException + * + * @return \RetailCrm\Response\ApiResponse + */ + public function customersCorporateList(array $filter = [], $page = null, $limit = null) + { + $parameters = []; + if (count($filter)) { + $parameters['filter'] = $filter; + } + if (null !== $page) { + $parameters['page'] = (int) $page; + } + if (null !== $limit) { + $parameters['limit'] = (int) $limit; + } + /* @noinspection PhpUndefinedMethodInspection */ + return $this->client->makeRequest( + '/customers-corporate', + Client::METHOD_GET, + $parameters + ); + } + + /** + * Returns filtered corporate customers notes list + * + * @param array $filter (default: array()) + * @param int $page (default: null) + * @param int $limit (default: null) + * + * @throws \InvalidArgumentException + * @throws \RetailCrm\Exception\CurlException + * @throws \RetailCrm\Exception\InvalidJsonException + * + * @return \RetailCrm\Response\ApiResponse + */ + public function customersCorporateNotesList(array $filter = [], $page = null, $limit = null) + { + $parameters = []; + if (count($filter)) { + $parameters['filter'] = $filter; + } + if (null !== $page) { + $parameters['page'] = (int) $page; + } + if (null !== $limit) { + $parameters['limit'] = (int) $limit; + } + /* @noinspection PhpUndefinedMethodInspection */ + return $this->client->makeRequest( + '/customers-corporate/notes', + Client::METHOD_GET, + $parameters + ); + } + + /** + * Create corporate customer note + * + * @param array $note (default: array()) + * @param string $site (default: null) + * + * @throws \InvalidArgumentException + * @throws \RetailCrm\Exception\CurlException + * @throws \RetailCrm\Exception\InvalidJsonException + * + * @return \RetailCrm\Response\ApiResponse + */ + public function customersCorporateNotesCreate($note, $site = null) + { + if (empty($note['customer']['id']) && empty($note['customer']['externalId'])) { + throw new \InvalidArgumentException( + 'Customer identifier must be set' + ); + } + /* @noinspection PhpUndefinedMethodInspection */ + return $this->client->makeRequest( + '/customers-corporate/notes/create', + Client::METHOD_POST, + $this->fillSite($site, ['note' => json_encode($note)]) + ); + } + + /** + * Delete corporate customer note + * + * @param integer $id + * + * @throws \InvalidArgumentException + * @throws \RetailCrm\Exception\CurlException + * @throws \RetailCrm\Exception\InvalidJsonException + * + * @return \RetailCrm\Response\ApiResponse + */ + public function customersCorporateNotesDelete($id) + { + if (empty($id)) { + throw new \InvalidArgumentException( + 'Note id must be set' + ); + } + /* @noinspection PhpUndefinedMethodInspection */ + return $this->client->makeRequest( + "/customers-corporate/notes/$id/delete", + Client::METHOD_POST + ); + } + + /** + * Get corporate customer addresses by id or externalId + * + * @param string $id corporate customer identifier + * @param array $filter (default: array()) + * @param int $page (default: null) + * @param int $limit (default: null) + * @param string $by (default: 'externalId') + * @param string $site (default: null) + * + * @throws \InvalidArgumentException + * @throws \RetailCrm\Exception\CurlException + * @throws \RetailCrm\Exception\InvalidJsonException + * + * @return \RetailCrm\Response\ApiResponse + */ + public function customersCorporateAddresses( + $id, + array $filter = [], + $page = null, + $limit = null, + $by = 'externalId', + $site = null + ) { + $this->checkIdParameter($by); + $parameters = ['by' => $by]; + if (count($filter)) { + $parameters['filter'] = $filter; + } + if (null !== $page) { + $parameters['page'] = (int) $page; + } + if (null !== $limit) { + $parameters['limit'] = (int) $limit; + } + /* @noinspection PhpUndefinedMethodInspection */ + return $this->client->makeRequest( + "/customers-corporate/$id/addresses", + Client::METHOD_GET, + $this->fillSite($site, $parameters) + ); + } + + /** + * Create corporate customer address + * + * @param string $id corporate customer identifier + * @param array $address (default: array()) + * @param string $by (default: 'externalId') + * @param string $site (default: null) + * + * @throws \InvalidArgumentException + * @throws \RetailCrm\Exception\CurlException + * @throws \RetailCrm\Exception\InvalidJsonException + * + * @return \RetailCrm\Response\ApiResponse + */ + public function customersCorporateAddressesCreate($id, array $address = [], $by = 'externalId', $site = null) + { + /* @noinspection PhpUndefinedMethodInspection */ + return $this->client->makeRequest( + "/customers-corporate/$id/addresses/create", + Client::METHOD_POST, + $this->fillSite($site, ['address' => json_encode($address), 'by' => $by]) + ); + } + + /** + * Edit corporate customer address + * + * @param string $customerId corporate customer identifier + * @param string $addressId corporate customer identifier + * @param array $address (default: array()) + * @param string $customerBy (default: 'externalId') + * @param string $addressBy (default: 'externalId') + * @param string $site (default: null) + * + * @throws \InvalidArgumentException + * @throws \RetailCrm\Exception\CurlException + * @throws \RetailCrm\Exception\InvalidJsonException + * + * @return \RetailCrm\Response\ApiResponse + */ + public function customersCorporateAddressesEdit( + $customerId, + $addressId, + array $address = [], + $customerBy = 'externalId', + $addressBy = 'externalId', + $site = null + ) { + $addressFiltered = array_filter($address); + if ((count(array_keys($addressFiltered)) <= 1) + && (!isset($addressFiltered['text']) + || (isset($addressFiltered['text']) && empty($addressFiltered['text'])) + ) + ) { + throw new \InvalidArgumentException( + 'Parameter `address` must contain address text or all other address field' + ); + } + /* @noinspection PhpUndefinedMethodInspection */ + return $this->client->makeRequest( + "/customers-corporate/$customerId/addresses/$addressId/edit", + Client::METHOD_POST, + $this->fillSite($site, [ + 'address' => json_encode($address), + 'by' => $customerBy, + 'entityBy' => $addressBy + ]) + ); + } + + /** + * Create corporate customer company + * + * @param string $id corporate customer identifier + * @param array $company (default: array()) + * @param string $by (default: 'externalId') + * @param string $site (default: null) + * + * @throws \InvalidArgumentException + * @throws \RetailCrm\Exception\CurlException + * @throws \RetailCrm\Exception\InvalidJsonException + * + * @return \RetailCrm\Response\ApiResponse + */ + public function customersCorporateCompaniesCreate($id, array $company = [], $by = 'externalId', $site = null) + { + /* @noinspection PhpUndefinedMethodInspection */ + return $this->client->makeRequest( + "/customers-corporate/$id/companies/create", + Client::METHOD_POST, + $this->fillSite($site, ['company' => json_encode($company), 'by' => $by]) + ); + } + + /** + * Edit corporate customer company + * + * @param string $customerId corporate customer identifier + * @param string $companyId corporate customer identifier + * @param array $company (default: array()) + * @param string $customerBy (default: 'externalId') + * @param string $companyBy (default: 'externalId') + * @param string $site (default: null) + * + * @return \RetailCrm\Response\ApiResponse + * @throws \InvalidArgumentException + * @throws \RetailCrm\Exception\CurlException + * @throws \RetailCrm\Exception\InvalidJsonException + * + */ + public function customersCorporateCompaniesEdit( + $customerId, + $companyId, + array $company = [], + $customerBy = 'externalId', + $companyBy = 'externalId', + $site = null + ) { + /* @noinspection PhpUndefinedMethodInspection */ + return $this->client->makeRequest( + "/customers-corporate/$customerId/companies/$companyId/edit", + Client::METHOD_POST, + $this->fillSite($site, [ + 'company' => json_encode($company), + 'by' => $customerBy, + 'entityBy' => $companyBy + ]) + ); + } + + /** + * Edit corporate customer contact + * + * @param string $customerId corporate customer identifier + * @param string $contactId corporate customer identifier + * @param array $contact (default: array()) + * @param string $customerBy (default: 'externalId') + * @param string $contactBy (default: 'externalId') + * @param string $site (default: null) + * + * @return \RetailCrm\Response\ApiResponse + * @throws \InvalidArgumentException + * @throws \RetailCrm\Exception\CurlException + * @throws \RetailCrm\Exception\InvalidJsonException + * + */ + public function customersCorporateContactsEdit( + $customerId, + $contactId, + array $contact = [], + $customerBy = 'externalId', + $contactBy = 'externalId', + $site = null + ) { + /* @noinspection PhpUndefinedMethodInspection */ + return $this->client->makeRequest( + "/customers-corporate/$customerId/contacts/$contactId/edit", + Client::METHOD_POST, + $this->fillSite($site, [ + 'contact' => json_encode($contact), + 'by' => $customerBy, + 'entityBy' => $contactBy + ]) + ); + } + + /** + * Edit a corporate customer + * + * @param array $customerCorporate corporate customer data + * @param string $by (default: 'externalId') + * @param string $site (default: null) + * + * @throws \InvalidArgumentException + * @throws \RetailCrm\Exception\CurlException + * @throws \RetailCrm\Exception\InvalidJsonException + * + * @return \RetailCrm\Response\ApiResponse + */ + public function customersCorporateEdit(array $customerCorporate, $by = 'externalId', $site = null) + { + if (!count($customerCorporate)) { + throw new \InvalidArgumentException( + 'Parameter `customerCorporate` must contains a data' + ); + } + $this->checkIdParameter($by); + if (!array_key_exists($by, $customerCorporate)) { + throw new \InvalidArgumentException( + sprintf('Corporate customer array must contain the "%s" parameter.', $by) + ); + } + /* @noinspection PhpUndefinedMethodInspection */ + return $this->client->makeRequest( + sprintf('/customers-corporate/%s/edit', $customerCorporate[$by]), + Client::METHOD_POST, + $this->fillSite( + $site, + ['customerCorporate' => json_encode($customerCorporate), 'by' => $by] + ) + ); + } + /** * Create a order * diff --git a/intaro.retailcrm/classes/general/Logger.php b/intaro.retailcrm/classes/general/Logger.php index 0010f44f..7e84d73b 100644 --- a/intaro.retailcrm/classes/general/Logger.php +++ b/intaro.retailcrm/classes/general/Logger.php @@ -1,10 +1,50 @@ logPath != $logPath || self::$instance->files != $files) + ) { + self::$instance = new Logger($logPath, $files); + } + + return self::$instance; + } + + /** + * Logger constructor. + * + * @param string $logPath + * @param int $files + */ + private function __construct($logPath = '/bitrix/modules/intaro.retailcrm/log', $files = 3) { $this->logPath = $logPath; $this->files = $files; diff --git a/intaro.retailcrm/classes/general/RCrmActions.php b/intaro.retailcrm/classes/general/RCrmActions.php index 1ab08b0f..ace42c0c 100644 --- a/intaro.retailcrm/classes/general/RCrmActions.php +++ b/intaro.retailcrm/classes/general/RCrmActions.php @@ -50,9 +50,9 @@ class RCrmActions } foreach ($arDeliveryServiceAll as $arDeliveryService) { if ((($arDeliveryService['PARENT_ID'] == '0' || $arDeliveryService['PARENT_ID'] == null) || - in_array($arDeliveryService['PARENT_ID'], $groups)) && - $arDeliveryService['ID'] != $noOrderId && - $arDeliveryService['CLASS_NAME'] != '\Bitrix\Sale\Delivery\Services\Group') { + in_array($arDeliveryService['PARENT_ID'], $groups)) && + $arDeliveryService['ID'] != $noOrderId && + $arDeliveryService['CLASS_NAME'] != '\Bitrix\Sale\Delivery\Services\Group') { if (in_array($arDeliveryService['PARENT_ID'], $groups)) { $arDeliveryService['PARENT_ID'] = 0; } @@ -204,7 +204,6 @@ class RCrmActions * * @return self name */ - public static function orderAgent() { if (COption::GetOptionString('main', 'agents_use_crontab', 'N') != 'N') { @@ -244,9 +243,10 @@ class RCrmActions /** * - * @global $APPLICATION - * @param $str in SITE_CHARSET - * @return $str in utf-8 + * @param array|bool|\SplFixedArray|string $str in SITE_CHARSET + * + * @return array|bool|\SplFixedArray|string $str in utf-8 + * @global $APPLICATION */ public static function toJSON($str) { @@ -257,9 +257,10 @@ class RCrmActions /** * - * @global $APPLICATION - * @param $str in utf-8 - * @return $str in SITE_CHARSET + * @param string|array|\SplFixedArray $str in utf-8 + * + * @return array|bool|\SplFixedArray|string $str in SITE_CHARSET + * @global $APPLICATION */ public static function fromJSON($str) { @@ -440,8 +441,10 @@ class RCrmActions case 'customerHistory': case 'ordersFixExternalIds': case 'customersFixExternalIds': + case 'customersCorporateContacts': + case 'customersList': + case 'customersCorporateList': return self::proxy($api, $methodApi, $method, array($params)); - case 'orderGet': return self::proxy($api, 'ordersGet', $method, array($params, 'id', $site)); @@ -449,7 +452,10 @@ class RCrmActions case 'ordersEdit': case 'customersGet': case 'customersEdit': + case 'customersСorporateGet': return self::proxy($api, $methodApi, $method, array($params, 'externalId', $site)); + case 'customersGetById': + return self::proxy($api, 'customersGet', $method, array($params, 'id', $site)); case 'paymentEditById': return self::proxy($api, 'ordersPaymentEdit', $method, array($params, 'id', $site)); @@ -463,14 +469,30 @@ class RCrmActions } private static function proxy($api, $methodApi, $method, $params) { - $log = new Logger(); $version = COption::GetOptionString(self::$MODULE_ID, self::$CRM_API_VERSION, 0); try { $result = call_user_func_array(array($api, $methodApi), $params); + if (!$result) { + $err = new RuntimeException( + $methodApi . ": Got null instead of valid result!" + ); + Logger::getInstance()->write(sprintf( + '%s%s%s', + $err->getMessage(), + PHP_EOL, + $err->getTraceAsString() + ), 'apiErrors'); + + return false; + } + if ($result->getStatusCode() !== 200 && $result->getStatusCode() !== 201) { - if ($methodApi == 'ordersGet' || $methodApi == 'customersGet') { - $log->write(array( + if ($methodApi == 'ordersGet' + || $methodApi == 'customersGet' + || $methodApi == 'customersСorporateGet' + ) { + Logger::getInstance()->write(array( 'api' => $version, 'methodApi' => $methodApi, 'errorMsg' => !empty($result['errorMsg']) ? $result['errorMsg'] : '', @@ -478,7 +500,7 @@ class RCrmActions 'params' => $params ), 'apiErrors'); } elseif ($methodApi == 'customersUpload' || $methodApi == 'ordersUpload') { - $log->write(array( + Logger::getInstance()->write(array( 'api' => $version, 'methodApi' => $methodApi, 'errorMsg' => !empty($result['errorMsg']) ? $result['errorMsg'] : '', @@ -486,8 +508,12 @@ class RCrmActions 'params' => $params ), 'uploadApiErrors'); } else { - self::eventLog(__CLASS__ . '::' . $method, 'RetailCrm\ApiClient::' . $methodApi, !empty($result['errorMsg']) ? $result['errorMsg'] : ''); - $log->write(array( + self::eventLog( + __CLASS__ . '::' . $method, + 'RetailCrm\ApiClient::' . $methodApi, + !empty($result['errorMsg']) ? $result['errorMsg'] : '' + ); + Logger::getInstance()->write(array( 'api' => $version, 'methodApi' => $methodApi, 'errorMsg' => !empty($result['errorMsg']) ? $result['errorMsg'] : '', @@ -507,63 +533,83 @@ class RCrmActions return false; } } catch (\RetailCrm\Exception\CurlException $e) { - self::eventLog( - __CLASS__ . '::' . $method, 'RetailCrm\ApiClient::' . $methodApi . '::CurlException', - $e->getCode() . ': ' . $e->getMessage() + static::logException( + $method, + $methodApi, + 'CurlException', + 'CurlException', + $e, + $version, + $params ); - $log->write(array( - 'api' => $version, - 'methodApi' => $methodApi, - 'errorMsg' => $e->getMessage(), - 'errors' => $e->getCode(), - 'params' => $params - ), 'apiErrors'); - - if (function_exists('retailCrmApiResult')) { - retailCrmApiResult($methodApi, false, 'CurlException'); - } return false; } catch (InvalidArgumentException $e) { - self::eventLog( - __CLASS__ . '::' . $method, 'RetailCrm\ApiClient::' . $methodApi . '::InvalidArgumentException', - $e->getCode() . ': ' . $e->getMessage() + static::logException( + $method, + $methodApi, + 'InvalidArgumentException', + 'ArgumentException', + $e, + $version, + $params ); - $log->write(array( - 'api' => $version, - 'methodApi' => $methodApi, - 'errorMsg' => $e->getMessage(), - 'errors' => $e->getCode(), - 'params' => $params - ), 'apiErrors'); - - if (function_exists('retailCrmApiResult')) { - retailCrmApiResult($methodApi, false, 'ArgumentException'); - } return false; } catch (\RetailCrm\Exception\InvalidJsonException $e) { - self::eventLog( - __CLASS__ . '::' . $method, 'RetailCrm\ApiClient::' . $methodApi . '::InvalidJsonException', - $e->getCode() . ': ' . $e->getMessage() + static::logException( + $method, + $methodApi, + 'InvalidJsonException', + 'ArgumentException', + $e, + $version, + $params ); - $log->write(array( - 'api' => $version, - 'methodApi' => $methodApi, - 'errorMsg' => $e->getMessage(), - 'errors' => $e->getCode(), - 'params' => $params - ), 'apiErrors'); - - if (function_exists('retailCrmApiResult')) { - retailCrmApiResult($methodApi, false, 'ArgumentException'); - } } if (function_exists('retailCrmApiResult')) { - retailCrmApiResult($methodApi, true, $result->getStatusCode()); + retailCrmApiResult($methodApi, true, isset($result) ? $result->getStatusCode() : 0); } return isset($result) ? $result : false; } + + /** + * Log exception into log file and event log + * + * @param string $method + * @param string $methodApi + * @param string $exceptionName + * @param string $apiResultExceptionName + * @param \Exception|\Error|\Throwable $exception + * @param string $version + * @param array $params + */ + protected static function logException( + $method, + $methodApi, + $exceptionName, + $apiResultExceptionName, + $exception, + $version, + $params + ) { + self::eventLog( + __CLASS__ . '::' . $method, 'RetailCrm\ApiClient::' . $methodApi . '::' . $exceptionName, + $exception->getCode() . ': ' . $exception->getMessage() + ); + + Logger::getInstance()->write(array( + 'api' => $version, + 'methodApi' => $methodApi, + 'errorMsg' => $exception->getMessage(), + 'errors' => $exception->getCode(), + 'params' => $params + ), 'apiErrors'); + + if (function_exists('retailCrmApiResult')) { + retailCrmApiResult($methodApi, false, $apiResultExceptionName); + } + } } diff --git a/intaro.retailcrm/classes/general/RetailcrmConfigProvider.php b/intaro.retailcrm/classes/general/RetailcrmConfigProvider.php new file mode 100644 index 00000000..27d408dd --- /dev/null +++ b/intaro.retailcrm/classes/general/RetailcrmConfigProvider.php @@ -0,0 +1,560 @@ + + * @license https://opensource.org/licenses/MIT MIT License + * @link http://www.retailcrm.ru/docs/Developers/ApiVersion4 + */ + +IncludeModuleLangFile(__FILE__); + +/** + * PHP version 5.3 + * + * RetailcrmConfigProvider class + * + * @category RetailCrm + * @package RetailCrm + * @author RetailCrm + * @license https://opensource.org/licenses/MIT MIT License + * @link http://www.retailcrm.ru/docs/Developers/ApiVersion4 + */ +class RetailcrmConfigProvider +{ + /** @var bool|null|string */ + private static $apiUrl; + + /** @var bool|null|string */ + private static $apiKey; + + /** @var bool|null|string */ + private static $catalogBasePrice; + + /** @var bool|null|string */ + private static $currency; + + /** @var bool|null|string */ + private static $orderDimensions; + + /** @var bool|null|string */ + private static $corporateClientName; + + /** @var bool|null|string */ + private static $corporateClientAddress; + + /** @var bool|null|string */ + private static $corporateClient; + + /** @var array $sitesList */ + private static $sitesList; + + /** @var array $sitesListCorporate */ + private static $sitesListCorporate; + + /** @var bool|null|string $orderNumbers */ + private static $orderNumbers; + + /** @var array $orderTypes */ + private static $orderTypes; + + /** @var array $deliveryTypes */ + private static $deliveryTypes; + + /** @var array $paymentTypes */ + private static $paymentTypes; + + /** @var array $paymentStatuses */ + private static $paymentStatuses; + + /** @var array $payment */ + private static $payment; + + /** @var array $orderProps */ + private static $orderProps; + + /** @var array $legalDetails */ + private static $legalDetails; + + /** @var array $contragentTypes */ + private static $contragentTypes; + + /** @var array $cancellableOrderPaymentStatuses */ + private static $cancellableOrderPaymentStatuses; + + /** @var array $customFields */ + private static $customFields; + + /** @var array $infoblocksInventories */ + private static $infoblocksInventories; + + /** @var array $stores */ + private static $stores; + + /** @var array $shops */ + private static $shops; + + /** + * @return bool|string|null + */ + public static function getApiUrl() + { + if (self::isEmptyNotZero(static::$apiUrl)) { + static::$apiUrl = static::getOption(RetailcrmConstants::CRM_API_HOST_OPTION); + } + + return static::$apiUrl; + } + + /** + * @return bool|string|null + */ + public static function getApiKey() + { + if (self::isEmptyNotZero(static::$apiKey)) { + static::$apiKey = static::getOption(RetailcrmConstants::CRM_API_KEY_OPTION); + } + + return static::$apiKey; + } + + /** + * getCorporateClientName + * + * @return bool|string|null + */ + public static function getCorporateClientName() + { + if (self::isEmptyNotZero(static::$corporateClientName)) { + static::$corporateClientName = static::getUnserializedOption(RetailcrmConstants::CRM_CORP_NAME); + } + + return static::$corporateClientName; + } + + /** + * getCorporateClientAddress + * + * @return bool|string|null + */ + public static function getCorporateClientAddress() + { + if (self::isEmptyNotZero(static::$corporateClientAddress)) { + static::$corporateClientAddress = static::getUnserializedOption(RetailcrmConstants::CRM_CORP_ADDRESS); + } + + return static::$corporateClientAddress; + } + + /** + * getCorporateClient + * + * @return bool|string|null + */ + public static function getCorporateClientStatus() + { + if (self::isEmptyNotZero(static::$corporateClient)) { + static::$corporateClient = static::getOption(RetailcrmConstants::CRM_CC); + } + + return static::$corporateClient; + } + + /** + * getSitesList + * + * @return array + */ + public static function getSitesList() + { + if (self::isEmptyNotZero(static::$sitesList)) { + static::$sitesList = static::getUnserializedOption(RetailcrmConstants::CRM_SITES_LIST); + } + + return static::$sitesList; + } + + /** + * getSitesListCorporate + * + * @return array + */ + public static function getSitesListCorporate() + { + if (self::isEmptyNotZero(static::$sitesListCorporate)) { + static::$sitesListCorporate = static::getUnserializedOption( + RetailcrmConstants::CRM_SITES_LIST_CORPORATE + ); + } + + return static::$sitesListCorporate; + } + + /** + * getOrderTypes + * + * @return array + */ + public static function getOrderTypes() + { + if (self::isEmptyNotZero(static::$orderTypes)) { + static::$orderTypes = static::getUnserializedOption(RetailcrmConstants::CRM_ORDER_TYPES_ARR); + } + + return static::$orderTypes; + } + + /** + * getDeliveryTypes + * + * @return array + */ + public static function getDeliveryTypes() + { + if (self::isEmptyNotZero(static::$deliveryTypes)) { + static::$deliveryTypes = static::getUnserializedOption(RetailcrmConstants::CRM_DELIVERY_TYPES_ARR); + } + + return static::$deliveryTypes; + } + + /** + * getPaymentTypes + * + * @return array + */ + public static function getPaymentTypes() + { + if (self::isEmptyNotZero(static::$paymentTypes)) { + static::$paymentTypes = static::getUnserializedOption(RetailcrmConstants::CRM_PAYMENT_TYPES); + } + + return static::$paymentTypes; + } + + /** + * getPaymentStatuses + * + * @return array + */ + public static function getPaymentStatuses() + { + if (self::isEmptyNotZero(static::$paymentStatuses)) { + static::$paymentStatuses = static::getUnserializedOption(RetailcrmConstants::CRM_PAYMENT_STATUSES); + } + + return static::$paymentStatuses; + } + + /** + * getPayment + * + * @return array + */ + public static function getPayment() + { + if (self::isEmptyNotZero(static::$payment)) { + static::$payment = static::getUnserializedOption(RetailcrmConstants::CRM_PAYMENT); + } + + return static::$payment; + } + + /** + * getOrderProps + * + * @return array + */ + public static function getOrderProps() + { + if (self::isEmptyNotZero(static::$orderProps)) { + static::$orderProps = static::getUnserializedOption(RetailcrmConstants::CRM_ORDER_PROPS); + } + + return static::$orderProps; + } + + /** + * getLegalDetails + * + * @return array + */ + public static function getLegalDetails() + { + if (self::isEmptyNotZero(static::$legalDetails)) { + static::$legalDetails = static::getUnserializedOption(RetailcrmConstants::CRM_LEGAL_DETAILS); + } + + return static::$legalDetails; + } + + /** + * getContragentTypes + * + * @return array + */ + public static function getContragentTypes() + { + if (self::isEmptyNotZero(static::$contragentTypes)) { + static::$contragentTypes = static::getUnserializedOption(RetailcrmConstants::CRM_CONTRAGENT_TYPE); + } + + return static::$contragentTypes; + } + + /** + * getCustomFields + * + * @return array + */ + public static function getCustomFields() + { + if (self::isEmptyNotZero(static::$customFields)) { + static::$customFields = static::getUnserializedOption(RetailcrmConstants::CRM_CUSTOM_FIELDS); + } + + return static::$customFields; + } + + /** + * getCancellableOrderPaymentStatuses + * + * @return array + */ + public static function getCancellableOrderPaymentStatuses() + { + if (self::isEmptyNotZero(static::$cancellableOrderPaymentStatuses)) { + static::$cancellableOrderPaymentStatuses = static::getUnserializedOption( + RetailcrmConstants::CRM_CANCEL_ORDER + ); + } + + return static::$cancellableOrderPaymentStatuses; + } + + /** + * getLastOrderId + * + * @return bool|string|null + */ + public static function getLastOrderId() + { + return static::getOption(RetailcrmConstants::CRM_ORDER_LAST_ID); + } + + /** + * setLastOrderId + * + * @param $id + */ + public static function setLastOrderId($id) + { + static::setOption(RetailcrmConstants::CRM_ORDER_LAST_ID, $id); + } + + /** + * getFailedOrdersIds + * + * @return array + */ + public static function getFailedOrdersIds() + { + return static::getUnserializedOption(RetailcrmConstants::CRM_ORDER_FAILED_IDS); + } + + /** + * setFailedOrdersIds + * + * @param $ids + */ + public static function setFailedOrdersIds($ids) + { + static::setOption(RetailcrmConstants::CRM_ORDER_FAILED_IDS, serialize($ids)); + } + + /** + * getOrderNumbers + * + * @return bool|string|null + */ + public static function getOrderNumbers() + { + if (self::isEmptyNotZero(self::$orderNumbers)) { + self::$orderNumbers = static::getOption(RetailcrmConstants::CRM_ORDER_NUMBERS); + } + + return self::$orderNumbers; + } + + /** + * getOrderHistoryDate + * + * @return bool|string|null + */ + public static function getOrderHistoryDate() + { + return static::getOption(RetailcrmConstants::CRM_ORDER_HISTORY_DATE); + } + + /** + * getCatalogBasePrice + * + * @return bool|string|null + */ + public static function getCatalogBasePrice() + { + if (self::isEmptyNotZero(static::$catalogBasePrice)) { + static::$catalogBasePrice = static::getOption(RetailcrmConstants::CRM_CATALOG_BASE_PRICE); + } + + return static::$catalogBasePrice; + } + + /** + * getOrderDimensions + * + * @return bool|string|null + */ + public static function getOrderDimensions() + { + if (self::isEmptyNotZero(static::$orderDimensions)) { + static::$orderDimensions = static::getOption(RetailcrmConstants::CRM_ORDER_DIMENSIONS, 'N'); + } + + return static::$orderDimensions; + } + + /** + * getCurrency + * + * @return bool|string|null + */ + public static function getCurrency() + { + if (self::isEmptyNotZero(static::$currency)) { + static::$currency = static::getOption(RetailcrmConstants::CRM_CURRENCY); + } + + return static::$currency; + } + + /** + * Returns currency from settings. If it's not set - returns Bitrix base currency. + * + * @return bool|string|null + */ + public static function getCurrencyOrDefault() + { + return self::getCurrency() ? self::getCurrency() : \Bitrix\Currency\CurrencyManager::getBaseCurrency(); + } + + /** + * getInfoblocksInventories + * + * @return array + */ + public static function getInfoblocksInventories() + { + if (self::isEmptyNotZero(static::$infoblocksInventories)) { + static::$infoblocksInventories = static::getUnserializedOption( + RetailcrmConstants::CRM_IBLOCKS_INVENTORIES + ); + } + + return static::$infoblocksInventories; + } + + /** + * getStores + * + * @return array + */ + public static function getStores() + { + if (self::isEmptyNotZero(static::$stores)) { + static::$stores = static::getUnserializedOption(RetailcrmConstants::CRM_STORES); + } + + return static::$stores; + } + + /** + * getShops + * + * @return array + */ + public static function getShops() + { + if (self::isEmptyNotZero(static::$shops)) { + static::$shops = static::getUnserializedOption(RetailcrmConstants::CRM_SHOPS); + } + + return static::$shops; + } + + /** + * Wraps Bitrix COption::GetOptionString(...) + * + * @param string $option + * @param int|string $def + * + * @return bool|string|null + */ + private static function getOption($option, $def = 0) + { + return COption::GetOptionString( + RetailcrmConstants::MODULE_ID, + $option, + $def + ); + } + + /** + * setOption + * + * @param $name + * @param string $value + * @param bool $desc + * @param string $site + */ + private static function setOption($name, $value = "", $desc = false, $site = "") + { + COption::SetOptionString( + RetailcrmConstants::MODULE_ID, + $name, + $value, + $desc, + $site + ); + } + + /** + * Wraps Bitrix unserialize(COption::GetOptionString(...)) + * + * @param string $option + * @param int|string $def + * + * @return mixed + */ + private static function getUnserializedOption($option, $def = 0) + { + return unserialize(static::getOption($option, $def)); + } + + /** + * Returns true if value is empty and not zero (0 - digit) + * + * @param mixed $value + * + * @return bool + */ + private static function isEmptyNotZero($value) + { + return empty($value) && $value !== 0; + } +} diff --git a/intaro.retailcrm/classes/general/RetailcrmConstants.php b/intaro.retailcrm/classes/general/RetailcrmConstants.php new file mode 100644 index 00000000..6daed3b1 --- /dev/null +++ b/intaro.retailcrm/classes/general/RetailcrmConstants.php @@ -0,0 +1,77 @@ + + * @license https://opensource.org/licenses/MIT MIT License + * @link http://www.retailcrm.ru/docs/Developers/ApiVersion4 + */ + +IncludeModuleLangFile(__FILE__); + +/** + * PHP version 5.3 + * + * RetailcrmConstants + * + * @category RetailCrm + * @package RetailCrm + * @author RetailCrm + * @license https://opensource.org/licenses/MIT MIT License + * @link http://www.retailcrm.ru/docs/Developers/ApiVersion4 + */ +class RetailcrmConstants +{ + const MODULE_ID = 'intaro.retailcrm'; + const CRM_API_HOST_OPTION = 'api_host'; + const CRM_API_KEY_OPTION = 'api_key'; + const CRM_ORDER_TYPES_ARR = 'order_types_arr'; + const CRM_DELIVERY_TYPES_ARR = 'deliv_types_arr'; + const CRM_DELIVERY_SERVICES_ARR = 'deliv_services_arr'; + const CRM_PAYMENT_TYPES = 'pay_types_arr'; + const CRM_PAYMENT_STATUSES = 'pay_statuses_arr'; + const CRM_PAYMENT = 'payment_arr'; //order payment Y/N + const CRM_ORDER_LAST_ID = 'order_last_id'; + const CRM_ORDER_SITES = 'sites_ids'; + const CRM_ORDER_DISCHARGE = 'order_discharge'; + const CRM_ORDER_PROPS = 'order_props'; + const CRM_LEGAL_DETAILS = 'legal_details'; + const CRM_CUSTOM_FIELDS = 'custom_fields'; + const CRM_CONTRAGENT_TYPE = 'contragent_type'; + const CRM_SITES_LIST = 'sites_list'; + const CRM_SITES_LIST_CORPORATE = 'shops-corporate'; + const CRM_ORDER_NUMBERS = 'order_numbers'; + const CRM_CANCEL_ORDER = 'cansel_order'; + const CRM_INVENTORIES_UPLOAD = 'inventories_upload'; + const CRM_STORES = 'stores'; + const CRM_SHOPS = 'shops'; + const CRM_IBLOCKS_INVENTORIES = 'iblocks_inventories'; + const CRM_PRICES_UPLOAD = 'prices_upload'; + const CRM_PRICES = 'prices'; + const CRM_PRICE_SHOPS = 'price_shops'; + const CRM_IBLOCKS_PRICES = 'iblock_prices'; + const CRM_COLLECTOR = 'collector'; + const CRM_COLL_KEY = 'coll_key'; + const CRM_UA = 'ua'; + const CRM_UA_KEYS = 'ua_keys'; + const CRM_DISCOUNT_ROUND = 'discount_round'; + const CRM_CC = 'cc'; + const CRM_CORP_SHOPS = 'shops-corporate'; + const CRM_CORP_NAME = 'nickName-corporate'; + const CRM_CORP_ADDRESS = 'adres-corporate'; + const CRM_API_VERSION = 'api_version'; + const CRM_CURRENCY = 'currency'; + const CRM_ADDRESS_OPTIONS = 'address_options'; + const CRM_DIMENSIONS = 'order_dimensions'; + const PROTOCOL = 'protocol'; + const CRM_ORDER_FAILED_IDS = 'order_failed_ids'; + const CRM_ORDER_HISTORY_DATE = 'order_history_date'; + const CRM_CATALOG_BASE_PRICE = 'catalog_base_price'; + const CRM_ORDER_DIMENSIONS = 'order_dimensions'; + const CANCEL_PROPERTY_CODE = 'INTAROCRM_IS_CANCELED'; +} diff --git a/intaro.retailcrm/classes/general/RetailcrmDependencyLoader.php b/intaro.retailcrm/classes/general/RetailcrmDependencyLoader.php new file mode 100644 index 00000000..b5d2c65c --- /dev/null +++ b/intaro.retailcrm/classes/general/RetailcrmDependencyLoader.php @@ -0,0 +1,104 @@ + + * @license https://opensource.org/licenses/MIT MIT License + * @link http://www.retailcrm.ru/docs/Developers/ApiVersion4 + */ + +IncludeModuleLangFile(__FILE__); + +/** + * PHP version 5.3 + * + * RetailcrmDependencyLoader class + * + * @category RetailCrm + * @package RetailCrm + * @author RetailCrm + * @license https://opensource.org/licenses/MIT MIT License + * @link http://www.retailcrm.ru/docs/Developers/ApiVersion4 + */ +class RetailcrmDependencyLoader +{ + /** @var int */ + const LEGACY_LOADER = 0; + + /** @var int */ + const D7_LOADER = 1; + + /** @var int $loader */ + private static $loader = self::D7_LOADER; + + /** + * Loads dependencies + * + * @return bool + */ + public static function loadDependencies() + { + foreach (self::getDependencies() as $dependency) { + if (self::LEGACY_LOADER == self::$loader) { + if (!CModule::IncludeModule($dependency)) { + RCrmActions::eventLog( + __CLASS__ . '::' . __METHOD__, + $dependency, + 'module not found' + ); + + return false; + } + } else { + try { + if (!\Bitrix\Main\Loader::includeModule($dependency)) { + RCrmActions::eventLog( + __CLASS__ . '::' . __METHOD__, + $dependency, + 'module not found' + ); + + return false; + } + } catch (\Bitrix\Main\LoaderException $exception) { + RCrmActions::eventLog( + __CLASS__ . '::' . __METHOD__, + $dependency, + sprintf('error while trying to load module: %s', $exception->getMessage()) + ); + + return false; + } + } + } + + return true; + } + + /** + * Set loader mode. Use RetailcrmDependencyLoader::LEGACY_LOADER or RetailcrmDependencyLoader::D7_LOADER + * + * @param $loader + */ + public static function setLoader($loader) + { + if (in_array($loader, array(self::LEGACY_LOADER, self::D7_LOADER))) { + self::$loader = $loader; + } + } + + /** + * Returns array of required modules names + * + * @return array + */ + public static function getDependencies() + { + return array("iblock", "sale", "catalog"); + } +} diff --git a/intaro.retailcrm/classes/general/config/objects.xml b/intaro.retailcrm/classes/general/config/objects.xml index e2d10b08..2cf7ad6c 100644 --- a/intaro.retailcrm/classes/general/config/objects.xml +++ b/intaro.retailcrm/classes/general/config/objects.xml @@ -7,6 +7,7 @@ patronymic email birthday + sex phones manager commentary diff --git a/intaro.retailcrm/classes/general/config/retailcrm.json b/intaro.retailcrm/classes/general/config/retailcrm.json index 8194eb2f..f9000881 100644 --- a/intaro.retailcrm/classes/general/config/retailcrm.json +++ b/intaro.retailcrm/classes/general/config/retailcrm.json @@ -80,6 +80,10 @@ "type": "bool", "default": false }, + "subscribed": { + "type": "bool", + "default": false + }, "commentary": { "type": "string" }, @@ -169,6 +173,49 @@ "type": "string" } }, + "customerCorporate": { + "externalId": { + "type": "string", + "required": true + }, + "createdAt": { + "type": "datetime", + "format": "Y-m-d H:i:s" + }, + "contragentType": { + "type": "enum", + "default": "legal-entity", + "values": ["individual", "legal-entity", "enterpreneur"] + }, + "isMain": { + "type": "bool", + "default": false + }, + "site": { + "type": "string" + }, + "nickName": { + "type": "string" + }, + "name": { + "type": "string" + }, + "text": { + "type": "string" + }, + "legalName": { + "type": "string" + }, + "legalAddress": { + "type": "string" + }, + "INN": { + "type": "string" + }, + "KPP": { + "type": "string" + } + }, "orders": { "number": { "type": "string" @@ -177,6 +224,10 @@ "type": "string", "required": true }, + "id": { + "type": "string", + "required": false + }, "createdAt": { "type": "datetime", "format": "Y-m-d H:i:s" diff --git a/intaro.retailcrm/classes/general/events/RetailCrmEvent.php b/intaro.retailcrm/classes/general/events/RetailCrmEvent.php index 6902d052..416bff1b 100644 --- a/intaro.retailcrm/classes/general/events/RetailCrmEvent.php +++ b/intaro.retailcrm/classes/general/events/RetailCrmEvent.php @@ -1,4 +1,5 @@ $optionsOrderTypes, - 'optionsDelivTypes' => $optionsDelivTypes, - 'optionsPayTypes' => $optionsPayTypes, - 'optionsPayStatuses' => $optionsPayStatuses, - 'optionsPayment' => $optionsPayment, - 'optionsOrderProps' => $optionsOrderProps, - 'optionsLegalDetails' => $optionsLegalDetails, + 'optionsOrderTypes' => $optionsOrderTypes, + 'optionsDelivTypes' => $optionsDelivTypes, + 'optionsPayTypes' => $optionsPayTypes, + 'optionsPayStatuses' => $optionsPayStatuses, + 'optionsPayment' => $optionsPayment, + 'optionsOrderProps' => $optionsOrderProps, + 'optionsLegalDetails' => $optionsLegalDetails, 'optionsContragentType' => $optionsContragentType, - 'optionsSitesList' => $optionsSitesList, - 'optionsCustomFields' => $optionsCustomFields + 'optionsSitesList' => $optionsSitesList, + 'optionsCustomFields' => $optionsCustomFields )); //many sites? @@ -192,20 +193,215 @@ class RetailCrmEvent $methodApi = 'ordersCreate'; } - //user - $userCrm = RCrmActions::apiMethod($api, 'customersGet', __METHOD__, $arOrder['USER_ID'], $site); - if (!isset($userCrm['customer'])) { - $arUser = Bitrix\Main\UserTable::getById($arOrder['USER_ID'])->fetch(); - $resultUser = RetailCrmUser::customerSend($arUser, $api, $optionsContragentType[$arOrder['PERSON_TYPE_ID']], true, $site); - if (!$resultUser) { - RCrmActions::eventLog('RetailCrmEvent::orderSave', 'RetailCrmUser::customerSend', 'error during creating customer'); + $orderCompany = null; + + if ("Y" == $optionCorpClient && $optionsContragentType[$arOrder['PERSON_TYPE_ID']] == 'legal-entity') { + //corparate cliente + $nickName = ''; + $address = ''; + $corpAddress = ''; + $contragent = array(); + $userCorp = array(); + $corpName = RetailcrmConfigProvider::getCorporateClientName(); + $corpAddress = RetailcrmConfigProvider::getCorporateClientAddress(); + + foreach ($arOrder['PROPS']['properties'] as $prop) { + if ($prop['CODE'] == $corpName) { + $nickName = $prop['VALUE'][0]; + } + + if ($prop['CODE'] == $corpAddress) { + $address = $prop['VALUE'][0]; + } + + if (!empty($optionsLegalDetails) + && $search = array_search($prop['CODE'], $optionsLegalDetails[$arOrder['PERSON_TYPE_ID']]) + ) { + $contragent[$search] = $prop['VALUE'][0];//legal order data + } + } + + if (!empty($contragentType)) { + $contragent['contragentType'] = $contragentType; + } + + $customersCorporate = false; + $response = $api->customersCorporateList(array('companyName' => $nickName)); + + if ($response && $response->getStatusCode() == 200) { + $customersCorporate = $response['customersCorporate']; + $singleCorp = reset($customersCorporate); + + if (!empty($singleCorp)) { + $userCorp['customerCorporate'] = $singleCorp; + $companiesResponse = $api->customersCorporateCompanies( + $singleCorp['id'], + array(), + null, + null, + 'id', + $site + ); + + if ($companiesResponse && $companiesResponse->isSuccessful()) { + $orderCompany = array_reduce( + $companiesResponse['companies'], + function ($carry, $item) use ($nickName) { + if (is_array($item) && $item['name'] == $nickName) { + $carry = $item; + } + + return $carry; + }, + null + ); + } + } + } else { + RCrmActions::eventLog( + 'RetailCrmEvent::orderSave', + 'ApiClient::customersCorporateList', + 'error during fetching corporate customers' + ); return false; } + + //user + $userCrm = RCrmActions::apiMethod($api, 'customersGet', __METHOD__, $arOrder['USER_ID'], $site); + + if (!isset($userCrm['customer'])) { + $arUser = Bitrix\Main\UserTable::getById($arOrder['USER_ID'])->fetch(); + + if (!empty($address)) { + $arUser['PERSONAL_STREET'] = $address; + } + + $resultUser = RetailCrmUser::customerSend($arUser, $api, "individual", true, $site); + + if (!$resultUser) { + RCrmActions::eventLog( + __CLASS__ . '::' . __METHOD__, + 'RetailCrmUser::customerSend', + 'error during creating customer' + ); + + return false; + } else { + $userCrm = array('customer' => array('externalId' => $arOrder['USER_ID'])); + } + } + + if (!isset($userCorp['customerCorporate'])) { + $resultUserCorp = RetailCrmCorporateClient::clientSend( + $arOrder, + $api, + $optionsContragentType[$arOrder['PERSON_TYPE_ID']], + true, + false, + $site + ); + + Logger::getInstance()->write($resultUserCorp, 'resultUserCorp'); + + if (!$resultUserCorp) { + RCrmActions::eventLog('RetailCrmEvent::orderSave', 'RetailCrmCorporateClient::clientSend', 'error during creating client'); + + return false; + } + + $arParams['customerCorporate'] = $resultUserCorp; + $arParams['orderCompany'] = isset($resultUserCorp['mainCompany']) ? $resultUserCorp['mainCompany'] : null; + + $customerCorporateAddress = array(); + $customerCorporateCompany = array(); + $addressResult = null; + $companyResult = null; + + if (!empty($address)) { + //TODO address builder add + $customerCorporateAddress = array( + 'name' => $nickName, + 'isMain' => true, + 'text' => $address + ); + + $addressResult = $api->customersCorporateAddressesCreate($resultUserCorp['id'], $customerCorporateAddress, 'id', $site); + } + + $customerCorporateCompany = array( + 'name' => $nickName, + 'isMain' => true, + 'contragent' => $contragent + ); + + if (!empty($addressResult)) { + $customerCorporateCompany['address'] = array( + 'id' => $addressResult['id'] + ); + } + + $companyResult = $api->customersCorporateCompaniesCreate($resultUserCorp['id'], $customerCorporateCompany, 'id', $site); + + $customerCorporateContact = array( + 'isMain' => true, + 'customer' => array( + 'externalId' => $arOrder['USER_ID'], + 'site' => $site + ) + ); + + if (!empty($companyResult)) { + $customerCorporateContact['companies'] = array( + array( + 'company' => array( + 'id' => $companyResult['id'] + ) + ) + ); + } + + $contactResult = $api->customersCorporateContactsCreate( + $resultUserCorp['id'], + $customerCorporateContact, + 'id', + $site + ); + } else { + + RetailCrmCorporateClient::addCustomersCorporateAddresses( + $userCorp['customerCorporate']['id'], + $nickName, + $address, + $api, + $site = null + ); + + $arParams['customerCorporate'] = $userCorp['customerCorporate']; + + if (!empty($orderCompany)) { + $arParams['orderCompany'] = $orderCompany; + } + } + + $arParams['contactExId'] = $userCrm['customer']['externalId']; + } else { + //user + $userCrm = RCrmActions::apiMethod($api, 'customersGet', __METHOD__, $arOrder['USER_ID'], $site); + if (!isset($userCrm['customer'])) { + $arUser = Bitrix\Main\UserTable::getById($arOrder['USER_ID'])->fetch(); + $resultUser = RetailCrmUser::customerSend($arUser, $api, $optionsContragentType[$arOrder['PERSON_TYPE_ID']], true, $site); + if (!$resultUser) { + RCrmActions::eventLog('RetailCrmEvent::orderSave', 'RetailCrmUser::customerSend', 'error during creating customer'); + + return false; + } + } } //order $resultOrder = RetailCrmOrder::orderSend($arOrder, $api, $arParams, true, $site, $methodApi); + if (!$resultOrder) { RCrmActions::eventLog('RetailCrmEvent::orderSave', 'RetailCrmOrder::orderSend', 'error during creating order'); @@ -218,9 +414,9 @@ class RetailCrmEvent /** * @param \Bitrix\Sale\Payment $event * + * @return bool * @throws InvalidArgumentException * - * @return bool */ function paymentSave($event) { @@ -236,18 +432,18 @@ class RetailCrmEvent return false; } - $optionsSitesList = unserialize(COption::GetOptionString(self::$MODULE_ID, self::$CRM_SITES_LIST, 0)); - $optionsPaymentTypes = unserialize(COption::GetOptionString(self::$MODULE_ID, self::$CRM_PAYMENT_TYPES, 0)); - $optionsPayStatuses = unserialize(COption::GetOptionString(self::$MODULE_ID, self::$CRM_PAYMENT, 0)); + $optionsSitesList = RetailcrmConfigProvider::getSitesList(); + $optionsPaymentTypes = RetailcrmConfigProvider::getPaymentTypes(); + $optionsPayStatuses = RetailcrmConfigProvider::getPayment(); $arPayment = array( - 'ID' => $event->getId(), - 'ORDER_ID' => $event->getField('ORDER_ID'), - 'PAID' => $event->getField('PAID'), + 'ID' => $event->getId(), + 'ORDER_ID' => $event->getField('ORDER_ID'), + 'PAID' => $event->getField('PAID'), 'PAY_SYSTEM_ID' => $event->getField('PAY_SYSTEM_ID'), - 'SUM' => $event->getField('SUM'), - 'LID' => $order->getSiteId(), - 'DATE_PAID' => $event->getField('DATE_PAID'), + 'SUM' => $event->getField('SUM'), + 'LID' => $order->getSiteId(), + 'DATE_PAID' => $event->getField('DATE_PAID'), ); if ($optionsSitesList) { @@ -360,9 +556,9 @@ class RetailCrmEvent $optionsSitesList = unserialize(COption::GetOptionString(self::$MODULE_ID, self::$CRM_SITES_LIST, 0)); $arPayment = array( - 'ID' => $event->getId(), - 'ORDER_ID' => $event->getField('ORDER_ID'), - 'LID' => $event->getCollection()->getOrder()->getSiteId() + 'ID' => $event->getId(), + 'ORDER_ID' => $event->getField('ORDER_ID'), + 'LID' => $event->getCollection()->getOrder()->getSiteId() ); if ($optionsSitesList) { diff --git a/intaro.retailcrm/classes/general/history/RetailCrmHistory_v4.php b/intaro.retailcrm/classes/general/history/RetailCrmHistory_v4.php index 0ef737ee..28a0e38c 100644 --- a/intaro.retailcrm/classes/general/history/RetailCrmHistory_v4.php +++ b/intaro.retailcrm/classes/general/history/RetailCrmHistory_v4.php @@ -60,8 +60,7 @@ class RetailCrmHistory $customerH = isset($customerHistory['history']) ? $customerHistory['history'] : array(); - $log = new Logger(); - $log->write($customerH, 'customerHistory'); + Logger::getInstance()->write($customerH, 'customerHistory'); if (count($customerH) == 0) { if ($customerHistory['history']['totalPageCount'] > $customerHistory['history']['currentPage']) { @@ -275,8 +274,7 @@ class RetailCrmHistory $orderH = isset($orderHistory['history']) ? $orderHistory['history'] : array(); - $log = new Logger(); - $log->write($orderH, 'orderHistory'); + Logger::getInstance()->write($orderH, 'orderHistory'); if (count($orderH) == 0) { if ($orderHistory['history']['totalPageCount'] > $orderHistory['history']['currentPage']) { @@ -305,7 +303,7 @@ class RetailCrmHistory } } - $log->write($order, 'assemblyOrderHistory'); + Logger::getInstance()->write($order, 'assemblyOrderHistory'); if ($order['deleted']) { continue; diff --git a/intaro.retailcrm/classes/general/history/RetailCrmHistory_v5.php b/intaro.retailcrm/classes/general/history/RetailCrmHistory_v5.php index 4622d78f..83c74f2b 100644 --- a/intaro.retailcrm/classes/general/history/RetailCrmHistory_v5.php +++ b/intaro.retailcrm/classes/general/history/RetailCrmHistory_v5.php @@ -19,6 +19,7 @@ class RetailCrmHistory public static $CRM_ORDER_FAILED_IDS = 'order_failed_ids'; public static $CRM_ORDER_HISTORY = 'order_history'; public static $CRM_CUSTOMER_HISTORY = 'customer_history'; + public static $CRM_CUSTOMER_CORPORATE_HISTORY = 'customer_corp_history'; public static $CRM_CATALOG_BASE_PRICE = 'catalog_base_price'; public static $CRM_ORDER_NUMBERS = 'order_numbers'; public static $CRM_CANSEL_ORDER = 'cansel_order'; @@ -29,19 +30,7 @@ class RetailCrmHistory public static function customerHistory() { - if (!CModule::IncludeModule("iblock")) { - RCrmActions::eventLog('RetailCrmHistory::customerHistory', 'iblock', 'module not found'); - - return false; - } - if (!CModule::IncludeModule("sale")) { - RCrmActions::eventLog('RetailCrmHistory::customerHistory', 'sale', 'module not found'); - - return false; - } - if (!CModule::IncludeModule("catalog")) { - RCrmActions::eventLog('RetailCrmHistory::customerHistory', 'catalog', 'module not found'); - + if (!RetailcrmDependencyLoader::loadDependencies()) { return false; } @@ -62,8 +51,7 @@ class RetailCrmHistory $customerH = isset($customerHistory['history']) ? $customerHistory['history'] : array(); - $log = new Logger(); - $log->write($customerH, 'customerHistory'); + Logger::getInstance()->write($customerH, 'customerHistory'); if (count($customerH) == 0) { if ($customerHistory['history']['totalPageCount'] > $customerHistory['history']['currentPage']) { @@ -79,7 +67,7 @@ class RetailCrmHistory $GLOBALS['RETAIL_CRM_HISTORY'] = true; - $newUser = new CUser; + $newUser = new CUser(); foreach ($customers as $customer) { if (function_exists('retailCrmBeforeCustomerSave')) { @@ -107,8 +95,10 @@ class RetailCrmHistory } $registerNewUser = true; + if (!isset($customer['email']) || $customer['email'] == '') { - $login = $customer['email'] = uniqid('user_' . time()) . '@crm.com'; + $login = uniqid('user_' . time()) . '@crm.com'; + $customer['email'] = $login; } else { $dbUser = CUser::GetList(($by = 'ID'), ($sort = 'ASC'), array('=EMAIL' => $customer['email'])); switch ($dbUser->SelectedRowsCount()) { @@ -137,12 +127,23 @@ class RetailCrmHistory "CONFIRM_PASSWORD" => $userPassword ); $registeredUserID = $newUser->Add($arFields); + if ($registeredUserID === false) { - RCrmActions::eventLog('RetailCrmHistory::orderHistory', 'CUser::Register', 'Error register user: ' . $newUser->LAST_ERROR); + RCrmActions::eventLog( + 'RetailCrmHistory::orderHistory', + 'CUser::Register', + 'Error register user: ' . $newUser->LAST_ERROR + ); + continue; } - if(RCrmActions::apiMethod($api, 'customersFixExternalIds', __METHOD__, array(array('id' => $customer['id'], 'externalId' => $registeredUserID))) == false) { + if(RCrmActions::apiMethod( + $api, + 'customersFixExternalIds', + __METHOD__, + array(array('id' => $customer['id'], 'externalId' => $registeredUserID))) == false + ) { continue; } } @@ -153,13 +154,16 @@ class RetailCrmHistory if (isset($customer['externalId'])) { $arUser = array(); if (array_key_exists('firstName', $customer)) { - $arUser["NAME"] = $customer['firstName'] ? RCrmActions::fromJSON($customer['firstName']) : ''; + $arUser["NAME"] = $customer['firstName'] + ? RCrmActions::fromJSON($customer['firstName']) : ''; } if (array_key_exists('lastName', $customer)) { - $arUser["LAST_NAME"] = $customer['lastName'] ? RCrmActions::fromJSON($customer['lastName']) : ''; + $arUser["LAST_NAME"] = $customer['lastName'] + ? RCrmActions::fromJSON($customer['lastName']) : ''; } if (array_key_exists('patronymic', $customer)) { - $arUser["SECOND_NAME"] = $customer['patronymic'] ? RCrmActions::fromJSON($customer['patronymic']) : ''; + $arUser["SECOND_NAME"] = $customer['patronymic'] + ? RCrmActions::fromJSON($customer['patronymic']) : ''; } // if (array_key_exists('email', $customer)) { @@ -167,7 +171,13 @@ class RetailCrmHistory // } if (isset($customer['phones'])) { - $user = CUser::GetList(($by = "ID"), ($order = "desc"), array('ID' => $customer['externalId']), array('FIELDS' => array('PERSONAL_PHONE', 'PERSONAL_MOBILE')))->fetch(); + $user = CUser::GetList( + ($by = "ID"), + ($order = "desc"), + array('ID' => $customer['externalId']), + array('FIELDS' => array('PERSONAL_PHONE', 'PERSONAL_MOBILE')) + )->fetch(); + foreach ($customer['phones'] as $phone) { if (isset($phone['old_number']) && in_array($phone['old_number'], $user)) { $key = array_search($phone['old_number'], $user); @@ -179,13 +189,18 @@ class RetailCrmHistory $user[$key] = ''; } } + if (isset($phone['number'])) { - if ((!isset($user['PERSONAL_PHONE']) || strlen($user['PERSONAL_PHONE']) == 0) && $user['PERSONAL_MOBILE'] != $phone['number']) { + if ((!isset($user['PERSONAL_PHONE']) || strlen($user['PERSONAL_PHONE']) == 0) + && $user['PERSONAL_MOBILE'] != $phone['number'] + ) { $arUser['PERSONAL_PHONE'] = $phone['number']; $user['PERSONAL_PHONE'] = $phone['number']; continue; } - if ((!isset($user['PERSONAL_MOBILE']) || strlen($user['PERSONAL_MOBILE']) == 0) && $user['PERSONAL_PHONE'] != $phone['number']) { + if ((!isset($user['PERSONAL_MOBILE']) || strlen($user['PERSONAL_MOBILE']) == 0) + && $user['PERSONAL_PHONE'] != $phone['number'] + ) { $arUser['PERSONAL_MOBILE'] = $phone['number']; $user['PERSONAL_MOBILE'] = $phone['number']; continue; @@ -194,15 +209,33 @@ class RetailCrmHistory } } if (array_key_exists('index', $customer['address'])) { - $arUser["PERSONAL_ZIP"] = $customer['address']['index'] ? RCrmActions::fromJSON($customer['address']['index']) : ''; + $arUser["PERSONAL_ZIP"] = $customer['address']['index'] + ? RCrmActions::fromJSON($customer['address']['index']) : ''; } if (array_key_exists('city', $customer['address'])) { - $arUser["PERSONAL_CITY"] = $customer['address']['city'] ? RCrmActions::fromJSON($customer['address']['city']) : ''; + $arUser["PERSONAL_CITY"] = $customer['address']['city'] + ? RCrmActions::fromJSON($customer['address']['city']) : ''; + } + + if (array_key_exists('birthday', $customer)) { + $arUser["PERSONAL_BIRTHDAY"] = date("d.m.Y", strtotime($customer['birthday'])); + } + + if (array_key_exists('email', $customer)) { + $arUser["EMAIL"] = $customer['email'] ? RCrmActions::fromJSON($customer['email']) : ''; + } + + if (array_key_exists('sex', $customer)) { + $arUser["PERSONAL_GENDER"] = $customer['sex'] ? RCrmActions::fromJSON($customer['sex']) : ''; } $u = $newUser->Update($customer['externalId'], $arUser); if (!$u) { - RCrmActions::eventLog('RetailCrmHistory::customerHistory', 'Error update user', $newUser->LAST_ERROR); + RCrmActions::eventLog( + 'RetailCrmHistory::customerHistory', + 'Error update user', + $newUser->LAST_ERROR + ); } if (function_exists('retailCrmAfterCustomerSave')) { @@ -228,54 +261,40 @@ class RetailCrmHistory public static function orderHistory() { global $USER; + if (is_object($USER) == false) { - $USER = new RetailUser; + $USER = new RetailUser(); } - if (!CModule::IncludeModule("iblock")) { - RCrmActions::eventLog('RetailCrmHistory::orderHistory', 'iblock', 'module not found'); - - return false; - } - if (!CModule::IncludeModule("sale")) { - RCrmActions::eventLog('RetailCrmHistory::orderHistory', 'sale', 'module not found'); - - return false; - } - if (!CModule::IncludeModule("catalog")) { - RCrmActions::eventLog('RetailCrmHistory::orderHistory', 'catalog', 'module not found'); + if (!RetailcrmDependencyLoader::loadDependencies()) { return false; } - $api_host = COption::GetOptionString(self::$MODULE_ID, self::$CRM_API_HOST_OPTION, 0); - $api_key = COption::GetOptionString(self::$MODULE_ID, self::$CRM_API_KEY_OPTION, 0); + $optionsOrderTypes = RetailcrmConfigProvider::getOrderTypes(); + $optionsDelivTypes = array_flip(RetailcrmConfigProvider::getDeliveryTypes()); + $optionsPayStatuses = array_flip(RetailcrmConfigProvider::getPaymentStatuses()); // --statuses + $optionsOrderProps = RetailcrmConfigProvider::getOrderProps(); + $optionsLegalDetails = RetailcrmConfigProvider::getLegalDetails(); + $optionsSitesList = RetailcrmConfigProvider::getSitesList(); + $optionsOrderNumbers = RetailcrmConfigProvider::getOrderNumbers(); + $optionsCanselOrder = RetailcrmConfigProvider::getCancellableOrderPaymentStatuses(); + $currency = RetailcrmConfigProvider::getCurrencyOrDefault(); + $contragentTypes = array_flip(RetailcrmConfigProvider::getContragentTypes()); - $optionsOrderTypes = unserialize(COption::GetOptionString(self::$MODULE_ID, self::$CRM_ORDER_TYPES_ARR, 0)); - $optionsDelivTypes = array_flip(unserialize(COption::GetOptionString(self::$MODULE_ID, self::$CRM_DELIVERY_TYPES_ARR, 0))); - $optionsPayStatuses = array_flip(unserialize(COption::GetOptionString(self::$MODULE_ID, self::$CRM_PAYMENT_STATUSES, 0))); // --statuses - $optionsOrderProps = unserialize(COption::GetOptionString(self::$MODULE_ID, self::$CRM_ORDER_PROPS, 0)); - $optionsLegalDetails = unserialize(COption::GetOptionString(self::$MODULE_ID, self::$CRM_LEGAL_DETAILS, 0)); - $optionsSitesList = unserialize(COption::GetOptionString(self::$MODULE_ID, self::$CRM_SITES_LIST, 0)); - $optionsOrderNumbers = COption::GetOptionString(self::$MODULE_ID, self::$CRM_ORDER_NUMBERS, 0); - $optionsCanselOrder = unserialize(COption::GetOptionString(self::$MODULE_ID, self::$CRM_CANSEL_ORDER, 0)); - $optionsCurrency = COption::GetOptionString(self::$MODULE_ID, self::$CRM_CURRENCY, 0); - $currency = $optionsCurrency ? $optionsCurrency : \Bitrix\Currency\CurrencyManager::getBaseCurrency(); - - $api = new RetailCrm\ApiClient($api_host, $api_key); + $api = new RetailCrm\ApiClient(RetailcrmConfigProvider::getApiUrl(), RetailcrmConfigProvider::getApiKey()); $historyFilter = array(); $historyStart = COption::GetOptionString(self::$MODULE_ID, self::$CRM_ORDER_HISTORY); + if ($historyStart && $historyStart > 0) { $historyFilter['sinceId'] = $historyStart; } while (true) { $orderHistory = RCrmActions::apiMethod($api, 'ordersHistory', __METHOD__, $historyFilter); - $orderH = isset($orderHistory['history']) ? $orderHistory['history'] : array(); - $log = new Logger(); - $log->write($orderH, 'orderHistory'); + Logger::getInstance()->write($orderH, 'orderHistory'); if (count($orderH) == 0) { if ($orderHistory['history']['totalPageCount'] > $orderHistory['history']['currentPage']) { @@ -288,13 +307,13 @@ class RetailCrmHistory } $orders = self::assemblyOrder($orderH); - $GLOBALS['RETAIL_CRM_HISTORY'] = true; //orders with changes foreach ($orders as $order) { if (function_exists('retailCrmBeforeOrderSave')) { $newResOrder = retailCrmBeforeOrderSave($order); + if (is_array($newResOrder) && !empty($newResOrder)) { $order = $newResOrder; } elseif ($newResOrder === false) { @@ -307,19 +326,29 @@ class RetailCrmHistory } } - $log->write($order, 'assemblyOrderHistory'); + Logger::getInstance()->write($order, 'assemblyOrderHistory'); if (isset($order['deleted'])) { if (isset($order['externalId'])) { try { $newOrder = Bitrix\Sale\Order::load($order['externalId']); } catch (Bitrix\Main\ArgumentNullException $e) { - RCrmActions::eventLog('RetailCrmHistory::orderHistory', 'Bitrix\Sale\Order::load', $e->getMessage() . ': ' . $order['externalId']); + RCrmActions::eventLog( + 'RetailCrmHistory::orderHistory', + 'Bitrix\Sale\Order::load', + $e->getMessage() . ': ' . $order['externalId'] + ); + continue; } if (!$newOrder instanceof \Bitrix\Sale\Order) { - RCrmActions::eventLog('RetailCrmHistory::orderHistory', 'Bitrix\Sale\Order::load', 'Error order load: ' . $order['externalId']); + RCrmActions::eventLog( + 'RetailCrmHistory::orderHistory', + 'Bitrix\Sale\Order::load', + 'Error order load: ' . $order['externalId'] + ); + continue; } @@ -330,89 +359,203 @@ class RetailCrmHistory continue; } + if ($optionsSitesList) { + $site = array_search($order['site'], $optionsSitesList); + } else { + $site = CSite::GetDefSite(); + } + + if (empty($site)) { + RCrmActions::eventLog( + __CLASS__ . '::' . __METHOD__, + 'Bitrix\Sale\Order::create', + 'Site = ' . $order['site'] . ' not found in setting. Order crm id=' . $order['id'] + ); + + continue; + } + if (isset($order['customer']['externalId']) && !is_numeric($order['customer']['externalId'])) { unset($order['customer']['externalId']); } + $corporateContact = array(); + $orderCustomerExtId = isset($order['customer']['externalId']) ? $order['customer']['externalId'] : null; + + if (RetailCrmOrder::isOrderCorporate($order)) { + // Fetch contact only if we think it's data is not fully present in order + if (!empty($order['contact'])) { + if (isset($order['contact']['email'])) { + $corporateContact = $order['contact']; + $orderCustomerExtId = isset($corporateContact['externalId']) + ? $corporateContact['externalId'] + : null; + } else { + $response = false; + + if (isset($order['contact']['externalId'])) { + $response = RCrmActions::apiMethod( + $api, + 'customersGet', + __METHOD__, + $order['contact']['externalId'], + $order['site'] + ); + } elseif (isset($order['contact']['id'])) { + $response = RCrmActions::apiMethod( + $api, + 'customersGetById', + __METHOD__, + $order['contact']['id'], + $order['site'] + ); + } + + if ($response && isset($response['customer'])) { + $corporateContact = $response['customer']; + $orderCustomerExtId = isset($corporateContact['externalId']) + ? $corporateContact['externalId'] + : null; + } + } + } + } + if (!isset($order['externalId'])) { - if (!isset($order['customer']['externalId'])) { - if (!isset($order['customer']['id'])) { + if (empty($orderCustomerExtId)) { + if (!isset($order['customer']['id']) + || (RetailCrmOrder::isOrderCorporate($order) + && (!isset($order['contact']['id']) || !isset($order['customer']['id']))) + ) { continue; } + $login = null; $registerNewUser = true; - if (!isset($order['customer']['email']) || $order['customer']['email'] == '') { - $login = $order['customer']['email'] = uniqid('user_' . time()) . '@crm.com'; - } else { - $dbUser = CUser::GetList(($by = 'ID'), ($sort = 'ASC'), array('=EMAIL' => $order['email'])); - switch ($dbUser->SelectedRowsCount()) { - case 0: - $login = $order['customer']['email']; - break; - case 1: - $arUser = $dbUser->Fetch(); - $registeredUserID = $arUser['ID']; - $registerNewUser = false; - break; - default: - $login = uniqid('user_' . time()) . '@crm.com'; - break; + if (!isset($order['customer']['email']) || empty($order['customer']['email'])) { + if (RetailCrmOrder::isOrderCorporate($order) && !empty($corporateContact['email'])) { + $login = $corporateContact['email']; + $order['customer']['email'] = $corporateContact['email']; + } else { + $login = uniqid('user_' . time()) . '@crm.com'; + $order['customer']['email'] = $login; } } + $dbUser = CUser::GetList( + ($by = 'ID'), + ($sort = 'ASC'), + array('=EMAIL' => $order['customer']['email']) + ); + + switch ($dbUser->SelectedRowsCount()) { + case 0: + $login = $order['customer']['email']; + break; + case 1: + $arUser = $dbUser->Fetch(); + $registeredUserID = $arUser['ID']; + $registerNewUser = false; + break; + default: + $login = uniqid('user_' . time()) . '@crm.com'; + break; + } + if ($registerNewUser === true) { $userPassword = uniqid("R"); + $userData = RetailCrmOrder::isOrderCorporate($order) + ? $corporateContact + : $order['customer']; - $newUser = new CUser; + $newUser = new CUser(); $arFields = array( - "NAME" => RCrmActions::fromJSON($order['customer']['firstName']), - "LAST_NAME" => RCrmActions::fromJSON($order['customer']['lastName']), - "SECOND_NAME" => RCrmActions::fromJSON($order['customer']['patronymic']), + "NAME" => RCrmActions::fromJSON($userData['firstName']), + "LAST_NAME" => RCrmActions::fromJSON($userData['lastName']), + "SECOND_NAME" => RCrmActions::fromJSON($userData['patronymic']), "EMAIL" => $order['customer']['email'], "LOGIN" => $login, "ACTIVE" => "Y", "PASSWORD" => $userPassword, "CONFIRM_PASSWORD" => $userPassword ); - if ($order['customer']['phones'][0]) { - $arFields['PERSONAL_PHONE'] = $order['customer']['phones'][0]; + + if ($userData['phones'][0]) { + $arFields['PERSONAL_PHONE'] = $userData['phones'][0]; } - if ($order['customer']['phones'][1]) { - $arFields['PERSONAL_MOBILE'] = $order['customer']['phones'][1]; + + if ($userData['phones'][1]) { + $arFields['PERSONAL_MOBILE'] = $userData['phones'][1]; } $registeredUserID = $newUser->Add($arFields); if ($registeredUserID === false) { - RCrmActions::eventLog('RetailCrmHistory::orderHistory', 'CUser::Register', 'Error register user' . $newUser->LAST_ERROR); + RCrmActions::eventLog( + 'RetailCrmHistory::orderHistory', + 'CUser::Register', + 'Error register user' . $newUser->LAST_ERROR + ); continue; } - if(RCrmActions::apiMethod($api, 'customersFixExternalIds', __METHOD__, array(array('id' => $order['customer']['id'], 'externalId' => $registeredUserID))) == false) { + if(RCrmActions::apiMethod( + $api, + 'customersFixExternalIds', + __METHOD__, + array(array( + 'id' => $order['customer']['id'], + 'externalId' => $registeredUserID + ))) == false + ) { continue; } } - $order['customer']['externalId'] = $registeredUserID; + $orderCustomerExtId = isset($registeredUserID) ? $registeredUserID : null; } - if ($optionsSitesList) { - $site = array_search($order['site'], $optionsSitesList); - } else { - $site = CSite::GetDefSite(); - } - if (empty($site)) { - RCrmActions::eventLog('RetailCrmHistory::orderHistory', 'Bitrix\Sale\Order::create', 'Site = ' . $order['site'] . ' not found in setting. Order crm id=' . $order['id']); + $buyerProfileToAppend = array(); - continue; + if (RetailCrmOrder::isOrderCorporate($order) && !empty($order['company'])) { + $buyerProfile = array( + "NAME" => $order['company']['name'], + "USER_ID" => $order['contact']['externalId'], + "PERSON_TYPE_ID" => $contragentTypes['legal-entity'] + ); + + $buyerProfileToAppend = Bitrix\Sale\OrderUserProperties::getList(array( + "filter" => $buyerProfile + ))->fetch(); + + if (empty($buyerProfileToAppend)) { + $buyerProfileInstance = new CSaleOrderUserProps(); + + if ($buyerProfileInstance->Add($buyerProfile)) { + $buyerProfileToAppend = Bitrix\Sale\OrderUserProperties::getList(array( + "filter" => $buyerProfile + ))->fetch(); + } + } } - $newOrder = Bitrix\Sale\Order::create($site, $order['customer']['externalId'], $currency); + $newOrder = Bitrix\Sale\Order::create($site, $orderCustomerExtId, $currency); + + if (isset($buyerProfileToAppend['ID']) && isset($optionsLegalDetails['legalName'])) { + $newOrder->setFields(array( + $optionsLegalDetails['legalName'] => $buyerProfileToAppend['NAME'], + 'PERSON_TYPE_ID' => $buyerProfileToAppend['PERSON_TYPE_ID'] + )); + } if (!is_object($newOrder) || !$newOrder instanceof \Bitrix\Sale\Order) { - RCrmActions::eventLog('RetailCrmHistory::orderHistory', 'Bitrix\Sale\Order::create', 'Error order create'); + RCrmActions::eventLog( + 'RetailCrmHistory::orderHistory', + 'Bitrix\Sale\Order::create', + 'Error order create' + ); continue; } @@ -428,14 +571,22 @@ class RetailCrmHistory try { $newOrder = Bitrix\Sale\Order::load($order['externalId']); } catch (Bitrix\Main\ArgumentNullException $e) { - RCrmActions::eventLog('RetailCrmHistory::orderHistory', 'Bitrix\Sale\Order::load', $e->getMessage() . ': ' . $order['externalId']); + RCrmActions::eventLog( + 'RetailCrmHistory::orderHistory', + 'Bitrix\Sale\Order::load', + $e->getMessage() . ': ' . $order['externalId'] + ); continue; } } if (!isset($newOrder) || $newOrder === null) { - RCrmActions::eventLog('RetailCrmHistory::orderHistory', 'Bitrix\Sale\Order::load', 'Error order load number=' . $order['number']); + RCrmActions::eventLog( + 'RetailCrmHistory::orderHistory', + 'Bitrix\Sale\Order::load', + 'Error order load number=' . $order['number'] + ); continue; } @@ -447,36 +598,59 @@ class RetailCrmHistory } if (empty($site)) { - RCrmActions::eventLog('RetailCrmHistory::orderHistory', 'Bitrix\Sale\Order::edit', 'Site = ' . $order['site'] . ' not found in setting. Order number=' . $order['number']); + RCrmActions::eventLog( + 'RetailCrmHistory::orderHistory', + 'Bitrix\Sale\Order::edit', + sprintf( + 'Site = %s not found in settings. Order number = %s', + $order['site'], + $order['number'] + ) + ); continue; } + $propsRemove = false; $personType = $newOrder->getField('PERSON_TYPE_ID'); - if (isset($order['orderType']) && $order['orderType']) { - $nType = array(); - $tList = RCrmActions::OrderTypesList(array(array('LID' => $site))); - foreach($tList as $type){ - if (isset($optionsOrderTypes[$type['ID']])) { - $nType[$optionsOrderTypes[$type['ID']]] = $type['ID']; - } - } - $newOptionsOrderTypes = $nType; - if ($newOptionsOrderTypes[$order['orderType']]) { - if ($personType != $newOptionsOrderTypes[$order['orderType']] && $personType != 0) { - $propsRemove = true; + if (RetailCrmOrder::isOrderCorporate($order)) { + $newOrder->setField('PERSON_TYPE_ID', $contragentTypes['legal-entity']); + $personType = $contragentTypes['legal-entity']; + } else { + if (isset($order['orderType']) && $order['orderType']) { + $nType = array(); + $tList = RCrmActions::OrderTypesList(array(array('LID' => $site))); + + foreach($tList as $type){ + if (isset($optionsOrderTypes[$type['ID']])) { + $nType[$optionsOrderTypes[$type['ID']]] = $type['ID']; + } + } + + $newOptionsOrderTypes = $nType; + + if ($newOptionsOrderTypes[$order['orderType']]) { + if ($personType != $newOptionsOrderTypes[$order['orderType']] && $personType != 0) { + $propsRemove = true; + } + + $personType = $newOptionsOrderTypes[$order['orderType']]; + $newOrder->setField('PERSON_TYPE_ID', $personType); + } elseif ($personType == 0) { + RCrmActions::eventLog( + 'RetailCrmHistory::orderHistory', + 'orderType not found', + 'PERSON_TYPE_ID = 0' + ); } - $personType = $newOptionsOrderTypes[$order['orderType']]; - $newOrder->setField('PERSON_TYPE_ID', $personType); - } elseif ($personType == 0) { - RCrmActions::eventLog('RetailCrmHistory::orderHistory', 'orderType not found', 'PERSON_TYPE_ID = 0'); } } //status if ($optionsPayStatuses[$order['status']]) { $newOrder->setField('STATUS_ID', $optionsPayStatuses[$order['status']]); + if (in_array($optionsPayStatuses[$order['status']], $optionsCanselOrder)) { self::unreserveShipment($newOrder); $newOrder->setFieldNoDemand('CANCELED', 'Y'); @@ -486,13 +660,18 @@ class RetailCrmHistory } if (array_key_exists('statusComment', $order)) { - self::setProp($newOrder, RCrmActions::fromJSON($order['statusComment']), 'REASON_CANCELED'); + self::setProp( + $newOrder, + RCrmActions::fromJSON($order['statusComment']), + 'REASON_CANCELED' + ); } //props $propertyCollection = $newOrder->getPropertyCollection(); $propertyCollectionArr = $propertyCollection->getArray(); $nProps = array(); + foreach ($propertyCollectionArr['properties'] as $orderProp) { if ($orderProp['ID'][0] == 'n') { $orderProp['ID'] = substr($orderProp['ID'], 1); @@ -504,8 +683,11 @@ class RetailCrmHistory continue; } } + $nProps[] = $orderProp; } + + $orderDump = array(); $propertyCollectionArr['properties'] = $nProps; if ($propsRemove) {//delete props @@ -515,6 +697,7 @@ class RetailCrmHistory self::setProp($somePropValue); } } + $orderCrm = RCrmActions::apiMethod($api, 'orderGet', __METHOD__, $order['id']); $orderDump = $order; @@ -522,13 +705,15 @@ class RetailCrmHistory } $propsKey = array(); + foreach ($propertyCollectionArr['properties'] as $prop) { if ($prop['PROPS_GROUP_ID'] != 0) { $propsKey[$prop['CODE']]['ID'] = $prop['ID']; $propsKey[$prop['CODE']]['TYPE'] = $prop['TYPE']; } } - //fio + + // fio if ($order['firstName'] || $order['lastName'] || $order['patronymic']) { $fio = ''; foreach ($propertyCollectionArr['properties'] as $prop) { @@ -543,9 +728,16 @@ class RetailCrmHistory $fio = RCrmActions::explodeFIO($fio); $newFio = array(); if ($fio) { - $newFio[] = isset($order['lastName']) ? RCrmActions::fromJSON($order['lastName']) : (isset($fio['lastName']) ? $fio['lastName'] : ''); - $newFio[] = isset($order['firstName']) ? RCrmActions::fromJSON($order['firstName']) : (isset($fio['firstName']) ? $fio['firstName'] : ''); - $newFio[] = isset($order['patronymic']) ? RCrmActions::fromJSON($order['patronymic']) : (isset($fio['patronymic']) ? $fio['patronymic'] : ''); + $newFio[] = isset($order['lastName']) + ? RCrmActions::fromJSON($order['lastName']) + : (isset($fio['lastName']) ? $fio['lastName'] : ''); + $newFio[] = isset($order['firstName']) + ? RCrmActions::fromJSON($order['firstName']) + : (isset($fio['firstName']) ? $fio['firstName'] : ''); + $newFio[] = isset($order['patronymic']) + ? RCrmActions::fromJSON($order['patronymic']) + : (isset($fio['patronymic']) ? $fio['patronymic'] : ''); + $order['fio'] = trim(implode(' ', $newFio)); } else { $newFio[] = isset($order['lastName']) ? RCrmActions::fromJSON($order['lastName']) : ''; @@ -559,7 +751,9 @@ class RetailCrmHistory if ($optionsOrderProps[$personType]) { foreach ($optionsOrderProps[$personType] as $key => $orderProp) { if (array_key_exists($key, $order)) { - $somePropValue = $propertyCollection->getItemByOrderPropertyId($propsKey[$orderProp]['ID']); + $somePropValue = $propertyCollection + ->getItemByOrderPropertyId($propsKey[$orderProp]['ID']); + if ($key == 'fio') { self::setProp($somePropValue, $order[$key]); } else { @@ -570,6 +764,7 @@ class RetailCrmHistory if( $order['delivery']['address']['index'] ) { $location = CSaleLocation::GetByZIP($order['delivery']['address']['index']); } + $order['delivery']['address'][$key] = trim($order['delivery']['address'][$key]); if(!empty($order['delivery']['address'][$key])){ $parameters = array(); @@ -579,7 +774,16 @@ class RetailCrmHistory } elseif (count($loc) == 2) { $parameters['filter']['PHRASE'] = RCrmActions::fromJSON(trim($loc[1])); } else { - RCrmActions::eventLog('RetailCrmHistory::orderHistory', 'RetailCrmHistory::setProp', 'Error location. ' . $order['delivery']['address'][$key] . ' not found add in order number=' . $order['number']); + RCrmActions::eventLog( + 'RetailCrmHistory::orderHistory', + 'RetailCrmHistory::setProp', + sprintf( + 'Error location. %s not found add in order number = %s', + $order['delivery']['address'][$key], + $order['number'] + ) + ); + continue; } @@ -587,35 +791,90 @@ class RetailCrmHistory try { if ( !isset($location) ) { - $location = \Bitrix\Sale\Location\Search\Finder::find($parameters, array('USE_INDEX' => false, 'USE_ORM' => false))->fetch(); + $location = \Bitrix\Sale\Location\Search\Finder::find( + $parameters, + array('USE_INDEX' => false, 'USE_ORM' => false) + )->fetch(); } - $somePropValue = $propertyCollection->getItemByOrderPropertyId($propsKey[$orderProp]['ID']); + + $somePropValue = $propertyCollection + ->getItemByOrderPropertyId($propsKey[$orderProp]['ID']); + self::setProp($somePropValue, $location['CODE']); } catch (\Bitrix\Main\ArgumentException $argumentException) { - RCrmActions::eventLog('RetailCrmHistory::orderHistory', 'RetailCrmHistory::setProp', 'Location parameter is incorrect in order number=' . $order['number']); + RCrmActions::eventLog( + 'RetailCrmHistory::orderHistory', + 'RetailCrmHistory::setProp', + 'Location parameter is incorrect in order number=' . $order['number'] + ); } } else { - RCrmActions::eventLog('RetailCrmHistory::orderHistory', 'RetailCrmHistory::setProp', 'Error location. ' . $order['delivery']['address'][$key] . ' is empty in order number=' . $order['number']); + RCrmActions::eventLog( + 'RetailCrmHistory::orderHistory', + 'RetailCrmHistory::setProp', + sprintf( + 'Error location. %s is empty in order number=%s', + $order['delivery']['address'][$key], + $order['number'] + ) + ); continue; } } else { - $somePropValue = $propertyCollection->getItemByOrderPropertyId($propsKey[$orderProp]['ID']); - self::setProp($somePropValue, RCrmActions::fromJSON($order['delivery']['address'][$key])); + $somePropValue = $propertyCollection + ->getItemByOrderPropertyId($propsKey[$orderProp]['ID']); + self::setProp( + $somePropValue, + RCrmActions::fromJSON($order['delivery']['address'][$key]) + ); } } } } - //optionsLegalDetails + // Corporate clients section if ($optionsLegalDetails[$personType]) { foreach ($optionsLegalDetails[$personType] as $key => $orderProp) { if (array_key_exists($key, $order)) { - $somePropValue = $propertyCollection->getItemByOrderPropertyId($propsKey[$orderProp]['ID']); + $somePropValue = $propertyCollection + ->getItemByOrderPropertyId($propsKey[$orderProp]['ID']); + self::setProp($somePropValue, RCrmActions::fromJSON($order[$key])); } elseif(array_key_exists($key, $order['contragent'])) { - $somePropValue = $propertyCollection->getItemByOrderPropertyId($propsKey[$orderProp]['ID']); + $somePropValue = $propertyCollection + ->getItemByOrderPropertyId($propsKey[$orderProp]['ID']); self::setProp($somePropValue, RCrmActions::fromJSON($order['contragent'][$key])); + } elseif (isset($order['company']) && (array_key_exists($key, $order['company']) + || array_key_exists( + lcfirst(str_replace('legal', '', $key)), + $order['company']) + ) + ) { + $somePropValue = $propertyCollection + ->getItemByOrderPropertyId($propsKey[$orderProp]['ID']); + + // fallback for order[company][name] + if ($key == 'legalName') { + $key = 'name'; + } + + self::setProp( + $somePropValue, + RCrmActions::fromJSON( + $key == 'legalAddress' + ? (isset($order['company']['address']['text']) + ? $order['company']['address']['text'] + : '') + : $order['company'][$key] + ) + ); + } elseif (isset($order['company']['contragent']) + && array_key_exists($key, $order['company']['contragent']) + ) { + $somePropValue = $propertyCollection + ->getItemByOrderPropertyId($propsKey[$orderProp]['ID']); + self::setProp($somePropValue, RCrmActions::fromJSON($order['company']['contragent'][$key])); } } } @@ -704,8 +963,9 @@ class RetailCrmHistory } } - $log->write($duplicateItems, 'duplicateItemsOrderHistory'); - $log->write($collectItems, 'collectItemsOrderHistory'); + Logger::getInstance()->write($duplicateItems, 'duplicateItemsOrderHistory'); + Logger::getInstance()->write($collectItems, 'collectItemsOrderHistory'); + $optionDiscRound = COption::GetOptionString(self::$MODULE_ID, self::$CRM_DISCOUNT_ROUND, 0); foreach ($order['items'] as $product) { @@ -740,7 +1000,11 @@ class RetailCrmHistory 'CATALOG_XML_ID' => $elem["IBLOCK_XML_ID"] )); } else { - RCrmActions::eventLog('RetailCrmHistory::orderHistory', 'createItem', 'Error item add'); + RCrmActions::eventLog( + 'RetailCrmHistory::orderHistory', + 'createItem', + 'Error item add' + ); continue; } @@ -786,6 +1050,7 @@ class RetailCrmHistory } $orderSumm = 0; + foreach ($basket as $item) { $orderSumm += $item->getFinalPrice(); } @@ -815,10 +1080,12 @@ class RetailCrmHistory //delivery if (array_key_exists('delivery', $order)) { $itemUpdate = true; + //delete empty if (!isset($orderCrm)) { $orderCrm = RCrmActions::apiMethod($api, 'orderGet', __METHOD__, $order['id']); } + if ($orderCrm) { self::deliveryUpdate($newOrder, $optionsDelivTypes, $orderCrm['order']); } @@ -847,7 +1114,12 @@ class RetailCrmHistory $paymentId = $orderPayment->getId(); $paymentExternalId = RCrmActions::generatePaymentExternalId($paymentId); if (is_null($paymentId)) { - RCrmActions::eventLog('RetailCrmHistory::orderHistory', 'paymentsUpdate', 'Save payment error, order=' . $order['number']); + RCrmActions::eventLog( + 'RetailCrmHistory::orderHistory', + 'paymentsUpdate', + 'Save payment error, order=' . $order['number'] + ); + continue; } @@ -855,7 +1127,13 @@ class RetailCrmHistory if ($paymentExternalId) { $newHistoryPayments[$orderPayment->getField('XML_ID')]['externalId'] = $paymentExternalId; - RCrmActions::apiMethod($api, 'paymentEditById', __METHOD__, $newHistoryPayments[$orderPayment->getField('XML_ID')]); + RCrmActions::apiMethod( + $api, + 'paymentEditById', + __METHOD__, + $newHistoryPayments[$orderPayment->getField('XML_ID')] + ); + if ($paymentId) { \Bitrix\Sale\Internals\PaymentTable::update($paymentId, array('XML_ID' => '')); } @@ -866,7 +1144,13 @@ class RetailCrmHistory if (!$order['externalId']) { $order["externalId"] = $newOrder->getId(); - if (RCrmActions::apiMethod($api, 'ordersFixExternalIds', __METHOD__, array(array('id' => $order['id'], 'externalId' => $newOrder->getId()))) == false){ + + if (RCrmActions::apiMethod( + $api, + 'ordersFixExternalIds', + __METHOD__, + array(array('id' => $order['id'], 'externalId' => $newOrder->getId()))) == false + ) { continue; } } @@ -891,6 +1175,8 @@ class RetailCrmHistory //new filter $historyFilter['sinceId'] = $end['id']; } + + return false; } /** @@ -937,6 +1223,18 @@ class RetailCrmHistory unset($change['customer']['contragent']); } + if ($change['field'] == 'segments') { + if ($change['newValue']['code'] == "genshchini") { + $customers[$change['customer']['id']]["sex"] = "F"; + } + } + + if ($change['field'] == 'segments') { + if ($change['newValue']['code'] == "mugchini") { + $customers[$change['customer']['id']]["sex"] = "M"; + } + } + if ($fields['customer'][$change['field']] == 'phones') { $key = count($customers[$change['customer']['id']]['phones']); if (isset($change['oldValue'])) { @@ -972,13 +1270,19 @@ class RetailCrmHistory public static function assemblyOrder($orderHistory) { $server = \Bitrix\Main\Context::getCurrent()->getServer()->getDocumentRoot(); + if (file_exists($server . '/bitrix/modules/intaro.retailcrm/classes/general/config/objects.xml')) { - $objects = simplexml_load_file($server . '/bitrix/modules/intaro.retailcrm/classes/general/config/objects.xml'); + $objects = simplexml_load_file( + $server . '/bitrix/modules/intaro.retailcrm/classes/general/config/objects.xml' + ); + foreach ($objects->fields->field as $object) { $fields[(string)$object["group"]][(string)$object["id"]] = (string)$object; } } + $orders = array(); + foreach ($orderHistory as $change) { $change['order'] = self::removeEmpty($change['order']); if ($change['order']['items']) { @@ -992,6 +1296,10 @@ class RetailCrmHistory $change['order']['items'] = $items; } + if ($change['field'] == 'number') { + $orders[$change['order']['id']]['number'] = $change['newValue']; + } + if ($change['order']['payments']) { $payments = array(); foreach ($change['order']['payments'] as $payment) { @@ -1013,10 +1321,6 @@ class RetailCrmHistory $orders[$change['order']['id']] = $change['order']; } - if ($change['field'] == 'number') { - $orders[$change['order']['id']]['number'] = $change['newValue']; - } - if ($change['item']) { if ($orders[$change['order']['id']]['items'][$change['item']['id']]) { $orders[$change['order']['id']]['items'][$change['item']['id']] = array_merge($orders[$change['order']['id']]['items'][$change['item']['id']], $change['item']); @@ -1345,9 +1649,23 @@ class RetailCrmHistory return $outputArray; } + /** + * setProp + * + * @param \Bitrix\Sale\PropertyValueBase|\Bitrix\Sale\Order $obj + * @param string $value + * @param string $prop + * + * @return bool + * @throws \Bitrix\Main\ArgumentNullException + * @throws \Bitrix\Main\ArgumentOutOfRangeException + * @throws \Bitrix\Main\NotImplementedException + * @throws \Bitrix\Main\ObjectNotFoundException + * @throws \Bitrix\Main\ArgumentException + */ public static function setProp($obj, $value = '', $prop = '') { - if (!isset($obj)) { + if (!isset($obj) || empty($obj)) { return false; } if ($prop && $value) { diff --git a/intaro.retailcrm/classes/general/inventories/RetailCrmInventories.php b/intaro.retailcrm/classes/general/inventories/RetailCrmInventories.php index 1e8683b8..02a04d0e 100644 --- a/intaro.retailcrm/classes/general/inventories/RetailCrmInventories.php +++ b/intaro.retailcrm/classes/general/inventories/RetailCrmInventories.php @@ -2,13 +2,6 @@ IncludeModuleLangFile(__FILE__); class RetailCrmInventories { - public static $MODULE_ID = 'intaro.retailcrm'; - public static $CRM_API_HOST_OPTION = 'api_host'; - public static $CRM_API_KEY_OPTION = 'api_key'; - public static $CRM_INVENTORIES_UPLOAD = 'inventories_upload'; - public static $CRM_STORES = 'stores'; - public static $CRM_SHOPS = 'shops'; - public static $CRM_IBLOCKS_INVENTORIES = 'iblocks_inventories'; public static $pageSize = 500; public static function inventoriesUpload() @@ -29,13 +22,10 @@ class RetailCrmInventories return false; } - $api_host = COption::GetOptionString(self::$MODULE_ID, self::$CRM_API_HOST_OPTION, 0); - $api_key = COption::GetOptionString(self::$MODULE_ID, self::$CRM_API_KEY_OPTION, 0); - $api = new RetailCrm\ApiClient($api_host, $api_key); - - $infoBlocks = unserialize(COption::GetOptionString(self::$MODULE_ID, self::$CRM_IBLOCKS_INVENTORIES, 0)); - $stores = unserialize(COption::GetOptionString(self::$MODULE_ID, self::$CRM_STORES, 0)); - $shops = unserialize(COption::GetOptionString(self::$MODULE_ID, self::$CRM_SHOPS, 0)); + $api = new RetailCrm\ApiClient(RetailcrmConfigProvider::getApiUrl(), RetailcrmConfigProvider::getApiKey()); + $infoBlocks = RetailcrmConfigProvider::getInfoblocksInventories(); + $stores = RetailcrmConfigProvider::getStores(); + $shops = RetailcrmConfigProvider::getShops(); try { $inventoriesList = $api->storesList()->stores; @@ -65,8 +55,6 @@ class RetailCrmInventories } if (count($infoBlocks) > 0) { - $log = new Logger(); - foreach ($infoBlocks as $id) { $iblockOffer = CCatalogSKU::GetInfoByProductIBlock($id); @@ -128,7 +116,7 @@ class RetailCrmInventories //for log $splitedItems = array_chunk($invUpload, 200); foreach ($splitedItems as $chunk) { - $log->write($chunk, 'inventoriesUpload'); + Logger::getInstance()->write($chunk, 'inventoriesUpload'); foreach ($shops as $shop) { RCrmActions::apiMethod($api, 'storeInventoriesUpload', __METHOD__, $chunk, $shop); diff --git a/intaro.retailcrm/classes/general/order/RetailCrmOrder_v4.php b/intaro.retailcrm/classes/general/order/RetailCrmOrder_v4.php index a3312917..7bcdac26 100644 --- a/intaro.retailcrm/classes/general/order/RetailCrmOrder_v4.php +++ b/intaro.retailcrm/classes/general/order/RetailCrmOrder_v4.php @@ -40,14 +40,13 @@ class RetailCrmOrder if (!$api || empty($arParams)) { // add cond to check $arParams return false; } + if (empty($arFields)) { RCrmActions::eventLog('RetailCrmOrder::orderSend', 'empty($arFields)', 'incorrect order'); return false; } - $optionsCurrency = COption::GetOptionString(self::$MODULE_ID, self::$CRM_CURRENCY, 0); - $currency = $optionsCurrency ? $optionsCurrency : \Bitrix\Currency\CurrencyManager::getBaseCurrency(); - + $currency = RetailcrmConfigProvider::getCurrencyOrDefault(); $order = array( 'number' => $arFields['NUMBER'], 'externalId' => $arFields['ID'], @@ -67,9 +66,11 @@ class RetailCrmOrder 'cost' => $arFields['PRICE_DELIVERY'] ), ); + if ($send && isset($_COOKIE['_rc']) && $_COOKIE['_rc'] != '') { $order['customer']['browserId'] = $_COOKIE['_rc']; } + $order['contragent']['contragentType'] = $arParams['optionsContragentType'][$arFields['PERSON_TYPE_ID']]; //fields @@ -175,8 +176,7 @@ class RetailCrmOrder $normalizer = new RestNormalizer(); $order = $normalizer->normalize($order, 'orders'); - $log = new Logger(); - $log->write($order, 'orderSend'); + Logger::getInstance()->write($order, 'orderSend'); if($send) { if (!RCrmActions::apiMethod($api, $methodApi, __METHOD__, $order, $site)) { @@ -189,31 +189,29 @@ class RetailCrmOrder /** * Mass order uploading, without repeating; always returns true, but writes error log - * @param $pSize - * @param $failed -- flag to export failed orders + * + * @param int $pSize + * @param bool $failed -- flag to export failed orders + * @param bool $orderList + * * @return boolean + * @throws \Bitrix\Main\ArgumentNullException + * @throws \Bitrix\Main\ObjectPropertyException + * @throws \Bitrix\Main\SystemException + * @throws \Bitrix\Main\ArgumentException */ public static function uploadOrders($pSize = 50, $failed = false, $orderList = false) { - if (!CModule::IncludeModule("iblock")) { - RCrmActions::eventLog('RetailCrmOrder::uploadOrders', 'iblock', 'module not found'); - return true; - } - if (!CModule::IncludeModule("sale")) { - RCrmActions::eventLog('RetailCrmOrder::uploadOrders', 'sale', 'module not found'); - return true; - } - if (!CModule::IncludeModule("catalog")) { - RCrmActions::eventLog('RetailCrmOrder::uploadOrders', 'catalog', 'module not found'); - return true; + if (!RetailcrmDependencyLoader::loadDependencies()) { + return false; } $resOrders = array(); $resCustomers = array(); $orderIds = array(); - $lastUpOrderId = COption::GetOptionString(self::$MODULE_ID, self::$CRM_ORDER_LAST_ID, 0); - $failedIds = unserialize(COption::GetOptionString(self::$MODULE_ID, self::$CRM_ORDER_FAILED_IDS, 0)); + $lastUpOrderId = RetailcrmConfigProvider::getLastOrderId(); + $failedIds = RetailcrmConfigProvider::getFailedOrdersIds(); if ($failed == true && $failedIds !== false && count($failedIds) > 0) { $orderIds = $failedIds; @@ -238,18 +236,18 @@ class RetailCrmOrder $api_host = COption::GetOptionString(self::$MODULE_ID, self::$CRM_API_HOST_OPTION, 0); $api_key = COption::GetOptionString(self::$MODULE_ID, self::$CRM_API_KEY_OPTION, 0); - $optionsSitesList = unserialize(COption::GetOptionString(self::$MODULE_ID, self::$CRM_SITES_LIST, 0)); - $optionsOrderTypes = unserialize(COption::GetOptionString(self::$MODULE_ID, self::$CRM_ORDER_TYPES_ARR, 0)); - $optionsDelivTypes = unserialize(COption::GetOptionString(self::$MODULE_ID, self::$CRM_DELIVERY_TYPES_ARR, 0)); - $optionsPayTypes = unserialize(COption::GetOptionString(self::$MODULE_ID, self::$CRM_PAYMENT_TYPES, 0)); - $optionsPayStatuses = unserialize(COption::GetOptionString(self::$MODULE_ID, self::$CRM_PAYMENT_STATUSES, 0)); // --statuses - $optionsPayment = unserialize(COption::GetOptionString(self::$MODULE_ID, self::$CRM_PAYMENT, 0)); - $optionsOrderProps = unserialize(COption::GetOptionString(self::$MODULE_ID, self::$CRM_ORDER_PROPS, 0)); - $optionsLegalDetails = unserialize(COption::GetOptionString(self::$MODULE_ID, self::$CRM_LEGAL_DETAILS, 0)); - $optionsContragentType = unserialize(COption::GetOptionString(self::$MODULE_ID, self::$CRM_CONTRAGENT_TYPE, 0)); - $optionsCustomFields = unserialize(COption::GetOptionString(self::$MODULE_ID, self::$CRM_CUSTOM_FIELDS, 0)); + $optionsSitesList = RetailcrmConfigProvider::getSitesList(); + $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(); - $api = new RetailCrm\ApiClient($api_host, $api_key); + $api = new RetailCrm\ApiClient(RetailcrmConfigProvider::getApiUrl(), RetailcrmConfigProvider::getApiKey()); $arParams = array( 'optionsOrderTypes' => $optionsOrderTypes, @@ -333,6 +331,18 @@ class RetailCrmOrder return true; } + /** + * Returns true if provided order array is corporate order data. v4 doesn't have corporate orders. + * + * @param array|\ArrayAccess $order + * + * @return bool + */ + public static function isOrderCorporate($order) + { + return false; + } + public static function orderObjToArr($obOrder) { $culture = new \Bitrix\Main\Context\Culture(array("FORMAT_DATETIME" => "Y-m-d HH:i:s")); diff --git a/intaro.retailcrm/classes/general/order/RetailCrmOrder_v5.php b/intaro.retailcrm/classes/general/order/RetailCrmOrder_v5.php index eae98ebf..90071528 100644 --- a/intaro.retailcrm/classes/general/order/RetailCrmOrder_v5.php +++ b/intaro.retailcrm/classes/general/order/RetailCrmOrder_v5.php @@ -2,29 +2,6 @@ IncludeModuleLangFile(__FILE__); class RetailCrmOrder { - public static $MODULE_ID = 'intaro.retailcrm'; - public static $CRM_API_HOST_OPTION = 'api_host'; - public static $CRM_API_KEY_OPTION = 'api_key'; - public static $CRM_ORDER_TYPES_ARR = 'order_types_arr'; - public static $CRM_DELIVERY_TYPES_ARR = 'deliv_types_arr'; - public static $CRM_PAYMENT_TYPES = 'pay_types_arr'; - public static $CRM_PAYMENT_STATUSES = 'pay_statuses_arr'; - public static $CRM_PAYMENT = 'payment_arr'; //order payment Y/N - public static $CRM_ORDER_LAST_ID = 'order_last_id'; - public static $CRM_SITES_LIST = 'sites_list'; - public static $CRM_ORDER_PROPS = 'order_props'; - public static $CRM_LEGAL_DETAILS = 'legal_details'; - public static $CRM_CUSTOM_FIELDS = 'custom_fields'; - public static $CRM_CONTRAGENT_TYPE = 'contragent_type'; - public static $CRM_ORDER_FAILED_IDS = 'order_failed_ids'; - public static $CRM_ORDER_HISTORY_DATE = 'order_history_date'; - public static $CRM_CATALOG_BASE_PRICE = 'catalog_base_price'; - public static $CRM_ORDER_NUMBERS = 'order_numbers'; - public static $CRM_ORDER_DIMENSIONS = 'order_dimensions'; - public static $CRM_CURRENCY = 'currency'; - - const CANCEL_PROPERTY_CODE = 'INTAROCRM_IS_CANCELED'; - /** * * Creates order or returns order for mass upload @@ -51,15 +28,17 @@ class RetailCrmOrder return false; } - $dimensionsSetting = COption::GetOptionString(self::$MODULE_ID, self::$CRM_ORDER_DIMENSIONS, 'N'); - $optionsCurrency = COption::GetOptionString(self::$MODULE_ID, self::$CRM_CURRENCY, 0); - $currency = $optionsCurrency ? $optionsCurrency : \Bitrix\Currency\CurrencyManager::getBaseCurrency(); + $dimensionsSetting = RetailcrmConfigProvider::getOrderDimensions(); + $currency = RetailcrmConfigProvider::getCurrencyOrDefault(); + $optionCorpClient = RetailcrmConfigProvider::getCorporateClientStatus(); $order = array( 'number' => $arFields['NUMBER'], 'externalId' => $arFields['ID'], 'createdAt' => $arFields['DATE_INSERT'], - 'customer' => array('externalId' => $arFields['USER_ID']), + 'customer' => isset($arParams['customerCorporate']) + ? array('id' => $arParams['customerCorporate']['id']) + : array('externalId' => $arFields['USER_ID']), 'orderType' => isset($arParams['optionsOrderTypes'][$arFields['PERSON_TYPE_ID']]) ? $arParams['optionsOrderTypes'][$arFields['PERSON_TYPE_ID']] : '', 'status' => isset($arParams['optionsPayStatuses'][$arFields['STATUS_ID']]) ? @@ -70,9 +49,27 @@ class RetailCrmOrder 'cost' => $arFields['PRICE_DELIVERY'] ), ); + + 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']; + } + } + if ($send && isset($_COOKIE['_rc']) && $_COOKIE['_rc'] != '') { $order['customer']['browserId'] = $_COOKIE['_rc']; } + $order['contragent']['contragentType'] = $arParams['optionsContragentType'][$arFields['PERSON_TYPE_ID']]; if ($methodApi == 'ordersEdit') { @@ -103,15 +100,18 @@ class RetailCrmOrder if ($arLoc) { $server = \Bitrix\Main\Context::getCurrent()->getServer()->getDocumentRoot(); $countrys = array(); + if (file_exists($server . '/bitrix/modules/intaro.retailcrm/classes/general/config/country.xml')) { $countrysFile = simplexml_load_file($server . '/bitrix/modules/intaro.retailcrm/classes/general/config/country.xml'); foreach ($countrysFile->country as $country) { $countrys[RCrmActions::fromJSON((string) $country->name)] = (string) $country->alpha; } } + $location = \Bitrix\Sale\Location\Name\LocationTable::getList(array( 'filter' => array('=LOCATION_ID' => $arLoc['CITY_ID'], 'LANGUAGE_ID' => 'ru') ))->fetch(); + if (count($countrys) > 0) { $countryOrder = \Bitrix\Sale\Location\Name\LocationTable::getList(array( 'filter' => array('=LOCATION_ID' => $arLoc['COUNTRY_ID'], 'LANGUAGE_ID' => 'ru') @@ -156,7 +156,7 @@ class RetailCrmOrder //basket foreach ($arFields['BASKET'] as $position => $product) { - $externalId = $position ."_". $product['PRODUCT_ID']; + $externalId = $position . "_" . $product['PRODUCT_ID']; if (isset($orderItems[$externalId])) { //update $externalIds = $orderItems[$externalId]['externalIds']; $key = array_search("bitrix", array_column($externalIds, 'code')); @@ -181,7 +181,7 @@ class RetailCrmOrder } $item = array( - 'externalIds' => $externalIds, + 'externalIds' => $externalIds, 'quantity' => $product['QUANTITY'], 'offer' => array('externalId' => $product['PRODUCT_ID'], 'xmlId' => $product['PRODUCT_XML_ID'] @@ -287,10 +287,9 @@ class RetailCrmOrder $normalizer = new RestNormalizer(); $order = $normalizer->normalize($order, 'orders'); - $log = new Logger(); - $log->write($order, 'orderSend'); + Logger::getInstance()->write($order, 'orderSend'); - if($send) { + if ($send) { if (!RCrmActions::apiMethod($api, $methodApi, __METHOD__, $order, $site)) { return false; } @@ -314,25 +313,18 @@ class RetailCrmOrder */ public static function uploadOrders($pSize = 50, $failed = false, $orderList = false) { - if (!CModule::IncludeModule("iblock")) { - RCrmActions::eventLog('RetailCrmOrder::uploadOrders', 'iblock', 'module not found'); - return true; - } - if (!CModule::IncludeModule("sale")) { - RCrmActions::eventLog('RetailCrmOrder::uploadOrders', 'sale', 'module not found'); - return true; - } - if (!CModule::IncludeModule("catalog")) { - RCrmActions::eventLog('RetailCrmOrder::uploadOrders', 'catalog', 'module not found'); + if (!RetailcrmDependencyLoader::loadDependencies()) { return true; } $resOrders = array(); $resCustomers = array(); + $resCustomersAdded = array(); + $resCustomersCorporate = array(); $orderIds = array(); - $lastUpOrderId = COption::GetOptionString(self::$MODULE_ID, self::$CRM_ORDER_LAST_ID, 0); - $failedIds = unserialize(COption::GetOptionString(self::$MODULE_ID, self::$CRM_ORDER_FAILED_IDS, 0)); + $lastUpOrderId = RetailcrmConfigProvider::getLastOrderId(); + $failedIds = RetailcrmConfigProvider::getFailedOrdersIds(); if ($failed == true && $failedIds !== false && count($failedIds) > 0) { $orderIds = $failedIds; @@ -345,6 +337,7 @@ class RetailCrmOrder 'limit' => $pSize, 'select' => array('ID') )); + while ($arOrder = $dbOrder->fetch()) { $orderIds[] = $arOrder['ID']; } @@ -354,21 +347,30 @@ class RetailCrmOrder return false; } - $api_host = COption::GetOptionString(self::$MODULE_ID, self::$CRM_API_HOST_OPTION, 0); - $api_key = COption::GetOptionString(self::$MODULE_ID, self::$CRM_API_KEY_OPTION, 0); + $optionsSitesList = RetailcrmConfigProvider::getSitesList(); + $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(); - $optionsSitesList = unserialize(COption::GetOptionString(self::$MODULE_ID, self::$CRM_SITES_LIST, 0)); - $optionsOrderTypes = unserialize(COption::GetOptionString(self::$MODULE_ID, self::$CRM_ORDER_TYPES_ARR, 0)); - $optionsDelivTypes = unserialize(COption::GetOptionString(self::$MODULE_ID, self::$CRM_DELIVERY_TYPES_ARR, 0)); - $optionsPayTypes = unserialize(COption::GetOptionString(self::$MODULE_ID, self::$CRM_PAYMENT_TYPES, 0)); - $optionsPayStatuses = unserialize(COption::GetOptionString(self::$MODULE_ID, self::$CRM_PAYMENT_STATUSES, 0)); // --statuses - $optionsPayment = unserialize(COption::GetOptionString(self::$MODULE_ID, self::$CRM_PAYMENT, 0)); - $optionsOrderProps = unserialize(COption::GetOptionString(self::$MODULE_ID, self::$CRM_ORDER_PROPS, 0)); - $optionsLegalDetails = unserialize(COption::GetOptionString(self::$MODULE_ID, self::$CRM_LEGAL_DETAILS, 0)); - $optionsContragentType = unserialize(COption::GetOptionString(self::$MODULE_ID, self::$CRM_CONTRAGENT_TYPE, 0)); - $optionsCustomFields = unserialize(COption::GetOptionString(self::$MODULE_ID, self::$CRM_CUSTOM_FIELDS, 0)); + $getSite = function ($key) use ($optionsSitesList) { + if ($optionsSitesList) { + if (array_key_exists($key, $optionsSitesList) && $optionsSitesList[$key] != null) { + return $optionsSitesList[$key]; + } else { + return false; + } + } - $api = new RetailCrm\ApiClient($api_host, $api_key); + return null; + }; + + $api = new RetailCrm\ApiClient(RetailcrmConfigProvider::getApiUrl(), RetailcrmConfigProvider::getApiKey()); $arParams = array( 'optionsOrderTypes' => $optionsOrderTypes, @@ -384,72 +386,222 @@ class RetailCrmOrder ); $recOrders = array(); + foreach ($orderIds as $orderId) { + $site = null; $id = \Bitrix\Sale\Order::load($orderId); + if (!$id) { continue; } + + $arCustomer = array(); + $arCustomerCorporate = array(); $order = self::orderObjToArr($id); $user = Bitrix\Main\UserTable::getById($order['USER_ID'])->fetch(); + $site = $getSite($order['LID']); - $arCustomers = RetailCrmUser::customerSend($user, $api, $optionsContragentType[$order['PERSON_TYPE_ID']], false, $site); - $arOrders = self::orderSend($order, $api, $arParams, false, $site); - - if (!$arCustomers || !$arOrders) { + if (true === $site) { continue; } - $resCustomers[$order['LID']][] = $arCustomers; - $resOrders[$order['LID']][] = $arOrders; + if ("Y" == RetailcrmConfigProvider::getCorporateClientStatus() + && $optionsContragentType[$order['PERSON_TYPE_ID']] == 'legal-entity' + ) { + // 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, + 'legal-entity', + false, + true, + $site + ); + + $arParams['orderCompany'] = isset($arCustomerCorporate['companies']) + ? reset($arCustomerCorporate['companies']) : null; + $arParams['contactExId'] = $user['ID']; + } else { + $arCustomer = RetailCrmUser::customerSend( + $user, + $api, + $optionsContragentType[$order['PERSON_TYPE_ID']], + false, + $site + ); + + if (isset($arParams['contactExId'])) { + unset($arParams['contactExId']); + } + } + + $arOrders = self::orderSend($order, $api, $arParams, false, $site); + + if (!$arCustomer || !$arOrders) { + continue; + } + + if (!empty($arCustomerCorporate) && !empty($arCustomerCorporate['nickName'])) { + $resCustomersCorporate[$arCustomerCorporate['nickName']] = $arCustomerCorporate; + } + + $email = isset($arCustomer['email']) ? $arCustomer['email'] : ''; + + if (!in_array($email, $resCustomersAdded)) { + $resCustomersAdded[] = $email; + $resCustomers[$order['LID']][] = $arCustomer; + } + + $resOrders[$order['LID']][] = $arOrders; $recOrders[] = $orderId; } if (count($resOrders) > 0) { - foreach ($resCustomers as $key => $customerLoad) { - if ($optionsSitesList) { - if (array_key_exists($key, $optionsSitesList) && $optionsSitesList[$key] != null) { - $site = $optionsSitesList[$key]; - } else { + $uploadItems = function ($pack, $method) use ($getSite, $api, $optionsSitesList) { + $uploaded = array(); + + foreach ($pack as $key => $itemLoad) { + $site = $getSite($key); + + if (true === $site) { continue; } - } elseif (!$optionsSitesList) { - $site = null; - } - if (RCrmActions::apiMethod($api, 'customersUpload', __METHOD__, $customerLoad, $site) === false) { - return false; - } - if (count($optionsSitesList) > 1) { - time_nanosleep(0, 250000000); - } - } - foreach ($resOrders as $key => $orderLoad) { - if ($optionsSitesList) { - if (array_key_exists($key, $optionsSitesList) && $optionsSitesList[$key] != null) { - $site = $optionsSitesList[$key]; - } else { - continue; + + /** @var \RetailCrm\Response\ApiResponse|bool $response */ + $response = RCrmActions::apiMethod( + $api, + $method, + __METHOD__, + $itemLoad, + $site + ); + + if ($response === false) { + return false; + } + + if ($response instanceof \RetailCrm\Response\ApiResponse) { + if ($response->offsetExists('uploadedCustomers')) { + $uploaded = array_merge($uploaded, $response['uploadedCustomers']); + } + + if ($response->offsetExists('uploadedOrders')) { + $uploaded = array_merge($uploaded, $response['uploadedOrders']); + } + } + + if (count($optionsSitesList) > 1) { + time_nanosleep(0, 250000000); } - } elseif (!$optionsSitesList) { - $site = null; } - if (RCrmActions::apiMethod($api, 'ordersUpload', __METHOD__, $orderLoad, $site) === false) { - return false; - } - if (count($optionsSitesList) > 1) { - time_nanosleep(0, 250000000); + + return $uploaded; + }; + + if (false === $uploadItems($resCustomers, 'customersUpload')) { + return false; + } + + if ("Y" == RetailcrmConfigProvider::getCorporateClientStatus()) { + $cachedCorporateIds = array(); + + foreach ($resOrders as $packKey => $pack) { + foreach ($pack as $key => $orderData) { + if (isset($orderData['contragent']['contragentType']) + && $orderData['contragent']['contragentType'] == 'legal-entity' + && !empty($orderData['contragent']['legalName']) + ) { + if (isset($cachedCorporateIds[$orderData['contragent']['legalName']])) { + $orderData['customer'] = array( + 'id' => $cachedCorporateIds[$orderData['contragent']['legalName']] + ); + } else { + $corpData = $api->customersCorporateList(array( + 'nickName' => array($orderData['contragent']['legalName']) + )); + + if ($corpData + && $corpData->isSuccessful() + && $corpData->offsetExists('customersCorporate') + && !empty($corpData['customersCorporate']) + ) { + $corpData = $corpData['customersCorporate']; + $corpData = reset($corpData); + + $orderData['customer'] = array('id' => $corpData['id']); + $cachedCorporateIds[$orderData['contragent']['legalName']] = $corpData['id']; + + RetailCrmCorporateClient::addCustomersCorporateAddresses( + $orderData['customer']['id'], + $orderData['contragent']['legalName'], + $orderData['delivery']['address']['text'], + $api, + $site = null + ); + } elseif (array_key_exists( + $orderData['contragent']['legalName'], + $resCustomersCorporate + )) { + $createResponse = $api + ->customersCorporateCreate( + $resCustomersCorporate[$orderData['contragent']['legalName']] + ); + + if ($createResponse && $createResponse->isSuccessful()) { + $orderData['customer'] = array('id' => $createResponse['id']); + $cachedCorporateIds[$orderData['contragent']['legalName']] + = $createResponse['id']; + } + } + + time_nanosleep(0, 250000000); + } + + $pack[$key] = $orderData; + } + } + + $resOrders[$packKey] = $pack; } } + + if (false === $uploadItems($resOrders, 'ordersUpload')) { + return false; + } + if ($failed == true && $failedIds !== false && count($failedIds) > 0) { - COption::SetOptionString(self::$MODULE_ID, self::$CRM_ORDER_FAILED_IDS, serialize(array_diff($failedIds, $recOrders))); + RetailcrmConfigProvider::setFailedOrdersIds(array_diff($failedIds, $recOrders)); } elseif ($lastUpOrderId < max($recOrders) && $orderList === false) { - COption::SetOptionString(self::$MODULE_ID, self::$CRM_ORDER_LAST_ID, max($recOrders)); + RetailcrmConfigProvider::setLastOrderId(max($recOrders)); } } return true; } + /** + * Returns true if provided order array is corporate order data + * + * @param array|\ArrayAccess $order + * + * @return bool + */ + public static function isOrderCorporate($order) + { + return (is_array($order) || $order instanceof ArrayAccess) + && isset($order['customer']) + && isset($order['customer']['type']) + && $order['customer']['type'] == 'customer_corporate'; + } + /** * Converts order object to array * @@ -478,10 +630,11 @@ class RetailCrmOrder 'BASKET' => array(), 'USER_DESCRIPTION' => $obOrder->getField('USER_DESCRIPTION'), 'COMMENTS' => $obOrder->getField('COMMENTS'), - 'REASON_CANCELED' => $obOrder->getField('REASON_CANCELED'), + 'REASON_CANCELED' => $obOrder->getField('REASON_CANCELED') ); $shipmentList = $obOrder->getShipmentCollection(); + foreach ($shipmentList as $shipmentData) { if ($shipmentData->isSystem()) { continue; @@ -506,11 +659,13 @@ class RetailCrmOrder } $paymentList = $obOrder->getPaymentCollection(); + foreach ($paymentList as $paymentData) { $arOrder['PAYMENTS'][] = $paymentData->getFields()->getValues(); } $basketItems = $obOrder->getBasket(); + foreach ($basketItems as $item) { $arOrder['BASKET'][] = $item->getFields(); } diff --git a/intaro.retailcrm/classes/general/prices/RetailCrmPrices.php b/intaro.retailcrm/classes/general/prices/RetailCrmPrices.php index c3f3564c..50a837e7 100644 --- a/intaro.retailcrm/classes/general/prices/RetailCrmPrices.php +++ b/intaro.retailcrm/classes/general/prices/RetailCrmPrices.php @@ -50,8 +50,6 @@ class RetailCrmPrices } if (count($infoBlocks) > 0) { - $log = new Logger(); - foreach ($infoBlocks as $id) { $iblockOffer = CCatalogSKU::GetInfoByProductIBlock($id); @@ -133,7 +131,7 @@ class RetailCrmPrices //for log $splitedItems = array_chunk($pricesUpload, 200); foreach ($splitedItems as $chunk) { - $log->write($chunk, 'storePricesUpload'); + Logger::getInstance()->write($chunk, 'storePricesUpload'); foreach ($shops as $shop) { RCrmActions::apiMethod($api, 'storePricesUpload', __METHOD__, $chunk, $shop); diff --git a/intaro.retailcrm/classes/general/user/RetailCrmCorporateClient.php b/intaro.retailcrm/classes/general/user/RetailCrmCorporateClient.php new file mode 100644 index 00000000..eb5fa120 --- /dev/null +++ b/intaro.retailcrm/classes/general/user/RetailCrmCorporateClient.php @@ -0,0 +1,157 @@ +fetch(); + + if (count($shops) == 0) { + RCrmActions::eventLog('RetailCrmCorporateClient::clientSend()', '$shops', 'No stores selected for download'); + + return false; + } + + foreach ($arOrder['PROPS']['properties'] as $prop) { + if ($prop['CODE'] == RetailcrmConfigProvider::getCorporateClientName()) { + $nickName = $prop['VALUE'][0]; + } + + if ($prop['CODE'] == RetailcrmConfigProvider::getCorporateClientAddress()) { + $address = $prop['VALUE'][0]; + } + + if (!empty($optionsLegalDetails) + && $search = array_search($prop['CODE'], $optionsLegalDetails[$arOrder['PERSON_TYPE_ID']]) + ) { + $contragent[$search] = $prop['VALUE'][0];//legal order data + } + } + + if (empty($nickName)) { + $nickName = $arUser['WORK_COMPANY']; + } + + if (!empty($contragentType)) { + $contragent['contragentType'] = $contragentType; + } + + foreach ($shops as $shop) { + $customerCorporate = array( + 'createdAt' => $arOrder['DATE_INSERT'], + "nickName" => $nickName, + ); + + if ($fillCorp) { + $customerCorporate = array_merge( + $customerCorporate, + array( + 'customerContacts' => array( + array( + 'isMain' => true, + 'customer' => array( + 'externalId' => $arUser['ID'], + 'site' => $shop + ) + ) + ), + 'companies' => array( + array( + 'name' => $nickName, + 'isMain' => true, + ) + ), + 'addresses' => array( + array( + 'name' => $nickName, + 'isMain' => true, + 'text' => $address + ) + ) + ) + ); + } + } + + if (isset($customerCorporate)) { + if ($send && isset($_COOKIE['_rc']) && $_COOKIE['_rc'] != '') { + $customerCorporate['browserId'] = $_COOKIE['_rc']; + } + + $normalizer = new RestNormalizer(); + $customerCorporate = $normalizer->normalize($customerCorporate, 'customerCorporate'); + + Logger::getInstance()->write($customerCorporate, 'clientCorporate'); + + if ($send) { + $result = RCrmActions::apiMethod($api, 'customersCorporateCreate', __METHOD__, $customerCorporate, $site); + if (!$result) { + return false; + } + + $customerCorporate['id'] = $result['id']; + } + + return $customerCorporate; + } + + return array(); + } + + public static function addCustomersCorporateAddresses($customeId, $legalName, $adress, $api, $site) + { + $found = false; + $addresses = $api->customersCorporateAddresses( + $customeId, + array(), + null, + 100, + 'id', + $site + ); + + if ($addresses && $addresses->isSuccessful() && $addresses->offsetExists('addresses')) { + foreach ($addresses['addresses'] as $corpAddress) { + if (isset($corpAddress['text']) && $corpAddress['text'] == $adress) { + $found = true; + + break; + } + } + + if (!$found) { + $customerCorporateAddress = array( + 'name' => $legalName, + 'text' => $adress + ); + + $addressResult = $api->customersCorporateAddressesCreate( + $customeId, + $customerCorporateAddress, + 'id', + $site + ); + + if (!$addressResult || ($addressResult && !$addressResult->isSuccessful())) { + Logger::getInstance()->write(sprintf( + 'error while trying to append address to corporate customer%s%s', + PHP_EOL, + print_r(array( + 'address' => $customerCorporateAddress, + 'customer' => $customeId + ), true) + ), 'apiErrors'); + } + } + } + } +} diff --git a/intaro.retailcrm/classes/general/user/RetailCrmUser.php b/intaro.retailcrm/classes/general/user/RetailCrmUser.php index 801cba2f..765684fc 100644 --- a/intaro.retailcrm/classes/general/user/RetailCrmUser.php +++ b/intaro.retailcrm/classes/general/user/RetailCrmUser.php @@ -16,6 +16,7 @@ class RetailCrmUser 'externalId' => $arFields['ID'], 'email' => $arFields['EMAIL'], 'createdAt' => new \DateTime($arFields['DATE_REGISTER']), + 'subscribed' => false, 'contragent' => array( 'contragentType' => $contragentType ) @@ -66,8 +67,7 @@ class RetailCrmUser $normalizer = new RestNormalizer(); $customer = $normalizer->normalize($customer, 'customers'); - $log = new Logger(); - $log->write($customer, 'customerSend'); + Logger::getInstance()->write($customer, 'customerSend'); if ($send) { if (!RCrmActions::apiMethod($api, 'customersCreate', __METHOD__, $customer, $site)) { @@ -148,8 +148,7 @@ class RetailCrmUser } } - $log = new Logger(); - $log->write($customer, 'customerSend'); + Logger::getInstance()->write($customer, 'customerSend'); RCrmActions::apiMethod($api, 'customersEdit', __METHOD__, $customer, $site); } diff --git a/intaro.retailcrm/description.ru b/intaro.retailcrm/description.ru index 3b857aaf..84e54c1e 100644 --- a/intaro.retailcrm/description.ru +++ b/intaro.retailcrm/description.ru @@ -1,2 +1 @@ -- Улучшена работа со скидками -- Добавлен сброс закупочной цены в icml при её отсутствии +- Добавлена поддержка корпоративных клиентов diff --git a/intaro.retailcrm/include.php b/intaro.retailcrm/include.php index 5fbc529a..98dfa6b0 100644 --- a/intaro.retailcrm/include.php +++ b/intaro.retailcrm/include.php @@ -5,6 +5,7 @@ $version = COption::GetOptionString('intaro.retailcrm', 'api_version'); CModule::AddAutoloadClasses( 'intaro.retailcrm', // module name array ( + 'RetailcrmDependencyLoader' => 'classes/general/RetailcrmDependencyLoader.php', 'RestNormalizer' => file_exists($server . '/bitrix/php_interface/retailcrm/RestNormalizer.php') ? '../../php_interface/retailcrm/RestNormalizer.php' : 'classes/general/RestNormalizer.php', 'Logger' => file_exists($server . '/bitrix/php_interface/retailcrm/Logger.php') ? '../../php_interface/retailcrm/Logger.php' : 'classes/general/Logger.php', 'RetailCrm\ApiClient' => file_exists($server . '/bitrix/php_interface/retailcrm/ApiClient.php') ? '../../php_interface/retailcrm/ApiClient.php' : 'classes/general/ApiClient_' . $version . '.php', @@ -22,5 +23,8 @@ CModule::AddAutoloadClasses( 'RetailCrm\Response\ApiResponse' => 'classes/general/Response/ApiResponse.php', 'RetailCrm\Exception\InvalidJsonException' => 'classes/general/Exception/InvalidJsonException.php', 'RetailCrm\Exception\CurlException' => 'classes/general/Exception/CurlException.php', + 'RetailCrmCorporateClient' => file_exists($server . '/bitrix/php_interface/retailcrm/RetailCrmCorporateClient.php') ? '../../php_interface/retailcrm/RetailCrmCorporateClient.php' : 'classes/general/user/RetailCrmCorporateClient.php', + 'RetailcrmConfigProvider' => 'classes/general/RetailcrmConfigProvider.php', + 'RetailcrmConstants' => 'classes/general/RetailcrmConstants.php', ) ); diff --git a/intaro.retailcrm/install/index.php b/intaro.retailcrm/install/index.php index 29fb8772..bc5be3dc 100644 --- a/intaro.retailcrm/install/index.php +++ b/intaro.retailcrm/install/index.php @@ -89,6 +89,20 @@ class intaro_retailcrm extends CModule $this->PARTNER_URI = GetMessage('MODULE_PARTNER_URI'); } + function loadDeps() + { + if (!class_exists('RetailcrmConstants')) { + require_once dirname(__FILE__) . '/../classes/general/RetailcrmConstants.php'; + } + if (!class_exists('RetailcrmConfigProvider')) { + require_once dirname(__FILE__) . '/../classes/general/RetailcrmConfigProvider.php'; + } + + if (!class_exists('RetailcrmDependencyLoader')) { + require_once dirname(__FILE__) . '/../classes/general/RetailcrmDependencyLoader.php'; + } + } + /** * Functions DoInstall and DoUninstall are * All other functions are optional @@ -564,6 +578,7 @@ class intaro_retailcrm extends CModule && $_POST['ajax'] == 1 ) { $historyTime = Date(''); + self::loadDeps(); RetailCrmOrder::uploadOrders(); // each 50 $lastUpOrderId = COption::GetOptionString($this->MODULE_ID, $this->CRM_ORDER_LAST_ID, 0); @@ -745,6 +760,12 @@ class intaro_retailcrm extends CModule $arResult['PRICE_TYPES'][$arPriceType['ID']] = $arPriceType; } + if (isset($_POST['back']) && $_POST['back']) { + $APPLICATION->IncludeAdminFile( + GetMessage('MODULE_INSTALL_TITLE'), $this->INSTALL_PATH . '/step3.php' + ); + } + $APPLICATION->IncludeAdminFile( GetMessage('MODULE_INSTALL_TITLE'), $this->INSTALL_PATH . '/step5.php' ); @@ -769,7 +790,7 @@ class intaro_retailcrm extends CModule if (isset($_POST['back']) && $_POST['back']) { $APPLICATION->IncludeAdminFile( - GetMessage('MODULE_INSTALL_TITLE'), $this->INSTALL_PATH . '/step3.php' + GetMessage('MODULE_INSTALL_TITLE'), $this->INSTALL_PATH . '/step4.php' ); } diff --git a/intaro.retailcrm/install/step1.php b/intaro.retailcrm/install/step1.php index 150b738c..60f8295f 100644 --- a/intaro.retailcrm/install/step1.php +++ b/intaro.retailcrm/install/step1.php @@ -2,7 +2,14 @@ IncludeModuleLangFile(__FILE__); if(isset($arResult['errCode']) && $arResult['errCode']) - echo CAdminMessage::ShowMessage(GetMessage($arResult['errCode'])); + echo CAdminMessage::ShowMessage(GetMessage($arResult['errCode'])); + +$MODULE_ID = 'intaro.retailcrm'; +$CRM_API_HOST_OPTION = 'api_host'; +$CRM_API_KEY_OPTION = 'api_key'; + +$arResult['API_HOST'] = COption::GetOptionString($MODULE_ID, $CRM_API_HOST_OPTION); +$arResult['API_KEY'] = COption::GetOptionString($MODULE_ID, $CRM_API_KEY_OPTION); ?>
diff --git a/intaro.retailcrm/install/step2.php b/intaro.retailcrm/install/step2.php index 90f4487c..e741f76f 100644 --- a/intaro.retailcrm/install/step2.php +++ b/intaro.retailcrm/install/step2.php @@ -3,7 +3,58 @@ IncludeModuleLangFile(__FILE__); $MODULE_ID = 'intaro.retailcrm'; $CRM_API_HOST_OPTION = 'api_host'; +$CRM_API_KEY_OPTION = 'api_key'; +$CRM_SITES_LIST= 'sites_list'; +$CRM_PAYMENT_TYPES = 'pay_types_arr'; +$CRM_DELIVERY_TYPES_ARR = 'deliv_types_arr'; +$CRM_PAYMENT_TYPES = 'pay_types_arr'; +$CRM_PAYMENT_STATUSES = 'pay_statuses_arr'; +$CRM_PAYMENT = 'payment_arr'; +$CRM_ORDER_TYPES_ARR = 'order_types_arr'; $api_host = COption::GetOptionString($MODULE_ID, $CRM_API_HOST_OPTION, 0); +$api_key = COption::GetOptionString($MODULE_ID, $CRM_API_KEY_OPTION, 0); +$arResult['arSites'] = RCrmActions::SitesList(); + +$RETAIL_CRM_API = new \RetailCrm\ApiClient($api_host, $api_key); +COption::SetOptionString($MODULE_ID, $CRM_API_HOST_OPTION, $api_host); +COption::SetOptionString($MODULE_ID, $CRM_API_KEY_OPTION, $api_key); +COption::SetOptionString($MODULE_ID, $CRM_SITES_LIST, serialize(array())); + +if (!isset($arResult['PAYMENT'])) { + $arResult['PAYMENT'] = unserialize(COption::GetOptionString($MODULE_ID, $CRM_PAYMENT, 0)); +} + +if (!isset($arResult['ORDER_TYPES'])) { + $arResult['ORDER_TYPES'] = unserialize(COption::GetOptionString($MODULE_ID, $CRM_ORDER_TYPES_ARR, 0)); +} + +if (!isset($arResult['paymentTypesList'])) { + $arResult['bitrixPaymentTypesList'] = RCrmActions::PaymentList(); + $arResult['paymentTypesList'] = $RETAIL_CRM_API->paymentTypesList()->paymentTypes; + $arResult['PAYMENT_TYPES'] = unserialize(COption::GetOptionString($MODULE_ID, $CRM_PAYMENT_TYPES, 0)); +} + +if (!isset($arResult['bitrixStatusesList'])) { + $arResult['bitrixStatusesList'] = RCrmActions::StatusesList(); + $arResult['paymentList'] = $RETAIL_CRM_API->statusesList()->statuses; + $arResult['paymentGroupList'] = $RETAIL_CRM_API->statusGroupsList()->statusGroups; +} + +if (!isset($arResult['orderTypesList'])) { + $arResult['bitrixOrderTypesList'] = RCrmActions::OrderTypesList($arResult['arSites']); + $arResult['orderTypesList'] = $RETAIL_CRM_API->orderTypesList()->orderTypes; +} + +if (!isset($arResult['paymentStatusesList'])) { + $arResult['paymentStatusesList'] = $RETAIL_CRM_API->paymentStatusesList()->paymentStatuses; + $arResult['PAYMENT_STATUSES'] = unserialize(COption::GetOptionString($MODULE_ID, $CRM_PAYMENT_STATUSES, 0)); +} + +if (!isset($arResult['bitrixDeliveryTypesList'])) { + $arResult['bitrixDeliveryTypesList'] = RCrmActions::DeliveryList(); + $arResult['deliveryTypesList'] = $RETAIL_CRM_API->deliveryTypesList()->deliveryTypes; + $arResult['DELIVERY_TYPES'] = unserialize(COption::GetOptionString($MODULE_ID, $CRM_DELIVERY_TYPES_ARR, 0)); +} //bitrix pyament Y/N $arResult['bitrixPaymentList'][0]['NAME'] = GetMessage('PAYMENT_Y'); diff --git a/intaro.retailcrm/install/step3.php b/intaro.retailcrm/install/step3.php index a72b53df..e213cd93 100644 --- a/intaro.retailcrm/install/step3.php +++ b/intaro.retailcrm/install/step3.php @@ -3,6 +3,36 @@ if (!check_bitrix_sessid()) return; IncludeModuleLangFile(__FILE__); +$MODULE_ID = 'intaro.retailcrm'; +$CRM_API_HOST_OPTION = 'api_host'; +$CRM_API_KEY_OPTION = 'api_key'; +$CRM_SITES_LIST= 'sites_list'; +$CRM_ORDER_PROPS = 'order_props'; +$CRM_CONTRAGENT_TYPE = 'contragent_type'; +$CRM_LEGAL_DETAILS = 'legal_details'; +$api_host = COption::GetOptionString($MODULE_ID, $CRM_API_HOST_OPTION, 0); +$api_key = COption::GetOptionString($MODULE_ID, $CRM_API_KEY_OPTION, 0); +$arResult['arSites'] = RCrmActions::SitesList(); + +$RETAIL_CRM_API = new \RetailCrm\ApiClient($api_host, $api_key); +COption::SetOptionString($MODULE_ID, $CRM_API_HOST_OPTION, $api_host); +COption::SetOptionString($MODULE_ID, $CRM_API_KEY_OPTION, $api_key); +COption::SetOptionString($MODULE_ID, $CRM_SITES_LIST, serialize(array())); + +if (!isset($arResult['bitrixOrderTypesList'])) { + $arResult['bitrixOrderTypesList'] = RCrmActions::OrderTypesList($arResult['arSites']); + $arResult['arProp'] = RCrmActions::OrderPropsList(); + $arResult['ORDER_PROPS'] = unserialize(COption::GetOptionString($MODULE_ID, $CRM_ORDER_PROPS, 0)); +} + +if (!isset($arResult['LEGAL_DETAILS'])) { + $arResult['LEGAL_DETAILS'] = unserialize(COption::GetOptionString($MODULE_ID, $CRM_LEGAL_DETAILS, 0)); +} + +if (!isset($arResult['CONTRAGENT_TYPES'])) { + $arResult['CONTRAGENT_TYPES'] = unserialize(COption::GetOptionString($MODULE_ID, $CRM_CONTRAGENT_TYPE, 0)); +} + if(isset($arResult['ORDER_PROPS'])){ $defaultOrderProps = $arResult['ORDER_PROPS']; } @@ -27,7 +57,28 @@ else{ ?>