Question

For some reason order canceled in bulk through my customly added order cancel mass action. Now I need to uncancel all orders.

  • Change status from cancel to the status that was previously set on order
  • Change state of order that was previously set
  • Subtract all quantities of products which are used in the order that are just reverted by cancelling.
  • Remove order history comments

Any help, experience and knowledge sharing would be highly appreciated.

Was it helpful?

Solution

Create a helper in any of your module

app/code/Vendor/Module/Helper/Data.php

And use following code:

<?php

namespace Vendor\Module\Helper;
use Magento\Framework\App\Helper\AbstractHelper;
use Magento\Framework\App\Helper;
use Magento\Sales\Model\Order;
use Magento\CatalogInventory\Model\Indexer\Stock\Processor as StockProcessor;
class Data extends AbstractHelper
{
    /**
     * @var \Magento\CatalogInventory\Api\StockManagementInterface
     */
    protected $stockManagement;
    /**
     * @var StockProcessor
     */
    protected $stockIndexerProcessor;

    public function __construct(
        Helper\Context $context,
        \Magento\CatalogInventory\Api\StockManagementInterface $stockManagement,
        StockProcessor $stockIndexerProcessor
    )
    {
        parent::__construct($context);
    }

    public function uncancleorder($order, $comment = "")
    {
        if(!($order)){
            throw new \Magento\Framework\Exception\LocalizedException(__('Invalid Order'));
        }

        if ($order->isCanceled()) {
            $state = Order::STATE_PROCESSING;
            $productStockQty = [];
            foreach ($order->getAllVisibleItems() as $item) {
                $productStockQty[$item->getProductId()] = $item->getQtyCanceled();
                foreach ($item->getChildrenItems() as $child) {
                    $productStockQty[$child->getProductId()] = $item->getQtyCanceled();
                    $child->setQtyCanceled(0);
                    $child->setTaxCanceled(0);
                    $child->setDiscountTaxCompensationCanceled(0);
                }
                $item->setQtyCanceled(0);
                $item->setTaxCanceled(0);
                $item->setDiscountTaxCompensationCanceled(0);
            }

            $order->setSubtotalCanceled(0);
            $order->setBaseSubtotalCanceled(0);
            $order->setTaxCanceled(0);
            $order->setBaseTaxCanceled(0);
            $order->setShippingCanceled(0);
            $order->setBaseShippingCanceled(0);
            $order->setDiscountCanceled(0);
            $order->setBaseDiscountCanceled(0);
            $order->setTotalCanceled(0);
            $order->setBaseTotalCanceled(0);
            $order->setState($state)
                ->setStatus($order->getConfig()->getStateDefaultStatus($state));
            if (!empty($comment)) {
                $order->addStatusHistoryComment($comment, false);
            }

            /* Reverting inventory */
            $itemsForReindex = $this->stockManagement->registerProductsSale(
                $productStockQty,
                $order->getStore()->getWebsiteId()
            );
            $productIds = [];
            foreach ($itemsForReindex as $item) {
                $item->save();
                $productIds[] = $item->getProductId();
            }
            if (!empty($productIds)) {
                $this->stockIndexerProcessor->reindexList($productIds);
            }
            $order->setInventoryProcessed(true);

            $order->save();

        } else {
            throw new \Magento\Framework\Exception\LocalizedException(__('We cannot un-cancel this order.'));
        }
        return true;
    }
}

Note: Edit this helper according to your requirements.

Now call uncancel method anywhere, just pass order object and comment(if required)

Reference module: https://github.com/Genmato/M2_UnCancelOrder

Licensed under: CC-BY-SA with attribution
Not affiliated with magento.stackexchange
scroll top