Commit a2e870bd0bf for woocommerce

commit a2e870bd0bfb5b568f226081581c35fafdf8f815
Author: Justin P <228780+layoutd@users.noreply.github.com>
Date:   Fri Sep 25 09:18:16 2026 +0200

    Fix Analytics reset defaults ignoring filtered order status defaults (#68688)

    * Preload resolved wc_admin setting defaults for the client

    * Use preloaded defaults for Analytics order status reset

    * Copy preloaded status defaults and skip settings without a default

    * Guard against a null preloaded settings defaults object

diff --git a/plugins/woocommerce/changelog/fix-analytics-reset-defaults-filtered-statuses b/plugins/woocommerce/changelog/fix-analytics-reset-defaults-filtered-statuses
new file mode 100644
index 00000000000..c50dd5ed9d0
--- /dev/null
+++ b/plugins/woocommerce/changelog/fix-analytics-reset-defaults-filtered-statuses
@@ -0,0 +1,4 @@
+Significance: patch
+Type: fix
+
+Make the Analytics settings "Reset defaults" button restore the filtered default order statuses instead of a hardcoded list.
diff --git a/plugins/woocommerce/client/admin/client/analytics/settings/config.js b/plugins/woocommerce/client/admin/client/analytics/settings/config.js
index 1c4a65c0713..b6ed263b9a3 100644
--- a/plugins/woocommerce/client/admin/client/analytics/settings/config.js
+++ b/plugins/woocommerce/client/admin/client/analytics/settings/config.js
@@ -12,7 +12,25 @@ import DefaultDate from './default-date';
 import { getAdminSetting, ORDER_STATUSES } from '~/utils/admin-settings';

 const SETTINGS_FILTER = 'woocommerce_admin_analytics_settings';
-export const DEFAULT_ACTIONABLE_STATUSES = [ 'processing', 'on-hold' ];
+
+// Defaults resolved by the server for the wc_admin settings group, including the
+// `woocommerce_analytics_settings_default_*_order_statuses` filters. Missing when the
+// page did not preload them, so every consumer keeps a built-in fallback.
+const settingsDefaults = getAdminSetting( 'wcAdminSettingsDefaults', {} ) || {};
+
+const getDefaultStatuses = ( setting, fallback ) => {
+	const statuses = settingsDefaults[ setting ];
+	return Array.isArray( statuses ) ? [ ...statuses ] : fallback;
+};
+
+export const DEFAULT_EXCLUDED_STATUSES = getDefaultStatuses(
+	'woocommerce_excluded_report_order_statuses',
+	[ 'pending', 'cancelled', 'failed' ]
+);
+export const DEFAULT_ACTIONABLE_STATUSES = getDefaultStatuses(
+	'woocommerce_actionable_order_statuses',
+	[ 'processing', 'on-hold' ]
+);
 export const DEFAULT_ORDER_STATUSES = [
 	'completed',
 	'processing',
@@ -98,7 +116,7 @@ const baseConfig = {
 				strong: <strong />,
 			},
 		} ),
-		defaultValue: [ 'pending', 'cancelled', 'failed' ],
+		defaultValue: DEFAULT_EXCLUDED_STATUSES,
 	},
 	woocommerce_actionable_order_statuses: {
 		label: __( 'Actionable statuses:', 'woocommerce' ),
diff --git a/plugins/woocommerce/client/admin/client/analytics/settings/test/config.test.js b/plugins/woocommerce/client/admin/client/analytics/settings/test/config.test.js
new file mode 100644
index 00000000000..e1f0bd8ff55
--- /dev/null
+++ b/plugins/woocommerce/client/admin/client/analytics/settings/test/config.test.js
@@ -0,0 +1,70 @@
+let mockPreloadedDefaults = {};
+
+jest.mock( '~/utils/admin-settings', () => ( {
+	...jest.requireActual( '~/utils/admin-settings' ),
+	getAdminSetting: ( name, fallback ) =>
+		name === 'wcAdminSettingsDefaults' ? mockPreloadedDefaults : fallback,
+} ) );
+
+// config.js reads the preloaded defaults at module load, so each case needs a fresh import.
+const loadConfig = ( preloadedDefaults ) => {
+	mockPreloadedDefaults = preloadedDefaults;
+	jest.resetModules();
+	return import( '../config' );
+};
+
+describe( 'Analytics settings config - order status defaults', () => {
+	it( 'uses the preloaded (filtered) defaults for the order status settings', async () => {
+		const config = await loadConfig( {
+			woocommerce_excluded_report_order_statuses: [ 'pending', 'failed' ],
+			woocommerce_actionable_order_statuses: [
+				'processing',
+				'on-hold',
+				'my-status',
+			],
+		} );
+
+		expect(
+			config.config.woocommerce_excluded_report_order_statuses
+				.defaultValue
+		).toEqual( [ 'pending', 'failed' ] );
+		expect(
+			config.config.woocommerce_actionable_order_statuses.defaultValue
+		).toEqual( [ 'processing', 'on-hold', 'my-status' ] );
+		expect( config.DEFAULT_ACTIONABLE_STATUSES ).toEqual( [
+			'processing',
+			'on-hold',
+			'my-status',
+		] );
+	} );
+
+	it( 'falls back to the built-in defaults when nothing was preloaded', async () => {
+		const config = await loadConfig( {} );
+
+		expect(
+			config.config.woocommerce_excluded_report_order_statuses
+				.defaultValue
+		).toEqual( [ 'pending', 'cancelled', 'failed' ] );
+		expect(
+			config.config.woocommerce_actionable_order_statuses.defaultValue
+		).toEqual( [ 'processing', 'on-hold' ] );
+	} );
+
+	it( 'falls back to the built-in defaults when the preload is null', async () => {
+		const config = await loadConfig( null );
+
+		expect(
+			config.config.woocommerce_actionable_order_statuses.defaultValue
+		).toEqual( [ 'processing', 'on-hold' ] );
+	} );
+
+	it( 'ignores a malformed preloaded default', async () => {
+		const config = await loadConfig( {
+			woocommerce_actionable_order_statuses: 'processing',
+		} );
+
+		expect(
+			config.config.woocommerce_actionable_order_statuses.defaultValue
+		).toEqual( [ 'processing', 'on-hold' ] );
+	} );
+} );
diff --git a/plugins/woocommerce/src/Internal/Admin/Settings.php b/plugins/woocommerce/src/Internal/Admin/Settings.php
index 188022dfd23..5b8cfb81b82 100644
--- a/plugins/woocommerce/src/Internal/Admin/Settings.php
+++ b/plugins/woocommerce/src/Internal/Admin/Settings.php
@@ -522,6 +522,10 @@ class Settings {
 	/**
 	 * Gets custom settings used for WC Admin.
 	 *
+	 * Exposes the current values as `wcAdminSettings` and the resolved defaults as
+	 * `wcAdminSettingsDefaults`, so the client can reset to the same (possibly filtered)
+	 * defaults the REST endpoint reports instead of a hardcoded copy.
+	 *
 	 * @param array $settings Array of settings to merge into.
 	 * @return array
 	 */
@@ -529,10 +533,15 @@ class Settings {
 		$wc_rest_settings_options_controller = new \WC_REST_Setting_Options_Controller();
 		$wc_admin_group_settings             = $wc_rest_settings_options_controller->get_group_settings( 'wc_admin' );
 		$settings['wcAdminSettings']         = array();
+		$settings['wcAdminSettingsDefaults'] = array();

 		foreach ( $wc_admin_group_settings as $setting ) {
-			if ( ! empty( $setting['id'] ) ) {
-				$settings['wcAdminSettings'][ $setting['id'] ] = $setting['value'];
+			if ( empty( $setting['id'] ) ) {
+				continue;
+			}
+			$settings['wcAdminSettings'][ $setting['id'] ] = $setting['value'];
+			if ( array_key_exists( 'default', $setting ) ) {
+				$settings['wcAdminSettingsDefaults'][ $setting['id'] ] = $setting['default'];
 			}
 		}
 		return $settings;
diff --git a/plugins/woocommerce/tests/php/src/Internal/Admin/SettingsTest.php b/plugins/woocommerce/tests/php/src/Internal/Admin/SettingsTest.php
index 7869126a13e..40abcae32cd 100644
--- a/plugins/woocommerce/tests/php/src/Internal/Admin/SettingsTest.php
+++ b/plugins/woocommerce/tests/php/src/Internal/Admin/SettingsTest.php
@@ -289,6 +289,25 @@ class SettingsTest extends WC_Unit_Test_Case {
 		$this->assertSame( array(), Settings::get_default_excluded_order_statuses(), 'The UI and runtime consumers should agree.' );
 	}

+	/**
+	 * @testdox The preloaded component settings expose the filtered defaults so "Reset defaults" can restore them.
+	 */
+	public function test_component_settings_expose_filtered_defaults(): void {
+		$this->add_default_status_filter( 'woocommerce_analytics_settings_default_actionable_order_statuses' );
+		// The settings are only injected in admin; the base tearDown unsets the current screen.
+		set_current_screen( 'dashboard' );
+
+		$settings = $this->sut->add_component_settings( array() );
+
+		$this->assertArrayHasKey( 'wcAdminSettingsDefaults', $settings, 'Defaults should be preloaded alongside wcAdminSettings.' );
+		$this->assertContains( 'refunded', $settings['wcAdminSettingsDefaults']['woocommerce_actionable_order_statuses'], 'The filtered default should reach the client.' );
+		$this->assertSame(
+			array( 'pending', 'cancelled', 'failed' ),
+			$settings['wcAdminSettingsDefaults']['woocommerce_excluded_report_order_statuses'],
+			'An unfiltered setting should keep its built-in default.'
+		);
+	}
+
 	/**
 	 * @testdox The preloaded component settings expose coupon discount types, including ones added by extensions.
 	 */