Question

I am making a connector for Magento, where orders from Magento are pushed into our system, then get shipments created that need to be pulled back into Magento and converted to the right format. In Magento 2, this is accomplished with shipRepo->create()

I believe, but I'm struggling to find the correct Magento 1 solution. I have the order's increment ID from the original order, so I'm trying to use that. Right now here is what I'm trying:

$order = Mage::getModel('sales/order')->loadByIncrementId($orderId);
if($order->canShip()) {
        $itemQty =  $order->getItemsCollection()->count();
        $shipment = Mage::getModel('sales/service_order', $order)->prepareShipment($itemQty);
        $shipment = new Mage_Sales_Model_Order_Shipment_Api();
        $shipmentId = $shipment->create($orderId, $itemQty,null,true,false);
}

However, when I try this out, I get a data_invalid error. What am I doing wrong?

PS: I'm basing my code off of this inchoo post and this stack overflow post but I'm pretty sure it's still failing on the create method.

I'm curious why we set $shipment twice. Does that first assignment actually accomplish anything?

Was it helpful?

Solution

Ok after a lot of trial and error I think I figured it out.

First of all, I've seen this method all over the place, but it is a mess. I would like to say I managed to cleaned it up into something that is actually usable.

This line: $itemQty = $order->getItemsCollection()->count(); sets $itemQty to a number, a count, but the create() method requires an array! That was ultimately the reason I was getting a data_invalid error, and when I changed

$shipment->create($orderId, $itemQty,null,true,false);

to

$shipment->create($orderId, array(),null,true,false);

it kind of fixed things, in that I no longer got an error. But I don't want to just blindly accept all quantities on the shipment. I want to accept only what is actually on the shipment (duh) so I had to figure out the right way to do it.

First thing to do was make a $itemQtys array of the format

array(
  'order_item_id'=>$qty,
  'order_item_id'=>$qty,
  'order_item_id'=>$qty
)

Then just create the API and shipment. But their way of making the API is very... not Magento-y. So I changed it from

$shipment = new Mage_Sales_Model_Order_Shipment_Api();

to

$newShip = Mage::getModel('sales/order_shipment_api');

For me, it looked something like this:

$order = Mage::getModel('sales/order')->loadByIncrementId($orderId);
if($order->canShip()) {
    $itemQtys = array();

    //cycle through the items on the shipment and add them to the array
    //note: you must previously define $shipItems from your shipment
    foreach($shipItems as $newItem) {
        $itemQtys[$newItem->getOrderItemId()] = $newItem->getQty();
    }

    //create the shipment
    $shipApi= Mage::getModel('sales/order_shipment_api');
    $shipId = $shipApi->create($orderId, $itemQtys);

    //get the actual shipment if you want to further manipulate it
    $magShip = Mage::getModel('sales/order_shipment')->loadByIncrementId($shipId);
}

I also experimented with using prepareShipment in the form of

$magShip = Mage::getModel('sales/service_order', $order)->prepareShipment($itemQtys);

However, this did not succeed in actually creating the shipment, nor was it necessary in my solution, so I'm still not totally sure what it's supposed to be used for.

Conclusion:

From the original post, only the last two lines did anything. To create a shipment programmatically, create a $itemQtys array and then call the create function.

Source code was also useful from here.

Licensed under: CC-BY-SA with attribution
Not affiliated with magento.stackexchange
scroll top