Commit c98203a8046 for woocommerce

commit c98203a80462f4d8e60510fb5cf5548b5be9e749
Author: Justin P <228780+layoutd@users.noreply.github.com>
Date:   Thu Sep 24 17:33:15 2026 +0200

    Show extension coupon discount type labels in the Analytics Coupons report (#68705)

    * Show extension coupon discount type labels in the Analytics Coupons report

    * Add tests for coupon discount type labels in Analytics

diff --git a/plugins/woocommerce/changelog/35667-analytics-coupon-custom-discount-types b/plugins/woocommerce/changelog/35667-analytics-coupon-custom-discount-types
new file mode 100644
index 00000000000..2963bcf34df
--- /dev/null
+++ b/plugins/woocommerce/changelog/35667-analytics-coupon-custom-discount-types
@@ -0,0 +1,4 @@
+Significance: patch
+Type: fix
+
+Show the labels of coupon discount types added by extensions in the Analytics Coupons report instead of N/A.
diff --git a/plugins/woocommerce/client/admin/client/analytics/report/coupons/table.js b/plugins/woocommerce/client/admin/client/analytics/report/coupons/table.js
index d1f9bdfd6f5..2fc06266bbd 100644
--- a/plugins/woocommerce/client/admin/client/analytics/report/coupons/table.js
+++ b/plugins/woocommerce/client/admin/client/analytics/report/coupons/table.js
@@ -195,7 +195,9 @@ class CouponsReportTable extends Component {
 	}

 	getCouponType( discountType ) {
+		// Extension types use their wc_get_coupon_types() label; core types keep the shorter labels below.
 		const couponTypes = {
+			...getAdminSetting( 'couponTypes', {} ),
 			percent: __( 'Percentage', 'woocommerce' ),
 			fixed_cart: __( 'Fixed cart', 'woocommerce' ),
 			fixed_product: __( 'Fixed product', 'woocommerce' ),
diff --git a/plugins/woocommerce/client/admin/client/analytics/report/coupons/test/table.test.js b/plugins/woocommerce/client/admin/client/analytics/report/coupons/test/table.test.js
new file mode 100644
index 00000000000..fd9256b6f45
--- /dev/null
+++ b/plugins/woocommerce/client/admin/client/analytics/report/coupons/test/table.test.js
@@ -0,0 +1,42 @@
+/**
+ * Internal dependencies
+ */
+import CouponsReportTable from '../table';
+
+const mockAdminSettings = {};
+
+jest.mock( '~/utils/admin-settings', () => ( {
+	getAdminSetting: ( key, fallback ) => mockAdminSettings[ key ] ?? fallback,
+} ) );
+
+describe( 'CouponsReportTable getCouponType', () => {
+	const table = new CouponsReportTable();
+
+	beforeEach( () => {
+		mockAdminSettings.couponTypes = {
+			percent: 'Percentage discount',
+			custom_type: 'Custom discount',
+		};
+	} );
+
+	it( 'keeps the core label for a built-in discount type', () => {
+		expect( table.getCouponType( 'percent' ) ).toBe( 'Percentage' );
+	} );
+
+	it( 'uses the admin setting label for a discount type added by an extension', () => {
+		expect( table.getCouponType( 'custom_type' ) ).toBe(
+			'Custom discount'
+		);
+	} );
+
+	it( 'returns N/A for a discount type without a label', () => {
+		expect( table.getCouponType( 'unknown_type' ) ).toBe( 'N/A' );
+	} );
+
+	it( 'falls back to the core labels when the admin setting is missing', () => {
+		delete mockAdminSettings.couponTypes;
+
+		expect( table.getCouponType( 'fixed_cart' ) ).toBe( 'Fixed cart' );
+		expect( table.getCouponType( 'custom_type' ) ).toBe( 'N/A' );
+	} );
+} );
diff --git a/plugins/woocommerce/src/Internal/Admin/Settings.php b/plugins/woocommerce/src/Internal/Admin/Settings.php
index f17e43bd3c4..188022dfd23 100644
--- a/plugins/woocommerce/src/Internal/Admin/Settings.php
+++ b/plugins/woocommerce/src/Internal/Admin/Settings.php
@@ -339,6 +339,7 @@ class Settings {
 			// E.g. an extension that added statuses is now inactive or removed.
 			$settings['unregisteredOrderStatuses'] = $this->get_unregistered_order_statuses();
 			$settings['usesNewFullRefundData']     = OrderUtil::uses_new_full_refund_data();
+			$settings['couponTypes']               = wc_get_coupon_types();
 		}

 		// The separator used for attributes found in Variation titles.
diff --git a/plugins/woocommerce/tests/php/src/Internal/Admin/SettingsTest.php b/plugins/woocommerce/tests/php/src/Internal/Admin/SettingsTest.php
index 497bb389cef..7869126a13e 100644
--- a/plugins/woocommerce/tests/php/src/Internal/Admin/SettingsTest.php
+++ b/plugins/woocommerce/tests/php/src/Internal/Admin/SettingsTest.php
@@ -289,6 +289,30 @@ 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 coupon discount types, including ones added by extensions.
+	 */
+	public function test_component_settings_expose_coupon_types(): void {
+		$add_type = function ( $types ) {
+			$types['custom_discount'] = 'Custom discount';
+			return $types;
+		};
+		add_filter( 'woocommerce_coupon_discount_types', $add_type );
+		$this->added_filters[] = array( 'woocommerce_coupon_discount_types', $add_type );
+		// Coupon types are only injected on wc-admin pages; the base tearDown unsets the current screen.
+		set_current_screen( 'dashboard' );
+		$_GET['page'] = 'wc-admin'; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
+
+		try {
+			$settings = $this->sut->add_component_settings( array() );
+		} finally {
+			unset( $_GET['page'] );
+		}
+
+		$this->assertSame( 'Custom discount', $settings['couponTypes']['custom_discount'] ?? null, 'A discount type added through the filter should reach the client.' );
+		$this->assertArrayHasKey( 'percent', $settings['couponTypes'], 'Core discount types should still be included.' );
+	}
+
 	/**
 	 * Get the resolved wc_admin group settings via the REST settings controller.
 	 *