2015-09-24 10 views
13

Próbuję zmienić wysyłkę na istniejącym zamówieniu w Magento. Działa to dobrze z poziomu zaplecza administracyjnego, nawet jeśli jest to dość skomplikowany proces, ponieważ muszę ręcznie zaktualizować wiele pól/atrybutów zamówień po ustawieniu nowej metody wysyłki w obiekcie adresu wysyłki i ponownie obliczyć sumy kwotowania.Magento: zmień metodę wysyłki na istniejącym zamówieniu

Mój problem polega na tym, że przy uruchomieniu tego samego kodu na interfejsie, to w ogóle nie działa, cytat collectTotals przywróci wszelkie zmiany wprowadzone w parametrze shippingAddress, i nie mam pojęcia, jak go rozwiązać lub dlaczego działa z zaplecza.

Jak to wyglądało:

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

I jak powiedziałem, że pracował w porządku za każdym razem od zaplecza, ale nie wtedy, gdy wywołana z frontend.

Próbowałem odmiany, takie jak to, aby spróbować i wyeliminować wszelkie ślady starej metody wysyłki, bez powodzenia.

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

Wydaje mi się, że cytat jest za pomocą starszej/wypróbujemy inny egzemplarz adresu wysyłkowego kiedy dzwonię collectTotals, bez względu na to, co robię.

Jakieś sugestie, a może wgląd w to, jak to możliwe, że działa to w backendach, ale nie w interfejsie?

EDIT

Po więcej debugowania, widzę, że przesyłka nie zmienia zarówno w frontend i backend. Problem polega na tym, że opłata zmieni się tylko podczas uruchamiania tego kodu przez backend. Bardzo dziwny. Po prostu odmawia aktualizacji opłaty za wysyłkę.

+0

Czy możesz podać bardziej kompletny kod (gdzie umieściłeś swój fragment) i dodatkowe informacje na temat twojego przypadku użycia? Potrzebuję jakiegoś kontekstu, by odpowiedzieć na twoje pytanie. –

+0

To jest kompletny kod i uruchamiam go z poziomu administratora i interfejsu użytkownika, gdy wysyłka zostanie zmieniona w zamówieniu złożonym –

+0

Chodzi mi o to, w której klasie umieściłeś swój kod i jak zamierzasz zaangażować ten kod z front-endu? –

Odpowiedz

2

Wygląda na to, że miałem pewne problemy z obserwatorem w sprawie collectTotals, i to dlatego, że działało w zapleczu, w którym wydarzenie nie zostało zwolnione.

Kompletny kod referencyjny, który ostatnio zmieniono, aby użyć bardziej bezpiecznej metody, aby skopiować wszystkie pola z powrotem do zamówienia.

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

i stosując tę ​​metodę do aktualizacji wszystkich pól porządkowe:

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

odsyłającym metodę powyżej może pętla $order->getAllItems() i zrobić $orderItem->cancel()->delete(); na nich pierwszy - ale nie będę wspierać usuwanie elementów prawo teraz.

Część przed usunięciem jest tak, że moduł CatalogInventory może przywrócić zapasy. Słucha wydarzenia sales_order_item_cancel.

Powiązane problemy