0

I am getting error on creating an shipment

TypeError: Argument 2 passed to 
Magento\Sales\Model\Order\Validation\ShipOrder::Magento\Sales\Model\Order\Validation\ 
{closure}() must be an instance of Magento\Sales\Api\Data\ShipmentItemCreationInterface, 
instance of Magento\Sales\Model\Order\Shipment\Item given in /vendor/magento/module- 
sales/Model/Order/Validation/ShipOrder.php:127

Here is how I am creating the shipment

    <?php

namespace Navien\Custom\Model;

class ShipmentManager 
{
    protected $_objectManager;

    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->_objectManager = \Magento\Framework\App\ObjectManager::getInstance();


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

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

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

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

        //Order converter to create shipment items
        $this->orderConverter = $this->_objectManager->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($shippingPartner, $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($shippingPartner); //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($orderId, array $items, $shippingPartner = "", $trackingNumber = '', $comment = null, $notify = false,  $includeComment = false )
    {
        $order = $this->orderInterface->load($orderId);
        // $order = $this->orderInterface->loadByIncrementId('000000050');


        if ($order->canShip()) {
            try {
                $orderId      = $order->getId();
                $tracks       = $this->setTrackingData($shippingPartner, $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 false;
            }

            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;
    }
}

Some users reported that the class was working on Magento 2.3 but not working on Magento 2.4 . I am using Magento 2.4.2. Can someone help me to find the fix.

1 Answer 1

0

You can Create Shipment for any order Like this

// Load the order increment ID
$order = $this->_objectManager->create('Magento\Sales\Model\Order')->loadByIncrementID($incrementid);

// OR
$order = $this->_objectManager->create('Magento\Sales\Model\Order')
    ->loadByAttribute('increment_id', '000000001');


//load by order 
$order = $this->_objectManager->create('Magento\Sales\Model\Order')
    ->load('1');

// Check if order can be shipped or has already shipped
if (! $order->canShip()) {
    throw new \Magento\Framework\Exception\LocalizedException(
                    __('You can\'t create an shipment.')
                );
}

// Initialize the order shipment object
$convertOrder = $this->_objectManager->create('Magento\Sales\Model\Convert\Order');
$shipment = $convertOrder->toShipment($order);

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

    $qtyShipped = $orderItem->getQtyToShip();

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

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

// Register shipment
$shipment->register();

$shipment->getOrder()->setIsInProcess(true);

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

    // Send email
    $this->_objectManager->create('Magento\Shipping\Model\ShipmentNotifier')
        ->notify($shipment);

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

Above I am looping through all the Order Items, you can check the skus which you want to ship with the help of condition so that partial shipment case can be managed.

Your Answer

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

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