[API][Channel] Add shippingAddressInCheckoutRequired field to channel entity

This commit is contained in:
Grzegorz Sadowski 2022-07-28 18:50:38 +02:00
parent 2bb910d8a6
commit b8fbd53549
No known key found for this signature in database
GPG key ID: EF87FF4E6E3BD364
14 changed files with 282 additions and 2 deletions

View file

@ -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

View file

@ -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',
);
}
}

View file

@ -64,6 +64,14 @@
<attribute name="summary">Use $code to retrieve a channel resource.</attribute>
</attribute>
</itemOperation>
<itemOperation name="admin_put">
<attribute name="method">PUT</attribute>
<attribute name="path">/admin/channels/{code}</attribute>
<attribute name="denormalization_context">
<attribute name="groups">admin:channel:update</attribute>
</attribute>
</itemOperation>
</itemOperations>
<subresourceOperations>
@ -92,6 +100,7 @@
<property name="skippingShippingStepAllowed" writable="true" readable="true" />
<property name="skippingPaymentStepAllowed" writable="true" readable="true" />
<property name="accountVerificationRequired" writable="true" readable="true" />
<property name="shippingAddressInCheckoutRequired" writable="true" readable="true" />
<property name="shopBillingData" readable="true" writable="true">
<subresource resourceClass="%sylius.model.shop_billing_data.class%" collection="false" />
</property>

View file

@ -94,6 +94,11 @@
<group>admin:channel:read</group>
<group>admin:channel:create</group>
</attribute>
<attribute name="shippingAddressInCheckoutRequired">
<group>admin:channel:read</group>
<group>admin:channel:create</group>
<group>admin:channel:update</group>
</attribute>
<attribute name="shopBillingData">
<group>admin:channel:read</group>
<group>admin:channel:create</group>

View file

@ -0,0 +1,26 @@
<?php
declare(strict_types=1);
namespace Sylius\Bundle\CoreBundle\Migrations;
use Doctrine\DBAL\Schema\Schema;
use Sylius\Bundle\CoreBundle\Doctrine\Migrations\AbstractMigration;
final class Version20220728115129 extends AbstractMigration
{
public function getDescription(): string
{
return 'Add shipping_address_in_checkout_required field to channel';
}
public function up(Schema $schema): void
{
$this->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');
}
}

View file

@ -24,6 +24,11 @@
<field name="skippingShippingStepAllowed" column="skipping_shipping_step_allowed" type="boolean" />
<field name="skippingPaymentStepAllowed" column="skipping_payment_step_allowed" type="boolean" />
<field name="accountVerificationRequired" column="account_verification_required" type="boolean" />
<field name="shippingAddressInCheckoutRequired" column="shipping_address_in_checkout_required" type="boolean">
<options>
<option name="default">0</option>
</options>
</field>
<many-to-one field="defaultLocale" target-entity="Sylius\Component\Locale\Model\LocaleInterface" fetch="EAGER">
<join-column name="default_locale_id" referenced-column-name="id" nullable="false" />

View file

@ -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;

View file

@ -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;

View file

@ -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);

View file

@ -0,0 +1,91 @@
<?php
/*
* This file is part of the Sylius package.
*
* (c) Paweł Jędrzejewski
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Sylius\Tests\Api\Admin;
use Sylius\Component\Core\Model\ChannelInterface;
use Sylius\Tests\Api\JsonApiTestCase;
use Sylius\Tests\Api\Utils\AdminUserLoginTrait;
use Symfony\Component\HttpFoundation\Response;
final class ChannelsTest extends JsonApiTestCase
{
use AdminUserLoginTrait;
/** @test */
public function it_creates_a_channel(): void
{
$this->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);
}
}

View file

@ -0,0 +1,3 @@
Sylius\Component\Currency\Model\Currency:
currency_usd:
code: 'USD'

View file

@ -0,0 +1,3 @@
Sylius\Component\Locale\Model\Locale:
locale_en:
code: 'en_US'

View file

@ -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@
}

View file

@ -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@
}