使用moneyphp计算税金

问题描述 投票:0回答:2

我正在使用 moneyphp/money 类来存储货币值。然而,在计算所欠税款时,我遇到一个问题,计算出的税款是小数,而图书馆正在寻找整数值。

示例:

$invoiceTotal = new Money("155" new Currency("USD")); //$1.55
$taxRate= 0.065;
$invoiceTotalWithTax = $invoiceTotal->multiply($taxRate);
echo $invoiceTotalWithTax; //0.10 whereas actual value is 1.55*0.065 = 0.10075
$formatter = new DecimalMoneyFormatter();
$formatter->format($invoiceTotalWithTax); //will return $0.10

从上面的示例中,一些小数分值正在丢失。单独来看并不是很多,但如果我们在一个纳税期内处理几千张发票,最终征收的总税款将超过1美分。

  • 有没有办法用 Money 套餐来处理这些情况?
  • 如果没有,那么是否有另一个包可以处理这个问题?
php currency tax money-php
2个回答
11
投票

无耻插件:我不知道是否有办法使用

moneyphp/money
库来做到这一点,但这里是如何使用 brick/money 库处理这种情况(免责声明:我创作了它)。

您选择的选项将取决于您想要实现的目标。

选项 1:使用具有默认比例的 Money,向上或向下舍入

如果您需要货币默认比例的结果(

USD
为小数点后两位),并知道要应用哪种舍入,请使用此方法:

use Brick\Money\Money;
use Brick\Math\RoundingMode;

$invoiceTotal = Money::ofMinor('155', 'USD'); // USD 1.55
// or
$invoiceTotal = Money::of('1.55', 'USD');

$taxRate = '0.065'; // prefer strings over floats!

$totalWithTax = $invoiceTotal->multipliedBy($taxRate, RoundingMode::DOWN); // USD 0.10
$totalWithTax = $invoiceTotal->multipliedBy($taxRate, RoundingMode::UP); // USD 0.11

您有更多舍入模式可供选择。如果您不提供舍入模式,并且结果不适合小数点后两位,则会出现异常。

选项 2:使用具有自定义比例的 Money

如果您需要使用给定的精度,例如 5 位小数,您可以在创建 Money 时指定:

use Brick\Money\Money;
use Brick\Money\Context\CustomContext;
use Brick\Math\RoundingMode;

$invoiceTotal = Money::of('1.55', 'USD', new CustomContext(5)); // USD 1.55000
$taxRate = '0.065';

$totalWithTax = $invoiceTotal->multipliedBy($taxRate); // USD 0.10075

如果结果不能精确到小数点后 5 位,您需要提供

RoundingMode
,否则会出现异常。

选项 3:使用带有自动秤的 Money

使用此方法可以自动将结果的比例调整为正确的小数位数:

use Brick\Money\Money;
use Brick\Money\Context\AutoContext;
use Brick\Math\RoundingMode;

$invoiceTotal = Money::of('1.55', 'USD', new AutoContext()); // USD 1.55
$taxRate = '0.065';

$totalWithTax = $invoiceTotal->multipliedBy($taxRate); // USD 0.10075

不涉及舍入模式,但如果除法产生无限位数的十进制数,则会出现异常。

选项 4:使用 RationalMoney

A

RationalMoney
是一个货币对象,将其金额表示为有理数(分数)。当您需要链接多个操作且不进行舍入时,它特别有用:

use Brick\Money\Money;
use Brick\Math\RoundingMode;

$amount = Money::of('1.55', 'USD'); // USD 1.55
$amount = $amount->toRational(); // USD 155/100

$amount = $amount->dividedBy(3); // USD 155/300
$amount = $amount->dividedBy(7); // USD 155/2100

执行完所有操作后,您可以将最终数字转换为小数货币,必要时使用舍入模式:

use Brick\Money\Context\DefaultContext;
use Brick\Money\Context\CustomContext;

$amount->to(new DefaultContext(), RoundingMode::DOWN); // USD 0.07
$amount->to(new CustomContext(6), RoundingMode::DOWN); // USD 0.073809

最后的考虑因素

brick/money 包提供格式化、现金四舍五入、货币分配、货币转换等功能。它基于 brick/math 包,可以对任何规模的数字执行计算。尝试一下!


0
投票

无需担心舍入等的其他可能性是:

$grossTotalMoney = money(12345); // 123.45

list($net_total, $tax_total) = $grossTotalMoney->allocate([100 - $tax_percentage, $tax_percentage]);

https://www.moneyphp.org/en/stable/features/allocation.html

© www.soinside.com 2019 - 2024. All rights reserved.