diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 0ca32283..5a339631 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -155,3 +155,160 @@ jobs: name: Behat logs path: etc/build/ if-no-files-found: ignore + + tests-with-pdf-generation-disabled: + runs-on: ubuntu-latest + + name: "PDF generation disabled: Sylius ${{ matrix.sylius }}, PHP ${{ matrix.php }}, Symfony ${{ matrix.symfony }}, MySQL ${{ matrix.mysql }}" + + strategy: + fail-fast: false + matrix: + php: ["8.1"] + symfony: ["^5.4"] + sylius: ["~1.11.0"] + node: ["14.x"] + mysql: ["8.0"] + + env: + APP_ENV: test + DATABASE_URL: "mysql://root:root@127.0.0.1/sylius?serverVersion=${{ matrix.mysql }}" + + steps: + - + uses: actions/checkout@v2 + + - + name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: "${{ matrix.php }}" + extensions: intl + tools: symfony + coverage: none + + - + name: Setup Node + uses: actions/setup-node@v1 + with: + node-version: "${{ matrix.node }}" + + - + name: Shutdown default MySQL + run: sudo service mysql stop + + - + name: Setup MySQL + uses: mirromutth/mysql-action@v1.1 + with: + mysql version: "${{ matrix.mysql }}" + mysql root password: "root" + + - + name: Remove wkhtmltopdf binary + run: rm tests/Application/etc/wkhtmltopdf + + - + name: Disable PDF generation + run: mv tests/Application/etc/sylius_invoicing_pdf_generation_disabled.yaml tests/Application/config/packages + + - + name: Get Composer cache directory + id: composer-cache + run: echo "::set-output name=dir::$(composer config cache-files-dir)" + + - + name: Cache Composer + uses: actions/cache@v2 + with: + path: ${{ steps.composer-cache.outputs.dir }} + key: ${{ runner.os }}-php-${{ matrix.php }}-composer-${{ hashFiles('**/composer.json **/composer.lock') }} + restore-keys: | + ${{ runner.os }}-php-${{ matrix.php }}-composer- + + - + name: Restrict Symfony version + if: matrix.symfony != '' + run: | + composer global require --no-progress --no-scripts --no-plugins "symfony/flex:^1.10" + composer config extra.symfony.require "${{ matrix.symfony }}" + + - + name: Restrict Sylius version + if: matrix.sylius != '' + run: composer require "sylius/sylius:${{ matrix.sylius }}" --no-update --no-scripts --no-interaction + + - + name: Install PHP dependencies + run: composer install --no-interaction + + - + name: Get Yarn cache directory + id: yarn-cache + run: echo "::set-output name=dir::$(yarn cache dir)" + + - + name: Cache Yarn + uses: actions/cache@v2 + with: + path: ${{ steps.yarn-cache.outputs.dir }} + key: ${{ runner.os }}-node-${{ matrix.node }}-yarn-${{ hashFiles('**/package.json **/yarn.lock') }} + restore-keys: | + ${{ runner.os }}-node-${{ matrix.node }}-yarn- + + - + name: Install JS dependencies + run: (cd tests/Application && yarn install) + + - + name: Prepare test application database + run: | + (cd tests/Application && bin/console doctrine:database:create -vvv) + (cd tests/Application && bin/console doctrine:migrations:migrate -n -vvv -q) + + - + name: Prepare test application assets + run: | + (cd tests/Application && bin/console assets:install public -vvv) + (cd tests/Application && yarn build) + + - + name: Prepare test application cache + run: (cd tests/Application && bin/console cache:warmup -vvv) + + - + name: Load fixtures in test application + run: (cd tests/Application && bin/console sylius:fixtures:load -n) + + - + name: Run security check + run: symfony security:check + + - + name: Run analysis + run: composer analyse + + - + name: Run PHPSpec + run: vendor/bin/phpspec run --ansi -f progress --no-interaction + + - + name: Run PHPUnit + run: vendor/bin/phpunit --colors=always + + - + name: Replace excluded directory in Behat + run: sed -i 's/pdf_generation_disabled/pdf_generation_enabled/g' behat.yml.dist + + - + name: Run Behat + run: vendor/bin/behat --colors --strict -vvv --no-interaction -f progress || vendor/bin/behat --colors --strict -vvv --no-interaction -f progress --rerun + + - + name: Upload Behat logs + uses: actions/upload-artifact@v2 + if: failure() + with: + name: Behat logs + path: etc/build/ + if-no-files-found: ignore diff --git a/README.md b/README.md index ff501f3b..946af26c 100644 --- a/README.md +++ b/README.md @@ -42,7 +42,16 @@ Additional feature of the plugin that fulfills Invoicing domain is the ability t bin/console doctrine:migrations:migrate ``` -3. Check if you have wkhtmltopdf binary. If not, you can download it [here](https://wkhtmltopdf.org/downloads.html). +3. Default configuration assumes enabled PDF file generation. If you don't want to use that feature change your app configuration: + + ```yaml + # config/packages/sylius_invoicing.yaml + sylius_invoicing: + pdf_generator: + enabled: false + ``` + + Otherwise, check if you have wkhtmltopdf binary. If not, you can download it [here](https://wkhtmltopdf.org/downloads.html). In case wkhtmltopdf is not located in `/usr/local/bin/wkhtmltopdf` modify the `WKHTMLTOPDF_PATH` environment variable in the `.env` file: diff --git a/UPGRADE.md b/UPGRADE.md index 799e3d32..3c96e40e 100644 --- a/UPGRADE.md +++ b/UPGRADE.md @@ -1,6 +1,9 @@ ### UPGRADE FROM 0.21.0 TO 0.22.0 1. `Sylius\InvoicingPlugin\Generator\InvoicePdfFileGenerator` takes `Sylius\InvoicingPlugin\Generator\TwigToPdfGeneratorInterface` as the first argument in place of `Twig\Environment`, `Knp\Snappy\GeneratorInterface` and `Sylius\InvoicingPlugin\Generator\PdfOptionsGeneratorInterface`. +2. `Sylius\InvoicingPlugin\Creator\InvoiceCreator` takes `%sylius_invoicing.pdf_generator.enabled%` as the sixth argument. +3. `Sylius\InvoicingPlugin\Ui\Action\DownloadInvoiceAction` takes `%sylius_invoicing.pdf_generator.enabled%` as the fourth argument. +4. `Sylius\InvoicingPlugin\Email\InvoiceEmailSender` takes `%sylius_invoicing.pdf_generator.enabled%` as the third argument. ### UPGRADE FROM 0.20.0 TO 0.21.0 diff --git a/behat.yml.dist b/behat.yml.dist index c4aa2e98..b744fe7c 100644 --- a/behat.yml.dist +++ b/behat.yml.dist @@ -41,3 +41,11 @@ default: class: Tests\Sylius\InvoicingPlugin\Application\Kernel FriendsOfBehat\VariadicExtension: ~ + + FriendsOfBehat\SuiteSettingsExtension: + paths: + - features + + FriendsOfBehat\ExcludeSpecificationsExtension: + features: + - features/managing_invoices/pdf_generation_disabled diff --git a/composer.json b/composer.json index 5a2718f0..645f648b 100644 --- a/composer.json +++ b/composer.json @@ -24,6 +24,7 @@ "require-dev": { "behat/behat": "^3.6.1", "behat/mink-selenium2-driver": "^1.4", + "friends-of-behat/exclude-specifications-extension": "^0.2 || ^0.3", "friends-of-behat/mink": "^1.8", "friends-of-behat/mink-browserkit-driver": "^1.3", "friends-of-behat/mink-debug-extension": "^2.0", diff --git a/features/managing_invoices/pdf_generation_disabled/being_unable_to_download_invoice_on_admin_order_view.feature b/features/managing_invoices/pdf_generation_disabled/being_unable_to_download_invoice_on_admin_order_view.feature new file mode 100644 index 00000000..9255347d --- /dev/null +++ b/features/managing_invoices/pdf_generation_disabled/being_unable_to_download_invoice_on_admin_order_view.feature @@ -0,0 +1,20 @@ +@managing_invoices +Feature: Being unable to download an invoice on a single order view + In order not to generate PDF files for invoices related to the order + As an Administrator + I want to be unable to download invoices on a single order view + + Background: + Given the store operates on a single channel in "United States" + And the store has a product "PHP T-Shirt" + And the store ships everywhere for free + And the store allows paying with "Cash on Delivery" + And there is a customer "john.doe@gmail.com" that placed an order "#00000022" + And the customer bought a single "PHP T-Shirt" + And the customer chose "Free" shipping method to "United States" with "Cash on Delivery" payment + And I am logged in as an administrator + + @ui + Scenario: Being unable to download an invoice on a single order view + When I view the summary of the order "#00000022" + Then I should not be able to download the first invoice diff --git a/features/managing_invoices/pdf_generation_disabled/being_unable_to_download_invoice_on_customer_order_view.feature b/features/managing_invoices/pdf_generation_disabled/being_unable_to_download_invoice_on_customer_order_view.feature new file mode 100644 index 00000000..ab8ac947 --- /dev/null +++ b/features/managing_invoices/pdf_generation_disabled/being_unable_to_download_invoice_on_customer_order_view.feature @@ -0,0 +1,22 @@ +@customer_browsing_invoices +Feature: Being unable to download an invoice on a single order view + In order not to generate a PDF file for an invoice related to the order + As a Customer + I want to be unable to download an invoice on a single order view + + Background: + Given the store operates on a single channel in "United States" + And the store has a product "Angel T-Shirt" + And the store ships everywhere for free + And the store allows paying with "Cash on Delivery" + And I am a logged in customer + And I placed an order "#00000666" + And I bought a single "Angel T-Shirt" + And I addressed it to "Lucifer Morningstar", "Seaside Fwy", "90802" "Los Angeles" in the "United States" + And for the billing address of "Mazikeen Lilim" in the "Pacific Coast Hwy", "90806" "Los Angeles", "United States" + And I chose "Free" shipping method with "Cash on Delivery" payment + + @ui + Scenario: Being unable to download an invoice on a single order view + When I view the summary of the order "#00000666" + Then I should not be able to download the first invoice diff --git a/features/managing_invoices/pdf_generation_disabled/being_unable_to_download_invoice_on_its_details_page.feature b/features/managing_invoices/pdf_generation_disabled/being_unable_to_download_invoice_on_its_details_page.feature new file mode 100644 index 00000000..b0cc3c7c --- /dev/null +++ b/features/managing_invoices/pdf_generation_disabled/being_unable_to_download_invoice_on_its_details_page.feature @@ -0,0 +1,23 @@ +@managing_invoices +Feature: Being unable to download an invoice from its details page + In order not to generate a PDF file for a specific invoice + As an Administrator + I want to be unable to download an invoice + + Background: + Given the store operates on a single channel in "United States" + And the store has a product "Angel T-Shirt" priced at "$60.00" + And the store has "UPS" shipping method with "$10.00" fee + And the store allows paying with "Cash on Delivery" + And I am logged in as an administrator + And I set shop billing data for channel "United States" as "Ragnarok", "1100110011", "Pacific Coast Hwy", "90806" "Los Angeles", "United States" + And there is a customer "lucy@teamlucifer.com" that placed an order "#00000666" + And the customer bought 2 "Angel T-Shirt" products + And the customer "Lucifer Morningstar" addressed it to "Seaside Fwy", "90802" "Los Angeles" in the "United States" + And for the billing address of "Mazikeen Lilim" in the "Pacific Coast Hwy", "90806" "Los Angeles", "United States" + And the customer chose "UPS" shipping method with "Cash on Delivery" payment + + @ui + Scenario: Being unable to download an invoice from its details page + Given I view the summary of the invoice for order "#00000666" + Then I should not be able to download the invoice diff --git a/features/managing_invoices/downloading_invoices_on_admin_order_view.feature b/features/managing_invoices/pdf_generation_enabled/downloading_invoice_on_admin_order_view.feature similarity index 97% rename from features/managing_invoices/downloading_invoices_on_admin_order_view.feature rename to features/managing_invoices/pdf_generation_enabled/downloading_invoice_on_admin_order_view.feature index c19326f0..5c81527d 100644 --- a/features/managing_invoices/downloading_invoices_on_admin_order_view.feature +++ b/features/managing_invoices/pdf_generation_enabled/downloading_invoice_on_admin_order_view.feature @@ -1,4 +1,4 @@ -@managing_invoices @ui +@managing_invoices Feature: Downloading invoices on a single order view In order to store all invoices related to the order As an Administrator @@ -14,6 +14,7 @@ Feature: Downloading invoices on a single order view And the customer chose "Free" shipping method to "United States" with "Cash on Delivery" payment And I am logged in as an administrator + @ui Scenario: Downloading an invoice on order view When I view the summary of the order "#00000022" And I download the first invoice diff --git a/features/managing_invoices/downloading_invoices_on_customer_order_view.feature b/features/managing_invoices/pdf_generation_enabled/downloading_invoice_on_customer_order_view.feature similarity index 96% rename from features/managing_invoices/downloading_invoices_on_customer_order_view.feature rename to features/managing_invoices/pdf_generation_enabled/downloading_invoice_on_customer_order_view.feature index d7f2be58..c9999699 100644 --- a/features/managing_invoices/downloading_invoices_on_customer_order_view.feature +++ b/features/managing_invoices/pdf_generation_enabled/downloading_invoice_on_customer_order_view.feature @@ -1,4 +1,4 @@ -@customer_browsing_invoices @ui +@customer_browsing_invoices Feature: Downloading invoices on a single order view In order to have access to all invoices related to the order that I've placed As a Customer @@ -16,6 +16,7 @@ Feature: Downloading invoices on a single order view And for the billing address of "Mazikeen Lilim" in the "Pacific Coast Hwy", "90806" "Los Angeles", "United States" And I chose "Free" shipping method with "Cash on Delivery" payment + @ui Scenario: Downloading an invoice on order view When I view the summary of the order "#00000666" And I download the first invoice diff --git a/features/managing_invoices/pdf_generation_enabled/downloading_invoice_on_its_details_page.feature b/features/managing_invoices/pdf_generation_enabled/downloading_invoice_on_its_details_page.feature new file mode 100644 index 00000000..4c653199 --- /dev/null +++ b/features/managing_invoices/pdf_generation_enabled/downloading_invoice_on_its_details_page.feature @@ -0,0 +1,24 @@ +@managing_invoices +Feature: Downloading an invoice from its details page + In order to store a specific invoice + As an Administrator + I want to be able to download an invoice + + Background: + Given the store operates on a single channel in "United States" + And the store has a product "Angel T-Shirt" priced at "$60.00" + And the store has "UPS" shipping method with "$10.00" fee + And the store allows paying with "Cash on Delivery" + And I am logged in as an administrator + And I set shop billing data for channel "United States" as "Ragnarok", "1100110011", "Pacific Coast Hwy", "90806" "Los Angeles", "United States" + And there is a customer "lucy@teamlucifer.com" that placed an order "#00000666" + And the customer bought 2 "Angel T-Shirt" products + And the customer "Lucifer Morningstar" addressed it to "Seaside Fwy", "90802" "Los Angeles" in the "United States" + And for the billing address of "Mazikeen Lilim" in the "Pacific Coast Hwy", "90806" "Los Angeles", "United States" + And the customer chose "UPS" shipping method with "Cash on Delivery" payment + + @ui + Scenario: Downloading an invoice + Given I view the summary of the invoice for order "#00000666" + When I download the invoice + Then the pdf file for this invoice should be downloaded successfully diff --git a/features/managing_invoices/saving_invoices_on_server_during_generation.feature b/features/managing_invoices/pdf_generation_enabled/saving_invoices_on_server_during_generation.feature similarity index 100% rename from features/managing_invoices/saving_invoices_on_server_during_generation.feature rename to features/managing_invoices/pdf_generation_enabled/saving_invoices_on_server_during_generation.feature diff --git a/features/managing_invoices/seeing_invoice.feature b/features/managing_invoices/seeing_invoice.feature index 4d85408d..a0f055cb 100644 --- a/features/managing_invoices/seeing_invoice.feature +++ b/features/managing_invoices/seeing_invoice.feature @@ -30,11 +30,6 @@ Feature: Seeing basic information about an invoice And its total should be "142.00" in "USD" currency And it should be issued in "United States" channel - Scenario: Downloading invoice - Given I view the summary of the invoice for order "#00000666" - When I download the invoice - Then the pdf file for this invoice should be downloaded successfully - Scenario: Going back to invoices view Given I view the summary of the invoice for order "#00000666" When I want to go back to invoices view diff --git a/spec/Creator/InvoiceCreatorSpec.php b/spec/Creator/InvoiceCreatorSpec.php index e4bacc8c..325c35d6 100644 --- a/spec/Creator/InvoiceCreatorSpec.php +++ b/spec/Creator/InvoiceCreatorSpec.php @@ -76,6 +76,40 @@ function it_creates_invoice_for_order( $this->__invoke('0000001', $invoiceDateTime); } + function it_creates_invoice_without_generating_pdf_file( + InvoiceRepositoryInterface $invoiceRepository, + OrderRepositoryInterface $orderRepository, + InvoiceGeneratorInterface $invoiceGenerator, + InvoicePdfFileGeneratorInterface $invoicePdfFileGenerator, + InvoiceFileManagerInterface $invoiceFileManager, + OrderInterface $order, + InvoiceInterface $invoice + ): void { + $this->beConstructedWith( + $invoiceRepository, + $orderRepository, + $invoiceGenerator, + $invoicePdfFileGenerator, + $invoiceFileManager, + false + ); + + $orderRepository->findOneByNumber('0000001')->willReturn($order); + + $invoiceRepository->findOneByOrder($order)->willReturn(null); + + $invoiceDateTime = new \DateTimeImmutable('2019-02-25'); + + $invoiceGenerator->generateForOrder($order, $invoiceDateTime)->willReturn($invoice); + + $invoicePdfFileGenerator->generate($invoice)->shouldNotBeCalled(); + $invoiceFileManager->save(Argument::any())->shouldNotBeCalled(); + + $invoiceRepository->add($invoice)->shouldBeCalled(); + + $this('0000001', $invoiceDateTime); + } + function it_removes_saved_invoice_file_if_database_update_fails( InvoiceRepositoryInterface $invoiceRepository, OrderRepositoryInterface $orderRepository, diff --git a/spec/Email/InvoiceEmailSenderSpec.php b/spec/Email/InvoiceEmailSenderSpec.php index 76f0519a..e4426599 100644 --- a/spec/Email/InvoiceEmailSenderSpec.php +++ b/spec/Email/InvoiceEmailSenderSpec.php @@ -54,4 +54,18 @@ function it_sends_an_invoice_to_a_given_email_address( $this->sendInvoiceEmail($invoice, 'sylius@example.com'); } + + function it_sends_an_invoice_without_attachment_to_a_given_email_address( + InvoiceInterface $invoice, + SenderInterface $sender, + InvoiceFileProviderInterface $invoiceFileProvider + ): void { + $this->beConstructedWith($sender, $invoiceFileProvider, false); + + $invoiceFileProvider->provide($invoice)->shouldNotBeCalled(); + + $sender->send(Emails::INVOICE_GENERATED, ['sylius@example.com'], ['invoice' => $invoice])->shouldBeCalled(); + + $this->sendInvoiceEmail($invoice, 'sylius@example.com'); + } } diff --git a/src/Creator/InvoiceCreator.php b/src/Creator/InvoiceCreator.php index e4ffc378..16faaa32 100644 --- a/src/Creator/InvoiceCreator.php +++ b/src/Creator/InvoiceCreator.php @@ -25,28 +25,14 @@ final class InvoiceCreator implements InvoiceCreatorInterface { - private InvoiceRepositoryInterface $invoiceRepository; - - private OrderRepositoryInterface $orderRepository; - - private InvoiceGeneratorInterface $invoiceGenerator; - - private InvoicePdfFileGeneratorInterface $invoicePdfFileGenerator; - - private InvoiceFileManagerInterface $invoiceFileManager; - public function __construct( - InvoiceRepositoryInterface $invoiceRepository, - OrderRepositoryInterface $orderRepository, - InvoiceGeneratorInterface $invoiceGenerator, - InvoicePdfFileGeneratorInterface $invoicePdfFileGenerator, - InvoiceFileManagerInterface $invoiceFileManager + private InvoiceRepositoryInterface $invoiceRepository, + private OrderRepositoryInterface $orderRepository, + private InvoiceGeneratorInterface $invoiceGenerator, + private InvoicePdfFileGeneratorInterface $invoicePdfFileGenerator, + private InvoiceFileManagerInterface $invoiceFileManager, + private bool $hasEnabledPdfFileGenerator = true ) { - $this->invoiceRepository = $invoiceRepository; - $this->orderRepository = $orderRepository; - $this->invoiceGenerator = $invoiceGenerator; - $this->invoicePdfFileGenerator = $invoicePdfFileGenerator; - $this->invoiceFileManager = $invoiceFileManager; } public function __invoke(string $orderNumber, \DateTimeInterface $dateTime): void @@ -62,6 +48,13 @@ public function __invoke(string $orderNumber, \DateTimeInterface $dateTime): voi } $invoice = $this->invoiceGenerator->generateForOrder($order, $dateTime); + + if (!$this->hasEnabledPdfFileGenerator) { + $this->invoiceRepository->add($invoice); + + return; + } + $invoicePdf = $this->invoicePdfFileGenerator->generate($invoice); $this->invoiceFileManager->save($invoicePdf); diff --git a/src/DependencyInjection/Configuration.php b/src/DependencyInjection/Configuration.php index 69274dfd..a0853c59 100644 --- a/src/DependencyInjection/Configuration.php +++ b/src/DependencyInjection/Configuration.php @@ -170,6 +170,9 @@ private function addPdfGeneratorSection(ArrayNodeDefinition $node): void ->variablePrototype()->end() ->end() ->end() + ->children() + ->booleanNode('enabled')->defaultTrue() + ->end() ->end() ->end() ; diff --git a/src/DependencyInjection/SyliusInvoicingExtension.php b/src/DependencyInjection/SyliusInvoicingExtension.php index 3c3e3a83..98db1ef6 100644 --- a/src/DependencyInjection/SyliusInvoicingExtension.php +++ b/src/DependencyInjection/SyliusInvoicingExtension.php @@ -41,6 +41,8 @@ public function prepend(ContainerBuilder $container): void { $config = $this->getCurrentConfiguration($container); + $container->setParameter('sylius_invoicing.pdf_generator.enabled', $config['pdf_generator']['enabled']); + $this->registerResources('sylius_invoicing_plugin', 'doctrine/orm', $config['resources'], $container); $this->prependDoctrineMigrations($container); diff --git a/src/Email/InvoiceEmailSender.php b/src/Email/InvoiceEmailSender.php index 7df5870b..1c1a9db8 100644 --- a/src/Email/InvoiceEmailSender.php +++ b/src/Email/InvoiceEmailSender.php @@ -16,30 +16,31 @@ use Sylius\Component\Mailer\Sender\SenderInterface; use Sylius\InvoicingPlugin\Entity\InvoiceInterface; use Sylius\InvoicingPlugin\Provider\InvoiceFileProviderInterface; +use Webmozart\Assert\Assert; final class InvoiceEmailSender implements InvoiceEmailSenderInterface { - private SenderInterface $emailSender; - - private InvoiceFileProviderInterface $invoiceFileProvider; - public function __construct( - SenderInterface $emailSender, - InvoiceFileProviderInterface $invoiceFileProvider + private SenderInterface $emailSender, + private InvoiceFileProviderInterface $invoiceFileProvider, + private bool $hasEnabledPdfFileGenerator = true ) { - $this->emailSender = $emailSender; - $this->invoiceFileProvider = $invoiceFileProvider; } public function sendInvoiceEmail( InvoiceInterface $invoice, string $customerEmail ): void { + if (!$this->hasEnabledPdfFileGenerator) { + $this->emailSender->send(Emails::INVOICE_GENERATED, [$customerEmail], ['invoice' => $invoice]); + + return; + } + $invoicePdf = $this->invoiceFileProvider->provide($invoice); + $invoicePdfPath = $invoicePdf->fullPath(); + Assert::notNull($invoicePdfPath); - $this - ->emailSender - ->send(Emails::INVOICE_GENERATED, [$customerEmail], ['invoice' => $invoice], [$invoicePdf->fullPath()]) - ; + $this->emailSender->send(Emails::INVOICE_GENERATED, [$customerEmail], ['invoice' => $invoice], [$invoicePdfPath]); } } diff --git a/src/Resources/config/config.yml b/src/Resources/config/config.yml index d08da185..a5fc7bf0 100644 --- a/src/Resources/config/config.yml +++ b/src/Resources/config/config.yml @@ -89,6 +89,7 @@ sylius_grid: download: type: default label: sylius_invoicing_plugin.ui.download_invoice + enabled: '%sylius_invoicing.pdf_generator.enabled%' icon: download options: link: @@ -112,12 +113,43 @@ sylius_ui: sylius_invoicing_plugin: template: '@SyliusInvoicingPlugin/Order/Admin/fetchInvoices.html.twig' priority: 15 + sylius.shop.account.order.show.subcontent: blocks: sylius_invoicing_plugin: template: '@SyliusInvoicingPlugin/Order/Shop/fetchInvoices.html.twig' priority: 15 + sylius_invoicing.admin.invoice.buttons: + blocks: + back_button: + template: '@SyliusInvoicingPlugin/Invoice/Show/_backButton.html.twig' + priority: 30 + download_button: + template: '@SyliusInvoicingPlugin/Invoice/Admin/_downloadButton.html.twig' + enabled: '%sylius_invoicing.pdf_generator.enabled%' + priority: 20 + resend_button: + template: '@SyliusInvoicingPlugin/Invoice/Admin/_resendButton.html.twig' + priority: 10 + + sylius_invoicing.admin.order.invoices.list.actions.buttons: + blocks: + download_button: + template: '@SyliusInvoicingPlugin/Invoice/Admin/_downloadButton.html.twig' + enabled: '%sylius_invoicing.pdf_generator.enabled%' + priority: 20 + resend_button: + template: '@SyliusInvoicingPlugin/Invoice/Admin/_resendButton.html.twig' + priority: 10 + + sylius_invoicing.shop.order.invoices.list.actions: + blocks: + download_button: + template: '@SyliusInvoicingPlugin/Order/Shop/_downloadButton.html.twig' + enabled: '%sylius_invoicing.pdf_generator.enabled%' + priority: 10 + framework: messenger: buses: diff --git a/src/Resources/config/services.xml b/src/Resources/config/services.xml index b0aea142..6b464568 100644 --- a/src/Resources/config/services.xml +++ b/src/Resources/config/services.xml @@ -18,6 +18,7 @@ + %sylius_invoicing.pdf_generator.enabled% diff --git a/src/Resources/config/services/actions.xml b/src/Resources/config/services/actions.xml index 0e51900e..16f8a78b 100644 --- a/src/Resources/config/services/actions.xml +++ b/src/Resources/config/services/actions.xml @@ -8,6 +8,7 @@ + %sylius_invoicing.pdf_generator.enabled% diff --git a/src/Resources/config/services/generators.xml b/src/Resources/config/services/generators.xml index 32505e5a..8b8abb92 100644 --- a/src/Resources/config/services/generators.xml +++ b/src/Resources/config/services/generators.xml @@ -43,6 +43,7 @@ + %sylius_invoicing.pdf_generator.enabled% diff --git a/src/Resources/views/Invoice/Admin/_downloadButton.html.twig b/src/Resources/views/Invoice/Admin/_downloadButton.html.twig new file mode 100644 index 00000000..068b8cc6 --- /dev/null +++ b/src/Resources/views/Invoice/Admin/_downloadButton.html.twig @@ -0,0 +1,5 @@ +{% import '@SyliusUi/Macro/buttons.html.twig' as buttons %} + +{% set path = path('sylius_invoicing_plugin_admin_invoice_download', {'id': invoice.id}) %} + +{{ buttons.default(path, 'sylius_invoicing_plugin.ui.download_invoice'|trans, invoice.id, 'download', 'blue') }} diff --git a/src/Resources/views/Invoice/Admin/_resendButton.html.twig b/src/Resources/views/Invoice/Admin/_resendButton.html.twig new file mode 100644 index 00000000..e6f57e3b --- /dev/null +++ b/src/Resources/views/Invoice/Admin/_resendButton.html.twig @@ -0,0 +1,5 @@ +{% import '@SyliusUi/Macro/buttons.html.twig' as buttons %} + +{% set path = path('sylius_invoicing_plugin_admin_invoice_resend', {'id': invoice.id}) %} + +{{ buttons.default(path, 'sylius_invoicing_plugin.ui.resend_invoice'|trans, invoice.id, 'send') }} diff --git a/src/Resources/views/Invoice/Show/_backButton.html.twig b/src/Resources/views/Invoice/Show/_backButton.html.twig new file mode 100644 index 00000000..03096ac8 --- /dev/null +++ b/src/Resources/views/Invoice/Show/_backButton.html.twig @@ -0,0 +1,5 @@ +{% import '@SyliusUi/Macro/buttons.html.twig' as buttons %} + +{% set path = path('sylius_invoicing_plugin_admin_invoice_index') %} + +{{ buttons.default(path, '', 'back', 'arrow alternate circle left outline') }} diff --git a/src/Resources/views/Invoice/show.html.twig b/src/Resources/views/Invoice/show.html.twig index a3ad226a..7fc4d914 100644 --- a/src/Resources/views/Invoice/show.html.twig +++ b/src/Resources/views/Invoice/show.html.twig @@ -2,8 +2,6 @@ {% import '@SyliusAdmin/Common/Macro/money.html.twig' as money %} -{% import '@SyliusUi/Macro/buttons.html.twig' as buttons %} - {% block title %}{{ 'sylius.ui.invoice'|trans ~ ' ' ~ invoice.number }} {{ parent() }}{% endblock %} {% block content %} @@ -13,14 +11,7 @@ {% include '@SyliusInvoicingPlugin/Invoice/Show/_breadcrumb.html.twig' %}
- {% set path = path('sylius_invoicing_plugin_admin_invoice_index') %} - {{ buttons.default(path, '', 'back', 'arrow alternate circle left outline') }} - - {% set path = path('sylius_invoicing_plugin_admin_invoice_download', {'id': invoice.id}) %} - {{ buttons.default(path, 'sylius_invoicing_plugin.ui.download_invoice'|trans, invoice.id, 'download', 'blue') }} - - {% set path = path('sylius_invoicing_plugin_admin_invoice_resend', {'id': invoice.id}) %} - {{ buttons.default(path, 'sylius_invoicing_plugin.ui.resend_invoice'|trans, invoice.id, 'send') }} + {{ sylius_template_event('sylius_invoicing.admin.invoice.buttons', _context) }}
diff --git a/src/Resources/views/Order/Admin/_invoices.html.twig b/src/Resources/views/Order/Admin/_invoices.html.twig index e817e746..119e7ff6 100644 --- a/src/Resources/views/Order/Admin/_invoices.html.twig +++ b/src/Resources/views/Order/Admin/_invoices.html.twig @@ -24,11 +24,7 @@
- {% set path = path('sylius_invoicing_plugin_admin_invoice_download', { 'id': invoice.id }) %} - {{ buttons.default(path, 'sylius_invoicing_plugin.ui.download_invoice'|trans, invoice.id, 'download', 'blue') }} - - {% set path = path('sylius_invoicing_plugin_admin_invoice_resend', { 'id': invoice.id }) %} - {{ buttons.default(path, 'sylius_invoicing_plugin.ui.resend_invoice'|trans, invoice.id, 'send') }} + {{ sylius_template_event('sylius_invoicing.admin.order.invoices.list.actions.buttons', _context) }}
diff --git a/src/Resources/views/Order/Shop/_downloadButton.html.twig b/src/Resources/views/Order/Shop/_downloadButton.html.twig new file mode 100644 index 00000000..84aeccdb --- /dev/null +++ b/src/Resources/views/Order/Shop/_downloadButton.html.twig @@ -0,0 +1,5 @@ +{% import '@SyliusUi/Macro/buttons.html.twig' as buttons %} + +{% set path = path('sylius_invoicing_plugin_shop_invoice_download', { 'id': invoice.id }) %} + +{{ buttons.default(path, 'sylius_invoicing_plugin.ui.download_invoice'|trans, invoice.id, 'download') }} diff --git a/src/Resources/views/Order/Shop/_invoices.html.twig b/src/Resources/views/Order/Shop/_invoices.html.twig index dbfd4f83..92375c69 100644 --- a/src/Resources/views/Order/Shop/_invoices.html.twig +++ b/src/Resources/views/Order/Shop/_invoices.html.twig @@ -1,5 +1,3 @@ -{% import '@SyliusUi/Macro/buttons.html.twig' as buttons %} -

