Jump to content

[Résolu] Suppression d'une réduction pour une commande automatisée [PS 1.7]


Recommended Posts

Bonjour à tous,

Je reviens avec un cas un peu spécifique qui me donne du fil à retordre, j'utilise un module d'abonnement qui lors d'une commande de type "abonnement" va passer un premier achat et recevoir des signaux de paiement à interval régulier pour les paiement suivant.

A chaque signal reçu une commande est créée à partir de la commande originel. Cependant, le prix du 1er versement diffère des suivants, le changement de prix est généré par une 'CartRule' de type "Discount".

Je voudrais pouvoir supprimer cette réduction de prix sur les commandes automatisés, et j'ai effectué la suppression des CartRule sur le panier :

foreach ($new_cart->getCartRules() as $rule) {
  if ($this->removeRule($subscription, $cart, $new_cart, $rule)) {
  	$new_cart->removeCartRule($rule['id_cart_rule']);
  }
}

Cependant lorsque j'envoi mon panier vers la classe PaymentModule afin de valider la commande ( validateOrder() ) il se trouve que les réductions sont ré-appliqués à nouveau sur mon panier.

Du coup je me demande si ma façon de faire est la bonne, comment faire en sorte de faire sauter ma réduction de façon propre, dois-je plutot me tourner vers la classe CartRule et lui appliquer un filtre spécifique ?

Ou même existe-t-il une option dans prestashop qui permette de gérer mon cas avec un premier prix spécifique sans avoir à utiliser les réductions ?

Actuellement je tente d'override la classe PaymentModule depuis mon module pour empêcher l'application d'un discount si un paramètre $noDiscount est passé :

public function validateOrder(
        $id_cart,
        $id_order_state,
        $amount_paid,
        $payment_method = 'Unknown',
        $message = null,
        $extra_vars = array(),
        $currency_special = null,
        $dont_touch_amount = false,
        $secure_key = false,
        $noDiscount = false,
        Shop $shop = null
)

// Début de la fonction ...

// Make sure CartRule caches are empty
CartRule::cleanCache();
// Modification anti-discount
if($noDiscount){
	$cart_rules = $this->context->cart->getCartRules(CartRule::FILTER_ACTION_ALL, true);
}else{
	$cart_rules = $this->context->cart->getCartRules();
}
foreach ($cart_rules as $cart_rule) {
  if (($rule = new CartRule((int) $cart_rule['obj']->id)) && Validate::isLoadedObject($rule)) {
    if ($error = $rule->checkValidity($this->context, true, true)) {
      $this->context->cart->removeCartRule((int) $rule->id);
      if (isset($this->context->cookie, $this->context->cookie->id_customer) && $this->context->cookie->id_customer && !empty($rule->code)) {
          Tools::redirect('index.php?controller=order&submitAddDiscount=1&discount_name=' . urlencode($rule->code));
      } else {
        $rule_name = isset($rule->name[(int) $this->context->cart->id_lang]) ? $rule->name[(int) $this->context->cart->id_lang] : $rule->code;
        $error = $this->trans('The cart rule named "%1s" (ID %2s) used in this cart is not valid and has been withdrawn from cart', array($rule_name, (int) 		$rule->id), 'Admin.Payment.Notification');
        PrestaShopLogger::addLog($error, 3, '0000002', 'Cart', (int) $this->context->cart->id);
      }
    }
  }
}

// Autre modification au moment de l'appel de createOrderCartRules()
if($noDiscount){
	$cart_rules_list = array();
}else{
  $cart_rules_list = $this->createOrderCartRules(
    $order,
    $this->context->cart,
    $order_list,
    $total_reduction_value_ti,
    $total_reduction_value_tex,
    $id_order_state
  );
}

J'espère que vous pourrez m'aider :) 

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

Je me rends vraiment compte que les réductions sont vérifiés et recréés à de nombreux endroits lors de la création de la commande et j'ai l'impression de coder à contre-courant ...

Peut-être que modifier la commande n'est pas la solution mais que je dois créer une réduction spécifique ?

Donnez-moi votre avis car je voudrais pouvoir produire quelque chose qui suive un minimum les bonnes pratiques.

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

Bonjour @Mediacom87,

J'avais eut la même réflexion dans un premier temps mais lors de mes tests j'ai vu que je ne pouvais pas retirer le prix spécifique d'un produit au moment de la commande non plus.

Le prix spécifique prends le dessus sur le prix de base au moment de la création de la commande et j'ai du abandonner l'idée pour me tourner vers les réductions qui sont plus facilement manipulables. 

Mais au bout du compte les 2 solutions retrouvent leur prix d'origine au moment de la création de commande.

Link to comment
Share on other sites

Je tente un coup de poker et j'override la classe CartRule et plus spécifiquement la fonction checkValidity.

L'idée est de créer une vérification si mon panier est un abonnement en cours et si c'est le cas la fonction checkValidity() retournera immédiatement false.

Etant donné que checkValidity est la fonction référence pour l'ajout des règles au panier, j'espère que ça empêchera l'ajout des réductions...

Link to comment
Share on other sites

Je viens de réussir à mettre en place mon système de paiement avec suppression des réductions, je partage la démarche pour ceux qui se retrouveraient dans le même cas.

Au final j'ai opté pour un override de la classe CartRule :

// === Code ajouté au début de la fonction checkValidity() de CartRule ===
$isSubscriptionLive = Db::getInstance()->getValue('
  SELECT count(*)
  FROM ' . _DB_PREFIX_ . 'ogone_cloned_cart
  WHERE id_cart = ' . (int) $context->cart->id . '
  AND id_customer = ' . (int) $context->cart->id_customer . '
');

// Si abonnement est en cours et 1er versement déjà effectué
if($isSubscriptionLive > 0){
	return false;
}

// === Code exécuté au moment du clone de mon panier ===
// Ajout du nouveau cart à la liste pour pouvoir l'identifier comme non affecté par les réductions
$result = Db::getInstance()->insert('ogone_cloned_cart', array(
  'id_ogone_cloned' => NULL,
  'id_cart' => (int) $new_cart->id,
  'id_initial_cart' => (int) $subscription->id_cart,
  'id_customer' => (int) $new_cart->id_customer,
  'date_add' => date('Y-m-d H:i:s')
));

Les données passent par une table faite spécialement pour l'occasion et qui permettent à checkValidity() de savoir si le panier dois ou non recevoir une réduction

 

En espérant que ça servira à certains, Enjoy

Edited by cryoth (see edit history)
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...