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 eef18aef2b..76a6fd88fa 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
@@ -8,19 +8,20 @@ Feature: Choosing a required address in the checkout for a channel
Given the store operates on a single channel in "United States"
And I am logged in as an administrator
- @todo
+ @api
Scenario: Adding a new channel with a required address in the checkout
When I want to create a new channel
And I specify its code as "MOBILE"
And I name it "Mobile Store"
And I choose "USD" as the base currency
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
And I add it
Then I should be notified that it has been successfully created
And the required address in the checkout for the "Mobile Store" channel should be shipping
- @todo
+ @api
Scenario: Changing a required address in the checkout for an existing channel
Given the store operates on a channel named "Web Store"
When I want to modify this channel
diff --git a/src/Sylius/Behat/Context/Api/Admin/ManagingChannelsContext.php b/src/Sylius/Behat/Context/Api/Admin/ManagingChannelsContext.php
index fd31aedac2..d9c87b1b3b 100644
--- a/src/Sylius/Behat/Context/Api/Admin/ManagingChannelsContext.php
+++ b/src/Sylius/Behat/Context/Api/Admin/ManagingChannelsContext.php
@@ -188,6 +188,30 @@ final class ManagingChannelsContext implements Context
$this->client->index(Resources::CHANNELS);
}
+ /**
+ * @When /^I choose (billing|shipping) address as a required address in the checkout$/
+ */
+ public function iChooseAddressAsARequiredAddressInTheCheckout(string $type): void
+ {
+ $this->client->addRequestData('shippingAddressInCheckoutRequired', $type === 'shipping');
+ }
+
+ /**
+ * @When /^I want to modify (this channel)$/
+ */
+ public function iWantToModifyThisChannel(ChannelInterface $channel): void
+ {
+ $this->client->buildUpdateRequest(Resources::CHANNELS, $channel->getCode());
+ }
+
+ /**
+ * @When I save my changes
+ */
+ public function iSaveMyChanges(): void
+ {
+ $this->client->update();
+ }
+
/**
* @Then I should be notified that it has been successfully created
*/
@@ -230,4 +254,27 @@ final class ManagingChannelsContext implements Context
{
Assert::same($this->responseChecker->countCollectionItems($this->client->getLastResponse()), $count);
}
+
+ /**
+ * @Then /^the required address in the checkout for the ("[^"]+" channel) should be (billing|shipping)$/
+ */
+ public function theDefaultTaxZoneForTheChannelShouldBe(ChannelInterface $channel, string $type): void
+ {
+ Assert::true($this->responseChecker->hasValue(
+ $this->client->getLastResponse(),
+ 'shippingAddressInCheckoutRequired',
+ $type === 'shipping',
+ ));
+ }
+
+ /**
+ * @Then I should be notified that it has been successfully edited
+ */
+ public function iShouldBeNotifiedThatItHasBeenSuccessfullyEdited(): void
+ {
+ Assert::true(
+ $this->responseChecker->isUpdateSuccessful($this->client->getLastResponse()),
+ 'Channel could not be edited',
+ );
+ }
}
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 c3444d015e..89fcd23258 100644
--- a/src/Sylius/Bundle/ApiBundle/Resources/config/api_resources/Channel.xml
+++ b/src/Sylius/Bundle/ApiBundle/Resources/config/api_resources/Channel.xml
@@ -64,6 +64,14 @@
Use $code to retrieve a channel resource.
+
+
+ PUT
+ /admin/channels/{code}
+
+ admin:channel:update
+
+
@@ -92,6 +100,7 @@
+
diff --git a/src/Sylius/Bundle/ApiBundle/Resources/config/serialization/Channel.xml b/src/Sylius/Bundle/ApiBundle/Resources/config/serialization/Channel.xml
index 69fbc730e3..af833fb9cb 100644
--- a/src/Sylius/Bundle/ApiBundle/Resources/config/serialization/Channel.xml
+++ b/src/Sylius/Bundle/ApiBundle/Resources/config/serialization/Channel.xml
@@ -94,6 +94,11 @@
admin:channel:read
admin:channel:create
+
+ admin:channel:read
+ admin:channel:create
+ admin:channel:update
+
admin:channel:read
admin:channel:create
diff --git a/src/Sylius/Bundle/CoreBundle/Migrations/Version20220728115129.php b/src/Sylius/Bundle/CoreBundle/Migrations/Version20220728115129.php
new file mode 100644
index 0000000000..de272feafc
--- /dev/null
+++ b/src/Sylius/Bundle/CoreBundle/Migrations/Version20220728115129.php
@@ -0,0 +1,26 @@
+addSql('ALTER TABLE sylius_channel ADD shipping_address_in_checkout_required TINYINT(1) DEFAULT 0 NOT NULL');
+ }
+
+ public function down(Schema $schema): void
+ {
+ $this->addSql('ALTER TABLE sylius_channel DROP shipping_address_in_checkout_required');
+ }
+}
diff --git a/src/Sylius/Bundle/CoreBundle/Resources/config/doctrine/model/Channel.orm.xml b/src/Sylius/Bundle/CoreBundle/Resources/config/doctrine/model/Channel.orm.xml
index 4b8fd5dbe0..014f0ff9ad 100644
--- a/src/Sylius/Bundle/CoreBundle/Resources/config/doctrine/model/Channel.orm.xml
+++ b/src/Sylius/Bundle/CoreBundle/Resources/config/doctrine/model/Channel.orm.xml
@@ -24,6 +24,11 @@
+
+
+
+
+
diff --git a/src/Sylius/Component/Core/Model/Channel.php b/src/Sylius/Component/Core/Model/Channel.php
index 8d61bdb246..de78b010dc 100644
--- a/src/Sylius/Component/Core/Model/Channel.php
+++ b/src/Sylius/Component/Core/Model/Channel.php
@@ -74,6 +74,8 @@ class Channel extends BaseChannel implements ChannelInterface
/** @var bool */
protected $accountVerificationRequired = true;
+ protected bool $shippingAddressInCheckoutRequired = false;
+
/** @var ShopBillingDataInterface|null */
protected $shopBillingData;
@@ -264,6 +266,16 @@ class Channel extends BaseChannel implements ChannelInterface
$this->accountVerificationRequired = $accountVerificationRequired;
}
+ public function isShippingAddressInCheckoutRequired(): bool
+ {
+ return $this->shippingAddressInCheckoutRequired;
+ }
+
+ public function setShippingAddressInCheckoutRequired(bool $shippingAddressInCheckoutRequired): void
+ {
+ $this->shippingAddressInCheckoutRequired = $shippingAddressInCheckoutRequired;
+ }
+
public function getShopBillingData(): ?ShopBillingDataInterface
{
return $this->shopBillingData;
diff --git a/src/Sylius/Component/Core/Model/ChannelInterface.php b/src/Sylius/Component/Core/Model/ChannelInterface.php
index ec9cd5d1d4..515ec7caad 100644
--- a/src/Sylius/Component/Core/Model/ChannelInterface.php
+++ b/src/Sylius/Component/Core/Model/ChannelInterface.php
@@ -67,6 +67,10 @@ interface ChannelInterface extends
public function setAccountVerificationRequired(bool $accountVerificationRequired): void;
+ public function isShippingAddressInCheckoutRequired(): bool;
+
+ public function setShippingAddressInCheckoutRequired(bool $shippingAddressInCheckoutRequired): void;
+
public function getShopBillingData(): ?ShopBillingDataInterface;
public function setShopBillingData(ShopBillingDataInterface $shopBillingData): void;
diff --git a/src/Sylius/Component/Core/spec/Model/ChannelSpec.php b/src/Sylius/Component/Core/spec/Model/ChannelSpec.php
index 6a350d2895..25b86be016 100644
--- a/src/Sylius/Component/Core/spec/Model/ChannelSpec.php
+++ b/src/Sylius/Component/Core/spec/Model/ChannelSpec.php
@@ -172,6 +172,17 @@ final class ChannelSpec extends ObjectBehavior
$this->isAccountVerificationRequired()->shouldReturn(false);
}
+ function it_does_not_have_shipping_address_in_checkout_required_by_default(): void
+ {
+ $this->isShippingAddressInCheckoutRequired()->shouldReturn(false);
+ }
+
+ function it_can_set_shipping_address_in_checkout_required(): void
+ {
+ $this->setShippingAddressInCheckoutRequired(true);
+ $this->isShippingAddressInCheckoutRequired()->shouldReturn(true);
+ }
+
function its_menu_taxon_is_mutable(TaxonInterface $taxon): void
{
$this->setMenuTaxon($taxon);
diff --git a/tests/Api/Admin/ChannelsTest.php b/tests/Api/Admin/ChannelsTest.php
new file mode 100644
index 0000000000..b931a27ab3
--- /dev/null
+++ b/tests/Api/Admin/ChannelsTest.php
@@ -0,0 +1,91 @@
+loadFixturesFromFiles(['authentication/api_administrator.yaml', 'currency.yaml', 'locale.yaml']);
+ $header = $this->getLoggedHeader();
+
+ $this->client->request(
+ 'POST',
+ '/api/v2/admin/channels',
+ [],
+ [],
+ $header,
+ json_encode([
+ 'name' => 'Web Store',
+ 'code' => 'WEB',
+ 'baseCurrency' => '/api/v2/admin/currencies/USD',
+ 'defaultLocale' => '/api/v2/admin/locales/en_US',
+ 'taxCalculationStrategy' => 'order_items_based',
+ 'shippingAddressInCheckoutRequired' => true,
+
+ ], JSON_THROW_ON_ERROR)
+ );
+
+ $this->assertResponse(
+ $this->client->getResponse(),
+ 'admin/post_channel_response',
+ Response::HTTP_CREATED
+ );
+ }
+
+ /** @test */
+ public function it_updates_an_existing_channel(): void
+ {
+ $fixtures = $this->loadFixturesFromFiles(['authentication/api_administrator.yaml', 'channel.yaml']);
+
+ /** @var ChannelInterface $channel */
+ $channel = $fixtures['channel_web'];
+
+ $header = $this->getLoggedHeader();
+
+ $this->client->request(
+ 'PUT',
+ '/api/v2/admin/channels/' . $channel->getCode(),
+ [],
+ [],
+ $header,
+ json_encode([
+ 'shippingAddressInCheckoutRequired' => true,
+ ], JSON_THROW_ON_ERROR)
+ );
+
+ $this->assertResponse(
+ $this->client->getResponse(),
+ 'admin/put_channel_response',
+ Response::HTTP_OK
+ );
+ }
+
+ private function getLoggedHeader(): array
+ {
+ $token = $this->logInAdminUser('api@example.com');
+ $authorizationHeader = self::$container->getParameter('sylius.api.authorization_header');
+ $header['HTTP_' . $authorizationHeader] = 'Bearer ' . $token;
+
+ return array_merge($header, self::CONTENT_TYPE_HEADER);
+ }
+}
diff --git a/tests/Api/DataFixtures/ORM/currency.yaml b/tests/Api/DataFixtures/ORM/currency.yaml
new file mode 100644
index 0000000000..5b7399c731
--- /dev/null
+++ b/tests/Api/DataFixtures/ORM/currency.yaml
@@ -0,0 +1,3 @@
+Sylius\Component\Currency\Model\Currency:
+ currency_usd:
+ code: 'USD'
diff --git a/tests/Api/DataFixtures/ORM/locale.yaml b/tests/Api/DataFixtures/ORM/locale.yaml
new file mode 100644
index 0000000000..762938d09d
--- /dev/null
+++ b/tests/Api/DataFixtures/ORM/locale.yaml
@@ -0,0 +1,3 @@
+Sylius\Component\Locale\Model\Locale:
+ locale_en:
+ code: 'en_US'
diff --git a/tests/Api/Responses/Expected/admin/post_channel_response.json b/tests/Api/Responses/Expected/admin/post_channel_response.json
new file mode 100644
index 0000000000..3bdcdda4fb
--- /dev/null
+++ b/tests/Api/Responses/Expected/admin/post_channel_response.json
@@ -0,0 +1,30 @@
+{
+ "@context": "\/api\/v2\/contexts\/Channel",
+ "@id": "\/api\/v2\/admin\/channels\/WEB",
+ "@type": "Channel",
+ "id":"@integer@",
+ "code": "WEB",
+ "name": "Web Store",
+ "enabled": true,
+ "baseCurrency": "\/api\/v2\/admin\/currencies\/USD",
+ "defaultLocale": "\/api\/v2\/admin\/locales\/en_US",
+ "defaultTaxZone": null,
+ "taxCalculationStrategy": "order_items_based",
+ "currencies": [],
+ "locales": [],
+ "countries": [],
+ "themeName": null,
+ "contactEmail": null,
+ "contactPhoneNumber": null,
+ "skippingShippingStepAllowed": false,
+ "skippingPaymentStepAllowed": false,
+ "accountVerificationRequired": true,
+ "shippingAddressInCheckoutRequired": true,
+ "shopBillingData": null,
+ "menuTaxon": null,
+ "description": null,
+ "hostname": null,
+ "color": null,
+ "createdAt": @string@,
+ "updatedAt": @string@
+}
diff --git a/tests/Api/Responses/Expected/admin/put_channel_response.json b/tests/Api/Responses/Expected/admin/put_channel_response.json
new file mode 100644
index 0000000000..1e755021b2
--- /dev/null
+++ b/tests/Api/Responses/Expected/admin/put_channel_response.json
@@ -0,0 +1,33 @@
+{
+ "@context": "\/api\/v2\/contexts\/Channel",
+ "@id": "\/api\/v2\/admin\/channels\/WEB",
+ "@type": "Channel",
+ "id":"@integer@",
+ "code": "WEB",
+ "name": "Web Channel",
+ "enabled": true,
+ "baseCurrency": "\/api\/v2\/admin\/currencies\/USD",
+ "defaultLocale": "\/api\/v2\/admin\/locales\/en_US",
+ "defaultTaxZone": null,
+ "taxCalculationStrategy": "order_items_based",
+ "currencies": [],
+ "locales": [
+ "\/api\/v2\/admin\/locales\/en_US",
+ "\/api\/v2\/admin\/locales\/pl_PL"
+ ],
+ "countries": [],
+ "themeName": null,
+ "contactEmail": "web@sylius.com",
+ "contactPhoneNumber": null,
+ "skippingShippingStepAllowed": false,
+ "skippingPaymentStepAllowed": false,
+ "accountVerificationRequired": true,
+ "shippingAddressInCheckoutRequired": true,
+ "shopBillingData": null,
+ "menuTaxon": null,
+ "description": "Lorem ipsum",
+ "hostname": "localhost",
+ "color": "black",
+ "createdAt": @string@,
+ "updatedAt": @string@
+}