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.

1128 lines
69 KiB
Java

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

package com.engine.jucailinkq.attendance.attendanceanalysis.cmd.getclockInpoint;
import com.engine.jucailinkq.attendance.attendanceanalysis.dto.clockpoint.ClockPointDTO;
import com.engine.jucailinkq.attendance.enums.AccountingUnitEnum;
import com.engine.jucailinkq.attendance.enums.CheckBoxEnum;
import com.engine.jucailinkq.attendance.enums.ClassSegmentTypeEnum;
import com.engine.jucailinkq.attendance.enums.ClockPointEnum;
import com.engine.common.biz.AbstractCommonCommand;
import com.engine.common.entity.BizLogContext;
import com.engine.jucailinkq.common.util.DateUtil;
import com.engine.jucailinkq.common.util.Utils;
import com.engine.core.interceptor.CommandContext;
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.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* 根据卡点、打卡时间将卡点和打卡时间一一对应
*/
@Slf4j
public class GetClockInPointCmd extends AbstractCommonCommand<Map<String, Object>> {
public GetClockInPointCmd(Map<String, Object> params) {
this.params = params;
}
/**
* 需要打卡的卡点
*/
private List<String> needClockDateList;
/**
* 分析日期
*/
private String analysisDate;
@Override
public BizLogContext getLogContext() {
return null;
}
@Override
public Map<String, Object> execute(CommandContext commandContext) {
Map<String, Object> resultMap = Maps.newHashMap();
String analysisDate = Util.null2String(params.get("analysisDate"));
this.analysisDate=analysisDate;
List<Map<String, Object>> scheduleResult = (List<Map<String, Object>>) params.get("scheduleResult");
List<Map<String, Object>> clockInTimeList = (List<Map<String, Object>>) params.get("clockInTimeList");
List<Map<String, Object>> askForLeaveAndEvctionScheduleList = (List<Map<String, Object>>) params.get("askForLeaveAndEvctionSchedule");
List<Map<String, Object>> needClockInList = scheduleResult.stream().filter(e -> !ClassSegmentTypeEnum.REST_AND_DINE.getKey().equals(e.get("bdlx")) && !ClassSegmentTypeEnum.REST_PERIOD.getKey().equals(e.get("bdlx")) &&
!ClassSegmentTypeEnum.DINING_PERIOD.getKey().equals(e.get("bdlx")) ).collect(Collectors.toList());
log.debug("未重新计算卡点时 老的scheduleResult : [{}],askForLeaveAndEvctionScheduleList:[{}]",scheduleResult,askForLeaveAndEvctionScheduleList);
//调整加班计时间段的打卡
scheduleResult = adjustWorkOverTimeClock(scheduleResult,analysisDate);
//调整请假出差时间段的打卡
askForLeaveAndEvctionScheduleList = adjustAskforSchedule(scheduleResult,analysisDate,askForLeaveAndEvctionScheduleList);
log.debug("经过adjustWorkOverTimeClock 加班调整过后的 的scheduleResult: [{}]",scheduleResult);
/**
* 当请假或外出开始时间和外出时间在上班之外时,不需要打卡
*/
//判断是否骑在上班卡或下班卡
boolean ifStartNeedClock=false;
String startNeedClockTime = "";
boolean ifEndNeedClock=false;
String endNeedClockTime = "";
if (needClockInList.size() > 0 && askForLeaveAndEvctionScheduleList.size() > 0) {
String startTime = Utils.getkssjTime(needClockInList.get(0),analysisDate);
String endStartTime = Utils.getkssjTime(needClockInList.get(needClockInList.size()-1),analysisDate);
String endTime = Utils.getjssjTime(needClockInList.get(needClockInList.size()-1),analysisDate);
for (Map<String, Object> askForLeaveAndEvctionSchedule :askForLeaveAndEvctionScheduleList){
String dtkssj = Utils.getkssjTime(askForLeaveAndEvctionSchedule,analysisDate);
String dtjssj = Utils.getjssjTime(askForLeaveAndEvctionSchedule,analysisDate);
if (DateUtil.getTime(dtkssj).compareTo(DateUtil.getTime(startTime))<=0 || DateUtil.getTime(dtkssj).compareTo(DateUtil.getTime(endTime)) >= 0){
askForLeaveAndEvctionSchedule.put("ksdk",CheckBoxEnum.UNCHECKED.getKey());
}
if (DateUtil.getTime(dtjssj).compareTo(DateUtil.getTime(endTime))>=0 || DateUtil.getTime(dtjssj).compareTo(DateUtil.getTime(startTime))<=0){
askForLeaveAndEvctionSchedule.put("jsdk",CheckBoxEnum.UNCHECKED.getKey());
}
if (DateUtil.getTime(dtkssj).compareTo(DateUtil.getTime(startTime))<=0 && DateUtil.getTime(dtjssj).compareTo(DateUtil.getTime(endTime))<0 && DateUtil.getTime(dtjssj).compareTo(DateUtil.getTime(startTime)) >0){
//骑在开始上班时间
for (Map<String,Object> needClockMap:needClockInList){
String kssj = Utils.getkssjTime(needClockMap,analysisDate);
String jssj = Utils.getjssjTime(needClockMap,analysisDate);
//中间只要有开始打卡,即上班需要打卡
if (CheckBoxEnum.CHECKED.getKey().equals(needClockMap.get("ksdk")) && DateUtil.getTime(dtjssj).compareTo(DateUtil.getTime(jssj)) >=0){
ifStartNeedClock=true;
startNeedClockTime = dtjssj;
}
}
}
if (DateUtil.getTime(dtkssj).compareTo(DateUtil.getTime(startTime)) > 0 && DateUtil.getTime(dtjssj).compareTo(DateUtil.getTime(endTime))>=0 && DateUtil.getTime(dtkssj).compareTo(DateUtil.getTime(endTime)) < 0){
//骑在下班时间
for (Map<String,Object> needClockMap:needClockInList){
String kssj = Utils.getkssjTime(needClockMap,analysisDate);
//中间只要有结束打卡,即下班需要打卡
if (CheckBoxEnum.CHECKED.getKey().equals(needClockMap.get("jsdk")) && DateUtil.getTime(dtkssj).compareTo(DateUtil.getTime(kssj)) <=0){
ifEndNeedClock=true;
endNeedClockTime = dtkssj;
}
}
}
}
}
/**
* 当请假或外出包含打卡卡点时,判断该卡点是否需要打卡
*/
for (Map<String, Object> askForLeaveAndEvctionMap :askForLeaveAndEvctionScheduleList){
String evctiondtkssj = Utils.getkssjTime(askForLeaveAndEvctionMap,analysisDate);
String evctionksdk = Util.null2String(askForLeaveAndEvctionMap.get("ksdk"));
String evctiondtjssj = Utils.getjssjTime(askForLeaveAndEvctionMap,analysisDate);
String evctionjsdk = Util.null2String(askForLeaveAndEvctionMap.get("jsdk"));
String zysd = Util.null2String(askForLeaveAndEvctionMap.get("zysd"));
List<String> lists = Lists.newArrayList();
for (int i=0;i<scheduleResult.size();i++){
String dtkssj = Utils.getkssjTime(scheduleResult.get(i),analysisDate);
String dtjssj = Utils.getjssjTime(scheduleResult.get(i),analysisDate);
String bdlx = Util.null2String(scheduleResult.get(i).get("bdlx"));
if (zysd.contains(Utils.getWorkFor(bdlx))){
if (DateUtil.getTime(evctiondtkssj).compareTo(DateUtil.getTime(dtkssj)) <= 0 && DateUtil.getTime(evctiondtjssj).compareTo(DateUtil.getTime(dtkssj)) >=0
&& !ClassSegmentTypeEnum.REST_AND_DINE.getKey().equals(bdlx) && !ClassSegmentTypeEnum.REST_PERIOD.getKey().equals(bdlx) && !ClassSegmentTypeEnum.DINING_PERIOD.getKey().equals(bdlx)){
lists.add(dtkssj+"&"+ClockPointEnum.START.getKey()+"&"+Util.null2String(scheduleResult.get(i).get("ksdk")));
}
if (DateUtil.getTime(evctiondtkssj).compareTo(DateUtil.getTime(dtjssj)) <= 0 && DateUtil.getTime(evctiondtjssj).compareTo(DateUtil.getTime(dtjssj)) >=0
&& !ClassSegmentTypeEnum.REST_AND_DINE.getKey().equals(bdlx) && !ClassSegmentTypeEnum.REST_PERIOD.getKey().equals(bdlx) && !ClassSegmentTypeEnum.DINING_PERIOD.getKey().equals(bdlx)){
lists.add(dtjssj+"&"+ClockPointEnum.END.getKey()+"&"+Util.null2String(scheduleResult.get(i).get("jsdk")));
}
}
}
//新打卡
List<String> newNeedClockLists = Lists.newArrayList();
//时间-结束卡\开始卡-是否打卡
if (lists.size() == 1){
String str = lists.get(0);
if (ClockPointEnum.START.getKey().equals(str.split("&")[1]) && CheckBoxEnum.CHECKED.getKey().equals(evctionjsdk)){
newNeedClockLists.add(str.split("&")[0]+"&"+str.split("&")[1]+"&0");
}else if (ClockPointEnum.END.getKey().equals(str.split("&")[1]) && CheckBoxEnum.CHECKED.getKey().equals(evctionksdk)){
newNeedClockLists.add(str.split("&")[0]+"&"+str.split("&")[1]+"&0");
}
}else if (lists.size() > 1){
for(int i=0;i<lists.size();i++){
String str = lists.get(i);
if (i ==0){
if (CheckBoxEnum.CHECKED.getKey().equals(evctionksdk) || ClockPointEnum.START.getKey().equals(str.split("&")[1])){
newNeedClockLists.add(str.split("&")[0]+"&"+str.split("&")[1]+"&0");
}
}else if (i == lists.size()-1){
if (CheckBoxEnum.CHECKED.getKey().equals(evctionjsdk) || ClockPointEnum.END.getKey().equals(str.split("&")[1])){
newNeedClockLists.add(str.split("&")[0]+"&"+str.split("&")[1]+"&0");
}
}else {
newNeedClockLists.add(str.split("&")[0]+"&"+str.split("&")[1]+"&0");
}
}
}
for (int i=0;i<scheduleResult.size();i++){
String dtkssj = Utils.getkssjTime(scheduleResult.get(i),analysisDate);
String dtjssj = Utils.getjssjTime(scheduleResult.get(i),analysisDate);
for (String newNeedClock : newNeedClockLists){
if (ClockPointEnum.START.getKey().equals(newNeedClock.split("&")[1])){
if (newNeedClock.split("&")[0].equals(dtkssj)){
scheduleResult.get(i).put("ksdk",newNeedClock.split("&")[2]);
}
}else if (ClockPointEnum.END.getKey().equals(newNeedClock.split("&")[1])){
if (newNeedClock.split("&")[0].equals(dtjssj)){
scheduleResult.get(i).put("jsdk",newNeedClock.split("&")[2]);
}
}
}
}
}
if (askForLeaveAndEvctionScheduleList.size() > 0){
scheduleResult.addAll(askForLeaveAndEvctionScheduleList);
scheduleResult = scheduleResult.stream().sorted(Comparator.comparing(e->DateUtil.getTime(Utils.getkssjTime(e,analysisDate)).toInstant(ZoneOffset.of("+8")).toEpochMilli())).collect(Collectors.toList());
}
List<String> needClockDateList = Lists.newArrayList();
for (int i=0;i<scheduleResult.size();i++){
String dtkssj = Utils.getkssjTime(scheduleResult.get(i),analysisDate);
String dtjssj = Utils.getjssjTime(scheduleResult.get(i),analysisDate);
if (CheckBoxEnum.CHECKED.getKey().equals(scheduleResult.get(i).get("ksdk"))) {
needClockDateList.add(dtkssj);
}
if (CheckBoxEnum.CHECKED.getKey().equals(scheduleResult.get(i).get("jsdk"))){
needClockDateList.add(dtjssj);
}
}
/**
* 当请假时间或出差时间包含最早上班时间和最晚下班时间时,补偿机制
*/
if (needClockDateList.size() == 1){
for (int i=0;i<scheduleResult.size();i++){
String dtkssj = Utils.getkssjTime(scheduleResult.get(i),analysisDate);
String dtjssj = Utils.getjssjTime(scheduleResult.get(i),analysisDate);
String bdlx = Util.null2String(scheduleResult.get(i).get("bdlx"));
if (ifStartNeedClock && DateUtil.getTime(startNeedClockTime).compareTo(DateUtil.getTime(dtkssj)) >=0 &&
DateUtil.getTime(startNeedClockTime).compareTo(DateUtil.getTime(dtjssj)) <0 &&
!ClassSegmentTypeEnum.EVECTION.getKey().equals(bdlx) &&
!ClassSegmentTypeEnum.ASK_FOR_LEAVE.getKey().equals(bdlx)){
String firstKssj = Utils.getkssjTime(scheduleResult.get(0),analysisDate);
String kssj = Utils.getkssjTime(scheduleResult.get(i),analysisDate);
scheduleResult.get(i).put("ksdk",CheckBoxEnum.CHECKED.getKey());
scheduleResult.get(i).put("tqdkfzs",DateUtil.getBetWeenMinutes(firstKssj,kssj));
needClockDateList.add(0,dtkssj);
break;
}
if (ifEndNeedClock && DateUtil.getTime(endNeedClockTime).compareTo(DateUtil.getTime(dtkssj)) >0 &&
DateUtil.getTime(endNeedClockTime).compareTo(DateUtil.getTime(dtjssj)) <=0 &&
!ClassSegmentTypeEnum.EVECTION.getKey().equals(bdlx) &&
!ClassSegmentTypeEnum.ASK_FOR_LEAVE.getKey().equals(bdlx)){
String lastjssj = Utils.getjssjTime(scheduleResult.get(scheduleResult.size()-1),analysisDate);
String jssj = Utils.getjssjTime(scheduleResult.get(i),analysisDate);
scheduleResult.get(i).put("jsdk",CheckBoxEnum.CHECKED.getKey());
scheduleResult.get(i).put("thdkfzs",DateUtil.getBetWeenMinutes(jssj,lastjssj));
needClockDateList.add(dtjssj);
break;
}
}
}
needClockDateList = needClockDateList.stream().sorted(Comparator.comparing(e->DateUtil.getTime(e).toInstant(ZoneOffset.of("+8")).toEpochMilli())).collect(Collectors.toList());
this.needClockDateList=needClockDateList;
log.debug("经过重新计算卡点时 新的scheduleResult : [{}]",scheduleResult);
List<ClockPointDTO> clcokInPointList = getClockInPoint(analysisDate, scheduleResult, clockInTimeList,needClockDateList);
log.debug("clcokInPointList :[{}]",clcokInPointList);
resultMap.put("clcokInPointList", clcokInPointList);
resultMap.put("scheduleResult",scheduleResult);
resultMap.put("clockInTimeList",clockInTimeList);
resultMap.put("needClockDateList",needClockDateList);
resultMap.put("askForLeaveAndEvctionScheduleList",askForLeaveAndEvctionScheduleList);
return resultMap;
}
/**
* 获取打卡卡点
*
* @param analysisDate 分析日期
* @param scheduleResult 需要打卡的班次
* @param clockInTimeList 打卡集合
* @param needClockDateList 需要打卡的时间点
* @return clcokInTimeData 卡点集合
*/
public List<ClockPointDTO> getClockInPoint(String analysisDate, List<Map<String, Object>> scheduleResult, List<Map<String, Object>> clockInTimeList, List<String> needClockDateList) {
/**卡点集合*/
List<ClockPointDTO> clcokInTimeData = Lists.newArrayList();
List<Map<String, Object>> restScheduleList = scheduleResult.stream().filter(e -> (ClassSegmentTypeEnum.REST_AND_DINE.getKey().equals(e.get("bdlx")) || ClassSegmentTypeEnum.REST_PERIOD.getKey().equals(e.get("bdlx"))
|| ClassSegmentTypeEnum.DINING_PERIOD.getKey().equals(e.get("bdlx"))) && CheckBoxEnum.CHECKED.getKey().equals(e.get("dtsfdx"))).collect(Collectors.toList());
for (Map<String, Object> needClockIn : scheduleResult) {
/**非请假外出开始打卡逻辑处理*/
if (CheckBoxEnum.CHECKED.getKey().equals(needClockIn.get("ksdk")) && !ClassSegmentTypeEnum.EVECTION.getKey().equals(needClockIn.get("bdlx")) &&
!ClassSegmentTypeEnum.ASK_FOR_LEAVE.getKey().equals(needClockIn.get("bdlx"))) {
String dtkssj = Utils.getkssjTime(needClockIn,analysisDate);
Map<ClockPointEnum, Map<String, Object>> ksdkNearestClcokInTime = Utils.getNearestClcokInTimeCmd(dtkssj, clockInTimeList);
ClockPointEnum timeType = getStartClassTimeType(needClockIn,ksdkNearestClcokInTime,dtkssj,dtkssj);
clcokInTimeData.add(ClockPointDTO.builder().classTime(dtkssj).pointType(ClockPointEnum.START).timeType(timeType).record(true).classSegmentType(needClockIn.get("bdlx").toString()).clockTime(ksdkNearestClcokInTime.get(timeType)).build());
}
/**非请假外出结束打卡逻辑处理*/
if (CheckBoxEnum.CHECKED.getKey().equals(needClockIn.get("jsdk")) && !ClassSegmentTypeEnum.EVECTION.getKey().equals(needClockIn.get("bdlx")) &&
!ClassSegmentTypeEnum.ASK_FOR_LEAVE.getKey().equals(needClockIn.get("bdlx"))) {
String dtjssj = Utils.getjssjTime(needClockIn,analysisDate);
Map<ClockPointEnum, Map<String, Object>> jsdkNearestClcokInTime = Utils.getNearestClcokInTimeCmd(dtjssj, clockInTimeList);
ClockPointEnum timeType = getEndClassTimeType(needClockIn,jsdkNearestClcokInTime,dtjssj,dtjssj);
clcokInTimeData.add(ClockPointDTO.builder().classTime(dtjssj).pointType(ClockPointEnum.END).timeType(timeType).record(true).classSegmentType(needClockIn.get("bdlx").toString()).clockTime(jsdkNearestClcokInTime.get(timeType)).build());
}
/**
* 请假外出的开始打卡处理
*/
if (CheckBoxEnum.CHECKED.getKey().equals(needClockIn.get("ksdk")) && (ClassSegmentTypeEnum.EVECTION.getKey().equals(needClockIn.get("bdlx")) ||
ClassSegmentTypeEnum.ASK_FOR_LEAVE.getKey().equals(needClockIn.get("bdlx")))){
String dtkssj = Utils.getkssjTime(needClockIn,analysisDate);
Map<ClockPointEnum, Map<String, Object>> jsdkNearestClcokInTime = Utils.getNearestClcokInTimeCmd(dtkssj, clockInTimeList);
ClockPointEnum timeType = getEndClassTimeType(needClockIn,jsdkNearestClcokInTime,dtkssj,dtkssj);
clcokInTimeData.add(ClockPointDTO.builder().classTime(dtkssj).pointType(ClockPointEnum.END).record(true).timeType(timeType).classSegmentType(needClockIn.get("bdlx").toString()).clockTime(jsdkNearestClcokInTime.get(timeType)).build());
}
/**
* 请假外出的结束打卡处理
*/
if (CheckBoxEnum.CHECKED.getKey().equals(needClockIn.get("jsdk")) && (ClassSegmentTypeEnum.EVECTION.getKey().equals(needClockIn.get("bdlx")) ||
ClassSegmentTypeEnum.ASK_FOR_LEAVE.getKey().equals(needClockIn.get("bdlx")))){
String dtjssj = Utils.getjssjTime(needClockIn,analysisDate);
Map<ClockPointEnum, Map<String, Object>> ksdkNearestClcokInTime = Utils.getNearestClcokInTimeCmd(dtjssj, clockInTimeList);
ClockPointEnum timeType = getStartClassTimeType(needClockIn,ksdkNearestClcokInTime,dtjssj,dtjssj);
clcokInTimeData.add(ClockPointDTO.builder().classTime(dtjssj).pointType(ClockPointEnum.START).record(true).timeType(timeType).classSegmentType(needClockIn.get("bdlx").toString()).clockTime(ksdkNearestClcokInTime.get(timeType)).build());
}
}
//根据班次时间排序
clcokInTimeData = clcokInTimeData.stream().sorted(Comparator.comparing(e-> DateUtil.getTime(e.getClassTime()).toInstant(ZoneOffset.of("+8")).toEpochMilli())).collect(Collectors.toList());
/**
* 计算弹性上下班
*/ //上下班弹性,
flexibleWork(clcokInTimeData,scheduleResult);
/**
* 计算休息时间段的弹性上下班
*/
if (restScheduleList.size() > 0){
flexibleRestClass(restScheduleList,clcokInTimeData,scheduleResult);
}
/**
* 当有2笔需要打卡时可能会有打卡歧义的情况歧义情况取2个时间点的中间值当打卡时间小于中间值归属前一个打卡大于则相反
*/
if (clcokInTimeData.size() > 1) {
for (int i = 0; i < clcokInTimeData.size() - 1; i++) {
ClockPointDTO beforeClcokDTO = clcokInTimeData.get(i);
ClockPointDTO afterClcokInDTO = clcokInTimeData.get(i + 1);
Map<String, Object> beforeClcokInTimeMap = beforeClcokDTO.getClockTime();
Map<String, Object> afterClcokInTimeMap = afterClcokInDTO.getClockTime();
//重复
if (beforeClcokInTimeMap != null && beforeClcokInTimeMap == afterClcokInTimeMap) {
String beforeTime = beforeClcokDTO.getClassTime();
if (beforeClcokDTO.getElasticTime() != null && !"".equals(beforeClcokDTO.getElasticTime())){
beforeTime = beforeClcokDTO.getElasticTime();
}
String afterTime = afterClcokInDTO.getClassTime();
if (afterClcokInDTO.getElasticTime() != null && !"".equals(afterClcokInDTO.getElasticTime())){
afterTime = afterClcokInDTO.getElasticTime();
}
long betWeenMinutes = DateUtil.getBetWeenMinutes(beforeTime, afterTime);
String middileTime = DateUtil.AfterMinutes(beforeTime, betWeenMinutes / 2);
String signdateTime = beforeClcokInTimeMap.get("signdate") + " " + beforeClcokInTimeMap.get("signtime");
ClockPointDTO resetClcokDTO =null;
if (DateUtil.getTime(signdateTime).compareTo(DateUtil.getTime(middileTime)) <= 0) {
//该打卡归属前一个打卡点,后一个打卡点需要重新设置
resetClcokDTO=afterClcokInDTO;
} else if (DateUtil.getTime(signdateTime).compareTo(DateUtil.getTime(middileTime)) > 0) {
//该打卡归属后一个打卡点,前一个打卡点需要重新设置
resetClcokDTO=beforeClcokDTO;
}
//需要重新赋值的打卡时间
String restTime = resetClcokDTO.getClassTime();
if (resetClcokDTO.getElasticTime() != null && !"".equals(resetClcokDTO.getElasticTime())){
restTime = resetClcokDTO.getElasticTime();
}
Map<ClockPointEnum, Map<String, Object>> nearestClcokInTime = Utils.getNearestClcokInTimeCmd(restTime, clockInTimeList);
//start开始打卡时间点end结束打卡时间点
ClockPointEnum pointType = resetClcokDTO.getPointType();
//empty:漏卡equal:打卡时间和班次时间相等before打卡时间在班次时间之前after打卡时间在班次时间之后
ClockPointEnum timeType = resetClcokDTO.getTimeType();
String time = resetClcokDTO.getClassTime();
ClockPointEnum newtimeType = null;
if (timeType.equals(ClockPointEnum.BEFORE)){
newtimeType = ClockPointEnum.AFTER;
}else if (timeType.equals(ClockPointEnum.AFTER)){
newtimeType = ClockPointEnum.BEFORE;
}
if (nearestClcokInTime.get(newtimeType) != null){
Map<String, Object> newClockTimeMap = nearestClcokInTime.get(newtimeType);
String newClockTime = newClockTimeMap.get("signdate")+ " "+newClockTimeMap.get("signtime");
int index = clcokInTimeData.indexOf(resetClcokDTO);
if (newtimeType.equals(ClockPointEnum.BEFORE)){
if (!getBeforeClockTime(needClockDateList,restTime).equals("") && DateUtil.getTime(newClockTime).compareTo(DateUtil.getTime(getBeforeClockTime(needClockDateList,restTime))) <= 0){
newClockTimeMap = null;
}
if ((index-1) >= 0){
//当重新需要打卡的时间戳与打卡时间之前的打卡集合时,进行比对
ClockPointDTO resetBeforeDTO = clcokInTimeData.get(index-1);
Map<String, Object> resetBeforeClcokInTimeMap = resetBeforeDTO.getClockTime();
if (newClockTimeMap == resetBeforeClcokInTimeMap){
newClockTimeMap = null;
}
}
}else if (newtimeType.equals(ClockPointEnum.AFTER)){
if (!getNextClockTime(needClockDateList,restTime).equals("") && DateUtil.getTime(newClockTime).compareTo(DateUtil.getTime(getNextClockTime(needClockDateList,restTime))) >= 0){
newClockTimeMap = null;
}
}
if (newClockTimeMap == null){
//当需要调整的卡点为漏卡时将打卡进行退回,若另一个卡点调整后为不漏卡情况,则调整该节点
if (resetClcokDTO == beforeClcokDTO){
resetClcokDTO=afterClcokInDTO;
}else if (resetClcokDTO == afterClcokInDTO){
resetClcokDTO=beforeClcokDTO;
}
if (!resetClcokInTimeData(analysisDate,resetClcokDTO,clockInTimeList,needClockDateList,clcokInTimeData,scheduleResult)){
if (resetClcokDTO == beforeClcokDTO){
resetClcokDTO = afterClcokInDTO;
}else if (resetClcokDTO == afterClcokInDTO){
resetClcokDTO = beforeClcokDTO;
}
if (newClockTimeMap == null){
resetClcokDTO.setTimeType(ClockPointEnum.EMPTY);
}else {
resetClcokDTO.setTimeType(newtimeType);
}
resetClcokDTO.setClockTime(newClockTimeMap);
}
}else {
if (newClockTimeMap == null){
resetClcokDTO.setTimeType(ClockPointEnum.EMPTY);
}else {
resetClcokDTO.setTimeType(newtimeType);
}
resetClcokDTO.setClockTime(newClockTimeMap);
}
}else {
if (resetClcokDTO == beforeClcokDTO){
resetClcokDTO = afterClcokInDTO;
}else if (resetClcokDTO == afterClcokInDTO){
resetClcokDTO = beforeClcokDTO;
}
if (!resetClcokInTimeData(analysisDate,resetClcokDTO,clockInTimeList,needClockDateList,clcokInTimeData,scheduleResult)){
if (resetClcokDTO == beforeClcokDTO){
resetClcokDTO = afterClcokInDTO;
}else if (resetClcokDTO == afterClcokInDTO){
resetClcokDTO = beforeClcokDTO;
}
resetClcokDTO.setClockTime(null);
resetClcokDTO.setTimeType(ClockPointEnum.EMPTY);
}
}
}
}
}
return clcokInTimeData;
}
public boolean resetClcokInTimeData(String analysisDate,ClockPointDTO resetClcokDTO,List<Map<String, Object>> clockInTimeList, List<String> needClockDateList,List<ClockPointDTO> clcokInTimeData,List<Map<String, Object>> scheduleResult){
String restTime = resetClcokDTO.getClassTime();
if (resetClcokDTO.getElasticTime() != null && !"".equals(resetClcokDTO.getElasticTime())){
restTime = resetClcokDTO.getElasticTime();
}
Map<ClockPointEnum, Map<String, Object>> nearestClcokInTime = Utils.getNearestClcokInTimeCmd(restTime, clockInTimeList);
//start开始打卡时间点end结束打卡时间点
ClockPointEnum pointType = resetClcokDTO.getPointType();
//empty:漏卡equal:打卡时间和班次时间相等before打卡时间在班次时间之前after打卡时间在班次时间之后
ClockPointEnum timeType = resetClcokDTO.getTimeType();
String time = resetClcokDTO.getClassTime();
ClockPointEnum newtimeType = null;
if (timeType.equals(ClockPointEnum.BEFORE)){
newtimeType = ClockPointEnum.AFTER;
}else if (timeType.equals(ClockPointEnum.AFTER)){
newtimeType = ClockPointEnum.BEFORE;
}
if (nearestClcokInTime.get(newtimeType) != null){
Map<String, Object> newClockTimeMap = nearestClcokInTime.get(newtimeType);
String newClockTime = newClockTimeMap.get("signdate")+ " "+newClockTimeMap.get("signtime");
int index = clcokInTimeData.indexOf(resetClcokDTO);
if (newtimeType.equals(ClockPointEnum.BEFORE)){
if (pointType.equals(ClockPointEnum.START)){
//开始卡点
Map<String,Object> needClockIn = scheduleResult.stream().filter(e -> {
String dtkssj = Utils.getkssjTime(e,analysisDate);
if (Utils.ifAskforOrEvctionClassSegment(e.get("bdlx").toString())){
dtkssj = Utils.getjssjTime(e,analysisDate);
}
if (time.equals(dtkssj)){
return true;
}else {
return false;
}
}).collect(Collectors.toList()).get(0);
//计算最大提前打卡分钟数
int tqdkfzs = 60;
if (Util.null2String(needClockIn.get("tqdkfzs")).equals("") && !"".equals(getBeforeClockTime(needClockDateList,restTime))){
tqdkfzs = DateUtil.getBetWeenMinutes(getBeforeClockTime(needClockDateList,restTime),restTime);
}else {
tqdkfzs = Util.null2String(needClockIn.get("tqdkfzs")).equals("")?60:Integer.valueOf(needClockIn.get("tqdkfzs").toString());
}
if (DateUtil.getTime(newClockTime).compareTo(DateUtil.getTime(DateUtil.beforeMinutes(restTime, tqdkfzs))) < 0){
newClockTimeMap =null;
}
}
if (!getBeforeClockTime(needClockDateList,restTime).equals("") && DateUtil.getTime(newClockTime).compareTo(DateUtil.getTime(getBeforeClockTime(needClockDateList,restTime))) <= 0){
newClockTimeMap = null;
}
if ((index-1) >= 0){
//当重新需要打卡的时间戳与打卡时间之前的打卡集合时,进行比对
ClockPointDTO resetBeforeDTO = clcokInTimeData.get(index-1);
Map<String, Object> resetBeforeClcokInTimeMap = resetBeforeDTO.getClockTime();
if (newClockTimeMap == resetBeforeClcokInTimeMap){
newClockTimeMap = null;
}
}
}else if (newtimeType.equals(ClockPointEnum.AFTER)){
if (pointType.equals(ClockPointEnum.END)){
//结束卡点
Map<String,Object> needClockIn = scheduleResult.stream().filter(e -> {
String dtjssj = Utils.getjssjTime(e,analysisDate);
if (Utils.ifAskforOrEvctionClassSegment(e.get("bdlx").toString())){
dtjssj = Utils.getkssjTime(e,analysisDate);
}
if (time.equals(dtjssj)){
return true;
}else {
return false;
}
}).collect(Collectors.toList()).get(0);
//计算最大退后打卡分钟数
int thdkfzs = 60;
if (Util.null2String(needClockIn.get("thdkfzs")).equals("") && !"".equals(getNextClockTime(needClockDateList,restTime))){
thdkfzs = DateUtil.getBetWeenMinutes(restTime,getNextClockTime(needClockDateList,restTime));
}else {
thdkfzs = Util.null2String(needClockIn.get("thdkfzs")).equals("")?60:Integer.valueOf(needClockIn.get("thdkfzs").toString());
}
if (DateUtil.getTime(newClockTime).compareTo(DateUtil.getTime(DateUtil.AfterMinutes(restTime, thdkfzs))) > 0){
newClockTimeMap = null;
}
}
if (!getNextClockTime(needClockDateList,restTime).equals("") && DateUtil.getTime(newClockTime).compareTo(DateUtil.getTime(getNextClockTime(needClockDateList,restTime))) >= 0){
newClockTimeMap = null;
}
}
if (newClockTimeMap != null){
resetClcokDTO.setTimeType(newtimeType);
resetClcokDTO.setClockTime(newClockTimeMap);
return true;
}
}
return false;
}
/**
* 连续两上上班段(正常工作、班段上加班、加班计划)如果上一个结束与下一个开始都需要打卡,则两个都调整来不需要打卡
* @param scheduleResult
* @return
*/
public List<Map<String, Object>> adjustWorkOverTimeClock(List<Map<String, Object>> scheduleResult,String analysisDate){
List<Map<String, Object>> workscheduleList = scheduleResult.stream().filter(e->!Utils.ifRestClassSegment(e.get("bdlx").toString())).collect(Collectors.toList());
List<Map<String, Object>> restscheduleList = scheduleResult.stream().filter(e->Utils.ifRestClassSegment(e.get("bdlx").toString())).collect(Collectors.toList());
workscheduleList = workscheduleList.stream().sorted(Comparator.comparing(e->DateUtil.getTime(Utils.getkssjTime(e,analysisDate)).toInstant(ZoneOffset.of("+8")).toEpochMilli())).collect(Collectors.toList());
for (int i=0;i<workscheduleList.size();i++){
Map<String, Object> scheduleMap = workscheduleList.get(i);
if (scheduleMap.get("bdlx").equals(ClassSegmentTypeEnum.OVERTIME_PLAN.getKey())){
String kssj = Utils.getkssjTime(scheduleMap,analysisDate);
String jssj = Utils.getjssjTime(scheduleMap,analysisDate);
Map<String, Object> beforeScheduleMap = i-1 >=0?workscheduleList.get(i-1):null;
Map<String, Object> afterScheduleMap = i+1 <=workscheduleList.size()-1?workscheduleList.get(i+1):null;
if (beforeScheduleMap != null && afterScheduleMap != null && ifWorkClassSegment(beforeScheduleMap.get("bdlx").toString()) &&
ifWorkClassSegment(afterScheduleMap.get("bdlx").toString())){
//加班计划处在工作中间,休息时段加班
String beforejssj = Utils.getjssjTime(beforeScheduleMap,analysisDate);
String afterkssj = Utils.getkssjTime(afterScheduleMap,analysisDate);
if (DateUtil.getTime(kssj).compareTo(DateUtil.getTime(beforejssj)) == 0){
beforeScheduleMap.put("jsdk",CheckBoxEnum.UNCHECKED.getKey());
scheduleMap.put("ksdk",CheckBoxEnum.UNCHECKED.getKey());
beforeScheduleMap.put("jsdk",CheckBoxEnum.UNCHECKED.getKey());
}
if (DateUtil.getTime(jssj).compareTo(DateUtil.getTime(afterkssj)) == 0){
scheduleMap.put("jsdk",CheckBoxEnum.UNCHECKED.getKey());
afterScheduleMap.put("ksdk",CheckBoxEnum.UNCHECKED.getKey());
}
}else {
if (beforeScheduleMap != null){
String beforejssj = Utils.getjssjTime(beforeScheduleMap,analysisDate);
if (DateUtil.getTime(kssj).compareTo(DateUtil.getTime(beforejssj)) == 0 && ifWorkClassSegment(beforeScheduleMap.get("bdlx").toString()) &&
scheduleMap.get("jsdk").equals(CheckBoxEnum.CHECKED.getKey())){
scheduleMap.put("ksdk",CheckBoxEnum.UNCHECKED.getKey());
beforeScheduleMap.put("jsdk",CheckBoxEnum.UNCHECKED.getKey());
}
if (DateUtil.getTime(kssj).compareTo(DateUtil.getTime(beforejssj)) == 0 && ifWorkClassSegment(beforeScheduleMap.get("bdlx").toString()) &&
scheduleMap.get("jsdk").equals(CheckBoxEnum.UNCHECKED.getKey()) && scheduleMap.get("ksdk").equals(CheckBoxEnum.CHECKED.getKey()) &&
beforeScheduleMap.get("jsdk").equals(CheckBoxEnum.CHECKED.getKey())){
scheduleMap.put("ksdk",CheckBoxEnum.UNCHECKED.getKey());
}
if (DateUtil.getTime(kssj).compareTo(DateUtil.getTime(beforejssj)) == 0 && ifWorkClassSegment(beforeScheduleMap.get("bdlx").toString()) &&
scheduleMap.get("jsdk").equals(CheckBoxEnum.UNCHECKED.getKey()) && scheduleMap.get("ksdk").equals(CheckBoxEnum.UNCHECKED.getKey()) &&
beforeScheduleMap.get("jsdk").equals(CheckBoxEnum.CHECKED.getKey())){
int thdkfzs = DateUtil.getBetWeenMinutes(Utils.getjssjTime(beforeScheduleMap,analysisDate),Utils.getjssjTime(scheduleMap,analysisDate))+Integer.valueOf(beforeScheduleMap.get("thdkfzs").toString());
beforeScheduleMap.put("thdkfzs",thdkfzs);
}
}
if (afterScheduleMap != null){
String afterkssj = Utils.getkssjTime(afterScheduleMap,analysisDate);
if (DateUtil.getTime(jssj).compareTo(DateUtil.getTime(afterkssj)) == 0 && ifWorkClassSegment(afterScheduleMap.get("bdlx").toString()) &&
scheduleMap.get("ksdk").equals(CheckBoxEnum.CHECKED.getKey())){
scheduleMap.put("jsdk",CheckBoxEnum.UNCHECKED.getKey());
afterScheduleMap.put("ksdk",CheckBoxEnum.UNCHECKED.getKey());
}
if (DateUtil.getTime(jssj).compareTo(DateUtil.getTime(afterkssj)) == 0 && ifWorkClassSegment(afterScheduleMap.get("bdlx").toString()) &&
scheduleMap.get("ksdk").equals(CheckBoxEnum.UNCHECKED.getKey()) &&scheduleMap.get("jsdk").equals(CheckBoxEnum.CHECKED.getKey()) &&
afterScheduleMap.get("ksdk").equals(CheckBoxEnum.CHECKED.getKey())){
scheduleMap.put("jsdk",CheckBoxEnum.UNCHECKED.getKey());
}
if (DateUtil.getTime(jssj).compareTo(DateUtil.getTime(afterkssj)) == 0 && ifWorkClassSegment(afterScheduleMap.get("bdlx").toString()) &&
scheduleMap.get("ksdk").equals(CheckBoxEnum.UNCHECKED.getKey()) &&scheduleMap.get("jsdk").equals(CheckBoxEnum.UNCHECKED.getKey()) &&
afterScheduleMap.get("ksdk").equals(CheckBoxEnum.CHECKED.getKey())){
int tqdkfzs = DateUtil.getBetWeenMinutes(Utils.getkssjTime(scheduleMap,analysisDate),Utils.getkssjTime(afterScheduleMap,analysisDate))+Integer.valueOf(afterScheduleMap.get("tqdkfzs").toString());
afterScheduleMap.put("tqdkfzs",tqdkfzs);
}
}
}
}
}
List<Map<String, Object>> newList = Lists.newArrayList();
newList.addAll(workscheduleList);
newList.addAll(restscheduleList);
newList = newList.stream().sorted(Comparator.comparing(e->DateUtil.getTime(Utils.getkssjTime(e,analysisDate)).toInstant(ZoneOffset.of("+8")).toEpochMilli())).collect(Collectors.toList());
return newList;
}
/**
* 请假出差碰到休息时段时调整打卡
* @param scheduleResult
* @param analysisDate
* @param askForLeaveAndEvctionScheduleList
* @return
*/
public List<Map<String, Object>> adjustAskforSchedule(List<Map<String, Object>> scheduleResult,String analysisDate,List<Map<String, Object>> askForLeaveAndEvctionScheduleList){
List<Map<String, Object>> restscheduleList = scheduleResult.stream().filter(e->Utils.ifRestClassSegment(e.get("bdlx").toString())).collect(Collectors.toList());
List<Map<String, Object>> newList = Lists.newArrayList();
if (askForLeaveAndEvctionScheduleList.size()>1){
askForLeaveAndEvctionScheduleList = askForLeaveAndEvctionScheduleList.stream().sorted(Comparator.comparing(e->DateUtil.getTime(Utils.getkssjTime(e,analysisDate)).toInstant(ZoneOffset.of("+8")).toEpochMilli())).collect(Collectors.toList());
for (int i = 0; i < askForLeaveAndEvctionScheduleList.size() - 1; i++) {
String beforeDtkssj = Utils.getkssjTime(askForLeaveAndEvctionScheduleList.get(i),analysisDate);
String beforeDtjssj = Utils.getjssjTime(askForLeaveAndEvctionScheduleList.get(i),analysisDate);
String afterDtkssj = Utils.getkssjTime(askForLeaveAndEvctionScheduleList.get(i+1),analysisDate);
String afterDtjssj= Utils.getkssjTime(askForLeaveAndEvctionScheduleList.get(i+1),analysisDate);
List<Map<String, Object>> occupyRestSchedule = restscheduleList.stream().filter(e->DateUtil.getTime(Utils.getkssjTime(e,analysisDate)).compareTo(DateUtil.getTime(beforeDtjssj))<=0 &&
DateUtil.getTime(Utils.getjssjTime(e,analysisDate)).compareTo(DateUtil.getTime(beforeDtjssj)) >= 0).collect(Collectors.toList());
if (occupyRestSchedule.size() > 0 && DateUtil.getTime(Utils.getjssjTime(occupyRestSchedule.get(0),analysisDate)).compareTo(DateUtil.getTime(afterDtkssj)) >=0){
askForLeaveAndEvctionScheduleList.get(i).put("jsdk",CheckBoxEnum.UNCHECKED.getKey());
askForLeaveAndEvctionScheduleList.get(i+1).put("ksdk",CheckBoxEnum.UNCHECKED.getKey());
}
}
newList=askForLeaveAndEvctionScheduleList;
}else {
newList = askForLeaveAndEvctionScheduleList;
}
return newList;
}
/**
* 早晚上下班弹性
*/
public void flexibleWork(List<ClockPointDTO> clcokInTimeData,List<Map<String, Object>> scheduleResult){
List<Map<String, Object>> clockInTimeList = (List<Map<String, Object>>) params.get("clockInTimeList");
List<Map<String, Object>> workScheduleList = scheduleResult.stream().filter(e -> ClassSegmentTypeEnum.WORK_TIME.getKey().equals(e.get("bdlx")) || ClassSegmentTypeEnum.EARLY_OVERTIME.getKey().equals(e.get("bdlx"))).collect(Collectors.toList());
if (scheduleResult.size() > 0 && workScheduleList.size()>0) {
//请假和外出集合
List<Map<String, Object>> leaveAndEvctionList = scheduleResult.stream().filter(e -> ClassSegmentTypeEnum.ASK_FOR_LEAVE.getKey().equals(e.get("bdlx")) ||
ClassSegmentTypeEnum.EVECTION.getKey().equals(e.get("bdlx"))).collect(Collectors.toList());
//是否弹性
String sfdx = Util.null2String(workScheduleList.get(0).get("sfdx"));
//上班是否需要打卡
String ifToWorkClock = Util.null2String(workScheduleList.get(0).get("ksdk"));
//下班是否需要打卡
String ifToCloseClock = Util.null2String(workScheduleList.get(workScheduleList.size()-1).get("jsdk"));
//第一条工作时段、早上加班
if (workScheduleList.size() > 0 && CheckBoxEnum.CHECKED.getKey().equals(sfdx)) {
//最大弹性分钟
int zddxfz = Integer.valueOf(Util.null2String(workScheduleList.get(0).get("zddxfz")));
//弹性核算
int dxhs = Integer.valueOf(Util.null2String(workScheduleList.get(0).get("dxhs")));
Map<String, Object> ksdkMap = workScheduleList.get(0);
//最早上班时间
String kssjStart = Utils.getkssjTime(ksdkMap,analysisDate);
Map<String, Object> jsdkMap = workScheduleList.get(workScheduleList.size() - 1);
//最晚下班时间
int thdkfzs = Integer.valueOf(Util.null2String(jsdkMap.get("thdkfzs")).equals("")?"60":Util.null2String(jsdkMap.get("thdkfzs")));
String jssjEnd = Utils.getjssjTime(jsdkMap,analysisDate);
//弹性上班时间
String flexibleWorkTime = "";
//弹性下班时间
String flexibleOffWorkTime="";
if (leaveAndEvctionList.size() >0){
//第一笔请假、外出时间
Map<String, Object> leaveAndEvctionMap = leaveAndEvctionList.get(0);
String leaveAndEvctionkssj = Utils.getkssjTime(leaveAndEvctionMap,analysisDate);
//最大开始弹性时间
String minkssjStart = DateUtil.beforeMinutes(kssjStart,zddxfz);
String maxkssjStart = DateUtil.AfterMinutes(kssjStart,zddxfz);
//请假开始时间在最大开始弹性时间之内
if (DateUtil.getTime(leaveAndEvctionkssj).compareTo(DateUtil.getTime(maxkssjStart))<=0){
//弹性上班卡
flexibleWorkTime = leaveAndEvctionkssj;
if (DateUtil.getTime(leaveAndEvctionkssj).compareTo(DateUtil.getTime(minkssjStart)) <0){
flexibleWorkTime=minkssjStart;
}
//弹性下班时间点
int betweenToWorkTime = DateUtil.getBetWeenMinutes(flexibleWorkTime, kssjStart);
//弹性下班时间点
flexibleOffWorkTime = jssjEnd;
if (betweenToWorkTime >= 0) {
flexibleOffWorkTime = DateUtil.beforeMinutes(flexibleOffWorkTime, Math.abs(betweenToWorkTime));
} else if (betweenToWorkTime < 0) {
flexibleOffWorkTime = DateUtil.AfterMinutes(flexibleOffWorkTime, Math.abs(betweenToWorkTime));
}
}
}
//弹性上班卡
for (int i = 0; i < clcokInTimeData.size(); i++) {
ClockPointDTO clockdto = clcokInTimeData.get(i);
//需要计算的班次打卡时间点
String pointTime = clockdto.getClassTime();
//start开始打卡时间点end结束打卡时间点
ClockPointEnum pointType = clockdto.getPointType();
//重新获取最早上班时间
Map<ClockPointEnum, Map<String, Object>> startNearestClcokInTime = Utils.getNearestClcokInTimeCmd(DateUtil.beforeMinutes(clockdto.getClassTime(),zddxfz), clockInTimeList);
ClockPointEnum timeType = getStartClassTimeType(ksdkMap,startNearestClcokInTime,kssjStart,DateUtil.beforeMinutes(kssjStart,zddxfz));
clockdto.setTimeType(timeType);
clockdto.setClockTime(startNearestClcokInTime.get(timeType));
Map<String, Object> clcokInTime = clockdto.getClockTime();
if (pointTime.equals(kssjStart) && ClockPointEnum.START.equals(pointType) && clcokInTime != null
&& CheckBoxEnum.CHECKED.getKey().equals(ifToWorkClock)) {
//该卡点是弹性开始时间
//弹性上班期间未被请假开始时间占据
if ("".equals(flexibleWorkTime) ){
String signTime = clcokInTime.get("signdate") + " " + clcokInTime.get("signtime");
if (ClockPointEnum.BEFORE.equals(timeType)) {
int betWeenTime = DateUtil.getBetWeenMinutes(signTime, kssjStart);
if (betWeenTime <= zddxfz) {
betWeenTime = Double.valueOf(Utils.getItemdurationDown(dxhs, AccountingUnitEnum.MINUTES.getKey(), betWeenTime, AccountingUnitEnum.MINUTES)).intValue();
flexibleWorkTime = DateUtil.beforeMinutes(kssjStart, betWeenTime);
clockdto.setTimeType(ClockPointEnum.EQUAL);
} else if (betWeenTime > zddxfz) {
flexibleWorkTime = DateUtil.beforeMinutes(kssjStart, zddxfz);
}
clockdto.setElasticTime(flexibleWorkTime);
} else if (ClockPointEnum.AFTER.equals(timeType)) {
//迟到
int betWeenTime = DateUtil.getBetWeenMinutes(kssjStart, signTime);
if (betWeenTime <= zddxfz) {
betWeenTime = Double.valueOf(Utils.getItemduration(dxhs, AccountingUnitEnum.MINUTES.getKey(), betWeenTime, AccountingUnitEnum.MINUTES,Double.valueOf(scheduleResult.get(0).get("edsc").toString()))).intValue();
flexibleWorkTime = DateUtil.AfterMinutes(kssjStart, betWeenTime);
clockdto.setTimeType(ClockPointEnum.EQUAL);
} else if (betWeenTime > zddxfz) {
flexibleWorkTime = DateUtil.AfterMinutes(kssjStart, zddxfz);
}
clockdto.setElasticTime(flexibleWorkTime);
}
}else {
//弹性上班期间被请假开始时间占据
clockdto.setElasticTime(flexibleWorkTime);
}
//重新设置打卡时间
int startWorkIndex = needClockDateList.indexOf(kssjStart);
needClockDateList.remove(startWorkIndex);
needClockDateList.add(startWorkIndex,clockdto.getElasticTime());
} else if (pointTime.equals(jssjEnd) && ClockPointEnum.END.equals(pointType) && CheckBoxEnum.CHECKED.getKey().equals(ifToCloseClock)) {
//该卡点是弹性下班点
if ("".equals(flexibleOffWorkTime) && !"".equals(flexibleWorkTime)){
int betweenToWorkTime = DateUtil.getBetWeenMinutes(flexibleWorkTime, kssjStart);
//弹性下班时间点
flexibleOffWorkTime = jssjEnd;
if (betweenToWorkTime >= 0) {
flexibleOffWorkTime = DateUtil.beforeMinutes(flexibleOffWorkTime, Math.abs(betweenToWorkTime));
} else if (betweenToWorkTime < 0) {
flexibleOffWorkTime = DateUtil.AfterMinutes(flexibleOffWorkTime, Math.abs(betweenToWorkTime));
}
}
if (!"".equals(flexibleOffWorkTime)){
//重新设置打卡时间
int endWorkIndex = needClockDateList.indexOf(jssjEnd);
needClockDateList.remove(endWorkIndex);
needClockDateList.add(endWorkIndex,flexibleOffWorkTime);
//根据弹性下班时间点重新计算
Map<ClockPointEnum, Map<String, Object>> jsdkNearestClcokInTime = Utils.getNearestClcokInTimeCmd(flexibleOffWorkTime, clockInTimeList);
ClockPointEnum newtimeType = getEndClassTimeType(jsdkMap,jsdkNearestClcokInTime,flexibleOffWorkTime,flexibleOffWorkTime);
clockdto.setClassTime(jssjEnd);
clockdto.setPointType(ClockPointEnum.END);
clockdto.setTimeType(newtimeType);
clockdto.setElasticTime(flexibleOffWorkTime);
clockdto.setClockTime(jsdkNearestClcokInTime.get(newtimeType));
}
}
}
}
}
}
/**
* 休息时段弹性
*/
public void flexibleRestClass(List<Map<String, Object>> restScheduleList,List<ClockPointDTO> clcokInTimeData,List<Map<String, Object>> scheduleResult){
String analysisDate = Util.null2String(params.get("analysisDate"));
List<Map<String, Object>> clockInTimeList = (List<Map<String, Object>>) params.get("clockInTimeList");
for (Map<String, Object> restSchedule:restScheduleList){
String dtkssj = Utils.getkssjTime(restSchedule,analysisDate);
String dtjssj = Utils.getjssjTime(restSchedule,analysisDate);
//最大弹性分钟
int dtzddxfz = Integer.valueOf(Util.null2String(restSchedule.get("dtzddxfz")));
//弹性核算
double dtdxhs = Utils.convertDouble(restSchedule.get("dtdxhs"));
//下班去休息卡点
ClockPointDTO toRestClockPointDTO = null;
//休息完上班卡点,.
ClockPointDTO endRestClockPointDTO = null;
for (ClockPointDTO clockPointDTO:clcokInTimeData){
if (clockPointDTO.getClassTime().equals(dtkssj) && clockPointDTO.getPointType()==ClockPointEnum.END){
toRestClockPointDTO = clockPointDTO;
}else if (clockPointDTO.getClassTime().equals(dtjssj) && clockPointDTO.getPointType()==ClockPointEnum.START){
endRestClockPointDTO = clockPointDTO;
}
}
List<Map<String, Object>> endRestSchedule = scheduleResult.stream().filter(e->dtjssj.equals(Utils.getkssjTime(e,analysisDate))).collect(Collectors.toList());
List<Map<String, Object>> startRestSchedule = scheduleResult.stream().filter(e->dtkssj.equals(Utils.getjssjTime(e,analysisDate))).collect(Collectors.toList());
/**
* 当休息时段的开始和结束时间都要打卡时才进行弹性
*/
if (toRestClockPointDTO != null && endRestClockPointDTO != null && toRestClockPointDTO.getClockTime() != null){
String toRestClassTime = toRestClockPointDTO.getClassTime();
String endRestClassTime = endRestClockPointDTO.getClassTime();
Map<ClockPointEnum, Map<String, Object>> toRestNearestClcokInTime = Utils.getNearestClcokInTimeCmd(DateUtil.beforeMinutes(dtkssj,dtzddxfz), clockInTimeList);
ClockPointEnum timeType = getEndClassTimeType(startRestSchedule.get(0),toRestNearestClcokInTime,dtkssj,DateUtil.AfterMinutes(dtkssj,dtzddxfz));
toRestClockPointDTO.setTimeType(timeType);
toRestClockPointDTO.setClockTime(toRestNearestClcokInTime.get(timeType));
Map<String, Object> toRestClockTimeMap = toRestClockPointDTO.getClockTime();
if (toRestClockTimeMap == null || toRestClockTimeMap.size() == 0 || toRestClockPointDTO.getTimeType() == ClockPointEnum.EQUAL || toRestClockPointDTO.getTimeType() == ClockPointEnum.EMPTY){
//不存在打卡时间,打卡时间与班次时间相等,漏卡
continue;
}
String toRestClockTime = toRestClockTimeMap.get("signdate")+" "+toRestClockTimeMap.get("signtime");
int betweenMinute = 0;
//设置下上班的弹性时间
if (toRestClockPointDTO.getTimeType() == ClockPointEnum.BEFORE){
betweenMinute = DateUtil.getBetWeenMinutes(toRestClockTime,toRestClassTime);
if (betweenMinute > dtzddxfz){
toRestClockPointDTO.setElasticTime(DateUtil.beforeMinutes(toRestClassTime,dtzddxfz));
toRestClockPointDTO.setTimeType(ClockPointEnum.BEFORE);
endRestClockPointDTO.setElasticTime(DateUtil.beforeMinutes(endRestClassTime,dtzddxfz));
}else {
betweenMinute = Double.valueOf(Utils.getItemdurationDown(dtdxhs, AccountingUnitEnum.MINUTES.getKey(), betweenMinute, AccountingUnitEnum.MINUTES)).intValue();
endRestClockPointDTO.setElasticTime(DateUtil.beforeMinutes(endRestClassTime,betweenMinute));
}
}else if (toRestClockPointDTO.getTimeType() == ClockPointEnum.AFTER){
betweenMinute = DateUtil.getBetWeenMinutes(toRestClassTime,toRestClockTime);
betweenMinute = Double.valueOf(Utils.getItemdurationDown(dtdxhs, AccountingUnitEnum.MINUTES.getKey(), betweenMinute, AccountingUnitEnum.MINUTES)).intValue();
endRestClockPointDTO.setElasticTime(DateUtil.AfterMinutes(endRestClassTime,betweenMinute));
if (betweenMinute > dtzddxfz){
toRestClockPointDTO.setElasticTime(DateUtil.AfterMinutes(toRestClassTime,dtzddxfz));
toRestClockPointDTO.setTimeType(ClockPointEnum.AFTER);
endRestClockPointDTO.setElasticTime(DateUtil.AfterMinutes(endRestClassTime,dtzddxfz));
}else {
betweenMinute = Double.valueOf(Utils.getItemdurationDown(dtdxhs, AccountingUnitEnum.MINUTES.getKey(), betweenMinute, AccountingUnitEnum.MINUTES)).intValue();
endRestClockPointDTO.setElasticTime(DateUtil.AfterMinutes(endRestClassTime,betweenMinute));
}
}
if (betweenMinute <= dtzddxfz){
toRestClockPointDTO.setElasticTime(toRestClockTime);
toRestClockPointDTO.setTimeType(ClockPointEnum.EQUAL);
}
//重新设置打卡时间
int toRestIndex = needClockDateList.indexOf(toRestClockPointDTO.getClassTime());
needClockDateList.remove(toRestIndex);
needClockDateList.add(toRestIndex,toRestClockPointDTO.getElasticTime());
int endRestIndex = needClockDateList.indexOf(endRestClockPointDTO.getClassTime());
needClockDateList.remove(endRestIndex);
needClockDateList.add(endRestIndex,endRestClockPointDTO.getElasticTime());
//变更休息时间
restSchedule.put("dtkssj",toRestClockPointDTO.getElasticTime().split(" ")[1]);
restSchedule.put("dtjssj",endRestClockPointDTO.getElasticTime().split(" ")[1]);
//根据弹性上班时间点重新获取打卡时间
Map<ClockPointEnum, Map<String, Object>> ksdkNearestClcokInTime = Utils.getNearestClcokInTimeCmd(endRestClockPointDTO.getElasticTime(), clockInTimeList);
ClockPointEnum endResttimeType = getStartClassTimeType(endRestSchedule.get(0),ksdkNearestClcokInTime,endRestClockPointDTO.getElasticTime(),endRestClockPointDTO.getElasticTime());
endRestClockPointDTO.setClockTime(ksdkNearestClcokInTime.get(endResttimeType));
endRestClockPointDTO.setTimeType(endResttimeType);
if (endRestClockPointDTO.getTimeType() == ClockPointEnum.EMPTY || endRestClockPointDTO.getClockTime() == null){
//当弹性结束未匹配到打卡,弹性失效,进行还原
restSchedule.put("dtkssj",toRestClockPointDTO.getClassTime().split(" ")[1]);
restSchedule.put("dtjssj",endRestClockPointDTO.getClassTime().split(" ")[1]);
//重新设置打卡时间
toRestIndex = needClockDateList.indexOf(toRestClockPointDTO.getElasticTime());
needClockDateList.remove(toRestIndex);
needClockDateList.add(toRestIndex,toRestClockPointDTO.getClassTime());
endRestIndex = needClockDateList.indexOf(endRestClockPointDTO.getElasticTime());
needClockDateList.remove(endRestIndex);
needClockDateList.add(endRestIndex,endRestClockPointDTO.getClassTime());
if (toRestClockPointDTO.getClockTime() != null){
String time = toRestClockPointDTO.getClockTime().get("signdate")+" "+toRestClockPointDTO.getClockTime().get("signtime");
if (DateUtil.getTime(time).compareTo(DateUtil.getTime(toRestClockPointDTO.getClassTime())) > 0){
toRestClockPointDTO.setTimeType(ClockPointEnum.AFTER);
}else if (DateUtil.getTime(time).compareTo(DateUtil.getTime(toRestClockPointDTO.getClassTime())) ==0){
toRestClockPointDTO.setTimeType(ClockPointEnum.EQUAL);
}else {
toRestClockPointDTO.setTimeType(ClockPointEnum.BEFORE);
}
}
toRestClockPointDTO.setElasticTime(null);
endRestClockPointDTO.setElasticTime(null);
}
}
}
}
/**
* 获取开始打卡的打卡数据在卡点的位置
* @param needClockIn
* @param ksdkNearestClcokInTime
* @return
*/
public ClockPointEnum getStartClassTimeType(Map<String, Object> needClockIn,Map<ClockPointEnum, Map<String, Object>> ksdkNearestClcokInTime,String dtkssj,String minelasticTime){
int tqdkfzs = 60;
if (Util.null2String(needClockIn.get("tqdkfzs")).equals("") && !"".equals(getBeforeClockTime(needClockDateList,dtkssj))){
tqdkfzs = DateUtil.getBetWeenMinutes(getBeforeClockTime(needClockDateList,dtkssj),dtkssj);
}else {
tqdkfzs = Util.null2String(needClockIn.get("tqdkfzs")).equals("")?60:Integer.valueOf(needClockIn.get("tqdkfzs").toString());
}
ClockPointEnum timeType = ClockPointEnum.EMPTY;
if (ksdkNearestClcokInTime.get(ClockPointEnum.EQUAL) != null) {
timeType = ClockPointEnum.EQUAL;
}
if (ClockPointEnum.EMPTY.equals(timeType) && ksdkNearestClcokInTime.get(ClockPointEnum.BEFORE) != null) {
String clockInTime = ksdkNearestClcokInTime.get(ClockPointEnum.BEFORE).get("signdate") + " " + ksdkNearestClcokInTime.get(ClockPointEnum.BEFORE).get("signtime");
if (DateUtil.getTime(clockInTime).compareTo(DateUtil.getTime(DateUtil.beforeMinutes(minelasticTime, tqdkfzs))) >= 0 &&
(getBeforeClockTime(needClockDateList,dtkssj).equals("") || DateUtil.getTime(clockInTime).compareTo(DateUtil.getTime(getBeforeClockTime(needClockDateList,dtkssj))) > 0)) {
//打卡时间大于等于最早打卡时间
timeType = ClockPointEnum.BEFORE;
}
}
if (ClockPointEnum.EMPTY.equals(timeType) && ksdkNearestClcokInTime.get(ClockPointEnum.AFTER) != null) {
String clockInTime = ksdkNearestClcokInTime.get(ClockPointEnum.AFTER).get("signdate") + " " + ksdkNearestClcokInTime.get(ClockPointEnum.AFTER).get("signtime");
if (getNextClockTime(needClockDateList,dtkssj).equals("") || DateUtil.getTime(clockInTime).compareTo(DateUtil.getTime(getNextClockTime(needClockDateList,dtkssj))) < 0) {
//打卡时间小于结束时间
timeType = ClockPointEnum.AFTER;
}
}
return timeType;
}
/**
* 获取结束打卡的打卡数据在卡点的位置
* @param needClockIn
* @param jsdkNearestClcokInTime
* @return
*/
public ClockPointEnum getEndClassTimeType(Map<String, Object> needClockIn,Map<ClockPointEnum, Map<String, Object>> jsdkNearestClcokInTime,String dtjssj,String maxelasticTime){
int thdkfzs = 60;
if (Util.null2String(needClockIn.get("thdkfzs")).equals("") && !"".equals(getNextClockTime(needClockDateList,dtjssj))){
thdkfzs = DateUtil.getBetWeenMinutes(dtjssj,getNextClockTime(needClockDateList,dtjssj));
}else {
thdkfzs = Util.null2String(needClockIn.get("thdkfzs")).equals("")?60:Integer.valueOf(needClockIn.get("thdkfzs").toString());
}
ClockPointEnum timeType = ClockPointEnum.EMPTY;
if (jsdkNearestClcokInTime.get(ClockPointEnum.EQUAL) != null) {
timeType = ClockPointEnum.EQUAL;
}
if (ClockPointEnum.EMPTY.equals(timeType) && jsdkNearestClcokInTime.get(ClockPointEnum.AFTER) != null) {
String clockInTime = jsdkNearestClcokInTime.get(ClockPointEnum.AFTER).get("signdate") + " " + jsdkNearestClcokInTime.get(ClockPointEnum.AFTER).get("signtime");
if (dtjssj.equals(maxelasticTime)){
if (DateUtil.getTime(clockInTime).compareTo(DateUtil.getTime(DateUtil.AfterMinutes(maxelasticTime, thdkfzs))) <= 0 &&
(getNextClockTime(needClockDateList,dtjssj).equals("") || DateUtil.getTime(clockInTime).compareTo(DateUtil.getTime(getNextClockTime(needClockDateList,dtjssj))) < 0)) {
timeType = ClockPointEnum.AFTER;
}
}else {
//弹性逻辑
if (DateUtil.getTime(clockInTime).compareTo(DateUtil.getTime(DateUtil.AfterMinutes(maxelasticTime, thdkfzs))) <= 0 &&
(getNextClockTime(needClockDateList,dtjssj).equals("") || DateUtil.getTime(clockInTime).compareTo(DateUtil.getTime(getNextClockTime(needClockDateList,dtjssj))) < 0 ||
DateUtil.getTime(maxelasticTime).compareTo(DateUtil.getTime(getNextClockTime(needClockDateList,dtjssj))) >= 0)) {
timeType = ClockPointEnum.AFTER;
}
}
if (DateUtil.getTime(clockInTime).compareTo(DateUtil.getTime(DateUtil.AfterMinutes(maxelasticTime, thdkfzs))) <= 0) {
timeType = ClockPointEnum.AFTER;
}
}
if (ClockPointEnum.EMPTY.equals(timeType) && jsdkNearestClcokInTime.get(ClockPointEnum.BEFORE) != null) {
String clockInTime = jsdkNearestClcokInTime.get(ClockPointEnum.BEFORE).get("signdate") + " " + jsdkNearestClcokInTime.get(ClockPointEnum.BEFORE).get("signtime");
if (dtjssj.equals(maxelasticTime)){
if (getBeforeClockTime(needClockDateList,dtjssj).equals("") || DateUtil.getTime(clockInTime).compareTo(DateUtil.getTime(getBeforeClockTime(needClockDateList,dtjssj))) > 0) {
timeType = ClockPointEnum.BEFORE;
}
}else {
int betweenTime = DateUtil.getBetWeenMinutes(dtjssj,maxelasticTime);
if (getBeforeClockTime(needClockDateList,dtjssj).equals("") || DateUtil.getTime(clockInTime).compareTo(DateUtil.getTime(getBeforeClockTime(needClockDateList,dtjssj))) > 0
|| DateUtil.getTime(clockInTime).compareTo(DateUtil.getTime(DateUtil.beforeMinutes(dtjssj,betweenTime))) >=0) {
timeType = ClockPointEnum.BEFORE;
}
}
}
return timeType;
}
public String getNextClockTime(List<String> needClockDateList,String time){
int index = 0;
for (int i=0;i<needClockDateList.size();i++){
if (needClockDateList.get(i).equals(time)){
index = i+1;
break;
}
}
if (index < needClockDateList.size() && index!=0){
return needClockDateList.get(index);
}else {
return "";
}
}
public String getBeforeClockTime(List<String> needClockDateList,String time){
int index = 0;
for (int i=0;i<needClockDateList.size();i++){
if (needClockDateList.get(i).equals(time)){
index = i-1;
break;
}
}
if (index >= 0){
return needClockDateList.get(index);
}else {
return "";
}
}
/**
* 判断是否是工作(包含加班)类型时段
* @param classSegmentType
* @return
*/
public boolean ifWorkClassSegment(String classSegmentType){
if (classSegmentType.equals(ClassSegmentTypeEnum.WORK_TIME.getKey()) || classSegmentType.equals(ClassSegmentTypeEnum.EXTENDED_OVERTIME.getKey())
||classSegmentType.equals(ClassSegmentTypeEnum.OVERTIME_PLAN.getKey()) || classSegmentType.equals(ClassSegmentTypeEnum.EARLY_OVERTIME.getKey()) || classSegmentType.equals(ClassSegmentTypeEnum.OVERTIME_IN_CLASS.getKey())){
return true;
}else {
return false;
}
}
public ClockPointEnum getTimeType(ClockPointDTO clockPointDTO,Map<String,Object> clockInMap){
if (clockInMap == null){
return ClockPointEnum.EMPTY;
}
String clockInTime = clockInMap.get("signdate")+ " "+clockInMap.get("signtime");
int compare = DateUtil.getTime(clockInTime).compareTo(DateUtil.getTime(clockPointDTO.getClassTime()));
if (compare == 0){
return ClockPointEnum.EQUAL;
}else if (compare > 0){
return ClockPointEnum.AFTER;
}else {
return ClockPointEnum.BEFORE;
}
}
}