Commit 44b7e3be13 for woocommerce
commit 44b7e3be137060c3fd406b9f473056a423cd76d6
Author: Michael Pretty <prettyboymp@users.noreply.github.com>
Date: Fri May 30 08:00:33 2025 -0400
Cherry-Pick: Revert: Fix incorrect net sales in analytics product reports for partial and full refunds #53019 (#58342) (#58410)
* Revert: Fix incorrect net sales in analytics product reports for partial and full refunds #53019 (#58342)
* Revert "Fix incorrect net sales in analytics product reports for partial and full refunds (#53019)"
This reverts commit 0b7aaa15a3a1724e11aeabdf1411d6b36cc22381.
* Add changelog
* Fix lint error
* Remove changelog
---------
Co-authored-by: Chi-Hsuan Huang <chihsuan.tw@gmail.com>
* remove changelog entry so it isn't duplicated in later release.
---------
Co-authored-by: louwie17 <lourensschep@gmail.com>
Co-authored-by: Chi-Hsuan Huang <chihsuan.tw@gmail.com>
diff --git a/plugins/woocommerce/includes/class-wc-install.php b/plugins/woocommerce/includes/class-wc-install.php
index fa27b9ad76..7723c11128 100644
--- a/plugins/woocommerce/includes/class-wc-install.php
+++ b/plugins/woocommerce/includes/class-wc-install.php
@@ -287,8 +287,6 @@ class WC_Install {
'wc_update_985_enable_new_payments_settings_page_feature',
),
'9.9.0' => array(
- 'wc_update_990_update_primary_key_to_composite_in_order_product_lookup_table',
- 'wc_update_990_add_old_refunded_order_items_to_product_lookup_table',
'wc_update_990_remove_wc_count_comments_transient',
'wc_update_990_remove_email_notes',
),
@@ -1900,7 +1898,7 @@ CREATE TABLE {$wpdb->prefix}wc_order_product_lookup (
tax_amount double DEFAULT 0 NOT NULL,
shipping_amount double DEFAULT 0 NOT NULL,
shipping_tax_amount double DEFAULT 0 NOT NULL,
- PRIMARY KEY (order_item_id, order_id),
+ PRIMARY KEY (order_item_id),
KEY order_id (order_id),
KEY product_id (product_id),
KEY customer_id (customer_id),
diff --git a/plugins/woocommerce/includes/class-wc-order.php b/plugins/woocommerce/includes/class-wc-order.php
index adea65575f..20e7135bdf 100644
--- a/plugins/woocommerce/includes/class-wc-order.php
+++ b/plugins/woocommerce/includes/class-wc-order.php
@@ -2207,31 +2207,6 @@ class WC_Order extends WC_Abstract_Order {
return $total_refunded;
}
- /**
- * Get the total shipping tax refunded.
- *
- * @since 9.9.0
- * @return float
- */
- public function get_total_shipping_tax_refunded() {
- $cache_key = WC_Cache_Helper::get_cache_prefix( 'orders' ) . 'total_shipping_tax_refunded' . $this->get_id();
- $cached_data = wp_cache_get( $cache_key, $this->cache_group );
-
- if ( false !== $cached_data ) {
- return $cached_data;
- }
-
- $total_shipping_tax_refunded = 0;
-
- if ( method_exists( $this->data_store, 'get_total_shipping_tax_refunded' ) ) {
- $total_shipping_tax_refunded = $this->data_store->get_total_shipping_tax_refunded( $this );
- }
-
- wp_cache_set( $cache_key, $total_shipping_tax_refunded, $this->cache_group );
-
- return $total_shipping_tax_refunded;
- }
-
/**
* Get the total shipping refunded.
*
diff --git a/plugins/woocommerce/includes/data-stores/class-wc-order-data-store-cpt.php b/plugins/woocommerce/includes/data-stores/class-wc-order-data-store-cpt.php
index 293be792fc..0205f00fd4 100644
--- a/plugins/woocommerce/includes/data-stores/class-wc-order-data-store-cpt.php
+++ b/plugins/woocommerce/includes/data-stores/class-wc-order-data-store-cpt.php
@@ -452,32 +452,6 @@ class WC_Order_Data_Store_CPT extends Abstract_WC_Order_Data_Store_CPT implement
return abs( $total );
}
- /**
- * Get the total shipping tax refunded.
- *
- * @param WC_Order $order Order object.
- *
- * @since 9.9.0
- * @return float
- */
- public function get_total_shipping_tax_refunded( $order ) {
- global $wpdb;
-
- $total = $wpdb->get_var(
- $wpdb->prepare(
- "SELECT SUM( order_itemmeta.meta_value )
- FROM {$wpdb->prefix}woocommerce_order_itemmeta AS order_itemmeta
- INNER JOIN $wpdb->posts AS posts ON ( posts.post_type = 'shop_order_refund' AND posts.post_parent = %d )
- INNER JOIN {$wpdb->prefix}woocommerce_order_items AS order_items ON ( order_items.order_id = posts.ID AND order_items.order_item_type = 'tax' )
- WHERE order_itemmeta.order_item_id = order_items.order_item_id
- AND order_itemmeta.meta_key = 'shipping_tax_amount'",
- $order->get_id()
- )
- ) ?? 0;
-
- return abs( $total );
- }
-
/**
* Get the total shipping refunded.
*
diff --git a/plugins/woocommerce/includes/interfaces/class-wc-order-data-store-interface.php b/plugins/woocommerce/includes/interfaces/class-wc-order-data-store-interface.php
index 30f5a9351e..1874517641 100644
--- a/plugins/woocommerce/includes/interfaces/class-wc-order-data-store-interface.php
+++ b/plugins/woocommerce/includes/interfaces/class-wc-order-data-store-interface.php
@@ -30,16 +30,6 @@ interface WC_Order_Data_Store_Interface {
*/
public function get_total_tax_refunded( $order );
- /**
- * Get the total shipping tax refunded.
- *
- * @param WC_Order $order Order object.
- *
- * @since 9.9.0
- * @return float
- */
- public function get_total_shipping_tax_refunded( $order );
-
/**
* Get the total shipping refunded.
*
diff --git a/plugins/woocommerce/includes/wc-update-functions.php b/plugins/woocommerce/includes/wc-update-functions.php
index 42919a5821..8829b4ace9 100644
--- a/plugins/woocommerce/includes/wc-update-functions.php
+++ b/plugins/woocommerce/includes/wc-update-functions.php
@@ -2993,56 +2993,6 @@ function wc_update_961_migrate_default_email_base_color() {
}
}
-/**
- * Add old refunded order items to the product_lookup_table.
- */
-function wc_update_990_add_old_refunded_order_items_to_product_lookup_table() {
- global $wpdb;
-
- // Get every order ID where:
- // 1. the total sales is less than 0, and
- // 2. is not refunded shipping fee only, and
- // 3. is not refunded tax fee only.
- $refunded_orders = $wpdb->get_results(
- "SELECT order_stats.order_id
- FROM {$wpdb->prefix}wc_order_stats AS order_stats
- WHERE order_stats.total_sales < 0 # Refunded orders
- AND order_stats.total_sales != order_stats.shipping_total # Exclude refunded orders that only include a shipping refund
- AND order_stats.total_sales != order_stats.tax_total # Exclude refunded orders that only include a tax refund"
- );
-
- if ( $refunded_orders ) {
- foreach ( $refunded_orders as $refunded_order ) {
- $order = wc_get_order( $refunded_order->order_id );
- wc_get_logger()->info( sprintf( 'order_id: %s', $refunded_order->order_id ) );
-
- // If the refund order has no line items, mark it as a full refund in orders_meta table.
- // In the above query we already excluded orders for refunded shipping and tax, so it's safe to assume that the refund order without items is a full refund.
- // Note that the "full" refund here means it's created by changing the order status to "Refunded", not partially refund all the items in the order.
- if ( $order && empty( $order->get_items() ) ) {
- $order->update_meta_data( '_refund_type', 'full' );
- $order->save_meta_data();
- }
-
- /**
- * Trigger an action to schedule the data import for old refunded order items.
- *
- * @param int $order_id The ID of the order to be synced.
- * @since 9.9.0
- */
- do_action( 'woocommerce_schedule_import', intval( $refunded_order->order_id ) );
- }
- }
-}
-
-/**
- * Update primary key to composite (order_item_id, order_id) in the wc_order_product_lookup table.
- */
-function wc_update_990_update_primary_key_to_composite_in_order_product_lookup_table() {
- global $wpdb;
- $wpdb->query( "ALTER TABLE {$wpdb->prefix}wc_order_product_lookup DROP PRIMARY KEY, ADD PRIMARY KEY (order_item_id, order_id)" );
-}
-
/**
* Remove the option woocommerce_order_attribution_install_banner_dismissed.
* This data is now stored in the user meta table in the PR #55715.
diff --git a/plugins/woocommerce/src/Admin/API/Reports/Orders/DataStore.php b/plugins/woocommerce/src/Admin/API/Reports/Orders/DataStore.php
index 03b9f7e453..2ab17305a5 100644
--- a/plugins/woocommerce/src/Admin/API/Reports/Orders/DataStore.php
+++ b/plugins/woocommerce/src/Admin/API/Reports/Orders/DataStore.php
@@ -502,9 +502,8 @@ class DataStore extends ReportsDataStore implements DataStoreInterface {
ELSE product_id
END
)
- WHERE 1 = 1
- AND order_id IN ({$included_order_ids})
- AND product_qty > 0
+ WHERE
+ order_id IN ({$included_order_ids})
",
ARRAY_A
);
diff --git a/plugins/woocommerce/src/Admin/API/Reports/Products/DataStore.php b/plugins/woocommerce/src/Admin/API/Reports/Products/DataStore.php
index 37b51d0108..c5e43ad4b4 100644
--- a/plugins/woocommerce/src/Admin/API/Reports/Products/DataStore.php
+++ b/plugins/woocommerce/src/Admin/API/Reports/Products/DataStore.php
@@ -112,40 +112,6 @@ class DataStore extends ReportsDataStore implements DataStoreInterface {
*/
public static function init() {
add_action( 'woocommerce_analytics_delete_order_stats', array( __CLASS__, 'sync_on_order_delete' ), 10 );
- add_action( 'woocommerce_order_partially_refunded', array( __CLASS__, 'add_partial_refund_type_meta' ), 10, 2 );
- add_action( 'woocommerce_order_fully_refunded', array( __CLASS__, 'add_full_refund_type_meta' ), 10, 2 );
- }
-
- /**
- * Add a partial refund type meta to the order.
- *
- * @param int $order_id Order ID.
- * @param int $refund_id Refund ID.
- */
- public static function add_partial_refund_type_meta( $order_id, $refund_id ) {
- self::add_refund_type_meta( $refund_id, 'partial' );
- }
-
- /**
- * Add a full refund type meta to the order.
- *
- * @param int $order_id Order ID.
- * @param int $refund_id Refund ID.
- */
- public static function add_full_refund_type_meta( $order_id, $refund_id ) {
- self::add_refund_type_meta( $refund_id, 'full' );
- }
-
- /**
- * Add a refund type meta to the order.
- *
- * @param int $refund_id Refund ID.
- * @param string $type Refund type.
- */
- public static function add_refund_type_meta( $refund_id, $type ) {
- $order = wc_get_order( $refund_id );
- $order->update_meta_data( '_refund_type', $type );
- $order->save_meta_data();
}
/**
@@ -467,126 +433,30 @@ class DataStore extends ReportsDataStore implements DataStoreInterface {
$decimals = wc_get_price_decimals();
$round_tax = 'no' === get_option( 'woocommerce_tax_round_at_subtotal' );
- $is_full_refund_without_line_items = false;
- $partial_refund_product_revenue = array();
- $refund_type = $order->get_meta( '_refund_type' );
-
- $parent_order = null;
-
- // When changing the order status to "Refunded", the refund order's type will be full refund, and the order items will be empty.
- // We need to get the parent order items, and exclude the items that is already being patially refunded.
- if (
- 'shop_order_refund' === $order->get_type() &&
- 'full' === $refund_type &&
- empty( $order_items )
- ) {
- $is_full_refund_without_line_items = true;
-
- $parent_order_id = $order->get_parent_id();
- $parent_order = wc_get_order( $parent_order_id );
- $order_items = $parent_order->get_items();
-
- // Get the partially refunded product and variation IDs along with their sum of product_net_revenue from the parent order.
- $partial_refund_products = $wpdb->get_results(
- $wpdb->prepare(
- "
- SELECT
- product_lookup.product_id,
- product_lookup.variation_id,
- SUM( product_lookup.product_net_revenue ) AS product_net_revenue
- FROM %i AS product_lookup
- INNER JOIN {$wpdb->prefix}wc_order_stats AS order_stats
- ON order_stats.order_id = product_lookup.order_id
- WHERE 1 = 1
- AND order_stats.parent_id = %d
- AND product_lookup.product_net_revenue < 0
- GROUP BY product_lookup.product_id, product_lookup.variation_id
- ",
- $table_name,
- $parent_order_id
- )
- );
-
- /**
- * Create a lookup table for partially refunded products.
- * E.g. [
- * '1' => -20,
- * '2' => -40,
- * '51' => -10,
- * '52' => -30,
- * ]
- */
- foreach ( $partial_refund_products as $product ) {
- $id = $product->variation_id ? $product->variation_id : $product->product_id;
- $partial_refund_product_revenue[ $id ] = (float) $product->product_net_revenue;
- }
- }
-
foreach ( $order_items as $order_item ) {
$order_item_id = $order_item->get_id();
unset( $existing_items[ $order_item_id ] );
$product_qty = $order_item->get_quantity( 'edit' );
- $product_id = $order_item->get_product_id( 'edit' );
- $variation_id = $order_item->get_variation_id( 'edit' );
$shipping_amount = $order->get_item_shipping_amount( $order_item );
$shipping_tax_amount = $order->get_item_shipping_tax_amount( $order_item );
$coupon_amount = $order->get_item_coupon_amount( $order_item );
- $tax_amount = $order->get_item_cart_tax_amount( $order_item );
- $net_revenue = round( $order_item->get_total( 'edit' ), $decimals );
-
- // If the order is a full refund and there is no order items. The order item here is the parent order item.
- if ( $is_full_refund_without_line_items ) {
- $id = $variation_id ? $variation_id : $product_id;
- $partial_refund = $partial_refund_product_revenue[ $id ] ?? 0;
- // If a single line item was refunded 60% then fully refunded after, we need store the difference in the product lookup table.
- // E.g. A product costs $100, it was previously partially refunded $60, then fully refunded $40.
- // So it will be -abs( 100 + (-60) ) = -40.
- $net_revenue = -abs( $net_revenue + $partial_refund );
-
- // Skip items that have already been fully refunded (single or multiple partial refunds).
- if ( 0.0 === $net_revenue ) {
- continue;
- }
-
- $product_qty = -abs( $product_qty );
-
- // Set coupon amount to 0 for full refunds without line items.
- $coupon_amount = 0;
-
- if ( $parent_order ) {
- $remaining_refund_items = $parent_order->get_remaining_refund_items();
-
- // Calculate the shipping amount to refund from the parent order.
- $total_shipping_refunded = $parent_order->get_total_shipping_refunded();
- $shipping_total = (float) $parent_order->get_shipping_total();
- $total_shipping_to_refund = $shipping_total - $total_shipping_refunded;
-
- if ( $total_shipping_to_refund > 0 ) {
- $shipping_amount = -abs( $parent_order->get_item_shipping_amount( $order_item, $remaining_refund_items, $total_shipping_to_refund ) );
- }
-
- // Calculate the shipping tax amount to refund from the parent order.
- $shipping_tax = (float) $parent_order->get_shipping_tax();
- $total_shipping_tax_refunded = $parent_order->get_total_shipping_tax_refunded();
- $total_shipping_tax_to_refund = $shipping_tax - $total_shipping_tax_refunded;
-
- if ( $total_shipping_tax_to_refund > 0 ) {
- $shipping_tax_amount = -abs( $parent_order->get_item_shipping_tax_amount( $order_item, $remaining_refund_items, $total_shipping_tax_to_refund ) );
- }
-
- // Calculate cart tax amount of the item from the parent order.
- $tax_amount = -abs( $parent_order->get_item_cart_tax_amount( $order_item ) );
- }
- }
-
- $is_refund = $net_revenue < 0;
// Skip line items without changes to product quantity.
- if ( ! $product_qty && ! $is_refund ) {
+ if ( ! $product_qty ) {
++$num_updated;
continue;
}
+ // Tax amount.
+ $tax_amount = 0;
+ $order_taxes = $order->get_taxes();
+ $tax_data = $order_item->get_taxes();
+ foreach ( $order_taxes as $tax_item ) {
+ $tax_item_id = $tax_item->get_rate_id();
+ $tax_amount += isset( $tax_data['total'][ $tax_item_id ] ) ? (float) $tax_data['total'][ $tax_item_id ] : 0;
+ }
+
+ $net_revenue = round( $order_item->get_total( 'edit' ), $decimals );
if ( $round_tax ) {
$tax_amount = round( $tax_amount, $decimals );
}
@@ -596,8 +466,8 @@ class DataStore extends ReportsDataStore implements DataStoreInterface {
array(
'order_item_id' => $order_item_id,
'order_id' => $order->get_id(),
- 'product_id' => $product_id,
- 'variation_id' => $variation_id,
+ 'product_id' => wc_get_order_item_meta( $order_item_id, '_product_id' ),
+ 'variation_id' => wc_get_order_item_meta( $order_item_id, '_variation_id' ),
'customer_id' => $order->get_report_customer_id(),
'product_qty' => $product_qty,
'product_net_revenue' => $net_revenue,
diff --git a/plugins/woocommerce/src/Admin/Overrides/OrderTraits.php b/plugins/woocommerce/src/Admin/Overrides/OrderTraits.php
index 1e4fb68580..682a3c81ac 100644
--- a/plugins/woocommerce/src/Admin/Overrides/OrderTraits.php
+++ b/plugins/woocommerce/src/Admin/Overrides/OrderTraits.php
@@ -16,30 +16,20 @@ trait OrderTraits {
/**
* Calculate shipping amount for line item/product as a total shipping amount ratio based on quantity.
*
- * @param WC_Order_Item $item Line item from order.
- * @param int $order_items_count (optional) The number of order items in an order. This could be the remaining items left to refund.
- * @param float $shipping_amount (optional) The shipping fee amount in an order. This could be the remaining shipping amount left to refund.
+ * @param WC_Order_Item $item Line item from order.
*
* @return float|int
*/
- public function get_item_shipping_amount( $item, $order_items_count = null, $shipping_amount = null ) {
+ public function get_item_shipping_amount( $item ) {
// Shipping amount loosely based on woocommerce code in includes/admin/meta-boxes/views/html-order-item(s).php
// distributed simply based on number of line items.
$product_qty = $item->get_quantity( 'edit' );
-
- // Use the passed order_items_count if provided, otherwise get the total number of items in the order.
- // This is useful when calculating refunds for partial items in an order.
- // For example, if 2 items are refunded from an order with 4 items. The remaining 2 items should have the shipping fee of the refunded items distributed to them.
- $order_items = $order_items_count ? $order_items_count : $this->get_item_count();
-
+ $order_items = $this->get_item_count();
if ( 0 === $order_items ) {
return 0;
}
- // Use the passed shipping_amount if provided, otherwise get the total shipping amount in the order.
- // This is useful when calculating refunds for partial shipping in an order.
- // For example, if $10 shipping is refunded from an order with $30 shipping, the remaining $20 should be distributed to the remaining items.
- $total_shipping_amount = $shipping_amount ? $shipping_amount : (float) $this->get_shipping_total();
+ $total_shipping_amount = (float) $this->get_shipping_total();
return $total_shipping_amount / $order_items * $product_qty;
}
@@ -52,43 +42,29 @@ trait OrderTraits {
* @todo If WC is currently not tax enabled, but it was before (or vice versa), would this work correctly?
*
* @param WC_Order_Item $item Line item from order.
- * @param int $order_items_count (optional) The number of order items in an order. This could be the remaining items left to refund.
- * @param float $shipping_tax_amount (optional) The shipping tax amount in an order. This could be the remaining shipping tax amount left to refund.
*
* @return float|int
*/
- public function get_item_shipping_tax_amount( $item, $order_items_count = null, $shipping_tax_amount = null ) {
- // Use the passed order_items_count if provided, otherwise get the total number of items in the order.
- // This is useful when calculating refunds for partial items in an order.
- // For example, if 2 items are refunded from an order with 4 items. The remaining 2 items should have the shipping tax of the refunded items distributed to them.
- $order_items = $order_items_count ? $order_items_count : $this->get_item_count();
-
+ public function get_item_shipping_tax_amount( $item ) {
+ $order_items = $this->get_item_count();
if ( 0 === $order_items ) {
return 0;
}
- // Use the passed shipping_tax_amount if provided, otherwise initiliase it to 0 and calculate the total shipping tax amount in the order.
- // This is useful when calculating refunds for partial shipping tax in an order.
- // For example, if $1 shipping tax is refunded from an order with $3 shipping tax, the remaining $2 should be distributed to the remaining items.
- $total_shipping_tax_amount = $shipping_tax_amount ? $shipping_tax_amount : 0;
-
- if ( null === $shipping_tax_amount ) {
- $order_taxes = $this->get_taxes();
- $line_items_shipping = $this->get_items( 'shipping' );
- foreach ( $line_items_shipping as $item_id => $shipping_item ) {
- $tax_data = $shipping_item->get_taxes();
- if ( $tax_data ) {
- foreach ( $order_taxes as $tax_item ) {
- $tax_item_id = $tax_item->get_rate_id();
- $tax_item_total = isset( $tax_data['total'][ $tax_item_id ] ) ? (float) $tax_data['total'][ $tax_item_id ] : 0;
- $total_shipping_tax_amount += $tax_item_total;
- }
+ $product_qty = $item->get_quantity( 'edit' );
+ $order_taxes = $this->get_taxes();
+ $line_items_shipping = $this->get_items( 'shipping' );
+ $total_shipping_tax_amount = 0;
+ foreach ( $line_items_shipping as $item_id => $shipping_item ) {
+ $tax_data = $shipping_item->get_taxes();
+ if ( $tax_data ) {
+ foreach ( $order_taxes as $tax_item ) {
+ $tax_item_id = $tax_item->get_rate_id();
+ $tax_item_total = isset( $tax_data['total'][ $tax_item_id ] ) ? (float) $tax_data['total'][ $tax_item_id ] : 0;
+ $total_shipping_tax_amount += $tax_item_total;
}
}
}
-
- $product_qty = $item->get_quantity( 'edit' );
-
return $total_shipping_tax_amount / $order_items * $product_qty;
}
@@ -104,24 +80,4 @@ trait OrderTraits {
public function get_item_coupon_amount( $item ) {
return floatval( $item->get_subtotal( 'edit' ) - $item->get_total( 'edit' ) );
}
-
- /**
- * Calculate cart tax amount for line item/product.
- *
- * @param WC_Order_Item $item Line item from order.
- *
- * @return float
- */
- public function get_item_cart_tax_amount( $item ) {
- $order_taxes = $this->get_taxes();
- $tax_data = $item->get_taxes();
- $cart_tax_amount = 0.0;
-
- foreach ( $order_taxes as $tax_item ) {
- $tax_item_id = $tax_item->get_rate_id();
- $cart_tax_amount += isset( $tax_data['total'][ $tax_item_id ] ) ? (float) $tax_data['total'][ $tax_item_id ] : 0;
- }
-
- return $cart_tax_amount;
- }
}
diff --git a/plugins/woocommerce/src/Internal/Admin/Schedulers/OrdersScheduler.php b/plugins/woocommerce/src/Internal/Admin/Schedulers/OrdersScheduler.php
index 7cd59b27e5..e197fa4929 100644
--- a/plugins/woocommerce/src/Internal/Admin/Schedulers/OrdersScheduler.php
+++ b/plugins/woocommerce/src/Internal/Admin/Schedulers/OrdersScheduler.php
@@ -42,7 +42,6 @@ class OrdersScheduler extends ImportScheduler {
add_action( 'woocommerce_update_order', array( __CLASS__, 'possibly_schedule_import' ) );
add_filter( 'woocommerce_create_order', array( __CLASS__, 'possibly_schedule_import' ) );
add_action( 'woocommerce_refund_created', array( __CLASS__, 'possibly_schedule_import' ) );
- add_action( 'woocommerce_schedule_import', array( __CLASS__, 'possibly_schedule_import' ) );
OrdersStatsDataStore::init();
CouponsDataStore::init();
@@ -215,7 +214,7 @@ AND status NOT IN ( 'wc-auto-draft', 'trash', 'auto-draft' )
* @returns int The order id
*/
public static function possibly_schedule_import( $order_id ) {
- if ( ! OrderUtil::is_order( $order_id, array( 'shop_order' ) ) && 'woocommerce_refund_created' !== current_filter() && 'woocommerce_schedule_import' !== current_filter() ) {
+ if ( ! OrderUtil::is_order( $order_id, array( 'shop_order' ) ) && 'woocommerce_refund_created' !== current_filter() ) {
return $order_id;
}
diff --git a/plugins/woocommerce/src/Internal/DataStores/Orders/OrdersTableDataStore.php b/plugins/woocommerce/src/Internal/DataStores/Orders/OrdersTableDataStore.php
index 96be8b3358..192f3adc19 100644
--- a/plugins/woocommerce/src/Internal/DataStores/Orders/OrdersTableDataStore.php
+++ b/plugins/woocommerce/src/Internal/DataStores/Orders/OrdersTableDataStore.php
@@ -1031,8 +1031,7 @@ WHERE
/**
* Get the total tax refunded.
*
- * @param WC_Order $order Order object.
- *
+ * @param WC_Order $order Order object.
* @return float
*/
public function get_total_tax_refunded( $order ) {
@@ -1049,36 +1048,6 @@ WHERE
INNER JOIN {$wpdb->prefix}woocommerce_order_items AS order_items ON ( order_items.order_id = orders.id AND order_items.order_item_type = 'tax' )
WHERE order_itemmeta.order_item_id = order_items.order_item_id
AND order_itemmeta.meta_key IN ('tax_amount', 'shipping_tax_amount')",
- $order->get_id(),
- )
- ) ?? 0;
- // phpcs:enable
-
- return abs( $total );
- }
-
- /**
- * Get the total shipping tax refunded.
- *
- * @param WC_Order $order Order object.
- *
- * @since 9.9.0
- * @return float
- */
- public function get_total_shipping_tax_refunded( $order ) {
- global $wpdb;
-
- $order_table = self::get_orders_table_name();
-
- $total = $wpdb->get_var(
- // phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- $order_table is hardcoded.
- $wpdb->prepare(
- "SELECT SUM( order_itemmeta.meta_value )
- FROM {$wpdb->prefix}woocommerce_order_itemmeta AS order_itemmeta
- INNER JOIN $order_table AS orders ON ( orders.type = 'shop_order_refund' AND orders.parent_order_id = %d )
- INNER JOIN {$wpdb->prefix}woocommerce_order_items AS order_items ON ( order_items.order_id = orders.id AND order_items.order_item_type = 'tax' )
- WHERE order_itemmeta.order_item_id = order_items.order_item_id
- AND order_itemmeta.meta_key = 'shipping_tax_amount'",
$order->get_id()
)
) ?? 0;
diff --git a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/reports/class-wc-tests-reports-orders-stats.php b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/reports/class-wc-tests-reports-orders-stats.php
index e82a23f6df..de1dc4d7ca 100644
--- a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/reports/class-wc-tests-reports-orders-stats.php
+++ b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/reports/class-wc-tests-reports-orders-stats.php
@@ -372,22 +372,12 @@ class WC_Admin_Tests_Reports_Orders_Stats extends WC_Unit_Test_Case {
}
// Add a partial refund on the last order.
- foreach ( $order->get_items() as $item_key => $item_values ) {
- $item_data = $item_values->get_data();
- $refund = wc_create_refund(
- array(
- 'amount' => 10,
- 'order_id' => $order->get_id(),
- 'line_items' => array(
- $item_data['id'] => array(
- 'qty' => 0,
- 'refund_total' => 10,
- ),
- ),
- )
- );
- break;
- }
+ $refund = wc_create_refund(
+ array(
+ 'amount' => 10,
+ 'order_id' => $order->get_id(),
+ )
+ );
WC_Helper_Queue::run_all_pending( 'wc-admin-data' );
@@ -418,7 +408,7 @@ class WC_Admin_Tests_Reports_Orders_Stats extends WC_Unit_Test_Case {
'shipping' => 0,
'net_revenue' => -60,
'total_customers' => 1,
- 'products' => 1,
+ 'products' => 0,
'segments' => array(),
),
'intervals' => array(
@@ -532,7 +522,7 @@ class WC_Admin_Tests_Reports_Orders_Stats extends WC_Unit_Test_Case {
'shipping' => 0,
'net_revenue' => -10,
'total_customers' => 1,
- 'products' => 1,
+ 'products' => 0,
'segments' => array(),
),
'intervals' => array(
@@ -589,7 +579,7 @@ class WC_Admin_Tests_Reports_Orders_Stats extends WC_Unit_Test_Case {
'shipping' => 0,
'net_revenue' => -50, // @todo - does this value make sense?
'total_customers' => 1,
- 'products' => 1,
+ 'products' => 0,
'segments' => array(),
),
'intervals' => array(
diff --git a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/reports/class-wc-tests-reports-products.php b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/reports/class-wc-tests-reports-products.php
index 142221ee0d..9e831e775d 100644
--- a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/reports/class-wc-tests-reports-products.php
+++ b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/reports/class-wc-tests-reports-products.php
@@ -8,7 +8,6 @@
use Automattic\WooCommerce\Admin\API\Reports\GenericQuery;
use Automattic\WooCommerce\Admin\API\Reports\Products\DataStore as ProductsDataStore;
-use Automattic\WooCommerce\Admin\API\Reports\TimeInterval;
use Automattic\WooCommerce\Admin\ReportCSVExporter;
use Automattic\WooCommerce\Enums\OrderStatus;
@@ -347,9 +346,9 @@ class WC_Admin_Tests_Reports_Products extends WC_Unit_Test_Case {
}
/**
- * Tests that line item (partial) refunds are reflected in product stats.
+ * Tests that line item refunds are reflected in product stats.
*/
- public function test_populate_and_partial_refund() {
+ public function test_populate_and_refund() {
WC_Helper_Reports::reset_stats_dbs();
// Populate all of the data.
@@ -368,7 +367,6 @@ class WC_Admin_Tests_Reports_Products extends WC_Unit_Test_Case {
$order->set_total( 97 ); // $25x4 products + $10 shipping - $20 discount + $7 tax.
$order->save();
- // Add a partial refund to the order.
foreach ( $order->get_items() as $item_key => $item_values ) {
$item_data = $item_values->get_data();
$refund = wc_create_refund(
@@ -419,209 +417,6 @@ class WC_Admin_Tests_Reports_Products extends WC_Unit_Test_Case {
$this->assertEquals( $expected_data, $query->get_data() );
}
- /**
- * Tests that full refunds are reflected in product stats.
- *
- * The full refunds here are the ones that change the order status to refunded.
- * The refund type will be full but there will not be refund order line items.
- */
- public function test_populate_and_full_refund() {
- WC_Helper_Reports::reset_stats_dbs();
-
- // Populate all of the data.
- $product = new WC_Product_Simple();
- $product->set_name( 'Test Product' );
- $product->set_regular_price( 25 );
- $product->save();
-
- $order = WC_Helper_Order::create_order( 1, $product );
- $order->set_status( OrderStatus::REFUNDED );
- $order->set_shipping_total( 10 );
- $order->set_discount_total( 20 );
- $order->set_discount_tax( 0 );
- $order->set_cart_tax( 5 );
- $order->set_shipping_tax( 2 );
- $order->set_total( 97 ); // $25x4 products + $10 shipping - $20 discount + $7 tax.
- $order->save();
-
- WC_Helper_Queue::run_all_pending( 'wc-admin-data' );
-
- $data_store = new ProductsDataStore();
- $start_time = gmdate( 'Y-m-d H:00:00', $order->get_date_created()->getOffsetTimestamp() );
- $end_time = gmdate( 'Y-m-d H:00:00', $order->get_date_created()->getOffsetTimestamp() + HOUR_IN_SECONDS );
- $args = array(
- 'after' => $start_time,
- 'before' => $end_time,
- );
-
- // Test retrieving the stats through the data store.
- $data = $data_store->get_data( $args );
- $expected_data = (object) array(
- 'total' => 1,
- 'pages' => 1,
- 'page_no' => 1,
- 'data' => array(
- 0 => array(
- 'product_id' => $product->get_id(),
- 'items_sold' => 0,
- 'net_revenue' => 0.0,
- 'orders_count' => 1,
- 'extended_info' => new ArrayObject(),
- ),
- ),
- );
- $this->assertEquals( $expected_data, $data );
-
- // Test retrieving the stats through the generic query class.
- $query = new GenericQuery( $args, 'products' );
- $this->assertEquals( $expected_data, $query->get_data() );
- }
-
- /**
- * Tests that line items that are all refunded are reflected in product stats.
- *
- * This is the case when all line items in an order are refunded each by 100%.
- * The refund type will be full and there will be refund order line items.
- */
- public function test_populate_and_refund_all_items_in_an_order() {
- WC_Helper_Reports::reset_stats_dbs();
-
- // Populate all of the data.
- $product = new WC_Product_Simple();
- $product->set_name( 'Test Product' );
- $product->set_regular_price( 25 );
- $product->save();
-
- $order = WC_Helper_Order::create_order( 1, $product );
- $order->set_status( OrderStatus::COMPLETED );
- $order->set_shipping_total( 10 );
- $order->set_discount_total( 20 );
- $order->set_discount_tax( 0 );
- $order->set_cart_tax( 5 );
- $order->set_shipping_tax( 2 );
- $order->set_total( 97 ); // $25x4 products + $10 shipping - $20 discount + $7 tax.
- $order->save();
-
- // Add a partial refund to the order.
- // This partial refund will refund all items in the order.
- foreach ( $order->get_items() as $item_key => $item_values ) {
- $item_data = $item_values->get_data();
- $refund = wc_create_refund(
- array(
- 'amount' => 97,
- 'order_id' => $order->get_id(),
- 'line_items' => array(
- $item_data['id'] => array(
- 'qty' => 4,
- 'refund_total' => 100,
- ),
- ),
- )
- );
- }
-
- WC_Helper_Queue::run_all_pending( 'wc-admin-data' );
-
- $data_store = new ProductsDataStore();
- $start_time = gmdate( 'Y-m-d H:00:00', $order->get_date_created()->getOffsetTimestamp() );
- $end_time = gmdate( 'Y-m-d H:00:00', $order->get_date_created()->getOffsetTimestamp() + HOUR_IN_SECONDS );
- $args = array(
- 'after' => $start_time,
- 'before' => $end_time,
- );
-
- // Test retrieving the stats through the data store.
- $data = $data_store->get_data( $args );
- $expected_data = (object) array(
- 'total' => 1,
- 'pages' => 1,
- 'page_no' => 1,
- 'data' => array(
- 0 => array(
- 'product_id' => $product->get_id(),
- 'items_sold' => 0,
- 'net_revenue' => 0.0, // $25 * 4 - $100 refund.
- 'orders_count' => 1,
- 'extended_info' => new ArrayObject(),
- ),
- ),
- );
- $this->assertEquals( $expected_data, $data );
-
- // Test retrieving the stats through the generic query class.
- $query = new GenericQuery( $args, 'products' );
- $this->assertEquals( $expected_data, $query->get_data() );
- }
-
- /**
- * Tests that shipping fee refunds are reflected in product stats.
- * Shipping fee refund is a partial refund without line items.
- */
- public function test_populate_and_shipping_fee_refund() {
- WC_Helper_Reports::reset_stats_dbs();
-
- // Populate all of the data.
- $product = new WC_Product_Simple();
- $product->set_name( 'Test Product' );
- $product->set_regular_price( 25 );
- $product->save();
-
- $order = WC_Helper_Order::create_order( 1, $product );
- $order->set_status( OrderStatus::COMPLETED );
- $order->set_shipping_total( 10 );
- $order->set_discount_total( 20 );
- $order->set_discount_tax( 0 );
- $order->set_cart_tax( 5 );
- $order->set_shipping_tax( 2 );
- $order->set_total( 97 ); // $25x4 products + $10 shipping - $20 discount + $7 tax.
- $order->save();
-
- // Add a partial refund without line items to the order.
- // Shipping fee refund is a partial refund without line items.
- foreach ( $order->get_items() as $item_key => $item_values ) {
- $item_data = $item_values->get_data();
- $refund = wc_create_refund(
- array(
- 'amount' => 10,
- 'order_id' => $order->get_id(),
- )
- );
- break;
- }
-
- WC_Helper_Queue::run_all_pending( 'wc-admin-data' );
-
- $data_store = new ProductsDataStore();
- $start_time = gmdate( 'Y-m-d H:00:00', $order->get_date_created()->getOffsetTimestamp() );
- $end_time = gmdate( 'Y-m-d H:00:00', $order->get_date_created()->getOffsetTimestamp() + HOUR_IN_SECONDS );
- $args = array(
- 'after' => $start_time,
- 'before' => $end_time,
- );
-
- // Test retrieving the stats through the data store.
- $data = $data_store->get_data( $args );
- $expected_data = (object) array(
- 'total' => 1,
- 'pages' => 1,
- 'page_no' => 1,
- 'data' => array(
- 0 => array(
- 'product_id' => $product->get_id(),
- 'items_sold' => 4,
- 'net_revenue' => 100.0,
- 'orders_count' => 1,
- 'extended_info' => new ArrayObject(),
- ),
- ),
- );
- $this->assertEquals( $expected_data, $data );
-
- // Test retrieving the stats through the generic query class.
- $query = new GenericQuery( $args, 'products' );
- $this->assertEquals( $expected_data, $query->get_data() );
- }
-
/**
* Test that filters get properly parsed for CSV exports.
* See: https://github.com/woocommerce/woocommerce-admin/issues/5503.
@@ -696,388 +491,4 @@ class WC_Admin_Tests_Reports_Products extends WC_Unit_Test_Case {
$this->assertEquals( 0, $export->get_total_exported() );
$this->assertEquals( $expected_csv, $actual_csv );
}
-
- /**
- * Tests the data stored in the wc_order_product_lookup table when a full refund is made.
- *
- * The full refunds here are the ones that change the order status to refunded.
- * The refund type will be full but there will not be refund order line items.
- */
- public function test_sync_order_products_full_refund() {
- global $wpdb;
-
- WC_Helper_Reports::reset_stats_dbs();
-
- // Enable Tax.
- update_option( 'woocommerce_prices_include_tax', 'no' );
- update_option( 'woocommerce_calc_taxes', 'yes' );
-
- // Create a 10% tax rate.
- $tax_rate = array(
- 'tax_rate_country' => '',
- 'tax_rate' => '10',
- 'tax_rate_name' => 'tax',
- 'tax_rate_order' => '0',
- 'tax_rate_shipping' => '1',
- );
- WC_Tax::_insert_tax_rate( $tax_rate );
-
- // Create product 1 with price $25.
- $product_1 = new WC_Product_Simple();
- $product_1->set_name( 'Test Product 1' );
- $product_1->set_regular_price( 25 );
- $product_1->save();
-
- // Create product 2 with price $30.
- $product_2 = new WC_Product_Simple();
- $product_2->set_name( 'Test Product 2' );
- $product_2->set_regular_price( 30 );
- $product_2->save();
-
- // Create an order and add product_1 as the order item. The quantity is set to 4.
- $order = WC_Helper_Order::create_order( 1, $product_1 );
-
- // Add product_2 as the second order item. The quantity is set to 2.
- $item = new WC_Order_Item_Product();
- $item->set_props(
- array(
- 'product' => $product_2,
- 'quantity' => 2,
- 'subtotal' => wc_get_price_excluding_tax( $product_2, array( 'qty' => 2 ) ),
- 'total' => wc_get_price_excluding_tax( $product_2, array( 'qty' => 2 ) ),
- )
- );
- $item->save();
- $order->add_item( $item );
-
- // Add a flat rate shipping method to the order. The shipping cost is $100.
- $rate = new WC_Shipping_Rate( 'flat_rate_shipping', 'Flat rate shipping', '100', array(), 'flat_rate' );
- $shipping_item = new WC_Order_Item_Shipping();
- $shipping_item->set_props(
- array(
- 'method_title' => $rate->label,
- 'method_id' => $rate->id,
- 'total' => wc_format_decimal( $rate->cost ),
- 'taxes' => $rate->taxes,
- )
- );
- foreach ( $rate->get_meta_data() as $key => $value ) {
- $shipping_item->add_meta_data( $key, $value, true );
- }
- // Remove existing shipping items that created by WC_Helper_Order::create_order.
- $order->remove_order_items( 'shipping' );
- $order->add_item( $shipping_item );
-
- $order->set_status( OrderStatus::COMPLETED );
- $order->calculate_totals( true );
- $order->save();
-
- WC_Helper_Queue::run_all_pending( 'wc-admin-data' );
-
- // Refund the order completely by changing the order status to refunded.
- $order->set_status( OrderStatus::REFUNDED );
- $order->save();
-
- WC_Helper_Queue::run_all_pending( 'wc-admin-data' );
-
- // Get the last order item from the order.
- $order_items = $order->get_items();
- $order_item_id = end( $order_items )->get_id();
-
- // Get the refund order id.
- $refund_order_id = $order->get_refunds()[0]->get_id();
-
- $result = $wpdb->get_results(
- $wpdb->prepare(
- "SELECT * FROM {$wpdb->prefix}wc_order_product_lookup WHERE order_item_id = %d AND order_id = %d",
- $order_item_id,
- $refund_order_id
- )
- );
-
- $this->assertEquals( '-2', $result[0]->product_qty );
- $this->assertEquals( -60.000000, $result[0]->product_net_revenue ); // -($30 product_2 * 2).
- $this->assertEquals( -33.333333, $result[0]->shipping_amount ); // -($100 shipping / 6 total items * 2 product_2 ).
- $this->assertEquals( -3.333333, $result[0]->shipping_tax_amount ); // -($10 shipping tax / 6 total items * 2 product_2 ).
- $this->assertEquals( -6, $result[0]->tax_amount ); // -($30 product_2 * 10% tax * 2 quantity).
- $this->assertEquals( 0, $result[0]->coupon_amount );
- $this->assertEquals( -102.666667, $result[0]->product_gross_revenue ); // product_net_revenue + shipping_amount + shipping_tax_amount + tax_amount.
- }
-
- /**
- * Tests the data stored in the wc_order_product_lookup table when an order item is refunded then a full refund is made.
- *
- * The full refunds here are the ones that change the order status to refunded.
- * The refund type will be full but there will not be refund order line items.
- */
- public function test_sync_order_products_refund_one_product_then_full_refund() {
- $this->markTestSkipped( 'Mark flaky test for revisit as first assertion occasionally fails with null value.' );
-
- global $wpdb;
-
- WC_Helper_Reports::reset_stats_dbs();
-
- // Enable Tax.
- update_option( 'woocommerce_prices_include_tax', 'no' );
- update_option( 'woocommerce_calc_taxes', 'yes' );
-
- // Create a 10% tax rate.
- $tax_rate = array(
- 'tax_rate_country' => '',
- 'tax_rate' => '10',
- 'tax_rate_name' => 'tax',
- 'tax_rate_order' => '0',
- 'tax_rate_shipping' => '1',
- );
- WC_Tax::_insert_tax_rate( $tax_rate );
-
- // Create product 1 with price $25.
- $product_1 = new WC_Product_Simple();
- $product_1->set_name( 'Test Product 1' );
- $product_1->set_regular_price( 25 );
- $product_1->save();
-
- // Create product 2 with price $30.
- $product_2 = new WC_Product_Simple();
- $product_2->set_name( 'Test Product 2' );
- $product_2->set_regular_price( 30 );
- $product_2->save();
-
- // Create product 3 with price $40.
- $product_3 = new WC_Product_Simple();
- $product_3->set_name( 'Test Product 3' );
- $product_3->set_regular_price( 40 );
- $product_3->save();
-
- // Create an order and add product_1 as the order item. The quantity is set to 4.
- $order = WC_Helper_Order::create_order( 1, $product_1 );
-
- // Add product_2 as the second order item with quantity set to 2.
- $item = new WC_Order_Item_Product();
- $item->set_props(
- array(
- 'product' => $product_2,
- 'quantity' => 2,
- 'subtotal' => wc_get_price_excluding_tax( $product_2, array( 'qty' => 2 ) ),
- 'total' => wc_get_price_excluding_tax( $product_2, array( 'qty' => 2 ) ),
- )
- );
- $item->save();
- $order->add_item( $item );
-
- // Add product_3 as the third order item with quantity set to 3.
- $item = new WC_Order_Item_Product();
- $item->set_props(
- array(
- 'product' => $product_3,
- 'quantity' => 3,
- 'subtotal' => wc_get_price_excluding_tax( $product_3, array( 'qty' => 3 ) ),
- 'total' => wc_get_price_excluding_tax( $product_3, array( 'qty' => 3 ) ),
- )
- );
- $item->save();
- $order->add_item( $item );
-
- // Add a flat rate shipping method to the order. The shipping cost is $100.
- $rate = new WC_Shipping_Rate( 'flat_rate_shipping', 'Flat rate shipping', '100', array(), 'flat_rate' );
- $shipping_item = new WC_Order_Item_Shipping();
- $shipping_item->set_props(
- array(
- 'method_title' => $rate->label,
- 'method_id' => $rate->id,
- 'total' => wc_format_decimal( $rate->cost ),
- 'taxes' => $rate->taxes,
- )
- );
- foreach ( $rate->get_meta_data() as $key => $value ) {
- $shipping_item->add_meta_data( $key, $value, true );
- }
- // Remove existing shipping items that created by WC_Helper_Order::create_order.
- $order->remove_order_items( 'shipping' );
- $order->add_item( $shipping_item );
-
- $order->set_status( OrderStatus::COMPLETED );
- $order->calculate_totals( true );
- $order->save();
-
- // Refund the first order item completely.
- foreach ( $order->get_items() as $item_key => $item_values ) {
- $item_data = $item_values->get_data();
- $refund = wc_create_refund(
- array(
- 'amount' => 100,
- 'order_id' => $order->get_id(),
- 'line_items' => array(
- $item_data['id'] => array(
- 'qty' => 4,
- 'refund_total' => 100,
- ),
- ),
- )
- );
- break;
- }
-
- WC_Helper_Queue::run_all_pending( 'wc-admin-data' );
-
- // Refund the order completely by changing the order status to refunded.
- $order->set_status( OrderStatus::REFUNDED );
- $order->save();
-
- WC_Helper_Queue::run_all_pending( 'wc-admin-data' );
-
- // Get the last order item (product_3) from the order.
- $order_items = $order->get_items();
- $order_item_id = end( $order_items )->get_id();
-
- // Get the last refund order id.
- $refunds = $order->get_refunds();
- $refund_order_id = end( $refunds )->get_id();
-
- $result = $wpdb->get_results(
- $wpdb->prepare(
- "SELECT * FROM {$wpdb->prefix}wc_order_product_lookup WHERE order_item_id = %d AND order_id = %d",
- $order_item_id,
- $refund_order_id
- )
- );
-
- $this->assertEquals( '-3', $result[0]->product_qty );
- $this->assertEquals( -120.000000, $result[0]->product_net_revenue ); // -($40 product_3 * 3).
- $this->assertEquals( -60.000000, $result[0]->shipping_amount ); // -($100 shipping / ( 9 total items - 4 refunded items ) * 3 product_3 ).
- $this->assertEquals( -6.000000, $result[0]->shipping_tax_amount ); // -($10 shipping tax / ( 9 total items - 4 refunded items ) * 3 product_3 ).
- $this->assertEquals( -12, $result[0]->tax_amount ); // -($40 product_3 * 10% tax * 3 quantity ).
- $this->assertEquals( 0, $result[0]->coupon_amount );
- $this->assertEquals( -198, $result[0]->product_gross_revenue ); // product_net_revenue + shipping_amount + shipping_tax_amount + tax_amount.
- }
-
- /**
- * Tests the data stored in the wc_order_product_lookup table when a full refund is made.
- *
- * The full refunds here are the ones that change the order status to refunded.
- * The refund type will be full but there will not be refund order line items.
- */
- public function test_sync_order_products_full_refund_compound_tax() {
- global $wpdb;
-
- WC_Helper_Reports::reset_stats_dbs();
-
- // Enable Tax.
- update_option( 'woocommerce_prices_include_tax', 'no' );
- update_option( 'woocommerce_calc_taxes', 'yes' );
-
- // Create a 10% tax rate for all countries.
- $tax_rate = array(
- 'tax_rate_country' => '',
- 'tax_rate' => '10',
- 'tax_rate_name' => 'tax',
- 'tax_rate_shipping' => '1',
- 'tax_rate_compound' => '1',
- 'tax_rate_order' => '1',
- 'tax_rate_priority' => '1',
- );
- WC_Tax::_insert_tax_rate( $tax_rate );
-
- // Create a 5% tax rate for US.
- $us_tax_rate = array(
- 'tax_rate_country' => 'US',
- 'tax_rate' => '5',
- 'tax_rate_name' => 'US tax',
- 'tax_rate_shipping' => '1',
- 'tax_rate_compound' => '1',
- 'tax_rate_order' => '2',
- 'tax_rate_priority' => '2',
- );
- WC_Tax::_insert_tax_rate( $us_tax_rate );
-
- // Create product 1 with price $25.
- $product_1 = new WC_Product_Simple();
- $product_1->set_name( 'Test Product 1' );
- $product_1->set_regular_price( 25 );
- $product_1->save();
-
- // Create product 2 with price $30.
- $product_2 = new WC_Product_Simple();
- $product_2->set_name( 'Test Product 2' );
- $product_2->set_regular_price( 30 );
- $product_2->save();
-
- // Create an order and add product_1 as the order item. The quantity is set to 4.
- $order = WC_Helper_Order::create_order( 1, $product_1 );
-
- // Add product_2 as the second order item. The quantity is set to 2.
- $item = new WC_Order_Item_Product();
- $item->set_props(
- array(
- 'product' => $product_2,
- 'quantity' => 2,
- 'subtotal' => wc_get_price_excluding_tax( $product_2, array( 'qty' => 2 ) ),
- 'total' => wc_get_price_excluding_tax( $product_2, array( 'qty' => 2 ) ),
- )
- );
- $item->save();
- $order->add_item( $item );
-
- // Add a flat rate shipping method to the order. The shipping cost is $100.
- $rate = new WC_Shipping_Rate( 'flat_rate_shipping', 'Flat rate shipping', '100', array(), 'flat_rate' );
- $shipping_item = new WC_Order_Item_Shipping();
- $shipping_item->set_props(
- array(
- 'method_title' => $rate->label,
- 'method_id' => $rate->id,
- 'total' => wc_format_decimal( $rate->cost ),
- 'taxes' => $rate->taxes,
- )
- );
- foreach ( $rate->get_meta_data() as $key => $value ) {
- $shipping_item->add_meta_data( $key, $value, true );
- }
- // Remove existing shipping items that created by WC_Helper_Order::create_order.
- $order->remove_order_items( 'shipping' );
- $order->add_item( $shipping_item );
-
- $order->set_status( OrderStatus::COMPLETED );
- $order->calculate_totals( true );
- $order->save();
-
- WC_Helper_Queue::run_all_pending( 'wc-admin-data' );
-
- // Refund the order completely by changing the order status to refunded.
- $order->set_status( OrderStatus::REFUNDED );
- $order->save();
-
- WC_Helper_Queue::run_all_pending( 'wc-admin-data' );
-
- // Get the last order item from the order.
- $order_items = $order->get_items();
- $order_item_id = end( $order_items )->get_id();
-
- // Get the refund order id.
- $refund_order_id = $order->get_refunds()[0]->get_id();
-
- $result = $wpdb->get_results(
- $wpdb->prepare(
- "SELECT * FROM {$wpdb->prefix}wc_order_product_lookup WHERE order_item_id = %d AND order_id = %d",
- $order_item_id,
- $refund_order_id
- )
- );
-
- $this->assertEquals( '-2', $result[0]->product_qty );
- $this->assertEquals( -60.000000, $result[0]->product_net_revenue ); // -($30 product_2 * 2).
- $this->assertEquals( -33.333333, $result[0]->shipping_amount ); // -($100 shipping / 6 total items * 2 product_2 ).
-
- // 10% tax: $100 shipping * 0.1 = $10.
- // 5% compound tax: $100 shipping * 1.1 * 0.05 = $5.5.
- // -($10 + $5.5) / 6 total items * 2 product_2 = -$5.166667.
- $this->assertEquals( -5.166667, $result[0]->shipping_tax_amount );
-
- // 10% tax: $30 product_2 * 0.1 = $3.
- // 5% compound tax: $30 product_2 * 1.1 * 0.05 = $1.65.
- // -($3 + $1.65) * 2 quantity = -$9.3.
- $this->assertEquals( -9.3, $result[0]->tax_amount );
-
- $this->assertEquals( 0, $result[0]->coupon_amount );
- $this->assertEquals( -107.8, $result[0]->product_gross_revenue ); // product_net_revenue + shipping_amount + shipping_tax_amount + tax_amount.
- }
}
diff --git a/plugins/woocommerce/tests/php/src/Internal/DataStores/Orders/OrdersTableDataStoreTests.php b/plugins/woocommerce/tests/php/src/Internal/DataStores/Orders/OrdersTableDataStoreTests.php
index beeb240a97..1563ecd285 100644
--- a/plugins/woocommerce/tests/php/src/Internal/DataStores/Orders/OrdersTableDataStoreTests.php
+++ b/plugins/woocommerce/tests/php/src/Internal/DataStores/Orders/OrdersTableDataStoreTests.php
@@ -1563,9 +1563,9 @@ class OrdersTableDataStoreTests extends \HposTestCase {
}
/**
- * Test methods get_total_tax_refunded, get_total_shipping_refunded, and get_total_shipping_tax_refunded.
+ * Test methods get_total_tax_refunded and get_total_shipping_refunded.
*/
- public function test_get_total_tax_refunded_and_get_total_shipping_refunded_and_get_total_shipping_tax_refunded() {
+ public function test_get_total_tax_refunded_and_get_total_shipping_refunded() {
update_option( 'woocommerce_prices_include_tax', 'yes' );
update_option( 'woocommerce_calc_taxes', 'yes' );
@@ -1629,7 +1629,6 @@ class OrdersTableDataStoreTests extends \HposTestCase {
$this->assertEquals( 5, $order->get_data_store()->get_total_tax_refunded( $order ) );
$this->assertEquals( 10, $order->get_data_store()->get_total_shipping_refunded( $order ) );
- $this->assertEquals( 3, $order->get_data_store()->get_total_shipping_tax_refunded( $order ) );
}
/**