การสร้างการจัดส่งโดยทางโปรแกรม


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

คำตอบ:


47

ฉันจะให้มันยิง ลองดูทีละอัน:

วิธีที่ 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));

นี่เป็นวิธีที่ได้รับความนิยมมากที่สุดใน Core ของ 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วัตถุซึ่งจะถูกแทนที่ด้วย insantiation 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

นี่คือแฮ็คที่ไม่ควรใช้โดยโมดูลหรือส่วนขยายใด ๆ 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;
}

ผู้แตกต่างหลักที่นี่ - หากคุณต้องการการจัดส่งไม่ต้องแฮ็กแฮ็คและมี increment_id เท่านั้น - ใช้วิธีนี้ นอกจากนี้ยังมีข้อมูลที่เป็นประโยชน์หากคุณต้องการจัดการผ่าน SOAP API

ฉันหวังว่าจะช่วย


1
คำตอบสำหรับทุกคนที่ใช้การจัดการสินค้าคงคลัง Magestore: วิธีที่ 3 ไม่เรียกใช้ตะขอของพวกเขาดังนั้นคุณจะพบว่ามีความคลาดเคลื่อนในการจัดส่งระหว่างการขนส่งหลักของวีโอไอพีและการขนส่งคลังสินค้า คำตอบที่ดีคือ OP :)
Ricky Odin Matthews

7

สิ่งสำคัญที่นี่คือวิธีการ 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)สำหรับทุกรายการสั่งซื้อที่มีสิทธิ์ด้วย อ้าววีโอไอพีนั้นขี้เกียจจริงๆคุณต้องเกลี้ยกล่อมให้ทุกคน เดียว ขั้นตอน จากนั้นคุณต้องข้ามไปอีกหลายห่วงเพื่อบันทึกการจัดส่งในฐานข้อมูล

ดังนั้นวิธีที่ 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();
    }
}

ทำไม qty_shipped ไม่ได้บรรจุในตาราง sales_flat_order_item ด้วยวิธีนี้
แอพสร้างสรรค์
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.