
某客戶企業為上市公司,公司員工規模800人左右,根據公司企業發展需要,后續公司員工規模還會持續性增長。因客戶沒有人力資源管理系統,所有的考勤、薪資、計件都是人工手動計算,同時客戶班次分類較多、較雜,當每個月每個事業部的考勤文員在核算員工的考勤時都比較痛苦,其中有一個加班補貼的核算場景,文員都是人工根據打卡數據以及紙質單據識別出來的加班餐補補貼。現客戶使用東寶人力資源管理系統,希望此需求能通過系統自動計算,減少人工成本。規則如下:
①加班需要打卡,并(bing)且提交加班單才計算加班餐(can)補補貼。
②滿足以下(xia)場景,才(cai)計算加班餐補補貼。
③日(ri)報(bao)統計(ji)加班餐補補貼(tie)次數,薪(xin)資(zi)核算(suan)加班餐補補貼(tie)。
通過在東寶DHG系(xi)統(tong)配置(zhi)的自定義過程實現,系(xi)統(tong)自動(dong)根據員工(gong)的打卡或加班單來(lai)統(tong)計(ji)不同的餐次次數。考(kao)勤匯總餐補(bu)次數,薪酬核算餐補(bu)費用。
以下(xia)是自定(ding)義(yi)識(shi)別(bie)加班場景(jing)來計算餐補的代碼實現部分:
/* 加班統計餐次 腳本執行的標識:工時日報-工時計算最后處理 1. 根據日報班段時間,將其中加班段處理為 "找餐時間段" - 如果員工的考勤制度勾選了加班需申請,那餐補次數的統計需要根據員工的加班單結合打卡時間來計算餐補次數。否則,只需要根據打卡來計算加班餐補的次數。 - 無需特殊處理:該控制會影響日報的班段結果,直接按日報班段結果處理即可 2. 固定的餐補應上下班時間、餐補 3. 匹配就餐 - “找餐時間段” 匹配 “就餐應上下班時間段”,計加班餐次 */ var debug = type.new("java.lang.StringBuilder"); try { // 處理前置空(保障更新原本算出來,現在算不出來的數據) // 早餐 workHourDayDTO.attWorkHourDay.extField['c_overtime_breakfast'] = 0; // 中餐 workHourDayDTO.attWorkHourDay.extField['c_overtime_lunch'] = 0; // 晚餐 workHourDayDTO.attWorkHourDay.extField['c_overtime_dinner'] = 0; // 夜宵 workHourDayDTO.attWorkHourDay.extField['c_overtime_night_snack'] = 0; // 1. 根據日報班段時間,將其中加班段處理為 "找餐時間段" var workBucketDTOList = workHourDayDTO.workShiftDTO.workBucketDTOList; // 4-請假 6-停工 7-曠工 8-休假 // 1-正班 3-休息 // 5-出差正班 51-出差加班 52-出差其他加班 62-出差推后加班 61-出差提前加班 // 11-正班提前加班 12-正班推后加班 2-正班加班 // 81-休假加班 82-休假其他加班 var overtimeBucketType = @com.google.common.collect.Sets.newHashSet(5, 51, 52, 61, 62, 11, 12, 2, 81, 82); var currFindRepastRange = null; var findRepastRangeList = []; for (var workBucketDTO in workBucketDTOList) { for (var workHourDayBucketDTO in workBucketDTO.workHourDayBucketDTOList) { @debug.append(" [").append(workHourDayBucketDTO.workBucketType).append("]"); @debug.append(workHourDayBucketDTO.workTimeBegin).append(" - ").append(workHourDayBucketDTO.workTimeEnd); if (workHourDayBucketDTO.effectiveWorkHour && @overtimeBucketType.contains(workHourDayBucketDTO.workBucketType)) { @debug.append(" 有效加班段"); if (currFindRepastRange == null) { var begin = workHourDayBucketDTO.cardTimeBegin != null ? workHourDayBucketDTO.cardTimeBegin : workHourDayBucketDTO.workTimeBegin; var end = workHourDayBucketDTO.cardTimeEnd != null ? workHourDayBucketDTO.cardTimeEnd : workHourDayBucketDTO.workTimeEnd; currFindRepastRange = { begin: begin, end: end }; @debug.append(" 初始找餐時間段:").append(currFindRepastRange.begin).append(" - ").append(currFindRepastRange.end); } else { currFindRepastRange.end = workHourDayBucketDTO.cardTimeEnd != null ? workHourDayBucketDTO.cardTimeEnd : workHourDayBucketDTO.workTimeEnd; @debug.append(" 合并緊鄰的有效加班段:~ ").append(currFindRepastRange.end); } } else { @debug.append(workHourDayBucketDTO.effectiveWorkHour ? " 非加班段" : " 無效時段"); if (currFindRepastRange != null) { @debug.append(" 記錄當前的找餐時間段:"); @debug.append(currFindRepastRange.begin).append(" - ").append(currFindRepastRange.end); @findRepastRangeList.add(currFindRepastRange); currFindRepastRange = null; } } } } if (currFindRepastRange != null) { @debug.append(" 記錄最后的找餐時間段:"); @debug.append(currFindRepastRange.begin).append(" - ").append(currFindRepastRange.end); @findRepastRangeList.add(currFindRepastRange); } // 2. 固定的餐補應上下班時間、餐補 var repastTimeConfList = [ // 早餐:6元/次,打卡時間為7:00前(含7點整); { flag: "breakfast", begin: "07:00", end: "07:00", cnt: 0 }, // 中餐:15元/次,上班打卡時間為10:00前(含10點整)并加班餐補下班打卡時間為14:00后(含14點整); { flag: "lunch", begin: "10:00", end: "14:00", cnt: 0 }, // 晚餐:15元/次,打卡時間為20:00后(含20點整); { flag:"dinner", begin: "20:00", end: "20:00", cnt: 0 }, // 夜宵:6元/次,打卡時間為24:00后(含24點整)。 { flag: "night_snack", begin: "00:00", end: "00:00", cnt: 0 } // ]; // 取進三天就餐具體時間 var repastDateTimeRangeList = []; var attendanceDate = workHourDayDTO.attWorkHourDay.attendanceDate; for (var i = -1; i <= 1; i++) { var date = @com.dongbao.core.util.DateUtil.dayOffset(attendanceDate, i); for (var repastTimeConf in repastTimeConfList) { @repastDateTimeRangeList.add({ conf: repastTimeConf, begin: @com.dongbao.core.util.DateUtil.getDateTime(date, repastTimeConf.begin), end: @com.dongbao.core.util.DateUtil.getDateTime(date, repastTimeConf.end) }); } } // 3. 匹配就餐 var i = 0; var j = 0; while (i < @findRepastRangeList.size() && j < @repastDateTimeRangeList.size()) { var findRepastRange = findRepastRangeList[i]; var repastDateTimeRange = repastDateTimeRangeList[j]; var isLater = repastDateTimeRange.begin < findRepastRange.begin; var isEarly = repastDateTimeRange.end > findRepastRange.end; if (isLater) { // 飯點過了——就餐時間早于找餐時間,接著找下段就餐時間 j++; } else if (isEarly) { // 飯點沒到——就餐時間晚于找餐時間,接著找下一段加班時間 i++; } else { // 包含飯點——匹配,計對應加班餐次,接著找下段就餐時間 @debug.append(" 匹配到餐點:"); @debug.append(repastDateTimeRange.begin).append(" - ").append(repastDateTimeRange.end); @debug.append(" 加班時間段:"); @debug.append(findRepastRange.begin).append(" - ").append(findRepastRange.end); var conf = repastDateTimeRange.conf; conf.cnt = conf.cnt + 1; @debug.append(" 餐補次數 - ").append(conf.flag).append(": ").append(conf.cnt); j++; } } // 4. 自定義字段賦值 for (var conf in repastTimeConfList) { workHourDayDTO.attWorkHourDay.extField["c_overtime_" + conf.flag] = conf.cnt; } } catch (e) { var writer = type.new("StringWriter"); var printer = @org.codehaus.groovy.runtime.IOGroovyMethods.newPrintWriter(writer); @e.printStackTrace(printer); @debug.append(" ").append(writer); }
①系(xi)統(tong)自(zi)動根(gen)據班(ban)(ban)次(ci)(ci)、打卡(ka)、加(jia)班(ban)(ban)單識別不同類型的加(jia)班(ban)(ban)餐次(ci)(ci),考勤(qin)文員由原來每(mei)月人工識別,縮短為系(xi)統(tong)實時數(shu)據更新,省(sheng)時省(sheng)力(li)。
②日考勤機(ji)準確率(lv)提升(sheng)至100%,同時每月能快(kuai)速高效完(wan)結考勤月報(bao)。
上一篇:員工參加培訓后的效果評估功能