Jump to content

création bon de réduction hors produits déjà soldé non possible ?


Recommended Posts

Bonjour,

 

je ne comprend pas les bons de réductions sur ps 1.5.4

 

je veux créer une remise en % à un groupe de clients.

 

j'ai créer un bon avec comme règle un groupe sélectionné, mais je voudrais que le bon

 

ne soit appliqué que si le produits n'est pas déjà soldé !!

 

hors je n'ai pas pu trouver comment créer un bon de remise ni en passant par regle de panier

ni par règle de prix catalogue ?

 

mon bon s'ajoute a mon panier même si le produit est déjà soldé ?

 

il me semble que avant avec ps 1.4 on pouvait mettre la règle que si le produit est déjà soldé

 

le bon ne peux être utilisé ??

 

y a t 'il une solution svp

 

je suis assez pressé

merci

Link to comment
Share on other sites

Bonjour,

je suis étonné que personne n'est répondu sur ce problème simple ?

 

ce forum n'est quand même pas vraiment très actif aux vu des questions posés et aux nombres des réponses !

 

pour ce problème j'ai fini par trouver, il faut juste mettre dans l'ordre des priorités la position 2 pour que le bon créer ne s'applique pas aux produits déjà soldé !!

Link to comment
Share on other sites

  • 2 weeks later...

Bonjour,

 

Je suis entrain de faire le même type de recherche pour le même soucis, pas simple de trouver des réponses!

 

Je suis actuellement sur OScommerce et je prévois la migration vers le 1.5.4. Sur la version actuel, les codes de réductions ne s'applique pas au produits déjà en promo.

 

Ce qui ne semble pas possible de faire sur prestashop 1.5.4!

 

Est ce que la "solution" de le mettre en priorité 2 est la bonne et efficace à 100%?

 

Merci

Link to comment
Share on other sites

Bonjour,

 

Oui ca fonctionne chez moi si un produit déja en promo, avec un bon en priorité a deux le bon ne s'applique pas,

par contre si il y a deux produits dans le panier un en promo l'autre pas, alors le bon fonctionne et ajoute la réduction sur le produit qui est déjà soldé. Donc pas bon!

 

J'ai fais une vente privé et j'ai eu pas mal de problèmes, ps 1.5 de base ne gère pas très bien les bons, ils ont voulu faire plus d'options, mais en fait ils ont oublier les fonctions de bases!

 

C'est pour ça que je laisse tomber les bons de promos de ps 1.5, je préfère attendre que mes dev me livre mon module spécifique bon de réductions avec les options que j'ai demandé, ce sera moins galère.

Link to comment
Share on other sites

Re,

 

J'ai testé, même en priorité 10, le coupon de réduction s'applique au produit déjà en promo...

 

Quelqu'un à une solution "miracle".

 

L'idéal serait de pouvoir sélectionner dans les exclusions, "produit déjà soldé"

Link to comment
Share on other sites

c'est en cours par mes dev, comme j'ai cherché et que j'ai rien trouve !

j'ai fais une demande de module, il sera dispo semaine prochaine en principe !

 

je leurs dirais qu'il pourront le mettre en vente sur addons, vu le nombre de personnes qui cherche une solution o)

  • Like 1
Link to comment
Share on other sites

Bonjour PAC6230,

 

As-tu vérifié que tu n'avais pas coché l'option "compatible avec les autres regles paniers" ?

Les règles paniers et leurs priorités se gèrent avec leur numéro respectif ...

La doc prestashop ici.

 

Solution alternative:

