[Promotion] Fix price range filter to also consider configuration with only max

This commit is contained in:
Jan Goralski 2023-04-24 12:29:41 +02:00
parent fc3b8ea90d
commit 61a2f38433
No known key found for this signature in database
GPG key ID: 95D91BA380F31EDD
5 changed files with 134 additions and 10 deletions

View file

@ -8,6 +8,7 @@ Feature: Receiving fixed discount on products from specific price range
Given the store operates on a single channel in "United States"
And the store has a product "PHP T-Shirt" priced at "$100.00"
And the store has a product "PHP Mug" priced at "$20.00"
And the store has a product "PHP Sticker" priced at "$5.00"
And there is a promotion "Christmas promotion"
@ui @api
@ -24,6 +25,20 @@ Feature: Receiving fixed discount on products from specific price range
Then its price should be decreased by "$10.00"
And my cart total should be "$90.00"
@ui @api
Scenario: Receiving fixed discount on a single item fulfilling maximum price criteria
Given the promotion gives "$10.00" off on every product with maximum price at "$50.00"
When I add product "PHP Mug" to the cart
Then its price should be decreased by "$10.00"
And my cart total should be "$10.00"
@ui @api
Scenario: Receiving fixed discount on a single item with price equal to filter maximum criteria
Given the promotion gives "$10.00" off on every product with minimum price at "$20.00"
When I add product "PHP Mug" to the cart
Then its price should be decreased by "$10.00"
And my cart total should be "$10.00"
@ui @api
Scenario: Receiving fixed discount on a single item fulfilling range price criteria
Given the promotion gives "$10.00" off on every product priced between "$15.00" and "$50.00"
@ -80,8 +95,12 @@ Feature: Receiving fixed discount on products from specific price range
Given the promotion gives "$10.00" off on every product with minimum price at "$80.00"
And there is a promotion "Mugs promotion"
And it gives "$5.00" off on every product priced between "$10.00" and "$50.00"
And there is a promotion "Stickers promotion"
And it gives "$1.00" off on every product with maximum price at "$10.00"
When I add product "PHP T-Shirt" to the cart
And I add product "PHP Mug" to the cart
And I add product "PHP Sticker" to the cart
Then product "PHP T-Shirt" price should be decreased by "$10.00"
And product "PHP Mug" price should be decreased by "$5.00"
And my cart total should be "$105.00"
And product "PHP Sticker" price should be decreased by "$1.00"
And my cart total should be "$109.00"

View file

@ -8,6 +8,7 @@ Feature: Receiving percentage discount on products from specific price range
Given the store operates on a single channel in "United States"
And the store has a product "PHP T-Shirt" priced at "$100.00"
And the store has a product "PHP Mug" priced at "$20.00"
And the store has a product "PHP Sticker" priced at "$5.00"
And there is a promotion "Christmas sale"
@ui @api
@ -24,6 +25,20 @@ Feature: Receiving percentage discount on products from specific price range
Then its price should be decreased by "$10.00"
And my cart total should be "$90.00"
@ui @api
Scenario: Receiving percentage discount on a single item fulfilling maximum price criteria
Given this promotion gives "10%" off on every product with maximum price at "$50.00"
When I add product "PHP Mug" to the cart
Then its price should be decreased by "$2.00"
And my cart total should be "$18.00"
@ui @api
Scenario: Receiving percentage discount on a single item with price equal to filter maximum criteria
Given this promotion gives "10%" off on every product with maximum price at "$20.00"
When I add product "PHP Mug" to the cart
Then its price should be decreased by "$2.00"
And my cart total should be "$18.00"
@ui @api
Scenario: Receiving percentage discount on a single item fulfilling range price criteria
Given this promotion gives "50%" off on every product priced between "$15.00" and "$50.00"
@ -66,8 +81,12 @@ Feature: Receiving percentage discount on products from specific price range
Given this promotion gives "10%" off on every product with minimum price at "$80.00"
And there is a promotion "Mugs promotion"
And it gives "90%" off on every product priced between "$10.00" and "$90.00"
And there is a promotion "Stickers promotion"
And it gives "20%" off on every product with maximum price at "$10.00"
When I add product "PHP T-Shirt" to the cart
And I add product "PHP Mug" to the cart
And I add product "PHP Sticker" to the cart
Then product "PHP T-Shirt" price should be decreased by "$10.00"
And product "PHP Mug" price should be decreased by "$18.00"
And my cart total should be "$92.00"
And product "PHP Sticker" price should be decreased by "$1.00"
And my cart total should be "$96.00"

View file

