开发FMS财务管理系统,每天都会与数据打交道,数据的核对与处理是日常工作的一部分,相信接触过财务系统的同学都深有感触,为了一个差异查来查去,最终发现是前端业务系统的问题,白忙一场,本篇就说一下关于财务数据核对的过程与方法,希望读后有所帮助!
一、系统数据生成过程
对于财务管理系统的数据是通过前端业务系统的数据进行抽取、计算、汇总生成的,其中又包括财务结算、付款、收款等核销过程,数据的准确性是第一位的。
1. 三个原则
(1)财务数据的生成原则
从业务单据明细->财务明细->财务汇总,即从细到粗的顺序生成。
为什么这么做?
因为在抽取财务相关数据时,有时候为了方便可以从业务相关的统计查询报表中获取数据,这样能减少很多工作(不需要了解具体的逻辑)。
但是如果这样设计就使得财务的数据过度依赖于前端业务系统,当业务系统的报表逻辑口径有变化时或不需要是就会影响到财务数据,所以我们应该尽可能的抽取相关明细的数据以防止过度耦合。
您可能说即便单据也会有变化,没错,但我们的原则是尽可能减小这种差异的产生。
从财务汇总->财务明细->业务单据明细 即从粗到细的顺序核对。
为什么这么做?
因为如果您核对数据时先从最细粒度的去核对,那么数据量是非常大,计算量可能是成指数级递增。
所以我们一定要先核对总数,总数有差异再核对明细,一层层的向下钻取直致查询到具体的问题数据。
我一直坚持在财务系统中的数据要分层,每层都要保留明细,当本层数据无误后再进行下一层数据生成。
(3)数据勾稽关系如何设计
了解报表的生成逻辑,先从各报表中相同的数据项进行比对,然后再根据报表间计算规则进行比对。
举个例子:销售收入成本报表中收入-成本=毛利;存货平衡表中有商品的成本,这里销售出库、销售退货、销售补发等成本的合计应该与收入成本报表中的成本数能够勾对上;如果不相对,那我们系统肯定有问题了。
在开发报表中要了解报表中各字段的统计时间口径及相关其他条件,这是设计勾稽关系的前提。
2. 理解数据依赖关系
这里最重要的是数据勾稽如何确定,需要产品研发同学非常清晰的理解相关数据的依赖关系。
首先,从系统的角度来考虑,先要保证数据的产生是正常,每天有很多定时任务在运行,要先确定各服务的依赖关系。
这和分布式服务(通过spring clound等来实现,但要防止循环依赖)中服务依赖还有点区别,这里更多的是指数据上的依赖。
通过消息来实现服务间的解耦,一个服务执行完发条消息到MQ,订阅者开始执行即可;
如果不通过MQ,可以采用最建立一个服务调度状态表来实现,设计好服务间的依赖关系,每个服务执行前循环扫描此表状态,如果依赖的服务都执行完毕,则执行(参照下表)。
其次,从数据的完整性和准确性上考虑。
这里涉及一个设计原则,既当服务在执行过程中出现了异常,是终止还是继续执行?
终止:后续依赖的任务都不会执行,系统产生不了数据,影响业务使用系统。
执行:有了异常数据,继续执行后依赖的数据也会有错误,业务虽然能够使用,但是会错上加错。
当这种问题出现后,相信多数人都会采用终止执行,由研发同学尽快解决后再继续。
其实这个问题有点类似于大促活动时服务降级策略;在系统设计过程中是务必要考虑的。
FMS财务管理系统的数据不像前端业务生产系统实时性要求那么高,所以一般情况下可以根据数据的使用用途来划分,原则上以数据的准确性为第一原则。
报表统计分析来数据,可以继续执行;有数据参考比没有数据要好,虽然有部分是错的。举个例子:公司老板每天必看的报表(一般都是汇总类数据),提供比不提供要好。
财务业务单据类数据,终止,等待处理后再执行。举个例子:应付结算单,如果产生了错误数据应会影响到付款,此时不执行比执行要好。
最后,数据重算机制
数据有问题或异常了,要考虑重算或补偿机制,保证数据准确性和完整性。
重要的服务,尽量不要借助人工处理,要写程序来完成。
举个例子:财务成本核算服务每天要根据出入库流水进行成本计算(移动加权或先进先出等),出现异常了,一定要写重算的过程,否则后续处理问题时相当麻烦。
其他的每层数据的生成时都应该考虑,人工和系统结合的方式来解决问题。
对于数据的核对需要借助于核对平台,按数据“汇总-〉明细”的过程进行。
我个人的处理原则还是先在数据库层面利用SQL来进行核对,然后借助于系统出具核对结果。
1. 为什么这么做?
因为财务库的数据是独立的,而且不会影响到前端业务生产库,可以充分利用脚本来进行。
这里我们可以开发一些定时任务服务来进行对财务数据进行汇总核对。
2. 核对的内容和方式
这个核对对于业务生产与财务抽取间既要核对数据条数,也要核对数量与金额等关键数据,防止数据的丢失和异常。
其它层级间主要是核对数量与金额,最复杂的是财务报表间的核对,要明确勾稽关系(这部分在设计报表时就需要确定)。
核对系统:以上的核对至少要做一个核对界面,每天来查看服务的执行状态(在数据库中查询也可以),查看核对的数据间差异,需要设置阀值,对于超过阀值的要高亮显示。
对于相关的预警,譬如服务假死,我们可以通过监控此服务产生的数据行数来判定。
出现异常后,产品研发还是应该及时处理,终止未执行的服务,解决后再启动,降低整体数据生成的时间,保证业务每天早上都能快快乐乐的使用系统,提升产品研发的高大形象。
作为研发、产品我们在设计核对平台时,都希望开发一个牛逼的系统,引入了规则引擎、大数据计算等技术,利用一个当前很流行的框架。但这样做好吗?
个人不赞成这样去做,我个人觉得可以在数据库层面利用脚本或存储过程核对的,就不要写程序(财务库不像各个业务生产库对读写要求非常高可以用存储过程等技术) ,可以用简单的技术实现的,不要引入过多复杂的技术(可以适当使用),降低开发成本。
最后介绍几个,本人在日常工作中的几个数据处理的小方法,供大家参考。
1. 利用Excel的公式来核对
主要是使用VLOOKUP公式进行,这个公式比较强大。
场景:从两个不同的数据库中来对比差异(两个库不能联合查询,也没有建立DBLINK)。
样例数据D1:
目标数据D2:
根据城市、月份从D1中查询出对应的销售额,并得出差异。
方法:在源数据列中输入公式:
=VLOOKUP(F2&G2,IF({1,0},Sheet3!$A$2:$A$6&Sheet3!$B$2:$B$6,$C$2:$C$6),2,0)
然后按CTRL+SHIT+ENTER组合键,再下拉即可。
2. 利用Excel与数据库脚本结合
场景:业务提供一个EXCEL,需要技术从数据库后台根据订单号获取其支付时间与发货仓库。
处理方法:通过拼接SQL方式去获取数据,这里的方法是和一位同事学习的,百试百灵。
1)先要插入一个关键字段,作为Excel文件中的一个主键,自增数字即可,然后拼写SQL。
2)将数据粘到文本中,去空格操作。
结果如下:
3)在数据库中拼写SQL,执行,注意这里就用到 order bykey_id进行排序了,保证输出的结果与Excel中的顺序一样,方便粘贴
4)将结果粘贴到Excel中进行处理(单元格设置为文本格式),注意key_id要与源数据增加的相同。
场景:业务提供一份几十万行的Excel文件数据(一般为CSV),需要技术在后台进行核对处理,并反馈出差异结果。
方法:由于数据量太大,此时不能利用方法一与方法二了,一般研发同学习惯于根据需求逻辑写个程序来进行处理,这里我习惯于利用数据库的SQL来核对处理,具体如下。
1)前提,本地机器上需要安装一个数据库,Mysql、SQLSERVER等都可以,如果有公共的测试数据库且有创建删除表权限的也可以,以MySql为例。
2)将数据文件导入到本地库中,Navicat中的导入工具可以用,这里用脚本。
3)首先创建一个表(根据数据文件进行创建),例如脚本如下:
4)数据文件保存成txt格式的文本。
5)导入数据到本地库。
脚本如下(语法可以百度一下load file):
6)将所有需要的数据导入到本地库,你就折腾吧。
这里可能需要生产库的数据,如果不涉及敏感信息,你这可以从生产中导出,再导入到本地库中进行与其它数据进行关联查询等。
其他数据库也是同样的过程,SQLServer的客户端功能强大,导入导出的工具很方便,Oracle可以利用SQLLoader工具来导入,导入百万级数据大约十几秒的时间,非常快。
如果需要的生产数据复杂,可以借助其它工具,例如Kettle,但这个需要安装,还要申请一些联接生产库的权限才可以使用。
注:对于数据和创建表都要注意编码格式,正常都采用UTF8
4. 写代码,利用程序来实现
这种方法我是极力不推荐的,不到万不得已,尽量不要写程序来完成大批量数据的处理与核对。
原因如下:
这种需求一般都是临时性的,对于源文件数据是否可以导入到生产,这个一般不允许;
程序需要连接生产库,需要创建项目,部署;通常开发环境与生产环境都是隔离的;
即便都可以在本地进行,但程序的逻辑要进行设计,如果调整不如脚本方便快捷。
总结
敏捷项目管理中提到,借助于有效的工具来提升研发效率是一个非常不错的选择。
在财务数据日常的核对处理时,可以借助各种工具来完成工作,但是过度的依赖最新的技术来完成简单的工作又会有种杀鸡用牛刀的感觉。
简单有效直接是行之有效的方法,通过总结,开发有效的工具是目标。
最后感谢您的阅读!