以编程方式创建发货


32

我遇到了多种以编程方式创建货运的方式。他们是

     //Type 1
     $converter=Mage::getModel('sales/convert_order');
     $shipment=$converter->toShipment($order);
     // snip

     //Type 2
     $shipment = Mage::getModel('sales/service_order', $order)
                                ->prepareShipment($this->_getItemQtys($order));
     // snip

     //Type 3
     $shipment = Mage::getModel('sales/service_order', $order)->prepareShipment($itemQty);
     $shipment = new Mage_Sales_Model_Order_Shipment_Api();
     $shipmentId = $shipment->create($orderId);
     // snip

这三种方法之间有什么区别。在这三种方法中,这是创建货件和添加跟踪号的正确方法。


您是否需要更多详细信息才能获得接受和赏金的奖励?如果您愿意,我可以公开批评或澄清。
philwinkle

Answers:


47

我会试一试。让我们一次带他们一个:

方法1

$converter=Mage::getModel('sales/convert_order');
$shipment=$converter->toShipment($order);

$converter上面的代码是从类加载的,该类Mage_Sales_Model_Convert_Order使用一个称为的核心帮助copyFieldset程序将订单详细信息复制到装运对象中。$ order必须是array或类型Varien_Object

此方法实际上是方法3的核心,因为它Mage::getModel('sales/convert_order')在其构造函数调用中使用。

此方法的主要区别 -可以采用数组或对象$order并生成基本$shipment对象。它是您在方法2,方法3中提出的方法专用的低级方法。

方法2

 $shipment = Mage::getModel('sales/service_order', $order)
                            ->prepareShipment($this->_getItemQtys($order));

这似乎是Magento的Core中最常用的生成货件的方式,因为它同时用于Shipment和Invoice控制器中。$order用作实例化的构造函数参数,并将其Mage_Sales_Model_Service_Order设置为对象的受保护属性。

然后prepareShipment,您要调用并传递数量。由于此方法使用方法1中的转换器类,因此您无需prepareShipment参数中指定更多详细信息,例如定单项传递物料装运数量详细信息,此处用调用$this->_getItemQtys。要在您自己的上下文中使用此功能,您需要做的就是以下列格式在数组中传递项目数量:

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

此方法的主要区别 -它给您$ shipment对象,但是所有项目都已转换。即插即用。

方法3

我找不到在Core中使用此方法的证据。老实说,这看起来像是骇客。方法如下:

$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);

步骤1与上面的方法2完全相同。没有不同。但是,您将获得一个$shipment对象,该对象将由的直接实例替换Mage_Sales_Model_Order_Shipment_Api。这是非标准的。获取货运Api对象的最佳实践方法是致电Mage::getModel('sales/order_shipment_api')

接下来,它使用该覆盖的新的Shipment API对象根据$orderId代码中未定义的变量创建货运。同样,这似乎是一种解决方法。

看起来Mage_Sales_Model_Order_Shipment_Api::create(),这就像生成货物的一站式服务,因为创建货物所需的最基本的细节只是订单increment_id

这是任何模块或扩展都不应该使用的hack。该API旨在通过XML RPC / SOAP API请求公开的功能使用,并且故意消除多步API请求。

最终,方法3进入实质,并通过调用Mage_Sales_Model_Order调用prepareShipment,这是上面熟悉的方法2的更高阶抽象:

public function prepareShipment($qtys = array())
{
    $shipment = Mage::getModel('sales/service_order', $this)->prepareShipment($qtys);
    return $shipment;
}

此处的主要区别 -如果您需要装运,请不要介意骇客,并且只有一个cremental_id-请使用此方法。如果您更愿意通过SOAP API处理此信息,则也很有用。

希望对您有所帮助。


1
使用Magestore库存管理的任何人都要注意:方法3不会触发钩子,因此您最终会在Magento核心货件和仓库货件之间出现货件差异。OP的回答也不错:)
Ricky Odin Matthews

7

这里的关键是方法1和2不起作用...

