diff --git a/classes/CartRule.php b/classes/CartRule.php index 210ec017..842197f7 100755 --- a/classes/CartRule.php +++ b/classes/CartRule.php @@ -299,7 +299,7 @@ class CartRuleCore extends ObjectModel continue 2; unset($result[$key]); } - + if (isset($cart) && isset($cart->id)) foreach ($result as $key => $cart_rule) if ($cart_rule['product_restriction']) diff --git a/modules/blockcart/blockcart.php b/modules/blockcart/blockcart.php index d3d7de32..5de24cb2 100755 --- a/modules/blockcart/blockcart.php +++ b/modules/blockcart/blockcart.php @@ -115,29 +115,68 @@ class BlockCart extends Module } // @Override [ticket 7902] - $all_cart_rules = CartRule::getCustomerCartRules($this->context->language->id, $this->context->customer->id, true, true, true); + // Previous override : understand business rule : + // If the cart contains any product not eligible for free shipping (in case there is any rule with free shipping) + // then the cart is not eligible. + // + // + // ticket 12906 - Addition to this business rule : + // The carts rules are ordered by priority + // the highest priority cart rules (minimal number) overrides other cart rules with products restricted (in case + // there no product in the restriction list) + // + $notEligible = false; + $all_cart_rules = CartRule::getCustomerCartRules($this->context->language->id, $this->context->customer->id, true, true, true); + $previous_priority = 1; + $is_cart_valid = false; + + $cartRulesAlreadyInCart = $this->context->cart->getCartRules(CartRule::FILTER_ACTION_SHIPPING); if($all_cart_rules) { foreach ($all_cart_rules as $key => $cart_rule) { if($cart_rule['id_discount_type'] == Discount::FREE_SHIPPING){ $cr = new CartRule((int)$cart_rule['id_cart_rule']); - if($cr->checkValidityWithoutAmount($this->context,false,false) && $cart_rule['minimal']>0){ - if(!isset($minimum_amount)) - $minimum_amount = $cart_rule['minimal']; - if($minimum_amount < $cart_rule['minimal']) + + // if this cart rule restrict to only N products and no cart product is in this restriction list, + // check if there was a previous eligible free shipping cart rule. + // if it is the case : skip this one. + // if not, it is not eligible + /* + if (!$cr->isAnyCartProductInRestrictionlist($this->context)) { + if ($is_cart_valid && $cr->priority > $previous_priority ) { continue; + } + elseif ($) + } + */ + + $previous_priority = $cr->priority; + + $is_cart_valid = $cr->checkValidityWithoutAmount($this->context,false,false); + if($is_cart_valid && $cart_rule['minimal']>0){ + if(!isset($minimum_amount)) { + $minimum_amount = $cart_rule['minimal']; + } + if($minimum_amount < $cart_rule['minimal']) { + continue; + } $minimum_amount = ($minimum_amount < $cart_rule['minimal'])?$minimum_amount:$cart_rule['minimal']; $minimum_amount_tax = $cart_rule['minimum_amount_tax'] ; - } elseif (!$cr->checkValidityWithoutAmount($this->context,false,false) && !$this->context->cart->getCartRules(CartRule::FILTER_ACTION_SHIPPING)) { + } elseif (!$is_cart_valid && empty($cartRulesAlreadyInCart)) { $notEligible = true; } } - } } - +error_log('blockcart - notEligible ?'.($notEligible?'true':'false')); +/* $infos = CartRule::getEligibilityAndMinimumAmount($this->context); + $minimum_amount = $infos['minimum_amount']; + $minimum_amount_tax = $infos['minimum_amount_tax']; + $notEligible = $infos['notEligible']; + $cartRulesAlreadyInCart = $infos['cartRulesAlreadyInCart']; +*/ // $nbOrder = Order::getCustomerNbOrders($this->context->customer->id); // Ajouter en condition s'il faut checker la première commande - if (isset($minimum_amount) && !$this->context->cart->getCartRules(CartRule::FILTER_ACTION_SHIPPING)){ + if (isset($minimum_amount) && empty($cartRulesAlreadyInCart)){ if($minimum_amount_tax && $minimum_amount > $totalWithoutShipping) $remaining_for_free_shipping = $minimum_amount - $totalWithoutShipping; elseif(!$minimum_amount_tax && $minimum_amount > $totalWithoutShippingAndTax) @@ -171,7 +210,8 @@ class BlockCart extends Module 'order_process' => Configuration::get('PS_ORDER_PROCESS_TYPE') ? 'order-opc' : 'order', 'ajax_allowed' => (int)(Configuration::get('PS_BLOCK_CART_AJAX')) == 1 ? true : false, 'static_token' => Tools::getToken(false), - 'free_shipping' => $total_free_shipping + 'free_shipping' => $total_free_shipping, + 'test_pour_voir' => "test", )); if (count($errors)) $this->smarty->assign('errors', $errors); diff --git a/override/classes/CartRule.php b/override/classes/CartRule.php index 46f34e4d..7b73f1ac 100644 --- a/override/classes/CartRule.php +++ b/override/classes/CartRule.php @@ -184,7 +184,9 @@ class CartRule extends CartRuleCore if ($otherCartRule['gift_product']) --$nb_products; - if ($this->cart_rule_restriction && $otherCartRule['cart_rule_restriction'] && $otherCartRule['id_cart_rule'] != $this->id) + // ANTADIS FIX : if any restriction from one cart rule or the other, check it !!! + //if ($this->cart_rule_restriction && $otherCartRule['cart_rule_restriction'] && $otherCartRule['id_cart_rule'] != $this->id) + if (($this->cart_rule_restriction || $otherCartRule['cart_rule_restriction']) && $otherCartRule['id_cart_rule'] != $this->id) { $combinable = Db::getInstance()->getValue(' SELECT id_cart_rule_1 @@ -577,4 +579,192 @@ class CartRule extends CartRuleCore Db::getInstance()->execute($sql); } } + + public function isAnyCartProductInRestrictionlist(Context $context) + { + if (!$this->product_restriction) { + return true; + } + + return parent::checkProductRestrictions($context, false, false, false); + } + + + public static function getCustomerCartRulesByPriority($id_lang, $id_customer, $active = false, $includeGeneric = true, $inStock = false, Cart $cart = null) + { + if (!CartRule::isFeatureActive()) + return array(); + + // override antadis : add sorted by priority + $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' + SELECT * + FROM `'._DB_PREFIX_.'cart_rule` cr + LEFT JOIN `'._DB_PREFIX_.'cart_rule_lang` crl ON (cr.`id_cart_rule` = crl.`id_cart_rule` AND crl.`id_lang` = '.(int)$id_lang.') + WHERE ( + cr.`id_customer` = '.(int)$id_customer.' OR cr.group_restriction = 1 + '.($includeGeneric ? 'OR cr.`id_customer` = 0' : '').' + ) + AND cr.date_from < "'.date('Y-m-d H:i:s').'" + AND cr.date_to > "'.date('Y-m-d H:i:s').'" + '.($active ? 'AND cr.`active` = 1' : '').' + '.($inStock ? 'AND cr.`quantity` > 0' : '')." + ORDER BY cr.`priority`" + ); + + + // Remove cart rule that does not match the customer groups + $customerGroups = Customer::getGroupsStatic($id_customer); + + foreach ($result as $key => $cart_rule) + if ($cart_rule['group_restriction']) + { + $cartRuleGroups = Db::getInstance()->executeS('SELECT id_group FROM '._DB_PREFIX_.'cart_rule_group WHERE id_cart_rule = '.(int)$cart_rule['id_cart_rule']); + foreach ($cartRuleGroups as $cartRuleGroup) + if (in_array($cartRuleGroup['id_group'], $customerGroups)) + continue 2; + unset($result[$key]); + } + + foreach ($result as &$cart_rule) + if ($cart_rule['quantity_per_user']) + { + $quantity_used = Order::getDiscountsCustomer((int)$id_customer, (int)$cart_rule['id_cart_rule']); + if (isset($cart) && isset($cart->id)) + $quantity_used += $cart->getDiscountsCustomer((int)$cart_rule['id_cart_rule']); + $cart_rule['quantity_for_user'] = $cart_rule['quantity_per_user'] - $quantity_used; + } + else + $cart_rule['quantity_for_user'] = 0; + unset($cart_rule); + + foreach ($result as $key => $cart_rule) + if ($cart_rule['shop_restriction']) + { + $cartRuleShops = Db::getInstance()->executeS('SELECT id_shop FROM '._DB_PREFIX_.'cart_rule_shop WHERE id_cart_rule = '.(int)$cart_rule['id_cart_rule']); + foreach ($cartRuleShops as $cartRuleShop) + if (Shop::isFeatureActive() && ($cartRuleShop['id_shop'] == Context::getContext()->shop->id)) + continue 2; + unset($result[$key]); + } + + if (isset($cart) && isset($cart->id)) + foreach ($result as $key => $cart_rule) + if ($cart_rule['product_restriction']) + { + $cr = new CartRule((int)$cart_rule['id_cart_rule']); + $r = $cr->checkProductRestrictions(Context::getContext(), false, false); + if ($r !== false) + continue; + unset($result[$key]); + } + + foreach ($result as $key => $cart_rule) + if ($cart_rule['country_restriction']) + { + $countries = Db::getInstance()->ExecuteS(' + SELECT `id_country` + FROM `'._DB_PREFIX_.'address` + WHERE `id_customer` = '.(int)$id_customer.' + AND `deleted` = 0' + ); + + if (is_array($countries) && count($countries)) + foreach($countries as $country) + { + $id_cart_rule = (bool)Db::getInstance()->getValue(' + SELECT crc.id_cart_rule + FROM '._DB_PREFIX_.'cart_rule_country crc + WHERE crc.id_cart_rule = '.(int)$cart_rule['id_cart_rule'].' + AND crc.id_country = '.(int)$country['id_country']); + if (!$id_cart_rule) + unset($result[$key]); + } + } + + // Retrocompatibility with 1.4 discounts + foreach ($result as &$cart_rule) + { + $cart_rule['value'] = 0; + $cart_rule['minimal'] = Tools::convertPriceFull($cart_rule['minimum_amount'], new Currency($cart_rule['minimum_amount_currency']), Context::getContext()->currency); + $cart_rule['cumulable'] = !$cart_rule['cart_rule_restriction']; + $cart_rule['id_discount_type'] = false; + if ($cart_rule['free_shipping']) + $cart_rule['id_discount_type'] = Discount::FREE_SHIPPING; + elseif ($cart_rule['reduction_percent'] > 0) + { + $cart_rule['id_discount_type'] = Discount::PERCENT; + $cart_rule['value'] = $cart_rule['reduction_percent']; + } + elseif ($cart_rule['reduction_amount'] > 0) + { + $cart_rule['id_discount_type'] = Discount::AMOUNT; + $cart_rule['value'] = $cart_rule['reduction_amount']; + } + } + unset($cart_rule); + + return $result; + } + + + /** @Override [ticket 7902] */ + // override + // Previous override : understand business rule : + // If the cart contains any product not eligible for free shipping (in case there is any rule with free shipping) + // then the cart is not eligible. + // + // ticket 12906 - Addition to this business rule : + // The carts rules are ordered by priority + // the highest priority cart rules (minimal number) overrides other cart rules with products restricted (in case + // there no product in the restriction list) + // + static function getEligibilityAndMinimumAmount(Context $context) + { + $all_cart_rules = CartRule::getCustomerCartRulesByPriority($context->language->id, $context->customer->id, true, true, true); + $notEligible = false; + $previous_priority = 1; + + $cartRulesAlreadyInCart = $context->cart->getCartRules(CartRule::FILTER_ACTION_SHIPPING); + + if($all_cart_rules) { + foreach ($all_cart_rules as $key => $cart_rule) { + if($cart_rule['id_discount_type'] == Discount::FREE_SHIPPING){ + $cr = new CartRule((int)$cart_rule['id_cart_rule']); + + // if this cart rule restrict to only N products and no cart product is in this restriction list, + // check if there was a previous eligible free shipping cart rule. + // if it is the case : skip this one. + // if not, it is not eligible + if (!$cr->isAnyCartProductInRestrictionlist($context)) { + if ($is_cart_valid && $cr->priority > $previous_priority ) { + continue; + } + } + + $previous_priority = $cr->priority; + + $is_cart_valid = $cr->checkValidityWithoutAmount($context,false,false); + if($is_cart_valid && $cart_rule['minimal']>0){ + if(!isset($minimum_amount)) { + $minimum_amount = $cart_rule['minimal']; + } + if($minimum_amount < $cart_rule['minimal']) { + continue; + } + $minimum_amount = ($minimum_amount < $cart_rule['minimal'])?$minimum_amount:$cart_rule['minimal']; + $minimum_amount_tax = (int)$cart_rule['minimum_amount_tax'] ; + } elseif (!$is_cart_valid && empty($cartRulesAlreadyInCart)) { + $notEligible = true; + } + } + } + } + + return array( + 'cartRulesAlreadyInCart' => $cartRulesAlreadyInCart, + 'notEligible' => $notEligible, + 'minimum_amount' => isset($minimum_amount) ? $minimum_amount : 0, + 'minimum_amount_tax' => isset($minimum_amount_tax) ? $minimum_amount_tax : 0 + ); + } } diff --git a/override/controllers/front/CartController.php b/override/controllers/front/CartController.php index 8d7cab8b..caca48e5 100644 --- a/override/controllers/front/CartController.php +++ b/override/controllers/front/CartController.php @@ -57,7 +57,13 @@ class CartController extends CartControllerCore $result['customizedDatas'] = Product::getAllCustomizedDatas($this->context->cart->id, null, true); $result['HOOK_SHOPPING_CART'] = Hook::exec('displayShoppingCartFooter', $result['summary']); $result['HOOK_SHOPPING_CART_EXTRA'] = Hook::exec('displayShoppingCart', $result['summary']); - +/* + $infos = CartRule::getEligibilityAndMinimumAmount($this->context); + $minimum_amount = $infos['minimum_amount']; + $minimum_amount_tax = $infos['minimum_amount_tax']; + $notEligible = $infos['notEligible']; + $cartRulesAlreadyInCart = $infos['cartRulesAlreadyInCart']; +*/ $all_cart_rules = CartRule::getCustomerCartRules($this->context->language->id, $this->context->customer->id, true, true, true); $notEligible = false; $cartRulesAlreadyInCart = $this->context->cart->getCartRules(CartRule::FILTER_ACTION_SHIPPING); @@ -78,6 +84,7 @@ class CartController extends CartControllerCore } } } +error_log('cartcontroller - notEligible ?'.($notEligible?'true':'false')); $free_shipping_ok = false; if (!empty($cartRulesAlreadyInCart)) { $free_shipping_ok = true; diff --git a/override/controllers/front/OrderController.php b/override/controllers/front/OrderController.php index 7efb1397..b797c670 100644 --- a/override/controllers/front/OrderController.php +++ b/override/controllers/front/OrderController.php @@ -240,13 +240,38 @@ class OrderController extends OrderControllerCore } // override + // Previous override : understand business rule : + // If the cart contains any product not eligible for free shipping (in case there is any rule with free shipping) + // then the cart is not eligible. + // + // ticket 12906 - Addition to this business rule : + // The carts rules are ordered by priority + // the highest priority cart rules (minimal number) overrides other cart rules with products restricted (in case + // there no product in the restriction list) + // $notEligible = false; - $all_cart_rules = CartRule::getCustomerCartRules($this->context->language->id, $this->context->customer->id, true, true, true); + $all_cart_rules = CartRule::getCustomerCartRulesByPriority($this->context->language->id, $this->context->customer->id, true, true, true); + $previous_priority = 1; + $cartRulesAlreadyInCart = $this->context->cart->getCartRules(CartRule::FILTER_ACTION_SHIPPING); foreach ($all_cart_rules as $key => $cart_rule) { if($cart_rule['id_discount_type'] == Discount::FREE_SHIPPING){ $cr = new CartRule((int)$cart_rule['id_cart_rule']); - if($cr->checkValidityWithoutAmount($this->context,false,false) && $cart_rule['minimal']>0){ + + // if this cart rule restrict to only N products and no cart product is in this restriction list, + // check if there was a previous eligible free shipping cart rule. + // if it is the case : skip this one. + // if not, it is not eligible + if (!$cr->isAnyCartProductInRestrictionlist($this->context)) { + if ($is_cart_valid && $cr->priority > $previous_priority ) { + continue; + } + } + + $previous_priority = $cr->priority; + + $is_cart_valid = $cr->checkValidityWithoutAmount($this->context,false,false); + if($is_cart_valid && $cart_rule['minimal']>0){ if(!isset($minimum_amount)) { $minimum_amount = $cart_rule['minimal']; } @@ -255,7 +280,7 @@ class OrderController extends OrderControllerCore } $minimum_amount = ($minimum_amount < $cart_rule['minimal'])?$minimum_amount:$cart_rule['minimal']; $minimum_amount_tax = (int)$cart_rule['minimum_amount_tax'] ; - } elseif (!$cr->checkValidityWithoutAmount($this->context,false,false) && empty($cartRulesAlreadyInCart)) { + } elseif (!$is_cart_valid && empty($cartRulesAlreadyInCart)) { $notEligible = true; } } @@ -328,14 +353,49 @@ class OrderController extends OrderControllerCore // Db::getInstance()->delete('cart_rule_combination','id_cart_rule_1='.$row['id_cart_rule_sponsor'].' OR id_cart_rule_2='.$row['id_cart_rule_sponsor']); // } + /** @Override [ticket 7902] */ - $all_cart_rules = CartRule::getCustomerCartRules($this->context->language->id, $this->context->customer->id, true, true, true); + // override + // Previous override : understand business rule : + // If the cart contains any product not eligible for free shipping (in case there is any rule with free shipping) + // then the cart is not eligible. + // + // ticket 12906 - Addition to this business rule : + // The carts rules are ordered by priority + // the highest priority cart rules (minimal number) overrides other cart rules with products restricted (in case + // there no product in the restriction list) + // + /* + $infos = CartRule::getEligibilityAndMinimumAmount($this->context); + $minimum_amount = $infos['minimum_amount']; + $minimum_amount_tax = $infos['minimum_amount_tax']; + $notEligible = $infos['notEligible']; + $cartRulesAlreadyInCart = $infos['cartRulesAlreadyInCart']; + + */ + $all_cart_rules = CartRule::getCustomerCartRulesByPriority($this->context->language->id, $this->context->customer->id, true, true, true); $notEligible = false; + $previous_priority = 1; + $cartRulesAlreadyInCart = $this->context->cart->getCartRules(CartRule::FILTER_ACTION_SHIPPING); foreach ($all_cart_rules as $key => $cart_rule) { if($cart_rule['id_discount_type'] == Discount::FREE_SHIPPING){ $cr = new CartRule((int)$cart_rule['id_cart_rule']); - if($cr->checkValidityWithoutAmount($this->context,false,false) && $cart_rule['minimal']>0){ + + // if this cart rule restrict to only N products and no cart product is in this restriction list, + // check if there was a previous eligible free shipping cart rule. + // if it is the case : skip this one. + // if not, it is not eligible + if (!$cr->isAnyCartProductInRestrictionlist($this->context)) { + if ($is_cart_valid && $cr->priority > $previous_priority ) { + continue; + } + } + + $previous_priority = $cr->priority; + + $is_cart_valid = $cr->checkValidityWithoutAmount($this->context,false,false); + if($is_cart_valid && $cart_rule['minimal']>0){ if(!isset($minimum_amount)) { $minimum_amount = $cart_rule['minimal']; } @@ -344,11 +404,13 @@ class OrderController extends OrderControllerCore } $minimum_amount = ($minimum_amount < $cart_rule['minimal'])?$minimum_amount:$cart_rule['minimal']; $minimum_amount_tax = (int)$cart_rule['minimum_amount_tax'] ; - } elseif (!$cr->checkValidityWithoutAmount($this->context,false,false) && empty($cartRulesAlreadyInCart)) { + } elseif (!$is_cart_valid && empty($cartRulesAlreadyInCart)) { $notEligible = true; } } } + + $free_shipping_ok = false; if (!empty($cartRulesAlreadyInCart)) { $free_shipping_ok = true;