diff --git a/src/com/engine/jucailinkq/attendance/component/ImportAndExport/service/impl/ExcelExportImportServiceImpl.java b/src/com/engine/jucailinkq/attendance/component/ImportAndExport/service/impl/ExcelExportImportServiceImpl.java index b546acf..6fcf2b4 100644 --- a/src/com/engine/jucailinkq/attendance/component/ImportAndExport/service/impl/ExcelExportImportServiceImpl.java +++ b/src/com/engine/jucailinkq/attendance/component/ImportAndExport/service/impl/ExcelExportImportServiceImpl.java @@ -107,7 +107,7 @@ public class ExcelExportImportServiceImpl extends Service implements ExcelExport List list = new ArrayList<>(); if (columnInfo != null && columnInfo.size() > 0) { for (Map columnItem : columnInfo) { - list.add(new WeaTableColumn("150px", Util.null2String(columnItem.get("title")), Util.null2String(columnItem.get("dataIndex")))); + list.add(new WeaTableColumn("150px", Util.null2String(columnItem.get("context")), Util.null2String(columnItem.get("dataIndex")))); } } return list; diff --git a/src/com/engine/jucailinkq/attendance/workflow/service/BusinessTripsApplyService.java b/src/com/engine/jucailinkq/attendance/workflow/service/BusinessTripsApplyService.java index 73bc016..a28c983 100644 --- a/src/com/engine/jucailinkq/attendance/workflow/service/BusinessTripsApplyService.java +++ b/src/com/engine/jucailinkq/attendance/workflow/service/BusinessTripsApplyService.java @@ -4,4 +4,11 @@ import java.util.Map; public interface BusinessTripsApplyService { Map getBusinessTripsApplyList(Map params); + + + /** + * 批量生成出差信息明细表数据 + * @param params + */ + Map generateBusinessTripsList(Map params); } diff --git a/src/com/engine/jucailinkq/attendance/workflow/service/impl/AskForLeaveServiceImpl.java b/src/com/engine/jucailinkq/attendance/workflow/service/impl/AskForLeaveServiceImpl.java index c727121..76fd809 100644 --- a/src/com/engine/jucailinkq/attendance/workflow/service/impl/AskForLeaveServiceImpl.java +++ b/src/com/engine/jucailinkq/attendance/workflow/service/impl/AskForLeaveServiceImpl.java @@ -458,7 +458,6 @@ public class AskForLeaveServiceImpl extends Service implements AskForLeaveServic : String.valueOf(qjscByAccount)); simpleLeaveDetailList.add(simpleLeaveDetailItem); } - simpleLeaveDetailList.add(simpleLeaveDetailItem); } else if (leaveMode.equals(AskAndEvctionWayEnum.ALLDAY.getKey()) && !restDateList.contains(leaveDate)) { simpleLeaveDetailItem = new HashMap<>(); //组装初步的请假明细数据 @@ -645,7 +644,7 @@ public class AskForLeaveServiceImpl extends Service implements AskForLeaveServic } totalLeaveDuration = totalLeaveDuration + leaveDuration; } - //减去编辑已使用时长 + //已编辑明细中已使用时长 Double checkItemEditedUseSc = editedUseJqlxWithEmp.getOrDefault(checkItemId + "_" + empId, (double) 0); Double firstItemEditedUseSc = editedUseJqlxWithEmp.getOrDefault(firstItemId + "_" + empId, (double) 0); // totalLeaveDuration = Utils.subtract(totalLeaveDuration, checkItemEditedUseSc == null ? 0 : checkItemEditedUseSc); diff --git a/src/com/engine/jucailinkq/attendance/workflow/service/impl/BusinessTripsApplyServiceImpl.java b/src/com/engine/jucailinkq/attendance/workflow/service/impl/BusinessTripsApplyServiceImpl.java index ee407e4..daa8d05 100644 --- a/src/com/engine/jucailinkq/attendance/workflow/service/impl/BusinessTripsApplyServiceImpl.java +++ b/src/com/engine/jucailinkq/attendance/workflow/service/impl/BusinessTripsApplyServiceImpl.java @@ -1,14 +1,26 @@ package com.engine.jucailinkq.attendance.workflow.service.impl; +import com.engine.common.util.ServiceUtil; +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.workflow.cmd.GetRestDayIntervalCmd; +import com.engine.jucailinkq.attendance.workflow.enums.AskAndEvctionWayEnum; import com.engine.jucailinkq.attendance.workflow.service.BusinessTripsApplyService; +import com.engine.jucailinkq.attendance.workflow.service.MakeUpClockInService; +import com.engine.jucailinkq.common.util.CommonUtil; +import com.engine.jucailinkq.common.util.DateUtil; import com.engine.jucailinkq.common.util.DbTools; import com.engine.core.impl.Service; +import com.engine.jucailinkq.common.util.Utils; import lombok.extern.slf4j.Slf4j; import weaver.general.Util; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; +import java.util.stream.Collectors; /** * @Author: sy @@ -17,6 +29,11 @@ import java.util.Map; **/ @Slf4j public class BusinessTripsApplyServiceImpl extends Service implements BusinessTripsApplyService { + + private SchedulingResultsService schedulingResultsService = ServiceUtil.getService(SchedulingResultsServiceImpl.class); + + private MakeUpClockInService makeUpClockInService = ServiceUtil.getService(MakeUpClockInServiceImpl.class); + @Override public Map getBusinessTripsApplyList(Map params) { @@ -40,4 +57,482 @@ public class BusinessTripsApplyServiceImpl extends Service implements BusinessTr return retmap; } + + @Override + public Map generateBusinessTripsList(Map params) { + Map resultMap = new HashMap<>(); + try { + List errorMessage = new ArrayList<>(); + // 流程表单主表数据 + Map mainTableData = (Map)params.get("mainTableData"); + log.info("mainTableData : {}", mainTableData); + // 流程表单明细表1数据 + List> detailTableData = (List>)params.get("detailTableData"); + //开始日期、结束日期、出差方式、开始时间、结束时间、出差类型、出差时长 + 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 ccMode = Util.null2String(mainTableData.get("ccsd")); + String ccType = Util.null2String(mainTableData.get("cclx")); + String ccDuration = Util.null2String(mainTableData.get("ccsc")); + String dailyRepeat = Util.null2String(mainTableData.get("mttsdcc")); + //获取出差日期集合 + List ccDateList = DateUtil.getDatesBetween(startDate, endDate); + //记录已编辑的出差记录,<人员id-出差类型-日期, 请假时长> + Map editedCcInfo = new HashMap<>(); + //处理明细表1数据,生成触发接口之前编辑内容中的出差信息 + editedCcInfo = dealDetailTableData(detailTableData, editedCcInfo); + //处理主表数据 + String ccr = Util.null2String(mainTableData.get("ccr")); + //出差人姓名映射 + Map empIdToName = new HashMap<>(); + //出差人员列表 + List ccEmpIdList = new ArrayList<>(); + if (!"".equals(ccr)) { + ccEmpIdList = Arrays.asList(ccr.split(",")); + String sql = "select id, lastname from hrmresource where id in (" + ccr + ")"; + List> data = DbTools.getSqlToList(sql); + empIdToName = data.stream().collect(Collectors.toMap(e->Util.null2String(e.get("id")), e->Util.null2String(e.get("lastname")))); + } + //获取填写的出差类型关联的考勤项目 + String sql = "select id,mc,hsdw,hsl,jcbyxsyqjb,yxsydjb,qzsyyxjb,zdycbcndfgzsd,zdycrqqjndxxb,yxyz,zdyzsl,zysd from uf_jcl_kq_kqxm where id=?"; + Map holidayItem = DbTools.getSqlToMap(sql,ccType); + //出差类型名称 + String checkItemName = Util.null2String(holidayItem.get("mc")); + //核算单位 + String hsdw = Util.null2String(holidayItem.get("hsdw")); + //核算量 + double hsl = Double.parseDouble(Util.null2String(holidayItem.get("hsl"))); + //核算单位为天时,只允许请全天假、半天假 + if (hsdw.equals(AccountingUnitEnum.DAY.getKey()) && !ccMode.equals(AskAndEvctionWayEnum.ALLDAY.getKey()) && !ccMode.equals(AskAndEvctionWayEnum.HALFDAY.getKey())) { + resultMap.put("status", false); + resultMap.put("errorInfo", "出差类型的核算单位为天时,只允许选择全天、半天!"); + resultMap.put("data", null); + return resultMap; + } + //判断是否需要自动移除时间区间内的非工作时长、自动移除日期区间内的休息日 + boolean removeNonWorkTimeRange = "1".equals(Util.null2String(holidayItem.get("zdycbcndfgzsd"))); + boolean removeNonWorkDayRange = "1".equals(Util.null2String(holidayItem.get("zdycrqqjndxxb"))); + //获取作用时段 + String zysd = Util.null2String(holidayItem.get("zysd")); + //获取需要统计时长的班段类型集合(仅作用在“指定时间区间”请假方式) + List countBdlxList = new ArrayList<>(); + List zysdList = new ArrayList<>(); + if (!"".equals(zysd)) { + zysdList = Arrays.asList(zysd.split(",")); + for(String zysdKey : zysdList) { + countBdlxList.add(Utils.getClassSegmenByWorkFor(zysdKey)); + } + if (!removeNonWorkTimeRange) { + countBdlxList.add(ClassSegmentTypeEnum.REST_AND_DINE.getKey()); + countBdlxList.add(ClassSegmentTypeEnum.REST_PERIOD.getKey()); + countBdlxList.add(ClassSegmentTypeEnum.DINING_PERIOD.getKey()); + } + } + //遍历人员、日期,生成人员+日期+出差时长的出差信息 + //出差人的出差区间内每一天的日期类型信息,来自于企业日历 + Map> restDayInfo = removeNonWorkDayRange ? getRestDayWithEmpId(ccEmpIdList, startDate, endDate) : new HashMap<>(); + //出差人的出差区间内的排班结果 + Map>> scheduleInfoMap = (removeNonWorkDayRange || removeNonWorkTimeRange) ? getScheduleInfoWithEmpId(ccEmpIdList, DateUtil.beforeDay(startDate,1), DateUtil.AfterDay(endDate,1)) : new HashMap<>(); + + //生成出差明细数据 + List> simpleDetailList; + if (ccMode.equals(AskAndEvctionWayEnum.TIME_INTERVAL.getKey()) && !"1".equals(dailyRepeat)) { + simpleDetailList = createDetailListWithNoDaily(ccEmpIdList, ccDateList, removeNonWorkDayRange, scheduleInfoMap, + restDayInfo, startDate, endDate, startTime, endTime, countBdlxList, hsdw, hsl, ccType, empIdToName, checkItemName); + } else { + simpleDetailList = createDetailList(ccEmpIdList, ccDateList, removeNonWorkDayRange, scheduleInfoMap, + restDayInfo, ccMode, startTime, endTime, ccDuration, countBdlxList, hsdw, hsl, ccType, empIdToName, checkItemName); + } + + //按照人员id分组处理请假明细信息,关联假期余额数据 + Map>> ccDetailGroupByEmp = simpleDetailList.stream().collect(Collectors.groupingBy(e -> Util.null2String(e.get("ccr")))); + //收集需要新建的出差明细数据 + List> completeLeaveDetailList = new ArrayList<>(); + Map finalEditedCcInfo = editedCcInfo; + for(Map.Entry>> entry : ccDetailGroupByEmp.entrySet()) { + //校验该人员的考勤周期是否正常 + boolean kqCycleAllow = kqCycleCheck(entry.getKey(), entry.getValue(), errorMessage, empIdToName.get(entry.getKey())); + if (!kqCycleAllow) { + continue; + } + List> detailListItem = entry.getValue().stream() + .filter(f -> finalEditedCcInfo.get(Util.null2String(f.get("ccr")) + "_" + Util.null2String(f.get("cclx")) + "_" + Util.null2String(f.get("ksrq"))) == null) + .collect(Collectors.toList()); + 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); + } + + } catch (Exception e) { + log.info(e.getMessage()); + resultMap.put("status", false); + resultMap.put("errorInfo", e.getMessage()); + resultMap.put("data", null); + } + return resultMap; + } + + /** + * 出差人的出差区间内属于休息日的日期集合,企业日历角度 + * @param empIdList 出差人id集合 + * @param startDate 开始日期 + * @param endDate 结束日期 + */ + private Map> getRestDayWithEmpId(List empIdList, String startDate, String endDate) { + Map> restDayInfoWithEmpId = new HashMap<>(); + + Map restDayParam = new HashMap<>(); + restDayParam.put("startDate", startDate); + restDayParam.put("endDate", endDate); + + List dateTypeList = new ArrayList<>(); + dateTypeList.add(DateTypeEnum.HOLIDAY.getKey()); + dateTypeList.add(DateTypeEnum.PUBLIC_RESTDAY.getKey()); + dateTypeList.add(DateTypeEnum.EXCHANGE_LEAVEDAY.getKey()); + Map restDayInfo; + List> dataList; + List restDateList = new ArrayList<>(); + for (String empId : empIdList) { + restDayParam.put("userId", empId); + restDayInfo = commandExecutor.execute(new GetRestDayIntervalCmd(restDayParam,user)); + dataList = (List>) 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; + } + + /** + * 出差人的出差区间内的排班结果 + * @param empIdList 出差人id集合 + * @param startDate 开始日期 + * @param endDate 结束日期 + */ + private Map>> getScheduleInfoWithEmpId(List empIdList, String startDate, String endDate) { + Map>> scheduleInfo = new HashMap<>(); + Map 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 : empIdList) { + params.put("pbdx", empId); + Map schedulingResultsMap = schedulingResultsService.queryDataTableActualUse(params); + scheduleInfo.put(empId, (List>) schedulingResultsMap.get("data")); + } + return scheduleInfo; + } + + /** + * @param empId 人员id + * @param detailTableData 明细数据列表 + * @param errorMessage 错误信息 + * @param empName 人员姓名 + * @return 校验该人员的考勤周期是否正常 + */ + private boolean kqCycleCheck(String empId, List> detailTableData, List errorMessage, String empName) { + + Map params = new HashMap<>(); + params.put("userId",empId); + 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 dataMap = makeUpClockInService.getKqCycleTimeIntervalCmd(params); + List> closeList = (List>)dataMap.get("closeList"); + List nocycleList = (List)dataMap.get("nocycleList"); + + 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 list = closeList.stream().map(e->e.get("rq").toString()).collect(Collectors.toList()); + message = message +String.join(",",list)+"对应的考勤周期的考勤周期已关账"; + } + errorMessage.add(message); + return false; + } + return true; + } + + /** + * @param detailTableData 明细表1数据 + * @param editedLeaveInfo 记录已编辑的出差记录,<人员id-出差类型-日期, 出差时长> + * @return 处理明细表1数据,生成触发接口之前编辑内容中的出差信息 + */ + private Map dealDetailTableData(List> detailTableData, Map editedLeaveInfo) { + if (detailTableData != null && detailTableData.size() > 0){ + editedLeaveInfo = detailTableData.stream() + .collect(Collectors.toMap(e-> Util.null2String(e.get("ccr")) + "_" + Util.null2String(e.get("cclx")) + "_" + Util.null2String(e.get("ksrq")), + e->Util.null2String(e.get("qjsc")))); + } + return editedLeaveInfo; + } + + /** + * @param empIdList 人员id集合 + * @param dateList 日期集合 + * @param removeNonWorkDayRange 是否移除非工作日时长 + * @param scheduleInfoMap 排班信息 + * @param restDayInfo 休息日信息 + * @param mode 出差方式 + * @param startTime 开始时间 + * @param endTime 结束时间 + * @param ccDuration 出差时长 + * @param countBdlxList 收集需要统计时长的班段类型 + * @return 组装初步的出差明细 + */ + private List> createDetailList(List empIdList, List dateList, boolean removeNonWorkDayRange, + Map>> scheduleInfoMap, Map> restDayInfo, + String mode, String startTime, String endTime, String ccDuration, List countBdlxList, + String hsdw, double hsl, String ccType, Map empIdToName, String checkItemName) { + List> simpleDetailList = new ArrayList<>(); + Map simpleDetailItem; + for (String ccEmpId : empIdList) { + //需要自动移除日期区间内的休息日时,去除出差日期区间中的休息日 + List> scheduleInfoList = scheduleInfoMap.getOrDefault(ccEmpId, new ArrayList<>()); + Map dateToBcxxMap = scheduleInfoList.stream().collect(Collectors.toMap(e->Util.null2String(e.get("bcrq")),e->Util.null2String(e.get("bcxx")))); + List restDateList = new ArrayList<>(); + if (removeNonWorkDayRange) { + //排班结果中休息的日期 + List 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 allDateListFromSchedule = scheduleInfoList.stream().map(e -> Util.null2String(e.get("bcrq"))).collect(Collectors.toList()); + //排班结果中未出现的日期 + List nonSetDateListFromSchedule = dateList.stream().filter(f -> !allDateListFromSchedule.contains(f)).collect(Collectors.toList()); + //企业日历中人员对应日期的休息日 + restDateList = restDayInfo.get(ccEmpId); + //筛选排班信息无法辨别的日期,依靠企业日历的日期信息 + restDateList = restDateList.stream().filter(nonSetDateListFromSchedule::contains).collect(Collectors.toList()); + restDateList.addAll(restDateListFromSchedule); + } + String ccEmpName = empIdToName.get(ccEmpId); + for (String ccDate : dateList) { + //出差方式为“指定时间区间”时 + if (mode.equals(AskAndEvctionWayEnum.TIME_INTERVAL.getKey())) { + simpleDetailItem = new HashMap<>(); + //组装初步的明细数据 + simpleDetailItem.put("ccr", ccEmpId); + simpleDetailItem.put("cclx", ccType); + simpleDetailItem.put("ccrName", ccEmpName); + simpleDetailItem.put("cclxName", checkItemName); + simpleDetailItem.put("ksrq", ccDate); + simpleDetailItem.put("jsrq", ccDate); + simpleDetailItem.put("kssj", startTime); + simpleDetailItem.put("jssj", endTime); + //获取当天班次id + String currentDayBcId = restDateList.contains(ccDate) ? "" : Util.null2String(dateToBcxxMap.get(ccDate)).split("-")[0]; + //获取前一天班次id + String yesterday = DateUtil.beforeDay(ccDate,1); + String yesterdayBcId = restDateList.contains(yesterday) ? "" : Util.null2String(dateToBcxxMap.get(yesterday)).split("-")[0]; + //获取次日班次id + String nextDay = DateUtil.AfterDay(ccDate,1); + String nextDayBcId = restDateList.contains(nextDay) ? "" : Util.null2String(dateToBcxxMap.get(nextDay)).split("-")[0]; + String sql = ""; + List> bcDetailData; + String endDate = ccDate; + int scMinutes = 0; + //开始时时和结束时间存在跨天情况时,即开始时间大于等于结束时间 + if (startTime.compareTo(endTime) >= 0) { + endDate = nextDay; + simpleDetailItem.put("jsrq", nextDay); + } + if (!"".equals(yesterdayBcId)) { + sql = "select id, bdlx, gsrq, kssj as dtkssj, jssj as dtjssj from uf_jcl_kq_bcxx_dt1 where mainid = " + yesterdayBcId; + bcDetailData = DbTools.getSqlToList(sql); + bcDetailData = bcDetailData.stream().filter(e -> countBdlxList.contains(Util.null2String(e.get("bdlx")))).collect(Collectors.toList()); + //获取需要累计的班段时长区间和请假区间存在交集的分钟数 + scMinutes = Utils.removeTime(ccDate + " " + startTime, endDate + " " + endTime, bcDetailData, yesterday); + } + if (!"".equals(currentDayBcId)) { + sql = "select id, bdlx, gsrq, kssj as dtkssj, jssj as dtjssj from uf_jcl_kq_bcxx_dt1 where mainid = " + currentDayBcId; + bcDetailData = DbTools.getSqlToList(sql); + bcDetailData = bcDetailData.stream().filter(e -> countBdlxList.contains(Util.null2String(e.get("bdlx")))).collect(Collectors.toList()); + //获取需要累计的班段时长区间和请假区间存在交集的分钟数 + scMinutes = scMinutes + Utils.removeTime(ccDate + " " + startTime, endDate + " " + endTime, bcDetailData, ccDate); + } + if (!"".equals(nextDayBcId)) { + sql = "select id, bdlx, gsrq, kssj as dtkssj, jssj as dtjssj from uf_jcl_kq_bcxx_dt1 where mainid = " + nextDayBcId; + bcDetailData = DbTools.getSqlToList(sql); + bcDetailData = bcDetailData.stream().filter(e -> countBdlxList.contains(Util.null2String(e.get("bdlx")))).collect(Collectors.toList()); + //获取需要累计的班段时长区间和请假区间存在交集的分钟数 + scMinutes = scMinutes + Utils.removeTime(ccDate + " " + startTime, endDate + " " + endTime, bcDetailData, nextDay); + } + //增加加班计划中的数据,加班计划明细中的数据作为“加班计划”班段类型数据的补充 + if (countBdlxList.contains(ClassSegmentTypeEnum.OVERTIME_PLAN.getKey())) { + sql = "select b.jbry,b.ksrq,b.kssj,b.jblx,b.jsrq,b.jssj,b.jbsc,b.gsrq from uf_jcl_kq_jbjh a left join uf_jcl_kq_jbjh_dt1 b on a.id=b.mainid where b.jbry =? and b.ksrq>=? and b.jsrq<=? and (b.jbcx=0 or b.jbcx is null) and a.jlzt=1"; + List> overtimePlanList = DbTools.getSqlToList(sql, ccEmpId, DateUtil.beforeDay(ccDate,1), DateUtil.AfterDay(endDate,1)); + int scMinutesInOvertimePlan = Utils.removeTimeWithOvertimePlan(ccDate + " " + startTime, endDate + " " + endTime, overtimePlanList); + scMinutes = scMinutes + scMinutesInOvertimePlan; + } + if (scMinutes > 0) { + double ccscByAccount = Utils.getItemduration(hsl, hsdw, scMinutes, AccountingUnitEnum.MINUTES, 8.0); + //组装初步的出差时长 + simpleDetailItem.put("ccsc", hsdw.equals(AccountingUnitEnum.MINUTES.getKey()) + ? String.format("%.2f", ccscByAccount / 60.0) + : String.valueOf(ccscByAccount)); + simpleDetailList.add(simpleDetailItem); + } + } else if (mode.equals(AskAndEvctionWayEnum.HOUR.getKey()) && !restDateList.contains(ccDate)) { + simpleDetailItem = new HashMap<>(); + //组装初步的明细数据 + simpleDetailItem.put("ccr", ccEmpId); + simpleDetailItem.put("cclx", ccType); + simpleDetailItem.put("ccrName", ccEmpName); + simpleDetailItem.put("cclxName", checkItemName); + simpleDetailItem.put("ksrq", ccDate); + simpleDetailItem.put("jsrq", ccDate); + simpleDetailItem.put("ccsc", ccDuration); + if (Double.parseDouble(ccDuration) > 0) { + double ccscByAccount = Utils.getItemduration(hsl, hsdw, Double.parseDouble(ccDuration), AccountingUnitEnum.HOUR, 8.0); + //组装初步的出差时长 + simpleDetailItem.put("ccsc", hsdw.equals(AccountingUnitEnum.MINUTES.getKey()) + ? String.format("%.2f", ccscByAccount / 60.0) + : String.valueOf(ccscByAccount)); + simpleDetailList.add(simpleDetailItem); + } + } else if (mode.equals(AskAndEvctionWayEnum.ALLDAY.getKey()) && !restDateList.contains(ccDate)) { + simpleDetailItem = new HashMap<>(); + //组装初步的明细数据 + simpleDetailItem.put("ccr", ccEmpId); + simpleDetailItem.put("cclx", ccType); + simpleDetailItem.put("ccrName", ccEmpName); + simpleDetailItem.put("cclxName", checkItemName); + simpleDetailItem.put("ksrq", ccDate); + simpleDetailItem.put("jsrq", ccDate); + simpleDetailItem.put("qtcc", "1"); + simpleDetailList.add(simpleDetailItem); + } else if (mode.equals(AskAndEvctionWayEnum.HALFDAY.getKey()) && !restDateList.contains(ccDate)) { + simpleDetailItem = new HashMap<>(); + //组装初步的明细数据 + simpleDetailItem.put("ccr", ccEmpId); + simpleDetailItem.put("cclx", ccType); + simpleDetailItem.put("ccrName", ccEmpName); + simpleDetailItem.put("cclxName", checkItemName); + simpleDetailItem.put("ksrq", ccDate); + simpleDetailItem.put("jsrq", ccDate); + simpleDetailItem.put("btcc", "1"); + simpleDetailList.add(simpleDetailItem); + } + } + } + return simpleDetailList; + } + + /** + * @param empIdList 出差人员id集合 + * @param dateList 出差日期集合 + * @param removeNonWorkDayRange 是否移除非工作日时长 + * @param scheduleInfoMap 排班信息 + * @param restDayInfo 休息日信息 + * @param startDate 开始日期 + * @param endDate 结束日期 + * @param startTime 开始时间 + * @param endTime 结束时间 + * @param countBdlxList 收集需要统计时长的班段类型 + * @return 组装初步的出差明细,这边只处理“每天同时段出差”未勾选,且出差方式为“指定时间区间” + */ + private List> createDetailListWithNoDaily(List empIdList, List dateList, boolean removeNonWorkDayRange, + Map>> scheduleInfoMap, Map> restDayInfo, + String startDate, String endDate, String startTime, String endTime, List countBdlxList, + String hsdw, double hsl, String ccType, Map empIdToName, String checkItemName) { + List> simpleDetailList = new ArrayList<>(); + Map simpleDetailItem; + String sql = ""; + List> bcDetailData; + String targetDateBcId = ""; + int scMinutes = 0; + dateList.add(0, DateUtil.beforeDay(startDate,1)); + dateList.add(DateUtil.AfterDay(endDate,1)); + for (String ccEmpId : empIdList) { + //需要自动移除日期区间内的休息日时,去除出差日期区间中的休息日 + List> scheduleInfoList = scheduleInfoMap.getOrDefault(ccEmpId, new ArrayList<>()); + Map dateToBcxxMap = scheduleInfoList.stream().collect(Collectors.toMap(e->Util.null2String(e.get("bcrq")),e->Util.null2String(e.get("bcxx")))); + + List restDateList = new ArrayList<>(); + if (removeNonWorkDayRange) { + //排班结果中休息的日期 + List 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 allDateListFromSchedule = scheduleInfoList.stream().map(e -> Util.null2String(e.get("bcrq"))).collect(Collectors.toList()); + //排班结果中未出现的日期 + List nonSetDateListFromSchedule = dateList.stream().filter(f -> !allDateListFromSchedule.contains(f)).collect(Collectors.toList()); + //企业日历中人员对应日期的休息日 + restDateList = restDayInfo.get(ccEmpId); + //筛选排班信息无法辨别的日期,依靠企业日历的日期信息 + restDateList = restDateList.stream().filter(nonSetDateListFromSchedule::contains).collect(Collectors.toList()); + restDateList.addAll(restDateListFromSchedule); + } + String ccEmpName = empIdToName.get(ccEmpId); + simpleDetailItem = new HashMap<>(); + //组装初步的出差明细数据 + simpleDetailItem.put("ccr", ccEmpId); + simpleDetailItem.put("cclx", ccType); + simpleDetailItem.put("ccrName", ccEmpName); + simpleDetailItem.put("cclxName", checkItemName); + simpleDetailItem.put("ksrq", startDate); + simpleDetailItem.put("jsrq", endDate); + simpleDetailItem.put("kssj", startTime); + simpleDetailItem.put("jssj", endTime); + for (String date : dateList) { + targetDateBcId = restDateList.contains(date) ? "" : Util.null2String(dateToBcxxMap.get(date)).split("-")[0]; + if (!"".equals(targetDateBcId)) { + sql = "select id, bdlx, gsrq, kssj as dtkssj, jssj as dtjssj from uf_jcl_kq_bcxx_dt1 where mainid = " + targetDateBcId; + bcDetailData = DbTools.getSqlToList(sql); + bcDetailData = bcDetailData.stream().filter(e -> countBdlxList.contains(Util.null2String(e.get("bdlx")))).collect(Collectors.toList()); + //获取需要累计的班段时长区间和请假区间存在交集的分钟数 + scMinutes = scMinutes + Utils.removeTime(startDate + " " + startTime, endDate + " " + endTime, bcDetailData, date); + } + } + //增加加班计划中的数据,加班计划明细中的数据作为“加班计划”班段类型数据的补充 + if (countBdlxList.contains(ClassSegmentTypeEnum.OVERTIME_PLAN.getKey())) { + sql = "select b.jbry,b.ksrq,b.kssj,b.jblx,b.jsrq,b.jssj,b.jbsc,b.gsrq from uf_jcl_kq_jbjh a left join uf_jcl_kq_jbjh_dt1 b on a.id=b.mainid where b.jbry =? and b.ksrq>=? and b.jsrq<=? and (b.jbcx=0 or b.jbcx is null) and a.jlzt=1"; + List> overtimePlanList = DbTools.getSqlToList(sql, ccEmpId, DateUtil.beforeDay(startDate,1), DateUtil.AfterDay(endDate,1)); + int scMinutesInOvertimePlan = Utils.removeTimeWithOvertimePlan(startDate + " " + startTime, endDate + " " + endTime, overtimePlanList); + scMinutes = scMinutes + scMinutesInOvertimePlan; + } + if (scMinutes > 0) { + double ccscByAccount = Utils.getItemduration(hsl, hsdw, scMinutes, AccountingUnitEnum.MINUTES, 8.0); + //组装初步的出差时长 + simpleDetailItem.put("ccsc", hsdw.equals(AccountingUnitEnum.MINUTES.getKey()) + ? String.format("%.2f", ccscByAccount / 60.0) + : String.valueOf(ccscByAccount)); + simpleDetailList.add(simpleDetailItem); + } + } + return simpleDetailList; + } }