diff --git a/features/channel/managing_channels/adding_channel.feature b/features/channel/managing_channels/adding_channel.feature index 30b6d2ef91..aa48daf64c 100644 --- a/features/channel/managing_channels/adding_channel.feature +++ b/features/channel/managing_channels/adding_channel.feature @@ -16,6 +16,7 @@ Feature: Adding a new channel And I specify its code as "MOBILE" And I name it "Mobile channel" And I choose "Euro" as the base currency + And I make it available in "English (United States)" And I choose "English (United States)" as a default locale And I select the "Order items based" as tax calculation strategy And I add it @@ -33,6 +34,7 @@ Feature: Adding a new channel And I set its contact phone number as "11331122" And I define its color as "blue" And I choose "Euro" as the base currency + And I make it available in "English (United States)" And I choose "English (United States)" as a default locale And I choose "United States" and "Poland" as operating countries And I select the "Order items based" as tax calculation strategy diff --git a/features/channel/managing_channels/adding_channel_with_shop_billing_data.feature b/features/channel/managing_channels/adding_channel_with_shop_billing_data.feature index 6c6ea0eee4..dd3e351a7f 100644 --- a/features/channel/managing_channels/adding_channel_with_shop_billing_data.feature +++ b/features/channel/managing_channels/adding_channel_with_shop_billing_data.feature @@ -16,6 +16,7 @@ Feature: Adding a new channel with shop billing data And I specify its code as "MOBILE" And I name it "Mobile channel" And I choose "Euro" as the base currency + And I make it available in "English (United States)" And I choose "English (United States)" as a default locale And I select the "Order items based" as tax calculation strategy And I specify company as "Ragnarok" diff --git a/features/channel/managing_channels/adding_new_channel_with_menu_taxon.feature b/features/channel/managing_channels/adding_new_channel_with_menu_taxon.feature index 943ae8e4aa..899fb6c75f 100644 --- a/features/channel/managing_channels/adding_new_channel_with_menu_taxon.feature +++ b/features/channel/managing_channels/adding_new_channel_with_menu_taxon.feature @@ -17,6 +17,7 @@ Feature: Adding a new channel with menu taxon And I specify its code as "MOBILE" And I name it "Mobile channel" And I choose "Euro" as the base currency + And I make it available in "English (United States)" And I choose "English (United States)" as a default locale And I select the "Order items based" as tax calculation strategy And I specify menu taxon as "Clothes" diff --git a/features/channel/managing_channels/choosing_required_address_in_checkout_for_channel.feature b/features/channel/managing_channels/choosing_required_address_in_checkout_for_channel.feature index 718788f7ce..bd44a3db81 100644 --- a/features/channel/managing_channels/choosing_required_address_in_checkout_for_channel.feature +++ b/features/channel/managing_channels/choosing_required_address_in_checkout_for_channel.feature @@ -14,6 +14,7 @@ Feature: Choosing a required address in the checkout for a channel And I specify its code as "MOBILE" And I name it "Mobile Store" And I choose "USD" as the base currency + And I make it available in "English (United States)" And I choose "English (United States)" as a default locale And I select the "Order items based" as tax calculation strategy And I choose shipping address as a required address in the checkout diff --git a/src/Sylius/Behat/Context/Api/Admin/ManagingChannelsContext.php b/src/Sylius/Behat/Context/Api/Admin/ManagingChannelsContext.php index 4a8d6ed929..e9690cc99c 100644 --- a/src/Sylius/Behat/Context/Api/Admin/ManagingChannelsContext.php +++ b/src/Sylius/Behat/Context/Api/Admin/ManagingChannelsContext.php @@ -265,8 +265,8 @@ final class ManagingChannelsContext implements Context public function iShouldBeNotifiedThatItHasBeenSuccessfullyCreated(): void { Assert::true( - $this->responseChecker->isCreationSuccessful($this->client->getLastResponse()), - 'Channel could not be created', + $this->responseChecker->isCreationSuccessful($response = $this->client->getLastResponse()), + 'Channel could not be created: ' . $response->getContent(), ); } diff --git a/src/Sylius/Bundle/ApiBundle/Resources/config/api_resources/Channel.xml b/src/Sylius/Bundle/ApiBundle/Resources/config/api_resources/Channel.xml index 7003380820..5a2dc00909 100644 --- a/src/Sylius/Bundle/ApiBundle/Resources/config/api_resources/Channel.xml +++ b/src/Sylius/Bundle/ApiBundle/Resources/config/api_resources/Channel.xml @@ -42,6 +42,7 @@ admin:channel:read + sylius @@ -77,6 +78,7 @@ admin:channel:read + sylius diff --git a/src/Sylius/Bundle/ApiBundle/Resources/config/serialization/Channel.xml b/src/Sylius/Bundle/ApiBundle/Resources/config/serialization/Channel.xml index df0ba4ce96..92f00cc2b1 100644 --- a/src/Sylius/Bundle/ApiBundle/Resources/config/serialization/Channel.xml +++ b/src/Sylius/Bundle/ApiBundle/Resources/config/serialization/Channel.xml @@ -111,5 +111,20 @@ admin:channel:read admin:channel:create + + admin:channel:read + admin:channel:create + admin:channel:update + + + admin:channel:read + admin:channel:create + admin:channel:update + + + admin:channel:read + admin:channel:create + admin:channel:update + diff --git a/src/Sylius/Bundle/ApiBundle/Resources/config/services/serializers.xml b/src/Sylius/Bundle/ApiBundle/Resources/config/services/serializers.xml index 69c63ee9bf..d85303db33 100644 --- a/src/Sylius/Bundle/ApiBundle/Resources/config/services/serializers.xml +++ b/src/Sylius/Bundle/ApiBundle/Resources/config/services/serializers.xml @@ -102,5 +102,10 @@ + + + + + diff --git a/src/Sylius/Bundle/ApiBundle/Serializer/ChannelExcludedTaxonsDenormalizer.php b/src/Sylius/Bundle/ApiBundle/Serializer/ChannelExcludedTaxonsDenormalizer.php new file mode 100644 index 0000000000..bc32287279 --- /dev/null +++ b/src/Sylius/Bundle/ApiBundle/Serializer/ChannelExcludedTaxonsDenormalizer.php @@ -0,0 +1,62 @@ +denormalizer->denormalize($data, $type, $format, $context); + Assert::isInstanceOf($channel, ChannelInterface::class); + + $channel->clearTaxonsExcludedFromShowingLowestPrice(); + + foreach ($data['taxonsExcludedFromShowingLowestPrice'] ?? [] as $excludedTaxonIri) { + /** @var TaxonInterface $taxon */ + $taxon = $this->iriConverter->getItemFromIri($excludedTaxonIri); + + $channel->addTaxonExcludedFromShowingLowestPrice($taxon); + } + + return $channel; + } +} diff --git a/src/Sylius/Bundle/ApiBundle/spec/Serializer/ChannelExcludedTaxonsDenormalizerSpec.php b/src/Sylius/Bundle/ApiBundle/spec/Serializer/ChannelExcludedTaxonsDenormalizerSpec.php new file mode 100644 index 0000000000..3f2fcb7fa3 --- /dev/null +++ b/src/Sylius/Bundle/ApiBundle/spec/Serializer/ChannelExcludedTaxonsDenormalizerSpec.php @@ -0,0 +1,147 @@ +beConstructedWith($iriConverter); + } + + function it_does_not_support_denormalization_when_the_denormalizer_has_already_been_called(): void + { + $this->supportsDenormalization([], 'string', context: [self::ALREADY_CALLED => true])->shouldReturn(false); + } + + function it_does_not_support_denormalization_when_data_is_not_an_array(): void + { + $this->supportsDenormalization('string', 'string')->shouldReturn(false); + } + + function it_does_not_support_denormalization_when_type_is_not_a_channel(): void + { + $this->supportsDenormalization([], 'string')->shouldReturn(false); + } + + function it_throws_an_exception_when_denormalizing_an_object_that_is_not_a_channel( + DenormalizerInterface $denormalizer, + ): void { + $this->setDenormalizer($denormalizer); + + $denormalizer->denormalize([], 'string', null, [self::ALREADY_CALLED => true])->willReturn(new \stdClass()); + + $this->shouldThrow(\InvalidArgumentException::class)->during('denormalize', [[], 'string']); + } + + function it_adds_excluded_taxons_from_data( + DenormalizerInterface $denormalizer, + IriConverterInterface $iriConverter, + TaxonInterface $firstTaxon, + TaxonInterface $secondTaxon, + ChannelInterface $channel, + ): void { + $this->setDenormalizer($denormalizer); + + $data = ['taxonsExcludedFromShowingLowestPrice' => [ + '/api/v2/taxons/first-new-taxon', + '/api/v2/taxons/second-new-taxon', + ]]; + + $channel->getTaxonsExcludedFromShowingLowestPrice()->willReturn(new ArrayCollection()); + + $denormalizer->denormalize($data, 'string', null, [self::ALREADY_CALLED => true])->willReturn($channel); + + $channel->clearTaxonsExcludedFromShowingLowestPrice()->shouldBeCalled(); + + $iriConverter->getItemFromIri('/api/v2/taxons/first-new-taxon')->shouldBeCalledTimes(1)->willReturn($firstTaxon); + $iriConverter->getItemFromIri('/api/v2/taxons/second-new-taxon')->shouldBeCalledTimes(1)->willReturn($secondTaxon); + + $channel->addTaxonExcludedFromShowingLowestPrice($firstTaxon)->shouldBeCalledTimes(1); + $channel->addTaxonExcludedFromShowingLowestPrice($secondTaxon)->shouldBeCalledTimes(1); + + $this->denormalize($data, 'string')->shouldReturn($channel); + } + + function it_removes_excluded_taxons_when_data_has_none( + DenormalizerInterface $denormalizer, + IriConverterInterface $iriConverter, + TaxonInterface $firstTaxon, + TaxonInterface $secondTaxon, + ChannelInterface $channel, + ): void { + $this->setDenormalizer($denormalizer); + + $data = []; + + $denormalizer->denormalize($data, 'string', null, [self::ALREADY_CALLED => true])->willReturn($channel); + + $channel->getTaxonsExcludedFromShowingLowestPrice()->willReturn(new ArrayCollection([ + $firstTaxon->getWrappedObject(), + $secondTaxon->getWrappedObject(), + ])); + + $channel->clearTaxonsExcludedFromShowingLowestPrice()->shouldBeCalled(); + + $iriConverter->getItemFromIri(Argument::cetera())->shouldNotBeCalled(); + + $channel->addTaxonExcludedFromShowingLowestPrice(Argument::any())->shouldNotBeCalled(); + + $this->denormalize($data, 'string')->shouldReturn($channel); + } + + function it_replaces_current_excluded_taxons_with_ones_from_data( + DenormalizerInterface $denormalizer, + IriConverterInterface $iriConverter, + TaxonInterface $firstCurrentTaxon, + TaxonInterface $secondCurrentTaxon, + TaxonInterface $firstNewTaxon, + TaxonInterface $secondNewTaxon, + ChannelInterface $channel, + ): void { + $this->setDenormalizer($denormalizer); + + $data = ['taxonsExcludedFromShowingLowestPrice' => [ + '/api/v2/taxons/first-new-taxon', + '/api/v2/taxons/second-new-taxon', + ]]; + + $denormalizer->denormalize($data, 'string', null, [self::ALREADY_CALLED => true])->willReturn($channel); + + $channel->getTaxonsExcludedFromShowingLowestPrice()->willReturn(new ArrayCollection([ + $firstCurrentTaxon->getWrappedObject(), + $secondCurrentTaxon->getWrappedObject(), + ])); + + $channel->clearTaxonsExcludedFromShowingLowestPrice()->shouldBeCalled(); + + $iriConverter->getItemFromIri('/api/v2/taxons/first-new-taxon')->shouldBeCalledTimes(1)->willReturn($firstNewTaxon); + $iriConverter->getItemFromIri('/api/v2/taxons/second-new-taxon')->shouldBeCalledTimes(1)->willReturn($secondNewTaxon); + + $channel->addTaxonExcludedFromShowingLowestPrice($firstNewTaxon)->shouldBeCalledTimes(1); + $channel->addTaxonExcludedFromShowingLowestPrice($secondNewTaxon)->shouldBeCalledTimes(1); + + $this->denormalize($data, 'string')->shouldReturn($channel); + } +} diff --git a/src/Sylius/Bundle/ChannelBundle/Resources/translations/validators.en.yml b/src/Sylius/Bundle/ChannelBundle/Resources/translations/validators.en.yml index 3346274b6b..906fde7a00 100644 --- a/src/Sylius/Bundle/ChannelBundle/Resources/translations/validators.en.yml +++ b/src/Sylius/Bundle/ChannelBundle/Resources/translations/validators.en.yml @@ -4,5 +4,8 @@ sylius: not_blank: Please enter channel code. regex: Channel code can only be comprised of letters, numbers, dashes and underscores. unique: Channel code has to be unique. + lowest_price_for_discounted_products_checking_period: + greater_than: 'Value must be greater than {{ compared_value }}' + less_than: 'Value must be less than {{ compared_value }}' name: not_blank: Please enter channel name. diff --git a/src/Sylius/Bundle/CoreBundle/Resources/config/services/price_history/listeners.xml b/src/Sylius/Bundle/CoreBundle/Resources/config/services/price_history/listeners.xml index cf26195259..75ad7b5310 100644 --- a/src/Sylius/Bundle/CoreBundle/Resources/config/services/price_history/listeners.xml +++ b/src/Sylius/Bundle/CoreBundle/Resources/config/services/price_history/listeners.xml @@ -24,7 +24,7 @@ %sylius_core.price_history.batch_size% - + diff --git a/src/Sylius/Bundle/CoreBundle/Resources/config/validation/Channel.xml b/src/Sylius/Bundle/CoreBundle/Resources/config/validation/Channel.xml index 6f68d60d52..986a21647b 100644 --- a/src/Sylius/Bundle/CoreBundle/Resources/config/validation/Channel.xml +++ b/src/Sylius/Bundle/CoreBundle/Resources/config/validation/Channel.xml @@ -54,5 +54,32 @@ + + + + + + + + + + + + + + + + + + +