Magento 2 - Change order status to 'Complete' using observer
-
08-03-2021 - |
Question
I am using sales_order_save_after event to change order status. It's working fine for all order status except STATE_COMPLETE. when i set the order status STATE_COMPLETE to make order Complete but it changed to Closed instead of being Complete. Other order States is working fine. The issue only happening when i try to use STATE_COMPLETE.
public function execute(\Magento\Framework\Event\Observer $observer)
{
$order = $observer->getEvent()->getOrder();
if($order->getState() != 'complete') {
$order->setState(\Magento\Sales\Model\Order::STATE_COMPLETE)->setStatus(\Magento\Sales\Model\Order::STATE_COMPLETE);
$order->save();
}
}
This is what i'm doing
Can anyone help me out to make order status to "Complete" via observer ?
Solution
Ok, so the problem was when i set STATE_COMPLETE Magento make the order closed. But if i set STATE_PROCESSING or STATE_PENDING with status Complete then order status show complete but when i view the order details there it show processing/pending. So i tried to figure out when magento make order status complete and it is when a invoice is generated.
So i use checkout_submit_all_after event and create an invoice through my observer. When i create invoice through my observer magento make the order completed because the invoice is generated.
Here's the observer code -
class CheckoutSubmitAllAfter implements ObserverInterface{
protected $_invoiceService;
protected $_transactionFactory;
public function __construct(
\Magento\Sales\Model\Service\InvoiceService $invoiceService,
\Magento\Framework\DB\TransactionFactory $transactionFactory
) {
$this->_invoiceService = $invoiceService;
$this->_transactionFactory = $transactionFactory;
}
public function execute(\Magento\Framework\Event\Observer $observer)
{
$order = $observer->getEvent()->getOrder();
try {
if(!$order->canInvoice()) {
return null;
}
if(!$order->getState() == 'new') {
return null;
}
$invoice = $this->_invoiceService->prepareInvoice($order);
$invoice->setRequestedCaptureCase(\Magento\Sales\Model\Order\Invoice::CAPTURE_ONLINE);
$invoice->register();
$transaction = $this->_transactionFactory->create()
->addObject($invoice)
->addObject($invoice->getOrder());
$transaction->save();
} catch (\Exception $e) {
$order->addStatusHistoryComment('Exception message: '.$e->getMessage(), false);
$order->save();
return null;
}
}}
OTHER TIPS
Please try following code:
use \Magento\Sales\Model\Order;
public function execute(\Magento\Framework\Event\Observer $observer)
{
$order = $observer->getEvent()->getOrder();
if($order->getState() != Order::STATE_COMPLETE) {
$orderState = Order::STATE_COMPLETE;
// set order status to COMPLETE
$order->setState($orderState)->setStatus(Order::STATE_COMPLETE);
// Save order
$order->save();
}
}
Hope it Works!
Please take note that invoking the the save
method of the order would trigger a state check which might explain why you are experiencing the issue.
Magento 2 has a separate class for checking the order state.
In the Magento\Sales\Model\ResourceModel\Order
class you will find the save method invoking state check
public function save(\Magento\Framework\Model\AbstractModel $object)
{
/** @var \Magento\Sales\Model\Order $object */
$this->stateHandler->check($object);
return parent::save($object);
}
The stateHandler
is an instance of Magento\Sales\Model\ResourceModel\Order\Handler\State
I would recommend that you have a look that the method "check" to trace the logic flow.
You could either override the method check
or create a plugin aroundCheck
to change the state logic flow