Skip to content

Commit

Permalink
feature #13375 Catalog promotion channel pricing relation (Rafikooo)
Browse files Browse the repository at this point in the history
This PR was merged into the 1.11-dev branch.

Discussion
----------

| Q               | A
| --------------- | -----
| Branch?         | master <!-- see the comment below -->
| Bug fix?        | no
| New feature?    | yes
| BC breaks?      | no
| Deprecations?   | no <!-- don't forget to update the UPGRADE-*.md file -->
| License         | MIT

<!--
 - Bug fixes must be submitted against the 1.10 branch
 - 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
-------

354ac0c [CatalogPromotion] Array to relation on channelPricing
  • Loading branch information
GSadee committed Dec 14, 2021
2 parents c7d508f + 354ac0c commit a31fe0b
Show file tree
Hide file tree
Showing 44 changed files with 396 additions and 349 deletions.
61 changes: 33 additions & 28 deletions src/Sylius/Behat/Context/Api/Shop/ProductVariantContext.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,25 +17,27 @@
use Sylius\Behat\Client\ApiClientInterface;
use Sylius\Behat\Client\ResponseCheckerInterface;
use Sylius\Behat\Service\SharedStorageInterface;
use Sylius\Component\Core\Formatter\StringInflector;
use Sylius\Component\Core\Model\ProductInterface;
use Sylius\Component\Core\Model\ProductVariantInterface;
use Webmozart\Assert\Assert;

