Commit 8c91802c96 for woocommerce
commit 8c91802c9606a4fb46d6f1692636c8a3fded1277
Author: Pavel Dohnal <pavel.dohnal@automattic.com>
Date: Fri Apr 25 15:15:49 2025 +0200
Hide backorder meta on completed orders (#57450)
* Add changelog
[WOOPLUG-266]
* Hide backorder meta on completed orders
Products previously on backorder continued showing the backorder status
in emails after the order was fulfilled.
[WOOPLUG-266]
* Use an enum instead of hardcoded string
[WOOPLUG-266]
* Use an enum instead of hardcoded string in test
[WOOPLUG-266]
* Remove redundant code
[WOOPLUG-266]
---------
Co-authored-by: Vladimir Reznichenko <kalessil@gmail.com>
diff --git a/plugins/woocommerce/changelog/wooplug-266-product-variation-backordered-product-bought-still-shows-as b/plugins/woocommerce/changelog/wooplug-266-product-variation-backordered-product-bought-still-shows-as
new file mode 100644
index 0000000000..5306d98218
--- /dev/null
+++ b/plugins/woocommerce/changelog/wooplug-266-product-variation-backordered-product-bought-still-shows-as
@@ -0,0 +1,4 @@
+Significance: patch
+Type: fix
+
+Hide backorder meta on completed orders
diff --git a/plugins/woocommerce/includes/class-wc-order-item-product.php b/plugins/woocommerce/includes/class-wc-order-item-product.php
index e0ac7a6506..ec4c4af155 100644
--- a/plugins/woocommerce/includes/class-wc-order-item-product.php
+++ b/plugins/woocommerce/includes/class-wc-order-item-product.php
@@ -7,6 +7,7 @@
* @since 3.0.0
*/
+use Automattic\WooCommerce\Enums\OrderStatus;
use Automattic\WooCommerce\Enums\ProductTaxStatus;
use Automattic\WooCommerce\Enums\ProductType;
use Automattic\WooCommerce\Utilities\NumberUtil;
@@ -435,6 +436,43 @@ class WC_Order_Item_Product extends WC_Order_Item {
return $product ? $product->get_tax_status() : ProductTaxStatus::TAXABLE;
}
+ /**
+ * Get formatted meta data for the item.
+ *
+ * This overrides the parent method to conditionally remove backorder
+ * meta data when the order is marked as completed.
+ *
+ * @param string $hideprefix Meta data prefix, (default: _).
+ * @param bool $include_all Include all meta data, this stop skip items with values already in the product name.
+ * @return array
+ */
+ public function get_formatted_meta_data( $hideprefix = '_', $include_all = false ) {
+ $formatted_meta = parent::get_formatted_meta_data( $hideprefix, $include_all );
+
+ $order = $this->get_order();
+
+ if ( $order && $order->has_status( OrderStatus::COMPLETED ) ) {
+ /**
+ * Filter the backorder meta key.
+ * Make sure to use the same filter as used in set_backorder_meta().
+ *
+ * @param string $backorder_meta_key The backorder meta key.
+ * @param WC_Order_Item_Product $item The order item product.
+ * @since 9.9.0
+ * @return string
+ */
+ $backorder_meta_key = apply_filters( 'woocommerce_backordered_item_meta_name', __( 'Backordered', 'woocommerce' ), $this );
+
+ foreach ( $formatted_meta as $meta_id => $meta ) {
+ if ( isset( $meta->key ) && $meta->key === $backorder_meta_key ) {
+ unset( $formatted_meta[ $meta_id ] );
+ }
+ }
+ }
+
+ return $formatted_meta;
+ }
+
/*
|--------------------------------------------------------------------------
| Array Access Methods
diff --git a/plugins/woocommerce/tests/php/includes/class-wc-order-item-product-test.php b/plugins/woocommerce/tests/php/includes/class-wc-order-item-product-test.php
new file mode 100644
index 0000000000..ac5ed212df
--- /dev/null
+++ b/plugins/woocommerce/tests/php/includes/class-wc-order-item-product-test.php
@@ -0,0 +1,76 @@
+<?php
+/**
+ * Unit tests for the WC_Order_Item_Product class functionalities.
+ *
+ * @package WooCommerce\Tests
+ */
+
+declare( strict_types=1 );
+
+use Automattic\WooCommerce\Enums\OrderStatus;
+
+/**
+ * WC_Order_Item_Product unit tests.
+ */
+class WC_Order_Item_Product_Test extends WC_Unit_Test_Case {
+
+ /**
+ * Test that backorder meta is excluded from formatted meta data
+ * for completed orders.
+ */
+ public function test_get_formatted_meta_data_excludes_backorder_on_completed() {
+ // 1. Setup: Create product and set backorders allowed.
+ $product = WC_Helper_Product::create_simple_product();
+ $product->set_manage_stock( true );
+ $product->set_stock_quantity( 0 );
+ $product->set_backorders( 'notify' ); // Allow backorders with notification.
+ $product->save();
+
+ // 2. Create Order and add product item.
+ $order = WC_Helper_Order::create_order();
+ $item = new WC_Order_Item_Product();
+ $item->set_product( $product );
+ $item->set_quantity( 1 );
+ $item->set_order_id( $order->get_id() );
+
+ // 3. Add backorder meta.
+ $backorder_meta_key = 'Backordered';
+ $item->add_meta_data( $backorder_meta_key, 1, true ); // Value typically is the backordered quantity.
+ $item->save();
+ $order->add_item( $item );
+ $order->save();
+
+ // 4. Assert: Check meta exists before completion.
+ $item_id = $item->get_id();
+ $order_item = $order->get_item( $item_id ); // Re-fetch item from order.
+ $formatted_meta_before = $order_item->get_formatted_meta_data();
+ $found_backorder_before = false;
+ foreach ( $formatted_meta_before as $meta ) {
+ if ( $meta->key === $backorder_meta_key ) {
+ $found_backorder_before = true;
+ break;
+ }
+ }
+ $this->assertTrue( $found_backorder_before, 'Backorder meta should exist before order completion.' );
+
+ // 5. Complete the order.
+ $order->update_status( OrderStatus::COMPLETED );
+ $order->save();
+
+ // 6. Assert: Check meta is excluded after completion.
+ $order_item_after_complete = $order->get_item( $item_id ); // Re-fetch item again after status change.
+ $formatted_meta_after = $order_item_after_complete->get_formatted_meta_data();
+ $found_backorder_after = false;
+ foreach ( $formatted_meta_after as $meta ) {
+ if ( $meta->key === $backorder_meta_key ) {
+ $found_backorder_after = true;
+ break;
+ }
+ }
+ $this->assertFalse( $found_backorder_after, 'Backorder meta should be excluded after order completion.' );
+
+ // Clean up.
+ WC_Helper_Product::delete_product( $product->get_id() );
+ WC_Helper_Order::delete_order( $order->get_id() );
+ }
+}