diff --git a/Block/Adminhtml/DocumentType/Edit/BackButton.php b/Block/Adminhtml/DocumentType/Edit/BackButton.php new file mode 100644 index 0000000..b317170 --- /dev/null +++ b/Block/Adminhtml/DocumentType/Edit/BackButton.php @@ -0,0 +1,23 @@ + __('Back'), + 'on_click' => sprintf("location.href = '%s';", $this->getBackUrl()), + 'class' => 'back', + 'sort_order' => 10 + ]; + } + + public function getBackUrl() + { + return $this->getUrl('*/*/'); + } +} \ No newline at end of file diff --git a/Block/Adminhtml/DocumentType/Edit/GenericButton.php b/Block/Adminhtml/DocumentType/Edit/GenericButton.php new file mode 100644 index 0000000..88756c6 --- /dev/null +++ b/Block/Adminhtml/DocumentType/Edit/GenericButton.php @@ -0,0 +1,36 @@ +urlBuilder = $context->getUrlBuilder(); + } + + /** + * Generate url by route and parameters + * + * @param string $route + * @param array $params + * @return string + */ + public function getUrl($route = '', $params = []) + { + return $this->urlBuilder->getUrl($route, $params); + } +} diff --git a/Block/Adminhtml/DocumentType/Edit/SaveButton.php b/Block/Adminhtml/DocumentType/Edit/SaveButton.php new file mode 100644 index 0000000..73c4442 --- /dev/null +++ b/Block/Adminhtml/DocumentType/Edit/SaveButton.php @@ -0,0 +1,21 @@ + __('Save'), + 'data_attribute' => [ + 'mage-init' => ['button' => ['event' => 'save']], + 'form-role' => 'save', + ], + 'sort_order' => 90, + 'class' => 'save primary' + ]; + } +} \ No newline at end of file diff --git a/Block/Adminhtml/DocumentType/GenericButton.php b/Block/Adminhtml/DocumentType/GenericButton.php new file mode 100644 index 0000000..da1fe91 --- /dev/null +++ b/Block/Adminhtml/DocumentType/GenericButton.php @@ -0,0 +1,45 @@ +scopeConfig = $context->getScopeConfig(); + $this->urlBuilder = $context->getUrlBuilder(); + } + + /** + * Generate url by route and parameters + * + * @param string $route + * @param array $params + * @return string + */ + public function getUrl($route = '', $params = []) + { + return $this->urlBuilder->getUrl($route, $params); + } + + public function shouldDisplayButton(){ + return (null !== $this->scopeConfig->getValue('megaventory/general/synctimestamp')); + } +} diff --git a/Block/Adminhtml/InventoryAdjustment/Edit/BackButton.php b/Block/Adminhtml/InventoryAdjustment/Edit/BackButton.php new file mode 100644 index 0000000..0b530c6 --- /dev/null +++ b/Block/Adminhtml/InventoryAdjustment/Edit/BackButton.php @@ -0,0 +1,23 @@ + __('Back'), + 'on_click' => sprintf("location.href = '%s';", $this->getBackUrl()), + 'class' => 'back', + 'sort_order' => 10 + ]; + } + + public function getBackUrl() + { + return $this->getUrl('*/index/index') . '#locations'; + } +} \ No newline at end of file diff --git a/Block/Adminhtml/InventoryAdjustment/Edit/GenericButton.php b/Block/Adminhtml/InventoryAdjustment/Edit/GenericButton.php new file mode 100644 index 0000000..f708e40 --- /dev/null +++ b/Block/Adminhtml/InventoryAdjustment/Edit/GenericButton.php @@ -0,0 +1,49 @@ +urlBuilder = $context->getUrlBuilder(); + $this->request = $requestInterface; + } + + /** + * Generate url by route and parameters + * + * @param string $route + * @param array $params + * @return string + */ + public function getUrl($route = '', $params = []) + { + return $this->urlBuilder->getUrl($route, $params); + } + + public function getId() + { + $id = $this->request->getParam('id',null); + return $id; + } +} diff --git a/Block/Adminhtml/InventoryAdjustment/Edit/SaveButton.php b/Block/Adminhtml/InventoryAdjustment/Edit/SaveButton.php new file mode 100644 index 0000000..c59efbd --- /dev/null +++ b/Block/Adminhtml/InventoryAdjustment/Edit/SaveButton.php @@ -0,0 +1,21 @@ + __('Save'), + 'data_attribute' => [ + 'mage-init' => ['button' => ['event' => 'save']], + 'form-role' => 'save', + ], + 'sort_order' => 90, + 'class' => 'save primary' + ]; + } +} \ No newline at end of file diff --git a/Block/Adminhtml/InventoryAdjustment/Edit/SourceRemove.php b/Block/Adminhtml/InventoryAdjustment/Edit/SourceRemove.php new file mode 100644 index 0000000..1489431 --- /dev/null +++ b/Block/Adminhtml/InventoryAdjustment/Edit/SourceRemove.php @@ -0,0 +1,50 @@ +_inventoryFactory = $inventoriesFactory; + $this->_inventoryResource = $inventoriesResource; + } + + public function getButtonData() + { + $data = []; + if ($this->getId() && $this->shouldDisplay()) { + $data = [ + 'label' => __('Remove Inventory Source Association'), + 'class' => 'action-secondary', + 'on_click' => 'deleteConfirm(\'' + . __('This will also disable this inventory location until an inventory source is assigned again. Are you sure?') + . '\', \'' . $this->getRemovalUrl() . '\')', + 'sort_order' => 20, + ]; + } + return $data; + } + + public function getRemovalUrl() + { + return $this->getUrl('megaventory/inventory/unassigninventorysource', ['id' => $this->getId()]); + } + + private function shouldDisplay(){ + $inventory = $this->_inventoryFactory->create(); + $this->_inventoryResource->load($inventory, $this->getId()); + return ($inventory->getStockSourceCode() !== null); + } +} \ No newline at end of file diff --git a/Block/Adminhtml/LogHeader.php b/Block/Adminhtml/LogHeader.php new file mode 100644 index 0000000..286b447 --- /dev/null +++ b/Block/Adminhtml/LogHeader.php @@ -0,0 +1,7 @@ +getUrl('megaventory/updates/process'); + } +} \ No newline at end of file diff --git a/Block/Settings.php b/Block/Settings.php index d343a44..d8c15ba 100644 --- a/Block/Settings.php +++ b/Block/Settings.php @@ -13,6 +13,9 @@ class Settings extends \Magento\Backend\Block\Template protected $_inventoriesHelper; protected $_taxesHelper; protected $_scopeConfig; + protected $_sourceRepository; + protected $_sourceCollection; + protected $_backendSession; private $_settings; private $_mvConnectivity; @@ -22,6 +25,16 @@ class Settings extends \Magento\Backend\Block\Template private $_defaultMegaventoryCurrency; private $_inventories; private $_taxes; + + private $_algorithmConfigSource; + private $_inventoryCollectionFactory; + + private $_productAttributeCollectionFactory; + + private $_adjustmentTemplateFactory; + private $_adjustmentTemplateResource; + private $_adjustmentTemplateCollectionFactory; + /** * @var string */ @@ -29,35 +42,49 @@ class Settings extends \Magento\Backend\Block\Template public function __construct( \Magento\Backend\Block\Template\Context $context, + \Magento\InventoryApi\Api\SourceRepositoryInterface $sourceRepo, + \Magento\Backend\Model\Session $backendSession, + \Magento\Inventory\Model\ResourceModel\Source\CollectionFactory $sourceCollection, + \Magento\Catalog\Model\ResourceModel\Product\Attribute\CollectionFactory $productAttributeCollectionFactory, + \Mv\Megaventory\Model\ResourceModel\Inventories\CollectionFactory $inventoriesCollectionFactory, \Mv\Megaventory\Helper\Data $mvHelper, \Mv\Megaventory\Helper\Inventories $inventoriesHelper, - \Mv\Megaventory\Helper\Taxes $taxesHelper + \Mv\Megaventory\Helper\Taxes $taxesHelper, + \Mv\Megaventory\Model\Config\Source\SourceSelectionAlgorithmConfigSource $sourceSelectionAlgorithmOptions, + \Mv\Megaventory\Model\AdjustmentTemplateFactory $adjustmentTemplateFactory, + \Mv\Megaventory\Model\ResourceModel\AdjustmentTemplate $adjustmentTemplateResource, + \Mv\Megaventory\Model\ResourceModel\AdjustmentTemplate\CollectionFactory $adjustmentTemplateCollectionFactory ) { parent::__construct($context); $this->_context = $context; + $this->_sourceRepository = $sourceRepo; + $this->_sourceCollection = $sourceCollection; + $this->_algorithmConfigSource = $sourceSelectionAlgorithmOptions; $this->_mvHelper = $mvHelper; + $this->_backendSession = $backendSession; $this->_inventoriesHelper = $inventoriesHelper; $this->_taxesHelper = $taxesHelper; $this->_scopeConfig = $context->getScopeConfig(); + $this->_inventoryCollectionFactory = $inventoriesCollectionFactory; + $this->_productAttributeCollectionFactory = $productAttributeCollectionFactory; + + $this->_adjustmentTemplateResource = $adjustmentTemplateResource; + $this->_adjustmentTemplateFactory = $adjustmentTemplateFactory; + $this->_adjustmentTemplateCollectionFactory = $adjustmentTemplateCollectionFactory; $this->_settings = $this->_scopeConfig->getValue('megaventory/general'); $this->_mvConnectivity = $this->_mvHelper->checkConnectivity(); + $this->_inventories = []; + $this->_taxes = []; - if ($this->_mvConnectivity !== false) { + if ($this->_mvHelper->checkAccount() !== false) { $setting = $this->_mvHelper->getMegaventoryAccountSettings('MagentoInstallations'); $this->_magentoInstallations = $setting['0']['SettingValue']; - /* if (isset($this->_settings['MagentoInstallations'])) - $this->_magentoInstallations = $this->_settings['MagentoInstallations']; - else - $this->_magentoInstallations = 1; */ - - $this->_defaultMegaventoryCurrency = $this->setDefaultMegaventoryCurrency(); $this->_defaultMagentoCurrency = $this->_scopeConfig->getValue('currency/options/default'); - $this->_inventories = $this->_inventoriesHelper->getInventories(); $this->_taxes = $this->_taxesHelper->getTaxes(); } @@ -67,7 +94,59 @@ protected function _prepareLayout() { parent::_prepareLayout(); } + + public function getInventoryEditUrl($inventory){ + $inventoryId = $inventory->getId(); + + $url = $this->getUrl('megaventory/inventory/edit',['id'=>$inventoryId]); + return $url; + } + + public function getAttributes() + { + return $this->_productAttributeCollectionFactory->create() + ->addVisibleFilter() + ->addFieldToFilter('frontend_input', ['in'=>['select','text']]); + } + public function getPriceAttributes() + { + return $this->_productAttributeCollectionFactory->create() + ->addVisibleFilter() + ->addFieldToFilter('frontend_input', 'price'); + } + public function getAlgorithmList() + { + return $this->_algorithmConfigSource->toOptionArray(); + } + public function getSources($inventoryId = false) + { + $inventoriesWithSource = $this->_inventoryCollectionFactory->create() + ->addFieldToSelect('stock_source_code') + ->addFieldToFilter('stock_source_code', ['notnull'=>true]); + $allocatedSources = array_values($inventoriesWithSource->toArray()['items']); + $sources = $this->_sourceCollection->create(); + if (count($allocatedSources) > 0) { + $sources->addFieldToFilter('source_code', ['nin'=>$allocatedSources]); + } + return $sources; + } + + public function getSource($inventory) + { + $result = -1; + + if ($inventory->getStockSourceCode() === null) { + return -1; + } + try { + $result = $this->_sourceRepository->get($inventory->getStockSourceCode()); + } catch (\Magento\Framework\Exception\NoSuchEntityException $e){ //Inventory Source Not Found + $result = -1; + } + return $result; + } + public function getSettingValue($name) { @@ -87,6 +166,10 @@ public function getMagentoInstallations() { return $this->_magentoInstallations; } + + public function isSyncStartAllowed(){ + return (!$this->_mvHelper->isSyncStartNotAllowed()); + } private function setDefaultMegaventoryCurrency() { @@ -97,7 +180,6 @@ private function setDefaultMegaventoryCurrency() $apikey = $this->_scopeConfig->getValue('megaventory/general/apikey'); $apiurl = $this->_scopeConfig->getValue('megaventory/general/apiurl'); - $data = [ 'APIKEY' => $apikey, @@ -137,4 +219,25 @@ public function getTaxes() { return $this->_taxes; } + + public function getAdjustmentNegativeTemplates(){ + return $this->_adjustmentTemplateCollectionFactory->create()->addFieldToFilter('stock_change',-1); + } + + public function getAdjustmentPositiveTemplates(){ + return $this->_adjustmentTemplateCollectionFactory->create()->addFieldToFilter('stock_change',1); + } + + public function getAdjustmentTemplateName($inventory, $positive = true){ + $templateId = ($positive) ? (int)$inventory->getMvAdjustmentPlusTypeId() : (int)$inventory->getMvAdjustmentMinusTypeId(); + + if($templateId > 0){ + $template = $this->_adjustmentTemplateFactory->create(); + + $this->_adjustmentTemplateResource->load($template, $templateId); + + return $template->getName(); + } + return ""; + } } diff --git a/Controller/Adminhtml/DocumentTypes/Edit.php b/Controller/Adminhtml/DocumentTypes/Edit.php new file mode 100644 index 0000000..e35724f --- /dev/null +++ b/Controller/Adminhtml/DocumentTypes/Edit.php @@ -0,0 +1,24 @@ +resultPageFactory = $resultPageFactory; + } + + public function execute() + { + /* @var \Magento\Backend\Model\View\Result\Page $resultPage */ + $resultPage = $this->resultPageFactory->create(); + + return $resultPage; + } +} \ No newline at end of file diff --git a/Controller/Adminhtml/DocumentTypes/Index.php b/Controller/Adminhtml/DocumentTypes/Index.php new file mode 100644 index 0000000..29e0ae0 --- /dev/null +++ b/Controller/Adminhtml/DocumentTypes/Index.php @@ -0,0 +1,37 @@ +resultPageFactory = $resultPageFactory; + $this->mvHelper = $mvHelper; + $this->documentTypeAdapter = $documentTypeAdapter; + } + + public function execute() + { + /* @var \Magento\Backend\Model\View\Result\Page $resultPage */ + if(($this->mvHelper->checkConnectivity() === true) && ($this->mvHelper->checkAccount())){ + $this->documentTypeAdapter->reloadDocumentTypesFromApi(); + } + $resultPage = $this->resultPageFactory->create(); + + return $resultPage; + } +} \ No newline at end of file diff --git a/Controller/Adminhtml/DocumentTypes/Save.php b/Controller/Adminhtml/DocumentTypes/Save.php new file mode 100644 index 0000000..0739326 --- /dev/null +++ b/Controller/Adminhtml/DocumentTypes/Save.php @@ -0,0 +1,75 @@ +documentTypeFactory = $documentTypeFactory; + $this->documentTypeResource = $documentTypeResource; + $this->documentTypeCollectionFactory = $documentTypeCollectionFactory; + $this->request = $request; + $this->redirectFactory = $redirectFactory; + $this->documentTypeHelper = $documentTypeHelper; + } + + public function execute() + { + $params = $this->_request->getParam('website_associations_general')['website_associations']; + + if(($params === null) || ! in_array('id', array_keys($params))){ + $this->messageManager->addErrorMessage('Invalid Request.'); + return $this->redirectFactory->create()->setUrl($this->_redirect->getRefererUrl()); + } + + $id = (in_array('id', array_keys($params))) ? (int)$params['id'] : null; + + if(null === $id || empty($id) || ($id === 0)){ + $this->messageManager->addErrorMessage('An unexpected error occurred and the entity could not be saved.'); + return $this->redirectFactory->create()->setUrl($this->_redirect->getRefererUrl()); + } + + $websiteIds = (in_array('magento_website_ids', array_keys($params)) && is_array($params['magento_website_ids'])) ? $params['magento_website_ids'] : []; + + $removedFromOtherTypes = $this->documentTypeHelper->removeWebsiteFromOtherTypes($websiteIds, [$id]); + + $currentAssociations = $this->documentTypeHelper->getAssociations($id); + + $assignedOrphansToDefault = $this->documentTypeHelper->assignOrphanedWebsitesToDefaultDocumentType($websiteIds, $currentAssociations); + + + if(!$removedFromOtherTypes || !$assignedOrphansToDefault){ + $this->messageManager->addErrorMessage('An unexpected error occurred and the entity could not be saved.'); + return $this->redirectFactory->create()->setPath('*/*/index'); + } + + $update = $this->documentTypeHelper->updateWebsiteAssociations($websiteIds, $id); + + if(!$update){ + $this->messageManager->addErrorMessage('Unable to save entity.'); + return $this->redirectFactory->create()->setPath('*/*/index'); + } + + $this->messageManager->addSuccessMessage('The order template has been assigned to the respective Magento websites successfully.'); + return $this->redirectFactory->create()->setPath('*/*/index'); + } +} \ No newline at end of file diff --git a/Controller/Adminhtml/Index/AlgorithmSave.php b/Controller/Adminhtml/Index/AlgorithmSave.php new file mode 100644 index 0000000..e864b0e --- /dev/null +++ b/Controller/Adminhtml/Index/AlgorithmSave.php @@ -0,0 +1,66 @@ +_configWriter = $configWriter; + $this->_messageManager = $messageManager; + $this->_cacheTypeList = $cacheTypeList; + $this->_urlBuilder = $urlBuilder; + $this->_redirectResultFactory = $redirectFactory; + + parent::__construct($context); + } + + public function execute() + { + $code = $this->getRequest()->getParam('algorithm_code'); + $result = ['message'=>'Algorithm has been saved','type'=>'success']; + $path = 'megaventory/orders/source_selection_algorithm_code'; + $scope = \Magento\Framework\App\Config\ScopeConfigInterface::SCOPE_TYPE_DEFAULT; + try { + $this->_configWriter->save($path, $code, $scope, 0); + } catch (\Exception $e) { + $result['message'] = $e->getMessage(); + $result['type'] = 'error'; + } + + try { + $this->_cacheTypeList->cleanType(\Magento\Framework\App\Cache\Type\Config::TYPE_IDENTIFIER); + } catch (\Exception $e) { + $result['message'] .= ", but unable to refresh configuration values, please clear the magento cache"; + } + + switch ($result['type']) { + case 'success': + $this->_messageManager->addSuccessMessage($result['message']); + break; + case 'warning': + $this->_messageManager->addWarningMessage($result['message']); + break; + case 'error': + $this->_messageManager->addErrorMessage($result['message']); + break; + } + + $url = $this->_urlBuilder->getUrl('megaventory/index/index') . '#locations'; + + return $this->_redirectResultFactory->create()->setUrl($url); + } +} diff --git a/Controller/Adminhtml/Index/CheckHeartBeatExpiration.php b/Controller/Adminhtml/Index/CheckHeartBeatExpiration.php new file mode 100644 index 0000000..b94926b --- /dev/null +++ b/Controller/Adminhtml/Index/CheckHeartBeatExpiration.php @@ -0,0 +1,60 @@ +jsonResultFactory = $jsonResultFactory; + $this->scopeConfig = $scopeConfig; + } + + public function execute() + { + $currentDateTime = date('Y-m-d H:i:s'); + $lastHeartBeat = $this->scopeConfig->getValue('megaventory/synchronization/starttime'); + if(empty($lastHeartBeat)){ + $result = [ + 'success'=>true, + 'status'=>'lock_expired' + ]; + + $jsonResponse = $this->jsonResultFactory->create(); + $jsonResponse->setHttpResponseCode(200); + $jsonResponse->setData($result); + + return $jsonResponse; + + } + $expiration = date('Y-m-d H:i:s',strtotime($lastHeartBeat . ' +3 minutes')); + + $result = ['success'=>true]; + if($currentDateTime > $expiration){ + $result['status'] = 'lock_expired'; + } + else{ + $diff = date_diff(date_create($expiration),date_create($currentDateTime)); + $representation = $diff->format('%I:%S'); + $result['status'] = 'lock_valid'; + $result['remaining'] = $representation; + } + + $jsonResponse = $this->jsonResultFactory->create(); + $jsonResponse->setHttpResponseCode(200); + $jsonResponse->setData($result); + + return $jsonResponse; + } +} \ No newline at end of file diff --git a/Controller/Adminhtml/Index/ExportStock.php b/Controller/Adminhtml/Index/ExportStock.php index ace7f96..a5451c7 100644 --- a/Controller/Adminhtml/Index/ExportStock.php +++ b/Controller/Adminhtml/Index/ExportStock.php @@ -5,15 +5,19 @@ class ExportStock extends \Magento\Backend\App\Action { protected $_inventoriesLoader; + protected $_inventoriesCollection; protected $_mvProductHelper; protected $_resultJsonFactory; protected $_cacheTypeList; protected $_directoryList; + protected $_mvInventoryResource; public function __construct( \Magento\Backend\App\Action\Context $context, \Mv\Megaventory\Model\InventoriesFactory $inventoriesLoader, \Mv\Megaventory\Helper\Product $mvProductHelper, + \Mv\Megaventory\Model\ResourceModel\Inventories\CollectionFactory $inventoriesCollection, + \Mv\Megaventory\Model\ResourceModel\Inventories $inventoriesResource, \Magento\Framework\App\Filesystem\DirectoryList $directoryList, \Magento\Framework\Controller\Result\JsonFactory $resultJsonFactory, \Magento\Framework\App\Cache\TypeListInterface $cacheTypeList @@ -23,27 +27,70 @@ public function __construct( $this->_resultJsonFactory = $resultJsonFactory; $this->_cacheTypeList = $cacheTypeList; $this->_directoryList = $directoryList; + $this->_inventoriesCollection = $inventoriesCollection; + $this->_mvInventoryResource = $inventoriesResource; parent::__construct($context); } public function execute() { - $inventoryId = $this->getRequest()->getParam('inventory'); + $enabledLocations = $this->_inventoriesCollection->create()->addFieldToFilter('stock_source_code',['notnull'=>true]); $startingIndex = (int) $this->getRequest()->getParam('startingIndex'); + $isInitialization = ((int)$this->getRequest()->getParam('init') === 1); + $adjIssued = ($this->getRequest()->getParam('adjustment') == 'true'); + $results = []; - if (isset($inventoryId)) { - $inventory = $this->_inventoriesLoader->create()->load($inventoryId); - $inventoryName = $inventory->getName() . ' (' . $inventory->getShortname() . ')'; - $inventoryMvId = (int) $inventory->getMegaventoryId(); - $results = $this->_mvProductHelper->exportStock($inventoryMvId, $startingIndex, $this->_directoryList); + if ($isInitialization) { + $locations = $this->getRequest()->getParam('locations'); + + foreach ($locations as $mvInventoryId => $preferences) { + $location = $this->_inventoriesLoader->create(); + $this->_mvInventoryResource->load($location, $mvInventoryId, 'megaventory_id'); + $location->setStockSourceCode($preferences['source']); + $location->setMvAdjustmentMinusTypeId($preferences['minus_template']); + $location->setMvAdjustmentPlusTypeId($preferences['plus_template']); + $location->setAdjustmentDocStatus($preferences['status']); + $this->_mvInventoryResource->save($location); + if($this->getRequest()->getParam('export_stock',false)){ + $results = $this->_mvProductHelper->exportStock( + $mvInventoryId, + $startingIndex, + $this->_directoryList, + $location->getStockSourceCode(), + $adjIssued + ); + if ($results['value'] == 'Error') { + break; + } + } + else{ + $results = [ + 'value' => 'Success', + 'message' => 'No adjustment was necessary', + 'startingIndex' => $startingIndex + ]; + } + } } else { - $results = [ - 'value' => 'Error', - 'message' => 'No inventory found', - 'startingIndex' => $startingIndex - ]; + foreach ($enabledLocations as $location) { + $results = $this->_mvProductHelper->exportStock( + $location->getMegaventoryId(), + $startingIndex, + $this->_directoryList, + $location->getStockSourceCode(), + $adjIssued + ); + if ($results['value'] == 'Error') { + break; + } + else{ + if($results['value'] === 'Continue'){ + $adjIssued = $results['adjMade']; + } + } + } } return $this->_resultJsonFactory->create()->setData($results); diff --git a/Controller/Adminhtml/Index/GetInventories.php b/Controller/Adminhtml/Index/GetInventories.php index 00faf50..95983de 100644 --- a/Controller/Adminhtml/Index/GetInventories.php +++ b/Controller/Adminhtml/Index/GetInventories.php @@ -29,10 +29,11 @@ public function __construct( public function execute() { $inventories = $this->_inventoriesHelper->getInventories(); + $options = []; + foreach ($inventories as $inventory) { - $options[] = ['value' => $inventory->getId() , 'text' => $inventory->getName()]; - //$options .= ''.$inventory->getName().'\n'; + $options[] = ['value' => $inventory->getMegaventoryId() , 'text' => $inventory->getName()]; } $result = ['options'=> $options]; diff --git a/Controller/Adminhtml/Index/GetProgress.php b/Controller/Adminhtml/Index/GetProgress.php index be8c0c5..a604513 100644 --- a/Controller/Adminhtml/Index/GetProgress.php +++ b/Controller/Adminhtml/Index/GetProgress.php @@ -7,10 +7,12 @@ class GetProgress extends \Magento\Backend\App\Action protected $_resource; protected $_resultJsonFactory; protected $_cacheTypeList; + protected $_mvDataHelper; public function __construct( \Magento\Backend\App\Action\Context $context, \Magento\Config\Model\ResourceModel\Config $resourceConfig, + \Mv\Megaventory\Helper\Data $mvDataHelper, \Magento\Framework\App\ResourceConnection $recource, \Magento\Framework\Controller\Result\JsonFactory $resultJsonFactory, \Magento\Framework\App\Cache\TypeListInterface $cacheTypeList @@ -19,12 +21,14 @@ public function __construct( $this->_resource = $recource; $this->_resultJsonFactory = $resultJsonFactory; $this->_cacheTypeList = $cacheTypeList; + $this->_mvDataHelper = $mvDataHelper; parent::__construct($context); } public function execute() { + $this->_mvDataHelper->updateHeartBeatTimestamp(); try { $connection = $this->_resource->getConnection(); $tableName = $this->_resource->getTableName('megaventory_progress'); @@ -32,7 +36,7 @@ public function execute() $lastlastMessagesSql = 'SELECT id, messagedata FROM '.$tableName.' ORDER BY id asc'; $deleteMessages = 'delete FROM '.$tableName; - $data = ""; + $data = []; $rows = $connection->fetchAll($lastlastMessagesSql); if (count($rows) > 0) { $message = ''; @@ -56,6 +60,7 @@ public function execute() return $this->_resultJsonFactory->create()->setData($data); } catch (\Exception $e) { + return $this->_resultJsonFactory->create()->setData([]); } } } diff --git a/Controller/Adminhtml/Index/ImportInventories.php b/Controller/Adminhtml/Index/ImportInventories.php index 96fa952..c63a3ae 100644 --- a/Controller/Adminhtml/Index/ImportInventories.php +++ b/Controller/Adminhtml/Index/ImportInventories.php @@ -24,6 +24,9 @@ public function __construct( public function execute() { $page = $this->getRequest()->getPost('page'); + if($page == 1){ + $this->_inventoriesHelper->truncateReservationsTable(); + } $nextPage = $this->_inventoriesHelper->syncrhonizeInventories($page, -1, -1); diff --git a/Controller/Adminhtml/Index/Index.php b/Controller/Adminhtml/Index/Index.php index aad8ba7..d8b8987 100644 --- a/Controller/Adminhtml/Index/Index.php +++ b/Controller/Adminhtml/Index/Index.php @@ -1,25 +1,41 @@ resultPageFactory = $resultPageFactory; + $this->inventoryHelper = $inventoryHelper; + $this->documentTypeAdapter = $documentTypeAdapter; + $this->mvHelper = $mvHelper; } public function execute() { - /* @var \Magento\Backend\Model\View\Result\Page $resultPage */ + if(($this->mvHelper->checkConnectivity() === true) && ($this->mvHelper->checkAccount())){ + $this->inventoryHelper->updateInventoryLocations(); + $this->documentTypeAdapter->reloadAdjustmentTemplatesFromApi(); + } $resultPage = $this->resultPageFactory->create(); return $resultPage; diff --git a/Controller/Adminhtml/Index/Savesettings.php b/Controller/Adminhtml/Index/Savesettings.php index 7620636..3526d96 100644 --- a/Controller/Adminhtml/Index/Savesettings.php +++ b/Controller/Adminhtml/Index/Savesettings.php @@ -7,14 +7,17 @@ class Savesettings extends \Magento\Backend\App\Action { protected $_resourceConfig; protected $_cacheTypeList; + protected $_urlBuilder; public function __construct( \Magento\Backend\App\Action\Context $context, \Magento\Config\Model\ResourceModel\Config $resourceConfig, - \Magento\Framework\App\Cache\TypeListInterface $cacheTypeList + \Magento\Framework\App\Cache\TypeListInterface $cacheTypeList, + \Magento\Framework\UrlInterface $urlBuilder ) { $this->_resourceConfig = $resourceConfig; $this->_cacheTypeList = $cacheTypeList; + $this->_urlBuilder = $urlBuilder; parent::__construct($context); } @@ -32,6 +35,7 @@ public function execute() /** @var \Magento\Backend\Model\View\Result\Redirect $resultRedirect */ $resultRedirect = $this->resultFactory->create(ResultFactory::TYPE_REDIRECT); - return $resultRedirect->setPath('*/*/'); + $url = $this->_urlBuilder->getUrl('megaventory/index/index'); + return $resultRedirect->setUrl($url); } } diff --git a/Controller/Adminhtml/Index/Setshippinganddiscountskus.php b/Controller/Adminhtml/Index/Setshippinganddiscountskus.php index ce83b10..19fc9cc 100644 --- a/Controller/Adminhtml/Index/Setshippinganddiscountskus.php +++ b/Controller/Adminhtml/Index/Setshippinganddiscountskus.php @@ -1,39 +1,90 @@ _resourceConfig = $resourceConfig; $this->_attributeFactory = $attributeFactory; $this->_resultJsonFactory = $resultJsonFactory; $this->_cacheTypeList = $cacheTypeList; + $this->_scopeConfig = $scopeConfigInterface; + $this->_mvDataHelper = $mvDataHelper; + $this->_backendSession = $backendSession; + $this->_mvInventoryHelper = $mvIntentoryHelper; + $this->_mvDocumentTypeAdapter =$documentTypeAdapter; parent::__construct($context); } public function execute() { - $shippingSKU = $this->getRequest()->getPost('shippingSKU'); - $discountSKU = $this->getRequest()->getPost('discountSKU'); - $magentoId = $this->getRequest()->getPost('magentoId'); + $shippingSKU = $this->getRequest()->getParam('shippingSKU'); + $discountSKU = $this->getRequest()->getParam('discountSKU'); + $magentoId = $this->getRequest()->getParam('magentoId'); + $purchasePriceAttributeCode = $this->getRequest()->getParam('purchase_price_attribute_code'); + + $isSyncStartNotAllowed = $this->_mvDataHelper->isSyncStartNotAllowed(); + + if($isSyncStartNotAllowed){ + $result = ['message'=>'Initial Synchronization is running','code'=>'initial_sync_runs']; + return $this->_resultJsonFactory->create()->setData($result); + } + + + + if((int)$this->_scopeConfig->getValue('megaventory/synchronization/started') == 1){ + $this->_resourceConfig->deleteConfig('megaventory/general/synctimestamp', 'default', 0); + $this->_resourceConfig->deleteConfig('megaventory/general/shippingproductsku', 'default', 0); + $this->_resourceConfig->deleteConfig('megaventory/general/discountproductsku', 'default', 0); + $this->_resourceConfig->deleteConfig('megaventory/general/magentoid', 'default', 0); + $this->_resourceConfig->deleteConfig('megaventory/general/supplierattributecode', 'default', 0); + $this->_resourceConfig->deleteConfig('megaventory/general/defaultguestid', 'default', 0); + $this->_resourceConfig->deleteConfig('megaventory/general/syncreport', 'default', 0); + $this->_resourceConfig->deleteConfig('megaventory/general/setupreport', 'default', 0); + $this->_resourceConfig->deleteConfig('megaventory/general/ordersynchronization', 'default', 0); + $this->_resourceConfig->deleteConfig('megaventory/feed/last_update', 'default', 0); + $this->_cacheTypeList->cleanType('config'); + + $this->_mvDataHelper->resetMegaventoryData(); + + $this->_mvInventoryHelper->updateInventoryLocations(); + + $this->_mvDocumentTypeAdapter->reloadAdjustmentTemplatesFromApi(); + } $this->_resourceConfig->saveConfig('megaventory/general/shippingproductsku', $shippingSKU, 'default', 0); $this->_resourceConfig->saveConfig('megaventory/general/discountproductsku', $discountSKU, 'default', 0); $this->_resourceConfig->saveConfig('megaventory/general/magentoid', $magentoId, 'default', 0); + $this->_resourceConfig->saveConfig('megaventory/general/purchasepriceattributecode', $purchasePriceAttributeCode, 'default', 0); //add supplier attribute in config data - $magentoSupplierAttributeCode = $this->getRequest()->getPost('magento_supplier_code'); + $magentoSupplierAttributeCode = $this->getRequest()->getParam('magento_supplier_code'); if (!empty($magentoSupplierAttributeCode)) { $attribute = $this->_attributeFactory->create()->loadByCode('catalog_product', $magentoSupplierAttributeCode); @@ -54,18 +105,18 @@ public function execute() 'message'=>'Supplier attribute must be of frontend type Text or Dropdown' ]; return $this->_resultJsonFactory->create()->setData($result); - //echo json_encode($result) . PHP_EOL; } $this->_resourceConfig->saveConfig('megaventory/general/supplierattributecode', $magentoSupplierAttributeCode, 'default', 0); } - //unfortunately $this->_cacheTypeList->cleanType('config'); $result = [ 'attribute_code'=>'ok' ]; + + $this->_mvDataHelper->saveInitialSyncFlags(); return $this->_resultJsonFactory->create()->setData($result); } } diff --git a/Controller/Adminhtml/Index/SyncData.php b/Controller/Adminhtml/Index/SyncData.php index fe158cc..b42d4dd 100644 --- a/Controller/Adminhtml/Index/SyncData.php +++ b/Controller/Adminhtml/Index/SyncData.php @@ -12,13 +12,13 @@ class SyncData extends \Magento\Backend\App\Action protected $_adminSession; protected $_mvHelper; - protected $_inventoriesHelper; protected $_categoryHelper; protected $_productHelper; protected $_customerHelper; protected $_currenciesHelper; protected $_taxesHelper; - + + protected $_apiDocumentTypeAdapter; public function __construct( \Magento\Backend\App\Action\Context $context, @@ -30,12 +30,12 @@ public function __construct( \Magento\Framework\Registry $registry, \Magento\Backend\Model\Auth\Session $adminSession, \Mv\Megaventory\Helper\Data $mvHelper, - \Mv\Megaventory\Helper\Inventories $inventoriesHelper, \Mv\Megaventory\Helper\Category $categoryHelper, \Mv\Megaventory\Helper\Product $productHelper, \Mv\Megaventory\Helper\Customer $customerHelper, \Mv\Megaventory\Helper\Currencies $currenciesHelper, - \Mv\Megaventory\Helper\Taxes $taxesHelper + \Mv\Megaventory\Helper\Taxes $taxesHelper, + \Mv\Megaventory\Model\ApiAdapter\DocumentTypeAdapter $documentTypeAdapter ) { $this->_scopeConfig = $scopeConfig; $this->_resourceConfig = $resourceConfig; @@ -46,12 +46,13 @@ public function __construct( $this->_adminSession = $adminSession; $this->_mvHelper = $mvHelper; - $this->_inventoriesHelper = $inventoriesHelper; $this->_categoryHelper = $categoryHelper; $this->_productHelper = $productHelper; $this->_customerHelper = $customerHelper; $this->_currenciesHelper = $currenciesHelper; $this->_taxesHelper = $taxesHelper; + + $this->_apiDocumentTypeAdapter = $documentTypeAdapter; parent::__construct($context); } @@ -64,73 +65,43 @@ public function execute() $result = ['message'=>'not_enabled']; return $this->_resultJsonFactory->create()->setData($result); } - + + $this->_mvHelper->updateHeartBeatTimestamp(); + static $step = 1; - //$totalSteps = 5; - $totalSteps = 4; - + $totalSteps = 3; $serverTime = '';//time(); - //TODO $tickImg = '';//''; $errorImg = '';//''; $this->_registry->register('tickImage', $tickImg); $this->_registry->register('errorImage', $errorImg); $result = []; - $syncStep = $this->getRequest()->get('step'); - $page = $this->getRequest()->get('page'); - $imported = $this->getRequest()->get('imported'); + $syncStep = $this->getRequest()->getParam('step'); + $page = $this->getRequest()->getParam('page'); + $imported = $this->getRequest()->getParam('imported'); if (empty($imported)) { $imported = 0; } - if ($syncStep == 'inventories') { - //first reset and then do it all from the beginning - $this->_mvHelper->resetMegaventoryData(); - - $this->_mvHelper->sendProgress(1, 'Step 1/'.$totalSteps.' Getting Inventory Locations from Megaventory', '0', 'inventories', false); - - $count = $this->_inventoriesHelper->initializeInventoryLocations(); - - if ($count == '-1') {//no inventories - $createdMessage = $this->_inventoriesHelper->createMainInventory(); - if ($createdMessage !== true) { - $this->_registry->registry(('errorImage'), '0', 'inventories-2', false); - $this->_mvHelper->sendProgress(3, $createdMessage, '0', 'inventories-3', false); - $result['nextstep'] = 'error'; - return $this->_resultJsonFactory->create()->setData($result); - } - - $this->_mvHelper->sendProgress(2, 'No Inventory Location found in Megaventory. Creating Main Inventory Location'.$this->_registry->registry('tickImage'), '0', 'inventories-2', false); - } else { - if (!$count == 1) { - $this->_mvHelper->sendProgress(2, $count.' Inventory Location imported from Megaventory'.$this->_registry->registry('tickImage'), '0', 'inventories', true); - } else { - $this->_mvHelper->sendProgress(2, $count.' Inventory Locations imported from Megaventory'.$this->_registry->registry('tickImage'), '0', 'inventories', true); - } - } - - $step++; - $result['currentstep'] = $syncStep; - $result['nextstep'] = 'supporting'; - $result['nextpage'] = '1'; - $result['imported'] = 0; - return $this->_resultJsonFactory->create()->setData($result); - } elseif ($syncStep == 'supporting') { - $this->_mvHelper->sendProgress(10, 'Step 2/'.$totalSteps.' Adding Supporting Entities to Megaventory', '0', 'entities', false); - $createdMessage = $this->_productHelper->addShippingProduct($this->_mvHelper); + if ($syncStep == 'supporting') { + $this->_mvHelper->sendProgress(10, 'Step 1/'.$totalSteps.' Adding Supporting Entities to Megaventory', '0', 'entities', false); + $shippingProductSku = $this->_scopeConfig->getValue('megaventory/general/shippingproductsku'); + $createdMessage = $this->_productHelper->addOrUpdateShippingProduct($shippingProductSku); if ($createdMessage !== true) { - $megaventoryHelper->sendProgress(11, 'There was a problem inserting Shipping Product in Megaventory!'.$this->_registry->registry('errorImage'), '0', 'shippingproduct', false); - $megaventoryHelper->sendProgress(12, $createdMessage, '0', 'shippingproduct', false); + $this->_mvHelper->sendProgress(11, 'There was a problem inserting Shipping Product in Megaventory!'.$this->_registry->registry('errorImage'), '0', 'shippingproduct', false); + $this->_mvHelper->sendProgress(12, $createdMessage, '0', 'shippingproduct', false); $result['nextstep'] = 'error'; return $this->_resultJsonFactory->create()->setData($result); } $this->_mvHelper->sendProgress(11, 'Shipping Product added successfully!', '0', 'shippingproduct', true); + + $discountProductSku = $this->_scopeConfig->getValue('megaventory/general/discountproductsku'); - $createdMessage = $this->_productHelper->addDiscountProduct(); + $createdMessage = $this->_productHelper->addOrUpdateDiscountProduct($discountProductSku); if ($createdMessage !== true) { $this->_mvHelper->sendProgress(12, 'There was a problem inserting Discount Product in Megaventory!'.$this->_registry->registry('errorImage'), '0', 'discountproduct', false); $this->_mvHelper->sendProgress(13, $createdMessage, '0', 'discountproduct', false); @@ -151,12 +122,11 @@ public function execute() return $this->_resultJsonFactory->create()->setData($result); } elseif ($syncStep == 'categories') { if ($page == '1') { - $this->_mvHelper->sendProgress(20, 'Step 3/'.$totalSteps.' Importing Categories to Megaventory..', '0', 'categories', false); + $this->_mvHelper->sendProgress(20, 'Step 2/'.$totalSteps.' Importing Categories to Megaventory..', '0', 'categories', false); } $import = $this->_categoryHelper->importCategoriesToMegaventory($page, $imported); - if ($import === false) { $result['currentstep'] = $syncStep; $result['nextstep'] = 'products'; @@ -172,16 +142,11 @@ public function execute() return $this->_resultJsonFactory->create()->setData($result); } elseif ($syncStep == 'products') { if ($page == '1') { - $this->_mvHelper->sendProgress(30, 'Step 4/'.$totalSteps.' Importing Products to Megaventory..', '0', 'products', false); + $this->_mvHelper->sendProgress(30, 'Step 3/'.$totalSteps.' Importing Products to Megaventory..', '0', 'products', false); } $import = $this->_productHelper->importProductsToMegaventory($page, $imported); - //TODO - //remove this!!!! - /* if ($page == 3) - $import = false; */ - if ($import === false) { $result['currentstep'] = $syncStep; $result['nextstep'] = 'finishing'; @@ -196,8 +161,9 @@ public function execute() return $this->_resultJsonFactory->create()->setData($result); } elseif ($syncStep == 'finishing') { + $this->_apiDocumentTypeAdapter->reloadDocumentTypesFromApi(true); $syncTimestamp = time(); - $this->_mvHelper->sendProgress(40, 'Entity import finished successfully at '.date(DATE_RFC2822, $syncTimestamp), '0', 'finish', true); + $this->_mvHelper->sendProgress(40, 'Setup Wizard finished successfully at '.date(DATE_RFC2822, $syncTimestamp), '0', 'finish', true); $this->_mvHelper->sendProgress(41, 'Saving Set up data for later reference!', '0', 'saveddata', false); $this->_mvHelper->sendProgress(42, 'Done!'.$this->_registry->registry('tickImage'), '0', 'done', false); @@ -205,7 +171,6 @@ public function execute() $this->_resourceConfig->saveConfig('megaventory/general/synctimestamp', $syncTimestamp, 'default', 0); $this->_resourceConfig->saveConfig('megaventory/general/setupreport', $this->_mvHelper->getProgressMessage(), 'default', 0); - //unfortunately $this->_cacheTypeList->cleanType('config'); $apikey = $this->_scopeConfig->getValue('megaventory/general/apikey'); @@ -235,15 +200,15 @@ public function execute() sleep(2); } + $this->_mvHelper->deleteInitialSyncFlags(); + $this->_registry->unregister('tickImage'); $result['nextstep'] = 'finish'; return $this->_resultJsonFactory->create()->setData($result); } elseif ($syncStep == 'error') { - //$syncTimestamp = time(); - $this->_mvHelper->sendProgress(90, 'Entity import did not finish succesfully.', '0', 'finisherror', true); + $this->_mvHelper->sendProgress(90, 'Setup Wizard did not finish succesfully.', '0', 'finisherror', true); $this->_mvHelper->sendProgress(100, 'Please refresh page and try again!', '0', 'done', false); - $connection = $this->_resource->getConnection(); $tableName = $this->_resource->getTableName('megaventory_progress'); diff --git a/Controller/Adminhtml/Index/SynchronizeOrder.php b/Controller/Adminhtml/Index/SynchronizeOrder.php index 62ecb69..ab75e36 100644 --- a/Controller/Adminhtml/Index/SynchronizeOrder.php +++ b/Controller/Adminhtml/Index/SynchronizeOrder.php @@ -6,7 +6,6 @@ class SynchronizeOrder extends \Magento\Backend\App\Action { - protected $_orderLoader; protected $_quoteLoader; protected $_websiteLoader; diff --git a/Controller/Adminhtml/Index/SynchronizeTaxes.php b/Controller/Adminhtml/Index/SynchronizeTaxes.php index 4b2378f..8da8862 100644 --- a/Controller/Adminhtml/Index/SynchronizeTaxes.php +++ b/Controller/Adminhtml/Index/SynchronizeTaxes.php @@ -6,14 +6,16 @@ class SynchronizeTaxes extends \Magento\Backend\App\Action { - protected $_taxesHelper; + protected $_sessionMessageManager; public function __construct( \Mv\Megaventory\Helper\Taxes $taxesHelper, - \Magento\Backend\App\Action\Context $context + \Magento\Backend\App\Action\Context $context, + \Magento\Framework\Message\ManagerInterface $messageManager ) { $this->_taxesHelper = $taxesHelper; + $this->_sessionMessageManager = $messageManager; parent::__construct($context); } @@ -22,6 +24,8 @@ public function execute() $this->_taxesHelper->synchronizeTaxes(false); /** @var \Magento\Backend\Model\View\Result\Redirect $resultRedirect */ $resultRedirect = $this->resultFactory->create(ResultFactory::TYPE_REDIRECT); - return $resultRedirect->setPath('megaventory/index/index'); + $this->_sessionMessageManager->addSuccessMessage('Taxes have been synchronized successfully'); + $url = $this->_url->getUrl('megaventory/index/index') . '#taxes'; + return $resultRedirect->setUrl($url); } } diff --git a/Controller/Adminhtml/Index/UndeleteEntity.php b/Controller/Adminhtml/Index/UndeleteEntity.php index 67d6aef..d0db514 100644 --- a/Controller/Adminhtml/Index/UndeleteEntity.php +++ b/Controller/Adminhtml/Index/UndeleteEntity.php @@ -6,7 +6,6 @@ class UndeleteEntity extends \Magento\Backend\App\Action { - protected $_scopeConfig; protected $_mvHelper; protected $_resultJsonFactory; diff --git a/Controller/Adminhtml/Index/UpdateAccountSettings.php b/Controller/Adminhtml/Index/UpdateAccountSettings.php new file mode 100644 index 0000000..08d1d0a --- /dev/null +++ b/Controller/Adminhtml/Index/UpdateAccountSettings.php @@ -0,0 +1,84 @@ +_resourceConfig = $resourceConfig; + $this->_resultJsonFactory = $resultJsonFactory; + $this->_cacheTypeList = $cacheTypeList; + $this->_attributeFactory = $attributeFactory; + $this->_scopeConfig = $scopeConfig; + $this->_mvProductHelper = $mvProductHelper; + parent::__construct($context); + } + + public function execute() + { + $result = [ + 'success'=>true + ]; + + $magentoId = $this->getRequest()->getParam('magento_id'); + $supplierAttributeCode = $this->getRequest()->getParam('magento_supplier_attribute_code'); + $shippingProductSku = $this->getRequest()->getParam('shipping_product_sku'); + $discountProductSku = $this->getRequest()->getParam('discount_product_sku'); + $currentShippingProductSku = $this->_scopeConfig->getValue('megaventory/general/shippingproductsku'); + $currentDiscountProductSku = $this->_scopeConfig->getValue('megaventory/general/discountproductsku'); + $cleanCache = false; + $purchasePriceAttributeCode = $this->getRequest()->getParam('purchase_price_attribute_code'); + + if (!empty($magentoId)) { + $this->_resourceConfig->saveConfig('megaventory/general/magentoid', $magentoId, 'default', 0); + $cleanCache = true; + } + if(!empty($supplierAttributeCode)){ + $attribute = $this->_attributeFactory->create()->loadByCode('catalog_product', $supplierAttributeCode); + + if ($attribute->getId()) { + $this->_resourceConfig->saveConfig('megaventory/general/supplierattributecode', $supplierAttributeCode, 'default', 0); + $cleanCache = true; + } + } + + if(!empty($discountProductSku) && ($discountProductSku != $currentDiscountProductSku)){ + $productAddedToMegaventory = $this->_mvProductHelper->addOrUpdateDiscountProduct($discountProductSku); + if (is_bool($productAddedToMegaventory) && ($productAddedToMegaventory === true)){ + $this->_resourceConfig->saveConfig('megaventory/general/discountproductsku', $discountProductSku, 'default', 0); + $cleanCache = true; + } + + } + + if(!empty($shippingProductSku) && ($shippingProductSku != $currentShippingProductSku)){ + $productAddedToMegaventory = $this->_mvProductHelper->addOrUpdateShippingProduct($shippingProductSku); + if (is_bool($productAddedToMegaventory) && ($productAddedToMegaventory === true)) { + $this->_resourceConfig->saveConfig('megaventory/general/shippingproductsku', $shippingProductSku, 'default', 0); + $cleanCache = true; + } + } + + $this->_resourceConfig->saveConfig('megaventory/general/purchasepriceattributecode', $purchasePriceAttributeCode, 'default', 0); + + if($cleanCache){ + $this->_cacheTypeList->cleanType('config'); + } + return $this->_resultJsonFactory->create()->setData($result); + } +} \ No newline at end of file diff --git a/Controller/Adminhtml/Index/UpdateAlertLevel.php b/Controller/Adminhtml/Index/UpdateAlertLevel.php index 10779c6..b9e0c1a 100644 --- a/Controller/Adminhtml/Index/UpdateAlertLevel.php +++ b/Controller/Adminhtml/Index/UpdateAlertLevel.php @@ -30,7 +30,6 @@ public function execute() $mvProductId = $this->getRequest()->getParam('mv_product_id'); $alertLevel = $this->getRequest()->getParam('alertlevel'); - $alertData = [ 'APIKEY' => $this->_scopeConfig->getValue('megaventory/general/apikey'), diff --git a/Controller/Adminhtml/Index/UpdateOrderSynchronization.php b/Controller/Adminhtml/Index/UpdateOrderSynchronization.php index d1d9c7e..e9b0bfe 100644 --- a/Controller/Adminhtml/Index/UpdateOrderSynchronization.php +++ b/Controller/Adminhtml/Index/UpdateOrderSynchronization.php @@ -6,20 +6,23 @@ class UpdateOrderSynchronization extends \Magento\Backend\App\Action { - protected $_resourceConfig; protected $_resultJsonFactory; protected $_cacheTypeList; + + protected $_scopeConfig; public function __construct( \Magento\Config\Model\ResourceModel\Config $resourceConfig, \Magento\Framework\Controller\Result\JsonFactory $resultJsonFactory, \Magento\Framework\App\Cache\TypeListInterface $cacheTypeList, - \Magento\Backend\App\Action\Context $context + \Magento\Backend\App\Action\Context $context, + \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig ) { $this->_resourceConfig = $resourceConfig; $this->_resultJsonFactory = $resultJsonFactory; $this->_cacheTypeList = $cacheTypeList; + $this->_scopeConfig = $scopeConfig; parent::__construct($context); } @@ -28,7 +31,25 @@ public function execute() $bCount = $this->getRequest()->getPost('value'); $bCount == 'true' ? $orderSynchronization = '1' : $orderSynchronization = '0'; - $this->_resourceConfig->saveConfig('megaventory/general/ordersynchronization', $orderSynchronization, 'default', 0); + $algorithmCode = $this->_scopeConfig->getValue('megaventory/orders/source_selection_algorithm_code'); + $isAlgorithmCodeNotSet = ($algorithmCode === null); + $isOrderSynchronizationEnabled = ($orderSynchronization == '1'); + + if (($isOrderSynchronizationEnabled) && ($isAlgorithmCodeNotSet)) { + $this->_resourceConfig->saveConfig( + 'megaventory/orders/source_selection_algorithm_code', + 'priority', + 'default', + 0 + ); + } + + $this->_resourceConfig->saveConfig( + 'megaventory/general/ordersynchronization', + $orderSynchronization, + 'default', + 0 + ); $this->_cacheTypeList->cleanType('config'); return $this->_resultJsonFactory->create()->setData([]); diff --git a/Controller/Adminhtml/Inventory/Edit.php b/Controller/Adminhtml/Inventory/Edit.php new file mode 100644 index 0000000..c60ade1 --- /dev/null +++ b/Controller/Adminhtml/Inventory/Edit.php @@ -0,0 +1,37 @@ +resultPageFactory = $resultPageFactory; + $this->locationFactory = $locationFactory; + $this->locationResource = $locationResource; + } + + public function execute() + { + /* @var \Magento\Backend\Model\View\Result\Page $resultPage */ + $resultPage = $this->resultPageFactory->create(); + + $location = $this->locationFactory->create(); + $this->locationResource->load($location, $this->getRequest()->getParam('id')); + + $pageMainTitle = $resultPage->getLayout()->getBlock('page.title'); + $title = 'Editing Preferences for Megaventory Location "'.$location->getName().'"'; + $pageMainTitle->setPageTitle($title); + + return $resultPage; + } +} \ No newline at end of file diff --git a/Controller/Adminhtml/Inventory/Save.php b/Controller/Adminhtml/Inventory/Save.php new file mode 100644 index 0000000..458c824 --- /dev/null +++ b/Controller/Adminhtml/Inventory/Save.php @@ -0,0 +1,63 @@ +inventoryFactory = $inventoryFactory; + $this->inventoryResource = $inventoryResource; + $this->redirectFactory = $redirectFactory; + $this->urlBuilder = $urlBuilder; + } + + public function execute() + { + $params = $this->getRequest()->getParam('inventory_source_associations'); + $params['mv_adjustment_plus_type_id'] = $this->getRequest()->getParam('inventory_adjustment_plus_templates_associations')['mv_adjustment_plus_type_id']; + $params['mv_adjustment_minus_type_id'] = $this->getRequest()->getParam('inventory_adjustment_minus_templates_associations')['mv_adjustment_minus_type_id']; + $params['adjustment_doc_status'] = $this->getRequest()->getParam('inventory_adjustment_document_status')['adjustment_doc_status']; + $id = -1; + if(array_key_exists('id', $params)){ + $id = $params['id']; + } + + if($id !== -1){ + $inventory = $this->inventoryFactory->create(); + $this->inventoryResource->load($inventory, $id); + if($inventory->getId() !== null){ + $inventory->setData($params); + try{ + $this->inventoryResource->save($inventory); + $this->messageManager->addSuccessMessage('Your preferences for the location "'.$inventory->getName().'" have been saved successfully.'); + } + catch(\Exception $e){ + $this->messageManager->addErrorMessage('Unexpected error. Unable to save your preferences. Please try again.'); + } + } + else{ + $this->messageManager->addErrorMessage('Unexpected error. Unable to save your preferences. Please try again.'); + } + } + else{ + $this->messageManager->addErrorMessage('Unexpected error. Unable to save your preferences. Please try again.'); + } + $url = $this->urlBuilder->getUrl('megaventory/index/index') . '#locations'; + return $this->redirectFactory->create()->setUrl($url); + } +} \ No newline at end of file diff --git a/Controller/Adminhtml/Inventory/UnassignInventorySource.php b/Controller/Adminhtml/Inventory/UnassignInventorySource.php new file mode 100644 index 0000000..838d05b --- /dev/null +++ b/Controller/Adminhtml/Inventory/UnassignInventorySource.php @@ -0,0 +1,40 @@ +_mvInventoryFactory = $mvInventoryFactory; + $this->_resultRedirectFactory = $redirectFactory; + $this->_mvInventoryResource = $mvInventoryResource; + + parent::__construct($context); + } + + public function execute() + { + $inventoryId = (int)$this->getRequest()->getParam('id'); + $mvInventory = $this->_mvInventoryFactory->create(); + $this->_mvInventoryResource->load($mvInventory, $inventoryId); + try { + $mvInventory->setData('stock_source_code'); + $mvInventory->setCountsInGlobalStock(0); + $this->_mvInventoryResource->save($mvInventory); + $this->messageManager->addSuccessMessage('Removed inventory source from megaventory location "'.$mvInventory->getName().'"'); + } catch (\Exception $e) { + $this->messageManager->addErrorMessage('Unexpected error. Unable to save your preferences. Please try again later.'); + } + + return $this->_resultRedirectFactory->create()->setPath('megaventory/inventory/edit',['id'=>$mvInventory->getId()]); + } +} diff --git a/Controller/Adminhtml/Log/Delete.php b/Controller/Adminhtml/Log/Delete.php index de43b68..fe66743 100644 --- a/Controller/Adminhtml/Log/Delete.php +++ b/Controller/Adminhtml/Log/Delete.php @@ -11,13 +11,21 @@ */ class Delete extends \Magento\Backend\App\Action { + protected $_mvLogFactory; + + public function __construct( + \Mv\Megaventory\Model\LogFactory $logFactory, + \Magento\Backend\App\Action\Context $context + ) { + $this->_mvLogFactory = $logFactory; + parent::__construct($context); + } /** * {@inheritdoc} */ protected function _isAllowed() { return true; - //return $this->_authorization->isAllowed('Ashsmith_Blog::delete'); } /** @@ -32,7 +40,7 @@ public function execute() $resultRedirect = $this->resultRedirectFactory->create(); if ($id) { try { - $model = $this->_objectManager->create('Mv\Megaventory\Model\Log'); + $model = $this->_mvLogFactory->create(); $model->load($id); $model->delete(); $this->messageManager->addSuccess(__('The log has been deleted.')); diff --git a/Controller/Adminhtml/Log/Index.php b/Controller/Adminhtml/Log/Index.php index bc1a383..c928cdd 100644 --- a/Controller/Adminhtml/Log/Index.php +++ b/Controller/Adminhtml/Log/Index.php @@ -44,6 +44,5 @@ public function execute() protected function _isAllowed() { return true; - //return $this->_authorization->isAllowed('Ashsmith_Blog::post'); } } diff --git a/Controller/Adminhtml/Log/MassDelete.php b/Controller/Adminhtml/Log/MassDelete.php index e2b6e8c..25e20de 100644 --- a/Controller/Adminhtml/Log/MassDelete.php +++ b/Controller/Adminhtml/Log/MassDelete.php @@ -8,6 +8,7 @@ /** * Class MassDelete + * This class provides mass deletion functionality for the megaventory logs */ class MassDelete extends \Magento\Backend\App\Action { diff --git a/Controller/Adminhtml/Log/Redo.php b/Controller/Adminhtml/Log/Redo.php index e156b74..6334e12 100644 --- a/Controller/Adminhtml/Log/Redo.php +++ b/Controller/Adminhtml/Log/Redo.php @@ -11,7 +11,14 @@ */ class Redo extends \Magento\Backend\App\Action { - + protected $_mvLogFactory; + public function __construct( + \Mv\Megaventory\Model\LogFactory $logFactory, + \Magento\Backend\App\Action\Context $context + ) { + $this->_mvLogFactory = $logFactory; + parent::__construct($context); + } /** * {@inheritdoc} */ @@ -24,7 +31,7 @@ protected function _isAllowed() public function execute() { $id = $this->getRequest()->getParam('log_id'); - $model = $this->_objectManager->create('Mv\Megaventory\Model\Log'); + $model = $this->_mvLogFactory->create(); $resultRedirect = $this->resultRedirectFactory->create(); diff --git a/Controller/Adminhtml/Updates/Process.php b/Controller/Adminhtml/Updates/Process.php index cc2992f..25bab92 100644 --- a/Controller/Adminhtml/Updates/Process.php +++ b/Controller/Adminhtml/Updates/Process.php @@ -28,6 +28,7 @@ public function execute() { $this->_megaventoryService->applyPendingUpdates(); $resultRedirect = $this->resultRedirectFactory->create(); - return $resultRedirect->setPath('*/*/'); + $this->messageManager->addSuccessMessage('Pending updates have been applied successfully.'); + return $resultRedirect->setPath('megaventory/log/index'); } } diff --git a/Cron/ApplyPendingUpdates.php b/Cron/ApplyPendingUpdates.php index e3f5e1c..7b884ee 100644 --- a/Cron/ApplyPendingUpdates.php +++ b/Cron/ApplyPendingUpdates.php @@ -11,13 +11,11 @@ class ApplyPendingUpdates protected $_megaventoryService; - public function __construct(\Mv\Megaventory\Model\Services\MegaventoryService $megaventoryService) { $this->_megaventoryService = $megaventoryService; } - public function execute() { $this->_megaventoryService->applyPendingUpdates(); diff --git a/Cron/CheckOrderSynchronization.php b/Cron/CheckOrderSynchronization.php index 462bc65..703f717 100644 --- a/Cron/CheckOrderSynchronization.php +++ b/Cron/CheckOrderSynchronization.php @@ -16,7 +16,6 @@ class CheckOrderSynchronization protected $_websiteRepository; protected $_mvOrderHelper; - public function __construct( \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig, \Magento\Sales\Model\ResourceModel\Order\CollectionFactory $orderCollectionFactory, @@ -36,33 +35,30 @@ public function __construct( public function execute() { $orderSynchronization = $this->_scopeConfig->getValue('megaventory/general/ordersynchronization'); - if (empty($orderSynchronization) || $orderSynchronization === '0') { - return; - } - - /* Format our dates */ - $fromDate = date('Y-m-d H:i:s', strtotime("-30 minutes")); - $toDate = date('Y-m-d H:i:s', strtotime("now")); - - - /* Get the collection */ - $orders = $this->_orderCollectionFactory->create() - ->addAttributeToFilter('created_at', ['from'=>$fromDate, 'to'=>$toDate]) - ->addAttributeToFilter('status', ['in' => ['pending','processing']]) - ->load(); - - - foreach ($orders as $tmpOrder) { - $order = $this->_orderLoader->create()->load($tmpOrder->getId()); + if (!empty($orderSynchronization) && ($orderSynchronization != '0')) { + + /* Format our dates */ + $fromDate = date('Y-m-d H:i:s', strtotime("-30 minutes")); + $toDate = date('Y-m-d H:i:s', strtotime("now")); - if ($order->getData('mv_inventory_id') == false) { - $quote = $this->_quoteLoader->create(); - $website = $this->_websiteRepository->getById($order->getStore()->getWebsite_id()); - $quote->setData('website', $website); - $quote = $quote->load($order->getQuote_id()); + /* Get the collection */ + $orders = $this->_orderCollectionFactory->create() + ->addAttributeToFilter('created_at', ['from'=>$fromDate, 'to'=>$toDate]) + ->addAttributeToFilter('status', ['in' => ['pending','processing']]) + ->load(); + + foreach ($orders as $tmpOrder) { + $order = $this->_orderLoader->create()->load($tmpOrder->getId()); - if ($quote->getId()) { - $this->_mvOrderHelper->addOrder($order, $quote); + if ($order->getData('mv_inventory_id') == false) { + $quote = $this->_quoteLoader->create(); + $website = $this->_websiteRepository->getById($order->getStore()->getWebsiteId()); + $quote->setData('website', $website); + $quote = $quote->load($order->getQuote_id()); + + if ($quote->getId()) { + $this->_mvOrderHelper->addOrder($order, $quote); + } } } } diff --git a/Helper/Category.php b/Helper/Category.php index 6d48cc9..f170a22 100644 --- a/Helper/Category.php +++ b/Helper/Category.php @@ -20,7 +20,6 @@ class Category extends \Magento\Framework\App\Helper\AbstractHelper protected $logger; protected $mvLogFactory; - public function __construct( \Magento\Framework\App\Helper\Context $context, Data $mvHelper, @@ -98,8 +97,8 @@ public function addCategory($category) } } } - } else //we must also update all children - { + } else {//we must also update all children + $this->updateCategoriesRecursively($category); } } @@ -139,8 +138,7 @@ public function importCategoriesToMegaventory($page = 1, $imported = 0) $isLastPage = true; } - - $total = $imported;// + ($page-1)*10; + $total = $imported; foreach ($collection as $category) { try { $inserted = $this->insertSingleCategory($category); @@ -199,7 +197,6 @@ public function insertSingleCategory($category) //the special [No Name] title if (empty($name)) { $name = '[No Name]'; - //return -1; } if (isset($descr) && $descr != null) { @@ -319,14 +316,12 @@ public function deleteCategoriesRecursively($category) $megaventoryCategoryId = $category->getData('mv_productcategory_id'); - if (isset($megaventoryCategoryId)) { $data = [ 'APIKEY' => $this->APIKEY, 'ProductCategoryIDToDelete' => $megaventoryCategoryId, 'mvCategoryDeleteAction' => 'LeaveProductsOrphan']; - $json_result = $this->_mvHelper->makeJsonRequest($data, 'ProductCategoryDelete', $category->getEntityId()); } } diff --git a/Helper/Common.php b/Helper/Common.php index a7c90e1..5b87872 100644 --- a/Helper/Common.php +++ b/Helper/Common.php @@ -2,6 +2,10 @@ namespace Mv\Megaventory\Helper; +use DateTime; + +use function Safe\strtotime; + class Common extends \Magento\Framework\App\Helper\AbstractHelper { const SHIPPINGSKU = 'shipping_service_01'; @@ -30,7 +34,6 @@ public function isMegaventoryEnabled() return true; } - return false; } diff --git a/Helper/Currencies.php b/Helper/Currencies.php index 38d2dcd..b29f9da 100644 --- a/Helper/Currencies.php +++ b/Helper/Currencies.php @@ -21,7 +21,6 @@ class Currencies extends \Magento\Framework\App\Helper\AbstractHelper protected $logger; protected $mvLogFactory; - public function __construct( \Magento\Framework\App\Helper\Context $context, Data $mvHelper, @@ -96,14 +95,12 @@ public function addMagentoCurrencies() $newMVCurrency->save(); } - $message = 'Added to Megaventory '.$totals.' currencies'.$this->_registry->registry('tickImage'); $this->_mvHelper->sendProgress(14, $message, '0', 'entities', true); return $totals; } - private function checkIfCurrencyExists($mvCurrency) { diff --git a/Helper/Customer.php b/Helper/Customer.php index 4cecd75..5835581 100644 --- a/Helper/Customer.php +++ b/Helper/Customer.php @@ -19,7 +19,6 @@ class Customer extends \Magento\Framework\App\Helper\AbstractHelper protected $logger; protected $mvLogFactory; - public function __construct( \Magento\Framework\App\Helper\Context $context, \Magento\Config\Model\ResourceModel\Config $resourceConfig, @@ -79,12 +78,11 @@ public function addCustomer($customer) $storeViewName = $customer->getCreated_in(); $clientComments = ''.'created at:'.$createdAt.',website:'.$webSiteId.',store:'.$storeId.',storeview:'.$storeViewName; - if (isset($megaVentoryId) && $megaVentoryId!=null) { //it is an update $mvCustomerId = $megaVentoryId; $mvRecordAction = 'Update'; - } else //it is an insert - { + } else {//it is an insert + $mvCustomerId = '0'; $mvRecordAction = 'Insert'; } @@ -145,8 +143,7 @@ public function addCustomer($customer) ], 'mvRecordAction' => $mvRecordAction, 'mvGrantPermissionsToAllUsers' => true]; - - + $json_result = $this->_mvHelper->makeJsonRequest($data, 'SupplierClientUpdate', $customer->getId()); $errorCode = $json_result['ResponseStatus']['ErrorCode']; @@ -240,7 +237,6 @@ public function addDefaultGuestCustomer() $json_result = $this->_mvHelper->makeJsonRequest($data, 'SupplierClientUpdate', 0); - $errorCode = $json_result['ResponseStatus']['ErrorCode']; if ($errorCode == 0) { $defaultGuestId = $json_result['mvSupplierClient']['SupplierClientID']; diff --git a/Helper/Data.php b/Helper/Data.php index afef34a..6bf8241 100644 --- a/Helper/Data.php +++ b/Helper/Data.php @@ -13,17 +13,24 @@ class Data extends \Magento\Framework\App\Helper\AbstractHelper protected $logger; protected $mvLogFactory; private $_progressMessage; + protected $_backendSession; + + protected $_resourceConfig; public function __construct( \Magento\Framework\App\Helper\Context $context, \Magento\Framework\App\ResourceConnection $recource, + \Magento\Backend\Model\Session $backendSession, \Mv\Megaventory\Helper\Common $commonHelper, \Mv\Megaventory\Model\LogFactory $mvLogFactory, + \Magento\Framework\App\Config\ConfigResource\ConfigInterface $resourceConfig, \Mv\Megaventory\Logger\Logger $logger ) { $this->_scopeConfig = $context->getScopeConfig(); $this->_resource = $recource; $this->_commonHelper = $commonHelper; + $this->_resourceConfig = $resourceConfig; + $this->_backendSession = $backendSession; $this->mvLogFactory = $mvLogFactory; $this->logger = $logger; @@ -32,8 +39,12 @@ public function __construct( public function makeJsonRequest($data, $action, $magentoId = 0, $apiurl = -1, $enabled = -1) { - //if (empty(self::$MEGAVENTORY_API_URL)) + $this->MEGAVENTORY_API_URL = $this->_scopeConfig->getValue('megaventory/general/apiurl'); + + $magentoId = $this->_scopeConfig->getValue('megaventory/general/magentoid'); + + $magentoId = (($magentoId !== null) && (count(explode('-',$magentoId)) >= 2)) ? (int)explode('-',$magentoId)[1] : 0; if ($apiurl != -1) { $this->MEGAVENTORY_API_URL = $apiurl; @@ -50,15 +61,12 @@ public function makeJsonRequest($data, $action, $magentoId = 0, $apiurl = -1, $e $data_string = json_encode($data); $this->logger->info('data = '.$data_string); - $ch = curl_init($this->MEGAVENTORY_API_URL.$action); curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST"); curl_setopt($ch, CURLOPT_POSTFIELDS, $data_string); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); - // letrim check in production if we need it curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); - // end of letrim curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json', 'Content-Length: ' . strlen($data_string) ]); $Jsonresult = curl_exec($ch); @@ -109,7 +117,6 @@ public function makeJsonRequest($data, $action, $magentoId = 0, $apiurl = -1, $e public function sendProgress($gid, $message, $progress, $step, $addToReport = false) { - //static $id = 1; static $headingid = 1; static $detailid = 1; static $flag = 0; @@ -155,6 +162,76 @@ public function getProgressMessage() { return $this->_progressMessage; } + + public function deleteCredetials() + { + $basePath = 'megaventory'; + $values = [ + 'general'=>[ + 'enabled', + 'apiurl', + 'apikey', + 'shippingproductsku', + 'discountproductsku', + 'magentoid', + 'supplierattributecode', + 'defaultguestid', + 'synctimestamp', + 'setupreport', + 'syncreport', + 'ordersynchronization' + ], + 'orders'=>[ + 'ordersynchronization' + ] + ]; + + foreach ($values as $section => $fields) { + foreach ($fields as $field) { + $configPath = $basePath . '/' . $section . '/' . $field; + $this->_resourceConfig->deleteConfig( + $configPath, + \Magento\Framework\App\Config\ScopeConfigInterface::SCOPE_TYPE_DEFAULT, + \Magento\Store\Model\Store::DEFAULT_STORE_ID + ); + } + } + } + + public function isSyncStartNotAllowed(){ + $syncTimestamp = $this->_scopeConfig->getValue('megaventory/general/synctimestamp'); + $isSyncRunning = ((int)$this->_scopeConfig->getValue('megaventory/synchronization/started') == 1); + $isSessionSame = ($this->_backendSession->getSessionId() == $this->_scopeConfig->getValue('megaventory/synchronization/started_by_session')); + + $expirationTime = date('Y-m-d H:i:s',strtotime($this->_scopeConfig->getValue('megaventory/synchronization/starttime') . ' +3 minutes')); + + $currentTime = date('Y-m-d H:i:s'); + + $isHeartBeatExpired = ($currentTime > $expirationTime); + + return (($isSyncRunning && !$isSessionSame && !$isHeartBeatExpired) || !empty($syncTimestamp)); + } + + public function saveInitialSyncFlags(){ + $this->_resourceConfig->saveConfig('megaventory/synchronization/started', 1, 'default', 0); + $this->_resourceConfig->saveConfig('megaventory/synchronization/started_by_session',$this->_backendSession->getSessionId(),'default',0); + $this->updateHeartBeatTimestamp(); + } + + public function deleteInitialSyncFlags(){ + $this->_resourceConfig->deleteConfig('megaventory/synchronization/started_by_session'); + $this->_resourceConfig->deleteConfig('megaventory/synchronization/starttime'); + $this->_resourceConfig->deleteConfig('megaventory/synchronization/started'); + } + + public function updateHeartBeatTimestamp(){ + $this->_resourceConfig->saveConfig('megaventory/synchronization/starttime',date('Y-m-d H:i:s'),'default',0); + } + + public function resetAutoincrement($table){ + $query = 'alter table ' . $this->_resource->getTableName($table) . ' auto_increment=1'; + $this->_resource->getConnection()->query($query); + } public function resetMegaventoryData() { @@ -163,18 +240,28 @@ public function resetMegaventoryData() $deleteInventories = 'delete from '.$this->_resource->getTableName('megaventory_inventories'); $write->query($deleteInventories); + $this->resetAutoincrement('megaventory_inventories'); + $deleteDocumentTypes = 'delete from '.$this->_resource->getTableName('megaventory_order_templates'); + $write->query($deleteDocumentTypes); + $this->resetAutoincrement('megaventory_order_templates'); $deleteBoms = 'delete from '.$this->_resource->getTableName('megaventory_bom'); $write->query($deleteBoms); + $this->resetAutoincrement('megaventory_bom'); $deleteTaxes = 'delete from '.$this->_resource->getTableName('megaventory_taxes'); $write->query($deleteTaxes); + $this->resetAutoincrement('megaventory_taxes'); $deleteCurrencies = 'delete from '.$this->_resource->getTableName('megaventory_currencies'); $write->query($deleteCurrencies); + $this->resetAutoincrement('megaventory_currencies'); $deleteStock = 'delete from '.$this->_resource->getTableName('megaventory_stock'); $write->query($deleteStock); + $this->resetAutoincrement('megaventory_stock'); $deleteLog = 'delete from '.$this->_resource->getTableName('megaventory_log'); $write->query($deleteLog); + $this->resetAutoincrement('megaventory_log'); $deleteProgress = 'delete from '.$this->_resource->getTableName('megaventory_progress'); $write->query($deleteProgress); + $this->resetAutoincrement('megaventory_progress'); $updateCustomer = 'update '.$this->_resource->getTableName('customer_entity').' set mv_supplierclient_id = NULL'; $write->query($updateCustomer); @@ -203,16 +290,23 @@ public function getMegaventoryAccountSettings($settingName = false, $apikey = fa 'SettingName' => ($settingName === false) ? 'All' : $settingName ]; - $json_result = $this->makeJsonRequest($data, 'AccountSettingsGet', 0, $apiurl); - $errorCode = $json_result['ResponseStatus']['ErrorCode']; - if ($errorCode != '0') { - return false; + if ($json_result !== false) { + $errorCode = $json_result['ResponseStatus']['ErrorCode']; + if ($errorCode != '0') { + return false; + } + + return $json_result['mvAccountSettings']; } - - - return $json_result['mvAccountSettings']; + return false; + } + + public function checkAccount() + { + $accountSettings = $this->getMegaventoryAccountSettings(); + return ($accountSettings !== false); } public function checkConnectivity() @@ -225,9 +319,7 @@ public function checkConnectivity() $accountSettings = $this->getMegaventoryAccountSettings(); - if ($accountSettings === false) { //connectivity problem - return 'There is a problem with your megaventory credentials!'; - } else { + if ($accountSettings !== false) { $message = ''; $magentoInstallationsIsSet = false; foreach ($accountSettings as $index => $accountSetting) { @@ -270,6 +362,8 @@ public function checkConnectivity() if (strpos($message, "Administrator") === false) { return "Magento Integration needs Administrator's Credentials."; } + } else { //Connectivity Problem + return 'There is a problem with your megaventory credentials!'; } return true; @@ -286,4 +380,8 @@ public function log($event) } } } + + public function getApiKey(){ + return $this->_scopeConfig->getValue('megaventory/general/apikey'); + } } diff --git a/Helper/DocumentType.php b/Helper/DocumentType.php new file mode 100644 index 0000000..7368414 --- /dev/null +++ b/Helper/DocumentType.php @@ -0,0 +1,95 @@ +documentTypeFactory = $documentTypeFactory; + $this->documentTypeResource = $documentTypeResource; + $this->documentTypeCollectionFactory = $documentTypeCollectionFactory; + } + + public function getDocumentTypeIdFromWebsiteId($websiteId){ + $documentTypes = $this->documentTypeCollectionFactory->create() + ->addFieldToFilter('magento_website_ids', ['finset'=>$websiteId]); + if(count($documentTypes) == 0) return self::DEFAULT_ORDER_DOCUMENT_TYPE; + return $documentTypes + ->getFirstItem()->getMegaventoryId(); + } + + public function removeWebsiteFromOtherTypes($websiteIds, $exculdedIds = []){ + foreach($websiteIds as $websiteId){ + $currentlyAssignedTypes = $this->documentTypeCollectionFactory->create()->addFieldToFilter('magento_website_ids',['finset'=>$websiteId])->addFieldToFilter('id',['nin'=>$exculdedIds]); + if((count($currentlyAssignedTypes) > 0)){ + foreach($currentlyAssignedTypes as $documentType){ + $assignedWebsites = explode(',', $documentType->getMagentoWebsiteIds()); + $key = array_search($websiteId, $assignedWebsites); + + unset($assignedWebsites[$key]); + $documentType->setMagentoWebsiteIds(trim(implode(',', $assignedWebsites),',')); + try{ + $this->documentTypeResource->save($documentType); + } + catch(\Exception $e){ + return false; + } + } + } + } + return true; + } + + public function assignOrphanedWebsitesToDefaultDocumentType($currentAssociations, $previousAssociations){ + $defaultType = $this->documentTypeFactory->create(); + $this->documentTypeResource->load($defaultType, 3, 'megaventory_id'); + + $defaultDocumentTypeWebsites = explode(',', $defaultType->getMagentoWebsiteIds()); + foreach($previousAssociations as $websiteId){ + if((!in_array($websiteId, $currentAssociations) && !in_array($websiteId, $defaultDocumentTypeWebsites) && !empty($websiteId))){ + $defaultDocumentTypeWebsites[] = $websiteId; + } + } + + $defaultType->setMagentoWebsiteIds(trim(implode(',', $defaultDocumentTypeWebsites),',')); + + try{ + $this->documentTypeResource->save($defaultType); + } + catch(\Exception $e){ + return false; + } + + return true; + } + + public function getAssociations($id){ + $documentTypeModel = $this->documentTypeFactory->create(); + $this->documentTypeResource->load($documentTypeModel, $id); + return explode(',', $documentTypeModel->getMagentoWebsiteIds()); + } + public function updateWebsiteAssociations($websiteIds, $id){ + $documentTypeModel = $this->documentTypeFactory->create(); + $this->documentTypeResource->load($documentTypeModel, $id); + + $documentTypeModel->setMagentoWebsiteIds(implode(',', $websiteIds)); + try{ + $this->documentTypeResource->save($documentTypeModel); + } + catch(\Exception $e){ + return false; + } + return true; + } +} \ No newline at end of file diff --git a/Helper/Inventories.php b/Helper/Inventories.php index 9e7912e..5df7104 100644 --- a/Helper/Inventories.php +++ b/Helper/Inventories.php @@ -2,20 +2,27 @@ namespace Mv\Megaventory\Helper; +use Magento\Framework\Event\ManagerInterface; use \Mv\Megaventory\Logger\Logger; use \Mv\Megaventory\Model\LogFactory; class Inventories extends \Magento\Framework\App\Helper\AbstractHelper { protected $_scopeConfig; + protected $_sourceStockItemInterface; + protected $_sourceItemSave; private $_mvHelper; private $_productstocksLoader; private $_inventoriesLoader; + protected $_sourceLowStockItemInterface; private $_inventoriesCollection; private $_resource; protected $_stockItemFactory; + protected $_productFactory; private $_messageManager; private $_backendUrl; + protected $_sourceItemCollectionFactory; + protected $_eventManager; private $APIKEY; protected $logger; @@ -23,7 +30,6 @@ class Inventories extends \Magento\Framework\App\Helper\AbstractHelper const PAGESIZE = 50; - public function __construct( \Magento\Framework\App\Helper\Context $context, Data $mvHelper, @@ -34,19 +40,32 @@ public function __construct( \Magento\CatalogInventory\Model\Stock\ItemFactory $stockItemFactory, \Magento\Framework\Message\ManagerInterface $messageManager, \Magento\Backend\Model\UrlInterface $backendUrl, + \Magento\InventoryApi\Api\Data\SourceItemInterfaceFactory $sourceStockItemInterface, + \Magento\Inventory\Model\ResourceModel\SourceItem\CollectionFactory $sourceCollection, + \Magento\Catalog\Model\ProductFactory $productFactory, + \Magento\InventoryApi\Api\SourceItemsSaveInterface $sourceItemSave, LogFactory $mvLogFactory, - Logger $logger + Logger $logger, + \Magento\InventoryLowQuantityNotificationApi\Api\GetSourceItemConfigurationInterface $sourceItemConfig, + ManagerInterface $eventManager ) { $this->_scopeConfig = $context->getScopeConfig(); $this->_mvHelper = $mvHelper; + $this->_sourceStockItemInterface = $sourceStockItemInterface; $this->_productstocksLoader = $productStocksLoader; $this->_inventoriesLoader = $inventoriesLoader; $this->_inventoriesCollection = $inventoriesCollection; + $this->_sourceItemSave = $sourceItemSave; $this->_resource = $recource; $this->_stockItemFactory = $stockItemFactory; $this->_messageManager = $messageManager; $this->_backendUrl = $backendUrl; $this->APIKEY = $this->_scopeConfig->getValue('megaventory/general/apikey'); + $this->_sourceItemCollectionFactory = $sourceCollection; + $this->_productFactory = $productFactory; + $this->_sourceLowStockItemInterface = $sourceItemConfig; + + $this->_eventManager = $eventManager; $this->mvLogFactory = $mvLogFactory; $this->logger = $logger; @@ -58,6 +77,30 @@ public function getInventories() return $this->_inventoriesCollection->load(); } + public function assignLocationToSource($inventory, $source) { + $codeAlreadyAssigned = ( + count( + $this->_inventoriesCollection->addFieldToFilter('stock_source_code', $source->getSourceCode()) + ->addFieldToFilter('id', ['neq'=>$inventory->getId()])->load() + ) > 0 + ); + if ($codeAlreadyAssigned) { + return [ + 'status'=>'error', + 'message'=>'Magento Inventory Source ' . $source->getName() . ' is already assigned to the Megaventory Location '.$inventory->getName() . '. If you are to proceed, please reassign this location to another source.' + ]; + } else { + $inventory = $this->_inventoriesLoader->create()->load($inventory->getId()); + $inventory->setStockSourceCode($source->getSourceCode()); + $inventory->setCountsInGlobalStock(1); + $inventory->save(); + return [ + 'status'=>'success', + 'message'=>'Magento Inventory Source ' . $source->getName() . ' has been successfully assigned to Megaventory Location '.$inventory->getName() . '.' + ]; + } + } + public function getInventoriesFromMegaventory($apikey = false, $apiurl = false, $enabled = -1) { if ($apikey != false) { @@ -66,7 +109,6 @@ public function getInventoriesFromMegaventory($apikey = false, $apiurl = false, $key = $this->APIKEY; } - $data = [ 'APIKEY' => $key @@ -147,7 +189,13 @@ public function syncrhonizeInventories($page, $apikey = -1, $apiurl = -1) return $nextPage; } - + + public function truncateReservationsTable() + { + $connection = $this->_resource->getConnection(); + $table = $this->_resource->getTableName('inventory_reservation'); + $connection->truncateTable($table); + } public function updateAllStock($page) { $nextPage = -1; @@ -186,13 +234,13 @@ public function updateAllStock($page) $i++; $pId = $this->getIdByMegaventoryId($productStockListItem['productID']); + $sku = $this->_productFactory->create()->load($pId)->getSku(); if (empty($pId) || $pId == false) { continue; } $warehouseStocks = $productStockListItem['mvStock']; - $totalStock = 0; foreach ($warehouseStocks as $warehouseStock) { $inventoryStockData['stockqty'] = $warehouseStock['StockPhysical']; $inventoryStockData['stockqtyonhold']= $warehouseStock['StockOnHold']; @@ -205,9 +253,11 @@ public function updateAllStock($page) //warehouseID changed in megaventory API v2 //we need to be compliant with both versions - $locationId = $warehouseStock['warehouseID']; - if (!isset($locationId)) { //v2 api + + if (!in_array('warehouseID', array_keys($warehouseStock))) { $locationId = $warehouseStock['InventoryLocationID']; + } else { + $locationId = $warehouseStock['warehouseID']; } $inventory = $this->_inventoriesLoader->create()->load($locationId, 'megaventory_id'); @@ -216,26 +266,44 @@ public function updateAllStock($page) $this->updateInventoryProductStock($pId, $inventoryId, $inventoryStockData); - $countsInTotalStock = $inventory->getCounts_in_total_stock(); - - if ($countsInTotalStock == '1') { + $sourceCode = $inventory->getStockSourceCode(); + if ($sourceCode !== null) { + $sourceItems = $this->_sourceItemCollectionFactory->create() + ->addFieldToFilter('source_code', $sourceCode) + ->addFieldToFilter('sku', $sku); + if (count($sourceItems) > 0) { + $sourceItem = $sourceItems->getFirstItem(); + $notifyQty = $this->_sourceLowStockItemInterface->execute($sourceCode, $sku) + ->getNotifyStockQty(); + } else { + $sourceItem = $this->_sourceStockItemInterface->create(); + $sourceItem->setSku($sku); + $sourceItem->setSourceCode($sourceCode); + $notifyQty = 1; + } + + $qty = 0; if ($configValue == '0') { //no decrease value when order is placed - $totalStock += $inventoryStockData['stockqty']; - } else //decrease stock when order is placed - { - $totalStock += $inventoryStockData['stockqty']-$inventoryStockData['stocknonshippedqty']-$inventoryStockData['stocknonallocatedwoqty']; + $qty = $inventoryStockData['stockqty']; + } else { //decrease stock when order is placed + + $stock = $inventoryStockData['stockqty']; + $nonShipped = $inventoryStockData['stocknonshippedqty']; + $allocated = $inventoryStockData['stocknonallocatedwoqty'] + $nonShipped; + $qty = $stock - $allocated; } + + $isInStock = ($qty > $notifyQty) ? 1 : 0; + $sourceItem->setQuantity($qty); + $sourceItem->setStatus($isInStock); + + $data = ['status'=>$isInStock, 'qty'=>$qty, 'sku'=>$sku, 'inventory_source'=>$sourceCode]; + + $this->_sourceItemSave->execute([$sourceItem]); + + $this->_eventManager->dispatch('mv_megaventory_update_stock_after',$data); } } - - $stockItem = $this->_stockItemFactory->create()->load($pId, 'product_id'); - - $stockItem->setQty($totalStock); - if ($totalStock > $stockItem->getMinQty()) { - $stockItem->setData('is_in_stock', 1); - } - - $stockItem->save(); } } @@ -255,8 +323,6 @@ public function initializeInventoryLocations($apikey = -1, $apiurl = -1) 'APIKEY' => $key ]; - - try { $json_result = $this->_mvHelper->makeJsonRequest($data, 'InventoryLocationGet', 0, $apiurl); } catch (\Exception $ex) { @@ -274,12 +340,7 @@ public function initializeInventoryLocations($apikey = -1, $apiurl = -1) $result = -1; $mvIds = []; foreach ($mvInventoryLocations as $mvInventory) { - if ($i == 0) { - $this->insertInventory($mvInventory, true); - } else { - $this->insertInventory($mvInventory); - } - + $this->insertInventory($mvInventory); $i++; } @@ -321,8 +382,13 @@ public function createMainInventory() return true; } - public function updateInventoryProductStock($productId, $inventoryId, $stockData, $parentId = false, $integrationId = 0) - { + public function updateInventoryProductStock( + $productId, + $inventoryId, + $stockData, + $parentId = false, + $integrationId = 0 + ) { if (isset($productId) && isset($inventoryId)) { $productStock = $this->_productstocksLoader->create() @@ -406,6 +472,8 @@ public function updateInventoryLocations($apikey = -1, $apiurl = -1) if ($i>0) { return $i; } + + $this->truncateReservationsTable(); return $result; } @@ -418,19 +486,6 @@ public function updateCountsInStock($inventoryId, $bCount) $inventory->save(); } - public function makeDefaultInventory($inventoryId) - { - if (isset($inventoryId)) { - $connection = $this->_resource->getConnection(); - $tableName = $this->_resource->getTableName('megaventory_inventories'); - - $noDefault = 'update '.$tableName.' set isdefault = 0'; - $connection->query($noDefault); - $makeefault = 'update '.$tableName.' set isdefault = 1, counts_in_total_stock = 1 where id = '.$inventoryId; - $connection->query($makeefault); - } - } - public function updateInventoryProductAlertValue($productId, $inventoryId, $alertValue) { @@ -513,7 +568,11 @@ private function insertInventory($mvInventory, $default = false) $mvInventoryLocationID = $mvInventory['InventoryLocationID']; $mvInventoryLocationName = $mvInventory['InventoryLocationName']; $mvInventoryLocationAbbreviation = $mvInventory['InventoryLocationAbbreviation']; - $mvInventoryLocationAddress = $mvInventory['InventoryLocationAddress']; + $mvInventoryLocationAddress = null; + if(array_key_exists('InventoryLocationAddress', $mvInventory)){ + $mvInventory['InventoryLocationAddress']; + } + $connection = $this->_resource->getConnection(); $tableName = $this->_resource->getTableName('megaventory_inventories'); @@ -521,7 +580,7 @@ private function insertInventory($mvInventory, $default = false) if ($default == false) { $sql_insert = 'insert into '.$tableName.' (name, shortname, address,megaventory_id, counts_in_total_stock) values ("'.$mvInventoryLocationName.'","'.$mvInventoryLocationAbbreviation.'","'.$mvInventoryLocationAddress.'","'.$mvInventoryLocationID.'","0")'; } else { - $sql_insert = 'insert into '.$tableName.' (name, shortname, address,megaventory_id, isdefault) values ("'.$mvInventoryLocationName.'","'.$mvInventoryLocationAbbreviation.'","'.$mvInventoryLocationAddress.'","'.$mvInventoryLocationID.'","1")'; + $sql_insert = 'insert into '.$tableName.' (name, shortname, address,megaventory_id, stock_source_code) values ("'.$mvInventoryLocationName.'","'.$mvInventoryLocationAbbreviation.'","'.$mvInventoryLocationAddress.'","'.$mvInventoryLocationID.'","default")'; } $connection->query($sql_insert); @@ -529,10 +588,15 @@ private function insertInventory($mvInventory, $default = false) private function updateInventory($inventory, $mvInventory) { + $mvInventoryLocationAddress = null; + if(array_key_exists('InventoryLocationAddress', $mvInventory)){ + $mvInventory['InventoryLocationAddress']; + } + $inventory->setData('shortname', $mvInventory['InventoryLocationAbbreviation']); $inventory->setData('name', $mvInventory['InventoryLocationName']); - $inventory->setData('address', $mvInventory['InventoryLocationAddress']); - $inventory->setData('InventoryLocationAddress', $mvInventory['InventoryLocationAddress']); + $inventory->setData('address', $mvInventoryLocationAddress); + $inventory->setData('InventoryLocationAddress', $mvInventoryLocationAddress); $inventory->save(); } @@ -543,15 +607,6 @@ private function deleteNotExistentInventories($mvIds) $sqlDelete = 'delete from '.$tableName.' where megaventory_id not in ('.implode(',', $mvIds).')'; $connection->query($sqlDelete); - - $inventory = $this->_inventoriesLoader->create()->loadDefault(); - - if (!$inventory ->getId() && count($mvIds) > 0) { //there is no default inventory - $newDefaultInventory = $this->_inventoriesLoader->create()->load($mvIds[0], 'megaventory_id'); - $newDefaultInventory->setData('isdefault', '1'); - $newDefaultInventory->setData('counts_in_total_stock', '1'); - $newDefaultInventory->save(); - } } public function getIdByMegaventoryId($mvId) diff --git a/Helper/Order.php b/Helper/Order.php index 15bd67b..940185c 100644 --- a/Helper/Order.php +++ b/Helper/Order.php @@ -15,6 +15,7 @@ class Order extends \Magento\Framework\App\Helper\AbstractHelper protected $_taxesHelper; protected $_customerHelper; protected $_productHelper; + protected $_inventoriesHelper; protected $_storeManager; protected $_orderLoader; @@ -29,11 +30,22 @@ class Order extends \Magento\Framework\App\Helper\AbstractHelper protected $_addressRenderer; protected $_priceCurrency; + protected $_sourceSelectionAddressFactory; + + protected $_sourceSelectionService; + protected $_inventoryRequestFactory; + protected $_inventoryItemFactory; + protected $_stockCollectionFactory; + protected $_salesChannelFactory; + protected $_salesStockByChannel; + protected $_orderItemCollectionFactory; + + protected $_documentTypeHelper; + protected $logger; protected $mvLogFactory; private $APIKEY; - public function __construct( \Magento\Framework\App\Helper\Context $context, \Magento\Framework\Registry $registry, @@ -42,20 +54,29 @@ public function __construct( \Mv\Megaventory\Helper\Currencies $currenciesHelper, \Mv\Megaventory\Helper\Taxes $taxesHelper, \Mv\Megaventory\Helper\Product $productHelper, + \Mv\Megaventory\Helper\Inventories $inventoriesHelper, \Magento\Store\Model\StoreManager $storeManager, \Magento\Sales\Model\OrderFactory $orderLoader, + \Magento\InventorySourceSelectionApi\Api\Data\AddressInterfaceFactory $sourceSelectionAddressFactory, \Magento\Catalog\Model\ProductFactory $productLoader, \Magento\Customer\Model\CustomerFactory $customerLoader, \Mv\Megaventory\Model\CurrenciesFactory $currenciesLoader, \Mv\Megaventory\Model\InventoriesFactory $inventoriesLoader, \Mv\Megaventory\Model\BomFactory $bomLoader, + \Mv\Megaventory\Helper\DocumentType $documentTypeHelper, \Magento\Tax\Model\Calculation $taxCalculation, \Magento\Tax\Model\Config $taxConfig, \Magento\Tax\Helper\Data $magentoTaxHelper, \Magento\Sales\Model\Order\Address\Renderer $addressRenderer, \Magento\Framework\Pricing\PriceCurrencyInterface $priceCurrency, LogFactory $mvLogFactory, - Logger $logger + Logger $logger, + \Magento\InventorySourceSelectionApi\Api\SourceSelectionServiceInterface $sourceSelectionService, + \Magento\InventorySourceSelectionApi\Api\Data\InventoryRequestInterfaceFactory $inventoryRequestFactory, + \Magento\InventorySourceSelectionApi\Api\Data\ItemRequestInterfaceFactory $itemRequestFactory, + \Magento\InventorySalesApi\Api\Data\SalesChannelInterfaceFactory $salesChannelFactory, + \Magento\InventorySalesApi\Api\GetStockBySalesChannelInterface $salesStock, + \Magento\Sales\Model\ResourceModel\Order\Item\CollectionFactory $orderItemCollectionFactory ) { $this->_scopeConfig = $context->getScopeConfig(); $this->_registry = $registry; @@ -65,6 +86,7 @@ public function __construct( $this->_taxesHelper = $taxesHelper; $this->_customerHelper = $customerHelper; $this->_productHelper = $productHelper; + $this->_inventoriesHelper = $inventoriesHelper; $this->_storeManager = $storeManager; $this->_orderLoader = $orderLoader; @@ -78,6 +100,16 @@ public function __construct( $this->_magentoTaxHelper = $magentoTaxHelper; $this->_addressRenderer = $addressRenderer; $this->_priceCurrency = $priceCurrency; + $this->_orderItemCollectionFactory = $orderItemCollectionFactory; + $this->_sourceSelectionAddressFactory = $sourceSelectionAddressFactory; + + $this->_sourceSelectionService = $sourceSelectionService; + $this->_inventoryRequestFactory = $inventoryRequestFactory; + $this->_inventoryItemFactory = $itemRequestFactory; + $this->_salesChannelFactory = $salesChannelFactory; + $this->_salesStockByChannel = $salesStock; + + $this->_documentTypeHelper = $documentTypeHelper; $this->mvLogFactory = $mvLogFactory; $this->logger = $logger; @@ -86,6 +118,148 @@ public function __construct( parent::__construct($context); } + public function getSourceFromOrderItem( + $items, + $stockId, + $algorithmCode, + $extraParameters = [], + $isQuote = true + ) { + $requestItems = []; + foreach ($items as $item) { + $requestItem = ''; + if ($isQuote) { + $requestItem = $this->_inventoryItemFactory->create(['sku'=>$item->getSku(),'qty'=>$item->getQty()]); + } else { + $qty = $item->getQtyOrdered(); + $requestItem = $this->_inventoryItemFactory->create(['sku'=>$item->getSku(),'qty'=>$qty]); + } + $requestItems[] = $requestItem; + } + + $inventoryRequest = $this->_inventoryRequestFactory->create(['stockId'=>$stockId,'items'=>$requestItems]); + $requestExtensionAttributes = $inventoryRequest->getExtensionAttributes(); + foreach ($extraParameters as $key => $value) { + $requestExtensionAttributes->setData($key, $value); + } + $inventoryRequest->setExtensionAttributes($requestExtensionAttributes); + $sources = $this->_sourceSelectionService->execute($inventoryRequest, $algorithmCode) + ->getSourceSelectionItems(); + return $sources; + } + + public function removeBundlesAndChildrenOfBundles($items) + { + $result = []; + foreach ($items as $item) { + if (($item->getProduct()->getTypeId() != 'bundle') && (($item->getParentItem() === null) || ($item->getParentItem()->getProduct()->getTypeId() != 'bundle'))) { + $result[] = $item; + } + } + + return $result; + } + + public function getOrderItemFromSourceResult($orderItems, $sourceResult) + { + foreach ($orderItems as $item) { + if ($item->getSku() == $sourceResult->getSku()) { + return $item; + } + } + return -1; + } + + public function getExtraParameters($order) + { + $shippingAddress = $order->getShippingAddress(); + + $data = [ + "country"=>$shippingAddress->getCountryId(), + "postcode"=>(string)$shippingAddress->getPostCode(), + "street"=>(string)$shippingAddress->getStreet()[0], + "region"=>(($shippingAddress->getRegionId() === null) ? (string)$shippingAddress->getRegion() : $shippingAddress->getRegionId()), + "city"=>(string)$shippingAddress->getCity() + ]; + $sourceSelectionAddress = $this->_sourceSelectionAddressFactory->create($data); + $extraParams = ['destination_address'=>$sourceSelectionAddress]; + return $extraParams; + } + + public function getShipments($order) + { + $algorithm = $this->getAlgorithmSourceCode(); + + $stockId = $this->getStockIdFromOrderWebsite($order); + + $items = $order->getAllItems(); + + $extraParams = $this->getExtraParameters($order); + + $sourceItems = $this->getSourceFromOrderItem($items, $stockId, $algorithm, $extraParams, false); + $shipments = []; + + foreach ($sourceItems as $sourceItem) { + $orderItem = $this->getOrderItemFromSourceResult($items, $sourceItem); + if (($sourceItem->getQtyToDeduct() > 0) && ($orderItem !== -1)) { + if (!in_array($sourceItem->getSourceCode(), array_keys($shipments))) { + $shipments[$sourceItem->getSourceCode()] = []; + } + $shipments[$sourceItem->getSourceCode()][] = [ + 'sku'=>$sourceItem->getSku(), + 'qty'=>$sourceItem->getQtyToDeduct(), + 'order_item'=>$orderItem + ]; + } + } + return $shipments; + } + + public function getPreferredLocation($sourceItems) + { + $sourceBucket = []; + foreach ($sourceItems as $sourceItem) { + if (!in_array($sourceItem->getSourceCode(), array_keys($sourceBucket))) { + $sourceBucket[$sourceItem->getSourceCode()] = 0; + } + + $sourceBucket[$sourceItem->getSourceCode()] += $sourceItem->getQtyToDeduct(); + } + + return array_search(max($sourceBucket), $sourceBucket); + } + + public function getOrderItemFromSourceResultItem(\Magento\Sales\Model\Order $order, $sourceResult) + { + $sku = $sourceResult->getSku(); + $orderId = $order->getId(); + + $item = $this->_orderItemCollectionFactory->create() + ->addFieldToFilter('sku', $sku) + ->addFieldToFilter('order_id', $orderId)->getFirstItem(); + + return $item; + } + + public function getAlgorithmSourceCode() + { + return $this->_scopeConfig->getValue('megaventory/orders/source_selection_algorithm_code'); + } + + public function getStockIdFromOrderWebsite(\Magento\Sales\Model\Order $order) + { + $websiteCode = $order->getStore()->getWebsite()->getCode(); + + $channel = $this->_salesChannelFactory->create(); + $channel->setType('website'); + $channel->setCode($websiteCode); + return $this->_salesStockByChannel->execute($channel)->getStockId(); + } + + public function addExtraDataToComment($order, $comment){ + return $comment; + } + public function addOrder(\Magento\Sales\Model\Order $order, \Magento\Quote\Model\Quote $quote) { $increment_id = $order->getIncrementId(); @@ -100,9 +274,7 @@ public function addOrder(\Magento\Sales\Model\Order $order, \Magento\Quote\Model $this->_currenciesHelper->addSingleCurrency($orderCurrencyCode); } - $billingAddress = $order->getBillingAddress(); - //$billingAddressString = $billingAddress->format('oneline'); $billingAddressString = $this->_addressRenderer->format($billingAddress, 'oneline'); $billingEmail = $billingAddress->getEmail(); $billingTelephone = $billingAddress->getTelephone(); @@ -112,8 +284,10 @@ public function addOrder(\Magento\Sales\Model\Order $order, \Magento\Quote\Model } $shippingAddress = $order->getShippingAddress(); - //$shippingAddressString = $shippingAddress->format('oneline'); - $shippingAddressString = $this->_addressRenderer->format($shippingAddress, 'oneline'); + $shippingAddressString = ''; + if(!empty($shippingAddress)){ + $shippingAddressString = $this->_addressRenderer->format($shippingAddress, 'oneline'); + } $shippingEmail = $shippingAddress->getEmail(); $shippingTelephone = $shippingAddress->getTelephone(); $shippingAddressString = trim($shippingAddressString); @@ -121,9 +295,7 @@ public function addOrder(\Magento\Sales\Model\Order $order, \Magento\Quote\Model $shippingAddressString .= ',' . $shippingTelephone; } - $orderDate = $order->getUpdated_at(); - //$customer = $order->getCustomer(); $customer = $this->_customerLoader->create()->load($order->getCustomer_id()); $megaVentoryCustomerId = 0; @@ -153,10 +325,29 @@ public function addOrder(\Magento\Sales\Model\Order $order, \Magento\Quote\Model } $items = $quote->getAllItems(); + $itemsWithoutBundles = $this->removeBundlesAndChildrenOfBundles($items); $salesOrderDetails = []; - $inventory = $this->_invnentoriesLoader->create()->loadDefault(); + $algorithm = $this->getAlgorithmSourceCode(); + + $stockId = $this->getStockIdFromOrderWebsite($order); + + $extraParams = $this->getExtraParameters($order); + $inventorySourceCode = $this->getPreferredLocation( + $this->getSourceFromOrderItem( + $itemsWithoutBundles, + $stockId, + $algorithm, + $extraParams + ) + ); + + $inventory = $this->_invnentoriesLoader->create() + ->load($inventorySourceCode, 'stock_source_code'); + + $bundleLocations = []; + foreach ($items as $productItem) { $product = $productItem->getProduct(); $product = $this->_productLoader->create()->load($product->getId()); @@ -165,6 +356,18 @@ public function addOrder(\Magento\Sales\Model\Order $order, \Magento\Quote\Model if ($productType == 'bundle') { $options = $this->_productHelper->getBundleOptions($productItem); + $bundleChildren = $productItem->getChildren(); + $bundleInventorySource = $this->getPreferredLocation( + $this->getSourceFromOrderItem( + $itemsWithoutBundles, + $stockId, + $algorithm, + $extraParams + ) + ); + $bundleInventory = $this->_invnentoriesLoader->create() + ->load($bundleInventorySource, 'stock_source_code'); + //keep bundle products to avoid duplicates $bundles = array_fill_keys(array_keys($options), '1'); $bundleCode = ''; @@ -212,9 +415,7 @@ public function addOrder(\Magento\Sales\Model\Order $order, \Magento\Quote\Model } } - //we need to set is_salable to option products - //because when we resynchronize an order we don't have - //a website id and products appear as no salable + //set product as saleable if ($product->hasCustomOptions()) { $customOption = $product->getCustomOption('bundle_option_ids'); $customOption = $product->getCustomOption('bundle_selection_ids'); @@ -236,17 +437,22 @@ public function addOrder(\Magento\Sales\Model\Order $order, \Magento\Quote\Model 'SalesOrderRowTaxID' => $salesOrderRowTaxID, 'SalesOrderRowProductSKU' => $bundleSKU ]; - $salesOrderDetails[] = $salesOrderItem; + if ($bundleInventory->getMegaventoryId() != $inventory->getMegaventoryId()) { + $bundleLocations[$bundleInventory->getMegaventoryId()][] = $salesOrderItem; + } else { + $salesOrderDetails[] = $salesOrderItem; + } //add work order if ($bundleSKU != -1) { $woComments = 'product:' . $product->getName(); $woComments .= ',order:' . $increment_id; - $this->addWorkOrder($bundleSKU, $productItem->getQty(), $inventory->getData('megaventory_id'), $woComments, $product->getId()); + $this->addWorkOrder($bundleSKU, $productItem->getQty(), $bundleInventory->getData('megaventory_id'), $woComments, $product->getId()); } //end of work order + } elseif ($productType == \Magento\Catalog\Model\Product\Type::TYPE_SIMPLE || $productType == \Magento\Catalog\Model\Product\Type::TYPE_VIRTUAL) { //if product is checked through bundle then do nothing more if (!empty($bundles)) { @@ -270,14 +476,15 @@ public function addOrder(\Magento\Sales\Model\Order $order, \Magento\Quote\Model $megaventoryProductId = $id; } - $parentItem = $productItem->getParentItem(); if (isset($parentItem)) { $productItem = $parentItem; - //$product = $productItem->getProduct(); } - $finalPriceNoTax = $this->getPrice($productItem->getProduct(), $productItem->getProduct()->getFinalPrice($productItem->getQty())); + $finalPriceNoTax = $this->getPrice( + $productItem->getProduct(), + $productItem->getProduct()->getFinalPrice($productItem->getQty()) + ); $taxPercent = $productItem->getTax_percent(); $tax = $this->_taxesHelper->getTaxByPercentage($taxPercent); @@ -326,14 +533,10 @@ public function addOrder(\Magento\Sales\Model\Order $order, \Magento\Quote\Model //add shipping as product //get base prices - /* $shippingNoTax = $order->getShipping_amount(); - $shippingWithTax = $order->getShipping_incl_tax(); - $shippingTax = $order->getShipping_tax_amount(); */ $shippingNoTax = $order->getBase_shipping_amount(); $shippingWithTax = $order->getBase_shipping_incl_tax(); $shippingTax = $order->getBase_shipping_tax_amount(); - $shippingProductSKU = $this->_scopeConfig->getValue('megaventory/general/shippingproductsku'); $shippingOrderItem = [ 'SalesOrderRowQuantity' => '1', @@ -413,24 +616,27 @@ public function addOrder(\Magento\Sales\Model\Order $order, \Magento\Quote\Model $shippingMethod = $order->getShipping_method(); $paymentMethodTitle = $order->getPayment()->getMethodInstance()->getTitle(); - $storeName = $order->getStore_name(); $comments .= 'ship:' . $shippingDescription . ',pay:' . $paymentMethodTitle; - $tags = ''; + $comments = $this->addExtraDataToComment($order, $comments); + $tags = ''; $magentoInstallationId = $this->_scopeConfig->getValue('megaventory/general/magentoid'); if (!isset($magentoInstallationId)) { $magentoInstallationId = "MagentoCommunity"; } + $documentTypeId = $this->_documentTypeHelper->getDocumentTypeIdFromWebsiteId($order->getStore()->getWebsiteId()); + $data = [ 'APIKEY' => $this->APIKEY, 'mvSalesOrder' => [ 'SalesOrderNo' => $increment_id, 'SalesOrderReferenceNo' => $increment_id, + 'SalesOrderTypeId' => $documentTypeId, 'SalesOrderReferenceApplication' => $magentoInstallationId, //magento, magento-2 ... //always insert orders in base currency 'SalesOrderCurrencyCode' => $baseCurrencyCode, @@ -452,12 +658,48 @@ public function addOrder(\Magento\Sales\Model\Order $order, \Magento\Quote\Model $orderAdded = $this->_orderLoader->create()->loadByIncrementId($increment_id); $json_result = $this->_mvHelper->makeJsonRequest($data, 'SalesOrderUpdate', $orderAdded->getId()); - $errorCode = $json_result['ResponseStatus']['ErrorCode']; if ($errorCode == '0') { //no errors - $orderAdded->setData('mv_salesorder_id', $json_result['mvSalesOrder']['SalesOrderNo']); - $orderAdded->setData('mv_inventory_id', $inventory->getData('id')); - $orderAdded->save(); + $error = false; + + //Create bundles based on the location availability of the children products + foreach ($bundleLocations as $mvInventoryId => $orderDetails) { + $data = [ + 'APIKEY' => $this->APIKEY, + 'mvSalesOrder' => + [ + 'SalesOrderNo' => $increment_id, + 'SalesOrderReferenceNo' => $increment_id, + 'SalesOrderReferenceApplication' => $magentoInstallationId, //magento, magento-2 ... + //always insert orders in base currency + 'SalesOrderCurrencyCode' => $baseCurrencyCode, + //'SalesOrderCurrencyCode' => $orderCurrencyCode, + 'SalesOrderClientID' => $megaVentoryCustomerId, + 'SalesOrderBillingAddress' => $billingAddressString, + 'SalesOrderShippingAddress' => $shippingAddressString, + 'SalesOrderContactPerson' => $billingAddress->getLastname() . ' ' . $billingAddress->getFirstname(), + 'SalesOrderInventoryLocationID' => $mvInventoryId, + 'SalesOrderComments' => $comments, + 'SalesOrderTags' => $tags, + 'SalesOrderAmountShipping' => $shippingWithTax, + 'SalesOrderDetails' => $orderDetails, + 'SalesOrderStatus' => 'Verified' + ], + 'mvRecordAction' => "Insert" + ]; + + $orderAdded = $this->_orderLoader->create()->loadByIncrementId($increment_id); + $json_result = $this->_mvHelper->makeJsonRequest($data, 'SalesOrderUpdate', $orderAdded->getId()); + if ($errorCode != '0') { + $error = true; + break; + } + } + if (!$error) { + $orderAdded->setData('mv_salesorder_id', $json_result['mvSalesOrder']['SalesOrderNo']); + $orderAdded->setData('mv_inventory_id', $inventory->getData('id')); + $orderAdded->save(); + } } } @@ -500,7 +742,6 @@ public function getPrice( $store = $this->_storeManager->getStore(); if (!$this->needPriceConversion($store)) { - //return $store->roundPrice($price); return $this->_priceCurrency->round($price); } @@ -547,14 +788,12 @@ public function getPrice( $product->setTaxPercent($percent); - if ($includingPercent != $percent) { $price = $this->_calculatePrice($price, $includingPercent, false); } else { $price = $this->_calculatePrice($price, $includingPercent, false, true); } - //return $store->roundPrice($price); return $this->_priceCurrency->round($price); } diff --git a/Helper/Product.php b/Helper/Product.php index fd5fcf8..bfe853b 100644 --- a/Helper/Product.php +++ b/Helper/Product.php @@ -4,19 +4,26 @@ use \Mv\Megaventory\Logger\Logger; use \Mv\Megaventory\Model\LogFactory; -use \Magento\Framework\Filesystem\Io\Magento\Framework\Filesystem\Io; +use PDO; class Product extends \Magento\Framework\App\Helper\AbstractHelper { + const RESULT_ERROR = -1; + const SKIP_SYNC = 0; + + const INTERNAL_SUPPLIER_CLIENT_FOR_ADJUSTMENTS = -1; + protected $_scopeConfig; private $_mvHelper; private $_inventoriesHelper; private $_productLoader; private $_categoryLoader; private $_inventoriesLoader; + private $_inventoryResource; private $_productStocksLoader; private $_bomLoader; private $_productCollectionFactory; + private $_sourceCollection; private $_productHelper; private $_storeManager; private $_resource; @@ -26,16 +33,18 @@ class Product extends \Magento\Framework\App\Helper\AbstractHelper private $APIKEY; private $_registry; private $_backendUrl; - + private $_sourceLowStockItemInterface; + private $_adjustmentFactory; + private $_adjustmentResource; protected $logger; protected $mvLogFactory; - public function __construct( \Magento\Framework\App\Helper\Context $context, Data $mvHelper, \Mv\Megaventory\Helper\Inventories $inventoriesHelper, \Magento\Catalog\Model\ProductFactory $productLoader, + \Magento\Inventory\Model\ResourceModel\SourceItem\CollectionFactory $sourceCollection, \Magento\Catalog\Model\CategoryFactory $categoryLoader, \Mv\Megaventory\Model\InventoriesFactory $inventoriesLoader, \Mv\Megaventory\Model\ProductstocksFactory $productStocksLoader, @@ -49,6 +58,10 @@ public function __construct( \Magento\ConfigurableProduct\Model\ResourceModel\Product\Type\Configurable $catalogProductTypeConfigurable, \Magento\Framework\Registry $registry, \Magento\Backend\Model\UrlInterface $backendUrl, + \Magento\InventoryLowQuantityNotificationApi\Api\GetSourceItemConfigurationInterface $sourceItemConfig, + \Mv\Megaventory\Model\AdjustmentTemplateFactory $adjustmentTemplateFactory, + \Mv\Megaventory\Model\ResourceModel\AdjustmentTemplate $adjustmentTemplateResource, + \Mv\Megaventory\Model\ResourceModel\Inventories $inventoryResource, LogFactory $mvLogFactory, Logger $logger ) { @@ -67,13 +80,17 @@ public function __construct( $this->_attributeFactory = $attributeFactory; $this->_attributeSetFactory = $attributeSetFactory; $this->_catalogProductTypeConfigurable = $catalogProductTypeConfigurable; + $this->_sourceCollection = $sourceCollection; + $this->_sourceLowStockItemInterface = $sourceItemConfig; + $this->_inventoryResource = $inventoryResource; + $this->_adjustmentFactory = $adjustmentTemplateFactory; + $this->_adjustmentResource = $adjustmentTemplateResource; $this->_registry = $registry; $this->_backendUrl = $backendUrl; $this->mvLogFactory = $mvLogFactory; $this->logger = $logger; - $this->APIKEY = $this->_scopeConfig->getValue('megaventory/general/apikey'); parent::__construct($context); } @@ -90,7 +107,6 @@ public function getProduct($mvProductId) ] ]; - $json_result = $this->_mvHelper->makeJsonRequest($data, 'ProductGet', 0); if ($json_result['ResponseStatus']['ErrorCode'] == 0) { @@ -104,7 +120,9 @@ public function addProduct($product) { $productType = $product->getType_id(); - if ($productType == \Magento\Catalog\Model\Product\Type::TYPE_SIMPLE || $productType == \Magento\Catalog\Model\Product\Type::TYPE_VIRTUAL) { + if ($productType == \Magento\Catalog\Model\Product\Type::TYPE_SIMPLE || + $productType == \Magento\Catalog\Model\Product\Type::TYPE_VIRTUAL + ) { $productId = $product->getEntityId(); $product = $this->_productLoader->create()->load($productId); @@ -177,8 +195,8 @@ public function addProduct($product) //supplier exists if (count($json_result['mvSupplierClients']) > 0) { $mvSupplierId = $json_result['mvSupplierClients'][0]['SupplierClientID']; - } else //supplier is new - { + } else {//supplier is new + $supplierData = [ 'APIKEY' => $this->APIKEY, 'mvSupplierClient' => [ @@ -199,7 +217,11 @@ public function addProduct($product) 'mvRecordAction' => 'Insert' ]; - $json_result = $this->_mvHelper->makeJsonRequest($supplierData, 'SupplierClientUpdate', 0); + $json_result = $this->_mvHelper->makeJsonRequest( + $supplierData, + 'SupplierClientUpdate', + 0 + ); $errorCode = $json_result['ResponseStatus']['ErrorCode']; if ($errorCode == '0') { //no errors @@ -222,12 +244,12 @@ public function addProduct($product) $simpleProduct = $product; $product = $parentProduct; - $productAttributeOptions = $product->getTypeInstance(true)->getConfigurableAttributesAsArray($product); + $productAttributeOptions = $product->getTypeInstance(true) + ->getConfigurableAttributesAsArray($product); $attributeOptions = []; $attributeValues = []; foreach ($productAttributeOptions as $productAttribute) { - //$attributeOptions[$productAttribute['attribute_code']] = $productAttribute['store_label']; foreach ($productAttribute['values'] as $attribute) { if ($attribute['value_index'] == $simpleProduct[$productAttribute['attribute_code']]) { @@ -235,7 +257,6 @@ public function addProduct($product) break; } - //$attributeOptions[$productAttribute['label']][$attribute['value_index']] = $attribute['store_label']; } } @@ -245,7 +266,6 @@ public function addProduct($product) } } - $shortDescription = ''; if (isset($product['short_description'])) { $shortDescription = $product['short_description']; @@ -253,7 +273,6 @@ public function addProduct($product) $shortDescription = mb_substr($shortDescription, 0, 400, "utf-8"); } - //$shortDescription = substr($shortDescription, 0, 400); } $description = ''; @@ -263,23 +282,21 @@ public function addProduct($product) $description = mb_substr($description, 0, 400, "utf-8"); } - //$description = substr($description, 0, 400); } try { $image = $this->_productHelper->getImageUrl($product); - //$this->_imagetHelper->init($product, 'product_base_image'); } catch (\Exception $e) { $image = ''; } + $mvRecordAction = 'InsertOrUpdateNonEmptyFields'; + if (isset($megaVentoryId) && $megaVentoryId != null) { //it is an update $mvProductId = $megaVentoryId; - $mvRecordAction = 'Update'; - } else //it is an insert - { + } else {//it is an insert + $mvProductId = '0'; - $mvRecordAction = 'Insert'; } $categoryIds = $product->getCategoryIds(); @@ -300,7 +317,6 @@ public function addProduct($product) } } - $attibuteSetId = $product->getAttributeSetId(); $attributeSetName = $this->_attributeSetFactory->create()->load($attibuteSetId)->getAttributeSetName(); @@ -339,14 +355,9 @@ public function addProduct($product) $json_result = $this->_mvHelper->makeJsonRequest($data, 'ProductUpdate', $productId); - $errorCode = $json_result['ResponseStatus']['ErrorCode']; if ($errorCode == '0') { //no errors - if (strcmp('Insert', $mvRecordAction) == 0) { - $this->updateProduct($productId, $json_result['mvProduct']['ProductID']); - /* $product->setData('mv_product_id',$json_result['mvProduct']['ProductID']); - $product->save(); */ - } + $this->updateProduct($productId, $json_result['mvProduct']['ProductID']); return $json_result['mvProduct']['ProductID']; } else { @@ -360,18 +371,17 @@ public function addProduct($product) return $result; } else { $this->updateProduct($productId, $entityId); - /* $product->setData('mv_product_id',$json_result['entityID']); - $product->save(); */ $data['mvProduct']['ProductID'] = $entityId; $data['mvRecordAction'] = 'Update'; $json_result = $this->_mvHelper->makeJsonRequest($data, 'ProductUpdate', $productId); + return $entityId; } } } + return self::RESULT_ERROR; } - - return 0; + return self::SKIP_SYNC; } public function deleteProduct($product) @@ -389,18 +399,14 @@ public function deleteProduct($product) $errorCode = $json_result['ResponseStatus']['ErrorCode']; if ($errorCode == '0') { //no errors - //make null the back end reference $this->updateProduct($productId, 'null'); } } } - public function addShippingProduct($megaventoryHelper) + public function addOrUpdateShippingProduct($shippingSKU = 'shipping_01') { - $shippingSKU = $this->_scopeConfig->getValue('megaventory/general/shippingproductsku'); - if (empty($shippingSKU)) { - $shippingSKU = 'shipping_01'; - } + $magentoId = $this->_scopeConfig->getValue('megaventory/general/magentoid'); $data = [ 'APIKEY' => $this->APIKEY, @@ -430,7 +436,8 @@ public function addShippingProduct($megaventoryHelper) 'ProductMainSupplierSKU' => '', 'ProductMainSupplierDescription' => '' ], - 'mvRecordAction' => 'Insert' + 'mvRecordAction' => 'InsertOrUpdateNonEmptyFields', + 'mvInsertUpdateDeleteSourceApplication'=>$magentoId ]; try { @@ -451,12 +458,9 @@ public function addShippingProduct($megaventoryHelper) } } - public function addDiscountProduct() + public function addOrUpdateDiscountProduct($discountSKU = 'discount_01') { - $discountSKU = $this->_scopeConfig->getValue('megaventory/general/discountproductsku'); - if (empty($discountSKU)) { - $discountSKU = 'discount_01'; - } + $magentoId = $this->_scopeConfig->getValue('megaventory/general/magentoid'); $data = [ 'APIKEY' => $this->APIKEY, @@ -486,7 +490,8 @@ public function addDiscountProduct() 'ProductMainSupplierSKU' => '', 'ProductMainSupplierDescription' => '' ], - 'mvRecordAction' => 'Insert' + 'mvRecordAction' => 'InsertOrUpdateNonEmptyFields', + 'mvInsertUpdateDeleteSourceApplication'=>$magentoId ]; try { @@ -510,7 +515,6 @@ public function addDiscountProduct() public function importProductsToMegaventory($page = 1, $imported = 0) { - $simple_products = $this->_productCollectionFactory->create() ->addAttributeToSelect('name') ->addAttributeToSelect('description') @@ -525,7 +529,6 @@ public function importProductsToMegaventory($page = 1, $imported = 0) ) ->addAttributeToSort('type_id', 'ASC'); - $simple_products->setPageSize(20); $simple_products->setCurPage($page); $totalCollectionSize = $simple_products->getSize(); @@ -534,7 +537,7 @@ public function importProductsToMegaventory($page = 1, $imported = 0) $isLastPage = true; } - $total = $imported; // + ($page-1)*10; + $total = $imported; foreach ($simple_products as $product) { try { $inserted = $this->insertSingleProduct($product); @@ -562,7 +565,7 @@ public function importProductsToMegaventory($page = 1, $imported = 0) $message = $total . '/' . $totalCollectionSize . ' products imported' . $this->_registry->registry('tickImage'); if ($total != $totalCollectionSize) { $logUrl = $this->_backendUrl->getUrl("megaventory/index/log"); - $message .= '' . $totalCollectionSize - $total . ' product(s) were not imported. Check Megaventory Log for details' . $this->_registry->registry('errorImage'); + $message .= '' . ($totalCollectionSize - $total) . ' product(s) were not imported. Check Megaventory Log for details' . $this->_registry->registry('errorImage'); } $this->_mvHelper->sendProgress(31, $message, $page, 'products', true); @@ -610,7 +613,6 @@ public function insertSingleProduct($product) $finalPriceNoTax = $finalPrice; } - if (isset($product['cost']) == false) { $cost = '0'; } else { @@ -655,8 +657,8 @@ public function insertSingleProduct($product) //supplier exists if (count($json_result['mvSupplierClients']) > 0) { $mvSupplierId = $json_result['mvSupplierClients'][0]['SupplierClientID']; - } else //supplier is new - { + } else {//supplier is new + $supplierData = [ 'APIKEY' => $this->APIKEY, 'mvSupplierClient' => [ @@ -691,7 +693,6 @@ public function insertSingleProduct($product) } } - $version = ''; $parentIds = $this->_catalogProductTypeConfigurable->getParentIdsByChild($productId); @@ -706,15 +707,12 @@ public function insertSingleProduct($product) $attributeValues = []; foreach ($productAttributeOptions as $productAttribute) { - //$attributeOptions[$productAttribute['attribute_code']] = $productAttribute['store_label']; foreach ($productAttribute['values'] as $attribute) { if ($attribute['value_index'] == $simpleProduct[$productAttribute['attribute_code']]) { $attributeValues[$productAttribute['store_label']] = $attribute['label']; break; } - - //$attributeOptions[$productAttribute['label']][$attribute['value_index']] = $attribute['store_label']; } } @@ -724,15 +722,12 @@ public function insertSingleProduct($product) } } - $shortDescription = ''; if (isset($product['short_description'])) { $shortDescription = $product['short_description']; if (strlen($shortDescription) > 400) { $shortDescription = mb_substr($shortDescription, 0, 400, "utf-8"); } - - //$shortDescription = substr($shortDescription, 0, 400); } $description = ''; @@ -741,13 +736,10 @@ public function insertSingleProduct($product) if (strlen($description) > 400) { $description = mb_substr($description, 0, 400, "utf-8"); } - - //$description = substr($description, 0, 400); } try { $image = $this->_productHelper->getImageUrl($product); - //$this->_imagetHelper->init($product, 'product_base_image'); } catch (\Exception $e) { $image = ''; } @@ -773,7 +765,6 @@ public function insertSingleProduct($product) } } - $attibuteSetId = $product->getAttributeSetId(); $attributeSetName = $this->_attributeSetFactory->create()->load($attibuteSetId)->getAttributeSetName(); @@ -872,49 +863,34 @@ public function insertSingleProduct($product) $mvProductId = $entityId; //update alert level - $stockItem = $product->getStock_item(); + $stockItems = $this->_sourceCollection->create()->addFieldToFilter('sku', $product->getSku()); $quantity = '0'; $alertLevel = 0; - if (isset($stockItem)) { - $useConfigNotify = $stockItem->getData('use_config_notify_stock_qty'); - if ($useConfigNotify == '1') { - //get config value - $configValue = $this->_scopeConfig->getValue('cataloginventory/item_options/notify_stock_qty'); - if (isset($configValue)) { - $alertLevel = $configValue; - } else { - $alertLevel = 0; - } - } else { - $alertLevel = $stockItem->getData('notify_stock_qty'); - } - } - - $inventory = $this->_inventoriesLoader->create()->loadDefault(); - $alertData = [ 'APIKEY' => $this->APIKEY, - 'mvProductStockAlertsAndSublocationsList' => [ - 'productID' => $mvProductId, - 'mvInventoryLocationStockAlertAndSublocations' => [ - 'InventoryLocationID' => $inventory->getData('megaventory_id'), - 'StockAlertLevel' => $alertLevel - ] - - ] + 'mvProductStockAlertsAndSublocationsList' => [] ]; - $this->_mvHelper->makeJsonRequest($alertData, 'InventoryLocationStockAlertAndSublocationsUpdate'); - - $productStock = $this->_productStocksLoader->create() - ->loadInventoryProductstock($inventory->getId(), $product->getId()); - - $productStock->setProduct_id($productId); - $productStock->setInventory_id($inventory->getId()); - $productStock->setStockalarmqty($alertLevel); - $productStock->save(); + if (isset($stockItems) && count($stockItems) > 0) { + foreach ($stockItems as $stockItem) { + $alertLevel = (int)$this->_sourceLowStockItemInterface + ->execute($stockItem->getSourceCode(), $product->getSku()) + ->getNotifyStockQty(); + $code = $stockItem->getSourceCode(); + $inventory = $this->_inventoriesLoader->create()->loadBySource($code); + $alertData['mvProductStockAlertsAndSublocationsList'][] = [ + 'productID' => $mvProductId, + 'mvInventoryLocationStockAlertAndSublocations' => [ + 'InventoryLocationID' => $inventory->getData('megaventory_id'), + 'StockAlertLevel' => $alertLevel + ] + ]; + } + + } + $this->_mvHelper->makeJsonRequest($alertData, 'InventoryLocationStockAlertAndSublocationsUpdate'); return 1; } @@ -928,7 +904,6 @@ public function getBundleOptions(\Magento\Quote\Model\Quote\Item $item) $options = []; $product = $item->getProduct(); - //\Magento\Bundle\Model\Product\Type $typeInstance = $product->getTypeInstance(true); @@ -1011,10 +986,7 @@ public function addBundleProduct($product, $bundleCode, $options) $productId = $product->getEntityId(); $product = $this->_productLoader->create()->load($productId); - $name = $product['name']; - //$sku = $product['sku'].'_'.$bundleCode; - //$sku = $bundleCode; $sku = 'bom_' . $this->generateRandomString(); if (isset($product['weight']) == false) { @@ -1033,10 +1005,8 @@ public function addBundleProduct($product, $bundleCode, $options) $cost = $product['cost']; } - $version = ''; - $shortDescription = ''; if (isset($product['short_description'])) { $shortDescription = $product['short_description']; @@ -1057,7 +1027,6 @@ public function addBundleProduct($product, $bundleCode, $options) //$description = substr($description, 0, 400); } - try { $image = $this->_productHelper->getImageUrl($product); } catch (\Exception $e) { @@ -1129,7 +1098,6 @@ public function addBundleProduct($product, $bundleCode, $options) $json_result = $this->_mvHelper->makeJsonRequest($data, 'ProductUpdate', $productId); - $errorCode = $json_result['ResponseStatus']['ErrorCode']; if ($errorCode == '0') { //no errors $mvRawMaterials = []; @@ -1145,7 +1113,6 @@ public function addBundleProduct($product, $bundleCode, $options) } $bomData = []; - //$data['mvProduct']['mvRawMaterials'] = $mvRawMaterials; unset($data['APIKEY']); unset($data['mvRecordAction']); @@ -1154,7 +1121,6 @@ public function addBundleProduct($product, $bundleCode, $options) $bomData['mvProductBOM']['ProductSKU'] = $sku; $bomData['mvProductBOM']['mvRawMaterials'] = $mvRawMaterials; - $json_result = $this->_mvHelper->makeJsonRequest($bomData, 'ProductBOMUpdate', $productId); $errorCode = $json_result['ResponseStatus']['ErrorCode']; @@ -1211,7 +1177,8 @@ public function addBomAsSimpleProduct($parentProduct, $sku, $bundleCode, $megave $inventories = $this->_inventoriesHelper->getInventories(); $stockData = [ 'stockqty' => 0, 'stockqtyonhold' => 0, 'stockalarmqty' => 0, 'stocknonshippedqty' => 0, - 'stocknonreceivedqty' => 0, 'stockwipcomponentqty' => 0, 'stocknonreceivedwoqty' => 0, 'stocknonallocatedwoqty' => 0 + 'stocknonreceivedqty' => 0, 'stockwipcomponentqty' => 0, + 'stocknonreceivedwoqty' => 0, 'stocknonallocatedwoqty' => 0 ]; foreach ($inventories as $inventory) { $this->_inventoriesHelper->updateInventoryProductStock($product->getId(), $inventory->getId(), $stockData); @@ -1237,24 +1204,46 @@ public function bundleProductExists($bundleCode) return $this->_bomLoader->create()->loadByBOMCode($bundleCode); } - public function exportStock($inventoryMvId, $startingIndex, \Magento\Framework\App\Filesystem\DirectoryList $directoryList) - { + public function exportStock( + $inventoryMvId, + $startingIndex, + \Magento\Framework\App\Filesystem\DirectoryList $directoryList, + $source, + $adjMade = false + ) { + $purchasePriceAttributeCode = $this->_scopeConfig->getValue('megaventory/general/purchasepriceattributecode'); + $simple_products = $this->_productCollectionFactory->create() - //->setPage(1, 10) ->addAttributeToSelect('name') + ->addAttributeToSelect('sku') ->addAttributeToSelect('description') - ->addAttributeToSelect('cost') ->addAttributeToSelect('qty') ->addFieldToFilter('status', \Magento\Catalog\Model\Product\Attribute\Source\Status::STATUS_ENABLED) - ->addAttributeToFilter('type_id', \Magento\Catalog\Model\Product\Type::TYPE_SIMPLE) - ->joinField( - 'qty', - 'cataloginventory_stock_item', - 'qty', - 'product_id=entity_id', - '{{table}}.stock_id=1', - 'left' - )->toArray(); + ->addAttributeToFilter('type_id', ['in'=>[\Magento\Catalog\Model\Product\Type::TYPE_SIMPLE, \Magento\Catalog\Model\Product\Type::TYPE_VIRTUAL]]) + ->toArray(); + + if(!empty($purchasePriceAttributeCode)){ + $simple_products = $this->_productCollectionFactory->create() + ->addAttributeToSelect('name') + ->addAttributeToSelect('sku') + ->addAttributeToSelect('description') + ->addAttributeToSelect($purchasePriceAttributeCode) + ->addAttributeToSelect('qty') + ->addFieldToFilter('status', \Magento\Catalog\Model\Product\Attribute\Source\Status::STATUS_ENABLED) + ->addAttributeToFilter('type_id', ['in'=>[\Magento\Catalog\Model\Product\Type::TYPE_SIMPLE, \Magento\Catalog\Model\Product\Type::TYPE_VIRTUAL]]) + ->toArray(); + } + + + foreach ($simple_products as $index => $product) { + $sources = $this->_sourceCollection->create() + ->addFieldToFilter('sku', $product['sku']) + ->addFieldToFilter('source_code', $source); + + if (count($sources) > 0) { + $simple_products[$index]['qty'] = $sources->getFirstItem()->getQuantity(); + } + } $selected_products_to_sync_stock = array_slice($simple_products, $startingIndex, 100); @@ -1266,10 +1255,10 @@ public function exportStock($inventoryMvId, $startingIndex, \Magento\Framework\A ]; - if ($startingIndex > 0) { + if (($startingIndex > 0) && $adjMade) { $results = [ 'value' => 'Success', - 'message' => 'Check your Adjustments List under Menu -> Inventory, to verify (Approve) them.', + 'message' => 'The adjustment documents have been generated, if you set the preferred generation status to "Pending" go to MV to approve them in order to import the stock.', 'startingIndex' => $startingIndex ]; } @@ -1283,152 +1272,213 @@ public function exportStock($inventoryMvId, $startingIndex, \Magento\Framework\A $filters = []; $locationFilter = []; - $locationFilter[] = $inventoryMvId; + $locationFilter[] = (int)$inventoryMvId; - foreach ($selected_products_to_sync_stock as $selected_product) { - $filter = [ - 'AndOr' => 'Or', - 'FieldName' => 'productID', - 'SearchOperator' => 'Equals', - 'SearchValue' => $selected_product['mv_product_id'], - ]; + $location = $this->_inventoriesLoader->create(); - array_push($filters, $filter); - } + $this->_inventoryResource->load($location, $inventoryMvId, 'megaventory_id'); - // call to get stock information for ids. + $docStatus = $location->getAdjustmentDocStatus(); - $stock_get_body = [ - 'APIKEY' => $this->APIKEY, - 'InventoryLocationID' => $locationFilter, - 'Filters' => $filters, - ]; - $inventoryLocationsStock = $this->_mvHelper->makeJsonRequest($stock_get_body, 'InventoryLocationStockGet'); - - $errorCode = $inventoryLocationsStock['ResponseStatus']['ErrorCode']; - if ($errorCode != 0) { - $event = [ - 'code' => 'Inventory Location Stock Get', - 'result' => 'fail', - 'magento_id' => 0, - 'return_entity' => '0', - 'details' => $inventoryLocationsStock['ResponseStatus']['Message'], - 'data' => '' - ]; - $this->_mvHelper->log($event); - - $results = [ - 'value' => 'Error', - 'message' => 'There has been an error, Check Megaventory logs.', - 'startingIndex' => $startingIndex - ]; - return $results; - } - - $mvProductStockList = $inventoryLocationsStock['mvProductStockList']; + $adjustmentPlusMvId = -99; + $adjustmentMinusMvId = -98; - foreach ($selected_products_to_sync_stock as $selected_product) { - //ignore products which are not synchronized - if (empty($selected_product['mv_product_id'])) { - continue; + if($location->getId() > 0){ + if((int)$location->getMvAdjustmentPlusTypeId() != 0){ + $plusTemplateId = (int)$location->getMvAdjustmentPlusTypeId(); + $template = $this->_adjustmentFactory->create(); + $this->_adjustmentResource->load($template, $plusTemplateId); + $adjustmentPlusMvId = $template->getMegaventoryId(); } - $index = array_search((int) $selected_product['mv_product_id'], array_column($mvProductStockList, 'productID'), true); - - $mv_qty = 0; - if (false !== $index) { - $mv_qty = $mvProductStockList[$index]['StockOnHandTotal']; - } - - $mg_qty = 0; - if (isset($selected_product['qty']) && $selected_product['qty'] > 0) { - $mg_qty = $selected_product['qty']; + if((int)$location->getMvAdjustmentMinusTypeId() != 0){ + $minusTemplateId = (int)$location->getMvAdjustmentMinusTypeId(); + $template = $this->_adjustmentFactory->create(); + $this->_adjustmentResource->load($template, $minusTemplateId); + $adjustmentMinusMvId = $template->getMegaventoryId(); } + } - $adjust = $mg_qty - $mv_qty; - - if ($adjust > 0) { - $row = [ - 'DocumentRowProductSKU' => $selected_product['sku'], - 'DocumentRowQuantity' => $adjust, - 'DocumentRowUnitPriceWithoutTaxOrDiscount' => isset($selected_product['cost']) ? $selected_product['cost'] : '0' - ]; - - $documentDetailsAdjsPlus[] = $row; - } elseif ($adjust < 0) { - $row = [ - 'DocumentRowProductSKU' => $selected_product['sku'], - 'DocumentRowQuantity' => $adjust * (-1), - 'DocumentRowUnitPriceWithoutTaxOrDiscount' => isset($selected_product['cost']) ? $selected_product['cost'] : '0' + foreach ($selected_products_to_sync_stock as $selected_product) { + if (!empty($selected_product['mv_product_id']) && + (false !== $selected_product['mv_product_id']) && + (null !== $selected_product['mv_product_id'])) { + $filter = [ + 'AndOr' => 'Or', + 'FieldName' => 'productID', + 'SearchOperator' => 'Equals', + 'SearchValue' => $selected_product['mv_product_id'], ]; - $documentDetailsAdjsMinus[] = $row; - } else { - continue; + array_push($filters, $filter); } } - $action = 'Insert'; - - if (0 < count($documentDetailsAdjsPlus)) { - $mv_document_plus = [ - 'DocumentTypeId' => -99, - 'DocumentSupplierClientID' => -1, - 'DocumentComments' => 'This is the initial stock document that was created based on available quantity for the following products', - 'DocumentDetails' => $documentDetailsAdjsPlus, - 'DocumentStatus' => 'Pending', - ]; - - $document_update = [ - 'APIKEY' => $this->APIKEY, - 'mvDocument' => $mv_document_plus, - 'mvRecordAction' => $action + // call to get stock information for ids. + if (count($filters) > 0) { + $stock_get_body = [ + 'APIKEY' => $this->APIKEY, + 'InventoryLocationID' => $locationFilter, + 'Filters' => $filters, ]; + $inventoryLocationsStock = $this->_mvHelper->makeJsonRequest($stock_get_body, 'InventoryLocationStockGet'); - $resultsAdjsPlus = $this->_mvHelper->makeJsonRequest($document_update, 'DocumentUpdate'); - $errorCodeAdjsPlus = $resultsAdjsPlus['ResponseStatus']['ErrorCode']; - - if ('0' !== $errorCodeAdjsPlus) { + $errorCode = $inventoryLocationsStock['ResponseStatus']['ErrorCode']; + if ($errorCode != 0) { $event = [ - 'code' => 'Adjustment Plus Creation Failed', + 'code' => 'Inventory Location Stock Get', 'result' => 'fail', 'magento_id' => 0, 'return_entity' => '0', - 'details' => $resultsAdjsPlus['ResponseStatus']['Message'], + 'details' => $inventoryLocationsStock['ResponseStatus']['Message'], 'data' => '' ]; $this->_mvHelper->log($event); + + $results = [ + 'value' => 'Error', + 'message' => 'There has been an error, Check Megaventory logs.', + 'startingIndex' => $startingIndex + ]; + return $results; } - } - if (0 < count($documentDetailsAdjsMinus)) { - $mv_document_minus = [ - 'DocumentTypeId' => -98, - 'DocumentSupplierClientID' => -1, - 'DocumentComments' => 'This is the initial stock document that was created based on available quantity for the following products', - 'DocumentDetails' => $documentDetailsAdjsMinus, - 'DocumentStatus' => 'Pending', - ]; + $mvProductStockList = $inventoryLocationsStock['mvProductStockList']; - $document_update = [ - 'APIKEY' => $this->APIKEY, - 'mvDocument' => $mv_document_minus, - 'mvRecordAction' => $action - ]; + foreach ($selected_products_to_sync_stock as $selected_product) { + //ignore products which are not synchronized + if (empty($selected_product['mv_product_id'])) { + continue; + } - $resultsAdjsMinus = $this->_mvHelper->makeJsonRequest($document_update, 'DocumentUpdate'); - $errorCodeAdjsMinus = $resultsAdjsMinus['ResponseStatus']['ErrorCode']; + $index = array_search((int) $selected_product['mv_product_id'], array_column($mvProductStockList, 'productID'), true); - if ('0' !== $errorCodeAdjsMinus) { - $event = [ - 'code' => 'Adjustment Minus Creation Failed', - 'result' => 'fail', - 'magento_id' => 0, - 'return_entity' => '0', - 'details' => $resultsAdjsPlus['ResponseStatus']['Message'], - 'data' => '' + $mv_qty = 0; + if (false !== $index) { + $mv_qty = $mvProductStockList[$index]['StockOnHandTotal']; + } + + $mg_qty = 0; + if (isset($selected_product['qty']) && $selected_product['qty'] > 0) { + $mg_qty = $selected_product['qty']; + } + + $adjust = $mg_qty - $mv_qty; + + if ($adjust > 0) { + $row = [ + 'DocumentRowProductSKU' => $selected_product['sku'], + 'DocumentRowQuantity' => $adjust, + 'DocumentRowUnitPriceWithoutTaxOrDiscount' => '0' + ]; + + if(!empty($purchasePriceAttributeCode) && isset($selected_product[$purchasePriceAttributeCode])){ + $row['DocumentRowUnitPriceWithoutTaxOrDiscount'] = $selected_product[$purchasePriceAttributeCode]; + } + + $documentDetailsAdjsPlus[] = $row; + } elseif ($adjust < 0) { + $row = [ + 'DocumentRowProductSKU' => $selected_product['sku'], + 'DocumentRowQuantity' => $adjust * (-1), + 'DocumentRowUnitPriceWithoutTaxOrDiscount' => '0' + ]; + + if(!empty($purchasePriceAttributeCode) && isset($selected_product[$purchasePriceAttributeCode])){ + $row['DocumentRowUnitPriceWithoutTaxOrDiscount'] = $selected_product[$purchasePriceAttributeCode]; + } + + $documentDetailsAdjsMinus[] = $row; + + } else { + continue; + } + } + + $action = 'Insert'; + + if (0 < count($documentDetailsAdjsPlus)) { + $comment = 'This is a stock document that was created based on available quantity'; + if (isset($source) && ($docStatus == 'Pending')) { + $comment .= ' and based on the stock of inventory location '.$this->_inventoriesLoader->create()->load($inventoryMvId, 'megaventory_id')->getName(); + } + $comment .= ' for the following products.'; + $mv_document_plus = [ + 'DocumentTypeId' => $adjustmentPlusMvId, + 'DocumentSupplierClientID' => self::INTERNAL_SUPPLIER_CLIENT_FOR_ADJUSTMENTS, + 'DocumentComments' => $comment, + 'DocumentDetails' => $documentDetailsAdjsPlus, + 'DocumentStatus' => $docStatus, ]; - $this->_mvHelper->log($event); + + if($docStatus == 'Verified'){ + $mv_document_plus['DocumentInventoryLocationID'] = $location->getMegaventoryId(); + } + + $document_update = [ + 'APIKEY' => $this->APIKEY, + 'mvDocument' => $mv_document_plus, + 'mvRecordAction' => $action + ]; + + $resultsAdjsPlus = $this->_mvHelper->makeJsonRequest($document_update, 'DocumentUpdate'); + $errorCodeAdjsPlus = $resultsAdjsPlus['ResponseStatus']['ErrorCode']; + + if ('0' !== $errorCodeAdjsPlus) { + $event = [ + 'code' => 'Adjustment Plus Creation Failed', + 'result' => 'fail', + 'magento_id' => 0, + 'return_entity' => '0', + 'details' => $resultsAdjsPlus['ResponseStatus']['Message'], + 'data' => '' + ]; + $this->_mvHelper->log($event); + } else { + $adjMade = true; + } + } + + if (0 < count($documentDetailsAdjsMinus)) { + $comment = 'This is a stock document that was created based on available quantity'; + if(isset($source) && ($docStatus == 'Pending')){ + $comment .= ' and based on the stock of inventory location '.$this->_inventoriesLoader->create()->load($inventoryMvId,'megaventory_id')->getName(); + } + $comment .= ' for the following products.'; + $mv_document_minus = [ + 'DocumentTypeId' => $adjustmentMinusMvId, + 'DocumentSupplierClientID' => self::INTERNAL_SUPPLIER_CLIENT_FOR_ADJUSTMENTS, + 'DocumentComments' => $comment, + 'DocumentDetails' => $documentDetailsAdjsMinus, + 'DocumentStatus' => $docStatus, + ]; + + if($docStatus == 'Verified'){ + $mv_document_minus['DocumentInventoryLocationID'] = $location->getMegaventoryId(); + } + + $document_update = [ + 'APIKEY' => $this->APIKEY, + 'mvDocument' => $mv_document_minus, + 'mvRecordAction' => $action + ]; + + $resultsAdjsMinus = $this->_mvHelper->makeJsonRequest($document_update, 'DocumentUpdate'); + $errorCodeAdjsMinus = $resultsAdjsMinus['ResponseStatus']['ErrorCode']; + + if ('0' !== $errorCodeAdjsMinus) { + $event = [ + 'code' => 'Adjustment Minus Creation Failed', + 'result' => 'fail', + 'magento_id' => 0, + 'return_entity' => '0', + 'details' => $resultsAdjsMinus['ResponseStatus']['Message'], + 'data' => '' + ]; + $this->_mvHelper->log($event); + } else { + $adjMade = true; + } } } @@ -1437,7 +1487,8 @@ public function exportStock($inventoryMvId, $startingIndex, \Magento\Framework\A $results = [ 'value' => 'Continue', 'message' => '', - 'startingIndex' => $startingIndex + 'startingIndex' => $startingIndex, + 'adjMade'=>$adjMade ]; return $results; } diff --git a/Helper/Taxes.php b/Helper/Taxes.php index 47aa340..0c579eb 100644 --- a/Helper/Taxes.php +++ b/Helper/Taxes.php @@ -20,7 +20,6 @@ class Taxes extends \Magento\Framework\App\Helper\AbstractHelper protected $logger; protected $mvLogFactory; - public function __construct( \Magento\Framework\App\Helper\Context $context, Data $mvHelper, @@ -66,7 +65,6 @@ public function synchronizeTaxes($sendProgress = true) $i = 0; - $connection = $this->_resource->getConnection(); $tableName = $this->_resource->getTableName('megaventory_taxes'); @@ -139,7 +137,6 @@ private function updateTax($tax, $mvTax) $tax->save(); } - private function checkIfTaxExists($mvTax) { $tax = $this->_taxesLoader->create()->load($mvTax['TaxID'], 'megaventory_id'); diff --git a/Model/AdjustmentTemplate.php b/Model/AdjustmentTemplate.php new file mode 100644 index 0000000..7fcd629 --- /dev/null +++ b/Model/AdjustmentTemplate.php @@ -0,0 +1,31 @@ +_init('Mv\Megaventory\Model\ResourceModel\AdjustmentTemplate'); + } + + /** + * Return unique ID(s) for each object in system + * + * @return array + */ + public function getIdentities() + { + return [self::CACHE_TAG . '_' . $this->getId()]; + } +} \ No newline at end of file diff --git a/Model/ApiAdapter/DocumentTypeAdapter.php b/Model/ApiAdapter/DocumentTypeAdapter.php new file mode 100644 index 0000000..20a60cc --- /dev/null +++ b/Model/ApiAdapter/DocumentTypeAdapter.php @@ -0,0 +1,277 @@ +_mappings = ['SalesOrder'=> + [ + "DocumentTypeID" => "megaventory_id", + "DocumentTypeAbbreviation" => "shortname", + "DocumentTypeDescription" => "name" + ], + 'Adjustment'=> + [ + "DocumentTypeID" => "megaventory_id", + "DocumentTypeAbbreviation" => "shortname", + "DocumentTypeDescription" => "name", + 'DocumentTypeStockChange'=> "stock_change" + ] + ]; + } + + protected function initializeFilters(){ + $this->_filters = ['SalesOrder'=> + [ + 'FieldName'=>'IsSalesOrder', + 'SearchOperator'=>'Equals', + 'SearchValue'=>true + ], + 'Adjustment'=>[ + [ + 'FieldName'=>'IsAdjustment', + 'SearchOperator'=>'Equals', + 'SearchValue'=>true + ] + ] + ]; + } + + protected function getMappings($type){ + return $this->_mappings[$type]; + } + + protected function getFilters($type){ + return $this->_filters[$type]; + } + + protected function getAllWebsiteIds(){ + $result = []; + $websites = $this->_storeManager->getWebsites(); + foreach($websites as $website){ + $result[] = $website->getId(); + } + return $result; + } + + public function __construct( + \Mv\Megaventory\Model\DocumentTypeFactory $documentTypeFactory, + \Mv\Megaventory\Model\ResourceModel\DocumentType $documentTypeResource, + \Mv\Megaventory\Model\ResourceModel\DocumentType\CollectionFactory $documentTypeCollectionFactory, + \Mv\Megaventory\Helper\Data $mvHelper, + \Mv\Megaventory\Model\AdjustmentTemplateFactory $adjustmentTemplateFactory, + \Mv\Megaventory\Model\ResourceModel\AdjustmentTemplate\CollectionFactory $adjustmentTemplateCollectionFactory, + ResourceModelAdjustmentTemplate $adjustmentTemplateResource, + StoreManagerInterface $storeManager + ) + { + $this->_documentTypeFactory = $documentTypeFactory; + $this->_documentTypeResource = $documentTypeResource; + $this->_documentTypeCollectionFactory = $documentTypeCollectionFactory; + $this->_adjustmentTemplateFactory = $adjustmentTemplateFactory; + $this->_adjustmentTemplateResource = $adjustmentTemplateResource; + $this->_adjustmentTemplateCollectionFactory = $adjustmentTemplateCollectionFactory; + $this->_mvHelper = $mvHelper; + $this->_storeManager = $storeManager; + $this->initializeFilters(); + $this->initializeMappings(); + } + + public function convertApiDataToModelData($apiData, $type){ + $data = []; + + $mappings = $this->getMappings($type); + + foreach($mappings as $apiDataField => $modelField){ + $data[$modelField] = $apiData[$apiDataField]; + if(($type == 'Adjustment') && ($apiDataField == 'DocumentTypeStockChange')){ + $data[$modelField] = ($apiData[$apiDataField] == 'Positive') ? 1 : -1; + } + } + + return $data; + } + + public function createOrUpdateDocumentType($data){ + $currentModel = $this->_documentTypeFactory->create(); + $this->_documentTypeResource->load($currentModel, $data['megaventory_id'], 'megaventory_id'); + if((null !== $currentModel->getId()) && ($currentModel->getId() > 0)){ + foreach($data as $field => $value){ + $currentModel->setData($field, $value); + } + } + else{ + $currentModel->setData($data); + } + + $this->_documentTypeResource->save($currentModel); + + return ($currentModel->getMegaventoryId() !== null); + } + + public function createOrUpdateAdjustmentTemplate($data){ + $currentModel = $this->_adjustmentTemplateFactory->create(); + $this->_adjustmentTemplateResource->load($currentModel, $data['megaventory_id'], 'megaventory_id'); + if((null !== $currentModel->getId()) && ($currentModel->getId() > 0)){ + foreach($data as $field => $value){ + $currentModel->setData($field, $value); + } + } + else{ + $currentModel->setData($data); + } + + $this->_adjustmentTemplateResource->save($currentModel); + + return ($currentModel->getMegaventoryId() !== null); + } + + protected function deleteTypesNotExistingInMv(){ + $action = 'DocumentTypeGet'; + $apiParams = [ + 'APIKEY' => $this->_mvHelper->getApiKey(), + ]; + + $mvTemplates = $this->_documentTypeCollectionFactory->create(); + + foreach($mvTemplates as $documentTemplate){ + $apiParams['Filters'] = [ + [ + 'FieldName'=>'DocumentTypeID', + 'SearchOperator'=>'Equals', + 'SearchValue'=>$documentTemplate->getMegaventoryId() + ] + ]; + + $result = $this->_mvHelper->makeJsonRequest($apiParams, $action); + + if(array_key_exists('mvDocumentTypes', $result) && count($result['mvDocumentTypes']) == 0){ + $this->_documentTypeResource->delete($documentTemplate); + } + } + } + + protected function deleteAdjustmentsNotExistingInMv(){ + $action = 'DocumentTypeGet'; + $apiParams = [ + 'APIKEY' => $this->_mvHelper->getApiKey(), + ]; + + $mvTemplates = $this->_adjustmentTemplateCollectionFactory->create(); + + foreach($mvTemplates as $adjustmentTemplate){ + $apiParams['Filters'] = [ + [ + 'FieldName'=>'DocumentTypeID', + 'SearchOperator'=>'Equals', + 'SearchValue'=>$adjustmentTemplate->getMegaventoryId() + ] + ]; + + $result = $this->_mvHelper->makeJsonRequest($apiParams, $action); + + if(array_key_exists('mvDocumentTypes', $result) && count($result['mvDocumentTypes']) == 0){ + $this->_adjustmentTemplateResource->delete($adjustmentTemplate); + } + } + } + + public function reloadDocumentTypesFromApi($resetWebsites = false){ + $filters = $this->getFilters('SalesOrder'); + + $apiParams = [ + 'APIKEY' => $this->_mvHelper->getApiKey() + ]; + + if(count($filters) > 0){ + $apiParams['Filters'] = $filters; + } + $action = 'DocumentTypeGet'; + + $data = $this->_mvHelper->makeJsonRequest($apiParams, $action); + + $errors = false; + + foreach($data['mvDocumentTypes'] as $documentType){ + $modelData = $this->convertApiDataToModelData($documentType, 'SalesOrder'); + if($resetWebsites){ + if(($modelData['shortname'] != 'SO')){ + $modelData['magento_website_ids'] = ''; + } + else{ + $modelData['magento_website_ids'] = implode(',', $this->getAllWebsiteIds()); + } + } + $isImported = $this->createOrUpdateDocumentType($modelData); + if(!$isImported){ + $event = [ + 'code' => $action, + 'result' => 'order template import failed', + 'magento_id' => '0', + 'return_entity' => '0', + 'details' => 'order template with abbreviation '. $data['DocumentTypeAbbreviation'] . ' has not been imported.', + 'data' => json_encode($data) + ]; + $this->_mvHelper->log($event); + $errors = true; + } + } + $this->deleteTypesNotExistingInMv(); + return $errors; + } + + public function reloadAdjustmentTemplatesFromApi(){ + $filters = $this->getFilters('Adjustment'); + + $apiParams = [ + 'APIKEY' => $this->_mvHelper->getApiKey() + ]; + + if(count($filters) > 0){ + $apiParams['Filters'] = $filters; + } + $action = 'DocumentTypeGet'; + + $data = $this->_mvHelper->makeJsonRequest($apiParams, $action); + + $errors = false; + + foreach($data['mvDocumentTypes'] as $documentType){ + $modelData = $this->convertApiDataToModelData($documentType, 'Adjustment'); + $isImported = $this->createOrUpdateAdjustmentTemplate($modelData); + if(!$isImported){ + $event = [ + 'code' => $action, + 'result' => 'adjustment template import failed', + 'magento_id' => '0', + 'return_entity' => '0', + 'details' => 'adjustment template with abbreviation '. $data['DocumentTypeAbbreviation'] . ' has not been imported.', + 'data' => json_encode($data) + ]; + $this->_mvHelper->log($event); + $errors = true; + } + } + $this->deleteAdjustmentsNotExistingInMv(); + return $errors; + } +} \ No newline at end of file diff --git a/Model/Config/Source/AdjustmentMinusTemplates.php b/Model/Config/Source/AdjustmentMinusTemplates.php new file mode 100644 index 0000000..e93393c --- /dev/null +++ b/Model/Config/Source/AdjustmentMinusTemplates.php @@ -0,0 +1,29 @@ +_templateCollectionFactory = $adjustmentTemplateCollectionFactory; + } + + public function toOptionArray() + { + $templates = $this->_templateCollectionFactory->create()->addFieldToFilter('stock_change',-1); + $options = []; + + foreach($templates as $template){ + $options[] = ['label'=>$template->getName(),'value'=>$template->getId()]; + } + + return $options; + } +} \ No newline at end of file diff --git a/Model/Config/Source/AdjustmentPlusTemplates.php b/Model/Config/Source/AdjustmentPlusTemplates.php new file mode 100644 index 0000000..4c706de --- /dev/null +++ b/Model/Config/Source/AdjustmentPlusTemplates.php @@ -0,0 +1,29 @@ +_templateCollectionFactory = $adjustmentTemplateCollectionFactory; + } + + public function toOptionArray() + { + $templates = $this->_templateCollectionFactory->create()->addFieldToFilter('stock_change',1); + $options = []; + + foreach($templates as $template){ + $options[] = ['label'=>$template->getName(),'value'=>$template->getId()]; + } + + return $options; + } +} \ No newline at end of file diff --git a/Model/Config/Source/AvailableInventorySources.php b/Model/Config/Source/AvailableInventorySources.php new file mode 100644 index 0000000..6eeb8bb --- /dev/null +++ b/Model/Config/Source/AvailableInventorySources.php @@ -0,0 +1,58 @@ +_sourceCollection = $sourceCollection; + $this->_inventoryCollectionFactory = $inventoriesCollectionFactory; + $this->_request = $requestInterface; + } + + public function toOptionArray() + { + $currentInventoryId = $this->_request->getParam('id'); + $sources = $this->getAvailableSources($currentInventoryId); + $options = []; + + $inventory = $this->_inventoryCollectionFactory->create()->addFieldToFilter('id',$currentInventoryId)->getFirstItem(); + if($inventory->getStockSourceCode() == null){ + $options[] = [ + 'label'=>' ', + 'value'=>'' + ]; + } + + foreach($sources as $source){ + $options[] = ['label'=>$source->getName(),'value'=>$source->getSourceCode()]; + } + + return $options; + } + + private function getAvailableSources($inventoryId = -1){ + $inventoriesWithSource = $this->_inventoryCollectionFactory->create() + ->addFieldToSelect('stock_source_code') + ->addFieldToFilter('stock_source_code', ['notnull'=>true]) + ->addFieldToFilter('id',['neq'=>$inventoryId]); + $allocatedSources = array_values($inventoriesWithSource->toArray()['items']); + $sources = $this->_sourceCollection->create(); + if (count($allocatedSources) > 0) { + $sources->addFieldToFilter('source_code', ['nin'=>$allocatedSources]); + } + return $sources; + } +} \ No newline at end of file diff --git a/Model/Config/Source/SourceSelectionAlgorithmConfigSource.php b/Model/Config/Source/SourceSelectionAlgorithmConfigSource.php new file mode 100644 index 0000000..ad0134f --- /dev/null +++ b/Model/Config/Source/SourceSelectionAlgorithmConfigSource.php @@ -0,0 +1,36 @@ +_sourceSelectionAlgorithmListInterface = $sourceSelectionInterface; + $this->_scopeConfig = $scopeConfig; + } + + public function toOptionArray() + { + $currentCode = $this->_scopeConfig->getValue('megaventory/orders/source_selection_algorithm_code'); + $options = []; + + $algorithmList = $this->_sourceSelectionAlgorithmListInterface->execute(); + + foreach ($algorithmList as $algorithm) { + $isSelected = ($algorithm->getCode() == $currentCode); + $options[] = [ + 'value'=>$algorithm->getCode(), + 'label'=>$algorithm->getTitle(), + 'selected'=>$isSelected + ]; + } + + return $options; + } +} diff --git a/Model/Config/Source/Websites.php b/Model/Config/Source/Websites.php new file mode 100644 index 0000000..12afa43 --- /dev/null +++ b/Model/Config/Source/Websites.php @@ -0,0 +1,33 @@ +_storeManager = $storeManager; + } + + public function toOptionArray() + { + $websites = $this->_storeManager->getWebsites(true); + + $options = []; + + foreach($websites as $website){ + if($website->getCode() != 'admin'){ + $options[] = ['label'=>$website->getName(),'value'=>$website->getId()]; + } + } + + return $options; + } +} \ No newline at end of file diff --git a/Model/DocumentType.php b/Model/DocumentType.php new file mode 100644 index 0000000..e18ae4f --- /dev/null +++ b/Model/DocumentType.php @@ -0,0 +1,31 @@ +_init('Mv\Megaventory\Model\ResourceModel\DocumentType'); + } + + /** + * Return unique ID(s) for each object in system + * + * @return array + */ + public function getIdentities() + { + return [self::CACHE_TAG . '_' . $this->getId()]; + } +} \ No newline at end of file diff --git a/Model/Inventories.php b/Model/Inventories.php index 631dd8a..f2ec864 100644 --- a/Model/Inventories.php +++ b/Model/Inventories.php @@ -29,9 +29,9 @@ public function getIdentities() return [self::CACHE_TAG . '_' . $this->getId()]; } - public function loadDefault() + public function loadBySource($sourceCode) { - return $this->load('1', 'isdefault'); + return $this->load($sourceCode, 'stock_source_code'); } public function loadByName($shortName) diff --git a/Model/Provider/DocumentType/DataProvider.php b/Model/Provider/DocumentType/DataProvider.php new file mode 100644 index 0000000..16dc58e --- /dev/null +++ b/Model/Provider/DocumentType/DataProvider.php @@ -0,0 +1,34 @@ +collection = $collection; + parent::__construct($name, $primaryFieldName, $requestFieldName, $meta, $data); + } + + public function getData() + { + if (isset($this->loadedData)) { + return $this->loadedData; + } + + $items = $this->collection->getItems(); + $this->loadedData = array(); + foreach ($items as $item) { + $this->loadedData[$item->getId()]['website_associations_general']['website_associations'] = $item->getData(); + } + + + return $this->loadedData; + } +} \ No newline at end of file diff --git a/Model/Provider/InventoryAdjustment/DataProvider.php b/Model/Provider/InventoryAdjustment/DataProvider.php new file mode 100644 index 0000000..a49dce0 --- /dev/null +++ b/Model/Provider/InventoryAdjustment/DataProvider.php @@ -0,0 +1,38 @@ +collection = $collection; + parent::__construct($name, $primaryFieldName, $requestFieldName, $meta, $data); + } + + public function getData() + { + if (isset($this->loadedData)) { + return $this->loadedData; + } + + $items = $this->collection->getItems(); + $this->loadedData = array(); + foreach ($items as $item) { + $this->loadedData[$item->getId()]['inventory_adjustment_plus_templates_associations'] = $item->getData(); + $this->loadedData[$item->getId()]['inventory_adjustment_minus_templates_associations'] = $item->getData(); + $this->loadedData[$item->getId()]['inventory_source_associations'] = $item->getData(); + $this->loadedData[$item->getId()]['inventory_adjustment_document_status'] = $item->getData(); + } + + + return $this->loadedData; + } +} \ No newline at end of file diff --git a/Model/ResourceModel/AdjustmentTemplate.php b/Model/ResourceModel/AdjustmentTemplate.php new file mode 100644 index 0000000..bb99e62 --- /dev/null +++ b/Model/ResourceModel/AdjustmentTemplate.php @@ -0,0 +1,12 @@ +_init('megaventory_adjustment_templates', 'id'); + } +} \ No newline at end of file diff --git a/Model/ResourceModel/AdjustmentTemplate/Collection.php b/Model/ResourceModel/AdjustmentTemplate/Collection.php new file mode 100644 index 0000000..7eb2eff --- /dev/null +++ b/Model/ResourceModel/AdjustmentTemplate/Collection.php @@ -0,0 +1,15 @@ +_init('Mv\Megaventory\Model\AdjustmentTemplate', 'Mv\Megaventory\Model\ResourceModel\AdjustmentTemplate'); + } +} \ No newline at end of file diff --git a/Model/ResourceModel/DocumentType.php b/Model/ResourceModel/DocumentType.php new file mode 100644 index 0000000..4884def --- /dev/null +++ b/Model/ResourceModel/DocumentType.php @@ -0,0 +1,12 @@ +_init('megaventory_order_templates', 'id'); + } +} \ No newline at end of file diff --git a/Model/ResourceModel/DocumentType/Collection.php b/Model/ResourceModel/DocumentType/Collection.php new file mode 100644 index 0000000..74d92d1 --- /dev/null +++ b/Model/ResourceModel/DocumentType/Collection.php @@ -0,0 +1,15 @@ +_init('Mv\Megaventory\Model\DocumentType', 'Mv\Megaventory\Model\ResourceModel\DocumentType'); + } +} \ No newline at end of file diff --git a/Model/ResourceModel/Log/Grid/Collection.php b/Model/ResourceModel/Log/Grid/Collection.php index 61e4a64..5c99133 100644 --- a/Model/ResourceModel/Log/Grid/Collection.php +++ b/Model/ResourceModel/Log/Grid/Collection.php @@ -14,7 +14,7 @@ public function __construct( FetchStrategy $fetchStrategy, EventManager $eventManager, $mainTable = 'megaventory_log', - $resourceModel = '\Mv\Megaventory\Model\ResourceModel\Log' + $resourceModel = \Mv\Megaventory\Model\ResourceModel\Log::class ) { parent::__construct($entityFactory, $logger, $fetchStrategy, $eventManager, $mainTable, $resourceModel); } diff --git a/Model/Services/MegaventoryService.php b/Model/Services/MegaventoryService.php index e99a465..fef7da5 100644 --- a/Model/Services/MegaventoryService.php +++ b/Model/Services/MegaventoryService.php @@ -2,6 +2,8 @@ namespace Mv\Megaventory\Model\Services; +use Magento\Framework\Event\ManagerInterface; + class MegaventoryService { const STOCK_CONSUME_LIMIT = 50; @@ -14,11 +16,16 @@ class MegaventoryService protected $_inventoriesHelper; protected $_productStocksFactory; protected $_stockItemFactory; + protected $_sourceStockItemCollection; + protected $_sourceItemSave; + protected $_sourceLowStockItemInterface; + protected $_sourceStockItemInterface; protected $_orderApi; protected $_orderFactory; protected $_orderStatusHistoryFactory; protected $_convertOrder; + protected $_mvOrderHelper; protected $_shipmentRepository; protected $_shipmentFactory; @@ -35,11 +42,14 @@ class MegaventoryService protected $_logger; protected $mvLogFactory; protected $_resource; + + protected $_eventManager; public function __construct( \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig, \Mv\Megaventory\Helper\Data $mvHelper, \Mv\Megaventory\Helper\Common $commonHelper, + \Mv\Megaventory\Helper\Order $orderHelper, \Magento\Catalog\Model\ProductFactory $productFactory, \Mv\Megaventory\Model\InventoriesFactory $inventoriesFactory, \Mv\Megaventory\Helper\Inventories $inventoriesHelper, @@ -48,6 +58,8 @@ public function __construct( \Magento\Sales\Api\OrderManagementInterface $orderApi, \Magento\Sales\Model\OrderFactory $orderFactory, \Magento\Sales\Model\Convert\Order $convertOrder, + \Magento\Inventory\Model\ResourceModel\SourceItem\CollectionFactory $sourceCollection, + \Magento\InventoryApi\Api\SourceItemsSaveInterface $sourceItemSave, \Magento\Sales\Model\Order\Status\HistoryFactory $orderStatusHistoryFactory, \Magento\Sales\Model\Service\InvoiceService $invoiceService, \Magento\Sales\Model\Order\InvoiceRepository $invoiceRepository, @@ -60,7 +72,10 @@ public function __construct( \Magento\Framework\DB\Transaction $transaction, \Mv\Megaventory\Model\LogFactory $mvLogFactory, \Mv\Megaventory\Logger\Logger $logger, - \Magento\Framework\App\ResourceConnection $resource + \Magento\Framework\App\ResourceConnection $resource, + \Magento\InventoryLowQuantityNotificationApi\Api\GetSourceItemConfigurationInterface $sourceItemConfig, + \Magento\InventoryApi\Api\Data\SourceItemInterfaceFactory $sourceStockItemInterface, + ManagerInterface $eventManager ) { $this->_scopeConfig = $scopeConfig; @@ -71,11 +86,17 @@ public function __construct( $this->_inventoriesHelper = $inventoriesHelper; $this->_productStocksFactory = $productStocksFactory; $this->_stockItemFactory = $stockItemFactory; + $this->_sourceStockItemCollection = $sourceCollection; + $this->_sourceItemSave = $sourceItemSave; + $this->_sourceLowStockItemInterface = $sourceItemConfig; + + $this->_sourceStockItemInterface = $sourceStockItemInterface; $this->_orderApi = $orderApi; $this->_orderFactory = $orderFactory; $this->_orderStatusHistoryFactory = $orderStatusHistoryFactory; $this->_convertOrder = $convertOrder; + $this->_mvOrderHelper = $orderHelper; $this->_shipmentRepository = $shipmentRepository; $this->_shipmentFactory = $shipmentFactory; @@ -92,6 +113,7 @@ public function __construct( $this->_mvLogFactory = $mvLogFactory; $this->_logger = $logger; $this->_resource = $resource; + $this->_eventManager = $eventManager; } public function applyPendingUpdates() @@ -117,10 +139,8 @@ public function applyPendingUpdates() ] ]; - $json_result = $this->_mvHelper->makeJsonRequest($data, 'IntegrationUpdateGet', 0); - $errorCode = $json_result['ResponseStatus']['ErrorCode']; if ($errorCode != '0') { $this->_logger->info('error'); @@ -243,26 +263,37 @@ public function applyPendingUpdates() $qtyShipped = $orderItem->getQtyToShip(); // Create shipment item with qty - $shipmentItem = $this->_convertOrder->itemToShipmentItem($orderItem)->setQty($qtyShipped); + $shipmentItem = $this->_convertOrder->itemToShipmentItem($orderItem) + ->setQty($qtyShipped); // Add shipment item to shipment $newShipment->addItem($shipmentItem); } - + $newShipment->register(); $newShipment->getOrder()->setIsInProcess(true); - $this->_transaction + + $sourceCode = $this->_inventoriesFactory->create() + ->load($order->getMvInventoryId())->getStockSourceCode(); + + $newShipment->getExtensionAttributes()->setSourceCode($sourceCode); + $error = false; + + try { + $this->_transaction ->addObject($newShipment) ->addObject($newShipment->getOrder()) ->save(); - - if ($extraShippingInformation['Notify'] == '1') {//then also send a shipment email - $this->_shipmentSender->send($newShipment); + } catch (\Exception $e) { + $error = true; + $this->_logger->debug('Exception message: '.$e->getMessage()); } - $result = $newShipment->getIncrementId(); - if ($result) { + if (!$error) { $this->deleteUpdate($mvIntegrationUpdateId); + if ($extraShippingInformation['Notify'] == '1') {//then also send a shipment email + $this->_shipmentSender->send($newShipment); + } } else { if ($tries > 10) { $this->deleteUpdate($mvIntegrationUpdateId); @@ -373,7 +404,6 @@ public function applyPendingUpdates() $result = $this->updateMegaventoryStock($entityIDs, $inventoryValues, $mvIntegrationUpdateId); - if ($result) { $this->deleteUpdate($mvIntegrationUpdateId); } else { @@ -407,7 +437,6 @@ private function deleteUpdate($mvIntegrationUpdateId) 'IntegrationUpdateIDToDelete' => $mvIntegrationUpdateId ]; - $json_result = $this->_mvHelper->makeJsonRequest($data, 'IntegrationUpdateDelete', 0); } @@ -428,6 +457,7 @@ private function updateIntegrationUpdate($mvIntegrationUpdate) public function updateMegaventoryStock($productSKUs, $inventoryValues, $integratiodId = 0) { + $configValue = $this->_scopeConfig->getValue('cataloginventory/options/can_subtract'); if (! $this->_commonHelper->isMegaventoryEnabled()) { return false; @@ -441,7 +471,6 @@ public function updateMegaventoryStock($productSKUs, $inventoryValues, $integrat $json = json_encode($inventoryValues); $inventoryValues = json_decode($json, true); - $totalStock = 0; $productIds = []; foreach ($productSKUs as $index => $productSKU) { if (empty($productSKU)) { @@ -472,8 +501,20 @@ public function updateMegaventoryStock($productSKUs, $inventoryValues, $integrat foreach ($productIds as $pId) { $productStockCollection = $this->_productStocksFactory->create()->loadProductstocks($pId); + + $sku = $this->_productFactory->create()->load($pId)->getSku(); + + $stockItem = $this->_stockItemFactory->create()->load($pId, 'product_id'); + + // Remove reserved quantities because it doubles the quantity removed from the saleable quantity of the product. + $connection = $this->_resource->getConnection(); + $tableName = $this->_resource->getTableName('inventory_reservation'); + + if (! $connection->isTableExists($tableName)) { + continue; + } + $connection->delete($tableName, ['sku = ?'=>$sku]); - $totalStock = 0; $totalAlertQuantity = 0; foreach ($productStockCollection as $key => $productStock) { $inventoryStock = $productStock ['stockqty']; @@ -487,28 +528,50 @@ public function updateMegaventoryStock($productSKUs, $inventoryValues, $integrat if ($inventory == false) { continue; } + + if (is_null($inventory->getStockSourceCode())) { + continue; + } - if ($inventory->getCounts_in_total_stock() == '1') { - $configValue = $this->_scopeConfig->getValue('cataloginventory/options/can_subtract'); - if ($configValue == '0') { // no decrease value when order is - // placed - $totalStock += $inventoryStock; - } else // decrease stock when order is placed - { - $totalStock += $inventoryStock - $inventoryNonShippedStock - $inventoryNonAllocatedWOStock; - } - - $totalAlertQuantity += $inventoryAlertQty; + $sourceItems = $this->_sourceStockItemCollection->create() + ->addFieldToFilter('source_code', $inventory->getStockSourceCode()) + ->addFieldToFilter('sku', $sku); + + if (count($sourceItems) > 0) { + $sourceItem = $sourceItems->getFirstItem(); + $notifyQty = $this->_sourceLowStockItemInterface->execute($inventory->getStockSourceCode(), $sku) + ->getNotifyStockQty(); + } else { + $sourceItem = $this->_sourceStockItemInterface->create(); + $sourceItem->setSku($sku); + $sourceItem->setSourceCode($inventory->getStockSourceCode()); + $notifyQty = 1; } - } - $stockItem = $this->_stockItemFactory->create()->load($pId, 'product_id'); - - $stockItem->setQty($totalStock); - if ($totalStock > $stockItem->getMinQty()) { - $stockItem->setData('is_in_stock', 1); - } + $qty = 0; + if ($configValue == '0') { //no decrease value when order is placed + $qty = $inventoryStock; + } else {//decrease stock when order is placed + $qty = $inventoryStock-$inventoryNonShippedStock-$inventoryNonAllocatedWOStock; + } + + $qty = ($qty > 0) ? $qty : 0; + + $isInStock = ($qty > $notifyQty) ? 1 : 0; + + $sourceItem->setStatus($isInStock); + $sourceItem->setQuantity($qty); + + $this->_sourceItemSave->execute([$sourceItem]); + + $data = ['status'=>$isInStock, 'qty'=>$qty, 'sku'=>$sku]; + + $this->_eventManager->dispatch('mv_megaventory_update_stock_after',$data); + + $totalAlertQuantity += $inventoryAlertQty; + } + //update notify quantity $useConfigNotify = $stockItem->getData('use_config_notify_stock_qty'); $configValue = $this->_scopeConfig->getValue('cataloginventory/item_options/notify_stock_qty'); @@ -530,31 +593,18 @@ public function updateMegaventoryStock($productSKUs, $inventoryValues, $integrat //end of notify quantity $stockItem->save(); - - // the salable qty is decreased when an order is placed. Based on order's qty. Assuming we have 10. - // if the order has 2 qty then the salable qty will be 8, but the product qty so far is 10. - // if we decrease the product qty then the salable qty will also be decreased. - // so the salable qty would be 6. - // https://github.com/magento/inventory/issues/2269#issuecomment-499479576 - $connection = $this->_resource->getConnection(); - $tableName = $this->_resource->getTableName('inventory_reservation'); - - if (! $connection->isTableExists($tableName)) { - continue; - } - - $sku = $this->_productFactory->create()->load($stockItem->getData('item_id'))->getSku(); - - $deleteReservations = 'delete FROM '.$tableName.' WHERE sku like '.'\''. $sku .'\''; - - $connection->query($deleteReservations); } return true; } - public function megaventoryAddTrack(\Magento\Sales\Model\Order\Shipment $shipment, $carrier, $title, $trackNumber, $notify) - { + public function megaventoryAddTrack( + \Magento\Sales\Model\Order\Shipment $shipment, + $carrier, + $title, + $trackNumber, + $notify + ) { if ($shipment) { $track = $this->_trackFactory->create(); diff --git a/Observer/Admin/LoginObserver.php b/Observer/Admin/LoginObserver.php index e80dad1..cad7e22 100644 --- a/Observer/Admin/LoginObserver.php +++ b/Observer/Admin/LoginObserver.php @@ -27,10 +27,6 @@ public function __construct( public function execute(\Magento\Framework\Event\Observer $observer) { - $event = $observer->getEvent(); - $user = $event->getUser(); - - $apikey = $this->_scopeConfig->getValue('megaventory/general/apikey'); $apiurl = $this->_scopeConfig->getValue('megaventory/general/apiurl'); diff --git a/Observer/Customer/SaveObserver.php b/Observer/Customer/SaveObserver.php index 25dbfbc..4001dbb 100644 --- a/Observer/Customer/SaveObserver.php +++ b/Observer/Customer/SaveObserver.php @@ -39,12 +39,6 @@ public function execute(\Magento\Framework\Event\Observer $observer) $result = $this->_mvCustomerHelper->addCustomer($customer); - /* if ($result == 0){ - $logUrl = $this->_backendUrl->getUrl("megaventory/log/index"); - $this->_messageManager->addError('Customer '.$customer->getId().' has not been updated in Megaventory. Please review Megaventory Log for details'); - return; - } */ - if (is_array($result)) { $undeleteUrl = $this->_backendUrl->getUrl("megaventory/index/undeleteEntity"); $this->_messageManager->addError('Customer '.$customer->getName().' is flagged as deleted in Megaventory. Presse here if you want to automatically undelete it'); diff --git a/Observer/Order/SaveObserver.php b/Observer/Order/SaveObserver.php index d522d5c..676bcc2 100644 --- a/Observer/Order/SaveObserver.php +++ b/Observer/Order/SaveObserver.php @@ -13,7 +13,7 @@ class SaveObserver implements ObserverInterface public function __construct( \Mv\Megaventory\Helper\Order $orderHelper, \Magento\Framework\Message\ManagerInterface $messageManager, - \Psr\Log\LoggerInterface $logger //log injection + \Psr\Log\LoggerInterface $logger ) { $this->_orderHelper = $orderHelper; @@ -23,7 +23,6 @@ public function __construct( public function execute(\Magento\Framework\Event\Observer $observer) { - //Observer execution code... $order = $observer->getEvent()->getOrder(); $quote = $observer->getEvent()->getQuote(); diff --git a/Observer/Product/ImportObserver.php b/Observer/Product/ImportObserver.php index f3b2a11..9a98049 100644 --- a/Observer/Product/ImportObserver.php +++ b/Observer/Product/ImportObserver.php @@ -15,7 +15,7 @@ public function __construct( \Mv\Megaventory\Helper\Product $mvProductHelper, \Magento\Framework\Message\ManagerInterface $messageManager, \Magento\Catalog\Model\ProductFactory $productLoader, - \Psr\Log\LoggerInterface $logger //log injection + \Psr\Log\LoggerInterface $logger ) { $this->_mvProductHelper = $mvProductHelper; $this->_messageManager = $messageManager; @@ -34,13 +34,13 @@ public function execute(\Magento\Framework\Event\Observer $observer) foreach ($newSku as $sku => $skuValues) { $productId = $skuValues['entity_id']; - $product = $this->_productLoader->create()->load((int)$productId); //Kudret: Fixed an assignment error + $product = $this->_productLoader->create()->load((int)$productId); if ($product->getId()) { $sku = $product->getSku(); $megaventoryId = $product->getData('mv_product_id'); - $startsWith = (\strpos($sku, 'bom_') === 0); //Check if SKU starts with the string 'bom_', strpos returns the position of the first occurrence of a part of text found on a string, so if strpos(,'bom_') returns 0 it means that the SKU starts with 'bom_' - if ($startsWith && empty($megaventoryId)) { //it is an insert of a bom and we should ignore + $startsWith = (\strpos($sku, 'bom_') === 0); + if ($startsWith && empty($megaventoryId)) { return; } diff --git a/Observer/Product/MassUpdateObserver.php b/Observer/Product/MassUpdateObserver.php index c737cdc..d94ae98 100644 --- a/Observer/Product/MassUpdateObserver.php +++ b/Observer/Product/MassUpdateObserver.php @@ -11,8 +11,12 @@ class MassUpdateObserver implements ObserverInterface private $_productLoader; protected $_logger; - public function __construct(\Mv\Megaventory\Helper\Product $mvProductHelper, \Magento\Framework\Message\ManagerInterface $messageManager, \Magento\Catalog\Model\ProductFactory $productLoader, \Psr\Log\LoggerInterface $logger) // log injection - { + public function __construct( + \Mv\Megaventory\Helper\Product $mvProductHelper, + \Magento\Framework\Message\ManagerInterface $messageManager, + \Magento\Catalog\Model\ProductFactory $productLoader, + \Psr\Log\LoggerInterface $logger // log injection + ) { $this->_mvProductHelper = $mvProductHelper; $this->_messageManager = $messageManager; $this->_productLoader = $productLoader; diff --git a/Observer/Product/SaveObserver.php b/Observer/Product/SaveObserver.php index 1b6238a..8c47b84 100644 --- a/Observer/Product/SaveObserver.php +++ b/Observer/Product/SaveObserver.php @@ -32,17 +32,13 @@ public function execute(\Magento\Framework\Event\Observer $observer) if (! $this->_commonHelper->isMegaventoryEnabled()) { return; } - - //Observer execution code... - //$productId = $observer->getEvent()->getProduct()->getId(); $product = $observer->getEvent()->getProduct(); if ($product != null) { - $result = -1; $result = $this->_mvProductHelper->addProduct($observer->getEvent()->getProduct()); - if ($result == 0) { + if ($result == \Mv\Megaventory\Helper\Product::RESULT_ERROR) { $logUrl = $this->_backendUrl->getUrl("megaventory/log/index"); - $this->_messageManager->addError('Product '.$product->getId().' did not updated in Megaventory. Please review Megaventory Log for details'); + $this->_messageManager->addError('Product '.$product->getId().' was not updated in Megaventory. Please review Megaventory Log for details'); } if (is_array($result)) { diff --git a/Setup/InstallData.php b/Setup/InstallData.php index e4fde16..4b23392 100644 --- a/Setup/InstallData.php +++ b/Setup/InstallData.php @@ -16,8 +16,10 @@ class InstallData implements InstallDataInterface { - public function __construct() + protected $_mvHelper; + public function __construct(\Mv\Megaventory\Helper\Data $mvHelper) { + $this->_mvHelper = $mvHelper; } /** @@ -28,15 +30,11 @@ public function __construct() */ public function install(ModuleDataSetupInterface $setup, ModuleContextInterface $context) { + $this->_mvHelper->resetMegaventoryData(); + $this->_mvHelper->deleteCredetials(); + $configTable = $setup->getTable('core_config_data'); - - /* delete from `{$installer->getTable('core_config_data')}` where path = 'cataloginventory/item_options/manage_stock'; - insert into `{$installer->getTable('core_config_data')}` (scope, scope_id, path, value) values ('default',0,'cataloginventory/item_options/manage_stock',1); - delete from `{$installer->getTable('core_config_data')}` where path = 'api/config/wsdl_cache_enabled'; - insert into `{$installer->getTable('core_config_data')}` (scope, scope_id, path, value) values ('default',0,'api/config/wsdl_cache_enabled',1); - delete from `{$installer->getTable('core_config_data')}` where path = 'api/config/compliance_wsi'; - insert into `{$installer->getTable('core_config_data')}` (scope, scope_id, path, value) values ('default',0,'api/config/compliance_wsi',0); */ - + $setup->getConnection()->delete( $configTable, ['path = ?' => 'cataloginventory/item_options/manage_stock'] @@ -44,17 +42,12 @@ public function install(ModuleDataSetupInterface $setup, ModuleContextInterface $setup->getConnection()->insert( $configTable, - ['scope' => 'default', 'scope_id' => '0', 'path' => 'cataloginventory/item_options/manage_stock', 'value' => '1'] + [ + 'scope' => 'default', + 'scope_id' => '0', + 'path' => 'cataloginventory/item_options/manage_stock', + 'value' => '1' + ] ); - - /* $setup->getConnection()->delete( - $configTable, - ['path = ?' => 'api/config/wsdl_cache_enabled'] - ); - - $setup->getConnection()->delete( - $configTable, - ['path = ?' => 'api/config/compliance_wsi'] - ); */ } } diff --git a/Setup/InstallSchema.php b/Setup/InstallSchema.php index 0280b82..d3e3e73 100644 --- a/Setup/InstallSchema.php +++ b/Setup/InstallSchema.php @@ -120,18 +120,32 @@ public function install(SchemaSetupInterface $setup, ModuleContextInterface $con 'Address' ) ->addColumn( - 'isdefault', + 'megaventory_id', \Magento\Framework\DB\Ddl\Table::TYPE_INTEGER, null, - ['unsigned' => true, 'nullable' => true ], - 'IsDefault' + [], + 'Megaventory Id' ) ->addColumn( - 'megaventory_id', + 'stock_source_code', + \Magento\Framework\DB\Ddl\Table::TYPE_TEXT, + 200, + ['nullable' => true, 'default' => null], + 'Magento Inventory Source' + ) + ->addColumn( + 'mv_adjustment_plus_type_id', \Magento\Framework\DB\Ddl\Table::TYPE_INTEGER, null, - [], - 'Megaventory Id' + ['nullable'=>true, 'default'=>null], + 'Megaventory Adjustment Plus Template ID' + ) + ->addColumn( + 'mv_adjustment_minus_type_id', + \Magento\Framework\DB\Ddl\Table::TYPE_INTEGER, + null, + ['nullable'=>true, 'default'=>null], + 'Megaventory Adjustment Minus Template ID' ) ->addColumn( 'counts_in_total_stock', @@ -139,6 +153,13 @@ public function install(SchemaSetupInterface $setup, ModuleContextInterface $con null, ['default' => 1], 'Counts In Total Stock' + ) + ->addColumn( + 'adjustment_doc_status', + \Magento\Framework\DB\Ddl\Table::TYPE_TEXT, + 100, + ['nullable' => false, 'default' => 'Pending'], + 'Issue Adjustment Document with this Status' ); $installer->getConnection()->createTable($table); @@ -425,6 +446,140 @@ public function install(SchemaSetupInterface $setup, ModuleContextInterface $con \Magento\Framework\DB\Ddl\Table::ACTION_CASCADE ); + $installer->getConnection()->createTable($table); + + $table = $installer->getConnection() + ->newTable($installer->getTable('megaventory_order_templates')) + ->addColumn( + 'id', + \Magento\Framework\DB\Ddl\Table::TYPE_INTEGER, + null, + ['identity' => true, 'unsigned' => true, 'nullable' => false, 'primary' => true], + 'ID' + ) + ->addColumn( + 'shortname', + \Magento\Framework\DB\Ddl\Table::TYPE_TEXT, + 20, + ['nullable' => true, 'default' => null], + 'Short Name' + ) + ->addColumn( + 'name', + \Magento\Framework\DB\Ddl\Table::TYPE_TEXT, + 50, + ['nullable' => true, 'default' => null], + 'Name' + ) + ->addColumn( + 'megaventory_id', + \Magento\Framework\DB\Ddl\Table::TYPE_INTEGER, + null, + [], + 'Megaventory ID' + ) + ->addColumn( + 'magento_website_ids', + \Magento\Framework\DB\Ddl\Table::TYPE_TEXT, + 500, + [], + 'Magento Websites' + ); + + $installer->getConnection()->createTable($table); + + $table = $installer->getConnection() + ->newTable($installer->getTable('megaventory_adjustment_templates')) + ->addColumn( + 'id', + \Magento\Framework\DB\Ddl\Table::TYPE_INTEGER, + null, + ['identity' => true, 'unsigned' => true, 'nullable' => false, 'primary' => true], + 'ID' + ) + ->addColumn( + 'shortname', + \Magento\Framework\DB\Ddl\Table::TYPE_TEXT, + 20, + ['nullable' => true, 'default' => null], + 'Short Name' + ) + ->addColumn( + 'name', + \Magento\Framework\DB\Ddl\Table::TYPE_TEXT, + 50, + ['nullable' => true, 'default' => null], + 'Name' + ) + ->addColumn( + 'stock_change', + \Magento\Framework\DB\Ddl\Table::TYPE_INTEGER, + null, + ['nullable' => false, 'default' => 0], + 'Stock Change(Plus/Minus)' + ) + ->addColumn( + 'megaventory_id', + \Magento\Framework\DB\Ddl\Table::TYPE_INTEGER, + null, + [], + 'Megaventory ID' + ); + + $installer->getConnection()->createTable($table); + + $table = $installer->getConnection() + ->newTable($installer->getTable('megaventory_integration_updates')) + ->addColumn( + 'id', + \Magento\Framework\DB\Ddl\Table::TYPE_INTEGER, + null, + ['identity' => true, 'unsigned' => true, 'nullable' => false, 'primary' => true], + 'ID' + ) + ->addColumn( + 'megaventory_integration_update_id', + \Magento\Framework\DB\Ddl\Table::TYPE_INTEGER, + null, + ['nullable' => false], + 'Integration Update ID' + ) + ->addColumn( + 'megaventory_entity', + \Magento\Framework\DB\Ddl\Table::TYPE_TEXT, + 255, + ['nullable' => false], + 'Megaventory Entity' + ) + ->addColumn( + 'megaventory_action', + \Magento\Framework\DB\Ddl\Table::TYPE_TEXT, + 255, + ['nullable' => false], + 'Megaventory Action' + ) + ->addColumn( + 'entity_ids', + \Magento\Framework\DB\Ddl\Table::TYPE_TEXT, + 10000, + ['nullable'=>false], + 'Entity IDs' + ) + ->addColumn( + 'update_date', + \Magento\Framework\DB\Ddl\Table::TYPE_DATETIME, + null, + ['nullable'=>false], + 'Update Date Time' + ) + ->addColumn( + 'tries', + \Magento\Framework\DB\Ddl\Table::TYPE_INTEGER, + null, + ['nullable'=>false, 'default'=>0], + 'Tries' + ); + $installer->getConnection()->createTable($table); $installer->getConnection()->addColumn( diff --git a/Setup/UpgradeData.php b/Setup/UpgradeData.php new file mode 100644 index 0000000..79b4575 --- /dev/null +++ b/Setup/UpgradeData.php @@ -0,0 +1,30 @@ +_inventoryCollectionFactory = $inventoryCollectionFactory; + } + + public function upgrade(ModuleDataSetupInterface $setup, ModuleContextInterface $context) + { + if (version_compare($context->getVersion(), '1.2.0', '>=') && version_compare($context->getVersion(), '1.3.0', '<')) { + $defaultInventories = $this->_inventoryCollectionFactory->create() + ->addFieldToFilter('isdefault', 1); + foreach ($defaultInventories as $inventory) { + $inventory->setStockSourceCode('default'); + $inventory->save(); + } + } + } +} diff --git a/Setup/UpgradeSchema.php b/Setup/UpgradeSchema.php new file mode 100644 index 0000000..4d04cb5 --- /dev/null +++ b/Setup/UpgradeSchema.php @@ -0,0 +1,160 @@ +startSetup(); + $table = $installer->getTable('megaventory_inventories'); + + if (version_compare($context->getVersion(), '1.3.0', '<=') && version_compare($context->getVersion(), '1.2.0', '>=')) { + if ($installer->getConnection()->tableColumnExists($table, 'stock_source_code') === false) { + $installer->getConnection()->addColumn( + $table, + 'stock_source_code', + [ + 'type' => \Magento\Framework\DB\Ddl\Table::TYPE_TEXT, + 'nullable' => true, + 'length' => 200, + 'comment' => 'Magento Inventory Source' + ] + ); + } + + if ($installer->getConnection()->tableColumnExists($table, 'mv_adjustment_plus_type_id') === false) { + $installer->getConnection()->addColumn( + $table, + 'mv_adjustment_plus_type_id', + [ + 'type' => \Magento\Framework\DB\Ddl\Table::TYPE_INTEGER, + 'nullable' => true, + 'comment' => 'Megaventory Adjustment Plus Template ID' + ] + ); + } + + if ($installer->getConnection()->tableColumnExists($table, 'mv_adjustment_minus_type_id') === false) { + $installer->getConnection()->addColumn( + $table, + 'mv_adjustment_minus_type_id', + [ + 'type' => \Magento\Framework\DB\Ddl\Table::TYPE_INTEGER, + 'nullable' => true, + 'comment' => 'Megaventory Adjustment Minus Template' + ] + ); + } + + if ($installer->getConnection()->tableColumnExists($table, 'isdefault') !== false) { + $installer->getConnection()->dropColumn( + $table, + 'isdefault' + ); + } + + $table = $installer->getConnection() + ->newTable($installer->getTable('megaventory_order_templates')) + ->addColumn( + 'id', + \Magento\Framework\DB\Ddl\Table::TYPE_INTEGER, + null, + ['identity' => true, 'unsigned' => true, 'nullable' => false, 'primary' => true], + 'ID' + ) + ->addColumn( + 'shortname', + \Magento\Framework\DB\Ddl\Table::TYPE_TEXT, + 20, + ['nullable' => true, 'default' => null], + 'Short Name' + ) + ->addColumn( + 'name', + \Magento\Framework\DB\Ddl\Table::TYPE_TEXT, + 50, + ['nullable' => true, 'default' => null], + 'Name' + ) + ->addColumn( + 'megaventory_id', + \Magento\Framework\DB\Ddl\Table::TYPE_INTEGER, + null, + [], + 'Megaventory ID' + ) + ->addColumn( + 'magento_website_ids', + \Magento\Framework\DB\Ddl\Table::TYPE_TEXT, + 500, + [], + 'Magento Websites' + ); + + $installer->getConnection()->createTable($table); + + $table = $installer->getConnection() + ->newTable($installer->getTable('megaventory_adjustment_templates')) + ->addColumn( + 'id', + \Magento\Framework\DB\Ddl\Table::TYPE_INTEGER, + null, + ['identity' => true, 'unsigned' => true, 'nullable' => false, 'primary' => true], + 'ID' + ) + ->addColumn( + 'shortname', + \Magento\Framework\DB\Ddl\Table::TYPE_TEXT, + 20, + ['nullable' => true, 'default' => null], + 'Short Name' + ) + ->addColumn( + 'name', + \Magento\Framework\DB\Ddl\Table::TYPE_TEXT, + 50, + ['nullable' => true, 'default' => null], + 'Name' + ) + ->addColumn( + 'stock_change', + \Magento\Framework\DB\Ddl\Table::TYPE_INTEGER, + null, + ['nullable' => false, 'default' => 0], + 'Stock Change(Plus/Minus)' + ) + ->addColumn( + 'megaventory_id', + \Magento\Framework\DB\Ddl\Table::TYPE_INTEGER, + null, + [], + 'Megaventory ID' + ); + + $installer->getConnection()->createTable($table); + } + elseif(version_compare($context->getVersion(), '1.4.2', '<')){ + if ($installer->getConnection()->tableColumnExists($installer->getTable('megaventory_inventories'), 'adjustment_doc_status') === false) { + $installer->getConnection()->addColumn( + $installer->getTable('megaventory_inventories'), + 'adjustment_doc_status', + [ + 'type' => \Magento\Framework\DB\Ddl\Table::TYPE_TEXT, + 'nullable' => false, + 'default' => 'Pending', + 'length' => 100, + 'comment' => 'Issue Adjustment Document with this Status' + ] + ); + } + } + + $installer->endSetup(); + } +} diff --git a/Ui/Component/Listing/Columns/DocumentTypeActions.php b/Ui/Component/Listing/Columns/DocumentTypeActions.php new file mode 100644 index 0000000..f62cd23 --- /dev/null +++ b/Ui/Component/Listing/Columns/DocumentTypeActions.php @@ -0,0 +1,43 @@ +urlBuilder = $urlBuilder; + parent::__construct($context, $uiComponentFactory, $components, $data); + } + + public function prepareDataSource(array $dataSource) + { + if (isset($dataSource['data']['items'])) { + foreach ($dataSource['data']['items'] as & $item) { + $name = $this->getData('name'); + if (isset($item['id'])) { + $item[$name]['edit'] = [ + 'href' => $this->urlBuilder->getUrl(self::DOCUMENT_TYPE_URL_PATH_EDIT, ['id' => $item['id']]), + 'label' => __('Edit') + ]; + } + } + } + + return $dataSource; + } +} \ No newline at end of file diff --git a/Ui/Component/Listing/Columns/DocumentTypeFieldset.php b/Ui/Component/Listing/Columns/DocumentTypeFieldset.php new file mode 100644 index 0000000..81f3ac8 --- /dev/null +++ b/Ui/Component/Listing/Columns/DocumentTypeFieldset.php @@ -0,0 +1,46 @@ +_documentTypeFactory = $documentTypeFactory; + $this->_documentTypeResource = $documentTypeResource; + $this->_request = $requestInterface; + } + public function prepare() + { + $id = (int)$this->_request->getParam('id',-1); + if($id > 0){ + $documentType = $this->_documentTypeFactory->create(); + $this->_documentTypeResource->load($documentType, $id); + + $config = $this->getData('config'); + + $config['label'] = $documentType->getName() . ' (' . $documentType->getShortname() . ')'; + + $this->setData('config',$config); + } + + parent::prepare(); + } +} \ No newline at end of file diff --git a/Ui/Component/Listing/Columns/DocumentTypeWebsite.php b/Ui/Component/Listing/Columns/DocumentTypeWebsite.php new file mode 100644 index 0000000..384b771 --- /dev/null +++ b/Ui/Component/Listing/Columns/DocumentTypeWebsite.php @@ -0,0 +1,54 @@ +_websiteRepository = $websiteRepository; + parent::__construct($context, $uiComponentFactory, $components, $data); + } + + public function prepareDataSource(array $dataSource) + { + if (isset($dataSource['data']['items'])) { + foreach ($dataSource['data']['items'] as & $item) { + $name = $this->getData('name'); + if (isset($item['id'])) { + $websites = explode(',', $item[$name]); + $content = ''; + if((count($websites) > 0) && (!empty($item[$name]))){ + foreach($websites as $website){ + try{ + $content .= $this->_websiteRepository->getById($website)->getName() . ''; + } + catch(NoSuchEntityException $e){ + // Empty handler to prevent a crash if a website is unable to be found on DB. + } + } + $content = rtrim($content, ' ,'); + } + + $item[$name] = $content; + } + } + } + + return $dataSource; + } +} \ No newline at end of file diff --git a/Ui/Component/Listing/Columns/InventoryColumn.php b/Ui/Component/Listing/Columns/InventoryColumn.php index 3a2ef8a..e386d38 100644 --- a/Ui/Component/Listing/Columns/InventoryColumn.php +++ b/Ui/Component/Listing/Columns/InventoryColumn.php @@ -42,7 +42,8 @@ public function prepareDataSource(array $dataSource) $inventory = $this->_inventoriesLoader->create()->load($item[$this->getData('name')]); $item[$this->getData('name')] = $inventory->getData('shortname'); } else { - $orderSynchronization = $this->_scopeConfig->getValue('megaventory/general/ordersynchronization'); + $orderSynchronization = $this->_scopeConfig + ->getValue('megaventory/general/ordersynchronization'); $notAssigned = 'Not Synchronized'; if (empty($orderSynchronization) || $orderSynchronization === '0') { diff --git a/Ui/Component/Listing/Columns/LogActions.php b/Ui/Component/Listing/Columns/LogActions.php index 07ebb9f..18e6b51 100644 --- a/Ui/Component/Listing/Columns/LogActions.php +++ b/Ui/Component/Listing/Columns/LogActions.php @@ -15,7 +15,6 @@ class LogActions extends Column /** @var UrlInterface */ protected $urlBuilder; - public function __construct( ContextInterface $context, UiComponentFactory $uiComponentFactory, @@ -24,7 +23,6 @@ public function __construct( array $data = [] ) { $this->urlBuilder = $urlBuilder; - //$this->editUrl = $editUrl; parent::__construct($context, $uiComponentFactory, $components, $data); } diff --git a/Ui/Component/Listing/Columns/ProductInventoriesColumn.php b/Ui/Component/Listing/Columns/ProductInventoriesColumn.php index 3a528a2..472cabc 100644 --- a/Ui/Component/Listing/Columns/ProductInventoriesColumn.php +++ b/Ui/Component/Listing/Columns/ProductInventoriesColumn.php @@ -45,9 +45,10 @@ public function prepareDataSource(array $dataSource) if ($item['mv_product_id'] != 0) { $html = ''; foreach ($inventories as $inventory) { - if ($inventory['counts_in_total_stock'] == 1) { + if ($inventory->getStockSourceCode() !== null) { $html .= ''; - $productStock = $this->_productStocksLoader->create()->loadInventoryProductstock($inventory->getId(), $item['entity_id']); + $productStock = $this->_productStocksLoader->create() + ->loadInventoryProductstock($inventory->getId(), $item['entity_id']); $html .= ''.$inventory->getShortname().''; $html .= ''.round($productStock->getStockqty(), 5).''; @@ -71,7 +72,7 @@ public function prepareDataSource(array $dataSource) $item[$this->getData('name')] = 'Not Connected'; } } else { - $item[$this->getData('name')] = ''; + $item[$this->getData('name')] = '--------'; } } catch (\Magento\Framework\Exception\NoSuchEntityException $exception) { $item[$this->getData('name')] = ''; diff --git a/composer.json b/composer.json index b78e5fd..3a02a22 100644 --- a/composer.json +++ b/composer.json @@ -1,7 +1,7 @@ { "name": "megaventory/module-megaventory-extension", "type": "magento2-module", - "version": "1.2.2", + "version": "1.4.2", "description": "Inventory Management for Multiple Locations", "authors": [ { @@ -22,7 +22,7 @@ } ], "require": { - "php": ">=5.3,<8.0-DEV" + "php": ">=7.0,<8.0-DEV" }, "autoload": { "psr-4": { "Mv\\Megaventory\\": "" }, diff --git a/etc/adminhtml/events.xml b/etc/adminhtml/events.xml new file mode 100644 index 0000000..7758225 --- /dev/null +++ b/etc/adminhtml/events.xml @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/etc/adminhtml/menu.xml b/etc/adminhtml/menu.xml index 5aee4fe..c9cf6e7 100644 --- a/etc/adminhtml/menu.xml +++ b/etc/adminhtml/menu.xml @@ -15,18 +15,19 @@ parent="Mv_Megaventory::megaventory" action="megaventory/index/" /> - + action="megaventory/documenttypes/index" + dependsOnConfig="megaventory/general/ordersynchronization" + /> - + */5 * * * * - + */10 * * * * diff --git a/etc/crontab/events.xml b/etc/crontab/events.xml new file mode 100644 index 0000000..7758225 --- /dev/null +++ b/etc/crontab/events.xml @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/etc/di.xml b/etc/di.xml index c2475f0..1c19cc6 100644 --- a/etc/di.xml +++ b/etc/di.xml @@ -24,19 +24,40 @@ - + - Mv\Megaventory\Model\ResourceModel\Updates\Collection + megaventory_integration_updates + Mv\Megaventory\Model\ResourceModel\IntegrationUpdate - Mv\Megaventory\Model\ResourceModel\Updates\Collection + Mv\Megaventory\Model\ResourceModel\IntegrationUpdate\Grid\Collection + + + + + Mv\Megaventory\Model\ResourceModel\DocumentType\Collection + + + + + megaventory_order_templates + Mv\Megaventory\Model\ResourceModel\DocumentType + + + + + + MegaventoryDocumentTypeGridCollection + + + diff --git a/etc/frontend/events.xml b/etc/frontend/events.xml new file mode 100644 index 0000000..d298a6c --- /dev/null +++ b/etc/frontend/events.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/etc/graphql/events.xml b/etc/graphql/events.xml new file mode 100644 index 0000000..7758225 --- /dev/null +++ b/etc/graphql/events.xml @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/etc/module.xml b/etc/module.xml index 3f56533..38a4444 100644 --- a/etc/module.xml +++ b/etc/module.xml @@ -1,4 +1,4 @@ - + \ No newline at end of file diff --git a/etc/webapi_rest/events.xml b/etc/webapi_rest/events.xml new file mode 100644 index 0000000..7758225 --- /dev/null +++ b/etc/webapi_rest/events.xml @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/etc/webapi_soap/events.xml b/etc/webapi_soap/events.xml new file mode 100644 index 0000000..7758225 --- /dev/null +++ b/etc/webapi_soap/events.xml @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/view/adminhtml/layout/default.xml b/view/adminhtml/layout/default.xml index 323bd66..412dc37 100644 --- a/view/adminhtml/layout/default.xml +++ b/view/adminhtml/layout/default.xml @@ -1,5 +1,6 @@ + \ No newline at end of file diff --git a/view/adminhtml/layout/megaventory_documenttypes_edit.xml b/view/adminhtml/layout/megaventory_documenttypes_edit.xml new file mode 100644 index 0000000..e911758 --- /dev/null +++ b/view/adminhtml/layout/megaventory_documenttypes_edit.xml @@ -0,0 +1,18 @@ + + + + + Order Template Configuration + + + + + + Mv_Megaventory::megaventory_document_types + + + + + + + \ No newline at end of file diff --git a/view/adminhtml/layout/megaventory_documenttypes_index.xml b/view/adminhtml/layout/megaventory_documenttypes_index.xml new file mode 100644 index 0000000..4cf2ed0 --- /dev/null +++ b/view/adminhtml/layout/megaventory_documenttypes_index.xml @@ -0,0 +1,16 @@ + + + + Megaventory Order Templates + + + + + Mv_Megaventory::megaventory_document_types + + + + + + + \ No newline at end of file diff --git a/view/adminhtml/layout/megaventory_inventory_edit.xml b/view/adminhtml/layout/megaventory_inventory_edit.xml new file mode 100644 index 0000000..1b41438 --- /dev/null +++ b/view/adminhtml/layout/megaventory_inventory_edit.xml @@ -0,0 +1,18 @@ + + + + + Editing Preferences for Megaventory Location + + + + + + Mv_Megaventory::megaventory_settings + + + + + + + \ No newline at end of file diff --git a/view/adminhtml/layout/megaventory_log_index.xml b/view/adminhtml/layout/megaventory_log_index.xml index d4c5c11..6fe5e6f 100644 --- a/view/adminhtml/layout/megaventory_log_index.xml +++ b/view/adminhtml/layout/megaventory_log_index.xml @@ -2,7 +2,7 @@ - Megaventory Log + Megaventory Integration Status diff --git a/view/adminhtml/templates/log_header.phtml b/view/adminhtml/templates/log_header.phtml new file mode 100644 index 0000000..ffb279f --- /dev/null +++ b/view/adminhtml/templates/log_header.phtml @@ -0,0 +1,16 @@ + + + + + = __('Log'); ?> + + \ No newline at end of file diff --git a/view/adminhtml/templates/product/form/megaventory.phtml b/view/adminhtml/templates/product/form/megaventory.phtml index 813b124..e2de2cf 100644 --- a/view/adminhtml/templates/product/form/megaventory.phtml +++ b/view/adminhtml/templates/product/form/megaventory.phtml @@ -1,16 +1,16 @@ getCurrentProduct(); -$inventories = $this->getInventories(); +$currentProduct = $block->getCurrentProduct(); +$inventories = $block->getInventories(); $mvProductId = $currentProduct->getData('mv_product_id'); -$workOrders = $this->getAdminSessionValue('mv_isWorksModuleEnabled'); +$workOrders = $block->getAdminSessionValue('mv_isWorksModuleEnabled'); -$subDomain = $this->getAdminSessionValue('mv_DomainName'); +$subDomain = $block->getAdminSessionValue('mv_DomainName'); $domain = '.megaventory.com'; $mvProduct = -1; if (!empty($mvProductId)) { - $mvProduct = $this->getMvProduct($mvProductId); + $mvProduct = $block->getMvProduct($mvProductId); } $links = ''; @@ -27,7 +27,7 @@ if ($mvProduct != -1 && $mvProduct != null) { $noticeSKU = ''; if ($mvProduct['ProductSKU'] != $currentProduct->getSku()) { - $messageImg = $this->getViewFileUrl('Mv_Megaventory::images/message.png'); + $messageImg = $block->getViewFileUrl('Mv_Megaventory::images/message.png'); $noticeSKU = ''; $noticeSKU .= 'Attention!Products are synchronized but SKUs are not the same.You should modify Magento Product SKU to exactly match Megaventory Product SKU'; } @@ -97,20 +97,20 @@ if ($mvProduct != -1 && $mvProduct != null) { -There are no Megaventory Inventories.Please import them in Settings Page +There are no Megaventory Inventories.Please import them in Settings Page