Question

I have created order shipment programmatically with below code but I don't know how to select SourceCode when multiple sources available in Magento backend.

public function execute()
    {
        $orderId = $this->getRequest()->getParam('order_id');
        $order = $this->_objectManager->create('Magento\Sales\Model\Order')->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.')
            );
        }

        // 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->getExtensionAttributes()->setSourceCode('default');
            $shipment->save();

            $order = $this->_objectManager->create('Magento\Sales\Model\Order')->load($orderId);
            $order->setState('processing')
                ->setStatus('processing')
                ->save();

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

            $this->messageManager->addSuccess(__('Shipment has been created successfully.'));

            $pathParams = ['order_id' => $orderId];
            $path = 'sales/order/view';

            return $this->resultRedirectFactory->create()->setPath($path, $pathParams);
        } catch (\Exception $e) {
            throw new \Magento\Framework\Exception\LocalizedException(
                __($e->getMessage())
            );
        }
    }

Here, I have put static code to select Source Code $shipment->getExtensionAttributes()->setSourceCode('default'); and its working fine.

I want to make it dynamic as per order.

How to get source code from order?

Was it helpful?

Solution

This depends on your seller's logic for fairly simple logic where only 1 source is assigned to each website and no fallback is required

     try {
            $orderShipment->getExtensionAttributes()
                ->setSourceCode(
                    array_reduce(
                    /* @var \Magento\Inventory\Model\Source\Command\GetSourcesAssignedToStockOrderedByPriority*/
                        $this->sourceCommand->execute(
                            /* @var \Magento\InventorySales\Model\StockResolver */
                            $this->stockResolver
                                ->execute(
                                    'website',
                                    $order->getStore()
                                        ->getWebsite()
                                        ->getCode()
                                )
                                ->getStockId()
                        ),
                        function ($sourceCode, $source) {
                            return $sourceCode ?: $source->getSourceCode();
                        },
                        false
                    )
                );
        } catch (Exception $e) {
            //no source or stock assigned to website;
        }
Licensed under: CC-BY-SA with attribution
Not affiliated with magento.stackexchange
scroll top