Question

I need to add several order statuses. Could not found info how to implement it via Data Patches

No correct solution

OTHER TIPS

The answer is pretty simple.

  1. Create folder Setup/Patch/Data in your module
  2. Create class UpdateOrderStatuses (listing below)
  3. Implement method apply in the class UpdateOrderStatuses.
  4. run bin/magento setup:upgrade

After that Magento runs your patch and in case of success - add your patch path to patch_list table.

class UpdateOrderStatuses implements DataPatchInterface
{
    /**
     * @var \Magento\Framework\Setup\ModuleDataSetupInterface
     */
    private $moduleDataSetup;

    public function __construct(
        \Magento\Framework\Setup\ModuleDataSetupInterface $moduleDataSetup
    ) {
        $this->moduleDataSetup = $moduleDataSetup;
    }

    /**
     * {@inheritdoc}
     */
    public function apply()
    {
        // Insert statuses
        // use insertOnDuplicate(), insertArray() etc here
        $this->moduleDataSetup->getConnection()->insertOnDuplicate(
            $this->moduleDataSetup->getTable('sales_order_status'),
            ['status' => 'new_status', 'label' => 'New Label']
        );

        //Bind status to state
        $states = [
            [
                'status'     => 'new_status',
                'state'      => 'processing',
                'is_default' => 0,
            ],
            [
                'status'     => 'new_status',
                'state'      => 'complete',
                'is_default' => 0,
            ],
            [
                'status'     => 'new_status',
                'state'      => 'closed',
                'is_default' => 0,
            ],
        ];
        foreach ($states as $state) {
            $this->moduleDataSetup->getConnection()->insertOnDuplicate(
                $this->moduleDataSetup->getTable('sales_order_status_state'),
                $state
            );
        }
    }

    /**
     * {@inheritdoc}
     */
    public static function getDependencies()
    {
        return [];
    }

    /**
     * {@inheritdoc}
     */
    public function getAliases()
    {
        return [];
    }
}

This will be similar to the above answer but with adding the order status via ResouceModel and Model classes. Tested in M2 version 2.3.5

Steps;

  1. Create folder Setup/Patch/Data in your module
  2. Create the class (i.e. AddManuallyClosedOrderStatus)
  3. Add the patch class content
    <?php
    
    namespace Vendor\Module\Setup\Patch\Data;
    
    use Magento\Framework\Setup\Patch\DataPatchInterface;
    use Magento\Framework\Setup\Patch\PatchRevertableInterface;
    use Magento\Sales\Model\ResourceModel\Order\Status;
    use Magento\Sales\Model\Order\StatusFactory;
    use Magento\Framework\Setup\ModuleDataSetupInterface;
    
    /**
    * Class to add Manually Closed order status
    */
    class AddManuallyClosedOrderStatus implements DataPatchInterface, PatchRevertableInterface
    {
        const ORDER_STATUS = 'manually_closed';
    
        const ORDER_STATUS_LABEL = 'Manually Closed';
    
        const ORDER_STATES = ['processing', 'complete', 'closed'];
    
        /**
         * @var Status
         */
        private $orderStatusResourceModel;
    
        /**
         * @var StatusFactory
         */
        private $orderStatusFactory;
    
        /**
         * @var ModuleDataSetupInterface
         */
        private $moduleDataSetup;
    
        /**
         * AddManuallyClosedOrderStatus constructor.
         * @param Status $orderStatusResourceModel
         * @param StatusFactory $orderStatusFactory
         */
        public function __construct(
            Status $orderStatusResourceModel,
            StatusFactory $orderStatusFactory,
            ModuleDataSetupInterface $moduleDataSetup
        ) {
            $this->orderStatusResourceModel = $orderStatusResourceModel;
            $this->orderStatusFactory = $orderStatusFactory;
            $this->moduleDataSetup = $moduleDataSetup;
        }
    
        /**
         * {@inheritdoc}
         */
        public function apply()
        {
            $manuallyCloseOrderStatus = $this->orderStatusFactory->create();
            $manuallyCloseOrderStatus->setStatus(self::ORDER_STATUS);
            $manuallyCloseOrderStatus->setLabel(self::ORDER_STATUS_LABEL);
            // save the custom order status
            $this->orderStatusResourceModel->save($manuallyCloseOrderStatus);
            // assign the custom order status to state
            foreach (self::ORDER_STATES as $state) {
                $this->orderStatusResourceModel->assignState(
                    self::ORDER_STATUS,
                    $state,
                    0,
                    true
                );
            }
        }
    
        /**
         * {@inheritdoc}
         */
        public static function getDependencies()
        {
            return [];
        }
    
        /**
         * {@inheritdoc}
         */
        public function revert()
        {
            // revert the changes if custom order status not be used in any order
            if (!$this->orderStatusResourceModel->checkIsStatusUsed(self::ORDER_STATUS)) {
                // un-assign the status from order state
                foreach (self::ORDER_STATES as $state) {
                    $this->orderStatusResourceModel->unassignState(self::ORDER_STATUS, $state);
                }
                // remove the custom order status
                $this->moduleDataSetup->getConnection()->startSetup();
                $tableName = $this->moduleDataSetup->getTable('sales_order_status');
                $this->moduleDataSetup->getConnection()->delete($tableName, ['status = ?' => self::ORDER_STATUS]);
                $this->moduleDataSetup->getConnection()->endSetup();
            }
        }
    
        /**
         * {@inheritdoc}
         */
        public function getAliases()
        {
            return [];
        }
    }
  1. run bin/magento setup:upgrade

Hope this will help someone who is looking to do the same thing with model and resource models.

Cheers!

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