diff --git a/classes/Cart.php b/classes/Cart.php index 41cc47716..f3f10f888 100644 --- a/classes/Cart.php +++ b/classes/Cart.php @@ -1259,9 +1259,10 @@ class CartCore extends ObjectModel * * @param boolean $withTaxes With or without taxes * @param integer $type Total type + * @param boolean $use_cache Allow using cache of the method CartRule::getContextualValue * @return float Order total */ - public function getOrderTotal($with_taxes = true, $type = Cart::BOTH, $products = null, $id_carrier = null) + public function getOrderTotal($with_taxes = true, $type = Cart::BOTH, $products = null, $id_carrier = null, $use_cache = true) { if (!$this->id) return 0; @@ -1448,7 +1449,7 @@ class CartCore extends ObjectModel { // If the cart rule offers free shipping, add the shipping cost if ($with_shipping && $cart_rule['obj']->free_shipping) - $order_total_discount += Tools::ps_round($cart_rule['obj']->getContextualValue($with_taxes, $virtual_context, CartRule::FILTER_ACTION_SHIPPING, ($param_product ? $package : null)), 2); + $order_total_discount += Tools::ps_round($cart_rule['obj']->getContextualValue($with_taxes, $virtual_context, CartRule::FILTER_ACTION_SHIPPING, ($param_product ? $package : null), $use_cache), 2); // If the cart rule is a free gift, then add the free gift value only if the gift is in this package if ((int)$cart_rule['obj']->gift_product) @@ -1462,13 +1463,13 @@ class CartCore extends ObjectModel $in_order = true; if ($in_order) - $order_total_discount += $cart_rule['obj']->getContextualValue($with_taxes, null, CartRule::FILTER_ACTION_GIFT, $package); + $order_total_discount += $cart_rule['obj']->getContextualValue($with_taxes, null, CartRule::FILTER_ACTION_GIFT, $package, $use_cache); } // If the cart rule offers a reduction, the amount is prorated (with the products in the package) if ($cart_rule['obj']->reduction_percent > 0 || $cart_rule['obj']->reduction_amount > 0) { - $order_total_discount += Tools::ps_round($cart_rule['obj']->getContextualValue($with_taxes, $virtual_context, CartRule::FILTER_ACTION_REDUCTION, $package), 2); + $order_total_discount += Tools::ps_round($cart_rule['obj']->getContextualValue($with_taxes, $virtual_context, CartRule::FILTER_ACTION_REDUCTION, $package, $use_cache), 2); } } @@ -2542,7 +2543,7 @@ class CartCore extends ObjectModel $free_fees_price = 0; if (isset($configuration['PS_SHIPPING_FREE_PRICE'])) $free_fees_price = Tools::convertPrice((float)$configuration['PS_SHIPPING_FREE_PRICE'], Currency::getCurrencyInstance((int)$this->id_currency)); - $orderTotalwithDiscounts = $this->getOrderTotal(true, Cart::BOTH_WITHOUT_SHIPPING); + $orderTotalwithDiscounts = $this->getOrderTotal(true, Cart::BOTH_WITHOUT_SHIPPING, null, null, false); if ($orderTotalwithDiscounts >= (float)($free_fees_price) && (float)($free_fees_price) > 0) return $shipping_cost; diff --git a/classes/CartRule.php b/classes/CartRule.php index c53b886ee..a2654c5c7 100644 --- a/classes/CartRule.php +++ b/classes/CartRule.php @@ -487,13 +487,17 @@ class CartRuleCore extends ObjectModel // If a product is given for free in this rule and already in the cart, the price is subtracted if ($this->gift_product && $alreadyInCart) { - $in_cart = (bool)Db::getInstance()->getValue(' - SELECT id_product - FROM '._DB_PREFIX_.'cart_product - WHERE id_product = '.(int)$this->gift_product.' - AND id_product_attribute = '.(int)$this->gift_product_attribute.' - AND id_cart = '.(int)$context->cart->id); - if ($in_cart) + $query = new DbQuery(); + + $query->select('id_product') + $query->from('cart_product') + $query->where('id_product = '.(int)$this->gift_product) + $query->where('id_cart = '.(int)$context->cart->id); + + if ((int)$this->gift_product_attribute) + $query->where('id_product_attribute = '.(int)$this->gift_product_attribute); + + if (Db::getInstance()->getValue($query)) { $ref = false; $product_price = Product::getPriceStatic( @@ -712,9 +716,10 @@ class CartRuleCore extends ObjectModel * * @param bool $use_tax * @param Context $context + * @param boolean $use_cache Allow using cache to avoid multiple free gift using multishipping * @return float|int|string */ - public function getContextualValue($use_tax, Context $context = null, $filter = null, $package = null) + public function getContextualValue($use_tax, Context $context = null, $filter = null, $package = null, $use_cache = true) { if (!CartRule::isFeatureActive()) return 0; @@ -895,16 +900,17 @@ class CartRuleCore extends ObjectModel { $id_address = (is_null($package) ? 0 : $package['id_address']); foreach ($package_products as $product) - if ($product['id_product'] == $this->gift_product && $product['id_product_attribute'] == $this->gift_product_attribute) + if ($product['id_product'] == $this->gift_product && ($product['id_product_attribute'] == $this->gift_product_attribute || !(int)$this->gift_product_attribute)) { // The free gift coupon must be applied to one product only (needed for multi-shipping which manage multiple product lists) if (!isset(CartRule::$only_one_gift[$this->id.'-'.$this->gift_product]) || CartRule::$only_one_gift[$this->id.'-'.$this->gift_product] == $id_address || CartRule::$only_one_gift[$this->id.'-'.$this->gift_product] == 0 - || $id_address == 0) + || $id_address == 0 + || !$use_cache) { $reduction_value += ($use_tax ? $product['price_wt'] : $product['price']); - if (!isset(CartRule::$only_one_gift[$this->id.'-'.$this->gift_product]) || CartRule::$only_one_gift[$this->id.'-'.$this->gift_product] == 0) + if ($use_cache && (!isset(CartRule::$only_one_gift[$this->id.'-'.$this->gift_product]) || CartRule::$only_one_gift[$this->id.'-'.$this->gift_product] == 0)) CartRule::$only_one_gift[$this->id.'-'.$this->gift_product] = $id_address; break; } diff --git a/classes/PaymentModule.php b/classes/PaymentModule.php index b309936a6..f43c5418f 100644 --- a/classes/PaymentModule.php +++ b/classes/PaymentModule.php @@ -321,6 +321,10 @@ abstract class PaymentModuleCore extends Module $cart_rule_used = array(); $products = $this->context->cart->getProducts(); $cart_rules = $this->context->cart->getCartRules(); + + // Make sure CarRule caches are empty + CartRule::cleanCache(); + foreach ($order_detail_list as $key => $order_detail) { $order = $order_list[$key];