我同意@philwinkle,但是方法3 hacky。实际上,不应在非API上下文中调用API函数。您永远不会知道将来的发行版可能带来什么来破坏这种代码。

那还剩下什么呢?好吧,方法1和2并没有完全被破坏。只是他们只做一部分工作。它们的外观如下:

注意:为简便起见,以下代码段会将所有符合条件的商品添加到货件中。如果您只想发送订单的一部分,则必须修改代码的某些部分-希望我已经给您足够的东西继续。

方法1

如果您查看中的代码app/code/core/Mage/Sales/Model/Order/Shipment/Api.php(方法3中使用的代码),您会发现该代码除了$convertor->toShipment($order)还调用$item = $convertor->itemToShipmentItem($orderItem)$item->setQty($qty)而且还$shipment->addItem($item)针对每个合格的订单商品。是的,Magento真的是那么懒,你必须哄它。单。步。然后,您必须跳过另外几个步骤,才能将货件实际保存到数据库中。

因此方法1应该看起来像这样:

$convertor = Mage::getModel('sales/convert_order');
$shipment = $convertor->toShipment($order);
foreach ($order->getAllItems() as $orderItem) {
    if ($orderItem->getQtyToShip() && !$orderItem->getIsVirtual()) {
        $item = $convertor->itemToShipmentItem($orderItem);
        $item->setQty($orderItem->getQtyToShip());
        $shipment->addItem($item);
    }
}
$shipment->register();
$order->setIsInProcess(true);
Mage::getModel('core/resource_transaction')
         ->addObject($shipment)
         ->addObject($order))
         ->save();

方法2

首先,您将有一个调用,$this->_getItemQtys()该调用当然仅适用于某些类(具有或继承_getItemQtys函数的类,即natch)。因此需要进行更改,并且与方法1一样,您还需要充实该过程。

展望app/code/core/Mage/Adminhtml/controllers/Sales/Order/ShipmentController.php它的这种方法稍微好一点的情况-似乎物品与货物本身一起转换。但是您仍然只需要取回一个临时对象,您必须自己将其保存到数据库,如下所示:

$itemQtys = array();
foreach ($order->getAllItems() as $orderItem) {
    if ($orderItem->getQtyToShip() && !$orderItem->getIsVirtual()) {
        $itemQtys[$orderItem->getId()] = $orderItem->getQtyToShip();
    }
}
$shipment = Mage::getModel('sales/service_order', $order)->prepareShipment($itemQtys);
$shipment->register();
$order->setIsInProcess(true);
Mage::getModel('core/resource_transaction')
         ->addObject($shipment)
         ->addObject($order)
         ->save();

我还建议在其中添加一些错误检查,例如,确保您的货件实际上包含任何物品register()

哪个最好?

我会说这是见仁见智。我没有进行任何基准测试,但是我非常有信心这两种方法之间的速度差异可以忽略不计。至于代码大小和可读性,它们之间没有太多关系。

我喜欢方法2,因为它不必显式转换订单中的所有项目,但是它仍然需要您仔细检查它们以提取数量。对于较小的代码占用量,我最喜欢方法3!但是作为软件工程师,我不推荐这样做。因此,我将介绍方法2。


1

伙计们以上都不是我的问题。以下对我有用。把它放在这里以防万一。

public function _createShipment($orderIncrementId = '100310634'){
    // Load Product ..
    $order = Mage::getModel('sales/order')->loadByIncrementId($orderIncrementId);

    // Create Qty array
    $shipmentItems = array();
    foreach ($order->getAllItems() as $item) {
        $shipmentItems [$item->getId()] = $item->getQtyToShip();
    }

    // Prepear shipment and save ....
    if ($order->getId() && !empty($shipmentItems) && $order->canShip()) {
        $shipment = Mage::getModel('sales/service_order', $order)->prepareShipment($shipmentItems);
        $shipment->save();
    }
}

为什么没有使用此方法在sales_flat_order_item表上填充qty_shipped?
Creative Apps
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.