计算外币含税价格的正确方法

Correct way to calculate prices including tax in foreign currencies

我正在尝试升级一个应用程序,以便可以将其销售到多个国家/地区。我将所有价格以英镑(不含税)存储在数据库中,最高 4dp,我需要计算以国家/地区货币含税的价格。

我是先用不含税价格乘以汇率(选项 1),还是先计算含税金额再乘以汇率(选项 2)?在查看了 OpenCart 如何计算它之后,我还添加了一个选项 3,它与选项 2 类似,但只在显示它时四舍五入。以下是所有 3 个选项的公式:

选项 1:

Round((Price * Exchange Rate) / 100 * (100 + Tax Rate))

选项 2:

Round(Round(Price / 100 * (100 + Tax Rate)) * Exchange Rate)

选项 3:

Round((Price / 100 * (100 + Tax Rate)) * Exchange Rate)

例如我有一个价格为 89.99 的产品。如果我想以汇率为 1.5 且税率为 20% 的货币显示它。我会说:

选项 1:

Round((89.99 * 1.5) / 100 * (100 + 20)) = 161.98

选项 2:

Round(Round(89.99 / 100 * (100 + 20)) * 1.5) = 161.99

选项 3:

Round((89.99 / 100 * (100 + 20)) * 1.5) = 161.98

我发现 OpenCart 最后总是将未四舍五入的数字乘以汇率。例如他们计算行总数的公式是:

Round((Price / 100 * (100 + Tax Rate)) * Quantity * Exchange Rate)

所以如果我要订购 3 个我的产品,它会给出:

Round((89.99 / 100 * (100 + 20)) * 3 * 1.5) = 485.95

我发现使用 OpenCart 的方式执行此操作的问题是用户将看到商品价格(含税)为 161.98 和一行总计 485.95。但是,如果我说 161.98 * 3,我会得到 485.94,所以它的总和不正确。

重要的是我做对了,因为你可以看到我最终会遇到一分钱的问题。如果有人可以让我知道哪种方式是正确的,或者如果 none 是正确的,我将不胜感激。谢谢

我不能告诉你正确的选项是什么,即使有一个正确的选项。但根据我的经验,我可以说,如果做一件事有多种选择,请在您的软件中对其进行配置。在这种情况下,您可以轻松使用 strategy pattern 并使计算价格的策略可配置。客户可以选择他们想要的计算方式。

正确的解决方案取决于您的业务。当您在不同的国家/地区销售商品时,您很可能在这些国家/地区设有分支机构 - 您需要以该国家/地区的货币计算的净价。这导致每件商品的净价 "translated" 外币,然后将此净价乘以金额并乘以税金 factor/percentage).

EU MOSS(当您在其他国家/地区提供服务或例如下载软件时收费)有些不同。您可以以英镑定价销售产品,但必须考虑消费者当地的税收因素。参见例如https://ec.europa.eu/taxation_customs/sites/taxation/files/resources/documents/taxation/vat/how_vat_works/telecom/one-stop-shop-guidelines_en.pdf

对于MOSS,我没有详细检查,但我希望你有一个不同的公式,使用你当地每件商品的英镑净价,乘以金额,乘以消费者的税率。我希望这个税额仍然以英镑为单位,然后应乘以货币汇率。

因为除 Exchange Rate 之外的所有变量都是四舍五入的,我希望它通常看起来像这样 1.3462,我们可以编写这样的测试:

// I'm guessing you need it in PHP
$price = 89.99;
$quantity = 1;
$tax = 20;
$tax = $tax/100.0 + 1;
// $tax = 1.2
$exchangeRate = 1.5;

$totalPrice = $price*$quantity*$tax;                     // Test #1
$totalPriceRounded = round($price*$quantity*$tax,2);     // Test #2

echo $totalPrice.'<br/>'.$totalPriceRounded;

会有这样的输出:

107.988   // Test #1 <--- This is amount that needs to be paid to you and Great Britain
107.99    // Test #2 <--- rounded

现在,金额上明显有区别,那么该选哪个呢?由于您从英国收取商品费用,因此您希望以英镑支付您要求的全额款项,所以让我们依靠这个因素。最后,如果我没理解错的话,客户要交的税是英国的税。

让我们检查外币的最终价格:

$totalPrice = round($totalPrice * $exchangeRate,2);
$totalPriceRounded = round($totalPriceRounded * $exchangeRate,2);

echo $totalPrice.'<br/>'.$totalPriceRounded;

会有这样的输出:

// Amount in foreign currency
161.98      // Test #1
161.99      // Test #2

综上所述,让我们检查一下当从外币计算回 GBP 时,其中哪一项会 return 您的值最接近 107.988 GBP

// To calculate the totalPrice back to price*tax*quantity in GBP
$totalPrice /= $exchangeRate;
$totalPriceRounded /= $exchangeRate;

echo $totalPrice.'<br/>'.$totalPriceRounded;

其输出为:

// totalPrice in GBP currency
107.98666666667       // Test #1
107.99333333333       // Test #2

当我们除以税收时:

$totalPrice /= $tax;
$totalPriceRounded /= $tax;

echo $totalPrice.'<br/>'.$totalPriceRounded;

输出为:

// the amount you get in GBP currency
89.988888888889    // End result of Test #1
89.994444444444    // End result of Test #2

因此,正如您所见,in this case,通过使用 round($price*$quantity*$tax*$exchangeRate, 2) 的基本数量,您获得的数量减少了,但是通过使用 round(round($price*$quantity*$tax,2)*$exchangeRate, 2),您获得的数量多了一点,再次四舍五入两者都给出相同的值。在其他一些情况下,差异可能与我们在这里得到的不同,也可能相反。

结论

  • 如果您有固定数量的产品,每个产品都带有 fixed prices,那么在时间。结果取决于每个产品的受欢迎程度和价格(即 round 函数会向上或向下舍入),以及您选择的计算方式。您可以根据产品受欢迎程度手动调整每个产品的价格,以最大限度地减少 loss/gain 随着时间的推移。

  • 如果您有 random prices 的产品,比如说您要租用 web servers,价格是 [=31=].01/second。那么你的 loss/gain 的期望值接近于零。购买的越多,它就越接近于零。因此,无论采用哪种方法,您都不会在这里丢失任何东西。一回赢一回输。

在我看来,我会将其标准化以将所有内容四舍五入:

$price = 4.47;
$quantity = 1.2    // lets say liters

// Even round the price before applying tax
$totalPrice = round($price * $quantity, 2);

因为如果您被迫显示所有不同的计算阶段,那么您将不得不舍入每一步。

但最精确的方法是使用它,因为丢失的信息最少:

// Round once at end
$totalPrice = round($price*$quantity*$tax*$exchangeRate, 2);

最终这完全取决于您如何设置产品价格或您的定价如何运作才能选择使用哪种方法。我会说这并不重要,我认为每个公司都只是选择最适合自己的。

在法律上,有些 countries/cities/etc。有关于如何计算这个的法律,你应该看看英国法律来检查你的问题的有效程序。