设计用于保存财务记录的数据库时,需要哪些特殊注意事项?


15

我希望这个问题不会太广泛。将来,我可能需要向某些应用程序(主要是基于Web的应用程序,但我的问题也涉及台式机应用程序)中添加一些会计和财务跟踪系统。

现在,从理论上讲,创建金融交易的简单记录很容易。一个带有几列的数据库表可以完成这项工作。甚至MS Access,Excel,甚至只是纯ASCII文本文件都可以用于存储交易日期,帐户ID和美元金额。但是,我认为,即使是具有事务完整性的频繁备份的SQL表也可能不足以进行严重的财务跟踪。

我听到诸如“两次进入记帐”之类的术语,并且我感到大多数财务跟踪应用程序(例如Mint.com或GnuCash)都具有更复杂的数据结构或流程来确保一切完全合乎要求,完美地相加,并且不会丢失或破坏任何数据。

我的问题是:在设计用于跟踪财务交易的应用程序时,应考虑哪些特殊的设计注意事项?似乎可能存在很多潜在的问题...舍入精度,奇偶校验,某种审核过程,特殊备份,安全性/加密,在数据输入中间出现崩溃的情况下保护数据的其他方式等问题。 ...我真的不知道我应该具体询问什么,但是我感到编程行业有一些我一无所知的最佳实践。这些是什么?

编辑:

看来我打开了比预期更大的蠕虫罐。为了明确起见,我正在特别考虑两种类型的应用程序:

  1. “检查注册表”类型的应用程序(例如GnuCash或Quicken)会保留个人交易记录供自己使用。
  2. 跟踪与公司打交道的供应商和客户的发票/贷项/或“积分”的应用程序。

我可能不会进行任何直接银行业务或(AFAIK)附带大量与金融相关的政府法规的工作。


4
每次看到这个问题,我都会听到“让我把经验告诉你!”的念头。然后它消失了,因为庞大的数据量如此之大,以至于我不知道该从哪里开始。我要说的是,这取决于业务类型,业务量以及要处理的零个数。在后两种情况下,如果您要处理大量事务,请聘请会计师。
Satanicpuppy 2011年

3
为了减轻您的担心,“重复输入记帐”与应用程序必须具有的健壮性无关。该术语只是一种会计惯例,它表示,每当您针对一个帐户(例如现金)进行借记交易时,都需要与针对另一个帐户(例如库存)的信贷交易进行匹配。
Mike Clark

@Satanicpuppy-好吧,假设我想创建一个新的GnuCash?我在考虑基本的交易或发票注册。不像CC结算应用或股票交易应用。
约书亚·卡莫迪

@Joshua:请将此问题编辑为您的问题:“我在考虑基本交易或开具发票注册中心。没有CC计费应用程序或股票交易应用程序。” (您在问题结尾处提到了“金融服务”。会计和金融服务并不完全相同。)
rwong 2011年

2
@约书亚:金融服务受更多的政府法规约束,因此与股票交易系统相比,例如股票交易软件将有很多“特殊考虑”。税务软件也可能要遵守税务法规。
rwong 2011年

Answers:


10

我敢肯定,您会得到很多答案,我也有很多理想主义者的答案,我只能从我的财务经验以及实际情况中回答。

您已经涵盖了大多数问题。

根据我的经验,舍入精度实际上并不是什么大问题。并非一夜之间成长起来的大多数大型金融机构(即对冲基金以外的所有机构)都有大量的遗留应用程序,这些应用程序由于各种燃料而被拆分。它们往往不能始终如一地进行舍入精度。通常,将一定的误差损益简单地四舍五入。确实,在我工作过的地方,人们花费了很多工时,在匹配精确/期望的总和时,最终的“是足够接近”选择器。请记住,这是基于现实的答案,而不是应该发生的事情。

加密-不要坦率地依赖它。将识别数据存储在物理上和逻辑上独立于未识别数据的系统中(即,到处都有帐户代码,个人数据分开)。

通常,虽然需要备份,但很少调用脱机备份-那时出现了严重错误。通常需要热生产副本-但这取决于您自己的特定需求。通常,我们为所有系统提供现场热备份生产副本,以及具有自己的生产和热备份的灾难恢复站点。热拷贝通常在复制等方面落后几分钟。

审计是我工作过的每个财务系统的关键。您有两个基本要求:A)您可以跟踪对数据所做的每个更改,由谁,何时以及为什么进行吗?B)您可以证明数据的历史状态吗?没被篡改吗?

A)是运营团队所必需的–您的系统将以您从未想到的100种方式使用,并且此信息对于扩展,临时报告,法律原因和调试至关重要。

B)参见AMEX诉Vee Vinhnee案– AMEX未能追回欠他们的4万英镑,因为他们无法证明自己的记录没有被弥补。通常用于此目的的解决方案是可信时间戳。大型金融机构拥有保证交易的担保银行,从而固有地提供了可信赖的时间戳。有针对其他行业/场景的商业提供商。


6

这些考虑主要是合法的。如果仅从安全性/可靠性的角度来看,excel纸在本质上可能不会比某些抽屉中的纸安全性差。Access的事务完整性可能比被呼叫打扰的业务员更好。

但是,为了允许您的客户使用它,您必须遵守当地法律。我遇到的一些事情(在德国)

  • 存储的文档格式很重要,因为法律规定企业必须将其书面文件保存10年。在10年后,您的程序可能不再可用。因此,您必须以DIN / ISO认证的方式存储文档(.pdf在德国似乎就足够了)
  • 审计跟踪通常是必要的,例如,您可能必须提供同一文档的不同版本以及修改日期。
  • 由于“ Datenschutz”(隐私)的原因,存储位置很重要,在存储国家中可能有所不同。这使得基于云的服务有些棘手。
  • 有些文档必须以不可更改的方式存储。如何实现这一目标似乎主要取决于合法主义的挑剔(一张纸是一成不变的,一张CD是可变的,一张由工人签名的CD不是)

您应就具体细节最终联系律师,或至少与客户密切合作。


3

当您处理人们的金钱时,可靠性因素变得异常重要。如果Twitter失去了一条推文,那没什么大不了的;如果您从某人的信用卡中扣款,但是却丢失了订单,那么您组织中的某人就会从生气的客户那里得到帮助。所以有两件事:1.您不希望一开始就发生这种情况,但是2.无论您多么小心,它最终都会发生,因此您需要在记录和跟踪机制中投入大量精力这将帮助您返回并找到“丢失”的订单并纠正情况。

绝对最糟糕的事情是,例如,收取信用卡费用,但在所有用途或所属对象等方面均没有记录。

对于财务方面的东西,您确实确实需要考虑看似超级不可能的情况,并计划如何处理它们:“我们已从信用卡中扣款,但数据库服务器已关闭,然后才能更新相应的记录。” 好,现在怎么办?无效吗?将交易记录到文件中,以便人类以后可以解决?好的,如果磁盘已满并且您无法写入文件怎么办?等等


3

[1]为用户和您的应用程序使用安全表(不要与内部数据库用户混淆)。模块,表格,网页:

User = {userID, username, pwd, email1, email2}
Modules = {moduleID, moduleTitle, moduledescription}
ModulesPerUser = {modulesperuser, userID, moduleID}

[2]不要删除应用程序中的记录,而应使用状态字段(可能是整数,布尔值或位)来表明该记录被视为“已删除”。让你的应用程序。显示未删除的记录(由该字段标记为已删除),并在应用程序的位置制作一些特殊情况表格。确实显示标记为已删除的记录。

anytable = {anytableID, anytablefield1, anytablefield2, ..., bool anytableisdeleted }

此功能称为“虚拟删除”。真正的删除通常被称为“物理删除”。

[3]在所有与访问相关的表中使用字段,存储创建记录的(单个)用户和更改记录的(最后)用户,以及日期时间(如果可能)在每个记录所在的位置添加模块或选项改性:

