2015-09-24 37 views
13

Sto provando a cambiare la spedizione su un ordine esistente in Magento. Funziona bene dal back-end dell'amministratore, anche se è piuttosto il processo poiché devo aggiornare manualmente molti campi/attributi dell'ordine dopo aver impostato il nuovo metodo di spedizione sull'oggetto indirizzo di spedizione e aver ricalcolato i totali delle quote.Magento: modifica il metodo di spedizione sull'ordine esistente

Il mio problema è quando si esegue lo stesso codice sul frontend, non funziona affatto, la quota collectTotals ripristinerà tutte le modifiche apportate nel shippingAddress, e non ho idea di come risolverlo o perché Funziona dal back-end.

Ecco come sembrava:

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

E come ho detto, che ha funzionato benissimo ogni volta dal backend, ma non quando chiamato dal frontend.

Ho provato delle varianti, come questa per cercare di sradicare qualsiasi traccia del vecchio metodo di spedizione, senza fortuna.

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

Sembra a me come se la citazione utilizza un/copia precedente differente del indirizzo di trasporto quando sto chiamando collectTotals, non importa quello che faccio.

Qualche suggerimento o forse idea di come sia possibile che funzioni nel back-end ma non nel frontend?

EDIT

Dopo più di debug, vedo che la spedizione non cambia sia in frontend e backend. Il problema è che la commissione cambierà solo quando si esegue questo codice attraverso il back-end. Molto strano. Si rifiuta semplicemente di aggiornare la tassa di spedizione.

+0

Potresti fornire un codice più completo (dove hai inserito lo snippet) e maggiori informazioni sul tuo caso d'uso? Avrei bisogno di un contesto, per rispondere alla tua domanda. –

+0

È il codice completo e lo eseguo da admin e frontend ogni volta che la spedizione viene modificata su un ordine disposto –

+0

Intendevo in quale classe hai inserito il tuo snippet e come proponi di utilizzare questo codice dal front-end? –

risposta

2

Sembra che ho avuto alcuni problemi con un osservatore su collectTotals, che è la ragione per cui ha funzionato nel back-end in cui l'evento non è stato licenziato.

Il codice completo di riferimento, che di recente ho modificato per utilizzare un metodo più sicuro per copiare tutti i campi indietro nell'ordine.

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

E con questo metodo per aggiornare tutti i campi d'ordine:

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

Per riferimento, il metodo di cui sopra potrebbe ciclo $order->getAllItems() e fare $orderItem->cancel()->delete(); su di loro prima - ma non voglio sostenere l'eliminazione di elementi a destra adesso.

La parte cancel() prima dell'eliminazione è tale che il modulo CatalogInventory può ripristinare lo stock. Sta ascoltando l'evento sales_order_item_cancel.