You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
367 lines
17 KiB
Java
367 lines
17 KiB
Java
package com.engine.attendance.attendanceanalysis.service.impl;
|
|
|
|
import com.engine.attendance.attendanceanalysis.cmd.item.AbsenteeismItemCmd;
|
|
import com.engine.attendance.attendanceanalysis.cmd.item.BeLateItemCmd;
|
|
import com.engine.attendance.attendanceanalysis.cmd.item.LeaveEarlyItemCmd;
|
|
import com.engine.attendance.attendanceanalysis.service.ComprehensiveWorkingHourService;
|
|
import com.engine.attendance.attendanceanalysis.service.UtilService;
|
|
import com.engine.attendance.enums.AccountingUnitEnum;
|
|
import com.engine.attendance.enums.CheckBoxEnum;
|
|
import com.engine.attendance.enums.SystemItemEnum;
|
|
import com.engine.common.util.CommonUtil;
|
|
import com.engine.common.util.DateUtil;
|
|
import com.engine.common.util.ServiceUtil;
|
|
import com.engine.common.util.Utils;
|
|
import com.engine.core.impl.Service;
|
|
import com.google.common.collect.Lists;
|
|
import com.google.common.collect.Maps;
|
|
import com.google.common.collect.Sets;
|
|
import lombok.extern.slf4j.Slf4j;
|
|
import weaver.general.Util;
|
|
|
|
import java.math.BigDecimal;
|
|
import java.math.RoundingMode;
|
|
import java.time.ZoneOffset;
|
|
import java.util.Comparator;
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
import java.util.Set;
|
|
import java.util.stream.Collectors;
|
|
|
|
@Slf4j
|
|
public class ComprehensiveWorkingHourServiceImpl extends Service implements ComprehensiveWorkingHourService {
|
|
private UtilService utilService = ServiceUtil.getService(UtilServiceImpl.class);
|
|
|
|
|
|
@Override
|
|
public Map<String, Object> excuteByWorkHour(Map<String, Object> param) {
|
|
Map<String, Object> resultMap = Maps.newHashMap();
|
|
|
|
//按照日期分割的打卡时间
|
|
List<Map<String,Object>> clockInTimeList = (List<Map<String,Object>>) param.get("clockInTimeCollect");
|
|
//分析日期
|
|
String analysisDate = Util.null2String(param.get("analysisDate"));
|
|
//人员
|
|
String userId = Util.null2String(param.get("userId"));
|
|
//考勤项目
|
|
List<Map<String,Object>> attendanceItems = (List<Map<String,Object>>)param.get("attendanceItems");
|
|
|
|
//综合工时
|
|
Map<String,Object> workHourItem = (Map<String,Object>)param.get("workHourItem");
|
|
//日工作时长不足,核算异常
|
|
String rgzscbzhsyc= Util.null2String(workHourItem.get("rgzscbzhsyc"));
|
|
//日最晚打卡报到时间
|
|
String rzwdkbdsj = Util.null2String(workHourItem.get("rzwdkbdsj"));
|
|
//日工作时长要求
|
|
double rgzscyq = Double.valueOf(Util.null2String(workHourItem.get("rgzscyq")));
|
|
//累计出勤时长的核算分钟数
|
|
int ljcqscdhsfzs = Integer.valueOf(Util.null2String(workHourItem.get("ljcqscdhsfzs")));
|
|
//超出日工作时长要求,计入出勤 时长
|
|
String ccrgzscyqjrcqsc = Util.null2String(workHourItem.get("ccrgzscyqjrcqsc"));
|
|
//日最长工作时长
|
|
double rzcgzsc = Double.valueOf(Util.null2String(workHourItem.get("rzcgzsc")));
|
|
//核算工时的日期类型
|
|
String hsgsdrqlx = Util.null2String(workHourItem.get("hsgsdrqlx"));
|
|
|
|
String cqzt = "0";
|
|
|
|
String rqlx = Utils.getDateType(analysisDate,Util.null2String(workHourItem.get("qyrl")));
|
|
|
|
if (!CommonUtil.ifContainStr(hsgsdrqlx,rqlx,",")){
|
|
log.info("userId :[{}],analysisDate :[{}] 综合工时执行的日期不在设置的日期类型内",userId,analysisDate);
|
|
resultMap.put("message","综合工时执行的日期不在设置的日期类型内");
|
|
return resultMap;
|
|
}
|
|
|
|
//异常项目
|
|
List<Map<String, Object>> recordDataList = Lists.newArrayList();
|
|
|
|
clockInTimeList = getClockInDataByRule(param);
|
|
|
|
int betweenMinute = getDurationMinute(clockInTimeList);
|
|
if (betweenMinute == 0 || clockInTimeList.size()==0){
|
|
if (rgzscbzhsyc.equals(CheckBoxEnum.CHECKED.getKey())){
|
|
//记漏打卡项目
|
|
Map<String, Object> itemMap = Maps.newHashMap();
|
|
itemMap.put("item", SystemItemEnum.MISSING_CLOCK_IN.getKey());
|
|
itemMap.put("itemduration","1");
|
|
recordDataList.add(itemMap);
|
|
}
|
|
}
|
|
double adjustBetWeenMinute = Utils.getItemdurationDown(ljcqscdhsfzs, AccountingUnitEnum.MINUTES.getKey(),betweenMinute,AccountingUnitEnum.MINUTES);
|
|
double adjustBetweenHour = new BigDecimal(adjustBetWeenMinute).divide(new BigDecimal(60),2, RoundingMode.HALF_UP).doubleValue();
|
|
log.info("betweenMinute : [{}],adjustBetWeenMinute: [{}],betweenHour:[{}]",betweenMinute,adjustBetWeenMinute,adjustBetweenHour);
|
|
|
|
if (clockInTimeList.size() > 0){
|
|
String reportTime = clockInTimeList.get(0).get("signdate")+" "+clockInTimeList.get(0).get("signtime");
|
|
int lateDurationTime = 0;
|
|
int earlyLeaveMinute = 0;
|
|
Map<String,Object> abnormalParams = Maps.newHashMap();
|
|
abnormalParams.put("attendanceItems",attendanceItems);
|
|
abnormalParams.put("rqlx",rqlx);
|
|
if (!"".equals(rzwdkbdsj)){
|
|
String lastReportTime = Utils.installTime(analysisDate,rzwdkbdsj);
|
|
if (Utils.dateGreaterThan(reportTime,lastReportTime)){
|
|
//迟到
|
|
lateDurationTime = DateUtil.getBetWeenMinutes(lastReportTime,reportTime);
|
|
}
|
|
}
|
|
if ((betweenMinute+lateDurationTime) < (rgzscyq*60)){
|
|
//早退
|
|
earlyLeaveMinute = Double.valueOf(rgzscyq*60-(betweenMinute+lateDurationTime)).intValue();
|
|
}
|
|
log.info("lateDurationTime : [{}],earlyLeaveMinute:[{}]",lateDurationTime,earlyLeaveMinute);
|
|
if (rgzscbzhsyc.equals(CheckBoxEnum.CHECKED.getKey())){
|
|
if (lateDurationTime > 0){
|
|
//计入迟到项目
|
|
abnormalParams.put("time",lateDurationTime);
|
|
Map<String,Object> result = commandExecutor.execute(new BeLateItemCmd(abnormalParams));
|
|
List<Map<String,Object>> workTimeBeLateItems = (List<Map<String,Object>>)result.get("attendanceItems");
|
|
if (workTimeBeLateItems.size() == 0){
|
|
workTimeBeLateItems = (List<Map<String,Object>>)commandExecutor.execute(new AbsenteeismItemCmd(abnormalParams)).get("attendanceItems");
|
|
}
|
|
if (workTimeBeLateItems.size() > 0){
|
|
double hsl = Double.valueOf(Util.null2String(workTimeBeLateItems.get(0).get("hsl")));
|
|
String hsdw = Util.null2String(workTimeBeLateItems.get(0).get("hsdw"));
|
|
double itemduration = Utils.getItemduration(hsl,hsdw,lateDurationTime,AccountingUnitEnum.MINUTES);
|
|
Map<String, Object> itemMap = Maps.newHashMap();
|
|
itemMap.put("item", workTimeBeLateItems.get(0).get("key"));
|
|
itemMap.put("itemduration",itemduration);
|
|
recordDataList.add(itemMap);
|
|
}
|
|
}
|
|
if (earlyLeaveMinute > 0){
|
|
//计早退项目
|
|
abnormalParams.put("time",lateDurationTime);
|
|
Map<String,Object> result = commandExecutor.execute(new LeaveEarlyItemCmd(abnormalParams));
|
|
List<Map<String,Object>> workTimeBeLateItems = (List<Map<String,Object>>)result.get("attendanceItems");
|
|
if (workTimeBeLateItems.size() == 0){
|
|
workTimeBeLateItems = (List<Map<String,Object>>)commandExecutor.execute(new AbsenteeismItemCmd(abnormalParams)).get("attendanceItems");
|
|
}
|
|
if (workTimeBeLateItems.size() > 0){
|
|
double hsl = Double.valueOf(Util.null2String(workTimeBeLateItems.get(0).get("hsl")));
|
|
String hsdw = Util.null2String(workTimeBeLateItems.get(0).get("hsdw"));
|
|
double itemduration = Utils.getItemduration(hsl,hsdw,earlyLeaveMinute,AccountingUnitEnum.MINUTES);
|
|
Map<String, Object> itemMap = Maps.newHashMap();
|
|
itemMap.put("item", workTimeBeLateItems.get(0).get("key"));
|
|
itemMap.put("itemduration",itemduration);
|
|
recordDataList.add(itemMap);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
//超出日工作时长要求,计入出勤 时长,否则最大为日工作时长要求
|
|
if (CheckBoxEnum.CHECKED.getKey().equals(ccrgzscyqjrcqsc)){
|
|
if (adjustBetweenHour > rzcgzsc){
|
|
adjustBetweenHour = rzcgzsc;
|
|
}
|
|
}else {
|
|
if (adjustBetweenHour > rgzscyq){
|
|
adjustBetweenHour=rgzscyq;
|
|
}
|
|
}
|
|
if (recordDataList.size() > 0){
|
|
cqzt="1";
|
|
}
|
|
|
|
|
|
|
|
Map<String,Object> recordParam = Maps.newHashMap();
|
|
recordParam.put("userId",userId);
|
|
recordParam.put("analysisDate",analysisDate);
|
|
recordParam.put("recordData",recordDataList);
|
|
recordParam.put("rqlx",rqlx);
|
|
recordParam.put("classInfo",Lists.newArrayList());
|
|
recordParam.put("recordDataTime",getRecordDataTime(clockInTimeList));
|
|
recordParam.put("attendanceDuration",adjustBetweenHour);
|
|
recordParam.put("formmodeIdMap",Utils.getFormmodeIdMap());
|
|
recordParam.put("cqzt",cqzt);
|
|
|
|
resultMap.put("recordParam",recordParam);
|
|
utilService.recordItem(recordParam);
|
|
return resultMap;
|
|
}
|
|
|
|
/**
|
|
* 根据综合工时规则获取打卡时间
|
|
* @param param
|
|
* @return
|
|
*/
|
|
public List<Map<String,Object>> getClockInDataByRule(Map<String, Object> param){
|
|
|
|
//按照日期分割的打卡时间
|
|
List<Map<String,Object>> clockInTimeList = (List<Map<String,Object>>) param.get("clockInTimeCollect");
|
|
//分析日期
|
|
String analysisDate = Util.null2String(param.get("analysisDate"));
|
|
//综合工时
|
|
Map<String,Object> workHourItem = (Map<String,Object>)param.get("workHourItem");
|
|
//最早打卡上班的开始时间
|
|
String zzdksbdkssj = Util.null2String(workHourItem.get("zzdksbdkssj"));
|
|
//最晚打卡下班的开始时间
|
|
String zwdkxbdkssj = Util.null2String(workHourItem.get("zwdkxbdkssj"));
|
|
//日工作时长计算规则
|
|
String rgzscjsgz = Util.null2String(workHourItem.get("rgzscjsgz"));
|
|
//调整上班开始到
|
|
String dzsbksd = Util.null2String(workHourItem.get("dzsbksd"));
|
|
//误打卡忽略分钟数
|
|
int wdkhlfzs = Util.null2String(workHourItem.get("wdkhlfzs")).equals("")?1:Integer.valueOf(Util.null2String(workHourItem.get("wdkhlfzs")));
|
|
|
|
|
|
|
|
|
|
String startTime = analysisDate+" "+zzdksbdkssj;
|
|
String endTime = analysisDate+" "+zwdkxbdkssj;
|
|
if ("".equals(zwdkxbdkssj)){
|
|
endTime = DateUtil.AfterDay(analysisDate,1)+" "+zzdksbdkssj;
|
|
endTime = DateUtil.beforeMinutes(endTime,1);
|
|
}
|
|
if (DateUtil.getTime(startTime).compareTo(DateUtil.getTime(endTime)) >=0){
|
|
endTime = DateUtil.AfterDay(analysisDate,1) +" "+zwdkxbdkssj;
|
|
}
|
|
|
|
String finalEndTime = endTime;
|
|
|
|
clockInTimeList = clockInTimeList.stream().filter(e -> {
|
|
String signdate = Util.null2String(e.get("signdate"));
|
|
String signtime = Util.null2String(e.get("signtime"));
|
|
String time = signdate +" "+signtime;
|
|
|
|
return DateUtil.getTime(startTime).compareTo(DateUtil.getTime(time)) <=0 && DateUtil.getTime(finalEndTime).compareTo(DateUtil.getTime(time)) >=0;
|
|
}).collect(Collectors.toList());
|
|
|
|
clockInTimeList = clockInTimeList.stream().sorted(Comparator.comparing(e->DateUtil.getTime(e.get("signdate")+" "+e.get("signtime")).toInstant(ZoneOffset.of("+8")).toEpochMilli())).collect(Collectors.toList());
|
|
|
|
if (clockInTimeList.size() == 0){
|
|
return clockInTimeList;
|
|
}
|
|
|
|
List<Map<String,Object>> newClockInTimeList = Lists.newArrayList();
|
|
if ("0".equals(rgzscjsgz)){
|
|
//最早最晚打卡间隔时长
|
|
newClockInTimeList.add(clockInTimeList.get(0));
|
|
newClockInTimeList.add(clockInTimeList.get(clockInTimeList.size()-1));
|
|
|
|
}else if ("1".equals(rgzscjsgz)){
|
|
//依次累加成对打卡间隔时长
|
|
if (clockInTimeList.size() > 1){
|
|
//数据清洗
|
|
Set<Map<String,Object>> needRemoveData = Sets.newHashSet();
|
|
for (int i=0;i<clockInTimeList.size()-1;i++){
|
|
String time1 = clockInTimeList.get(i).get("signdate")+" "+clockInTimeList.get(i).get("signtime");
|
|
for (int j=i+1;j<clockInTimeList.size();j++){
|
|
String time2 = clockInTimeList.get(j).get("signdate")+" "+clockInTimeList.get(j).get("signtime");
|
|
if (DateUtil.getBetWeenMinutes(time1,time2) <wdkhlfzs){
|
|
needRemoveData.add(clockInTimeList.get(j));
|
|
}
|
|
}
|
|
}
|
|
for (Map<String,Object> map:needRemoveData){
|
|
clockInTimeList.remove(map);
|
|
}
|
|
}
|
|
|
|
if (clockInTimeList.size() %2 == 1){
|
|
clockInTimeList.remove(clockInTimeList.size()-1);
|
|
newClockInTimeList = clockInTimeList;
|
|
}else {
|
|
newClockInTimeList = clockInTimeList;
|
|
}
|
|
}
|
|
|
|
if (newClockInTimeList.size() > 0){
|
|
String time = newClockInTimeList.get(0).get("signdate")+" "+newClockInTimeList.get(0).get("signtime");
|
|
int minute = DateUtil.getTime(time).getMinute();
|
|
int hour = DateUtil.getTime(time).getHour();
|
|
if ("1".equals(dzsbksd)){
|
|
//整点
|
|
if (minute > 0){
|
|
hour=hour+1;
|
|
}
|
|
String hourstr = DateUtil.getTimeStr(hour);
|
|
newClockInTimeList.get(0).put("signtime",hourstr+":00");
|
|
|
|
}else if ("2".equals(dzsbksd)){
|
|
//半点
|
|
String minuteStr = "";
|
|
if (minute < 30){
|
|
minuteStr = "30";
|
|
}else if (minute > 30){
|
|
minuteStr = "00";
|
|
hour = hour+1;
|
|
}
|
|
String hourstr = DateUtil.getTimeStr(hour);
|
|
newClockInTimeList.get(0).put("signtime",hourstr+":"+minuteStr);
|
|
|
|
}else if ("3".equals(dzsbksd)){
|
|
//15分钟
|
|
if (minute%15 > 0){
|
|
minute = (minute/15)*15+15;
|
|
if (minute == 60){
|
|
minute = 0;
|
|
hour = hour+1;
|
|
}
|
|
}
|
|
String hourstr = DateUtil.getTimeStr(hour);
|
|
String minutestr = DateUtil.getTimeStr(minute);
|
|
newClockInTimeList.get(0).put("signtime",hourstr+":"+minutestr);
|
|
}
|
|
if (newClockInTimeList.size() > 1){
|
|
String firstSignDate = newClockInTimeList.get(0).get("signdate")+" "+newClockInTimeList.get(0).get("signtime");
|
|
String twoSignDate = newClockInTimeList.get(1).get("signdate")+" "+newClockInTimeList.get(1).get("signtime");
|
|
//当调整后第一笔上班时间超过第二比那么去除这2比记录
|
|
if (DateUtil.getTime(firstSignDate).compareTo(DateUtil.getTime(twoSignDate)) >=0){
|
|
newClockInTimeList.remove(0);
|
|
newClockInTimeList.remove(0);
|
|
}
|
|
}
|
|
|
|
}
|
|
log.info("newClockInTimeList : [{}]",newClockInTimeList);
|
|
return newClockInTimeList;
|
|
}
|
|
|
|
/**
|
|
* 获得打卡时间两两直接的时间
|
|
* @param clockInTimeList 打卡时间
|
|
* @return 分钟数
|
|
*/
|
|
public int getDurationMinute(List<Map<String,Object>> clockInTimeList){
|
|
if (clockInTimeList.size() == 0){
|
|
return 0;
|
|
}
|
|
int logarithm = clockInTimeList.size()/2;
|
|
int betweenMinute = 0;
|
|
for (int i =0;i<logarithm;i++){
|
|
int index1 = i*2;
|
|
int index2 = index1+1;
|
|
String time1 = clockInTimeList.get(index1).get("signdate") +" "+clockInTimeList.get(index1).get("signtime");
|
|
String time2 = clockInTimeList.get(index2).get("signdate") +" "+clockInTimeList.get(index2).get("signtime");
|
|
betweenMinute += DateUtil.getBetWeenMinutes(time1,time2);
|
|
}
|
|
log.info("betweenMinute : [{}]",betweenMinute);
|
|
return betweenMinute;
|
|
}
|
|
|
|
/**
|
|
* 获得进出时间
|
|
* @param clockInTimeList
|
|
* @return
|
|
*/
|
|
public Map<String,Object> getRecordDataTime(List<Map<String,Object>> clockInTimeList){
|
|
Map<String,Object> resultMap = Maps.newHashMap();
|
|
if (clockInTimeList.size() == 0){
|
|
return resultMap;
|
|
}
|
|
int logarithm = clockInTimeList.size()/2;
|
|
|
|
for (int i =0;i<logarithm;i++){
|
|
int index1 = i*2;
|
|
int index2 = index1+1;
|
|
resultMap.put("j"+(i+1),"'"+clockInTimeList.get(index1).get("signtime")+"'");
|
|
resultMap.put("c"+(i+1),"'"+clockInTimeList.get(index2).get("signtime")+"'");
|
|
}
|
|
log.info("betweenMinute : [{}]",resultMap);
|
|
return resultMap;
|
|
}
|
|
}
|