diff --git a/app/code/Magento/InventorySalesAlert/Api/ProductIsSalableInterface.php b/app/code/Magento/InventorySalesAlert/Api/ProductIsSalableInterface.php new file mode 100644 index 000000000000..db07a9d785c9 --- /dev/null +++ b/app/code/Magento/InventorySalesAlert/Api/ProductIsSalableInterface.php @@ -0,0 +1,34 @@ +stockItem = $stockItem ?: ObjectManager::getInstance()->get(IsProductInStock::class); + $this->stockResolver = $stockResolver ?: ObjectManager::getInstance()->get(StockResolver::class); + } + + + /** + * @param ProductInterface $product + * + * @return bool + */ + public function isSalable( + ProductInterface $product, + string $websiteCode, + string $salesChannel = SalesChannelInterface::TYPE_WEBSITE + ): bool + { + $stock = $this->stockResolver->get($salesChannel, $websiteCode); + if ($stock->getId()) { + return $this->stockItem->execute($product->getSku(), (int) $stock->getStockId()); + } + return false; + } +} \ No newline at end of file diff --git a/app/code/Magento/InventorySalesAlert/composer.json b/app/code/Magento/InventorySalesAlert/composer.json new file mode 100644 index 000000000000..e870c3bac327 --- /dev/null +++ b/app/code/Magento/InventorySalesAlert/composer.json @@ -0,0 +1,42 @@ +{ + "name": "magento/module-inventory-sales-alert", + "description": "", + "require": { + "php": "7.0.2|7.0.4|~7.0.6|~7.1.0", + "magento/framework": "100.3.*", + "magento/module-backend": "100.0.*", + "magento/module-catalog": "100.0.*", + "magento/module-catalog-inventory": "100.0.*", + "magento/module-inventory": "100.0.*", + "magento/module-inventory-api": "100.0.*", + "magento/module-inventory-catalog": "100.0.*", + "magento/module-inventory-sales-api": "100.0.*", + "magento/module-store": "100.3.*", + "magento/module-ui": "100.3.*", + "magento/magento-composer-installer": "*" + }, + "suggest": { + + }, + "type": "magento2-module", + "version": "0.1.0", + "license": [ + + ], + "autoload": { + "files": [ + "registration.php" + ], + "psr-4": { + "Magento\\InventorySalesAlert\\": "" + } + }, + "extra": { + "map": [ + [ + "*", + "Magento/InventorySalesAlert" + ] + ] + } +} \ No newline at end of file diff --git a/app/code/Magento/InventorySalesAlert/etc/di.xml b/app/code/Magento/InventorySalesAlert/etc/di.xml new file mode 100644 index 000000000000..cc18447618d2 --- /dev/null +++ b/app/code/Magento/InventorySalesAlert/etc/di.xml @@ -0,0 +1,10 @@ + + + + + diff --git a/app/code/Magento/InventorySalesAlert/etc/module.xml b/app/code/Magento/InventorySalesAlert/etc/module.xml new file mode 100644 index 000000000000..871eec000cd3 --- /dev/null +++ b/app/code/Magento/InventorySalesAlert/etc/module.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/code/Magento/InventorySalesAlert/registration.php b/app/code/Magento/InventorySalesAlert/registration.php new file mode 100644 index 000000000000..1868109415e4 --- /dev/null +++ b/app/code/Magento/InventorySalesAlert/registration.php @@ -0,0 +1,7 @@ +_catalogData = $catalogData; - $this->_scopeConfig = $scopeConfig; - $this->_storeManager = $storeManager; - $this->_priceColFactory = $priceColFactory; + $this->catalogData = $catalogData; + $this->scopeConfig = $scopeConfig; + $this->storeManager = $storeManager; + $this->priceColFactory = $priceColFactory; $this->customerRepository = $customerRepository; - $this->productRepository = $productRepository; - $this->_dateFactory = $dateFactory; - $this->_stockColFactory = $stockColFactory; - $this->_transportBuilder = $transportBuilder; - $this->_emailFactory = $emailFactory; - $this->inlineTranslation = $inlineTranslation; + $this->productRepository = $productRepository; + $this->dateFactory = $dateFactory; + $this->stockColFactory = $stockColFactory; + $this->transportBuilder = $transportBuilder; + $this->emailFactory = $emailFactory; + $this->inlineTranslation = $inlineTranslation; + $this->productIsSalable = $productIsSalable; } /** @@ -161,27 +189,29 @@ public function __construct( */ protected function _getWebsites() { - if ($this->_websites === null) { + if ($this->websites === null) { try { - $this->_websites = $this->_storeManager->getWebsites(); + $this->websites = $this->storeManager->getWebsites(); } catch (\Exception $e) { - $this->_errors[] = $e->getMessage(); + $this->errors[] = $e->getMessage(); throw $e; } } - return $this->_websites; + + return $this->websites; } /** * Process price emails * * @param \Magento\ProductAlert\Model\Email $email + * * @return $this * @throws \Exception * @SuppressWarnings(PHPMD.CyclomaticComplexity) * @SuppressWarnings(PHPMD.NPathComplexity) */ - protected function _processPrice(\Magento\ProductAlert\Model\Email $email) + protected function _processPrice(Email $email): Observer { $email->setType('price'); foreach ($this->_getWebsites() as $website) { @@ -189,20 +219,20 @@ protected function _processPrice(\Magento\ProductAlert\Model\Email $email) if (!$website->getDefaultGroup() || !$website->getDefaultGroup()->getDefaultStore()) { continue; } - if (!$this->_scopeConfig->getValue( + if (!$this->scopeConfig->getValue( self::XML_PATH_PRICE_ALLOW, - \Magento\Store\Model\ScopeInterface::SCOPE_STORE, + ScopeInterface::SCOPE_STORE, $website->getDefaultGroup()->getDefaultStore()->getId() ) ) { continue; } try { - $collection = $this->_priceColFactory->create()->addWebsiteFilter( + $collection = $this->priceColFactory->create()->addWebsiteFilter( $website->getId() )->setCustomerOrder(); } catch (\Exception $e) { - $this->_errors[] = $e->getMessage(); + $this->errors[] = $e->getMessage(); throw $e; } @@ -234,18 +264,18 @@ protected function _processPrice(\Magento\ProductAlert\Model\Email $email) $product->setCustomerGroupId($customer->getGroupId()); if ($alert->getPrice() > $product->getFinalPrice()) { $productPrice = $product->getFinalPrice(); - $product->setFinalPrice($this->_catalogData->getTaxPrice($product, $productPrice)); - $product->setPrice($this->_catalogData->getTaxPrice($product, $product->getPrice())); + $product->setFinalPrice($this->catalogData->getTaxPrice($product, $productPrice)); + $product->setPrice($this->catalogData->getTaxPrice($product, $product->getPrice())); $email->addPriceProduct($product); $alert->setPrice($productPrice); - $alert->setLastSendDate($this->_dateFactory->create()->gmtDate()); + $alert->setLastSendDate($this->dateFactory->create()->gmtDate()); $alert->setSendCount($alert->getSendCount() + 1); $alert->setStatus(1); $alert->save(); } } catch (\Exception $e) { - $this->_errors[] = $e->getMessage(); + $this->errors[] = $e->getMessage(); throw $e; } } @@ -253,11 +283,12 @@ protected function _processPrice(\Magento\ProductAlert\Model\Email $email) try { $email->send(); } catch (\Exception $e) { - $this->_errors[] = $e->getMessage(); + $this->errors[] = $e->getMessage(); throw $e; } } } + return $this; } @@ -265,12 +296,13 @@ protected function _processPrice(\Magento\ProductAlert\Model\Email $email) * Process stock emails * * @param \Magento\ProductAlert\Model\Email $email + * * @return $this * @throws \Exception * @SuppressWarnings(PHPMD.CyclomaticComplexity) * @SuppressWarnings(PHPMD.NPathComplexity) */ - protected function _processStock(\Magento\ProductAlert\Model\Email $email) + protected function _processStock(Email $email): Observer { $email->setType('stock'); @@ -280,22 +312,22 @@ protected function _processStock(\Magento\ProductAlert\Model\Email $email) if (!$website->getDefaultGroup() || !$website->getDefaultGroup()->getDefaultStore()) { continue; } - if (!$this->_scopeConfig->getValue( + if (!$this->scopeConfig->getValue( self::XML_PATH_STOCK_ALLOW, - \Magento\Store\Model\ScopeInterface::SCOPE_STORE, + ScopeInterface::SCOPE_STORE, $website->getDefaultGroup()->getDefaultStore()->getId() ) ) { continue; } try { - $collection = $this->_stockColFactory->create()->addWebsiteFilter( + $collection = $this->stockColFactory->create()->addWebsiteFilter( $website->getId() )->addStatusFilter( 0 )->setCustomerOrder(); } catch (\Exception $e) { - $this->_errors[] = $e->getMessage(); + $this->errors[] = $e->getMessage(); throw $e; } @@ -326,16 +358,16 @@ protected function _processStock(\Magento\ProductAlert\Model\Email $email) $product->setCustomerGroupId($customer->getGroupId()); - if ($product->isSalable()) { + if ($this->productIsSalable->isSalable($product, $website->getCode())) { $email->addStockProduct($product); - $alert->setSendDate($this->_dateFactory->create()->gmtDate()); + $alert->setSendDate($this->dateFactory->create()->gmtDate()); $alert->setSendCount($alert->getSendCount() + 1); $alert->setStatus(1); $alert->save(); } } catch (\Exception $e) { - $this->_errors[] = $e->getMessage(); + $this->errors[] = $e->getMessage(); throw $e; } } @@ -344,7 +376,7 @@ protected function _processStock(\Magento\ProductAlert\Model\Email $email) try { $email->send(); } catch (\Exception $e) { - $this->_errors[] = $e->getMessage(); + $this->errors[] = $e->getMessage(); throw $e; } } @@ -357,13 +389,14 @@ protected function _processStock(\Magento\ProductAlert\Model\Email $email) * Send email to administrator if error * * @return $this + * @throws \Magento\Framework\Exception\MailException */ - protected function _sendErrorEmail() + protected function _sendErrorEmail(): Observer { - if (count($this->_errors)) { - if (!$this->_scopeConfig->getValue( + if (count($this->errors)) { + if (!$this->scopeConfig->getValue( self::XML_PATH_ERROR_TEMPLATE, - \Magento\Store\Model\ScopeInterface::SCOPE_STORE + ScopeInterface::SCOPE_STORE ) ) { return $this; @@ -371,35 +404,36 @@ protected function _sendErrorEmail() $this->inlineTranslation->suspend(); - $transport = $this->_transportBuilder->setTemplateIdentifier( - $this->_scopeConfig->getValue( + $transport = $this->transportBuilder->setTemplateIdentifier( + $this->scopeConfig->getValue( self::XML_PATH_ERROR_TEMPLATE, - \Magento\Store\Model\ScopeInterface::SCOPE_STORE + ScopeInterface::SCOPE_STORE ) )->setTemplateOptions( [ - 'area' => \Magento\Backend\App\Area\FrontNameResolver::AREA_CODE, - 'store' => \Magento\Store\Model\Store::DEFAULT_STORE_ID, + 'area' => FrontNameResolver::AREA_CODE, + 'store' => Store::DEFAULT_STORE_ID, ] )->setTemplateVars( - ['warnings' => join("\n", $this->_errors)] + ['warnings' => join("\n", $this->errors)] )->setFrom( - $this->_scopeConfig->getValue( + $this->scopeConfig->getValue( self::XML_PATH_ERROR_IDENTITY, - \Magento\Store\Model\ScopeInterface::SCOPE_STORE + ScopeInterface::SCOPE_STORE ) )->addTo( - $this->_scopeConfig->getValue( + $this->scopeConfig->getValue( self::XML_PATH_ERROR_RECIPIENT, - \Magento\Store\Model\ScopeInterface::SCOPE_STORE + ScopeInterface::SCOPE_STORE ) )->getTransport(); $transport->sendMessage(); $this->inlineTranslation->resume(); - $this->_errors[] = []; + $this->errors[] = []; } + return $this; } @@ -407,11 +441,13 @@ protected function _sendErrorEmail() * Run process send product alerts * * @return $this + * @throws \Exception + * @throws \Magento\Framework\Exception\MailException */ public function process() { - /* @var $email \Magento\ProductAlert\Model\Email */ - $email = $this->_emailFactory->create(); + /* @var $email Email */ + $email = $this->emailFactory->create(); $this->_processPrice($email); $this->_processStock($email); $this->_sendErrorEmail();