Salta al contenuto ID

In Prestashop 1.7.6 non funziona “escludi i prodotti scontati” nei Buoni Sconto

Nelle versioni di Prestashop 1.7.6 è apparso un problema con l’opzione “Escludi i prodotti scontati” presente nelle Regole Carrello dei buoni sconto, al pannello Azioni.

L’esclusione funziona se nel carrello sono aggiunti solo prodotti scontati, altrimenti, con un misto di prodotti scontati e a prezzo pieno, la regola non funziona e lo sconto si applica a tutti i prodotti indistintamente.

Per risolvere questo problema bisogna modificare il file src/Core/Cart/CartRuleCalculator.php

Maggiori informazioni qui: https://github.com/PrestaShop/PrestaShop/pull/13704#issuecomment-579778237

Per comodità riporto di seguito il file completo da sostituire in una versione PS 1.7.6.5

<?php
/**
 * 2007-2019 PrestaShop and Contributors
 *
 * NOTICE OF LICENSE
 *
 * This source file is subject to the Open Software License (OSL 3.0)
 * that is bundled with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * https://opensource.org/licenses/OSL-3.0
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to license@prestashop.com so we can send you a copy immediately.
 *
 * DISCLAIMER
 *
 * Do not edit or add to this file if you wish to upgrade PrestaShop to newer
 * versions in the future. If you wish to customize PrestaShop for your
 * needs please refer to https://www.prestashop.com for more information.
 *
 * @author    PrestaShop SA <contact@prestashop.com>
 * @copyright 2007-2019 PrestaShop SA and Contributors
 * @license   https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
 * International Registered Trademark & Property of PrestaShop SA
 */
 
namespace PrestaShop\PrestaShop\Core\Cart;
 
use Cart;
 
class CartRuleCalculator
{
    /**
     * @var Calculator
     */
    protected $calculator;
 
    /**
     * @var CartRowCollection
     */
    protected $cartRows;
 
    /**
     * @var CartRuleCollection
     */
    protected $cartRules;
 
    /**
     * @var Fees
     */
    protected $fees;
 
    /**
     * process cartrules calculation
     */
    public function applyCartRules()
    {
        foreach ($this->cartRules as $cartRule) {
            $this->applyCartRule($cartRule);
        }
    }
 
    /**
     * process cartrules calculation, excluding free-shipping processing
     */
    public function applyCartRulesWithoutFreeShipping()
    {
        foreach ($this->cartRules as $cartRule) {
            $this->applyCartRule($cartRule, false);
        }
    }
 
    /**
     * @param \PrestaShop\PrestaShop\Core\Cart\CartRuleCollection $cartRules
     *
     * @return CartRuleCalculator
     */
    public function setCartRules($cartRules)
    {
        $this->cartRules = $cartRules;
 
        return $this;
    }
 
