Secara terprogram Membuat Pengiriman

32

Saya menemukan berbagai cara untuk membuat pengiriman secara terprogram. Mereka

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

Apa perbedaan antara metode-metode ini. Di luar dari tiga metode yang merupakan metode yang tepat untuk membuat pengiriman dan menambahkan nomor pelacakan.

blakcaps
sumber
Apakah ada detail lain yang Anda butuhkan pada jawaban saya untuk menjamin penghargaan yang diterima dan hadiah? Saya terbuka untuk kritik atau klarifikasi jika Anda menginginkannya.
philwinkle

Jawaban:

47

Saya akan mencobanya. Mari kita ambil satu per satu:

Metode 1

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

$converterdi atas diambil dari kelas Mage_Sales_Model_Convert_Order, yang menggunakan penolong inti yang dipanggil copyFieldsetuntuk menyalin detail pesanan ke objek pengiriman. $ order harus bertipe array atau Varien_Object.

Metode ini sebenarnya merupakan inti dari Metode 3, seperti yang digunakan Mage::getModel('sales/convert_order')dalam panggilan konstruktornya.

Diferensiator kunci dari metode ini - dapat mengambil array atau objek $orderdan menghasilkan $shipmentobjek dasar . Ini adalah metode tingkat rendah yang digunakan secara eksklusif oleh metode yang Anda ajukan dalam Metode 2, Metode 3.

Metode 2

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

Ini sepertinya menjadi cara yang paling populer di Magento's Core menghasilkan kiriman karena digunakan di pengontrol Pengiriman dan Faktur. $orderdigunakan sebagai argumen konstruktor ke instantiation Mage_Sales_Model_Service_Order, menetapkannya sebagai properti yang dilindungi pada objek.

Anda kemudian menelepon prepareShipmentdan memberikan kuantitas. Karena metode ini menggunakan kelas konverter dari Metode 1, Anda tidak perlu menentukan detail lebih lanjut seperti item pesanan melewati detail pengiriman barang dalam prepareShipmentargumen, yang disebut di sini dengan $this->_getItemQtys. Untuk menggunakan ini pada konteks Anda sendiri, yang perlu Anda lakukan adalah meneruskan jumlah item dalam array dengan format berikut:

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

Pembeda utama dari metode ini - ia memberi Anda objek pengiriman $, tetapi dengan semua item dikonversi di dalamnya. Ini plug-and-play.

Metode 3

Saya tidak dapat menemukan bukti menggunakan metode ini di Core. Sejujurnya seperti retasan. Inilah metodenya:

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

Langkah 1 persis sama dengan Metode 2 di atas. Tidak ada perbedaan. Namun, Anda mendapatkan kembali $shipmentobjek, yang diganti dengan insantiasi langsung Mage_Sales_Model_Order_Shipment_Api. Ini tidak standar. Cara terbaik untuk mendapatkan kiriman objek Api adalah dengan menelepon Mage::getModel('sales/order_shipment_api').

Selanjutnya, ia menggunakan objek API Pengiriman baru yang ditimpa itu untuk membuat pengiriman dari $orderIdvariabel yang belum didefinisikan dalam kode Anda. Sekali lagi, ini tampak seperti solusi.

Melihat Mage_Sales_Model_Order_Shipment_Api::create(), sepertinya toko serba ada untuk menghasilkan kiriman karena detail paling dasar yang diperlukan untuk membuat kiriman hanya pesanan increment_id.

Ini adalah retasan yang tidak boleh digunakan oleh modul atau ekstensi apa pun. API ini dimaksudkan untuk dikonsumsi oleh fitur yang diekspos melalui permintaan API XML RPC / SOAP dan sengaja dibuat untuk menghilangkan beberapa permintaan API langkah.

Akhirnya Metode 3 sampai ke seluk-beluk, meskipun, dan melalui panggilan ke Mage_Sales_Model_Order, itu panggilan prepareShipment, yang merupakan abstraksi tingkat tinggi untuk Metode 2 yang akrab di atas:

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

Diferensiator utama di sini - jika Anda memerlukan kiriman, jangan pedulikan peretasan, dan hanya ada increment_id - gunakan metode ini. Juga informasi yang berguna jika Anda lebih suka menangani ini melalui API SOAP.

