diff --git a/doc/installation.md b/doc/installation.md index 3ed4773..b250deb 100644 --- a/doc/installation.md +++ b/doc/installation.md @@ -43,6 +43,108 @@ bitbag_shipping_export_plugin.yaml to the config/packages and config/routes dire It also adding the appropriate entry to config/bundles.php. If it doesn't, so please remember to do the same as above for SyliusShippingExportPlugin configuration. +### Create a new controller: +```php +// src/Controller/ShippingExportController + +requestConfigurationFactory->create($this->metadata, $request); + + Assert::implementsInterface($this->repository, ShippingExportRepositoryInterface::class); + $shippingExports = $this->repository->findAllWithNewOrPendingState(); + + if (0 === count($shippingExports)) { + /** @var FlashBagInterface $flashBag */ + $flashBag = $request->getSession()->getBag('flashes'); + $flashBag->add('error', 'bitbag.ui.no_new_shipments_to_export'); + + return $this->redirectToReferer($request); + } + + foreach ($shippingExports as $shippingExport) { + $this->eventDispatcher->dispatch( + ExportShipmentEvent::SHORT_NAME, + $configuration, + $shippingExport, + ); + } + + return $this->redirectToReferer($request); + } + + public function exportSingleShipmentAction(Request $request): RedirectResponse + { + $configuration = $this->requestConfigurationFactory->create($this->metadata, $request); + + /** @var ResourceInterface|null $shippingExport */ + $shippingExport = $this->repository->find($request->get('id')); + Assert::notNull($shippingExport); + + $this->eventDispatcher->dispatch( + ExportShipmentEvent::SHORT_NAME, + $configuration, + $shippingExport, + ); + + return $this->redirectToReferer($request); + } + + private function redirectToReferer(Request $request): RedirectResponse + { + $referer = $request->headers->get('referer'); + if (null !== $referer) { + return new RedirectResponse($referer); + } + + return $this->redirectToRoute($request->attributes->get('_route')); + } +} +``` + +Complete the **config/packages/bitbag_shipping_export_plugin.yaml** file with the following data: + +```yaml +# config/packages/bitbag_shipping_export_plugin.yaml + +imports: + - { resource: "@BitBagSyliusShippingExportPlugin/Resources/config/config.yml" } + +sylius_resource: + resources: + bitbag.shipping_export: + classes: + model: App\Entity\Shipping\ShippingExport + controller: App\Controller\ShippingExportController +``` +Remember that in case of different mapping, the model path may be different. +Default: +```yaml + model: App\Entity\ShippingExport +``` + ### Extend entities with parameters You can implement this using xml-mapping or attributes. Instructions for both settings are described below. @@ -63,7 +165,6 @@ sylius_shipping: shipping_method: classes: model: App\Entity\ShippingMethod - ``` Add trait and interface to your Order and ShippingMethod entity classes: @@ -101,6 +202,22 @@ class ShippingMethod extends BaseShippingMethod implements ImageAwareInterface use ShippingMethodImageTrait; } ``` +```php + - @@ -156,6 +272,19 @@ Define new Entity mapping inside your src/Resources/config/doctrine directory. ``` +```xml + + + + + + + + +``` #### You can do it with attributes if you prefer. Remember to mark it appropriately in the config/doctrine.yaml configuration file. ``` doctrine: @@ -166,7 +295,6 @@ doctrine: App: ... type: attribute - ``` ```php point = $point; } } - ``` ```php @@ -239,9 +366,44 @@ class ShippingMethod extends BaseShippingMethod implements ImageAwareInterface { $this->image = $image; } + + // other methods } +``` +```php +parcel_template; + } + + public function setParcelTemplate(?string $parcel_template): void + { + $this->parcel_template = $parcel_template; + } +} ``` + Finish the installation by updating the database schema (check in advance: [Known Issues](known_issues.md)): ``` @@ -273,10 +435,7 @@ vendor/bitbag/inpost-plugin/tests/Application/templates/bundles/SyliusShopBundle webpack_encore: output_path: '%kernel.project_dir%/public/build/default' builds: - admin: '%kernel.project_dir%/public/build/admin' - shop: '%kernel.project_dir%/public/build/shop' - app.admin: '%kernel.project_dir%/public/build/app/admin' - app.shop: '%kernel.project_dir%/public/build/app/shop' + ... inpost_admin: '%kernel.project_dir%/public/build/bitbag/inpost/admin' inpost_shop: '%kernel.project_dir%/public/build/bitbag/inpost/shop' ``` @@ -317,14 +476,7 @@ By a standard, the `webpack.config.js` file should be available in your reposito framework: assets: packages: - admin: - json_manifest_path: '%kernel.project_dir%/public/build/admin/manifest.json' - shop: - json_manifest_path: '%kernel.project_dir%/public/build/shop/manifest.json' - app.admin: - json_manifest_path: '%kernel.project_dir%/public/build/app/admin/manifest.json' - app.shop: - json_manifest_path: '%kernel.project_dir%/public/build/app/shop/manifest.json' + ... inpost_shop: json_manifest_path: '%kernel.project_dir%/public/build/bitbag/inpost/shop/manifest.json' inpost_admin: @@ -340,6 +492,24 @@ By a standard, the `webpack.config.js` file should be available in your reposito ``` +## Default parameters configuration +In the .env file, the default parcel size and label type can be specified by adding: + +```` +BITBAG_INPOST_DEFAULT_PARCEL_TEMPLATE='medium' +BITBAG_INPOST_DEFAULT_LABEL_TYPE='normal' +```` + +Three types of parcel templates are allowed: +- 'small' +- 'medium' +- 'large' + +Two types of labels are allowed: +- 'normal' +- 'A6' + + ## Testing & running the plugin ```bash diff --git a/features/adding_image_to_shipping_method.feature b/features/adding_image_to_shipping_method.feature index 1ea5b4e..b97fd28 100644 --- a/features/adding_image_to_shipping_method.feature +++ b/features/adding_image_to_shipping_method.feature @@ -14,4 +14,4 @@ Feature: Adding shipping method image When I want to modify a shipping method "InPost" And I upload the "image/shipping_logo.jpg" image as shipping method logo And I save my changes - Then I should be notified that it has been successfully edited \ No newline at end of file + Then I should be notified that it has been successfully edited diff --git a/features/changing_shipping_method_parcel_template.feature b/features/changing_shipping_method_parcel_template.feature new file mode 100644 index 0000000..c7341f4 --- /dev/null +++ b/features/changing_shipping_method_parcel_template.feature @@ -0,0 +1,28 @@ +@managing_shipping_export_parcel_template_inpost +Feature: Changing shipping export parcel template + To send a query to the Inpost API with a different shipment template + As an Administrator + I need to be able to choose a parcel template + + Background: + Given the store operates on a single channel in the "United States" named "Web-US" + And I am logged in as an administrator + And the store has "Inpost" shipping method with "$10.00" fee + And there is a registered "inpost" shipping gateway for this shipping method named "INPOST_PL" + And it has "Access token" field set to "123" + And it has "Organization ID" field set to "123" + And it has "Environment" field set to "sandbox" + And it has "service" field set to "inpost_locker_standard" + And the store has a product "Chicken" priced at "$2.00" in "Web-US" channel + And customer "user@bitbag.pl" has placed 1 orders on the "Web-US" channel in each buying 5 "Chicken" products + And the customer set the shipping address "Mike Ross" addressed it to "350 5th Ave", "10118" "New York" in the "United States" to orders + And those orders were placed with "Inpost" shipping method + And set product weight to "10" + And set units to the shipment + + @ui + Scenario: Seeing shipments to export + When I go to the shipping export page + Then I should see 1 shipments with "New" state + Then I select parcel template + Then I should see that shipping export parcel template is set diff --git a/spec/Api/WebClientSpec.php b/spec/Api/WebClientSpec.php index e93737a..2a0cdd2 100644 --- a/spec/Api/WebClientSpec.php +++ b/spec/Api/WebClientSpec.php @@ -28,13 +28,15 @@ final class WebClientSpec extends ObjectBehavior public const LABEL_TYPE = "normal"; + public const PARCEL_TEMPLATE = "medium"; + public function let( ClientInterface $client, RequestFactoryInterface $requestFactory, StreamFactoryInterface $streamFactory, ): void { - $this->beConstructedWith($client, $requestFactory, $streamFactory, self::LABEL_TYPE); + $this->beConstructedWith($client, $requestFactory, $streamFactory, self::LABEL_TYPE, self::PARCEL_TEMPLATE); } public function it_is_initializable(): void diff --git a/spec/EventListener/SelectParcelTemplateEventListener/SelectParcelTemplateActionSpec.php b/spec/EventListener/SelectParcelTemplateEventListener/SelectParcelTemplateActionSpec.php new file mode 100644 index 0000000..0744837 --- /dev/null +++ b/spec/EventListener/SelectParcelTemplateEventListener/SelectParcelTemplateActionSpec.php @@ -0,0 +1,46 @@ +beConstructedWith($shippingExportRepository, $requestStack, $translator); + } + + public function it_is_initializable() + { + $this->shouldHaveType(SelectParcelTemplateAction::class); + $this->shouldBeAnInstanceOf(SelectParcelTemplateActionInterface::class); + } + + public function it_should_save_shipping_export_changes( + ShippingExportInterface $shippingExport, + ShippingExportRepositoryInterface $shippingExportRepository, + RequestStack $requestStack, + SessionInterface $session, + FlashBagInterface $flashBag + ): void { + $shippingExportRepository->add($shippingExport)->shouldBeCalled(); + + $requestStack->getSession()->willReturn($session); + $session->getBag('flashes')->willReturn($flashBag); + + $this->execute($shippingExport); + } + +} diff --git a/spec/EventListener/SelectParcelTemplateEventListenerSpec.php b/spec/EventListener/SelectParcelTemplateEventListenerSpec.php new file mode 100644 index 0000000..0de6466 --- /dev/null +++ b/spec/EventListener/SelectParcelTemplateEventListenerSpec.php @@ -0,0 +1,80 @@ +beConstructedWith($action); + } + + public function it_is_initializable(): void + { + $this->shouldHaveType(SelectParcelTemplateEventListener::class); + } + + public function it_should_throw_exception_if_subject_is_not_shipping_export_instance(ResourceControllerEvent $event): void + { + $event->getSubject()->willReturn(new \stdClass()); + + $this + ->shouldThrow(\InvalidArgumentException::class) + ->during('setParcelTemplate', [$event]) + ; + } + + public function it_should_throw_exception_if_incorrect_parcel_template_is_passed(ResourceControllerEvent $event): void + { + $shippingGateway = ShippingGatewayBuilder::create()->withCode(self::INPOST)->build(); + $shipment = ShipmentBuilder::create()->build(); + $shippingExport = ShippingExportBuilder::create() + ->withShippingGateway($shippingGateway) + ->withShipment($shipment) + ->withParcelTemplate(self::INCORRECT_PARCEL_TEMPLATE) + ->build(); + $event->getSubject()->willReturn($shippingExport); + + $this + ->shouldThrow(\Exception::class) + ->during('setParcelTemplate', [$event]) + ; + } + + public function it_should_perform_set_parcel_template_action(ResourceControllerEvent $event): void + { + $shippingGateway = ShippingGatewayBuilder::create()->withCode(self::INPOST)->build(); + $shippingGateway->setConfig(['service' => 'inpost_locker_standard']); + $shipment = ShipmentBuilder::create()->build(); + $shippingExport = ShippingExportBuilder::create() + ->withShippingGateway($shippingGateway) + ->withShipment($shipment) + ->withParcelTemplate(self::EXPECTED_PARCEL_TEMPLATE) + ->build(); + $event->getSubject()->willReturn($shippingExport); + $this->setParcelTemplate($event); + } +} diff --git a/spec/EventListener/ShippingExportEventListenerSpec.php b/spec/EventListener/ShippingExportEventListenerSpec.php index 6476d99..bfa7964 100644 --- a/spec/EventListener/ShippingExportEventListenerSpec.php +++ b/spec/EventListener/ShippingExportEventListenerSpec.php @@ -52,7 +52,8 @@ public function let( WebClientInterface $webClient, InPostShippingExportActionProviderInterface $shippingExportActionProvider, RequestStack $requestStack, - LoggerInterface $logger + LoggerInterface $logger, + ): void { $this->beConstructedWith($webClient, $shippingExportActionProvider, $requestStack, $logger); } @@ -128,7 +129,7 @@ public function it_should_handle_when_create_shipment_throws_exception( $event->getSubject()->willReturn($shippingExport); $webClient->setShippingGateway($shippingGateway); - $webClient->createShipment($shipment)->willThrow(InvalidInPostResponseException::class); + $webClient->createShipment($shipment, $shippingExport)->willThrow(InvalidInPostResponseException::class); $requestStack->getSession()->willReturn($session); $session->getBag('flashes')->willReturn($flashBag); $flashBag->add(self::ERROR, self::SHIPPING_EXPORT_ERROR_MESSAGE)->shouldBeCalled(); @@ -155,7 +156,7 @@ public function it_should_handle_when_get_shipment_by_id_throws_exception( $event->getSubject()->willReturn($shippingExport); $webClient->setShippingGateway($shippingGateway); - $webClient->createShipment($shipment)->willReturn(self::EXPECTED_CREATE_SHIPMENT_RESPONSE); + $webClient->createShipment($shipment, $shippingExport)->willReturn(self::EXPECTED_CREATE_SHIPMENT_RESPONSE); $webClient->getShipmentById(self::SHIPMENT_ID)->willThrow(InvalidInPostResponseException::class); $requestStack->getSession()->willReturn($session); $session->getBag('flashes')->willReturn($flashBag); @@ -184,7 +185,7 @@ public function it_should_handle_when_provide_shipment_action_throws_exception( $event->getSubject()->willReturn($shippingExport); $webClient->setShippingGateway($shippingGateway); - $webClient->createShipment($shipment)->willReturn(self::EXPECTED_CREATE_SHIPMENT_RESPONSE); + $webClient->createShipment($shipment, $shippingExport)->willReturn(self::EXPECTED_CREATE_SHIPMENT_RESPONSE); $webClient->getShipmentById(self::SHIPMENT_ID)->willReturn(self::EXPECTED_GET_SHIPMENT_RESPONSE); $shippingExportActionProvider->provide(Argument::type('string'))->willThrow(\Exception::class); $requestStack->getSession()->willReturn($session); @@ -210,7 +211,7 @@ public function it_should_execute_shipping_export_action( $event->getSubject()->willReturn($shippingExport); $webClient->setShippingGateway($shippingGateway); - $webClient->createShipment($shipment)->willReturn(self::EXPECTED_CREATE_SHIPMENT_RESPONSE); + $webClient->createShipment($shipment, $shippingExport)->willReturn(self::EXPECTED_CREATE_SHIPMENT_RESPONSE); $webClient->getShipmentById(self::SHIPMENT_ID)->willReturn(self::EXPECTED_GET_SHIPMENT_RESPONSE); $shippingExportActionProvider->provide(Argument::type('string'))->willReturn($shippingExportAction); $shippingExportAction->execute($shippingExport)->shouldBeCalled(); diff --git a/src/Api/WebClient.php b/src/Api/WebClient.php index 03d236e..e6e887b 100644 --- a/src/Api/WebClient.php +++ b/src/Api/WebClient.php @@ -12,6 +12,7 @@ namespace BitBag\SyliusInPostPlugin\Api; use BitBag\SyliusInPostPlugin\Entity\InPostPoint; +use BitBag\SyliusInPostPlugin\Entity\ShippingExportInterface; use BitBag\SyliusInPostPlugin\Exception\InvalidInPostResponseException; use BitBag\SyliusInPostPlugin\Model\InPostPointsAwareInterface; use BitBag\SyliusShippingExportPlugin\Entity\ShippingGatewayInterface; @@ -41,18 +42,22 @@ final class WebClient implements WebClientInterface private ShippingGatewayInterface $shippingGateway; - private string $labelType = 'normal'; + private string $labelType; + + private string $parcelTemplate; public function __construct( ClientInterface $client, RequestFactoryInterface $requestFactory, StreamFactoryInterface $streamFactory, string $labelType, + string $parcelTemplate, ) { $this->apiClient = $client; $this->requestFactory = $requestFactory; $this->streamFactory = $streamFactory; $this->labelType = $labelType; + $this->parcelTemplate = $parcelTemplate; } public function setShippingGateway(ShippingGatewayInterface $shippingGateway): WebClientInterface @@ -149,8 +154,10 @@ public function getShipments(): ?array return $this->request('GET', $url); } - public function createShipment(ShipmentInterface $shipment): array - { + public function createShipment( + ShipmentInterface $shipment, + ShippingExportInterface $shippingExport, + ): array { /** @var OrderInterface $order */ $order = $shipment->getOrder(); @@ -161,7 +168,7 @@ public function createShipment(ShipmentInterface $shipment): array 'external_customer_id' => $customer->getId(), 'receiver' => $this->createReceiverDetails($order), 'custom_attributes' => $this->createCustomAttributes($shipment), - 'parcels' => [$this->createParcel($shipment)], + 'parcels' => [$this->createParcel($shipment, $shippingExport)], 'service' => $this->getShippingGatewayConfig('service'), 'additional_services' => $this->getAdditionalServices(), 'reference' => 'Order: ' . $order->getNumber(), @@ -317,9 +324,12 @@ private function isCashOnDelivery(OrderInterface $order): bool return false; } - private function createParcel(ShipmentInterface $shipment): array - { + private function createParcel( + ShipmentInterface $shipment, + ShippingExportInterface $shippingExport, + ): array { $weight = $shipment->getShippingWeight(); + $template = $shippingExport->getParcelTemplate(); return [ 'id' => $shipment->getId(), @@ -328,7 +338,7 @@ private function createParcel(ShipmentInterface $shipment): array 'unit' => 'kg', ], 'dimensions' => [], - 'template' => 'large', + 'template' => $template ?? $this->parcelTemplate, 'tracking_number' => null, 'is_non_standard' => false, ]; diff --git a/src/Api/WebClientInterface.php b/src/Api/WebClientInterface.php index 49cc2ce..69b89b8 100644 --- a/src/Api/WebClientInterface.php +++ b/src/Api/WebClientInterface.php @@ -11,6 +11,7 @@ namespace BitBag\SyliusInPostPlugin\Api; +use BitBag\SyliusInPostPlugin\Entity\ShippingExportInterface; use BitBag\SyliusShippingExportPlugin\Entity\ShippingGatewayInterface; use Sylius\Component\Core\Model\ShipmentInterface; @@ -78,7 +79,7 @@ public function getLabels(array $shipmentIds): ?string; public function getAuthorizedHeaderWithContentType(): array; - public function createShipment(ShipmentInterface $shipment): array; + public function createShipment(ShipmentInterface $shipment, ShippingExportInterface $shippingExport): array; public function request( string $method, diff --git a/src/Controller/SelectParcelTemplateTrait.php b/src/Controller/SelectParcelTemplateTrait.php new file mode 100644 index 0000000..7e6d385 --- /dev/null +++ b/src/Controller/SelectParcelTemplateTrait.php @@ -0,0 +1,38 @@ +requestConfigurationFactory->create($this->metadata, $request); + + /** @var ResourceInterface|null $shippingExport */ + $shippingExport = $this->repository->find($request->get('id')); + Assert::notNull($shippingExport); + $shippingExport->setParcelTemplate($request->get('template')); + + $this->eventDispatcher->dispatch( + self::SELECT_PARCEL_TEMPLATE_EVENT, + $configuration, + $shippingExport, + ); + + return $this->redirectToReferer($request); + } +} diff --git a/src/Entity/ShippingExportInterface.php b/src/Entity/ShippingExportInterface.php new file mode 100644 index 0000000..0c8a032 --- /dev/null +++ b/src/Entity/ShippingExportInterface.php @@ -0,0 +1,21 @@ +action = $action; + } + + public function setParcelTemplate(ResourceControllerEvent $exportShipmentEvent): void + { + /** @var ?ShippingExportInterface $shippingExport */ + $shippingExport = $exportShipmentEvent->getSubject(); + Assert::isInstanceOf($shippingExport, ShippingExportInterface::class); + + $service = $shippingExport->getShippingGateway()->getConfig()['service']; + $parcelTemplate = $shippingExport->getParcelTemplate(); + + if (in_array($service, [self::INPOST_LOCKER_STANDARD, self::INPOST_LOCKER_PASS_THRU])) { + $validTemplates = self::INPOST_LOCKER_PARCEL_TEMPLATES; + } else { + $validTemplates = self::INPOST_COURIER_PARCEL_TEMPLATES; + } + + if (!in_array($parcelTemplate, $validTemplates, true)) { + throw new \Exception(sprintf(self::ERROR_INVALID_PARCEL_TEMPLATE, $parcelTemplate)); + } + + $this->action->execute($shippingExport); + } +} diff --git a/src/EventListener/SelectParcelTemplateEventListener/SelectParcelTemplateAction.php b/src/EventListener/SelectParcelTemplateEventListener/SelectParcelTemplateAction.php new file mode 100644 index 0000000..bd903dc --- /dev/null +++ b/src/EventListener/SelectParcelTemplateEventListener/SelectParcelTemplateAction.php @@ -0,0 +1,47 @@ +shippingExportRepository = $shippingExportRepository; + $this->requestStack = $requestStack; + $this->translator = $translator; + } + + public function execute(ShippingExportInterface $shippingExport): void + { + $message = $this->translator->trans(self::TRANSLATION_KEY); + $this->shippingExportRepository->add($shippingExport); + $this->requestStack->getSession()->getBag('flashes')->add(self::INFO, $message); + } +} diff --git a/src/EventListener/SelectParcelTemplateEventListener/SelectParcelTemplateActionInterface.php b/src/EventListener/SelectParcelTemplateEventListener/SelectParcelTemplateActionInterface.php new file mode 100644 index 0000000..3ed308e --- /dev/null +++ b/src/EventListener/SelectParcelTemplateEventListener/SelectParcelTemplateActionInterface.php @@ -0,0 +1,19 @@ +getExternalId()) { try { - $createShipmentResponse = $this->webClient->createShipment($shipment); + $createShipmentResponse = $this->webClient->createShipment($shipment, $shippingExport); } catch (InPostException $exception) { $this->requestStack->getSession()->getBag('flashes')->add('error', 'bitbag.ui.shipping_export_error'); $this->logError($exception, $shipment); diff --git a/src/Model/ParcelTemplateTrait.php b/src/Model/ParcelTemplateTrait.php new file mode 100644 index 0000000..dd4b900 --- /dev/null +++ b/src/Model/ParcelTemplateTrait.php @@ -0,0 +1,27 @@ +parcel_template; + } + + public function setParcelTemplate(?string $parcel_template): void + { + $this->parcel_template = $parcel_template; + } +} diff --git a/src/Resources/config/config.yml b/src/Resources/config/config.yml index 141e502..b02e731 100644 --- a/src/Resources/config/config.yml +++ b/src/Resources/config/config.yml @@ -1,10 +1,17 @@ parameters: - bitbag.inpost.label_type: 'normal' + bitbag.inpost.label_type: '%env(BITBAG_INPOST_DEFAULT_LABEL_TYPE)%' + bitbag.inpost.parcel_template: '%env(BITBAG_INPOST_DEFAULT_PARCEL_TEMPLATE)%' + env(BITBAG_INPOST_DEFAULT_LABEL_TYPE): 'normal' + env(BITBAG_INPOST_DEFAULT_PARCEL_TEMPLATE): 'large' + imports: - { resource: "@BitBagSyliusInPostPlugin/Resources/config/services.xml" } - { resource: "@BitBagSyliusInPostPlugin/Resources/config/resource/bitbag_inpost.yml" } - { resource: "@BitBagSyliusInPostPlugin/Resources/config/sylius_ui.yml" } - { resource: "@BitBagSyliusInPostPlugin/Resources/config/grid/*" } + twig: globals: inpost_client: '@bitbag.sylius_inpost_plugin.api.web_client' + bitbag_inpost_parcel_template: '%env(BITBAG_INPOST_DEFAULT_PARCEL_TEMPLATE)%' + diff --git a/src/Resources/config/grid/order.yml b/src/Resources/config/grid/order.yml index b0aa5c2..a15ae67 100644 --- a/src/Resources/config/grid/order.yml +++ b/src/Resources/config/grid/order.yml @@ -2,33 +2,85 @@ # (c) Paweł Jędrzejewski sylius_grid: - templates: - action: - shop_quick_return: "@SyliusShop/Grid/Action/quickReturn.html.twig" - grids: - sylius_shop_account_order: - actions: - item: - quick_return: - type: shop_quick_return - label: bitbag_sylius_inpost_plugin.ui.quick_return - options: - link: - route: sylius_shop_account_order_return - - show: - type: shop_show - label: sylius.ui.show - options: - link: - route: sylius_shop_account_order_show - parameters: - number: resource.number - pay: - type: shop_pay - label: sylius.ui.pay - options: - link: - route: sylius_shop_order_show - parameters: - tokenValue: resource.tokenValue + templates: + action: + shop_quick_return: "@SyliusShop/Grid/Action/quickReturn.html.twig" + grids: + sylius_shop_account_order: + actions: + item: + quick_return: + type: shop_quick_return + label: bitbag_sylius_inpost_plugin.ui.quick_return + options: + link: + route: sylius_shop_account_order_return + + show: + type: shop_show + label: sylius.ui.show + options: + link: + route: sylius_shop_account_order_show + parameters: + number: resource.number + pay: + type: shop_pay + label: sylius.ui.pay + options: + link: + route: sylius_shop_order_show + parameters: + tokenValue: resource.tokenValue + + bitbag_admin_shipping_export: + fields: + order: + type: twig + label: sylius.ui.order + path: . + sortable: shipment.order + options: + template: "@BitBagSyliusShippingExportPlugin/ShippingExport/Grid/Field/orderNumber.html.twig" + shipment: + type: datetime + label: sylius.ui.created_at + path: shipment.createdAt + sortable: shipment.createdAt + options: + format: 'd-m-Y H:i:s' + exportedAt: + type: twig + label: bitbag.ui.exported_at + path: . + sortable: ~ + options: + template: "@BitBagSyliusShippingExportPlugin/ShippingExport/Grid/Field/exportedAt.html.twig" + shippingMethod: + type: twig + label: sylius.ui.shipping_method + path: . + sortable: shipment.method + options: + template: "@BitBagSyliusShippingExportPlugin/ShippingExport/Grid/Field/shippingMethod.html.twig" + labelPath: + type: twig + label: bitbag.ui.shipping_export_label + path: . + sortable: ~ + options: + template: "@BitBagSyliusShippingExportPlugin/ShippingExport/Grid/Field/shippingExportLabel.html.twig" + parcel_template: + type: twig + label: bitbag_sylius_inpost_plugin.ui.parcel_template.label + path: . + sortable: ~ + options: + template: "@BitBagSyliusInPostPlugin/ShippingExport/Grid/Field/parcel_template.html.twig" + state: + type: twig + label: sylius.ui.state + path: . + sortable: ~ + options: + template: "@BitBagSyliusShippingExportPlugin/ShippingExport/Grid/Field/state.html.twig" diff --git a/src/Resources/config/routes.yml b/src/Resources/config/routes.yml index 9947e5e..97b1517 100644 --- a/src/Resources/config/routes.yml +++ b/src/Resources/config/routes.yml @@ -8,3 +8,9 @@ bitbag_sylius_inpost_plugin_admin_add_point_to_order: methods: [POST] defaults: _controller: bitbag.sylius_inpost_plugin.controller.add_point_to_order::addPointToOrderAction + +bitbag_admin_shipping_export_select_parcel_template: + path: /admin/shipping_export/select_parcel_template/{id}/{template} + methods: [POST, PUT] + defaults: + _controller: bitbag.controller.shipping_export::selectParcelTemplate diff --git a/src/Resources/config/services.xml b/src/Resources/config/services.xml index 3faab35..b06d055 100644 --- a/src/Resources/config/services.xml +++ b/src/Resources/config/services.xml @@ -27,6 +27,13 @@ + + + + %bitbag.inpost.label_type% + %bitbag.inpost.parcel_template% + + + + + + + + + + + + diff --git a/src/Resources/translations/messages.en.yml b/src/Resources/translations/messages.en.yml index 30f1d0c..9c21f56 100644 --- a/src/Resources/translations/messages.en.yml +++ b/src/Resources/translations/messages.en.yml @@ -17,6 +17,13 @@ bitbag_sylius_inpost_plugin: not_blank: This field cannot be blank is_quick_return: Quick Return quick_return: Quick Return + parcel_template: + label: Parcel template + select_template: Select template + template_a: Template A (8 x 38 x 64 cm) + template_b: Template B (19 x 38 x 64 cm) + template_c: Template C (41 x 38 x 64 cm) + select_action_performed: Parcel template has been changed main_service: inpost_locker_standard: Inpost Locker Standard inpost_locker_pass_thru: Inpost Locker Pass Thru diff --git a/src/Resources/views/ShippingExport/Grid/Field/ParcelTemplate/_inpost_template.html.twig b/src/Resources/views/ShippingExport/Grid/Field/ParcelTemplate/_inpost_template.html.twig new file mode 100644 index 0000000..be535f4 --- /dev/null +++ b/src/Resources/views/ShippingExport/Grid/Field/ParcelTemplate/_inpost_template.html.twig @@ -0,0 +1,31 @@ +{% set parcelTemplate = data.getParcelTemplate %} +{% if parcelTemplate is null %} + {% set parcelTemplate = bitbag_inpost_parcel_template %} +{% endif %} + +{% set templates = {} %} +{% if data.getShippingGateway.getConfig.service == 'inpost_locker_standard' %} + {% set templates = {'small': 'A', 'medium': 'B', 'large': 'C'} %} +{% else %} + {% set templates = {'small': 'A', 'medium': 'B', 'large': 'C', 'xlarge': 'D'} %} +{% endif %} + +
+ {% for key, label in templates %} + {% if parcelTemplate == key %} + + {% else %} + {% if data.getExportedAt != null %} + + {% else %} +
+ + +
+ {% endif %} + {% endif %} + {% endfor %} +
diff --git a/src/Resources/views/ShippingExport/Grid/Field/parcel_template.html.twig b/src/Resources/views/ShippingExport/Grid/Field/parcel_template.html.twig new file mode 100644 index 0000000..56bb6a0 --- /dev/null +++ b/src/Resources/views/ShippingExport/Grid/Field/parcel_template.html.twig @@ -0,0 +1,5 @@ +{% if data.getShippingGateway.getName == 'INPOST_PL' %} + {% include '@BitBagSyliusInPostPlugin/ShippingExport/Grid/Field/ParcelTemplate/_inpost_template.html.twig' %} +{% else %} + +{% endif %} diff --git a/tests/Application/.env b/tests/Application/.env index f4d17a6..83583c2 100644 --- a/tests/Application/.env +++ b/tests/Application/.env @@ -15,6 +15,9 @@ APP_SECRET=EDITME DATABASE_URL=mysql://root@127.0.0.1/bitbag_sylius_inpost_plugin_%kernel.environment% ###< doctrine/doctrine-bundle ### +BITBAG_INPOST_DEFAULT_LABEL_TYPE='normal' +BITBAG_INPOST_DEFAULT_PARCEL_TEMPLATE='medium' + ###> lexik/jwt-authentication-bundle ### JWT_SECRET_KEY=%kernel.project_dir%/config/jwt/private.pem JWT_PUBLIC_KEY=%kernel.project_dir%/config/jwt/public.pem diff --git a/tests/Application/config/packages/bitbag_sylius_shipping_export_plugin.yaml b/tests/Application/config/packages/bitbag_sylius_shipping_export_plugin.yaml index 15c0929..5944ca5 100644 --- a/tests/Application/config/packages/bitbag_sylius_shipping_export_plugin.yaml +++ b/tests/Application/config/packages/bitbag_sylius_shipping_export_plugin.yaml @@ -1,2 +1,9 @@ imports: - - { resource: "@BitBagSyliusShippingExportPlugin/Resources/config/config.yml" } \ No newline at end of file + - { resource: "@BitBagSyliusShippingExportPlugin/Resources/config/config.yml" } + +sylius_resource: + resources: + bitbag.shipping_export: + classes: + model: Tests\BitBag\SyliusInPostPlugin\Application\src\Entity\ShippingExport + controller: Tests\BitBag\SyliusInPostPlugin\Application\src\Controller\ShippingExportController diff --git a/tests/Application/src/Controller/ShippingExportController.php b/tests/Application/src/Controller/ShippingExportController.php new file mode 100644 index 0000000..ffe644b --- /dev/null +++ b/tests/Application/src/Controller/ShippingExportController.php @@ -0,0 +1,82 @@ +requestConfigurationFactory->create($this->metadata, $request); + + Assert::implementsInterface($this->repository, ShippingExportRepositoryInterface::class); + $shippingExports = $this->repository->findAllWithNewOrPendingState(); + + if (0 === count($shippingExports)) { + /** @var FlashBagInterface $flashBag */ + $flashBag = $request->getSession()->getBag('flashes'); + $flashBag->add('error', 'bitbag.ui.no_new_shipments_to_export'); + + return $this->redirectToReferer($request); + } + + foreach ($shippingExports as $shippingExport) { + $this->eventDispatcher->dispatch( + ExportShipmentEvent::SHORT_NAME, + $configuration, + $shippingExport, + ); + } + + return $this->redirectToReferer($request); + } + + public function exportSingleShipmentAction(Request $request): RedirectResponse + { + $configuration = $this->requestConfigurationFactory->create($this->metadata, $request); + + /** @var ResourceInterface|null $shippingExport */ + $shippingExport = $this->repository->find($request->get('id')); + Assert::notNull($shippingExport); + + $this->eventDispatcher->dispatch( + ExportShipmentEvent::SHORT_NAME, + $configuration, + $shippingExport, + ); + + return $this->redirectToReferer($request); + } + + private function redirectToReferer(Request $request): RedirectResponse + { + $referer = $request->headers->get('referer'); + if (null !== $referer) { + return new RedirectResponse($referer); + } + + return $this->redirectToRoute($request->attributes->get('_route')); + } +} diff --git a/tests/Application/src/Entity/ShippingExport.php b/tests/Application/src/Entity/ShippingExport.php new file mode 100644 index 0000000..d039367 --- /dev/null +++ b/tests/Application/src/Entity/ShippingExport.php @@ -0,0 +1,21 @@ + - + diff --git a/tests/Application/src/Resources/config/doctrine/ShippingExport.orm.xml b/tests/Application/src/Resources/config/doctrine/ShippingExport.orm.xml new file mode 100644 index 0000000..041d614 --- /dev/null +++ b/tests/Application/src/Resources/config/doctrine/ShippingExport.orm.xml @@ -0,0 +1,9 @@ + + + + + diff --git a/tests/Behat/Context/Ui/Admin/ShippingExportContext.php b/tests/Behat/Context/Ui/Admin/ShippingExportContext.php index 0b0e852..a20f6f1 100644 --- a/tests/Behat/Context/Ui/Admin/ShippingExportContext.php +++ b/tests/Behat/Context/Ui/Admin/ShippingExportContext.php @@ -13,7 +13,7 @@ use Behat\Behat\Context\Context; use Tests\BitBag\SyliusInPostPlugin\Behat\Mocker\InPostApiMocker; -use Tests\BitBag\SyliusShippingExportPlugin\Behat\Page\Admin\ShippingExport\IndexPageInterface; +use Tests\BitBag\SyliusInPostPlugin\Behat\Page\Admin\ShippingExport\IndexPageInterface; final class ShippingExportContext implements Context { @@ -48,4 +48,20 @@ public function iExportFirsShipments(): void $this->indexPage->exportFirsShipment(); }); } + + /** + * @When I select parcel template + */ + public function iSelectParcelTemplate(): void + { + $this->indexPage->selectParcelTemplate(); + } + + /** + * @Then I should see that shipping export parcel template is set + */ + public function iCheckParcelTemplate(): void + { + $this->indexPage->checkParcelTemplate(); + } } diff --git a/tests/Behat/Page/Admin/ShippingExport/IndexPage.php b/tests/Behat/Page/Admin/ShippingExport/IndexPage.php new file mode 100644 index 0000000..59a0e72 --- /dev/null +++ b/tests/Behat/Page/Admin/ShippingExport/IndexPage.php @@ -0,0 +1,56 @@ +getDocument()->findAll('css', '.shipping-export-state'); + $result = []; + + /** @var ElementInterface $item */ + foreach ($items as $item) { + if ($item->getText() === $state) { + $result[] = $item; + } + } + + return $result; + } + + public function exportAllShipments(): void + { + $this->getDocument()->pressButton('Export all new shipments'); + } + + public function exportFirsShipment(): void + { + $this->getDocument()->find('css', '.shipping-export-state')->click(); + } + + public function selectParcelTemplate(): void + { + $this->getDocument()->find('css', '.shipping-export-select-template')->click(); + } + + public function checkParcelTemplate(): void + { + $button = $this->getDocument()->find('xpath', '//button[@data-shipping-export-selected-template]'); + if (null === $button) { + throw new \Exception('Parcel template is not selected.'); + } + } +} diff --git a/tests/Behat/Page/Admin/ShippingExport/IndexPageInterface.php b/tests/Behat/Page/Admin/ShippingExport/IndexPageInterface.php new file mode 100644 index 0000000..0273f59 --- /dev/null +++ b/tests/Behat/Page/Admin/ShippingExport/IndexPageInterface.php @@ -0,0 +1,19 @@ +shippingExport->setParcelTemplate($template); + + return $this; + } + public function build(): ShippingExportInterface { return $this->shippingExport;