Lập trình tạo lô hàng


32

Tôi đã tìm ra nhiều cách khác nhau để tạo ra lô hàng theo chương trình. họ đang

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

Sự khác biệt giữa các phương thức này là gì. Nhưng trong ba phương pháp là phương pháp phù hợp để tạo lô hàng và thêm số theo dõi.


Có bất kỳ chi tiết nào bạn cần về câu trả lời của tôi để đảm bảo một giải thưởng chấp nhận và tiền thưởng không? Tôi sẵn sàng chỉ trích hoặc làm rõ nếu bạn mong muốn.
philwinkle

Câu trả lời:


47

Tôi sẽ cho nó một viên đạn. Chúng ta hãy đưa họ từng cái một:

Phương pháp 1

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

$converterở trên được tải từ lớp Mage_Sales_Model_Convert_Order, trong đó sử dụng một trình trợ giúp cốt lõi được gọi copyFieldsetđể sao chép chi tiết đơn hàng vào một đối tượng giao hàng. $ order phải là kiểu mảng hoặc Varien_Object.

Phương thức này thực sự là cốt lõi của Phương thức 3, vì nó sử dụng Mage::getModel('sales/convert_order')trong lệnh gọi hàm tạo của nó.

Khác biệt chính của phương pháp này - nó có thể lấy một mảng hoặc một đối tượng $ordervà tạo ra một $shipmentđối tượng cơ bản . Đó là một phương thức cấp thấp hơn được sử dụng riêng cho các phương pháp bạn đưa ra trong Phương pháp 2, Phương pháp 3.

Phương pháp 2

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

Đây dường như là cách phổ biến nhất trong Lõi của Magento trong việc tạo ra một lô hàng vì nó được sử dụng trong cả hai bộ điều khiển Lô hàng và Hóa đơn. $orderđược sử dụng làm đối số của hàm tạo để khởi tạo Mage_Sales_Model_Service_Order, đặt nó làm thuộc tính được bảo vệ trên đối tượng.

Sau đó, bạn đang gọi prepareShipmentvà chuyển một số lượng. Vì phương thức này sử dụng lớp trình chuyển đổi từ Phương thức 1, nên bạn không cần chỉ định thêm chi tiết, chẳng hạn như các mục đơn hàng vượt qua lô hàng qty chi tiết trong prepareShipmentđối số, được gọi ở đây với $this->_getItemQtys. Để sử dụng điều này trên ngữ cảnh của riêng bạn, tất cả những gì bạn cần làm là chuyển số lượng mục trong một mảng với định dạng sau:

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

Khác biệt chính của phương pháp này - nó mang lại cho bạn một đối tượng lô hàng $, nhưng với tất cả các mục được chuyển đổi trên nó. Đó là plug-and-play.

Phương pháp 3

Tôi không thể tìm thấy bằng chứng về việc sử dụng phương pháp này trong Core. Nó trông giống như một hack, thành thật mà nói. Đây là phương pháp:

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

Bước 1 hoàn toàn giống như Phương pháp 2 ở trên. Không khác nhau. Tuy nhiên, bạn nhận lại một $shipmentđối tượng, được thay thế bằng cách đặt trực tiếp vào Mage_Sales_Model_Order_Shipment_Api. Đây là không chuẩn. Cách thực hành tốt nhất để nhận một đối tượng Api giao hàng sẽ là gọi Mage::getModel('sales/order_shipment_api').

Tiếp theo, nó sử dụng đối tượng API Lô hàng mới được ghi đè để tạo một lô hàng từ một $orderIdbiến chưa được xác định trong mã của bạn. Một lần nữa, điều này có vẻ như một cách giải quyết.

Nhìn vào Mage_Sales_Model_Order_Shipment_Api::create(), có vẻ như một cửa hàng duy nhất để tạo ra một lô hàng vì các chi tiết cơ bản nhất cần thiết để tạo ra lô hàng chỉ là một đơn đặt hàng increment_id.

Đây là một hack không nên được sử dụng bởi bất kỳ mô-đun hoặc phần mở rộng. API này có nghĩa là được sử dụng bởi các tính năng được hiển thị thông qua các yêu cầu API RPC / SOAP của XML và là cơ bản cố ý để loại bỏ các yêu cầu API nhiều bước.

Cuối cùng, Phương thức 3 nhận được nitty-gritty, và thông qua một cuộc gọi đến Mage_Sales_Model_Order, nó gọi prepareShipment, đó là một sự trừu tượng hóa bậc cao hơn cho Phương thức 2 quen thuộc ở trên:

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

