1

Im trying to get the correct price for each item variation however it only seems to be getting the first price of that product variation. Not sure how to solve this.

Code:

$query = new WC_Order_Query( array(
        'status' => 'on-hold',
        'orderby' => 'date',
        'order' => 'DESC',
        'return' => 'ids',
    ) );
    $order_ids = $query->get_orders();

    foreach( $order_ids as $order_id ) {


        $order = new WC_Order($order_id);


        foreach ($order->get_items() as $item_id => $item_obj) {
            $_product = wc_get_product($item_obj['product_id']);
            $product = new WC_Product_Variable($item_obj['product_id']);
            $product_variations = $product->get_available_variations();

            $variation_product_id = $product_variations [0]['variation_id'];

            $variation_product = new WC_Product_Variation( $variation_product_id );
            $t_dy =  $variation_product->get_price();
            $item_qty = $item_obj['qty'];
            $it_total = $item_qty * $t_dy;
            $td = wc_update_order_item_meta($item_id, '_line_total', $it_total);
            $order->calculate_totals();
            $order->save();
        }

    }
LoicTheAztec
  • 229,944
  • 23
  • 356
  • 399
Omar T
  • 123
  • 11

3 Answers3

2

Updated 3

To get the correct current variation price when the order item is a product variation is much more simple than you are doing. Then you will use Woocommerce 3 CRUD setter and getter methods to set the order item totals, save it and update the order.

The code:

// Loop through order items
foreach ($order->get_items() as $item_id => $item ) {

    // Targeting only product variation items
    if( $item->get_variation_id() > 0 ){ 

        // Get an instance of the WC_Product_Variation object
        $product = $item->get_product(); 

        $price   = (float) $product->get_price(); // <=== HERE the variation price

        $qty     = (int) $item->get_quantity(); // <=== HERE the quantity

        // set line totals
        $item->set_total( $price * $qty );
        $item->set_subtotal( $price * $qty );

        $item->save(); // save order item data
    }
}

// The following need to be outside the order item loop
$order->calculate_totals(); // Save is included into the method

It should better work this way.

Related:

LoicTheAztec
  • 229,944
  • 23
  • 356
  • 399
  • I think that is wrong: $product->get_price(); will NOT give you the variation price as ordered on the order. each order line has a product id and a variation id and you can see below that they are always different ids. your code is also wrong because you have accidentally grabbed the current variation price, but what if the price changed since the customer placed the order. you want the variation price at the time of the order. not the variation price that it is now. your code will not work as expected. – hamish Apr 22 '23 at 14:20
1

Found the issue! - it was giving out wrong id replace:

 $variation_product_id = $product_variations [0]['variation_id'];

with this:

$product_variation_id = $item_obj->get_variation_id();
$variation_product_id = $product_variation_id;
$variation_product = new WC_Product_Variation( $variation_product_id );
Omar T
  • 123
  • 11
  • To get the current product variation object when an order item is a variation, you should better use directly `get_product()` method like `$product = $item_obj->get_product();` … It will simplify your code. – LoicTheAztec Jun 14 '18 at 12:51
  • @LoicTheAztec no thats not true, do not use get product. as you can see in the documentaion that class WC_Product_Variation extends WC_Product { so although yes it will give you code that does not error, your idea on get_product is flawed. what Omar T did "with this" new code is perfect. – hamish Apr 22 '23 at 14:27
0

This is the code I am running with for now, I also found this is the only place on the internet that discusses code for this, which surprises me somewhat considering how popular woocommerce is. either people are not sharing or its just obvious to everyone. (next up: getting currency, calculating the exchange rate and correct line item tax rates, that will be fun)

    foreach ($order_data['line_items'] as $order_line_item) {
        $product_id = $order_line_item['product_id'];
        $product = wc_get_product($product_id);
        $variation_id = $order_line_item['variation_id'];
        if($variation_id !== 0){
            $variation = new WC_Product_Variation( $variation_id );
            $regular_price = $variation->get_regular_price();
            $is_virtual = $variation->is_virtual();
            $is_downloadable = $variation->is_downloadable();
        } else {
            $regular_price = $product->get_regular_price();
            $is_virtual = $product->is_virtual();
            $is_downloadable = $product->is_downloadable();
        }
    }

as you can see when you do print_r($order_data) or var_dump($order_data) you can clearly see each line has a variation id stored against each order line that the customer added to their cart and checked out. This is the variation that your customer selected when ordering.

[line_items] => Array
    (
        [0] => Array
            (
                [id] => 32500
                [name] => Test Product Name
                [product_id] => 66
                [variation_id] => 26077
                [quantity] => 1
                [tax_class] => 
                [subtotal] => 279.45
                [subtotal_tax] => 0.00
                [total] => 279.45
                [total_tax] => 0.00
                [taxes] => Array
                    (
                        [0] => Array
                            (
                                [id] => 1
                                [total] => 0
                                [subtotal] => 0
                            )

                    )
hamish
  • 1,141
  • 1
  • 12
  • 21