Commit c1a3588c by 王志超

feat: 变更工单完结时间和超期处理

parent f93efe87
...@@ -58,6 +58,7 @@ import com.netease.mail.yanxuan.change.dal.entity.ChangeFile; ...@@ -58,6 +58,7 @@ import com.netease.mail.yanxuan.change.dal.entity.ChangeFile;
import com.netease.mail.yanxuan.change.dal.entity.ChangeRecord; import com.netease.mail.yanxuan.change.dal.entity.ChangeRecord;
import com.netease.mail.yanxuan.change.dal.entity.ChangeSubFlowRecord; import com.netease.mail.yanxuan.change.dal.entity.ChangeSubFlowRecord;
import com.netease.mail.yanxuan.change.dal.entity.ChangeType; import com.netease.mail.yanxuan.change.dal.entity.ChangeType;
import com.netease.mail.yanxuan.change.dal.mapper.ChangeExecRecordMapper;
import com.netease.mail.yanxuan.change.dal.mapper.ChangeRecordMapper; import com.netease.mail.yanxuan.change.dal.mapper.ChangeRecordMapper;
import com.netease.mail.yanxuan.change.dal.mapper.ChangeSubFlowRecordMapper; import com.netease.mail.yanxuan.change.dal.mapper.ChangeSubFlowRecordMapper;
import com.netease.mail.yanxuan.change.dal.meta.model.po.ChangeCommanderPO; import com.netease.mail.yanxuan.change.dal.meta.model.po.ChangeCommanderPO;
...@@ -133,6 +134,9 @@ public class ChangeFlowBiz { ...@@ -133,6 +134,9 @@ public class ChangeFlowBiz {
private ChangeRecordMapper changeRecordMapper; private ChangeRecordMapper changeRecordMapper;
@Autowired @Autowired
private ChangeExecRecordMapper changeExecRecordMapper;
@Autowired
private ChangeSubFlowRecordMapper changeSubFlowRecordMapper; private ChangeSubFlowRecordMapper changeSubFlowRecordMapper;
@Autowired @Autowired
...@@ -1301,19 +1305,20 @@ public class ChangeFlowBiz { ...@@ -1301,19 +1305,20 @@ public class ChangeFlowBiz {
if (CollectionUtils.isNotEmpty(changeRecords)) { if (CollectionUtils.isNotEmpty(changeRecords)) {
// 批量查询所有变更行动工单,构建 Map<changeRecordId, List<subFlowId>>,提升性能 // 批量查询所有变更行动工单,构建 Map<changeRecordId, List<subFlowId>>,提升性能
final Map<Long, List<String>> subFlowIdsMap; final Map<Long, List<String>> subFlowIdsMap;
List<Long> changeRecordIds = changeRecords.stream() // 批量查询所有行动工单,构建 Map<changeRecordId, List<ChangeSubFlowRecord>>,用于后续过滤和超期判断
.map(ChangeRecord::getId) final Map<Long, List<ChangeSubFlowRecord>> subFlowRecordsMap;
.collect(Collectors.toList()); List<Long> changeRecordIds = changeRecords.stream().map(ChangeRecord::getId).collect(Collectors.toList());
List<ChangeSubFlowRecord> subFlowRecords = changeSubFlowRecordService.getByChangeRecordIds(changeRecordIds); List<ChangeSubFlowRecord> subFlowRecords = changeSubFlowRecordService.getByChangeRecordIds(changeRecordIds);
if (CollectionUtils.isNotEmpty(subFlowRecords)) { if (CollectionUtils.isNotEmpty(subFlowRecords)) {
subFlowIdsMap = subFlowRecords.stream() subFlowIdsMap = subFlowRecords.stream().filter(record -> StringUtils.isNotBlank(record.getSubFlowId()))
.filter(record -> StringUtils.isNotBlank(record.getSubFlowId())) .collect(Collectors.groupingBy(ChangeSubFlowRecord::getChangeRecordId,
.collect(Collectors.groupingBy( Collectors.mapping(ChangeSubFlowRecord::getSubFlowId, Collectors.toList())));
ChangeSubFlowRecord::getChangeRecordId, // 按 changeRecordId 分组,不过滤状态,后续在内部方法中根据业务需求过滤
Collectors.mapping(ChangeSubFlowRecord::getSubFlowId, Collectors.toList()) subFlowRecordsMap = subFlowRecords.stream()
)); .collect(Collectors.groupingBy(ChangeSubFlowRecord::getChangeRecordId));
} else { } else {
subFlowIdsMap = new HashMap<>(); subFlowIdsMap = new HashMap<>();
subFlowRecordsMap = new HashMap<>();
} }
list = changeRecords.stream().map(c -> { list = changeRecords.stream().map(c -> {
ChangeFlowVO changeFlowVO = new ChangeFlowVO(); ChangeFlowVO changeFlowVO = new ChangeFlowVO();
...@@ -1382,6 +1387,9 @@ public class ChangeFlowBiz { ...@@ -1382,6 +1387,9 @@ public class ChangeFlowBiz {
changeFlowVO.setFlowOwnership(flowOwnership); changeFlowVO.setFlowOwnership(flowOwnership);
} }
// 设置变更完结时间和是否超期标识
buildChangeEndTime(c, changeFlowVO, subFlowRecordsMap);
return changeFlowVO; return changeFlowVO;
}).collect(Collectors.toList()); }).collect(Collectors.toList());
...@@ -2055,4 +2063,133 @@ public class ChangeFlowBiz { ...@@ -2055,4 +2063,133 @@ public class ChangeFlowBiz {
return resetCount; return resetCount;
} }
/**
* 构建变更完结时间和是否超期标识
*
* 时间展示逻辑:
* - 未完成的工单:展示预期完成时间(changeConfirmResultTime)
* - 已完成工单(END):展示实际完成时间(updateTime)
* - 取消的工单(CANCEL):展示取消时间(updateTime)
*
* 超期判断逻辑(仅针对非完结/取消的变更单):
* - 变更单的 changeConfirmResultTime 超过两个工作日未处理
* - 或者工单下属的执行项里的 changeExecFinishTime 超过两个工作日未处理(仅判断未完结或未取消的行动工单对应的行动项)
*
* @param changeRecord 变更记录
* @param changeFlowVO 变更工单视图对象
* @param subFlowRecordsMap 所有行动工单Map,key为changeRecordId,value为该主单下所有行动工单列表
*/
private void buildChangeEndTime(ChangeRecord changeRecord, ChangeFlowVO changeFlowVO, Map<Long, List<ChangeSubFlowRecord>> subFlowRecordsMap) {
Integer state = changeRecord.getState();
Long changeConfirmResultTime = changeRecord.getChangeConfirmResultTime();
Long updateTime = changeRecord.getUpdateTime();
if (ChangeStatusEnum.END.getStatus().equals(state)) {
// 已完成工单:展示实际完成时间(updateTime)
changeFlowVO.setChangeEndTime(updateTime);
changeFlowVO.setIsOverdue(false);
} else if (ChangeStatusEnum.CANCEL.getStatus().equals(state)) {
// 取消的工单:展示取消时间(updateTime)
changeFlowVO.setChangeEndTime(updateTime);
changeFlowVO.setIsOverdue(false);
} else {
// 未完成的工单:展示预期完成时间(changeConfirmResultTime)
changeFlowVO.setChangeEndTime(changeConfirmResultTime);
// 超期判断:非完结/取消的变更单,判断是否超过两个工作日未处理
boolean isOverdue = false;
Long currentTime = DateUtils.getCurrentTime();
// 判断变更单的 changeConfirmResultTime 是否超过两个工作日
if (isOverdueByWorkdays(changeConfirmResultTime, currentTime, 2)) {
isOverdue = true;
}
// 判断执行项的 changeExecFinishTime 是否超过两个工作日
// 注意:只判断未完结或未取消的行动工单对应的行动项
if (!isOverdue) {
// 从Map中获取该主单下所有行动工单
List<ChangeSubFlowRecord> allSubFlows = subFlowRecordsMap.getOrDefault(changeRecord.getId(), new ArrayList<>());
// 内部过滤:只保留未完结或未取消的行动工单
List<ChangeSubFlowRecord> activeSubFlows = allSubFlows.stream()
.filter(subFlow -> {
Integer status = subFlow.getStatus();
return status != null
&& !ChangeSubFlowStatusEnum.FINISHED.getStatus().equals(status)
&& !ChangeSubFlowStatusEnum.CANCELLED.getStatus().equals(status);
})
.collect(Collectors.toList());
if (CollectionUtils.isNotEmpty(activeSubFlows)) {
// 提取未完结或未取消的行动工单的ID
Set<Long> activeSubFlowRecordIds = activeSubFlows.stream()
.map(ChangeSubFlowRecord::getId)
.collect(Collectors.toSet());
// 批量查询这些行动工单对应的行动项
List<ChangeExecRecord> execRecords = changeExecRecordMapper.selectBySubFlowRecordIds(new ArrayList<>(activeSubFlowRecordIds));
if (CollectionUtils.isNotEmpty(execRecords)) {
for (ChangeExecRecord execRecord : execRecords) {
Long changeExecFinishTime = execRecord.getChangeExecFinishTime();
if (changeExecFinishTime != null && isOverdueByWorkdays(changeExecFinishTime, currentTime, 2)) {
isOverdue = true;
break;
}
}
}
}
}
changeFlowVO.setIsOverdue(isOverdue);
}
}
/**
* 判断指定时间是否超过指定工作日数未处理
*
* @param targetTime 目标时间(需要判断的时间)
* @param currentTime 当前时间
* @param workdays 工作日数
* @return true: 超过指定工作日数未处理;false: 未超过
*/
private boolean isOverdueByWorkdays(Long targetTime, Long currentTime, int workdays) {
if (targetTime == null || currentTime == null) {
return false;
}
// 计算目标时间加上指定工作日数后的时间
Long deadlineTime = addWorkdays(targetTime, workdays);
// 如果当前时间超过截止时间,则超期
return currentTime > deadlineTime;
}
/**
* 在指定时间基础上增加指定工作日数(排除周末)
*
* @param time 起始时间
* @param workdays 工作日数
* @return 增加工作日数后的时间
*/
private Long addWorkdays(Long time, int workdays) {
if (time == null || workdays <= 0) {
return time;
}
java.util.Calendar calendar = java.util.Calendar.getInstance();
calendar.setTimeInMillis(time);
int addedDays = 0;
while (addedDays < workdays) {
calendar.add(java.util.Calendar.DAY_OF_MONTH, 1);
int dayOfWeek = calendar.get(java.util.Calendar.DAY_OF_WEEK);
// 排除周六(7)和周日(1)
if (dayOfWeek != java.util.Calendar.SATURDAY && dayOfWeek != java.util.Calendar.SUNDAY) {
addedDays++;
}
}
return calendar.getTimeInMillis();
}
} }
...@@ -356,12 +356,37 @@ public class ChangeFlowExportCallback implements DesCallbackService { ...@@ -356,12 +356,37 @@ public class ChangeFlowExportCallback implements DesCallbackService {
ChangeResultEnum resultEnum = ChangeResultEnum.getByValue(record.getChangeResult()); ChangeResultEnum resultEnum = ChangeResultEnum.getByValue(record.getChangeResult());
log.debug("[obtainOther] record:{}, resultEnum:{}", JSON.toJSONString(record), resultEnum); log.debug("[obtainOther] record:{}, resultEnum:{}", JSON.toJSONString(record), resultEnum);
changeFlowExcelDTO.setChangeResult(resultEnum == null ? "/" : resultEnum.getDesc()); changeFlowExcelDTO.setChangeResult(resultEnum == null ? "/" : resultEnum.getDesc());
if (record.getState().equals(ChangeStatusEnum.CANCEL.getStatus())
|| record.getState().equals(ChangeStatusEnum.END.getStatus())) { // 时间展示逻辑:
changeFlowExcelDTO.setChangeEndTime(DateUtils.parseLongToString(record.getUpdateTime(), DateUtils.DATE_TIME_FORMAT)); // - 未完成的工单:展示预期完成时间(changeConfirmResultTime)
// - 已完成工单(END):展示实际完成时间(updateTime)
// - 取消的工单(CANCEL):展示取消时间(updateTime)
Integer state = record.getState();
Long changeConfirmResultTime = record.getChangeConfirmResultTime();
Long updateTime = record.getUpdateTime();
if (ChangeStatusEnum.END.getStatus().equals(state)) {
// 已完成工单:展示实际完成时间(updateTime)
if (updateTime != null) {
changeFlowExcelDTO.setChangeEndTime(DateUtils.parseLongToString(updateTime, DateUtils.DATE_TIME_FORMAT));
} else {
changeFlowExcelDTO.setChangeEndTime("/");
}
} else if (ChangeStatusEnum.CANCEL.getStatus().equals(state)) {
// 取消的工单:展示取消时间(updateTime)
if (updateTime != null) {
changeFlowExcelDTO.setChangeEndTime(DateUtils.parseLongToString(updateTime, DateUtils.DATE_TIME_FORMAT));
} else { } else {
changeFlowExcelDTO.setChangeEndTime("/"); changeFlowExcelDTO.setChangeEndTime("/");
} }
} else {
// 未完成的工单:展示预期完成时间(changeConfirmResultTime)
if (changeConfirmResultTime != null) {
changeFlowExcelDTO.setChangeEndTime(DateUtils.parseLongToString(changeConfirmResultTime, DateUtils.DATE_TIME_FORMAT));
} else {
changeFlowExcelDTO.setChangeEndTime("/");
}
}
} }
private void buildGoodsPrincipal(ChangeGoodsPrincipalPO changeGoodsPrincipalPO, ChangeFlowExcelDTO changeFlowExcelDTO) { private void buildGoodsPrincipal(ChangeGoodsPrincipalPO changeGoodsPrincipalPO, ChangeFlowExcelDTO changeFlowExcelDTO) {
......
...@@ -162,11 +162,26 @@ public class ChangeFlowVO { ...@@ -162,11 +162,26 @@ public class ChangeFlowVO {
private Long createTime; private Long createTime;
/** /**
* 变更结果确认时间 * 变更结果确认时间(预期完成时间)
*/ */
private Long changeConfirmResultTime; private Long changeConfirmResultTime;
/** /**
* 变更完结时间(实际完成时间/取消时间)
* 未完成的工单:展示预期完成时间(changeConfirmResultTime)
* 已完成工单:展示实际完成时间(updateTime)
* 取消的工单:展示取消时间(updateTime)
*/
private Long changeEndTime;
/**
* 是否超出预计完成时间(用于前端标红展示)
* true: 已完成工单的实际完成时间超出预期完成时间
* false: 其他情况
*/
private Boolean isOverdue;
/**
* 取消原因 * 取消原因
*/ */
private String cancelReason; private String cancelReason;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment