@ -1,28 +1,33 @@
package com.engine.attendance.workflow.service.impl ;
import com.engine.attendance.component.persongroup.service.SchedulingResultsService ;
import com.engine.attendance.component.persongroup.service.impl.SchedulingResultsServiceImpl ;
import com.engine.attendance.enums.AccountingUnitEnum ;
import com.engine.attendance.enums.CheckBoxEnum ;
import com.engine.attendance.enums.DateTypeEnum ;
import com.engine.attendance.workflow.cmd.GetAskForLeaveRecordListCmd ;
import com.engine.attendance.workflow.cmd.GetKqCycleTimeIntervalCmd ;
import com.engine.attendance.workflow.cmd.GetRestDayIntervalCmd ;
import com.engine.attendance.workflow.enums.AskAndEvctionWayEnum ;
import com.engine.attendance.workflow.service.AskForLeaveService ;
import com.engine.attendance.workflow.service.MakeUpClockInService ;
import com.engine.common.exception.AttendanceRunTimeException ;
import com.engine.common.util.DateUtil ;
import com.engine.common.util.DbTools ;
import com.engine.common.util.* ;
import com.engine.core.impl.Service ;
import com.google.common.collect.Lists ;
import com.google.common.collect.Maps ;
import lombok.extern.slf4j.Slf4j ;
import weaver.general.Util ;
import java.text.ParseException ;
import java.time.ZoneOffset ;
import java.util.Comparator ;
import java.util.HashMap ;
import java.util.List ;
import java.util.Map ;
import java.util.* ;
import java.util.stream.Collectors ;
@Slf4j
public class AskForLeaveServiceImpl extends Service implements AskForLeaveService {
private SchedulingResultsService schedulingResultsService = ServiceUtil . getService ( SchedulingResultsServiceImpl . class ) ;
private MakeUpClockInService makeUpClockInService = ServiceUtil . getService ( MakeUpClockInServiceImpl . class ) ;
@Override
public Map < String , Object > getUesdHolidayItem ( Map < String , Object > params ) {
@ -128,4 +133,602 @@ public class AskForLeaveServiceImpl extends Service implements AskForLeaveServic
}
return commandExecutor . execute ( new GetRestDayIntervalCmd ( params , user ) ) ;
}
/ * *
* 批 量 请 假 - 生 成 请 假 信 息 明 细 表 数 据
* @param params
* @return
* /
@Override
public Map < String , Object > generateLeaveInfoList ( Map < String , Object > params ) throws ParseException {
Map < String , Object > resultMap = Maps . newHashMap ( ) ;
List < String > errorMessage = new ArrayList < > ( ) ;
// 流程表单主表数据
Map < String , String > mainTableData = ( Map < String , String > ) params . get ( "mainTableData" ) ;
// 流程表单明细表1数据
List < Map < String , String > > detailTableData = ( List < Map < String , String > > ) params . get ( "detailTableData" ) ;
//需要校验假期额度的假期类型
List < String > checkAmountJqIdList = CommonUtil . getJqInfoWithAmount ( ) ;
//已编辑内容中的假期额度使用信息
Map < String , Double > editedUseJqed = new HashMap < > ( ) ;
//已编辑内容中的假期类型使用时长_人员信息
Map < String , Double > editedUseJqlxWithEmp = new HashMap < > ( ) ;
//假期余额时长已用完的假期余额id
List < String > unableUseJqyeIdList = new ArrayList < > ( ) ;
//记录已编辑的请假记录,<人员id-请假类型-日期, 请假时长>
Map < String , String > editedLeaveInfo = new HashMap < > ( ) ;
//处理明细表1数据, 生成之前编辑内容中已使用的假期额度信息
if ( detailTableData ! = null & & detailTableData . size ( ) > 0 ) {
for ( Map < String , String > detailItem : detailTableData ) {
double detailSc = "" . equals ( Util . null2String ( detailItem . get ( "qjsc" ) ) ) ? 0 : Double . parseDouble ( Util . null2String ( detailItem . get ( "qjsc" ) ) ) ;
String leaveType = Util . null2String ( detailItem . get ( "qjlx" ) ) ;
String empId = Util . null2String ( detailItem . get ( "qjr" ) ) ;
editedUseJqlxWithEmp . merge ( leaveType + "_" + empId , detailSc , Double : : sum ) ;
String jqye = Util . null2String ( detailItem . get ( "jqye" ) ) ;
if ( "" . equals ( jqye ) ) {
continue ;
} else if ( jqye . contains ( "," ) ) {
List < String > jqyeIds = Arrays . asList ( jqye . split ( "," ) ) ;
for ( int i = 0 ; i < jqyeIds . size ( ) ; i + + ) {
//假期余额id会用下划线“_”拼接上该假期余额记录被使用的时长
String jqyeIdStr = jqyeIds . get ( i ) ;
String [ ] jqyeInfo = jqyeIdStr . split ( "_" ) ;
String jqyeId = jqyeInfo [ 0 ] ;
double qjsc = Double . parseDouble ( jqyeInfo [ 1 ] ) ;
editedUseJqed . merge ( jqyeId , qjsc , Double : : sum ) ;
//最后一个id前的jqye的id都属于额度已使用完的, 记录到已用完假期余额id集合中
if ( i < jqyeIds . size ( ) - 1 ) {
unableUseJqyeIdList . add ( jqyeId ) ;
}
}
} else {
String [ ] jqyeInfo = jqye . split ( "_" ) ;
String jqyeId = jqyeInfo [ 0 ] ;
double qjsc = Double . parseDouble ( jqyeInfo [ 1 ] ) ;
editedUseJqed . merge ( jqyeId , qjsc , Double : : sum ) ;
}
}
editedLeaveInfo = detailTableData . stream ( )
. collect ( Collectors . toMap ( e - > Util . null2String ( e . get ( "qjr" ) ) + "_" + Util . null2String ( e . get ( "qjlx" ) ) + "_" + Util . null2String ( e . get ( "ksrq" ) ) ,
e - > Util . null2String ( e . get ( "qjsc" ) ) ) ) ;
}
//处理主表数据
String qjr = Util . null2String ( mainTableData . get ( "qjr" ) ) ;
//请假人姓名映射
Map < String , String > empIdToName = new HashMap < > ( ) ;
//请假人员列表
List < String > leaveEmpIdList = new ArrayList < > ( ) ;
if ( ! "" . equals ( qjr ) ) {
leaveEmpIdList = Arrays . asList ( qjr . split ( "," ) ) ;
String sql = "select id, lastname from hrmresource where id in (" + qjr + ")" ;
List < Map < String , Object > > data = DbTools . getSqlToList ( sql ) ;
empIdToName = data . stream ( ) . collect ( Collectors . toMap ( e - > Util . null2String ( e . get ( "id" ) ) , e - > Util . null2String ( e . get ( "lastname" ) ) ) ) ;
}
//开始日期、结束日期、请假方式、开始时间、结束时间、假期类型、请假时长
String startDate = Util . null2String ( mainTableData . get ( "ksrq" ) ) ;
String endDate = Util . null2String ( mainTableData . get ( "jsrq" ) ) ;
String startTime = Util . null2String ( mainTableData . get ( "kssj" ) ) ;
String endTime = Util . null2String ( mainTableData . get ( "jssj" ) ) ;
String leaveMode = Util . null2String ( mainTableData . get ( "cxjqj" ) ) ;
String leaveType = Util . null2String ( mainTableData . get ( "jqlx" ) ) ;
String leaveDuration = Util . null2String ( mainTableData . get ( "qjsc" ) ) ;
//获取填写的请假类型关联的考勤项目
String sql = "select id,mc,hsdw,hsl,jcbyxsyqjb,yxsydjb,qzsyyxjb,zdycbcndfgzsd,zdycrqqjndxxb from uf_jcl_kq_kqxm where id=?" ;
Map < String , Object > holidayItem = DbTools . getSqlToMap ( sql , leaveType ) ;
//判断是否需要自动移除时间区间内的非工作时长、自动移除日期区间内的休息日
boolean removeNonWorkTimeRange = "1" . equals ( Util . null2String ( holidayItem . get ( "zdycbcndfgzsd" ) ) ) ;
boolean removeNonWorkDayRange = "1" . equals ( Util . null2String ( holidayItem . get ( "zdycrqqjndxxb" ) ) ) ;
//判断考勤项目是否需要强制使用“优先使用项目”
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 ;
//遍历人员、日期,生成人员+日期+请假时长的请假信息
//获取请假日期集合
List < String > leaveDateList = DateUtil . getDatesBetween ( startDate , endDate ) ;
//请假人的请假区间内每一天的日期类型信息
Map < String , List < String > > restDayInfo = removeNonWorkDayRange ? getRestDayWithEmpId ( leaveEmpIdList , leaveType , startDate , endDate ) : null ;
//请假人的请假区间内的排班结果
Map < String , List < Map < String , Object > > > scheduleInfoMap = ( removeNonWorkDayRange | | removeNonWorkTimeRange ) ? getScheduleInfoWithEmpId ( leaveEmpIdList , startDate , endDate ) : null ;
//实际需要请假的日期集合
List < String > realLeaveDateList ;
//收集未关联假期余额的请假明细数据
List < Map < String , String > > simpleLeaveDetailList = new ArrayList < > ( ) ;
//收集已关联假期余额的请假明细数据
List < Map < String , String > > completeLeaveDetailList = new ArrayList < > ( ) ;
Map < String , String > simpleLeaveDetailItem ;
for ( String leaveEmpId : leaveEmpIdList ) {
//需要自动移除日期区间内的休息日时,去除请假日期区间中的休息日
List < Map < String , Object > > scheduleInfoList = new ArrayList < > ( ) ;
Map < String , String > dateToBcxxMap = new HashMap < > ( ) ;
if ( removeNonWorkDayRange | | removeNonWorkTimeRange ) {
scheduleInfoList = scheduleInfoMap . get ( leaveEmpId ) ;
dateToBcxxMap = scheduleInfoList . stream ( ) . collect ( Collectors . toMap ( e - > Util . null2String ( e . get ( "bcrq" ) ) , e - > Util . null2String ( e . get ( "bcxx" ) ) ) ) ;
}
if ( removeNonWorkDayRange ) {
//排班结果中休息的日期
List < String > restDateListFromSchedule = scheduleInfoList . stream ( )
. filter ( f - > Util . null2String ( f . get ( "sfxx" ) ) . equals ( CheckBoxEnum . CHECKED . getKey ( ) ) )
. map ( e - > Util . null2String ( e . get ( "bcrq" ) ) )
. collect ( Collectors . toList ( ) ) ;
List < String > allDateListFromSchedule = scheduleInfoList . stream ( ) . map ( e - > Util . null2String ( e . get ( "bcrq" ) ) ) . collect ( Collectors . toList ( ) ) ;
//排班结果中未出现的日期
List < String > nonSetDateListFromSchedule = leaveDateList . stream ( ) . filter ( f - > ! allDateListFromSchedule . contains ( f ) ) . collect ( Collectors . toList ( ) ) ;
//企业日历中人员对应日期的休息日
List < String > restDateList = restDayInfo . get ( leaveEmpId ) ;
//筛选排班信息无法辨别的日期,依靠企业日历的日期信息
restDateList = restDateList . stream ( ) . filter ( nonSetDateListFromSchedule : : contains ) . collect ( Collectors . toList ( ) ) ;
List < String > finalRestDateList = restDateList ;
realLeaveDateList = leaveDateList . stream ( ) . filter ( f - > ! finalRestDateList . contains ( f ) & & ! restDateListFromSchedule . contains ( f ) ) . collect ( Collectors . toList ( ) ) ;
} else {
realLeaveDateList = leaveDateList ;
}
for ( String leaveDate : realLeaveDateList ) {
//请假方式为“指定时间区间”时
if ( leaveMode . equals ( AskAndEvctionWayEnum . TIME_INTERVAL . getKey ( ) ) ) {
simpleLeaveDetailItem = new HashMap < > ( ) ;
//组装初步的请假明细数据
simpleLeaveDetailItem . put ( "qjr" , leaveEmpId ) ;
simpleLeaveDetailItem . put ( "ksrq" , leaveDate ) ;
simpleLeaveDetailItem . put ( "jsrq" , leaveDate ) ;
simpleLeaveDetailItem . put ( "kssj" , startTime ) ;
simpleLeaveDetailItem . put ( "jssj" , endTime ) ;
//获取班次id
String bcId = Util . null2String ( dateToBcxxMap . get ( leaveDate ) ) . split ( "-" ) [ 0 ] ;
//需要自动移除时间区间内的非工作时长,且请假方式为“指定时间区间”时,去除当前明细中开始时间、结束时间之间的非工作时长
if ( removeNonWorkTimeRange & & ! "" . equals ( bcId ) ) {
//查询班次明细
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 ) ;
//获取移除后的分钟数
int scMinutes = Utils . removeRestTime ( leaveDate + " " + startTime , leaveDate + " " + endTime , bcDetailData , leaveDate ) ;
//组装初步的请假时长
simpleLeaveDetailItem . put ( "qjsc" , String . format ( "%.2f" , scMinutes / 60.0 ) ) ;
} else {
//组装初步的请假时长
simpleLeaveDetailItem . put ( "qjsc" , leaveDuration ) ;
}
simpleLeaveDetailList . add ( simpleLeaveDetailItem ) ;
} else if ( leaveMode . equals ( AskAndEvctionWayEnum . HOUR . getKey ( ) ) ) {
simpleLeaveDetailItem = new HashMap < > ( ) ;
//组装初步的请假明细数据
simpleLeaveDetailItem . put ( "qjr" , leaveEmpId ) ;
simpleLeaveDetailItem . put ( "ksrq" , leaveDate ) ;
simpleLeaveDetailItem . put ( "jsrq" , leaveDate ) ;
simpleLeaveDetailItem . put ( "qjsc" , leaveDuration ) ;
simpleLeaveDetailList . add ( simpleLeaveDetailItem ) ;
} else if ( leaveMode . equals ( AskAndEvctionWayEnum . ALLDAY . getKey ( ) ) ) {
simpleLeaveDetailItem = new HashMap < > ( ) ;
//组装初步的请假明细数据
simpleLeaveDetailItem . put ( "qjr" , leaveEmpId ) ;
simpleLeaveDetailItem . put ( "ksrq" , leaveDate ) ;
simpleLeaveDetailItem . put ( "jsrq" , leaveDate ) ;
simpleLeaveDetailItem . put ( "qtj" , "1" ) ;
simpleLeaveDetailList . add ( simpleLeaveDetailItem ) ;
} else if ( leaveMode . equals ( AskAndEvctionWayEnum . HALFDAY . getKey ( ) ) ) {
simpleLeaveDetailItem = new HashMap < > ( ) ;
//组装初步的请假明细数据
simpleLeaveDetailItem . put ( "qjr" , leaveEmpId ) ;
simpleLeaveDetailItem . put ( "ksrq" , leaveDate ) ;
simpleLeaveDetailItem . put ( "jsrq" , leaveDate ) ;
simpleLeaveDetailItem . put ( "btj" , "1" ) ;
simpleLeaveDetailList . add ( simpleLeaveDetailItem ) ;
}
}
}
//按照人员id分组处理请假明细信息, 关联假期余额数据
Map < String , List < Map < String , String > > > leaveDetailGroupByEmp = simpleLeaveDetailList . stream ( ) . collect ( Collectors . groupingBy ( e - > Util . null2String ( e . get ( "qjr" ) ) ) ) ;
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 , leaveType , startDate , entry . getKey ( ) ) ;
List < Map < String , String > > detailListItem = new ArrayList < > ( ) ;
//判断考勤项目是否需要强制使用“优先使用项目”
if ( useFirstItemSign ) {
//2-收集优先使用的项目关联的可使用的余额, 才能够生成请假明细, 可使用的条件为, a-满足最小使用时长, b-满足使用次数上限, c-存在未休时长
List < Map < String , Object > > canUseFirstJqyeInfo = collectUsableHolidayBalance ( unableUseJqyeIdList , editedUseJqed , holidayPriorityItem . get ( "id" ) . toString ( ) , 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 ( ) ) ;
} else {
detailListItem = matchHolidayBalance ( editedLeaveInfo , checkAmountJqIdList , errorMessage , entry . getKey ( ) , empIdToName . get ( entry . getKey ( ) ) , canUseCheckJqyeInfo , null , editedUseJqed , editedUseJqlxWithEmp , entry . getValue ( ) , leaveType , null ) ;
}
if ( detailListItem . size ( ) > 0 ) {
completeLeaveDetailList . addAll ( detailListItem ) ;
}
}
if ( errorMessage . size ( ) = = 0 ) {
resultMap . put ( "status" , true ) ;
resultMap . put ( "data" , completeLeaveDetailList ) ;
} else {
resultMap . put ( "status" , false ) ;
resultMap . put ( "errorInfo" , errorMessage ) ;
resultMap . put ( "data" , null ) ;
}
return resultMap ;
}
private boolean kqCycleCheck ( String qjry , List < Map < String , String > > detailTableData , List < String > errorMessage , String empName ) {
/ * *
* 补 打 卡 日 期 是 否 关 账
* /
Map < String , Object > params = Maps . newHashMap ( ) ;
params . put ( "userId" , qjry ) ;
params . put ( "submitDate" , DateUtil . getCurrentDate ( ) ) ;
params . put ( "submitStr" , "ksrq" ) ;
params . put ( "submitDataList" , detailTableData ) ;
if ( detailTableData = = null | | detailTableData . size ( ) = = 0 ) {
errorMessage . add ( empName + "没有请假明细数据!" ) ;
return false ;
}
Map < String , Object > dataMap = makeUpClockInService . getKqCycleTimeIntervalCmd ( params ) ;
List < Map < String , Object > > closeList = ( List < Map < String , Object > > ) dataMap . get ( "closeList" ) ;
List < String > nocycleList = ( List < String > ) dataMap . get ( "nocycleList" ) ;
List < Map < String , Object > > dateList = ( List < Map < String , Object > > ) dataMap . get ( "dataList" ) ;
boolean status = ( boolean ) dataMap . get ( "status" ) ;
if ( ! status ) {
errorMessage . add ( empName + "没有考勤周期!" ) ;
return false ;
}
if ( closeList . size ( ) > 0 | | nocycleList . size ( ) > 0 ) {
String message = empName + ": " ;
if ( nocycleList . size ( ) > 0 ) {
message = message + String . join ( "," , nocycleList ) + "未找对对应的考勤周期;" ;
}
if ( closeList . size ( ) > 0 ) {
List < String > list = closeList . stream ( ) . map ( e - > e . get ( "rq" ) . toString ( ) ) . collect ( Collectors . toList ( ) ) ;
message = message + String . join ( "," , list ) + "对应的考勤周期的考勤周期已关账" ;
}
errorMessage . add ( message ) ;
return false ;
}
return true ;
}
private List < Map < String , String > > matchHolidayBalance ( Map < String , String > editedLeaveInfo , List < String > checkAmountJqIdList , List < String > errorMessage , String empId , String empName ,
List < Map < String , Object > > canUseCheckJqyeInfo , List < Map < String , Object > > canUseFirstJqyeInfo , Map < String , Double > editedUseJqed ,
Map < String , Double > editedUseJqlxWithEmp , List < Map < String , String > > leaveDetailList , String checkItemId , String firstItemId ) {
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 = 0 ;
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 ;
}
//减去编辑已使用时长
Double checkItemEditedUseSc = editedUseJqlxWithEmp . get ( checkItemId + "_" + empId ) ;
Double firstItemEditedUseSc = editedUseJqlxWithEmp . get ( firstItemId + "_" + empId ) ;
totalLeaveDuration = Utils . subtract ( totalLeaveDuration , checkItemEditedUseSc = = null ? 0 : checkItemEditedUseSc ) ;
totalLeaveDuration = Utils . subtract ( totalLeaveDuration , firstItemEditedUseSc = = null ? 0 : firstItemEditedUseSc ) ;
//如果总时长为0, 则退出
if ( totalLeaveDuration < = 0 ) {
return result ;
}
Map < String , Double > leaveDurationMap = new HashMap < > ( ) ;
leaveDurationMap . put ( "totalLeaveDuration" , totalLeaveDuration ) ;
//默认存在优先使用项目时长
boolean firstItemHaveDuration = true ;
//优先使用的假期类型项目是否不需要校验假期余额的额度
boolean firstItemNonCheck = firstItemId ! = null & & ! checkAmountJqIdList . contains ( firstItemId ) ;
//勾选的假期类型项目是否不需要校验假期余额的额度
boolean checkItemNonCheck = ! checkAmountJqIdList . contains ( checkItemId ) ;
//遍历关联请假余额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" ) ) ;
//请假时间
double leaveDuration = 0 ;
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 ) ;
//优先使用的的请假项目是否已被编辑
double firstItemEditedDetailSc = editedLeaveInfo . get ( empId + "_" + firstItemId + "_" + ksrq ) = = null ? 0 : Double . parseDouble ( editedLeaveInfo . get ( empId + "_" + firstItemId + "_" + ksrq ) ) ;
boolean firstItemEditedDetail = editedLeaveInfo . get ( empId + "_" + firstItemId + "_" + ksrq ) ! = null ;
//勾选的请假项目是否已被编辑
double checkItemEditedDetailSc = editedLeaveInfo . get ( empId + "_" + checkItemId + "_" + ksrq ) = = null ? 0 : Double . parseDouble ( editedLeaveInfo . get ( empId + "_" + checkItemId + "_" + ksrq ) ) ;
boolean checkItemEditedDetail = editedLeaveInfo . get ( empId + "_" + checkItemId + "_" + ksrq ) ! = null | | ( firstItemEditedDetail & & firstItemEditedDetailSc - leaveDuration > = 0 ) ;
if ( checkItemEditedDetail ) {
leaveDuration = Utils . subtract ( leaveDuration , firstItemEditedDetailSc ) ;
leaveDuration = Utils . subtract ( leaveDuration , checkItemEditedDetailSc ) ;
if ( leaveDuration < = 0 ) {
continue ;
}
}
//存在优先使用假期类型时,且该假期类型不需要进行额度校验
if ( firstItemNonCheck & & ! firstItemEditedDetail ) {
detailData . put ( "qjlx" , firstItemId ) ;
detailData . put ( "qjsc" , String . valueOf ( leaveDuration ) ) ;
result . add ( detailData ) ;
continue ;
}
//不存在优先使用假期类型时,勾选的假期类型不需要进行额度校验
if ( firstItemId = = null & & checkItemNonCheck & & ! checkItemEditedDetail ) {
detailData . put ( "qjlx" , checkItemId ) ;
detailData . put ( "qjsc" , String . valueOf ( leaveDuration ) ) ;
result . add ( detailData ) ;
continue ;
}
leaveDurationMap . put ( "leaveDuration" , leaveDuration ) ;
//存在优先使用假期类型时,但是需要进行额度校验
if ( canUseFirstJqyeInfo ! = null & & canUseFirstJqyeInfo . size ( ) > 0 & & firstItemHaveDuration & & ! firstItemEditedDetail ) {
dealLeaveDetailWithJqyeInfo ( detailData , canUseFirstJqyeInfo , editedUseJqed , leaveDurationMap , ksrq , firstItemId , result ) ;
if ( leaveDurationMap . get ( "leaveDuration" ) = = 0 ) {
//如果同假期类型出现多假期余额拼接配置一条请假明细时,请假明细的时长需要重新设置下
//请假明细初始要求时长已配置完成则赋值为初始请假时长,否则为初始时长-剩余未配置时长
if ( Util . null2String ( detailData . get ( "jqye" ) ) . contains ( "," ) ) {
detailData . put ( "qjsc" , String . valueOf ( leaveDuration ) ) ;
}
continue ;
} else {
firstItemHaveDuration = false ;
if ( Util . null2String ( detailData . get ( "jqye" ) ) . contains ( "," ) ) {
detailData . put ( "qjsc" , String . valueOf ( leaveDuration - leaveDurationMap . get ( "leaveDuration" ) ) ) ;
}
}
}
if ( ! "" . equals ( Util . null2String ( detailData . get ( "qjlx" ) ) ) ) {
result . add ( new HashMap < > ( detailData ) ) ;
detailData . remove ( "qjlx" ) ;
detailData . remove ( "qjsc" ) ;
detailData . remove ( "jqye" ) ;
}
//不存在优先使用假期类型,或者优先使用假期类型关联的假期余额用完时
//勾选的假期类型不需要进行额度校验
if ( checkItemNonCheck & & ! checkItemEditedDetail ) {
detailData . put ( "qjlx" , checkItemId ) ;
detailData . put ( "qjsc" , String . valueOf ( leaveDurationMap . get ( "leaveDuration" ) ) ) ;
result . add ( detailData ) ;
continue ;
}
//勾选的假期类型需要进行额度校验
if ( ! checkItemEditedDetail ) {
dealLeaveDetailWithJqyeInfo ( detailData , canUseCheckJqyeInfo , editedUseJqed , leaveDurationMap , ksrq , checkItemId , result ) ;
}
if ( leaveDurationMap . get ( "leaveDuration" ) > 0 ) {
//假期余额不足
String message = empName + "假期余额不足!" ;
errorMessage . add ( message ) ;
matchResultSign = false ;
break ;
}
}
return matchResultSign ? result : new ArrayList < > ( ) ;
}
private void dealLeaveDetailWithJqyeInfo ( Map < String , String > detailData , List < Map < String , Object > > canUseJqyeInfo ,
Map < String , Double > editedUseJqed , Map < String , Double > leaveDurationMap ,
String ksrq , String itemId , List < Map < String , String > > result ) {
double totalLeaveDuration = leaveDurationMap . get ( "totalLeaveDuration" ) ;
double leaveDuration = leaveDurationMap . get ( "leaveDuration" ) ;
//假期类型相关的假期余额记录
List < Map < String , Object > > holidayBalancefilterList = Lists . newArrayList ( ) ;
for ( Map < String , Object > map : canUseJqyeInfo ) {
if ( DateUtil . getTime ( map . get ( "yqsxrq" ) . toString ( ) ) . compareTo ( DateUtil . getTime ( ksrq ) ) > = 0 ) {
holidayBalancefilterList . add ( map ) ;
}
}
//使用的假期类型的额度单位
String eddw = Util . null2String ( holidayBalancefilterList . get ( 0 ) . get ( "eddw" ) ) ;
int multipleNum = eddw . equals ( AccountingUnitEnum . DAY . getKey ( ) ) ? 8 : 1 ;
for ( Map < String , Object > holidayBalance : holidayBalancefilterList ) {
//1-如果已编辑的请假明细中已有该假期余额id的记录, 则满足最小使用时长
boolean minLeaveDurationSign = editedUseJqed . get ( holidayBalance . get ( "id" ) . toString ( ) ) ! = null ;
//2-如果编辑记录中不存在,则需要判断是否满足最小使用时长
if ( ! minLeaveDurationSign ) {
String minLeaveDuration = Util . null2String ( holidayBalance . get ( "minLeaveDuration" ) ) ;
minLeaveDurationSign = "" . equals ( minLeaveDuration ) | | totalLeaveDuration > Double . parseDouble ( minLeaveDuration ) ;
}
//不满足最小使用时长,直接执行下一条
if ( ! minLeaveDurationSign ) {
continue ;
}
//额定未休时长
double wxsc = Util . null2String ( holidayBalance . get ( "wxsc" ) ) . equals ( "" ) ? 0 : Double . valueOf ( holidayBalance . get ( "wxsc" ) . toString ( ) ) ;
wxsc = multipleNum * wxsc ;
if ( leaveDuration > 0 & & wxsc > 0 ) {
detailData . put ( "qjlx" , itemId ) ;
String jqyeId = Util . null2String ( detailData . get ( "jqye" ) ) ;
if ( leaveDuration > wxsc ) {
detailData . put ( "qjsc" , String . valueOf ( wxsc ) ) ;
leaveDuration = Utils . subtract ( leaveDuration , wxsc ) ;
totalLeaveDuration = Utils . subtract ( totalLeaveDuration , wxsc ) ;
if ( "" . equals ( jqyeId ) ) {
detailData . put ( "jqye" , holidayBalance . get ( "id" ) . toString ( ) + "_" + wxsc ) ;
} else {
//同一假期类型, 当一条假期余额记录不足请假时长需求时, 需要拼接上另一条假期余额记录的id
detailData . put ( "jqye" , jqyeId + "," + holidayBalance . get ( "id" ) . toString ( ) + "_" + wxsc ) ;
}
wxsc = 0 ;
} else {
detailData . put ( "qjsc" , String . valueOf ( leaveDuration ) ) ;
wxsc = Utils . subtract ( wxsc , leaveDuration ) ;
//可能存在倍数转换
wxsc = Utils . divide ( wxsc , multipleNum ) ;
totalLeaveDuration = Utils . subtract ( totalLeaveDuration , leaveDuration ) ;
if ( "" . equals ( jqyeId ) ) {
detailData . put ( "jqye" , holidayBalance . get ( "id" ) . toString ( ) + "_" + leaveDuration ) ;
} else {
//同一假期类型, 当一条假期余额记录不足请假时长需求时, 需要拼接上另一条假期余额记录的id
detailData . put ( "jqye" , jqyeId + "," + holidayBalance . get ( "id" ) . toString ( ) + "_" + leaveDuration ) ;
}
leaveDuration = 0 ;
result . add ( detailData ) ;
}
holidayBalance . put ( "wxsc" , wxsc ) ;
}
}
leaveDurationMap . put ( "totalLeaveDuration" , totalLeaveDuration ) ;
leaveDurationMap . put ( "leaveDuration" , leaveDuration ) ;
}
/ * *
* 收 集 假 期 类 型 关 联 的 可 使 用 的 假 期 余 额
* @param unableUseJqyeIdList 不 可 使 用 的 假 期 余 额 id 集 合
* @param editedUseJqed 已 编 辑 过 的 假 期 余 额 id 和 具 体 使 用 的 时 长 映 射
* @param itemId 假 期 类 型 对 应 的 考 勤 项 目 id
* @param startDate
* @param leaveEmpId
* @return
* /
private List < Map < String , Object > > collectUsableHolidayBalance ( List < String > unableUseJqyeIdList , Map < String , Double > editedUseJqed , String itemId , String startDate , String leaveEmpId ) {
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 sxrq" ;
List < Map < String , Object > > holidayBalanceList = DbTools . getSqlToList ( sql , leaveEmpId , itemId , startDate , startDate ) ;
//获取假期额度规则中额度可修次数、单次最小休时长、额度单位
String jqedSql = "select eddw, dczskxsc, edbxdcxw from uf_jcl_kq_jqed where jb = ?" ;
Map < String , Object > jqedInfo = DbTools . getSqlToMap ( jqedSql , itemId ) ;
//假期额度的额度单位, 0-天、1-小时
String eddw = Util . null2String ( jqedInfo . get ( "eddw" ) ) ;
//单次最小休时长
String minDuration = Util . null2String ( jqedInfo . get ( "dczskxsc" ) ) ;
Double minLeaveDuration = null ;
if ( ! "" . equals ( eddw ) & & ! "" . equals ( minDuration ) ) {
minLeaveDuration = Double . parseDouble ( minDuration ) ;
if ( eddw . equals ( AccountingUnitEnum . DAY . getKey ( ) ) ) {
minLeaveDuration = minLeaveDuration * 8 ;
}
}
//额度可修次数
String allowLeaveNumStr = Util . null2String ( jqedInfo . get ( "edbxdcxw" ) ) ;
if ( ! "" . equals ( allowLeaveNumStr ) & & holidayBalanceList . size ( ) > 0 ) {
//查询请假记录中, 人员id+假期类别id情况下的结果, 遍历每条主表数据下的明细数据中使用了哪些假期余额id
sql = "select a.id,dt2.jqye from uf_jcl_kq_qjjl a left join uf_jcl_kq_qjjl_dt1 dt1 on dt1.mainid = a.id left join uf_jcl_kq_qjjl_dt2 dt2 on dt2.glmxid = dt1.glmxid " +
"where a.jqlx = " + itemId + " and qjry = " + leaveEmpId + " and a.cxqj = 0 and dt1.cxqj = 0 and a.jlzt in (0, 1) and dt1.glmxid is not null" ;
List < Map < String , Object > > leaveList = DbTools . getSqlToList ( sql ) ;
Map < String , Integer > jqyeUseNumInfo = new HashMap < > ( ) ;
List < String > leaveUseList = new ArrayList < > ( ) ;
Integer useNum = 0 ;
for ( Map < String , Object > leaveItem : leaveList ) {
String jqyeId = Util . null2String ( leaveItem . get ( "jqye" ) ) ;
if ( ! "" . equals ( jqyeId ) ) {
String leaveInfo = leaveItem . get ( "id" ) . toString ( ) + "_" + jqyeId ;
if ( leaveUseList . size ( ) = = 0 ) {
leaveUseList . add ( leaveInfo ) ;
jqyeUseNumInfo . put ( jqyeId , 1 ) ;
} else if ( ! leaveUseList . contains ( leaveInfo ) ) {
leaveUseList . add ( leaveInfo ) ;
useNum = jqyeUseNumInfo . get ( jqyeId ) ;
jqyeUseNumInfo . put ( jqyeId , useNum = = null ? 1 : + + useNum ) ;
}
}
}
//筛选次数未使用完的假期余额
holidayBalanceList = holidayBalanceList . stream ( ) . filter ( f - > {
int beforeUseNum = jqyeUseNumInfo . get ( f . get ( "id" ) . toString ( ) ) = = null ? 0 : jqyeUseNumInfo . get ( f . get ( "id" ) . toString ( ) ) ;
return Integer . parseInt ( allowLeaveNumStr ) > beforeUseNum ;
} ) . collect ( Collectors . toList ( ) ) ;
}
//遍历可使用的假期余额,去除已编辑请假明细记录中使用的时长
List < Map < String , Object > > canUseHolidayBalanceList = new ArrayList < > ( ) ;
for ( Map < String , Object > holidayBalance : holidayBalanceList ) {
String jqyeId = Util . null2String ( holidayBalance . get ( "id" ) ) ;
if ( ! unableUseJqyeIdList . contains ( jqyeId ) ) {
double wxsc = Utils . convertDouble ( holidayBalance . get ( "wxsc" ) ) ;
double editedUseSc = Utils . convertDouble ( editedUseJqed . get ( jqyeId ) ) ;
double realWxsc = wxsc - editedUseSc ;
if ( ( minLeaveDuration = = null | | wxsc > = minLeaveDuration ) & & realWxsc > 0 ) {
holidayBalance . put ( "wxsc" , realWxsc ) ;
holidayBalance . put ( "minLeaveDuration" , minLeaveDuration ) ;
holidayBalance . put ( "eddw" , eddw ) ;
canUseHolidayBalanceList . add ( holidayBalance ) ;
}
}
}
return canUseHolidayBalanceList ;
}
/ * *
* 请 假 人 的 请 假 区 间 内 的 排 班 结 果
* @param leaveEmpIdList
* @param startDate
* @param endDate
* @return
* /
private Map < String , List < Map < String , Object > > > getScheduleInfoWithEmpId ( List < String > leaveEmpIdList , String startDate , String endDate ) {
Map < String , List < Map < String , Object > > > scheduleInfo = new HashMap < > ( ) ;
Map < String , Object > params = new HashMap < > ( ) ;
params . put ( "tableName" , "uf_pbjg" ) ;
params . put ( "startDate" , startDate ) ;
params . put ( "endDate" , endDate ) ;
params . put ( "pblx" , "0" ) ;
params . put ( "current" , "1" ) ;
params . put ( "pageSize" , "999" ) ;
params . put ( "recurrence" , "1" ) ;
for ( String empId : leaveEmpIdList ) {
params . put ( "pbdx" , empId ) ;
Map < String , Object > schedulingResultsMap = schedulingResultsService . queryDataTableActualUse ( params ) ;
scheduleInfo . put ( empId , ( List < Map < String , Object > > ) schedulingResultsMap . get ( "data" ) ) ;
}
return scheduleInfo ;
}
/ * *
* 请 假 人 的 请 假 区 间 内 属 于 休 息 日 的 日 期 集 合
* @param leaveEmpIdList
* @param leaveType
* @param startDate
* @param endDate
* @return
* /
private Map < String , List < String > > getRestDayWithEmpId ( List < String > leaveEmpIdList , String leaveType , String startDate , String endDate ) {
Map < String , List < String > > restDayInfoWithEmpId = new HashMap < > ( ) ;
Map < String , Object > restDayParam = new HashMap < > ( ) ;
restDayParam . put ( "itemId" , leaveType ) ;
restDayParam . put ( "startDate" , startDate ) ;
restDayParam . put ( "endDate" , endDate ) ;
List < String > dateTypeList = new ArrayList < > ( ) ;
dateTypeList . add ( DateTypeEnum . HOLIDAY . getKey ( ) ) ;
dateTypeList . add ( DateTypeEnum . PUBLIC_RESTDAY . getKey ( ) ) ;
dateTypeList . add ( DateTypeEnum . EXCHANGE_LEAVEDAY . getKey ( ) ) ;
Map < String , Object > restDayInfo = new HashMap < > ( ) ;
List < Map < String , Object > > dataList = new ArrayList < > ( ) ;
List < String > restDateList = new ArrayList < > ( ) ;
for ( String empId : leaveEmpIdList ) {
restDayParam . put ( "userId" , empId ) ;
restDayInfo = getRestDayInterval ( restDayParam ) ;
dataList = ( List < Map < String , Object > > ) restDayInfo . get ( "data" ) ;
if ( dataList ! = null & & dataList . size ( ) > 0 ) {
restDateList = dataList . stream ( )
. filter ( f - > dateTypeList . contains ( Util . null2String ( f . get ( "rqlx" ) ) ) )
. map ( e - > Util . null2String ( e . get ( "rq" ) ) )
. collect ( Collectors . toList ( ) ) ;
}
restDayInfoWithEmpId . put ( empId , restDateList ) ;
}
return restDayInfoWithEmpId ;
}
}