2015-09-24 15 views
13

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を呼んだときの引用には関係なく、私は何をすべきか、配送先住所の切り抜いた/古いコピーを使用していないかのように私には見えます。

これはバックエンドではなくフロントエンドではどのように動作する可能性がありますか?

EDITは、より多くのデバッグの後、私は送料がフロントエンドとバックエンドの両方で変化しないことがわかります。問題は、このコードをバックエンド経由で実行する場合にのみ料金が変更されることです。非常に奇妙な。それは単に送料を更新することを拒否します。

+0

より完全なコード(あなたのスニペットはどこに入れましたか)とユースケースの詳細を教えてください。私はあなたの質問に答えるために、いくつかの文脈が必要です。 –

+0

これは完全なコードです。配送先が変更された場合は、管理者とフロントエンドから実行します。 –

+0

スニペットをどのクラスに入れましたか、フロントエンドからこのコードをどのように提案するのですか? –

答えて

2

observerに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イベントをリッスンしています。

関連する問題