करों की गणना करते समय मैगेंटो एक गोल डेल्टा क्यों रखता है


14

मॉडल में tax/Sales_Total_Quote_Tax, एक विधि है _deltaRound()जो एक मूल्य को गोल करती है। यह एक छोटा डेल्टा जोड़ता है, 0.5 के चक्कर में नॉनडेर्मिनिस्टिक व्यवहार को रोकने के लिए।

/**
 * Round price based on previous rounding operation delta
 *
 * @param float $price
 * @param string $rate
 * @param bool $direction price including or excluding tax
 * @param string $type
 * @return float
 */
protected function _deltaRound($price, $rate, $direction, $type = 'regular')
{
    if ($price) {
        $rate = (string)$rate;
        $type = $type . $direction;
        // initialize the delta to a small number to avoid non-deterministic behavior with rounding of 0.5
        $delta = isset($this->_roundingDeltas[$type][$rate]) ? $this->_roundingDeltas[$type][$rate] : 0.000001;
        $price += $delta;
        $this->_roundingDeltas[$type][$rate] = $price - $this->_calculator->round($price);
        $price = $this->_calculator->round($price);
    }
    return $price;
}

लेकिन यह एक डेल्टा को संग्रहीत करता है। यदि उसे ऐसा संग्रहित डेल्टा नहीं मिल सकता है, तो यह एक को बना देता है। क्यों? टार के रूप में मैं बता सकता हूं, यह समान संचालन के साथ अलग-अलग परिणामों की ओर जाता है।

मान लें कि हमारे पास $price3.595 है, और हमारे पास कैश नहीं है $delta। जैसा कि हम विधि के माध्यम से जाते हैं, हम $ डेल्टा = 0.000001 प्राप्त करेंगे। फिर हमें $price= 3.595001 मिलता है , जो 3.60 तक पहुंच जाता है, इसलिए हमारे पास $delta-0.004999 का नया नंबर है। और हम 3.60 लौटाते हैं।

सिवाय अब हमारे पास एक डेल्टा है तो चलो इसे फिर से करते हैं, $price= 3.595 के साथ । $price= 3.595 - 0.004999 = 3.590001

जिसे अगर हम गोल करते हैं, तो हमें 3.59 मिलते हैं। अलग-अलग जवाब।

यह मुझे लगता है कि किसी भी राउंडिंग एल्गोरिथ्म का उपयोग कम से कम एक ही जवाब देना चाहिए हर बार एक ही तर्कों के साथ चलाया जाता है, लेकिन इस बार नहीं।


जवाबों:


9

मेरे पास मेरे सर्वर पर Magento 1.8 है और मैंने _deltaRound()विधि की जांच की है। अब ऐसा दिखता है।

/**
 * Round price based on previous rounding operation delta
 *
 * @param float $price
 * @param string $rate
 * @param bool $direction price including or excluding tax
 * @param string $type
 * @return float
 */
protected function _deltaRound($price, $rate, $direction, $type = 'regular')
{
    if ($price) {
        $rate  = (string) $rate;
        $type  = $type . $direction;
        $delta = isset($this->_roundingDeltas[$type][$rate]) ? $this->_roundingDeltas[$type][$rate] : 0;
        $price += $delta;
        $this->_roundingDeltas[$type][$rate] = $price - $this->_calculator->round($price);
        $price = $this->_calculator->round($price);
    }
    return $price;
}

जैसा कि आप देख सकते हैं, यदि _roundingDeltas()सेट नहीं किया गया है, तो यह zeroअपने डिफ़ॉल्ट मान के रूप में लेता है । यह सिर्फ आपको ध्यान देने के लिए है। Magento की टीम आपके संदेह को पलट सकती है। उन्होंने आपकी समस्या को चुपचाप हल किया। :)

संपादित करें

आइए हम इस फ़ंक्शन के उपयोग को वास्तविक समय उदाहरण में लागू करके विश्लेषण करें। मान लीजिए मेरे पास कार्ट में एक उत्पाद है जो कर योग्य है। मैं जो मात्रा खरीदने जा रहा हूं, 5. कर लगाने के बाद, प्रॉडक्ट की कीमत $ 10.5356 है। तो यह मेरी स्थिति है

CART
-------
   Product A
       - Price (including tax) - 10.5356
       - Quantity              - 5
       - Tax Rule  - Apply tax for each product. Then calculate the total price according to the quantity purchased.

तो अब हम इस स्थिति में उत्पन्न होने वाले वास्तविक मूल्य की गणना करते हैं। यह

  Total =  10.5356 x 5 = 52.678

अब हम मान लेते हैं, Magento _deltaRound()पद्धति का उपयोग नहीं करता है । यह सिर्फ दो दशमलव स्थानों तक उत्पाद की कीमत को गोल करता है और फिर कुल मूल्य की गणना करता है। इस मामले में, उत्पाद की कीमत पूरी हो जाएगी 10.54और इसलिए कुल कीमत होगी

  Total = 10.54 x 5 = 52.7

अब मान लेते हैं कि Magento _deltaRound()पद्धति का उपयोग कर रहा है और यह फ़ंक्शन वास्तव में उत्पाद की कीमत को दो दशमलव तक बढ़ाता है। इसके साथ ही यह एक डेल्टा मूल्य रखेगा, जो वास्तव में वास्तविक मूल्य और गोल कीमत के बीच का अंतर है, बाद में गोल कीमत की गणना के लिए उपयोग करेगा। यहाँयहाँ छवि विवरण दर्ज करें

  Total =  10.54+10.53+10.54+10.53+10.54 = 52.68

