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).
// -------------------------------------------------------------------------