Je sais que le module Maxi-Promo arrive bien à gérer ce genre de règles. (Personnellement je n'aime pas ce module, mais il faut avouer que sur ce point là, il fonctionne bien.)

Link to comment
Share on other sites

Bonjour Daskoff,

 

Je pense avoir tout essayé, cela ne change rien :(

 

Par contre, je ne comprends pas "Les règles paniers et leurs priorités se gèrent avec leur numéro respectif ..."

Se sont les priorités?

 

Je vais regarder le module Maxi-promo

Link to comment
Share on other sites

Excuse moi je m'étais mal exprimé.

"Les priorités des règles paniers se gèrent avec leurs numéro de priorité" (N°1 - N°2 - etc)

 

Après, je ne veux pas m'avancer et dire que ce n'est pas possible sans module, mais en revanche, je suis sur que Maxi Promo le fait. (pour l'avoir utilisé .. ou du moins tenté) :)

 

[ Petite question ... Créer des groupes/familles de promotions dans "règles panier" c'est possible ou pas ?

Parce que j'en ai créée environ 80, et j'aimerai les activer/désactiver d'un coup .. ]

Link to comment
Share on other sites

  • 3 weeks later...

Résolu pour moi,

mes dev ce sont servi d'un module que j'avais pour créer un nouveau module bon de réductions,

qui fonctionne très bien,

si produits en promo choix cumulable ou pas sur promo, cumulable ou pas avec les autres bons.

si deux produits un en promo l'autre pas, le bon ne fonctionne que sur le produit prix normal, et ne touche pas les prods en promo.

création du bon par clients, ou par groupes clients.

tiens compte des frais de ports, (avec les bon de ps par défauts les frais était compté une fois oui une fois non sans explications?)

un vrai bonheurs par rapport à l'utilisation des fonctions de ps qui sont incompréhensibles, et non adapté à une utilisation en production.

Link to comment
Share on other sites

  • 5 weeks later...
  • 1 month later...

Bonjour,

 

en effet cela était possible en 1.4 mais pas en 1.5 ...

 

En faisant l'override de la classe CartRule on s'en sort très bien !

 

Il s'agit de la méthode "public function checkValidity" :

 

il faut rajouter : 

$products = $context->cart->getProducts();
$product_on_sale = false;
foreach($products as $product){
    if(!empty($product["reduction_applies"]) && $product["reduction_applies"] > 0)
        $product_on_sale = true;
}
if ($product_on_sale)
    return (!$display_error) ? false : Tools::displayError('This voucher isn\'t cumulative on products with reduction or marked as on sale');

Il faut place cela après le code suivant : (je vous incite fortement à utiliser l'override pour faire la modification.)

if (strtotime($this->date_to) < time())
    return (!$display_error) ? false : Tools::displayError('This voucher has expired');

Ce qui donne une fonction "checkValidity" qui ressemble à ça : 

public function checkValidity(Context $context, $alreadyInCart = false, $display_error = true)
{
		if (!CartRule::isFeatureActive())
			return false;

		if (!$this->active)
			return (!$display_error) ? false : Tools::displayError('This voucher is disabled');
		if (!$this->quantity)
			return (!$display_error) ? false : Tools::displayError('This voucher has already been used');
		if (strtotime($this->date_from) > time())
			return (!$display_error) ? false : Tools::displayError('This voucher is not valid yet');
		if (strtotime($this->date_to) < time())
			return (!$display_error) ? false : Tools::displayError('This voucher has expired');
		$products = $context->cart->getProducts();
		$product_on_sale = false;
		foreach($products as $product){
			if(!empty($product["reduction_applies"]) && $product["reduction_applies"] > 0)
				$product_on_sale = true;
		}
		if ($product_on_sale)
			return (!$display_error) ? false : Tools::displayError('This voucher isn\'t cumulative on products with reduction or marked as on sale');
		if ($context->cart->id_customer)
		{
			$quantityUsed = Db::getInstance()->getValue('
			SELECT count(*)
			FROM '._DB_PREFIX_.'orders o
			LEFT JOIN '._DB_PREFIX_.'order_cart_rule od ON o.id_order = od.id_order
			WHERE o.id_customer = '.$context->cart->id_customer.'
			AND od.id_cart_rule = '.(int)$this->id.'
			AND '.(int)Configuration::get('PS_OS_ERROR').' != (
				SELECT oh.id_order_state
				FROM '._DB_PREFIX_.'order_history oh
				WHERE oh.id_order = o.id_order
				ORDER BY oh.date_add DESC
				LIMIT 1
			)');
			if ($quantityUsed + 1 > $this->quantity_per_user)
				return (!$display_error) ? false : Tools::displayError('You cannot use this voucher anymore (usage limit reached)');
		}

		// Get an intersection of the customer groups and the cart rule groups (if the customer is not logged in, the default group is 1)
		if ($this->group_restriction)
		{
			$id_cart_rule = (int)Db::getInstance()->getValue('
			SELECT crg.id_cart_rule
			FROM '._DB_PREFIX_.'cart_rule_group crg
			WHERE crg.id_cart_rule = '.(int)$this->id.'
			AND crg.id_group '.($context->cart->id_customer ? 'IN (SELECT cg.id_group FROM '._DB_PREFIX_.'customer_group cg WHERE cg.id_customer = '.(int)$context->cart->id_customer.')' : '= 1'));
			if (!$id_cart_rule)
				return (!$display_error) ? false : Tools::displayError('You cannot use this voucher');
		}

		// Check if the customer delivery address is usable with the cart rule
		if ($this->country_restriction)
		{
			if (!$context->cart->id_address_delivery)
				return (!$display_error) ? false : Tools::displayError('You must choose a delivery address before applying this voucher to your order');
			$id_cart_rule = (int)Db::getInstance()->getValue('
			SELECT crc.id_cart_rule
			FROM '._DB_PREFIX_.'cart_rule_country crc
			WHERE crc.id_cart_rule = '.(int)$this->id.'
			AND crc.id_country = (SELECT a.id_country FROM '._DB_PREFIX_.'address a WHERE a.id_address = '.(int)$context->cart->id_address_delivery.' LIMIT 1)');
			if (!$id_cart_rule)
				return (!$display_error) ? false : Tools::displayError('You cannot use this voucher in your country of delivery');
		}

		// Check if the carrier chosen by the customer is usable with the cart rule
		if ($this->carrier_restriction)
		{
			if (!$context->cart->id_carrier)
				return (!$display_error) ? false : Tools::displayError('You must choose a carrier before applying this voucher to your order');
			$id_cart_rule = (int)Db::getInstance()->getValue('
			SELECT crc.id_cart_rule
			FROM '._DB_PREFIX_.'cart_rule_carrier crc
			INNER JOIN '._DB_PREFIX_.'carrier c ON (c.id_reference = crc.id_carrier AND c.deleted = 0)
			WHERE crc.id_cart_rule = '.(int)$this->id.'
			AND c.id_carrier = '.(int)$context->cart->id_carrier);
			if (!$id_cart_rule)
				return (!$display_error) ? false : Tools::displayError('You cannot use this voucher with this carrier');
		}

		// Check if the cart rules appliy to the shop browsed by the customer
		if ($this->shop_restriction && $context->shop->id && Shop::isFeatureActive())
		{
			$id_cart_rule = (int)Db::getInstance()->getValue('
			SELECT crs.id_cart_rule
			FROM '._DB_PREFIX_.'cart_rule_shop crs
			WHERE crs.id_cart_rule = '.(int)$this->id.'
			AND crs.id_shop = '.(int)$context->shop->id);
			if (!$id_cart_rule)
				return (!$display_error) ? false : Tools::displayError('You cannot use this voucher');
		}

		// Check if the products chosen by the customer are usable with the cart rule
		if ($this->product_restriction)
		{
			$r = $this->checkProductRestrictions($context, false, $display_error);
			if ($r !== false && $display_error)
				return $r;
			elseif (!$r && !$display_error)
				return false;
		}

		// Check if the cart rule is only usable by a specific customer, and if the current customer is the right one
		if ($this->id_customer && $context->cart->id_customer != $this->id_customer)
		{
			if (!Context::getContext()->customer->isLogged())
				return (!$display_error) ? false : (Tools::displayError('You cannot use this voucher').' - '.Tools::displayError('Please log in'));
			return (!$display_error) ? false : Tools::displayError('You cannot use this voucher');
		}

		if ($this->minimum_amount)
		{
			// Minimum amount is converted to the default currency
			$minimum_amount = $this->minimum_amount;
			if ($this->minimum_amount_currency != Configuration::get('PS_CURRENCY_DEFAULT'))
			{
				$minimum_amount_currency = new Currency($this->minimum_amount_currency);
				if ($this->minimum_amount == 0 || $minimum_amount_currency->conversion_rate == 0)
					$minimum_amount = 0;
				else
					$minimum_amount = $this->minimum_amount / $minimum_amount_currency->conversion_rate;
			}

			$cartTotal = $context->cart->getOrderTotal($this->minimum_amount_tax, Cart::ONLY_PRODUCTS);
			if ($this->minimum_amount_shipping)
				$cartTotal += $context->cart->getOrderTotal($this->minimum_amount_tax, Cart::ONLY_SHIPPING);

			// If a product is given for free in this rule and already in the cart, the price is subtracted
			if ($this->gift_product && $alreadyInCart)
			{
				$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(
						$this->gift_product,
						$this->minimum_amount_tax,
						$this->gift_product_attribute,
						null, null, false, true, 1, null,
						$context->cart->id_customer ? $context->cart->id_customer : null,
						$context->cart->id,
						(int)$context->cart->{Configuration::get('PS_TAX_ADDRESS_TYPE')} ? (int)$context->cart->{Configuration::get('PS_TAX_ADDRESS_TYPE')} : null,
						$ref, true, true, $context, true
					);
					$cartTotal -= $product_price;
				}
			}

			if ($cartTotal < $minimum_amount)
				return (!$display_error) ? false : Tools::displayError('You have not reached the minimum amount required to use this voucher');
		}
		
		// Check if the voucher is already in the cart of if a non compatible voucher is in the cart
		// Important note: this MUST be the last check, because if the tested cart rule has priority over a non combinable one in the cart, we will switch them
		$otherCartRules = $context->cart->getCartRules();
		if (count($otherCartRules))
			foreach ($otherCartRules as $otherCartRule)
			{
				if ($otherCartRule['id_cart_rule'] == $this->id && !$alreadyInCart)
					return (!$display_error) ? false : Tools::displayError('This voucher is already in your cart');
				if ($this->cart_rule_restriction && $otherCartRule['cart_rule_restriction'] && $otherCartRule['id_cart_rule'] != $this->id)
				{
					$combinable = Db::getInstance()->getValue('
					SELECT id_cart_rule_1
					FROM '._DB_PREFIX_.'cart_rule_combination
					WHERE (id_cart_rule_1 = '.(int)$this->id.' AND id_cart_rule_2 = '.(int)$otherCartRule['id_cart_rule'].')
					OR (id_cart_rule_2 = '.(int)$this->id.' AND id_cart_rule_1 = '.(int)$otherCartRule['id_cart_rule'].')');
					if (!$combinable)
					{
						$cart_rule = new CartRule((int)$otherCartRule['id_cart_rule'], $context->cart->id_lang);
						// The cart rules are not combinable and the cart rule currently in the cart has priority over the one tested
						if ($cart_rule->priority <= $this->priority)
							return (!$display_error) ? false : Tools::displayError('This voucher is not combinable with an other voucher already in your cart:').' '.$cart_rule->name;
						// But if the cart rule that is tested has priority over the one in the cart, we remove the one in the cart and keep this new one
						else
							$context->cart->removeCartRule($cart_rule->id);
					}
				}
			}
		
		if (!$display_error)
			return true;
}

(à placer dans override/classes/CartRule.php)

 

 

Cordialement,

Edited by Manuel Corbet (see edit history)
  • Like 1
Link to comment
Share on other sites

  • 6 months later...

Bonjour,

 

J'ai essayé votre méthode mais pour ma part ça ne fonctionne pas. Les produits en promotions bénéficient toujours du code de réduction. Snif snif.

Si quelqu'un à une autre idée...

Link to comment
Share on other sites

Après une nuit de sommeil, je comprends que je ne fais pas la modif sur le bon serveur ^^

Sur que si je bidouille à droite et regarde à gauche, je ne vois rien...

Merci pour cette contribution.

 

Surflibre, j'ai fait la modification sur le fichier cartrules.php situé dans le dossier classes de mon répertoire principal et non dans l'override.

Edited by Kloan (see edit history)
Link to comment
Share on other sites

  • 2 weeks later...

Bonjour,

 

en effet cela était possible en 1.4 mais pas en 1.5 ...

 

En faisant l'override de la classe CartRule on s'en sort très bien !

 

Il s'agit de la méthode "public function checkValidity" :

 

il faut rajouter : 

$products = $context->cart->getProducts();
$product_on_sale = false;
foreach($products as $product){
    if(!empty($product["reduction_applies"]) && $product["reduction_applies"] > 0)
        $product_on_sale = true;
}
if ($product_on_sale)
    return (!$display_error) ? false : Tools::displayError('This voucher isn\'t cumulative on products with reduction or marked as on sale');

Il faut place cela après le code suivant : (je vous incite fortement à utiliser l'override pour faire la modification.)

if (strtotime($this->date_to) < time())
    return (!$display_error) ? false : Tools::displayError('This voucher has expired');

Ce qui donne une fonction "checkValidity" qui ressemble à ça : 

public function checkValidity(Context $context, $alreadyInCart = false, $display_error = true)
{
		if (!CartRule::isFeatureActive())
			return false;

		if (!$this->active)
			return (!$display_error) ? false : Tools::displayError('This voucher is disabled');
		if (!$this->quantity)
			return (!$display_error) ? false : Tools::displayError('This voucher has already been used');
		if (strtotime($this->date_from) > time())
			return (!$display_error) ? false : Tools::displayError('This voucher is not valid yet');
		if (strtotime($this->date_to) < time())
			return (!$display_error) ? false : Tools::displayError('This voucher has expired');
		$products = $context->cart->getProducts();
		$product_on_sale = false;
		foreach($products as $product){
			if(!empty($product["reduction_applies"]) && $product["reduction_applies"] > 0)
				$product_on_sale = true;
		}
		if ($product_on_sale)
			return (!$display_error) ? false : Tools::displayError('This voucher isn\'t cumulative on products with reduction or marked as on sale');
		if ($context->cart->id_customer)
		{
			$quantityUsed = Db::getInstance()->getValue('
			SELECT count(*)
			FROM '._DB_PREFIX_.'orders o
			LEFT JOIN '._DB_PREFIX_.'order_cart_rule od ON o.id_order = od.id_order
			WHERE o.id_customer = '.$context->cart->id_customer.'
			AND od.id_cart_rule = '.(int)$this->id.'
			AND '.(int)Configuration::get('PS_OS_ERROR').' != (
				SELECT oh.id_order_state
				FROM '._DB_PREFIX_.'order_history oh
				WHERE oh.id_order = o.id_order
				ORDER BY oh.date_add DESC
				LIMIT 1
			)');
			if ($quantityUsed + 1 > $this->quantity_per_user)
				return (!$display_error) ? false : Tools::displayError('You cannot use this voucher anymore (usage limit reached)');
		}

		// Get an intersection of the customer groups and the cart rule groups (if the customer is not logged in, the default group is 1)
		if ($this->group_restriction)
		{
			$id_cart_rule = (int)Db::getInstance()->getValue('
			SELECT crg.id_cart_rule
			FROM '._DB_PREFIX_.'cart_rule_group crg
			WHERE crg.id_cart_rule = '.(int)$this->id.'
			AND crg.id_group '.($context->cart->id_customer ? 'IN (SELECT cg.id_group FROM '._DB_PREFIX_.'customer_group cg WHERE cg.id_customer = '.(int)$context->cart->id_customer.')' : '= 1'));
			if (!$id_cart_rule)
				return (!$display_error) ? false : Tools::displayError('You cannot use this voucher');
		}

		// Check if the customer delivery address is usable with the cart rule
		if ($this->country_restriction)
		{
			if (!$context->cart->id_address_delivery)
				return (!$display_error) ? false : Tools::displayError('You must choose a delivery address before applying this voucher to your order');
			$id_cart_rule = (int)Db::getInstance()->getValue('
			SELECT crc.id_cart_rule
			FROM '._DB_PREFIX_.'cart_rule_country crc
			WHERE crc.id_cart_rule = '.(int)$this->id.'
			AND crc.id_country = (SELECT a.id_country FROM '._DB_PREFIX_.'address a WHERE a.id_address = '.(int)$context->cart->id_address_delivery.' LIMIT 1)');
			if (!$id_cart_rule)
				return (!$display_error) ? false : Tools::displayError('You cannot use this voucher in your country of delivery');
		}

		// Check if the carrier chosen by the customer is usable with the cart rule
		if ($this->carrier_restriction)
		{
			if (!$context->cart->id_carrier)
				return (!$display_error) ? false : Tools::displayError('You must choose a carrier before applying this voucher to your order');
			$id_cart_rule = (int)Db::getInstance()->getValue('
			SELECT crc.id_cart_rule
			FROM '._DB_PREFIX_.'cart_rule_carrier crc
			INNER JOIN '._DB_PREFIX_.'carrier c ON (c.id_reference = crc.id_carrier AND c.deleted = 0)
			WHERE crc.id_cart_rule = '.(int)$this->id.'
			AND c.id_carrier = '.(int)$context->cart->id_carrier);
			if (!$id_cart_rule)
				return (!$display_error) ? false : Tools::displayError('You cannot use this voucher with this carrier');
		}

		// Check if the cart rules appliy to the shop browsed by the customer
		if ($this->shop_restriction && $context->shop->id && Shop::isFeatureActive())
		{
			$id_cart_rule = (int)Db::getInstance()->getValue('
			SELECT crs.id_cart_rule
			FROM '._DB_PREFIX_.'cart_rule_shop crs
			WHERE crs.id_cart_rule = '.(int)$this->id.'
			AND crs.id_shop = '.(int)$context->shop->id);
			if (!$id_cart_rule)
				return (!$display_error) ? false : Tools::displayError('You cannot use this voucher');
		}

		// Check if the products chosen by the customer are usable with the cart rule
		if ($this->product_restriction)
		{
			$r = $this->checkProductRestrictions($context, false, $display_error);
			if ($r !== false && $display_error)
				return $r;
			elseif (!$r && !$display_error)
				return false;
		}

		// Check if the cart rule is only usable by a specific customer, and if the current customer is the right one
		if ($this->id_customer && $context->cart->id_customer != $this->id_customer)
		{
			if (!Context::getContext()->customer->isLogged())
				return (!$display_error) ? false : (Tools::displayError('You cannot use this voucher').' - '.Tools::displayError('Please log in'));
			return (!$display_error) ? false : Tools::displayError('You cannot use this voucher');
		}

		if ($this->minimum_amount)
		{
			// Minimum amount is converted to the default currency
			$minimum_amount = $this->minimum_amount;
			if ($this->minimum_amount_currency != Configuration::get('PS_CURRENCY_DEFAULT'))
			{
				$minimum_amount_currency = new Currency($this->minimum_amount_currency);
				if ($this->minimum_amount == 0 || $minimum_amount_currency->conversion_rate == 0)
					$minimum_amount = 0;
				else
					$minimum_amount = $this->minimum_amount / $minimum_amount_currency->conversion_rate;
			}

			$cartTotal = $context->cart->getOrderTotal($this->minimum_amount_tax, Cart::ONLY_PRODUCTS);
			if ($this->minimum_amount_shipping)
				$cartTotal += $context->cart->getOrderTotal($this->minimum_amount_tax, Cart::ONLY_SHIPPING);

			// If a product is given for free in this rule and already in the cart, the price is subtracted
			if ($this->gift_product && $alreadyInCart)
			{
				$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(
						$this->gift_product,
						$this->minimum_amount_tax,
						$this->gift_product_attribute,
						null, null, false, true, 1, null,
						$context->cart->id_customer ? $context->cart->id_customer : null,
						$context->cart->id,
						(int)$context->cart->{Configuration::get('PS_TAX_ADDRESS_TYPE')} ? (int)$context->cart->{Configuration::get('PS_TAX_ADDRESS_TYPE')} : null,
						$ref, true, true, $context, true
					);
					$cartTotal -= $product_price;
				}
			}

			if ($cartTotal < $minimum_amount)
				return (!$display_error) ? false : Tools::displayError('You have not reached the minimum amount required to use this voucher');
		}
		
		// Check if the voucher is already in the cart of if a non compatible voucher is in the cart
		// Important note: this MUST be the last check, because if the tested cart rule has priority over a non combinable one in the cart, we will switch them
		$otherCartRules = $context->cart->getCartRules();
		if (count($otherCartRules))
			foreach ($otherCartRules as $otherCartRule)
			{
				if ($otherCartRule['id_cart_rule'] == $this->id && !$alreadyInCart)
					return (!$display_error) ? false : Tools::displayError('This voucher is already in your cart');
				if ($this->cart_rule_restriction && $otherCartRule['cart_rule_restriction'] && $otherCartRule['id_cart_rule'] != $this->id)
				{
					$combinable = Db::getInstance()->getValue('
					SELECT id_cart_rule_1
					FROM '._DB_PREFIX_.'cart_rule_combination
					WHERE (id_cart_rule_1 = '.(int)$this->id.' AND id_cart_rule_2 = '.(int)$otherCartRule['id_cart_rule'].')
					OR (id_cart_rule_2 = '.(int)$this->id.' AND id_cart_rule_1 = '.(int)$otherCartRule['id_cart_rule'].')');
					if (!$combinable)
					{
						$cart_rule = new CartRule((int)$otherCartRule['id_cart_rule'], $context->cart->id_lang);
						// The cart rules are not combinable and the cart rule currently in the cart has priority over the one tested
						if ($cart_rule->priority <= $this->priority)
							return (!$display_error) ? false : Tools::displayError('This voucher is not combinable with an other voucher already in your cart:').' '.$cart_rule->name;
						// But if the cart rule that is tested has priority over the one in the cart, we remove the one in the cart and keep this new one
						else
							$context->cart->removeCartRule($cart_rule->id);
					}
				}
			}
		
		if (!$display_error)
			return true;
}

(à placer dans override/classes/CartRule.php)

 

 

Cordialement,

 

C'est parfait ça :) Merci

Link to comment
Share on other sites

  • 1 month later...

Si je peux me permettre, le code de Manuel fonctionne mais il refuse le coupon sur tous les articles lorsque seulement un des article est en promo dans le panier. Il faudrait qu'il ne s'applique que sur les articles qui ne sont pas en promo et qu'il soit valide pour les autres...

Link to comment
Share on other sites

  • 9 months later...

Je relance le sujet (version 1.5.2) :

 

J'ai un bon début de solution pour appliquer une réduction à tous les produits sauf ceux déjà en promotion.

 

il faut faire un override de la fonction "getContextualValue" dans la class "CartRule"

 

Pour ma part j'ai une reduction automatique qui s'applique à partir d'un certain montant et sur certaines catégories.

et je ne voulais pas que cette réduction s'applique aux produits déjà en promotion.

 

j'ai donc chercher dans la fonction "getContextualValue" le if correspondant et rajouter une condition assez simple !

 

voilà la partie qui me concerne :

// Discount (%) on the selection of products
        if ($this->reduction_percent && $this->reduction_product == -2)
        {
            $selected_products_reduction = 0;
            $selected_products = $this->checkProductRestrictions($context, true);
            
            if (is_array($selected_products)){
                foreach ($package_products as $product){
                    //pour ne pas appliquer la reduction automatique aux promotions et dans la condition suivante on rajoute "and !$product_on_sale"
                    if(!empty($product["reduction_applies"]) && $product["reduction_applies"] > 0)
                        $product_on_sale = true;
                        //fin
                    if ( (in_array($product['id_product'].'-'.$product['id_product_attribute'], $selected_products)
                                    || in_array($product['id_product'].'-0', $selected_products)) and !$product_on_sale )
                    {
                        $price = ($use_tax ? $product['price_wt'] : $product['price']);
                        $selected_products_reduction += $price * $product['cart_quantity'];
                    }
                }
            }
            $reduction_value += $selected_products_reduction * $this->reduction_percent / 100;
        }

en analysant le code on peut voir que pour chaque produit on regarde s'il est en promotion, si c'est le cas on a ajouté une condition qui permet de ne pas appliquer la réduction.

 

ça fonction pour ma règle panier qui est particulière.

Maintenant si vous avez une autre règle panier veillez à adapter et à faire la modification dans la bonne condition (if) de cette fonction.

 

j'espère que ça aidera certain qui cherche encore...

Edited by Fabien_ss2i (see edit history)
Link to comment
Share on other sites

  • 3 weeks later...

J'ai trouvé !!!
Dans "Conditions" inclure les catégories sur lesquelles vous souhaitez que le bon de réduction s'applique.
Dans "Action" / "Appliquer la réduction à " / "Produits sélectionnés"

 

Vos bons de réductions s'appliqueront uniquement aux produits dans les catégories sélectionnées.

 

J'ai galéré 2 heures !!

Link to comment
Share on other sites

  • 1 year later...

Bonjour,

 

je reviens sur ce vieux topic, en effet le code de checkvalidity fonctionne très bien mais au final bloque un peu tout.

 

en effet puisqu'on joue sur du true/false il n'y a pas de demi mesure, hors si j'ai par exemple,

 

un peignoir en réduction et une serviette dans mon panier, et que je harcèle le commercial pour avoir une remise de 10% j'aimerais que mon bon ne s'applique que sur ma serviette et pas sur mon peignoir ! hors la il ne s'applique pas du tout, cela deplaira surement a mes client friands de petites attentions de ce genre.

 

quelqu'un à une solution pour que le check validity fonctionne mais pour le bypass quand même lorsque l'ont trouve un autre produit?

 

merci beaucoup !

  • Like 1
Link to comment
Share on other sites

  • 4 months later...

Parti sur la piste de "Fabien_ss2i" j'ai modifié la fonction "getContextualValue" du fichier CartRule.php

 

Les règles panier s'appliqueront à tout sauf les produits en promo.

 

J'ai commenté le code pour s'y retrouver ^^

 

PS : je suis sur Prestashop 1.6

    public function getContextualValue($use_tax, Context $context = null, $filter = null, $package = null, $use_cache = true)
    {
        if (!CartRule::isFeatureActive()) {
            return 0;
        }
        if (!$context) {
            $context = Context::getContext();
        }
        if (!$filter) {
            $filter = CartRule::FILTER_ACTION_ALL;
        }

        $all_products = $context->cart->getProducts();
        $package_products = (is_null($package) ? $all_products : $package['products']);

        $all_cart_rules_ids = $context->cart->getOrderedCartRulesIds();

        $cart_amount_ti = $context->cart->getOrderTotal(true, Cart::ONLY_PRODUCTS);
        $cart_amount_te = $context->cart->getOrderTotal(false, Cart::ONLY_PRODUCTS);

        $reduction_value = 0;

        $cache_id = 'getContextualValue_'.(int)$this->id.'_'.(int)$use_tax.'_'.(int)$context->cart->id.'_'.(int)$filter;
        foreach ($package_products as $product) {
            $cache_id .= '_'.(int)$product['id_product'].'_'.(int)$product['id_product_attribute'].(isset($product['in_stock']) ? '_'.(int)$product['in_stock'] : '');
        }

        if (Cache::isStored($cache_id)) {
            return Cache::retrieve($cache_id);
        }

        // Free shipping on selected carriers
        if ($this->free_shipping && in_array($filter, array(CartRule::FILTER_ACTION_ALL, CartRule::FILTER_ACTION_ALL_NOCAP, CartRule::FILTER_ACTION_SHIPPING))) {
            if (!$this->carrier_restriction) {
                $reduction_value += $context->cart->getOrderTotal($use_tax, Cart::ONLY_SHIPPING, is_null($package) ? null : $package['products'], is_null($package) ? null : $package['id_carrier']);
            } else {
                $data = Db::getInstance()->executeS('
					SELECT crc.id_cart_rule, c.id_carrier
					FROM '._DB_PREFIX_.'cart_rule_carrier crc
					INNER JOIN '._DB_PREFIX_.'carrier c ON (c.id_reference = crc.id_carrier AND c.deleted = 0)
					WHERE crc.id_cart_rule = '.(int)$this->id.'
					AND c.id_carrier = '.(int)$context->cart->id_carrier);

                if ($data) {
                    foreach ($data as $cart_rule) {
                        $reduction_value += $context->cart->getCarrierCost((int)$cart_rule['id_carrier'], $use_tax, $context->country);
                    }
                }
            }
        }

        if (in_array($filter, array(CartRule::FILTER_ACTION_ALL, CartRule::FILTER_ACTION_ALL_NOCAP, CartRule::FILTER_ACTION_REDUCTION))) {
            // Discount (%) on the whole order
            if ($this->reduction_percent && $this->reduction_product == 0) {
                // Do not give a reduction on free products!
                $order_total = $context->cart->getOrderTotal($use_tax, Cart::ONLY_PRODUCTS, $package_products);
                foreach ($context->cart->getCartRules(CartRule::FILTER_ACTION_GIFT) as $cart_rule) {
                    $order_total -= Tools::ps_round($cart_rule['obj']->getContextualValue($use_tax, $context, CartRule::FILTER_ACTION_GIFT, $package), _PS_PRICE_COMPUTE_PRECISION_);
                }

				// MODIF : Pour ne pas appliquer la reduction aux promotions. Pour la règle : montant total de la commande
				// AJOUT
				foreach ($package_products as $product) {
					if (!empty($product['reduction_applies']) && $product['reduction_applies'] > 0) {
						$reduction_value -= ($use_tax ? $product['total_wt'] : $product['total']) * $this->reduction_percent / 100;
					}
				}
				// fin

                $reduction_value += $order_total * $this->reduction_percent / 100;
            }

            // Discount (%) on a specific product
            if ($this->reduction_percent && $this->reduction_product > 0) {
                foreach ($package_products as $product) {
					// MODIF : Pour ne pas appliquer la reduction aux promotions. Pour la règle : produit spécifique
                    //if ($product['id_product'] == $this->reduction_product) {
                    //    $reduction_value += ($use_tax ? $product['total_wt'] : $product['total']) * $this->reduction_percent / 100;
                    //}
					if (!empty($product["reduction_applies"]) && $product["reduction_applies"] > 0) {
						$product_on_sale = true;
					}
                    if ($product['id_product'] == $this->reduction_product && !$product_on_sale) {
                        $reduction_value += ($use_tax ? $product['total_wt'] : $product['total']) * $this->reduction_percent / 100;
                    }
					// fin
                }
            }

            // Discount (%) on the cheapest product
            if ($this->reduction_percent && $this->reduction_product == -1) {
                $minPrice = false;
                $cheapest_product = null;
                foreach ($all_products as $product) {

                    // MODIF : Pour prendre en compte la quantité. Pour la règle : produit le moins cher
					//$price = $product['price'];
					$price = $product['price']*$product['cart_quantity'];
					// fin
                    if ($use_tax) {
                        // since later on we won't be able to know the product the cart rule was applied to,
                        // use average cart VAT for price_wt
                        $price *= (1 + $context->cart->getAverageProductsTaxRate());
                    }

                    // MODIF : Pour ne pas appliquer la reduction aux promotions. Pour la règle : montant total de la commande
					//if ($price > 0 && ($minPrice === false || $minPrice > $price)) {
                    //    $minPrice = $price;
                    //    $cheapest_product = $product['id_product'].'-'.$product['id_product_attribute'];
                    //}
					if ($price > 0 && ($minPrice === false || $minPrice > $price) && $product["reduction_applies"] <= 0) {
                        $minPrice = $price;
                        $cheapest_product = $product['id_product'].'-'.$product['id_product_attribute'];
                    }
					// fin
                }

                // Check if the cheapest product is in the package
                $in_package = false;
                foreach ($package_products as $product) {
                    if ($product['id_product'].'-'.$product['id_product_attribute'] == $cheapest_product || $product['id_product'].'-0' == $cheapest_product) {
                        $in_package = true;
                    }
                }
                if ($in_package) {
                    $reduction_value += $minPrice * $this->reduction_percent / 100;
                }
            }

            // Discount (%) on the selection of products
            if ($this->reduction_percent && $this->reduction_product == -2) {
                $selected_products_reduction = 0;
                $selected_products = $this->checkProductRestrictions($context, true);
                if (is_array($selected_products)) {
                    foreach ($package_products as $product) {
						if (in_array($product['id_product'].'-'.$product['id_product_attribute'], $selected_products)
                            || in_array($product['id_product'].'-0', $selected_products)) {
							// MODIF : Pour ne pas appliquer la reduction aux promotions. Pour la règle : selection de produit
							//$price = $product['price'];
							//if ($use_tax) {
							//	$infos = Product::getTaxesInformations($product, $context);
							//	$tax_rate = $infos['rate'] / 100;
							//	$price *= (1 + $tax_rate);
							//}
							//$selected_products_reduction += $price * $product['cart_quantity'];
							if ($product["reduction_applies"] <= 0) {
								$price = $product['price'];
								if ($use_tax) {
									$infos = Product::getTaxesInformations($product, $context);
									$tax_rate = $infos['rate'] / 100;
									$price *= (1 + $tax_rate);
								}
								$selected_products_reduction += $price * $product['cart_quantity'];
							}
							// fin
                        }
                    }
                }
                $reduction_value += $selected_products_reduction * $this->reduction_percent / 100;
            }

            // Discount (¤)
            if ((float)$this->reduction_amount > 0) {
                $prorata = 1;
                if (!is_null($package) && count($all_products)) {
                    $total_products = $context->cart->getOrderTotal($use_tax, Cart::ONLY_PRODUCTS);
                    if ($total_products) {
                        $prorata = $context->cart->getOrderTotal($use_tax, Cart::ONLY_PRODUCTS, $package['products']) / $total_products;
                    }
                }

                $reduction_amount = $this->reduction_amount;
                // If we need to convert the voucher value to the cart currency
                if (isset($context->currency) && $this->reduction_currency != $context->currency->id) {
                    $voucherCurrency = new Currency($this->reduction_currency);

                    // First we convert the voucher value to the default currency
                    if ($reduction_amount == 0 || $voucherCurrency->conversion_rate == 0) {
                        $reduction_amount = 0;
                    } else {
                        $reduction_amount /= $voucherCurrency->conversion_rate;
                    }

                    // Then we convert the voucher value in the default currency into the cart currency
                    $reduction_amount *= $context->currency->conversion_rate;
                    $reduction_amount = Tools::ps_round($reduction_amount, _PS_PRICE_COMPUTE_PRECISION_);
                }

                // If it has the same tax application that you need, then it's the right value, whatever the product!
                if ($this->reduction_tax == $use_tax) {
                    // The reduction cannot exceed the products total, except when we do not want it to be limited (for the partial use calculation)
                    if ($filter != CartRule::FILTER_ACTION_ALL_NOCAP) {
                        $cart_amount = $context->cart->getOrderTotal($use_tax, Cart::ONLY_PRODUCTS);
                        $reduction_amount = min($reduction_amount, $cart_amount);
                    }
                    $reduction_value += $prorata * $reduction_amount;
                } else {
                    if ($this->reduction_product > 0) {
                        foreach ($context->cart->getProducts() as $product) {
                            if ($product['id_product'] == $this->reduction_product) {
                                $product_price_ti = $product['price_wt'];
                                $product_price_te = $product['price'];
                                $product_vat_amount = $product_price_ti - $product_price_te;

                                if ($product_vat_amount == 0 || $product_price_te == 0) {
                                    $product_vat_rate = 0;
                                } else {
                                    $product_vat_rate = $product_vat_amount / $product_price_te;
                                }

                                if ($this->reduction_tax && !$use_tax) {
                                    $reduction_value += $prorata * $reduction_amount / (1 + $product_vat_rate);
                                } elseif (!$this->reduction_tax && $use_tax) {
                                    $reduction_value += $prorata * $reduction_amount * (1 + $product_vat_rate);
                                }
                            }
                        }
                    }
                    // Discount (¤) on the whole order
                    elseif ($this->reduction_product == 0) {
                        $cart_amount_te = null;
                        $cart_amount_ti = null;
                        $cart_average_vat_rate = $context->cart->getAverageProductsTaxRate($cart_amount_te, $cart_amount_ti);

                        // The reduction cannot exceed the products total, except when we do not want it to be limited (for the partial use calculation)
                        if ($filter != CartRule::FILTER_ACTION_ALL_NOCAP) {
                            $reduction_amount = min($reduction_amount, $this->reduction_tax ? $cart_amount_ti : $cart_amount_te);
                        }

                        if ($this->reduction_tax && !$use_tax) {
                            $reduction_value += $prorata * $reduction_amount / (1 + $cart_average_vat_rate);
                        } elseif (!$this->reduction_tax && $use_tax) {
                            $reduction_value += $prorata * $reduction_amount * (1 + $cart_average_vat_rate);
                        }
                    }
                    /*
                     * 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)
                    */
                }

                // Take care of the other cart rules values if the filter allow it
                if ($filter != CartRule::FILTER_ACTION_ALL_NOCAP) {
                    // Cart values
                    $cart = Context::getContext()->cart;

                    if (!Validate::isLoadedObject($cart)) {
                        $cart = new Cart();
                    }

                    $cart_average_vat_rate = $cart->getAverageProductsTaxRate();
                    $current_cart_amount = $use_tax ? $cart_amount_ti : $cart_amount_te;

                    foreach ($all_cart_rules_ids as $current_cart_rule_id) {
                        if ((int)$current_cart_rule_id['id_cart_rule'] == (int)$this->id) {
                            break;
                        }

                        $previous_cart_rule = new CartRule((int)$current_cart_rule_id['id_cart_rule']);
                        $previous_reduction_amount = $previous_cart_rule->reduction_amount;

                        if ($previous_cart_rule->reduction_tax && !$use_tax) {
                            $previous_reduction_amount = $prorata * $previous_reduction_amount / (1 + $cart_average_vat_rate);
                        } elseif (!$previous_cart_rule->reduction_tax && $use_tax) {
                            $previous_reduction_amount = $prorata * $previous_reduction_amount * (1 + $cart_average_vat_rate);
                        }

                        $current_cart_amount = max($current_cart_amount - (float)$previous_reduction_amount, 0);
                    }

                    $reduction_value = min($reduction_value, $current_cart_amount);
                }
            }
        }

        // Free gift
        if ((int)$this->gift_product && in_array($filter, array(CartRule::FILTER_ACTION_ALL, CartRule::FILTER_ACTION_ALL_NOCAP, CartRule::FILTER_ACTION_GIFT))) {
            $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 || !(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
                        || !$use_cache) {
                        $reduction_value += ($use_tax ? $product['price_wt'] : $product['price']);
                        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;
                    }
                }
            }
        }

        Cache::store($cache_id, $reduction_value);
        return $reduction_value;
    }

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...