Programlı Gönderiler Yaratma


32

Programlı olarak sevkiyat oluşturmanın farklı yollarını gördüm. Onlar

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

Bu yöntemler arasındaki fark nedir? Gönderiler oluşturmak ve takip numaraları eklemek için uygun yöntem olan üç yöntemin dışında.


Kabul ve ödül ödülünü almak için cevabımda ihtiyacın olan herhangi bir detay var mı? Arzu ederseniz eleştiriye veya açıklığa açığım.
Philwinkle

Yanıtlar:


47

Bir şans vereceğim. Onları birer birer alalım:

Yöntem 1

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

$converterYukarıdaki, sipariş ayrıntılarını bir gönderi nesnesine kopyalamak için Mage_Sales_Model_Convert_Orderçağrılan bir çekirdek yardımcı kullanan sınıftan yüklenir copyFieldset. $ order, array türünde olmalı Varien_Object.

Bu yöntem aslında Mage::getModel('sales/convert_order'), Yapıcı çağrısında kullandığı gibi, Yöntem 3'ün merkezindedir .

Bu yöntemin temel ayırıcısı - bir diziyi veya nesneyi $orderalıp temel bir nesne üretebilir $shipment. Yalnızca Yöntem 2, Yöntem 3'te ortaya konan yöntemlerin kullandığı düşük seviye bir yöntemdir.

Yöntem 2

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

Bu, hem Gönderi hem de Fatura denetleyicilerinde kullanıldığı gibi, Magento Çekirdeğinde bir sevkıyat üretmenin en popüler yoludur. nesnenin korumalı bir özellik olarak ayarlanması $order, örneğinin başlatılması için yapıcı argüman olarak kullanılır Mage_Sales_Model_Service_Order.

Daha sonra arayacak prepareShipmentve bir miktar geçiyorsun. Bu yöntem, Yöntem 1'deki dönüştürücü sınıfını kullandığından, burada adlandırılan argümandaki sipariş öğelerinin gönderi adetlerini iletme gibi daha fazla ayrıntı belirtmeniz gerekmez . Bunu kendi bağlamınızda kullanmak için tek yapmanız gereken, bir dizideki öğelerin miktarını aşağıdaki biçimde aktarmaktır:prepareShipment$this->_getItemQtys

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

Bu yöntemin temel ayırıcısı - size bir $ gönderi nesnesini geri verir, ancak üzerinde tüm öğeler bulunur. Tak ve çalıştır.

Yöntem 3

Çekirdekte bu yöntemi kullandığına dair kanıt bulamadım. Dürüst olmak gerekirse, bir kesmek gibi görünüyor. İşte yöntem:

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

Adım 1, yukarıdaki Yöntem 2 ile tamamen aynıdır. Fark yok. Bununla birlikte, $shipmentdoğrudan bir insantiasyonu ile değiştirilen bir nesneyi geri alırsınız.Mage_Sales_Model_Order_Shipment_Api . Bu standart değil. Bir Api nesnesini sevkiyatı almanın en iyi yolu aramaktır Mage::getModel('sales/order_shipment_api').

Sonra, bir gönderi oluşturmak için bu üzerine yazılmış, yeni Gönderi API'si nesnesini kullanır. $orderId sonra, kodunuzda tanımlanmayan değişkenden . Yine, bu bir geçici çözüm gibi görünüyor.

Baktığımızda, Mage_Sales_Model_Order_Shipment_Api::create()bir gönderi oluşturmak için tek adresli bir mağaza gibi gözüküyor, çünkü gönderiyi oluşturmak için gereken en temel ayrıntılar yalnızca bir siparişdirincrement_id .

Bu, herhangi bir modül veya eklenti tarafından kullanılmaması gereken bir kesmek. Bu API, XML RPC / SOAP API istekleri tarafından sunulan özellikler tarafından tüketilmek içindir ve birden fazla adımlı API isteğini ortadan kaldırmak için kasıtlı olarak temeldir.

Sonunda Metod 3, nitty kumuna rağmen, ve Mage_Sales_Model_Order'e yapılan bir çağrı yoluyla, prepareShipmentyukarıdaki tanıdık Metod 2 için daha yüksek dereceli bir soyutlama olarak adlandırılır:

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

