Magento 2: Split order for every Item
I've been checking this on my own Magento 2.2 Enterprise local implementation, and I got it working using this:
public function placeOrder($cartId, PaymentInterface $paymentMethod = null)
{
$quote = $this->quoteRepository->getActive($cartId);
$paymentMethodString = $quote->getPayment()->getMethod(); // edit 19.10.17
// get data from addresses and remove ids
$billingAddress = $quote->getBillingAddress()->getData();
$shippingAddress = $quote->getShippingAddress()->getData();
unset($billingAddress['id']);
unset($billingAddress['quote_id']);
unset($shippingAddress['id']);
unset($shippingAddress['quote_id']);
foreach($quote->getAllItems() as $item) {
// init Quote Split
$quoteSplit = $this->quoteFactory->create();
$quoteSplit->setStoreId($quote->getStoreId());
$quoteSplit->setCustomer($quote->getCustomer());
$quoteSplit->setCustomerIsGuest($quote->getCustomerIsGuest());
if ($quote->getCheckoutMethod() === self::METHOD_GUEST) {
$quoteSplit->setCustomerEmail($quote->getBillingAddress()->getEmail());
$quoteSplit->setCustomerGroupId(\Magento\Customer\Api\Data\GroupInterface::NOT_LOGGED_IN_ID);
}
// save quoteSplit in order to have a quote id for item
$this->quoteRepository->save($quoteSplit);
// add item
$item->setId(null); // init item id for force to be added to quoteSplit collection
$quoteSplit->addItem($item);
// set addresses
$quoteSplit->getBillingAddress()->setData($billingAddress);
$quoteSplit->getShippingAddress()->setData($shippingAddress);
// recollect totals into the quote
$quoteSplit->setTotalsCollectedFlag(false)->collectTotals();
// set payment method // edit 19.10.17
$quoteSplit->getPayment()->setMethod($paymentMethodString);
if ($paymentMethod) {
$quoteSplit->getPayment()->setQuote($quoteSplit);
$data = $paymentMethod->getData();
$quoteSplit->getPayment()->importData($data);
}
// dispatch this event as Magento standard once per each quote split
$this->eventManager->dispatch('checkout_submit_before', ['quote' => $quoteSplit]);
$this->quoteRepository->save($quoteSplit);
$order = $this->submit($quoteSplit);
$orders[] = $order;
if (null == $order) {
throw new LocalizedException(
__('An error occurred on the server. Please try to place the order again.')
);
}
}
// disable origin quote
$quote->setIsActive(false);
$this->quoteRepository->save($quote); // edit 19.10.17
$this->checkoutSession->setLastQuoteId($quoteSplit->getId());
$this->checkoutSession->setLastSuccessQuoteId($quoteSplit->getId());
$this->checkoutSession->setLastOrderId($order->getId());
$this->checkoutSession->setLastRealOrderId($order->getIncrementId());
$this->checkoutSession->setLastOrderStatus($order->getStatus());
$this->eventManager->dispatch('checkout_submit_all_after', ['orders' => $orders, 'quote' => $quote]);
/**
* the API declaration and interface describe this function returning int, you can't return an array.
* in order to do that you will have to create a new end point for that.
*/
return $order->getId();
}
Please let me know if this fix the issue for you or if you got some error.