1

I have a question, is it possible to get Magento to set order status to "sent" after you have shipped the product instead of "Processing"? Sometimes we have so many orders that need to be shipped and then invoiced when it is a company that is buying the product.

As far as I understand it the order status is set and stays at "Processing" until you have shipped and invoiced the order.

Hope someone can give me a tip how to solve this.

2
  • yes, you need some customization for that.
    – Sohel Rana
    Aug 16, 2022 at 14:30
  • Do you know where I can find a "guide" for that? Aug 16, 2022 at 14:48

1 Answer 1

1

1. Add order status

app/code/Acme/StackExchange/Setup/Patch/Data/AddShippedOrderStatus.php

<?php
declare(strict_types=1);

namespace Acme\StackExchange\Setup\Patch\Data;

use Magento\Framework\Setup\ModuleDataSetupInterface;
use Magento\Framework\Setup\Patch\DataPatchInterface;
use Magento\Framework\Setup\Patch\PatchRevertableInterface;
use Magento\Sales\Model\Order;

class AddShippedOrderStatus implements DataPatchInterface, PatchRevertableInterface
{
    protected const STATUS_SHIPPED  = 'shipped';

    protected ModuleDataSetupInterface $moduleDataSetup;

    public function __construct(
        ModuleDataSetupInterface $moduleDataSetup
    ) {
        $this->moduleDataSetup = $moduleDataSetup;
    }

    /**
     * @inheritDoc
     */
    public function apply()
    {
        $statuses = [
            self::STATUS_SHIPPED => __('Shipped'),
        ];
        $data     = [];
        foreach ($statuses as $code => $info) {
            $data[] = ['status' => $code, 'label' => $info];
        }
        $this->moduleDataSetup->getConnection()->insertArray(
            $this->moduleDataSetup->getTable('sales_order_status'),
            ['status', 'label'],
            $data
        );

        $states = [
            [
                'status'           => self::STATUS_SHIPPED,
                'state'            => Order::STATE_PROCESSING,
                'is_default'       => 0,
                'visible_on_front' => 1,
            ],
        ];

        $this->moduleDataSetup->getConnection()->insertMultiple(
            $this->moduleDataSetup->getTable('sales_order_status_state'),
            $states
        );

        return $this;
    }

    /**
     * @inheritDoc
     */
    public function revert(): void
    {
        $adapter = $this->moduleDataSetup->getConnection();
        $adapter->delete(
            $this->moduleDataSetup->getTable('sales_order_status'),
            $adapter->quoteInto('status = ?', self::STATUS_SHIPPED)
        );
        $adapter->delete(
            $this->moduleDataSetup->getTable('sales_order_status_state'),
            $adapter->quoteInto('status = ?', self::STATUS_SHIPPED)
        );
    }

    /**
     * @inheritDoc
     */
    public function getAliases(): array
    {
        return [];
    }

    /**
     * @inheritDoc
     */
    public static function getDependencies(): array
    {
        return [];
    }
}

2. Register plugin for shipment

app/code/Acme/StackExchange/etc/di.xml

<?xml version="1.0" encoding="UTF-8"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
    <type name="Magento\Sales\Model\Order\Shipment">
        <plugin name="Acme_StackExchange_Plugin_Sales_Model_Order_ShipmentPlugin"
                type="Acme\StackExchange\Plugin\Sales\Model\Order\ShipmentPlugin" sortOrder="10"/>
    </type>
</config>

3. Create plugin and implement your logic

app/code/Acme/StackExchange/Plugin/Sales/Model/Order/ShipmentPlugin.php

<?php
declare(strict_types=1);

namespace Acme\StackExchange\Plugin\Sales\Model\Order;

use Magento\Sales\Model\Order\Shipment;

class ShipmentPlugin
{
    public function afterRegister(Shipment $subject, Shipment $result): Shipment
    {
        // implement your logic here
        $order = $subject->getOrder();
        if (!$order->canShip() && $order->canInvoice()
            && in_array($order->getState(), [$order::STATE_PROCESSING, $order::STATE_NEW], true)
        ) {
            $order->setState($order::STATE_PROCESSING);
            $order->setStatus('shipped');
        }

        return $result;
    }
}

P.S. Make sense to move STATUS_SHIPPED to some helper or model, but I've used constant in Data Patch for simplify the example

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.