Magento:更改现有订单的运输方式

Posted

技术标签:

【中文标题】Magento:更改现有订单的运输方式【英文标题】:Magento: change shipping method on existing order 【发布时间】:2015-12-22 10:25:02 【问题描述】:

我正在尝试更改 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 时,报价似乎都使用了较旧/不同的收货地址副本。

有什么建议,或者关于它如何在后端而不是前端起作用的见解?

编辑

经过更多调试,我可以看到前端和后端的运输确实发生了变化。问题是,费用只会在通过后端运行此代码时发生变化。很奇怪。它只是拒绝更新运费。

【问题讨论】:

您能否提供更完整的代码(您将 sn-p 放在哪里)以及有关您的用例的更多信息?我需要一些上下文来回答你的问题。 这是完整的代码,每当下订单的运费发生变化时,我都会从管理员和前端运行它 我的意思是你把你的 sn-p 放在了哪个类,你打算如何从前端使用这个代码? 它位于一个辅助函数中,并从一个前端控制器调用,当用户更改所下订单的运输时,该前端控制器接受一个 ajax 调用。 嗯,我想我已将其范围缩小到“sales_quote_collect_totals_before”事件。我可以在地址本身上运行 collectTotals(),但如果我在报价上运行它,此事件会将运输方式恢复为原始方式。 【参考方案1】:

看起来我与 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 事件。

【讨论】:

以上是关于Magento:更改现有订单的运输方式的主要内容,如果未能解决你的问题,请参考以下文章

前端magento的发货区域“没有可用的发货信息”

根据不同的运输方式更改 Woocommerce 订单状态

订单提交 Magento

从 Magento 导出订单以进行装运

Magento 2.3 发货

如何更改 Magento 订单状态默认流程?