Programmatically Create New Shipment in Magento 2

Magento 2 provides an inbuilt option on the admin side to create a shipment. Here are the steps to create the shipment on the admin panel,

  • Log in to your Magento 2 admin panel.
  • Click SALES in the admin sidebar, and then choose Orders from the menu.
  • The order grid will be opened. From this order grid, click View link to which order you wish to create the shipment. Then the order view page will be opened.
  • Click the Ship button on the header section and the New Shipment page will be opened.
  • Enter all the valid data like qty to ship, comments, tracking number, etc and click the Submit Shipment button to create the shipment.

After completing all the above steps, you can see the newly created shipment by clicking the Shipments tab on the order view page.

But if you want to generate a custom script to create the shipment programmatically, use the following full set of code to create the shipment by using the order id. Here, I have given the example for both dependence injection and object manager method.

Create Shipment Using Dependence Injection

Here is the full set of code to create the shipment using dependence injection method,

/**
 * @var \Magento\Sales\Api\OrderRepositoryInterface
 */
protected $orderRepository;

/**
 * @var \Magento\Sales\Model\Convert\Order
 */
protected $convertOrder;

/**
 * @var \Magento\Sales\Model\Order\Shipment\TrackFactory
 */
protected $trackFactory;

/**
 * @var \Magento\Shipping\Model\ShipmentNotifier
 */
protected $shipmentNotifier;

public function __construct(
    ...
    \Magento\Sales\Api\OrderRepositoryInterface $orderRepository,
    \Magento\Sales\Model\Convert\Order $convertOrder,
    \Magento\Sales\Model\Order\Shipment\TrackFactory $trackFactory,
    \Magento\Shipping\Model\ShipmentNotifier $shipmentNotifier
    ...
) {
    ...
    $this->orderRepository = $orderRepository;
    $this->convertOrder = $convertOrder;
    $this->trackFactory = $trackFactory;
    $this->shipmentNotifier = $shipmentNotifier;
    ...
}

/**
 * function to create order shipment
 */
public function createShipment($orderId)
{
    $order = $this->orderRepository->get($orderId);

    // check whether the order can ship or not
    if (!$order->canShip()) {
        throw new \Magento\Framework\Exception\LocalizedException(
            __('Can\'t create the shipment for this order.')
        );
    }

    $shipment = $this->convertOrder->toShipment($order);

    foreach ($order->getAllItems() AS $orderItem) {
        // Check whether the order item has the quantity to ship or is virtual
        if (!$orderItem->getQtyToShip() || $orderItem->getIsVirtual()) {
            continue;
        }

        $qtyToShip = $orderItem->getQtyToShip();

        // Create shipment item with quantity
        $shipmentItem = $convertOrder->itemToShipmentItem($orderItem)->setQty($qtyToShip);

        // Add shipment item to shipment
        $shipment->addItem($shipmentItem);
    }

    // Register shipment
    $shipment->register();
    $shipment->getOrder()->setIsInProcess(true);
    try {
        // Add tracking information, Can add multiple tracking information
        $trackingIds = [
            '0' => ['carrier_code'=>'fedex','title' => 'Federal Express','number'=>'1234567890']
        ];
        foreach ($trackingIds as $trackingId) {
            $data = [
                'carrier_code' => $trackingId['carrier_code'],
                'title' => $trackingId['title'],
                'number' => $trackingId['number'],
            ];
            $track = $this->trackFactory->create()->addData($data);
            $shipment->addTrack($track)->save();
        }

        // Save created shipment and order
        $shipment->save();
        $shipment->getOrder()->save();

        // Send shipment email
        $this->shipmentNotifier->notify($shipment);
        $shipment->save();
    } catch (\Exception $e) {
        throw new \Magento\Framework\Exception\LocalizedException(
            __($e->getMessage())
        );
    }
}

Create Shipment Using Object Manager

Here is the full set of code to create the shipment using object manager method,

<?php
use Magento\Framework\App\Bootstrap;
   
/**
 * If the external file is in the root folder
 */
require __DIR__ . '/app/bootstrap.php';
  
$params = $_SERVER;
   
$bootstrap = Bootstrap::create(BP, $params);
   
$obj = $bootstrap->getObjectManager();
   
$state = $obj->get('Magento\Framework\App\State');
$state->setAreaCode('adminhtml');

$orderId = 1;
$order = $obj->get('\Magento\Sales\Api\OrderRepositoryInterface')->get($orderId);
if ($order->canShip()) {
    $convertOrder = $obj->get('Magento\Sales\Model\Convert\Order');
    $shipment = $convertOrder->toShipment($order);

    foreach ($order->getAllItems() AS $orderItem) {
        // Check whether the order item has the quantity to ship or is virtual
        if (! $orderItem->getQtyToShip() || $orderItem->getIsVirtual()) {
            continue;
        }

        $qtyToShip = $orderItem->getQtyToShip();

        // Create shipment item with quantity
        $shipmentItem = $convertOrder->itemToShipmentItem($orderItem)->setQty($qtyToShip);

        // Add shipment item to shipment
        $shipment->addItem($shipmentItem);
    }

    // Register shipment
    $shipment->register();
    $shipment->getOrder()->setIsInProcess(true);
    try {

        // Add tracking information, Can add multiple tracking information
        $trackingIds = [
            '0' => [
                'carrier_code' => 'fedex',
                'title' => 'Federal Express',
                'number' => '1234567890'
            ]
        ];
        foreach ($trackingIds as $trackingId) {
            $data = [
                'carrier_code' => $trackingId['carrier_code'],
                'title' => $trackingId['title'],
                'number' => $trackingId['number'],
            ];
            $track = $obj->get('\Magento\Sales\Model\Order\Shipment\Track')->addData($data);
            $shipment->addTrack($track)->save();
        }

        // Save created shipment and order
        $shipment->save();
        $shipment->getOrder()->save();

        // Send shipment email
        $obj->get('Magento\Shipping\Model\ShipmentNotifier')
            ->notify($shipment);

        $shipment->save();
    } catch (\Exception $e) {
        throw new \Magento\Framework\Exception\LocalizedException(
            __($e->getMessage())
        );
    }
}

Read Also: Programmatically Create New Invoice in Magento 2

Hope this helps.

Leave a Reply

Your email address will not be published. Required fields are marked *