考勤-请假流程请假明细假期余额失效期优先使用

main
sy 5 months ago
parent e3fa2b207d
commit 160ad5d0ab

@ -157,6 +157,11 @@ public class AskForLeaveServiceImpl extends Service implements AskForLeaveServic
String leaveType = Util.null2String(mainTableData.get("jqlx")); String leaveType = Util.null2String(mainTableData.get("jqlx"));
String leaveDuration = Util.null2String(mainTableData.get("qjsc")); String leaveDuration = Util.null2String(mainTableData.get("qjsc"));
String dailyRepeat = Util.null2String(mainTableData.get("mtcfsdjq")); String dailyRepeat = Util.null2String(mainTableData.get("mtcfsdjq"));
//假期余额使用规则0-假别优先1-失效日期优先默认0
String jqyeUsePriority = Util.null2String(mainTableData.get("yesygz"));
if ("".equals(jqyeUsePriority)) {
jqyeUsePriority = "0";
}
//获取请假日期集合 //获取请假日期集合
List<String> leaveDateList = DateUtil.getDatesBetween(startDate, endDate); List<String> leaveDateList = DateUtil.getDatesBetween(startDate, endDate);
//已编辑内容中的假期额度使用信息 //已编辑内容中的假期额度使用信息
@ -277,11 +282,37 @@ public class AskForLeaveServiceImpl extends Service implements AskForLeaveServic
// } // }
//20241021逻辑变更根据考勤项目的“优先使用项目”信息获取所有可使用假期余额信息 //20241021逻辑变更根据考勤项目的“优先使用项目”信息获取所有可使用假期余额信息
Map<String, List<Map<String, Object>>> canUseJqyeInfo = new HashMap<>(); Map<String, List<Map<String, Object>>> canUseJqyeInfo = new HashMap<>();
//20241107需求变更获取所有可使用假期余额信息列表并按照失效期+级联优先级排序
List<Map<String, Object>> canUseJqyeList = new ArrayList<>();
//记录假别优先级
int jbPriorityValue = 1;
List<Map<String, Object>> canUseJqyeItem;
for (Map<String, Object> item : holidayPriorityItemList) { 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)); if (!checkAmountJqIdList.contains(item.get("id").toString())) {
continue;
}
//20241107需求变更根据流程中设置的假期额度使用优先规则收集假期余额数据
canUseJqyeItem = collectUsableHolidayBalance(unableUseJqyeIdList, editedUseJqed, item, startDate, entry.getKey(), empIdToName.get(entry.getKey()), modeId, errorMessage, jbPriorityValue);
if ("0".equals(jqyeUsePriority)) {
canUseJqyeInfo.put(item.get("id").toString(), canUseJqyeItem);
} else if ("1".equals(jqyeUsePriority)) {
canUseJqyeList.addAll(canUseJqyeItem);
}
}
if (canUseJqyeList.size() > 0) {
//按照延期失效日期早+级联优先级高(优先数字小)规则排序
canUseJqyeList.sort(Comparator.comparing((Map<String, Object> h) -> (String) h.get("yqsxrq"))
.thenComparing(h -> (Integer) h.get("jbPriorityValue")));
}
List<Map<String,String>> detailListItem = new ArrayList<>();
if ("0".equals(jqyeUsePriority)) {
detailListItem = matchHolidayWithPriority(editedLeaveInfo, checkAmountJqIdList, errorMessage, entry.getKey(),
empIdToName.get(entry.getKey()), canUseJqyeInfo, holidayPriorityItemList, editedUseJqed, editedUseJqlxWithEmp, entry.getValue(), editedEmpLeaveInfo.get(entry.getKey()));
} else if ("1".equals(jqyeUsePriority)) {
detailListItem = matchHolidayWithDatePriority(editedLeaveInfo, checkAmountJqIdList, errorMessage, entry.getKey(),
empIdToName.get(entry.getKey()), canUseJqyeList, holidayPriorityItemList, editedUseJqed, editedUseJqlxWithEmp, entry.getValue(), editedEmpLeaveInfo.get(entry.getKey()));
} }
List<Map<String,String>> detailListItem = matchHolidayWithPriority(editedLeaveInfo, checkAmountJqIdList, errorMessage, entry.getKey(),
empIdToName.get(entry.getKey()), canUseJqyeInfo, holidayPriorityItemList, editedUseJqed, editedUseJqlxWithEmp, entry.getValue(), editedEmpLeaveInfo.get(entry.getKey()));
if (detailListItem.size() > 0) { if (detailListItem.size() > 0) {
completeLeaveDetailList.addAll(detailListItem); completeLeaveDetailList.addAll(detailListItem);
} }
@ -876,6 +907,7 @@ public class AskForLeaveServiceImpl extends Service implements AskForLeaveServic
jqlxEdited = editedLeaveInfo.get(empId + "_" + jqlxId + "_" + ksrq) != null; jqlxEdited = editedLeaveInfo.get(empId + "_" + jqlxId + "_" + ksrq) != null;
//本次请假日期范围内,已存在该请假类型开始日期相同的请假明细,则不使用该请假类型 //本次请假日期范围内,已存在该请假类型开始日期相同的请假明细,则不使用该请假类型
if (jqlxEditedUseSc > 0 || jqlxEdited) { if (jqlxEditedUseSc > 0 || jqlxEdited) {
jqlxEdited = true;
continue; continue;
} }
leaveDuration = leaveDurationMap.get("leaveDuration"); leaveDuration = leaveDurationMap.get("leaveDuration");
@ -934,6 +966,118 @@ public class AskForLeaveServiceImpl extends Service implements AskForLeaveServic
return matchResultSign ? result : new ArrayList<>(); return matchResultSign ? result : new ArrayList<>();
} }
/**
* @param editedLeaveInfo
* @param checkAmountJqIdList id
* @param errorMessage
* @param empId id
* @param empName
* @param canUseJqyeList 使+
* @param editedUseJqed 使
* @param editedUseJqlxWithEmp ,id_id使
* @param leaveDetailList
* @return id
*/
private List<Map<String, String>> matchHolidayWithDatePriority(Map<String, String> editedLeaveInfo, List<String> checkAmountJqIdList, List<String> errorMessage, String empId, String empName,
List<Map<String, Object>> canUseJqyeList, List<Map<String, Object>> holidayPriorityItemList, Map<String, Double> editedUseJqed,
Map<String, Double> editedUseJqlxWithEmp, List<Map<String, String>> leaveDetailList, List<Map<String, String>> editedLeaveInfoList) {
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")));
}
//单日假期“全局唯一性”约束校验
boolean dailyCheckSign = checkDailyLeaveLicense(empId, empName, detailData, editedLeaveInfoList, leaveDuration, errorMessage);
if (!dailyCheckSign) {
leaveDurationMap.put("totalLeaveDuration", Utils.subtract(leaveDurationMap.get("totalLeaveDuration"), leaveDuration));
continue;
}
log.info("leaveDuration : [{}]", leaveDuration);
leaveDurationMap.put("leaveDuration", leaveDuration);
//20241107逻辑变更按照假期余额延长失效日期+假期项目级联优先级,(失效日期越早+优先级越高)依次分配请假时长
Map<String, String> jqlxIdToNameInfo = holidayPriorityItemList.stream().collect(Collectors.toMap(e->Util.null2String(e.get("id")),e->Util.null2String(e.get("mc"))));
dealLeaveDetailWithAllJqye(detailData, canUseJqyeList, editedUseJqed, leaveDurationMap, ksrq, result, jqlxIdToNameInfo, editedLeaveInfo, editedUseJqlxWithEmp, empId);
//额度假匹配结束,如果还有请假时长未分配,筛选出假期中非额度假的假期类型来分配请假时长
leaveDuration = leaveDurationMap.get("leaveDuration");
if (leaveDuration > 0) {
holidayPriorityItemList = holidayPriorityItemList.stream().filter(f -> !checkAmountJqIdList.contains(f.get("id").toString())).collect(Collectors.toList());
if (holidayPriorityItemList.size() == 0) {
errorMessage.add(empName + "_" + ksrq + "假期余额不足!");
matchResultSign = false;
}
boolean jqlxEdited = false;
for (Map<String, Object> holidayItem : holidayPriorityItemList) {
Double jqlxEditedUseSc = editedUseJqlxWithEmp.getOrDefault(holidayItem.get("id") + "_" + empId, (double) 0);
//使用的的请假项目是否已被编辑
jqlxEdited = editedLeaveInfo.get(empId + "_" + holidayItem.get("id") + "_" + ksrq) != null;
//本次请假日期范围内,已存在该请假类型开始日期相同的请假明细,则不使用该请假类型
if (jqlxEditedUseSc > 0 || jqlxEdited) {
jqlxEdited = true;
continue;
}
detailData.put("qjlx", holidayPriorityItemList.get(0).get("id").toString());
detailData.put("qjlxName", jqlxIdToNameInfo.get(holidayPriorityItemList.get(0).get("id").toString()));
detailData.put("qjsc", leaveDurationMap.get("leaveDuration").toString());
detailData.put("jqye", "");
result.add(detailData);
leaveDuration = 0;
}
if (leaveDuration > 0) {
String message = empName;
if (jqlxEdited) {
//人员id+日期+假期类型三种条件约束唯一性
message = message + "_" + ksrq + "本流程中已存在一笔该请假类型的请假明细!";
} else {
//假期余额不足
message = message + "_" + ksrq + "假期余额不足!";
}
errorMessage.add(message);
matchResultSign = false;
}
}
}
return matchResultSign ? result : new ArrayList<>();
}
private boolean checkDailyLeaveLicense(String empId, String empName, Map<String, String> detailData, List<Map<String, String>> editedLeaveInfoList, private boolean checkDailyLeaveLicense(String empId, String empName, Map<String, String> detailData, List<Map<String, String>> editedLeaveInfoList,
double leaveDuration, List<String> errorMessage) { double leaveDuration, List<String> errorMessage) {
//判断当前请假信息属于哪一种请假方式(全天、半天、指定时长、指定区间) //判断当前请假信息属于哪一种请假方式(全天、半天、指定时长、指定区间)
@ -1121,8 +1265,10 @@ public class AskForLeaveServiceImpl extends Service implements AskForLeaveServic
return false; return false;
} }
//使用的假期类型的额度单位 //使用的假期类型的额度单位
String eddw = Util.null2String(holidayBalancefilterList.get(0).get("eddw")); // String eddw = Util.null2String(holidayBalancefilterList.get(0).get("eddw"));
int multipleNum = eddw.equals(AccountingUnitEnum.DAY.getKey()) ? 8 : 1; // int multipleNum = eddw.equals(AccountingUnitEnum.DAY.getKey()) ? 8 : 1;
String hsdw = Util.null2String(holidayBalancefilterList.get(0).get("hsdw"));
int multipleNum = hsdw.equals(AccountingUnitEnum.DAY.getKey()) ? 8 : 1;
for (Map<String, Object> holidayBalance : holidayBalancefilterList) { for (Map<String, Object> holidayBalance : holidayBalancefilterList) {
//1-如果已编辑的请假明细中已有该假期余额id的记录则满足最小使用时长;如果result的请假明细中已有该假期余额id的记录则满足最小使用时长 //1-如果已编辑的请假明细中已有该假期余额id的记录则满足最小使用时长;如果result的请假明细中已有该假期余额id的记录则满足最小使用时长
boolean minLeaveDurationSign = editedUseJqed.get(holidayBalance.get("id").toString()) != null || result.stream().anyMatch(map -> itemId.equals(map.get("qjlx"))); boolean minLeaveDurationSign = editedUseJqed.get(holidayBalance.get("id").toString()) != null || result.stream().anyMatch(map -> itemId.equals(map.get("qjlx")));
@ -1182,6 +1328,94 @@ public class AskForLeaveServiceImpl extends Service implements AskForLeaveServic
} }
private void dealLeaveDetailWithAllJqye(Map<String, String> detailData, List<Map<String, Object>> canUseJqyeList, Map<String, Double> editedUseJqed,
Map<String, Double> leaveDurationMap, String ksrq, List<Map<String, String>> result, Map<String, String> jqlxIdToNameInfo,
Map<String, String> editedLeaveInfo, Map<String, Double> editedUseJqlxWithEmp, String empId) {
double totalLeaveDuration = leaveDurationMap.get("totalLeaveDuration");
double leaveDuration = leaveDurationMap.get("leaveDuration");
List<Map<String, String>> simpleResult = new ArrayList<>();
//假期余额记录
List<Map<String, Object>> holidayBalancefilterList = new ArrayList<>();
for (Map<String, Object> map : canUseJqyeList){
if (DateUtil.getTime(map.get("yqsxrq").toString()).compareTo(DateUtil.getTime(ksrq)) >= 0){
holidayBalancefilterList.add(map);
}
}
if (holidayBalancefilterList.size() == 0) {
return;
}
//使用的假期类型的额度单位
String hsdw = Util.null2String(holidayBalancefilterList.get(0).get("hsdw"));
int multipleNum = hsdw.equals(AccountingUnitEnum.DAY.getKey()) ? 8 : 1;
boolean jqlxEdited;
for (Map<String, Object> holidayBalance : holidayBalancefilterList) {
String jqlxId = holidayBalance.get("jqid").toString();
Double jqlxEditedUseSc = editedUseJqlxWithEmp.getOrDefault(jqlxId + "_" + empId, (double) 0);
//使用的的请假项目是否已被编辑
jqlxEdited = editedLeaveInfo.get(empId + "_" + jqlxId + "_" + ksrq) != null;
//本次请假日期范围内,已存在该请假类型开始日期相同的请假明细,则不使用该请假类型
if (jqlxEditedUseSc > 0 || jqlxEdited) {
continue;
}
//1-如果已编辑的请假明细中已有该假期余额id的记录则满足最小使用时长;如果result的请假明细中已有该假期余额id的记录则满足最小使用时长
boolean minLeaveDurationSign = editedUseJqed.get(holidayBalance.get("id").toString()) != null || result.stream().anyMatch(map -> jqlxId.equals(map.get("qjlx")));
//2-如果编辑记录中不存在,则需要判断是否满足最小使用时长
if (!minLeaveDurationSign) {
String minLeaveDuration = Util.null2String(holidayBalance.get("minLeaveDuration"));
minLeaveDurationSign = "".equals(minLeaveDuration) || totalLeaveDuration >= Double.parseDouble(minLeaveDuration) * multipleNum;
}
//不满足最小使用时长,直接执行下一条
if (!minLeaveDurationSign) {
continue;
}
//额定未休时长
double wxsc = "".equals(Util.null2String(holidayBalance.get("wxsc"))) ? 0 : Double.parseDouble(holidayBalance.get("wxsc").toString());
wxsc = multipleNum * wxsc;
if (leaveDuration > 0 && wxsc > 0) {
detailData.put("qjlx", jqlxId);
detailData.put("qjlxName", jqlxIdToNameInfo.get(jqlxId));
if (leaveDuration > wxsc) {
detailData.put("qjsc", String.valueOf(wxsc));
leaveDuration = Utils.subtract(leaveDuration, wxsc);
totalLeaveDuration = Utils.subtract(totalLeaveDuration, wxsc);
detailData.put("jqye", holidayBalance.get("id").toString() + "_" + wxsc);
wxsc = 0;
simpleResult.add(new HashMap<>(detailData));
} else {
detailData.put("qjsc", String.valueOf(leaveDuration));
wxsc = Utils.subtract(wxsc, leaveDuration);
//可能存在倍数转换
wxsc = Utils.divide(wxsc, multipleNum);
totalLeaveDuration = Utils.subtract(totalLeaveDuration, leaveDuration);
detailData.put("jqye", holidayBalance.get("id").toString() + "_" + leaveDuration);
leaveDuration = 0;
simpleResult.add(detailData);
}
holidayBalance.put("wxsc", wxsc);
}
}
//合并同一假期类型的明细
if (simpleResult.size() > 0) {
Map<String, List<Map<String, String>>> simpleResultGroup = simpleResult.stream().collect(Collectors.groupingBy(m -> m.get("qjlx")));
for (Map.Entry<String, List<Map<String, String>>> entry : simpleResultGroup.entrySet()) {
double qjscSum = entry.getValue().stream().mapToDouble(f->Double.parseDouble(f.get("qjsc"))).sum();
String jqyeUseInfo = entry.getValue().stream().map(map -> map.get("jqye")).collect(Collectors.joining(","));
Map<String, String> resultItem = entry.getValue().get(0);
resultItem.put("qjsc", String.valueOf(qjscSum));
resultItem.put("jqye", jqyeUseInfo);
result.add(resultItem);
}
}
leaveDurationMap.put("totalLeaveDuration", totalLeaveDuration);
leaveDurationMap.put("leaveDuration", leaveDuration);
}
/** /**
* 使 * 使
* @param unableUseJqyeIdList 使id * @param unableUseJqyeIdList 使id
@ -1189,9 +1423,10 @@ public class AskForLeaveServiceImpl extends Service implements AskForLeaveServic
* @param holidayItem * @param holidayItem
* @param startDate * @param startDate
* @param leaveEmpId id * @param leaveEmpId id
* @param jbPriorityValue
*/ */
private List<Map<String, Object>> collectUsableHolidayBalance(List<String> unableUseJqyeIdList, Map<String, Double> editedUseJqed, Map<String,Object> holidayItem, 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 startDate, String leaveEmpId, String empName, String modeId, List<String> errorMessage, int jbPriorityValue) {
String itemId = Util.null2String(holidayItem.get("id")); 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"; 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";
@ -1228,6 +1463,8 @@ public class AskForLeaveServiceImpl extends Service implements AskForLeaveServic
errorMessage.add(message); errorMessage.add(message);
return new ArrayList<>(); return new ArrayList<>();
} }
//假期的核算单位0-天、1-小时
String hsdw = Util.null2String(holidayItem.get("hsdw"));
//假期额度的额度单位0-天、1-小时 //假期额度的额度单位0-天、1-小时
String eddw = Util.null2String(jqedInfo.get("eddw")); String eddw = Util.null2String(jqedInfo.get("eddw"));
int multiple = 1; int multiple = 1;
@ -1289,6 +1526,8 @@ public class AskForLeaveServiceImpl extends Service implements AskForLeaveServic
holidayBalance.put("wxsc", Utils.divide(realWxsc, multiple)); holidayBalance.put("wxsc", Utils.divide(realWxsc, multiple));
holidayBalance.put("minLeaveDuration", minLeaveDuration == null ? null : Utils.divide(minLeaveDuration, multiple)); holidayBalance.put("minLeaveDuration", minLeaveDuration == null ? null : Utils.divide(minLeaveDuration, multiple));
holidayBalance.put("eddw", eddw); holidayBalance.put("eddw", eddw);
holidayBalance.put("hsdw", hsdw);
holidayBalance.put("jbPriorityValue", jbPriorityValue);
canUseHolidayBalanceList.add(holidayBalance); canUseHolidayBalanceList.add(holidayBalance);
} }
} }