@ -512,6 +512,21 @@ final class PromotionContext implements Context
$this->createUnitFixedPromotion($promotion, $discount, $this->getPriceRangeFilterConfiguration($amount));
}
/**
* @Given /^([^"]+) gives ("(?:|£|\$)[^"]+") off on every product with maximum price at ("(?:€|£|\$)[^"]+")$/
*/
public function thisPromotionGivesOffOnEveryProductWithMaximumPriceAt(
PromotionInterface $promotion,
int $discount,
int $amount,
): void {
$this->createUnitFixedPromotion(
$promotion,
$discount,
$this->getPriceRangeFilterConfiguration(maxAmount: $amount),
);
}
/**
* @Given /^([^"]+) gives ("(?:|£|\$)[^"]+") off on every product priced between ("(?:€|£|\$)[^"]+") and ("(?:|£|\$)[^"]+")$/
*/
@ -539,6 +554,21 @@ final class PromotionContext implements Context
$this->createUnitPercentagePromotion($promotion, $discount, $this->getPriceRangeFilterConfiguration($amount));
}
/**
* @Given /^([^"]+) gives ("[^"]+%") off on every product with maximum price at ("(?:€|£|\$)[^"]+")$/
*/
public function thisPromotionPercentageGivesOffOnEveryProductWithMaximumPriceAt(
PromotionInterface $promotion,
float $discount,
int $amount,
): void {
$this->createUnitPercentagePromotion(
$promotion,
$discount,
$this->getPriceRangeFilterConfiguration(maxAmount: $amount),
);
}
/**
* @Given /^([^"]+) gives ("[^"]+%") off on every product priced between ("(?:€|£|\$)[^"]+") and ("(?:|£|\$)[^"]+")$/
*/
@ -893,9 +923,13 @@ final class PromotionContext implements Context
return ['filters' => ['products_filter' => ['products' => $productCodes]]];
}
private function getPriceRangeFilterConfiguration(int $minAmount, int $maxAmount = null): array
private function getPriceRangeFilterConfiguration(?int $minAmount = null, ?int $maxAmount = null): array
{
$configuration = ['filters' => ['price_range_filter' => ['min' => $minAmount]]];
$configuration = [];
if (null !== $minAmount) {
$configuration['filters']['price_range_filter']['min'] = $minAmount;
}
if (null !== $maxAmount) {
$configuration['filters']['price_range_filter']['max'] = $maxAmount;
}

View file

@ -50,11 +50,17 @@ final class PriceRangeFilter implements FilterInterface
return $priceRange['min'] <= $price && $priceRange['max'] >= $price;
}
return $priceRange['min'] <= $price;
return
(!isset($priceRange['min']) && $priceRange['max'] >= $price) ||
(!isset($priceRange['max']) && $priceRange['min'] <= $price)
;
}
private function isConfigured(array $configuration): bool
{
return isset($configuration['filters']['price_range_filter']['min']);
return
isset($configuration['filters']['price_range_filter']['min']) ||
isset($configuration['filters']['price_range_filter']['max'])
;
}
}

View file

@ -155,16 +155,62 @@ final class PriceRangeFilterSpec extends ObjectBehavior
;
}
function it_filters_items_which_has_product_with_price_that_is_bigger_than_configured_maximum_criteria(
ChannelInterface $channel,
OrderItemInterface $item1,
OrderItemInterface $item2,
OrderItemInterface $item3,
ProductVariantInterface $item1Variant,
ProductVariantInterface $item2Variant,
ProductVariantInterface $item3Variant,
ProductVariantPriceCalculatorInterface $productVariantPriceCalculator,
): void {
$item1->getVariant()->willReturn($item1Variant);
$item2->getVariant()->willReturn($item2Variant);
$item3->getVariant()->willReturn($item3Variant);
$productVariantPriceCalculator->calculate($item1Variant, ['channel' => $channel])->willReturn(500);
$productVariantPriceCalculator->calculate($item2Variant, ['channel' => $channel])->willReturn(5000);
$productVariantPriceCalculator->calculate($item3Variant, ['channel' => $channel])->willReturn(10000);
$this
->filter([$item1, $item2, $item3], [
'filters' => ['price_range_filter' => ['max' => 1000]],
'channel' => $channel,
])
->shouldReturn([$item1])
;
}
function it_filters_items_which_has_product_with_price_equal_to_configured_maximum_criteria(
ChannelInterface $channel,
OrderItemInterface $item1,
OrderItemInterface $item2,
ProductVariantInterface $item1Variant,
ProductVariantInterface $item2Variant,
ProductVariantPriceCalculatorInterface $productVariantPriceCalculator,
): void {
$item1->getVariant()->willReturn($item1Variant);
$item2->getVariant()->willReturn($item2Variant);
$productVariantPriceCalculator->calculate($item1Variant, ['channel' => $channel])->willReturn(500);
$productVariantPriceCalculator->calculate($item2Variant, ['channel' => $channel])->willReturn(1000);
$this
->filter([$item1, $item2], [
'filters' => ['price_range_filter' => ['max' => 1000]],
'channel' => $channel,
])
->shouldReturn([$item1, $item2])
;
}
function it_returns_all_items_if_configuration_is_invalid(
ChannelInterface $channel,
OrderItemInterface $item1,
OrderItemInterface $item2,
): void {
$this->filter([$item1, $item2], [])->shouldReturn([$item1, $item2]);
$this->filter([$item1, $item2], [
'filters' => ['price_range_filter' => ['max' => 10000]],
'channel' => $channel,
])->shouldReturn([$item1, $item2]);
}
function it_throws_exception_if_channel_is_not_configured(