diff --git a/meta/documents/changelog_de.md b/meta/documents/changelog_de.md index e7fb774..a515284 100644 --- a/meta/documents/changelog_de.md +++ b/meta/documents/changelog_de.md @@ -1,6 +1,10 @@ # Release Notes für Kauf auf Rechnung -## 2.0.3 (2019-12-17) +## 2.0.4 (2020-02-25) +### Gefixt +- Alle Einstellungen / Beschränkungen werden nun korrekt abgefragt. + +## 2.0.3 (2020-02-10) ### Gefixt - Der Mindest- und Maximalbetrag wird nun korrekt geprüft, wenn der Kunde die Zahlungsart in Mein Konto ändern will. diff --git a/meta/documents/changelog_en.md b/meta/documents/changelog_en.md index c1a7031..4004f1d 100644 --- a/meta/documents/changelog_en.md +++ b/meta/documents/changelog_en.md @@ -1,6 +1,10 @@ # Release Notes for Invoice -## 2.0.3 (2019-12-17) +## 2.0.4 (2020-02-25) +### Fixed +- All settings / restrictions are now queried correctly. + +## 2.0.3 (20120-02-10) ### Fixed - The minimum and maximum limit is now checked properly, when a customer wants to change the payment method in an order under My Account. diff --git a/plugin.json b/plugin.json index aced9d4..2fedb95 100644 --- a/plugin.json +++ b/plugin.json @@ -1,5 +1,5 @@ { - "version" : "2.0.3", + "version" : "2.0.4", "name" : "Invoice", "marketplaceName" : {"de":"Kauf auf Rechnung","en":"Invoice"}, "license" : "AGPL-3.0", diff --git a/src/Helper/SettingsHelper.php b/src/Helper/SettingsHelper.php new file mode 100644 index 0000000..3df1836 --- /dev/null +++ b/src/Helper/SettingsHelper.php @@ -0,0 +1,145 @@ + + * + * @package Invoice\Helper + */ +class SettingsHelper +{ + /** + * The current settings + * + * @var SettingsService + */ + private $settings; + + /** + * The current plenty id. + * + * @var int + */ + private $plentyId; + + /** + * SettingsHelper constructor. + * + * @param SettingsService $settings The settings service + * @param int $plentyId The plenty ID + */ + public function __construct(SettingsService $settings, int $plentyId) + { + $this->settings = $settings; + $this->plentyId = $plentyId; + } + + /** + * Get whether the country is active or not + * + * @param int $countryId The country ID to be checked. + * + * @return bool + */ + public function isCountryActive(int $countryId): bool + { + $countries = $this->settings->getShippingCountriesByPlentyId($this->plentyId); + return in_array($countryId, $countries); + } + + /** + * Get whether or not the payment method has active countries. + * + * @return bool + */ + public function hasActiveCountries(): bool + { + $countries = $this->settings->getShippingCountriesByPlentyId($this->plentyId); + return count($countries) > 0; + } + + /** + * Get the minimum amount for using the payment method. + * + * @return float + */ + public function minimumAmount(): float + { + return $this->getSettingFloatValue('minimumAmount'); + } + + /** + * Get the maximum amount for using the payment method. + * + * @return float + */ + public function maximumAmount(): float + { + return $this->getSettingFloatValue('maximumAmount'); + } + + /** + * Get the minimum order count for using the payment method. + * + * @return int + */ + public function minimumOrderCount(): int + { + return $this->getSettingIntValue('quorumOrders'); + } + + /** + * Get whether the invoice payment is allowed for guests or not. + * + * @return bool + */ + public function guestsAllowed():bool + { + return $this->getSettingIntValue('disallowInvoiceForGuest', 1) != 1; + + } + + /** + * Get whether the delivery address should equals the billing address or not. + * + * @return bool + */ + public function shouldHaveIdenticalAddresses(): bool + { + return $this->getSettingIntValue('invoiceEqualsShippingAddress', 0) != 0; + } + + /** + * Get an integer setting. + * + * @param string $setting The setting key + * @param int $default The default value, if setting key is not set + * + * @return int + */ + private function getSettingIntValue(string $setting, int $default = 0): int + { + $settings = $this->settings->getSettingsForPlentyId($this->plentyId, 'de'); + return isset($settings[$setting]) ? (int)$settings[$setting] : $default; + } + + /** + * Get a float setting. + * + * @param string $setting The setting key + * @param float $default The default value, if setting key is not set + * + * @return float + */ + private function getSettingFloatValue(string $setting, float $default = 0.0): float + { + $settings = $this->settings->getSettingsForPlentyId($this->plentyId, 'de'); + return isset($settings[$setting]) ? (float)$settings[$setting] : $default; + } +} + diff --git a/src/Methods/InvoicePaymentMethod.php b/src/Methods/InvoicePaymentMethod.php index cc97ea1..3f26297 100755 --- a/src/Methods/InvoicePaymentMethod.php +++ b/src/Methods/InvoicePaymentMethod.php @@ -3,16 +3,14 @@ namespace Invoice\Methods; use Invoice\Helper\InvoiceHelper; +use Invoice\Helper\SettingsHelper; +use Invoice\Services\InvoiceLimitationsService; use Invoice\Services\SessionStorageService; use Invoice\Services\SettingsService; -use Plenty\Legacy\Repositories\Frontend\CurrencyExchangeRepository; use Plenty\Modules\Account\Contact\Contracts\ContactRepositoryContract; -use Plenty\Modules\Account\Contact\Models\Contact; -use Plenty\Modules\Account\Contact\Models\ContactAllowedMethodOfPayment; use Plenty\Modules\Category\Contracts\CategoryRepositoryContract; -use Plenty\Modules\Frontend\Contracts\CurrencyExchangeRepositoryContract; -use Plenty\Modules\Frontend\PaymentMethod\Contracts\FrontendPaymentMethodRepositoryContract; use Plenty\Modules\Frontend\Services\AccountService; +use Plenty\Modules\Frontend\Services\SystemService; use Plenty\Modules\Order\Contracts\OrderRepositoryContract; use Plenty\Plugin\Application; use Plenty\Modules\Frontend\Contracts\Checkout; @@ -28,6 +26,9 @@ */ class InvoicePaymentMethod extends PaymentMethodService { + /** @var SystemService */ + protected $systemService; + /** @var SettingsService */ protected $settings; @@ -44,12 +45,14 @@ class InvoicePaymentMethod extends PaymentMethodService protected $invoiceHelper; public function __construct( + SystemService $systemService, SettingsService $settings, SessionStorageService $session, Checkout $checkout, AccountService $accountService, InvoiceHelper $invoiceHelper ) { + $this->systemService = $systemService; $this->settings = $settings; $this->session = $session; $this->checkout = $checkout; @@ -67,86 +70,33 @@ public function __construct( */ public function isActive( BasketRepositoryContract $basketRepositoryContract):bool { - + /** @var InvoiceLimitationsService $service */ + $service = pluginApp(InvoiceLimitationsService::class); + + /** @var ContactRepositoryContract $contactRepo */ + $contactRepo = pluginApp(ContactRepositoryContract::class); + /** @var Basket $basket */ $basket = $basketRepositoryContract->load(); - - $lang = $this->session->getLang(); - - if($this->accountService->getIsAccountLoggedIn() && $basket->customerId > 0) { - /** @var ContactRepositoryContract $contactRepository */ - $contactRepository = pluginApp(ContactRepositoryContract::class); - $contact = $contactRepository->findContactById($basket->customerId); - if(!is_null($contact) && $contact instanceof Contact) { - $allowed = $contact->allowedMethodsOfPayment->first(function($method) { - if($method instanceof ContactAllowedMethodOfPayment) { - if($method->methodOfPaymentId == $this->invoiceHelper->getInvoiceMopId() && $method->allowed) { - return true; - } - } - }); - if($allowed) { - return true; - } - - if((int)$this->settings->getSetting('quorumOrders') > 0 && $contact->orderSummary->orderCount < $this->settings->getSetting('quorumOrders')) { - return false; - } - } - } elseif ((int)$this->settings->getSetting('quorumOrders') > 0 && !$this->accountService->getIsAccountLoggedIn()) { - return false; - } - /** @var CurrencyExchangeRepository $currencyService */ - $currencyService = pluginApp(CurrencyExchangeRepositoryContract::class); - $minAmount = (float)$currencyService->convertFromDefaultCurrency($basket->currency, $this->settings->getSetting('minimumAmount')); - $maxAmount = (float)$currencyService->convertFromDefaultCurrency($basket->currency, $this->settings->getSetting('maximumAmount')); - - /** - * Check the minimum amount - */ - if( $minAmount > 0.00 && $basket->basketAmount < $minAmount) - { - return false; - } - - /** - * Check the maximum amount - */ - if( $maxAmount > 0.00 && $maxAmount < $basket->basketAmount) - { - return false; - } - - - /** - * Check whether the invoice address is the same as the shipping address - */ - if( $this->settings->getSetting('invoiceEqualsShippingAddress',$lang) == 1) - { - $invoiceAddressId = $basket->customerInvoiceAddressId; - $shippingAddressId = $basket->customerShippingAddressId; - - if($shippingAddressId != null && $invoiceAddressId != $shippingAddressId) - { - return false; - } - } - - /** - * Check whether the user is logged in - */ - if( $this->settings->getSetting('disallowInvoiceForGuest',$lang) == 1 && !$this->accountService->getIsAccountLoggedIn()) - { - return false; - } - - if(!in_array($this->checkout->getShippingCountryId(), $this->settings->getShippingCountries())) - { - return false; + $isGuest = !($this->accountService->getIsAccountLoggedIn() && $basket->customerId > 0); + $contact = null; + if(!$isGuest) { + try { + $contact = $contactRepo->findContactById($basket->customerId, ['orderSummary']); + } catch(\Exception $ex) {} } - - return true; + + return $service->respectsAllLimitations( + pluginApp(SettingsHelper::class, [$this->settings, $this->systemService->getPlentyId()]), + $this->checkout->getShippingCountryId(), + $isGuest, + $basket->basketAmount, + $basket->currency, + $this->checkout->getCustomerInvoiceAddressId(), + $this->checkout->getCustomerShippingAddressId(), + $contact + ); } /** @@ -171,15 +121,6 @@ public function getName($lang = 'de') public function getFee( BasketRepositoryContract $basketRepositoryContract):float { return 0.00; - $basket = $basketRepositoryContract->load(); - if($basket->shippingCountryId == 1) - { - return $this->settings->getSetting('feeDomestic', $this->session->getLang()); - } - else - { - return $this->settings->getSetting('feeForeign', $this->session->getLang()); - } } /** @@ -262,37 +203,62 @@ public function getDescription():string */ public function isSwitchableTo(int $orderId = null):bool { + /** @var InvoiceLimitationsService $service */ + $service = pluginApp(InvoiceLimitationsService::class); + + // If order ID is given check the order data if(!is_null($orderId) && $orderId > 0) { /** @var OrderRepositoryContract $orderRepo */ $orderRepo = pluginApp(OrderRepositoryContract::class); $filters = $orderRepo->getFilters(); $filters['addOrderItems'] = false; $orderRepo->setFilters($filters); + try { - $order = $orderRepo->findOrderById($orderId, ['amounts']); - $amount = $order->amount; - - /** @var CurrencyExchangeRepository $currencyService */ - $currencyService = pluginApp(CurrencyExchangeRepositoryContract::class); - $minAmount = (float)$currencyService->convertFromDefaultCurrency($amount->currency, $this->settings->getSetting('minimumAmount')); - $maxAmount = (float)$currencyService->convertFromDefaultCurrency($amount->currency, $this->settings->getSetting('maximumAmount')); + $order = $orderRepo->findOrderById($orderId, ['amounts', 'addresses']); + $contact = $order->contactReceiver; - /** - * Check the minimum amount - */ - if( $minAmount > 0.00 && $amount->invoiceTotal < $minAmount) { - return false; - } - - /** - * Check the maximum amount - */ - if( $maxAmount > 0.00 && $maxAmount < $amount->invoiceTotal) { - return false; - } - } catch(\Exception $e) {} + return $service->respectsAllLimitations( + pluginApp(SettingsHelper::class, [$this->settings, $order->plentyId]), + $order->deliveryAddress->countryId, + $contact === null || $contact->singleAccess === "1", + $order->amount->invoiceTotal, + $order->amount->currency, + $order->billingAddress->id, + $order->deliveryAddress->id, + $contact + ); + } catch(\Exception $e) { + return false; + } + } + // Else check the basket data + else { + /** @var BasketRepositoryContract $basketRepo */ + $basketRepo = pluginApp(BasketRepositoryContract::class); + /** @var ContactRepositoryContract $contactRepo */ + $contactRepo = pluginApp(ContactRepositoryContract::class); + + $basket = $basketRepo->load(); + $isGuest = !($this->accountService->getIsAccountLoggedIn() && $basket->customerId > 0); + $contact = null; + if(!$isGuest) { + try { + $contact = $contactRepo->findContactById($basket->customerId, ['orderSummary']); + } catch(\Exception $ex) {} + } + + return $service->respectsAllLimitations( + pluginApp(SettingsHelper::class, [$this->settings, $this->systemService->getPlentyId()]), + $this->checkout->getShippingCountryId(), + $isGuest, + $basket->basketAmount, + $basket->currency, + $this->checkout->getCustomerInvoiceAddressId(), + $this->checkout->getCustomerShippingAddressId(), + $contact + ); } - return true; } /** diff --git a/src/Providers/InvoiceServiceProvider.php b/src/Providers/InvoiceServiceProvider.php index 774f4ca..f60d76e 100644 --- a/src/Providers/InvoiceServiceProvider.php +++ b/src/Providers/InvoiceServiceProvider.php @@ -3,6 +3,7 @@ namespace Invoice\Providers; use Invoice\Extensions\InvoiceTwigServiceProvider; +use Invoice\Helper\SettingsHelper; use Plenty\Modules\Payment\Events\Checkout\ExecutePayment; use Plenty\Modules\Payment\Events\Checkout\GetPaymentMethodContent; use Plenty\Plugin\ServiceProvider; @@ -29,6 +30,7 @@ class InvoiceServiceProvider extends ServiceProvider public function register() { $this->getApplication()->register(InvoiceRouteServiceProvider::class); + $this->getApplication()->bind(SettingsHelper::class); } /** diff --git a/src/Services/InvoiceLimitationsService.php b/src/Services/InvoiceLimitationsService.php new file mode 100644 index 0000000..8dbaf07 --- /dev/null +++ b/src/Services/InvoiceLimitationsService.php @@ -0,0 +1,117 @@ + + * + * @package Invoice\Services + */ +class InvoiceLimitationsService +{ + /** + * Get whether all payment method limitations are respected or not. + * + * @param SettingsHelper $settingsHelper The setting helper + * @param int $shippingCountryId The ID of the shipping country + * @param bool $isGuest Whether or not the current customer is a guest or not + * @param float $amount The total amount + * @param string $currency The current currency + * @param int $billingAddressId The ID of the billing address + * @param int $deliveryAddressId The ID of the delivery address + * @param Contact|null $contact The contact instance, if customer is not a quest + * + * @return bool + */ + public function respectsAllLimitations( + SettingsHelper $settingsHelper, + int $shippingCountryId, + bool $isGuest, + float $amount, + string $currency = 'EUR', + int $billingAddressId = null, + int $deliveryAddressId = null, + Contact $contact = null + ): bool + { + // First: Check the activated countries + if(!$settingsHelper->isCountryActive($shippingCountryId)) { + // Payment has not activated the requested country + // Possible reasons are: + // 1. No country is configured at all + // 2. The requested country is not activated + // => if guest return false, else check payment allowance for contact + if($isGuest || !$this->explicitlyAllowedFor($contact)) { + return false; + } + } + + // Second: Check guests + if($isGuest && !$settingsHelper->guestsAllowed()) { + return false; + } + + // Third: Check the addresses + // Addresses are equal when: $deliveryAddressId === null || $billingAddressId === $deliveryAddressId + if($settingsHelper->shouldHaveIdenticalAddresses() && $deliveryAddressId !== null && $billingAddressId !== $deliveryAddressId) { + return false; + } + + // Forth: Check minimum order count + $minOrderCount = $settingsHelper->minimumOrderCount(); + if($minOrderCount > 0) { + if($isGuest || is_null($contact)) { + // Guests have no orders, the current order is the first one + return false; + } + $orderCount = $contact->orderSummary->orderCount; + if($minOrderCount > $orderCount) { + return false; + } + } + + if($amount > 0.0) { + /** @var CurrencyExchangeRepositoryContract $currencyService */ + $currencyService = pluginApp(CurrencyExchangeRepositoryContract::class); + + // Fifth: Check minimum amount + $minAmount = (float)$currencyService->convertFromDefaultCurrency($currency, $settingsHelper->minimumAmount()); + if($minAmount > 0.0 && $minAmount > $amount) { + return false; + } + + // Sixth: Check maximum amount + $maxAmount = (float)$currencyService->convertFromDefaultCurrency($currency, $settingsHelper->maximumAmount()); + if($maxAmount > 0.0 && $maxAmount < $amount) { + return false; + } + } + + return true; + } + + /** + * Get whether or not the invoice payment method is excplicitly allowed for the contact. + * + * @param Contact|null $contact + * + * @return bool + */ + private function explicitlyAllowedFor(Contact $contact = null): bool + { + if(is_null($contact)) { + return false; + } + /** @var ContactAllowedMethodOfPayment $allowed */ + $allowed = $contact->allowedMethodsOfPayment->where('methodOfPaymentId', '=', 2)->first(); + return $allowed->allowed == 1; + } +} +