Commit a96e5adcef3 for woocommerce

commit a96e5adcef3284ef96f0c4255da81b108a5969df
Author: Ricardo Sawir <37329575+sawirricardo@users.noreply.github.com>
Date:   Wed Jul 1 12:11:42 2026 +0700

    Fix customer history CPT order fallback (#65921)

    * Fix customer history CPT order fallback

    * Address review nits: rename CPT report ID helper and reorder test asserts

    ---------

    Co-authored-by: Chi-Hsuan Huang <chihsuan.tw@gmail.com>

diff --git a/plugins/woocommerce/changelog/65867-customer-history-cpt-order b/plugins/woocommerce/changelog/65867-customer-history-cpt-order
new file mode 100644
index 00000000000..dc9363cd3c2
--- /dev/null
+++ b/plugins/woocommerce/changelog/65867-customer-history-cpt-order
@@ -0,0 +1,4 @@
+Significance: patch
+Type: fix
+
+Prevent customer history metabox warnings for CPT-backed orders.
diff --git a/plugins/woocommerce/src/Internal/Admin/Orders/MetaBoxes/CustomerHistory.php b/plugins/woocommerce/src/Internal/Admin/Orders/MetaBoxes/CustomerHistory.php
index 1d8e1aa7798..d6020bb3ba0 100644
--- a/plugins/woocommerce/src/Internal/Admin/Orders/MetaBoxes/CustomerHistory.php
+++ b/plugins/woocommerce/src/Internal/Admin/Orders/MetaBoxes/CustomerHistory.php
@@ -1,8 +1,10 @@
 <?php
+declare( strict_types = 1 );

 namespace Automattic\WooCommerce\Internal\Admin\Orders\MetaBoxes;

 use Automattic\WooCommerce\Admin\API\Reports\Customers\Query as CustomersQuery;
+use Automattic\WooCommerce\Admin\Overrides\Order as AdminOrder;
 use Automattic\WooCommerce\Internal\DataStores\Orders\OrdersTableDataStore;
 use Automattic\WooCommerce\Utilities\OrderUtil;
 use WC_Order;
@@ -51,17 +53,16 @@ class CustomerHistory {
 			$customer_id   = $order->get_customer_id();
 			$billing_email = $order->get_billing_email();
 			$result        = $this->query_hpos( $customer_id, $billing_email );
-		} elseif ( method_exists( $order, 'get_report_customer_id' ) ) {
-			$result = $this->query_cpt( $order->get_report_customer_id() );
 		} else {
-			wc_get_logger()->warning(
-				'CustomerHistory: Order object does not have get_report_customer_id method.',
-				array( 'source' => 'customer-history' )
-			);
-			$result = (object) array(
-				'orders_count' => 0,
-				'total_spend'  => 0,
-			);
+			$customer_report_id = $this->get_cpt_report_customer_id( $order );
+			if ( $customer_report_id > 0 ) {
+				$result = $this->query_cpt( $customer_report_id );
+			} else {
+				$result = (object) array(
+					'orders_count' => 0,
+					'total_spend'  => 0,
+				);
+			}
 		}

 		$orders_count = (int) ( $result->orders_count ?? 0 );
@@ -226,6 +227,22 @@ class CustomerHistory {
 		);
 	}

+	/**
+	 * Get the analytics customer ID for a CPT-backed order.
+	 *
+	 * @param WC_Order $order The order object.
+	 * @return int The reports customer ID.
+	 */
+	private function get_cpt_report_customer_id( WC_Order $order ): int {
+		if ( ! $order->get_id() ) {
+			return 0;
+		}
+
+		$report_order = $order instanceof AdminOrder ? $order : new AdminOrder( $order->get_id() );
+
+		return (int) $report_order->get_report_customer_id();
+	}
+
 	/**
 	 * Get the list of excluded order statuses for customer history.
 	 *
diff --git a/plugins/woocommerce/tests/php/src/Internal/Admin/Orders/MetaBoxes/CustomerHistoryTest.php b/plugins/woocommerce/tests/php/src/Internal/Admin/Orders/MetaBoxes/CustomerHistoryTest.php
index e43bb7f8ad5..ff2a3a5ea54 100644
--- a/plugins/woocommerce/tests/php/src/Internal/Admin/Orders/MetaBoxes/CustomerHistoryTest.php
+++ b/plugins/woocommerce/tests/php/src/Internal/Admin/Orders/MetaBoxes/CustomerHistoryTest.php
@@ -4,6 +4,7 @@ declare( strict_types = 1 );
 namespace Automattic\WooCommerce\Tests\Internal\Admin\Orders\MetaBoxes;

 use Automattic\WooCommerce\Admin\API\Reports\Orders\Stats\DataStore as OrdersStatsDataStore;
+use Automattic\WooCommerce\Admin\Overrides\Order as AdminOrder;
 use Automattic\WooCommerce\Internal\Admin\Orders\MetaBoxes\CustomerHistory;
 use Automattic\WooCommerce\RestApi\UnitTests\HPOSToggleTrait;
 use WC_Helper_Order;
@@ -542,4 +543,45 @@ class CustomerHistoryTest extends WC_Unit_Test_Case {
 		$this->assertMatchesRegularExpression( '/order-attribution-total-orders">\s*1\s*</', $output, 'Should show 1 order from analytics data' );
 		$this->assertMatchesRegularExpression( '/order-attribution-total-spend">\s*.*100\.00/', $output, 'Should show total spend of 100' );
 	}
+
+	/**
+	 * @testdox CPT fallback should render customer history from a base WC_Order without logging warnings.
+	 */
+	public function test_cpt_fallback_renders_with_base_order(): void {
+		$this->toggle_cot_feature_and_usage( false );
+
+		\WC_Helper_Reports::reset_stats_dbs();
+
+		$customer_id = $this->factory->user->create();
+
+		$order = WC_Helper_Order::create_order( $customer_id );
+		$order->set_status( 'completed' );
+		$order->set_total( 100 );
+		$order->save();
+
+		OrdersStatsDataStore::update( new AdminOrder( $order->get_id() ) );
+
+		$logger = $this->getMockBuilder( \WC_Logger_Interface::class )->getMock();
+		$logger->expects( $this->never() )->method( 'warning' );
+
+		$inject_logger = function () use ( $logger ) {
+			return $logger;
+		};
+		add_filter( 'woocommerce_logging_class', $inject_logger );
+
+		$this->assertInstanceOf( \WC_Order::class, $order, 'Test should pass a base order to the metabox' );
+		$this->assertNotInstanceOf( AdminOrder::class, $order, 'Test should not pass the admin override order to the metabox' );
+
+		ob_start();
+		try {
+			$this->sut->output( $order );
+			$output = ob_get_clean();
+		} finally {
+			remove_filter( 'woocommerce_logging_class', $inject_logger );
+		}
+
+		$this->assertStringContainsString( 'order-attribution-total-orders', $output, 'Should render the metabox template' );
+		$this->assertMatchesRegularExpression( '/order-attribution-total-orders">\s*1\s*</', $output, 'Should show 1 order from analytics data' );
+		$this->assertMatchesRegularExpression( '/order-attribution-total-spend">\s*.*100\.00/', $output, 'Should show total spend of 100' );
+	}
 }