From 7a8be5f637487146af5944bb99cb63e9e1625596 Mon Sep 17 00:00:00 2001 From: gleemand Date: Mon, 15 Nov 2021 15:14:16 +0300 Subject: [PATCH] Added middleware to receive order number (CRM->PS) --- retailcrm/lib/RetailcrmExport.php | 9 +- retailcrm/lib/api/RetailcrmProxy.php | 45 ++-- .../RetailcrmReferenceMiddleware.php | 71 ++++++ retailcrm/retailcrm.php | 6 +- tests/RetailcrmTest.php | 209 ++++++++++++++---- tests/helpers/RetailcrmTestCase.php | 22 ++ tests/lib/RetailcrmHistoryTest.php | 6 +- .../api/RetailcrmReferenceMiddlewareTest.php | 94 ++++++++ 8 files changed, 396 insertions(+), 66 deletions(-) create mode 100644 retailcrm/lib/api/middleware/RetailcrmReferenceMiddleware.php create mode 100644 tests/lib/api/RetailcrmReferenceMiddlewareTest.php diff --git a/retailcrm/lib/RetailcrmExport.php b/retailcrm/lib/RetailcrmExport.php index b2abef5..4f1b27a 100644 --- a/retailcrm/lib/RetailcrmExport.php +++ b/retailcrm/lib/RetailcrmExport.php @@ -368,7 +368,6 @@ class RetailcrmExport /** * @param int $id - * @param false $receiveOrderNumber * * @return bool * @@ -376,7 +375,7 @@ class RetailcrmExport * @throws PrestaShopDatabaseException * @throws PrestaShopException */ - public static function exportOrder($id, $receiveOrderNumber = false) + public static function exportOrder($id) { if (!static::$api) { return false; @@ -410,12 +409,6 @@ class RetailcrmExport if (empty($existingOrder)) { $response = static::$api->ordersCreate($crmOrder); - - if ($receiveOrderNumber && $response instanceof RetailcrmApiResponse && $response->isSuccessful()) { - $crmOrder = $response->order; - $object->reference = $crmOrder['number']; - $object->update(); - } } else { $response = static::$api->ordersEdit($crmOrder); diff --git a/retailcrm/lib/api/RetailcrmProxy.php b/retailcrm/lib/api/RetailcrmProxy.php index 3513a4d..a4718cd 100755 --- a/retailcrm/lib/api/RetailcrmProxy.php +++ b/retailcrm/lib/api/RetailcrmProxy.php @@ -52,22 +52,7 @@ class RetailcrmProxy { $this->client = new RetailcrmApiClientV5($url, $key); - $this->pipeline = new RetailcrmPipeline(); - $this->pipeline - ->setMiddlewares( - RetailcrmTools::filter( - 'RetailcrmFilterMiddlewares', - [ - RetailcrmExceptionMiddleware::class, - RetailcrmLoggerMiddleware::class, - ] - ) - ) - ->setAction(function ($request) { - return call_user_func_array([$this->client, $request->getMethod()], $request->getData()); - }) - ->build() - ; + $this->buildPipeline(); } public function __call($method, $arguments) @@ -81,4 +66,32 @@ class RetailcrmProxy return $this->pipeline->run($request); } + + public function setClient($client) + { + $this->client = $client; + + $this->buildPipeline(); + } + + private function buildPipeline() + { + $this->pipeline = new RetailcrmPipeline(); + $this->pipeline + ->setMiddlewares( + RetailcrmTools::filter( + 'RetailcrmFilterMiddlewares', + [ + RetailcrmExceptionMiddleware::class, + RetailcrmLoggerMiddleware::class, + RetailcrmReferenceMiddleware::class, + ] + ) + ) + ->setAction(function ($request) { + return call_user_func_array([$this->client, $request->getMethod()], $request->getData()); + }) + ->build() + ; + } } diff --git a/retailcrm/lib/api/middleware/RetailcrmReferenceMiddleware.php b/retailcrm/lib/api/middleware/RetailcrmReferenceMiddleware.php new file mode 100644 index 0000000..b2183c2 --- /dev/null +++ b/retailcrm/lib/api/middleware/RetailcrmReferenceMiddleware.php @@ -0,0 +1,71 @@ + + * @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 RetailcrmReferenceMiddleware implements RetailcrmMiddlewareInterface +{ + /** + * {@inheritDoc} + */ + public function __invoke(RetailcrmApiRequest $request, callable $next = null) + { + /** @var RetailcrmApiResponse $response */ + $response = $next($request); + + if ( + $response->isSuccessful() + && ( + 'ordersCreate' === $request->getMethod() + || 'ordersEdit' === $request->getMethod() + ) + ) { + $receiveOrderNumber = (bool) (Configuration::get(RetailCRM::ENABLE_ORDER_NUMBER_RECEIVING)); + $crmOrder = $response->order; + + if ( + $receiveOrderNumber + && isset($crmOrder['externalId'], $crmOrder['number']) + ) { + $object = new Order($crmOrder['externalId']); + $object->reference = $crmOrder['number']; + $object->update(); + } + } + + return $response; + } +} diff --git a/retailcrm/retailcrm.php b/retailcrm/retailcrm.php index a3d07ff..ae41786 100644 --- a/retailcrm/retailcrm.php +++ b/retailcrm/retailcrm.php @@ -356,13 +356,12 @@ class RetailCRM extends Module $isSuccessful = true; $skippedOrders = []; RetailcrmExport::$api = $this->api; - $receiveOrderNumber = (bool) (Configuration::get(RetailCRM::ENABLE_ORDER_NUMBER_RECEIVING)); foreach ($orderIds as $orderId) { $response = false; try { - $response = RetailcrmExport::exportOrder($orderId, $receiveOrderNumber); + $response = RetailcrmExport::exportOrder($orderId); } catch (PrestaShopObjectNotFoundExceptionCore $e) { $skippedOrders[] = $orderId; } catch (Exception $e) { @@ -736,13 +735,12 @@ class RetailCRM extends Module } $status = json_decode(Configuration::get(static::STATUS), true); - $receiveOrderNumber = (bool) (Configuration::get(RetailCRM::ENABLE_ORDER_NUMBER_RECEIVING)); if (isset($params['orderStatus'])) { try { RetailcrmExport::$api = $this->api; - return RetailcrmExport::exportOrder($params['order']->id, $receiveOrderNumber); + return RetailcrmExport::exportOrder($params['order']->id); } catch (Exception $e) { RetailcrmLogger::writeCaller(__METHOD__, $e->getMessage()); RetailcrmLogger::writeNoCaller($e->getTraceAsString()); diff --git a/tests/RetailcrmTest.php b/tests/RetailcrmTest.php index aa79598..425ce70 100644 --- a/tests/RetailcrmTest.php +++ b/tests/RetailcrmTest.php @@ -3,7 +3,6 @@ class RetailCRMTest extends RetailcrmTestCase { private $retailcrmModule; - private $apiMock; protected function setUp() { @@ -11,54 +10,78 @@ class RetailCRMTest extends RetailcrmTestCase $this->setConfig(); - $this->apiMock = $this->apiMockBuilder()->getMock(); - $this->retailcrmModule = new RetailCRM(); - $this->retailcrmModule->api = $this->apiMock; - } - - private function apiMockBuilder() - { - return $this->getMockBuilder('RetailcrmProxy') - ->disableOriginalConstructor() - ->setMethods( - [ - 'customersCreate', - 'customersEdit', - 'customersGet', - 'ordersCreate', - 'ordersEdit', - 'ordersGet', - 'ordersPaymentEdit', - 'ordersPaymentCreate', - ] - ) - ; + $this->retailcrmModule->api = $this->getApiMock( + [ + 'customersCreate', + 'customersEdit', + 'customersGet', + 'ordersCreate', + 'ordersEdit', + 'ordersGet', + 'ordersPaymentEdit', + 'ordersPaymentCreate', + ] + ); } public function testUploadOrders() { Configuration::updateValue(RetailCRM::API_URL, 'https://test.test'); Configuration::updateValue(RetailCRM::API_KEY, 'test_key'); + $order = new Order(1); $reference = $order->reference; $updReference = 'test'; - $this->apiMock->expects($this->any())->method('ordersGet')->willReturn(new RetailcrmApiResponse( + + $this->apiClientMock->expects($this->any())->method('ordersGet')->willReturn(new RetailcrmApiResponse( 200, json_encode([ 'success' => true, 'order' => [], ]) )); - $this->apiMock->expects($this->any())->method('ordersCreate')->willReturn(new RetailcrmApiResponse( + $this->apiClientMock->expects($this->any())->method('ordersCreate')->willReturn(new RetailcrmApiResponse( 200, json_encode([ 'success' => true, 'order' => [ + 'externalId' => 1, 'number' => $updReference, ], ]) )); + $this->apiClientMock->expects($this->any())->method('ordersEdit')->willReturn(new RetailcrmApiResponse( + 200, + json_encode([ + 'success' => true, + 'order' => [ + 'externalId' => 1, + 'number' => $updReference, + ], + ]) + )); + $this->apiClientMock->expects($this->any())->method('customersGet')->willReturn(new RetailcrmApiResponse( + 200, + json_encode([ + 'success' => true, + 'customer' => [], + ]) + )); + $this->apiClientMock->expects($this->any())->method('customersCreate')->willReturn(new RetailcrmApiResponse( + 200, + json_encode([ + 'success' => true, + 'customer' => [], + ]) + )); + $this->apiClientMock->expects($this->any())->method('ordersPaymentCreate')->willReturn(new RetailcrmApiResponse( + 200, + json_encode([ + 'success' => true, + 'payment' => [], + ]) + )); Configuration::updateValue(RetailCRM::ENABLE_ORDER_NUMBER_RECEIVING, false); $this->retailcrmModule->uploadOrders([1]); @@ -78,6 +101,21 @@ class RetailCRMTest extends RetailcrmTestCase $newCustomer = new Customer(1); $params = ['newCustomer' => $newCustomer]; + $this->apiClientMock->expects($this->any())->method('customersGet')->willReturn(new RetailcrmApiResponse( + 200, + json_encode([ + 'success' => true, + 'customer' => [], + ]) + )); + $this->apiClientMock->expects($this->any())->method('customersCreate')->willReturn(new RetailcrmApiResponse( + 200, + json_encode([ + 'success' => true, + 'customer' => [], + ]) + )); + $this->assertTrue($this->retailcrmModule->hookActionCustomerAccountAdd($params)); } @@ -86,6 +124,23 @@ class RetailCRMTest extends RetailcrmTestCase $customer = new Customer(1); $params = ['customer' => $customer]; + $this->apiClientMock->expects($this->any())->method('customersGet')->willReturn(new RetailcrmApiResponse( + 200, + json_encode([ + 'success' => true, + 'customer' => [ + 'phones' => [], + ], + ]) + )); + $this->apiClientMock->expects($this->any())->method('customersEdit')->willReturn(new RetailcrmApiResponse( + 200, + json_encode([ + 'success' => true, + 'customer' => [], + ]) + )); + $this->assertTrue($this->retailcrmModule->hookActionCustomerAccountUpdate($params)); } @@ -97,15 +152,7 @@ class RetailCRMTest extends RetailcrmTestCase $reference = $order->reference; $updReference = 'test'; - $this->apiMock->expects($this->any())->method('ordersGet')->willReturn(new RetailcrmApiResponse( - 200, - json_encode([ - 'success' => true, - 'order' => [], - ]) - )); - - $this->apiMock->expects($this->any())->method('ordersCreate')->willReturn(new RetailcrmApiResponse( + $this->apiClientMock->expects($this->any())->method('ordersGet')->willReturn(new RetailcrmApiResponse( 200, json_encode([ 'success' => true, @@ -114,15 +161,56 @@ class RetailCRMTest extends RetailcrmTestCase ], ]) )); + $this->apiClientMock->expects($this->any())->method('ordersCreate')->willReturn(new RetailcrmApiResponse( + 200, + json_encode([ + 'success' => true, + 'order' => [ + 'number' => $updReference, + ], + ]) + )); + $this->apiClientMock->expects($this->any())->method('ordersEdit')->willReturn(new RetailcrmApiResponse( + 200, + json_encode([ + 'success' => true, + 'order' => [ + 'number' => $updReference, + ], + ]) + )); + $this->apiClientMock->expects($this->any())->method('customersGet')->willReturn(new RetailcrmApiResponse( + 200, + json_encode([ + 'success' => true, + 'customer' => [], + ]) + )); + $this->apiClientMock->expects($this->any())->method('customersCreate')->willReturn(new RetailcrmApiResponse( + 200, + json_encode([ + 'success' => true, + 'customer' => [], + ]) + )); + $this->apiClientMock->expects($this->any())->method('ordersPaymentCreate')->willReturn(new RetailcrmApiResponse( + 200, + json_encode([ + 'success' => true, + 'payment' => [], + ]) + )); Configuration::updateValue(RetailCRM::ENABLE_ORDER_NUMBER_RECEIVING, false); $this->assertTrue($this->retailcrmModule->hookActionOrderEdited($params)); + $order = new Order(1); $this->assertEquals($reference, $order->reference); Configuration::updateValue(RetailCRM::ENABLE_ORDER_NUMBER_RECEIVING, true); $this->assertTrue($this->retailcrmModule->hookActionOrderEdited($params)); + $order = new Order(1); $this->assertEquals($updReference, $order->reference); } @@ -158,7 +246,7 @@ class RetailCRMTest extends RetailcrmTestCase 'cart' => $cart, ]; - $this->apiMock->expects($this->any())->method('ordersGet')->willReturn(new RetailcrmApiResponse( + $this->apiClientMock->expects($this->any())->method('ordersGet')->willReturn(new RetailcrmApiResponse( 200, json_encode([ 'success' => true, @@ -167,15 +255,47 @@ class RetailCRMTest extends RetailcrmTestCase )); } - $this->apiMock->expects($this->any())->method('ordersCreate')->willReturn(new RetailcrmApiResponse( + $this->apiClientMock->expects($this->any())->method('ordersCreate')->willReturn(new RetailcrmApiResponse( 200, json_encode([ 'success' => true, 'order' => [ + 'externalId' => 1, 'number' => $updReference, ], ]) )); + $this->apiClientMock->expects($this->any())->method('ordersEdit')->willReturn(new RetailcrmApiResponse( + 200, + json_encode([ + 'success' => true, + 'order' => [ + 'externalId' => 1, + 'number' => $updReference, + ], + ]) + )); + $this->apiClientMock->expects($this->any())->method('customersGet')->willReturn(new RetailcrmApiResponse( + 200, + json_encode([ + 'success' => true, + 'customer' => [], + ]) + )); + $this->apiClientMock->expects($this->any())->method('customersCreate')->willReturn(new RetailcrmApiResponse( + 200, + json_encode([ + 'success' => true, + 'customer' => [], + ]) + )); + $this->apiClientMock->expects($this->any())->method('ordersPaymentCreate')->willReturn(new RetailcrmApiResponse( + 200, + json_encode([ + 'success' => true, + 'payment' => [], + ]) + )); Configuration::updateValue(RetailCRM::ENABLE_ORDER_NUMBER_RECEIVING, false); @@ -204,10 +324,25 @@ class RetailCRMTest extends RetailcrmTestCase 'cart' => $cart, ]; + $this->apiClientMock->expects($this->any())->method('ordersPaymentCreate')->willReturn(new RetailcrmApiResponse( + 200, + json_encode([ + 'success' => true, + 'payment' => [], + ]) + )); + $this->apiClientMock->expects($this->any())->method('ordersGet')->willReturn(new RetailcrmApiResponse( + 200, + json_encode([ + 'success' => true, + 'order' => [], + ]) + )); + $referenceMock = $this->createMock('RetailcrmReferences'); $referenceMock->expects($this->once())->method('getSystemPaymentModules')->willReturn($this->getSystemPaymentModules()); $this->retailcrmModule->reference = $referenceMock; - $this->apiMock->expects($this->any())->method('ordersGet')->willReturn($ordersGet); + $this->apiClientMock->expects($this->any())->method('ordersGet')->willReturn($ordersGet); $result = $this->retailcrmModule->hookActionPaymentCCAdd($params); diff --git a/tests/helpers/RetailcrmTestCase.php b/tests/helpers/RetailcrmTestCase.php index 5b0d967..49b3fd5 100644 --- a/tests/helpers/RetailcrmTestCase.php +++ b/tests/helpers/RetailcrmTestCase.php @@ -6,6 +6,10 @@ if (class_exists('LegacyTests\Unit\ContextMocker')) { abstract class RetailcrmTestCase extends \PHPUnit\Framework\TestCase { + private $apiMock; + + protected $apiClientMock; + protected $contextMock; protected function setUp() @@ -18,6 +22,16 @@ abstract class RetailcrmTestCase extends \PHPUnit\Framework\TestCase } } + protected function getApiMock(array $methods) + { + $this->apiClientMock = $this->apiMockBuilder($methods)->getMock(); + + $this->apiMock = new RetailcrmProxy('https://test.test', 'test_key'); + $this->apiMock->setClient($this->apiClientMock); + + return $this->apiMock; + } + protected function setConfig() { $delivery = json_encode( @@ -46,4 +60,12 @@ abstract class RetailcrmTestCase extends \PHPUnit\Framework\TestCase Configuration::updateValue('RETAILCRM_API_STATUS', $status); Configuration::updateValue('RETAILCRM_API_PAYMENT', $payment); } + + private function apiMockBuilder(array $methods) + { + return $this->getMockBuilder('RetailcrmApiClientV5') + ->disableOriginalConstructor() + ->setMethods($methods) + ; + } } diff --git a/tests/lib/RetailcrmHistoryTest.php b/tests/lib/RetailcrmHistoryTest.php index fc6e11b..e7a2580 100644 --- a/tests/lib/RetailcrmHistoryTest.php +++ b/tests/lib/RetailcrmHistoryTest.php @@ -135,7 +135,11 @@ class RetailcrmHistoryTest extends RetailcrmTestCase '200', json_encode( [ - 'order' => [], + 'success' => true, + 'order' => [ + 'externalId' => $order->id, + 'number' => $updReference, + ], ] ) ) diff --git a/tests/lib/api/RetailcrmReferenceMiddlewareTest.php b/tests/lib/api/RetailcrmReferenceMiddlewareTest.php new file mode 100644 index 0000000..8a54a00 --- /dev/null +++ b/tests/lib/api/RetailcrmReferenceMiddlewareTest.php @@ -0,0 +1,94 @@ +apiMock = $this->getApiMock( + [ + 'ordersCreate', + 'ordersEdit', + 'ordersGet', + ] + ); + } + + public function getRequests() + { + return [ + [ + 'method' => 'ordersGet', + 'params' => [[]], + 'reference' => 'reference', + ], + [ + 'method' => 'ordersEdit', + 'params' => [['number' => 'test', 'externalId' => 1]], + 'reference' => 'test', + ], + [ + 'method' => 'ordersCreate', + 'params' => [['number' => 'test', 'externalId' => 1]], + 'reference' => 'test', + ], + ]; + } + + /** + * @dataProvider getRequests + */ + public function testRequest($method, $params, $reference) + { + $this->apiClientMock->expects($this->any())->method('ordersCreate')->willReturn(new RetailcrmApiResponse( + 200, + json_encode([ + 'success' => true, + 'order' => [ + 'number' => 'test', + 'externalId' => 1, + ], + ]) + )); + $this->apiClientMock->expects($this->any())->method('ordersEdit')->willReturn(new RetailcrmApiResponse( + 200, + json_encode([ + 'success' => true, + 'order' => [ + 'number' => 'test', + 'externalId' => 1, + ], + ]) + )); + $this->apiClientMock->expects($this->any())->method('ordersGet')->willReturn(new RetailcrmApiResponse( + 200, + json_encode([ + 'success' => true, + 'order' => [ + 'number' => 'test', + 'externalId' => 1, + ], + ]) + )); + + Configuration::updateValue(RetailCRM::ENABLE_ORDER_NUMBER_RECEIVING, true); + + $order = new Order(1); + $order->reference = 'reference'; + $order->update(); + unset($order); + + /** @var RetailcrmApiResponse $response */ + $response = $this->apiMock->$method($params); + + $this->assertInstanceOf(RetailcrmApiResponse::class, $response); + $this->assertTrue($response->isSuccessful()); + + $order = new Order(1); + + $this->assertEquals($reference, $order->reference); + } +}