1
0
mirror of synced 2024-11-21 21:06:09 +03:00

ref #89486 Оптимизирован алгоритм получения истории заказов и клиентов (#289)

This commit is contained in:
Uryvskiy Dima 2023-04-26 17:18:38 +03:00 committed by GitHub
parent 198d8b2e9e
commit c67eb37124
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 175 additions and 268 deletions

View File

@ -1,3 +1,6 @@
## 2023-04-26 v.6.3.4
- Оптимизирован алгоритм получения истории заказов и клиентов
## 2023-04-10 v.6.3.3
- Исправлено некорректное отображение настроек модуля
- Добавлена поддержка PHP 8.1-8.2

View File

@ -347,29 +347,16 @@ class ApiClient
/**
* Get orders history
* @param array $filter
* @param null $page
* @param null $limit
* @param int $limit
*
* @return ApiResponse
*/
public function ordersHistory(array $filter = array(), $page = null, $limit = null)
public function ordersHistory(array $filter = [], int $limit = 100)
{
$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(
'/orders/history',
Client::METHOD_GET,
$parameters
['filter' => $filter, 'limit' => $limit]
);
}
@ -552,30 +539,18 @@ class ApiClient
/**
* Get customers history
*
* @param array $filter
* @param null $page
* @param null $limit
* @param int $limit
*
* @return ApiResponse
*/
public function customersHistory(array $filter = array(), $page = null, $limit = null)
public function customersHistory(array $filter = [], int $limit = 100)
{
$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/history',
Client::METHOD_GET,
$parameters
['filter' => $filter, 'limit' => $limit]
);
}
@ -643,9 +618,8 @@ class ApiClient
/**
* Get orders assembly history
*
* @param array $filter (default: array())
* @param int $page (default: null)
* @param int $limit (default: null)
* @param array $filter
* @param int $limit
*
* @throws \InvalidArgumentException
* @throws \RetailCrm\Exception\CurlException
@ -653,24 +627,12 @@ class ApiClient
*
* @return ApiResponse
*/
public function ordersPacksHistory(array $filter = array(), $page = null, $limit = null)
public function ordersPacksHistory(array $filter = [], int $limit = 100)
{
$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(
'/orders/packs/history',
Client::METHOD_GET,
$parameters
['filter' => $filter, 'limit' => $limit]
);
}

View File

@ -345,34 +345,21 @@ class ApiClient
);
}
/*
/**
* Get customers corporate history
*
* @param array $filter
* @param null $page
* @param null $limit
* @param int|null $limit
*
* @return ApiResponse
*
*/
public function customersCorporateHistory(array $filter = array(), $page = null, $limit = null)
public function customersCorporateHistory(array $filter = [], ?int $limit = 100)
{
$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
['filter' => $filter, 'limit' => $limit]
);
}
@ -994,30 +981,18 @@ class ApiClient
/**
* Get orders history
*
* @param array $filter
* @param null $page
* @param null $limit
* @param int|null $limit
*
* @return ApiResponse
*/
public function ordersHistory(array $filter = array(), $page = null, $limit = null)
public function ordersHistory(array $filter = [], ?int $limit = 100)
{
$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(
'/orders/history',
Client::METHOD_GET,
$parameters
['filter' => $filter, 'limit' => $limit]
);
}
@ -1200,30 +1175,18 @@ class ApiClient
/**
* Get customers history
*
* @param array $filter
* @param null $page
* @param null $limit
* @param int|null $limit
*
* @return ApiResponse
*/
public function customersHistory(array $filter = array(), $page = null, $limit = null)
public function customersHistory(array $filter = [], ?int $limit = 100)
{
$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/history',
Client::METHOD_GET,
$parameters
['filter' => $filter, 'limit' => $limit]
);
}
@ -1851,34 +1814,17 @@ class ApiClient
/**
* Get orders assembly history
*
* @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
* @param array $filter
* @param int|null $limit
*
* @return ApiResponse
*/
public function ordersPacksHistory(array $filter = array(), $page = null, $limit = null)
public function ordersPacksHistory(array $filter = [], ?int $limit = 100)
{
$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(
'/orders/packs/history',
Client::METHOD_GET,
$parameters
['filter' => $filter, 'limit' => $limit]
);
}

View File