Buradaki anahtar farkatör - bir gönderime ihtiyacınız varsa, bilgisayar korsanlarına aldırış etmeyin ve yalnızca bir increment_id değerine sahipseniz - bu yöntemi kullanın. Ayrıca, bunu SOAP API üzerinden yapmayı tercih ederseniz faydalı bilgiler.

Umarım bu yardımcı olur.


1
Magestore Envanter Yönetimi'ni kullanan herkes için kafa yormak: Yöntem 3, kancalarını tetiklemez, bu nedenle Magento'nun ana gönderileri ile Depo gönderileri arasında gönderi tutarsızlıkları yaşarsınız. Ayrıca iyi cevap OP :)
Ricky Odin Matthews

7

Buradaki en önemli şey, yöntem 1 ve 2'nin işe yaramamasıdır ...

@ Phililinkle ile aynı fikirdeyim, yöntem 3 hacky. API işlevleri gerçekten API dışı bir bağlamda çağrılmamalıdır. Gelecekteki sürümlerin bu tür bir kodu kırmak için ne getireceğini asla bilemezsiniz.

Peki bu ne ayrılıyor? Peki, yöntem 1 ve 2 tam olarak bozulmamış. Sadece işin bir kısmını yapıyorlar. İşte nasıl görünmeleri gerektiği:

Not: kısalık için, aşağıdaki kod parçacıkları tüm uygun öğeleri gönderiye ekleyecektir. Eğer sadece bir siparişin bir kısmını göndermek istiyorsanız, kodun bazı kısımlarını değiştirmeniz gerekecektir - umarım yine de devam edecek kadar verdim.

Yöntem 1

İçinde koduna baktığımızda app/code/core/Mage/Sales/Model/Order/Shipment/Api.php(yönteminde 3'de kullanılan gibi) ek olarak göreceksiniz $convertor->toShipment($order)o da çağırır $item = $convertor->itemToShipmentItem($orderItem), $item->setQty($qty)ve $shipment->addItem($item)her uygun düzen öğesi için. Evet, Magento gerçekten tembel, herşeyi karıştırmak zorundasın. Tek. Adım. O zaman gönderiyi veri tabanına kaydetmek için birkaç çember üzerinden atlamanız gerekiyor.

Yani yöntem 1 şöyle görünmeli:

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

Yöntem 2

Öncelikle, aramanız var. $this->_getItemQtys() , elbette yalnızca belirli sınıflarda çalışacak bir aramanız var (_getItemQtys işlevine sahip olan veya kalıtsal olan). Bu yüzden değişmesi gerekiyor ve yöntem 1'de olduğu gibi, işlemi de bitirmeniz gerekiyor.

Baktığında app/code/core/Mage/Adminhtml/controllers/Sales/Order/ShipmentController.phpbunun bu yaklaşımla biraz daha iyi bir durum - ürün sevkiyat kendisi ile birlikte dönüştürülür görünüyor. Ancak yine de geçici bir nesneyi geri alıyorsunuz, veritabanına kendiniz kaydetmeniz gerekiyor, şöyle:

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

Ayrıca, içeriye küçük bir hata kontrolü eklemenizi tavsiye ederim, örneğin gönderinizin aslında sizden önce herhangi bir öğe içerdiğinden emin olmak için register().

Hangisi en iyi?

Bunun bir fikir meselesi olduğunu söyleyebilirim. Herhangi bir kıyaslama testi yapmadım, ancak iki yöntem arasındaki hız farkının önemsiz olacağına eminim. Kod büyüklüğü ve okunabilirlik konusunda ise aralarında fazla bir şey yok.

Açıkça sırayla tüm öğeleri sırayla dönüştürmek zorunda olmadığım için yöntem 2'yi sevdim, ancak yine de miktarları çıkarmak için onlardan geçmenizi gerektiriyor. Güzel bir küçük kod ayak izi için, yöntem 3 benim favorim olur! Ancak bir yazılım mühendisi olarak bunu öneremem. Bu yüzden yöntem 2 için tombul olacağım.


1

Çocuklar Yukarıdakilerin hiçbiri Sorunum üzerinde çalışmadı. Aşağıdaki benim için çalıştı. Herhangi birinize yardım etmesi durumunda, buraya koymanız.

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 neden bu yöntemle sales_flat_order_item tablosunda doldurulmuyor?
Creative Apps
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.