mirror of
https://github.com/Sylius/Sylius.git
synced 2026-07-14 17:10:53 +00:00
[API] cover shipment filtering and simple state machine
This commit is contained in:
parent
cec2bc0494
commit
e5d369c120
12 changed files with 210 additions and 9 deletions
|
|
@ -27,7 +27,7 @@ Feature: Filtering shipments by a channel
|
|||
And the customer chose "FEDEX" shipping method with "bank transfer" payment
|
||||
And I am logged in as an administrator
|
||||
|
||||
@ui
|
||||
@ui @api
|
||||
Scenario: Filtering shipments by channel on index
|
||||
When I browse shipments
|
||||
And I choose "United States" as a channel filter
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ Feature: Filtering shipments by state
|
|||
And the customer chose "UPS" shipping method with "Cash on Delivery" payment
|
||||
And I am logged in as an administrator
|
||||
|
||||
@ui
|
||||
@ui @api
|
||||
Scenario: Filtering payments in state "Shipped"
|
||||
When I browse shipments
|
||||
And I choose "Shipped" as a shipment state
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ Feature: Shipping a shipment from shipment list
|
|||
And the customer chose "UPS" shipping method with "Cash on Delivery" payment
|
||||
And I am logged in as an administrator
|
||||
|
||||
@ui @email
|
||||
@ui @api @email
|
||||
Scenario: Shipping a shipment from shipments index
|
||||
When I browse shipments
|
||||
And I ship the shipment of order "#00000001"
|
||||
|
|
@ -30,7 +30,7 @@ Feature: Shipping a shipment from shipment list
|
|||
Then I should be notified that the shipment has been successfully shipped
|
||||
And an email with the shipment's confirmation of the order "#00000001" should be sent to "donald@duck.com"
|
||||
|
||||
@ui
|
||||
@ui @api @email
|
||||
Scenario: Setting date when a shipment has been shipped
|
||||
Given it is "20-02-2020 10:30:05" now
|
||||
When I browse shipments
|
||||
|
|
|
|||
|
|
@ -19,8 +19,9 @@ use Sylius\Behat\Client\ApiClientInterface;
|
|||
use Sylius\Behat\Client\ResponseCheckerInterface;
|
||||
use Sylius\Component\Channel\Model\ChannelInterface;
|
||||
use Sylius\Component\Core\Formatter\StringInflector;
|
||||
use Sylius\Component\Core\Model\OrderInterface;
|
||||
use Sylius\Component\Customer\Model\CustomerInterface;
|
||||
use Sylius\Component\Order\Model\OrderInterface;
|
||||
use Sylius\Component\Shipping\ShipmentTransitions;
|
||||
use Webmozart\Assert\Assert;
|
||||
|
||||
final class ManagingShipmentsContext implements Context
|
||||
|
|
@ -52,6 +53,30 @@ final class ManagingShipmentsContext implements Context
|
|||
$this->client->index();
|
||||
}
|
||||
|
||||
/**
|
||||
* @When I choose :shipmentState as a shipment state
|
||||
*/
|
||||
public function iChooseShipmentState(string $state): void
|
||||
{
|
||||
$this->client->addFilter('state', $state);
|
||||
}
|
||||
|
||||
/**
|
||||
* @When I choose :channel as a channel filter
|
||||
*/
|
||||
public function iChooseChannelAsAChannelFilter(ChannelInterface $channel): void
|
||||
{
|
||||
$this->client->addFilter('order.channel.code', $channel->getCode());
|
||||
}
|
||||
|
||||
/**
|
||||
* @When I filter
|
||||
*/
|
||||
public function iFilter(): void
|
||||
{
|
||||
$this->client->filter();
|
||||
}
|
||||
|
||||
/**
|
||||
* @Then I should see( only) :count shipment(s) in the list
|
||||
* @Then I should see a single shipment in the list
|
||||
|
|
@ -61,13 +86,29 @@ final class ManagingShipmentsContext implements Context
|
|||
Assert::same($this->responseChecker->countCollectionItems($this->client->getLastResponse()), $count);
|
||||
}
|
||||
|
||||
/**
|
||||
* @When I ship the shipment of order :order
|
||||
*/
|
||||
public function iShipShipmentOfOrder(OrderInterface $order): void
|
||||
{
|
||||
$this->client->applyTransition((string) $order->getShipments()->first()->getId(), ShipmentTransitions::TRANSITION_SHIP);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Then I should be notified that the shipment has been successfully shipped
|
||||
*/
|
||||
public function iShouldBeNotifiedThatTheShipmentHasBeenSuccessfullyShipped(): void
|
||||
{
|
||||
Assert::same($this->responseChecker->getValue($this->client->getLastResponse(), 'state'), 'shipped', 'Shipment is not shipped');
|
||||
}
|
||||
|
||||
/**
|
||||
* @Then /^I should see the shipment of (order "[^"]+") as "([^"]+)"$/
|
||||
*/
|
||||
public function iShouldSeeTheShipmentOfOrderAs(OrderInterface $order, string $shippingState): void
|
||||
{
|
||||
Assert::true(
|
||||
$this->responseChecker->hasItemWithValues($this->client->getLastResponse(), [
|
||||
$this->responseChecker->hasItemWithValues($this->client->index(), [
|
||||
'order' => $this->iriConverter->getIriFromItem($order),
|
||||
'state' => strtolower($shippingState)
|
||||
]),
|
||||
|
|
@ -91,6 +132,20 @@ final class ManagingShipmentsContext implements Context
|
|||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Then I should see the shipment of order :order shipped at :dateTime
|
||||
*/
|
||||
public function iShouldSeeTheShippingDateAs(OrderInterface $order, string $dateTime): void
|
||||
{
|
||||
$shipmentShowResponse = $this->client->show((string) $order->getShipments()->first()->getId());
|
||||
|
||||
if (
|
||||
strtotime($this->responseChecker->getValue($shipmentShowResponse, 'shippedAt')) != strtotime($dateTime)
|
||||
) {
|
||||
throw new \InvalidArgumentException('Shipment was shipped in different date');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @Then the shipment of the :orderNumber order should be :shippingState for :customer
|
||||
* @Then the shipment of the :orderNumber order should be :shippingState for :customer in :channel channel
|
||||
|
|
@ -105,8 +160,7 @@ final class ManagingShipmentsContext implements Context
|
|||
|
||||
foreach ($this->responseChecker->getCollectionItemsWithValue($this->client->getLastResponse(), 'state',
|
||||
StringInflector::nameToLowercaseCode($shippingState)) as $shipment) {
|
||||
$orderIri = $shipment['order'];
|
||||
$orderShowResponse = $this->client->showByIri($orderIri);
|
||||
$orderShowResponse = $this->client->showByIri($shipment['order']);
|
||||
|
||||
if (!$this->responseChecker->HasValue($orderShowResponse, 'number', $orderNumber)) {
|
||||
continue;
|
||||
|
|
@ -124,4 +178,35 @@ final class ManagingShipmentsContext implements Context
|
|||
|
||||
throw new \InvalidArgumentException('There is no shipment with given data');
|
||||
}
|
||||
|
||||
/**
|
||||
* @Then I should see a shipment of order :order
|
||||
*/
|
||||
public function iShouldSeeShipmentWithOrderNumber(OrderInterface $order): void
|
||||
{
|
||||
Assert::true(
|
||||
$this->isShipmentForOrder($order),
|
||||
sprintf('There is no shipment for order %s', $order->getNumber())
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Then I should not see a shipment of order :order
|
||||
*/
|
||||
public function iShouldNotSeeShipmentWithOrderNumber(OrderInterface $order): void
|
||||
{
|
||||
Assert::false(
|
||||
$this->isShipmentForOrder($order),
|
||||
sprintf('There is shipment for order %s', $order->getNumber())
|
||||
);
|
||||
}
|
||||
|
||||
private function isShipmentForOrder(OrderInterface $order): bool
|
||||
{
|
||||
return $this->responseChecker->hasItemWithValue(
|
||||
$this->client->getLastResponse(),
|
||||
'order',
|
||||
$this->iriConverter->getIriFromItem($order)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,6 +28,8 @@ default:
|
|||
- sylius.behat.context.setup.shipping
|
||||
- sylius.behat.context.setup.zone
|
||||
|
||||
- sylius.behat.context.ui.email
|
||||
|
||||
- sylius.behat.context.api.admin.managing_shipments
|
||||
filters:
|
||||
tags: "@managing_shipments && @api"
|
||||
|
|
|
|||
|
|
@ -0,0 +1,42 @@
|
|||
<?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\Bundle\ApiBundle\Applicator;
|
||||
|
||||
use SM\Factory\FactoryInterface as StateMachineFactoryInterface;
|
||||
use Sylius\Component\Core\Model\ShipmentInterface;
|
||||
use Sylius\Component\Shipping\ShipmentTransitions;
|
||||
|
||||
final class ShipmentStateMachineTransitionApplicator
|
||||
{
|
||||
/** @var StateMachineFactoryInterface $stateMachineFactory */
|
||||
private $stateMachineFactory;
|
||||
|
||||
public function __construct(StateMachineFactoryInterface $stateMachineFactory)
|
||||
{
|
||||
$this->stateMachineFactory = $stateMachineFactory;
|
||||
}
|
||||
|
||||
public function ship(ShipmentInterface $data): ShipmentInterface
|
||||
{
|
||||
$this->applyTransition( $data, ShipmentTransitions::TRANSITION_SHIP);
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
private function applyTransition(ShipmentInterface $shipment, string $transition): void
|
||||
{
|
||||
$stateMachine = $this->stateMachineFactory->get($shipment, ShipmentTransitions::GRAPH);
|
||||
$stateMachine->apply($transition);
|
||||
}
|
||||
}
|
||||
|
|
@ -35,11 +35,20 @@
|
|||
</attribute>
|
||||
|
||||
<collectionOperations>
|
||||
<collectionOperation name="get" />
|
||||
<collectionOperation name="get">
|
||||
<attribute name="filters">
|
||||
<attribute>sylius.api.search_shipment_filter</attribute>
|
||||
</attribute>
|
||||
</collectionOperation>
|
||||
</collectionOperations>
|
||||
|
||||
<itemOperations>
|
||||
<itemOperation name="get" />
|
||||
<itemOperation name="ship">
|
||||
<attribute name="method">PATCH</attribute>
|
||||
<attribute name="path">/shipments/{id}/ship</attribute>
|
||||
<attribute name="controller">sylius.api.shipment_machine_transition_applicator::ship</attribute>
|
||||
</itemOperation>
|
||||
</itemOperations>
|
||||
|
||||
<property name="id" identifier="true" />
|
||||
|
|
|
|||
|
|
@ -28,6 +28,12 @@
|
|||
|
||||
<collectionOperations />
|
||||
|
||||
<itemOperations>
|
||||
<itemOperation name="get" />
|
||||
</itemOperations>
|
||||
|
||||
<collectionOperations />
|
||||
|
||||
<property name="id" identifier="true" writable="false" />
|
||||
</resource>
|
||||
</resources>
|
||||
|
|
|
|||
|
|
@ -28,6 +28,12 @@
|
|||
|
||||
<collectionOperations />
|
||||
|
||||
<itemOperations>
|
||||
<itemOperation name="get" />
|
||||
</itemOperations>
|
||||
|
||||
<collectionOperations />
|
||||
|
||||
<property name="id" identifier="true" writable="false" />
|
||||
</resource>
|
||||
</resources>
|
||||
|
|
|
|||
|
|
@ -24,5 +24,9 @@
|
|||
<service id="sylius.api.product_review_state_machine_transition_applicator" class="Sylius\Bundle\ApiBundle\Applicator\ProductReviewStateMachineTransitionApplicator" public="true">
|
||||
<argument id="sm.factory" type="service" />
|
||||
</service>
|
||||
|
||||
<service id="sylius.api.shipment_machine_transition_applicator" class="Sylius\Bundle\ApiBundle\Applicator\ShipmentStateMachineTransitionApplicator" public="true">
|
||||
<argument id="sm.factory" type="service" />
|
||||
</service>
|
||||
</services>
|
||||
</container>
|
||||
|
|
|
|||
|
|
@ -17,6 +17,14 @@
|
|||
<tag name="api_platform.filter" />
|
||||
</service>
|
||||
|
||||
<service id="sylius.api.search_shipment_filter" parent="api_platform.doctrine.orm.search_filter">
|
||||
<argument type="collection">
|
||||
<argument key="state">exact</argument>
|
||||
<argument key="order.channel.code">exact</argument>
|
||||
</argument>
|
||||
<tag name="api_platform.filter" />
|
||||
</service>
|
||||
|
||||
<service id="sylius.api.exchange_rate_filter" class="Sylius\Bundle\ApiBundle\Filters\ExchangeRateFilter">
|
||||
<argument type="service" id="doctrine" />
|
||||
<tag name="api_platform.filter" />
|
||||
|
|
|
|||
|
|
@ -0,0 +1,39 @@
|
|||
<?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 spec\Sylius\Bundle\ApiBundle\Applicator;
|
||||
|
||||
use PhpSpec\ObjectBehavior;
|
||||
use SM\Factory\FactoryInterface as StateMachineFactoryInterface;
|
||||
use SM\StateMachine\StateMachine;
|
||||
use Sylius\Component\Core\Model\ShipmentInterface;
|
||||
use Sylius\Component\Shipping\ShipmentTransitions;
|
||||
|
||||
final class ShipmentStateMachineTransitionApplicatorSpec extends ObjectBehavior
|
||||
{
|
||||
function let(StateMachineFactoryInterface $stateMachineFactory)
|
||||
{
|
||||
$this->beConstructedWith($stateMachineFactory);
|
||||
}
|
||||
|
||||
function it_ships_shipment(
|
||||
StateMachineFactoryInterface $stateMachineFactory,
|
||||
ShipmentInterface $shipment,
|
||||
StateMachine $stateMachine
|
||||
): void {
|
||||
$stateMachineFactory->get($shipment, ShipmentTransitions::GRAPH)->willReturn($stateMachine);
|
||||
$stateMachine->apply(ShipmentTransitions::TRANSITION_SHIP)->shouldBeCalled();
|
||||
|
||||
$this->ship($shipment);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue