Updated paginated API requests to use sinceId instead of page number

This commit is contained in:
max-baranikov 2022-06-14 17:17:05 +03:00 committed by GitHub
parent 1568783e9f
commit fb811c7bdf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 298 additions and 172 deletions

View File

@ -1,3 +1,6 @@
## v3.4.2
* Переработан механизм постраничной обработки истории изменений на использование sinceId вместо page
## v3.4.1 ## v3.4.1
* Исправлено стили страницы настроек для старых версий PS * Исправлено стили страницы настроек для старых версий PS
* Исправлена сортировка файлов журналов на странице настроек * Исправлена сортировка файлов журналов на странице настроек

View File

@ -1 +1 @@
3.4.1 3.4.2

View File

@ -78,25 +78,22 @@ class RetailcrmHistory
{ {
$lastSync = Configuration::get('RETAILCRM_LAST_CUSTOMERS_SYNC'); $lastSync = Configuration::get('RETAILCRM_LAST_CUSTOMERS_SYNC');
$customerFix = [];
$filter = false === $lastSync $filter = false === $lastSync
? ['startDate' => date('Y-m-d H:i:s', strtotime('-1 days', strtotime(date('Y-m-d H:i:s'))))] ? ['startDate' => date('Y-m-d H:i:s', strtotime('-1 days', strtotime(date('Y-m-d H:i:s'))))]
: ['sinceId' => $lastSync]; : ['sinceId' => $lastSync];
$request = new RetailcrmApiPaginatedRequest(); $request = new RetailcrmApiSinceIdRequest();
$historyChanges = [];
$history = $request $history = $request
->setApi(self::$api) ->setApi(self::$api)
->setMethod('customersHistory') ->setMethod('customersHistory')
->setParams([$filter, '{{page}}']) ->setParams([$filter])
->setDataKey('history') ->setDataKey('history')
->setLimit(100)
->setPageLimit(50) ->setPageLimit(50)
->execute() ->execute()
->getData() ->getData()
; ;
$historyChanges = [];
if (0 < count($history)) { if (0 < count($history)) {
$historyChanges = static::filterHistory($history, 'customer'); $historyChanges = static::filterHistory($history, 'customer');
$end = end($history); $end = end($history);
@ -107,6 +104,8 @@ class RetailcrmHistory
$customersHistory = RetailcrmHistoryHelper::assemblyCustomer($historyChanges); $customersHistory = RetailcrmHistoryHelper::assemblyCustomer($historyChanges);
RetailcrmLogger::writeDebugArray(__METHOD__, ['Assembled history:', $customersHistory]); RetailcrmLogger::writeDebugArray(__METHOD__, ['Assembled history:', $customersHistory]);
$customerFix = [];
foreach ($customersHistory as $customerHistory) { foreach ($customersHistory as $customerHistory) {
$customerHistory = RetailcrmTools::filter( $customerHistory = RetailcrmTools::filter(
'RetailcrmFilterCustomersHistory', 'RetailcrmFilterCustomersHistory',
@ -211,37 +210,23 @@ class RetailcrmHistory
public static function ordersHistory() public static function ordersHistory()
{ {
$lastSync = Configuration::get('RETAILCRM_LAST_ORDERS_SYNC'); $lastSync = Configuration::get('RETAILCRM_LAST_ORDERS_SYNC');
$lastDate = Configuration::get('RETAILCRM_LAST_SYNC');
if (false === $lastSync && false === $lastDate) { $filter = false === $lastSync
$filter = [ ? ['startDate' => date('Y-m-d H:i:s', strtotime('-1 days', strtotime(date('Y-m-d H:i:s'))))]
'startDate' => date( : ['sinceId' => $lastSync];
'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 = [];
}
$historyChanges = []; $request = new RetailcrmApiSinceIdRequest();
$request = new RetailcrmApiPaginatedRequest();
$history = $request $history = $request
->setApi(self::$api) ->setApi(self::$api)
->setMethod('ordersHistory') ->setMethod('ordersHistory')
->setParams([$filter, '{{page}}']) ->setParams([$filter])
->setDataKey('history') ->setDataKey('history')
->setLimit(100)
->setPageLimit(50) ->setPageLimit(50)
->execute() ->execute()
->getData() ->getData()
; ;
$historyChanges = [];
if (0 < count($history)) { if (0 < count($history)) {
$historyChanges = static::filterHistory($history, 'order'); $historyChanges = static::filterHistory($history, 'order');
$end = end($history); $end = end($history);

View File

@ -36,27 +36,17 @@
* to avoid any conflicts with others containers. * to avoid any conflicts with others containers.
*/ */
class RetailcrmApiPaginatedRequest class RetailcrmApiPaginatedRequest extends RetailcrmApiRequest
{ {
/**
* @var \RetailcrmProxy|\RetailcrmApiClientV5
*/
private $api;
/**
* @var string
*/
private $method;
/** /**
* @var array * @var array
*/ */
private $params; protected $params;
/** /**
* @var string * @var string
*/ */
private $dataKey; protected $dataKey;
/** /**
* @var int * @var int
@ -66,12 +56,7 @@ class RetailcrmApiPaginatedRequest
/** /**
* @var int|null * @var int|null
*/ */
private $pageLimit; protected $pageLimit;
/**
* @var array
*/
private $data;
/** /**
* RetailcrmApiPaginatedRequest constructor. * RetailcrmApiPaginatedRequest constructor.
@ -81,34 +66,6 @@ class RetailcrmApiPaginatedRequest
$this->reset(); $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) * 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)) { if ($response instanceof RetailcrmApiResponse && $response->offsetExists($this->dataKey)) {
$this->data = array_merge($this->data, $response[$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) { if (null !== $this->pageLimit && $page > $this->pageLimit) {
@ -198,16 +156,6 @@ class RetailcrmApiPaginatedRequest
return $this; return $this;
} }
/**
* Returns data
*
* @return array
*/
public function getData()
{
return $this->data;
}
/** /**
* Reset paginated request * Reset paginated request
* *
@ -224,14 +172,14 @@ class RetailcrmApiPaginatedRequest
} }
/** /**
* buildParams * buildParams for the request
* *
* @param array $placeholderParams * @param array $placeholderParams
* @param int $currentPage * @param int $currentPage
* *
* @return mixed * @return mixed
*/ */
private function buildParams($placeholderParams, $currentPage) protected function buildParams($placeholderParams, $currentPage)
{ {
foreach ($placeholderParams as $key => $param) { foreach ($placeholderParams as $key => $param) {
if ('{{page}}' == $param) { if ('{{page}}' == $param) {
@ -245,4 +193,17 @@ class RetailcrmApiPaginatedRequest
return $placeholderParams; 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;
}
} }

View File

@ -38,11 +38,17 @@
class RetailcrmApiRequest class RetailcrmApiRequest
{ {
private $api; /**
* @var \RetailcrmProxy|\RetailcrmApiClientV5
*/
protected $api;
private $data; protected $data;
private $method; /**
* @var string
*/
protected $method;
/** /**
* @return mixed * @return mixed

View File

@ -0,0 +1,67 @@
<?php
/**
* MIT License
*
* Copyright (c) 2021 DIGITAL RETAIL TECHNOLOGIES SL
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to http://www.prestashop.com for more information.
*
* @author DIGITAL RETAIL TECHNOLOGIES SL <mail@simlachat.com>
* @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;
}
}

View File

@ -111,7 +111,7 @@ class RetailCRM extends Module
{ {
$this->name = 'retailcrm'; $this->name = 'retailcrm';
$this->tab = 'export'; $this->tab = 'export';
$this->version = '3.4.1'; $this->version = '3.4.2';
$this->author = 'DIGITAL RETAIL TECHNOLOGIES SL'; $this->author = 'DIGITAL RETAIL TECHNOLOGIES SL';
$this->displayName = $this->l('Simla.com'); $this->displayName = $this->l('Simla.com');
$this->description = $this->l('Integration module for Simla.com'); $this->description = $this->l('Integration module for Simla.com');

View File

@ -49,6 +49,7 @@ require_once __DIR__ . '/../retailcrm/retailcrm.php';
require_once __DIR__ . '/../../PrestaShop/init.php'; require_once __DIR__ . '/../../PrestaShop/init.php';
require_once __DIR__ . '/helpers/RetailcrmTestCase.php'; require_once __DIR__ . '/helpers/RetailcrmTestCase.php';
require_once __DIR__ . '/helpers/RetailcrmTestHelper.php'; require_once __DIR__ . '/helpers/RetailcrmTestHelper.php';
require_once __DIR__ . '/lib/api/RetailcrmApiRequestTestAbstract.php';
$module = new RetailCRM(); $module = new RetailCRM();
$module->install(); $module->install();

View File

@ -36,46 +36,13 @@
* to avoid any conflicts with others containers. * to avoid any conflicts with others containers.
*/ */
class RetailcrmApiPaginatedRequestTest extends RetailcrmTestCase class RetailcrmApiPaginatedRequestTest extends RetailcrmApiRequestTestAbstract
{ {
private $apiMock; public function doApiHistoryRequest($limit, $pageLimit)
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))
;
$request = new RetailcrmApiPaginatedRequest(); $request = new RetailcrmApiPaginatedRequest();
$history = $request
return $request
->setApi($this->apiMock) ->setApi($this->apiMock)
->setMethod('ordersHistory') ->setMethod('ordersHistory')
->setParams([[], '{{page}}']) ->setParams([[], '{{page}}'])
@ -85,49 +52,5 @@ class RetailcrmApiPaginatedRequestTest extends RetailcrmTestCase
->execute() ->execute()
->getData() ->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,
],
]
)
);
}
} }
} }

View File

@ -0,0 +1,125 @@
<?php
/**
* MIT License
*
* Copyright (c) 2021 DIGITAL RETAIL TECHNOLOGIES SL
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to http://www.prestashop.com for more information.
*
* @author DIGITAL RETAIL TECHNOLOGIES SL <mail@simlachat.com>
* @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);
}

View File

@ -0,0 +1,55 @@
<?php
/**
* MIT License
*
* Copyright (c) 2021 DIGITAL RETAIL TECHNOLOGIES SL
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to http://www.prestashop.com for more information.
*
* @author DIGITAL RETAIL TECHNOLOGIES SL <mail@simlachat.com>
* @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()
;
}
}