From eec1fb85c82f7aed8ea79ee1e5c6e343f6015349 Mon Sep 17 00:00:00 2001 From: Sergiu Moscalu Date: Fri, 23 Aug 2024 13:33:07 +0000 Subject: [PATCH] Composer 1.5.3 --- Model/Carrier/Unifaun.php | 53 +- Model/Management/CreateMerchantPayment.php | 69 ++- Model/Management/PlaceRecurringOrder.php | 567 ++++++++++++++++++ .../Builder/CreateRequestBuilder.php | 37 ++ .../Builder/CreateRequestBuilder.php | 2 +- .../Builder/UpdateRequestBuilder.php | 2 +- .../Converter/OrderItemsConverter.php | 6 +- .../RecurringQuoteFromOrderConverter.php | 92 +++ Service/RecurringPayments/PlaceOrders.php | 85 +-- composer.json | 2 +- 10 files changed, 820 insertions(+), 95 deletions(-) create mode 100644 Model/Management/PlaceRecurringOrder.php create mode 100755 Model/QliroOrder/Converter/RecurringQuoteFromOrderConverter.php diff --git a/Model/Carrier/Unifaun.php b/Model/Carrier/Unifaun.php index dbdc89b..964b122 100755 --- a/Model/Carrier/Unifaun.php +++ b/Model/Carrier/Unifaun.php @@ -5,11 +5,11 @@ */ namespace Qliro\QliroOne\Model\Carrier; -use Magento\Checkout\Model\Session; use Magento\Quote\Model\Quote\Address\RateRequest; use Magento\Shipping\Model\Rate\Result; use Qliro\QliroOne\Api\LinkRepositoryInterface; use Qliro\QliroOne\Model\Config; +use Magento\Quote\Api\CartRepositoryInterface; class Unifaun extends \Magento\Shipping\Model\Carrier\AbstractCarrier implements \Magento\Shipping\Model\Carrier\CarrierInterface @@ -31,10 +31,6 @@ class Unifaun extends \Magento\Shipping\Model\Carrier\AbstractCarrier implements * @var \Magento\Quote\Model\Quote\Address\RateResult\MethodFactory */ protected $_rateMethodFactory; - /** - * @var Session - */ - private $checkoutSession; /** * @var LinkRepositoryInterface */ @@ -43,6 +39,17 @@ class Unifaun extends \Magento\Shipping\Model\Carrier\AbstractCarrier implements * @var Config */ private $qliroConfig; + /** + * @var CartRepositoryInterface + */ + private $quoteRepository; + + /** + * @var + */ + private $quoteId; + + /** * Shipping constructor. @@ -52,9 +59,9 @@ class Unifaun extends \Magento\Shipping\Model\Carrier\AbstractCarrier implements * @param \Psr\Log\LoggerInterface $logger * @param \Magento\Shipping\Model\Rate\ResultFactory $rateResultFactory * @param \Magento\Quote\Model\Quote\Address\RateResult\MethodFactory $rateMethodFactory - * @param Session $checkoutSession * @param LinkRepositoryInterface $linkRepository - * @param Config $qliroConfig + * @param Cart $name + * @param CartRepositoryInterface $quoteRepository * @param array $data */ public function __construct( @@ -63,16 +70,16 @@ public function __construct( \Psr\Log\LoggerInterface $logger, \Magento\Shipping\Model\Rate\ResultFactory $rateResultFactory, \Magento\Quote\Model\Quote\Address\RateResult\MethodFactory $rateMethodFactory, - Session $checkoutSession, LinkRepositoryInterface $linkRepository, + CartRepositoryInterface $quoteRepository, Config $qliroConfig, array $data = [] ) { $this->_rateResultFactory = $rateResultFactory; $this->_rateMethodFactory = $rateMethodFactory; parent::__construct($scopeConfig, $rateErrorFactory, $logger, $data); - $this->checkoutSession = $checkoutSession; $this->linkRepository = $linkRepository; + $this->quoteRepository = $quoteRepository; $this->qliroConfig = $qliroConfig; } @@ -90,9 +97,9 @@ public function getAllowedMethods() */ private function getShippingPrice() { - $quote = $this->getQuote(); + $quoteId = $this->quoteId; try { - $link = $this->linkRepository->getByQuoteId($quote->getId()); + $link = $this->linkRepository->getByQuoteId($quoteId); if ($link->getUnifaunShippingAmount()) { $shippingPrice = $link->getUnifaunShippingAmount(); } else { @@ -129,29 +136,23 @@ public function collectRates(RateRequest $request) $method->setMethod($this->_code); $method->setMethodTitle($this->getConfigData('name')); + if(count($request->getAllItems())){ + $this->quoteId = $request->getAllItems()[0]->getQuoteId(); + $quote = $this->quoteRepository->get($this->quoteId); + if($quote->getShippingAddress()->getShippingDescription() && strpos($quote->getShippingAddress()->getShippingDescription(), 'Unifaun -') !== false) { + $shipingMethod = explode(' - ', $quote->getShippingAddress()->getShippingDescription()); + $method->setCarrierTitle($shipingMethod[0]); + $method->setMethodTitle($shipingMethod[1]); + } + } $amount = $this->getShippingPrice(); $method->setPrice($amount); $method->setCost($amount); - if($this->getQuote()->getShippingDescription() && strpos($this->getQuote()->getShippingDescription(), 'Unifaun -') !== false) { - $shipingMethod = explode(' - ', $this->getQuote()->getShippingDescription()); - $method->setCarrierTitle($shipingMethod[0]); - $method->setMethodTitle($shipingMethod[1]); - } $result->append($method); return $result; } - - /** - * Get current quote from checkout session - * - * @return \Magento\Quote\Model\Quote - */ - private function getQuote() - { - return $this->checkoutSession->getQuote(); - } } \ No newline at end of file diff --git a/Model/Management/CreateMerchantPayment.php b/Model/Management/CreateMerchantPayment.php index 74008e2..0b745c0 100644 --- a/Model/Management/CreateMerchantPayment.php +++ b/Model/Management/CreateMerchantPayment.php @@ -9,6 +9,7 @@ use Qliro\QliroOne\Model\Logger\Manager; use Qliro\QliroOne\Model\Api\Client\OrderManagement; use Qliro\QliroOne\Service\General\LinkService; +use Qliro\QliroOne\Model\Management\PlaceRecurringOrder; class CreateMerchantPayment extends AbstractManagement { @@ -49,6 +50,13 @@ class CreateMerchantPayment extends AbstractManagement */ private Manager $logManager; + /** + * @var \Qliro\QliroOne\Model\Management\PlaceRecurringOrder + */ + private $placeOrder; + + private $order; + public function __construct( LinkService $linkService, CreateRequestBuilder $createRequestBuilder, @@ -56,7 +64,8 @@ public function __construct( LinkRepositoryInterface $linkRepository, CartManagementInterface $quoteManagement, OrderManagement $qliroOrderManagement, - Manager $logManager + Manager $logManager, + PlaceRecurringOrder $placeOrder ) { $this->linkService = $linkService; $this->createRequestBuilder = $createRequestBuilder; @@ -65,6 +74,7 @@ public function __construct( $this->logManager = $logManager; $this->quoteManagement = $quoteManagement; $this->qliroOrderManagement = $qliroOrderManagement; + $this->placeOrder = $placeOrder; } /** @@ -75,6 +85,7 @@ public function __construct( */ public function execute(): void { + $order = $this->getOrder(); $quote = $this->getQuote(); $quoteId = $quote->getEntityId(); @@ -82,7 +93,7 @@ public function execute(): void $this->logManager->setMerchantReference($orderReference); $this->logManager->setMark('CREATE MERCHANT PAYMENT'); - $request = $this->createRequestBuilder->setQuote($quote)->create(); + $request = $this->createRequestBuilder->setQuote($quote)->setOrder($order)->create(); $request->setMerchantReference($orderReference); $merchantPaymentResponse = null; @@ -92,23 +103,59 @@ public function execute(): void $request, (int)$quote->getStoreId() ); - $newOrderId = $this->quoteManagement->placeOrder($quote->getId()); - - $link = $this->linkFactory->create(); - - // A real Quote Snapshot is not needed here but the value is required - $link->setQuoteSnapshot('merchantPayment'); + $qliroOrderId = $merchantPaymentResponse->getOrderId(); + $paymentTransactions = $merchantPaymentResponse->getPaymentTransactions(); + $state = $paymentTransactions[0]->getStatus(); + $qliroOrder = $this->qliroOrderManagement->getOrder($qliroOrderId); + $link = $this->linkFactory->create(); + $link->setQuoteSnapshot('merchantPayment');// A real Quote Snapshot is not needed here but the value is required $link->setQuoteId($quoteId); - $link->setReference($orderReference); - $link->setQliroOrderId($merchantPaymentResponse->getOrderId()); - $link->setOrderId($newOrderId); + $link->setReference($qliroOrder->getMerchantReference()); + $link->setQliroOrderId($qliroOrderId); $link->setQliroOrderStatus(self::DEFAULT_QLIRO_STATUS); $link->setIsActive(1); // The convention is setting the link as Active if the order is placed without errors + $orderItems = $qliroOrder->getOrderItemActions(); + foreach ($orderItems as $orderItem) { + if($orderItem->getType() == 'Shipping') + $link->setUnifaunShippingAmount($orderItem->getPricePerItemIncVat()); + } $this->linkRepository->save($link); + + + $this->placeOrder->setQuote($quote); + $magentoOrder = $this->placeOrder->execute($qliroOrder, $state); } catch (\Exception $exception) { $this->logManager->critical($exception->getMessage()); return; } } + + /** + * Get the order from the management class + * + * @return \Magento\Sales\Model\Order + */ + public function getOrder() + { + if (!($this->order instanceof \Magento\Sales\Model\Order)) { + throw new \LogicException('Order must be set before it is fetched.'); + } + + return $this->order; + } + + /** + * Set the order in the management class + * + * @param \Magento\Sales\Model\Order $order + * @return $this + */ + public function setOrder($order) + { + $order->setFirstCaptureFlag(true); + $this->order = $order; + + return $this; + } } diff --git a/Model/Management/PlaceRecurringOrder.php b/Model/Management/PlaceRecurringOrder.php new file mode 100644 index 0000000..8c31152 --- /dev/null +++ b/Model/Management/PlaceRecurringOrder.php @@ -0,0 +1,567 @@ +qliroConfig = $qliroConfig; + $this->merchantApi = $merchantApi; + $this->orderManagementApi = $orderManagementApi; + $this->linkRepository = $linkRepository; + $this->quoteRepository = $quoteRepository; + $this->containerMapper = $containerMapper; + $this->logManager = $logManager; + $this->quoteFromOrderConverter = $quoteFromOrderConverter; + $this->orderPlacer = $orderPlacer; + $this->lock = $lock; + $this->orderRepository = $orderRepository; + $this->orderSender = $orderSender; + $this->quoteManagement = $quoteManagement; + $this->paymentManagement = $paymentManagement; + $this->recurringDataService = $recurringDataService; + $this->cartManagementInterface = $cartManagementInterface; + $this->order = $order; + } + + /** + * Poll for Magento order placement and return order increment ID if successful + * + * @return \Magento\Sales\Model\Order + * @throws TerminalException + */ + public function poll() + { + $quoteId = $this->getQuote()->getId(); + + try { + $link = $this->linkRepository->getByQuoteId($quoteId); + $orderId = $link->getOrderId(); + $qliroOrderId = $link->getQliroOrderId(); + $this->logManager->setMerchantReference($link->getReference()); + + if (empty($orderId)) { + try { + $responseContainer = $this->merchantApi->getOrder($qliroOrderId); + + if ($responseContainer->getCustomerCheckoutStatus() == CheckoutStatusInterface::STATUS_IN_PROCESS) { + throw new OrderPlacementPendingException( + __('QliroOne order status is "InProcess" and order cannot be placed.') + ); + } + if (!$this->lock->lock($qliroOrderId)) { + throw new FailToLockException(__('Failed to aquire lock when placing order')); + } + + $this->lock->unlock($qliroOrderId); + + } catch (FailToLockException $exception) { + $this->logManager->critical( + $exception, + [ + 'extra' => [ + 'quote_id' => $quoteId, + 'qliro_order_id' => $qliroOrderId, + ], + ] + ); + + throw $exception; + } catch (OrderPlacementPendingException $exception) { + $this->logManager->critical( + $exception, + [ + 'extra' => [ + 'quote_id' => $quoteId, + 'qliro_order_id' => $qliroOrderId, + ], + ] + ); + $this->lock->unlock($qliroOrderId); + + throw $exception; + } catch (\Exception $exception) { + $this->logManager->critical( + $exception, + [ + 'extra' => [ + 'quote_id' => $quoteId, + 'qliro_order_id' => $qliroOrderId, + ], + ] + ); + $this->lock->unlock($qliroOrderId); + + throw new TerminalException('Order placement failed', $exception->getCode(), $exception); + } + } else { + $order = $this->orderRepository->get($orderId); + } + } catch (NoSuchEntityException $exception) { + $this->logManager->critical( + $exception, + [ + 'extra' => [ + 'quote_id' => $quoteId, + 'order_id' => $orderId ?? null, + 'qliro_order_id' => $qliroOrderId ?? null, + ], + ] + ); + throw new TerminalException('Failed to link current session with Qliro One order', $exception->getCode(), $exception); + } catch (\Exception $exception) { + $this->logManager->critical( + $exception, + [ + 'extra' => [ + 'quote_id' => $quoteId, + 'order_id' => $orderId ?? null, + 'qliro_order_id' => $qliroOrderId ?? null, + ], + ] + ); + + throw new TerminalException('Something went wrong during order placement polling', $exception->getCode(), $exception); + } + + return $order; + } + + /** + * Get a QliroOne order, update the quote, then place Magento order + * If placeOrder is successful, it returns the Magento Order + * If an error occurs it returns null + * If it's not possible to aquire lock, it returns false + * + * @param \Qliro\QliroOne\Api\Data\AdminOrderInterface $qliroOrder + * @param string $state + * @return \Magento\Sales\Model\Order + * @throws TerminalException + * @todo May require doing something upon $this->applyQliroOrderStatus($orderId) returning false + */ + public function execute(AdminOrderInterface $qliroOrder, $state = Order::STATE_PENDING_PAYMENT) + { + $qliroOrderId = $qliroOrder->getOrderId(); + + $this->logManager->setMark('PLACE ORDER'); + $order = null; // Placeholder, this method may never return null as an order + + try { + $link = $this->linkRepository->getByQliroOrderId($qliroOrderId); + + try { + if ($orderId = $link->getOrderId()) { + $this->logManager->debug( + 'Order is already created, skipping', + [ + 'extra' => [ + 'qliro_order' => $qliroOrderId, + 'quote_id' => $this->getQuote()->getId(), + 'order_id' => $orderId, + ], + ] + ); + + $order = $this->orderRepository->get($orderId); + } else { + $this->setQuote($this->quoteRepository->get($link->getQuoteId())); + + $this->logManager->debug( + 'Placing order', + [ + 'extra' => [ + 'qliro_order' => $qliroOrderId, + 'quote_id' => $this->getQuote()->getId(), + ], + ] + ); + + $this->quoteFromOrderConverter->convert($qliroOrder, $this->getQuote()); + $paymentTransactions = $qliroOrder->getPaymentTransactions(); + foreach ($paymentTransactions as $paymentTransaction) { + $this->addAdditionalInfoToQuote($link, $paymentTransaction); + } + $this->addAdditionalShippingInfoToQuote($qliroOrder); + $this->quoteManagement->setQuote($this->getQuote())->recalculateAndSaveQuote(); + + // $order = $this->orderPlacer->place($this->getQuote()); + $orderId = $this->cartManagementInterface->placeOrder($this->getQuote()->getId()); + $order = $this->order->load($orderId); + + + // $orderId = $order->getId(); + + $link->setOrderId($orderId); + $this->linkRepository->save($link); + + $this->paymentManagement->createPaymentTransaction($order, $qliroOrder, $state); + + $this->logManager->debug( + 'Order placed successfully', + [ + 'extra' => [ + 'qliro_order' => $qliroOrderId, + 'quote_id' => $this->getQuote()->getId(), + 'order_id' => $orderId, + ], + ] + ); + + $link->setMessage(sprintf('Created order %s', $order->getIncrementId())); + $this->linkRepository->save($link); + } + + $this->applyQliroOrderStatus($order); + } catch (\Exception $exception) { + $link->setIsActive(false); + $link->setMessage($exception->getMessage()); + $this->linkRepository->save($link); + + $this->logManager->critical( + $exception, + [ + 'extra' => [ + 'qliro_order_id' => $qliroOrderId, + 'quote_id' => $link->getQuoteId(), + ], + ] + ); + + throw $exception; + } + } catch (\Exception $exception) { + $this->logManager->critical( + $exception, + [ + 'extra' => [ + 'qliro_order_id' => $qliroOrderId, + ], + ] + ); + + throw new TerminalException($exception->getMessage(), $exception->getCode(), $exception); + } finally { + $this->logManager->setMark(null); + } + + return $order; + } + + /** + * Act on the order based on the qliro order status + * It can be one of: + * - Completed - the order can be shipped + * - OnHold - review of buyer require more time + * - Refused - deny the purchase + * + * @param Order $order + * @return bool + */ + public function applyQliroOrderStatus($order) + { + $orderId = $order->getId(); + + try { + $link = $this->linkRepository->getByOrderId($orderId); + + switch ($link->getQliroOrderStatus()) { + case CheckoutStatusInterface::STATUS_COMPLETED: + $this->applyOrderState($order, Order::STATE_NEW); + + if ($order->getCanSendNewEmailFlag() && !$order->getEmailSent()) { + try { + $this->orderSender->send($order); + } catch (\Exception $exception) { + $this->logManager->critical( + $exception, + [ + 'extra' => [ + 'order_id' => $orderId, + ], + ] + ); + } + } + + /* + * If Magento order has already been placed and QliroOne order status is completed, + * the order merchant reference must be replaced with Magento order increment ID + */ + /** @var \Qliro\QliroOne\Api\Data\AdminUpdateMerchantReferenceRequestInterface $request */ + $request = $this->containerMapper->fromArray( + [ + 'OrderId' => $link->getQliroOrderId(), + 'NewMerchantReference' => $order->getIncrementId(), + ], + AdminUpdateMerchantReferenceRequestInterface::class + ); + + $response = $this->orderManagementApi->updateMerchantReference($request, $order->getStoreId()); + $transactionId = 'unknown'; + if ($response && $response->getPaymentTransactionId()) { + $transactionId = $response->getPaymentTransactionId(); + } + $this->logManager->debug('New merchant reference was assigned to the Qliro One order', [ + 'payment_transaction_id' => $transactionId, + 'qliro_order_id' => $link->getQliroOrderId(), + 'order_id' => $order->getId(), + 'new_merchant_reference' => $order->getIncrementId(), + ]); + + break; + + case CheckoutStatusInterface::STATUS_ONHOLD: + $this->applyOrderState($order, Order::STATE_PAYMENT_REVIEW); + break; + + case CheckoutStatusInterface::STATUS_REFUSED: + // Deactivate link regardless of if the upcoming order cancellation successful or not + $link->setIsActive(false); + $link->setMessage(sprintf('Order #%s marked as canceled', $order->getIncrementId())); + $this->linkRepository->save($link); + $this->applyOrderState($order, Order::STATE_NEW); + + if ($order->canCancel()) { + $order->cancel(); + $this->orderRepository->save($order); + } + + break; + + case CheckoutStatusInterface::STATUS_IN_PROCESS: + default: + return false; + } + + return true; + } catch (\Exception $exception) { + $this->logManager->critical( + $exception, + [ + 'extra' => [ + 'order_id' => $orderId, + ], + ] + ); + + return false; + } + } + + /** + * Add information regarding this purchase to Quote, which will transfer to Order + * + * @param \Qliro\QliroOne\Api\Data\LinkInterface $link + * @param \Qliro\QliroOne\Model\QliroOrder\Admin\OrderPaymentTransaction $paymentTransaction + * @throws \Magento\Framework\Exception\LocalizedException + */ + private function addAdditionalInfoToQuote($link, $paymentTransaction) + { + $payment = $this->getQuote()->getPayment(); + $payment->setAdditionalInformation(Config::QLIROONE_ADDITIONAL_INFO_QLIRO_ORDER_ID, $link->getQliroOrderId()); + $payment->setAdditionalInformation(Config::QLIROONE_ADDITIONAL_INFO_REFERENCE, $link->getReference()); + + if ($paymentTransaction) { + $payment->setAdditionalInformation( + Config::QLIROONE_ADDITIONAL_INFO_PAYMENT_METHOD_CODE, + $paymentTransaction->getType() + ); + + $payment->setAdditionalInformation( + Config::QLIROONE_ADDITIONAL_INFO_PAYMENT_METHOD_NAME, + $paymentTransaction->getPaymentMethodName() + ); + } + } + + /** + * @param AdminOrderInterface $order + * @return void + */ + private function addAdditionalShippingInfoToQuote(AdminOrderInterface $order) + { + $payment = $this->getQuote()->getPayment(); + foreach ($order->getOrderItemActions() as $orderItem) { + $metadata = $orderItem->getMetadata(); + $additionalShippingProperties = $metadata['AdditionalShippingProperties'] ?? false; + if (!$additionalShippingProperties) { + continue; + } + + $payment->setAdditionalInformation( + Config::QLIROONE_ADDITIONAL_INFO_SHIPPING_PROPERTIES, + $additionalShippingProperties + ); + return; + } + } + + /** + * Apply a proper state with its default status to the order + * + * @param \Magento\Sales\Model\Order $order + * @param string $state + */ + private function applyOrderState(Order $order, $state) + { + $status = Order::STATE_NEW === $state + ? $this->qliroConfig->getOrderStatus() + : $order->getConfig()->getStateDefaultStatus($state); + + $order->setState($state); + $order->setStatus($status); + $this->orderRepository->save($order); + } +} diff --git a/Model/MerchantPayment/Builder/CreateRequestBuilder.php b/Model/MerchantPayment/Builder/CreateRequestBuilder.php index c8b0b5e..2c1e142 100755 --- a/Model/MerchantPayment/Builder/CreateRequestBuilder.php +++ b/Model/MerchantPayment/Builder/CreateRequestBuilder.php @@ -6,10 +6,12 @@ namespace Qliro\QliroOne\Model\MerchantPayment\Builder; +use Magento\Checkout\Block\Cart\Shipping; use Magento\Framework\Event\ManagerInterface; use Magento\Quote\Api\Data\CartInterface; use Magento\Store\Model\StoreManagerInterface; use Magento\Quote\Model\Quote; +use \Magento\Sales\Model\Order; use Magento\Framework\Url\QueryParamsResolverInterface; use Qliro\QliroOne\Api\LanguageMapperInterface; use Qliro\QliroOne\Model\Config; @@ -20,6 +22,8 @@ use Qliro\QliroOne\Model\QliroOrder\Builder\CustomerAddressBuilder; use Qliro\QliroOne\Model\QliroOrder\Builder\OrderItemsBuilder; use Qliro\QliroOne\Model\MerchantPayment\Builder\PaymentMethodBuilder; +use Qliro\QliroOne\Model\QliroOrder\Admin\Builder\Handler\InvoiceFeeHandler; +use Qliro\QliroOne\Model\QliroOrder\Admin\Builder\Handler\ShippingFeeHandler; /** * QliroOne Merchant Payment create request builder class @@ -36,6 +40,11 @@ class CreateRequestBuilder */ private ?Quote $quote = null; + /** + * @var \Magento\Sales\Model\Order + */ + private ?Order $order = null; + /** * @var \Qliro\QliroOne\Api\Data\AdminCreateMerchantPaymentRequestInterfaceFactory */ @@ -86,6 +95,16 @@ class CreateRequestBuilder */ private QueryParamsResolverInterface $queryParamsResolver; + /** + * @var \Qliro\QliroOne\Model\QliroOrder\Admin\Builder\Handler\ShippingFeeHandler + */ + private $shippingFeeHandler; + + /** + * @var \Qliro\QliroOne\Model\QliroOrder\Admin\Builder\Handler\InvoiceFeeHandler + */ + private $invoiceFeeHandler; + /** * @var \Magento\Framework\Event\ManagerInterface */ @@ -102,6 +121,8 @@ public function __construct( StoreManagerInterface $storeManager, CallbackToken $callbackToken, QueryParamsResolverInterface $queryParamsResolver, + ShippingFeeHandler $shippingFeeHandler, + InvoiceFeeHandler $invoiceFeeHandler, ManagerInterface $eventManager ) { $this->createRequestFactory = $createRequestFactory; @@ -114,6 +135,8 @@ public function __construct( $this->storeManager = $storeManager; $this->callbackToken = $callbackToken; $this->queryParamsResolver = $queryParamsResolver; + $this->shippingFeeHandler = $shippingFeeHandler; + $this->invoiceFeeHandler = $invoiceFeeHandler; $this->eventManager = $eventManager; } @@ -130,6 +153,19 @@ public function setQuote(CartInterface $quote) return $this; } + /** + * Set order for data extraction + * + * @param \Magento\Sales\Model\Order $order + * @return $this + */ + public function setOrder(Order $order) + { + $this->order = $order; + + return $this; + } + /** * Generate a QliroOne order create request object * @@ -146,6 +182,7 @@ public function create() $createRequest->setMerchantApiKey($this->qliroConfig->getMerchantApiKey($this->quote->getStoreId())); $orderItems = $this->orderItemsBuilder->setQuote($this->quote)->create(); + $orderItems = $this->shippingFeeHandler->handle($orderItems, $this->order); $createRequest->setOrderItems($orderItems); diff --git a/Model/QliroOrder/Builder/CreateRequestBuilder.php b/Model/QliroOrder/Builder/CreateRequestBuilder.php index 97d4f7d..f56a441 100755 --- a/Model/QliroOrder/Builder/CreateRequestBuilder.php +++ b/Model/QliroOrder/Builder/CreateRequestBuilder.php @@ -324,7 +324,7 @@ private function prepareCreateRequest() $createRequest->setAskForNewsletterSignup($this->qliroConfig->shouldAskForNewsletterSignup()); $createRequest->setAskForNewsletterSignupChecked($this->qliroConfig->askForNewsletterSignupChecked()); $createRequest->setRequireIdentityVerification($this->qliroConfig->requireIdentityVerification()); - foreach ($this->quote->getItems() as $item) { + foreach ($this->quote->getAllItems() as $item) { if ($item->getProductType() == Type::TYPE_VIRTUAL && !$item->getParentItemId()) { $createRequest->setRequireIdentityVerification(1); } diff --git a/Model/QliroOrder/Builder/UpdateRequestBuilder.php b/Model/QliroOrder/Builder/UpdateRequestBuilder.php index fc7ad17..e8a1566 100755 --- a/Model/QliroOrder/Builder/UpdateRequestBuilder.php +++ b/Model/QliroOrder/Builder/UpdateRequestBuilder.php @@ -126,7 +126,7 @@ private function prepareUpdateRequest() /** @var \Qliro\QliroOne\Api\Data\QliroOrderUpdateRequestInterface $qliroOrderUpdateRequest */ $qliroOrderUpdateRequest = $this->updateRequestFactory->create(); $qliroOrderUpdateRequest->setRequireIdentityVerification($this->qliroConfig->requireIdentityVerification()); - foreach ($this->quote->getItems() as $item) { + foreach ($this->quote->getAllItems() as $item) { if ($item->getProductType() == Type::TYPE_VIRTUAL && !$item->getParentItemId()) { $qliroOrderUpdateRequest->setRequireIdentityVerification(1); } diff --git a/Model/QliroOrder/Converter/OrderItemsConverter.php b/Model/QliroOrder/Converter/OrderItemsConverter.php index 8ea1ce1..4bffa71 100755 --- a/Model/QliroOrder/Converter/OrderItemsConverter.php +++ b/Model/QliroOrder/Converter/OrderItemsConverter.php @@ -138,8 +138,10 @@ private function applyShippingMethod($code, Quote $quote, string $shippingMercha if ($extensionAttributes !== null) { $shippingAssignments = $quote->getExtensionAttributes()->getShippingAssignments(); - foreach ($shippingAssignments as $assignment) { - $assignment->getShipping()->setMethod($code); + if(is_array($shippingAssignments)) { + foreach ($shippingAssignments as $assignment) { + $assignment->getShipping()->setMethod($code); + } } } diff --git a/Model/QliroOrder/Converter/RecurringQuoteFromOrderConverter.php b/Model/QliroOrder/Converter/RecurringQuoteFromOrderConverter.php new file mode 100755 index 0000000..36dc1e8 --- /dev/null +++ b/Model/QliroOrder/Converter/RecurringQuoteFromOrderConverter.php @@ -0,0 +1,92 @@ +orderItemsConverter = $orderItemsConverter; + $this->customerConverter = $customerConverter; + $this->subscription = $subscription; + $this->addressConverter = $addressConverter; + } + + /** + * Convert update shipping methods request into quote + * + * @param \Qliro\QliroOne\Api\Data\AdminOrderInterface $container + * @param \Magento\Quote\Model\Quote $quote + * @throws \Magento\Framework\Exception\LocalizedException + */ + public function convert($container, Quote $quote) + { + $this->customerConverter->convert($container->getCustomer(), $quote); + + if ($qliroBillingAddress = $container->getBillingAddress()) { + $this->addressConverter->convert( + $qliroBillingAddress, + $container->getCustomer(), + $quote->getBillingAddress() + ); + } + + if (!$quote->isVirtual() && ($qliroShippingAddress = $container->getShippingAddress())) { + $this->addressConverter->convert( + $qliroShippingAddress, + $container->getCustomer(), + $quote->getShippingAddress() + ); + } + + $this->orderItemsConverter->convert($container->getOrderItemActions(), $quote); + + $signupForNewsletter = $container->getSignupForNewsletter(); + if ($signupForNewsletter) { + $email = $quote->getCustomer()->getEmail(); + $this->subscription->addSubscription($email, $quote->getStoreId()); + } + } +} diff --git a/Service/RecurringPayments/PlaceOrders.php b/Service/RecurringPayments/PlaceOrders.php index fc89e53..ff03b92 100644 --- a/Service/RecurringPayments/PlaceOrders.php +++ b/Service/RecurringPayments/PlaceOrders.php @@ -20,12 +20,15 @@ use Magento\Checkout\Model\Session; use \Magento\Sales\Api\OrderRepositoryInterface; use Magento\Framework\Api\SearchCriteriaBuilder; +use Magento\Quote\Model\Quote\Address\Rate; /** * Service class for placing recurring orders */ class PlaceOrders { + const RECURRING_PAYMENT_INFO_KEY = 'qliro_recurring_info'; + private Create $orderCreate; private QuoteFactory $quoteFactory; @@ -56,6 +59,8 @@ class PlaceOrders private SearchCriteriaBuilder $searchCriteriaBuilder; + private Rate $shippingRate; + private array $results = []; private string $personalNumber; @@ -74,6 +79,7 @@ public function __construct( Session $checkoutSession, OrderRepositoryInterface $orderRepository, SearchCriteriaBuilder $searchCriteriaBuilder, + Rate $shippingRate, Manager $logger, CreateMerchantPayment $createMerchantPaymentManagement ) { @@ -90,6 +96,7 @@ public function __construct( $this->checkoutSession = $checkoutSession; $this->orderRepository = $orderRepository; $this->searchCriteriaBuilder = $searchCriteriaBuilder; + $this->shippingRate = $shippingRate; $this->logger = $logger; $this->createMerchantPaymentManagement = $createMerchantPaymentManagement; } @@ -141,31 +148,31 @@ private function commit(RecurringInfoInterface $recurringInfo): void } $originalOrderId = (int)$order->getEntityId(); - // Populate quote payment with order payment data - $this->orderCreate->setQuote($this->quoteFactory->create()); + + $this->orderCreate->setQuote($this->quoteFactory->create()->setStoreId($order->getStoreId())); $this->orderCreate->initFromOrder($order); $quote = $this->orderCreate->getQuote(); + + $payment = $order->getPayment(); + $dataArray = $payment->getAdditionalInformation(self::RECURRING_PAYMENT_INFO_KEY); + $quote->getPayment()->setAdditionalInformation(self::RECURRING_PAYMENT_INFO_KEY, $dataArray); + $quote->setStoreId($order->getStoreId()); $quote->reserveOrderId(); - $this->objectCopyService->copyFieldsetToTarget( - 'sales_convert_order_payment', - 'to_quote_payment', - $order->getPayment(), - $quote->getPayment() - ); - - // Update recurring info for new Quote - $this->dataService->scheduleNextRecurringOrder($quote); - $this->quoteRepo->save($quote); - $quote->setShippingDescription($order->getShippingDescription()); + $this->checkoutSession->replaceQuote($quote); - $this->qliroManagement->setQuote($quote)->getLinkFromQuote(); - if($order->getFee() > 0){ - $this->qliroManagement->updateFee($order->getFee() + $order->getFeeTax()); - } - $this->qliroManagement->updateShippingPrice($order->getShippingInclTax()); - $this->saveQuoteShippingInfo($quote, $order); - $this->createMerchantPaymentManagement->setQuote($quote); + //set shipping method from order to quote + $this->shippingRate + ->setCode($order->getShippingMethod()) + ->getPrice(1); + $shippingAddress = $quote->getShippingAddress(); + $quote->getShippingAddress()->addShippingRate($this->shippingRate); + //save shipping method to quote + $this->quoteRepo->save($quote); + $shippingAddress->setCollectShippingRates(true) + ->collectShippingRates() + ->setShippingMethod($order->getShippingMethod()); + $this->createMerchantPaymentManagement->setOrder($order)->setQuote($quote); if($recurringInfo->getPersonalNumber()){ $quote->setCustomerPersonalNumber($recurringInfo->getPersonalNumber()); } @@ -177,10 +184,11 @@ private function commit(RecurringInfoInterface $recurringInfo): void $this->orderRepository->save($newOrder); } - $recurringInfo->setNextOrderDate($this->dataService->quoteGetter($quote)->getNextOrderDate()); - $this->results[$originalOrderId] = [ - 'success' => 'true' - ]; + // Update recurring info for parent Order + $quoteFromParrentOrder = $this->quoteRepo->get($order->getQuoteId()); + $this->dataService->quoteGetter($quoteFromParrentOrder); + $this->dataService->scheduleNextRecurringOrder($quoteFromParrentOrder); + $recurringInfo->setNextOrderDate($this->dataService->quoteGetter($quoteFromParrentOrder)->getNextOrderDate()); } /** @@ -199,35 +207,6 @@ public function logError(int $orderId, array $messages): void $this->logger->error(sprintf('[RecurringPayment Error End. Original order: %s]', $orderId)); } - /** - * Transfer shipping info from order to new Quote - * - * @param Quote $quote - * @param string $methodCode - * @param string $carrier - * @return void - * @throws InputException - * @throws NoSuchEntityException - * @throws StateException - */ - private function saveQuoteShippingInfo(Quote $quote, Order $order): void - { - if ($order->getIsVirtual()) { - return; - } - - $shippingMethod = $order->getShippingMethod(true); - $carrier = $shippingMethod->getCarrierCode(); - $method = $shippingMethod->getMethod(); - - $shipInfo = $this->shipInfoFactory->create(); - $shipInfo->setBillingAddress($quote->getBillingAddress()); - $shipInfo->setShippingAddress($quote->getShippingAddress()); - $shipInfo->setShippingCarrierCode($carrier); - $shipInfo->setShippingMethodCode(strtolower($method)); - $this->shipInfoManagement->saveAddressInformation($quote->getId(), $shipInfo); - } - public function getOrderByQuoteId($quoteId) { $searchCriteria = $this->searchCriteriaBuilder diff --git a/composer.json b/composer.json index 93afed5..a4b1bd5 100755 --- a/composer.json +++ b/composer.json @@ -3,7 +3,7 @@ "type": "magento2-module", "description": "QliroOne checkout", "license": "proprietary", - "version": "1.5.2", + "version": "1.5.3", "authors": [ { "name": "Andreas Wickberg",