Commit 05b1544d372 for woocommerce

commit 05b1544d3722fb79405ed1475b3481a40e32c291
Author: Jorge A. Torres <jorge.torres@automattic.com>
Date:   Tue Oct 27 14:35:27 2026 -0500

    Show the "Paid" line on the order screen for custom paid statuses (#70268)

diff --git a/plugins/woocommerce/changelog/69660-show-paid-totals-for-paid-statuses b/plugins/woocommerce/changelog/69660-show-paid-totals-for-paid-statuses
new file mode 100644
index 00000000000..188ab0fe716
--- /dev/null
+++ b/plugins/woocommerce/changelog/69660-show-paid-totals-for-paid-statuses
@@ -0,0 +1,4 @@
+Significance: minor
+Type: enhancement
+
+Show the "Paid" line on the order screen for custom paid statuses.
diff --git a/plugins/woocommerce/includes/admin/meta-boxes/views/html-order-items.php b/plugins/woocommerce/includes/admin/meta-boxes/views/html-order-items.php
index 182a2a8a541..0ed8283c99a 100644
--- a/plugins/woocommerce/includes/admin/meta-boxes/views/html-order-items.php
+++ b/plugins/woocommerce/includes/admin/meta-boxes/views/html-order-items.php
@@ -21,6 +21,23 @@ defined( 'ABSPATH' ) || exit;
  */
 $render_refunds = (bool) apply_filters( 'woocommerce_admin_order_should_render_refunds', 0 < $order->get_total() - $order->get_total_refunded() || 0 < absint( $order->get_item_count() - $order->get_item_count_refunded() ), $order->get_id(), $order );

+$date_paid          = $order->get_date_paid(); // @phpstan-ignore variable.undefined ($order is set by the code that includes this view.)
+$render_paid_totals = false;
+
+if ( $date_paid ) {
+	/**
+	 * Allow plugins to determine whether the "Paid" totals section should be rendered in the template.
+	 * Only applies to orders with a paid date.
+	 *
+	 * @since 11.4.0
+	 *
+	 * @param bool     $render_paid_totals If the "Paid" totals section should be rendered.
+	 * @param int      $order_id           The Order ID.
+	 * @param WC_Order $order              The Order object.
+	 */
+	$render_paid_totals = (bool) apply_filters( 'woocommerce_admin_order_should_render_paid_totals', $order->is_paid() || $order->has_status( OrderStatus::REFUNDED ), $order->get_id(), $order );
+}
+
 global $wpdb;

 $payment_gateway     = wc_get_payment_gateway_by_order( $order );
@@ -236,7 +253,7 @@ if ( wc_tax_enabled() ) {

 	<div class="clear"></div>

-	<?php if ( in_array( $order->get_status(), array( OrderStatus::PROCESSING, OrderStatus::COMPLETED, OrderStatus::REFUNDED ), true ) && ! empty( $order->get_date_paid() ) ) : ?>
+	<?php if ( $render_paid_totals ) : ?>

 		<table class="wc-order-totals" style="border-top: 1px solid #999; margin-top:12px; padding-top:12px">
 			<tr>
@@ -252,9 +269,9 @@ if ( wc_tax_enabled() ) {
 					<?php
 					if ( $order->get_payment_method_title() ) {
 						/* translators: 1: payment date. 2: payment method */
-						echo esc_html( sprintf( __( '%1$s via %2$s', 'woocommerce' ), $order->get_date_paid()->date_i18n( get_option( 'date_format' ) ), $order->get_payment_method_title() ) );
+						echo esc_html( sprintf( __( '%1$s via %2$s', 'woocommerce' ), $date_paid->date_i18n( get_option( 'date_format' ) ), $order->get_payment_method_title() ) );
 					} else {
-						echo esc_html( $order->get_date_paid()->date_i18n( get_option( 'date_format' ) ) );
+						echo esc_html( $date_paid->date_i18n( get_option( 'date_format' ) ) );
 					}
 					?>
 					</span>
diff --git a/plugins/woocommerce/tests/php/includes/admin/meta-boxes/views/html-order-items-test.php b/plugins/woocommerce/tests/php/includes/admin/meta-boxes/views/html-order-items-test.php
index 0193c1aeb4d..01274385821 100644
--- a/plugins/woocommerce/tests/php/includes/admin/meta-boxes/views/html-order-items-test.php
+++ b/plugins/woocommerce/tests/php/includes/admin/meta-boxes/views/html-order-items-test.php
@@ -86,6 +86,43 @@ class WC_Admin_Meta_Box_Order_Items_View_Test extends WC_Unit_Test_Case {
 		$this->assertSame( '$0.00', trim( $refunded_nodes->item( 0 )->textContent ), 'A zero refunded total should render without a minus sign.' );
 	}

+	/**
+	 * @testdox The "Paid" totals section is shown for custom paid statuses and can be hidden with a filter.
+	 */
+	public function test_paid_totals_render_for_custom_paid_status_and_can_be_filtered(): void {
+		add_filter(
+			'wc_order_statuses',
+			static function ( $statuses ) {
+				$statuses['wc-ready-for-pickup'] = 'Ready for pickup';
+				return $statuses;
+			}
+		);
+		add_filter(
+			'woocommerce_order_is_paid_statuses',
+			static function ( $statuses ) {
+				$statuses[] = 'ready-for-pickup';
+				return $statuses;
+			}
+		);
+
+		$order = wc_create_order();
+		$order->set_status( 'ready-for-pickup' );
+		$order->set_date_paid( time() );
+		$order->save();
+
+		$render_order_items = function () use ( $order ): string {
+			ob_start();
+			include WC_ABSPATH . 'includes/admin/meta-boxes/views/html-order-items.php';
+			return (string) ob_get_clean();
+		};
+
+		$this->assertStringContainsString( 'Paid:', $render_order_items(), 'The "Paid" totals section should show for a custom paid status.' );
+
+		add_filter( 'woocommerce_admin_order_should_render_paid_totals', '__return_false' );
+
+		$this->assertStringNotContainsString( 'Paid:', $render_order_items(), 'The filter should be able to hide the "Paid" totals section.' );
+	}
+
 	/**
 	 * @testdox The refund quantity input's max excludes units that were already refunded.
 	 */