Commit dc0108a9c31 for woocommerce

commit dc0108a9c3133719b538fcfca5e43d6b133b3a48
Author: Zeba Afia Shama <zebashama2@gmail.com>
Date:   Tue Sep 8 00:09:58 2026 +0600

    Normalize coupon spend amounts before minimum/maximum validation (#68251)

    * Normalize coupon spend amounts before minimum/maximum validation

    * Add changelog entry for coupon spend amount normalization

    ---------

    Co-authored-by: Zeba Afia Shama <manvarse@gmail.com>

diff --git a/plugins/woocommerce/changelog/fix-67704-normalize-coupon-spend-amounts b/plugins/woocommerce/changelog/fix-67704-normalize-coupon-spend-amounts
new file mode 100644
index 00000000000..bf6ef8b8869
--- /dev/null
+++ b/plugins/woocommerce/changelog/fix-67704-normalize-coupon-spend-amounts
@@ -0,0 +1,4 @@
+Significance: patch
+Type: fix
+
+Normalize locale-formatted coupon minimum/maximum spend amounts before validating and storing them in WC_Coupon::set_minimum_amount() and WC_Coupon::set_maximum_amount().
diff --git a/plugins/woocommerce/includes/class-wc-coupon.php b/plugins/woocommerce/includes/class-wc-coupon.php
index 67e36d79dfd..a991b4dfce2 100644
--- a/plugins/woocommerce/includes/class-wc-coupon.php
+++ b/plugins/woocommerce/includes/class-wc-coupon.php
@@ -803,10 +803,11 @@ class WC_Coupon extends WC_Legacy_Coupon {
 	 * @return void
 	 */
 	public function set_minimum_amount( $amount ) {
+		$amount = wc_format_decimal( $amount );
 		if ( (float) $this->get_maximum_amount() && (float) $amount > (float) $this->get_maximum_amount() ) {
 			$this->error( 'coupon_invalid_minimum_amount', __( 'Invalid minimum spend value.', 'woocommerce' ) );
 		}
-		$this->set_prop( 'minimum_amount', wc_format_decimal( $amount ) );
+		$this->set_prop( 'minimum_amount', $amount );
 	}

 	/**
@@ -817,11 +818,12 @@ class WC_Coupon extends WC_Legacy_Coupon {
 	 * @return void
 	 */
 	public function set_maximum_amount( $amount ) {
+		$amount = wc_format_decimal( $amount );
 		if ( (float) $amount && (float) $this->get_minimum_amount() > (float) $amount ) {
 			$this->error( 'coupon_invalid_maximum_amount', __( 'Invalid maximum spend value.', 'woocommerce' ) );
 		}

-		$this->set_prop( 'maximum_amount', wc_format_decimal( $amount ) );
+		$this->set_prop( 'maximum_amount', $amount );
 	}

 	/**
diff --git a/plugins/woocommerce/tests/php/includes/class-wc-coupon-test.php b/plugins/woocommerce/tests/php/includes/class-wc-coupon-test.php
index ecde529f337..8bf2a6da214 100644
--- a/plugins/woocommerce/tests/php/includes/class-wc-coupon-test.php
+++ b/plugins/woocommerce/tests/php/includes/class-wc-coupon-test.php
@@ -359,6 +359,51 @@ class WC_Coupon_Tests extends WC_Unit_Test_Case {
 		$this->assertSame( '100.00', $coupon->get_minimum_amount() );
 	}

+	// -------------------------------------------------------------------------
+	// Locale-formatted amounts (comma decimal separator).
+	// -------------------------------------------------------------------------
+
+	/**
+	 * @testdox set_minimum_amount throws exception when a comma-decimal minimum exceeds existing maximum.
+	 */
+	public function test_set_minimum_amount_throws_when_comma_decimal_exceeds_maximum(): void {
+		$original_decimal_separator = get_option( 'woocommerce_price_decimal_sep' );
+		update_option( 'woocommerce_price_decimal_sep', ',' );
+
+		try {
+			$coupon = new WC_Coupon();
+			$coupon->set_maximum_amount( '100,00' );
+
+			try {
+				$coupon->set_minimum_amount( '100,50' );
+				$this->fail( 'Expected WC_Data_Exception was not thrown.' );
+			} catch ( \WC_Data_Exception $e ) {
+				$this->assertSame( 'coupon_invalid_minimum_amount', $e->getErrorCode() );
+			}
+		} finally {
+			update_option( 'woocommerce_price_decimal_sep', $original_decimal_separator );
+		}
+	}
+
+	/**
+	 * @testdox set_maximum_amount succeeds and stores the normalized value when a comma-decimal maximum satisfies the existing minimum.
+	 */
+	public function test_set_maximum_amount_succeeds_when_comma_decimal_satisfies_minimum(): void {
+		$original_decimal_separator = get_option( 'woocommerce_price_decimal_sep' );
+		update_option( 'woocommerce_price_decimal_sep', ',' );
+
+		try {
+			$coupon = new WC_Coupon();
+			$coupon->set_minimum_amount( '100.50' );
+
+			$coupon->set_maximum_amount( '100,75' );
+
+			$this->assertSame( '100.75', $coupon->get_maximum_amount() );
+		} finally {
+			update_option( 'woocommerce_price_decimal_sep', $original_decimal_separator );
+		}
+	}
+
 	// -------------------------------------------------------------------------
 	// Atomic set_props() validation (both amounts supplied together).
 	// -------------------------------------------------------------------------