diff --git a/CHACNGELOG.md b/CHACNGELOG.md index 47f4fa3..2bfc3a3 100644 --- a/CHACNGELOG.md +++ b/CHACNGELOG.md @@ -1,3 +1,6 @@ +## 2018-12-25 v.2.4.0 +* Добавлен функционал получения остатков из retailCRM + ## 2018-12-25 v.2.3.2 * Добавлена выгрузка картинок категорий товаров в ICML diff --git a/VERSION b/VERSION index e703481..9183195 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.3.2 \ No newline at end of file +2.4.0 \ No newline at end of file diff --git a/src/Cron/Inventories.php b/src/Cron/Inventories.php new file mode 100644 index 0000000..7433eab --- /dev/null +++ b/src/Cron/Inventories.php @@ -0,0 +1,24 @@ +helper = $helper; + $this->inventoriesUpload = $InventoriesUpload; + } + + public function execute() + { + if ($this->helper->getInventoriesUpload() == true) { + $this->inventoriesUpload->uploadInventory(); + } + } +} diff --git a/src/Helper/Data.php b/src/Helper/Data.php index 91792c5..dc805fc 100644 --- a/src/Helper/Data.php +++ b/src/Helper/Data.php @@ -16,6 +16,7 @@ class Data extends AbstractHelper const XML_PATH_DEFAULT_SITE = 'retailcrm_site/default'; const XML_PATH_SITES = 'retailcrm_sites/'; const XML_PATH_DAEMON_COLLECTOR = 'daemon_collector/'; + const XML_PATH_INVENTORIES = 'inventories_upload/'; public function __construct( Context $context, @@ -131,6 +132,20 @@ class Data extends AbstractHelper return false; } + public function getInventoriesUpload() + { + $inventories = $this->scopeConfig->getValue( + self::XML_PATH_RETAILCRM . self::XML_PATH_INVENTORIES . 'active', + ScopeConfigInterface::SCOPE_TYPE_DEFAULT + ); + + if ($inventories) { + return true; + } + + return false; + } + /** * @param $website * diff --git a/src/Model/Service/InventoriesUpload.php b/src/Model/Service/InventoriesUpload.php new file mode 100644 index 0000000..73c7e60 --- /dev/null +++ b/src/Model/Service/InventoriesUpload.php @@ -0,0 +1,55 @@ +productRepo = $productRepo; + $this->api = $api; + } + + /** + * {@inheritdoc} + */ + public function uploadInventory() + { + if (!$this->api->isConfigured()) { + return false; + } + + $page = 1; + + do { + $response = $this->api->storeInventories(array(), $page, 250); + + if ($response === false || !$response->isSuccessful()) { + return false; + } + + foreach ($response['offers'] as $offer) { + if (isset($offer['externalId'])) { + $product = $this->productRepo->getById($offer['externalId']); + $product->setStockData( + ['qty' => $offer['quantity'], + 'is_in_stock' => $offer['quantity'] > 0] + ); + $product->save(); + } + } + + $totalPageCount = $response['pagination']['totalPageCount']; + $page++; + } while ($page <= $totalPageCount); + + return true; + } +} diff --git a/src/Model/Setting/DaemonCollector.php b/src/Model/Setting/Select.php similarity index 76% rename from src/Model/Setting/DaemonCollector.php rename to src/Model/Setting/Select.php index fc838ca..7fedb6e 100644 --- a/src/Model/Setting/DaemonCollector.php +++ b/src/Model/Setting/Select.php @@ -2,7 +2,7 @@ namespace Retailcrm\Retailcrm\Model\Setting; -class DaemonCollector implements \Magento\Framework\Option\ArrayInterface +class Select implements \Magento\Framework\Option\ArrayInterface { public function toOptionArray() { diff --git a/src/Test/Unit/Model/Service/InventoriesUploadTest.php b/src/Test/Unit/Model/Service/InventoriesUploadTest.php new file mode 100644 index 0000000..edbe880 --- /dev/null +++ b/src/Test/Unit/Model/Service/InventoriesUploadTest.php @@ -0,0 +1,123 @@ +mockApi = $this->getMockBuilder(\Retailcrm\Retailcrm\Helper\Proxy::class) + ->disableOriginalConstructor() + ->setMethods([ + 'storeInventories', + 'isConfigured' + ]) + ->getMock(); + + $this->mockProductRepository = $this->getMockBuilder(\Magento\Catalog\Api\ProductRepositoryInterface::class) + ->disableOriginalConstructor() + ->setMethods(['getById']) + ->getMockForAbstractClass(); + + $this->mockResponse = $this->getMockBuilder(\RetailCrm\Response\ApiResponse::class) + ->disableOriginalConstructor() + ->setMethods(['isSuccessful']) + ->getMock(); + + $this->mockProduct = $this->getMockBuilder(\Magento\Catalog\Model\Product::class) + ->disableOriginalConstructor() + ->setMethods([ + 'setStockData', + 'save' + ]) + ->getMock(); + } + + /** + * @param $response + * + * @dataProvider dataProviderLoadStocks + */ + public function testInventoriesUpdload($response) + { + if ($response != false) { + $responseInventories = new \RetailCrm\Response\ApiResponse(200, json_encode($response)); + + $this->mockResponse->expects($this->any()) + ->method('isSuccessful') + ->willReturn(true); + + $this->mockApi->expects($this->any()) + ->method('isConfigured') + ->willReturn(true); + + $this->mockApi->expects($this->any()) + ->method('storeInventories') + ->willReturn($responseInventories); + + $this->mockProductRepository->expects($this->any()) + ->method('getById') + ->willReturn($this->mockProduct); + } else { + $this->mockResponse->expects($this->any()) + ->method('isSuccessful') + ->willReturn($response); + } + + $inventoriesUpload = new \Retailcrm\Retailcrm\Model\Service\InventoriesUpload($this->mockProductRepository, $this->mockApi); + $result = $inventoriesUpload->uploadInventory(); + + if (!$response['success']) { + $this->assertEquals(false, $result); + } else { + $this->assertEquals(true, $result); + } + } + + private function getResponseData() + { + return array( + 'true' => $this->getApiInventories(), + 'false' => false + ); + } + + public function dataProviderLoadStocks() + { + $response = $this->getResponseData(); + + return array( + array( + 'response' => $response['true'] + ), + array( + 'response' => $response['false'] + ) + ); + } + + private function getApiInventories() + { + return array( + 'success' => true, + 'pagination' => array( + 'limit' => 250, + 'totalCount' => 1, + 'currentPage' => 1, + 'totalPageCount' => 1 + ), + 'offers' => array( + array( + 'externalId' => 1, + 'xmlId' => 'xmlId', + 'quantity' => 10 + ) + ) + ); + } +} diff --git a/src/composer.json b/src/composer.json index 4c327d5..97f5bc7 100644 --- a/src/composer.json +++ b/src/composer.json @@ -5,7 +5,7 @@ "retailcrm/api-client-php": "~5.0" }, "type": "magento2-module", - "version": "2.3.2", + "version": "2.4.0", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/src/etc/adminhtml/system.xml b/src/etc/adminhtml/system.xml index 8fa6dac..3130bb6 100644 --- a/src/etc/adminhtml/system.xml +++ b/src/etc/adminhtml/system.xml @@ -68,12 +68,19 @@ - Retailcrm\Retailcrm\Model\Setting\DaemonCollector + Retailcrm\Retailcrm\Model\Setting\Select + + + + + Retailcrm\Retailcrm\Model\Setting\Select + + diff --git a/src/etc/crontab.xml b/src/etc/crontab.xml index 44e38d3..3ee7f21 100644 --- a/src/etc/crontab.xml +++ b/src/etc/crontab.xml @@ -7,5 +7,8 @@ */5 * * * * + + */15 * * * * + \ No newline at end of file diff --git a/src/i18n/es_ES.csv b/src/i18n/es_ES.csv index 0dc474f..edd009c 100644 --- a/src/i18n/es_ES.csv +++ b/src/i18n/es_ES.csv @@ -23,4 +23,5 @@ "Send","Enviar" "Default site","Tienda por defecto" "Activate","Active" -"Site key","Clave de la página web" \ No newline at end of file +"Site key","Clave de la página web" +"Synchronization of the stock balance","Sincronizar el stock" \ No newline at end of file diff --git a/src/i18n/ru_RU.csv b/src/i18n/ru_RU.csv index 35339e3..43d50aa 100644 --- a/src/i18n/ru_RU.csv +++ b/src/i18n/ru_RU.csv @@ -23,4 +23,5 @@ "Send","Выгрузить" "Default site","Сайт по умолчанию" "Activate","Активировать" -"Site key","Ключ сайта" \ No newline at end of file +"Site key","Ключ сайта" +"Synchronization of the stock balance","Синхронизация остатков" \ No newline at end of file