久久久久久久av_日韩在线中文_看一级毛片视频_日本精品二区_成人深夜福利视频_武道仙尊动漫在线观看

排序算法:Magento 結(jié)帳總額排序錯誤導(dǎo)致運費計算

Sort algorithm: Magento checkout totals sorted wrongly causing wrong shipping tax calculation(排序算法:Magento 結(jié)帳總額排序錯誤導(dǎo)致運費計算錯誤)
本文介紹了排序算法:Magento 結(jié)帳總額排序錯誤導(dǎo)致運費計算錯誤的處理方法,對大家解決問題具有一定的參考價值,需要的朋友們下面隨著小編來一起學習吧!

問題描述

在 Magento 中有一個功能,您可以通過指定運行總計之前和之后的總計來定義總計計算的順序.

我添加了一個自定義總數(shù),如果我將以下幾行添加到 config.xml,排序是錯誤的.錯誤的意思是:tax_shipping before shipping.這會導(dǎo)致運費稅金增加兩次.

但這違反了條件

tax_shipping之后:航運

我的猜測:在全套規(guī)則中肯定有一些矛盾.但是我怎么才能找到它呢?

這是我添加的唯一規(guī)則.如果沒有此規(guī)則,tax_shipping 將排在 shipping 之后.

<class>n98_shippingprotection/quote_address_total_shippingprotectionTax</class><after>小計,折扣,運費,稅</after><before>grand_total</before></shippingprotectiontax>

下面我將 usort 調(diào)用返回的排序數(shù)組粘貼到 Mage_Sales_Model_Quote_Address_Total_Collector::_getSortedCollectorCodes()對于沒有安裝Magento的,代碼是這樣的:

