@ -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 ) ;
}
}