Skip to content

Commit

Permalink
feature #13081 [CatalogPromotion][API] Apply catalog promotion in pro…
Browse files Browse the repository at this point in the history
…per channels (GSadee)

This PR was merged into the 1.11-dev branch.

Discussion
----------

| Q               | A
| --------------- | -----
| Branch?         | master
| Bug fix?        | no
| New feature?    | yes
| BC breaks?      | no
| Deprecations?   | no
| Related tickets | #13009
| License         | MIT

<!--
 - Bug fixes must be submitted against the 1.9 or 1.10 branch (the lowest possible)
 - Features and deprecations must be submitted against the master branch
 - Make sure that the correct base branch is set

 To be sure you are not breaking any Backward Compatibilities, check the documentation:
 https://docs.sylius.com/en/latest/book/organization/backward-compatibility-promise.html
-->


Commits
-------

f438c80 [CatalogPromotion][API] Add scenarios for applying catalog promotion in proper channels
6ffdba1 [CatalogPromotion][API] Improve and implement scenarios for applying catalog promotion in proper channels
bda8906 [CatalogPromotion][API] Apply catalog promotion in proper channels
8f3c9d1 [CatalogPromotion][Behat] Remove unused step definition
8305c48 [CatalogPromotion][Fixtures] Remove unnecessary normalizing rules and actions in example factory
  • Loading branch information
AdamKasp committed Sep 10, 2021
2 parents eb173e7 + 8305c48 commit 7be6878
Show file tree
Hide file tree
Showing 10 changed files with 129 additions and 67 deletions.
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
@applying_catalog_promotions
Feature: Applying catalog promotions for variants
In order to be attracted to products
As a Customer
As a Visitor
I want to see discounted products in the catalog

Background:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
@applying_catalog_promotions
Feature: Applying catalog promotions only in proper channels
In order to be attracted to products
As a Visitor
I want to see discounted products in the catalog of proper channel

Background:
Given the store operates on a channel named "Web-US" with hostname "web-us"
And the store operates on another channel named "Web-GB" with hostname "web-gb"
And the store has a "T-Shirt" configurable product
And this product has "PHP T-Shirt" variant priced at "$20.00" in "Web-US" channel
And "PHP T-Shirt" variant priced at "$30.00" in "Web-GB" channel
And this product is available in "Web-US" channel and "Web-GB" channel
And there is a catalog promotion "Winter sale" available in "Web-US" channel that reduces price by "30%" and applies on "PHP T-shirt" variant

@api
Scenario: Applying catalog promotion
When I change my current channel to "Web-US"
And I view product "T-Shirt"
Then I should see the product price "$14.00"
And I should see the product original price "$20.00"

@api
Scenario: Not applying catalog promotion if it is not available in current channel
When I change my current channel to "Web-GB"
And I view product "T-Shirt"
Then I should see the product price "$30.00"
And I should see the product original price "$30.00"
10 changes: 4 additions & 6 deletions src/Sylius/Behat/Context/Api/Shop/ProductContext.php
Original file line number Diff line number Diff line change
Expand Up @@ -139,12 +139,10 @@ public function iShouldNotSeeTheProduct(string $name): void
*/
public function iShouldSeeTheProductPrice(int $price): void
{
Assert::true(
$this->hasProductWithPrice(
[$this->responseChecker->getResponseContent($this->client->getLastResponse())],
$price,
)
);
Assert::true($this->hasProductWithPrice(
[$this->responseChecker->getResponseContent($this->client->getLastResponse())],
$price,
));
}

