3

I have an menu option to create multiple shipments from selected orders in an extension.

It works on some stores (tested) but the store I'm trying to get it to work on (2.3.1) uses MSI and I'm wondering if it's something to do with that?

 protected function massAction(AbstractCollection $collection)
{  

        $countShipOrder = 0;
        foreach ($collection->getItems() as $order) 
        {  
            try 
            {    
                $shipOrder = $this->_shipOrder->create();
                $ship = $shipOrder->shipOrder($order->getId());
                $countShipOrder++;                                          
            }
            catch (\Exception $e) 
            {
                $this->messageManager->addError(__('Order Shipments Already Created For : %1',$order['increment_id']));
            }               
        }

        $countNonShipOrder = $collection->count() - $countShipOrder;

        if ($countShipOrder) {

            $string = $countShipOrder.' success, '.$countNonShipOrder .' fails';
            $this->messageManager->addSuccess(__('Order shipments processed : %1.', $string));
        }

        $this->_redirect('sales/order/index');

}

class ShipOrder extends \Magento\Framework\Model\AbstractModel
{   
    protected $_scopeConfig;
    protected $_order;
    protected $_orderConverter;
    protected $eventManager;

    public function __construct(
           \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig,
           \Magento\Sales\Model\OrderFactory $order,
           \Magento\Sales\Model\Convert\OrderFactory $orderConverter,
           \Magento\Framework\Event\Manager $eventManager,
           \Magento\Framework\Model\Context $context

    ){
        $this->_scopeConfig = $scopeConfig;
        $this->_order = $order;
        $this->eventManager = $eventManager;
        $this->_orderConverter = $orderConverter;
    }

    public function shipOrder($orderId)
    {
        //load by order 
        $order = $this->_order->create()->load($orderId);

        // 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 for order increment id: %1', $order->getIncrementId())
                        );
            return false;
        }
        else {
            $shipment = $this->createShipment($order);
            return  $shipment;
        }
    }


    public function createShipment($order){

        // Initialize the order shipment object
        $convertOrder = $this->_orderConverter->create();
        $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();
            return $shipment;

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

That final try catch where it tries to save the shipment is where the error is being thrown.

The undefined variable sourceCode is coming from /vendor/magento/module-inventory-shipping/Observer/SourceDeductionProcessor.php on line 112

5
  • Have you search for sourceCode references? Aug 7, 2019 at 10:37
  • I missed the full exception, my bad, I've put in where the undefined variable sits in Magento vendor
    – Mark
    Aug 7, 2019 at 10:44
  • Well I'm afraid you going to have to put a fix of your own github.com/magento/inventory/blob/2.3-develop/app/code/Magento/… Is not done properly :/ Aug 7, 2019 at 10:55
  • this doesnt help explain to me what the problem is.
    – Mark
    Aug 7, 2019 at 13:34
  • 1
    The problem is $this->isSingleSourceMode->execute() and $shipment->getExtensionAttributes() fail the conditions therefore the $sourceCode variable is never initialise. You will need to find out why both of those fail. Use a debugger and trace it down. Aug 7, 2019 at 13:42

2 Answers 2

4

As MSI has been implemented, in your code you have to specify the source location.

Add the following line before $shipment save()

$shipment->getExtensionAttributes()->setSourceCode('default');
0
$source = '';
$product = $this->_productFactory->create()->load($productId);
$_sources = $this->getSourceItemDetailBySKU($product->getSku());
if(empty($source)) {
    if (count($_sources) > 0) {
        foreach ($_sources as $_source) {
            $dataSource = $_source->getData();
            $qty = (int)$dataSource['quantity'];
            if((int)$dataSource['quantity'] == 0){ continue ;}

            if (empty($arraySource[$dataSource['source_code']])) {
                $arraySource[$dataSource['source_code']] = 1;
            } else {
                $arraySource[$dataSource['source_code']] = (int)$arraySource[$dataSource['source_code']] + 1;
            }


            if ($arraySource[$dataSource['source_code']] == count($order->getAllItems())) {
                $source = $dataSource['source_code'];
                break;
            }
        }
    }
}

$shipment->getExtensionAttributes()->setSourceCode($source);

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.