Khác biệt chính ở đây - nếu bạn cần một lô hàng, đừng bận tâm đến việc hack và chỉ có gia tăng_id - hãy sử dụng phương pháp này. Ngoài ra thông tin hữu ích nếu bạn muốn xử lý việc này thông qua API SOAP.

Tôi hy vọng điều đó sẽ giúp.


1
Bất cứ ai sử dụng Magestore Inventory Management: Phương thức 3 không kích hoạt móc của họ, vì vậy cuối cùng bạn sẽ có sự khác biệt về lô hàng giữa các lô hàng cốt lõi của Magento và các lô hàng Kho. Cũng có câu trả lời tốt OP :)
Ricky Odin Matthews

7

Điều quan trọng ở đây là phương pháp 1 và 2 không hoạt động ...

Tôi đồng ý với @philwinkle, phương thức 3 là hacky. Các hàm API không thực sự được gọi trong ngữ cảnh không phải API. Bạn không bao giờ biết những gì phát hành trong tương lai có thể mang lại để phá vỡ loại mã này.

Vì vậy, những gì mà để lại? Chà, phương pháp 1 và 2 không bị hỏng chính xác. Chỉ là họ chỉ làm một phần của công việc. Đây là những gì họ nên trông giống như:

Lưu ý: để đơn giản, các đoạn mã sau sẽ thêm tất cả các mặt hàng đủ điều kiện vào lô hàng. Nếu bạn chỉ muốn gửi một phần của đơn đặt hàng, bạn sẽ phải sửa đổi một số phần nhất định của mã - tuy nhiên, hy vọng tôi đã cung cấp cho bạn đủ để tiếp tục.

Phương pháp 1

Nếu bạn nhìn vào các mã trong app/code/core/Mage/Sales/Model/Order/Shipment/Api.php(như được sử dụng trong phương pháp 3) bạn sẽ thấy rằng ngoài việc $convertor->toShipment($order)nó cũng kêu gọi $item = $convertor->itemToShipmentItem($orderItem), $item->setQty($qty)$shipment->addItem($item)cho tất cả các mục để đủ điều kiện. Đúng, Magento thực sự là lười biếng, bạn phải dỗ nó qua mọi. Độc thân. Bậc thang. Sau đó, bạn phải nhảy qua một vài vòng nữa để thực sự lưu lô hàng trong cơ sở dữ liệu.

Vì vậy, phương pháp 1 sẽ giống như thế này:

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

Phương pháp 2

Trước hết, bạn có một lệnh gọi $this->_getItemQtys()tất nhiên sẽ chỉ hoạt động trong một số lớp nhất định (những lớp có hoặc kế thừa hàm _getItemQtys, natch). Vì vậy, điều đó cần phải thay đổi, và như với phương pháp 1, bạn cũng cần đưa ra quy trình.

Nhìn vào app/code/core/Mage/Adminhtml/controllers/Sales/Order/ShipmentController.phpđó là một tình huống tốt hơn một chút với cách tiếp cận này - có vẻ như các mặt hàng được chuyển đổi cùng với chính lô hàng. Nhưng bạn vẫn chỉ cần lấy lại một đối tượng thoáng qua, rằng bạn phải tự lưu vào cơ sở dữ liệu, như vậy:

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

Tôi cũng khuyên bạn nên thêm một chút kiểm tra lỗi trong đó, ví dụ để đảm bảo lô hàng của bạn thực sự có chứa bất kỳ mặt hàng nào trước bạn register().

Tốt nhất?

Tôi muốn nói đó là vấn đề quan điểm. Tôi chưa thực hiện bất kỳ bài kiểm tra điểm chuẩn nào nhưng tôi khá tự tin rằng sự khác biệt về tốc độ giữa hai phương pháp sẽ không đáng kể. Đối với kích thước mã và khả năng đọc không có nhiều giữa chúng.

Tôi thích phương pháp 2 vì không phải chuyển đổi rõ ràng tất cả các mục theo thứ tự, nhưng nó vẫn yêu cầu bạn phải thực hiện chúng để trích xuất số lượng. Đối với một dấu chân mã nhỏ đẹp, phương pháp 3 sẽ là yêu thích của tôi! Nhưng là một kỹ sư phần mềm, tôi không thể khuyên bạn nên nó. Vì vậy, tôi sẽ đầy đặn cho phương pháp 2.


1

Không có ai ở trên làm việc về vấn đề của tôi. Sau đây làm việc cho tôi. Đặt nó xuống đây trong trường hợp nó giúp bất kỳ bạn ngoài đó.

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();
    }
}

Tại sao qty_shipped không được điền trên bảng sales_flat_order_item với phương thức này?
Ứng dụng sáng tạo
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.