2015-09-24 11 views
13

Ich versuche, den Versand für eine bestehende Bestellung in Magento zu ändern. Dies funktioniert gut aus dem Admin-Backend, auch wenn es ziemlich der Prozess ist, da ich viele der Auftragsfelder/Attribute manuell aktualisieren muss, nachdem ich die neue Versandmethode für das Lieferadresse-Objekt festgelegt und die Angebotssummen neu berechnet habe.Magento: Ändern der Versandmethode für bestehende Bestellung

Mein Problem ist, wenn der gleiche Code auf dem Frontend läuft, funktioniert es überhaupt nicht, das Zitat collectTotals wird alle Änderungen, die ich in der shippingAddress gemacht habe, und ich habe keine Ahnung, wie man es löst oder warum Es funktioniert vom Backend.

Dies ist, wie es aussah:

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

Und wie gesagt, das funktionierte jedes Mal aus dem Backend in Ordnung, aber wenn sie nicht vom Frontend genannt.

Ich habe versucht, Variationen, wie diese zu versuchen und jede Spur der alten Versandmethode zu beseitigen, ohne Glück.

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

Es scheint mir, als ob das Zitat eine ältere/diffrent Kopie der Versandadresse verwendet, wenn ich collectTotals ich anrufen, egal was ich tue.

Irgendwelche Vorschläge, oder vielleicht Einblick, wie es überhaupt möglich ist, dass dies im Backend aber nicht im Frontend funktioniert?

EDIT

Nach mehr Debugging, kann ich sehen, dass der Versand in Frontend und Backend beide nicht ändert. Das Problem ist, dass sich die Gebühr nur ändern wird, wenn Sie diesen Code über das Backend ausführen. Sehr eigenartig. Es lehnt nur ab, Verschiffengebühr zu aktualisieren.

+0

Können Sie einen vollständigeren Code (wo haben Sie Ihr Snippet bereitgestellt) und weitere Informationen zu Ihrem Anwendungsfall angeben? Ich würde einen Zusammenhang brauchen, um deine Frage zu beantworten. –

+0

Es ist der vollständige Code, und ich führe es von Admin und Frontend, wenn der Versand geändert wird, um eine Bestellung aufgegeben –

+0

Ich meinte, in welcher Klasse haben Sie Ihr Snippet eingefügt, und wie schlagen Sie vor, diesen Code aus dem Front-End zu engagieren? –

Antwort

2

Sieht aus, als hätte ich einige Probleme mit einem Beobachter auf CollectTotals, was der Grund dafür ist, dass es im Backend arbeitete, wo das Ereignis nicht ausgelöst wurde.

Der vollständige Code als Referenz, den ich vor kurzem geändert habe, um eine ausfallsicherere Methode zu verwenden, um alle Felder zurück in den Auftrag zu kopieren.

/* @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(); 
    } 

Und mit dieser Methode für die Aktualisierung der alle Auftragsfelder:

/** 
* 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; 
} 

als Referenz, wobei das Verfahren oben konnte Schleife $order->getAllItems() und erste $orderItem->cancel()->delete(); auf ihnen tun - aber ich werde nicht unterstützt Artikel direkt zu löschen jetzt.

Der cancel() Teil vor dem Löschen ist so, dass das CatalogInventory-Modul den Bestand wiederherstellen kann. Es hört auf das sales_order_item_cancel Ereignis.

Verwandte Themen