/**
Expand Down
65 changes: 51 additions & 14 deletions src/Sylius/Behat/Context/Setup/CatalogPromotionContext.php
Original file line number Diff line number Diff line change
Expand Up @@ -124,35 +124,72 @@ public function thereIsACatalogPromotionThatReducesPriceByAndAppliesOn(
float $discount,
ProductVariantInterface ...$variants
): void {
$catalogPromotion = $this->createCatalogPromotion($name);
$variantCodes = [];
foreach ($variants as $variant) {
$variantCodes[] = $variant->getCode();
}

/** @var CatalogPromotionRuleInterface $catalogPromotionRule */
$catalogPromotionRule = $this->catalogPromotionRuleFactory->createNew();
$catalogPromotionRule->setType(CatalogPromotionRuleInterface::TYPE_FOR_VARIANTS);
$catalogPromotionRule->setConfiguration(['variants' => array_values($variantCodes)]);
$this->createCatalogPromotion(
$name,
null,
[],
[[
'type' => CatalogPromotionRuleInterface::TYPE_FOR_VARIANTS,
'configuration' => ['variants' => $variantCodes],
]],
[[
'type' => CatalogPromotionActionInterface::TYPE_PERCENTAGE_DISCOUNT,
'configuration' => ['amount' => $discount],
]]
);

$catalogPromotion->addRule($catalogPromotionRule);

/** @var CatalogPromotionActionInterface $catalogPromotionAction */
$catalogPromotionAction = $this->catalogPromotionActionFactory->createNew();
$catalogPromotionAction->setType(CatalogPromotionActionInterface::TYPE_PERCENTAGE_DISCOUNT);
$catalogPromotionAction->setConfiguration(['amount' => $discount]);
$this->entityManager->flush();
}

$catalogPromotion->addAction($catalogPromotionAction);
/**
* @Given /^there is a catalog promotion "([^"]*)" available in ("[^"]+" channel) that reduces price by ("[^"]+") and applies on ("[^"]+" variant)$/
*/
public function thereIsACatalogPromotionAvailableInChannelThatReducesPriceByAndAppliesOnVariant(
string $name,
ChannelInterface $channel,
float $discount,
ProductVariantInterface $variant
): void {
$this->createCatalogPromotion(
$name,
null,
[$channel->getCode()],
[[
'type' => CatalogPromotionRuleInterface::TYPE_FOR_VARIANTS,
'configuration' => ['variants' => [$variant->getCode()]],
]],
[[
'type' => CatalogPromotionActionInterface::TYPE_PERCENTAGE_DISCOUNT,
'configuration' => ['amount' => $discount],
]]
);

$this->entityManager->flush();
}

