Ändern des WooCommerce-Einkaufswagenpreises nach Anwendung des Gutscheincodes

Lesezeit: 7 Minuten

Benutzer-Avatar
Archana

Ich habe ein Produkt auf WooCommerce erstellt und hinzugefügt zwei Optionen auf der Produktdetailseite mit dem Haken woocommerce_before_add_to_cart_button. Wenn Kunden jetzt ein Produkt von der Produktdetailseite in den Warenkorb legen, haben sie zwei Möglichkeiten. Sie können eine Option aus diesen beiden Optionen auswählen.

Dann habe ich den vom Benutzer ausgewählten Wert im Warenkorb-Meta mit dem Woocommerce-Hook woocommerce_add_cart_item_data gespeichert.

Ich verwende den Code aus dieser Antwort: Speichern Sie den Optionsfeldwert des benutzerdefinierten Felds im Warenkorb und zeigen Sie ihn auf der Warenkorbseite an

Das ist mein Code:

// single Product Page options  
add_action("woocommerce_before_add_to_cart_button", "options_on_single_product");
function options_on_single_product(){
    $dp_product_id = get_the_ID(); 
    $product_url = get_permalink($dp_product_id);

    ?>
        <input type="radio" name="custom_options" checked="checked" value="option1"> option1<br />
        <input type="radio" name="custom_options" value="option2"> option2
    <?php
}


//Store the custom field
add_filter( 'woocommerce_add_cart_item_data', 'save_custom_data_with_add_to_cart', 10, 2 );
function save_custom_data_with_add_to_cart( $cart_item_meta, $product_id ) {
    global $woocommerce;
    $cart_item_meta['custom_options'] = $_POST['custom_options'];
    return $cart_item_meta; 
}

Und das habe ich versucht:

add_action( 'woocommerce_before_calculate_totals', 'add_custom_price', 10, 1);
function add_custom_price( $cart_obj ) {

    if ( is_admin() && ! defined( 'DOING_AJAX' ) )
        return;

    foreach ( $cart_obj->get_cart() as $key => $value ) {
        $product_id = $value['product_id'];
        $custom_options = $value['custom_options'];
        $coupon_code = $value['coupon_code'];
        if($custom_options == 'option2')
        {
            if($coupon_code !='')
            {
                global $woocommerce;
                if ( WC()->cart->has_discount( $coupon_code ) ) return;
                (WC()->cart->add_discount( $coupon_code ))

            //code for second discount
            }
            else{
                $percentage = get_post_meta( $product_id , 'percentage', true );
                //print_r($value);
                $old_price = $value['data']->regular_price;
                $new_price = ($percentage / 100) * $old_price;
                $value['data']->set_price( $new_price );
            }
        } 
    }
}

Was ich nun versuche, mit diesem letzten Ausschnitt zu bekommen, ist:

  • Wenn Option1 vom Kunden ausgewählt wird, wird der reguläre WooCommerce-Prozess ausgeführt.
  • Wenn Option2 ausgewählt ist, wird zuerst der Gutscheincode auf den Warenkorb angewendet (wenn der Code vom Kunden eingegeben wurde) und dann wird der Preis durch einen bestimmten Prozentsatz geteilt (in der Produktmeta gespeichert). wird danach angewendet.

Aber es funktioniert nicht wie erwartet, da der geänderte Produktpreis vorher ein Dienstmädchen ist und der Coupon-Rabatt danach auf diesen geänderten Preis angewendet wird.

Was ich möchte, ist, dass der Coupon-Rabatt zuerst auf den regulären Produktpreis angewendet wird und dann diesen Preis mit meinem benutzerdefinierten Produktrabatt ändert.

Ist das möglich? Wie kann ich das erreichen?

Vielen Dank.

Benutzer-Avatar
LoicTheAztec

Dies ist nicht wirklich möglich … Warum? … Da (die Logik):

  1. Sie haben den Produktpreis
  2. Dann wird der Coupon-Rabatt auf diesen Preis angewendet (nachher)
    ==> Wenn Sie den Produktpreis ändern, wird der Gutschein auf diesen geänderten Preis angewendet

Was Sie stattdessen tun können:

  1. Sie ändern den Produktpreis nicht
  2. bei Eingabe wird der Gutschein eingelöst und …
  3. Wenn das Produkt “option2” zum Warenkorb hinzugefügt wird:
  4. Wenden Sie einen benutzerdefinierten Rabatt (eine negative Gebühr) basierend auf dem nach der Verwendung hinzugefügten Produktpreis an WC_cart add_fee() Methode…

Für diesen letzten Fall müssen Sie Ihren zusätzlichen Rabatt fein abstimmen.
Wenn der Gutschein nicht eingelöst oder entfernt wurde, gibt es keinen zusätzlichen Rabatt.

Ihre benutzerdefinierte Funktion wird eingebunden woocommerce_cart_calculate_fees Action-Hook stattdessen:

add_action( 'woocommerce_cart_calculate_fees', 'option2_additional_discount', 10, 1 );
function option2_additional_discount( $cart_obj ) {

    if ( is_admin() && ! defined( 'DOING_AJAX' ) )
        return;

    $discount = 0;
    $applied_coupons = $cart_obj->get_applied_coupons();

    foreach ( $cart_obj->get_cart() as $item_values ) {
        if( 'option2' == $item_values['custom_options'] && !empty($applied_coupons) ){
            $product_id = $item_values['product_id'];
            $percentage = get_post_meta( $product_id , 'percentage', true );
            $quantity = $item_values['quantity'];
            $product_reg_price = $item_values['data']->regular_price;
            $line_total = $item_values['line_total'];
            $line_subtotal = $item_values['line_subtotal'];
            $percentage = 90;

            ## ----- CALCULATIONS (To Fine tune) ----- ##

            $item_discounted_price = ($percentage / 100) *  $product_reg_price * $item_values['quantity'];
            // Or Besed on line item subtotal
            $discounted_price = ($percentage / 100) * $line_subtotal;

            $discount += $product_reg_price - $item_discounted_price;
        }
    }
    if($discount != 0)
        $cart_obj->add_fee( __( 'Option2 discount', 'woocommerce' ) , - $discount );
}

Code geht in die function.php-Datei Ihres aktiven Child-Themes (oder Themes) oder auch in jede Plugin-Datei.

Dieser Code ist getestet und funktioniert.

Hinzufügen einer negativen Gebühr mit der WC_Cart->add_fee() Methode hat bei mir nicht funktioniert. Wenn ich die WC-Cart-Klasse überprüfe, heißt es sogar, dass Sie keinen negativen Betrag verwenden dürfen.

Siehe die Dokumente.

Ich habe folgendes gemacht:

  • einen Platzhalter-Gutschein mit einem „sicheren“ Code erstellen, zB custom_discount_fjgndfl28. Legen Sie einen Rabattbetrag von 0 fest, sodass der Rabatt immer noch 0 beträgt, wenn jemand diesen Gutschein (irgendwie) außerhalb Ihres Programms verwendet.
  • Filter verwenden woocommerce_get_shop_coupon_dataund legen Sie alle gewünschten Coupondaten für diesen Coupon/diese Sitzung fest.
  • Einhaken woocommerce_before_calculate_totals und legen Sie Ihren benutzerdefinierten Gutschein in den Warenkorb.
  • An dieser Stelle sollte der Warenkorb alles richtig berechnen. Und wenn es eine Bestellung wird, hat es auch den richtigen Rabattbetrag.
  • Hinweis: Der Gutscheincode wird in einigen Vorlagen auch als Label verwendet. Filter verwenden woocommerce_cart_totals_coupon_label um es zu ändern.

Beispielfunktionen:

/**
 * NOTE: All the hooks and filters below have to be called from your own
 * does_it_need_custom_discount() function. I used the 'wp' hook for mine.
 * Do not copy/paste this to your functions.php.
**/

add_filter('woocommerce_get_shop_coupon_data', 'addVirtualCoupon', 10, 2);
function addVirtualCoupon($unknown_param, $curr_coupon_code) {

    if($curr_coupon_code == 'custom_discount_fjgndfl28') {

      // possible types are: 'fixed_cart', 'percent', 'fixed_product' or 'percent_product.
      $discount_type="fixed_cart"; 

      // how you calculate the ammount and where you get the data from is totally up to you.
      $amount = $get_or_calculate_the_coupon_ammount;

      if(!$discount_type || !$amount) return false;

        $coupon = array(
            'id' => 9999999999 . rand(2,9),
            'amount' => $amount,
            'individual_use' => false,
            'product_ids' => array(),
            'exclude_product_ids' => array(),
            'usage_limit' => '',
            'usage_limit_per_user' => '',
            'limit_usage_to_x_items' => '',
            'usage_count' => '',
            'expiry_date' => '',
            'apply_before_tax' => 'yes',
            'free_shipping' => false,
            'product_categories' => array(),
            'exclude_product_categories' => array(),
            'exclude_sale_items' => false,
            'minimum_amount' => '',
            'maximum_amount' => '',
            'customer_email' => '',
            'discount_type' => $discount_type,
        );

        return $coupon;
    }
}

add_action('woocommerce_before_calculate_totals', 'applyFakeCoupons');
function applyFakeCoupons() {
  global $woocommerce;
  // $woocommerce->cart->remove_coupons(); remove existing coupons if needed.
  $woocommerce->cart->applied_coupons[] = $this->coupon_code; 
}

add_filter( 'woocommerce_cart_totals_coupon_label', 'cart_totals_coupon_label', 100, 2 );
function cart_totals_coupon_label($label, $coupon) {

    if($coupon) {
      $code = $coupon->get_code();
      if($code == 'custom_discount_fjgndfl28') {
        return 'Your custom coupon label';
      }
    }

    return $label;
}

Bitte beachten Sie: Ich habe diese Funktionen aus einer Klasse kopiert, die viel mehr handhabt, es soll Ihnen nur helfen, loszulegen.

  • Hallo, können Sie bitte erklären “Alle Hooks und Filter unten müssen von Ihrer eigenen Funktion does_it_need_custom_discount() aufgerufen werden”, danke?

    – Darko

    26. März 2020 um 17:37 Uhr

  • Ich erstelle immer eine virtual_coupon-Klasse in meiner App. Wenn ein Rabatt benötigt wird, rufe ich die Klasse an und lege die Rabattinformationen in a fest public $discounts = array();. Die Aktion virtual_coupon und die Filter-Hooks werden nur ausgeführt, wenn $this->discounts eingestellt sind. Mir ist klar, dass dies keine sehr detaillierten Informationen sind, aber es hängt wirklich davon ab, was Sie erreichen möchten und wie Ihre App / Ihr Plugin strukturiert ist.

    – Björn

    18. April 2020 um 18:26 Uhr


1353370cookie-checkÄndern des WooCommerce-Einkaufswagenpreises nach Anwendung des Gutscheincodes

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy