diff --git a/src/EventListener/SendEmailWithGiftCardToCustomerSubscriber.php b/src/EventListener/SendEmailWithGiftCardToCustomerSubscriber.php index 140a395d..18a3fae3 100644 --- a/src/EventListener/SendEmailWithGiftCardToCustomerSubscriber.php +++ b/src/EventListener/SendEmailWithGiftCardToCustomerSubscriber.php @@ -42,6 +42,10 @@ public function postCreate(ResourceControllerEvent $event): void return; } + if (!$giftCard->getSendNotificationEmail()) { + return; + } + $this->giftCardEmailManager->sendEmailToCustomerWithGiftCard($customer, $giftCard); } } diff --git a/src/Form/Type/GiftCardType.php b/src/Form/Type/GiftCardType.php index cb16d7b1..78a259ee 100644 --- a/src/Form/Type/GiftCardType.php +++ b/src/Form/Type/GiftCardType.php @@ -41,55 +41,68 @@ public function __construct( public function buildForm(FormBuilderInterface $builder, array $options): void { - $builder - ->addEventSubscriber(new AddCodeFormSubscriber()) - ->add('customer', CustomerAutocompleteChoiceType::class, [ - 'label' => 'sylius.ui.customer', - ]) - ->add('amount', NumberType::class, [ - 'label' => 'sylius.ui.amount', - ]) - ->add('enabled', CheckboxType::class, [ - 'label' => 'sylius.ui.enabled', - 'required' => false, - ]) - ->add('customMessage', TextareaType::class, [ - 'label' => 'setono_sylius_gift_card.form.gift_card.custom_message', + $builder->addEventSubscriber(new AddCodeFormSubscriber()); + $builder->add('customer', CustomerAutocompleteChoiceType::class, [ + 'label' => 'sylius.ui.customer', + ]); + $builder->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event): void { + /** @var GiftCardInterface $giftCard */ + $giftCard = $event->getData(); + + // We only add the notification input if the gift card is new + if (null !== $giftCard->getId()) { + return; + } + + $form = $event->getForm(); + $form->add('sendNotificationEmail', CheckboxType::class, [ 'required' => false, - 'attr' => [ - 'placeholder' => 'setono_sylius_gift_card.form.gift_card.custom_message_placeholder', - ], - ]) - ->add('expiresAt', DateTimeType::class, [ - 'label' => 'setono_sylius_gift_card.form.gift_card.expires_at', - 'widget' => 'single_text', - 'html5' => true, - ]) - ->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event): void { - /** @var GiftCardInterface $giftCard */ - $giftCard = $event->getData(); - - if ($giftCard->getCode() === null) { - $giftCard->setCode($this->giftCardCodeGenerator->generate()); - } - - /** @var ChannelInterface $channel */ - $channel = $giftCard->getChannel(); - - /** @var CurrencyInterface $currency */ - $currency = $channel->getBaseCurrency(); - - $form = $event->getForm(); - $form - ->add('currencyCode', ChoiceType::class, [ - 'label' => 'sylius.ui.currency', - 'choices' => $this->currencyRepository->findAll(), - 'choice_label' => 'code', - 'choice_value' => 'code', - 'preferred_choices' => [$currency->getCode()], - ]); - }) - ; + 'label' => 'setono_sylius_gift_card.form.gift_card.send_notification_email', + ]); + }); + $builder->add('amount', NumberType::class, [ + 'label' => 'sylius.ui.amount', + ]); + $builder->add('enabled', CheckboxType::class, [ + 'label' => 'sylius.ui.enabled', + 'required' => false, + ]); + $builder->add('customMessage', TextareaType::class, [ + 'label' => 'setono_sylius_gift_card.form.gift_card.custom_message', + 'required' => false, + 'attr' => [ + 'placeholder' => 'setono_sylius_gift_card.form.gift_card.custom_message_placeholder', + ], + ]); + $builder->add('expiresAt', DateTimeType::class, [ + 'label' => 'setono_sylius_gift_card.form.gift_card.expires_at', + 'widget' => 'single_text', + 'html5' => true, + ]); + $builder->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event): void { + /** @var GiftCardInterface $giftCard */ + $giftCard = $event->getData(); + + if ($giftCard->getCode() === null) { + $giftCard->setCode($this->giftCardCodeGenerator->generate()); + } + + /** @var ChannelInterface $channel */ + $channel = $giftCard->getChannel(); + + /** @var CurrencyInterface $currency */ + $currency = $channel->getBaseCurrency(); + + $form = $event->getForm(); + $form + ->add('currencyCode', ChoiceType::class, [ + 'label' => 'sylius.ui.currency', + 'choices' => $this->currencyRepository->findAll(), + 'choice_label' => 'code', + 'choice_value' => 'code', + 'preferred_choices' => [$currency->getCode()], + ]); + }); $builder->get('amount')->addModelTransformer(new CallbackTransformer(static function (?int $amount): ?float { if (null === $amount) { diff --git a/src/Model/GiftCard.php b/src/Model/GiftCard.php index c8f02e1f..9c6b5600 100644 --- a/src/Model/GiftCard.php +++ b/src/Model/GiftCard.php @@ -49,6 +49,8 @@ class GiftCard implements GiftCardInterface protected ?DateTimeInterface $expiresAt = null; + protected bool $sendNotificationEmail = true; + public function __construct() { $this->appliedOrders = new ArrayCollection(); @@ -296,4 +298,14 @@ public function isExpired(DateTimeInterface $date = null): bool return $date > $giftCardValidUntil; } + + public function getSendNotificationEmail(): bool + { + return $this->sendNotificationEmail; + } + + public function setSendNotificationEmail(bool $sendNotificationEmail = true): void + { + $this->sendNotificationEmail = $sendNotificationEmail; + } } diff --git a/src/Model/GiftCardInterface.php b/src/Model/GiftCardInterface.php index 2cd52965..40911a1f 100644 --- a/src/Model/GiftCardInterface.php +++ b/src/Model/GiftCardInterface.php @@ -127,4 +127,8 @@ public function getExpiresAt(): ?\DateTimeInterface; public function setExpiresAt(?\DateTimeInterface $expiresAt): void; public function isExpired(\DateTimeInterface $date = null): bool; + + public function getSendNotificationEmail(): bool; + + public function setSendNotificationEmail(bool $sendNotificationEmail = true): void; } diff --git a/src/Resources/config/app/config.yaml b/src/Resources/config/app/config.yaml index 0cc44f08..7d55f54c 100644 --- a/src/Resources/config/app/config.yaml +++ b/src/Resources/config/app/config.yaml @@ -33,3 +33,7 @@ sylius_ui: setono_sylius_gift_card.admin.gift_card_configuration.update.javascripts: blocks: live_pdf_rendering_js: '@SetonoSyliusGiftCardPlugin/Admin/GiftCardConfiguration/Update/_javascripts.html.twig' + + setono_sylius_gift_card.admin.gift_card.create.javascripts: + blocks: + send_customer_email_js: '@SetonoSyliusGiftCardPlugin/Admin/GiftCard/Create/_javascripts.html.twig' diff --git a/src/Resources/config/validation/GiftCard.xml b/src/Resources/config/validation/GiftCard.xml index 2a7acc72..aae70712 100644 --- a/src/Resources/config/validation/GiftCard.xml +++ b/src/Resources/config/validation/GiftCard.xml @@ -37,5 +37,12 @@ + + + + + + + diff --git a/src/Resources/public/setono-sylius-gift-card-send-notification-email.js b/src/Resources/public/setono-sylius-gift-card-send-notification-email.js new file mode 100644 index 00000000..68d172c1 --- /dev/null +++ b/src/Resources/public/setono-sylius-gift-card-send-notification-email.js @@ -0,0 +1,32 @@ +(function ($) { + 'use strict'; + + $.fn.extend({ + sendNotificationEmailInput: function () { + const $customerInput = $(this); + const $sendCustomerNotificationEmail = $($customerInput.data('target')); + + if ($customerInput.val() !== '') { + $sendCustomerNotificationEmail.show(); + } else { + $sendCustomerNotificationEmail.hide(); + } + + $('label[for="setono_sylius_gift_card_gift_card_customer"]').prepend(''); + + $customerInput.on('change', () => { + if ($customerInput.val() !== '') { + $sendCustomerNotificationEmail.show(); + } else { + $sendCustomerNotificationEmail.hide(); + } + }); + + $('.js-ssgc-clear-input').on('click', () => { + $customerInput.parent().children('div.text').html(''); + $customerInput.val(''); + $customerInput.trigger('change'); + }); + } + }); +})(jQuery); diff --git a/src/Resources/translations/messages.da.yml b/src/Resources/translations/messages.da.yml index 1ebfa4f9..e05ab9fb 100644 --- a/src/Resources/translations/messages.da.yml +++ b/src/Resources/translations/messages.da.yml @@ -21,6 +21,7 @@ setono_sylius_gift_card: custom_message: Personlig besked custom_message_placeholder: This message is printed on the gift card PDF... expires_at: Udløber + send_notification_email: Send email med gavekort til kunde gift_card_configuration: background_image: Baggrundsbillede channel_configurations: Kanalkonfigurationer diff --git a/src/Resources/translations/messages.en.yml b/src/Resources/translations/messages.en.yml index cf376aeb..8bc9783b 100644 --- a/src/Resources/translations/messages.en.yml +++ b/src/Resources/translations/messages.en.yml @@ -21,6 +21,7 @@ setono_sylius_gift_card: custom_message: Custom message custom_message_placeholder: This message is printed on the gift card PDF... expires_at: Expires at + send_notification_email: Send notification email gift_card_configuration: background_image: Background image channel_configurations: Channel configurations diff --git a/src/Resources/translations/messages.fr.yml b/src/Resources/translations/messages.fr.yml index 96eee893..2bb3bcf8 100644 --- a/src/Resources/translations/messages.fr.yml +++ b/src/Resources/translations/messages.fr.yml @@ -21,6 +21,7 @@ setono_sylius_gift_card: custom_message: Message personnalisé custom_message_placeholder: Ce message sera affiché sur le PDF du chèque-cadeau... expires_at: Expire le + send_notification_email: Envoyer un email de notification gift_card_configuration: background_image: Image de fond channel_configurations: Configurations des canaux @@ -49,7 +50,7 @@ setono_sylius_gift_card: covered_by_gift_cards: Montant pris en charge count: Nombre create_for_channel: Créer pour %channel% - customer_help_text: When you associate a customer with a gift card, Sylius will automatically notify this customer via email + customer_help_text: Quand vous attribuez un chèque-cadeau à un client, Sylius enverra un email à ce client. customer_email: Customer email download_pdf: PDF edit_gift_card: Edit gift card diff --git a/src/Resources/translations/validators.da.yml b/src/Resources/translations/validators.da.yml index fe6e93bd..d4be52ec 100644 --- a/src/Resources/translations/validators.da.yml +++ b/src/Resources/translations/validators.da.yml @@ -16,6 +16,8 @@ setono_sylius_gift_card: integer: Beløb skal være heltal min: Beløbet kan ikke være mindre en 1 greater_than_or_equal: Beløbet skal være større eller lig med 1 + send_notification_email: + boolean: Send notification email must be a boolean gift_card_configuration: background_image_required: Baggrundsbillede er påkrævet gift_card_search_command: diff --git a/src/Resources/translations/validators.en.yml b/src/Resources/translations/validators.en.yml index 90516bb7..9b217406 100644 --- a/src/Resources/translations/validators.en.yml +++ b/src/Resources/translations/validators.en.yml @@ -16,6 +16,8 @@ setono_sylius_gift_card: integer: Amount must be an integer min: Amount cannot be lower than 1 greater_than_or_equal: The amount must be greater than or equal to 1 + send_notification_email: + boolean: Send notification email must be a boolean gift_card_configuration: background_image_required: The background image is required gift_card_search_command: diff --git a/src/Resources/translations/validators.fr.yml b/src/Resources/translations/validators.fr.yml index 085c9c33..894b687a 100644 --- a/src/Resources/translations/validators.fr.yml +++ b/src/Resources/translations/validators.fr.yml @@ -15,6 +15,8 @@ setono_sylius_gift_card: not_blank: Veuillez renseigner un montant integer: Le montant doit être un entier min: Le montant ne dois pas être en-dessous de 1 + send_notification_email: + boolean: L'envoi de l'email de notification doit être un booléen gift_card_configuration: background_image_required: L'image de fond est requise gift_card_search_command: diff --git a/src/Resources/views/Admin/GiftCard/Create/_javascripts.html.twig b/src/Resources/views/Admin/GiftCard/Create/_javascripts.html.twig new file mode 100644 index 00000000..4fbabf62 --- /dev/null +++ b/src/Resources/views/Admin/GiftCard/Create/_javascripts.html.twig @@ -0,0 +1,6 @@ + + diff --git a/src/Resources/views/Admin/GiftCard/_form.html.twig b/src/Resources/views/Admin/GiftCard/_form.html.twig index eae7fe30..73d9dfd2 100644 --- a/src/Resources/views/Admin/GiftCard/_form.html.twig +++ b/src/Resources/views/Admin/GiftCard/_form.html.twig @@ -6,8 +6,13 @@ {{ form_row(form.code) }} {{ form_row(form.enabled) }} {{ form_row(form.expiresAt) }} -
{{ 'setono_sylius_gift_card.ui.customer_help_text'|trans }}
- {{ form_row(form.customer) }} + {{ form_row(form.customer, {'attr': {'data-target': '.js-ssgc-send-customer-email'}}) }} + {% if form.sendNotificationEmail is defined %} + + {% endif %} diff --git a/tests/Unit/EventListener/SendEmailWithGiftCardToCustomerSubscriberTest.php b/tests/Unit/EventListener/SendEmailWithGiftCardToCustomerSubscriberTest.php new file mode 100644 index 00000000..276bde0c --- /dev/null +++ b/tests/Unit/EventListener/SendEmailWithGiftCardToCustomerSubscriberTest.php @@ -0,0 +1,88 @@ +prophesize(GiftCardEmailManagerInterface::class); + $event = $this->prophesize(ResourceControllerEvent::class); + $event->getSubject()->willReturn(new \stdClass()); + + $this->expectException(UnexpectedTypeException::class); + $subscriber = new SendEmailWithGiftCardToCustomerSubscriber($giftCardEmailManager->reveal()); + $subscriber->postCreate($event->reveal()); + } + + /** + * @test + */ + public function it_does_not_send_email_if_no_customer(): void + { + $giftCardEmailManager = $this->prophesize(GiftCardEmailManagerInterface::class); + $giftCard = $this->prophesize(GiftCardInterface::class); + $event = $this->prophesize(ResourceControllerEvent::class); + $event->getSubject()->willReturn($giftCard); + + $subscriber = new SendEmailWithGiftCardToCustomerSubscriber($giftCardEmailManager->reveal()); + $subscriber->postCreate($event->reveal()); + + $giftCardEmailManager->sendEmailToCustomerWithGiftCard(Argument::any(), Argument::any())->shouldNotHaveBeenCalled(); + } + + /** + * @test + */ + public function it_does_not_send_email_if_it_was_not_asked(): void + { + $giftCardEmailManager = $this->prophesize(GiftCardEmailManagerInterface::class); + $customer = $this->prophesize(CustomerInterface::class); + $giftCard = $this->prophesize(GiftCardInterface::class); + $giftCard->getCustomer()->willReturn($customer); + $giftCard->getSendNotificationEmail()->willReturn(false); + $event = $this->prophesize(ResourceControllerEvent::class); + $event->getSubject()->willReturn($giftCard); + + $subscriber = new SendEmailWithGiftCardToCustomerSubscriber($giftCardEmailManager->reveal()); + $subscriber->postCreate($event->reveal()); + + $giftCardEmailManager->sendEmailToCustomerWithGiftCard(Argument::any(), Argument::any())->shouldNotHaveBeenCalled(); + } + + /** + * @test + */ + public function it_sends_email_if_it_was_asked(): void + { + $giftCardEmailManager = $this->prophesize(GiftCardEmailManagerInterface::class); + $customer = $this->prophesize(CustomerInterface::class); + $giftCard = $this->prophesize(GiftCardInterface::class); + $giftCard->getCustomer()->willReturn($customer); + $giftCard->getSendNotificationEmail()->willReturn(true); + $event = $this->prophesize(ResourceControllerEvent::class); + $event->getSubject()->willReturn($giftCard); + + $subscriber = new SendEmailWithGiftCardToCustomerSubscriber($giftCardEmailManager->reveal()); + $subscriber->postCreate($event->reveal()); + + $giftCardEmailManager->sendEmailToCustomerWithGiftCard(Argument::any(), Argument::any())->shouldHaveBeenCalled(); + } +} diff --git a/tests/Unit/Model/GiftCardTest.php b/tests/Unit/Model/GiftCardTest.php index 66edeb23..2663641b 100644 --- a/tests/Unit/Model/GiftCardTest.php +++ b/tests/Unit/Model/GiftCardTest.php @@ -61,6 +61,9 @@ public function it_has_properties(): void $expiresAt = new \DateTime(); $giftCard->setExpiresAt($expiresAt); $this->assertSame($expiresAt, $giftCard->getExpiresAt()); + + $giftCard->setSendNotificationEmail(false); + $this->assertFalse($giftCard->getSendNotificationEmail()); } /**