Refactor Order Class to use shared calculation logic.
We added a trait to move shared logic betweem Orders and Cart. This commit refactors Order class to use that shared logic. Also adds a test for a failing case.
This commit is contained in:
parent
bee7ea4490
commit
60cd7b3651
|
@ -18,6 +18,7 @@ require_once WC_ABSPATH . 'includes/legacy/abstract-wc-legacy-order.php';
|
|||
* WC_Abstract_Order class.
|
||||
*/
|
||||
abstract class WC_Abstract_Order extends WC_Abstract_Legacy_Order {
|
||||
use WC_Item_Totals;
|
||||
|
||||
/**
|
||||
* Order Data array. This is the core order data exposed in APIs since 3.0.0.
|
||||
|
@ -769,6 +770,23 @@ abstract class WC_Abstract_Order extends WC_Abstract_Legacy_Order {
|
|||
return apply_filters( 'woocommerce_order_get_items', $items, $this, $types );
|
||||
}
|
||||
|
||||
/**
|
||||
* Return array of values for calculations.
|
||||
*
|
||||
* @param string $field Field name to return.
|
||||
*
|
||||
* @return array Array of values.
|
||||
*/
|
||||
protected function get_values_for_total( $field ) {
|
||||
$items = array_map(
|
||||
function ( $item ) use ( $field ) {
|
||||
return wc_add_number_precision( $item[ $field ] );
|
||||
},
|
||||
array_values( $this->get_items() )
|
||||
);
|
||||
return $items;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an array of coupons within this order.
|
||||
*
|
||||
|
@ -1508,18 +1526,13 @@ abstract class WC_Abstract_Order extends WC_Abstract_Legacy_Order {
|
|||
public function calculate_totals( $and_taxes = true ) {
|
||||
do_action( 'woocommerce_order_before_calculate_totals', $and_taxes, $this );
|
||||
|
||||
$cart_subtotal = 0;
|
||||
$cart_total = 0;
|
||||
$fees_total = 0;
|
||||
$shipping_total = 0;
|
||||
$cart_subtotal_tax = 0;
|
||||
$cart_total_tax = 0;
|
||||
|
||||
// Sum line item costs.
|
||||
foreach ( $this->get_items() as $item ) {
|
||||
$cart_subtotal += round( $item->get_subtotal(), wc_get_price_decimals() );
|
||||
$cart_total += round( $item->get_total(), wc_get_price_decimals() );
|
||||
}
|
||||
$cart_subtotal = wc_remove_number_precision( $this->get_rounded_items_total( 'subtotal' ) );
|
||||
$cart_total = wc_remove_number_precision( $this->get_rounded_items_total() );
|
||||
|
||||
// Sum shipping costs.
|
||||
foreach ( $this->get_shipping_methods() as $shipping ) {
|
||||
|
|
|
@ -553,6 +553,16 @@ final class WC_Cart_Totals {
|
|||
return $in_cents ? $this->totals : wc_remove_number_precision_deep( $this->totals );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns array of values for totals calculation.
|
||||
*
|
||||
* @param string $field Field name. Will probably be `total` or `subtotal`.
|
||||
* @return array Items object
|
||||
*/
|
||||
protected function get_values_for_total( $field ) {
|
||||
return array_values( wp_list_pluck( $this->items, $field ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get taxes merged by type.
|
||||
*
|
||||
|
|
|
@ -13,24 +13,28 @@ if ( ! defined( 'ABSPATH' ) ) {
|
|||
/**
|
||||
* Trait WC_Item_Totals.
|
||||
*
|
||||
* Right now this do not have much, but plan is to eventually move all shared calculation logic between Orders and Cart in this file.
|
||||
*
|
||||
* @since 3.9.0
|
||||
*/
|
||||
trait WC_Item_Totals {
|
||||
|
||||
/**
|
||||
* Line items to calculate. Overwrite in child class.
|
||||
* Line items to calculate. Define in child class.
|
||||
*
|
||||
* @since 3.9.0
|
||||
* @var WC_Order_Item[]
|
||||
* @param string $field Field name to calculate upon.
|
||||
*
|
||||
* @return array having `total`|`subtotal` property.
|
||||
*/
|
||||
protected $items = array();
|
||||
abstract protected function get_values_for_total( $field );
|
||||
|
||||
/**
|
||||
* Return rounded total based on settings. Will be used by Cart and Orders.
|
||||
*
|
||||
* @since 3.9.0
|
||||
*
|
||||
* @param string $field Field to round and sum based on setting. Will likely be `total` or `subtotal`.
|
||||
* @param string $field Field to round and sum based on setting. Will likely be `total` or `subtotal`. Values must be without precision.
|
||||
*
|
||||
* @return float|int Appropriately rounded value.
|
||||
*/
|
||||
|
@ -38,7 +42,7 @@ trait WC_Item_Totals {
|
|||
return array_sum(
|
||||
array_map(
|
||||
array( $this, 'round_item_subtotal' ),
|
||||
array_values( wp_list_pluck( $this->items, $field ) )
|
||||
$this->get_values_for_total( $field )
|
||||
)
|
||||
);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
<?php
|
||||
/**
|
||||
* Class WC_Tests_Order file.
|
||||
*
|
||||
* @package WooCommerce|Tests|Order
|
||||
*/
|
||||
|
||||
/**
|
||||
* Class WC_Tests_Order.
|
||||
*/
|
||||
class WC_Tests_Order extends WC_Unit_Test_Case {
|
||||
|
||||
/**
|
||||
* Test for total when round at subtotal is enabled.
|
||||
*
|
||||
* @link https://github.com/woocommerce/woocommerce/issues/24695
|
||||
*/
|
||||
public function test_order_calculate_total_rounding_24695() {
|
||||
update_option( 'woocommerce_prices_include_tax', 'yes' );
|
||||
update_option( 'woocommerce_calc_taxes', 'yes' );
|
||||
update_option( 'woocommerce_tax_round_at_subtotal', 'yes' );
|
||||
|
||||
$tax_rate = array(
|
||||
'tax_rate_country' => '',
|
||||
'tax_rate_state' => '',
|
||||
'tax_rate' => '7.0000',
|
||||
'tax_rate_name' => 'CGST',
|
||||
'tax_rate_priority' => '1',
|
||||
'tax_rate_compound' => '0',
|
||||
'tax_rate_shipping' => '0',
|
||||
'tax_rate_order' => '1',
|
||||
'tax_rate_class' => 'tax_1',
|
||||
);
|
||||
WC_Tax::_insert_tax_rate( $tax_rate );
|
||||
|
||||
$product1 = WC_Helper_Product::create_simple_product();
|
||||
$product1->set_regular_price( 2 );
|
||||
$product1->save();
|
||||
|
||||
$product2 = WC_Helper_Product::create_simple_product();
|
||||
$product2->set_regular_price( 2.5 );
|
||||
$product2->save();
|
||||
|
||||
$order = new WC_Order();
|
||||
$order->add_product( $product1, 1 );
|
||||
$order->add_product( $product2, 4 );
|
||||
$order->save();
|
||||
|
||||
$order->calculate_totals( true );
|
||||
|
||||
$this->assertEquals( 12, $order->get_total() );
|
||||
$this->assertEquals( 0.79, $order->get_total_tax() );
|
||||
}
|
||||
|
||||
}
|
|
@ -62,7 +62,7 @@ class WC_Tests_Order_Coupons extends WC_Unit_Test_Case {
|
|||
array(
|
||||
'product' => $product,
|
||||
'quantity' => 1,
|
||||
'subtotal' => 909.09, // Ex tax.
|
||||
'subtotal' => 909.09, // Ex tax 10%.
|
||||
'total' => 726.36,
|
||||
)
|
||||
);
|
||||
|
|
Loading…
Reference in New Issue