@ -22,6 +22,7 @@ use Intaro\RetailCrm\Service\OrderLoyaltyDataService;
use Intaro\RetailCrm\Component\ConfigProvider;
use Intaro\RetailCrm\Component\Constants;
use Intaro\RetailCrm\Component\Handlers\EventsHandlers;
use RetailCrm\Response\ApiResponse;
IncludeModuleLangFile(__FILE__);
class RetailCrmHistory
@ -49,6 +50,7 @@ class RetailCrmHistory
public static $CRM_CURRENCY = 'currency';
public static $CRM_DISCOUNT_ROUND = 'discount_round';
const PAGE_LIMIT = 25;
const CANCEL_PROPERTY_CODE = 'INTAROCRM_IS_CANCELED';
public static function customerHistory()
@ -57,7 +59,8 @@ class RetailCrmHistory
return false;
}
$historyFilter = array();
$page = 1;
$historyFilter = [];
$historyStart = RetailcrmConfigProvider::getCustomersHistorySinceId();
$api = new RetailCrm\ApiClient(RetailcrmConfigProvider::getApiUrl(), RetailcrmConfigProvider::getApiKey());
@ -65,27 +68,31 @@ class RetailCrmHistory
$historyFilter['sinceId'] = $historyStart;
}
while (true) {
$customerHistory = RCrmActions::apiMethod($api, 'customersHistory', __METHOD__, $historyFilter);
do {
$historyResponse = RCrmActions::apiMethod($api, 'customersHistory', __METHOD__, $historyFilter);
$customerH = isset($customerHistory['history']) ? $customerHistory['history'] : array();
Logger::getInstance()->write($customerH, 'customerHistory');
if (is_array($customerH) && count($customerH) === 0) {
if ($customerHistory['history']['totalPageCount'] > $customerHistory['history']['currentPage']) {
$historyFilter['page'] = $customerHistory['history']['currentPage'] + 1;
continue;
}
return true;
if (
!$historyResponse instanceof ApiResponse
|| !$historyResponse->isSuccessful()
|| empty($historyResponse['history'])
|| empty($historyResponse['pagination'])
) {
return false;
}
$customers = self::assemblyCustomer($customerH);
$customerHistory = $historyResponse['history'];
Logger::getInstance()->write($customerHistory, 'customerHistory');
$customers = self::assemblyCustomer($customerHistory);
$GLOBALS['RETAIL_CRM_HISTORY'] = true;
// Set sinceId for customer history
$lastId = array_pop($customerHistory);
$historyFilter['sinceId'] = $lastId['id'];
RetailcrmConfigProvider::setCustomersHistorySinceId($lastId['id']);
$newUser = new CUser();
$customerBuilder = new CustomerBuilder();
@ -210,16 +217,12 @@ class RetailCrmHistory
$GLOBALS['RETAIL_CRM_HISTORY'] = false;
//last id
$end = array_pop($customerH);
RetailcrmConfigProvider::setCustomersHistorySinceId($end['id']);
$page++;
if ($customerHistory['pagination']['totalPageCount'] == 1) {
return true;
if ($page > self::PAGE_LIMIT) {
break;
}
//new filter
$historyFilter['sinceId'] = $end['id'];
}
} while ($historyResponse['pagination']['currentPage'] < $historyResponse['pagination']['totalPageCount']);
}
/**
@ -259,7 +262,7 @@ class RetailCrmHistory
$shipmentDeducted = RetailcrmConfigProvider::getShipmentDeducted();
$api = new RetailCrm\ApiClient(RetailcrmConfigProvider::getApiUrl(), RetailcrmConfigProvider::getApiKey());
$page = 1;
/* @var OrderLoyaltyDataService $orderLoyaltyDataService */
$orderLoyaltyDataService = ServiceLocator::get(OrderLoyaltyDataService::class);
@ -270,25 +273,31 @@ class RetailCrmHistory
$historyFilter['sinceId'] = $historyStart;
}
while (true) {
$orderHistory = RCrmActions::apiMethod($api, 'ordersHistory', __METHOD__, $historyFilter);
$orderH = $orderHistory['history'] ?? [];
do {
$historyResponse = RCrmActions::apiMethod($api, 'ordersHistory', __METHOD__, $historyFilter);
Logger::getInstance()->write($orderH, 'orderHistory');
if (is_array($orderH) && count($orderH) === 0) {
if ($orderHistory['history']['totalPageCount'] > $orderHistory['history']['currentPage']) {
$historyFilter['page'] = $orderHistory['history']['currentPage'] + 1;
continue;
}
return true;
if (
!$historyResponse instanceof ApiResponse
|| !$historyResponse->isSuccessful()
|| empty($historyResponse['history'])
|| empty($historyResponse['pagination'])
) {
return false;
}
$orders = self::assemblyOrder($orderH);
$orderHistory = $historyResponse['history'];
Logger::getInstance()->write($orderHistory, 'orderHistory');
$orders = self::assemblyOrder($orderHistory);
$GLOBALS['RETAIL_CRM_HISTORY'] = true;
// Set sinceId for order history
$lastId = array_pop($orderHistory);
$historyFilter['sinceId'] = $lastId['id'];
COption::SetOptionString(self::$MODULE_ID, self::$CRM_ORDER_HISTORY, $lastId['id']);
//orders with changes
foreach ($orders as $order) {
if (function_exists('retailCrmBeforeOrderSave')) {
@ -1288,16 +1297,12 @@ class RetailCrmHistory
$GLOBALS['RETAIL_CRM_HISTORY'] = false;
//end id
$end = array_pop($orderH);
COption::SetOptionString(self::$MODULE_ID, self::$CRM_ORDER_HISTORY, $end['id']);
$page++;
if ($orderHistory['pagination']['totalPageCount'] == 1) {
return true;
if ($page > self::PAGE_LIMIT) {
break;
}
//new filter
$historyFilter['sinceId'] = $end['id'];
}
} while ($historyResponse['pagination']['currentPage'] < $historyResponse['pagination']['totalPageCount']);
return false;
}

View File

@ -1,2 +1 @@
- Исправлено некорректное отображение настроек модуля
- Добавлена поддержка PHP 8.1-8.2
- Оптимизирован алгоритм получения истории заказов и клиентов

View File

@ -20,6 +20,7 @@ use Intaro\RetailCrm\Vendor\Symfony\Component\Process\PhpExecutableFinder;
use RetailCrm\ApiClient;
use RetailCrm\Exception\CurlException;
use RetailCrm\Http\Client;
use RetailCrm\Response\ApiResponse;
Loader::IncludeModule('highloadblock');
@ -1379,64 +1380,49 @@ class intaro_retailcrm extends CModule
public function historyLoad($api, $method)
{
$page = null;
$end['id'] = 0;
$lastSinceId = 0;
$startDate = new DateTime('-1 days');
try {
$history = $api->$method([], $page);
$historyResponse = $api->$method(['startDate' => $startDate->format('Y-m-d H:i:s')]);
} catch (CurlException $e) {
RCrmActions::eventLog(
'RetailCrmHistory::' . $method, 'RetailCrm\RestApi::' . $method . '::CurlException',
'RetailCrmHistory::m' . $method, 'RetailCrm\RestApi::' . $method . '::CurlException',
$e->getCode() . ': ' . $e->getMessage()
);
return $end['id'];
return $lastSinceId;
} catch (InvalidArgumentException $e) {
RCrmActions::eventLog(
'RetailCrmHistory::' . $method, 'RetailCrm\RestApi::' . $method . '::InvalidArgumentException',
$e->getCode() . ': ' . $e->getMessage()
);
return $end['id'];
return $lastSinceId;
}
if ($history['pagination']['totalPageCount'] > $history['pagination']['currentPage']) {
$page = $history['pagination']['totalPageCount'];
while (true) {
try {
$history = $api->$method([], $page);
} catch (CurlException $e) {
RCrmActions::eventLog(
'RetailCrmHistory::' . $method, 'RetailCrm\RestApi::' . $method . '::CurlException',
$e->getCode() . ': ' . $e->getMessage()
);
return $end['id'];
} catch (InvalidArgumentException $e) {
RCrmActions::eventLog(
'RetailCrmHistory::' . $method, 'RetailCrm\RestApi::' . $method . '::InvalidArgumentException',
$e->getCode() . ': ' . $e->getMessage()
);
if (
!$historyResponse instanceof ApiResponse
|| !$historyResponse->isSuccessful()
|| empty($historyResponse['history'])
|| empty($historyResponse['pagination'])
) {
return $lastSinceId;
}
return $end['id'];
}
$startPage = $historyResponse['pagination']['currentPage'];
$lastPage = $historyResponse['pagination']['totalPageCount'];
if (isset($history['history'])) {
$end = array_pop($history['history']);
for ($startPage; $startPage <= $lastPage; ++$startPage) {
if ($historyResponse instanceof ApiResponse && !empty($historyResponse['history'])) {
$history = $historyResponse['history'];
$lastSinceId = end($history)['id'];
break;
} else {
$page--;
}
}
} else {
if (isset($history['history']) && count($history['history']) > 0) {
$end = array_pop($history['history']);
} else {
$end['id'] = 0;
$historyResponse = $api->$method(['sinceId' => $lastSinceId]);
}
}
return $end['id'];
return $lastSinceId;
}
/**

View File

@ -1,6 +1,6 @@
<?php
$arModuleVersion = [
'VERSION' => '6.3.3',
'VERSION_DATE' => '2023-04-14 15:00:00'
'VERSION' => '6.3.4',
'VERSION_DATE' => '2023-04-26 11:00:00'
];

View File

@ -40,7 +40,7 @@ use RetailCrm\Response\ApiResponse;
* @method ApiResponse ordersStatuses(array $ids = array(), array $externalIds = array())
* @method ApiResponse ordersUpload(array $orders, $site = null)
* @method ApiResponse ordersGet($id, $by = 'externalId', $site = null)
* @method ApiResponse ordersHistory(array $filter = array(), $page = null, $limit = null)
* @method ApiResponse ordersHistory(array $filter = array(), $limit = 100)
* @method ApiResponse ordersCombine($order, $resultOrder, $technique = 'ours')
* @method ApiResponse ordersPaymentCreate(array $payment, $site = null)
* @method ApiResponse ordersPaymentEdit(array $payment, $by = 'id', $site = null)
@ -61,7 +61,7 @@ use RetailCrm\Response\ApiResponse;
* @method ApiResponse tasksGet($id)
* @method ApiResponse ordersPacksList(array $filter = array(), $page = null, $limit = null)
* @method ApiResponse ordersPacksCreate(array $pack, $site = null)
* @method ApiResponse ordersPacksHistory(array $filter = array(), $page = null, $limit = null)
* @method ApiResponse ordersPacksHistory(array $filter = array(), $limit = 100)
* @method ApiResponse ordersPacksGet($id)
* @method ApiResponse ordersPacksDelete($id)
* @method ApiResponse ordersPacksEdit(array $pack, $site = null)

View File

@ -130,7 +130,6 @@ trait CustomersCorporateTrait
{
$response = $this->client->customersCorporateHistory(
Serializer::serializeArray($request->filter),
$request->page,
$request->limit
);

View File

@ -177,7 +177,6 @@ trait CustomersTrait
{
$response = $this->client->customersHistory(
Serializer::serializeArray($request->filter),
$request->page,
$request->limit
);

View File

@ -2,6 +2,7 @@
use Bitrix\Sale\Order;
use Bitrix\Currency\CurrencyManager;
use RetailCrm\Response\ApiResponse;
use Tests\Intaro\RetailCrm\DataHistory;
/**
@ -27,13 +28,14 @@ class RetailCrmHistory_v5Test extends \BitrixTestCase
public function testRegisterUser(): void
{
$actionsMock = Mockery::mock('alias:' . RCrmActions::class);
$apiResponse = new ApiResponse(200, DataHistory::get_history_data_new_customer());
$actionsMock->shouldReceive('apiMethod')->withAnyArgs()->andReturn(DataHistory::get_history_data_new_customer());
$actionsMock->shouldReceive('apiMethod')->withAnyArgs()->andReturn($apiResponse);
$this->deleteTestingUser();
RetailCrmHistory::customerHistory();
$dbUser = CUser::GetList(($by = 'ID'), ($sort = 'DESC'), array('=EMAIL' => 'testbitrixreg@gmail.com'));
$dbUser = CUser::GetList(($by = 'ID'), ($sort = 'DESC'), ['=EMAIL' => 'testbitrixreg@gmail.com']);
$this->assertEquals(1, $dbUser->SelectedRowsCount());
}
@ -64,11 +66,13 @@ class RetailCrmHistory_v5Test extends \BitrixTestCase
$this->assertTrue((int) $ID > 0);
$actionsMock = Mockery::mock('alias:' . RCrmActions::class);
$actionsMock->shouldReceive('apiMethod')->withAnyArgs()->andReturn(DataHistory::get_history_data_new_customer());
$apiResponse = new ApiResponse(200, DataHistory::get_history_data_new_customer());
$actionsMock->shouldReceive('apiMethod')->withAnyArgs()->andReturn($apiResponse);
RetailCrmHistory::customerHistory();
$dbUser = CUser::GetList(($by = 'ID'), ($sort = 'DESC'), array('=EMAIL' => 'testbitrixreg@gmail.com'));
$dbUser = CUser::GetList(($by = 'ID'), ($sort = 'DESC'), ['=EMAIL' => 'testbitrixreg@gmail.com']);
$this->assertEquals(1, $dbUser->SelectedRowsCount());
@ -91,7 +95,7 @@ class RetailCrmHistory_v5Test extends \BitrixTestCase
RetailCrmHistory::customerHistory();
$dbUser = CUser::GetList(($by = 'ID'), ($sort = 'DESC'), array('=EMAIL' => 'testbitrixreg@gmail.com'));
$dbUser = CUser::GetList(($by = 'ID'), ($sort = 'DESC'), ['=EMAIL' => 'testbitrixreg@gmail.com']);
$this->assertEquals(2, $dbUser->SelectedRowsCount());
}
@ -181,7 +185,7 @@ class RetailCrmHistory_v5Test extends \BitrixTestCase
private function deleteTestingUser(): void
{
$dbUser = CUser::GetList(($by = 'ID'), ($sort = 'DESC'), array('=EMAIL' => 'testbitrixreg@gmail.com'));
$dbUser = CUser::GetList(($by = 'ID'), ($sort = 'DESC'), ['=EMAIL' => 'testbitrixreg@gmail.com']);
if ($dbUser->SelectedRowsCount() > 0) {
while ($user = $dbUser->Fetch()) {

View File

@ -9,56 +9,60 @@ class DataHistory
{
public static function get_history_data_new_customer()
{
return [
'success' => true,
'history' => [
[
'id' => 18009,
'createdAt' => '2021-12-03 13:22:45',
'created' => true,
'source' => 'user',
'user' => ['id' => 11],
'field' => 'id',
'oldValue' => null,
'newValue' => 3758,
'customer' => [
'type' => 'customer',
'id' => 3758,
'isContact' => false,
'createdAt' => '2021-12-03 13:22:45',
'vip' => false,
'bad' => false,
'site' => 'bitrix',
'marginSumm' => 0,
'totalSumm' => 0,
'averageSumm' => 0,
'ordersCount' => 0,
'personalDiscount' => 0,
'cumulativeDiscount' => 0,
'address' => [
'id' => 3503,
'index' => 123456,
'countryIso' => 'ES',
'region' => 'Region',
'city' => 'City',
'text' => 'Street',
],
'customFields' => ['crm_customer' => 'test_customer'],
'segments' => [],
'firstName' => 'Test_Name',
'lastName' => 'Test_LastName',
'email' => 'testbitrixreg@gmail.com',
'phones' => ['0' => ['number' => '+79184563200']],
'birthday' => '2021-10-01'
]
]
],
'pagination' => [
'limit' => 100,
'totalCount' => 1,
'currentPage' => 1,
'totalPageCount' => 1
]
];
return '{
"success": true,
"history": [{
"id": 18009,
"createdAt": "2021-12-03 13:22:45",
"created": true,
"source": "user",
"user": {
"id": 11
},
"field": "id",
"oldValue": null,
"newValue": 3758,
"customer": {
"type": "customer",
"id": 3758,
"isContact": false,
"createdAt": "2021-12-03 13:22:45",
"vip": false,
"bad": false,
"site": "bitrix",
"marginSumm": 0,
"totalSumm": 0,
"averageSumm": 0,
"ordersCount": 0,
"personalDiscount": 0,
"cumulativeDiscount": 0,
"address": {
"id": 3503,
"index": 123456,
"countryIso": "ES",
"region": "Region",
"city": "City",
"text": "Street"
},
"customFields": {
"crm_customer": "test_customer"
},
"segments": [],
"firstName": "Test_Name",
"lastName": "Test_LastName",
"email": "testbitrixreg@gmail.com",
"phones": [{
"number": "+79184563200"
}],
"birthday": "2021-10-01"
}
}],
"pagination": {
"limit": 100,
"totalCount": 1,
"currentPage": 1,
"totalPageCount": 1
}
}';
}
}