AnyTable = {anytableID, anytablecreateuserID, anytablecreatedatetime,
anytableupdateuserID, anytableupdatedatetime,
moduleID, anytablefield1, anytablefield2, ..., anytableisdeleted }

[4]在某些情况下,当详细使用多个记录并在标头记录中添加到单个值中时,货币或货币值可能会影响结果。

如今,大多数数据库品牌都支持货币或货币数据字段。用它。

在某些特殊情况下,有些人将它们存储到固定的浮点值中,该值支持几个小数位(“十进制”)或什至作为字符串值。

这些技术是一把双刃剑。如果您的应用程序需要这种要求,请在网上搜索有关如何正确实施该方法的教程。

干杯。[别忘了给小猫开一个开放的金枪鱼罐头,否则就不会投票]


2

您已经用问题标记了您的问题,security但是您主要谈论的是一致性和可靠性,因此我将尝试回答方程式的这一部分:

  • 使用数据库事务来确保批处理操作的完整性。最基本的示例是两个帐户之间的转帐-一个帐户扣除金额,另一个帐户记入贷方。使用事务来确保永远不会发生部分转移(仅更改一侧)。
  • 为了提高精度,请使用DECIMAL类型而不是浮点数。计算速度要慢得多,但您不应感觉到它,因为大多数财务计算都是非常基本的
  • 将复制用于正常运行时间,将热拷贝用于备份。您还应该查看LVM快照以进行恢复

2

我看到的一些注意事项是您必须考虑内部控制。这意味着对表(插入/删除/更新)的所有操作访问都必须通过存储的proc(而不是动态SQl)进行,以便除系统管理员外,任何表都不允许直接向任何人授予对表的写或删除权限。您还必须考虑不允许某人创建新公司然后向该公司收费的内部控制措施(欺诈途径)。这样的动作总是需要两个不同角色的人来批准。此外,除非一个人输入数据并且另一人批准费用,否则不应削减支票。

所有表都应具有创建审核记录的触发器。您正在寻找防止欺诈行为的机会,以及是否能准确确定谁在何时采取了行动。

在金融应用程序中,您更加关心许多用户界面从未见过的后端流程。您首先要考虑的是防止欺诈,因此在后端进行了许多没人知道的检查。

我不会彻底阅读GAAP(在美国,其他国家/地区拥有自己的会计标准)并且以注册会计师(CPA)作为顾问,因为任何不正确的会计做法都会导致入狱,因此我不会处理任何形式的财务申请。这是一个技术含量很高的领域,没有必要的知识的人就不会尝试在此领域创建软件。


1

会计通常是关于验证的。只要您记住这一点并理解每个实体之间的关系,就很难将其弄错。

我将尝试列出尽可能多的支票,但总是会漏掉一些支票,希望这足以让您开始自己的挖掘工作。

总借方==总贷方,无论您是在谈论整个帐户集还是一个单独的交易,都是如此。如果不相符,您在某处错过了至少一个帖子。这就是总帐管理系统自身的平衡方式。

应收帐款(控制帐户的借方净额)==已开票总额(所有可开票金额的总和)-已收总额(已收所有付款的总和)。这是一个示例,说明以实物和有形单据形式进行的交易总计应与总账(两次输入)保持平衡。

银行余额(根据您的银行对帐单)==该帐户的总账+收到的未存入的支票-已发行的未存入的支票。这是银行/现金帐户如何与总账进行核算的一个示例分类帐。

如您所见,每笔交易,子分类账甚至股票都直接与总账联系在一起。

如果您要进行单元测试,那么只要您知道要检查的内容,它就很容易运行以确保每次插入/更新事务时都存在这些余额。

当然,还有更多的余额需要检查/统计,但是您应该掌握所需工作的要点。从本质上讲,无论是实物凭证,总帐项目,银行对账单,所有事物都与其他事物保持平衡。它应该是一个完美的平衡,或者在您懒于处理舍入的情况下,接近完美。

开发过程中执行的检查越多,发现错误的几率就越小。

顺便说一句,当您处理舍入时,请尝试使用小数而不是浮点数,它将为您省去很多麻烦。:P

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.