Saya harap itu membantu.

Philwinkle
sumber
1
Kepala bagi siapa saja yang menggunakan Manajemen Inventaris Magestore: Metode 3 tidak memicu kaitannya sehingga Anda akhirnya akan memiliki perbedaan pengiriman antara pengiriman inti Magento dan pengiriman Gudang. Juga jawaban yang bagus OP :)
Ricky Odin Matthews
7

Kuncinya di sini adalah bahwa metode 1 dan 2 tidak berfungsi ...

Saya setuju dengan @philwinkle, metode 3 adalah peretasan. Fungsi API seharusnya tidak benar-benar dipanggil dalam konteks non-API. Anda tidak pernah tahu rilis apa yang akan datang untuk memecahkan kode semacam ini.

Jadi apa yang tersisa? Nah, metode 1 dan 2 tidak rusak persis. Hanya saja mereka hanya melakukan sebagian dari pekerjaan. Seperti apa bentuknya:

Catatan: untuk singkatnya, cuplikan kode berikut akan menambahkan semua item yang memenuhi syarat ke kiriman. Jika Anda hanya ingin mengirimkan bagian dari suatu pesanan, Anda harus memodifikasi bagian tertentu dari kode - semoga saya telah memberi Anda cukup banyak untuk melanjutkan.

Metode 1

Jika Anda melihat kode di app/code/core/Mage/Sales/Model/Order/Shipment/Api.php(seperti yang digunakan dalam metode 3) Anda akan melihat bahwa selain $convertor->toShipment($order)itu juga memanggil $item = $convertor->itemToShipmentItem($orderItem), $item->setQty($qty)dan $shipment->addItem($item)untuk setiap item pesanan yang memenuhi syarat. Yap, Magento benar-benar malas, Anda harus membujuknya melalui setiap. Tunggal. Langkah. Maka Anda harus melompati beberapa simpai lagi untuk benar-benar menyimpan kiriman di basis data.

Jadi metode 1 akan terlihat seperti ini:

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

Metode 2

Pertama, Anda memiliki panggilan $this->_getItemQtys()yang tentu saja hanya akan bekerja di kelas-kelas tertentu (yang memiliki atau mewarisi fungsi _getItemQtys, natch). Jadi itu perlu diubah, dan seperti halnya metode 1, Anda juga perlu menyempurnakan prosesnya.

Melihat app/code/core/Mage/Adminhtml/controllers/Sales/Order/ShipmentController.phpitu adalah situasi yang sedikit lebih baik dengan pendekatan ini - tampaknya barang-barang dikonversi bersama dengan pengiriman itu sendiri. Tetapi Anda masih hanya mendapatkan kembali objek sementara, yang harus Anda simpan sendiri ke database, seperti:

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

Saya juga merekomendasikan untuk menambahkan sedikit pemeriksaan kesalahan di sana, misalnya untuk memastikan bahwa kiriman Anda benar-benar berisi barang apa pun sebelum Anda register().

Mana yang terbaik?

Saya akan mengatakan itu masalah pendapat. Saya belum melakukan tes benchmark, tetapi saya cukup yakin perbedaan kecepatan antara kedua metode ini dapat diabaikan. Adapun ukuran kode & keterbacaan tidak ada banyak di antara mereka.

Saya suka metode 2 karena tidak harus secara eksplisit mengkonversi semua item dalam urutan, tetapi masih mengharuskan Anda untuk melewatinya untuk mengekstraksi kuantitas. Untuk jejak kode kecil yang bagus, metode 3 akan menjadi favorit saya! Tetapi sebagai seorang insinyur perangkat lunak saya tidak bisa merekomendasikannya. Jadi saya akan pilih metode 2.

Doug McLean
sumber
1

Guys Tak satu pun dari yang di atas bekerja pada Masalah saya. Berikut ini bekerja untuk saya. Menempatkannya di sini kalau-kalau ada yang membantu Anda di luar sana.

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();
    }
}
m82amjad
sumber
Mengapa qty_shipped tidak diisi pada tabel sales_flat_order_item dengan metode ini?
Aplikasi Kreatif