diff --git a/README.md b/README.md index 10ae57c6..2cc24371 100644 --- a/README.md +++ b/README.md @@ -88,7 +88,7 @@ $bundles = [ You will find the templates you need to override in the [test application](https://github.com/Setono/SyliusGiftCardPlugin/tree/master/tests/Application/templates). -### Extend `Product`, `Order`, `OrderRepository`, and `CustomerRepository` +### Extend entities **Extend `Product`** ```php @@ -150,6 +150,31 @@ class Order extends BaseOrder implements SetonoSyliusGiftCardPluginOrderInterfac } ``` +**Extend `OrderItem`** + +```php +beConstructedWith( - $giftCardFactory, - $giftCardRepository, - $giftCardManager, - $giftCardOrderEmailManager - ); - } - - public function it_is_initializable(): void - { - $this->shouldHaveType(OrderGiftCardOperator::class); - } - - public function it_implements_order_gift_card_operator_interface(): void - { - $this->shouldImplement(OrderGiftCardOperatorInterface::class); - } - - public function it_creates_disabled_gift_cards( - OrderInterface $order, - OrderItemInterface $orderItem, - ProductInterface $product, - OrderItemUnitInterface $orderItemUnit, - GiftCardInterface $giftCard, - GiftCardFactoryInterface $giftCardFactory, - EntityManagerInterface $giftCardManager - ): void { - $product->isGiftCard()->willReturn(true); - - $orderItem->getProduct()->willReturn($product); - $orderItem->getUnits()->willReturn(new ArrayCollection([$orderItemUnit->getWrappedObject()])); - $order->getItems()->willReturn(new ArrayCollection([$orderItem->getWrappedObject()])); - - $giftCardFactory->createFromOrderItemUnit($orderItemUnit)->willReturn($giftCard); - - $giftCardManager->persist($giftCard)->shouldBeCalled(); - $giftCardManager->flush()->shouldBeCalled(); - - $this->create($order); - } - - public function it_enables_gift_cards_on_given_order( - OrderInterface $order, - OrderItemInterface $orderItem, - ProductInterface $product, - OrderItemUnitInterface $orderItemUnit, - GiftCardInterface $giftCard, - GiftCardRepositoryInterface $giftCardRepository, - EntityManagerInterface $giftCardManager - ): void { - $product->isGiftCard()->willReturn(true); - - $orderItem->getProduct()->willReturn($product); - $orderItem->getUnits()->willReturn(new ArrayCollection([$orderItemUnit->getWrappedObject()])); - $order->getItems()->willReturn(new ArrayCollection([$orderItem->getWrappedObject()])); - - $giftCardRepository->findOneByOrderItemUnit($orderItemUnit)->willReturn($giftCard); - - $giftCard->enable()->shouldBeCalled(); - - $giftCardManager->flush()->shouldBeCalled(); - - $this->enable($order); - } - - public function it_disables_gift_cards_on_given_order( - OrderInterface $order, - OrderItemInterface $orderItem, - ProductInterface $product, - OrderItemUnitInterface $orderItemUnit, - GiftCardInterface $giftCard, - GiftCardRepositoryInterface $giftCardRepository, - EntityManagerInterface $giftCardManager - ): void { - $product->isGiftCard()->willReturn(true); - - $orderItem->getProduct()->willReturn($product); - $orderItem->getUnits()->willReturn(new ArrayCollection([$orderItemUnit->getWrappedObject()])); - $order->getItems()->willReturn(new ArrayCollection([$orderItem->getWrappedObject()])); - - $giftCardRepository->findOneByOrderItemUnit($orderItemUnit)->willReturn($giftCard); - - $giftCard->disable()->shouldBeCalled(); - - $giftCardManager->flush()->shouldBeCalled(); - - $this->disable($order); - } - - public function it_sends_gift_cards_on_given_order( - OrderInterface $order, - OrderItemInterface $orderItem, - ProductInterface $product, - OrderItemUnitInterface $orderItemUnit, - GiftCardInterface $giftCard, - GiftCardRepositoryInterface $giftCardRepository, - GiftCardEmailManagerInterface $giftCardOrderEmailManager - ): void { - $product->isGiftCard()->willReturn(true); - - $orderItem->getProduct()->willReturn($product); - $orderItem->getUnits()->willReturn(new ArrayCollection([$orderItemUnit->getWrappedObject()])); - $order->getItems()->willReturn(new ArrayCollection([$orderItem->getWrappedObject()])); - - $giftCardRepository->findOneByOrderItemUnit($orderItemUnit)->willReturn($giftCard); - - $giftCardOrderEmailManager->sendEmailWithGiftCardsFromOrder($order, [$giftCard])->shouldBeCalled(); - - $this->send($order); - } -} diff --git a/src/Factory/GiftCardFactory.php b/src/Factory/GiftCardFactory.php index a941b13d..5345a9ed 100644 --- a/src/Factory/GiftCardFactory.php +++ b/src/Factory/GiftCardFactory.php @@ -46,27 +46,32 @@ public function createFromOrderItemUnit(OrderItemUnitInterface $orderItemUnit): { /** @var OrderInterface|null $order */ $order = $orderItemUnit->getOrderItem()->getOrder(); - Assert::isInstanceOf($order, OrderInterface::class); - /** @var ChannelInterface|null $channel */ - $channel = $order->getChannel(); - - Assert::isInstanceOf($channel, ChannelInterface::class); - - $currencyCode = $order->getCurrencyCode(); - Assert::notNull($currencyCode); - /** @var CustomerInterface|null $customer */ $customer = $order->getCustomer(); Assert::isInstanceOf($customer, CustomerInterface::class); - $giftCard = $this->createNew(); + $giftCard = $this->createFromOrderItemUnitAndCart($orderItemUnit, $order); $giftCard->setCustomer($customer); + + return $giftCard; + } + + public function createFromOrderItemUnitAndCart( + OrderItemUnitInterface $orderItemUnit, + OrderInterface $cart + ): GiftCardInterface { + $channel = $cart->getChannel(); + Assert::isInstanceOf($channel, ChannelInterface::class); + $currencyCode = $cart->getCurrencyCode(); + Assert::notNull($currencyCode); + + $giftCard = $this->createNew(); $giftCard->setOrderItemUnit($orderItemUnit); - $giftCard->setChannel($channel); $giftCard->setAmount($orderItemUnit->getTotal()); $giftCard->setCurrencyCode($currencyCode); + $giftCard->setChannel($channel); $giftCard->disable(); return $giftCard; diff --git a/src/Factory/GiftCardFactoryInterface.php b/src/Factory/GiftCardFactoryInterface.php index 00c1c59c..faa92257 100644 --- a/src/Factory/GiftCardFactoryInterface.php +++ b/src/Factory/GiftCardFactoryInterface.php @@ -7,6 +7,7 @@ use Setono\SyliusGiftCardPlugin\Model\GiftCardInterface; use Setono\SyliusGiftCardPlugin\Model\OrderItemUnitInterface; use Sylius\Component\Core\Model\ChannelInterface; +use Sylius\Component\Core\Model\OrderInterface; use Sylius\Component\Resource\Factory\FactoryInterface; interface GiftCardFactoryInterface extends FactoryInterface @@ -16,4 +17,9 @@ public function createNew(): GiftCardInterface; public function createForChannel(ChannelInterface $channel): GiftCardInterface; public function createFromOrderItemUnit(OrderItemUnitInterface $orderItemUnit): GiftCardInterface; + + public function createFromOrderItemUnitAndCart( + OrderItemUnitInterface $orderItemUnit, + OrderInterface $cart + ): GiftCardInterface; } diff --git a/src/Form/Extension/AddToCartTypeExtension.php b/src/Form/Extension/AddToCartTypeExtension.php new file mode 100644 index 00000000..4920529a --- /dev/null +++ b/src/Form/Extension/AddToCartTypeExtension.php @@ -0,0 +1,102 @@ +giftCardFactory = $giftCardFactory; + $this->giftCardManager = $giftCardManager; + } + + public static function getExtendedTypes(): iterable + { + return [ + AddToCartType::class, + ]; + } + + public function buildForm(FormBuilderInterface $builder, array $options): void + { + $builder->addEventListener(FormEvents::PRE_SET_DATA, [$this, 'reworkFormForGiftCard']); + + $builder->addEventListener(FormEvents::POST_SUBMIT, [$this, 'populateCartItem']); + } + + public function reworkFormForGiftCard(FormEvent $event): void + { + /** @var AddToCartCommandInterface|null $data */ + $data = $event->getData(); + if (null === $data) { + return; + } + + /** @var ProductInterface|null $product */ + $product = $data->getCartItem()->getProduct(); + if (null === $product) { + return; + } + + // If the product is a gift card, we add the GiftCardInformation fields + if ($product->isGiftCard()) { + $form = $event->getForm(); + $form->add('giftCardInformation', AddToCartGiftCardInformationType::class, [ + 'product' => $product, + ]); + } + } + + public function populateCartItem(FormEvent $event): void + { + /** @var AddToCartCommandInterface|null $data */ + $data = $event->getData(); + if (null === $data) { + return; + } + + /** @var ProductInterface|null $product */ + $product = $data->getCartItem()->getProduct(); + if (null === $product) { + return; + } + + $cartItem = $data->getCartItem(); + $giftCardInformation = $data->getGiftCardInformation(); + + if ($product->isGiftCardAmountConfigurable()) { + $cartItem->setUnitPrice($giftCardInformation->getAmount()); + $cartItem->setImmutable(true); + } + + $cart = $data->getCart(); + /** @var OrderItemUnitInterface $unit */ + foreach ($cartItem->getUnits() as $unit) { + $giftCard = $this->giftCardFactory->createFromOrderItemUnitAndCart($unit, $cart); + $giftCard->setCustomMessage($giftCardInformation->getCustomMessage()); + + // As the common flow for any add to cart action will flush later. Do not flush here. + $this->giftCardManager->persist($giftCard); + } + } +} diff --git a/src/Form/Extension/ProductTypeExtension.php b/src/Form/Extension/ProductTypeExtension.php index 77ec36ef..88f624da 100644 --- a/src/Form/Extension/ProductTypeExtension.php +++ b/src/Form/Extension/ProductTypeExtension.php @@ -17,6 +17,10 @@ public function buildForm(FormBuilderInterface $builder, array $options): void 'required' => false, 'label' => 'setono_sylius_gift_card.form.product.gift_card', ]); + $builder->add('giftCardAmountConfigurable', CheckboxType::class, [ + 'required' => false, + 'label' => 'setono_sylius_gift_card.form.product.gift_card_amount_configurable', + ]); } public static function getExtendedTypes(): iterable diff --git a/src/Form/Type/AddToCartGiftCardInformationType.php b/src/Form/Type/AddToCartGiftCardInformationType.php new file mode 100644 index 00000000..cb963d55 --- /dev/null +++ b/src/Form/Type/AddToCartGiftCardInformationType.php @@ -0,0 +1,56 @@ +dataClass = $dataClass; + $this->validationGroups = $validationGroups; + } + + public function buildForm(FormBuilderInterface $builder, array $options): void + { + $builder->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) use ($options): void { + $form = $event->getForm(); + /** @var ProductInterface|null $product */ + $product = $options['product']; + if (null === $product || !$product->isGiftCardAmountConfigurable()) { + return; + } + + $form->add('amount', MoneyType::class, [ + 'label' => 'setono_sylius_gift_card.form.add_to_cart.gift_card_information.amount', + ]); + }); + + $builder->add('customMessage', TextareaType::class, [ + 'required' => false, + 'label' => 'setono_sylius_gift_card.form.add_to_cart.gift_card_information.custom_message', + ]); + } + + public function configureOptions(OptionsResolver $resolver): void + { + $resolver->setDefault('data_class', $this->dataClass); + $resolver->setDefault('validation_groups', $this->validationGroups); + $resolver->setDefault('product', null); + $resolver->addAllowedTypes('product', ['null', ProductInterface::class]); + } +} diff --git a/src/Model/GiftCard.php b/src/Model/GiftCard.php index 4ce4c8d0..d800af97 100644 --- a/src/Model/GiftCard.php +++ b/src/Model/GiftCard.php @@ -42,6 +42,8 @@ class GiftCard implements GiftCardInterface protected ?ChannelInterface $channel = null; + protected ?string $customMessage = null; + public function __construct() { $this->appliedOrders = new ArrayCollection(); @@ -245,4 +247,14 @@ public function hasOrderOrCustomer(): bool { return null !== $this->getCustomer() || null !== $this->getOrder(); } + + public function getCustomMessage(): ?string + { + return $this->customMessage; + } + + public function setCustomMessage(?string $customMessage): void + { + $this->customMessage = $customMessage; + } } diff --git a/src/Model/GiftCardInterface.php b/src/Model/GiftCardInterface.php index bea0eac3..30e3caea 100644 --- a/src/Model/GiftCardInterface.php +++ b/src/Model/GiftCardInterface.php @@ -107,4 +107,8 @@ public function getOrderIdentification(): ?array; public function getChannelCode(): ?string; public function hasOrderOrCustomer(): bool; + + public function getCustomMessage(): ?string; + + public function setCustomMessage(?string $customMessage): void; } diff --git a/src/Model/OrderItemTrait.php b/src/Model/OrderItemTrait.php new file mode 100644 index 00000000..2d4a40d1 --- /dev/null +++ b/src/Model/OrderItemTrait.php @@ -0,0 +1,15 @@ +getProduct()->isGiftCard(); + } +} diff --git a/src/Model/ProductInterface.php b/src/Model/ProductInterface.php index bccfed28..bfbb3386 100644 --- a/src/Model/ProductInterface.php +++ b/src/Model/ProductInterface.php @@ -14,4 +14,11 @@ interface ProductInterface extends BaseProductInterface public function isGiftCard(): bool; public function setGiftCard(bool $isGiftCard): void; + + /** + * True if product is a gift card with configurable amount + */ + public function isGiftCardAmountConfigurable(): bool; + + public function setGiftCardAmountConfigurable(bool $giftCardAmountConfigurable): void; } diff --git a/src/Model/ProductTrait.php b/src/Model/ProductTrait.php index 80b02dd2..e4bad295 100644 --- a/src/Model/ProductTrait.php +++ b/src/Model/ProductTrait.php @@ -11,6 +11,9 @@ trait ProductTrait /** @ORM\Column(type="boolean", options={"default": false}) */ protected bool $giftCard = false; + /** @ORM\Column(type="boolean", options={"default": false}) */ + protected bool $giftCardAmountConfigurable = false; + public function isGiftCard(): bool { return $this->giftCard; @@ -20,4 +23,14 @@ public function setGiftCard(bool $isGiftCard): void { $this->giftCard = $isGiftCard; } + + public function isGiftCardAmountConfigurable(): bool + { + return $this->giftCardAmountConfigurable; + } + + public function setGiftCardAmountConfigurable(bool $giftCardAmountConfigurable): void + { + $this->giftCardAmountConfigurable = $giftCardAmountConfigurable; + } } diff --git a/src/Operator/OrderGiftCardOperator.php b/src/Operator/OrderGiftCardOperator.php index 86c6c749..44d9a57d 100644 --- a/src/Operator/OrderGiftCardOperator.php +++ b/src/Operator/OrderGiftCardOperator.php @@ -7,11 +7,10 @@ use Doctrine\Common\Collections\Collection; use Doctrine\ORM\EntityManagerInterface; use Setono\SyliusGiftCardPlugin\EmailManager\GiftCardEmailManagerInterface; -use Setono\SyliusGiftCardPlugin\Factory\GiftCardFactoryInterface; use Setono\SyliusGiftCardPlugin\Model\GiftCardInterface; use Setono\SyliusGiftCardPlugin\Model\OrderItemUnitInterface; use Setono\SyliusGiftCardPlugin\Model\ProductInterface; -use Setono\SyliusGiftCardPlugin\Repository\GiftCardRepositoryInterface; +use Sylius\Component\Core\Model\CustomerInterface; use Sylius\Component\Core\Model\OrderInterface; use Sylius\Component\Core\Model\OrderItemInterface; use Webmozart\Assert\Assert; @@ -22,27 +21,19 @@ */ final class OrderGiftCardOperator implements OrderGiftCardOperatorInterface { - private GiftCardFactoryInterface $giftCardFactory; - - private GiftCardRepositoryInterface $giftCardRepository; - private EntityManagerInterface $giftCardManager; private GiftCardEmailManagerInterface $giftCardOrderEmailManager; public function __construct( - GiftCardFactoryInterface $giftCardFactory, - GiftCardRepositoryInterface $giftCardRepository, EntityManagerInterface $giftCardManager, GiftCardEmailManagerInterface $giftCardOrderEmailManager ) { - $this->giftCardFactory = $giftCardFactory; - $this->giftCardRepository = $giftCardRepository; $this->giftCardManager = $giftCardManager; $this->giftCardOrderEmailManager = $giftCardOrderEmailManager; } - public function create(OrderInterface $order): void + public function associateToCustomer(OrderInterface $order): void { $items = self::getOrderItemsThatAreGiftCards($order); @@ -50,12 +41,17 @@ public function create(OrderInterface $order): void return; } + /** @var CustomerInterface|null $customer */ + $customer = $order->getCustomer(); + Assert::isInstanceOf($customer, CustomerInterface::class); + foreach ($items as $item) { /** @var OrderItemUnitInterface $unit */ foreach ($item->getUnits() as $unit) { - $giftCard = $this->giftCardFactory->createFromOrderItemUnit($unit); + $giftCard = $unit->getGiftCard(); + Assert::notNull($giftCard); - $this->giftCardManager->persist($giftCard); + $giftCard->setCustomer($customer); } } @@ -120,7 +116,7 @@ private function getGiftCards(OrderInterface $order): array foreach ($items as $item) { /** @var OrderItemUnitInterface $unit */ foreach ($item->getUnits() as $unit) { - $giftCard = $this->giftCardRepository->findOneByOrderItemUnit($unit); + $giftCard = $unit->getGiftCard(); if (null === $giftCard) { continue; } diff --git a/src/Operator/OrderGiftCardOperatorInterface.php b/src/Operator/OrderGiftCardOperatorInterface.php index 107e7194..0107d64d 100644 --- a/src/Operator/OrderGiftCardOperatorInterface.php +++ b/src/Operator/OrderGiftCardOperatorInterface.php @@ -11,7 +11,7 @@ interface OrderGiftCardOperatorInterface /** * Will create and persist all gift cards on the given order */ - public function create(OrderInterface $order): void; + public function associateToCustomer(OrderInterface $order): void; public function enable(OrderInterface $order): void; diff --git a/src/Order/AddToCartCommand.php b/src/Order/AddToCartCommand.php new file mode 100644 index 00000000..bccd0154 --- /dev/null +++ b/src/Order/AddToCartCommand.php @@ -0,0 +1,42 @@ +cart = $cart; + $this->cartItem = $cartItem; + $this->giftCardInformation = $giftCardInformation; + } + + public function getCart(): OrderInterface + { + return $this->cart; + } + + public function getCartItem(): OrderItemInterface + { + return $this->cartItem; + } + + public function getGiftCardInformation(): GiftCardInformationInterface + { + return $this->giftCardInformation; + } +} diff --git a/src/Order/AddToCartCommandInterface.php b/src/Order/AddToCartCommandInterface.php new file mode 100644 index 00000000..fb205306 --- /dev/null +++ b/src/Order/AddToCartCommandInterface.php @@ -0,0 +1,18 @@ + */ + private string $className; + + private GiftCardInformationFactoryInterface $giftCardInformationFactory; + + /** + * @param class-string $className + */ + public function __construct( + string $className, + GiftCardInformationFactoryInterface $giftCardInformationFactory + ) { + $this->className = $className; + $this->giftCardInformationFactory = $giftCardInformationFactory; + } + + public function createWithCartAndCartItem(OrderInterface $cart, OrderItemInterface $cartItem): AddToCartCommandInterface + { + return new $this->className($cart, $cartItem, $this->giftCardInformationFactory->createNew($cartItem)); + } +} diff --git a/src/Order/Factory/GiftCardInformationFactory.php b/src/Order/Factory/GiftCardInformationFactory.php new file mode 100644 index 00000000..5275433b --- /dev/null +++ b/src/Order/Factory/GiftCardInformationFactory.php @@ -0,0 +1,27 @@ + */ + private string $className; + + /** + * @param class-string $className + */ + public function __construct(string $className) + { + $this->className = $className; + } + + public function createNew(OrderItemInterface $orderItem): GiftCardInformationInterface + { + return new $this->className($orderItem->getUnitPrice()); + } +} diff --git a/src/Order/Factory/GiftCardInformationFactoryInterface.php b/src/Order/Factory/GiftCardInformationFactoryInterface.php new file mode 100644 index 00000000..89bb3d30 --- /dev/null +++ b/src/Order/Factory/GiftCardInformationFactoryInterface.php @@ -0,0 +1,13 @@ +amount = $amount; + $this->customMessage = $customMessage; + } + + public function getAmount(): int + { + return $this->amount; + } + + public function setAmount(int $amount): void + { + $this->amount = $amount; + } + + public function getCustomMessage(): ?string + { + return $this->customMessage; + } + + public function setCustomMessage(?string $customMessage): void + { + $this->customMessage = $customMessage; + } +} diff --git a/src/Order/GiftCardInformationInterface.php b/src/Order/GiftCardInformationInterface.php new file mode 100644 index 00000000..440c73dc --- /dev/null +++ b/src/Order/GiftCardInformationInterface.php @@ -0,0 +1,16 @@ + + diff --git a/src/Resources/config/services.xml b/src/Resources/config/services.xml index 95096bbc..7a16b9fb 100644 --- a/src/Resources/config/services.xml +++ b/src/Resources/config/services.xml @@ -14,6 +14,7 @@ + diff --git a/src/Resources/config/services/form.xml b/src/Resources/config/services/form.xml index 8245ce07..a8b2f720 100644 --- a/src/Resources/config/services/form.xml +++ b/src/Resources/config/services/form.xml @@ -27,6 +27,10 @@ setono_sylius_gift_card + + + sylius + + + + + + + @@ -47,6 +58,13 @@ + + %setono_sylius_gift_card.order.model.gift_card_information.class% + %setono_sylius_gift_card.form.type.add_to_cart_gift_card_information.validation_groups% + + + %setono_sylius_gift_card.model.gift_card.class% diff --git a/src/Resources/config/services/misc.xml b/src/Resources/config/services/misc.xml index 0a7c053f..22814a10 100644 --- a/src/Resources/config/services/misc.xml +++ b/src/Resources/config/services/misc.xml @@ -28,8 +28,6 @@ - - diff --git a/src/Resources/config/services/order.xml b/src/Resources/config/services/order.xml new file mode 100644 index 00000000..9bdf1023 --- /dev/null +++ b/src/Resources/config/services/order.xml @@ -0,0 +1,30 @@ + + + + Setono\SyliusGiftCardPlugin\Order\GiftCardInformation + Setono\SyliusGiftCardPlugin\Order\AddToCartCommand + + + + + %setono_sylius_gift_card.order.model.gift_card_information.class% + + + + + %setono_sylius_gift_card.order.model.add_to_cart_command.class% + + + + + %setono_sylius_gift_card.order.model.add_to_cart_command.class% + %sylius.form.type.add_to_cart.validation_groups% + + + + diff --git a/src/Resources/config/state_machine/sylius_order_checkout.yaml b/src/Resources/config/state_machine/sylius_order_checkout.yaml index 3756458e..12c9d934 100644 --- a/src/Resources/config/state_machine/sylius_order_checkout.yaml +++ b/src/Resources/config/state_machine/sylius_order_checkout.yaml @@ -2,7 +2,7 @@ winzou_state_machine: sylius_order_checkout: callbacks: after: - setono_gift_card_create: + setono_gift_card_associate_to_customer: on: ["complete"] - do: ["@setono_sylius_gift_card.operator.order_gift_card", "create"] + do: ["@setono_sylius_gift_card.operator.order_gift_card", "associateToCustomer"] args: ["object"] diff --git a/src/Resources/config/sylius_ui.yaml b/src/Resources/config/sylius_ui.yaml new file mode 100644 index 00000000..7a641d5e --- /dev/null +++ b/src/Resources/config/sylius_ui.yaml @@ -0,0 +1,7 @@ +sylius_ui: + events: + sylius.shop.product.show.add_to_cart_form: + blocks: + setono_sylius_gift_card_information: + template: '@SetonoSyliusGiftCardPlugin/Shop/Product/Show/_addToCartGiftCardInformation.html.twig' + priority: 10 diff --git a/src/Resources/config/validation/AddToCardCommand.xml b/src/Resources/config/validation/AddToCardCommand.xml new file mode 100644 index 00000000..2f3db908 --- /dev/null +++ b/src/Resources/config/validation/AddToCardCommand.xml @@ -0,0 +1,12 @@ + + + + + + + + + + diff --git a/src/Resources/config/validation/AddToCardGiftCardInformation.xml b/src/Resources/config/validation/AddToCardGiftCardInformation.xml new file mode 100644 index 00000000..4487e211 --- /dev/null +++ b/src/Resources/config/validation/AddToCardGiftCardInformation.xml @@ -0,0 +1,12 @@ + + + + + + + + + + diff --git a/src/Resources/translations/messages.da.yml b/src/Resources/translations/messages.da.yml index 4f2d46a3..a1cd38fa 100644 --- a/src/Resources/translations/messages.da.yml +++ b/src/Resources/translations/messages.da.yml @@ -1,5 +1,9 @@ setono_sylius_gift_card: form: + add_to_cart: + gift_card_information: + amount: Beløb + custom_message: Personlig besked channel_configuration: channel: Kanal locale: Lokalitet @@ -13,6 +17,7 @@ setono_sylius_gift_card: enabled: Aktiveret product: gift_card: Gavekort + gift_card_amount_configurable: Valgfrit beløb på gavekort ui: active: Aktiv add_gift_card_to_order: Tilføj gavekort diff --git a/src/Resources/translations/messages.en.yml b/src/Resources/translations/messages.en.yml index 4cd4f452..3805012a 100644 --- a/src/Resources/translations/messages.en.yml +++ b/src/Resources/translations/messages.en.yml @@ -1,5 +1,9 @@ setono_sylius_gift_card: form: + add_to_cart: + gift_card_information: + amount: Amount + custom_message: Custom message channel_configuration: channel: Channel locale: Locale @@ -13,6 +17,7 @@ setono_sylius_gift_card: enabled: Enabled product: gift_card: Gift card + gift_card_amount_configurable: Gift card amount configurable ui: active: Active add_gift_card_to_order: Add gift card diff --git a/src/Resources/translations/messages.fr.yml b/src/Resources/translations/messages.fr.yml index cf122076..d2b25492 100644 --- a/src/Resources/translations/messages.fr.yml +++ b/src/Resources/translations/messages.fr.yml @@ -1,5 +1,9 @@ setono_sylius_gift_card: form: + add_to_cart: + gift_card_information: + amount: Valeure + custom_message: Message personnalisé channel_configuration: channel: Canal locale: Langue @@ -13,6 +17,7 @@ setono_sylius_gift_card: enabled: Activé product: gift_card: Chèque-cadeau + gift_card_amount_configurable: Montant chèque-cadeau configurable ui: active: Actif add_gift_card_to_order: Ajouter le chèque-cadeau diff --git a/src/Resources/views/Shop/Product/Show/_addToCartGiftCardInformation.html.twig b/src/Resources/views/Shop/Product/Show/_addToCartGiftCardInformation.html.twig new file mode 100644 index 00000000..63d1c883 --- /dev/null +++ b/src/Resources/views/Shop/Product/Show/_addToCartGiftCardInformation.html.twig @@ -0,0 +1,7 @@ +{% if form.giftCardInformation is defined %} + {% set giftCardInformationForm = form.giftCardInformation %} + {% if giftCardInformationForm.amount is defined %} + {{ form_row(giftCardInformationForm.amount) }} + {% endif %} + {{ form_row(giftCardInformationForm.customMessage) }} +{% endif %} diff --git a/tests/Application/Model/OrderItem.php b/tests/Application/Model/OrderItem.php new file mode 100644 index 00000000..0dbc85e0 --- /dev/null +++ b/tests/Application/Model/OrderItem.php @@ -0,0 +1,21 @@ +prophesize(FactoryInterface::class); + $giftCardCodeGenerator = $this->prophesize(GiftCardCodeGeneratorInterface::class); + + $decoratedFactory->createNew()->willReturn($giftCard); + $giftCardCodeGenerator->generate()->willReturn('super-code'); + + $factory = new GiftCardFactory($decoratedFactory->reveal(), $giftCardCodeGenerator->reveal()); + $createdGiftCard = $factory->createNew(); + + $this->assertSame($giftCard, $createdGiftCard); + $this->assertSame('super-code', $createdGiftCard->getCode()); + } + + /** + * @test + */ + public function it_creates_a_new_gift_card_for_channel(): void + { + $giftCard = new GiftCard(); + $channel = new Channel(); + + $decoratedFactory = $this->prophesize(FactoryInterface::class); + $giftCardCodeGenerator = $this->prophesize(GiftCardCodeGeneratorInterface::class); + + $decoratedFactory->createNew()->willReturn($giftCard); + $giftCardCodeGenerator->generate()->willReturn('super-code'); + + $factory = new GiftCardFactory($decoratedFactory->reveal(), $giftCardCodeGenerator->reveal()); + $createdGiftCard = $factory->createForChannel($channel); + + $this->assertSame($giftCard, $createdGiftCard); + $this->assertSame($channel, $createdGiftCard->getChannel()); + } + + /** + * @test + */ + public function it_creates_a_new_gift_card_for_order_item_unit_and_cart(): void + { + $giftCard = new GiftCard(); + $channel = new Channel(); + $currencyCode = 'USD'; + $cart = new Order(); + $cart->setChannel($channel); + $cart->setCurrencyCode($currencyCode); + $orderItemUnit = $this->prophesize(OrderItemUnit::class); + $orderItemUnit->getTotal()->willReturn(1000); + + $decoratedFactory = $this->prophesize(FactoryInterface::class); + $giftCardCodeGenerator = $this->prophesize(GiftCardCodeGeneratorInterface::class); + + $decoratedFactory->createNew()->willReturn($giftCard); + $giftCardCodeGenerator->generate()->willReturn('super-code'); + + $factory = new GiftCardFactory($decoratedFactory->reveal(), $giftCardCodeGenerator->reveal()); + $createdGiftCard = $factory->createFromOrderItemUnitAndCart($orderItemUnit->reveal(), $cart); + + $orderItemUnit->setGiftCard($giftCard)->shouldBeCalled(); + $this->assertSame($giftCard, $createdGiftCard); + $this->assertSame($channel, $createdGiftCard->getChannel()); + $this->assertSame($currencyCode, $createdGiftCard->getCurrencyCode()); + $this->assertSame($currencyCode, $createdGiftCard->getCurrencyCode()); + $this->assertSame(1000, $createdGiftCard->getAmount()); + $this->assertFalse($createdGiftCard->isEnabled()); + } + + /** + * @test + */ + public function it_creates_a_new_gift_card_for_order_item_unit(): void + { + $giftCard = new GiftCard(); + $channel = new Channel(); + $currencyCode = 'USD'; + $customer = new Customer(); + $cart = new Order(); + $cart->setChannel($channel); + $cart->setCurrencyCode($currencyCode); + $cart->setCustomer($customer); + $orderItem = new OrderItem(); + $orderItem->setOrder($cart); + $orderItemUnit = $this->prophesize(OrderItemUnit::class); + $orderItemUnit->getTotal()->willReturn(1000); + $orderItemUnit->getOrderItem()->willReturn($orderItem); + + $decoratedFactory = $this->prophesize(FactoryInterface::class); + $giftCardCodeGenerator = $this->prophesize(GiftCardCodeGeneratorInterface::class); + + $decoratedFactory->createNew()->willReturn($giftCard); + $giftCardCodeGenerator->generate()->willReturn('super-code'); + + $factory = new GiftCardFactory($decoratedFactory->reveal(), $giftCardCodeGenerator->reveal()); + $createdGiftCard = $factory->createFromOrderItemUnit($orderItemUnit->reveal()); + + $orderItemUnit->setGiftCard($giftCard)->shouldBeCalled(); + $this->assertSame($giftCard, $createdGiftCard); + $this->assertSame($channel, $createdGiftCard->getChannel()); + $this->assertSame($currencyCode, $createdGiftCard->getCurrencyCode()); + $this->assertSame($currencyCode, $createdGiftCard->getCurrencyCode()); + $this->assertSame(1000, $createdGiftCard->getAmount()); + $this->assertSame($customer, $createdGiftCard->getCustomer()); + $this->assertFalse($createdGiftCard->isEnabled()); + } +} diff --git a/tests/Unit/Model/GiftCardTest.php b/tests/Unit/Model/GiftCardTest.php new file mode 100644 index 00000000..0cde0d5d --- /dev/null +++ b/tests/Unit/Model/GiftCardTest.php @@ -0,0 +1,134 @@ +prophesize(OrderItemUnitInterface::class); + $customer = new Customer(); + $giftCard = new GiftCard(); + $channel = new Channel(); + + $giftCard->setCode('test-code'); + $this->assertSame('test-code', $giftCard->getCode()); + + $giftCard->setOrderItemUnit($orderItemUnit->reveal()); + $this->assertSame($orderItemUnit->reveal(), $giftCard->getOrderItemUnit()); + + $giftCard->setCustomer($customer); + $this->assertSame($customer, $giftCard->getCustomer()); + + $giftCard->setInitialAmount(25000); + $this->assertSame(25000, $giftCard->getInitialAmount()); + + $giftCard->setAmount(25000); + $this->assertSame(25000, $giftCard->getAmount()); + + $giftCard->addAppliedOrder(new Order()); + $giftCard->addAppliedOrder(new Order()); + $this->assertSame(2, $giftCard->getAppliedOrders()->count()); + + $giftCard->setCurrencyCode('EUR'); + $this->assertSame('EUR', $giftCard->getCurrencyCode()); + + $giftCard->setChannel($channel); + $this->assertSame($channel, $giftCard->getChannel()); + + $giftCard->setCustomMessage('custom message'); + $this->assertSame('custom message', $giftCard->getCustomMessage()); + } + + /** + * @test + */ + public function it_can_be_converted_to_string(): void + { + $giftCard = new GiftCard(); + $giftCard->setCode('test-code'); + $this->assertSame('test-code', $giftCard->__toString()); + } + + /** + * @test + */ + public function it_can_be_deletable(): void + { + $giftCard = new GiftCard(); + $this->assertSame(true, $giftCard->isDeletable()); + } + + /** + * @test + */ + public function it_is_not_deletable_if_it_has_order_item_unit(): void + { + $orderItemUnit = $this->prophesize(OrderItemUnitInterface::class); + $giftCard = new GiftCard(); + $giftCard->setOrderItemUnit($orderItemUnit->reveal()); + $this->assertSame(false, $giftCard->isDeletable()); + } + + /** + * @test + */ + public function it_has_order_from_order_item_unit(): void + { + $giftCard = new GiftCard(); + $this->assertNull($giftCard->getOrder()); + + $orderItemUnit = $this->prophesize(OrderItemUnitInterface::class); + $orderItem = new OrderItem(); + $orderItemUnit->getOrderItem()->willReturn($orderItem); + $giftCard->setOrderItemUnit($orderItemUnit->reveal()); + $orderItemUnit->setGiftCard($giftCard)->shouldBeCalled(); + + $this->assertNull($giftCard->getOrder()); + + $order = new Order(); + $orderItem->setOrder($order); + + $this->assertSame($order, $giftCard->getOrder()); + } + + /** + * @test + */ + public function it_has_applied_orders(): void + { + $giftCard = new GiftCard(); + + $this->assertFalse($giftCard->hasAppliedOrders()); + + $order1 = new Order(); + $giftCard->addAppliedOrder($order1); + $this->assertSame(1, $giftCard->getAppliedOrders()->count()); + $this->assertTrue($giftCard->hasAppliedOrder($order1)); + + $order2 = new Order(); + $giftCard->addAppliedOrder($order2); + $this->assertSame(2, $giftCard->getAppliedOrders()->count()); + $this->assertTrue($giftCard->hasAppliedOrder($order2)); + + $giftCard->removeAppliedOrder($order1); + $this->assertSame(1, $giftCard->getAppliedOrders()->count()); + $this->assertFalse($giftCard->hasAppliedOrder($order1)); + } +} diff --git a/tests/Unit/Model/OrderItemTraitTest.php b/tests/Unit/Model/OrderItemTraitTest.php new file mode 100644 index 00000000..2fde6aba --- /dev/null +++ b/tests/Unit/Model/OrderItemTraitTest.php @@ -0,0 +1,35 @@ +setProduct($product); + $firstOrderItem->setVariant($variant); + + $variant->setProduct($product); + $secondOrderItem->setVariant($variant); + + $this->assertTrue($firstOrderItem->equals($secondOrderItem)); + + $product->setGiftCard(true); + $this->assertFalse($firstOrderItem->equals($secondOrderItem)); + } +} diff --git a/tests/Unit/Model/ProductTraitTest.php b/tests/Unit/Model/ProductTraitTest.php new file mode 100644 index 00000000..7ee90463 --- /dev/null +++ b/tests/Unit/Model/ProductTraitTest.php @@ -0,0 +1,25 @@ +setGiftCard(true); + $this->assertTrue($product->isGiftCard()); + + $product->setGiftCardAmountConfigurable(true); + $this->assertTrue($product->isGiftCardAmountConfigurable()); + } +} diff --git a/tests/Unit/Operator/GiftCardOperatorTest.php b/tests/Unit/Operator/GiftCardOperatorTest.php new file mode 100644 index 00000000..d36cd3f2 --- /dev/null +++ b/tests/Unit/Operator/GiftCardOperatorTest.php @@ -0,0 +1,157 @@ +setCustomer($customer); + + $product = new Product(); + $product->setGiftCard(true); + $productVariant = new ProductVariant(); + $productVariant->setProduct($product); + $orderItemUnit = $this->prophesize(OrderItemUnit::class); + $orderItemUnit->getGiftCard()->willReturn($giftCard); + $orderItem = $this->prophesize(OrderItem::class); + $orderItem->getVariant()->willReturn($productVariant); + $orderItem->getProduct()->willReturn($product); + $orderItem->getUnits()->willReturn(new ArrayCollection([$orderItemUnit->reveal()])); + $orderItem->getTotal()->willReturn(0); + $orderItem->setOrder($order)->shouldBeCalled(); + $order->addItem($orderItem->reveal()); + + $giftCardManager = $this->prophesize(EntityManagerInterface::class); + $giftCardOrderEmailManager = $this->prophesize(GiftCardEmailManagerInterface::class); + + $orderGiftCardOperator = new OrderGiftCardOperator( + $giftCardManager->reveal(), + $giftCardOrderEmailManager->reveal() + ); + + $orderGiftCardOperator->associateToCustomer($order); + $this->assertEquals($customer, $giftCard->getCustomer()); + } + + /** + * @test + */ + public function it_returns_if_there_is_no_gift_card_item(): void + { + $order = $this->prophesize(Order::class); + $order->getItems()->willReturn(new ArrayCollection()); + + $giftCardManager = $this->prophesize(EntityManagerInterface::class); + $giftCardOrderEmailManager = $this->prophesize(GiftCardEmailManagerInterface::class); + + $orderGiftCardOperator = new OrderGiftCardOperator( + $giftCardManager->reveal(), + $giftCardOrderEmailManager->reveal() + ); + + $orderGiftCardOperator->associateToCustomer($order->reveal()); + $order->getCustomer()->shouldNotBeCalled(); + } + + /** + * @test + */ + public function it_enables_gift_card(): void + { + $order = new Order(); + $customer = new Customer(); + $giftCard = new GiftCard(); + $giftCard->setEnabled(false); + + $order->setCustomer($customer); + + $product = new Product(); + $product->setGiftCard(true); + $productVariant = new ProductVariant(); + $productVariant->setProduct($product); + $orderItemUnit = $this->prophesize(OrderItemUnit::class); + $orderItemUnit->getGiftCard()->willReturn($giftCard); + $orderItem = $this->prophesize(OrderItem::class); + $orderItem->getVariant()->willReturn($productVariant); + $orderItem->getProduct()->willReturn($product); + $orderItem->getUnits()->willReturn(new ArrayCollection([$orderItemUnit->reveal()])); + $orderItem->getTotal()->willReturn(0); + $orderItem->setOrder($order)->shouldBeCalled(); + $order->addItem($orderItem->reveal()); + + $giftCardManager = $this->prophesize(EntityManagerInterface::class); + $giftCardOrderEmailManager = $this->prophesize(GiftCardEmailManagerInterface::class); + + $orderGiftCardOperator = new OrderGiftCardOperator( + $giftCardManager->reveal(), + $giftCardOrderEmailManager->reveal() + ); + + $orderGiftCardOperator->enable($order); + $this->assertTrue($giftCard->isEnabled()); + } + + /** + * @test + */ + public function it_disables_gift_card(): void + { + $order = new Order(); + $customer = new Customer(); + $giftCard = new GiftCard(); + $giftCard->setEnabled(true); + + $order->setCustomer($customer); + + $product = new Product(); + $product->setGiftCard(true); + $productVariant = new ProductVariant(); + $productVariant->setProduct($product); + $orderItemUnit = $this->prophesize(OrderItemUnit::class); + $orderItemUnit->getGiftCard()->willReturn($giftCard); + $orderItem = $this->prophesize(OrderItem::class); + $orderItem->getVariant()->willReturn($productVariant); + $orderItem->getProduct()->willReturn($product); + $orderItem->getUnits()->willReturn(new ArrayCollection([$orderItemUnit->reveal()])); + $orderItem->getTotal()->willReturn(0); + $orderItem->setOrder($order)->shouldBeCalled(); + $order->addItem($orderItem->reveal()); + + $giftCardManager = $this->prophesize(EntityManagerInterface::class); + $giftCardOrderEmailManager = $this->prophesize(GiftCardEmailManagerInterface::class); + + $orderGiftCardOperator = new OrderGiftCardOperator( + $giftCardManager->reveal(), + $giftCardOrderEmailManager->reveal() + ); + + $orderGiftCardOperator->disable($order); + $this->assertFalse($giftCard->isEnabled()); + } +} diff --git a/tests/Unit/Order/AddToCartCommandTest.php b/tests/Unit/Order/AddToCartCommandTest.php new file mode 100644 index 00000000..cedfef3b --- /dev/null +++ b/tests/Unit/Order/AddToCartCommandTest.php @@ -0,0 +1,29 @@ +assertEquals($cart, $addToCartCommand->getCart()); + $this->assertEquals($cartItem, $addToCartCommand->getCartItem()); + $this->assertEquals($giftCardInformation, $addToCartCommand->getGiftCardInformation()); + } +} diff --git a/tests/Unit/Order/Factory/AddToCardCommandFactoryTest.php b/tests/Unit/Order/Factory/AddToCardCommandFactoryTest.php new file mode 100644 index 00000000..75255994 --- /dev/null +++ b/tests/Unit/Order/Factory/AddToCardCommandFactoryTest.php @@ -0,0 +1,33 @@ +createWithCartAndCartItem($cart, $cartItem); + $this->assertEquals($cart, $addToCartCommand->getCart()); + $this->assertEquals($cartItem, $addToCartCommand->getCartItem()); + $this->assertInstanceOf(GiftCardInformation::class, $addToCartCommand->getGiftCardInformation()); + } +} diff --git a/tests/Unit/Order/Factory/GiftCardInformationFactoryTest.php b/tests/Unit/Order/Factory/GiftCardInformationFactoryTest.php new file mode 100644 index 00000000..da8625b9 --- /dev/null +++ b/tests/Unit/Order/Factory/GiftCardInformationFactoryTest.php @@ -0,0 +1,25 @@ +setUnitPrice(2500); + $factory = new GiftCardInformationFactory(GiftCardInformation::class); + $giftCardInformation = $factory->createNew($orderItem); + $this->assertEquals($orderItem->getUnitPrice(), $giftCardInformation->getAmount()); + } +} diff --git a/tests/Unit/Order/GiftCardInformationTest.php b/tests/Unit/Order/GiftCardInformationTest.php new file mode 100644 index 00000000..a94135c8 --- /dev/null +++ b/tests/Unit/Order/GiftCardInformationTest.php @@ -0,0 +1,42 @@ +assertEquals($giftCardInformation->getAmount(), 80); + $this->assertEquals($giftCardInformation->getCustomMessage(), 'message'); + } + + /** + * @test + */ + public function it_has_settable_amount(): void + { + $giftCardInformation = new GiftCardInformation(80, 'message'); + $giftCardInformation->setAmount(200); + $this->assertEquals($giftCardInformation->getAmount(), 200); + } + + /** + * @test + */ + public function it_has_settable_message(): void + { + $giftCardInformation = new GiftCardInformation(80, 'message'); + $giftCardInformation->setCustomMessage('new message'); + $this->assertEquals($giftCardInformation->getCustomMessage(), 'new message'); + } +}