diff --git a/CHANGELOG.md b/CHANGELOG.md index 25957be..4634ea2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,6 @@ +## v3.4.2 +* Переработан механизм постраничной обработки истории изменений на использование sinceId вместо page + ## v3.4.1 * Исправлено стили страницы настроек для старых версий PS * Исправлена сортировка файлов журналов на странице настроек diff --git a/VERSION b/VERSION index 47b322c..4d9d11c 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -3.4.1 +3.4.2 diff --git a/retailcrm/lib/RetailcrmHistory.php b/retailcrm/lib/RetailcrmHistory.php index 3485e3c..4702850 100755 --- a/retailcrm/lib/RetailcrmHistory.php +++ b/retailcrm/lib/RetailcrmHistory.php @@ -78,25 +78,22 @@ class RetailcrmHistory { $lastSync = Configuration::get('RETAILCRM_LAST_CUSTOMERS_SYNC'); - $customerFix = []; - $filter = false === $lastSync ? ['startDate' => date('Y-m-d H:i:s', strtotime('-1 days', strtotime(date('Y-m-d H:i:s'))))] : ['sinceId' => $lastSync]; - $request = new RetailcrmApiPaginatedRequest(); - $historyChanges = []; + $request = new RetailcrmApiSinceIdRequest(); $history = $request ->setApi(self::$api) ->setMethod('customersHistory') - ->setParams([$filter, '{{page}}']) + ->setParams([$filter]) ->setDataKey('history') - ->setLimit(100) ->setPageLimit(50) ->execute() ->getData() ; + $historyChanges = []; if (0 < count($history)) { $historyChanges = static::filterHistory($history, 'customer'); $end = end($history); @@ -107,6 +104,8 @@ class RetailcrmHistory $customersHistory = RetailcrmHistoryHelper::assemblyCustomer($historyChanges); RetailcrmLogger::writeDebugArray(__METHOD__, ['Assembled history:', $customersHistory]); + $customerFix = []; + foreach ($customersHistory as $customerHistory) { $customerHistory = RetailcrmTools::filter( 'RetailcrmFilterCustomersHistory', @@ -211,37 +210,23 @@ class RetailcrmHistory public static function ordersHistory() { $lastSync = Configuration::get('RETAILCRM_LAST_ORDERS_SYNC'); - $lastDate = Configuration::get('RETAILCRM_LAST_SYNC'); - if (false === $lastSync && false === $lastDate) { - $filter = [ - 'startDate' => date( - 'Y-m-d H:i:s', - strtotime('-1 days', strtotime(date('Y-m-d H:i:s'))) - ), - ]; - } elseif (false === $lastSync && false !== $lastDate) { - $filter = ['startDate' => $lastDate]; - } elseif (false !== $lastSync) { - $filter = ['sinceId' => $lastSync]; - } else { - $filter = []; - } + $filter = false === $lastSync + ? ['startDate' => date('Y-m-d H:i:s', strtotime('-1 days', strtotime(date('Y-m-d H:i:s'))))] + : ['sinceId' => $lastSync]; - $historyChanges = []; - - $request = new RetailcrmApiPaginatedRequest(); + $request = new RetailcrmApiSinceIdRequest(); $history = $request ->setApi(self::$api) ->setMethod('ordersHistory') - ->setParams([$filter, '{{page}}']) + ->setParams([$filter]) ->setDataKey('history') - ->setLimit(100) ->setPageLimit(50) ->execute() ->getData() ; + $historyChanges = []; if (0 < count($history)) { $historyChanges = static::filterHistory($history, 'order'); $end = end($history); diff --git a/retailcrm/lib/api/RetailcrmApiPaginatedRequest.php b/retailcrm/lib/api/RetailcrmApiPaginatedRequest.php index 1af49e9..94bdae7 100644 --- a/retailcrm/lib/api/RetailcrmApiPaginatedRequest.php +++ b/retailcrm/lib/api/RetailcrmApiPaginatedRequest.php @@ -36,27 +36,17 @@ * to avoid any conflicts with others containers. */ -class RetailcrmApiPaginatedRequest +class RetailcrmApiPaginatedRequest extends RetailcrmApiRequest { - /** - * @var \RetailcrmProxy|\RetailcrmApiClientV5 - */ - private $api; - - /** - * @var string - */ - private $method; - /** * @var array */ - private $params; + protected $params; /** * @var string */ - private $dataKey; + protected $dataKey; /** * @var int @@ -66,12 +56,7 @@ class RetailcrmApiPaginatedRequest /** * @var int|null */ - private $pageLimit; - - /** - * @var array - */ - private $data; + protected $pageLimit; /** * RetailcrmApiPaginatedRequest constructor. @@ -81,34 +66,6 @@ class RetailcrmApiPaginatedRequest $this->reset(); } - /** - * Sets retailCRM api client to request - * - * @param \RetailcrmApiClientV5|\RetailcrmProxy $api - * - * @return RetailcrmApiPaginatedRequest - */ - public function setApi($api) - { - $this->api = $api; - - return $this; - } - - /** - * Sets API client method to request - * - * @param string $method - * - * @return RetailcrmApiPaginatedRequest - */ - public function setMethod($method) - { - $this->method = $method; - - return $this; - } - /** * Sets method params for API client (leave `{{page}}` instead of page and `{{limit}}` instead of limit) * @@ -184,7 +141,8 @@ class RetailcrmApiPaginatedRequest if ($response instanceof RetailcrmApiResponse && $response->offsetExists($this->dataKey)) { $this->data = array_merge($this->data, $response[$this->dataKey]); - $page = $response['pagination']['currentPage'] + 1; + + $page = $this->getNextPageNumber($page, $response); } if (null !== $this->pageLimit && $page > $this->pageLimit) { @@ -198,16 +156,6 @@ class RetailcrmApiPaginatedRequest return $this; } - /** - * Returns data - * - * @return array - */ - public function getData() - { - return $this->data; - } - /** * Reset paginated request * @@ -224,14 +172,14 @@ class RetailcrmApiPaginatedRequest } /** - * buildParams + * buildParams for the request * * @param array $placeholderParams * @param int $currentPage * * @return mixed */ - private function buildParams($placeholderParams, $currentPage) + protected function buildParams($placeholderParams, $currentPage) { foreach ($placeholderParams as $key => $param) { if ('{{page}}' == $param) { @@ -245,4 +193,17 @@ class RetailcrmApiPaginatedRequest return $placeholderParams; } + + /** + * Get the next page number from the response + * + * @param int $page + * @param RetailcrmApiResponse $response + * + * @return int + */ + protected function getNextPageNumber($page, $response) + { + return $response['pagination']['currentPage'] + 1; + } } diff --git a/retailcrm/lib/api/RetailcrmApiRequest.php b/retailcrm/lib/api/RetailcrmApiRequest.php index 715aba5..cdd8dc8 100644 --- a/retailcrm/lib/api/RetailcrmApiRequest.php +++ b/retailcrm/lib/api/RetailcrmApiRequest.php @@ -38,11 +38,17 @@ class RetailcrmApiRequest { - private $api; + /** + * @var \RetailcrmProxy|\RetailcrmApiClientV5 + */ + protected $api; - private $data; + protected $data; - private $method; + /** + * @var string + */ + protected $method; /** * @return mixed diff --git a/retailcrm/lib/api/RetailcrmApiSinceIdRequest.php b/retailcrm/lib/api/RetailcrmApiSinceIdRequest.php new file mode 100644 index 0000000..8b13495 --- /dev/null +++ b/retailcrm/lib/api/RetailcrmApiSinceIdRequest.php @@ -0,0 +1,67 @@ + + * @copyright 2021 DIGITAL RETAIL TECHNOLOGIES SL + * @license https://opensource.org/licenses/MIT The MIT License + * + * Don't forget to prefix your containers with your own identifier + * to avoid any conflicts with others containers. + */ + +class RetailcrmApiSinceIdRequest extends RetailcrmApiPaginatedRequest +{ + private $currentSinceId; + + protected function buildParams($placeholderParams, $currentPage = null) + { + if (null !== $this->currentSinceId) { + $placeholderParams[0]['sinceId'] = $this->currentSinceId; + + if (isset($placeholderParams[0]['startDate'])) { + unset($placeholderParams[0]['startDate']); + } + } + + return parent::buildParams($placeholderParams, 1); + } + + protected function getNextPageNumber($page, $response) + { + $resultData = $response[$this->dataKey]; + $lastRecord = end($resultData); + + if (isset($lastRecord['id'])) { + $this->currentSinceId = $lastRecord['id']; + } + + return $page + 1; + } +} diff --git a/retailcrm/retailcrm.php b/retailcrm/retailcrm.php index 955c280..9cc2d56 100644 --- a/retailcrm/retailcrm.php +++ b/retailcrm/retailcrm.php @@ -111,7 +111,7 @@ class RetailCRM extends Module { $this->name = 'retailcrm'; $this->tab = 'export'; - $this->version = '3.4.1'; + $this->version = '3.4.2'; $this->author = 'DIGITAL RETAIL TECHNOLOGIES SL'; $this->displayName = $this->l('Simla.com'); $this->description = $this->l('Integration module for Simla.com'); diff --git a/tests/bootstrap.php b/tests/bootstrap.php index af64aa3..aa29f7c 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -49,6 +49,7 @@ require_once __DIR__ . '/../retailcrm/retailcrm.php'; require_once __DIR__ . '/../../PrestaShop/init.php'; require_once __DIR__ . '/helpers/RetailcrmTestCase.php'; require_once __DIR__ . '/helpers/RetailcrmTestHelper.php'; +require_once __DIR__ . '/lib/api/RetailcrmApiRequestTestAbstract.php'; $module = new RetailCRM(); $module->install(); diff --git a/tests/lib/api/RetailcrmApiPaginatedRequestTest.php b/tests/lib/api/RetailcrmApiPaginatedRequestTest.php index 18d65c2..6bcdddd 100644 --- a/tests/lib/api/RetailcrmApiPaginatedRequestTest.php +++ b/tests/lib/api/RetailcrmApiPaginatedRequestTest.php @@ -36,46 +36,13 @@ * to avoid any conflicts with others containers. */ -class RetailcrmApiPaginatedRequestTest extends RetailcrmTestCase +class RetailcrmApiPaginatedRequestTest extends RetailcrmApiRequestTestAbstract { - private $apiMock; - - protected function setUp() + public function doApiHistoryRequest($limit, $pageLimit) { - parent::setUp(); - - $this->apiMock = $this->getMockBuilder('RetailcrmProxy') - ->disableOriginalConstructor() - ->setMethods( - [ - 'ordersHistory', - ] - ) - ->getMock() - ; - } - - public function getPageLimits() - { - return [ - 'Big history' => [2, 3, 12, 6], - 'Equal history' => [2, 3, 6, 6], - 'Small history' => [2, 3, 3, 3], - ]; - } - - /** - * @dataProvider getPageLimits - */ - public function testPageLimit($limit, $pageLimit, $totalCount, $expectedTotalCount) - { - $this->apiMock->expects($this->any()) - ->method('ordersHistory') - ->willReturnOnConsecutiveCalls(...$this->getHistory($limit, $totalCount)) - ; - $request = new RetailcrmApiPaginatedRequest(); - $history = $request + + return $request ->setApi($this->apiMock) ->setMethod('ordersHistory') ->setParams([[], '{{page}}']) @@ -85,49 +52,5 @@ class RetailcrmApiPaginatedRequestTest extends RetailcrmTestCase ->execute() ->getData() ; - - $lastId = end($history)['id']; - - $this->assertEquals($expectedTotalCount, count($history)); - $this->assertEquals($expectedTotalCount, $lastId); - } - - private function getHistory($limit, $totalCount) - { - $totalPageCount = ceil($totalCount / $limit); - $currentPage = 0; - - while ($currentPage < $totalPageCount) { - $history = []; - - $from = ($limit * $currentPage) + 1; - $to = ($limit * $currentPage) + $limit; - if ($to > $totalCount) { - $to = $totalCount; - } - - foreach (range($from, $to) as $historyId) { - $history[] = [ - 'id' => $historyId, - ]; - } - ++$currentPage; - - yield new RetailcrmApiResponse( - '200', - json_encode( - [ - 'success' => true, - 'history' => $history, - 'pagination' => [ - 'limit' => $limit, - 'totalCount' => $totalCount, - 'currentPage' => $currentPage, - 'totalPageCount' => $totalPageCount, - ], - ] - ) - ); - } } } diff --git a/tests/lib/api/RetailcrmApiRequestTestAbstract.php b/tests/lib/api/RetailcrmApiRequestTestAbstract.php new file mode 100644 index 0000000..d860513 --- /dev/null +++ b/tests/lib/api/RetailcrmApiRequestTestAbstract.php @@ -0,0 +1,125 @@ + + * @copyright 2021 DIGITAL RETAIL TECHNOLOGIES SL + * @license https://opensource.org/licenses/MIT The MIT License + * + * Don't forget to prefix your containers with your own identifier + * to avoid any conflicts with others containers. + */ + +abstract class RetailcrmApiRequestTestAbstract extends RetailcrmTestCase +{ + protected $apiMock; + + protected function setUp() + { + parent::setUp(); + + $this->apiMock = $this->getMockBuilder('RetailcrmProxy') + ->disableOriginalConstructor() + ->setMethods( + [ + 'ordersHistory', + ] + ) + ->getMock() + ; + } + + public function getPageLimits() + { + return [ + 'Big history' => [2, 3, 12, 6], + 'Equal history' => [2, 3, 6, 6], + 'Small history' => [2, 3, 3, 3], + ]; + } + + /** + * @dataProvider getPageLimits + */ + public function testPageLimit($limit, $pageLimit, $totalCount, $expectedTotalCount) + { + $this->apiMock->expects($this->any()) + ->method('ordersHistory') + ->willReturnOnConsecutiveCalls(...$this->getHistory($limit, $totalCount)) + ; + + $history = $this->doApiHistoryRequest($limit, $pageLimit); + + $lastId = end($history)['id']; + + $this->assertEquals($expectedTotalCount, count($history)); + $this->assertEquals($expectedTotalCount, $lastId); + } + + private function getHistory($limit, $totalCount) + { + $totalPageCount = ceil($totalCount / $limit); + $currentPage = 0; + + while ($currentPage < $totalPageCount) { + $history = []; + + $from = ($limit * $currentPage) + 1; + $to = ($limit * $currentPage) + $limit; + if ($to > $totalCount) { + $to = $totalCount; + } + + foreach (range($from, $to) as $historyId) { + $history[] = [ + 'id' => $historyId, + ]; + } + ++$currentPage; + + yield new RetailcrmApiResponse( + '200', + json_encode( + [ + 'success' => true, + 'history' => $history, + 'pagination' => [ + 'limit' => $limit, + 'totalCount' => $totalCount, + 'currentPage' => $currentPage, + 'totalPageCount' => $totalPageCount, + ], + ] + ) + ); + } + } + + abstract function doApiHistoryRequest($limit, $pageLimit); +} diff --git a/tests/lib/api/RetailcrmApiSinceIdRequestTest.php b/tests/lib/api/RetailcrmApiSinceIdRequestTest.php new file mode 100644 index 0000000..8439cc9 --- /dev/null +++ b/tests/lib/api/RetailcrmApiSinceIdRequestTest.php @@ -0,0 +1,55 @@ + + * @copyright 2021 DIGITAL RETAIL TECHNOLOGIES SL + * @license https://opensource.org/licenses/MIT The MIT License + * + * Don't forget to prefix your containers with your own identifier + * to avoid any conflicts with others containers. + */ + +class RetailcrmApiSinceIdRequestTest extends RetailcrmApiRequestTestAbstract +{ + public function doApiHistoryRequest($limit, $pageLimit) + { + $request = new RetailcrmApiSinceIdRequest(); + + return $request + ->setApi($this->apiMock) + ->setMethod('ordersHistory') + ->setParams([[]]) + ->setDataKey('history') + ->setPageLimit($pageLimit) + ->execute() + ->getData() + ; + } +}