4

In Magento 2 how can I programmatically ship a order? I am currently developing a custom XML order import, which sends requests to a SOAP back office service. This service replies with the order entity_id and order. status.

In the mean while I am loading the order by entity_idvia the \Magento\Sales\Api\OrderRepositoryInterface class. I haven't been able to find any method that ships the order.

  • This is for Magento 1 amitbera.com/… But it will help you to get Idea & u can convert code in Magento 2 – Ankit Shah Sep 8 '16 at 2:56
10

This is how i managed to create shipment. Hope this will help:

protected $container;

protected $orderInterface;

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

/**
 * @var \Magento\Sales\Api\Data\ShipmentCommentCreationInterface
 */
protected $commentInterface;

/**
 * @var \Magento\Sales\Model\ShipOrder
 */
protected $shipOrderService;

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


/**
 * ShipmentManager constructor.
 */
public function __construct()
{
    //this is instance of my custom class to get instance object manager.
    $this->container = Container::getInstance();


    //order interface
    $this->orderInterface = $this->container->get(
        \Magento\Sales\Api\Data\OrderInterface::class
    );

    //instance of tracking factory to add tracking number in shipment
    $this->trackingFactory = $this->container->get(
        \Magento\Sales\Model\Order\Shipment\TrackFactory::class
    );

    //Comment interface to add comment on the shipment.
    $this->commentInterface = $this->container->get(
        \Magento\Sales\Api\Data\ShipmentCommentCreationInterface::class
    );

    //Shipment order service to create shipment
    $this->shipOrderService = $this->container->get(
        \Magento\Sales\Model\ShipOrder::class
    );

    //Order converter to create shipment items
    $this->orderConverter = $this->container->get(
        \Magento\Sales\Model\Convert\Order::class);
}

/**
 * Prepares tracking data form tracking number.
 *
 * @param $trackingNumber
 *
 * @return \Magento\Sales\Model\Order\Shipment\Track
 */
protected function setTrackingData($trackingNumber)
{
    $track = $this->trackingFactory->create();
    $track->setTrackNumber($trackingNumber);
    //Carrier code can not be null/empty. Default carrier code is used
    $track->setCarrierCode('custom');//Put your carrier code here
    $track->setTitle('');//add your title here
    $trackInfo[] = $track;

    return $trackInfo;
}

/**
 * @param string $comment
 *
 * @return \Magento\Sales\Api\Data\ShipmentCommentCreationInterface
 */
protected function setShipmentComment($comment)
{
    //comment can not be empty
    $comment = !empty($comment) ? $comment : 'Not Available';

    return $this->commentInterface->setComment($comment);
}

/**
 * {@inheritdoc}
 */
public function createShipment($orderIncrementId, array $items, $comment = null, $notify = false,
    $includeComment = false, $trackingNumber = '')
{
    $order = $this->orderInterface->loadOrderByIncrementId($orderIncrementId);

    if ($order->canShip()) {
        try {
            $orderId = $order->getId();
            $tracks = $this->setTrackingData($trackingNumber);
            $comment = $this->setShipmentComment($comment);
            $shippedItems = $this->createShipmentItems($items, $order);

            //creates shipment 
            $shipmentId = $this->shipOrderService->execute($orderId,
                $shippedItems,
                $notify,
                $includeComment,
                $comment,
                $tracks);
        } catch (\Exception $e) {
            echo $e->getMessage();
        }

        return $shipmentId;
    }

    return null;
}

/**
 * Create shipment items required to create shipment.
 *
 * @param array                      $items
 * @param \Magento\Sales\Model\Order $order
 *
 * @return array
 */
protected function createShipmentItems(array $items, $order)
{
    $shipmentItem = [];
    foreach ($order->getAllItems() as $orderItem) {
        if (array_key_exists($orderItem->getId(), $items)) {
            $shipmentItem[] = $this->orderConverter
                ->itemToShipmentItem($orderItem)
                ->setQty($items[$orderItem->getId()]);
        }
    }

    return $shipmentItem;
}
  • 1
    After trying multiple other answers to this question, not just here but other stackexchange questions, yours is the only one that worked. I only had to change one thing, loadOrderByIncrementId is now loadByIncrementId. loadOrderByIncrementId doesn't exist anymore. – user44406 Mar 24 '18 at 10:41
  • 1
    Than you @Wolfe . Sorry the method loadOrderByIncrementId was something i created in my custom order interface class and forgot to change it while i was posted the answer. Anyways good to know my answer helped you – Sarjan Gautam May 4 '18 at 0:53
  • 1
    Check \Magento\Sales\Api\ShipOrderInterface, it is a much simpler way – Phoenix128_RiccardoT Jul 30 '18 at 9:48
  • @SarjanGautam where should i put this code, and how to execute it? – Kris Wen Apr 9 '19 at 18:06
  • @KrisWen, in my case i have used this script in integration code to receive order shipment info (tracjking number, items, qty) from external system and create shipment in magento. You might need to create your module or class similar to above one (exact same code might not work in your case). Please note that my class above is to give idea how shipment can be created and what services can be used.Implementation to match your requirement could be different. – Sarjan Gautam Apr 23 '19 at 23:25
