Magento: изменить способ доставки на существующий заказ

Я пытаюсь изменить доставку существующего заказа в Magento. Это прекрасно работает в бэкэнде администратора, даже если это довольно сложный процесс, так как мне приходится вручную обновлять многие поля / атрибуты заказа после того, как я установил новый метод доставки для объекта адреса доставки и пересчитал итоговые значения предложения.

Моя проблема заключается в том, что при запуске одного и того же кода во внешнем интерфейсе он не работает вообще, цитата collectTotals отменит все изменения, которые я внес в shippingAddress, и я понятия не имею, как его решить или почему он работает из бэкенд.

Вот как это выглядело:

    $shippingAddress = $quote->getShippingAddress();

$shippingAddress->setShippingMethod('dynamicshipping_'.$shippingCode);
$shippingAddress->setCollectShippingRates(true);
$shippingAddress->collectShippingRates();

$quote->setUseCustomerBalance(1)->setTotalsCollectedFlag(false)->collectTotals()->save();

$order->setShippingHiddenTaxAmount($shippingAddress->getShippingHiddenTaxAmount());
$order->setBaseShippingHiddenTaxAmount($shippingAddress->getBaseShippingHiddenTaxAmount());
$order->setBaseShippingHiddenTaxAmnt($shippingAddress->getBaseShippingHiddenTaxAmnt());
$order->setShippingInclTax($shippingAddress->getShippingInclTax());
$order->setBaseShippingInclTax($shippingAddress->getBaseShippingInclTax());
$order->setShippingTaxAmount($shippingAddress->getShippingTaxAmount());
$order->setBaseShippingTaxAmount($shippingAddress->getBaseShippingTaxAmount());
$order->setShippingAmount($shippingAddress->getShippingAmount());
$order->setBaseShippingAmount($shippingAddress->getBaseShippingAmount());
$order->setShippingDiscountAmount($shippingAddress->getShippingDiscountAmount());
$order->setBaseShippingDiscountAmount($shippingAddress->getBaseShippingDiscountAmount());
$order->setGrandTotal($shippingAddress->getGrandTotal());
$order->setBaseGrandTotal($shippingAddress->getBaseGrandTotal());
$order->setShippingMethod('dynamicshipping_'.$shippingCode);
$order->setShippingDescription($shippingDescription);

$order->setServicePoint($servicePoint);
$order->save();

И, как я уже сказал, это прекрасно работало каждый раз из бэкэнда, но не тогда, когда вызывали из внешнего интерфейса.

Я попробовал варианты, такие как этот, чтобы попытаться уничтожить любые следы старого метода доставки, но не повезло.

    $quote->getShippingAddress()->removeAllShippingRates()
->setShippingMethod('dynamicshipping_'.$shippingCode)
->setShippingDescription($shippingDescription)
//->setBaseShippingAmount(0)
//->setBaseShippingTaxAmount(0)
//->setShippingTaxAmount(0)
//->setShippingInclTax(0)
->setCollectShippingRates(true)
//->unsetData('cached_items_all')
//->unsetData('cached_items_nominal')
//->unsetData('cached_items_nonnominal')
->collectShippingRates()
//->collectTotals()
->save();

Мне кажется, что цитата использует более старую / разную копию адреса доставки, когда я звоню collectTotals, независимо от того, что я делаю.

Любые предложения, или, возможно, понимание того, как это вообще возможно, работает в бэкэнде, но не во внешнем интерфейсе?

РЕДАКТИРОВАТЬ

После дополнительной отладки я вижу, что доставка меняется как во внешнем, так и во внутреннем интерфейсе. Проблема в том, что плата будет меняться только при запуске этого кода через бэкэнд. Очень странно. Он просто отказывается обновлять стоимость доставки.

13

Решение

Похоже, у меня были некоторые проблемы с наблюдателем на collectTotals, поэтому он работал в бэкэнде, где событие не было запущено.

Полный код для справки, который я недавно изменил, чтобы использовать более отказоустойчивый метод для копирования всех полей обратно в порядок.

    /* @var $order Mage_Sales_Model_Order */
/* @var $quote Mage_Sales_Model_Quote */

$shippingAddress = $quote->getShippingAddress();
$shippingAddress->setShippingMethod('dynamicshipping_'.$shippingCode);
$shippingAddress->setShippingDescription($shippingDescription);

$shippingAddress->setCollectShippingRates(true)->collectShippingRates();
$quote->collectTotals();

if ($this->updateMagentoOrder($order, $quote)) {

// here's where I check if we successfully updated the authorized
// amount at the payment gateway, before saving anything
// wrapping the payment update and save in a try-catch

$quote->save();
$order->save();
}

И используя этот метод для обновления всех полей заказа:

/**
* Updates a Magento order based on quote changes
* will not save anything, up to the caller.
* deleting items not supported.
*
* @param  $order Mage_Sales_Model_Order
* @param  $quote Mage_Sales_Model_Quote
* @return bool
*/
public function updateMagentoOrder($order, $quote) {
if (!$order instanceof Mage_Sales_Model_Order || !$quote instanceof Mage_Sales_Model_Quote) {
return false;
}

try {
$converter = Mage::getSingleton('sales/convert_quote');
$converter->toOrder($quote, $order);

foreach ($quote->getAllItems() as $quoteItem) {

$orderItem     = $converter->itemToOrderItem($quoteItem);
$quoteItemId   = $quoteItem->getId();
$origOrderItem = empty($quoteItemId) ? null : $order->getItemByQuoteItemId($quoteItemId);

if ($origOrderItem) {
$origOrderItem->addData($orderItem->getData());
} else {
if ($quoteItem->getParentItem()) {
$orderItem->setParentItem(
$order->getItemByQuoteItemId($quoteItem->getParentItem()->getId())
);
$orderItem->setParentItemId($quoteItem->getParentItemId());
}
$order->addItem($orderItem);
}
}

if ($shippingAddress = $quote->getShippingAddress()) {
$converter->addressToOrder($shippingAddress, $order);
}
} catch (Exception $e) {
Mage::logException($e);
return false;
}

return true;
}

Для справки, метод выше может зацикливаться $order->getAllItems() и делать $orderItem->cancel()->delete(); сначала на них — но я не буду поддерживать удаление элементов прямо сейчас.

cancel() часть перед удалением, так что модуль CatalogInventory может восстановить запас. Это слушает sales_order_item_cancel событие.

2

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]