private function createCatalogPromotion(string $name, ?string $code = null): CatalogPromotionInterface
{
private function createCatalogPromotion(
string $name,
?string $code = null,
array $channels = [],
array $rules = [],
array $actions = []
): CatalogPromotionInterface {
if (empty($channels) && $this->sharedStorage->has('channel')) {
$channels = [$this->sharedStorage->get('channel')];
}

/** @var CatalogPromotionInterface $catalogPromotion */
$catalogPromotion = $this->catalogPromotionExampleFactory->create([
'name' => $name,
'code' => $code,
'channels' => $channels,
'actions' => $actions,
'rules' => $rules,
]);

$this->entityManager->persist($catalogPromotion);
Expand Down
16 changes: 15 additions & 1 deletion src/Sylius/Behat/Context/Setup/ProductContext.php
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,9 @@ public function thisProductIsAlsoPricedAtInChannel(ProductInterface $product, in

/** @var ProductVariantInterface $productVariant */
$productVariant = $this->defaultVariantResolver->getVariant($product);
$productVariant->addChannelPricing($this->createChannelPricingForChannel($price, $channel));
if (!$productVariant->hasChannelPricingForChannel($channel)) {
$productVariant->addChannelPricing($this->createChannelPricingForChannel($price, $channel));
}

$this->objectManager->flush();
}
Expand Down Expand Up @@ -1055,6 +1057,18 @@ public function allVariantsOfThisProductAreDisabled(ProductInterface $product):
$this->objectManager->flush();
}

/**
* @Given /^(this product) is available in ("[^"]+" channel) and ("[^"]+" channel)$/
*/
public function thisProductIsAvailableInChannels(ProductInterface $product, ChannelInterface ...$channels): void
{
foreach ($channels as $channel) {
$product->addChannel($channel);
}

$this->saveProduct($product);
}

private function getPriceFromString(string $price): int
{
return (int) round((float) str_replace(['€', '£', '$'], '', $price) * 100, 2);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ default:
- sylius.behat.context.setup.taxonomy
- Sylius\Behat\Context\Setup\CatalogPromotionContext

- sylius.behat.context.transform.channel
- sylius.behat.context.transform.lexical
- sylius.behat.context.transform.product
- sylius.behat.context.transform.product_variant
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@

use Sylius\Bundle\CoreBundle\Formatter\AppliedPromotionInformationFormatterInterface;
use Sylius\Component\Core\Model\CatalogPromotionInterface;
use Sylius\Component\Core\Model\ChannelPricingInterface;
use Sylius\Component\Core\Model\ProductVariantInterface;
use Sylius\Component\Promotion\Model\CatalogPromotionActionInterface;

Expand Down Expand Up @@ -44,17 +43,18 @@ private function applyDiscountFromAction(
): void {
$discount = $action->getConfiguration()['amount'];

/** @var ChannelPricingInterface $channelPricing */
foreach ($variant->getChannelPricings() as $channelPricing) {
foreach ($catalogPromotion->getChannels() as $channel) {
$channelPricing = $variant->getChannelPricingForChannel($channel);
if ($channelPricing === null) {
continue;
}

if ($channelPricing->getOriginalPrice() === null) {
$channelPricing->setOriginalPrice($channelPricing->getPrice());
}

$channelPricing->setPrice((int) ($channelPricing->getPrice() - ($channelPricing->getPrice() * $discount)));

$channelPricing->addAppliedPromotion(
$this->appliedPromotionInformationFormatter->format($catalogPromotion)
);
$channelPricing->addAppliedPromotion($this->appliedPromotionInformationFormatter->format($catalogPromotion));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -132,21 +132,7 @@ protected function configureOptions(OptionsResolver $resolver): void
->setAllowedTypes('channels', 'array')
->setNormalizer('channels', LazyOption::findBy($this->channelRepository, 'code'))
->setDefined('rules')
->setNormalizer('rules', function (Options $options, array $rules): array {
if (empty($rules)) {
return [[]];
}

return $rules;
})
->setDefined('actions')
->setNormalizer('actions', function (Options $options, array $actions): array {
if (empty($actions)) {
return [[]];
}

return $actions;
})
;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
namespace Sylius\Bundle\CoreBundle\Provider;

use Sylius\Component\Core\Model\CatalogPromotionInterface;
use Sylius\Component\Core\Model\ProductInterface;
use Sylius\Component\Core\Model\ProductVariantInterface;
use Sylius\Component\Core\Provider\CatalogPromotionVariantsProviderInterface;
use Sylius\Component\Core\Repository\ProductVariantRepositoryInterface;
Expand All @@ -39,17 +38,17 @@ public function provideEligibleVariants(CatalogPromotionInterface $catalogPromot

/** We can do that for now, as we have only one rule */
if (array_key_exists('variants', $configuration)) {
$variants = $this->getVariantsProducts($configuration, $variants);
$variants = $this->getVariants($configuration['variants'], $variants);
}
}

return $variants;
}

private function getVariantsProducts(array $configuration, array $variants): array
private function getVariants(array $configuration, array $variants): array
{
/** @var string $variantCode */
foreach ($configuration['variants'] as $variantCode) {
foreach ($configuration as $variantCode) {
/** @var ProductVariantInterface|null $variant */
$variant = $this->productVariantRepository->findOneBy(['code' => $variantCode]);
if ($variant === null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@
use Sylius\Bundle\CoreBundle\Applicator\CatalogPromotionApplicatorInterface;
use Sylius\Bundle\CoreBundle\Formatter\AppliedPromotionInformationFormatterInterface;
use Sylius\Component\Core\Model\CatalogPromotionInterface;
use Sylius\Component\Core\Model\ChannelInterface;
use Sylius\Component\Core\Model\ChannelPricingInterface;
use Sylius\Component\Core\Model\ProductVariantInterface;
use Sylius\Component\Promotion\Model\CatalogPromotionActionInterface;
use Sylius\Component\Promotion\Model\CatalogPromotionTranslationInterface;

final class CatalogPromotionApplicatorSpec extends ObjectBehavior
{
Expand All @@ -41,17 +41,19 @@ function it_applies_percentage_discount_on_all_products_variants(
ProductVariantInterface $variant,
CatalogPromotionInterface $catalogPromotion,
CatalogPromotionActionInterface $catalogPromotionAction,
ChannelInterface $firstChannel,
ChannelInterface $secondChannel,
ChannelPricingInterface $firstChannelPricing,
ChannelPricingInterface $secondChannelPricing
): void {
$catalogPromotion->getActions()->willReturn(new ArrayCollection([
$catalogPromotionAction->getWrappedObject(),
$catalogPromotion->getActions()->willReturn(new ArrayCollection([$catalogPromotionAction->getWrappedObject()]));
$catalogPromotion->getChannels()->willReturn(new ArrayCollection([
$firstChannel->getWrappedObject(),
$secondChannel->getWrappedObject(),
]));

$variant->getChannelPricings()->willReturn(new ArrayCollection([
$firstChannelPricing->getWrappedObject(),
$secondChannelPricing->getWrappedObject(),
]));
$variant->getChannelPricingForChannel($firstChannel)->willReturn($firstChannelPricing);
$variant->getChannelPricingForChannel($secondChannel)->willReturn($secondChannelPricing);

$appliedPromotionInformationFormatter->format($catalogPromotion)->willReturn(['winter_sale' => ['name' => 'Winter sale']]);
$catalogPromotionAction->getConfiguration()->willReturn(['amount' => 0.3]);
Expand All @@ -76,25 +78,22 @@ function it_does_not_set_original_price_during_application_if_its_already_there(
ProductVariantInterface $variant,
CatalogPromotionInterface $catalogPromotion,
CatalogPromotionActionInterface $catalogPromotionAction,
CatalogPromotionTranslationInterface $translation,
ChannelPricingInterface $firstChannelPricing
ChannelInterface $channel,
ChannelPricingInterface $channelPricing
): void {
$variant->getChannelPricings()->willReturn(new ArrayCollection([
$firstChannelPricing->getWrappedObject(),
]));
$catalogPromotion->getActions()->willReturn(new ArrayCollection([$catalogPromotionAction->getWrappedObject()]));
$catalogPromotion->getChannels()->willReturn(new ArrayCollection([$channel->getWrappedObject()]));

$catalogPromotion->getActions()->willReturn(new ArrayCollection([
$catalogPromotionAction->getWrappedObject(),
]));
$variant->getChannelPricingForChannel($channel)->willReturn($channelPricing);

$appliedPromotionInformationFormatter->format($catalogPromotion)->willReturn(['winter_sale' => ['name' => 'Winter sale']]);
$catalogPromotionAction->getConfiguration()->willReturn(['amount' => 0.5]);

$firstChannelPricing->getPrice()->willReturn(1000);
$firstChannelPricing->getOriginalPrice()->willReturn(2000);
$firstChannelPricing->setOriginalPrice(Argument::any())->shouldNotBeCalled();
$firstChannelPricing->setPrice(500)->shouldBeCalled();
$firstChannelPricing->addAppliedPromotion(['winter_sale' => ['name' => 'Winter sale']])->shouldBeCalled();
$channelPricing->getPrice()->willReturn(1000);
$channelPricing->getOriginalPrice()->willReturn(2000);
$channelPricing->setOriginalPrice(Argument::any())->shouldNotBeCalled();
$channelPricing->setPrice(500)->shouldBeCalled();
$channelPricing->addAppliedPromotion(['winter_sale' => ['name' => 'Winter sale']])->shouldBeCalled();

$this->applyCatalogPromotion($variant, $catalogPromotion);
}
Expand Down

0 comments on commit 7be6878

Please sign in to comment.