定義工資公式的功能是企業工資計算中常見的做法,這其實就像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代碼
對象定義
Id { ; 基本工資 { ; 狀態 { ; 員工性質 { ; 計薪方式 { ; 姓名 { ; 結果定義 _結果 = { { _結果 = List<字段定義> _字段集合 = List<字段定義> List<字段定義> { { _字段集合 = 名稱 { ; 值 { ; 名稱 { ; 正向 { ; 值 { ; 實發工資 { ; <工資項定義> _工資項集合 = List<工資項定義> List<工資項定義> { { _工資項集合 =
加載設置數據
_table = _access.GetTable().ToList<SalaryCond> _projs = _access.GetTable().ToList<工資項定義> ( item _subList = _access.GetTable( + item.Id + ).ToList<字段定義>== ;
規則引擎中定義
在本項目中,公式解釋與模型設計工作是由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;
調用規則引擎計算
tsbCalc_Click( (dgvLst.SelectedRows.Count == ) _selRow = dgvLst.SelectedRows[ (_selRow == ) _cond = _selRow.DataBoundItem = _strResult = + _cond.結果.實發工資 + _index = ( _prop (_index > && _index % == +=+= _prop.名稱 + + _prop.值 + ++=
計算結果會在界面下方顯示。
源代碼下載