Програмно створення відправлень


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для копіювання реквізитів замовлення в об'єкт відвантаження. $ order має бути типу масиву або 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 Core для генерації вантажу, оскільки він використовується як у контролерах відвантаження, так і в рахунках-фактурах. $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

Я не зміг знайти доказів використання цього методу в Core. Якщо чесно, це схоже на злом. Ось метод:

$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 призначений для використання функцій, відкритих через запити API XML RPC / SOAP, і навмисно є базовим для усунення декількох крокових запитів API.

Врешті-решт, метод 3 потрапляє до азотно-зернистого, і через дзвінок до Mage_Sales_Model_Order він викликає prepareShipment, що є абстракцією вищого порядку для звичного вищевказаного Методу 2:

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

Ключовий диференціатор тут - якщо вам потрібна відправка, не забувайте про злами, а маєте лише приріст_id - використовуйте цей метод. Також корисна інформація, якщо ви хочете обробляти це через API SOAP.

Я сподіваюся, що це допомагає.


1
Кожен, хто використовує управління запасами Magestore: метод 3 не запускає їх гачки, тож у вас виникнуть розбіжності між основними відправленнями Magento та товарами зі складу. Також хороша відповідь OP :)
Рікі Одін Меттьюз

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)для кожного елемента , що мають право замовлення. Так, 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). Отже, це потрібно змінити, як і в першому способі, ви також повинні чітко розробити процес.

Дивлячись на 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 цим методом?
Creative Apps
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.