final class ProductVariantContext implements Context
{
private ApiClientInterface $client;
private ApiClientInterface $variantClient;

private ApiClientInterface $catalogPromotionClient;

private ResponseCheckerInterface $responseChecker;

private SharedStorageInterface $sharedStorage;

public function __construct(
ApiClientInterface $client,
ApiClientInterface $variantClient,
ApiClientInterface $catalogPromotionClient,
ResponseCheckerInterface $responseChecker,
SharedStorageInterface $sharedStorage
) {
$this->client = $client;
$this->variantClient = $variantClient;
$this->catalogPromotionClient = $catalogPromotionClient;
$this->responseChecker = $responseChecker;
$this->sharedStorage = $sharedStorage;
}
Expand All @@ -47,7 +49,8 @@ public function __construct(
*/
public function iSelectVariant(ProductVariantInterface $variant): void
{
$this->client->show($variant->getCode());
$this->sharedStorage->set('variant', $variant);
$this->variantClient->show($variant->getCode());
}

/**
Expand All @@ -56,15 +59,15 @@ public function iSelectVariant(ProductVariantInterface $variant): void
public function visitorViewVariant(ProductVariantInterface $variant): void
{
$this->sharedStorage->set('token', null);
$this->client->show($variant->getCode());
$this->variantClient->show($variant->getCode());
}

/**
* @When I view variants
*/
public function iViewVariants(): void
{
$this->client->index();
$this->variantClient->index();
}

/**
Expand All @@ -73,7 +76,7 @@ public function iViewVariants(): void
*/
public function theProductVariantPriceShouldBe(int $price): void
{
$response = $this->responseChecker->getResponseContent($this->client->getLastResponse());
$response = $this->responseChecker->getResponseContent($this->variantClient->getLastResponse());

Assert::same($response['price'], $price);
}
Expand All @@ -83,7 +86,7 @@ public function theProductVariantPriceShouldBe(int $price): void
*/
public function theProductOriginalPriceShouldBe(int $originalPrice): void
{
$response = $this->responseChecker->getResponseContent($this->client->getLastResponse());
$response = $this->responseChecker->getResponseContent($this->variantClient->getLastResponse());

Assert::same($response['originalPrice'], $originalPrice);
}
Expand All @@ -105,10 +108,11 @@ public function iShouldSeeVariantIsDiscountedFromToWithPromotions(

Assert::same($content['price'], $price);
Assert::same($content['originalPrice'], $originalPrice);
foreach ($promotionsNames as $promotionName) {
$catalogPromotionCode = StringInflector::nameToCode($promotionName);
Assert::same($content['appliedPromotions'][$catalogPromotionCode]['translations']['en_US']['name'], $promotionName);
Assert::same($content['appliedPromotions'][$catalogPromotionCode]['translations']['en_US']['description'], $promotionName . ' description');
foreach ($content['appliedPromotions'] as $promotionIri) {
$catalogPromotionContent = $this->responseChecker->getResponseContent(
$this->catalogPromotionClient->showByIri($promotionIri)
);
Assert::inArray($catalogPromotionContent['label'], $promotionsNames);
}
}

Expand Down Expand Up @@ -137,14 +141,15 @@ public function iShouldSeeVariantIsDiscountedFromToWithOnlyPromotion(
int $price,
string $promotionName
): void {
$content = $this->findVariant($variant);

Assert::same(sizeof($content['appliedPromotions']), 1);
Assert::same($content['price'], $price);
Assert::same($content['originalPrice'], $originalPrice);
$catalogPromotionCode = StringInflector::nameToCode($promotionName);
Assert::same($content['appliedPromotions'][$catalogPromotionCode]['translations']['en_US']['name'], $promotionName);
Assert::same($content['appliedPromotions'][$catalogPromotionCode]['translations']['en_US']['description'], $promotionName . ' description'); }
$variantContent = $this->findVariant($variant);
$catalogPromotionResponse = $this->variantClient->showByIri($variantContent['appliedPromotions'][0]);
$catalogPromotionContent = $this->responseChecker->getResponseContent($catalogPromotionResponse);

Assert::count($variantContent['appliedPromotions'], 1);
Assert::same($variantContent['price'], $price);
Assert::same($variantContent['originalPrice'], $originalPrice);
Assert::same($catalogPromotionContent['label'], $promotionName);
}

/**
* @Then /^the visitor should(?:| still) see that the ("[^"]+" variant) is discounted from ("[^"]+") to ("[^"]+") with "([^"]+)" promotion$/
Expand All @@ -156,7 +161,7 @@ public function theVisitorShouldSeeThatTheVariantIsDiscountedWithPromotion(
string $promotionName
): void {
$this->sharedStorage->set('token', null);
$this->client->show($productVariant->getCode());
$this->variantClient->show($productVariant->getCode());

$this->iShouldSeeVariantIsDiscountedFromToWithPromotions($productVariant, $originalPrice, $price, $promotionName);
}
Expand All @@ -166,7 +171,7 @@ public function theVisitorShouldSeeThatTheVariantIsDiscountedWithPromotion(
*/
public function iShouldSeeVariantIsNotDiscounted(ProductVariantInterface $variant): void
{
$items = $this->responseChecker->getCollectionItemsWithValue($this->client->getLastResponse(), 'code', $variant->getCode());
$items = $this->responseChecker->getCollectionItemsWithValue($this->variantClient->getLastResponse(), 'code', $variant->getCode());
$item = array_pop($items);
Assert::keyNotExists($item, 'appliedPromotions');
}
Expand All @@ -187,7 +192,7 @@ public function theVisitorShouldSeeThatTheVariantIsNotDiscounted(ProductVariantI
*/
public function iShouldSeeThisVariantIsNotDiscounted(ProductVariantInterface $variant): void
{
$content = $this->responseChecker->getResponseContent($this->client->show($variant->getCode()));
$content = $this->responseChecker->getResponseContent($this->variantClient->show($variant->getCode()));

Assert::keyNotExists($content, 'appliedPromotions');
}
Expand All @@ -202,7 +207,7 @@ public function variantAndVariantShouldBeDiscounted(ProductVariantInterface ...$

/** @var ProductVariantInterface $variant */
foreach ($variants as $variant) {
$content = $this->responseChecker->getResponseContent($this->client->show($variant->getCode()));
$content = $this->responseChecker->getResponseContent($this->variantClient->show($variant->getCode()));
Assert::keyExists(
$content,
'appliedPromotions',
Expand All @@ -221,7 +226,7 @@ public function variantAndVariantShouldNotBeDiscounted(ProductVariantInterface .

/** @var ProductVariantInterface $variant */
foreach ($variants as $variant) {
$content = $this->responseChecker->getResponseContent($this->client->show($variant->getCode()));
$content = $this->responseChecker->getResponseContent($this->variantClient->show($variant->getCode()));
Assert::keyNotExists(
$content,
'appliedPromotions',
Expand All @@ -232,7 +237,7 @@ public function variantAndVariantShouldNotBeDiscounted(ProductVariantInterface .

private function findVariant(?ProductVariantInterface $variant): array
{
$response = $this->client->getLastResponse();
$response = $this->variantClient->getLastResponse();

if ($variant !== null && $this->responseChecker->hasValue($response, '@type', 'hydra:Collection')) {
$returnValue = $this->responseChecker->getCollectionItemsWithValue($response, 'code', $variant->getCode());
Expand Down
5 changes: 5 additions & 0 deletions src/Sylius/Behat/Resources/config/services/api.xml
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,11 @@
<argument>admin</argument>
</service>

<service id="sylius.behat.api_platform_client.shop.catalog_promotion" class="Sylius\Behat\Client\ApiPlatformClient" parent="sylius.behat.api_platform_client">
<argument>catalog-promotions</argument>
<argument>shop</argument>
</service>

<service id="Sylius\Behat\Client\ResponseCheckerInterface" class="Sylius\Behat\Client\ResponseChecker">
<argument type="service" id="test.client" />
</service>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@

<service id="sylius.behat.context.api.shop.product_variant" class="Sylius\Behat\Context\Api\Shop\ProductVariantContext">
<argument type="service" id="sylius.behat.api_platform_client.shop.product_variant" />
<argument type="service" id="sylius.behat.api_platform_client.shop.catalog_promotion" />
<argument type="service" id="Sylius\Behat\Client\ResponseCheckerInterface" />
<argument type="service" id="sylius.behat.shared_storage" />
</service>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,19 +16,20 @@
xsi:schemaLocation="https://api-platform.com/schema/metadata https://api-platform.com/schema/metadata/metadata-2.0.xsd"
>
<resource class="%sylius.model.catalog_promotion.class%" shortName="CatalogPromotion">
<attribute name="route_prefix">admin</attribute>

<attribute name="validation_groups">sylius</attribute>

<collectionOperations>
<collectionOperation name="admin_get">
<attribute name="path">/admin/catalog-promotions</attribute>
<attribute name="method">GET</attribute>
<attribute name="normalization_context">
<attribute name="groups">admin:catalog_promotion:read</attribute>
</attribute>
</collectionOperation>

<collectionOperation name="admin_post">
<attribute name="path">/admin/catalog-promotions</attribute>
<attribute name="method">POST</attribute>
<attribute name="normalization_context">
<attribute name="groups">admin:catalog_promotion:read</attribute>
Expand Down Expand Up @@ -68,13 +69,22 @@ Example configuration for `percentage_discount` action type:

<itemOperations>
<itemOperation name="admin_get">
<attribute name="path">/admin/catalog-promotions/{code}</attribute>
<attribute name="method">GET</attribute>
<attribute name="normalization_context">
<attribute name="groups">admin:catalog_promotion:read</attribute>
</attribute>
</itemOperation>
<itemOperation name="shop_get">
<attribute name="path">/shop/catalog-promotions/{code}</attribute>
<attribute name="method">GET</attribute>
<attribute name="normalization_context">
<attribute name="groups">shop:catalog_promotion:read</attribute>
</attribute>
</itemOperation>

<itemOperation name="admin_put">
<attribute name="path">/admin/catalog-promotions/{code}</attribute>
<attribute name="method">PUT</attribute>
<attribute name="normalization_context">
<attribute name="groups">admin:catalog_promotion:read</attribute>
Expand Down Expand Up @@ -135,5 +145,6 @@ Example configuration for `percentage_discount` action type:
<property name="scopes" writable="true" />
<property name="actions" writable="true" />
<property name="enabled" writable="true" />
<property name="label" writable="true" />
</resource>
</resources>
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
<group>admin:catalog_promotion:read</group>
<group>admin:catalog_promotion:create</group>
<group>admin:catalog_promotion:update</group>
<group>shop:catalog_promotion:read</group>
</attribute>

<attribute name="code">
Expand Down Expand Up @@ -57,21 +58,28 @@
<group>admin:catalog_promotion:read</group>
</attribute>

<attribute name="label">
<group>shop:catalog_promotion:read</group>
</attribute>

<attribute name="translations">
<group>admin:catalog_promotion:read</group>
<group>admin:catalog_promotion:create</group>
<group>admin:catalog_promotion:update</group>
</attribute>

<attribute name="scopes">
<group>admin:catalog_promotion:read</group>
<group>admin:catalog_promotion:create</group>
<group>admin:catalog_promotion:update</group>
</attribute>

<attribute name="actions">
<group>admin:catalog_promotion:read</group>
<group>admin:catalog_promotion:create</group>
<group>admin:catalog_promotion:update</group>
</attribute>

<attribute name="enabled">
<group>admin:catalog_promotion:read</group>
<group>admin:catalog_promotion:create</group>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@
<argument type="service" id="sylius.context.channel" />
<argument type="service" id="sylius.availability_checker" />
<argument type="service" id="sylius.section_resolver.uri_based_section_resolver" />
<argument type="service" id="api_platform.iri_converter" />
<tag name="serializer.normalizer" priority="64" />
</service>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,14 @@

namespace Sylius\Bundle\ApiBundle\Serializer;

use ApiPlatform\Core\Api\IriConverterInterface;
use Doctrine\Common\Collections\ArrayCollection;
use Sylius\Bundle\ApiBundle\SectionResolver\AdminApiSection;
use Sylius\Bundle\CoreBundle\SectionResolver\SectionProviderInterface;
use Sylius\Component\Channel\Context\ChannelContextInterface;
use Sylius\Component\Channel\Context\ChannelNotFoundException;
use Sylius\Component\Core\Calculator\ProductVariantPricesCalculatorInterface;
use Sylius\Component\Core\Model\CatalogPromotionInterface;
use Sylius\Component\Core\Model\ProductVariantInterface;
use Sylius\Component\Inventory\Checker\AvailabilityCheckerInterface;
use Symfony\Component\Serializer\Normalizer\ContextAwareNormalizerInterface;
Expand All @@ -41,16 +44,20 @@ final class ProductVariantNormalizer implements ContextAwareNormalizerInterface,
/** @var SectionProviderInterface */
private $uriBasedSectionContext;

private IriConverterInterface $iriConverter;

public function __construct(
ProductVariantPricesCalculatorInterface $priceCalculator,
ChannelContextInterface $channelContext,
AvailabilityCheckerInterface $availabilityChecker,
SectionProviderInterface $uriBasedSectionContext
SectionProviderInterface $uriBasedSectionContext,
IriConverterInterface $iriConverter
) {
$this->priceCalculator = $priceCalculator;
$this->channelContext = $channelContext;
$this->availabilityChecker = $availabilityChecker;
$this->uriBasedSectionContext = $uriBasedSectionContext;
$this->iriConverter = $iriConverter;
}

public function normalize($object, $format = null, array $context = [])
Expand All @@ -59,7 +66,6 @@ public function normalize($object, $format = null, array $context = [])
Assert::keyNotExists($context, self::ALREADY_CALLED);

$context[self::ALREADY_CALLED] = true;

$data = $this->normalizer->normalize($object, $format, $context);
$channel = $this->channelContext->getChannel();

Expand All @@ -71,9 +77,13 @@ public function normalize($object, $format = null, array $context = [])
unset($data['originalPrice']);
}

/** @var ArrayCollection $appliedPromotions */
$appliedPromotions = $object->getAppliedPromotionsForChannel($channel);
if (!empty($appliedPromotions)) {
$data['appliedPromotions'] = $appliedPromotions;
if (!$appliedPromotions->isEmpty()) {
$data['appliedPromotions'] = array_map(fn (CatalogPromotionInterface $catalogPromotion) =>
$this->iriConverter->getIriFromItem($catalogPromotion),
$appliedPromotions->toArray()
);
}

$data['inStock'] = $this->availabilityChecker->isStockAvailable($object);
Expand Down

0 comments on commit a31fe0b

Please sign in to comment.