123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210 |
- <?php
- /**
- * @copyright Vertex. All rights reserved. https://www.vertexinc.com/
- * @author Mediotype https://www.mediotype.com/
- */
- namespace Vertex\Tax\Model\Api\Data;
- use Magento\Framework\Exception\LocalizedException;
- use Magento\Framework\Exception\NoSuchEntityException;
- use Magento\Store\Model\ScopeInterface;
- use Magento\Store\Model\StoreManagerInterface;
- use Magento\Tax\Api\Data\QuoteDetailsInterface;
- use Magento\Tax\Api\Data\QuoteDetailsItemInterface;
- use Magento\Tax\Api\Data\TaxClassKeyInterface;
- use Vertex\Data\LineItemInterface;
- use Vertex\Services\Quote\RequestInterface;
- use Vertex\Services\Quote\RequestInterfaceFactory;
- use Vertex\Tax\Model\AddressDeterminer;
- use Vertex\Tax\Model\Api\Utility\DeliveryTerm;
- use Vertex\Tax\Model\Config;
- use Vertex\Tax\Model\DateTimeImmutableFactory;
- /**
- * Builds a Quotation Request for the Vertex SDK
- */
- class QuotationRequestBuilder
- {
- const TRANSACTION_TYPE = 'SALE';
- /** @var AddressDeterminer */
- private $addressDeterminer;
- /** @var Config */
- private $config;
- /** @var CustomerBuilder */
- private $customerBuilder;
- /** @var DateTimeImmutableFactory */
- private $dateTimeFactory;
- /** @var DeliveryTerm */
- private $deliveryTerm;
- /** @var LineItemBuilder */
- private $lineItemBuilder;
- /** @var RequestInterfaceFactory */
- private $requestFactory;
- /** @var SellerBuilder */
- private $sellerBuilder;
- /** @var StoreManagerInterface */
- private $storeManager;
- /**
- * @param LineItemBuilder $lineItemBuilder
- * @param RequestInterfaceFactory $requestFactory
- * @param CustomerBuilder $customerBuilder
- * @param SellerBuilder $sellerBuilder
- * @param Config $config
- * @param DeliveryTerm $deliveryTerm
- * @param DateTimeImmutableFactory $dateTimeFactory
- * @param AddressDeterminer $addressDeterminer
- * @param StoreManagerInterface $storeManager
- */
- public function __construct(
- LineItemBuilder $lineItemBuilder,
- RequestInterfaceFactory $requestFactory,
- CustomerBuilder $customerBuilder,
- SellerBuilder $sellerBuilder,
- Config $config,
- DeliveryTerm $deliveryTerm,
- DateTimeImmutableFactory $dateTimeFactory,
- AddressDeterminer $addressDeterminer,
- StoreManagerInterface $storeManager
- ) {
- $this->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;
- }
- }
|