会计财务系统的工程原则

创建准确、可靠的基于软件的会计财务系统的最佳实践和原则。

在过去的几百年里,会计并没有太大的变化。尽管如此,人们对如何正确构建财务系统软件仍存在很多困惑。

在这篇文章中,我将分享我在大型科技公司从事财务系统工作多年所获得的经验教训。我们的重点是建立会计系统,但这些原则也适用于更一般的财务系统。

这篇文章将讨论以下内容

  1. 与职位相关的基本财务定义
  2. 会计系统的高级目标
  3. 实现这些目标的工程原理
  4. 最佳实践

定义

  • 总帐 (General Ledger :GL) :公司的主要会计记录,总结特定时间段内的所有财务交易。您可以将其视为其相应子分类帐的集合。
  • 子分类账(Sub-ledger):包含与特定 GL 相关的所有单个交易的详细信息。子分类账中的记录将比总分类账包含更详细的数据,例如特定客户是谁、订单中的特定项目等。子分类账和 GL 之间的数据差异取决于业务类型和您处理的数据量。一些小型企业可以完全不使用任何子分类账,但他们是否需要定制软件来管理规模如此小的事物值得怀疑。
  • 财务记录:指总账和明细账。
  • 重要性(Material):重要性是指财务报表中的信息错报是否会影响合理的利益相关者的决策陈述。请注意,此定义在设计上有些模糊,因为不同的企业具有不同的重要性阈值。例如,对于年收入 25 万美元的企业来说可能很重要的事情,对于年收入 10 亿美元的企业来说可能并不重要。从设计角度来看,此概念的主要价值在于对不同类别的财务数据进行分类。

目标
会计系统的三个主要目标是

  • (1)准确,
  • (2)可审计
  • (3)及时

准确
财务记录需要反映已知的业务状况。这个说法有点宽泛,需要一些解释:

如果我们销售 10 件售价 9.99 美元的产品,相应的财务记录必须总计 99.90 美元。这似乎很明显,但当您汇总数千(很多情况下是数百万)笔交易时,系统之间的简单求和或舍入误差可能会导致重大错误。

Wasteman 的注释:人们说命名是计算机科学中最难的问题,而我认为紧随其后的是加法。

过去几年,我一直在处理大型金融系统,我记不清最小的错误导致我们的数据出现巨大差异的次数。
另外

  • 不要让我一开始就使用浮点数求和
  • 我通过惨痛的经历学到了为什么应该始终使用整数。

财务记录也需要完整。更具体地说,分类账和总账都是在特定时间发生的所有业务活动的完整表示。
如果发生了某个事件但未记录在财务记录中,则系统不完整。
请注意,这并不意味着最终一致性不可接受。
您只需要知道您的数据何时会完整,以通知利益相关者数据已完成。

另一个令人惊讶的难题是保证完整性。随着系统规模的扩大,数据在许多系统之间跳跃,每次跳跃时数据都很容易意外改变或丢失。

可审计
与准确性密切相关的是,您的财务记录必须易于审计,以便利益相关者能够发现错误并准确衡量您的业务绩效。即使您不关心,国税局肯定关心。

及时
这一点完全取决于您的业务及其具体需求。小型企业只需在月底之前将所有数字全部转储即可,刚好可以及时结账。大型企业通常希望避免这种情况,并拥有近乎实时的系统。这使他们能够监控当月的财务状况,更快地根据财务数据做出决策,并减少在月初几天匆忙结账的现象。

但无论需求是什么,我们的会计系统都应该满足您的业务需求,以及及时性对它们意味着什么。


工程原理
您的会计系统应遵循的三个主要工程原则是

  1. 数据的不变性和持久性
  2. 数据应该以最小的粒度表示
  3. 代码应该是幂等的

不变且持久
这允许可审计性,从而有助于调试并进而提高准确性。当数据不可变时,您可以记录系统在任何给定时间的状态。这使得从以前的状态重新计算世界变得非常容易,因为没有状态会丢失。

此外,一旦数据被记录在财务记录中,它就不能被删除。对系统的任何更正都必须表示为新的财务交易。

例如:

  • 假设您的系统有一个错误,并意外地报告了一项服务的售价为 1000 美元,而实际价格应该是 900 美元。
  • 要纠正这个错误,您应该首先撤销与错误相对应的会计分录,然后重新记录正确金额的会计分录。

以最小粒度记录的数据
与上述原则类似,这对于实现清晰的审计线索也至关重要。尽管财务报告和总账是汇总的,但它们是根据更精细的事件计算出来的。当数据不合理时,您需要最精细的数据来调试可能存在的问题。

以最低粒度保存数据还可以非常轻松地更正从该数据集派生的数据。如果单个不可变数据集是该数据所有视图的核心事实来源,则要更正该视图,您只需在修复数据后重新运行创建该视图的管道即可。

同样,当会计准备结账时,他们会核对账户余额与发生的所有交易,以验证账簿是否准确。当发现差异时,您可以深入研究可能导致问题的确切交易

幂等性
每个财务事件只能处理一次,财务记录中的重复将导致明显的不准确性。因此,所有生成财务记录的代码都应该是幂等的。

最佳实践
多年来,我遇到了不少让我痛苦不堪的陷阱。以下是我推荐的最佳做法,可以避免我亲身遇到的诸多陷阱。

1、最好使用整数来表示财务金额。
这样算术就容易多了。某些小数表示是可以的,但要尽量避免使用浮点数。

2、财务金额的粒度应支持货币转换,同时将精度损失降至最低。
如果您只使用美元,那么用美分表示价值可能就足够了。如果您是一家全球性企业,则最好使用微位数或小数DECIMAL(19, 4)。小数选择在财务系统中非常流行,但微位数一直是广告财务系统的标准。这限制了在货币之间转换时精度的损失。

3、使用一致的舍入方法。
在规模上,舍入方式可能会导致预期金额之间出现重大差异。例如,

  • 一种舍入方法是将所有 5 及以上的值四舍五入到下一个有效数字,4 及以下则向下舍入。
  • 另一种有效方法是始终向上舍入。重要的是要始终保持一致。
当您处理数百万笔交易时,每笔交易 1 美分的偏差都可能导致重大差异。(1000 万笔交易中 1 美分的偏差会导致 10 万美元的差额)。这可能对您在这种规模上的业务并不重要,但对于政府来说,这足以因您少缴税款而追究您的责任。

如果您是一家全球性企业,那么在四舍五入和货币兑换方面可能会遇到很多问题。我甚至建议您应该创建一个集中式库/服务来处理四舍五入和货币兑换。不同的政府在计算税款时遵循不同的四舍五入规则,因此将所有这些细微差别抽象为单一服务将降低复杂性。

4、尽可能延迟货币兑换。
提前兑换货币可能会导致精度损失。请延迟货币兑换,直到以当地货币进行汇总之后再进行。

5、使用整数表示时间。
不同技术中有许多库可以将时间戳解析为对象,而且它们都以不同的方式执行。
避免这种麻烦,只需使用整数即可。

  • Unix 时间戳,甚至基于整数的 UTC 日期时间都可以正常工作。
  • 系统之间发生的数据转换越少越好。