Merge pull request #21241 from woocommerce/fix/21226
Revise coupon logic and add tests.
This commit is contained in:
commit
f5d5cad65c
|
@ -764,7 +764,7 @@ class WC_Discounts {
|
|||
* @return bool
|
||||
*/
|
||||
protected function validate_coupon_sale_items( $coupon ) {
|
||||
if ( $coupon->get_exclude_sale_items() && 'fixed_product' !== $coupon->get_discount_type() ) {
|
||||
if ( $coupon->get_exclude_sale_items() ) {
|
||||
$valid = true;
|
||||
|
||||
foreach ( $this->get_items_to_validate() as $item ) {
|
||||
|
@ -820,6 +820,7 @@ class WC_Discounts {
|
|||
*/
|
||||
protected function validate_coupon_eligible_items( $coupon ) {
|
||||
if ( ! $coupon->is_type( wc_get_product_coupon_types() ) ) {
|
||||
$this->validate_coupon_sale_items( $coupon );
|
||||
$this->validate_coupon_excluded_product_ids( $coupon );
|
||||
$this->validate_coupon_excluded_product_categories( $coupon );
|
||||
}
|
||||
|
@ -946,7 +947,6 @@ class WC_Discounts {
|
|||
$this->validate_coupon_maximum_amount( $coupon );
|
||||
$this->validate_coupon_product_ids( $coupon );
|
||||
$this->validate_coupon_product_categories( $coupon );
|
||||
$this->validate_coupon_sale_items( $coupon );
|
||||
$this->validate_coupon_excluded_items( $coupon );
|
||||
$this->validate_coupon_eligible_items( $coupon );
|
||||
|
||||
|
|
|
@ -1395,20 +1395,76 @@ class WC_Tests_Discounts extends WC_Unit_Test_Case {
|
|||
}
|
||||
|
||||
/**
|
||||
* Test the is_coupon_valid logic with sale items.
|
||||
* Test the percent coupon logic with and without sale items.
|
||||
*
|
||||
* @since 3.4.5
|
||||
* @since 3.4.6
|
||||
*/
|
||||
public function test_is_coupon_valid_sale_items() {
|
||||
public function test_is_coupon_valid_percent_sale_items() {
|
||||
$product_no_sale = new WC_Product_Simple();
|
||||
$product_no_sale->set_regular_price( 20 );
|
||||
$product_no_sale->save();
|
||||
|
||||
$product1 = new WC_Product_Simple();
|
||||
$product1->set_regular_price( 20 );
|
||||
$product1->save();
|
||||
$product_sale = new WC_Product_Simple();
|
||||
$product_sale->set_regular_price( 20 );
|
||||
$product_sale->set_sale_price( 10 );
|
||||
$product_sale->save();
|
||||
|
||||
$product2 = new WC_Product_Simple();
|
||||
$product2->set_regular_price( 20 );
|
||||
$product2->set_sale_price( 10 );
|
||||
$product2->save();
|
||||
$coupon_percent = new WC_Coupon();
|
||||
$coupon_percent->set_props( array(
|
||||
'amount' => 10,
|
||||
'discount_type' => 'percent',
|
||||
'exclude_sale_items' => false,
|
||||
) );
|
||||
$coupon_percent->save();
|
||||
|
||||
$coupon_percent_no_sale = new WC_Coupon();
|
||||
$coupon_percent_no_sale->set_props( array(
|
||||
'amount' => 10,
|
||||
'discount_type' => 'percent',
|
||||
'exclude_sale_items' => true,
|
||||
) );
|
||||
$coupon_percent_no_sale->save();
|
||||
|
||||
WC()->cart->empty_cart();
|
||||
WC()->cart->add_to_cart( $product_no_sale->get_id(), 1 );
|
||||
$discounts = new WC_Discounts( WC()->cart );
|
||||
|
||||
// Percent coupons should be valid when no sale items are in the cart.
|
||||
$this->assertTrue( $discounts->is_coupon_valid( $coupon_percent ) );
|
||||
$this->assertTrue( $discounts->is_coupon_valid( $coupon_percent_no_sale ) );
|
||||
|
||||
// Percent coupons should be valid when sale items are in the cart.
|
||||
WC()->cart->add_to_cart( $product_sale->get_id(), 1 );
|
||||
$discounts = new WC_Discounts( WC()->cart );
|
||||
$this->assertTrue( $discounts->is_coupon_valid( $coupon_percent ) );
|
||||
$this->assertTrue( $discounts->is_coupon_valid( $coupon_percent_no_sale ) );
|
||||
|
||||
// Sale-allowed coupons should apply discount to both cart items.
|
||||
$discounts->apply_coupon( $coupon_percent );
|
||||
$coupon_discounts = array_sum( $discounts->get_discounts_by_coupon() );
|
||||
$this->assertEquals( 3.0, $coupon_discounts ); // 10% off $20 + 10% off $10.
|
||||
|
||||
// No-sale coupons should only apply discount to non-sale items.
|
||||
$discounts = new WC_Discounts( WC()->cart );
|
||||
$discounts->apply_coupon( $coupon_percent_no_sale );
|
||||
$coupon_discounts = array_sum( $discounts->get_discounts_by_coupon() );
|
||||
$this->assertEquals( 2.0, $coupon_discounts ); // 10% off $20.
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the fixed cart coupon logic with and without sale items.
|
||||
*
|
||||
* @since 3.4.6
|
||||
*/
|
||||
public function test_is_coupon_valid_fixed_cart_sale_items() {
|
||||
$product_no_sale = new WC_Product_Simple();
|
||||
$product_no_sale->set_regular_price( 20 );
|
||||
$product_no_sale->save();
|
||||
|
||||
$product_sale = new WC_Product_Simple();
|
||||
$product_sale->set_regular_price( 20 );
|
||||
$product_sale->set_sale_price( 10 );
|
||||
$product_sale->save();
|
||||
|
||||
$coupon_cart = new WC_Coupon();
|
||||
$coupon_cart->set_props( array(
|
||||
|
@ -1426,6 +1482,41 @@ class WC_Tests_Discounts extends WC_Unit_Test_Case {
|
|||
) );
|
||||
$coupon_cart_no_sale->save();
|
||||
|
||||
WC()->cart->empty_cart();
|
||||
WC()->cart->add_to_cart( $product_no_sale->get_id(), 1 );
|
||||
$discounts = new WC_Discounts( WC()->cart );
|
||||
|
||||
// Fixed cart coupons should be valid when no sale items are in the cart.
|
||||
$this->assertTrue( $discounts->is_coupon_valid( $coupon_cart ) );
|
||||
$this->assertTrue( $discounts->is_coupon_valid( $coupon_cart_no_sale ) );
|
||||
|
||||
// No-sale fixed cart coupons should not be valid when sale items are in the cart.
|
||||
WC()->cart->add_to_cart( $product_sale->get_id(), 1 );
|
||||
$discounts = new WC_Discounts( WC()->cart );
|
||||
$this->assertTrue( $discounts->is_coupon_valid( $coupon_cart ) );
|
||||
$this->assertTrue( is_wp_error( $discounts->is_coupon_valid( $coupon_cart_no_sale ) ) );
|
||||
|
||||
// Sale-allowed coupons should apply discount to total cart.
|
||||
$discounts->apply_coupon( $coupon_cart );
|
||||
$coupon_discounts = array_sum( $discounts->get_discounts_by_coupon() );
|
||||
$this->assertEquals( 5.0, $coupon_discounts ); // $5 fixed cart discount.
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the per product coupon logic with and without sale items.
|
||||
*
|
||||
* @since 3.4.6
|
||||
*/
|
||||
public function test_is_coupon_valid_fixed_product_sale_items() {
|
||||
$product_no_sale = new WC_Product_Simple();
|
||||
$product_no_sale->set_regular_price( 20 );
|
||||
$product_no_sale->save();
|
||||
|
||||
$product_sale = new WC_Product_Simple();
|
||||
$product_sale->set_regular_price( 20 );
|
||||
$product_sale->set_sale_price( 10 );
|
||||
$product_sale->save();
|
||||
|
||||
$coupon_product = new WC_Coupon();
|
||||
$coupon_product->set_props( array(
|
||||
'amount' => 5,
|
||||
|
@ -1443,28 +1534,28 @@ class WC_Tests_Discounts extends WC_Unit_Test_Case {
|
|||
$coupon_product_no_sale->save();
|
||||
|
||||
WC()->cart->empty_cart();
|
||||
WC()->cart->add_to_cart( $product1->get_id(), 1 );
|
||||
WC()->cart->add_to_cart( $product2->get_id(), 1 );
|
||||
WC()->cart->add_to_cart( $product_no_sale->get_id(), 1 );
|
||||
$discounts = new WC_Discounts( WC()->cart );
|
||||
|
||||
// Cart coupon with no sale restriction should be valid if sale item is in cart.
|
||||
$this->assertTrue( $discounts->is_coupon_valid( $coupon_cart ) );
|
||||
|
||||
// Cart coupon with sale restriction should not be valid if sale item is in cart.
|
||||
$this->assertTrue( is_wp_error( $discounts->is_coupon_valid( $coupon_cart_no_sale ) ) );
|
||||
|
||||
// Product coupon with no sale restriction should be valid if sale item is in cart.
|
||||
// Per product coupons should be valid when no sale items are in the cart.
|
||||
$this->assertTrue( $discounts->is_coupon_valid( $coupon_product ) );
|
||||
|
||||
// Product coupon with sale restriction should be valid if sale item is in cart,
|
||||
// but it should not apply the discount to the sale item.
|
||||
$this->assertTrue( $discounts->is_coupon_valid( $coupon_product_no_sale ) );
|
||||
|
||||
$discounts->apply_coupon( $coupon_product_no_sale );
|
||||
$coupon_discounts = $discounts->get_discounts_by_coupon();
|
||||
$coupon_discount = reset( $coupon_discounts );
|
||||
// Per product coupons should be valid when sale items are in the cart.
|
||||
WC()->cart->add_to_cart( $product_sale->get_id(), 1 );
|
||||
$discounts = new WC_Discounts( WC()->cart );
|
||||
$this->assertTrue( $discounts->is_coupon_valid( $coupon_product ) );
|
||||
$this->assertTrue( $discounts->is_coupon_valid( $coupon_product_no_sale ) );
|
||||
|
||||
// $5 coupon should only get applied to the one cart item not on sale.
|
||||
$this->assertEquals( 5, $coupon_discount );
|
||||
// Sale-allowed coupons should apply discount to each item.
|
||||
$discounts->apply_coupon( $coupon_product );
|
||||
$coupon_discounts = array_sum( $discounts->get_discounts_by_coupon() );
|
||||
$this->assertEquals( 10.0, $coupon_discounts ); // $5 discount for 2 products.
|
||||
|
||||
// No-sale coupons should only apply discount to non-sale items.
|
||||
$discounts = new WC_Discounts( WC()->cart );
|
||||
$discounts->apply_coupon( $coupon_product_no_sale );
|
||||
$coupon_discounts = array_sum( $discounts->get_discounts_by_coupon() );
|
||||
$this->assertEquals( 5.0, $coupon_discounts ); // $5 discount for 1 product.
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue