Search code examples
magento2shipping-method

Magento 2: How can I get Customer during collectRates on custom shipping method


How can I get the customer and cart during collectRates() function of my custom shipping method.

public function __construct(
    \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig,
    \Magento\Quote\Model\Quote\Address\RateResult\ErrorFactory $rateErrorFactory,
    \Psr\Log\LoggerInterface $logger,
    \Magento\Shipping\Model\Rate\ResultFactory $rateResultFactory,
    \Magento\Quote\Model\Quote\Address\RateResult\MethodFactory $rateMethodFactory,
    \Magento\Checkout\Model\Cart $cart,
    \Magento\Customer\Model\Session $customerSession,
    array $data = []
) {
    $this->_cart = $cart;
    $this->_rateResultFactory = $rateResultFactory;
    $this->_rateMethodFactory = $rateMethodFactory;
    $this->_customerSession = $customerSession;

    parent::__construct($scopeConfig, $rateErrorFactory, $logger, $data);
}

public function collectRates(RateRequest $request)
{

    if (!$this->getConfigFlag('active')) {
        return false;
    }

    if(!$this->_customerSession->isLoggedIn()) {
        return false;
    }

    $customer = $this->_customerSession->getCustomer();
    $qty = $this->_cart->getItemsQty();
    ...

Using customer session and checking if isLoggedIn() only works for frontend but returns false when placing order in the admin.

How can I get customer properly and calculate my price per item for both frontend and admin order placement?


Solution

  • If you can detect when your code runs in Admin, you can use \Magento\Backend\Model\Session\Quote as your [admin_session] and use [admin_session]->getCustomerId(), along with the customer repository (inject interfaces in constructor and let DI pass the correct objects) to fetch the customer object.

    I would suggest to check the contents of the \Magento\Backend\Model\Session\Quote object, as it might contain a pre-loaded customer object already, in which case you can avoid loading it.

    You could use \Magento\Framework\App\State::getAreaCode() to check if within admin