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.
369 lines
20 KiB
Java
369 lines
20 KiB
Java
package com.engine.attendance.attendanceanalysis.wrapper;
|
|
|
|
import com.engine.attendance.attendanceanalysis.service.ForgetClockInService;
|
|
import com.engine.attendance.attendanceanalysis.service.UtilService;
|
|
import com.engine.attendance.attendanceanalysis.service.impl.ForgetClockInServiceImpl;
|
|
import com.engine.attendance.attendanceanalysis.service.impl.UtilServiceImpl;
|
|
import com.engine.attendance.enums.CheckBoxEnum;
|
|
import com.engine.attendance.enums.ClassSegmentTypeEnum;
|
|
import com.engine.common.util.DateUtil;
|
|
import com.engine.common.util.DbTools;
|
|
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 lombok.extern.slf4j.Slf4j;
|
|
import weaver.general.Util;
|
|
|
|
import java.time.ZoneOffset;
|
|
import java.util.Comparator;
|
|
import java.util.HashMap;
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
import java.util.stream.Collectors;
|
|
|
|
/**
|
|
* 考勤分析主题逻辑
|
|
*/
|
|
@Slf4j
|
|
public class AttendanceAnalysisWrapper extends Service {
|
|
|
|
private UtilService utilService = ServiceUtil.getService(UtilServiceImpl.class);
|
|
private ForgetClockInService forgetClockInService = ServiceUtil.getService(ForgetClockInServiceImpl.class);
|
|
private UpdateAttendanceResultWrapper updateAttendanceResultWrapper = ServiceUtil.getService(UpdateAttendanceResultWrapper.class);
|
|
|
|
/**
|
|
* 考勤分析主逻辑入口
|
|
* @param userId 人员id
|
|
* @param dataList 打卡日期
|
|
* @param attendanceItems 考勤项目
|
|
*/
|
|
public void attendanceAnalysis(String userId, List<Map<String,Object>> dataList,List<Map<String,Object>> attendanceItems){
|
|
log.info("***********analysis userId:{} start***********",userId);
|
|
log.info("clockInTimeDate : [{}]",dataList);
|
|
|
|
String beforeThreeDayDate = DateUtil.getCurrentDateMinusDay(3);
|
|
String beforeTwoDayDate = DateUtil.getCurrentDateMinusDay(2);
|
|
String beforeOneDayDate = DateUtil.getCurrentDateMinusDay(1);
|
|
/** 打卡数据 */
|
|
Map<String, List<Map<String,Object>>> collect = Maps.newHashMap();
|
|
if (dataList != null && dataList.size() >0){
|
|
collect = dataList.stream().collect(Collectors.groupingBy(e -> Util.null2String(e.get("signdate"))));
|
|
}
|
|
/** 获取人员班次*/
|
|
Map<String,Object> classesParamMap = Maps.newHashMap();
|
|
classesParamMap.put("tableName","uf_pbjg");
|
|
classesParamMap.put("startDate",beforeThreeDayDate);
|
|
classesParamMap.put("endDate",beforeOneDayDate);
|
|
classesParamMap.put("pblx","0");
|
|
classesParamMap.put("pbdx",userId);
|
|
classesParamMap.put("current","1");
|
|
classesParamMap.put("pageSize",10);
|
|
classesParamMap.put("recurrence",1);
|
|
classesParamMap.put("attendanceItems",attendanceItems);
|
|
Map<String,Object> schedulMap = utilService.getSchedulingInFormation(classesParamMap);
|
|
Map<String,List<Map<String,Object>>> schedulingResultsMap = (Map<String,List<Map<String,Object>>>)schedulMap.get("schedulingResultsMap");
|
|
Map<String,List<Map<String,Object>>> schedulingMapBydate = (Map<String,List<Map<String,Object>>>)schedulMap.get("schedulingMapBydate");
|
|
|
|
/**计算获取前一天和第二天打卡数据*/
|
|
Map<String,Object> getClockTimeParam = Maps.newHashMap();
|
|
getClockTimeParam.put("date",beforeOneDayDate);
|
|
getClockTimeParam.put("clockInTimeCollect",collect);
|
|
getClockTimeParam.put("schedulingResultCollect",schedulingResultsMap);
|
|
//前一天打卡数据
|
|
log.info("getClockTimeParam : [{}]",getClockTimeParam);
|
|
List<Map<String, Object>> beforeOneDayClockInTimeList = utilService.getClockInTime(getClockTimeParam);
|
|
log.info("beforeOneDayClockInTimeList : [{}]",beforeOneDayClockInTimeList);
|
|
//分析前一天考勤
|
|
analysis(userId,beforeOneDayDate,beforeOneDayClockInTimeList,schedulingResultsMap.get(beforeOneDayDate),attendanceItems,schedulingMapBydate.get(beforeOneDayDate));
|
|
|
|
getClockTimeParam.put("date",beforeTwoDayDate);
|
|
//前第二天打卡数据
|
|
List<Map<String, Object>> beforeTwoDayClockInTimeList = utilService.getClockInTime(getClockTimeParam);
|
|
log.info("beforeTwoDayClockInTimeList : [{}]",beforeTwoDayClockInTimeList);
|
|
//分析前第二天考勤
|
|
analysis(userId,beforeTwoDayDate,beforeTwoDayClockInTimeList,schedulingResultsMap.get(beforeTwoDayDate),attendanceItems,schedulingMapBydate.get(beforeTwoDayDate));
|
|
|
|
|
|
}
|
|
|
|
/**
|
|
* 考勤分析主逻辑入口
|
|
* @param userId 人员id
|
|
* @param analysisDate 分析日期
|
|
* @param dataList 需要包含分析日期以及分析日期前后2天的3天打卡数据
|
|
* @param attendanceItems 人员考勤项目
|
|
*/
|
|
public void attendanceAnalysisForApi(String userId,String analysisDate, List<Map<String,Object>> dataList,List<Map<String,Object>> attendanceItems,Map<String,Object> schedulMap){
|
|
log.info("***********analysis userId:{} start***********",userId);
|
|
log.info("clockInTimeDate : [{}]",dataList);
|
|
Map<String, List<Map<String,Object>>> collect = Maps.newHashMap();
|
|
if (dataList != null && dataList.size() >0){
|
|
collect = dataList.stream().collect(Collectors.groupingBy(e -> Util.null2String(e.get("signdate"))));
|
|
}
|
|
Map<String,List<Map<String,Object>>> schedulingResultsMap = (Map<String,List<Map<String,Object>>>)schedulMap.get("schedulingResultsMap");
|
|
Map<String,List<Map<String,Object>>> schedulingMapBydate = (Map<String,List<Map<String,Object>>>)schedulMap.get("schedulingMapBydate");
|
|
/**计算获取前一天和第二天打卡数据*/
|
|
Map<String,Object> getClockTimeParam = Maps.newHashMap();
|
|
getClockTimeParam.put("date",analysisDate);
|
|
getClockTimeParam.put("clockInTimeCollect",collect);
|
|
getClockTimeParam.put("schedulingResultCollect",schedulingResultsMap);
|
|
//前一天打卡数据
|
|
log.info("getClockTimeParam : [{}]",getClockTimeParam);
|
|
List<Map<String, Object>> clockInTimeList = utilService.getClockInTime(getClockTimeParam);
|
|
|
|
analysis(userId,analysisDate,clockInTimeList,schedulingResultsMap.get(analysisDate),attendanceItems,schedulingMapBydate.get(analysisDate));
|
|
|
|
}
|
|
/**
|
|
* 分析数据
|
|
* @param userId 分析人员
|
|
* @param analysisDate 分析日期
|
|
* @param clockInTimeList 打卡数据
|
|
* @param scheduleResult 班次
|
|
* @param attendanceItems 考勤项目
|
|
*/
|
|
public void analysis(String userId,String analysisDate,List<Map<String, Object>> clockInTimeList,List<Map<String, Object>> scheduleResult,List<Map<String,Object>> attendanceItems,List<Map<String, Object>> scheduleList){
|
|
Map<String,Object> recordParam = Maps.newHashMap();
|
|
Map<String,String> formModeIdMap = Utils.getFormmodeIdMap();
|
|
recordParam.put("userId",userId);
|
|
recordParam.put("analysisDate",analysisDate);
|
|
recordParam.put("classInfo",scheduleResult);
|
|
recordParam.put("formmodeIdMap",formModeIdMap);
|
|
recordParam.put("attendanceDuration",0);
|
|
|
|
recordParam.put("modeId",formModeIdMap.get("uf_jcl_kq_cqjg"));
|
|
|
|
if (scheduleResult == null || scheduleResult.size() ==0){
|
|
|
|
//没有排班
|
|
Map<String,Object> params = Maps.newHashMap();
|
|
params.put("userId",userId);
|
|
params.put("analysisDate",analysisDate);
|
|
params.put("modeId",formModeIdMap.get("uf_jcl_kq_cqjg"));
|
|
params.put("scheduleList",scheduleList);
|
|
updateAttendanceResultWrapper.recordNoClass(params);
|
|
return;
|
|
}
|
|
recordParam.put("rqlx",scheduleResult.get(0).get("rqlx"));
|
|
List<Map<String, Object>> needClockInSchedule = scheduleResult.stream().filter(e -> "1".equals(e.get("ksdk")) || "1".equals(e.get("jsdk"))).collect(Collectors.toList());
|
|
if(clockInTimeList == null || clockInTimeList.size() == 0){
|
|
if (needClockInSchedule.size() > 0){
|
|
//全天漏打卡
|
|
recordParam.put("cqzt",0);
|
|
recordParam.put("recordData",forgetClockInService.forgetClockInAllDays());
|
|
utilService.recordItem(recordParam);
|
|
return;
|
|
}
|
|
}
|
|
//请假记录
|
|
String sql = "select a.qjry,a.jqlx,a.cxjqj,b.ksrq,b.kssj,b.jsrq,b.jssj,b.qjsc,b.qtj,b.btj from uf_jcl_kq_qjjl a left join uf_jcl_kq_qjjl_dt1 b on a.id = b.mainid where a.qjry=? and b.ksrq=? and (b.cxqj=0 or b.cxqj is null)";
|
|
List<Map<String,Object>> askForLeaveList = DbTools.getSqlToList(sql,userId,analysisDate);
|
|
log.info("askForLeaveList :{}",askForLeaveList);
|
|
//考勤项目
|
|
Map<String,Map<String,Object>> askForLeaveItems = Maps.newHashMap();
|
|
|
|
//出差记录
|
|
sql = "select b.ccr,a.cclx,a.ccsd,b.ksrq,b.jsrq,b.kssj,b.jssj,b.ccsc,b.qtcc,b.btcc,b.cxcc from uf_jcl_kq_ccjl a left join uf_jcl_kq_ccjl_dt1 b on a.id = b.mainid where b.ccr=? and b.ksrq=? and (b.cxcc=0 or b.cxcc is null)";
|
|
List<Map<String,Object>> evectionList = DbTools.getSqlToList(sql,userId,analysisDate);
|
|
log.info("evectionList :{}",evectionList);
|
|
//出差项目
|
|
Map<String,Map<String,Object>> evectionItems = Maps.newHashMap();
|
|
|
|
|
|
sql = "select hsl,hsdw,lgsbxydk,tqlghlfzs,fgsbxydk,thfghlfzs,tybcndbjlhbjs,zdycbcndfgzsd,zdycrqqjndxxb,zysd from uf_jcl_kq_kqxm where id=?";
|
|
List<Map<String,Object>> askForLeaveAndEvctionSchedule = Lists.newArrayList();
|
|
for (Map<String,Object> askForLeaveData : askForLeaveList){
|
|
Map<String,Object> askForLeaveItem = DbTools.getSqlToMap(sql,askForLeaveData.get("jqlx"));
|
|
//全天请假
|
|
if (CheckBoxEnum.CHECKED.getKey().equals(askForLeaveData.get("qtj"))){
|
|
List<Map<String,Object>> resultList = Lists.newArrayList();
|
|
Map<String,Object> resultMap = Maps.newHashMap();
|
|
resultMap.put("item",askForLeaveData.get("jqlx"));
|
|
resultMap.put("itemduration",scheduleResult.get(0).get("edsc"));
|
|
resultList.add(resultMap);
|
|
recordParam.put("cqzt",CheckBoxEnum.UNCHECKED.getKey());
|
|
recordParam.put("recordData",resultList);
|
|
utilService.recordItem(recordParam);
|
|
return;
|
|
}
|
|
|
|
askForLeaveItems.put(askForLeaveData.get("jqlx").toString(),askForLeaveItem);
|
|
List<Map<String, Object>> finalScheduleResult = scheduleResult;
|
|
Map<String,Object> askForLeaveMap = new HashMap(){{
|
|
put("bcxx", finalScheduleResult.get(0).get("bcxx"));
|
|
put("bcsdxx", finalScheduleResult.get(0).get("bcsdxx"));
|
|
put("edsc", finalScheduleResult.get(0).get("edsc"));
|
|
put("bdlx", ClassSegmentTypeEnum.ASK_FOR_LEAVE.getKey());
|
|
put("dtkssj",askForLeaveData.get("kssj"));
|
|
put("dtjssj",askForLeaveData.get("jssj"));
|
|
put("ksdk",askForLeaveItem.get("fgsbxydk"));
|
|
put("jsdk",askForLeaveItem.get("lgsbxydk"));
|
|
put("tqdkfzs","60");
|
|
put("thdkfzs","60");
|
|
put("tqlghlfzs",askForLeaveItem.get("tqlghlfzs"));
|
|
put("thfghlfzs",askForLeaveItem.get("thfghlfzs"));
|
|
}};
|
|
|
|
if (!"".equals(Util.null2String(askForLeaveData.get("kssj"))) && !"".equals(Util.null2String(askForLeaveData.get("jssj")))){
|
|
//scheduleResult.add(askForLeaveMap);
|
|
askForLeaveAndEvctionSchedule.add(askForLeaveMap);
|
|
}
|
|
}
|
|
for (Map<String,Object> evectionData :evectionList){
|
|
//全天出差
|
|
Map<String,Object> evectionItem = DbTools.getSqlToMap(sql,evectionData.get("cclx"));
|
|
if (CheckBoxEnum.CHECKED.getKey().equals(evectionData.get("qtcc"))) {
|
|
List<Map<String,Object>> resultList = Lists.newArrayList();
|
|
Map<String,Object> resultMap = Maps.newHashMap();
|
|
resultMap.put("item", evectionData.get("cclx"));
|
|
resultMap.put("itemduration", scheduleResult.get(0).get("edsc"));
|
|
resultList.add(resultMap);
|
|
recordParam.put("cqzt",CheckBoxEnum.UNCHECKED.getKey());
|
|
recordParam.put("recordData",resultList);
|
|
utilService.recordItem(recordParam);
|
|
return;
|
|
}
|
|
evectionItems.put(evectionData.get("cclx").toString(),evectionItem);
|
|
List<Map<String, Object>> finalScheduleResult1 = scheduleResult;
|
|
Map<String,Object> evectionMap = new HashMap(){{
|
|
put("bcxx", finalScheduleResult1.get(0).get("bcxx"));
|
|
put("bcsdxx", finalScheduleResult1.get(0).get("bcsdxx"));
|
|
put("edsc", finalScheduleResult1.get(0).get("edsc"));
|
|
put("bdlx", ClassSegmentTypeEnum.EVECTION.getKey());
|
|
put("dtkssj",evectionData.get("kssj"));
|
|
put("dtjssj",evectionData.get("jssj"));
|
|
put("ksdk",evectionItem.get("fgsbxydk"));
|
|
put("jsdk",evectionItem.get("lgsbxydk"));
|
|
put("tqdkfzs","60");
|
|
put("thdkfzs","60");
|
|
put("tqlghlfzs",evectionItem.get("tqlghlfzs"));
|
|
put("thfghlfzs",evectionItem.get("thfghlfzs"));
|
|
}};
|
|
if (!"".equals(Util.null2String(evectionData.get("kssj"))) && !"".equals(Util.null2String(evectionData.get("jssj")))){
|
|
//scheduleResult.add(evectionMap);
|
|
askForLeaveAndEvctionSchedule.add(evectionMap);
|
|
}
|
|
}
|
|
|
|
scheduleResult = scheduleResult.stream().sorted(Comparator.comparing(e->DateUtil.getTime(analysisDate+" "+e.get("dtkssj")).toInstant(ZoneOffset.of("+8")).toEpochMilli())).collect(Collectors.toList());
|
|
|
|
if (askForLeaveAndEvctionSchedule.size() > 0){
|
|
askForLeaveAndEvctionSchedule = mergeAskForLeaveAndEvctionSchedule(askForLeaveAndEvctionSchedule,analysisDate);
|
|
}
|
|
Map<String,Object> clcokInTimeDataParam = Maps.newHashMap();
|
|
clcokInTimeDataParam.put("analysisDate",analysisDate);
|
|
clcokInTimeDataParam.put("scheduleResult",scheduleResult);
|
|
clcokInTimeDataParam.put("clockInTimeList",clockInTimeList);
|
|
clcokInTimeDataParam.put("askForLeaveAndEvctionSchedule",askForLeaveAndEvctionSchedule);
|
|
List<Map<String,Map<String,Object>>> clcokInTimeData = utilService.getClockInPointCmd(clcokInTimeDataParam);
|
|
|
|
Map<String,Object> recordAbnormalParam = Maps.newHashMap();
|
|
recordAbnormalParam.put("clcokInTimeList",clcokInTimeData);
|
|
recordAbnormalParam.put("attendanceItems",attendanceItems);
|
|
recordAbnormalParam.put("scheduleResult",scheduleResult);
|
|
recordAbnormalParam.put("analysisDate",analysisDate);
|
|
recordAbnormalParam.put("userId",userId);
|
|
recordAbnormalParam.put("rqlx",scheduleResult.get(0).get("rqlx"));
|
|
|
|
recordAbnormalParam.put("formmodeIdMap",formModeIdMap);
|
|
|
|
log.info("recordAbnormalParam clcokInTimeList:{},attendanceItems size :{},scheduleResult :{},analysisDate:[{}],userId:[{}],rqlx:[{}],modeId:[{}]",clcokInTimeData,
|
|
attendanceItems.size(),scheduleResult,analysisDate,userId,scheduleResult.get(0).get("rqlx"));
|
|
|
|
/**
|
|
* 正常上下班入结果表
|
|
*/
|
|
//
|
|
// List<Map<String,Object>> normalList= updateAttendanceResultWrapper.recordNormal(recordAbnormalParam);
|
|
|
|
/**
|
|
* 计算是否考勤异常,是否有早退、迟到、漏卡的情况
|
|
*
|
|
**/
|
|
|
|
recordAbnormalParam.put("askForLeaveList",askForLeaveList);
|
|
recordAbnormalParam.put("askForLeaveItems",askForLeaveItems);
|
|
recordAbnormalParam.put("evectionList",evectionList);
|
|
recordAbnormalParam.put("evectionItems",evectionItems);
|
|
|
|
List<Map<String,Object>> abnormalClockInList = updateAttendanceResultWrapper.recordAbnormalClockIn(recordAbnormalParam);
|
|
|
|
/**
|
|
* 请假
|
|
*/
|
|
recordAbnormalParam.put("abnormalClockInList",abnormalClockInList);
|
|
Map<String, Object> vactionMap = updateAttendanceResultWrapper.recordAskForLeave(recordAbnormalParam);
|
|
List<Map<String,Object>> abnormalClockInListByAskForLeave = (List<Map<String,Object>>)vactionMap.get("abnormalClockInList");
|
|
List<Map<String,Object>> vactionList = (List<Map<String,Object>>)vactionMap.get("resultList");
|
|
recordAbnormalParam.put("offsetAskForLeaveAnomaly",vactionMap.get("offsetAskForLeaveAnomaly"));
|
|
log.info("请假后消除的异常 : [{}]",vactionMap.get("offsetAskForLeaveAnomaly"));
|
|
/**
|
|
* 出差、外出
|
|
*/
|
|
recordAbnormalParam.put("abnormalClockInList",abnormalClockInListByAskForLeave);
|
|
|
|
Map<String, Object> recordEvection= updateAttendanceResultWrapper.recordEvection(recordAbnormalParam);
|
|
List<Map<String,Object>> abnormalClockInListByEvction = (List<Map<String,Object>>)recordEvection.get("abnormalClockInList");
|
|
List<Map<String,Object>> evectionResultList = (List<Map<String,Object>>)recordEvection.get("resultList");
|
|
recordAbnormalParam.put("abnormalClockInList",abnormalClockInListByEvction);
|
|
recordAbnormalParam.put("offsetEvectionAnomaly",recordEvection.get("offsetEvectionAnomaly"));
|
|
log.info("出差外出后消除的异常 : [{}]",recordEvection.get("offsetEvectionAnomaly"));
|
|
/**
|
|
* 加班
|
|
*/
|
|
List<Map<String,Object>> recordWorkOverTime= updateAttendanceResultWrapper.recordWorkOverTime(recordAbnormalParam);
|
|
|
|
/**
|
|
* 计算出勤时长
|
|
*/
|
|
double attendanceDuration = utilService.computeAttendanceDuration(recordAbnormalParam);
|
|
|
|
/**
|
|
* 入库
|
|
*/
|
|
List<Map<String,Object>> recordData = Lists.newArrayList();
|
|
recordData.addAll(vactionList);
|
|
recordData.addAll(evectionResultList);
|
|
recordData.addAll(abnormalClockInListByEvction);
|
|
recordData.addAll(recordWorkOverTime);
|
|
recordParam.put("recordData",recordData);
|
|
recordParam.put("recordDataTime",utilService.getNeedRecordClockInTime(clcokInTimeData));
|
|
recordParam.put("attendanceDuration",attendanceDuration);
|
|
log.info("recordParam : {}",recordParam);
|
|
if (abnormalClockInListByEvction.size()>0){
|
|
recordParam.put("cqzt",CheckBoxEnum.CHECKED.getKey());
|
|
}else {
|
|
recordParam.put("cqzt",CheckBoxEnum.UNCHECKED.getKey());
|
|
}
|
|
utilService.recordItem(recordParam);
|
|
}
|
|
|
|
|
|
public List<Map<String,Object>> mergeAskForLeaveAndEvctionSchedule(List<Map<String,Object>> askForLeaveAndEvctionSchedule,String analysisDate){
|
|
|
|
askForLeaveAndEvctionSchedule = askForLeaveAndEvctionSchedule.stream().sorted(Comparator.comparing(e->DateUtil.getTime(analysisDate+" "+e.get("dtkssj")).toInstant(ZoneOffset.of("+8")).toEpochMilli())).collect(Collectors.toList());
|
|
|
|
for (int i=0;i<askForLeaveAndEvctionSchedule.size()-1;i++){
|
|
String beforeDtkssj = askForLeaveAndEvctionSchedule.get(i).get("dtkssj").toString();
|
|
String beforeDtjssj = askForLeaveAndEvctionSchedule.get(i).get("dtjssj").toString();
|
|
|
|
for (int j=i+1;j<askForLeaveAndEvctionSchedule.size();j++){
|
|
String dtkssj = askForLeaveAndEvctionSchedule.get(j).get("dtkssj").toString();
|
|
String dtjssj = askForLeaveAndEvctionSchedule.get(j).get("dtjssj").toString();
|
|
if (beforeDtjssj.equals(dtkssj)){
|
|
askForLeaveAndEvctionSchedule.get(i).put("dtjssj",dtjssj);
|
|
askForLeaveAndEvctionSchedule.get(i).put("jsdk",askForLeaveAndEvctionSchedule.get(j).get("jsdk"));
|
|
askForLeaveAndEvctionSchedule.get(i).put("thfghlfzs",askForLeaveAndEvctionSchedule.get(j).get("thfghlfzs"));
|
|
askForLeaveAndEvctionSchedule.remove(askForLeaveAndEvctionSchedule.get(j));
|
|
j--;
|
|
i--;
|
|
}
|
|
}
|
|
}
|
|
|
|
return askForLeaveAndEvctionSchedule;
|
|
}
|
|
}
|