diff --git a/README.md b/README.md index 58beec7b..9990a2f5 100644 --- a/README.md +++ b/README.md @@ -89,6 +89,16 @@ bin/console sylius:theme:assets:install ``` +6. _Optional_. If you want you can also add the Schedule Akeneo PIM import button in the product's detail and edit page. +Override Sylius template by create a new file in the folder: `templates/bundles/SyliusAdminBundle/Product/_showInShopButton.html.twig`. Copy the content from the original Sylius file and paste it in the new file. Finally, add the button to the bottom of the file. + + # ... + + + + {{ 'webgriffe_sylius_akeneo.ui.enqueue'|trans }} + + ## Configuration First of all you must configure your Akeneo API connection parameters. Edit the `config/packages/webgriffe_sylius_akeneo_plugin.yaml` file by adding the following content: @@ -356,6 +366,12 @@ This plugin will also import product associations. It's a zero configuration imp To actually import data you must first create queue items with the **enqueue command** and then you can import them with the **consume command**. +#### Schedule Akeneo PIM import button + +This button allows you to queue a product directly from the admin index page. By adding the product to the queue, it will be updated by the Akeneo PIM at the next consume run. + +![Schedule Akeneo PIM import button](schedule-akeneo-import-button.png) + #### Enqueue command To create queue items you can use the `webgriffe:akeneo:enqueue` console command: diff --git a/features/enqueuing_products.feature b/features/enqueuing_products.feature index 51d94044..c7770d3e 100644 --- a/features/enqueuing_products.feature +++ b/features/enqueuing_products.feature @@ -32,3 +32,24 @@ Feature: Enqueuing products Then the queue item with identifier "product-1" for the "Product" importer should not be in the Akeneo queue And the queue item with identifier "product-2" for the "Product" importer should be in the Akeneo queue And there is a file with name "last-date" that contains "2020-01-25T12:00:00+01:00" + + @ui + Scenario: Enqueue a product + Given I am logged in as an administrator + And the store has a product "Braided hat m" with code "braided-hat-m" + When I browse products + And I schedule an Akeneo PIM import for the "braided-hat-m" product + Then I should be notified that it has been successfully enqueued + When I browse Akeneo queue items + Then I should see 1, not imported, queue items in the list + + @ui + Scenario: Enqueue a product already enqueued + Given I am logged in as an administrator + And the store has a product "Braided hat l" with code "braided-hat-l" + And there is one item to import with identifier "braided-hat-l" for the "Product" importer in the Akeneo queue + When I browse products + And I schedule an Akeneo PIM import for the "braided-hat-l" product + Then I should be notified that it has been already enqueued + When I browse Akeneo queue items + Then I should see 1, not imported, queue items in the list diff --git a/schedule-akeneo-import-button.png b/schedule-akeneo-import-button.png new file mode 100644 index 00000000..ff8e8979 Binary files /dev/null and b/schedule-akeneo-import-button.png differ diff --git a/src/Controller/ProductEnqueueController.php b/src/Controller/ProductEnqueueController.php new file mode 100644 index 00000000..6caa9c77 --- /dev/null +++ b/src/Controller/ProductEnqueueController.php @@ -0,0 +1,82 @@ +queueItemRepository = $queueItemRepository; + $this->urlGenerator = $urlGenerator; + $this->productRepository = $productRepository; + } + + public function enqueueAction(int $productId): Response + { + /** @var TranslatorInterface $translator */ + $translator = $this->get('translator'); + /** @var ProductInterface|null $product */ + $product = $this->productRepository->find($productId); + if ($product === null) { + throw new NotFoundHttpException('Product not found'); + } + + /** @var array $productEnqueued */ + $productEnqueued = $this->queueItemRepository->findBy([ + 'akeneoIdentifier' => $product->getCode(), + 'akeneoEntity' => 'Product', + 'importedAt' => null, + ]); + if (count($productEnqueued) > 0) { + $this->addFlash( + 'error', + $translator->trans('webgriffe_sylius_akeneo.ui.product_already_enqueued') + ); + + return $this->redirectToRoute('sylius_admin_product_index'); + } + + /** @var ?string $productCode */ + $productCode = $product->getCode(); + + Assert::notNull($productCode); + + $queueItem = new QueueItem(); + $queueItem->setAkeneoEntity('Product'); + $queueItem->setAkeneoIdentifier($productCode); + $queueItem->setCreatedAt(new \DateTime()); + $this->queueItemRepository->add($queueItem); + + $this->addFlash( + 'success', + $translator->trans('webgriffe_sylius_akeneo.ui.enqueued_success') + ); + + return $this->redirectToRoute('sylius_admin_product_index'); + } +} diff --git a/src/Resources/config/admin_routing.yaml b/src/Resources/config/admin_routing.yaml index 7b71fafa..1334e6ee 100644 --- a/src/Resources/config/admin_routing.yaml +++ b/src/Resources/config/admin_routing.yaml @@ -13,3 +13,7 @@ webgriffe_sylius_akeneo_admin_queue_item: index: icon: 'cloud download' type: sylius.resource + +webgriffe_sylius_akeneo_product_enqueue: + controller: webgriffe_sylius_akeneo_plugin.controller.product_enqueue_controller:enqueueAction + path: product/{productId}/enqueue diff --git a/src/Resources/config/config.yaml b/src/Resources/config/config.yaml index 4478b488..5d946c84 100644 --- a/src/Resources/config/config.yaml +++ b/src/Resources/config/config.yaml @@ -6,6 +6,9 @@ sylius_resource: repository: Webgriffe\SyliusAkeneoPlugin\Doctrine\ORM\QueueItemRepository sylius_grid: + templates: + action: + enqueueProduct: '@WebgriffeSyliusAkeneoPlugin\Product\Grid\Action\enqueue.html.twig' grids: webgriffe_sylius_akeneo_admin_queue_item: driver: @@ -54,3 +57,18 @@ sylius_grid: actions: main: ~ item: ~ + + sylius_admin_product: + actions: + item: + enqueue: + type: enqueueProduct + label: webgriffe_sylius_akeneo.ui.enqueue + options: + link: + route: webgriffe_sylius_akeneo_product_enqueue + parameters: + productId: resource.id + icon: cloud download + color: violet + diff --git a/src/Resources/config/services.xml b/src/Resources/config/services.xml index 6f70834d..9b5d2153 100644 --- a/src/Resources/config/services.xml +++ b/src/Resources/config/services.xml @@ -63,6 +63,13 @@ + + + + + + + diff --git a/src/Resources/translations/messages.en.yaml b/src/Resources/translations/messages.en.yaml index 7b77e3f4..fd429551 100644 --- a/src/Resources/translations/messages.en.yaml +++ b/src/Resources/translations/messages.en.yaml @@ -8,3 +8,8 @@ webgriffe_sylius_akeneo: imported_yes: Yes, at %date% imported_no: No error_message: Error message + enqueue: Schedule Akeneo PIM import + enqueued_success: Akeneo PIM product import has been successfully scheduled + product_not_exist: Product not found + product_already_enqueued: Akeneo PIM import for this product has been already scheduled before + product_without_code: Product does not have code diff --git a/src/Resources/translations/messages.it.yaml b/src/Resources/translations/messages.it.yaml index 00f66963..ff82b24f 100644 --- a/src/Resources/translations/messages.it.yaml +++ b/src/Resources/translations/messages.it.yaml @@ -8,3 +8,8 @@ webgriffe_sylius_akeneo: imported_yes: Si, il %date% imported_no: No error_message: Messaggio d'errore + enqueue: Programma importazione da Akeneo PIM + enqueued_success: L'importazione del prodotto da Akeneo PIM è stata correttamente programmata + product_not_exist: Prodotto non trovato + product_already_enqueued: L'importazione del prodotto da Akeneo PIM è già stata programmata precedentemente + product_without_code: Prodotto senza codice diff --git a/src/Resources/views/Product/Grid/Action/enqueue.html.twig b/src/Resources/views/Product/Grid/Action/enqueue.html.twig new file mode 100644 index 00000000..cfefd091 --- /dev/null +++ b/src/Resources/views/Product/Grid/Action/enqueue.html.twig @@ -0,0 +1,5 @@ +{% import '@SyliusUi/Macro/buttons.html.twig' as buttons %} + +{% set path = options.link.url|default(path(options.link.route, options.link.parameters)) %} + +{{ buttons.default(path, action.label, null, options.icon, options.color) }} diff --git a/tests/Application/templates/bundles/SyliusAdminBundle/Product/_showInShopButton.html.twig b/tests/Application/templates/bundles/SyliusAdminBundle/Product/_showInShopButton.html.twig new file mode 100644 index 00000000..491033e8 --- /dev/null +++ b/tests/Application/templates/bundles/SyliusAdminBundle/Product/_showInShopButton.html.twig @@ -0,0 +1,42 @@ +{% set enabledChannels = product.channels|filter(channel => channel.enabled == true) %} + +{% if sylius_bundle_loaded_checker('SyliusShopBundle') %} + {% if not product.enabled or enabledChannels|length < 1 %} + + + {{ 'sylius.ui.show_product_in_shop_page'|trans }} + + {% elseif enabledChannels|length > 1 %} + + {% else %} + {% for channel in enabledChannels %} + {% set url = channel.hostname is not null ? 'http://' ~ channel.hostname ~ path('sylius_shop_product_show', {'slug': product.slug, '_locale': channel.defaultLocale.code}) : url('sylius_shop_product_show', {'slug': product.slug, '_locale': channel.defaultLocale.code}) %} + + + {{ 'sylius.ui.show_product_in_shop_page'|trans }} + + {% endfor %} + {% endif %} +{% endif %} + + + + {{ 'webgriffe_sylius_akeneo.ui.enqueue'|trans }} + diff --git a/tests/Behat/Context/Ui/Admin/ManagingProductsContext.php b/tests/Behat/Context/Ui/Admin/ManagingProductsContext.php new file mode 100644 index 00000000..8dd45d2b --- /dev/null +++ b/tests/Behat/Context/Ui/Admin/ManagingProductsContext.php @@ -0,0 +1,67 @@ +indexPage = $indexPage; + $this->testHelper = $testHelper; + $this->notificationChecker = $notificationChecker; + } + + /** + * @When /^I schedule an Akeneo PIM import for the "([^"]*)" product$/ + */ + public function scheduleAnAkeneoPimImportForTheProduct($code) + { + /** @var NodeElement $actionsNodeProduct */ + $actionsNodeProduct = $this->indexPage->getActionsForResource(['code' => $code]); + + $actionsNodeProduct->clickLink(self::SCHEDULE_AKENEO_PIM_IMPORT); + } + + /** + * @Then I should be notified that it has been successfully enqueued + */ + public function iShouldBeNotifiedThatItHasBeenSuccessfullyEnqueued() + { + $this->testHelper->waitUntilNotificationPopups( + $this->notificationChecker, NotificationType::success(), 'Akeneo PIM product import has been successfully scheduled' + ); + } + + /** + * @Given /^I should be notified that it has been already enqueued$/ + */ + public function iShouldBeNotifiedThatItHasBeenAlreadyEnqueued() + { + $this->testHelper->waitUntilNotificationPopups( + $this->notificationChecker, NotificationType::success(), 'Akeneo PIM import for this product has been already scheduled before' + ); + } +} diff --git a/tests/Behat/Resources/services.xml b/tests/Behat/Resources/services.xml index 02a9643a..d28599ed 100644 --- a/tests/Behat/Resources/services.xml +++ b/tests/Behat/Resources/services.xml @@ -53,6 +53,12 @@ + + + + + + webgriffe_sylius_akeneo_admin_queue_item_index diff --git a/tests/Behat/Resources/suites.yml b/tests/Behat/Resources/suites.yml index 589cc564..5c78a00c 100644 --- a/tests/Behat/Resources/suites.yml +++ b/tests/Behat/Resources/suites.yml @@ -73,6 +73,20 @@ default: filters: tags: "@enqueuing_products && @cli" + ui_enqueuing_products: + contexts: + - sylius.behat.context.hook.doctrine_orm + + - sylius.behat.context.setup.admin_security + - sylius.behat.context.setup.product + - webgriffe_sylius_akeneo.behat.context.setup.queue + + - sylius.behat.context.ui.admin.managing_products + - webgriffe_sylius_akeneo.behat.context.ui.admin.managing_products + - webgriffe_sylius_akeneo.behat.context.ui.admin.managing_queue_items + filters: + tags: "@enqueuing_products && @ui" + cli_enqueuing_products_associations: contexts: - sylius.behat.context.hook.doctrine_orm