{{ 'sylius_invoicing_plugin.ui.invoices'|trans }}

@@ -20,9 +18,7 @@ {{ invoice.issuedAt|format_date }} {% endfor %} diff --git a/src/Ui/Action/DownloadInvoiceAction.php b/src/Ui/Action/DownloadInvoiceAction.php index b9cec6f3..32013403 100644 --- a/src/Ui/Action/DownloadInvoiceAction.php +++ b/src/Ui/Action/DownloadInvoiceAction.php @@ -24,24 +24,20 @@ final class DownloadInvoiceAction { - private InvoiceRepositoryInterface $invoiceRepository; - - private AuthorizationCheckerInterface $authorizationChecker; - - private InvoiceFileProviderInterface $invoiceFilePathProvider; - public function __construct( - InvoiceRepositoryInterface $invoiceRepository, - AuthorizationCheckerInterface $authorizationChecker, - InvoiceFileProviderInterface $invoiceFilePathProvider + private InvoiceRepositoryInterface $invoiceRepository, + private AuthorizationCheckerInterface $authorizationChecker, + private InvoiceFileProviderInterface $invoiceFilePathProvider, + private bool $hasEnabledPdfFileGenerator = true ) { - $this->invoiceRepository = $invoiceRepository; - $this->authorizationChecker = $authorizationChecker; - $this->invoiceFilePathProvider = $invoiceFilePathProvider; } public function __invoke(string $id): Response { + if (!$this->hasEnabledPdfFileGenerator) { + return new Response('', Response::HTTP_NOT_FOUND); + } + /** @var InvoiceInterface|null $invoice */ $invoice = $this->invoiceRepository->find($id); Assert::notNull($invoice); diff --git a/tests/Application/etc/sylius_invoicing_pdf_generation_disabled.yaml b/tests/Application/etc/sylius_invoicing_pdf_generation_disabled.yaml new file mode 100644 index 00000000..a6ad576c --- /dev/null +++ b/tests/Application/etc/sylius_invoicing_pdf_generation_disabled.yaml @@ -0,0 +1,3 @@ +sylius_invoicing: + pdf_generator: + enabled: false diff --git a/tests/Behat/Context/Hook/InvoicesContext.php b/tests/Behat/Context/Hook/InvoicesContext.php index f3f91846..08c161d3 100644 --- a/tests/Behat/Context/Hook/InvoicesContext.php +++ b/tests/Behat/Context/Hook/InvoicesContext.php @@ -8,11 +8,8 @@ final class InvoicesContext implements Context { - private string $invoicesSavePath; - - public function __construct(string $invoicesSavePath) + public function __construct(private string $invoicesSavePath) { - $this->invoicesSavePath = $invoicesSavePath; } /** @@ -20,6 +17,10 @@ public function __construct(string $invoicesSavePath) */ public function clearInvoicesPath(): void { + if (!is_dir($this->invoicesSavePath)) { + return; + } + foreach (scandir($this->invoicesSavePath) as $file) { if (is_file($this->invoicesSavePath.'/'.$file)) { unlink($this->invoicesSavePath.'/'.$file); diff --git a/tests/Behat/Context/Ui/Admin/ManagingInvoicesContext.php b/tests/Behat/Context/Ui/Admin/ManagingInvoicesContext.php index 3d3f03ab..e324a793 100644 --- a/tests/Behat/Context/Ui/Admin/ManagingInvoicesContext.php +++ b/tests/Behat/Context/Ui/Admin/ManagingInvoicesContext.php @@ -335,4 +335,20 @@ public function itShouldBeUnpaid(): void { Assert::false($this->showPage->isPaid()); } + + /** + * @Then I should not be able to download the first invoice + */ + public function iShouldNotBeAbleToDownloadTheFirstInvoice(): void + { + Assert::false($this->orderShowPage->hasDownloadButtonForInvoice()); + } + + /** + * @Then I should not be able to download the invoice + */ + public function iShouldNotBeAbleToDownloadTheInvoice(): void + { + Assert::false($this->showPage->hasDownloadButton()); + } } diff --git a/tests/Behat/Context/Ui/Shop/CustomerBrowsingInvoicesContext.php b/tests/Behat/Context/Ui/Shop/CustomerBrowsingInvoicesContext.php index a8a34d1c..1f2dafdd 100644 --- a/tests/Behat/Context/Ui/Shop/CustomerBrowsingInvoicesContext.php +++ b/tests/Behat/Context/Ui/Shop/CustomerBrowsingInvoicesContext.php @@ -66,4 +66,12 @@ public function invoiceForOrderShouldNotBeDownloaded(string $orderNumber): void Assert::false($this->downloadInvoicePage->isOpen(['id' => $invoice->id()])); } + + /** + * @Then I should not be able to download the first invoice + */ + public function iShouldNotBeAbleToDownloadTheFirstInvoice(): void + { + Assert::false($this->orderShowPage->hasDownloadButtonForInvoice()); + } } diff --git a/tests/Behat/Page/Admin/Invoice/ShowPage.php b/tests/Behat/Page/Admin/Invoice/ShowPage.php index 955b644f..24d0f428 100644 --- a/tests/Behat/Page/Admin/Invoice/ShowPage.php +++ b/tests/Behat/Page/Admin/Invoice/ShowPage.php @@ -163,6 +163,11 @@ public function isPaid(): bool return str_contains($this->getElement('paid')->getHtml(), 'Yes'); } + public function hasDownloadButton(): bool + { + return $this->getDocument()->hasLink('Download'); + } + protected function getDefinedElements(): array { return array_merge(parent::getDefinedElements(), [ diff --git a/tests/Behat/Page/Admin/Invoice/ShowPageInterface.php b/tests/Behat/Page/Admin/Invoice/ShowPageInterface.php index 6fba6dce..603b4b31 100644 --- a/tests/Behat/Page/Admin/Invoice/ShowPageInterface.php +++ b/tests/Behat/Page/Admin/Invoice/ShowPageInterface.php @@ -56,4 +56,6 @@ public function resend(): void; public function goBack(): void; public function isPaid(): bool; + + public function hasDownloadButton(): bool; } diff --git a/tests/Behat/Page/Admin/Order/ShowPage.php b/tests/Behat/Page/Admin/Order/ShowPage.php index b270981f..35487045 100644 --- a/tests/Behat/Page/Admin/Order/ShowPage.php +++ b/tests/Behat/Page/Admin/Order/ShowPage.php @@ -50,6 +50,13 @@ public function isPdfFileDownloaded(): bool ; } + public function hasDownloadButtonForInvoice(): bool + { + $invoice = $this->getFirstInvoice(); + + return $invoice->hasLink('Download'); + } + protected function getDefinedElements(): array { return array_merge(parent::getDefinedElements(), [ diff --git a/tests/Behat/Page/Admin/Order/ShowPageInterface.php b/tests/Behat/Page/Admin/Order/ShowPageInterface.php index 6147fea4..6e148852 100644 --- a/tests/Behat/Page/Admin/Order/ShowPageInterface.php +++ b/tests/Behat/Page/Admin/Order/ShowPageInterface.php @@ -17,4 +17,6 @@ public function downloadFirstInvoice(): void; public function resendFirstInvoice(): void; public function isPdfFileDownloaded(): bool; + + public function hasDownloadButtonForInvoice(): bool; } diff --git a/tests/Behat/Page/Shop/Order/ShowPage.php b/tests/Behat/Page/Shop/Order/ShowPage.php index efbd3355..57bac4a1 100644 --- a/tests/Behat/Page/Shop/Order/ShowPage.php +++ b/tests/Behat/Page/Shop/Order/ShowPage.php @@ -31,6 +31,13 @@ public function isPdfFileDownloaded(): bool ; } + public function hasDownloadButtonForInvoice(): bool + { + $invoice = $this->getFirstInvoice(); + + return $invoice->hasLink('Download'); + } + protected function getDefinedElements(): array { return array_merge(parent::getDefinedElements(), [ diff --git a/tests/Behat/Page/Shop/Order/ShowPageInterface.php b/tests/Behat/Page/Shop/Order/ShowPageInterface.php index 4666a8c6..acf4097a 100644 --- a/tests/Behat/Page/Shop/Order/ShowPageInterface.php +++ b/tests/Behat/Page/Shop/Order/ShowPageInterface.php @@ -7,6 +7,8 @@ interface ShowPageInterface { public function downloadFirstInvoice(): void; - + public function isPdfFileDownloaded(): bool; + + public function hasDownloadButtonForInvoice(): bool; } diff --git a/tests/Behat/Resources/suites/admin/managing_invoices.yml b/tests/Behat/Resources/suites/admin/managing_invoices.yml index 040d565e..28aab16f 100644 --- a/tests/Behat/Resources/suites/admin/managing_invoices.yml +++ b/tests/Behat/Resources/suites/admin/managing_invoices.yml @@ -61,7 +61,7 @@ default: - Tests\Sylius\InvoicingPlugin\Behat\Context\Setup\OrderContext filters: - tags: "@managing_invoices && @ui" + tags: "@managing_invoices&&@ui" managing_invoices_application: contexts: @@ -102,7 +102,7 @@ default: - Tests\Sylius\InvoicingPlugin\Behat\Context\Application\ManagingInvoicesContext filters: - tags: "@managing_invoices && @application" + tags: "@managing_invoices&&@application" managing_invoices_cli: contexts: @@ -157,4 +157,4 @@ default: - Tests\Sylius\InvoicingPlugin\Behat\Context\Cli\InvoicesGenerationContext filters: - tags: "@managing_invoices && @cli" + tags: "@managing_invoices&&@cli" diff --git a/tests/Behat/Resources/suites/customer.yml b/tests/Behat/Resources/suites/customer.yml index 990c67ae..48e01c5e 100644 --- a/tests/Behat/Resources/suites/customer.yml +++ b/tests/Behat/Resources/suites/customer.yml @@ -52,7 +52,7 @@ default: - Tests\Sylius\InvoicingPlugin\Behat\Context\Ui\Shop\CustomerBrowsingInvoicesContext filters: - tags: "@customer_browsing_invoices && @ui" + tags: "@customer_browsing_invoices&&@ui" customer_browsing_invoices_application: contexts: - sylius.behat.context.hook.doctrine_orm @@ -94,4 +94,4 @@ default: - sylius.behat.context.transform.shared_storage filters: - tags: "@customer_browsing_invoices && @application" + tags: "@customer_browsing_invoices&&@application" diff --git a/tests/Unit/DependencyInjection/SyliusInvoicingConfigurationTest.php b/tests/DependencyInjection/SyliusInvoicingConfigurationTest.php similarity index 62% rename from tests/Unit/DependencyInjection/SyliusInvoicingConfigurationTest.php rename to tests/DependencyInjection/SyliusInvoicingConfigurationTest.php index 5c48b473..a2371c4a 100644 --- a/tests/Unit/DependencyInjection/SyliusInvoicingConfigurationTest.php +++ b/tests/DependencyInjection/SyliusInvoicingConfigurationTest.php @@ -11,7 +11,7 @@ declare(strict_types=1); -namespace Tests\Sylius\InvoicingPlugin\Unit\DependencyInjection; +namespace Tests\Sylius\InvoicingPlugin\DependencyInjection; use Matthias\SymfonyConfigTest\PhpUnit\ConfigurationTestCaseTrait; use PHPUnit\Framework\TestCase; @@ -27,7 +27,7 @@ public function it_does_not_define_any_allowed_files_by_default(): void $this->assertProcessedConfigurationEquals( [[]], ['pdf_generator' => ['allowed_files' => []]], - 'pdf_generator' + 'pdf_generator.allowed_files' ); } @@ -37,7 +37,27 @@ public function it_allows_to_define_allowed_files(): void $this->assertProcessedConfigurationEquals( [['pdf_generator' => ['allowed_files' => ['swans.png', 'product.png']]]], ['pdf_generator' => ['allowed_files' => ['swans.png', 'product.png']]], - 'pdf_generator' + 'pdf_generator.allowed_files' + ); + } + + /** @test */ + public function it_has_enabled_pdf_generator_by_default(): void + { + $this->assertProcessedConfigurationEquals( + [], + ['pdf_generator' => ['enabled' => true]], + 'pdf_generator.enabled' + ); + } + + /** @test */ + public function it_allows_to_disable_pdf_generator(): void + { + $this->assertProcessedConfigurationEquals( + [['pdf_generator' => ['enabled' => false]]], + ['pdf_generator' => ['enabled' => false]], + 'pdf_generator.enabled' ); } diff --git a/tests/DependencyInjection/SyliusInvoicingExtensionTest.php b/tests/DependencyInjection/SyliusInvoicingExtensionTest.php index 91b7bc63..aa9764ee 100644 --- a/tests/DependencyInjection/SyliusInvoicingExtensionTest.php +++ b/tests/DependencyInjection/SyliusInvoicingExtensionTest.php @@ -91,6 +91,19 @@ public function it_loads_allowed_files_for_pdf_generator_configuration(): void ); } + /** @test */ + public function it_prepends_configuration_with_enabled_pdf_generator(): void + { + $this->container->prependExtensionConfig( + 'sylius_invoicing', + ['pdf_generator' => ['enabled' => false]] + ); + + $this->prepend(); + + $this->assertContainerBuilderHasParameter('sylius_invoicing.pdf_generator.enabled', false); + } + /** @test */ public function it_prepends_configuration_with_invoice_resource_services(): void {
- {% set path = path('sylius_invoicing_plugin_shop_invoice_download', { 'id': invoice.id }) %} - - {{ buttons.default(path, 'sylius_invoicing_plugin.ui.download_invoice'|trans, invoice.id, 'download') }} + {{ sylius_template_event('sylius_invoicing.shop.order.invoices.list.actions', _context) }}