@ -18,6 +18,7 @@
kssj: WfForm.getFieldValue(WfForm.convertFieldNameToId("kssj")), kssj: WfForm.getFieldValue(WfForm.convertFieldNameToId("kssj")),
jssj: WfForm.getFieldValue(WfForm.convertFieldNameToId("jssj")), jssj: WfForm.getFieldValue(WfForm.convertFieldNameToId("jssj")),
cxjqj: WfForm.getFieldValue(WfForm.convertFieldNameToId("cxjqj")), cxjqj: WfForm.getFieldValue(WfForm.convertFieldNameToId("cxjqj")),
yesygz: WfForm.getFieldValue(WfForm.convertFieldNameToId("yesygz")),
qjsc: WfForm.getFieldValue(WfForm.convertFieldNameToId("qjsc")) qjsc: WfForm.getFieldValue(WfForm.convertFieldNameToId("qjsc"))
} }

@ -19,6 +19,7 @@
kssj: WfForm.getFieldValue(WfForm.convertFieldNameToId("kssj")), kssj: WfForm.getFieldValue(WfForm.convertFieldNameToId("kssj")),
jssj: WfForm.getFieldValue(WfForm.convertFieldNameToId("jssj")), jssj: WfForm.getFieldValue(WfForm.convertFieldNameToId("jssj")),
cxjqj: WfForm.getFieldValue(WfForm.convertFieldNameToId("cxjqj")), cxjqj: WfForm.getFieldValue(WfForm.convertFieldNameToId("cxjqj")),
yesygz: WfForm.getFieldValue(WfForm.convertFieldNameToId("yesygz")),
qjsc: WfForm.getFieldValue(WfForm.convertFieldNameToId("qjsc")) qjsc: WfForm.getFieldValue(WfForm.convertFieldNameToId("qjsc"))
} }

Loading…
Cancel
Save