lineItemBuilder = $lineItemBuilder; $this->requestFactory = $requestFactory; $this->customerBuilder = $customerBuilder; $this->sellerBuilder = $sellerBuilder; $this->config = $config; $this->deliveryTerm = $deliveryTerm; $this->dateTimeFactory = $dateTimeFactory; $this->addressDeterminer = $addressDeterminer; $this->storeManager = $storeManager; } /** * Create a properly formatted Quote Request for the Vertex API * * @param QuoteDetailsInterface $quoteDetails * @param string|null $scopeCode * @return RequestInterface * @throws LocalizedException * @throws NoSuchEntityException */ public function buildFromQuoteDetails(QuoteDetailsInterface $quoteDetails, $scopeCode = null) { /** @var RequestInterface $request */ $request = $this->requestFactory->create(); $request->setShouldReturnAssistedParameters(true); $request->setDocumentDate($this->dateTimeFactory->create()); $request->setTransactionType(static::TRANSACTION_TYPE); $request->setCurrencyCode($this->storeManager->getStore($scopeCode)->getBaseCurrencyCode()); $taxLineItems = $this->getLineItemData($quoteDetails->getItems()); $request->setLineItems($taxLineItems); $address = $this->addressDeterminer->determineAddress( $quoteDetails->getShippingAddress() ?: $quoteDetails->getBillingAddress(), $quoteDetails->getCustomerId(), $this->isVirtual($quoteDetails) ); $seller = $this->sellerBuilder ->setScopeCode($scopeCode) ->setScopeType(ScopeInterface::SCOPE_STORE) ->build(); $request->setSeller($seller); $taxClassKey = $quoteDetails->getCustomerTaxClassKey(); if ($taxClassKey && $taxClassKey->getType() === TaxClassKeyInterface::TYPE_ID) { $customerTaxClassId = $taxClassKey->getValue(); } else { $customerTaxClassId = $quoteDetails->getCustomerTaxClassId(); } $request->setCustomer( $this->customerBuilder->buildFromCustomerAddress( $address, $quoteDetails->getCustomerId(), $customerTaxClassId, $scopeCode ) ); $this->deliveryTerm->addIfApplicable($request); if ($this->config->getLocationCode($scopeCode)) { $request->setLocationCode($this->config->getLocationCode($scopeCode)); } return $request; } /** * Build Line Items for the Request * * @param QuoteDetailsItemInterface[] $items * @return LineItemInterface[] */ private function getLineItemData(array $items) { // The resulting LineItemInterface[] to be used with Vertex $taxLineItems = []; // An array of codes for parent items $parentCodes = []; // A map of all items by their code $itemMap = []; // Item codes already processed - to prevent duplicates from bundles & configurables $processedItems = []; foreach ($items as $item) { $itemMap[$item->getCode()] = $item; if ($item->getParentCode()) { $parentCodes[] = $item->getParentCode(); } } foreach ($items as $item) { if (in_array($item->getCode(), array_merge($parentCodes, $processedItems), true)) { // We merge these two arrays together as a convenience so we only need to run in_array once continue; } $quantity = $item->getParentCode() ? $item->getQuantity() * $itemMap[$item->getParentCode()]->getQuantity() : $item->getQuantity(); $taxLineItems[] = $this->lineItemBuilder->buildFromQuoteDetailsItem($item, $quantity); $processedItems[] = $item->getCode(); } return $taxLineItems; } /** * Determine if the Quote is virtual * * @param QuoteDetailsInterface $quoteDetails * @return bool */ private function isVirtual(QuoteDetailsInterface $quoteDetails) { foreach ($quoteDetails->getItems() as $item) { if ($item->getType() === 'shipping') { return false; } } return true; } }