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