Eutanasio Posted August 9, 2023 Share Posted August 9, 2023 Issue Description: In PrestaShop 1.7, I've been using the "Mail alerts" module to receive email alerts when a product becomes out of stock. However, I've noticed that the module is sending email alerts even when a customer places an order for a product that is already out of stock. Ideally, the alert should only trigger when a product's stock decreases from a positive value (i.e., 1 or more) to zero or below. Possible Solution: To address this issue, I've looked into the hookActionUpdateQuantity function within the ps_emailalerts.php file. The proposed solution is to calculate the product's previous stock by considering the current stock and the delta_quantity. Then, by comparing the previous stock with the updated stock, the function can determine if the stock changed from a positive value to zero or below. Here's the modification: public function hookActionUpdateQuantity($params) { // Calculate stock before update $previousQuantity = (int)$params['quantity'] + (int)$params['delta_quantity']; // Check if the stock went from >=1 to <=0 $stockWentToZeroOrBelowFromPositive = $previousQuantity >= 1 && (int)$params['quantity'] <= 0; // If the stock didn't go from >=1 to <=0, return and avoid sending the alert if (!$stockWentToZeroOrBelowFromPositive) { return; } // ... } With this change, the function first checks if the stock has decreased from 1 (or more) to zero or below. If not, it immediately exits and does not proceed with sending the email alert. I'm sharing this solution in the hopes that fellow developers can validate this approach and confirm if it's an effective workaround. Any feedback or suggestions for improvement would be greatly appreciated. Link to comment Share on other sites More sharing options...
Eutanasio Posted August 16, 2023 Author Share Posted August 16, 2023 If someone is interested, this is the code that seem to work: Just under this lines: public function hookActionUpdateQuantity($params) { // Do not send email if stock did not change if (isset($params['delta_quantity']) && (int) $params['delta_quantity'] === 0) { return; } insert this: // Calculate stock before update $previousQuantity = (int)$params['quantity'] + (int)$params['delta_quantity']; // Check if the stock went from >=1 to <=0 $stockWentToZeroOrBelowFromPositive = $previousQuantity >= 1 && (int)$params['quantity'] <= 0; // If the stock didn't go from >=1 to <=0, return if (!$stockWentToZeroOrBelowFromPositive) { return; } Link to comment Share on other sites More sharing options...
Eutanasio Posted September 2, 2023 Author Share Posted September 2, 2023 The previous approach had many issues and was not properly working. This new code provides a more efficient and accurate way to determine stock levels by: 1.- Using PrestaShop's built-in functions to fetch the current stock. 2.- Calculating the previous stock level based on the current stock and the quantity difference. 3.- Setting clear conditions for when an alert should or shouldn't be sent based on the stock levels. This approach ensures that email alerts are sent only in the intended scenarios, improving the accuracy and efficiency of the stock alert system. public function hookActionUpdateQuantity($params) { // Start logging //PrestaShopLogger::addLog('hookActionUpdateQuantity started for product ID: ' . $params['id_product'], 1, null, 'Order', $params['id_product'], true); // Get the product ID from the hook parameters $productId = $params['id_product']; // Load the product using PrestaShop's Product class $product = new Product($productId); // Check if the product is loaded successfully if (!Validate::isLoadedObject($product)) { PrestaShopLogger::addLog('Failed to load product with ID: ' . $productId, 3, null, 'Order', $productId, true); return; } // Get the current stock of the product $currentStock = StockAvailable::getQuantityAvailableByProduct($productId); // Calculate the previous stock level $previousStockLevel = $currentStock + $params['quantity_difference']; // Determine if an alert should be sent based on stock levels if ($previousStockLevel > 0 && $currentStock <= 0) { // Intended condition for sending an alert // The rest of the code in the native function will handle the email alert } elseif ($previousStockLevel == 0 && $currentStock <= 0) { // Intended condition for not sending an alert return; } elseif ($previousStockLevel < 0 && $currentStock <= 0) { // Intended condition for not sending an alert return; } //rest of the code Link to comment Share on other sites More sharing options...
Eutanasio Posted September 7, 2023 Author Share Posted September 7, 2023 It was all a mess, I spent many days looking into this, there was an issue with bad code on StockAvailable.php, you need to first fix it in order to work with emailAlerts.php: Then you need to do a couple fixes on emailalerts.php, I share the section of the code with the modifications applied: public function hookActionUpdateQuantity($params) { // Do not send email if stock did not change if (isset($params['delta_quantity']) && (int) $params['delta_quantity'] === 0) { return; } $id_product = (int) $params['id_product']; $id_product_attribute = (int) $params['id_product_attribute']; // NEW CODE // Get the current stock (which is actually the previous stock before the change) $previousStock = StockAvailable::getQuantityAvailableByProduct($id_product); if ($previousStock === false) { return; } $newStock = $previousStock + $params['delta_quantity']; // FIN NEW CODE $context = Context::getContext(); $id_shop = (int) $context->shop->id; $id_lang = (int) $context->language->id; $locale = $context->language->getLocale(); $product = new Product($id_product, false, $id_lang, $id_shop, $context); if (!Validate::isLoadedObject($product) || $product->active != 1) { return; } $quantity = (int) $params['quantity']; $product_has_attributes = $product->hasAttributes(); $configuration = Configuration::getMultiple( [ 'MA_LAST_QTIES', 'PS_STOCK_MANAGEMENT', 'PS_SHOP_EMAIL', 'PS_SHOP_NAME', ], null, null, $id_shop ); $ma_last_qties = (int) $configuration['MA_LAST_QTIES']; $check_oos = ($product_has_attributes && $id_product_attribute) || (!$product_has_attributes && !$id_product_attribute); if ($check_oos && $previousStock > $ma_last_qties && $newStock <= $ma_last_qties && // LOGIC MODIFIED, WAS: (int) $quantity <= $ma_last_qties !(!$this->merchant_oos || empty($this->merchant_oos_emails)) && $configuration['PS_STOCK_MANAGEMENT']) { $iso = Language::getIsoById($id_lang); $product_name = Product::getProductName($id_product, $id_product_attribute, $id_lang); $template_vars = [ '{qty}' => $quantity, '{last_qty}' => $ma_last_qties, '{product}' => $product_name, ]; This should be done on an override, for both php files! so when you update the modules or something you don't lose everything Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now