diff --git a/composer.json b/composer.json index cb2569150..bb6410130 100644 --- a/composer.json +++ b/composer.json @@ -30,7 +30,8 @@ "autoload": { "psr-4": { "Mollie\\": "src/", - "Mollie\\Subscription\\": "subscription/" + "Mollie\\Subscription\\": "subscription/", + "Mollie\\Shared\\": "shared/" }, "classmap": [ "mollie.php", diff --git a/controllers/front/ajax.php b/controllers/front/ajax.php index 1df5a79fd..12c637541 100644 --- a/controllers/front/ajax.php +++ b/controllers/front/ajax.php @@ -15,7 +15,7 @@ use Mollie\Controller\AbstractMollieController; use Mollie\Exception\FailedToProvidePaymentFeeException; use Mollie\Provider\PaymentFeeProviderInterface; -use Mollie\Repository\CurrencyRepositoryInterface; +use Mollie\Shared\Infrastructure\Repository\CurrencyRepositoryInterface; use Mollie\Subscription\Exception\SubscriptionProductValidationException; use Mollie\Subscription\Validator\CanProductBeAddedToCartValidator; use Mollie\Utility\NumberUtility; diff --git a/src/Repository/CurrencyRepository.php b/shared/Infrastructure/Repository/CurrencyRepository.php similarity index 95% rename from src/Repository/CurrencyRepository.php rename to shared/Infrastructure/Repository/CurrencyRepository.php index 440b55379..039d36524 100644 --- a/src/Repository/CurrencyRepository.php +++ b/shared/Infrastructure/Repository/CurrencyRepository.php @@ -34,9 +34,10 @@ * @codingStandardsIgnoreStart */ -namespace Mollie\Repository; +namespace Mollie\Shared\Infrastructure\Repository; use Currency; +use Mollie\Repository\AbstractRepository; if (!defined('_PS_VERSION_')) { exit; diff --git a/src/Repository/CurrencyRepositoryInterface.php b/shared/Infrastructure/Repository/CurrencyRepositoryInterface.php similarity index 94% rename from src/Repository/CurrencyRepositoryInterface.php rename to shared/Infrastructure/Repository/CurrencyRepositoryInterface.php index 891e93609..9364f6272 100644 --- a/src/Repository/CurrencyRepositoryInterface.php +++ b/shared/Infrastructure/Repository/CurrencyRepositoryInterface.php @@ -34,7 +34,9 @@ * @codingStandardsIgnoreStart */ -namespace Mollie\Repository; +namespace Mollie\Shared\Infrastructure\Repository; + +use Mollie\Repository\ReadOnlyRepositoryInterface; if (!defined('_PS_VERSION_')) { exit; diff --git a/shared/Infrastructure/Repository/index.php b/shared/Infrastructure/Repository/index.php new file mode 100644 index 000000000..88355f610 --- /dev/null +++ b/shared/Infrastructure/Repository/index.php @@ -0,0 +1,11 @@ +addService($container, CountryRepositoryInterface::class, $container->get(CountryRepository::class)); $this->addService($container, PaymentMethodRepositoryInterface::class, $container->get(PaymentMethodRepository::class)); $this->addService($container, GenderRepositoryInterface::class, $container->get(GenderRepository::class)); + $this->addService($container, CombinationRepositoryInterface::class, $container->get(CombinationRepository::class)); $this->addService($container, MolCustomerRepository::class, MolCustomerRepository::class) ->withArgument('MolCustomer'); diff --git a/subscription/DTO/SubscriptionCarrierDeliveryPriceData.php b/subscription/DTO/SubscriptionCarrierDeliveryPriceData.php new file mode 100644 index 000000000..d5fb5bac8 --- /dev/null +++ b/subscription/DTO/SubscriptionCarrierDeliveryPriceData.php @@ -0,0 +1,85 @@ + + * @copyright Mollie B.V. + * @license https://github.com/mollie/PrestaShop/blob/master/LICENSE.md + * + * @see https://github.com/mollie/PrestaShop + * @codingStandardsIgnoreStart + */ + +namespace Mollie\Subscription\DTO; + +if (!defined('_PS_VERSION_')) { + exit; +} + +class SubscriptionCarrierDeliveryPriceData +{ + /** @var int */ + private $deliveryAddressId; + /** @var int */ + private $cartId; + /** @var int */ + private $customerId; + /** @var array */ + private $subscriptionProduct; + /** @var int */ + private $subscriptionCarrierId; + + public function __construct( + int $deliveryAddressId, + int $cartId, + int $customerId, + array $subscriptionProduct, + int $subscriptionCarrierId + ) { + $this->deliveryAddressId = $deliveryAddressId; + $this->cartId = $cartId; + $this->customerId = $customerId; + $this->subscriptionProduct = $subscriptionProduct; + $this->subscriptionCarrierId = $subscriptionCarrierId; + } + + /** + * @return int + */ + public function getDeliveryAddressId(): int + { + return $this->deliveryAddressId; + } + + /** + * @return int + */ + public function getCartId(): int + { + return $this->cartId; + } + + /** + * @return int + */ + public function getCustomerId(): int + { + return $this->customerId; + } + + /** + * @return array + */ + public function getSubscriptionProduct(): array + { + return $this->subscriptionProduct; + } + + /** + * @return int + */ + public function getSubscriptionCarrierId(): int + { + return $this->subscriptionCarrierId; + } +} diff --git a/subscription/Exception/CouldNotCreateSubscriptionData.php b/subscription/Exception/CouldNotCreateSubscriptionData.php new file mode 100644 index 000000000..4083d65fa --- /dev/null +++ b/subscription/Exception/CouldNotCreateSubscriptionData.php @@ -0,0 +1,63 @@ + + * @copyright Mollie B.V. + * @license https://github.com/mollie/PrestaShop/blob/master/LICENSE.md + * + * @see https://github.com/mollie/PrestaShop + * @codingStandardsIgnoreStart + */ + +namespace Mollie\Subscription\Exception; + +if (!defined('_PS_VERSION_')) { + exit; +} + +class CouldNotCreateSubscriptionData extends MollieSubscriptionException +{ + public static function failedToFindMollieCustomer(string $email): self + { + return new self( + sprintf( + 'Failed to find Mollie customer. Email: (%s)', + $email + ), + ExceptionCode::ORDER_FAILED_TO_FIND_MOLLIE_CUSTOMER + ); + } + + public static function failedToRetrieveSubscriptionInterval(\Throwable $exception, int $productAttributeId): self + { + return new self( + sprintf( + 'Failed to retrieve subscription interval. Product attribute ID: (%s)', + $productAttributeId + ), + ExceptionCode::ORDER_FAILED_TO_RETRIEVE_SUBSCRIPTION_INTERVAL, + $exception + ); + } + + public static function failedToProvideCarrierDeliveryPrice(\Throwable $exception): self + { + return new self( + 'Failed to provide carrier delivery price.', + ExceptionCode::ORDER_FAILED_TO_PROVIDE_CARRIER_DELIVERY_PRICE, + $exception + ); + } + + public static function failedToFindCurrency(int $currencyId): self + { + return new self( + sprintf( + 'Failed to find currency. Currency ID: (%s)', + $currencyId + ), + ExceptionCode::ORDER_FAILED_TO_FIND_CURRENCY + ); + } +} diff --git a/subscription/Exception/CouldNotHandleRecurringOrder.php b/subscription/Exception/CouldNotHandleRecurringOrder.php index 64533dd68..87fee45f6 100644 --- a/subscription/Exception/CouldNotHandleRecurringOrder.php +++ b/subscription/Exception/CouldNotHandleRecurringOrder.php @@ -18,6 +18,19 @@ class CouldNotHandleRecurringOrder extends MollieSubscriptionException { + public static function failedToMatchSelectedCarrier( + int $activeSubscriptionCarrierId, + int $orderSubscriptionCarrierId + ): self { + return new self( + sprintf('Failed to match selected carrier. active_carrier_id: (%s), order_carrier_id: (%s),', + $activeSubscriptionCarrierId, + $orderSubscriptionCarrierId + ), + ExceptionCode::RECURRING_ORDER_FAILED_TO_MATCH_SELECTED_CARRIER + ); + } + public static function failedToFindSelectedCarrier(): self { return new self( diff --git a/subscription/Exception/CouldNotProvideSubscriptionCarrierDeliveryPrice.php b/subscription/Exception/CouldNotProvideSubscriptionCarrierDeliveryPrice.php index 72fbdae54..e5da18caf 100644 --- a/subscription/Exception/CouldNotProvideSubscriptionCarrierDeliveryPrice.php +++ b/subscription/Exception/CouldNotProvideSubscriptionCarrierDeliveryPrice.php @@ -18,58 +18,79 @@ class CouldNotProvideSubscriptionCarrierDeliveryPrice extends MollieSubscriptionException { - public static function failedToFindSelectedCarrier(): self + public static function failedToFindSelectedCarrier(int $subscriptionCarrierId): self { return new self( - 'Failed to find selected carrier', + sprintf( + 'Failed to find selected carrier. Subscription carrier ID: (%s)', + $subscriptionCarrierId + ), ExceptionCode::ORDER_FAILED_TO_FIND_SELECTED_CARRIER ); } - public static function failedToFindOrderCart(): self + public static function failedToFindCart(int $cartId): self { return new self( - 'Failed to find order cart', - ExceptionCode::ORDER_FAILED_TO_FIND_ORDER_CART + sprintf( + 'Failed to find cart. Cart ID: (%s)', + $cartId + ), + ExceptionCode::ORDER_FAILED_TO_FIND_CART ); } - public static function failedToFindOrderCustomer(): self + public static function failedToFindCustomer(int $customerId): self { return new self( - 'Failed to find order customer', - ExceptionCode::ORDER_FAILED_TO_FIND_ORDER_CUSTOMER + sprintf( + 'Failed to find customer. Customer ID: (%s)', + $customerId + ), + ExceptionCode::ORDER_FAILED_TO_FIND_CUSTOMER ); } - public static function failedToApplySelectedCarrier(): self + public static function failedToApplySelectedCarrier(int $subscriptionCarrierId): self { return new self( - 'Failed to apply selected carrier', + sprintf( + 'Failed to apply selected carrier. Subscription carrier ID: (%s)', + $subscriptionCarrierId + ), ExceptionCode::ORDER_FAILED_TO_APPLY_SELECTED_CARRIER ); } - public static function failedToFindOrderDeliveryAddress(): self + public static function failedToFindDeliveryAddress(int $deliveryAddressId): self { return new self( - 'Failed to find order delivery address', - ExceptionCode::ORDER_FAILED_TO_FIND_ORDER_DELIVERY_ADDRESS + sprintf( + 'Failed to find delivery address. Delivery address ID: (%s)', + $deliveryAddressId + ), + ExceptionCode::ORDER_FAILED_TO_FIND_DELIVERY_ADDRESS ); } - public static function failedToFindOrderDeliveryCountry(): self + public static function failedToFindDeliveryCountry(int $countryId): self { return new self( - 'Failed to find order delivery country', - ExceptionCode::ORDER_FAILED_TO_FIND_ORDER_DELIVERY_COUNTRY + sprintf( + 'Failed to find delivery country. Country ID: (%s)', + $countryId + ), + ExceptionCode::ORDER_FAILED_TO_FIND_DELIVERY_COUNTRY ); } - public static function failedToGetSelectedCarrierPrice(): self + public static function failedToGetSelectedCarrierPrice(int $subscriptionCarrierId): self { return new self( - 'Failed to get selected carrier price', + sprintf( + 'Failed to get selected carrier price. Subscription carrier ID: (%s)', + $subscriptionCarrierId + ), ExceptionCode::ORDER_FAILED_TO_GET_SELECTED_CARRIER_PRICE ); } diff --git a/subscription/Exception/ExceptionCode.php b/subscription/Exception/ExceptionCode.php index 43432ad4d..c8eada765 100644 --- a/subscription/Exception/ExceptionCode.php +++ b/subscription/Exception/ExceptionCode.php @@ -21,16 +21,21 @@ class ExceptionCode //Order error codes starts from 1000 public const ORDER_FAILED_TO_FIND_SELECTED_CARRIER = 1001; - public const ORDER_FAILED_TO_FIND_ORDER_CART = 1002; - public const ORDER_FAILED_TO_FIND_ORDER_CUSTOMER = 1003; + public const ORDER_FAILED_TO_FIND_CART = 1002; + public const ORDER_FAILED_TO_FIND_CUSTOMER = 1003; public const ORDER_FAILED_TO_APPLY_SELECTED_CARRIER = 1004; - public const ORDER_FAILED_TO_FIND_ORDER_DELIVERY_ADDRESS = 1005; - public const ORDER_FAILED_TO_FIND_ORDER_DELIVERY_COUNTRY = 1006; + public const ORDER_FAILED_TO_FIND_DELIVERY_ADDRESS = 1005; + public const ORDER_FAILED_TO_FIND_DELIVERY_COUNTRY = 1006; public const ORDER_FAILED_TO_GET_SELECTED_CARRIER_PRICE = 1007; public const ORDER_FAILED_TO_FIND_ORDER = 1008; public const ORDER_FAILED_TO_FIND_ORDER_DETAIL = 1009; public const ORDER_FAILED_TO_FIND_PRODUCT = 1010; public const ORDER_FAILED_TO_FIND_CURRENCY = 1011; + public const ORDER_FAILED_TO_FIND_MOLLIE_CUSTOMER = 1012; + public const ORDER_FAILED_TO_RETRIEVE_SUBSCRIPTION_INTERVAL = 1013; + public const ORDER_FAILED_TO_PROVIDE_CARRIER_DELIVERY_PRICE = 1014; + public const ORDER_FAILED_TO_FIND_COMBINATION = 1015; + public const ORDER_FAILED_TO_FIND_MATCHING_INTERVAL = 1016; //Cart error codes starts from 2000 @@ -41,4 +46,7 @@ class ExceptionCode public const RECURRING_ORDER_FAILED_TO_FIND_SELECTED_CARRIER = 3001; public const RECURRING_ORDER_FAILED_TO_APPLY_SELECTED_CARRIER = 3002; public const RECURRING_ORDER_CART_AND_PAID_PRICE_ARE_NOT_EQUAL = 3003; + public const RECURRING_ORDER_FAILED_TO_MATCH_SELECTED_CARRIER = 3004; + + public const UNKNOWN_ERROR = 9001; } diff --git a/subscription/Exception/MollieSubscriptionException.php b/subscription/Exception/MollieSubscriptionException.php index 59b721c62..b0168dc55 100644 --- a/subscription/Exception/MollieSubscriptionException.php +++ b/subscription/Exception/MollieSubscriptionException.php @@ -14,12 +14,18 @@ namespace Mollie\Subscription\Exception; -use Exception; - if (!defined('_PS_VERSION_')) { exit; } -class MollieSubscriptionException extends Exception +class MollieSubscriptionException extends \Exception { + public static function unknownError(\Throwable $exception): self + { + return new self( + 'An unknown error error occurred. Please check system logs or contact Mollie support.', + ExceptionCode::UNKNOWN_ERROR, + $exception + ); + } } diff --git a/subscription/Exception/SubscriptionIntervalException.php b/subscription/Exception/SubscriptionIntervalException.php index f2db408a3..24445e360 100644 --- a/subscription/Exception/SubscriptionIntervalException.php +++ b/subscription/Exception/SubscriptionIntervalException.php @@ -20,4 +20,25 @@ class SubscriptionIntervalException extends MollieSubscriptionException { + public static function failedToFindCombination(int $productAttributeId): self + { + return new self( + sprintf( + 'Failed to find combination. Product attribute ID: (%s)', + $productAttributeId + ), + ExceptionCode::ORDER_FAILED_TO_FIND_COMBINATION + ); + } + + public static function failedToFindMatchingInterval(int $productAttributeId): self + { + return new self( + sprintf( + 'Failed to find matching interval. Product attribute ID: (%s)', + $productAttributeId + ), + ExceptionCode::ORDER_FAILED_TO_FIND_MATCHING_INTERVAL + ); + } } diff --git a/subscription/Factory/CreateSubscriptionDataFactory.php b/subscription/Factory/CreateSubscriptionDataFactory.php index c3deca151..29af3e437 100644 --- a/subscription/Factory/CreateSubscriptionDataFactory.php +++ b/subscription/Factory/CreateSubscriptionDataFactory.php @@ -15,18 +15,20 @@ namespace Mollie\Subscription\Factory; use Mollie; +use Mollie\Adapter\ConfigurationAdapter; use Mollie\Adapter\Context; +use Mollie\Config\Config; use Mollie\Repository\MolCustomerRepository; use Mollie\Repository\PaymentMethodRepositoryInterface; +use Mollie\Shared\Infrastructure\Repository\CurrencyRepositoryInterface; use Mollie\Subscription\DTO\CreateSubscriptionData as SubscriptionDataDTO; use Mollie\Subscription\DTO\Object\Amount; -use Mollie\Subscription\Exception\CouldNotProvideSubscriptionCarrierDeliveryPrice; -use Mollie\Subscription\Exception\SubscriptionIntervalException; +use Mollie\Subscription\DTO\SubscriptionCarrierDeliveryPriceData; +use Mollie\Subscription\Exception\CouldNotCreateSubscriptionData; +use Mollie\Subscription\Exception\MollieSubscriptionException; use Mollie\Subscription\Provider\SubscriptionCarrierDeliveryPriceProvider; use Mollie\Subscription\Provider\SubscriptionDescriptionProvider; use Mollie\Subscription\Provider\SubscriptionIntervalProvider; -use Mollie\Subscription\Repository\CombinationRepository; -use Mollie\Subscription\Repository\CurrencyRepository as CurrencyAdapter; use Mollie\Utility\SecureKeyUtility; use Order; @@ -38,19 +40,12 @@ class CreateSubscriptionDataFactory { /** @var MolCustomerRepository */ private $customerRepository; - /** @var SubscriptionIntervalProvider */ private $subscriptionInterval; - /** @var SubscriptionDescriptionProvider */ private $subscriptionDescription; - - /** @var CurrencyAdapter */ - private $currencyAdapter; - - /** @var CombinationRepository */ - private $combination; - + /** @var CurrencyRepositoryInterface */ + private $currencyRepository; /** @var PaymentMethodRepositoryInterface */ private $methodRepository; /** @var Mollie */ @@ -59,62 +54,92 @@ class CreateSubscriptionDataFactory private $context; /** @var SubscriptionCarrierDeliveryPriceProvider */ private $subscriptionCarrierDeliveryPriceProvider; + /** @var ConfigurationAdapter */ + private $configuration; public function __construct( MolCustomerRepository $customerRepository, SubscriptionIntervalProvider $subscriptionInterval, SubscriptionDescriptionProvider $subscriptionDescription, - CurrencyAdapter $currencyAdapter, - CombinationRepository $combination, + CurrencyRepositoryInterface $currencyRepository, PaymentMethodRepositoryInterface $methodRepository, Mollie $module, Context $context, - SubscriptionCarrierDeliveryPriceProvider $subscriptionCarrierDeliveryPriceProvider + SubscriptionCarrierDeliveryPriceProvider $subscriptionCarrierDeliveryPriceProvider, + ConfigurationAdapter $configuration ) { $this->customerRepository = $customerRepository; $this->subscriptionInterval = $subscriptionInterval; $this->subscriptionDescription = $subscriptionDescription; - $this->currencyAdapter = $currencyAdapter; - $this->combination = $combination; + $this->currencyRepository = $currencyRepository; $this->methodRepository = $methodRepository; $this->module = $module; $this->context = $context; $this->subscriptionCarrierDeliveryPriceProvider = $subscriptionCarrierDeliveryPriceProvider; + $this->configuration = $configuration; } /** - * @throws \PrestaShopException - * @throws CouldNotProvideSubscriptionCarrierDeliveryPrice - * @throws SubscriptionIntervalException + * @throws MollieSubscriptionException */ public function build(Order $order, array $subscriptionProduct): SubscriptionDataDTO { - $customer = $order->getCustomer(); - /** @var \MolCustomer $molCustomer */ - //todo: will need to improve mollie module logic to have shop id or card it so that multishop doesn't break - $molCustomer = $this->customerRepository->findOneBy(['email' => $customer->email]); + // TODO modify mol_customer table to hold id_customer (default PS customer ID as it holds id_shop). Then we won't need separate id_shop and id_shop_group column - $combination = $this->combination->getById((int) $subscriptionProduct['id_product_attribute']); - $interval = $this->subscriptionInterval->getSubscriptionInterval($combination); + try { + /** @var \MolCustomer|null $molCustomer */ + $molCustomer = $this->customerRepository->findOneBy([ + 'email' => $order->getCustomer()->email, + ]); + } catch (\Throwable $exception) { + throw CouldNotCreateSubscriptionData::unknownError($exception); + } + + if (!$molCustomer) { + throw CouldNotCreateSubscriptionData::failedToFindMollieCustomer((string) $order->getCustomer()->email); + } + + try { + $interval = $this->subscriptionInterval->getSubscriptionInterval((int) $subscriptionProduct['id_product_attribute']); + } catch (\Throwable $exception) { + throw CouldNotCreateSubscriptionData::failedToRetrieveSubscriptionInterval($exception, (int) $subscriptionProduct['id_product_attribute']); + } - $currency = $this->currencyAdapter->getById((int) $order->id_currency); $description = $this->subscriptionDescription->getSubscriptionDescription($order); + $subscriptionCarrierId = (int) $this->configuration->get(Config::MOLLIE_SUBSCRIPTION_ORDER_CARRIER_ID); + try { $deliveryPrice = $this->subscriptionCarrierDeliveryPriceProvider->getPrice( - (int) $order->id_address_delivery, - (int) $order->id_cart, - (int) $order->id_customer, - $subscriptionProduct + new SubscriptionCarrierDeliveryPriceData( + (int) $order->id_address_delivery, + (int) $order->id_cart, + (int) $order->id_customer, + $subscriptionProduct, + $subscriptionCarrierId + ) ); - } catch (CouldNotProvideSubscriptionCarrierDeliveryPrice $exception) { - // TODO throw generic error when new logger will be implemented - throw $exception; + } catch (\Throwable $exception) { + throw CouldNotCreateSubscriptionData::failedToProvideCarrierDeliveryPrice($exception); } $orderTotal = (float) $subscriptionProduct['total_price_tax_incl'] + $deliveryPrice; + try { + /** @var \Currency|null $currency */ + $currency = $this->currencyRepository->findOneBy([ + 'id_currency' => (int) $order->id_currency, + ]); + } catch (\Throwable $exception) { + throw CouldNotCreateSubscriptionData::unknownError($exception); + } + + if (!$currency) { + throw CouldNotCreateSubscriptionData::failedToFindCurrency((int) $order->id_currency); + } + $orderAmount = new Amount($orderTotal, $currency->iso_code); + $subscriptionData = new SubscriptionDataDTO( $molCustomer->customer_id, $orderAmount, @@ -127,20 +152,20 @@ public function build(Order $order, array $subscriptionProduct): SubscriptionDat 'subscriptionWebhook' )); - $key = SecureKeyUtility::generateReturnKey( + $secureKey = SecureKeyUtility::generateReturnKey( $order->id_customer, $order->id_cart, $this->module->name ); - $subscriptionData->setMetaData( - [ - 'secure_key' => $key, - ] - ); + $subscriptionData->setMetaData([ + 'secure_key' => $secureKey, + 'subscription_carrier_id' => $subscriptionCarrierId, + ]); // todo: check for solution what to do when mandate is missing $payment = $this->methodRepository->getPaymentBy('cart_id', $order->id_cart); + $subscriptionData->setMandateId($payment['mandate_id']); return $subscriptionData; diff --git a/subscription/Handler/RecurringOrderHandler.php b/subscription/Handler/RecurringOrderHandler.php index d7bb97a36..91480246a 100644 --- a/subscription/Handler/RecurringOrderHandler.php +++ b/subscription/Handler/RecurringOrderHandler.php @@ -219,11 +219,16 @@ private function createSubscription(Payment $transaction, MolRecurringOrder $rec $recurringOrderProduct = new MolRecurringOrdersProduct($recurringOrder->id_mol_recurring_orders_product); - $subscriptionCarrierId = (int) $this->configuration->get(Config::MOLLIE_SUBSCRIPTION_ORDER_CARRIER_ID); + $activeSubscriptionCarrierId = (int) $this->configuration->get(Config::MOLLIE_SUBSCRIPTION_ORDER_CARRIER_ID); + $orderSubscriptionCarrierId = (int) ($subscription->metadata->subscription_carrier_id ?? 0); + + if ($activeSubscriptionCarrierId !== $orderSubscriptionCarrierId) { + throw CouldNotHandleRecurringOrder::failedToMatchSelectedCarrier($activeSubscriptionCarrierId, $orderSubscriptionCarrierId); + } /** @var \Carrier|null $carrier */ $carrier = $this->carrierRepository->findOneBy([ - 'id_carrier' => $subscriptionCarrierId, + 'id_carrier' => $activeSubscriptionCarrierId, 'active' => 1, 'deleted' => 0, ]); diff --git a/subscription/Presenter/OrderDetailPresenter.php b/subscription/Presenter/OrderDetailPresenter.php index a7deae596..d9b16733e 100644 --- a/subscription/Presenter/OrderDetailPresenter.php +++ b/subscription/Presenter/OrderDetailPresenter.php @@ -14,9 +14,9 @@ use Mollie\Adapter\Context; use Mollie\Api\Types\SubscriptionStatus; -use Mollie\Repository\CurrencyRepositoryInterface; use Mollie\Repository\OrderRepositoryInterface; use Mollie\Repository\ProductRepositoryInterface; +use Mollie\Shared\Infrastructure\Repository\CurrencyRepositoryInterface; use Mollie\Subscription\Exception\CouldNotPresentOrderDetail; use Mollie\Subscription\Repository\OrderDetailRepositoryInterface; use Mollie\Utility\NumberUtility; diff --git a/subscription/Provider/SubscriptionCarrierDeliveryPriceProvider.php b/subscription/Provider/SubscriptionCarrierDeliveryPriceProvider.php index 5fbc7d64e..6c0fad82f 100644 --- a/subscription/Provider/SubscriptionCarrierDeliveryPriceProvider.php +++ b/subscription/Provider/SubscriptionCarrierDeliveryPriceProvider.php @@ -12,13 +12,12 @@ namespace Mollie\Subscription\Provider; -use Mollie\Adapter\ConfigurationAdapter; -use Mollie\Config\Config; use Mollie\Repository\AddressRepositoryInterface; use Mollie\Repository\CarrierRepositoryInterface; use Mollie\Repository\CartRepositoryInterface; use Mollie\Repository\CountryRepositoryInterface; use Mollie\Repository\CustomerRepositoryInterface; +use Mollie\Subscription\DTO\SubscriptionCarrierDeliveryPriceData; use Mollie\Subscription\Exception\CouldNotProvideSubscriptionCarrierDeliveryPrice; if (!defined('_PS_VERSION_')) { @@ -27,8 +26,6 @@ class SubscriptionCarrierDeliveryPriceProvider { - /** @var ConfigurationAdapter */ - private $configuration; /** @var CarrierRepositoryInterface */ private $carrierRepository; /** @var AddressRepositoryInterface */ @@ -41,14 +38,12 @@ class SubscriptionCarrierDeliveryPriceProvider private $countryRepository; public function __construct( - ConfigurationAdapter $configuration, CarrierRepositoryInterface $carrierRepository, AddressRepositoryInterface $addressRepository, CustomerRepositoryInterface $customerRepository, CartRepositoryInterface $cartRepository, CountryRepositoryInterface $countryRepository ) { - $this->configuration = $configuration; $this->carrierRepository = $carrierRepository; $this->addressRepository = $addressRepository; $this->customerRepository = $customerRepository; @@ -59,56 +54,54 @@ public function __construct( /** * @throws CouldNotProvideSubscriptionCarrierDeliveryPrice */ - public function getPrice(int $addressDeliveryId, int $cartId, int $customerId, array $subscriptionProduct): float + public function getPrice(SubscriptionCarrierDeliveryPriceData $data): float { - $subscriptionCarrierId = (int) $this->configuration->get(Config::MOLLIE_SUBSCRIPTION_ORDER_CARRIER_ID); - /** @var \Carrier|null $carrier */ $carrier = $this->carrierRepository->findOneBy([ - 'id_carrier' => $subscriptionCarrierId, + 'id_carrier' => $data->getSubscriptionCarrierId(), 'active' => 1, 'deleted' => 0, ]); if (!$carrier) { - throw CouldNotProvideSubscriptionCarrierDeliveryPrice::failedToFindSelectedCarrier(); + throw CouldNotProvideSubscriptionCarrierDeliveryPrice::failedToFindSelectedCarrier($data->getSubscriptionCarrierId()); } /** @var \Cart|null $cart */ $cart = $this->cartRepository->findOneBy([ - 'id_cart' => $cartId, + 'id_cart' => $data->getCartId(), ]); if (!$cart) { - throw CouldNotProvideSubscriptionCarrierDeliveryPrice::failedToFindOrderCart(); + throw CouldNotProvideSubscriptionCarrierDeliveryPrice::failedToFindCart($data->getCartId()); } /** @var \Customer|null $customer */ $customer = $this->customerRepository->findOneBy([ - 'id_customer' => $customerId, + 'id_customer' => $data->getCustomerId(), ]); if (!$customer) { - throw CouldNotProvideSubscriptionCarrierDeliveryPrice::failedToFindOrderCustomer(); + throw CouldNotProvideSubscriptionCarrierDeliveryPrice::failedToFindCustomer($data->getCustomerId()); } $getAvailableOrderCarriers = $this->carrierRepository->getCarriersForOrder( - $this->addressRepository->getZoneById($addressDeliveryId), + $this->addressRepository->getZoneById($data->getDeliveryAddressId()), $customer->getGroups(), $cart ); - if (!in_array($subscriptionCarrierId, array_column($getAvailableOrderCarriers, 'id_carrier'), false)) { - throw CouldNotProvideSubscriptionCarrierDeliveryPrice::failedToApplySelectedCarrier(); + if (!in_array($data->getSubscriptionCarrierId(), array_column($getAvailableOrderCarriers, 'id_carrier'), false)) { + throw CouldNotProvideSubscriptionCarrierDeliveryPrice::failedToApplySelectedCarrier($data->getSubscriptionCarrierId()); } /** @var \Address|bool $address */ $address = $this->addressRepository->findOneBy([ - 'id_address' => $addressDeliveryId, + 'id_address' => $data->getDeliveryAddressId(), ]); if (!$address) { - throw CouldNotProvideSubscriptionCarrierDeliveryPrice::failedToFindOrderDeliveryAddress(); + throw CouldNotProvideSubscriptionCarrierDeliveryPrice::failedToFindDeliveryAddress($data->getDeliveryAddressId()); } /** @var \Country|bool $country */ @@ -117,20 +110,20 @@ public function getPrice(int $addressDeliveryId, int $cartId, int $customerId, a ]); if (!$country) { - throw CouldNotProvideSubscriptionCarrierDeliveryPrice::failedToFindOrderDeliveryCountry(); + throw CouldNotProvideSubscriptionCarrierDeliveryPrice::failedToFindDeliveryCountry((int) $address->id_country); } /** @var float|bool $deliveryPrice */ $deliveryPrice = $cart->getPackageShippingCost( - $subscriptionCarrierId, + $data->getSubscriptionCarrierId(), true, $country, - [$subscriptionProduct], - $this->addressRepository->getZoneById($addressDeliveryId) + [$data->getSubscriptionProduct()], + $this->addressRepository->getZoneById($data->getDeliveryAddressId()) ); if (is_bool($deliveryPrice) && !$deliveryPrice) { - throw CouldNotProvideSubscriptionCarrierDeliveryPrice::failedToGetSelectedCarrierPrice(); + throw CouldNotProvideSubscriptionCarrierDeliveryPrice::failedToGetSelectedCarrierPrice($data->getSubscriptionCarrierId()); } return (float) $deliveryPrice; diff --git a/subscription/Provider/SubscriptionIntervalProvider.php b/subscription/Provider/SubscriptionIntervalProvider.php index be232827b..fc9813c3b 100644 --- a/subscription/Provider/SubscriptionIntervalProvider.php +++ b/subscription/Provider/SubscriptionIntervalProvider.php @@ -14,11 +14,11 @@ namespace Mollie\Subscription\Provider; -use Combination; use Mollie\Adapter\ConfigurationAdapter; use Mollie\Subscription\Config\Config; use Mollie\Subscription\DTO\Object\Interval; use Mollie\Subscription\Exception\SubscriptionIntervalException; +use Mollie\Subscription\Repository\CombinationRepositoryInterface; if (!defined('_PS_VERSION_')) { exit; @@ -28,10 +28,15 @@ class SubscriptionIntervalProvider { /** @var ConfigurationAdapter */ private $configuration; + /** @var CombinationRepositoryInterface */ + private $combinationRepository; - public function __construct(ConfigurationAdapter $configuration) - { + public function __construct( + ConfigurationAdapter $configuration, + CombinationRepositoryInterface $combinationRepository + ) { $this->configuration = $configuration; + $this->combinationRepository = $combinationRepository; } /** @@ -39,8 +44,17 @@ public function __construct(ConfigurationAdapter $configuration) * * @throws SubscriptionIntervalException */ - public function getSubscriptionInterval(Combination $combination): Interval + public function getSubscriptionInterval(int $productAttributeId): Interval { + /** @var \Combination|null $combination */ + $combination = $this->combinationRepository->findOneBy([ + 'id_product_attribute' => $productAttributeId, + ]); + + if (!$combination) { + throw SubscriptionIntervalException::failedToFindCombination($productAttributeId); + } + foreach ($combination->getWsProductOptionValues() as $attribute) { switch ($attribute['id']) { case $this->configuration->get(Config::SUBSCRIPTION_ATTRIBUTE_DAILY): @@ -54,6 +68,6 @@ public function getSubscriptionInterval(Combination $combination): Interval } } - throw new SubscriptionIntervalException(sprintf('No interval exists for this %s attribute', $combination->id)); + throw SubscriptionIntervalException::failedToFindMatchingInterval($productAttributeId); } } diff --git a/subscription/Repository/CombinationRepository.php b/subscription/Repository/CombinationRepository.php index 2d30c74d3..a5acb6d62 100644 --- a/subscription/Repository/CombinationRepository.php +++ b/subscription/Repository/CombinationRepository.php @@ -18,10 +18,10 @@ exit; } -class CombinationRepository +class CombinationRepository extends AbstractRepository implements CombinationRepositoryInterface { - public function getById(int $id): \Combination + public function __construct() { - return new \Combination($id); + parent::__construct(\Combination::class); } } diff --git a/subscription/Repository/CurrencyRepository.php b/subscription/Repository/CombinationRepositoryInterface.php similarity index 72% rename from subscription/Repository/CurrencyRepository.php rename to subscription/Repository/CombinationRepositoryInterface.php index 18348cfbc..488e213a2 100644 --- a/subscription/Repository/CurrencyRepository.php +++ b/subscription/Repository/CombinationRepositoryInterface.php @@ -10,18 +10,14 @@ * @codingStandardsIgnoreStart */ -declare(strict_types=1); - namespace Mollie\Subscription\Repository; +use Mollie\Repository\ReadOnlyRepositoryInterface; + if (!defined('_PS_VERSION_')) { exit; } -class CurrencyRepository +interface CombinationRepositoryInterface extends ReadOnlyRepositoryInterface { - public function getById(int $id): \Currency - { - return new \Currency($id); - } } diff --git a/subscription/Repository/ProductCombinationRepository.php b/subscription/Repository/ProductCombinationRepository.php deleted file mode 100644 index e3cd0c145..000000000 --- a/subscription/Repository/ProductCombinationRepository.php +++ /dev/null @@ -1,33 +0,0 @@ - - * @copyright Mollie B.V. - * @license https://github.com/mollie/PrestaShop/blob/master/LICENSE.md - * - * @see https://github.com/mollie/PrestaShop - * @codingStandardsIgnoreStart - */ - -declare(strict_types=1); - -namespace Mollie\Subscription\Repository; - -if (!defined('_PS_VERSION_')) { - exit; -} - -class ProductCombinationRepository -{ - public function getIds(int $combinationId): array - { - $query = new \DbQuery(); - $query - ->select('combination.id_attribute') - ->from('product_attribute_combination', 'combination') - ->where('combination.id_product_attribute = ' . $combinationId); - - return \Db::getInstance()->executeS($query) ?: []; - } -} diff --git a/subscription/Validator/CanProductBeAddedToCartValidator.php b/subscription/Validator/CanProductBeAddedToCartValidator.php index 0a0ae61c0..7cbd29f62 100644 --- a/subscription/Validator/CanProductBeAddedToCartValidator.php +++ b/subscription/Validator/CanProductBeAddedToCartValidator.php @@ -29,25 +29,22 @@ class CanProductBeAddedToCartValidator private $cart; /** @var SubscriptionProductValidator */ - private $subscriptionProduct; + private $subscriptionProductValidator; /** @var ToolsAdapter */ private $tools; public function __construct( CartAdapter $cart, - SubscriptionProductValidator $subscriptionProduct, + SubscriptionProductValidator $subscriptionProductValidator, ToolsAdapter $tools ) { $this->cart = $cart; - $this->subscriptionProduct = $subscriptionProduct; + $this->subscriptionProductValidator = $subscriptionProductValidator; $this->tools = $tools; } /** - * Validates if product can be added to the cart. - * Only 1 subscription product can be to the cart - * * @throws SubscriptionProductValidationException */ public function validate(int $productAttributeId): bool @@ -58,7 +55,7 @@ public function validate(int $productAttributeId): bool return true; } - $isNewSubscriptionProduct = $this->subscriptionProduct->validate($productAttributeId); + $isNewSubscriptionProduct = $this->subscriptionProductValidator->validate($productAttributeId); return !$isNewSubscriptionProduct || $this->validateIfSubscriptionProductCanBeAdded($productAttributeId); } @@ -71,7 +68,7 @@ private function validateIfSubscriptionProductCanBeAdded(int $productAttributeId $cartProducts = $this->cart->getProducts(); foreach ($cartProducts as $cartProduct) { - if (!$this->subscriptionProduct->validate((int) $cartProduct['id_product_attribute'])) { + if (!$this->subscriptionProductValidator->validate((int) $cartProduct['id_product_attribute'])) { continue; } diff --git a/subscription/Validator/SubscriptionProductValidator.php b/subscription/Validator/SubscriptionProductValidator.php index 0be48321b..03af5128e 100644 --- a/subscription/Validator/SubscriptionProductValidator.php +++ b/subscription/Validator/SubscriptionProductValidator.php @@ -18,8 +18,7 @@ use Mollie\Adapter\ConfigurationAdapter; use Mollie\Adapter\ProductAttributeAdapter; use Mollie\Subscription\Config\Config; -use Mollie\Subscription\Repository\CombinationRepository; -use Mollie\Subscription\Repository\ProductCombinationRepository; +use Mollie\Subscription\Repository\CombinationRepositoryInterface; if (!defined('_PS_VERSION_')) { exit; @@ -29,24 +28,18 @@ class SubscriptionProductValidator { /** @var ConfigurationAdapter */ private $configuration; - - /** @var ProductCombinationRepository */ + /** @var CombinationRepositoryInterface */ private $combinationRepository; - - /** @var CombinationRepository */ - private $combination; /** @var ProductAttributeAdapter */ private $productAttributeAdapter; public function __construct( ConfigurationAdapter $configuration, - ProductCombinationRepository $combinationRepository, - CombinationRepository $combination, + CombinationRepositoryInterface $combinationRepository, ProductAttributeAdapter $productAttributeAdapter ) { $this->configuration = $configuration; $this->combinationRepository = $combinationRepository; - $this->combination = $combination; $this->productAttributeAdapter = $productAttributeAdapter; } @@ -55,11 +48,17 @@ public function __construct( */ public function validate(int $productAttributeId): bool { - $combination = $this->combination->getById($productAttributeId); - $attributeIds = $this->combinationRepository->getIds((int) $combination->id); + /** @var \Combination|null $combination */ + $combination = $this->combinationRepository->findOneBy([ + 'id_product_attribute' => $productAttributeId, + ]); + + if (!$combination) { + return false; + } - foreach ($attributeIds as $attributeId) { - if ($this->isSubscriptionAttribute((int) $attributeId['id_attribute'])) { + foreach ($combination->getWsProductOptionValues() as $attribute) { + if ($this->isSubscriptionAttribute((int) $attribute['id'])) { return true; } } diff --git a/tests/Integration/Subscription/Provider/SubscriptionCarrierDeliveryPriceProviderTest.php b/tests/Integration/Subscription/Provider/SubscriptionCarrierDeliveryPriceProviderTest.php index 0be142fb1..881043b6b 100644 --- a/tests/Integration/Subscription/Provider/SubscriptionCarrierDeliveryPriceProviderTest.php +++ b/tests/Integration/Subscription/Provider/SubscriptionCarrierDeliveryPriceProviderTest.php @@ -12,8 +12,7 @@ namespace Mollie\Tests\Integration\Subscription\Provider; -use Mollie\Adapter\ConfigurationAdapter; -use Mollie\Config\Config; +use Mollie\Subscription\DTO\SubscriptionCarrierDeliveryPriceData; use Mollie\Subscription\Exception\CouldNotProvideSubscriptionCarrierDeliveryPrice; use Mollie\Subscription\Exception\ExceptionCode; use Mollie\Subscription\Provider\SubscriptionCarrierDeliveryPriceProvider; @@ -25,26 +24,6 @@ class SubscriptionCarrierDeliveryPriceProviderTest extends BaseTestCase { - public function setUp(): void - { - /** @var ConfigurationAdapter $configuration */ - $configuration = $this->getService(ConfigurationAdapter::class); - - $this->subscriptionOrderCarrierId = $configuration->get(Config::MOLLIE_SUBSCRIPTION_ORDER_CARRIER_ID); - - parent::setUp(); - } - - public function tearDown(): void - { - /** @var ConfigurationAdapter $configuration */ - $configuration = $this->getService(ConfigurationAdapter::class); - - $configuration->updateValue(Config::MOLLIE_SUBSCRIPTION_ORDER_CARRIER_ID, $this->subscriptionOrderCarrierId); - - parent::tearDown(); - } - public function testItSuccessfullyProvidesCarrierDeliveryPrice(): void { $address = AddressFactory::create(); @@ -55,11 +34,6 @@ public function testItSuccessfullyProvidesCarrierDeliveryPrice(): void 'id_carrier' => $carrier->id, ]); - /** @var ConfigurationAdapter $configuration */ - $configuration = $this->getService(ConfigurationAdapter::class); - - $configuration->updateValue(Config::MOLLIE_SUBSCRIPTION_ORDER_CARRIER_ID, $carrier->id); - $targetProduct = ProductFactory::create([ 'quantity' => 10, ]); @@ -81,10 +55,13 @@ public function testItSuccessfullyProvidesCarrierDeliveryPrice(): void $subscriptionCarrierDeliveryPriceProvider = $this->getService(SubscriptionCarrierDeliveryPriceProvider::class); $result = $subscriptionCarrierDeliveryPriceProvider->getPrice( - $address->id, - $cart->id, - $cart->id_customer, - $targetProductArray + new SubscriptionCarrierDeliveryPriceData( + $address->id, + $cart->id, + $cart->id_customer, + $targetProductArray, + $carrier->id + ) ); $this->assertEquals(999.00, $result); @@ -112,11 +89,6 @@ public function testItUnsuccessfullyProvidesCarrierDeliveryPriceCarrierIsOutOfZo 'id_carrier' => $carrier->id, ]); - /** @var ConfigurationAdapter $configuration */ - $configuration = $this->getService(ConfigurationAdapter::class); - - $configuration->updateValue(Config::MOLLIE_SUBSCRIPTION_ORDER_CARRIER_ID, $carrier->id); - $targetProduct = ProductFactory::create([ 'quantity' => 10, ]); @@ -141,10 +113,13 @@ public function testItUnsuccessfullyProvidesCarrierDeliveryPriceCarrierIsOutOfZo $subscriptionCarrierDeliveryPriceProvider = $this->getService(SubscriptionCarrierDeliveryPriceProvider::class); $subscriptionCarrierDeliveryPriceProvider->getPrice( - $address->id, - $cart->id, - $cart->id_customer, - $targetProductArray + new SubscriptionCarrierDeliveryPriceData( + $address->id, + $cart->id, + $cart->id_customer, + $targetProductArray, + $carrier->id + ) ); $this->removeFactories([ diff --git a/tests/Integration/Subscription/Validator/CanProductBeAddedToCartValidatorTest.php b/tests/Integration/Subscription/Validator/CanProductBeAddedToCartValidatorTest.php index 0274d901c..56937101e 100644 --- a/tests/Integration/Subscription/Validator/CanProductBeAddedToCartValidatorTest.php +++ b/tests/Integration/Subscription/Validator/CanProductBeAddedToCartValidatorTest.php @@ -13,11 +13,9 @@ namespace Mollie\Tests\Integration\Subscription\Validator; use Mollie\Adapter\CartAdapter; -use Mollie\Adapter\ProductAttributeAdapter; +use Mollie\Adapter\ToolsAdapter; use Mollie\Subscription\Config\Config; use Mollie\Subscription\Exception\SubscriptionProductValidationException; -use Mollie\Subscription\Repository\CombinationRepository; -use Mollie\Subscription\Repository\ProductCombinationRepository; use Mollie\Subscription\Validator\CanProductBeAddedToCartValidator; use Mollie\Subscription\Validator\SubscriptionProductValidator; use Mollie\Tests\Integration\BaseTestCase; @@ -68,7 +66,8 @@ protected function setUp(): void */ public function testValidate(string $combinationReference, bool $hasExtraAttribute, array $cartProducts, $expectedResult): void { - $cartAdapterMock = $this->createMock(CartAdapter::class); + // TODO cart factory + $cart = $this->createMock(CartAdapter::class); $cartProducts = array_map(function (array $product) { return [ @@ -76,19 +75,14 @@ public function testValidate(string $combinationReference, bool $hasExtraAttribu ]; }, $cartProducts); - $cartAdapterMock->method('getProducts')->willReturn($cartProducts); + $cart->method('getProducts')->willReturn($cartProducts); $combination = $this->getCombination($combinationReference, $hasExtraAttribute); $subscriptionCartValidator = new CanProductBeAddedToCartValidator( - $cartAdapterMock, - new SubscriptionProductValidator( - $this->configuration, - new ProductCombinationRepository(), - new CombinationRepository(), - new ProductAttributeAdapter() - ), - $this->getService(\Mollie\Adapter\ToolsAdapter::class) + $cart, + $this->getService(SubscriptionProductValidator::class), + $this->getService(ToolsAdapter::class) ); if ($expectedResult !== true) { @@ -161,6 +155,7 @@ public function productDataProvider(): array private function getCombination(string $combinationReference, bool $hasExtraAttribute): int { $reference = $this->configuration->get($combinationReference); + if ($hasExtraAttribute) { $reference = $reference ? implode('-', [ $this->configuration->get($combinationReference), diff --git a/tests/Integration/Subscription/Validator/SubscriptionOrderValidatorTest.php b/tests/Integration/Subscription/Validator/SubscriptionOrderValidatorTest.php index 1c9af8f6d..f9f4e1ee6 100644 --- a/tests/Integration/Subscription/Validator/SubscriptionOrderValidatorTest.php +++ b/tests/Integration/Subscription/Validator/SubscriptionOrderValidatorTest.php @@ -13,7 +13,6 @@ namespace Mollie\Tests\Integration\Subscription\Validator; use Mollie\Subscription\Config\Config; -use Mollie\Subscription\Repository\CombinationRepository as CombinationAdapter; use Mollie\Subscription\Validator\SubscriptionOrderValidator; use Mollie\Subscription\Validator\SubscriptionProductValidator; use Mollie\Tests\Integration\BaseTestCase; @@ -63,20 +62,16 @@ protected function setUp(): void */ public function testValidate(array $orderProducts, $expectedResult): void { - $cartMock = $this->createMock('Cart'); + $cart = $this->createMock('Cart'); $orderProductsMapped = array_map(function ($product) { return $this->getProducts($product); }, $orderProducts); - $cartMock->method('getProducts')->willReturn($orderProductsMapped); + $cart->method('getProducts')->willReturn($orderProductsMapped); - $combinationMock = $this->createMock(CombinationAdapter::class); - $combinationMock - ->method('getById') - ->willReturn(new \Combination(1)); + $subscriptionProductValidator = $this->createMock(SubscriptionProductValidator::class); - $subscriptionProductMock = $this->createMock(SubscriptionProductValidator::class); $mockedValidation = [ [(int) $this->configuration->get(Config::SUBSCRIPTION_ATTRIBUTE_NONE), false], [(int) $this->configuration->get(Config::SUBSCRIPTION_ATTRIBUTE_DAILY), true], @@ -84,13 +79,14 @@ public function testValidate(array $orderProducts, $expectedResult): void [(int) $this->configuration->get(Config::SUBSCRIPTION_ATTRIBUTE_MONTHLY), true], [self::NORMAL_PRODUCT_ATTRIBUTE_ID, false], ]; - $subscriptionProductMock->method('validate')->will( + + $subscriptionProductValidator->method('validate')->will( $this->returnValueMap($mockedValidation) ); - $subscriptionOrderValidator = new SubscriptionOrderValidator($subscriptionProductMock); + $subscriptionOrderValidator = new SubscriptionOrderValidator($subscriptionProductValidator); - $canBeAdded = $subscriptionOrderValidator->validate($cartMock); + $canBeAdded = $subscriptionOrderValidator->validate($cart); $this->assertEquals($expectedResult, $canBeAdded); } diff --git a/tests/Unit/BaseTestCase.php b/tests/Unit/BaseTestCase.php new file mode 100644 index 000000000..0e47a0f01 --- /dev/null +++ b/tests/Unit/BaseTestCase.php @@ -0,0 +1,48 @@ + + * @copyright Mollie B.V. + * @license https://github.com/mollie/PrestaShop/blob/master/LICENSE.md + * + * @see https://github.com/mollie/PrestaShop + * @codingStandardsIgnoreStart + */ + +namespace Mollie\Tests\Unit; + +use Mollie\Adapter\ConfigurationAdapter; +use Mollie\Adapter\Context; +use PHPUnit\Framework\TestCase; + +class BaseTestCase extends TestCase +{ + protected $backupGlobals = false; + + /** @var \Mollie */ + public $module; + /** @var ConfigurationAdapter */ + public $configuration; + /** @var Context */ + public $context; + /** @var \Customer */ + public $customer; + + protected function setUp(): void + { + $this->module = $this->mock(\Mollie::class); + $this->configuration = $this->mock(ConfigurationAdapter::class); + $this->context = $this->mock(Context::class); + $this->customer = $this->mock(\Customer::class); + + parent::setUp(); + } + + public function mock(string $className) + { + return $this->getMockBuilder($className) + ->disableOriginalConstructor() + ->getMock(); + } +} diff --git a/tests/Unit/Builder/InvoicePdfTemplateBuilderTest.php b/tests/Unit/Builder/InvoicePdfTemplateBuilderTest.php index f02d70f4d..b5775f456 100644 --- a/tests/Unit/Builder/InvoicePdfTemplateBuilderTest.php +++ b/tests/Unit/Builder/InvoicePdfTemplateBuilderTest.php @@ -13,8 +13,8 @@ namespace Mollie\Tests\Unit\Builder; use Mollie\Builder\InvoicePdfTemplateBuilder; -use Mollie\Repository\CurrencyRepositoryInterface; use Mollie\Repository\MolOrderPaymentFeeRepositoryInterface; +use Mollie\Shared\Infrastructure\Repository\CurrencyRepositoryInterface; use MolOrderPaymentFee; use PHPUnit\Framework\TestCase; use PrestaShop\PrestaShop\Core\Localization\Locale; diff --git a/tests/Unit/Factory/SubscriptionDataTest.php b/tests/Unit/Subscription/Factory/CreateSubscriptionDataFactoryTest.php similarity index 68% rename from tests/Unit/Factory/SubscriptionDataTest.php rename to tests/Unit/Subscription/Factory/CreateSubscriptionDataFactoryTest.php index 400edd280..25428fb76 100644 --- a/tests/Unit/Factory/SubscriptionDataTest.php +++ b/tests/Unit/Subscription/Factory/CreateSubscriptionDataFactoryTest.php @@ -12,12 +12,11 @@ declare(strict_types=1); -namespace Mollie\Tests\Unit\Factory; +namespace Mollie\Tests\Unit\Subscription\Factory; -use Mollie; -use Mollie\Adapter\Context; use Mollie\Repository\MolCustomerRepository; use Mollie\Repository\PaymentMethodRepository; +use Mollie\Shared\Infrastructure\Repository\CurrencyRepositoryInterface; use Mollie\Subscription\Constants\IntervalConstant; use Mollie\Subscription\DTO\CreateSubscriptionData as SubscriptionDataDTO; use Mollie\Subscription\DTO\Object\Amount; @@ -26,12 +25,10 @@ use Mollie\Subscription\Provider\SubscriptionCarrierDeliveryPriceProvider; use Mollie\Subscription\Provider\SubscriptionDescriptionProvider; use Mollie\Subscription\Provider\SubscriptionIntervalProvider; -use Mollie\Subscription\Repository\CombinationRepository; -use Mollie\Subscription\Repository\CurrencyRepository; +use Mollie\Tests\Unit\BaseTestCase; use Mollie\Utility\SecureKeyUtility; -use PHPUnit\Framework\TestCase; -class SubscriptionDataTest extends TestCase +class CreateSubscriptionDataFactoryTest extends BaseTestCase { private const TEST_ORDER_ID = 1; private const TEST_ORDER_REFERENCE = 111; @@ -45,22 +42,34 @@ class SubscriptionDataTest extends TestCase */ public function testBuildSubscriptionData(string $customerId, float $totalAmount, string $description, SubscriptionDataDTO $expectedResult): void { - $molCustomer = $this->createMock('MolCustomer'); + // TODO replace data provider with multiple methods, which tests various exception cases + + /** @var \MolCustomer $molCustomer */ + $molCustomer = $this->createMock(\MolCustomer::class); $molCustomer->customer_id = $customerId; - $customerRepositoryMock = $this->createMock(MolCustomerRepository::class); - $customerRepositoryMock->method('findOneBy')->willReturn($molCustomer); - $subscriptionIntervalProviderMock = $this->createMock(SubscriptionIntervalProvider::class); - $subscriptionIntervalProviderMock->method('getSubscriptionInterval')->willReturn(new Interval(1, IntervalConstant::DAY)); + $customerRepository = $this->createMock(MolCustomerRepository::class); + $customerRepository->method('findOneBy')->willReturn($molCustomer); + + $interval = new Interval(1, 'day'); + + $subscriptionIntervalProvider = $this->createMock(SubscriptionIntervalProvider::class); + $subscriptionIntervalProvider->method('getSubscriptionInterval')->willReturn($interval); $subscriptionDescriptionProviderMock = $this->createMock(SubscriptionDescriptionProvider::class); $subscriptionDescriptionProviderMock->method('getSubscriptionDescription')->willReturn($description); - $currency = $this->createMock('Currency'); + $this->configuration->method('get')->willReturn(1); + + $subscriptionCarrierDeliveryPriceProvider = $this->createMock(SubscriptionCarrierDeliveryPriceProvider::class); + $subscriptionCarrierDeliveryPriceProvider->method('getPrice')->willReturn(10.00); + + /** @var \Currency $currency */ + $currency = $this->createMock(\Currency::class); $currency->iso_code = 'EUR'; - $currencyAdapterMock = $this->createMock(CurrencyRepository::class); - $currencyAdapterMock->method('getById')->willReturn($currency); + $currencyRepository = $this->createMock(CurrencyRepositoryInterface::class); + $currencyRepository->method('findOneBy')->willReturn($currency); $paymentMethodRepositoryMock = $this->createMock(PaymentMethodRepository::class); $paymentMethodRepositoryMock->method('getPaymentBy')->willReturn( @@ -69,29 +78,27 @@ public function testBuildSubscriptionData(string $customerId, float $totalAmount ] ); - $context = $this->createMock(Context::class); - $context->expects($this->once())->method('getModuleLink')->willReturn('example-link'); + $this->context->method('getModuleLink')->willReturn('example-link'); - $subscriptionCarrierDeliveryPriceProvider = $this->createMock(SubscriptionCarrierDeliveryPriceProvider::class); - $subscriptionCarrierDeliveryPriceProvider->expects($this->once())->method('getPrice')->willReturn(10.00); + $this->module->name = 'mollie'; $subscriptionDataFactory = new CreateSubscriptionDataFactory( - $customerRepositoryMock, - $subscriptionIntervalProviderMock, + $customerRepository, + $subscriptionIntervalProvider, $subscriptionDescriptionProviderMock, - $currencyAdapterMock, - new CombinationRepository(), + $currencyRepository, $paymentMethodRepositoryMock, - new Mollie(), - $context, - $subscriptionCarrierDeliveryPriceProvider + $this->module, + $this->context, + $subscriptionCarrierDeliveryPriceProvider, + $this->configuration ); - $customerMock = $this->createMock('Customer'); - $customerMock->email = 'test.gmail.com'; + $this->customer->email = 'test.gmail.com'; $order = $this->createMock('Order'); - $order->method('getCustomer')->willReturn($customerMock); + $order->method('getCustomer')->willReturn($this->customer); + $order->id = self::TEST_ORDER_ID; $order->reference = self::TEST_ORDER_REFERENCE; $order->id_cart = self::TEST_CART_ID; @@ -117,6 +124,7 @@ public function subscriptionDataProvider() new Interval(1, IntervalConstant::DAY), 'subscription-' . self::TEST_ORDER_REFERENCE ); + $subscriptionDto->setMandateId(self::TEST_MANDATE_ID); $key = SecureKeyUtility::generateReturnKey( @@ -128,6 +136,7 @@ public function subscriptionDataProvider() $subscriptionDto->setMetaData( [ 'secure_key' => $key, + 'subscription_carrier_id' => 1, ] ); diff --git a/tests/Unit/Subscription/Factory/index.php b/tests/Unit/Subscription/Factory/index.php new file mode 100644 index 000000000..88355f610 --- /dev/null +++ b/tests/Unit/Subscription/Factory/index.php @@ -0,0 +1,11 @@ +createMock(ConfigurationAdapter::class); - $configurationMock - ->expects($this->any()) - ->method('get') - ->will( - $this->returnValueMap($mockedGetResults) - ); - $subscriptionIntervalProvider = new SubscriptionIntervalProvider($configurationMock); + $configurationMock->method('get')->will( + $this->returnValueMap($mockedGetResults) + ); + + $combination = $this->createMock('Combination'); + $combination->method('getWsProductOptionValues')->willReturn($attributeId); + + $combinationRepository = $this->createMock(CombinationRepositoryInterface::class); + $combinationRepository->method('findOneBy')->willReturn($combination); + + $subscriptionIntervalProvider = new SubscriptionIntervalProvider( + $configurationMock, + $combinationRepository + ); if ($expectedInterval === null) { $this->expectException(SubscriptionIntervalException::class); } - $combination = $this->createMock('Combination'); - $combination->method('getWsProductOptionValues')->willReturn($attributeId); - $description = $subscriptionIntervalProvider->getSubscriptionInterval($combination); + + $description = $subscriptionIntervalProvider->getSubscriptionInterval(1); $this->assertEquals($expectedInterval, $description); } diff --git a/tests/Unit/Subscription/Provider/index.php b/tests/Unit/Subscription/Provider/index.php new file mode 100644 index 000000000..88355f610 --- /dev/null +++ b/tests/Unit/Subscription/Provider/index.php @@ -0,0 +1,11 @@ +