• 自定义工资项和公式


    1,自定义工资项

    定义工资公式的功能是企业工资计算中常见的做法,这其实就像Excel系统中的公式一样的普通。但某位技术员在要自己开发的程序中增加公式系统,那就要开发一个像样的公式解释逻辑了,该工作我们在之前已经介绍过。

    不过实际的工作生活中,工资项目常常不是固定不变的,对于某个企业而言,其考核办法也是随时变化的,如果技术员没理解清楚工资业务的变化并进行抽象,那常常导致程序反复修改,客户也很不满意。如奖金发放这个业务逻辑中,原来就只有奖金点数和每点奖金两种部分:

    1

    奖金点数

    各个员工级别设置不同的资金点数。

    2

    每点奖金

    根据每个月的业绩和资金点数和落实的每点奖金。

    但某天客户新制定的奖金方案要增加部门这个项目,如部门是销售部的才发奖金,这样系统就会有很多变化。

    上述例子只是一个客户的情况,但软件开发,一般都想做成产品,要有很多客户,那变化就更多了。

    序号

    客户类型

    说明

    1

    小单位-销售类

    销售计提方案复杂,考勤简化。

    2

    小单位-研发类

    无多少提成方案,考勤严谨。

    3

    大单位-综合类

    有研发式计提,有销售式计提,有复杂的考勤类生产工资计算公式。

    于是,简单定义有多少个工资项目,似乎是非常不明智的做法。让客户来定义工资项目是最好的办法。这也大大降低了开发的成本和实施维护的工作量。

    2,技术实现

    自定义工资项和公式在技术上需要做如下设计:

    序号

    类型

    设计项目

    说明

    1

    对象设计

    工资字段定义

    如月工作天数,周末日加班天数,奖金点数,病假小时,餐补,多种类型补贴等。

    2

    对象设计

    实发工资项目

    如实发基本工资,实发餐补,实扣请假,实收奖金等等。

    3

    对象设计

    主类

    能够引用字段和工资项的内容。

    4

    逻辑设计

    公式解释

    解释器使用CKRule的.Net解释逻辑。

    5

    逻辑设计

    调度模型

    设计业务程序与CKRule规则引擎的调用逻辑。

    6

    数据库设计

    允许工资字段设置,实发工资项目设置

    允许在数据库中定义字段及工资项目。

    7

    界面设计

    员工工资数据加载

    可以加载员工的基本工资信息和工资字段信息。

    8

    界面设计

    工资公式编辑

    允许用户对工资公式进行编辑。编辑过程要使用到自定义的字段和工资项。

    2.1 界面效果图

    工资计算界面

       界面与原来固定工资项时,有明显分别,如下内容值得注意:

    序号

    项目

    说明

    1

    数据库

    每个员工的工资字段信息都是从数据库加载的。

    2

    周期性

    应该有一个地方定义某个工资周期的字段,如3月份使用这一批字段。

    3

    有效性

    每个员工使用到的工资字段是不相同的,虽然字段有很多,但该员工使用到的才会被设置。

    注意第2点,公式设置时,也有周期性的问题,即有新字段了,就要编辑新的公式。当然对于某个公司而言,有新工资方案才可以有新的公式的。

    工资公式编辑界面

     

    公式设置界面也与原来的非常不同,注意如下变化:

    序号

    项目

    说明

    1

    数据库

    计算名称那里的信息都是从数据库加载的。(代码偷懒了,没实现)

    2

    资源

    资源那里基本上没什么关键词了。因为基本上找不到直接定义的字段内容。

    3

    动态取字段

    P(…)是一个动态取字段值的方法,在CKRule中定义的,可返回double类型参数,所以可以使用如下的编写方法。

    Round(IIF(状态=="转正",1310/P("月工作天数")*P("转正前天数") + 基本工资/P("月工作天数")*P("转正后天数"),基本工资/P("月工作天数")*P("实际出勤天数")),2) 

    2.2代码

    对象定义

        [Serializable]
        public class SalaryCond
        {
            public string Id { get; set; }
            public double 基本工资 { get; set; }
            public string 状态 { get; set; }
            public string 员工性质 { get; set; }
            public string 计薪方式 { get; set; }
            public string 姓名 { get; set; }
            
            private 结果定义 _结果 = new 结果定义();
    
            public 结果定义 结果
            {
                get { return _结果; }
                set { _结果 = value; }
            }
    
            private List<字段定义> _字段集合 = new List<字段定义>();
    
            public List<字段定义> 字段集合
            {
                get { return _字段集合; }
                set { _字段集合 = value; }
            }
        }
    
        [Serializable]
        public class 字段定义
        {
            public string 名称 { get; set; }
            public double 值 { get; set; }
        }
    
        [Serializable]
        public class 工资项定义
        {
            public string 名称 { get; set; }
            public bool 正向 { get; set; }
            public double 值 { get; set; }
        }
    
        [Serializable]
        public class 结果定义
        {
            public double 实发工资 { get; set; }
            List<工资项定义> _工资项集合 = new List<工资项定义>();
    
            public List<工资项定义> 工资项集合
            {
                get { return _工资项集合; }
                set { _工资项集合 = value; }
            }
    }

    加载设置数据

                var _table = _access.GetTable("select * from 工资基本信息 order by id").ToList<SalaryCond>();
    
                var _projs = _access.GetTable("select 名称,正向,0 as 值 from 工资项").ToList<工资项定义>();
    
                foreach (var item in _table)
    
                {
    
                    var _subList = _access.GetTable("select 名称,值 from 工资字段 where baseid ='" + item.Id + "'").ToList<字段定义>();
    
                    item.字段集合.AddRange(_subList);
    
                    item.结果.工资项集合.AddRange(_projs);
    
                }
    
                dgvLst.DataSource = _table;
    
                dgvLst.AllowUserToAddRows = false;

    规则引擎中定义

    在本项目中,公式解释与模型设计工作是由CKRule规则引擎处理的,其调用关系图如下:

     CKRule与业务系统关系图

    (该工具相关信息请访问:www.ckrule.com)

    需要设置的内容如下:

    序号

    模块

    内容

    代码

    1

    客户规则池定义

    P方法

    double _result = 0;

    Loop(字段集合,x=>{

             if(x.名称 == 字段名称){

                       _result = x.值;

             }

    });

    return _result;

    2

    客户规则池定义

    SET方法

    Loop(结果.工资项集合,x=>{

             if(x.名称 == 工资项名称){

                       x.值 = 值;

             }

    });

    3

    主规则

    加载设置

    var _table = LookDB(@"

    select

    '' as id,

    sindex as ""index"",

    '' as returnType,

    'Get' + name as propname,

    0 as codestyle,

    ''  as ifcode,

    0 as thencodeisscript,

    'SET(""' + name + '"",' + CalcCode + ');' as thencode,

    0 as priority ,

    '' as execstep

    from poolset

    ");

    InitPool(_table);

    ExePool();

    4

    主规则

    计算实发工资

    double _result = 0;

    Loop(结果.工资项集合,x=>{

             _result += x.正向 ? x.值 : 0- x.值;

    });

    结果.实发工资 = _result;

    调用规则引擎计算

            private void tsbCalc_Click(object sender, EventArgs e)
    
            {
    
                if (dgvLst.SelectedRows.Count == 0) return;
    
                var _selRow = dgvLst.SelectedRows[0];
    
                if (_selRow == null) return;
    
                var _cond = _selRow.DataBoundItem as SalaryCond;
    
                _cond = new RuleFacade().Exec(FrmRulePoolSet.RuleInstName, _cond);
    
                var _strResult = "实发工资 : " + _cond.结果.实发工资 + "		";
    
                int _index = 1;
    
                foreach (var _prop in _cond.结果.工资项集合)
    
                {
    
                    if (_index > 0 && _index % 4 == 0)
    
                        _strResult += Environment.NewLine;
    
                    _strResult += _prop.名称 + " : " + _prop.值 + "		";
    
                    _index++;
    
                }
    
                txtResult.Text = _strResult;
    
            }

    计算结果会在界面下方显示。

    源代码下载

  • 相关阅读:
    facebook开源前端UI框架React初探
    javascript中数组的map方法
    处理 InterruptedException——Brian Goetz
    eclipse 打开是报错"reload maven project has encountered a problem"
    Java并发大师Brain Goetz和Doug Lea 的中英文博客文章地址
    修复 Java 内存模型,第 2 部分——Brian Goetz
    修复 Java 内存模型,第 1 部分——Brian Goetz
    正确使用 Volatile 变量——Brian Goetz
    mysql数据备份
    小知识点
  • 原文地址:https://www.cnblogs.com/jingle/p/3674831.html
Copyright © 2020-2023  润新知