Woocommerce – Add Coupon is not deducting totals

I am creating my order like so:

$order = wc_create_order();

$product = wc_get_product( $_POST["product"] );
$order->add_product( $product, 1 );

$kupon = new WC_Coupon( $_POST["coupon"] );
$amount = $kupon->get_discount_amount( $product->price );
$order->add_coupon( $_POST["coupon"], $amount, $amount );

$order->calculate_shipping();
$order->calculate_totals();

If you take a closer look, I am adding a coupon code dynamicaly with add_coupon function from WC_Order class. Everythings works perfectly, the order is added to database with correct product, quantites, and ALSO the coupon is added – but the problem is that coupon is not “applied” to the total. It is not deducting the totals price. Here is the image:
enter image description here

Related posts

2 comments

  1. While adding a product to an Order, we should pass an argument containing subtotal and total like this:

    $args = array(
        "totals" => array('subtotal' => $item["price"],
                          'total' => $item["price"] - $coupon_discount)
    );                      
    $order->add_product( $product, 1, $args);
    

    Where $product is Woocommerce product. Hope this helps somebody.

  2. Here is the solution that worked in my case for modifying order line items then applying a discount afterward – $order is a WC_Order object:

        $order_total        = $order->get_total()
        $coupon_code        = $this->get_coupon_code( $order );
        $coupon             = new WC_Coupon( $coupon_code );
        $coupon_type        = $coupon->discount_type;
        $coupon_amount      = $coupon->coupon_amount;
        $final_discount     = 0;
    
        // You must calculate the discount yourself! I have not found a convenient method outside the WC_Cart context to do this for you.
        $final_discount = $coupon_amount * ( $order_total / 100 );
    
        $order->add_coupon( $coupon_code, $final_discount, 0 );
        $order->set_total( $final_discount );
    

    Here is the method to retrieve the coupon code for a WC_Order object. In my case I know there will never be more then 1 coupon per order so you may want to adjust it to accommodate more:

    public function get_coupon_code( $subscription ) {
    
        $coupon_used = '';
        if( $subscription->get_used_coupons() ) {
    
          $coupons_count = count( $subscription->get_used_coupons() );
    
          foreach( $subscription->get_used_coupons() as $coupon) {
            $coupon_used = $coupon;
            break;
          } 
        }
    
        if ( $coupon_used !== '' ) {
            return $coupon_used;
        } else {
            return false;
        }
    }
    

Comments are closed.