772 lines
27 KiB
PHP
772 lines
27 KiB
PHP
<?php
|
|
|
|
namespace JR\NetSuite\Service;
|
|
|
|
|
|
use Magento\Customer\Model\AddressFactory;
|
|
use Magento\Quote\Model\Quote;
|
|
use Magento\Quote\Model\QuoteFactory;
|
|
use Magento\Quote\Model\QuoteManagement;
|
|
use Magento\Quote\Model\Quote\Address\Rate;
|
|
use Magento\Quote\Api\CartRepositoryInterface;
|
|
use Magento\Quote\Api\CartManagementInterface;
|
|
use Magento\Quote\Api\Data\AddressExtensionInterfaceFactory;
|
|
use Magento\Quote\Api\Data\AddressInterface;
|
|
use Magento\Store\Model\StoreManagerInterface;
|
|
use Magento\CatalogInventory\Api\StockRegistryInterface;
|
|
use Magento\Catalog\Api\ProductRepositoryInterface;
|
|
use Magento\Framework\Exception\LocalizedException;
|
|
use Magento\Framework\Api\SearchCriteriaBuilder;
|
|
use Magento\Sales\Api\OrderRepositoryInterface;
|
|
use Magento\Sales\Api\Data\OrderInterface;
|
|
use Magento\Sales\Model\OrderFactory;
|
|
use Magento\InventoryApi\Api\SourceRepositoryInterface;
|
|
use Magento\InventoryCatalog\Model\GetStockIdForCurrentWebsite;
|
|
use Magento\InventoryReservationsApi\Model\GetReservationsQuantityInterface;
|
|
use JR\Netsuite\Mapper\OrderMapper;
|
|
|
|
|
|
class OrdersSyncService {
|
|
|
|
const TAX_GROUP = 'TaxGroup';
|
|
const SHIP_ITEM = 'ShipItem';
|
|
const INVT_PART = 'InvtPart';
|
|
const DISCOUNT = 'Discount';
|
|
|
|
/**
|
|
* @var \Magento\Customer\Model\AddressFactory
|
|
*/
|
|
protected $addressFactory;
|
|
|
|
/**
|
|
* @var \Magento\Quote\Model\QuoteFactory
|
|
*/
|
|
protected $quoteFactory;
|
|
|
|
/**
|
|
* @var \Magento\Quote\Model\QuoteManagement
|
|
*/
|
|
protected $quoteManagement;
|
|
|
|
/**
|
|
* @var \Magento\Quote\Api\CartRepositoryInterface
|
|
*/
|
|
protected $cartRepository;
|
|
|
|
/**
|
|
* @var \Magento\Quote\Api\CartManagementInterface
|
|
*/
|
|
protected $cartManagement;
|
|
|
|
/**
|
|
* @var \Magento\Store\Model\StoreManagerInterface
|
|
*/
|
|
protected $storeManager;
|
|
|
|
/**
|
|
* @var \Magento\CatalogInventory\Api\StockRegistryInterface
|
|
*/
|
|
protected $stockRegistry;
|
|
|
|
/**
|
|
* @var GetStockIdForCurrentWebsite
|
|
*/
|
|
protected $getStockIdForCurrentWebsite;
|
|
|
|
/**
|
|
* @var GetReservationsQuantityInterface
|
|
*/
|
|
protected $getReservationsQuantity;
|
|
|
|
/**
|
|
* @var CustomersSyncService
|
|
*/
|
|
protected $customersSyncService;
|
|
|
|
/**
|
|
* @var OrderMapper
|
|
*/
|
|
protected $orderMapper;
|
|
|
|
/**
|
|
* @var SourceRepositoryInterface
|
|
*/
|
|
protected $sourceRepository;
|
|
|
|
/**
|
|
* @var \Magento\Catalog\Api\ProductRepositoryInterface
|
|
*/
|
|
protected $productRepository;
|
|
|
|
/**
|
|
* @var \Magento\Sales\Api\OrderRepositoryInterface
|
|
*/
|
|
protected $orderRepository;
|
|
|
|
/**
|
|
* @var \Magento\Sales\Model\OrderFactory
|
|
*/
|
|
protected $orderFactory;
|
|
|
|
/**
|
|
* @var \Magento\Framework\Api\SearchCriteriaBuilder
|
|
*/
|
|
protected $searchCriteriaBuilder;
|
|
|
|
/**
|
|
* @var \Magento\Quote\Api\Data\AddressExtensionInterfaceFactory
|
|
*/
|
|
protected $addressExtensionFactory;
|
|
|
|
/**
|
|
* @var \Magento\Quote\Model\Quote\Address\Rate
|
|
*/
|
|
private $shippingRate;
|
|
|
|
/**
|
|
* @var ProductsSyncService
|
|
*/
|
|
protected $productsSync;
|
|
|
|
/**
|
|
* @var \JR\NetSuite\Helper\Data
|
|
*/
|
|
|
|
protected $helper;
|
|
|
|
/**
|
|
* @var \JR\NetSuite\Logger\Logger
|
|
*/
|
|
protected $logger;
|
|
|
|
/**
|
|
* @var int
|
|
*/
|
|
protected $defaultStoreId;
|
|
|
|
/**
|
|
* @var array
|
|
*/
|
|
protected $productStocks = [];
|
|
|
|
/**
|
|
* OrdersSyncService constructor.
|
|
* @param AddressFactory $addressFactory
|
|
* @param QuoteFactory $quoteFactory
|
|
* @param QuoteManagement $quoteManagement
|
|
* @param CartRepositoryInterface $cartRepository
|
|
* @param CartManagementInterface $cartManagement
|
|
* @param StoreManagerInterface $storeManager
|
|
* @param StockRegistryInterface $stockRegistry
|
|
* @param GetStockIdForCurrentWebsite $getStockIdForCurrentWebsite
|
|
* @param GetReservationsQuantityInterface $getReservationsQuantity
|
|
* @param CustomersSyncService $customersSyncService
|
|
* @param OrderMapper $orderMapper
|
|
* @param SourceRepositoryInterface $sourceRepository
|
|
* @param ProductRepositoryInterface $productRepository
|
|
* @param OrderRepositoryInterface $orderRepository
|
|
* @param OrderFactory $orderFactory
|
|
* @param SearchCriteriaBuilder $searchCriteriaBuilder
|
|
* @param AddressExtensionInterfaceFactory $addressExtensionFactory
|
|
* @param Rate $shippingRate
|
|
* @param ProductsSyncService $productsSync
|
|
* @param \JR\NetSuite\Helper\Data $helper
|
|
* @param \JR\NetSuite\Logger\Logger $logger
|
|
*/
|
|
public function __construct(
|
|
AddressFactory $addressFactory,
|
|
QuoteFactory $quoteFactory,
|
|
QuoteManagement $quoteManagement,
|
|
CartRepositoryInterface $cartRepository,
|
|
CartManagementInterface $cartManagement,
|
|
StoreManagerInterface $storeManager,
|
|
StockRegistryInterface $stockRegistry,
|
|
GetStockIdForCurrentWebsite $getStockIdForCurrentWebsite,
|
|
GetReservationsQuantityInterface $getReservationsQuantity,
|
|
CustomersSyncService $customersSyncService,
|
|
OrderMapper $orderMapper,
|
|
SourceRepositoryInterface $sourceRepository,
|
|
ProductRepositoryInterface $productRepository,
|
|
OrderRepositoryInterface $orderRepository,
|
|
OrderFactory $orderFactory,
|
|
SearchCriteriaBuilder $searchCriteriaBuilder,
|
|
AddressExtensionInterfaceFactory $addressExtensionFactory,
|
|
Rate $shippingRate,
|
|
ProductsSyncService $productsSync,
|
|
\JR\NetSuite\Helper\Data $helper,
|
|
\JR\NetSuite\Logger\Logger $logger
|
|
) {
|
|
$this->addressFactory = $addressFactory;
|
|
$this->quoteFactory = $quoteFactory;
|
|
$this->quoteManagement = $quoteManagement;
|
|
$this->cartRepository = $cartRepository;
|
|
$this->cartManagement = $cartManagement;
|
|
$this->storeManager = $storeManager;
|
|
$this->stockRegistry = $stockRegistry;
|
|
$this->getStockIdForCurrentWebsite = $getStockIdForCurrentWebsite;
|
|
$this->getReservationsQuantity = $getReservationsQuantity;
|
|
$this->customersSyncService = $customersSyncService;
|
|
$this->orderMapper = $orderMapper;
|
|
$this->sourceRepository = $sourceRepository;
|
|
$this->productRepository = $productRepository;
|
|
$this->orderRepository = $orderRepository;
|
|
$this->orderFactory = $orderFactory;
|
|
$this->searchCriteriaBuilder = $searchCriteriaBuilder;
|
|
$this->addressExtensionFactory = $addressExtensionFactory;
|
|
$this->shippingRate = $shippingRate;
|
|
$this->productsSync = $productsSync;
|
|
$this->helper = $helper;
|
|
$this->logger = $logger;
|
|
$this->defaultStoreId = $this->helper->getDefaultStoreId();
|
|
}
|
|
|
|
/**
|
|
* Create or Skip a order based on the provided data
|
|
*
|
|
* @param array $data
|
|
* @return array
|
|
* @throws LocalizedException
|
|
*/
|
|
public function createOrSkip(array $data) {
|
|
$order = $this->orderMapper->getOrderBy('netsuite_id', $data['netsuite_order_id']);
|
|
if ($order) {
|
|
return [
|
|
'data' => $order,
|
|
'is_new' => false
|
|
];
|
|
}
|
|
|
|
$order = $this->create($data);
|
|
return [
|
|
'data' => $order,
|
|
'is_new' => true
|
|
];
|
|
}
|
|
|
|
/**
|
|
* Create or Update a order based on the provided data. Only update status for now. TODO: Update other order attributes including item, price etc.
|
|
*
|
|
* @param array $data
|
|
* @return array
|
|
* @throws LocalizedException
|
|
*/
|
|
public function createOrUpdate(array $data) {
|
|
// $this->logger->info("[OrdersSyncService] createOrUpdate: " . json_encode($data));
|
|
$order = $this->orderMapper->getOrderBy('netsuite_id', $data['netsuite_order_id']);
|
|
|
|
if ($order) {
|
|
$this->updateOrderStatus($order, $data['status']);
|
|
return [
|
|
'data' => $order,
|
|
'is_new' => false
|
|
];
|
|
}
|
|
|
|
$order = $this->create($data);
|
|
return [
|
|
'data' => $order,
|
|
'is_new' => true
|
|
];
|
|
}
|
|
|
|
private function updateOrderStatus($order, $newStatus) {
|
|
$currentStatus = $order->getStatus();
|
|
if ($currentStatus === $newStatus) {
|
|
// $this->logger->info("[OrdersSyncService] updateOrderStatus: Order #" . $order->getIncrementId() . " is already in status '$currentStatus'. No change needed.");
|
|
return false;
|
|
}
|
|
|
|
// Map status ? state
|
|
$statusStateMap = [
|
|
'pending' => \Magento\Sales\Model\Order::STATE_NEW,
|
|
'processing' => \Magento\Sales\Model\Order::STATE_PROCESSING,
|
|
'complete' => \Magento\Sales\Model\Order::STATE_COMPLETE,
|
|
'canceled' => \Magento\Sales\Model\Order::STATE_CANCELED,
|
|
'closed' => \Magento\Sales\Model\Order::STATE_CLOSED,
|
|
'holded' => \Magento\Sales\Model\Order::STATE_HOLDED,
|
|
'payment_review' => \Magento\Sales\Model\Order::STATE_PAYMENT_REVIEW,
|
|
];
|
|
|
|
$newState = $statusStateMap[$newStatus] ?? null;
|
|
if (!$newState) {
|
|
$this->logger->error("[OrdersSyncService] updateOrderStatus: Unknown status '$newStatus'.");
|
|
return false;
|
|
}
|
|
|
|
try {
|
|
$order->setStatus($newStatus);
|
|
$order->setState($newState);
|
|
|
|
$this->orderRepository->save($order);
|
|
|
|
// $this->logger->info("[OrdersSyncService] updateOrderStatus: Order #" . $order->getIncrementId() . " updated from status '$currentStatus' to '$newStatus' (state: '$newState').");
|
|
return true;
|
|
|
|
} catch (\Exception $e) {
|
|
$this->logger->error("[OrdersSyncService] updateOrderStatus: Error updating order -> " . $e->getMessage());
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Create or Update a order based on the provided data
|
|
*
|
|
* @param array $data
|
|
* @return OrderInterface
|
|
* @throws LocalizedException
|
|
*/
|
|
public function create(array $data) {
|
|
$quote = $this->buildQuote($data);
|
|
$order = $this->quoteManagement->submit($quote);
|
|
$order = $this->orderRepository->get($order->getId());
|
|
$order->setStatus($data['status'])
|
|
->setState($data['status'])
|
|
->setCreatedAt($data['purchase_date'])
|
|
->setEmailSent(0)
|
|
->setNetsuiteId($data['netsuite_order_id'])
|
|
->setNetsuiteNumber($data['netsuite_order_number'])
|
|
->setIsNetsuiteSync(!empty($data['netsuite_order_number']));
|
|
$this->addDiscount($order, $data['items']);
|
|
$this->addTax($order, $data['items']);
|
|
$this->addShipping($order, $data['items']);
|
|
$this->orderRepository->save($order);
|
|
$this->afterOrderSave();
|
|
return $order;
|
|
}
|
|
|
|
/**
|
|
* @param array $data
|
|
* @return Quote
|
|
* @throws LocalizedException
|
|
*/
|
|
private function buildQuote(array $data): Quote {
|
|
$quote = $this->initQuote($data);
|
|
$quote = $this->addItems($quote, $data['items']);
|
|
$quote = $this->setAddresses($quote, $data);
|
|
$quote = $this->setPayment($quote, $data['payment']['method'] ?? 'checkmo');
|
|
$quote->setInventoryProcessed(false);
|
|
$quote->setTotalsCollectedFlag(false);
|
|
$quote->collectTotals();
|
|
// $this->addTax($quote, $data['items']);
|
|
// $quote->setTaxAmount($data['tax']);
|
|
// $quote->setBaseTaxAmount($data['tax']);
|
|
$this->cartRepository->save($quote);
|
|
|
|
return $quote;
|
|
}
|
|
|
|
/**
|
|
* @param array $data
|
|
* @return Quote
|
|
* @throws LocalizedException
|
|
*/
|
|
private function initQuote(array $data): Quote {
|
|
$store = $this->storeManager->getStore($this->defaultStoreId);
|
|
$websiteId = $store->getWebsiteId();
|
|
// get the customer by email
|
|
$customer = $this->getOrCreateCustomer($data, $websiteId);
|
|
$cartId = $this->cartManagement->createEmptyCart();
|
|
$quote = $this->cartRepository->get($cartId);
|
|
|
|
$quote->setStore($store);
|
|
$quote->setCurrency();
|
|
$quote->assignCustomer($customer);
|
|
if ($quote->getCustomer()->getId()) {
|
|
$quote->setCustomerIsGuest(0);
|
|
}
|
|
|
|
// Write PO Number
|
|
$quote->setOtherRefNum($data['other_ref_num']);
|
|
|
|
// Set custom data
|
|
$quote->setData('netsuite_order_id', $data['netsuite_order_id']);
|
|
|
|
return $quote;
|
|
}
|
|
|
|
/**
|
|
* @param array $data
|
|
* @param int $websiteId
|
|
* @return \Magento\Customer\Api\Data\CustomerInterface
|
|
* @throws LocalizedException
|
|
*/
|
|
private function getOrCreateCustomer(array $data, int $websiteId) {
|
|
if (empty($data['firstname'])) $data['firstname'] = $data['shipping_address']['firstname'] ?? $data['billing_address']['firstname'] ?? '';
|
|
if (empty($data['lastname'])) $data['lastname'] = $data['shipping_address']['lastname'] ?? $data['billing_address']['lastname'] ?? '';
|
|
|
|
$customerData = $data;
|
|
if (isset($data['customer'])) {
|
|
if (count($data['customer']) == 1) $data['customer'] = reset($data['customer']);
|
|
if (($data['customer']['email'] ?? '') == '') $data['customer']['email'] = $data['email'];
|
|
$customerData = $data['customer'];
|
|
}
|
|
if (empty($data['firstname'])) $data['firstname'] = $data['shipping_address']['firstname'] ?? $data['billing_address']['firstname'] ?? $customerData['firstname'] ?? '';
|
|
if (empty($data['lastname'])) $data['lastname'] = $data['shipping_address']['lastname'] ?? $data['billing_address']['lastname'] ?? $customerData['lastname'] ?? '';
|
|
|
|
$result = $this->customersSyncService->createOrSkip($customerData);
|
|
|
|
return $result['data'];
|
|
|
|
// try {
|
|
// $customer = $this->customerRepository->get($data['email'], $websiteId);
|
|
// } catch (\Magento\Framework\Exception\NoSuchEntityException $e) {
|
|
// $customer = $this->customerFactory->create();
|
|
// }
|
|
// if (!$customer->getId()) {
|
|
// $customer->setWebsiteId($websiteId)
|
|
// ->setFirstname($data['shipping_address']['firstname'])
|
|
// ->setLastname($data['shipping_address']['lastname'])
|
|
// ->setEmail($data['email']);
|
|
// $customer = $this->customerRepository->save($customer);
|
|
// }
|
|
// return $customer;
|
|
}
|
|
|
|
/**
|
|
* @param Quote $quote
|
|
* @param Quote $quote
|
|
* @return Quote
|
|
* @throws LocalizedException
|
|
*/
|
|
private function addItems(Quote $quote, array $items = []): Quote {
|
|
$productNameError = '';
|
|
foreach ($items as $item) {
|
|
if ($item['type'] != self::INVT_PART) continue;
|
|
$product = $this->productRepository->get($item['sku']);
|
|
// need to be changed if multi location
|
|
// Product stock is being synced by cronjob, ProductSyncWorker::processQueueItems. There is no need to touch stock during order sync
|
|
/*
|
|
$stockDetail = $this->productsSync->updateStockForProduct($item['sku'], $item, $product->getStore()->getWebsiteId());
|
|
$this->productStocks[$item['sku']] = $stockDetail;
|
|
*/
|
|
$stockItem = $this->stockRegistry->getStockItem($product->getId());
|
|
$qty = (int) $stockItem->getQty() + $item['qty'];
|
|
$stockId = $this->getStockIdForCurrentWebsite->execute();
|
|
$qty -= $this->getReservationsQuantity->execute($item['sku'], $stockId);
|
|
$stockItem->setData('is_in_stock', 1);
|
|
$stockItem->setData('qty', $qty);
|
|
$stockItem->setData('manage_stock', 1);
|
|
$stockItem->setData('use_config_notify_stock_qty', 1);
|
|
$stockItem->save();
|
|
// $status = $product->getStatus();
|
|
// $salable = $product->getData('salable');
|
|
$product->setOrigData('status', 1);
|
|
$product->setStatus(1);
|
|
$product->setData('salable', true);
|
|
$product->setPrice($item['price']);
|
|
$discountAmount = ((float)$item['amount'] - (float)$item['price'] * $item['qty']) / $item['qty'];
|
|
// $product->setSpecialPrice($item['price'] + $discountAmount);
|
|
$productNameError = $productNameError . ' ' . $product->getName() . '( SKU : ' . $product->getSku() . ')';
|
|
// $this->logger->info($product->getSku() . ' ' . $item['qty']);
|
|
$quoteItem = $quote->addProduct($product, (int) $item['qty']);
|
|
// $product->setStatus($status);
|
|
// $product->setData('salable', $salable);
|
|
// $product->save();
|
|
// $quoteItem->setTaxPercent($quote->getTaxPercent());
|
|
// $quoteItem->setTaxAmount($item['amount'] * $quote->getTaxPercent() / 100);
|
|
// $quoteItem->setBaseTaxAmount($item['amount'] * $quote->getTaxPercent() / 100);
|
|
// $quoteItem->setDiscountAmount($discountAmount);
|
|
// $quoteItem->setBaseDiscountAmount($discountAmount);
|
|
// $quoteItem->setSubtotal($item['price'] * $item['qty']);
|
|
// $quoteItem->setBaseSubtotal($item['price'] * $item['qty']);
|
|
// $quoteItem->setRowTotal($item['amount']);
|
|
// $quoteItem->setBaseRowTotal($item['amount']);
|
|
$quoteItem->setCustomPrice($item['price']);
|
|
$quoteItem->setOriginalCustomPrice($item['price']);
|
|
$quoteItem->getProduct()->setIsSuperMode(true);
|
|
}
|
|
return $quote;
|
|
}
|
|
|
|
/**
|
|
* @param OrderInterface $order
|
|
* @param array $items
|
|
*/
|
|
private function addDiscount(OrderInterface $order, array $items): void {
|
|
$discount = 0;
|
|
$discountDescription = '';
|
|
$itemMap = [];
|
|
foreach ($items as $item) {
|
|
if ($item['type'] == self::DISCOUNT) {
|
|
$discount += $item['amount'];
|
|
$discountDescription = $item['sku'];
|
|
} else {
|
|
$itemMap[$item['sku']] = $item;
|
|
}
|
|
}
|
|
|
|
if ($discount == 0) {
|
|
return;
|
|
}
|
|
|
|
$order->setDiscountAmount($discount);
|
|
$order->setBaseDiscountAmount($discount);
|
|
$order->setDiscountDescription($discountDescription);
|
|
$order->setGrandTotal($order->getGrandTotal() + $discount);
|
|
$order->setBaseGrandTotal($order->getBaseGrandTotal() + $discount);
|
|
|
|
foreach ($order->getAllItems() as $item) {
|
|
if ($item) {
|
|
$itemData = $itemMap[$item->getSku()];
|
|
$discountAmount = $itemData['price'] * $itemData['qty'] - $itemData['amount'];
|
|
$discountRate = $itemData['price'] == 0 ? 0 : $discountAmount / ($itemData['price'] * $itemData['qty']) * 100;
|
|
$item->setDiscountPercent($discountRate);
|
|
$item->setDiscountAmount($discountAmount);
|
|
$item->setBaseDiscountAmount($discountAmount);
|
|
$item->save();
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param OrderInterface $order
|
|
* @param array $items
|
|
*/
|
|
private function addTax(OrderInterface $order, array $items): void {
|
|
$tax = 0;
|
|
$taxRate = 0;
|
|
foreach ($items as $item) {
|
|
if ($item['type'] == self::TAX_GROUP) {
|
|
$tax += $item['amount'];
|
|
$taxRate += $item['price'];
|
|
}
|
|
}
|
|
|
|
if ($tax <= 0) {
|
|
return;
|
|
}
|
|
// $order->setTaxPercent($taxRate);
|
|
$order->setTaxAmount($tax);
|
|
$order->setBaseTaxAmount($tax);
|
|
$order->setGrandTotal($order->getGrandTotal() + $tax);
|
|
$order->setBaseGrandTotal($order->getBaseGrandTotal() + $tax);
|
|
|
|
foreach ($order->getAllItems() as $item) {
|
|
if ($item) {
|
|
$item->setTaxPercent($taxRate);
|
|
$taxAmount = $item->getPrice() * $item->getQtyOrdered() * $taxRate / 100;
|
|
$item->setTaxAmount($taxAmount);
|
|
$item->setBaseTaxAmount($taxAmount);
|
|
$priceInclTax = $item->getPrice() + $item->getPrice() * $taxRate / 100;
|
|
$item->setPriceInclTax($priceInclTax);
|
|
$item->setBasePriceInclTax($priceInclTax);
|
|
$item->setRowTotalInclTax($item->getRowTotal() + $item->getTaxAmount());
|
|
$item->setBaseRowTotalInclTax($item->getBaseRowTotal() + $item->getBaseTaxAmount());
|
|
$item->save();
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param Quote $quote
|
|
* @param array $data
|
|
* @return Quote
|
|
*/
|
|
private function setAddresses(Quote $quote, array $data): Quote {
|
|
if (!isset($data['shipping_address']) || empty($data['shipping_address'])) {
|
|
if (isset($data['customer']) && ($data['customer']['isdefaultshipping'] ?? false)) {
|
|
$data['shipping_address'] = $data['customer']['shipping_address'];
|
|
} else if ($shippingAddressId = $quote->getCustomer()->getDefaultShipping()) {
|
|
$shippingAddress = $this->addressFactory->create()->load($shippingAddressId);
|
|
$data['shipping_address'] = $shippingAddress->getData();
|
|
} else if (isset($data['customer'][0]['shipping_address'])) {
|
|
$data['shipping_address'] = $data['customer'][0]['shipping_address'];
|
|
}
|
|
} else {
|
|
if ($data['shipping_address']['firstname'] == '') {
|
|
if (isset($data['customer'])) {
|
|
$data['shipping_address']['firstname'] = $data['customer']['firstname'];
|
|
} else {
|
|
$data['shipping_address']['firstname'] = $quote->getCustomer()->getFirstname();
|
|
}
|
|
}
|
|
if ($data['shipping_address']['lastname'] == '') {
|
|
if (isset($data['customer'])) {
|
|
$data['shipping_address']['lastname'] = $data['customer']['lastname'];
|
|
} else {
|
|
$data['shipping_address']['lastname'] = $quote->getCustomer()->getLastname();
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!isset($data['billing_address']) || empty($data['billing_address'])) {
|
|
if (isset($data['customer']) && ($data['customer']['isdefaultbilling'] ?? false)) {
|
|
$data['billing_address'] = $data['customer']['billing_address'];
|
|
} else if ($billingAddressId = $quote->getCustomer()->getDefaultBilling()) {
|
|
$billingAddress = $this->addressFactory->create()->load($billingAddressId);
|
|
$data['billing_address'] = $billingAddress->getData();
|
|
unset($data['billing_address']['entity_id']);
|
|
} else if (isset($data['customer'][0]['billing_address'])) {
|
|
$data['billing_address'] = $data['customer'][0]['billing_address'];
|
|
}
|
|
}
|
|
|
|
if (isset($data['shipping_address']) && !$data['shipping_address']['company']) $data['shipping_address']['company'] = $data['company'];
|
|
if (isset($data['billing_address']) && !$data['billing_address']['company']) $data['billing_address']['company'] = $data['company'];
|
|
$quote->getBillingAddress()->addData($data['billing_address'] ?? $data['shipping_address'] ?? []);
|
|
$shippingAddress = $quote->getShippingAddress()
|
|
->addData($data['shipping_address'] ?? $data['billing_address'] ?? []);
|
|
// $shippingAddress->getShippingRateByCode($shippingAddress->getShippingMethod());
|
|
$shippingItem = $this->getShippingItem($data['items']);
|
|
$shippingItem['sku'] = $shippingItem['sku'] ?? '';
|
|
$this->shippingRate->setCode($shippingItem['sku'])
|
|
->setPrice($shippingItem['amount'] ?? 0);
|
|
|
|
if (strpos(strtolower($shippingItem['sku']), 'ups') !== false) {
|
|
$shippingAddress->setShippingMethod('ups');
|
|
} else if (strpos(strtolower($shippingItem['sku']), 'fedex') !== false) {
|
|
$shippingAddress->setShippingMethod('fedex');
|
|
} else {
|
|
$shippingAddress->setShippingMethod('flatrate_flatrate');
|
|
}
|
|
|
|
$m2ShipMethod = $this->orderMapper->parseNetSuiteShippingMethod($shippingItem['netsuite_order_item_id'] ?? '');
|
|
$this->logger->info("Shipping Method: " . $shippingItem['netsuite_order_item_id'] . " -> " . $m2ShipMethod);
|
|
if ($m2ShipMethod == 'instore_pickup') {
|
|
$pickupLocationCode = $this->getPickupLocationSourceCode($data['netsuite_order_location_id']);
|
|
$pickupSource = $this->sourceRepository->get($pickupLocationCode);
|
|
$this->logger->info("Pickup Location: {$pickupLocationCode}");
|
|
|
|
$street = $pickupSource->getStreet();
|
|
if (!is_array($street)) {
|
|
$street = [$street];
|
|
}
|
|
|
|
$shippingAddress->setShippingMethod($m2ShipMethod)
|
|
->setFirstname($data['shipping_address']['firstname'])
|
|
->setLastname($data['shipping_address']['lastname'])
|
|
->setSameAsBilling(false) // ***
|
|
->setStreet($street) // ***
|
|
->setCity($pickupSource->getCity()) // ***
|
|
->setRegionId($pickupSource->getRegionId()) // ***
|
|
->setRegion($pickupSource->getRegion()) // ***
|
|
->setPostcode($pickupSource->getPostcode()) // ***
|
|
->setCountryId($pickupSource->getCountryId()) // ***
|
|
->setTelephone($data['shipping_address']['telephone'] ?? '000-000-0000')
|
|
->setShippingDescription("In-Store Pickup Delivery - {$pickupSource->getName()}");
|
|
|
|
$extensionAttributes = $shippingAddress->getExtensionAttributes();
|
|
if (!$extensionAttributes) {
|
|
$extensionAttributes = $this->addressExtensionFactory->create();
|
|
}
|
|
$extensionAttributes->setPickupLocationCode($pickupLocationCode);
|
|
$shippingAddress->setExtensionAttributes($extensionAttributes);
|
|
} else {
|
|
$shippingAddress->setCollectShippingRates(true)
|
|
->setShippingMethod($m2ShipMethod)
|
|
->collectShippingRates();
|
|
$shippingAmount = (float) $shippingItem['amount'];
|
|
$quote->getShippingAddress()
|
|
->setShippingAmount($shippingAmount)
|
|
->setBaseShippingAmount((float) $shippingItem['amount'])
|
|
->setShippingDescription($shippingItem['sku']);
|
|
$quote->getShippingAddress()->addShippingRate($this->shippingRate);
|
|
}
|
|
|
|
// $shippingAddress->setCollectShippingRates(true)
|
|
// ->setShippingMethod('ups_03')
|
|
// ->collectShippingRates();
|
|
// $shippingAmount = (float) $shippingItem['amount'];
|
|
// $quote->getShippingAddress()
|
|
// ->setShippingAmount($shippingAmount)
|
|
// ->setBaseShippingAmount((float) $shippingItem['amount'])
|
|
// ->setShippingDescription($shippingItem['sku']);
|
|
// $quote->getShippingAddress()->addShippingRate($this->shippingRate);
|
|
|
|
$quote->getBillingAddress()->setCustomerAddressId(null);
|
|
$quote->getShippingAddress()->setCustomerAddressId(null);
|
|
|
|
return $quote;
|
|
}
|
|
|
|
/**
|
|
* get shipping item
|
|
*
|
|
* @param array $items
|
|
* @return array
|
|
*/
|
|
private function getShippingItem(array $items): array {
|
|
foreach ($items as $item) {
|
|
if ($item['type'] === self::SHIP_ITEM && $item['price']) {
|
|
return $item;
|
|
}
|
|
}
|
|
return [];
|
|
}
|
|
|
|
/**
|
|
* set shipping to order
|
|
*
|
|
* @param OrderInterface $order
|
|
* @param array $items
|
|
*/
|
|
private function addShipping(OrderInterface $order, array $items) {
|
|
$shippingItem = $this->getShippingItem($items);
|
|
$originShippingAmount = $order->getShippingAmount();
|
|
$order->setShippingAmount($shippingItem['amount']);
|
|
$order->setBaseShippingAmount($shippingItem['amount']);
|
|
$order->setShippingDescription($shippingItem['sku']);
|
|
$grandTotal = $order->getGrandTotal() - $originShippingAmount + $shippingItem['amount'];
|
|
$order->setGrandTotal($grandTotal);
|
|
$order->setBaseGrandTotal($grandTotal);
|
|
}
|
|
|
|
/**
|
|
* @param Quote $quote
|
|
* @param string $paymentMethod
|
|
* @return Quote
|
|
*/
|
|
private function setPayment(Quote $quote, string $paymentMethod): Quote {
|
|
if (!$paymentMethod || $paymentMethod == '') {
|
|
$paymentMethod = 'checkmo';
|
|
}
|
|
$quote->setPaymentMethod($paymentMethod);
|
|
$quote->getPayment()->importData(['method' => $paymentMethod]);
|
|
return $quote;
|
|
}
|
|
|
|
public function afterOrderSave() {
|
|
// Product stock is being synced by cronjob, ProductSyncWorker::processQueueItems. There is no need to touch stock during order sync
|
|
// If for some reason need to uncomment the below, also need to uncomment the part inside addItems()
|
|
/*
|
|
foreach ($this->productStocks as $sku => $stockDetail) {
|
|
$stockDetail['qty'] = $stockDetail['from'];
|
|
$this->productsSync->updateStockForProduct($sku, $stockDetail);
|
|
}
|
|
$this->productStocks = [];
|
|
*/
|
|
}
|
|
|
|
/**
|
|
* Save NetSuite Order ID to Magento Order
|
|
*
|
|
* @param OrderInterface $order
|
|
* @param string $netsuiteOrderId
|
|
* @return void
|
|
*/
|
|
public function saveNetsuiteId(OrderInterface $order, string $netsuiteOrderId) {
|
|
$order->setNetsuiteId($netsuiteOrderId);
|
|
$this->orderRepository->save($order);
|
|
}
|
|
|
|
/**
|
|
* Search inventory source code by NetSuite location id.
|
|
*
|
|
* @param string $nsLocationId
|
|
* @return string
|
|
*/
|
|
private function getPickupLocationSourceCode($nsLocationId) {
|
|
$searchCriteria = $this->searchCriteriaBuilder
|
|
->addFilter('netsuite_id', $nsLocationId)
|
|
->create();
|
|
$sources = $this->sourceRepository->getList($searchCriteria)->getItems();
|
|
if (count($sources) > 0) {
|
|
$source = reset($sources);
|
|
return $source->getSourceCode() ?? '';
|
|
}
|
|
return '';
|
|
}
|
|
|
|
}
|
|
|