Newer
Older
TillQliro / Model / Order / OrderPlacer.php
@Jonas Jonsson Jonas Jonsson on 2 Apr 2024 7 KB Initial
<?php
/**
 * Copyright © Qliro AB. All rights reserved.
 * See LICENSE.txt for license details.
 */

namespace Qliro\QliroOne\Model\Order;

use Magento\Customer\Api\CustomerRepositoryInterface;
use Magento\Quote\Model\Quote;
use Magento\Quote\Api\CartRepositoryInterface;
use Magento\Checkout\Model\Type\Onepage;
use Magento\Quote\Api\CartManagementInterface;
use Magento\Sales\Api\OrderRepositoryInterface;
use Magento\Framework\Event\ManagerInterface;

/**
 * Magento order placer class
 */
class OrderPlacer
{
    /**
     * @var \Magento\Quote\Api\CartRepositoryInterface
     */
    private $quoteRepository;

    /**
     * @var \Magento\Quote\Api\CartManagementInterface
     */
    private $cartManagement;

    /**
     * @var \Magento\Sales\Api\OrderRepositoryInterface
     */
    private $orderRepository;

    /**
     * @var \Magento\Framework\Event\ManagerInterface
     */
    private $eventManager;

    /**
     * @var CustomerRepositoryInterface
     */
    private $customerRepository;

    /**
     * @var \Magento\Checkout\Model\GuestPaymentInformationManagement
     */
    private $guestPaymentInformationManagement;

    /**
     * @var \Magento\Checkout\Model\PaymentInformationManagement
     */
    private $paymentInformationManagement;

    /**
     * @var \Magento\Quote\Model\QuoteIdMaskFactory
     */
    private $quoteIdMaskFactory;

    /**
     * Inject dependencies
     *
     * @param \Magento\Quote\Api\CartRepositoryInterface $quoteRepository
     * @param \Magento\Quote\Api\CartManagementInterface $cartManagement
     * @param \Magento\Sales\Api\OrderRepositoryInterface $orderRepository
     * @param \Magento\Framework\Event\ManagerInterface $eventManager
     * @param CustomerRepositoryInterface $customerRepository
     */
    public function __construct(
        CartRepositoryInterface $quoteRepository,
        CartManagementInterface $cartManagement,
        OrderRepositoryInterface $orderRepository,
        ManagerInterface $eventManager,
        CustomerRepositoryInterface $customerRepository,
        \Magento\Checkout\Model\GuestPaymentInformationManagement $guestPaymentInformationManagement,
        \Magento\Checkout\Model\PaymentInformationManagement $paymentInformationManagement,
        \Magento\Quote\Model\QuoteIdMaskFactory $quoteIdMaskFactory
    ) {
        $this->quoteRepository = $quoteRepository;
        $this->cartManagement = $cartManagement;
        $this->orderRepository = $orderRepository;
        $this->eventManager = $eventManager;
        $this->customerRepository = $customerRepository;
        $this->guestPaymentInformationManagement = $guestPaymentInformationManagement;
        $this->paymentInformationManagement = $paymentInformationManagement;
        $this->quoteIdMaskFactory = $quoteIdMaskFactory;
    }

    /**
     * Place order should be very small, all validations and updates should be done before calling this
     * Onepage::METHOD_REGISTER should not be possible to get
     *
     * @param Quote $quote
     * @return \Magento\Sales\Model\Order
     * @throws \Magento\Framework\Exception\CouldNotSaveException
     */
    public function place($quote)
    {
        switch ($this->getCheckoutMethod($quote)) {
            case Onepage::METHOD_GUEST:
                $this->prepareGuestQuote($quote);
                $quote->save(); // quoteRepository->save does stupid things...
                $quoteIdMask = $this->quoteIdMaskFactory->create()->load($quote->getId(),'quote_id');
                $maskedCartId = $quoteIdMask->getMaskedId();
                $orderId = $this->guestPaymentInformationManagement->savePaymentInformationAndPlaceOrder(
                    $maskedCartId,
                    $quote->getCustomerEmail(),
                    $quote->getPayment()
                );
                break;
            default:
                $this->prepareCustomerQuote($quote);
                $quote->save(); // quoteRepository->save does stupid things...
                $orderId = $this->paymentInformationManagement->savePaymentInformationAndPlaceOrder(
                    $quote->getId(),
                    $quote->getPayment()
                );
                break;
        }

        /** @var \Magento\Sales\Model\Order $order */
        $order = $this->orderRepository->get($orderId);

        return $order;
    }

    /**
     * Get quote checkout method
     * No need to test for guest, as it's impossible to get to checkout if that's disallowed.
     *
     * @param Quote $quote
     * @return string
     */
    private function getCheckoutMethod($quote)
    {
        if ($quote->getCustomerId()) {
            $quote->setCheckoutMethod(Onepage::METHOD_CUSTOMER);
            return $quote->getCheckoutMethod();
        }
        if (!$quote->getCheckoutMethod()) {
            $quote->setCheckoutMethod(Onepage::METHOD_GUEST);
        }

        return $quote->getCheckoutMethod();
    }

    /**
     * Prepare quote for guest checkout order submit
     *
     * @param Quote $quote
     * @return $this
     */
    private function prepareGuestQuote($quote)
    {
        $quote->setCustomerId(null)
            ->setCustomerEmail($quote->getBillingAddress()->getEmail())
            ->setCustomerIsGuest(true)
            ->setCustomerGroupId(\Magento\Customer\Api\Data\GroupInterface::NOT_LOGGED_IN_ID);
        return $this;
    }

    /**
     * Prepare quote for customer order submit
     *
     * @param Quote $quote
     * @return void
     * @SuppressWarnings(PHPMD.CyclomaticComplexity)
     */
    private function prepareCustomerQuote($quote)
    {
        $billing = $quote->getBillingAddress();
        $shipping = $quote->isVirtual() ? null : $quote->getShippingAddress();

        /** @var \Magento\Customer\Model\Customer $customer */
        $customer = $this->customerRepository->getById($quote->getCustomerId());
        $hasDefaultBilling = (bool)$customer->getDefaultBilling();
        $hasDefaultShipping = (bool)$customer->getDefaultShipping();

        if ($shipping && !$shipping->getSameAsBilling() &&
            (!$shipping->getCustomerId() || $shipping->getSaveInAddressBook())
        ) {
            $shippingAddress = $shipping->exportCustomerAddress();
            if (!$hasDefaultShipping) {
                //Make provided address as default shipping address
                $shippingAddress->setIsDefaultShipping(true);
                $hasDefaultShipping = true;
            }
            $quote->addCustomerAddress($shippingAddress);
            $shipping->setCustomerAddressData($shippingAddress);
        }

        if (!$billing->getCustomerId() || $billing->getSaveInAddressBook()) {
            $billingAddress = $billing->exportCustomerAddress();
            if (!$hasDefaultBilling) {
                //Make provided address as default shipping address
                if (!$hasDefaultShipping) {
                    //Make provided address as default shipping address
                    $billingAddress->setIsDefaultShipping(true);
                }
                $billingAddress->setIsDefaultBilling(true);
            }
            $quote->addCustomerAddress($billingAddress);
            $billing->setCustomerAddressData($billingAddress);
        }
    }

}