订购/开具发票的最佳做法:存储净值/毛额/增值税还是计算?

时间:2018-07-13 16:56:57

标签: sql sql-server database data-structures database-design

我希望有人可以对此提供帮助。

我正在更新订购/发货和发票系统。

我有一个OrderItem表,其中包含以下内容(为方便起见,已将其截断):

  • OrderItemId(PK)
  • OrderId
  • ProductId
  • 单价
  • 数量
  • VatCodeId(FK)

根据需要计算净值,毛额,总计和增值税字段。

我一直使用这种方法,但现在我认为值应该存储在OrderItemTable中,如下所示:

  • OrderItemId(PK)
  • OrderId
  • ProductId
  • UnitNet
  • UnitVat
  • UnitGross
  • LineNet
  • LineVat
  • LineGross
  • 数量
  • VatCodeId(FK)

我意识到此表现在尚未规范化,但在与该领域的某个人交谈时,他们已经非常成功地说服我,这是历史数据,应永远不要更改,因此应将其存储在发布时间。我倾向于相信他们。

从性能角度来看,我认为这两种方式都不会带来太大变化,但可能会使报告工作变得更加轻松。

我可以厚颜无耻地问你们中的一些专家您的意见吗?

与往常一样,非常感谢!

4 个答案:

答案 0 :(得分:1)

强烈建议存储所有字段的计算值,因为税率和计算方式会发生变化。包括净额,毛额,增值税和总额。原因是因为计算可能随时更改。

例如,今天想象一下税率是10%。您以10美元的价格出售10个单位。因此,毛额为$ 100。您计算税款,减去10%,现在的净值为$ 90。

但是从现在开始的两年后,税率升至13%。您是否要修改报告程序,以使它们对旧交易的税款计算方式有所不同?过去已经做到这一点,我敢打赌,您在某个地方弄错了。您将不得不更改数十个或数百个报告程序。您一定会错过其中的一些,并且在中找不到所有这些。减轻您的头痛:存储所需的一切。不必依赖于明天计算今天计算出的事物的能力。

还请注意,汇率以外的其他情况可能会发生变化。他们可能会更改哪些项目应课税。他们可能会增加分级税率,或者让您计算两种不同的税率,或者……相信我,很多不同的事情都会改变。在美国,汽油的税率计算会让您旋转,联邦,州,县,市等的税率也不同。有时,税率取决于您库存的燃料存放了多长时间以及在哪里运输从哪里,您将其运送到哪里,以及(我不是在开玩笑)要在一周中的哪一天交付它。太疯狂了!

某些产品的税率和计算经常会令人痛苦地变化。您可以尝试保留历史税率数据,以便可以重新计算以前的交易的税费,但是保存您当时计算的内容要容易得多且可靠得多。

答案 1 :(得分:0)

因此,这将取决于其他一些因素。

这是新环境还是已经运行了一段时间的环境?改变当前正在使用的数据库设计令人头疼。如果OrderItem表是入站业务流程的关键部分,则尤其如此。

如果我们在没有用户或数据的新数据库环境中,那么我可以安全地进行更改。但是,我们还应该问,这种“历史数据”将来是否有可能成为“活动数据”。

如果这是一个活动的数据库,那么我们需要一个充分的理由来解决用已关联的数据更改表模式的麻烦。在当前的报告流程中,我们需要多久按一次VatCodeID(FK)?如果答案是“不是很经常”,那么我们可以通过保留原状来节省很多时间和金钱。

但是也许我们经常使用OrderItem,出于商业原因,将所有数据都放在一个平面表上会很好。然后,我们应该问,我可以少做些事,实现类似的性能提升吗?

由于我们检查了OrderItem在连接到VatCodeId所引用的内容时被查询的频率,因此我们可以查询这些查询,并查看它们是否可以进行优化。这可能涉及向OrderItemVatCodeId的引用添加索引,这在大多数时候还是比改变表结构更可取。

请记住,即使在altered表涉及并迁移了数据之后,您也可能不得不修复开发人员懒惰而又没有像以前那样的任何insert语句。像他们本来应该明确的那样。此外,如果OrderItem上的一条记录与表VatCodeId所引用的表上的多个记录相关联,那么我们可能还必须通过并修复从{{1 }}。

然后,您可能需要修改引用您已更改表的任何第三方报告软件,因为该报告软件通常还需要显式标注。

基本上,您的问题的答案是不,除非我们有充分的理由不这样做,否则我们应该保留该表不变。但是,如果我们确实有很好的理由,那么下一步就是要花费几个小时来研究我们需要做的所有其他事情才能使这项工作生效。

答案 2 :(得分:0)

由于其他张贴者指出的原因,我还将存储整个历史记录。但是,这是给您的一个想法:通过使用SqlServer的临时表,您可以设计查询以在交易日期时获取各种税收结构。数据库引擎提供了此功能,而SQL仅包含几个额外的关键字。我敢肯定,这种方法会吸引您的秩序感和正确性,但是显然有责任确保您适当地使用该功能(很容易忽略或忘记)。另一个缺点是。许多报表或ORM尚不本地支持,因此您可以使用更多的SQL或过程。

值得深思。您将不得不决定是否值得(我怀疑不是,但我不知道您的应用程序的详细信息)

答案 3 :(得分:0)

无论您做什么,都要让用户和客户端程序访问视图和存储过程,而不是基表。这样,您可以毫无问题地更改存储和计算内容。这是关系DBMS的关键功能之一。

请记住,如果引入冗余(通过存储“所有内容”)而不用限制对其进行控制,则 最终将导致数据不一致。规则属于数据库。

如果您的规则当前很简单(例如,VatCodeId确定增值税(并且如果增值税发生变化,则更改),UnitGross = UnitNet + UnitVat等),如果您避免冗余并仅存储最少的内容,则系统将是最简单,最可靠的系统。创建一个看起来就像您存储了所有内容的视图,然后将其用于报表,UI等,很简单。

如果规则随后发生更改,请更改基表(并使用简单的规则来填充新列),并重新定义视图和存储过程以解决表更改(最好不更改其标题/签名) )。这样可以避免您可能永远不需要的数据库架构复杂性。