इसका मतलब है कि _deltaRound()विधि वास्तव में कर मूल्य को वास्तविक कर मूल्य निर्धारण के लिए अधिक सटीक बनाती है। जैसा कि आपने बताया कि यह विधि अलग-अलग गोल मान देती है, डेल्टा मान पर निर्भर करती है। यह डेल्टा मूल्य वास्तव में कर गोलाई को अधिक सटीक बनाता है।

इसके अनुसार, हम यह निष्कर्ष निकाल सकते हैं कि जैसे-जैसे मात्रा बढ़ती है, अगर हम इस पद्धति को नहीं अपना रहे हैं, तो यह गोल मूल्य और वास्तविक मूल्य के बीच एक बड़ा अंतर पैदा करेगा। लेकिन अगर हम इस पद्धति का उपयोग करते हैं, तो यह वास्तविक मूल्य के साथ हमारे गोल मूल्य को यथासंभव बंद कर देगा।

दो दशमलव स्थानों पर डिफ़ॉल्ट राउंड द्वारा Magento। यह वह विधि है जो गोलाई में दो दशमलव स्थानों के लिए जिम्मेदार है

Location :app/code/core/Mage/Core/Model/Store.php
public function roundPrice($price)
{
    return round($price, 2);
}

यदि हम इसे 4 या कुछ पर सेट करते हैं, तो हम गोलाई की सटीकता को और बढ़ा सकते हैं।

नोट: यह मेरा खुलापन और अवलोकन है। यह सच हो भी सकता है और नहीं भी। हालांकि यह मेरे लिए सटीक और तार्किक लगता है।

धन्यवाद।


मुझे वास्तव में हार्ड कोडेड 2 इनroundPrice
डेविड मैनर्स

@DavidManners: हां यह सही है। लेकिन Magento _deltaRound()कुछ विस्तार से कठिनाई को दूर करने के लिए उपयोग करता है। किसी भी तरह से इसकी हार्ड कोडिंग। यह निश्चित रूप से कुछ मामलों में कुछ कठिनाइयों को दूर कर देगा
राजीव के टॉमी

1
को देखते हुए github.com/OpenMage/magento-mirror/blob/magento-1.9/app/code/... Magento 1.9, जो है हमें शिपिंग पर कर calcualtions ith एक rouning त्रुटि हुई के लिए में अब भी 0.0001 डिफ़ॉल्ट मान है
ProxiBlue

2

जानकारी

पिछले गोलाई ऑपरेशन डेल्टा के आधार पर Magento में गोल मूल्य।

एप्लिकेशन / कोड / कोर / दाना / कर / मॉडल / बिक्री / कुल / बोली / कर.php: 1392 एप्लिकेशन / कोड / कोर / दाना / कर / मॉडल / बिक्री / कुल / उद्धरण / उप-योग: 719

protected function _deltaRound($price, $rate, $direction, $type = 'regular')
{
    if ($price) {
        $rate = (string)$rate;
        $type = $type . $direction;
        // initialize the delta to a small number to avoid non-deterministic behavior with rounding of 0.5
        $delta = isset($this->_roundingDeltas[$type][$rate]) ? $this->_roundingDeltas[$type][$rate] : 0.000001;
        $price += $delta;
        $this->_roundingDeltas[$type][$rate] = $price - $this->_calculator->round($price);
        $price = $this->_calculator->round($price);
    }
    return $price;
}

कभी-कभी उच्च डेल्टा गणना त्रुटि ( $this->_calculator->round($price)) के कारण यह त्रुटि हो सकती है । उदाहरण के लिए, इस कारण से, कुछ कीमतें । 1 प्रतिशत की सीमा में भिन्न हो सकती हैं ।

समाधान

इससे बचने के लिए, आपको डेल्टा गणना की सटीकता में सुधार करने की आवश्यकता है।

परिवर्तन

$this->_roundingDeltas[$type][$rate] = $price - $this->_calculator->round($price);

सेवा

$this->_roundingDeltas[$type][$rate] = $price - round($price, 4);

दोनों फ़ाइलों में परिवर्तन किए जाने की आवश्यकता है:

एप्लिकेशन / कोड / कोर / दाना / कर / मॉडल / बिक्री / कुल / बोली / कर.php: 1392 एप्लिकेशन / कोड / कोर / दाना / कर / मॉडल / बिक्री / कुल / उद्धरण / उप-योग: 719

कोर फ़ाइलों को संशोधित या हैक न करें! फिर से लिखना!

Magento 1.9.x के विभिन्न संस्करणों पर समाधान का परीक्षण किया गया था, लेकिन शायद यह पहले के संस्करणों में काम करेगा।

पुनश्च

परिवर्तन roundPriceफ़ंक्शन, जैसा कि नीचे दिखाया गया है, गोलाई त्रुटि की समस्या को हल कर सकता है, लेकिन यह दूसरों का कारण बन सकता है (उदाहरण के लिए, कुछ प्लेटफार्मों को 2 दशमलव स्थानों तक गोलाई की आवश्यकता होती है)।

एप्लिकेशन / कोड / कोर / दाना / कोर / मॉडल / Store.php: 995

public function roundPrice($price)
{
    return round($price, 4);
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.