Magento가 세금 계산시 반올림 델타를 저장하는 이유


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

그러나 델타는 저장합니다. 저장된 델타를 찾을 수 없으면 하나를 구성합니다. 왜? 내가 알 수 있듯이 tar는 동일한 작업으로 다른 결과를 초래합니다.

$price3.595가 있고 캐시가 없다고 가정 해 봅시다 $delta. 방법을 살펴보면 $ 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를 얻습니다. 다른 답변.

사용 된 모든 반올림 알고리즘은 동일한 인수로 실행될 때마다 적어도 동일한 대답을 제공해야하지만 이번에는 그렇지 않습니다.


BTW, 마 젠토 2.2.2에서 같은 오류가 발생
TheKitMurkit

답변:


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기본값으로 사용됩니다. 당신을 알아 차리기위한 것입니다. 마 젠토 팀이 당신의 의심을 지나치게들을 수 있습니다. 그들은 당신의 문제를 조용히 해결했습니다. :)

편집하다

이 기능을 실시간 예제에 적용하여이 기능의 사용을 분석해 보겠습니다. 과세 대상인 장바구니에 제품이 있다고 가정합니다. 구매할 수량은 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()메소드를 사용한다고 가정 하고이 함수는 실제로 제품 가격을 소수점 2 자리로 반올림합니다. 이와 함께 실제 가격과 반올림 가격의 차이 인 델타 값을 유지하면 나중에 반올림 가격을 계산하는 데 사용됩니다. 여기여기에 이미지 설명을 입력하십시오

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

즉, _deltaRound()방법이 실제로 세금 가격 반올림을 실제 세금 가격보다 더 정확하게 만듭니다. 언급 했듯이이 방법은 델타 값에 따라 다른 라운드 값을 반환합니다. 이 델타 값은 실제로 세금 반올림을보다 정확하게 만듭니다.

이에 따르면, 수량이 증가함에 따라이 방법을 채택하지 않으면 반올림 값과 실제 값 사이에 큰 차이가 생길 것이라고 결론을 내릴 수 있습니다. 그러나이 방법을 사용하면 반올림 값을 실제 값과 최대한 가깝게 만듭니다.

마 젠토는 기본적으로 소수점 이하 두 자리로 반올림됩니다. 이것은 소수점 이하 두 자리 반올림을 담당하는 방법입니다

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

4로 설정하면 반올림 정확도를 더욱 높일 수 있습니다.

참고 : 이것은 나의 개통과 개요입니다. 사실 일 수도 있고 아닐 수도 있습니다. 그러나 그것은 정확하고 논리적 인 것 같습니다.

감사.


나는 정말로 하드 코딩 된 2 in을 싫어한다roundPrice
David Manners

@DavidManners : 예 맞습니다. 그러나 마 젠토는 _deltaRound()일부 확장으로 어려움을 극복하기 위해 사용 합니다. 하드 코딩 방법. 어떤 경우에는 확실히 어려움을 겪을 것입니다
Rajeev K Tomy

1
github.com/OpenMage/magento-mirror/blob/magento-1.9/app/code/…를 보면 magento 1.9에서 기본값은 여전히 ​​0.0001이며, 배송에 대한 루팅 오류 iT 세금 계산 오류가 발생했습니다
ProxiBlue

2

정보

이전 라운딩 작업 델타를 기반으로하는 마젠 토의 라운드 가격.

app / code / core / Mage / Tax / Model / Sales / Total / Quote / Tax.php : 1392 app / code / core / Mage / Tax / Model / Sales / Total / Quote / Subtotal.php : 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);

두 파일 모두에서 변경해야합니다.

app / code / core / Mage / Tax / Model / Sales / Total / Quote / Tax.php : 1392 app / code / core / Mage / Tax / Model / Sales / Total / Quote / Subtotal.php : 719 : 앱

핵심 파일을 수정하거나 해킹하지 마십시오! 다시 작성하십시오!

이 솔루션은 Magento 1.9.x의 다른 버전에서 테스트되었지만 이전 버전에서는 작동 할 수 있습니다.

추신

roundPrice아래와 같이 변경 기능을 사용하면 반올림 오류 문제를 해결할 수 있지만 다른 오류가 발생할 수 있습니다 (예 : 일부 플랫폼에서는 소수점 이하 2 자리까지 반올림해야 함).

app / code / core / Mage / Core / Model / Store.php : 995

public function roundPrice($price)
{
    return round($price, 4);
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.