【问题标题】:Calculating tax correctly using Mysql and php使用 Mysql 和 php 正确计算税金
【发布时间】:2014-02-06 02:14:39
【问题描述】:

我正在尝试在将销售输入数据库后重新计算销售税。我可以在存储到数据库之前正确计算信息,但是由于舍入错误,从数据库中计算它以用于报告目的被证明很麻烦。

应用程序显示一个界面,允许用户添加项目并查看小计、税款和总计。

示例输入:

第 1 项:9.95

第 2 项:2.95

小计:12.90

税金(每个项目可能不同,但现在每个项目都相同)

2.900%:0.37

1.000%:0.13

1.100%:0.14

3.000%:0.39

税收总额:1.03

总计:13.93

我在存储到数据库之前计算税收的方式:

foreach Item as $price
{
  foreach Tax as $percent
  {
    $taxes[$percent]+=$price*($percent/100);
  }
}

foreach($taxes as $percent => $tax_amount)
{
  $taxes[$percent] = ROUND_TO_2_DECIMALS($tax_amount);
}

在计算完所有这些信息后,我将这些信息存储在数据库中,以便日后检索以进行报告。

示例架构:

phppos_sales_items
- sale_id
- item_id
- price

phppos_sales_items_taxes
- sale_id
- item_id
- tax_percent

phppos_sales_items 表的示例数据

sale_id:1,item_id:1,item_unit_price:9.95

sale_id:1,item_id:2,item_unit_price:2.95

phppos_sales_items_taxes 表的示例数据

sale_id:1,item_id:1,百分比:2.90

sale_id:1,item_id:1,百分比:1.00

sale_id:1,item_id:1,百分比:1.10

sale_id:1,item_id:1,百分比:3.00

sale_id:1,item_id:2,百分比:2.90

sale_id:1,item_id:2,百分比:1.00

sale_id:1,item_id:2,百分比:1.10

sale_id:1,item_id:2,百分比:3.00

计算销售税的示例查询

(SELECT SUM(tax) FROM (SELECT ROUND((item_unit_price)*(SUM(percent)/100),2) as tax
FROM phppos_sales_items
INNER JOIN phppos_sales_items_taxes USING (sale_id, item_id)
WHERE sale_id = 1
GROUP BY sale_id, item_id) as tax)

当我需要获取1.03 时,输出为1.04。此查询在大多数情况下都有效,但在出现舍入问题时会失败很多。

我需要能够使用 sql 准确地生成摘要信息。我愿意接受有关如何在销售前和数据库中计算信息的任何建议。

【问题讨论】:

  • 最后是圆的。四舍五入您的总和,而不是分别计算每项税款。据我了解,税款是按最终金额缴纳的,因此只应四舍五入。否则,如果每个项目分别缴纳税款,那么您的查询是正确的。这是两个不同的公式,都不是错误的,取决于它在现实中是如何完成的。
  • 你认为我应该如何调整我的 php 逻辑呢?我的问题是物品可以有不同的税收,所以每件物品的税收都可以不同。
  • 您在插入数据库时​​将其四舍五入。如果将其四舍五入,则无法恢复它。您可以做的是不四舍五入地存储它。
  • 再想一想,或者,根本不要从数据库中读取四舍五入的税款。您可以使用原始价格重新计算税金,这些价格以及百分比也应该在数据库中。
  • 我没有在数据库中存储任何四舍五入的值,只是原始价格和税率。

标签: php mysql


【解决方案1】:

好的,所以,你的问题,据我所知,它与编程没有太大关系。

所以,您有一件价值 1 美元的物品。现在,你有两种税,一种是 1.4%,另一种是 1.3%。现在,这就是你正在做的事情

tax1 = round($1*0.014, 2) = $0.01
tax2 = round($1*0.013, 2) = $0.01
totaltax = $0.02

到目前为止一切顺利...好吧,但现在让我们换个方式。如果我们把税加起来,我们应该支付1.4 + 1.3 = 2.7%的总和,这意味着:

totaltax = round($1*0.027, 2) = $0.03

看看这里发生了什么?

现在,这些方法中哪一种是正确的?如果您在物理上需要与 tax2 分开支付 tax1,那么它们中的每一个都以美分量化,第一种方式是正确的。但是,我觉得您很可能只支付最终的总税,即您先将百分比相加,计算您的税,然后将其支付到最接近的一分钱。


相对于您的代码,您应该得到 1.03,没错,但是您的查询犯了与第一个变体类似的错误,即在将每个项目的结果相加之前对其进行四舍五入(它正在执行round(price1*tax1, 2) + round(price2*tax2, 2))。 (实际上,为了完整起见,您需要四舍五入三个位置:个人税级、项目级和总级。)

要在末尾舍入而不是对每个项目进行舍入,请移出您的ROUND

(SELECT ROUND(SUM(tax),2) FROM (SELECT (item_unit_price)*(SUM(percent)/100) as tax
FROM phppos_sales_items
INNER JOIN phppos_sales_items_taxes USING (sale_id, item_id)
WHERE sale_id = 1
GROUP BY sale_id, item_id) as tax)

【讨论】:

    【解决方案2】:

    很抱歉作为答案,因为注释无法正确显示代码。

    怎么样

    (SELECT ROUND(SUM(tax)/100,2) FROM (SELECT item_unit_price*SUM(percent) as tax
    FROM phppos_sales_items
    INNER JOIN phppos_sales_items_taxes USING (sale_id, item_id)
    WHERE sale_id = 1
    GROUP BY sale_id, item_id) as tax)
    

    您可以将表导出为 sql,以便我可以在本地尝试吗?如果没有什么太保密的话。

    【讨论】:

    • 我将 sql 结构简化了很多...有一个巨大的查询可以创建一个临时表并执行所有计算。如果您有兴趣帮助我,可以提供补偿以分析问题并提出解决方案。如果您查看我的 stackoverflow 个人资料,然后查看 --> 网站,我会列出一个电子邮件地址。由于预算有限,我不能提供太多东西,但我今天尝试修复它大约 5 个小时,但没有运气。它只发生在几个边缘情况......我修复了一个,它打破了另一个。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-12-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-17
    • 1970-01-01
    相关资源
    最近更新 更多