我遇到了不同的方式来编程创建货物。他们是

     //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

这些方法之间有什么区别。三种方法的out是创建货物和添加跟踪数字的正确方法。

有帮助吗?

解决方案

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

方法1

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

$converter 以上是从班级加载的 Mage_Sales_Model_Convert_Order, ,使用核心助手称为 copyFieldset 将订单详细信息复制到装运对象中。 $订单必须是类型数组或 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生成货物的核心中最受欢迎的方式,因为它在发货和发票控制器中都使用。 $order 用作实例化的构造函数论点 Mage_Sales_Model_Service_Order, ,将其设置为对象上的受保护属性。

然后您打电话 prepareShipment 并通过数量。由于此方法使用方法1的转换器类,您 不需要指定更多详细信息,例如订单项目 通过物品发货的数量详细信息 prepareShipment 参数,在这里称为 $this->_getItemQtys. 。要在您自己的上下文中使用它,您需要做的就是以以下格式传递数组中的项目数量:

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

钥匙区分 在此方法中 - 它使您可以回到$运输对象,但是所有项目都会转换为其中。它是插件。

方法3

我找不到在核心中使用此方法的证据。老实说,它看起来像是一个黑客。这是方法:

$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').

接下来,它使用覆盖的新装运API对象来创建一个从 $orderId 在您的代码中尚未定义的变量。同样,这似乎是解决方法。

看着 Mage_Sales_Model_Order_Shipment_Api::create(), ,似乎是一站式发货的一站式服务 increment_id.

这是任何模块或扩展名不应使用的黑客。该API的目的是通过XML RPC / SOAP API请求暴露的功能消耗,并且有意基本消除了多个步骤API请求。

最终,方法3到达nitty-gritty,并通过呼叫mage_sales_model_order来调用 prepareShipment, ,这是上述熟悉方法2的高阶抽象:

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

关键区别在这里 - 如果您需要发货,请不要介意hacks,只有一个rezement_id-使用此方法。如果您希望通过SOAP API处理此操作,也有用的信息。

我希望这会有所帮助。

其他提示

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

我同意@philwinkle,方法3是骇人听闻的。在非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() 它。

哪个最好?

我会说这是一个意见问题。我没有进行任何基准测试,但是我非常有信心两种方法之间的速度差异可以忽略不计。至于代码尺寸和可读性,它们之间没有太多。

我确实喜欢Method 2,因为不必明确转换订单中的所有项目,但它仍然需要您通过它们来提取数量。对于不错的小型代码足迹,方法3将是我的最爱!但是作为软件工程师,我不建议这样做。因此,我将大吃一惊。

伙计们以上都没有在我的问题上奏效。以下对我有用。将其放在这里,以防万一它可以帮助你们中的任何人。

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();
    }
}
许可以下: CC-BY-SA归因
scroll top