一个crystal report水晶报表无法实现的多数据源计算

来源:互联网 发布:软件许可协议模板 编辑:程序博客网 时间:2024/05/18 22:46

项目背景:用户新上线了绩效考核系统,原本的工资算法需要相的调整。以前的工资表主要由员工的基本工资计算得到,基本工资存储在财务管理软件的MSSQL数据库中。新的工资表由基本工资+绩效工资组成。绩效工资由绩效分数计算得出,而绩效分数存储在绩效考核系统的Oracle数据库中。显然,新的工资表需要两个数据库的跨库计算才能得到。

具体的绩效工资算法比较复杂。首先,不同的岗位算法不同。有些岗位是根据基本工资的区间来计算的,而有些岗位不需要按区间来计算。有些岗位只是单纯的用绩效来计算,而有些岗位要考虑绩效和工龄双重因素。还有些岗位有绩效得分但没有绩效工资。其次,同样是按基本工资区间来计算绩效的岗位,不同的岗位其区间划分方法、每个区间内的具体算法也有不同。最后,所有的员工工资要合并为一张报表。

为了便于理解,这里将算法大幅简化,并去掉交税的影响,岗位也简化为2个:normal和sales。Normal有绩效得分但没有绩效工资,其税前工资=基本工资。sales的税前工资=基本工资+绩效工资。其中绩效工资是这样算的:

基本工资在2000以下的:基本工资*(绩效得分/100)

基本工资在2000至4000的:基本工资*((绩效得分*0.9)/100)

基本工资在4000以上的基本工资*((绩效得分*0.8)/100)

可以看到,要计算完整的工资表,需要将MSSQL的employee表按照岗位分成多份(简化后是2份),每份数据单独计算出税前工资,最后再将不同岗位的税前工资合并起来。两种岗位的算法不同,岗位是sales的需要关联Oracle中的performance表,其税前工资需要按不同的区间分别计算。而岗位是normal不需要做这种关联计算。

这张报表的难点在于:一、employee和performance分属不同的数据库,需要跨库计算。二、算法较复杂,仅将两张表简单地关联起来是无法实现目标的。

跨库计算最理想的解决方案是依靠报表工具。如果报表工具能在一张报表中处理两种数据源就可以实现“报表层跨库”。但Crystal report处理多数据源的办法很复杂,实现成本不低。而且报表工具也只能提供简单的内外关联,难以处理这种循环中判断以及多结果集合并的复杂算法。

报表工具无法解决这种问题,只能从报表之外寻求解法。事先ETL到一个库里显然不是个好办法,一方面ETL开发成本太高,另一方面还有数据同步和实时性的麻烦。

最后用集算器解决了这个问题,具体代码如下:

代码的意思也很好理解:

A1A2:分别从ORACLE和MSSQL取数据。A3:为employee加一个空列preTax,用来存储将来的税前工资。

A4A10:从employee分别取出岗位是sales和normal的数据。由于后期要合并,用业务名引用比较方便,因此这两部分数据分别定义为sales和normal。当然,A3这种临时的计算结果并没有额外定义变量,而是直接在A4中按格名来引用A3。类似的还有A5中引用A1。

A5-C9:计算sales的税前工资。其中A5是关联计算,将sales的基本工资和绩效分数关联了起来。A6到C9是个循环,将sales逐条循环判断,按不同区间不同算法来计算税前工资。这里需要注意三点。一是循环体是用缩进来表示的,B7-C9都是循环体。二是循环变量就是for所在的单元格,即A6。循环体中可以用A6来表示当前记录。三是A6.empID.score的用法,这是对象的引用方式。这表示当前记录A6的empID字段所关联的记录(即performance中的记录)的score字段,即当前员工的绩效分数。

A11:直接将normal的preTax赋值为baseSalary。

A12:将不同岗位的计算结果合并起来。当然,实际的算法中远不止两种岗位,每种岗位的税前工资算法也比示例中复杂。

A13:从A12中挑选一些需要输出的字段。

 A14:以JDBC的形式输出A13,以便JAVA代码或报表工具通过JDBCURL直接调用。可以看到,这实际上这也是一种将多数据源合并为单数据源的方法,只是Crystal的数据源关联过于简单,无法实现这种过程性的跨库计算罢了。

可以看到,水晶报表中的这个跨库的问题被轻松解决了。另外水晶报表会把集算器当作MSSQL或Oracle这样的数据库来调用,配合起来也很容易。
0 0
原创粉丝点击