考勤-加班计划流程,加班累计小时数考虑加班计划数据,提交节点增加已存在加班计划和班次时段重叠校验

main
sy 8 months ago
parent 58af4d387f
commit cc0a7f53ea

@ -2,10 +2,7 @@ package com.engine.jucailinkq.attendance.workflow.action;
import com.engine.jucailinkq.attendance.attendanceanalysis.service.UtilService;
import com.engine.jucailinkq.attendance.attendanceanalysis.service.impl.UtilServiceImpl;
import com.engine.jucailinkq.attendance.enums.AccountingUnitEnum;
import com.engine.jucailinkq.attendance.enums.AttendanceItemTypeEnum;
import com.engine.jucailinkq.attendance.enums.DateTypeEnum;
import com.engine.jucailinkq.attendance.enums.WorkForTimeEnum;
import com.engine.jucailinkq.attendance.enums.*;
import com.engine.jucailinkq.attendance.workflow.service.MakeUpClockInService;
import com.engine.jucailinkq.attendance.workflow.service.impl.MakeUpClockInServiceImpl;
import com.engine.jucailinkq.common.util.CommonUtil;
@ -42,6 +39,8 @@ public class OvertimePlanCheckAction implements Action {
log.info("OvertimePlanCheckAction_start, detailTableData_size : {}",detailTableData.size());
//加班人员
String jbry = mainTableData.get("jbry");
String mainStartDate = Util.null2String(mainTableData.get("ksrq"));
String mainEndDate = Util.null2String(mainTableData.get("jsrq"));
try {
//获取人员id和姓名信息
List<String> empIdList = Arrays.asList(jbry.split(","));
@ -52,6 +51,14 @@ public class OvertimePlanCheckAction implements Action {
Map<String, Map<String, Object>> jblxInfo = jblxAttendanceList.stream()
.filter(f -> Util.null2String(f.get("zysd")).contains(WorkForTimeEnum.PLAN_WORK_OVERTIME.getKey()))
.collect(Collectors.toMap(e->e.get("id").toString(), e->e));
//获取目标人员列表已存在的加班计划
Map<String, List<Map<String, Object>>> existOvertimePlanInfo = getOvertimePlanInfo(empIdList, DateUtil.beforeDay(mainStartDate, 1));
List<Map<String, Object>> existOvertimePlanList = new ArrayList<>();
//获取人员列表在日期区间的班次数据
Map<String, List<Map<String, Object>>> scheduleInfoMap = utilService.getScheduleInfoWithEmpId(empIdList, DateUtil.beforeDay(mainStartDate, 1), DateUtil.AfterDay(mainEndDate,1));
List<String> workBdlxList = new ArrayList<>();
workBdlxList.add(ClassSegmentTypeEnum.WORK_TIME.getKey());workBdlxList.add(ClassSegmentTypeEnum.EXTENDED_OVERTIME.getKey());
workBdlxList.add(ClassSegmentTypeEnum.EARLY_OVERTIME.getKey());workBdlxList.add(ClassSegmentTypeEnum.OVERTIME_IN_CLASS.getKey());
//明细数据按照人员分组
Map<String,List<Map<String, String>>> detailGroupMap = detailTableData.stream().collect(Collectors.groupingBy(e->Util.null2String(e.get("jbry"))));
List<String> errorMessage = new ArrayList<>();
@ -70,7 +77,6 @@ public class OvertimePlanCheckAction implements Action {
params.put("submitDate",DateUtil.getCurrentDate());
params.put("submitStr","ksrq");
params.put("submitDataList",detailGroupByUserList);
/**
*
*/
@ -105,7 +111,11 @@ public class OvertimePlanCheckAction implements Action {
requestInfo.getRequestManager().setMessagecontent(message);
return Action.FAILURE_AND_CONTINUE;
}
//获取人员已存在的加班计划信息
existOvertimePlanList = existOvertimePlanInfo.get(empId);
//获取该人员的日期与班次id的映射
List<Map<String, Object>> scheduleInfoList = scheduleInfoMap.get(empId);
Map<String, String> dateToBcxxMap = scheduleInfoList == null ? new HashMap<>() : scheduleInfoList.stream().collect(Collectors.toMap(e->Util.null2String(e.get("bcrq")), e->Util.null2String(e.get("bcxx"))));
//校验加班类型中最小加班分钟数、工作日最大加班小时数、周最大加班小时数、月最大加班小时数等限定值
List<Map<String, String>> overtimeDetailList = tableEntry.getValue();
Map<String, Object> matchItemInfo;
@ -123,11 +133,66 @@ public class OvertimePlanCheckAction implements Action {
//排班和日历都无法获取时,默认为工作日
belongDateType = "".equals(belongDateType) ? DateTypeEnum.WORK_DAY.getKey() : belongDateType;
String startDate = overtimeDetailItem.get("ksrq");
String startTime = overtimeDetailItem.get("ksrq");
String endDate = overtimeDetailItem.get("jsrq");
String endTime = overtimeDetailItem.get("jssj");
String jbsc = overtimeDetailItem.get("jbsc");
double overtimeMinutes = Double.parseDouble(jbsc) * 60;
String jblxId = overtimeDetailItem.getOrDefault("jblx", "");
matchItemInfo = jblxInfo.getOrDefault(jblxId, new HashMap<>());
//判断改组明细是否与已存在的加班计划有重叠
boolean overLappingSign = checkOverlapping(existOvertimePlanList, startDate + " " +startTime, endDate + " " + endTime);
if (overLappingSign) {
String message = Util.null2String(empIdToNameInfo.get(empId)) + "在日期" + startDate + "的加班计划区间和已申请的加班计划(已审核/待审核)出现时间重叠,不允许申请加班!";
log.error(message);
requestInfo.getRequestManager().setMessageid("11111" + requestid + "22222");
requestInfo.getRequestManager().setMessagecontent(message);
return Action.FAILURE_AND_CONTINUE;
}
//判断是否与临近班次班段重叠,重叠班次是否为非休息班次的非休息时段
//获取当天班次id
String currentDayBcId = Util.null2String(dateToBcxxMap.get(startDate)).split("-")[0];
//判断当天班次是否为休息班次、且“休息班打卡自动加班”未勾选
boolean currentDayRestBc = checkRestBc(currentDayBcId);
if (!currentDayRestBc) {
String overlapInfo = checkBcOverlap(startDate, currentDayBcId, workBdlxList, startDate + " " + startTime, endDate + " " + endTime);
if (!"".equals(overlapInfo)) {
String message = Util.null2String(empIdToNameInfo.get(empId)) + "在日期" + startDate + "的加班计划区间" + overlapInfo;
log.error(message);
requestInfo.getRequestManager().setMessageid("11111" + requestid + "22222");
requestInfo.getRequestManager().setMessagecontent(message);
return Action.FAILURE_AND_CONTINUE;
}
}
//获取前1天班次id
String beforeDayBcId = Util.null2String(dateToBcxxMap.get(DateUtil.beforeDay(startDate, 1))).split("-")[0];
//判断前1天班次是否为休息班次、且“休息班打卡自动加班”未勾选
boolean beforeDayRestBc = checkRestBc(beforeDayBcId);
if (!beforeDayRestBc) {
String overlapInfo = checkBcOverlap(DateUtil.beforeDay(startDate, 1), beforeDayBcId, workBdlxList, startDate + " " + startTime, endDate + " " + endTime);
if (!"".equals(overlapInfo)) {
String message = Util.null2String(empIdToNameInfo.get(empId)) + "在日期" + startDate + "的加班计划区间" + overlapInfo;
log.error(message);
requestInfo.getRequestManager().setMessageid("11111" + requestid + "22222");
requestInfo.getRequestManager().setMessagecontent(message);
return Action.FAILURE_AND_CONTINUE;
}
}
//获取次日班次id
String nextDayBcId = Util.null2String(dateToBcxxMap.get(DateUtil.AfterDay(startDate, 1))).split("-")[0];
//判断次日班次是否为休息班次、且“休息班打卡自动加班”未勾选
boolean nextDayRestBc = checkRestBc(nextDayBcId);
if (!nextDayRestBc) {
String overlapInfo = checkBcOverlap(DateUtil.AfterDay(startDate, 1), nextDayBcId, workBdlxList, startDate + " " + startTime, endDate + " " + endTime);
if (!"".equals(overlapInfo)) {
String message = Util.null2String(empIdToNameInfo.get(empId)) + "在日期" + startDate + "的加班计划区间" + overlapInfo;
log.error(message);
requestInfo.getRequestManager().setMessageid("11111" + requestid + "22222");
requestInfo.getRequestManager().setMessagecontent(message);
return Action.FAILURE_AND_CONTINUE;
}
}
//判断是否满足最小加班分钟数
String minMinutes = Util.null2String(matchItemInfo.get("jbqsfzs"));
if (!"".equals(minMinutes) && Integer.parseInt(minMinutes) > overtimeMinutes) {
//最小加班分钟数大于单条明细的加班时长分钟数
@ -267,8 +332,124 @@ public class OvertimePlanCheckAction implements Action {
*
*/
public List<Map<String, Object>> getWorkOverTimeResults(String startDate,String endDate,String userId){
String sql = "select a.sjjbsc, a.sjksrq, a.sjjsrq, a.jblx, b.hsdw from uf_jcl_kq_jbjg a left join uf_jcl_kq_kqxm b on a.jblx = b.id where a.jbry=? and a.sjksrq>=? and a.sjjsrq<=?";
List<Map<String, Object>> dataList = DbTools.getSqlToList(sql,userId,startDate,endDate);
return dataList;
String sql = "select a.sjjbsc, a.sjksrq, a.sjjsrq, a.jbjhid, a.jblx, b.hsdw from uf_jcl_kq_jbjg a left join uf_jcl_kq_kqxm b on a.jblx = b.id where a.zt != 2 and a.jbry=? and a.sjksrq>=? and a.sjjsrq<=?";
List<Map<String, Object>> jbjgDataList = DbTools.getSqlToList(sql,userId,startDate,endDate);
sql = "select b.jbsc as sjjbsc, b.ksrq as sjksrq, b.jsrq as sjjsrq, a.id as jbjhid, b.jblx, c.hsdw from uf_jcl_kq_jbjh a " +
"left join uf_jcl_kq_jbjh_dt1 b on a.id = b.mainid left join uf_jcl_kq_kqxm c on b.jblx = c.id where a.jlzt != 2 and b.jbry = ? and b.ksrq >= ? and b.jsrq <= ?";
List<Map<String, Object>> jbjhDataList = DbTools.getSqlToList(sql,userId,startDate,endDate);
//去除加班计划中数据已转换为加班结果的数据
Set<String> jbjhIds = jbjgDataList.stream().filter(f -> !"".equals(Util.null2String(f.get("jbjhid")))).map(e->e.get("jbjhid").toString()).collect(Collectors.toSet());
jbjhDataList = jbjhDataList.stream().filter(f -> !jbjhIds.contains(f.get("jbjhid").toString())).collect(Collectors.toList());
if (jbjhDataList.size() > 0) {
jbjgDataList.addAll(jbjhDataList);
}
return jbjgDataList;
}
private boolean checkOverlapping(List<Map<String, Object>> existOvertimePlanList, String startTimePoint, String endTimePoint) {
boolean overlappingSign = false;
if (existOvertimePlanList != null && existOvertimePlanList.size() > 0) {
String contrastStartPoint = "";
String contrastEndPoint = "";
for (Map<String, Object> item : existOvertimePlanList) {
contrastStartPoint = item.get("ksrq") + " " + item.get("kssj");
contrastEndPoint = item.get("jsrq") + " " + item.get("jssj");
overlappingSign = DateUtil.isOverlapping(contrastStartPoint, contrastEndPoint, startTimePoint, endTimePoint);
if (overlappingSign) {
break;
}
}
}
return overlappingSign;
}
/**
*
* @param empIdList id
* @param matchDate
* @returnd
*/
private Map<String, List<Map<String, Object>>> getOvertimePlanInfo(List<String> empIdList, String matchDate) {
Map<String, List<Map<String, Object>>> result = new HashMap<>();
if (empIdList.size() > 0 && !"".equals(matchDate)) {
String sql = "select b.id, b.jbry, b.ksrq, b.jsrq, b.kssj, b.jssj from uf_jcl_kq_jbjh a left join uf_jcl_kq_jbjh_dt1 b on b.mainid = a.id where a.jlzt != 2 and b.jsrq >= '"
+ matchDate + "' and b.jbry in (" + String.join(",",empIdList) + ")";
List<Map<String, Object>> data = DbTools.getSqlToList(sql);
result = data.stream().collect(Collectors.groupingBy(e->e.get("jbry").toString()));
}
return result;
}
private boolean checkRestBc(String bcId) {
boolean restSign = false;
if (!"".equals(bcId)) {
//查询当天班次明细
String sql = "select id, sfxx, xxbdkzdjb from uf_jcl_kq_bcxx where id = " + bcId;
Map<String, Object> data = DbTools.getSqlToMap(sql);
if ("1".equals(Util.null2String(data.get("sfxx"))) && !"1".equals(Util.null2String(data.get("xxbdkzdjb")))) {
restSign = true;
}
}
return restSign;
}
public String getBcStartAndEndTime(String date, String currentDayBcId, List<String> workBdlxList) {
String startToEnd = "";
if (!"".equals(currentDayBcId)) {
//查询当天班次明细
String sql = "select id, bdlx, gsrq, kssj, jssj from uf_jcl_kq_bcxx_dt1 where mainid = " + currentDayBcId + " order by gsrq desc, kssj desc";
List<Map<String, Object>> bcDetailData = DbTools.getSqlToList(sql);
bcDetailData = bcDetailData.stream().filter(e -> workBdlxList.contains(Util.null2String(e.get("bdlx")))).collect(Collectors.toList());
if (bcDetailData.size() > 0) {
String endGsrqValue = Util.null2String(bcDetailData.get(0).get("gsrq"));
String lastJssj = Util.null2String(bcDetailData.get(0).get("jssj"));
String lastKssj = Util.null2String(bcDetailData.get(0).get("kssj"));
String bdEndDate = "2".equals(endGsrqValue) ? DateUtil.AfterDay(date,1) : ("0".equals(endGsrqValue) ? DateUtil.beforeDay(date,1) : date);
bdEndDate = lastKssj.compareTo(lastJssj) >= 0 ? DateUtil.AfterDay(bdEndDate,1) : bdEndDate;
String startGsrqValue = Util.null2String(bcDetailData.get(bcDetailData.size() - 1).get("gsrq"));
String firstKssj = Util.null2String(bcDetailData.get(bcDetailData.size() - 1).get("kssj"));
String bdStartDate = "2".equals(startGsrqValue) ? DateUtil.AfterDay(date,1) : ("0".equals(startGsrqValue) ? DateUtil.beforeDay(date,1) : date);
startToEnd = bdStartDate + " " + firstKssj + "," + bdEndDate + " " + lastJssj;
}
}
return startToEnd;
}
private String checkBcOverlap(String startDate, String currentDayBcId, List<String> workBdlxList, String overtimePlanStart, String overtimePlanEnd) {
//获取当前日期班次开始时间和结束时间
String currentDayStartToEnd = getBcStartAndEndTime(startDate, currentDayBcId, workBdlxList);
String currentDayStartTime = !"".equals(currentDayStartToEnd) ? currentDayStartToEnd.split(",")[0] : "";
String currentDayEndTime = !"".equals(currentDayStartToEnd) ? currentDayStartToEnd.split(",")[1] : "";
//如果加班计划区间和班次区间有交集
boolean noOverlapSign = overtimePlanStart.compareTo(currentDayEndTime) >= 0 || overtimePlanEnd.compareTo(currentDayStartTime) <= 0;
if (!noOverlapSign) {
//判断交集部分是否完全属于班次的休息、就餐时段
boolean onlyInRestPeriod = overtimeOnlyInRestRange(currentDayBcId, overtimePlanStart, overtimePlanEnd, startDate);
if (!onlyInRestPeriod) {
return "与" + startDate + "班次中的非休息、就餐时段存在交集!";
} else {
return "";
}
} else {
return "";
}
}
/**
*
*/
private boolean overtimeOnlyInRestRange(String bcId, String startTime, String endTime, String date) {
int overRangeMinutes = DateUtil.getBetWeenMinutes(startTime, endTime);
List<String> countBdlxList = new ArrayList<>();
countBdlxList.add(ClassSegmentTypeEnum.REST_AND_DINE.getKey());
countBdlxList.add(ClassSegmentTypeEnum.REST_PERIOD.getKey());
countBdlxList.add(ClassSegmentTypeEnum.DINING_PERIOD.getKey());
String sql = "select id, bdlx, gsrq, kssj as dtkssj, jssj as dtjssj from uf_jcl_kq_bcxx_dt1 where mainid = " + bcId;
List<Map<String, Object>> bcDetailData = DbTools.getSqlToList(sql);
bcDetailData = bcDetailData.stream().filter(e -> countBdlxList.contains(Util.null2String(e.get("bdlx")))).collect(Collectors.toList());
//获取需要累计的班段时长区间和目标区间存在交集的分钟数,并与请假区间内的分钟数最比较
return overRangeMinutes == Utils.removeTime(startTime, endTime, bcDetailData, date);
}
}

@ -60,7 +60,7 @@ public class OvertimePlanServiceImpl extends Service implements OvertimePlanServ
//获取人员id和姓名信息
Map<String, String> empIdToNameInfo = CommonUtil.empIdToNameInfo(empIdList);
//获取目标人员列表已存在的加班计划
Map<String, List<Map<String, Object>>> existOvertimePlanInfo = getOvertimePlanInfo(empIdList, startDate);
Map<String, List<Map<String, Object>>> existOvertimePlanInfo = getOvertimePlanInfo(empIdList, DateUtil.beforeDay(startDate, 1));
List<Map<String, Object>> existOvertimePlanList = new ArrayList<>();
for (String empId : empIdList) {
@ -543,11 +543,20 @@ public class OvertimePlanServiceImpl extends Service implements OvertimePlanServ
}
/**
*
* ,20240830
*/
public List<Map<String, Object>> getWorkOverTimeResults(String startDate,String endDate,String userId){
String sql = "select a.sjjbsc, a.sjksrq, a.sjjsrq, a.jblx, b.hsdw from uf_jcl_kq_jbjg a left join uf_jcl_kq_kqxm b on a.jblx = b.id where a.jbry=? and a.sjksrq>=? and a.sjjsrq<=?";
List<Map<String, Object>> dataList = DbTools.getSqlToList(sql,userId,startDate,endDate);
return dataList;
String sql = "select a.sjjbsc, a.sjksrq, a.sjjsrq, a.jbjhid, a.jblx, b.hsdw from uf_jcl_kq_jbjg a left join uf_jcl_kq_kqxm b on a.jblx = b.id where a.zt != 2 and a.jbry=? and a.sjksrq>=? and a.sjjsrq<=?";
List<Map<String, Object>> jbjgDataList = DbTools.getSqlToList(sql,userId,startDate,endDate);
sql = "select b.jbsc as sjjbsc, b.ksrq as sjksrq, b.jsrq as sjjsrq, a.id as jbjhid, b.jblx, c.hsdw from uf_jcl_kq_jbjh a " +
"left join uf_jcl_kq_jbjh_dt1 b on a.id = b.mainid left join uf_jcl_kq_kqxm c on b.jblx = c.id where a.jlzt != 2 and b.jbry = ? and b.ksrq >= ? and b.jsrq <= ?";
List<Map<String, Object>> jbjhDataList = DbTools.getSqlToList(sql,userId,startDate,endDate);
//去除加班计划中数据已转换为加班结果的数据
Set<String> jbjhIds = jbjgDataList.stream().filter(f -> !"".equals(Util.null2String(f.get("jbjhid")))).map(e->e.get("jbjhid").toString()).collect(Collectors.toSet());
jbjhDataList = jbjhDataList.stream().filter(f -> !jbjhIds.contains(f.get("jbjhid").toString())).collect(Collectors.toList());
if (jbjhDataList.size() > 0) {
jbjgDataList.addAll(jbjhDataList);
}
return jbjgDataList;
}
}

Loading…
Cancel
Save