5

You can practice more with this until you'll find exactly what you are searching for.

$objectManager = \Magento\Framework\App\ObjectManager::getInstance();
$_order = $objectManager->create('\Magento\Sales\Model\Order');
$order = $_order->load(1);
if (!$order->canShip()) {
    throw new \Magento\Framework\Exception\LocalizedException(
        __('You can\'t create an shipment.')
    );
}

$packageParams = array();
$packageParams['width'] = 100;
$packageParams['length'] = 100;
$packageParams['height'] = 100;
$packageParams['weight'] = 1;

$convertOrder = $objectManager->create('\Magento\Sales\Model\Convert\Order');
$shipment = $convertOrder->toShipment($order);

$package = array();

$packaging = array(
    'items' => array()
);

$subtotal = 0;
foreach ($order->getAllItems() AS $orderItem) {
    if (! $orderItem->getQtyToShip() || $orderItem->getIsVirtual()) {
        continue;
    }
    $qtyShipped = $orderItem->getQtyToShip();
    $shipmentItem = $convertOrder->itemToShipmentItem($orderItem)->setQty($qtyShipped);
    $packaging['items'][$shipmentItem->getOrderItemId()] = array(
        'qty' => $shipmentItem->getQty(),
        'custom_value' => $shipmentItem->getPrice(),
        'price' => $shipmentItem->getPrice(),
        'name' => $shipmentItem->getName(),
        'weight' => $shipmentItem->getWeight(),
        'product_id' => $shipmentItem->getProductId(),
        'order_item_id' => $shipmentItem->getOrderItemId()
    );
    $subtotal += $shipmentItem->getRowTotal();
    $shipment->addItem($shipmentItem);
}

if(empty($packaging['items']))
{   
    throw new \Magento\Framework\Exception\LocalizedException(__('No items to ship'));
}

$packaging['params'] = array(
            'container' => '',
            'weight' => $packageParams['weight'],
            'custom_value' => $subtotal,
            'length' => $packageParams['length'],
            'width' => $packageParams['width'],
            'height' => $packageParams['height'],
            'weight_units' => 'KILOGRAM',
            'dimension_units' => 'CENTIMETER',
            'content_type' => '',
            'content_type_other' => ''
);
$package[] = $packaging;

$shipment->setPackages($package);
$shipment->register();
$shipment->getOrder()->setIsInProcess(true);
try {
    $shipment->save();
    $shipment->getOrder()->save();
    $notify = $objectManager->create('Magento\Shipping\Model\ShipmentNotifier');
    $notify->notify($shipment);
    $shipment->save();
} catch (\Exception $e) {
    throw new \Magento\Framework\Exception\LocalizedException(
        __($e->getMessage())
    );
}
  • can you tell me please how i set the height width and length and weight lke $skuArray[] = array("sku"=>$item['sku'] this ? – Rahul Katoch Mar 3 '17 at 13:53
  • @catalin lonita this answer is helpful for me. can u please help me how to set custom filed value in shipment items table. same as qty – kim na na Mar 16 '19 at 13:03
2

To Create partial or complete Shipment with updating shipping qty follow below code

<?php

protected function _prepareShipment($order,$items)
    {
        $shipmentFactory = $objectManager->create('\Magento\Sales\Model\Convert\Order');
        $shipment = $shipmentFactory->create($order,$items);

        if (!$shipment->getTotalQty()) {
            return false;
        }

        return $shipment->register();
    }

    $items = [];
    $objectManager = \Magento\Framework\App\ObjectManager::getInstance();
    $_order = $objectManager->create('\Magento\Sales\Model\Order');
    $order = $_order->load(1);

    foreach ($order->getAllItems() AS $orderItem) {
        if (! $orderItem->getQtyToShip() || $orderItem->getIsVirtual()) {
            continue;
        }
        $qtyShipped = $orderItem->getQtyToShip();
        $items[$orderItem->getId()] = $qtyShipped;
    }

    if($shipment = $this->_prepareShipment($this->_order,$items)) {

        $track = $objectManager->create('\Magento\Sales\Model\Order\Shipment\TrackFactory')->create();
        $track->setNumber('1111111111');
        $track->setCarrierCode('custom');
        $track->setTitle('Shipment Tracking Number');
        $track->setDescription("Description"));
        $track->setUrl($tracking['url']);
        $shipment->addTrack($track);

    }else{
        echo 'Already Processed';
    }

?>
  • Tracking url not working after generate the shipment with all tracking information. please advice – Purushotam Sharma Feb 7 '18 at 5:38

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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