Jump to content

[Solved] Issue with "Mail alerts" Module Triggering for Already Out-of-Stock Products


Eutanasio

Recommended Posts

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

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

  • Eutanasio changed the title to [Solved] Issue with "Mail alerts" Module Triggering for Already Out-of-Stock Products
  • 3 weeks later...

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

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

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 account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...