/*** uasort回調(diào)函數(shù)** @param 數(shù)組 $a* @param 數(shù)組 $b* @return 整數(shù)*/受保護的函數(shù) _compareTotals($a, $b){$aCode = $a['_code'];$bCode = $b['_code'];if (in_array($aCode, $b['after']) || in_array($bCode, $a['before'])) {$res = -1;} elseif (in_array($bCode, $a['after']) || in_array($aCode, $b['before'])) {$res = 1;} 別的 {$res = 0;}返回 $res;}受保護的函數(shù) _getSortedCollectorCodes(){...uasort($configArray, array($this, '_compareTotals'));Mage::log('排序:');//這會產(chǎn)生下面的輸出$loginfo = "";foreach($configArray as $code=>$data) {$loginfo .= "$code
";$loginfo .= "after: ".implode(',',$data['after'])."
";$loginfo .= "before: ".implode(',',$data['before'])."
";$loginfo .= "
";}法師::日志($loginfo);...

日志輸出:

名義后:之前:小計,grand_total小計之后:名義上之前:總計,運費,免運費,稅小計,折扣,稅,小,禮品包裝,現(xiàn)金交付,現(xiàn)金交付_稅,運輸保護,運輸保護稅免運費之后:小計,名義之前:tax_subtotal,shipping,grand_total,tax,discounttax_shipping之后:運費,小計,免運費,tax_subtotal,名義之前:稅收,折扣,grand_total,grand_total禮品包裝之后:小計,名義前:tax_小計之后:免費送貨,小計,小計,名義之前:稅收,折扣,運費,grand_total,weee,customerbalance,giftcardaccount,reward嗚嗚嗚之后:小計,tax_subtotal,名義,免費送貨,小計,小計,名義之前:稅收,折扣,grand_total,grand_total,稅收運輸之后:小計,免運費,tax_subtotal,名義之前:grand_total,discount,tax_shipping,tax,cashondelivery,cashondelivery_tax,shippingprotection,shippingprotectiontax折扣之后:小計,運費,名義,免費送貨,tax_subtotal,tax_shipping,weee之前:grand_total,tax,customerbalance,giftcardaccount,reward,cashondelivery,cashondelivery_tax,shippingprotection,shippingprotectiontax貨到付款之后:小計,折扣,運費,名義,小計,運費,名義,免運費,tax_subtotal,tax_shipping,小,小計,免運費,tax_subtotal,名義之前:稅,總金額,總金額,客戶余額,禮品卡帳戶,稅金包裝,獎勵,客戶余額,禮品卡帳戶,獎勵運輸保護之后:小計,折扣,運費,名義,小計,運費,名義,免運費,tax_subtotal,tax_shipping,小,小計,免運費,tax_subtotal,名義之前:稅,總金額,總金額,客戶余額,禮品卡帳戶,稅金禮品包裝,獎勵,現(xiàn)金交付_稅,客戶余額,禮品卡帳戶,獎勵稅之后:小計,運費,折扣,tax_subtotal,免費送貨,tax_shipping,名義,小,現(xiàn)金交付,shippingprotection之前:grand_total,customerbalance,giftcardaccount,tax_giftwrapping,reward,cashondelivery_tax,shippingprotectiontax運輸保護稅之后:小計,折扣,運費,稅,名義,小計,運費,名義,免費送貨,tax_subtotal,tax_shipping,小,小計,免費送貨,tax_subtotal,名義,小計,運費,折扣,tax_subtotal,免費送貨,tax_shipping,名義,weee,貨到付款,運輸保障之前:grand_total,customerbalance,giftcardaccount,rewardcashondelivery_tax之后:小計,折扣,運費,稅,名義,小計,運費,名義,免費送貨,tax_subtotal,tax_shipping,小,小計,免費送貨,tax_subtotal,名義,小計,運費,折扣,tax_subtotal,免費送貨,tax_shipping,名義,weee,貨到付款之前:grand_total,customerbalance,giftcardaccount,rewardtax_giftwrapping后:稅,小計,運費,折扣,tax_subtotal,免費送貨,tax_shipping,名義,小之前:grand_total、customerbalance、giftcardaccount累計之后:小計、名義、運費、免運費、tax_subtotal、折扣、稅、tax_giftwrapping、cashondelivery、cashondelivery_tax、shippingprotection、shippingprotectiontax之前:客戶余額,禮品卡帳戶,獎勵報酬之后:wee,discount,tax,tax_subtotal,grand_total,subtotal,shipping,nominal,freeshipping,tax_subtotal,tax_shipping,weee,subtotal,shipping,discount,tax_subtotal,freeshipping,tax_shipping,nominal,weee,freeshipping,subtotal,subtotal,nominal小計,名義,運費,免運費,tax_subtotal,折扣,tax,tax_giftwrapping之前:禮品卡帳戶,客戶余額,客戶余額禮品卡賬戶之后:小,折扣,稅收,tax_subtotal,grand_total,獎勵,小計,運費,名義,免費送貨,tax_shipping,weee之前:客戶余額客戶余額之后:wee,discount,tax,tax_subtotal,grand_total,reward,giftcardaccount,subtotal,shipping,nominal,freeshipping,tax_shipping,weee前:

在 Vinai 的回答之后,我添加了更多調(diào)試代碼

$fp = fopen('/tmp/dotfile','w');fwrite($fp,"digraph TotalOrder
");fwrite($fp,"{
");foreach($configArray as $code=>$data) {$_code = $data['_code'];foreach($data['before'] 作為 $beforeCode) {fwrite($fp,"$beforeCode -> $_code;
");}foreach($data['after'] 作為 $afterCode) {fwrite($fp,"$_code -> $afterCode;
");}}fwrite($fp,"}
");fclose($fp);

并使用graphviz對其進行可視化:dot -Tpng dotfile >即.png.這是第一次嘗試的結(jié)果.排序后調(diào)用.

編輯 2:

我覺得這沒什么用.

所以我在合并之后/之前條目之前對數(shù)組進行了可視化.(緊跟在 $configArray = $this->_modelsConfig; 之后)

這是沒有我的shippingprotectiontax條目:

這是我的shippingprotectiontax條目:

我沒有看到任何明顯的矛盾.

編輯 3:

uasort 之前的配置數(shù)組:

<前>大批 ('名義' =>大批 ('class' => 'sales/quote_address_total_nominal','之前' =>大批 (0 => '小計',1 => 'grand_total',),'renderer' => 'checkout/total_nominal','之后' =>大批 (),'_code' => '名義',),'小計' =>大批 ('class' => 'sales/quote_address_total_subtotal','之后' =>大批 (0 => '名義',),'之前' =>大批 (0 => 'grand_total',1 => '運輸',2 => '免費送貨',3 => 'tax_subtotal',4 => '折扣',5 => '稅',6 => '小',7 => '禮品包裝',8 => '現(xiàn)金交付',9 => 'cashondelivery_tax',10 => '運輸保護',11 => 'shippingprotectiontax',),'renderer' => 'tax/checkout_subtotal','admin_renderer' => 'adminhtml/sales_order_create_totals_subtotal','_code' => '小計',),'運輸' =>大批 ('class' => 'sales/quote_address_total_shipping','之后' =>大批 (0 => '小計',1 => '免費送貨',2 => 'tax_subtotal',3 => '名義',),'之前' =>大批 (0 => 'grand_total',1 => '折扣',2 => 'tax_shipping',3 => '稅',4 => '現(xiàn)金交付',5 => 'cashondelivery_tax',6 => '運輸保護',7 => 'shippingprotectiontax',),'renderer' => 'tax/checkout_shipping','admin_renderer' => 'adminhtml/sales_order_create_totals_shipping','_code' => '運輸',),'grand_total' =>大批 ('class' => 'sales/quote_address_total_grand','之后' =>大批 (0 => '小計',1 => '名義',2 => '運輸',3 => '免費送貨',4 => 'tax_subtotal',5 => '折扣',6 => '稅',7 => 'tax_giftwrapping',8 => '現(xiàn)金交付',9 => 'cashondelivery_tax',10 => '運輸保護',11 => 'shippingprotectiontax',),'renderer' => 'tax/checkout_grandtotal','admin_renderer' => 'adminhtml/sales_order_create_totals_grandtotal','之前' =>大批 (0 => '客戶余額',1 => '禮品卡賬戶',2 => '獎勵',),'_code' => 'grand_total',),'免費送貨' =>大批 ('class' => 'salesrule/quote_freeshipping','之后' =>大批 (0 => '小計',1 => '名義',),'之前' =>大批 (0 => 'tax_subtotal',1 => '運輸',2 => 'grand_total',3 => '稅',4 => '折扣',),'_code' => '免費送貨',),'折扣' =>大批 ('class' => 'salesrule/quote_discount','之后' =>大批 (0 => '小計',1 => '運輸',2 => '名義',3 => '免費送貨',4 => 'tax_subtotal',5 => 'tax_shipping',6 => '小',),'之前' =>大批 (0 => 'grand_total',1 => '稅',2 => '客戶余額',3 => '禮品卡賬戶',4 => '獎勵',5 => '現(xiàn)金交付',6 => 'cashondelivery_tax',7 => '運輸保護',8 => 'shippingprotectiontax',),'renderer' => 'tax/checkout_discount','admin_renderer' => 'adminhtml/sales_order_create_totals_discount','_code' => '折扣',),'tax_subtotal' =>大批 ('class' => 'tax/sales_total_quote_subtotal','之后' =>大批 (0 => '免費送貨',1 => '小計',2 => '小計',3 => '名義',),'之前' =>大批 (0 => '稅',1 => '折扣',2 => '運輸',3 => 'grand_total',4 => '小',5 => '客戶余額',6 => '禮品卡賬戶',7 => '獎勵',),'_code' => 'tax_subtotal',),'tax_shipping' =>大批 ('class' => 'tax/sales_total_quote_shipping','之后' =>大批 (0 => '運輸',1 => '小計',2 => '免費送貨',3 => 'tax_subtotal',4 => '名義',),'之前' =>大批 (0 => '稅',1 => '折扣',2 => 'grand_total',3 => 'grand_total',),'_code' => 'tax_shipping',),'稅' =>大批 ('class' => 'tax/sales_total_quote_tax','之后' =>大批 (0 => '小計',1 => '運輸',2 => '折扣',3 => 'tax_subtotal',4 => '免費送貨',5 => 'tax_shipping',6 => '名義',7 => '小',8 => '現(xiàn)金交付',9 => '運輸保護',),'之前' =>大批 (0 => 'grand_total',1 => '客戶余額',2 => '禮品卡賬戶',3 => 'tax_giftwrapping',4 => '獎勵',5 => 'cashondelivery_tax',6 => 'shippingprotectiontax',),'renderer' => 'tax/checkout_tax','admin_renderer' => 'adminhtml/sales_order_create_totals_tax','_code' => '稅',),'小' =>大批 ('class' => 'weee/total_quote_weee','之后' =>大批 (0 => '小計',1 => 'tax_subtotal',2 => '名義',3 => '免費送貨',4 => '小計',5 => '小計',6 => '名義',),'之前' =>大批 (0 => '稅',1 => '折扣',2 => 'grand_total',3 => 'grand_total',4 => '稅',),'_code' => 'weee',),'客戶余額' =>大批 ('class' => 'enterprise_customerbalance/total_quote_customerbalance','之后' =>大批 (0 => '小',1 => '折扣',2 => '稅',3 => 'tax_subtotal',4 => 'grand_total',5 => '獎勵',6 => '禮品卡賬戶',7 => '小計',8 => '運輸',9 => '名義',10 => '免費送貨',11 => 'tax_shipping',12 => '小',),'renderer' => 'enterprise_customerbalance/checkout_total','之前' =>大批 (),'_code' => '客戶余額',),'禮品卡帳戶' =>大批 ('class' => 'enterprise_giftcardaccount/total_quote_giftcardaccount','之后' =>大批 (0 => '小',1 => '折扣',2 => '稅',3 => 'tax_subtotal',4 => 'grand_total',5 => '獎勵',6 => '小計',7 => '運輸',8 => '名義',9 => '免費送貨',11 => 'tax_shipping',12 => '小',),'之前' =>大批 (0 => '客戶余額',),'renderer' => 'enterprise_giftcardaccount/checkout_cart_total','_code' => 'giftcardaccount',),'禮品包裝' =>大批 ('class' => 'enterprise_giftwrapping/total_quote_giftwrapping','之后' =>大批 (0 => '小計',1 => '名義',),'renderer' => 'enterprise_giftwrapping/checkout_totals','之前' =>大批 (),'_code' => '禮品包裝',),'tax_giftwrapping' =>大批 ('class' => 'enterprise_giftwrapping/total_quote_tax_giftwrapping','之后' =>大批 (0 => '稅',1 => '小計',2 => '運輸',3 => '折扣',4 => 'tax_subtotal',5 => '免費送貨',6 => 'tax_shipping',7 => '名義',8 => '小',),'之前' =>大批 (0 => 'grand_total',1 => '客戶余額',2 => '禮品卡賬戶',),'_code' => 'tax_giftwrapping',),'獎勵' =>大批 ('class' => 'enterprise_reward/total_quote_reward','之后' =>大批 (0 => '小',1 => '折扣',2 => '稅',3 => 'tax_subtotal',4 => 'grand_total',5 => '小計',6 => '運輸',7 => '名義',8 => '免費送貨',9 => 'tax_subtotal',10 => 'tax_shipping',11 => '小',12 => '小計',13 => '運輸',14 => '折扣',15 => 'tax_subtotal',16 => '免費送貨',17 => 'tax_shipping',18 => '名義',19 => '小',20 => '免費送貨',21 => '小計',22 => '小計',23 => '名義',24 => '小計',25 => '名義',26 => '運輸',27 => '免費送貨',28 => 'tax_subtotal',29 => '折扣',30 => '稅',31 => 'tax_giftwrapping',),'之前' =>大批 (0 => '禮品卡賬戶',1 => '客戶余額',2 => '客戶余額',),'renderer' => 'enterprise_reward/checkout_total','_code' => '獎勵',),'現(xiàn)金交付' =>大批 ('class' => 'cashondelivery/quote_total','之后' =>大批 (0 => '小計',1 => '折扣',2 => '運輸',3 => '名義',4 => '小計',5 => '運輸',6 => '名義',7 => '免費送貨',8 => 'tax_subtotal',9 => 'tax_shipping',10 => '小',11 => '小計',12 => '免費送貨',13 => 'tax_subtotal',14 => '名義',),'之前' =>大批 (0 => '稅',1 => 'grand_total',2 => 'grand_total',3 => '客戶余額',4 => '禮品卡賬戶',5 => 'tax_giftwrapping',6 => '獎勵',7 => '客戶余額',8 => '禮品卡賬戶',9 => '獎勵',),'renderer' => 'cashondelivery/checkout_cod','admin_renderer' => 'cashondelivery/adminhtml_sales_order_create_totals_cod','_code' => '現(xiàn)金交貨',),'cashondelivery_tax' =>大批 ('class' => 'cashondelivery/quote_taxTotal','之后' =>大批 (0 => '小計',1 => '折扣',2 => '運輸',3 => '稅',4 => '名義',5 => '小計',6 => '運輸',7 => '名義',8 => '免費送貨',9 => 'tax_subtotal',10 => 'tax_shipping',11 => '小',12 => '小計',13 => '免費送貨',14 => 'tax_subtotal',15 => '名義',16 => '小計',17 => '運輸',18 => '折扣',19 => 'tax_subtotal',20 => '免費送貨',21 => 'tax_shipping',22 => '名義',23 => '小',24 => '現(xiàn)金交付',),'之前' =>大批 (0 => 'grand_total',1 => '客戶余額',2 => '禮品卡賬戶',3 => '獎勵',),'_code' => 'cashondelivery_tax',),'運輸保護' =>大批 ('class' => 'n98_shippingprotection/quote_address_total_shippingprotection','之后' =>大批 (0 => '小計',1 => '折扣',2 => '運輸',3 => '名義',4 => '小計',5 => '運輸',6 => '名義',7 => '免費送貨',8 => 'tax_subtotal',9 => 'tax_shipping',10 => '小',11 => '小計',12 => '免費送貨',13 => 'tax_subtotal',14 => '名義',),'之前' =>大批 (0 => '稅',1 => 'grand_total',2 => 'grand_total',3 => '客戶余額',4 => '禮品卡賬戶',5 => 'tax_giftwrapping',6 => '獎勵',7 => 'cashondelivery_tax',8 => '客戶余額',9 => '禮品卡賬戶',10 => '獎勵',),'_code' => 'shippingprotection',),'運輸保護稅' =>大批 ('class' => 'n98_shippingprotection/quote_address_total_shippingprotectionTax','之后' =>大批 (0 => '小計',1 => '折扣',2 => '運輸',3 => '稅',4 => '名義',5 => '小計',6 => '運輸',7 => '名義',8 => '免費送貨',9 => 'tax_subtotal',10 => 'tax_shipping',11 => '小',12 => '小計',13 => '免費送貨',14 => 'tax_subtotal',15 => '名義',16 => '小計',17 => '運輸',18 => '折扣',19 => 'tax_subtotal',20 => '免費送貨',21 => 'tax_shipping',22 => '名義',23 => '小',24 => '現(xiàn)金交付',25 => '運輸保護',),'之前' =>大批 (0 => 'grand_total',1 => '客戶余額',2 => '禮品卡賬戶',3 => '獎勵',),'_code' => 'shippingprotectiontax',),)

<小時>

更新: Magento 錯誤票證:https://jira.magento.com/browse/MCACE-129

解決方案

最后,這是我針對這個問題的補丁.

它實現(xiàn)了 Vinai 建議的拓撲排序.

  1. app/code/core/Mage/Sales/Model/Config/Ordered.php復(fù)制到app/code/local/Mage/Sales/Model/Config/Ordered.php
  2. 將補丁的內(nèi)容保存到文件 total-sorting.patch 并調(diào)用 patch -p0 app/code/local/Mage/Sales/Model/Config/Ordered.php

如果升級,請確保重新應(yīng)用這些步驟.

該補丁經(jīng)過測試可與 Magento 1.7.0.2 配合使用

<前>--- app/code/core/Mage/Sales/Model/Config/Ordered.php 2012-08-14 14:19:50.306504947 +0200+++ app/code/local/Mage/Sales/Model/Config/Ordered.php 2012-08-15 10:00:47.027003404 +0200@@ -121,6 +121,78 @@返回 $totalConfig;}+//[補丁代碼開始]++/**+ * 拓撲排序+ *+ * 版權(quán)所有:http://www.calcatraz.com/blog/php-topological-sort-function-384+ * 并修復(fù)見 http://stackoverflow.com/questions/11953021/topological-sorting-in-php 上的評論+ *+ * @param $nodeids 節(jié)點 ID+ * @param $edges 邊數(shù)組.每條邊被指定為一個包含兩個元素的數(shù)組:邊的源節(jié)點和目標節(jié)點+ * @return 數(shù)組|null+ */+ 函數(shù)拓撲排序($nodeids,$edges){+ $L = $S = $nodes = array();+ foreach($nodeids 作為 $id) {+ $nodes[$id] = array('in'=>array(), 'out'=>array());+ foreach($edges as $e) {+ if ($id==$e[0]) { $nodes[$id]['out'][]=$e[1];}+ if ($id==$e[1]) { $nodes[$id]['in'][]=$e[0];}+ }+ }+ foreach ($nodes as $id=>$n) { if (empty($n['in'])) $S[]=$id;}+ while ($id = array_shift($S)) {+ if (!in_array($id, $L)) {+ $L[] = $id;+ foreach($nodes[$id]['out'] as $m) {+ $nodes[$m]['in'] = array_diff($nodes[$m]['in'], array($id));+ if (empty($nodes[$m]['in'])) { $S[] = $m;}+ }+ $nodes[$id]['out'] = array();+ }+ }+ foreach($nodes as $n) {+ if (!empty($n['in']) 或 !empty($n['out'])) {+ 返回空;//不可排序,因為圖是循環(huán)的+ }+ }+ 返回 $L;+ }++/**+ * 排序配置數(shù)組+ *+ * public 可以通過測試輕松訪問+ *+ * @param $configArray+ * @return 數(shù)組+ */+ 公共函數(shù) _topSortConfigArray($configArray)+ {+ $nodes = array_keys($configArray);+ $edges = 數(shù)組();++ foreach ($configArray as $code => $data) {+ $_code = $data['_code'];+ if (!isset($configArray[$_code])) 繼續(xù);+ foreach ($data['before'] as $beforeCode) {+ if (!isset($configArray[$beforeCode])) 繼續(xù);+ $edges[] = array($_code, $beforeCode);+ }++ foreach ($data['after'] as $afterCode) {+ if (!isset($configArray[$afterCode])) 繼續(xù);+ $edges[] = array($afterCode, $_code);+ }+ }+ 返回 $this->topological_sort($nodes, $edges);+ }++//[補丁代碼結(jié)束]++/*** 匯總所有項目的前后信息并根據(jù)此數(shù)據(jù)對總數(shù)進行排序*@@ -138,38 +210,16 @@//如果第一個元素包含sort_order"鍵,則調(diào)用簡單排序重置($configArray);$element = current($configArray);+//[補丁代碼開始]如果 (isset($element['sort_order'])) {uasort($configArray, array($this, '_compareSortOrder'));+ $sortedCollectors = array_keys($configArray);+} 別的 {- foreach ($configArray as $code => $data) {- foreach ($data['before'] as $beforeCode) {- 如果 (!isset($configArray[$beforeCode])) {- 繼續(xù);- }- $configArray[$code]['before'] = array_unique(array_merge(- $configArray[$code]['before'], $configArray[$beforeCode]['before']- ));- $configArray[$beforeCode]['after'] = array_merge(- $configArray[$beforeCode]['after'], array($code), $data['after']- );- $configArray[$beforeCode]['after'] = array_unique($configArray[$beforeCode]['after']);- }- foreach ($data['after'] as $afterCode) {- 如果 (!isset($configArray[$afterCode])) {- 繼續(xù);- }- $configArray[$code]['after'] = array_unique(array_merge(- $configArray[$code]['after'], $configArray[$afterCode]['after']- ));- $configArray[$afterCode]['before'] = array_merge(- $configArray[$afterCode]['before'], array($code), $data['before']- );- $configArray[$afterCode]['before'] = array_unique($configArray[$afterCode]['before']);- }- }- uasort($configArray, array($this, '_compareTotals'));+ $sortedCollectors = $this->_topSortConfigArray($configArray);}- $sortedCollectors = array_keys($configArray);+//[補丁代碼結(jié)束]+if (Mage::app()->useCache('config')) {Mage::app()->saveCache(serialize($sortedCollectors), $this->_collectorsCacheKey, array(Mage_Core_Model_Config::CACHE_TAG@@ -196,27 +246,6 @@}/**- * 使用 after/before 進行比較的回調(diào)- *- * @param 數(shù)組 $a- * @param 數(shù)組 $b- * @return int- */- 受保護的函數(shù) _compareTotals($a, $b)- {- $aCode = $a['_code'];- $bCode = $b['_code'];- if (in_array($aCode, $b['after']) || in_array($bCode, $a['before'])) {- $res = -1;- } elseif (in_array($bCode, $a['after']) || in_array($aCode, $b['before'])) {- $res = 1;- } 別的 {- $res = 0;- }- 返回 $res;- }——-/*** 使用 sort_order 進行比較的回調(diào)** @param 數(shù)組 $a

編輯:還有另一個建議的更改(對于 Magento 2):https://github.com/magento/magento2/pull/49

In Magento there is a functionality where you can define the order of total calculation by specifing before and after which totals a total should be run.

I added a custom total and if I add the following lines to the config.xml, the sorting is wrong. Wrong means: tax_shipping comes before shipping. This causes the tax for the shipping cost to be added twice.

But this violates the condition

tax_shipping
after: shipping

My guess: There must be some contradiction in the full set of rules. But how can I find it?

This is the only rule I add. Without this rule, tax_shipping is sorted after shipping.

<shippingprotectiontax>
    <class>n98_shippingprotection/quote_address_total_shippingprotectionTax</class>
    <after>subtotal,discount,shipping,tax</after>
    <before>grand_total</before>
</shippingprotectiontax>

Below I paste the sorted array that is returned by the usort call in Mage_Sales_Model_Quote_Address_Total_Collector::_getSortedCollectorCodes() For those who do not have a Magento installation, the code is like this:

/**
 * uasort callback function
 *
 * @param   array $a
 * @param   array $b
 * @return  int
 */
protected function _compareTotals($a, $b)
{
    $aCode = $a['_code'];
    $bCode = $b['_code'];
    if (in_array($aCode, $b['after']) || in_array($bCode, $a['before'])) {
        $res = -1;
    } elseif (in_array($bCode, $a['after']) || in_array($aCode, $b['before'])) {
        $res = 1;
    } else {
        $res = 0;
    }
    return $res;
}

protected function _getSortedCollectorCodes()
{

    ...

    uasort($configArray, array($this, '_compareTotals'));
    Mage::log('Sorted:');

    // this produces the output below
    $loginfo = "";
    foreach($configArray as $code=>$data) {
        $loginfo .= "$code
";
        $loginfo .= "after: ".implode(',',$data['after'])."
";
        $loginfo .= "before: ".implode(',',$data['before'])."
";
        $loginfo .= "
";
    }
    Mage::log($loginfo);

    ...

Log output:

nominal
after: 
before: subtotal,grand_total

subtotal
after: nominal
before: grand_total,shipping,freeshipping,tax_subtotal,discount,tax,weee,giftwrapping,cashondelivery,cashondelivery_tax,shippingprotection,shippingprotectiontax

freeshipping
after: subtotal,nominal
before: tax_subtotal,shipping,grand_total,tax,discount

tax_shipping
after: shipping,subtotal,freeshipping,tax_subtotal,nominal
before: tax,discount,grand_total,grand_total

giftwrapping
after: subtotal,nominal
before: 

tax_subtotal
after: freeshipping,subtotal,subtotal,nominal
before: tax,discount,shipping,grand_total,weee,customerbalance,giftcardaccount,reward

weee
after: subtotal,tax_subtotal,nominal,freeshipping,subtotal,subtotal,nominal
before: tax,discount,grand_total,grand_total,tax

shipping
after: subtotal,freeshipping,tax_subtotal,nominal
before: grand_total,discount,tax_shipping,tax,cashondelivery,cashondelivery_tax,shippingprotection,shippingprotectiontax

discount
after: subtotal,shipping,nominal,freeshipping,tax_subtotal,tax_shipping,weee
before: grand_total,tax,customerbalance,giftcardaccount,reward,cashondelivery,cashondelivery_tax,shippingprotection,shippingprotectiontax

cashondelivery
after: subtotal,discount,shipping,nominal,subtotal,shipping,nominal,freeshipping,tax_subtotal,tax_shipping,weee,subtotal,freeshipping,tax_subtotal,nominal
before: tax,grand_total,grand_total,customerbalance,giftcardaccount,tax_giftwrapping,reward,customerbalance,giftcardaccount,reward

shippingprotection
after: subtotal,discount,shipping,nominal,subtotal,shipping,nominal,freeshipping,tax_subtotal,tax_shipping,weee,subtotal,freeshipping,tax_subtotal,nominal
before: tax,grand_total,grand_total,customerbalance,giftcardaccount,tax_giftwrapping,reward,cashondelivery_tax,customerbalance,giftcardaccount,reward

tax
after: subtotal,shipping,discount,tax_subtotal,freeshipping,tax_shipping,nominal,weee,cashondelivery,shippingprotection
before: grand_total,customerbalance,giftcardaccount,tax_giftwrapping,reward,cashondelivery_tax,shippingprotectiontax

shippingprotectiontax
after: subtotal,discount,shipping,tax,nominal,subtotal,shipping,nominal,freeshipping,tax_subtotal,tax_shipping,weee,subtotal,freeshipping,tax_subtotal,nominal,subtotal,shipping,discount,tax_subtotal,freeshipping,tax_shipping,nominal,weee,cashondelivery,shippingprotection
before: grand_total,customerbalance,giftcardaccount,reward

cashondelivery_tax
after: subtotal,discount,shipping,tax,nominal,subtotal,shipping,nominal,freeshipping,tax_subtotal,tax_shipping,weee,subtotal,freeshipping,tax_subtotal,nominal,subtotal,shipping,discount,tax_subtotal,freeshipping,tax_shipping,nominal,weee,cashondelivery
before: grand_total,customerbalance,giftcardaccount,reward

tax_giftwrapping
after: tax,subtotal,shipping,discount,tax_subtotal,freeshipping,tax_shipping,nominal,weee
before: grand_total,customerbalance,giftcardaccount

grand_total
after: subtotal,nominal,shipping,freeshipping,tax_subtotal,discount,tax,tax_giftwrapping,cashondelivery,cashondelivery_tax,shippingprotection,shippingprotectiontax
before: customerbalance,giftcardaccount,reward

reward
after: wee,discount,tax,tax_subtotal,grand_total,subtotal,shipping,nominal,freeshipping,tax_subtotal,tax_shipping,weee,subtotal,shipping,discount,tax_subtotal,freeshipping,tax_shipping,nominal,weee,freeshipping,subtotal,subtotal,nominal,subtotal,nominal,shipping,freeshipping,tax_subtotal,discount,tax,tax_giftwrapping
before: giftcardaccount,customerbalance,customerbalance

giftcardaccount
after: wee,discount,tax,tax_subtotal,grand_total,reward,subtotal,shipping,nominal,freeshipping,tax_shipping,weee
before: customerbalance

customerbalance
after: wee,discount,tax,tax_subtotal,grand_total,reward,giftcardaccount,subtotal,shipping,nominal,freeshipping,tax_shipping,weee
before: 

EDIT:

After Vinai's answer I added more debug code

$fp = fopen('/tmp/dotfile','w');
fwrite($fp,"digraph TotalOrder
");
fwrite($fp,"{
");
foreach($configArray as $code=>$data) {
    $_code = $data['_code'];
    foreach($data['before'] as $beforeCode) {
        fwrite($fp,"$beforeCode -> $_code;
");
    }
    foreach($data['after'] as $afterCode) {
        fwrite($fp,"$_code -> $afterCode;
");
    }
}
fwrite($fp,"}
");
fclose($fp);

And visualized it with graphviz: dot -Tpng dotfile > viz.png. That's the result of the first try. Called after the sorting.

EDIT2:

I think this is pretty useless.

So I made a visualization of the array before merging the after/before entries. (right after $configArray = $this->_modelsConfig;)

This is it without my shippingprotectiontax entry:

This is it with my shippingprotectiontax entry:

I do not see any clear contradictions.

EDIT3:

Config array just before uasort:

array (
  'nominal' => 
  array (
    'class' => 'sales/quote_address_total_nominal',
    'before' => 
    array (
      0 => 'subtotal',
      1 => 'grand_total',
    ),
    'renderer' => 'checkout/total_nominal',
    'after' => 
    array (
    ),
    '_code' => 'nominal',
  ),
  'subtotal' => 
  array (
    'class' => 'sales/quote_address_total_subtotal',
    'after' => 
    array (
      0 => 'nominal',
    ),
    'before' => 
    array (
      0 => 'grand_total',
      1 => 'shipping',
      2 => 'freeshipping',
      3 => 'tax_subtotal',
      4 => 'discount',
      5 => 'tax',
      6 => 'weee',
      7 => 'giftwrapping',
      8 => 'cashondelivery',
      9 => 'cashondelivery_tax',
      10 => 'shippingprotection',
      11 => 'shippingprotectiontax',
    ),
    'renderer' => 'tax/checkout_subtotal',
    'admin_renderer' => 'adminhtml/sales_order_create_totals_subtotal',
    '_code' => 'subtotal',
  ),
  'shipping' => 
  array (
    'class' => 'sales/quote_address_total_shipping',
    'after' => 
    array (
      0 => 'subtotal',
      1 => 'freeshipping',
      2 => 'tax_subtotal',
      3 => 'nominal',
    ),
    'before' => 
    array (
      0 => 'grand_total',
      1 => 'discount',
      2 => 'tax_shipping',
      3 => 'tax',
      4 => 'cashondelivery',
      5 => 'cashondelivery_tax',
      6 => 'shippingprotection',
      7 => 'shippingprotectiontax',
    ),
    'renderer' => 'tax/checkout_shipping',
    'admin_renderer' => 'adminhtml/sales_order_create_totals_shipping',
    '_code' => 'shipping',
  ),
  'grand_total' => 
  array (
    'class' => 'sales/quote_address_total_grand',
    'after' => 
    array (
      0 => 'subtotal',
      1 => 'nominal',
      2 => 'shipping',
      3 => 'freeshipping',
      4 => 'tax_subtotal',
      5 => 'discount',
      6 => 'tax',
      7 => 'tax_giftwrapping',
      8 => 'cashondelivery',
      9 => 'cashondelivery_tax',
      10 => 'shippingprotection',
      11 => 'shippingprotectiontax',
    ),
    'renderer' => 'tax/checkout_grandtotal',
    'admin_renderer' => 'adminhtml/sales_order_create_totals_grandtotal',
    'before' => 
    array (
      0 => 'customerbalance',
      1 => 'giftcardaccount',
      2 => 'reward',
    ),
    '_code' => 'grand_total',
  ),
  'freeshipping' => 
  array (
    'class' => 'salesrule/quote_freeshipping',
    'after' => 
    array (
      0 => 'subtotal',
      1 => 'nominal',
    ),
    'before' => 
    array (
      0 => 'tax_subtotal',
      1 => 'shipping',
      2 => 'grand_total',
      3 => 'tax',
      4 => 'discount',
    ),
    '_code' => 'freeshipping',
  ),
  'discount' => 
  array (
    'class' => 'salesrule/quote_discount',
    'after' => 
    array (
      0 => 'subtotal',
      1 => 'shipping',
      2 => 'nominal',
      3 => 'freeshipping',
      4 => 'tax_subtotal',
      5 => 'tax_shipping',
      6 => 'weee',
    ),
    'before' => 
    array (
      0 => 'grand_total',
      1 => 'tax',
      2 => 'customerbalance',
      3 => 'giftcardaccount',
      4 => 'reward',
      5 => 'cashondelivery',
      6 => 'cashondelivery_tax',
      7 => 'shippingprotection',
      8 => 'shippingprotectiontax',
    ),
    'renderer' => 'tax/checkout_discount',
    'admin_renderer' => 'adminhtml/sales_order_create_totals_discount',
    '_code' => 'discount',
  ),
  'tax_subtotal' => 
  array (
    'class' => 'tax/sales_total_quote_subtotal',
    'after' => 
    array (
      0 => 'freeshipping',
      1 => 'subtotal',
      2 => 'subtotal',
      3 => 'nominal',
    ),
    'before' => 
    array (
      0 => 'tax',
      1 => 'discount',
      2 => 'shipping',
      3 => 'grand_total',
      4 => 'weee',
      5 => 'customerbalance',
      6 => 'giftcardaccount',
      7 => 'reward',
    ),
    '_code' => 'tax_subtotal',
  ),
  'tax_shipping' => 
  array (
    'class' => 'tax/sales_total_quote_shipping',
    'after' => 
    array (
      0 => 'shipping',
      1 => 'subtotal',
      2 => 'freeshipping',
      3 => 'tax_subtotal',
      4 => 'nominal',
    ),
    'before' => 
    array (
      0 => 'tax',
      1 => 'discount',
      2 => 'grand_total',
      3 => 'grand_total',
    ),
    '_code' => 'tax_shipping',
  ),
  'tax' => 
  array (
    'class' => 'tax/sales_total_quote_tax',
    'after' => 
    array (
      0 => 'subtotal',
      1 => 'shipping',
      2 => 'discount',
      3 => 'tax_subtotal',
      4 => 'freeshipping',
      5 => 'tax_shipping',
      6 => 'nominal',
      7 => 'weee',
      8 => 'cashondelivery',
      9 => 'shippingprotection',
    ),
    'before' => 
    array (
      0 => 'grand_total',
      1 => 'customerbalance',
      2 => 'giftcardaccount',
      3 => 'tax_giftwrapping',
      4 => 'reward',
      5 => 'cashondelivery_tax',
      6 => 'shippingprotectiontax',
    ),
    'renderer' => 'tax/checkout_tax',
    'admin_renderer' => 'adminhtml/sales_order_create_totals_tax',
    '_code' => 'tax',
  ),
  'weee' => 
  array (
    'class' => 'weee/total_quote_weee',
    'after' => 
    array (
      0 => 'subtotal',
      1 => 'tax_subtotal',
      2 => 'nominal',
      3 => 'freeshipping',
      4 => 'subtotal',
      5 => 'subtotal',
      6 => 'nominal',
    ),
    'before' => 
    array (
      0 => 'tax',
      1 => 'discount',
      2 => 'grand_total',
      3 => 'grand_total',
      4 => 'tax',
    ),
    '_code' => 'weee',
  ),
  'customerbalance' => 
  array (
    'class' => 'enterprise_customerbalance/total_quote_customerbalance',
    'after' => 
    array (
      0 => 'wee',
      1 => 'discount',
      2 => 'tax',
      3 => 'tax_subtotal',
      4 => 'grand_total',
      5 => 'reward',
      6 => 'giftcardaccount',
      7 => 'subtotal',
      8 => 'shipping',
      9 => 'nominal',
      10 => 'freeshipping',
      11 => 'tax_shipping',
      12 => 'weee',
    ),
    'renderer' => 'enterprise_customerbalance/checkout_total',
    'before' => 
    array (
    ),
    '_code' => 'customerbalance',
  ),
  'giftcardaccount' => 
  array (
    'class' => 'enterprise_giftcardaccount/total_quote_giftcardaccount',
    'after' => 
    array (
      0 => 'wee',
      1 => 'discount',
      2 => 'tax',
      3 => 'tax_subtotal',
      4 => 'grand_total',
      5 => 'reward',
      6 => 'subtotal',
      7 => 'shipping',
      8 => 'nominal',
      9 => 'freeshipping',
      11 => 'tax_shipping',
      12 => 'weee',
    ),
    'before' => 
    array (
      0 => 'customerbalance',
    ),
    'renderer' => 'enterprise_giftcardaccount/checkout_cart_total',
    '_code' => 'giftcardaccount',
  ),
  'giftwrapping' => 
  array (
    'class' => 'enterprise_giftwrapping/total_quote_giftwrapping',
    'after' => 
    array (
      0 => 'subtotal',
      1 => 'nominal',
    ),
    'renderer' => 'enterprise_giftwrapping/checkout_totals',
    'before' => 
    array (
    ),
    '_code' => 'giftwrapping',
  ),
  'tax_giftwrapping' => 
  array (
    'class' => 'enterprise_giftwrapping/total_quote_tax_giftwrapping',
    'after' => 
    array (
      0 => 'tax',
      1 => 'subtotal',
      2 => 'shipping',
      3 => 'discount',
      4 => 'tax_subtotal',
      5 => 'freeshipping',
      6 => 'tax_shipping',
      7 => 'nominal',
      8 => 'weee',
    ),
    'before' => 
    array (
      0 => 'grand_total',
      1 => 'customerbalance',
      2 => 'giftcardaccount',
    ),
    '_code' => 'tax_giftwrapping',
  ),
  'reward' => 
  array (
    'class' => 'enterprise_reward/total_quote_reward',
    'after' => 
    array (
      0 => 'wee',
      1 => 'discount',
      2 => 'tax',
      3 => 'tax_subtotal',
      4 => 'grand_total',
      5 => 'subtotal',
      6 => 'shipping',
      7 => 'nominal',
      8 => 'freeshipping',
      9 => 'tax_subtotal',
      10 => 'tax_shipping',
      11 => 'weee',
      12 => 'subtotal',
      13 => 'shipping',
      14 => 'discount',
      15 => 'tax_subtotal',
      16 => 'freeshipping',
      17 => 'tax_shipping',
      18 => 'nominal',
      19 => 'weee',
      20 => 'freeshipping',
      21 => 'subtotal',
      22 => 'subtotal',
      23 => 'nominal',
      24 => 'subtotal',
      25 => 'nominal',
      26 => 'shipping',
      27 => 'freeshipping',
      28 => 'tax_subtotal',
      29 => 'discount',
      30 => 'tax',
      31 => 'tax_giftwrapping',
    ),
    'before' => 
    array (
      0 => 'giftcardaccount',
      1 => 'customerbalance',
      2 => 'customerbalance',
    ),
    'renderer' => 'enterprise_reward/checkout_total',
    '_code' => 'reward',
  ),
  'cashondelivery' => 
  array (
    'class' => 'cashondelivery/quote_total',
    'after' => 
    array (
      0 => 'subtotal',
      1 => 'discount',
      2 => 'shipping',
      3 => 'nominal',
      4 => 'subtotal',
      5 => 'shipping',
      6 => 'nominal',
      7 => 'freeshipping',
      8 => 'tax_subtotal',
      9 => 'tax_shipping',
      10 => 'weee',
      11 => 'subtotal',
      12 => 'freeshipping',
      13 => 'tax_subtotal',
      14 => 'nominal',
    ),
    'before' => 
    array (
      0 => 'tax',
      1 => 'grand_total',
      2 => 'grand_total',
      3 => 'customerbalance',
      4 => 'giftcardaccount',
      5 => 'tax_giftwrapping',
      6 => 'reward',
      7 => 'customerbalance',
      8 => 'giftcardaccount',
      9 => 'reward',
    ),
    'renderer' => 'cashondelivery/checkout_cod',
    'admin_renderer' => 'cashondelivery/adminhtml_sales_order_create_totals_cod',
    '_code' => 'cashondelivery',
  ),
  'cashondelivery_tax' => 
  array (
    'class' => 'cashondelivery/quote_taxTotal',
    'after' => 
    array (
      0 => 'subtotal',
      1 => 'discount',
      2 => 'shipping',
      3 => 'tax',
      4 => 'nominal',
      5 => 'subtotal',
      6 => 'shipping',
      7 => 'nominal',
      8 => 'freeshipping',
      9 => 'tax_subtotal',
      10 => 'tax_shipping',
      11 => 'weee',
      12 => 'subtotal',
      13 => 'freeshipping',
      14 => 'tax_subtotal',
      15 => 'nominal',
      16 => 'subtotal',
      17 => 'shipping',
      18 => 'discount',
      19 => 'tax_subtotal',
      20 => 'freeshipping',
      21 => 'tax_shipping',
      22 => 'nominal',
      23 => 'weee',
      24 => 'cashondelivery',
    ),
    'before' => 
    array (
      0 => 'grand_total',
      1 => 'customerbalance',
      2 => 'giftcardaccount',
      3 => 'reward',
    ),
    '_code' => 'cashondelivery_tax',
  ),
  'shippingprotection' => 
  array (
    'class' => 'n98_shippingprotection/quote_address_total_shippingprotection',
    'after' => 
    array (
      0 => 'subtotal',
      1 => 'discount',
      2 => 'shipping',
      3 => 'nominal',
      4 => 'subtotal',
      5 => 'shipping',
      6 => 'nominal',
      7 => 'freeshipping',
      8 => 'tax_subtotal',
      9 => 'tax_shipping',
      10 => 'weee',
      11 => 'subtotal',
      12 => 'freeshipping',
      13 => 'tax_subtotal',
      14 => 'nominal',
    ),
    'before' => 
    array (
      0 => 'tax',
      1 => 'grand_total',
      2 => 'grand_total',
      3 => 'customerbalance',
      4 => 'giftcardaccount',
      5 => 'tax_giftwrapping',
      6 => 'reward',
      7 => 'cashondelivery_tax',
      8 => 'customerbalance',
      9 => 'giftcardaccount',
      10 => 'reward',
    ),
    '_code' => 'shippingprotection',
  ),
  'shippingprotectiontax' => 
  array (
    'class' => 'n98_shippingprotection/quote_address_total_shippingprotectionTax',
    'after' => 
    array (
      0 => 'subtotal',
      1 => 'discount',
      2 => 'shipping',
      3 => 'tax',
      4 => 'nominal',
      5 => 'subtotal',
      6 => 'shipping',
      7 => 'nominal',
      8 => 'freeshipping',
      9 => 'tax_subtotal',
      10 => 'tax_shipping',
      11 => 'weee',
      12 => 'subtotal',
      13 => 'freeshipping',
      14 => 'tax_subtotal',
      15 => 'nominal',
      16 => 'subtotal',
      17 => 'shipping',
      18 => 'discount',
      19 => 'tax_subtotal',
      20 => 'freeshipping',
      21 => 'tax_shipping',
      22 => 'nominal',
      23 => 'weee',
      24 => 'cashondelivery',
      25 => 'shippingprotection',
    ),
    'before' => 
    array (
      0 => 'grand_total',
      1 => 'customerbalance',
      2 => 'giftcardaccount',
      3 => 'reward',
    ),
    '_code' => 'shippingprotectiontax',
  ),
)


Update: Magento Bug Ticket: https://jira.magento.com/browse/MCACE-129

解決方案

So finally, here is my patch for this issue.

It implements topological sorting as suggested by Vinai.

  1. Copy app/code/core/Mage/Sales/Model/Config/Ordered.php to app/code/local/Mage/Sales/Model/Config/Ordered.php
  2. Save the contents of the patch to a file total-sorting.patch and call patch -p0 app/code/local/Mage/Sales/Model/Config/Ordered.php

In case of upgrades make sure to re-apply these steps.

The patch is tested to work with Magento 1.7.0.2

--- app/code/core/Mage/Sales/Model/Config/Ordered.php   2012-08-14 14:19:50.306504947 +0200
+++ app/code/local/Mage/Sales/Model/Config/Ordered.php  2012-08-15 10:00:47.027003404 +0200
@@ -121,6 +121,78 @@
         return $totalConfig;
     }

+// [PATCHED CODE BEGIN]
+
+    /**
+     * Topological sort
+     *
+     * Copyright: http://www.calcatraz.com/blog/php-topological-sort-function-384
+     * And fix see comment on http://stackoverflow.com/questions/11953021/topological-sorting-in-php
+     *
+     * @param $nodeids Node Ids
+     * @param $edges Array of Edges. Each edge is specified as an array with two elements: The source and destination node of the edge
+     * @return array|null
+     */
+    function topological_sort($nodeids, $edges) {
+        $L = $S = $nodes = array();
+        foreach($nodeids as $id) {
+            $nodes[$id] = array('in'=>array(), 'out'=>array());
+            foreach($edges as $e) {
+                if ($id==$e[0]) { $nodes[$id]['out'][]=$e[1]; }
+                if ($id==$e[1]) { $nodes[$id]['in'][]=$e[0]; }
+            }
+        }
+        foreach ($nodes as $id=>$n) { if (empty($n['in'])) $S[]=$id; }
+        while ($id = array_shift($S)) {
+            if (!in_array($id, $L)) {
+                $L[] = $id;
+                foreach($nodes[$id]['out'] as $m) {
+                    $nodes[$m]['in'] = array_diff($nodes[$m]['in'], array($id));
+                    if (empty($nodes[$m]['in'])) { $S[] = $m; }
+                }
+                $nodes[$id]['out'] = array();
+            }
+        }
+        foreach($nodes as $n) {
+            if (!empty($n['in']) or !empty($n['out'])) {
+                return null; // not sortable as graph is cyclic
+            }
+        }
+        return $L;
+    }
+
+    /**
+     * Sort config array
+     *
+     * public to be easily accessable by test
+     *
+     * @param $configArray
+     * @return array
+     */
+    public function _topSortConfigArray($configArray)
+    {
+        $nodes = array_keys($configArray);
+        $edges = array();
+
+        foreach ($configArray as $code => $data) {
+            $_code = $data['_code'];
+            if (!isset($configArray[$_code])) continue;
+            foreach ($data['before'] as $beforeCode) {
+                if (!isset($configArray[$beforeCode])) continue;
+                $edges[] = array($_code, $beforeCode);
+            }
+
+            foreach ($data['after'] as $afterCode) {
+                if (!isset($configArray[$afterCode])) continue;
+                $edges[] = array($afterCode, $_code);
+            }
+        }
+        return $this->topological_sort($nodes, $edges);
+    }
+
+// [PATCHED CODE END]
+
+
     /**
      * Aggregate before/after information from all items and sort totals based on this data
      *
@@ -138,38 +210,16 @@
         // invoke simple sorting if the first element contains the "sort_order" key
         reset($configArray);
         $element = current($configArray);
+        // [PATCHED CODE BEGIN]
         if (isset($element['sort_order'])) {
             uasort($configArray, array($this, '_compareSortOrder'));
+            $sortedCollectors = array_keys($configArray);
+
         } else {
-            foreach ($configArray as $code => $data) {
-                foreach ($data['before'] as $beforeCode) {
-                    if (!isset($configArray[$beforeCode])) {
-                        continue;
-                    }
-                    $configArray[$code]['before'] = array_unique(array_merge(
-                        $configArray[$code]['before'], $configArray[$beforeCode]['before']
-                    ));
-                    $configArray[$beforeCode]['after'] = array_merge(
-                        $configArray[$beforeCode]['after'], array($code), $data['after']
-                    );
-                    $configArray[$beforeCode]['after'] = array_unique($configArray[$beforeCode]['after']);
-                }
-                foreach ($data['after'] as $afterCode) {
-                    if (!isset($configArray[$afterCode])) {
-                        continue;
-                    }
-                    $configArray[$code]['after'] = array_unique(array_merge(
-                        $configArray[$code]['after'], $configArray[$afterCode]['after']
-                    ));
-                    $configArray[$afterCode]['before'] = array_merge(
-                        $configArray[$afterCode]['before'], array($code), $data['before']
-                    );
-                    $configArray[$afterCode]['before'] = array_unique($configArray[$afterCode]['before']);
-                }
-            }
-            uasort($configArray, array($this, '_compareTotals'));
+            $sortedCollectors = $this->_topSortConfigArray($configArray);
         }
-        $sortedCollectors = array_keys($configArray);
+        // [PATCHED CODE END]
+
         if (Mage::app()->useCache('config')) {
             Mage::app()->saveCache(serialize($sortedCollectors), $this->_collectorsCacheKey, array(
                     Mage_Core_Model_Config::CACHE_TAG
@@ -196,27 +246,6 @@
     }

     /**
-     * Callback that uses after/before for comparison
-     *
-     * @param   array $a
-     * @param   array $b
-     * @return  int
-     */
-    protected function _compareTotals($a, $b)
-    {
-        $aCode = $a['_code'];
-        $bCode = $b['_code'];
-        if (in_array($aCode, $b['after']) || in_array($bCode, $a['before'])) {
-            $res = -1;
-        } elseif (in_array($bCode, $a['after']) || in_array($aCode, $b['before'])) {
-            $res = 1;
-        } else {
-            $res = 0;
-        }
-        return $res;
-    }
-
-    /**
      * Callback that uses sort_order for comparison
      *
      * @param array $a

EDIT: There is also another suggested change (for Magento 2): https://github.com/magento/magento2/pull/49

這篇關(guān)于排序算法:Magento 結(jié)帳總額排序錯誤導(dǎo)致運費計算錯誤的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網(wǎng)!

【網(wǎng)站聲明】本站部分內(nèi)容來源于互聯(lián)網(wǎng),旨在幫助大家更快的解決問題,如果有圖片或者內(nèi)容侵犯了您的權(quán)益,請聯(lián)系我們刪除處理,感謝您的支持!

相關(guān)文檔推薦

Override Magento Config(覆蓋 Magento 配置)
What would cause a print_r and/or a var_dump to fail debugging a variable?(什么會導(dǎo)致 print_r 和/或 var_dump 調(diào)試變量失敗?)
How to update custom options programatically in magento?(如何在 magento 中以編程方式更新自定義選項?)
Magento 404 on Admin Page(管理頁面上的 Magento 404)
Magento - get price rules from order(Magento - 從訂單中獲取價格規(guī)則)
Magento Change Product Page Titles to Include Attributes(Magento 更改產(chǎn)品頁面標題以包含屬性)
主站蜘蛛池模板: 欧美成年网站 | 亚洲成人日韩 | 成人网av | 成人国产在线视频 | 国产精品视频久久久久久 | 国产999精品久久久 午夜天堂精品久久久久 | 亚洲先锋影音 | 91九色在线观看 | 亚洲 中文 欧美 日韩 在线观看 | 高清一区二区三区 | 久亚州在线播放 | 久在线精品视频 | 日日夜夜精品视频 | 精品国产91乱码一区二区三区 | 精品三级在线观看 | 国产激情视频网 | 久久综合入口 | xx视频在线| 亚洲精品第一 | 自拍偷拍亚洲欧美 | 日韩一区中文字幕 | 干干天天 | av官网在线| 日韩免费一区二区 | 国产亚洲一区二区三区在线 | 亚洲第一成年免费网站 | 国内久久| 国产精品国产成人国产三级 | 国产精品视频不卡 | 在线观看精品 | 国产精品久久久久久久久久免费看 | 国产精品国产三级国产aⅴ中文 | 国内精品久久久久久 | 中文字幕久久精品 | 国产精品免费一区二区 | 色黄视频在线 | 一区二区三区视频在线观看 | 国产精品久久久久一区二区三区 | 免费在线观看一区二区 | 剑来高清在线观看 | www国产精|