Suppose in an order there are 3 items(i1,i2,i3) and I want to create separate shipment with tracking number for all the items.


i1 have Carrier Title as "Title1" and Tracking Number as "123456"

i2 have Carrier Title as "Title2" and Tracking Number as "321234"

i2 have Carrier Title as "Title3" and Tracking Number as "654321"

PFA for more clarification:-

enter image description here

how can i achieve the same?also let me know when order status will be changed(either after creating shipment for all items or any one of the item)?

Please help me to achieve the same.

Waiting for the update!!!

2 Answers 2

use Magento\Sales\Api\OrderRepositoryInterface;
use Magento\Framework\DB\TransactionFactory;
use Magento\Sales\Model\Order\Email\Sender\ShipmentSender;
use Magento\Sales\Model\Order\ShipmentDocumentFactory;
use Magento\Sales\Api\Data\ShipmentItemCreationInterfaceFactory;
use Magento\Sales\Api\Data\ShipmentItemCreationInterface;
use Magento\Sales\Api\Data\ShipmentTrackCreationInterface;
use Magento\Sales\Api\Data\ShipmentTrackCreationInterfaceFactory;
use Magento\Framework\Registry;


public function __construct(
    \Psr\Log\LoggerInterface $logger,
    OrderRepositoryInterface $orderRepository,
    TransactionFactory $transactionFactory,
    ShipmentSender $shipmentSender,
    ShipmentDocumentFactory $shipmentDocumentFactory,
    ShipmentItemCreationInterfaceFactory $shipmentItemCreationInterfaceFactory,
    ShipmentTrackCreationInterfaceFactory $shipmentTrackCreationInterfaceFactory,
    Registry $registry
) {
    $this->logger = $logger;
    $this->orderRepository = $orderRepository;
    $this->transactionFactory = $transactionFactory;
    $this->shipmentSender = $shipmentSender;
    $this->shipmentDocumentFactory = $shipmentDocumentFactory;
    $this->shipmentItemCreationInterfaceFactory = $shipmentItemCreationInterfaceFactory;
    $this->shipmentTrackCreationInterfaceFactory = $shipmentTrackCreationInterfaceFactory;
    $this->registry = $registry;



/** @var \Magento\Sales\Model\Order $order */
$order = $this->orderRepository->get(7);
// Check if order can be shipped or has already shipped
if (! $order->canShip()) {
        "Order {$order->getIncrementId()} cannot be shipped"

    return false;

$title = $order->getShippingDescription();
$carrierCode = $order->getShippingMethod();
$trackingNumber = $order->getIncrementId();
$number = 1;
foreach ($order->getAllItems() AS $orderItem) {
    if ($this->registry->registry('current_shipment')) {
    try {
        // Check if order item has qty to ship or is virtual
        if (! $orderItem->getQtyToShip() || $orderItem->getIsVirtual()) {
        $qtyShipped = $orderItem->getQtyToShip();
        // Create shipment item with qty
        $shipmentItem = [];
        /** @var ShipmentItemCreationInterface $item */
        $item = $this->shipmentItemCreationInterfaceFactory->create();
        $shipmentItem[] = $item;

        $trackingCreation = [];
        /** @var ShipmentTrackCreationInterface $trackCreation */
        $trackCreation = $this->shipmentTrackCreationInterfaceFactory->create();
        $trackingCreation[] = $trackCreation;

        $shipment = $this->shipmentDocumentFactory->create(
        // Register shipment

        $this->registry->register('current_shipment', $shipment);
        /** @var \Magento\Framework\DB\Transaction $transaction */
        $transaction = $this->transactionFactory->create();

    } catch (\Exception $e) {

Tested for 2.3

  • thanks for the reply,i'm using for M2.2.4 and when i injected your code in controller then getting "Class INW\Shipment\Controller\Index\OrderRepositoryInterface does not exist in [INW\Shipment\Controller\Index\Index\Interceptor]" isssue. Commented May 13, 2019 at 7:48
  • Did you add first code block before class? Do you know how to use 'use' inside class?
    – Sohel Rana
    Commented May 29, 2019 at 8:41
  • I added everything you given but doesn't work...by the way, the problem is resolved thankyou so much for the help...really appreciable. Commented May 29, 2019 at 12:07
  • definitely, you made a mistake. this is working fine with m2.3, 2.2 version
    – Sohel Rana
    Commented May 29, 2019 at 12:10
  • i'm using M2.2.4,may be it's version problem.thankyou so much for your post. Commented May 29, 2019 at 12:34

On the phtml file,i added checkbox and added some hidden input type fields...then on selecting checkbox i'm passing item_id,product_id,shipment_method on those hidden fields using jQuery.

Here is the snippet for the same:-

enter image description here

Controller:- Then Via "MyControllerAction" I'm fetching those hidden fields and applied filters on existing code.

It's works for me.

Note:- Magento don't change the order status to 'complete' until all item shipped.


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.