@ -3,10 +3,7 @@ package com.engine.jucailinkq.attendance.workflow.service.impl;
import com.engine.jucailinkq.attendance.component.persongroup.commonutil.PersongroupCommonUtil ;
import com.engine.jucailinkq.attendance.component.persongroup.service.SchedulingResultsService ;
import com.engine.jucailinkq.attendance.component.persongroup.service.impl.SchedulingResultsServiceImpl ;
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.DateTypeEnum ;
import com.engine.jucailinkq.attendance.enums.* ;
import com.engine.jucailinkq.attendance.workflow.cmd.GetAskForLeaveRecordListCmd ;
import com.engine.jucailinkq.attendance.workflow.cmd.GetRestDayIntervalCmd ;
import com.engine.jucailinkq.attendance.workflow.enums.AskAndEvctionWayEnum ;
@ -220,8 +217,17 @@ public class AskForLeaveServiceImpl extends Service implements AskForLeaveServic
}
}
//判断考勤项目是否需要强制使用“优先使用项目”
boolean useFirstItemSign = CheckBoxEnum . CHECKED . getKey ( ) . equals ( holidayItem . get ( "qzsyyxjb" ) ) & & CheckBoxEnum . CHECKED . getKey ( ) . equals ( holidayItem . get ( "jcbyxsyqjb" ) ) ;
Map < String , Object > holidayPriorityItem = useFirstItemSign ? DbTools . getSqlToMap ( sql , holidayItem . get ( "yxsydjb" ) ) : null ;
// boolean useFirstItemSign = CheckBoxEnum.CHECKED.getKey().equals(holidayItem.get("qzsyyxjb")) && CheckBoxEnum.CHECKED.getKey().equals(holidayItem.get("jcbyxsyqjb"));
// Map<String,Object> holidayPriorityItem = useFirstItemSign ? DbTools.getSqlToMap(sql,holidayItem.get("yxsydjb")) : null;
//20241021逻辑变更, 根据考勤项目的“优先使用项目”信息, 逐级找到所有“优先使用项目”, 找到的先后顺序, 来决定使用优先级, 最后的优先级最大
List < Map < String , Object > > holidayPriorityItemList = new ArrayList < > ( ) ;
holidayPriorityItemList . add ( holidayItem ) ;
//获取假期类型的考勤项目
sql = "select id,mc,hsdw,hsl,jcbyxsyqjb,yxsydjb,qzsyyxjb,zdycbcndfgzsd,zdycrqqjndxxb,yxyz,zdyzsl,zysd from uf_jcl_kq_kqxm where xmlx=?" ;
List < Map < String , Object > > holidayItemList = DbTools . getSqlToList ( sql , AttendanceItemTypeEnum . HOLIDAY . getKey ( ) ) ;
Map < String , Map < String , Object > > holidayItemInfos = holidayItemList . stream ( ) . collect ( Collectors . toMap ( e - > e . get ( "id" ) . toString ( ) , e - > e ) ) ;
//逐级获取优先使用项目
getHolidayPriorityItem ( holidayPriorityItemList , holidayItemInfos , holidayItem ) ;
//遍历人员、日期,生成人员+日期+请假时长的请假信息
//请假人的请假区间内每一天的日期类型信息
Map < String , List < String > > restDayInfo = removeNonWorkDayRange ? getRestDayWithEmpId ( leaveEmpIdList , leaveType , startDate , endDate ) : new HashMap < > ( ) ;
@ -241,28 +247,37 @@ public class AskForLeaveServiceImpl extends Service implements AskForLeaveServic
List < Map < String , String > > completeLeaveDetailList = new ArrayList < > ( ) ;
//按照人员id分组处理请假明细信息, 关联假期余额数据
Map < String , List < Map < String , String > > > leaveDetailGroupByEmp = simpleLeaveDetailList . stream ( ) . collect ( Collectors . groupingBy ( e - > Util . null2String ( e . get ( "qjr" ) ) ) ) ;
//获取modeId, 假期额度规则的modeId
Map < String , String > formmodeIdMap = Utils . getFormmodeIdMap ( ) ;
String modeId = formmodeIdMap . get ( "uf_jcl_kq_jqed" ) ;
for ( Map . Entry < String , List < Map < String , String > > > entry : leaveDetailGroupByEmp . entrySet ( ) ) {
//校验该人员的考勤周期是否正常
boolean kqCycleAllow = kqCycleCheck ( entry . getKey ( ) , entry . getValue ( ) , errorMessage , empIdToName . get ( entry . getKey ( ) ) ) ;
if ( ! kqCycleAllow ) {
continue ;
}
//1-收集使用勾选的关联的可使用的余额, 才能够生成请假明细, 可使用的条件为, a-满足最小使用时长, b-满足使用次数上限, c-存在未休时长
List < Map < String , Object > > canUseCheckJqyeInfo = collectUsableHolidayBalance ( unableUseJqyeIdList , editedUseJqed , holidayItem , startDate , entry . getKey ( ) ) ;
List < Map < String , String > > detailListItem ;
//判断考勤项目是否需要强制使用“优先使用项目”
if ( useFirstItemSign ) {
//勾选假期类型名称
String firstItemName = Util . null2String ( holidayPriorityItem . get ( "mc" ) ) ;
//2-收集优先使用的项目关联的可使用的余额, 才能够生成请假明细, 可使用的条件为, a-满足最小使用时长, b-满足使用次数上限, c-存在未休时长
List < Map < String , Object > > canUseFirstJqyeInfo = collectUsableHolidayBalance ( unableUseJqyeIdList , editedUseJqed , holidayPriorityItem , startDate , entry . getKey ( ) ) ;
detailListItem = matchHolidayBalance ( editedLeaveInfo , checkAmountJqIdList , errorMessage , entry . getKey ( ) , empIdToName . get ( entry . getKey ( ) ) , canUseCheckJqyeInfo , canUseFirstJqyeInfo , editedUseJqed ,
editedUseJqlxWithEmp , entry . getValue ( ) , leaveType , holidayPriorityItem . get ( "id" ) . toString ( ) , checkItemName , firstItemName ) ;
} else {
detailListItem = matchHolidayBalance ( editedLeaveInfo , checkAmountJqIdList , errorMessage , entry . getKey ( ) , empIdToName . get ( entry . getKey ( ) ) , canUseCheckJqyeInfo , null , editedUseJqed ,
editedUseJqlxWithEmp , entry . getValue ( ) , leaveType , null , checkItemName , null ) ;
// //1-收集使用勾选的关联的可使用的余额, 才能够生成请假明细, 可使用的条件为, a-满足最小使用时长, b-满足使用次数上限, c-存在未休时长
// List<Map<String, Object>> canUseCheckJqyeInfo = collectUsableHolidayBalance(unableUseJqyeIdList, editedUseJqed, holidayItem, startDate, entry.getKey());
// List<Map<String,String>> detailListItem;
// //判断考勤项目是否需要强制使用“优先使用项目”
// if (useFirstItemSign) {
// //勾选假期类型名称
// String firstItemName = Util.null2String(holidayPriorityItem.get("mc"));
// //2-收集优先使用的项目关联的可使用的余额, 才能够生成请假明细, 可使用的条件为, a-满足最小使用时长, b-满足使用次数上限, c-存在未休时长
// List<Map<String, Object>> canUseFirstJqyeInfo = collectUsableHolidayBalance(unableUseJqyeIdList, editedUseJqed, holidayPriorityItem, startDate, entry.getKey());
// detailListItem = matchHolidayBalance(editedLeaveInfo, checkAmountJqIdList, errorMessage, entry.getKey(), empIdToName.get(entry.getKey()), canUseCheckJqyeInfo, canUseFirstJqyeInfo, editedUseJqed,
// editedUseJqlxWithEmp, entry.getValue(), leaveType, holidayPriorityItem.get("id").toString(), checkItemName, firstItemName);
// } else {
// detailListItem = matchHolidayBalance(editedLeaveInfo, checkAmountJqIdList, errorMessage, entry.getKey(), empIdToName.get(entry.getKey()), canUseCheckJqyeInfo, null, editedUseJqed,
// editedUseJqlxWithEmp, entry.getValue(), leaveType, null, checkItemName, null);
// }
//20241021逻辑变更, 根据考勤项目的“优先使用项目”信息, 获取所有可使用假期余额信息
Map < String , List < Map < String , Object > > > canUseJqyeInfo = new HashMap < > ( ) ;
for ( Map < String , Object > item : holidayPriorityItemList ) {
canUseJqyeInfo . put ( item . get ( "id" ) . toString ( ) , collectUsableHolidayBalance ( unableUseJqyeIdList , editedUseJqed , item , startDate , entry . getKey ( ) , empIdToName . get ( entry . getKey ( ) ) , modeId , errorMessage ) ) ;
}
List < Map < String , String > > detailListItem = matchHolidayWithPriority ( editedLeaveInfo , checkAmountJqIdList , errorMessage , entry . getKey ( ) ,
empIdToName . get ( entry . getKey ( ) ) , canUseJqyeInfo , holidayPriorityItemList , editedUseJqed , editedUseJqlxWithEmp , entry . getValue ( ) ) ;
if ( detailListItem . size ( ) > 0 ) {
completeLeaveDetailList . addAll ( detailListItem ) ;
}
@ -286,6 +301,16 @@ public class AskForLeaveServiceImpl extends Service implements AskForLeaveServic
return resultMap ;
}
private void getHolidayPriorityItem ( List < Map < String , Object > > holidayPriorityItemList , Map < String , Map < String , Object > > holidayItemInfos , Map < String , Object > holidayItem ) {
boolean useFirstItemSign = CheckBoxEnum . CHECKED . getKey ( ) . equals ( holidayItem . get ( "qzsyyxjb" ) ) & & CheckBoxEnum . CHECKED . getKey ( ) . equals ( holidayItem . get ( "jcbyxsyqjb" ) ) ;
String useFirstItemId = useFirstItemSign ? Util . null2String ( holidayItem . get ( "yxsydjb" ) ) : "" ;
if ( ! "" . equals ( useFirstItemId ) & & holidayItemInfos . get ( useFirstItemId ) ! = null ) {
holidayPriorityItemList . add ( 0 , holidayItemInfos . get ( useFirstItemId ) ) ;
//获取下一级优先使用项目
getHolidayPriorityItem ( holidayPriorityItemList , holidayItemInfos , holidayItemInfos . get ( useFirstItemId ) ) ;
}
}
/ * *
* @param detailTableData 明 细 表 1 数 据
* @param leaveDateList 请 假 日 期 集 合
@ -766,6 +791,137 @@ public class AskForLeaveServiceImpl extends Service implements AskForLeaveServic
return matchResultSign ? result : new ArrayList < > ( ) ;
}
/ * *
* @param editedLeaveInfo 触 发 接 口 前 已 编 辑 的 请 假 明 细 信 息
* @param checkAmountJqIdList 需 要 校 验 假 期 额 度 的 假 期 类 型 id 集 合
* @param errorMessage 错 误 信 息 记 录 集 合
* @param empId 请 假 人 员 id
* @param empName 请 假 人 员 姓 名
* @param canUseJqyeInfo 可 使 用 的 假 期 余 额 信 息
* @param editedUseJqed 触 发 接 口 前 已 编 辑 的 假 期 额 度 使 用 信 息
* @param editedUseJqlxWithEmp 触 发 接 口 前 , 本 次 提 交 的 日 期 集 合 中 已 编 辑 的 假 期 类 型 id_ 人 员 id 条 件 下 已 使 用 的 时 长
* @param leaveDetailList 请 假 明 细 集 合
* @return 给 请 假 明 细 中 请 假 时 长 分 配 应 扣 的 假 期 余 额 id 及 时 长
* /
private List < Map < String , String > > matchHolidayWithPriority ( Map < String , String > editedLeaveInfo , List < String > checkAmountJqIdList , List < String > errorMessage , String empId , String empName ,
Map < String , List < Map < String , Object > > > canUseJqyeInfo , List < Map < String , Object > > holidayPriorityItemList , Map < String , Double > editedUseJqed ,
Map < String , Double > editedUseJqlxWithEmp , List < Map < String , String > > leaveDetailList ) {
List < Map < String , String > > result = new ArrayList < > ( ) ;
//记录分配假期余额的结果
boolean matchResultSign = true ;
//此次遍历请假总时长
double totalLeaveDuration = 0 ;
for ( Map < String , String > detailData : leaveDetailList ) {
String qtj = Util . null2String ( detailData . get ( "qtj" ) ) ;
String btj = Util . null2String ( detailData . get ( "btj" ) ) ;
//请假时间
double leaveDuration ;
if ( qtj . equals ( CheckBoxEnum . CHECKED . getKey ( ) ) ) {
//全天默认8小时
leaveDuration = 8 ;
} else if ( btj . equals ( CheckBoxEnum . CHECKED . getKey ( ) ) ) {
//半天默认4小时
leaveDuration = 4 ;
} else {
leaveDuration = Double . parseDouble ( Util . null2String ( detailData . get ( "qjsc" ) ) ) ;
}
totalLeaveDuration = totalLeaveDuration + leaveDuration ;
}
Map < String , Double > leaveDurationMap = new HashMap < > ( ) ;
leaveDurationMap . put ( "totalLeaveDuration" , totalLeaveDuration ) ;
//遍历关联请假余额id和假期类型id
for ( Map < String , String > detailData : leaveDetailList ) {
String ksrq = Util . null2String ( detailData . get ( "ksrq" ) ) ;
String qtj = Util . null2String ( detailData . get ( "qtj" ) ) ;
String btj = Util . null2String ( detailData . get ( "btj" ) ) ;
detailData . put ( "qjrName" , empName ) ;
//请假时间
double leaveDuration ;
if ( qtj . equals ( CheckBoxEnum . CHECKED . getKey ( ) ) ) {
//全天默认8小时
leaveDuration = 8 ;
} else if ( btj . equals ( CheckBoxEnum . CHECKED . getKey ( ) ) ) {
//半天默认4小时
leaveDuration = 4 ;
} else {
leaveDuration = Double . parseDouble ( Util . null2String ( detailData . get ( "qjsc" ) ) ) ;
}
log . info ( "leaveDuration : [{}]" , leaveDuration ) ;
leaveDurationMap . put ( "leaveDuration" , leaveDuration ) ;
//20241021逻辑变更, 按照假期项目级联优先级, 由后往前依次分配请假时长
List < Map < String , Object > > jqyeList ;
String jqlxId ;
String jqlxName ;
boolean jqlxEdited = false ;
boolean dealSign = true ;
for ( Map < String , Object > jqlxItem : holidayPriorityItemList ) {
jqlxId = Util . null2String ( jqlxItem . get ( "id" ) ) ;
jqlxName = Util . null2String ( jqlxItem . get ( "mc" ) ) ;
jqyeList = canUseJqyeInfo . get ( jqlxId ) ;
Double jqlxEditedUseSc = editedUseJqlxWithEmp . getOrDefault ( jqlxId + "_" + empId , ( double ) 0 ) ;
//使用的的请假项目是否已被编辑
jqlxEdited = editedLeaveInfo . get ( empId + "_" + jqlxId + "_" + ksrq ) ! = null ;
//本次请假日期范围内,已存在该请假类型开始日期相同的请假明细,则不使用该请假类型
if ( jqlxEditedUseSc > 0 | | jqlxEdited ) {
continue ;
}
leaveDuration = leaveDurationMap . get ( "leaveDuration" ) ;
//使用的假期项目需要额度校验的话
if ( checkAmountJqIdList . contains ( jqlxId ) ) {
leaveDurationMap . put ( "leaveDuration" , leaveDuration ) ;
dealSign = dealLeaveDetailWithJqyeInfo ( detailData , jqyeList , editedUseJqed , leaveDurationMap , ksrq , jqlxId , jqlxName , result ) ;
if ( ! dealSign ) {
continue ;
}
if ( leaveDurationMap . get ( "leaveDuration" ) = = 0 ) {
//如果同假期类型出现多假期余额拼接配置一条请假明细时,请假明细的时长需要重新设置下
//请假明细初始要求时长已配置完成则赋值为初始请假时长,否则为初始时长-剩余未配置时长
if ( Util . null2String ( detailData . get ( "jqye" ) ) . contains ( "," ) ) {
detailData . put ( "qjsc" , String . valueOf ( leaveDuration ) ) ;
}
break ;
} else {
if ( Util . null2String ( detailData . get ( "jqye" ) ) . contains ( "," ) ) {
detailData . put ( "qjsc" , String . valueOf ( leaveDuration - leaveDurationMap . get ( "leaveDuration" ) ) ) ;
}
}
} else {
detailData . put ( "qjlx" , jqlxId ) ;
detailData . put ( "qjlxName" , jqlxName ) ;
detailData . put ( "qjsc" , String . valueOf ( leaveDuration ) ) ;
result . add ( detailData ) ;
leaveDurationMap . put ( "totalLeaveDuration" , Utils . subtract ( leaveDurationMap . get ( "totalLeaveDuration" ) , leaveDurationMap . get ( "leaveDuration" ) ) ) ;
leaveDurationMap . put ( "leaveDuration" , ( double ) 0 ) ;
break ;
}
if ( ! "" . equals ( Util . null2String ( detailData . get ( "qjlx" ) ) ) ) {
result . add ( new HashMap < > ( detailData ) ) ;
detailData . remove ( "qjlx" ) ;
detailData . remove ( "qjlxName" ) ;
detailData . remove ( "qjsc" ) ;
detailData . remove ( "jqye" ) ;
}
}
if ( leaveDurationMap . get ( "leaveDuration" ) > 0 ) {
String message = empName ;
if ( jqlxEdited ) {
//人员id+日期+假期类型三种条件约束唯一性
message = message + "_" + ksrq + "已存在一笔该请假类型的请假明细!" ;
} else if ( ! dealSign ) {
message = message + "_" + ksrq + "不存在可使用的假期余额,请检查假期余额使用次数和最小使用时长设置!" ;
} else {
//假期余额不足
message = message + "_" + ksrq + "假期余额不足!" ;
}
errorMessage . add ( message ) ;
matchResultSign = false ;
}
}
return matchResultSign ? result : new ArrayList < > ( ) ;
}
private boolean dealLeaveDetailWithJqyeInfo ( Map < String , String > detailData , List < Map < String , Object > > canUseJqyeInfo ,
Map < String , Double > editedUseJqed , Map < String , Double > leaveDurationMap ,
String ksrq , String itemId , String itemName , List < Map < String , String > > result ) {
@ -851,7 +1007,8 @@ public class AskForLeaveServiceImpl extends Service implements AskForLeaveServic
* @param startDate 开 始 日 期
* @param leaveEmpId 请 假 人 id
* /
private List < Map < String , Object > > collectUsableHolidayBalance ( List < String > unableUseJqyeIdList , Map < String , Double > editedUseJqed , Map < String , Object > holidayItem , String startDate , String leaveEmpId ) {
private List < Map < String , Object > > collectUsableHolidayBalance ( List < String > unableUseJqyeIdList , Map < String , Double > editedUseJqed , Map < String , Object > holidayItem ,
String startDate , String leaveEmpId , String empName , String modeId , List < String > errorMessage ) {
String itemId = Util . null2String ( holidayItem . get ( "id" ) ) ;
String sql = "select id,jqid,sxrq,ktsc,yxsc,wxsc,yqsxrq,ztsc from uf_jcl_kq_jqye where ygid=? and jqid=? and sxrq<=? and yqsxrq>=? order by yqsxrq, modedatacreatedate, modedatacreatetime" ;
@ -859,8 +1016,35 @@ public class AskForLeaveServiceImpl extends Service implements AskForLeaveServic
//获取延期失效日期最晚的一条
Map < String , Object > maxYqsxrqMap = holidayBalanceList . stream ( ) . reduce ( ( m1 , m2 ) - > m2 ) . orElse ( null ) ;
//获取假期额度规则中额度可休次数、单次最小休时长、额度单位
String jqedSql = "select eddw, dczskxsc, edbxdcxw from uf_jcl_kq_jqed where jb = ?" ;
Map < String , Object > jqedInfo = DbTools . getSqlToMap ( jqedSql , itemId ) ;
Map < String , Object > jqedInfo = new HashMap < > ( ) ;
String jqedSql = "select id, eddw, dczskxsc, edbxdcxw from uf_jcl_kq_jqed where jb = ? and gzzt = 0" ;
List < Map < String , Object > > jqedData = DbTools . getSqlToList ( jqedSql , itemId ) ;
Integer empPriority = null ;
boolean samePriority = false ;
for ( Map < String , Object > jqedItem : jqedData ) {
String dataId = jqedItem . get ( "id" ) . toString ( ) ;
//获取假期额度规则适用的人员id列表
// List<String> empIdList = CommonUtil.getEmpIds(dataId, modeId);
Map < String , Integer > empInfo = CommonUtil . getEmpIdWithPriority ( dataId , modeId ) ;
if ( empInfo . get ( leaveEmpId ) ! = null ) {
if ( empPriority = = null ) {
jqedInfo = jqedItem ;
empPriority = empInfo . get ( leaveEmpId ) ;
} else if ( empPriority > empInfo . get ( leaveEmpId ) ) {
jqedInfo = jqedItem ;
empPriority = empInfo . get ( leaveEmpId ) ;
} else if ( empPriority . equals ( empInfo . get ( leaveEmpId ) ) ) {
samePriority = true ;
}
}
}
if ( empPriority ! = null & & samePriority ) {
String message = empName ;
message = message + "可使用的假别—‘" + holidayItem . get ( "mc" ) + "’同一优先级情况下存在超过一种适用的假期额度规则,无法确定唯一规则!" ;
errorMessage . add ( message ) ;
return new ArrayList < > ( ) ;
}
//假期额度的额度单位, 0-天、1-小时
String eddw = Util . null2String ( jqedInfo . get ( "eddw" ) ) ;
int multiple = 1 ;