    /**
     * @param CartRuleData $cartRuleData
     * @param bool $withFreeShipping used to calculate free shipping discount (avoid loop on shipping calculation)
     *
     * @throws \PrestaShopDatabaseException
     */
    protected function applyCartRule(CartRuleData $cartRuleData, $withFreeShipping = true)
    {
        $cartRule = $cartRuleData->getCartRule();
        $cart = $this->calculator->getCart();
 
        if (!\CartRule::isFeatureActive()) {
            return;
        }
 
        // Free shipping on selected carriers
        if ($cartRule->free_shipping && $withFreeShipping) {
            $initialShippingFees = new AmountImmutable(
                $cart->getOrderTotal(true, Cart::ONLY_SHIPPING),
                $cart->getOrderTotal(false, Cart::ONLY_SHIPPING)
            );
            $this->calculator->getFees()->subDiscountValueShipping($initialShippingFees);
            $cartRuleData->addDiscountApplied($initialShippingFees);
        }
 
        // Free gift
        if ((int) $cartRule->gift_product) {
            foreach ($this->cartRows as $cartRow) {
                $product = $cartRow->getRowData();
                if ($product['id_product'] == $cartRule->gift_product
                    && ($product['id_product_attribute'] == $cartRule->gift_product_attribute
                        || !(int) $cartRule->gift_product_attribute)
                ) {
                    $cartRuleData->addDiscountApplied($cartRow->getFinalUnitPrice());
                    $cartRow->applyFlatDiscount($cartRow->getFinalUnitPrice());
                }
            }
        }
 
        // Discount (%) on the whole order
        if ($cartRule->reduction_percent && $cartRule->reduction_product == 0) {
            foreach ($this->cartRows as $cartRow) {
              $product = $cartRow->getRowData();
              if ((($cartRule->reduction_exclude_special && !$product['reduction_applies'])
                    || !$cartRule->reduction_exclude_special)) {
                $amount = $cartRow->applyPercentageDiscount($cartRule->reduction_percent);
                $cartRuleData->addDiscountApplied($amount);
              }
            }
        }
 
        // Discount (%) on a specific product
        if ($cartRule->reduction_percent && $cartRule->reduction_product > 0) {
            foreach ($this->cartRows as $cartRow) {
                if ($cartRow->getRowData()['id_product'] == $cartRule->reduction_product) {
                    $amount = $cartRow->applyPercentageDiscount($cartRule->reduction_percent);
                    $cartRuleData->addDiscountApplied($amount);
                }
            }
        }
 
        // Discount (%) on the cheapest product
        if ($cartRule->reduction_percent && $cartRule->reduction_product == -1) {
            /** @var CartRow|null $cartRowCheapest */
            $cartRowCheapest = null;
            foreach ($this->cartRows as $cartRow) {
                $product = $cartRow->getRowData();
                if (((($cartRule->reduction_exclude_special && !$product['reduction_applies'])
                        || !$cartRule->reduction_exclude_special)) && ($cartRowCheapest === null
                        || $cartRowCheapest->getInitialUnitPrice()->getTaxIncluded() > $cartRow->getInitialUnitPrice()
                            ->getTaxIncluded())
                ) {
                    $cartRowCheapest = $cartRow;
                }
            }
            if ($cartRowCheapest !== null) {
                // apply only on one product of the cheapest row
                $discountTaxIncluded = $cartRowCheapest->getInitialUnitPrice()->getTaxIncluded()
                                       * $cartRule->reduction_percent / 100;
                $discountTaxExcluded = $cartRowCheapest->getInitialUnitPrice()->getTaxExcluded()
                                       * $cartRule->reduction_percent / 100;
                $amount = new AmountImmutable($discountTaxIncluded, $discountTaxExcluded);
                $cartRowCheapest->applyFlatDiscount($amount);
                $cartRuleData->addDiscountApplied($amount);
            }
        }
 
        // Discount (%) on the selection of products
        if ($cartRule->reduction_percent && $cartRule->reduction_product == -2) {
            $selected_products = $cartRule->checkProductRestrictionsFromCart($cart, true);
            if (is_array($selected_products)) {
                foreach ($this->cartRows as $cartRow) {
                    $product = $cartRow->getRowData();
                    if (in_array($product['id_product'] . '-' . $product['id_product_attribute'], $selected_products)
                        || in_array($product['id_product'] . '-0', $selected_products)
                           && (($cartRule->reduction_exclude_special && !$product['reduction_applies'])
                               || !$cartRule->reduction_exclude_special)) {
                        $amount = $cartRow->applyPercentageDiscount($cartRule->reduction_percent);
                        $cartRuleData->addDiscountApplied($amount);
                    }
                }
            }
        }
 
        // Discount (¤) : weighted calculation on all concerned rows
        //                weight factor got from price with same tax (incl/excl) as voucher
        if ((float) $cartRule->reduction_amount > 0) {
            $concernedRows = new CartRowCollection();
            if ($cartRule->reduction_product > 0) {
                // discount on single product
                foreach ($this->cartRows as $cartRow) {
                    if ($cartRow->getRowData()['id_product'] == $cartRule->reduction_product) {
                        $concernedRows->addCartRow($cartRow);
                    }
                }
            } elseif ($cartRule->reduction_product == 0) {
                // Discount (¤) on the whole order
                $concernedRows = $this->cartRows;
            }
            /*
             * Reduction on the cheapest or on the selection is not really meaningful and has been disabled in the backend
             * Please keep this code, so it won't be considered as a bug
             * elseif ($this->reduction_product == -1)
             * elseif ($this->reduction_product == -2)
             */
 
            // currency conversion
            $discountConverted = $this->convertAmountBetweenCurrencies(
                $cartRule->reduction_amount,
                new \Currency($cartRule->reduction_currency),
                new \Currency($cart->id_currency)
            );
 
            // get total of concerned rows
            $totalTaxIncl = $totalTaxExcl = 0;
            foreach ($concernedRows as $concernedRow) {
                $totalTaxIncl += $concernedRow->getFinalTotalPrice()->getTaxIncluded();
                $totalTaxExcl += $concernedRow->getFinalTotalPrice()->getTaxExcluded();
            }
 
            // The reduction cannot exceed the products total, except when we do not want it to be limited (for the partial use calculation)
            $discountConverted = min($discountConverted, $cartRule->reduction_tax ? $totalTaxIncl : $totalTaxExcl);
 
            // apply weighted discount :
            // on each line we apply a part of the discount corresponding to discount*rowWeight/total
            foreach ($concernedRows as $concernedRow) {
                // get current line tax rate
                $taxRate = 0;
                if ($concernedRow->getFinalTotalPrice()->getTaxExcluded() != 0) {
                    $taxRate = ($concernedRow->getFinalTotalPrice()->getTaxIncluded()
                                - $concernedRow->getFinalTotalPrice()->getTaxExcluded())
                               / $concernedRow->getFinalTotalPrice()->getTaxExcluded();
                }
                $weightFactor = 0;
                if ($cartRule->reduction_tax) {
                    // if cart rule amount is set tax included : calculate weight tax included
                    if ($totalTaxIncl != 0) {
                        $weightFactor = $concernedRow->getFinalTotalPrice()->getTaxIncluded() / $totalTaxIncl;
                    }
                    $discountAmountTaxIncl = $discountConverted * $weightFactor;
                    // recalculate tax included
                    $discountAmountTaxExcl = $discountAmountTaxIncl / (1 + $taxRate);
                } else {
                    // if cart rule amount is set tax excluded : calculate weight tax excluded
                    if ($totalTaxExcl != 0) {
                        $weightFactor = $concernedRow->getFinalTotalPrice()->getTaxExcluded() / $totalTaxExcl;
                    }
                    $discountAmountTaxExcl = $discountConverted * $weightFactor;
                    // recalculate tax excluded
                    $discountAmountTaxIncl = $discountAmountTaxExcl * (1 + $taxRate);
                }
                $amount = new AmountImmutable($discountAmountTaxIncl, $discountAmountTaxExcl);
                $concernedRow->applyFlatDiscount($amount);
                $cartRuleData->addDiscountApplied($amount);
            }
        }
    }
 
    /**
     * @param \PrestaShop\PrestaShop\Core\Cart\Calculator $calculator
     *
     * @return CartRuleCalculator
     */
    public function setCalculator($calculator)
    {
        $this->calculator = $calculator;
 
        return $this;
    }
 
    protected function convertAmountBetweenCurrencies($amount, \Currency $currencyFrom, \Currency $currencyTo)
    {
        if ($amount == 0 || $currencyFrom->conversion_rate == 0) {
            return 0;
        }
 
        // convert to default currency
        $amount /= $currencyFrom->conversion_rate;
        // convert to destination currency
        $amount *= $currencyTo->conversion_rate;
 
        return $amount;
    }
 
    /**
     * @param \PrestaShop\PrestaShop\Core\Cart\CartRowCollection $cartRows
     *
     * @return CartRuleCalculator
     */
    public function setCartRows($cartRows)
    {
        $this->cartRows = $cartRows;
 
        return $this;
    }
 
    /**
     * @return CartRuleCollection
     */
    public function getCartRulesData()
    {
        return $this->cartRules;
    }
}

 

Questa è la comparazione delle righe di codice modificate.

Questo articolo ha 0 commenti

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *

Torna su