@@ -32,6 +32,7 @@ import org.apache.commons.lang3.StringUtils; | |||||
import org.checkerframework.checker.nullness.qual.Nullable; | import org.checkerframework.checker.nullness.qual.Nullable; | ||||
import org.flowable.engine.TaskService; | import org.flowable.engine.TaskService; | ||||
import org.flowable.task.api.Task; | import org.flowable.task.api.Task; | ||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; | |||||
import org.springframework.scheduling.annotation.Scheduled; | import org.springframework.scheduling.annotation.Scheduled; | ||||
import org.springframework.stereotype.Component; | import org.springframework.stereotype.Component; | ||||
@@ -48,6 +49,7 @@ import java.util.stream.Collectors; | |||||
@Component | @Component | ||||
@Slf4j | @Slf4j | ||||
@RequiredArgsConstructor | @RequiredArgsConstructor | ||||
@ConditionalOnExpression("${early-warning-without-submit.open:true}") | |||||
public class EarlyWarningProjectTask { | public class EarlyWarningProjectTask { | ||||
private final IProjectService projectService; | private final IProjectService projectService; | ||||
@@ -6,7 +6,13 @@ import java.time.temporal.ChronoUnit; | |||||
import java.util.*; | import java.util.*; | ||||
import java.util.stream.Collectors; | import java.util.stream.Collectors; | ||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; | |||||
import com.hz.pm.api.common.statemachine.event.TenderStateChangeEvent; | |||||
import com.hz.pm.api.projectlib.entity.PurchaseStatusChange; | |||||
import com.hz.pm.api.projectlib.service.IPurchaseStatusChangeService; | |||||
import com.hz.pm.api.sys.model.entity.ProjectEarlyWarning; | import com.hz.pm.api.sys.model.entity.ProjectEarlyWarning; | ||||
import com.hz.pm.api.sys.model.entity.WflowEarlyWarningRecords; | |||||
import com.hz.pm.api.sys.service.IEarlyWarningRecordsService; | |||||
import org.apache.commons.lang3.StringUtils; | import org.apache.commons.lang3.StringUtils; | ||||
import org.checkerframework.checker.nullness.qual.Nullable; | import org.checkerframework.checker.nullness.qual.Nullable; | ||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; | import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; | ||||
@@ -74,6 +80,8 @@ public class EarlyWarningWithoutSubmitTask { | |||||
private final IProjectStatusChangeService projectStatusChangeService; | private final IProjectStatusChangeService projectStatusChangeService; | ||||
private final EnvironmentUtil environmentUtil; | private final EnvironmentUtil environmentUtil; | ||||
private final UserInfoHelper userInfoHelper; | private final UserInfoHelper userInfoHelper; | ||||
private final IEarlyWarningRecordsService earlyWarningRecordsService; | |||||
private final IPurchaseStatusChangeService purchaseStatusChangeService; | |||||
private ChronoUnit getTimeUnit() { | private ChronoUnit getTimeUnit() { | ||||
if (environmentUtil.isDevEnv()) { | if (environmentUtil.isDevEnv()) { | ||||
@@ -91,16 +99,60 @@ public class EarlyWarningWithoutSubmitTask { | |||||
log.info("=========== 滞后预警任务开始 ==========="); | log.info("=========== 滞后预警任务开始 ==========="); | ||||
StopWatch stopWatch = new StopWatch(); | StopWatch stopWatch = new StopWatch(); | ||||
stopWatch.start(); | stopWatch.start(); | ||||
// 1.查询 填报的 滞后预警规则 填报类型的 每个单位的 每个规则 | |||||
Wrapper<WflowEarlyWarning> query = Wrappers.lambdaQuery(WflowEarlyWarning.class) | |||||
.eq(WflowEarlyWarning::getRuleType, WarningRuleTypeEnum.DELAY_WARNING.getCode()) | |||||
.eq(WflowEarlyWarning::getIsOpen, true); | |||||
List<WflowEarlyWarning> warnings = earlyWarningService.list(query); | |||||
for (WflowEarlyWarning warning : warnings) { | |||||
long mhUnitId = warning.getMhUnitId(); | |||||
// 获取项目库所有建设单位不为空的项目 | |||||
LambdaQueryWrapper<Project> queryWrapper = Wrappers.lambdaQuery(Project.class).isNotNull(Project::getBuildOrgCode); | |||||
List<Project> projects = projectService.list(queryWrapper); | |||||
// 根据项目code分组 获取最新的一条数据 | |||||
Map<String, Project> projectMap = projects.stream().collect(Collectors.groupingBy(Project::getProjectCode, Collectors.collectingAndThen( | |||||
// 根据创建日期找到最新的记录 | |||||
Collectors.maxBy(Comparator.comparing(Project::getCreateOn)), | |||||
// 如果没有记录则返回null | |||||
optional -> optional.orElse(null) | |||||
))); | |||||
List<Project> projectList = new ArrayList<>(projectMap.values()); | |||||
List<ProjectEarlyWarning> projectEarlyWarnings = Lists.newArrayList(); | |||||
List<WflowEarlyWarningRecords> earlyWarningRecords = Lists.newArrayList(); | |||||
List<ProjectEarlyWarning> needRemoved = Lists.newArrayList(); | |||||
// 查询当前预警表中 已存在的的滞后预警数据 | |||||
Wrapper<ProjectEarlyWarning> warningQuery = Wrappers.lambdaQuery(ProjectEarlyWarning.class) | |||||
.eq(ProjectEarlyWarning::getRuleType, WarningRuleTypeEnum.DELAY_WARNING.getCode()); | |||||
List<ProjectEarlyWarning> earlyWarnings = projectEarlyWarningService.list(warningQuery); | |||||
Map<String, ProjectEarlyWarning> projectEarlyWarningMap = CollUtils.listToMap(earlyWarnings, c -> c.getProjectCode() + StrPool.DASH + c.getStepName()); | |||||
// 遍历项目 获取对应申报单位的滞后预警规则 | |||||
for (Project project : projectList) { | |||||
String buildOrgCode = project.getBuildOrgCode(); | |||||
String projectCode = project.getProjectCode(); | |||||
Long mhUnitId = Long.valueOf(buildOrgCode); | |||||
List<Long> unitIdPaths = mhUnitCache.getUnitIdPaths(mhUnitId); | |||||
if (unitIdPaths.isEmpty()) { | |||||
log.error("该单位无法进行滞后预警:{}", mhUnitId); | |||||
continue; | |||||
} | |||||
List<String> unitIdPathsStr = CollUtils.convert(unitIdPaths, String::valueOf); | |||||
String orderSql = String.format(" order by field(mh_unit_id, %s) desc limit 1", | |||||
CollUtils.join(unitIdPaths, w -> "'" + w + "'", StrUtil.COMMA)); | |||||
log.info("单位ID路径:{}", unitIdPathsStr); | |||||
// 从当前建设单位开始向上获取滞后预警规则 | |||||
WflowEarlyWarning warning = earlyWarningService.getOne(Wrappers.lambdaQuery(WflowEarlyWarning.class) | |||||
.eq(WflowEarlyWarning::getRuleType, WarningRuleTypeEnum.DELAY_WARNING.getCode()) | |||||
.eq(WflowEarlyWarning::getIsOpen, true) | |||||
.in(WflowEarlyWarning::getMhUnitId, unitIdPathsStr) | |||||
.last(orderSql)); | |||||
if (Objects.isNull(warning)){ | |||||
log.info("未找到对应单位:{} 的滞后预警规则", mhUnitId); | |||||
continue; | |||||
} | |||||
String rule = warning.getRule(); | String rule = warning.getRule(); | ||||
if (StringUtils.isNotBlank(rule)) { | if (StringUtils.isNotBlank(rule)) { | ||||
JSONArray ruleArray = JSON.parseArray(rule); | JSONArray ruleArray = JSON.parseArray(rule); | ||||
// 对JSONArray 根据"biz"字段从小到大排序 | |||||
ruleArray.sort((o1, o2) -> { | |||||
JSONObject o1Json = JSON.parseObject(JSON.toJSONString(o1)); | |||||
JSONObject o2Json = JSON.parseObject(JSON.toJSONString(o2)); | |||||
Integer o1Biz = o1Json.getInteger("biz"); | |||||
Integer o2Biz = o2Json.getInteger("biz"); | |||||
return o1Biz.compareTo(o2Biz); | |||||
}); | |||||
if (CollUtil.isNotEmpty(ruleArray)) { | if (CollUtil.isNotEmpty(ruleArray)) { | ||||
ruleArray.forEach(r -> { | ruleArray.forEach(r -> { | ||||
JSONObject rJson = JSON.parseObject(JSON.toJSONString(r)); | JSONObject rJson = JSON.parseObject(JSON.toJSONString(r)); | ||||
@@ -113,15 +165,16 @@ public class EarlyWarningWithoutSubmitTask { | |||||
return; | return; | ||||
} | } | ||||
String path = flowType.getPath(); | String path = flowType.getPath(); | ||||
// 查询 所有这个单位 所配置滞后规则节点 未提交的项目 | |||||
Wrapper<Project> projectQuery = Wrappers.lambdaQuery(Project.class) | |||||
.eq(Project::getBuildOrgCode, mhUnitId) | |||||
.eq(Project::getNewest, Boolean.TRUE) | |||||
.eq(Project::getStatus, flowType.getProjectStatus().getCode()); | |||||
List<Project> needNextProjects = projectService.list(projectQuery); | |||||
List<String> projectCodes = CollUtils.fieldList(needNextProjects, Project::getProjectCode); | |||||
Map<String, ProjectStatusChange> projectStatusChangeMap = MapUtil.newHashMap(); | Map<String, ProjectStatusChange> projectStatusChangeMap = MapUtil.newHashMap(); | ||||
String stepName = null; | String stepName = null; | ||||
List<String> projectCodes = Lists.newArrayList(); | |||||
projectCodes.add(project.getProjectCode()); | |||||
// 是否进行采购&合同备案 | |||||
boolean isPurchase = false; | |||||
// 适配改造是否完成单位确认 | |||||
boolean isModified = false; | |||||
// 终验申请是否提交 | |||||
boolean isFinalInspection = false; | |||||
switch (flowType) { | switch (flowType) { | ||||
// 已立项未采购 获取 立项时间 | // 已立项未采购 获取 立项时间 | ||||
case APPROVED_PROJECT_NOT_PURCHASED:{ | case APPROVED_PROJECT_NOT_PURCHASED:{ | ||||
@@ -129,6 +182,13 @@ public class EarlyWarningWithoutSubmitTask { | |||||
if (CollUtil.isNotEmpty(projectCodes)) { | if (CollUtil.isNotEmpty(projectCodes)) { | ||||
Map<String, ProjectStatusChange> approvedProjectNotPurchasedMap = projectStatusChangeService.listLastEventMap(projectCodes, | Map<String, ProjectStatusChange> approvedProjectNotPurchasedMap = projectStatusChangeService.listLastEventMap(projectCodes, | ||||
ProjectStateChangeEvent.DECLARED_RECORD_PASS); | ProjectStateChangeEvent.DECLARED_RECORD_PASS); | ||||
List<ProjectStateChangeEvent> events = Lists.newArrayList(); | |||||
events.add(ProjectStateChangeEvent.SUBMIT_PURCHASE_CONTRACT_RECORD); | |||||
ProjectStatusChange projectStatusChange = projectStatusChangeService.getLastOne(projectCode, events); | |||||
// 说明进行了采购&合同信息备案 | |||||
if (Objects.nonNull(projectStatusChange)) { | |||||
isPurchase = true; | |||||
} | |||||
if (CollUtil.isNotEmpty(approvedProjectNotPurchasedMap)) { | if (CollUtil.isNotEmpty(approvedProjectNotPurchasedMap)) { | ||||
projectStatusChangeMap.putAll(approvedProjectNotPurchasedMap); | projectStatusChangeMap.putAll(approvedProjectNotPurchasedMap); | ||||
} | } | ||||
@@ -144,6 +204,13 @@ public class EarlyWarningWithoutSubmitTask { | |||||
if (CollUtil.isNotEmpty(purchasedUnmodifiedMap)) { | if (CollUtil.isNotEmpty(purchasedUnmodifiedMap)) { | ||||
projectStatusChangeMap.putAll(purchasedUnmodifiedMap); | projectStatusChangeMap.putAll(purchasedUnmodifiedMap); | ||||
} | } | ||||
List<TenderStateChangeEvent> events = Lists.newArrayList(); | |||||
events.add(TenderStateChangeEvent.SUBMIT_PURCHASE_ORG_CONFIRM); | |||||
PurchaseStatusChange purchaseStatusChange = purchaseStatusChangeService.getLastOne(projectCode, events); | |||||
// 说明进行了单位确认 | |||||
if (Objects.nonNull(purchaseStatusChange)) { | |||||
isModified = true; | |||||
} | |||||
} | } | ||||
} | } | ||||
break; | break; | ||||
@@ -157,76 +224,238 @@ public class EarlyWarningWithoutSubmitTask { | |||||
projectStatusChangeMap.putAll(modifiedNotFinalInspectionMap); | projectStatusChangeMap.putAll(modifiedNotFinalInspectionMap); | ||||
} | } | ||||
} | } | ||||
List<ProjectStateChangeEvent> events = Lists.newArrayList(); | |||||
events.add(ProjectStateChangeEvent.FINAL_ACCEPTANCE_APPLICATION); | |||||
ProjectStatusChange projectStatusChange = projectStatusChangeService.getLastOne(projectCode, events); | |||||
// 说明提交了终验申请 | |||||
if (Objects.nonNull(projectStatusChange)) { | |||||
isFinalInspection = true; | |||||
} | |||||
} | } | ||||
break; | break; | ||||
default: | default: | ||||
log.error("Unexpected value: {}", flowType); | log.error("Unexpected value: {}", flowType); | ||||
} | } | ||||
// 查询当前预警表中 已存在的的滞后预警数据 | |||||
Wrapper<ProjectEarlyWarning> warningQuery = Wrappers.lambdaQuery(ProjectEarlyWarning.class) | |||||
.eq(ProjectEarlyWarning::getRuleType, WarningRuleTypeEnum.DELAY_WARNING.getCode()); | |||||
List<ProjectEarlyWarning> projectEarlyWarnings = projectEarlyWarningService.list(warningQuery); | |||||
Map<String, ProjectEarlyWarning> projectEarlyWarningMap = CollUtils.listToMap(projectEarlyWarnings, c -> c.getProjectCode() + StrPool.DASH + c.getStepName()); | |||||
// 按照当前配置的滞后规则 获取需要首页监测预警展示的项目 | |||||
// 需要首页监测预警展示的项目 | |||||
// 获取项目 滞后(历时)时间 | // 获取项目 滞后(历时)时间 | ||||
HashMap<String, LocalDateTime> touchTimeMap = MapUtil.newHashMap(); | HashMap<String, LocalDateTime> touchTimeMap = MapUtil.newHashMap(); | ||||
String finalStepName = stepName; | String finalStepName = stepName; | ||||
List<ProjectEarlyWarning> needRemoved = Lists.newArrayList(); | |||||
List<Project> needToWaringProjects = needNextProjects.stream() | |||||
.filter(p -> { | |||||
ProjectStatusChange change = projectStatusChangeMap.get(p.getProjectCode()); | |||||
LocalDateTime touchTime = change == null ? null : change.getCreateOn(); | |||||
if (touchTime != null) { | |||||
touchTimeMap.put(p.getProjectCode() + StrPool.DASH + biz, touchTime); | |||||
long duration = getDurationTime(touchTime,LocalDateTime.now(),getTimeUnit()); | |||||
if (duration > delayTime) { | |||||
// 项目 滞后预警 | |||||
projectEarlyWarningService.earlyWarning(p, WarningRuleTypeEnum.DELAY_WARNING.getCode(), com.wflow.enums.WarningNoticeTypeEnum.DELAY.getCode(), finalStepName); | |||||
return Boolean.TRUE; | |||||
}else { | |||||
// 判断是否已经存在对应节点预警 如果有 从预警信息表中移除 | |||||
if (projectEarlyWarningMap.containsKey(p.getProjectCode() + StrPool.DASH + finalStepName)) { | |||||
ProjectEarlyWarning projectEarlyWarning = projectEarlyWarningMap.get(p.getProjectCode() + StrPool.DASH + finalStepName); | |||||
needRemoved.add(projectEarlyWarning); | |||||
} | |||||
} | |||||
} | |||||
return Boolean.FALSE; | |||||
}).collect(Collectors.toList()); | |||||
// 根据当前配置的滞后规则 将不满足规则的历史预警信息从预警信息表中移除 | |||||
if (CollUtil.isNotEmpty(needRemoved)){ | |||||
projectEarlyWarningService.removeBatchByIds(needRemoved); | |||||
} | |||||
for (Project needToWaringProject : needToWaringProjects) { | |||||
// 目前没有通知 | |||||
// 如果去预警通知人 1.超级管理员 2.单位管理员 如果都包含 都要发 | |||||
List<String> batchEmployees = Lists.newArrayList(); | |||||
if (StringUtils.isNotBlank(notice) && notice.contains(WarningNoticeTypeEnum.SUPER_ADMIN.getCode().toString())) { | |||||
// 获取超级管理员用户信息 | |||||
List<UserInfo> superAdminUsers = userInfoHelper.getEmployeeCodesByRoleEnum(RoleEnum.SUPER_ADMIN); | |||||
List<String> superAdminEmployeeCodes = superAdminUsers.stream().map(UserInfo::getEmployeeCode).collect(Collectors.toList()); | |||||
batchEmployees.addAll(superAdminEmployeeCodes); | |||||
} | |||||
if (StringUtils.isNotBlank(notice) && notice.contains(WarningNoticeTypeEnum.UNIT_ADMIN.getCode().toString())) { | |||||
// 获取单位管理员用户信息 | |||||
List<UserInfo> unitAdminUsers = userInfoHelper.getEmployeeCodesByRoleEnum(RoleEnum.COMPANY_MANAGER); | |||||
// 过滤出当前项目所属单位的单位管理员 | |||||
List<String> unitAdminEmployeeCodes = unitAdminUsers.stream().filter(user -> Objects.equals(user.getMhUnitId().toString(), needToWaringProject.getBuildOrgCode())) | |||||
.map(UserInfo::getEmployeeCode).collect(Collectors.toList()); | |||||
batchEmployees.addAll(unitAdminEmployeeCodes); | |||||
ProjectStatusChange change = projectStatusChangeMap.get(projectCode); | |||||
LocalDateTime touchTime = change == null ? null : change.getCreateOn(); | |||||
// 是否进行预警 | |||||
boolean isTouch = isTouch(flowType, isPurchase, isModified, isFinalInspection); | |||||
if (touchTime != null) { | |||||
touchTimeMap.put(projectCode + StrPool.DASH + biz, touchTime); | |||||
long duration = getDurationTime(touchTime,LocalDateTime.now(),getTimeUnit()); | |||||
// 如果对应节点超期 且未提交至下一步 | |||||
if (duration > delayTime && isTouch) { | |||||
List<ProjectEarlyWarning> projectEarlyWarningList = Lists.newArrayList(); | |||||
List<WflowEarlyWarningRecords> earlyWarningRecordsList = Lists.newArrayList(); | |||||
// 项目 滞后预警 | |||||
projectEarlyWarningList = projectEarlyWarningService.earlyWarning(project, WarningRuleTypeEnum.DELAY_WARNING.getCode(), com.wflow.enums.WarningNoticeTypeEnum.DELAY.getCode(), finalStepName, projectEarlyWarningList); | |||||
projectEarlyWarnings.addAll(projectEarlyWarningList); | |||||
// 目前没有通知 | |||||
// 如果去预警通知人 1.超级管理员 2.单位管理员 如果都包含 都要发 | |||||
List<String> batchEmployees = Lists.newArrayList(); | |||||
if (StringUtils.isNotBlank(notice) && notice.contains(WarningNoticeTypeEnum.SUPER_ADMIN.getCode().toString())) { | |||||
// 获取超级管理员用户信息 | |||||
List<UserInfo> superAdminUsers = userInfoHelper.getEmployeeCodesByRoleEnum(RoleEnum.SUPER_ADMIN); | |||||
List<String> superAdminEmployeeCodes = superAdminUsers.stream().map(UserInfo::getEmployeeCode).collect(Collectors.toList()); | |||||
batchEmployees.addAll(superAdminEmployeeCodes); | |||||
} | |||||
if (StringUtils.isNotBlank(notice) && notice.contains(WarningNoticeTypeEnum.UNIT_ADMIN.getCode().toString())) { | |||||
// 获取单位管理员用户信息 | |||||
List<UserInfo> unitAdminUsers = userInfoHelper.getEmployeeCodesByRoleEnum(RoleEnum.COMPANY_MANAGER); | |||||
// 过滤出当前项目所属单位的单位管理员 | |||||
List<String> unitAdminEmployeeCodes = unitAdminUsers.stream().filter(user -> Objects.equals(user.getMhUnitId().toString(), project.getBuildOrgCode())) | |||||
.map(UserInfo::getEmployeeCode).collect(Collectors.toList()); | |||||
batchEmployees.addAll(unitAdminEmployeeCodes); | |||||
} | |||||
// 保存到预警记录中 | |||||
earlyWarningRecordsList = earlyWarningManage.getEarlyWarningDelayRecords(warning.getNoticeMethod(), biz, project, | |||||
WarningRuleTypeEnum.DELAY_WARNING.getCode(), ProjectEarlyWarningStatusEnum.DELAY_TIME.getCode(), | |||||
path, touchTimeMap, earlyWarningRecordsList); | |||||
earlyWarningRecords.addAll(earlyWarningRecordsList); | |||||
}else { | |||||
// 判断是否已经存在对应节点预警 如果有 从预警信息表中移除 | |||||
if (projectEarlyWarningMap.containsKey(project.getProjectCode() + StrPool.DASH + finalStepName)) { | |||||
ProjectEarlyWarning projectEarlyWarning = projectEarlyWarningMap.get(projectCode + StrPool.DASH + finalStepName); | |||||
needRemoved.add(projectEarlyWarning); | |||||
} | |||||
} | } | ||||
// 保存到预警记录中 | |||||
earlyWarningManage.doEarlyWarningDelay(warning.getNoticeMethod(), biz, needToWaringProject, | |||||
WarningRuleTypeEnum.DELAY_WARNING.getCode(), ProjectEarlyWarningStatusEnum.DELAY_TIME.getCode(), | |||||
path, touchTimeMap); | |||||
} | } | ||||
}); | }); | ||||
} | } | ||||
} | } | ||||
} | } | ||||
// 每个规则按通知节点顺序 更新保存一次 | |||||
if (CollUtil.isNotEmpty(needRemoved)){ | |||||
projectEarlyWarningService.removeBatchByIds(needRemoved); | |||||
} | |||||
if (CollUtil.isNotEmpty(projectEarlyWarnings)){ | |||||
log.info("需要滞后预警通知的项目数:{}", projectEarlyWarnings.size()); | |||||
projectEarlyWarningService.saveOrUpdateBatch(projectEarlyWarnings); | |||||
} | |||||
if (CollUtil.isNotEmpty(earlyWarningRecords)){ | |||||
log.info("需要滞后预警通知记录数:{}", earlyWarningRecords.size()); | |||||
earlyWarningRecordsService.saveOrUpdateBatch(earlyWarningRecords); | |||||
} | |||||
stopWatch.stop(); | stopWatch.stop(); | ||||
log.info("=========== 滞后预警任务结束 耗时{}s", stopWatch.getTotalTimeSeconds()); | log.info("=========== 滞后预警任务结束 耗时{}s", stopWatch.getTotalTimeSeconds()); | ||||
//log.info("=========== 滞后预警任务开始 ==========="); | |||||
//StopWatch stopWatch = new StopWatch(); | |||||
//stopWatch.start(); | |||||
//// 1.查询 填报的 滞后预警规则 填报类型的 每个单位的 每个规则 | |||||
//Wrapper<WflowEarlyWarning> query = Wrappers.lambdaQuery(WflowEarlyWarning.class) | |||||
// .eq(WflowEarlyWarning::getRuleType, WarningRuleTypeEnum.DELAY_WARNING.getCode()) | |||||
// .eq(WflowEarlyWarning::getIsOpen, true); | |||||
//List<WflowEarlyWarning> warnings = earlyWarningService.list(query); | |||||
//for (WflowEarlyWarning warning : warnings) { | |||||
// long mhUnitId = warning.getMhUnitId(); | |||||
// String rule = warning.getRule(); | |||||
// if (StringUtils.isNotBlank(rule)) { | |||||
// JSONArray ruleArray = JSON.parseArray(rule); | |||||
// if (CollUtil.isNotEmpty(ruleArray)) { | |||||
// ruleArray.forEach(r -> { | |||||
// JSONObject rJson = JSON.parseObject(JSON.toJSONString(r)); | |||||
// Integer biz = rJson.getInteger("biz"); | |||||
// Integer delayTime = rJson.getInteger("delayTime"); | |||||
// String notice = rJson.getString("notice"); | |||||
// WarningFlowTypeEnum flowType = WarningFlowTypeEnum.getByCode(biz); | |||||
// if (Objects.isNull(delayTime) || Objects.isNull(biz) || flowType == null) { | |||||
// log.warn("规则数据 错误 :{}", rJson); | |||||
// return; | |||||
// } | |||||
// String path = flowType.getPath(); | |||||
// // 查询 所有这个单位 所配置滞后规则节点 未提交的项目 | |||||
// Wrapper<Project> projectQuery = Wrappers.lambdaQuery(Project.class) | |||||
// .eq(Project::getBuildOrgCode, mhUnitId) | |||||
// .eq(Project::getNewest, Boolean.TRUE) | |||||
// .eq(Project::getStatus, flowType.getProjectStatus().getCode()); | |||||
// List<Project> needNextProjects = projectService.list(projectQuery); | |||||
// List<String> projectCodes = CollUtils.fieldList(needNextProjects, Project::getProjectCode); | |||||
// Map<String, ProjectStatusChange> projectStatusChangeMap = MapUtil.newHashMap(); | |||||
// String stepName = null; | |||||
// switch (flowType) { | |||||
// // 已立项未采购 获取 立项时间 | |||||
// case APPROVED_PROJECT_NOT_PURCHASED:{ | |||||
// stepName = TaskConstant.StepName.PURCHASE; | |||||
// if (CollUtil.isNotEmpty(projectCodes)) { | |||||
// Map<String, ProjectStatusChange> approvedProjectNotPurchasedMap = projectStatusChangeService.listLastEventMap(projectCodes, | |||||
// ProjectStateChangeEvent.DECLARED_RECORD_PASS); | |||||
// if (CollUtil.isNotEmpty(approvedProjectNotPurchasedMap)) { | |||||
// projectStatusChangeMap.putAll(approvedProjectNotPurchasedMap); | |||||
// } | |||||
// } | |||||
// } | |||||
// break; | |||||
// // 已采购未改造完成 获取合同签订时间 | |||||
// case PURCHASED_UNMODIFIED:{ | |||||
// stepName = TaskConstant.StepName.ADAPT_MODIFY; | |||||
// if (CollUtil.isNotEmpty(projectCodes)) { | |||||
// Map<String, ProjectStatusChange> purchasedUnmodifiedMap = projectStatusChangeService.listLastEventMap(projectCodes, | |||||
// ProjectStateChangeEvent.SUBMIT_PURCHASE_CONTRACT_RECORD); | |||||
// if (CollUtil.isNotEmpty(purchasedUnmodifiedMap)) { | |||||
// projectStatusChangeMap.putAll(purchasedUnmodifiedMap); | |||||
// } | |||||
// } | |||||
// } | |||||
// break; | |||||
// // 已改造完成未终验 获取单位确认时间 | |||||
// case MODIFIED_NOT_FINAL_INSPECTION:{ | |||||
// stepName = TaskConstant.StepName.FINAL; | |||||
// if (CollUtil.isNotEmpty(projectCodes)) { | |||||
// Map<String, ProjectStatusChange> modifiedNotFinalInspectionMap = projectStatusChangeService.listLastEventMap(projectCodes, | |||||
// ProjectStateChangeEvent.SUBMIT_PURCHASE_ORG_CONFIRM); | |||||
// if (CollUtil.isNotEmpty(modifiedNotFinalInspectionMap)) { | |||||
// projectStatusChangeMap.putAll(modifiedNotFinalInspectionMap); | |||||
// } | |||||
// } | |||||
// } | |||||
// break; | |||||
// default: | |||||
// log.error("Unexpected value: {}", flowType); | |||||
// } | |||||
// // 查询当前预警表中 已存在的的滞后预警数据 | |||||
// Wrapper<ProjectEarlyWarning> warningQuery = Wrappers.lambdaQuery(ProjectEarlyWarning.class) | |||||
// .eq(ProjectEarlyWarning::getRuleType, WarningRuleTypeEnum.DELAY_WARNING.getCode()); | |||||
// List<ProjectEarlyWarning> projectEarlyWarnings = projectEarlyWarningService.list(warningQuery); | |||||
// Map<String, ProjectEarlyWarning> projectEarlyWarningMap = CollUtils.listToMap(projectEarlyWarnings, c -> c.getProjectCode() + StrPool.DASH + c.getStepName()); | |||||
// // 按照当前配置的滞后规则 获取需要首页监测预警展示的项目 | |||||
// // 获取项目 滞后(历时)时间 | |||||
// HashMap<String, LocalDateTime> touchTimeMap = MapUtil.newHashMap(); | |||||
// String finalStepName = stepName; | |||||
// List<ProjectEarlyWarning> needRemoved = Lists.newArrayList(); | |||||
// List<Project> needToWaringProjects = needNextProjects.stream() | |||||
// .filter(p -> { | |||||
// ProjectStatusChange change = projectStatusChangeMap.get(p.getProjectCode()); | |||||
// LocalDateTime touchTime = change == null ? null : change.getCreateOn(); | |||||
// if (touchTime != null) { | |||||
// touchTimeMap.put(p.getProjectCode() + StrPool.DASH + biz, touchTime); | |||||
// long duration = getDurationTime(touchTime,LocalDateTime.now(),getTimeUnit()); | |||||
// if (duration > delayTime) { | |||||
// // 项目 滞后预警 | |||||
// projectEarlyWarningService.earlyWarning(p, WarningRuleTypeEnum.DELAY_WARNING.getCode(), com.wflow.enums.WarningNoticeTypeEnum.DELAY.getCode(), finalStepName); | |||||
// return Boolean.TRUE; | |||||
// }else { | |||||
// // 判断是否已经存在对应节点预警 如果有 从预警信息表中移除 | |||||
// if (projectEarlyWarningMap.containsKey(p.getProjectCode() + StrPool.DASH + finalStepName)) { | |||||
// ProjectEarlyWarning projectEarlyWarning = projectEarlyWarningMap.get(p.getProjectCode() + StrPool.DASH + finalStepName); | |||||
// needRemoved.add(projectEarlyWarning); | |||||
// } | |||||
// } | |||||
// } | |||||
// return Boolean.FALSE; | |||||
// }).collect(Collectors.toList()); | |||||
// // 根据当前配置的滞后规则 将不满足规则的历史预警信息从预警信息表中移除 | |||||
// if (CollUtil.isNotEmpty(needRemoved)){ | |||||
// projectEarlyWarningService.removeBatchByIds(needRemoved); | |||||
// } | |||||
// for (Project needToWaringProject : needToWaringProjects) { | |||||
// // 目前没有通知 | |||||
// // 如果去预警通知人 1.超级管理员 2.单位管理员 如果都包含 都要发 | |||||
// List<String> batchEmployees = Lists.newArrayList(); | |||||
// if (StringUtils.isNotBlank(notice) && notice.contains(WarningNoticeTypeEnum.SUPER_ADMIN.getCode().toString())) { | |||||
// // 获取超级管理员用户信息 | |||||
// List<UserInfo> superAdminUsers = userInfoHelper.getEmployeeCodesByRoleEnum(RoleEnum.SUPER_ADMIN); | |||||
// List<String> superAdminEmployeeCodes = superAdminUsers.stream().map(UserInfo::getEmployeeCode).collect(Collectors.toList()); | |||||
// batchEmployees.addAll(superAdminEmployeeCodes); | |||||
// } | |||||
// if (StringUtils.isNotBlank(notice) && notice.contains(WarningNoticeTypeEnum.UNIT_ADMIN.getCode().toString())) { | |||||
// // 获取单位管理员用户信息 | |||||
// List<UserInfo> unitAdminUsers = userInfoHelper.getEmployeeCodesByRoleEnum(RoleEnum.COMPANY_MANAGER); | |||||
// // 过滤出当前项目所属单位的单位管理员 | |||||
// List<String> unitAdminEmployeeCodes = unitAdminUsers.stream().filter(user -> Objects.equals(user.getMhUnitId().toString(), needToWaringProject.getBuildOrgCode())) | |||||
// .map(UserInfo::getEmployeeCode).collect(Collectors.toList()); | |||||
// batchEmployees.addAll(unitAdminEmployeeCodes); | |||||
// } | |||||
// // 保存到预警记录中 | |||||
// earlyWarningManage.doEarlyWarningDelay(warning.getNoticeMethod(), biz, needToWaringProject, | |||||
// WarningRuleTypeEnum.DELAY_WARNING.getCode(), ProjectEarlyWarningStatusEnum.DELAY_TIME.getCode(), | |||||
// path, touchTimeMap); | |||||
// } | |||||
// }); | |||||
// } | |||||
// } | |||||
//} | |||||
// | |||||
//stopWatch.stop(); | |||||
//log.info("=========== 滞后预警任务结束 耗时{}s", stopWatch.getTotalTimeSeconds()); | |||||
} | |||||
private boolean isTouch(WarningFlowTypeEnum flowType, Boolean isPurchase, Boolean isModified, Boolean isFinalInspection) { | |||||
switch (flowType) { | |||||
case APPROVED_PROJECT_NOT_PURCHASED: | |||||
return !isPurchase; | |||||
case MODIFIED_NOT_FINAL_INSPECTION: | |||||
return !isModified && !isFinalInspection; | |||||
case PURCHASED_UNMODIFIED: | |||||
return isPurchase && !isModified; | |||||
default: | |||||
return false; | |||||
} | |||||
} | } | ||||
private long getDurationTime(LocalDateTime touchTime, LocalDateTime now, ChronoUnit timeUnit) { | private long getDurationTime(LocalDateTime touchTime, LocalDateTime now, ChronoUnit timeUnit) { | ||||
@@ -25,6 +25,7 @@ import org.springframework.transaction.annotation.Transactional; | |||||
import java.time.LocalDateTime; | import java.time.LocalDateTime; | ||||
import java.util.HashMap; | import java.util.HashMap; | ||||
import java.util.List; | |||||
import java.util.Objects; | import java.util.Objects; | ||||
/** | /** | ||||
@@ -169,6 +170,41 @@ public class EarlyWarningManage { | |||||
earlyWarningRecordsService.saveOrUpdate(records); | earlyWarningRecordsService.saveOrUpdate(records); | ||||
} | } | ||||
public List<WflowEarlyWarningRecords> getEarlyWarningDelayRecords(String noticeMethod, Integer biz, Project project, | |||||
Integer ruleType, Integer noticeType, String path, | |||||
HashMap<String, LocalDateTime> touchTimeMap, List<WflowEarlyWarningRecords> earlyWarningRecords) { | |||||
// 1.存入 预警记录 | |||||
WflowEarlyWarningRecords records = new WflowEarlyWarningRecords(); | |||||
String projectCode = project.getProjectCode(); | |||||
WflowEarlyWarningRecords old = earlyWarningRecordsService.getOne(Wrappers.lambdaQuery(WflowEarlyWarningRecords.class) | |||||
.eq(WflowEarlyWarningRecords::getProjectCode, projectCode) | |||||
.eq(WflowEarlyWarningRecords::getBiz, biz) | |||||
.last(BizConst.LIMIT_1)); | |||||
if (Objects.nonNull(old)){ | |||||
records.setId(old.getId()); | |||||
}else { | |||||
records.setCreateOn(LocalDateTime.now()); | |||||
} | |||||
LocalDateTime startTime = touchTimeMap.get(projectCode + StrPool.DASH + biz); | |||||
records.setRuleType(ruleType); | |||||
records.setAreaCode(project.getAreaCode()); | |||||
records.setBuildOrgCode(project.getBuildOrgCode()); | |||||
records.setBuildOrgName(project.getBuildOrgName()); | |||||
records.setWarningTime(LocalDateTime.now()); | |||||
records.setInstStart(startTime); | |||||
records.setInstType(biz); | |||||
records.setNoticeMethod(noticeMethod); | |||||
records.setProjectName(project.getProjectName()); | |||||
records.setProjectId(project.getId()); | |||||
records.setProjectCode(project.getProjectCode()); | |||||
records.setProjectStatus(project.getStatus()); | |||||
records.setNoticeType(noticeType); | |||||
records.setPath(path); | |||||
records.setBiz(biz); | |||||
earlyWarningRecords.add(records); | |||||
return earlyWarningRecords; | |||||
} | |||||
/** | /** | ||||
* 催办 | * 催办 | ||||
* | * | ||||
@@ -18,4 +18,6 @@ public interface IProjectEarlyWarningService extends IService<ProjectEarlyWarnin | |||||
Boolean earlyWarning(String projectCode, Integer code, List<Integer> noticeTypes); | Boolean earlyWarning(String projectCode, Integer code, List<Integer> noticeTypes); | ||||
Boolean earlyWarning(Project project, Integer ruleType, Integer noticeType, String stepName); | Boolean earlyWarning(Project project, Integer ruleType, Integer noticeType, String stepName); | ||||
List<ProjectEarlyWarning> earlyWarning(Project project, Integer ruleType, Integer noticeType, String stepName,List<ProjectEarlyWarning> projectEarlyWarningList); | |||||
} | } |
@@ -17,6 +17,7 @@ import lombok.extern.slf4j.Slf4j; | |||||
import org.springframework.stereotype.Service; | import org.springframework.stereotype.Service; | ||||
import java.time.LocalDateTime; | import java.time.LocalDateTime; | ||||
import java.util.Collections; | |||||
import java.util.List; | import java.util.List; | ||||
import java.util.Objects; | import java.util.Objects; | ||||
@@ -68,6 +69,11 @@ public class ProjectEarlyWarningServiceImpl extends ServiceImpl<ProjectEarlyWarn | |||||
return doEarlyWarning(project, ruleType, noticeType, stepName); | return doEarlyWarning(project, ruleType, noticeType, stepName); | ||||
} | } | ||||
@Override | |||||
public List<ProjectEarlyWarning> earlyWarning(Project project, Integer ruleType, Integer noticeType, String stepName, List<ProjectEarlyWarning> projectEarlyWarningList) { | |||||
return doEarlyWarning(project, ruleType, noticeType, stepName, projectEarlyWarningList); | |||||
} | |||||
private Boolean doEarlyWarning(Project project, Integer ruleType, Integer noticeType, String stepName) { | private Boolean doEarlyWarning(Project project, Integer ruleType, Integer noticeType, String stepName) { | ||||
if(Objects.isNull(project) || Objects.isNull(ruleType)){ | if(Objects.isNull(project) || Objects.isNull(ruleType)){ | ||||
return Boolean.FALSE; | return Boolean.FALSE; | ||||
@@ -125,4 +131,63 @@ public class ProjectEarlyWarningServiceImpl extends ServiceImpl<ProjectEarlyWarn | |||||
warning.setStepName(stepName); | warning.setStepName(stepName); | ||||
return saveOrUpdate(warning); | return saveOrUpdate(warning); | ||||
} | } | ||||
private List<ProjectEarlyWarning> doEarlyWarning(Project project, Integer ruleType, Integer noticeType, String stepName, List<ProjectEarlyWarning> projectEarlyWarningList) { | |||||
if(Objects.isNull(project) || Objects.isNull(ruleType)){ | |||||
return Collections.emptyList(); | |||||
} | |||||
String projectCode = project.getProjectCode(); | |||||
ProjectEarlyWarning old = getOne(Wrappers.lambdaQuery(ProjectEarlyWarning.class) | |||||
.eq(ProjectEarlyWarning::getProjectCode, projectCode) | |||||
.last(BizConst.LIMIT_1)); | |||||
ProjectEarlyWarning warning = new ProjectEarlyWarning(); | |||||
if(Objects.nonNull(old)){ | |||||
warning.setId(old.getId()); | |||||
}else{ | |||||
warning.setBuildOrgCode(project.getBuildOrgCode()); | |||||
warning.setAreaCode(project.getAreaCode()); | |||||
warning.setCreateOn(LocalDateTime.now()); | |||||
warning.setProjectCode(projectCode); | |||||
} | |||||
switch (WarningRuleTypeEnum.checkByCode(ruleType)){ | |||||
case DELAY_WARNING: | |||||
warning.setDelayWarning(Boolean.TRUE); | |||||
break; | |||||
case DECLARED_WARNING: | |||||
warning.setDeclaredWarning(Boolean.TRUE); | |||||
break; | |||||
case PROCESS_WARNING: | |||||
warning.setProcessWarning(Boolean.TRUE); | |||||
break; | |||||
default: | |||||
return Collections.emptyList(); | |||||
} | |||||
warning.setRuleType(ruleType); | |||||
if(Objects.isNull(noticeType)){ | |||||
warning.setStatus(ProjectEarlyWarningStatusEnum.OVER_TIME.name()); | |||||
}else{ | |||||
switch (WarningNoticeTypeEnum.match(noticeType)){ | |||||
case OVER: | |||||
warning.setStatus(ProjectEarlyWarningStatusEnum.OVER_TIME.name()); | |||||
break; | |||||
case ADVENT: | |||||
warning.setStatus(ProjectEarlyWarningStatusEnum.ADVENT_TIME.name()); | |||||
break; | |||||
case DELAY: | |||||
warning.setStatus(ProjectEarlyWarningStatusEnum.DELAY_TIME.name()); | |||||
break; | |||||
default: | |||||
warning.setStatus(ProjectEarlyWarningStatusEnum.OVER_TIME.name()); | |||||
break; | |||||
} | |||||
} | |||||
warning.setNoticeType(noticeType); | |||||
warning.setNormal(Boolean.FALSE); | |||||
warning.setStepName(stepName); | |||||
projectEarlyWarningList.add(warning); | |||||
return projectEarlyWarningList; | |||||
} | |||||
} | } |
@@ -5,12 +5,15 @@ import javax.annotation.Resource; | |||||
import cn.hutool.core.collection.CollUtil; | import cn.hutool.core.collection.CollUtil; | ||||
import cn.hutool.core.date.StopWatch; | import cn.hutool.core.date.StopWatch; | ||||
import cn.hutool.core.map.MapUtil; | import cn.hutool.core.map.MapUtil; | ||||
import cn.hutool.core.util.StrUtil; | |||||
import com.alibaba.fastjson.JSONArray; | import com.alibaba.fastjson.JSONArray; | ||||
import com.alibaba.fastjson.JSONObject; | import com.alibaba.fastjson.JSONObject; | ||||
import com.baomidou.mybatisplus.core.conditions.Wrapper; | import com.baomidou.mybatisplus.core.conditions.Wrapper; | ||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; | |||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers; | import com.baomidou.mybatisplus.core.toolkit.Wrappers; | ||||
import com.google.common.collect.Lists; | import com.google.common.collect.Lists; | ||||
import com.google.common.collect.Sets; | import com.google.common.collect.Sets; | ||||
import com.hz.pm.api.common.enumeration.ProjectProcessType; | |||||
import com.hz.pm.api.common.helper.UserInfoHelper; | import com.hz.pm.api.common.helper.UserInfoHelper; | ||||
import com.hz.pm.api.common.model.constant.BizConst; | import com.hz.pm.api.common.model.constant.BizConst; | ||||
import com.hz.pm.api.common.statemachine.event.ProjectStateChangeEvent; | import com.hz.pm.api.common.statemachine.event.ProjectStateChangeEvent; | ||||
@@ -39,11 +42,14 @@ import com.hz.pm.api.user.service.IUserInfoService; | |||||
import com.ningdatech.basic.util.CollUtils; | import com.ningdatech.basic.util.CollUtils; | ||||
import com.ningdatech.basic.util.StrPool; | import com.ningdatech.basic.util.StrPool; | ||||
import com.wflow.bean.entity.WflowEarlyWarning; | import com.wflow.bean.entity.WflowEarlyWarning; | ||||
import com.wflow.bean.entity.WflowModels; | |||||
import com.wflow.enums.WarningRuleTypeEnum; | import com.wflow.enums.WarningRuleTypeEnum; | ||||
import com.wflow.service.IEarlyWarningService; | import com.wflow.service.IEarlyWarningService; | ||||
import com.wflow.workflow.service.ProcessModelService; | |||||
import lombok.RequiredArgsConstructor; | import lombok.RequiredArgsConstructor; | ||||
import lombok.extern.slf4j.Slf4j; | import lombok.extern.slf4j.Slf4j; | ||||
import org.apache.commons.lang3.StringUtils; | import org.apache.commons.lang3.StringUtils; | ||||
import org.checkerframework.checker.nullness.qual.Nullable; | |||||
import org.flowable.engine.TaskService; | import org.flowable.engine.TaskService; | ||||
import org.flowable.task.api.Task; | import org.flowable.task.api.Task; | ||||
import org.junit.Test; | import org.junit.Test; | ||||
@@ -89,6 +95,10 @@ public class DelayWarningTest extends AppTests { | |||||
private TaskService taskService; | private TaskService taskService; | ||||
@Autowired | @Autowired | ||||
private IPurchaseStatusChangeService purchaseStatusChangeService; | private IPurchaseStatusChangeService purchaseStatusChangeService; | ||||
@Autowired | |||||
private MhUnitCache mhUnitCache; | |||||
@Autowired | |||||
private ProcessModelService processModelService; | |||||
private ChronoUnit getTimeUnit() { | private ChronoUnit getTimeUnit() { | ||||
if (environmentUtil.isDevEnv()) { | if (environmentUtil.isDevEnv()) { | ||||
@@ -100,20 +110,63 @@ public class DelayWarningTest extends AppTests { | |||||
@Test | @Test | ||||
public void one(){ | public void one(){ | ||||
log.info("=========== 滞后预警任务开始 ==========="); | log.info("=========== 滞后预警任务开始 ==========="); | ||||
StopWatch stopWatch = new StopWatch(); | StopWatch stopWatch = new StopWatch(); | ||||
stopWatch.start(); | stopWatch.start(); | ||||
// 1.查询 填报的 滞后预警规则 填报类型的 每个单位的 每个规则 | |||||
Wrapper<WflowEarlyWarning> query = Wrappers.lambdaQuery(WflowEarlyWarning.class) | |||||
.eq(WflowEarlyWarning::getRuleType, WarningRuleTypeEnum.DELAY_WARNING.getCode()) | |||||
.eq(WflowEarlyWarning::getIsOpen, true); | |||||
List<WflowEarlyWarning> warnings = earlyWarningService.list(query); | |||||
for (WflowEarlyWarning warning : warnings) { | |||||
long mhUnitId = warning.getMhUnitId(); | |||||
// 获取项目库所有建设单位不为空的项目 | |||||
LambdaQueryWrapper<Project> queryWrapper = Wrappers.lambdaQuery(Project.class).isNotNull(Project::getBuildOrgCode); | |||||
List<Project> projects = projectService.list(queryWrapper); | |||||
// 根据项目code分组 获取最新的一条数据 | |||||
Map<String, Project> projectMap = projects.stream().collect(Collectors.groupingBy(Project::getProjectCode, Collectors.collectingAndThen( | |||||
// 根据创建日期找到最新的记录 | |||||
Collectors.maxBy(Comparator.comparing(Project::getCreateOn)), | |||||
// 如果没有记录则返回null | |||||
optional -> optional.orElse(null) | |||||
))); | |||||
List<Project> projectList = new ArrayList<>(projectMap.values()); | |||||
List<ProjectEarlyWarning> projectEarlyWarnings = Lists.newArrayList(); | |||||
List<WflowEarlyWarningRecords> earlyWarningRecords = Lists.newArrayList(); | |||||
List<ProjectEarlyWarning> needRemoved = Lists.newArrayList(); | |||||
// 查询当前预警表中 已存在的的滞后预警数据 | |||||
Wrapper<ProjectEarlyWarning> warningQuery = Wrappers.lambdaQuery(ProjectEarlyWarning.class) | |||||
.eq(ProjectEarlyWarning::getRuleType, WarningRuleTypeEnum.DELAY_WARNING.getCode()); | |||||
List<ProjectEarlyWarning> earlyWarnings = projectEarlyWarningService.list(warningQuery); | |||||
Map<String, ProjectEarlyWarning> projectEarlyWarningMap = CollUtils.listToMap(earlyWarnings, c -> c.getProjectCode() + StrPool.DASH + c.getStepName()); | |||||
// 遍历项目 获取对应申报单位的滞后预警规则 | |||||
for (Project project : projectList) { | |||||
String buildOrgCode = project.getBuildOrgCode(); | |||||
String projectCode = project.getProjectCode(); | |||||
Long mhUnitId = Long.valueOf(buildOrgCode); | |||||
List<Long> unitIdPaths = mhUnitCache.getUnitIdPaths(mhUnitId); | |||||
if (unitIdPaths.isEmpty()) { | |||||
log.error("该单位无法进行滞后预警:{}", mhUnitId); | |||||
continue; | |||||
} | |||||
List<String> unitIdPathsStr = CollUtils.convert(unitIdPaths, String::valueOf); | |||||
String orderSql = String.format(" order by field(mh_unit_id, %s) desc limit 1", | |||||
CollUtils.join(unitIdPaths, w -> "'" + w + "'", StrUtil.COMMA)); | |||||
log.info("单位ID路径:{}", unitIdPathsStr); | |||||
// 从当前建设单位开始向上获取滞后预警规则 | |||||
WflowEarlyWarning warning = earlyWarningService.getOne(Wrappers.lambdaQuery(WflowEarlyWarning.class) | |||||
.eq(WflowEarlyWarning::getRuleType, WarningRuleTypeEnum.DELAY_WARNING.getCode()) | |||||
.eq(WflowEarlyWarning::getIsOpen, true) | |||||
.in(WflowEarlyWarning::getMhUnitId, unitIdPathsStr) | |||||
.last(orderSql)); | |||||
if (Objects.isNull(warning)){ | |||||
log.info("未找到对应单位:{} 的滞后预警规则", mhUnitId); | |||||
continue; | |||||
} | |||||
String rule = warning.getRule(); | String rule = warning.getRule(); | ||||
if (StringUtils.isNotBlank(rule)) { | if (StringUtils.isNotBlank(rule)) { | ||||
JSONArray ruleArray = JSON.parseArray(rule); | JSONArray ruleArray = JSON.parseArray(rule); | ||||
// 对JSONArray 根据"biz"字段从小到大排序 | |||||
ruleArray.sort((o1, o2) -> { | |||||
JSONObject o1Json = JSON.parseObject(JSON.toJSONString(o1)); | |||||
JSONObject o2Json = JSON.parseObject(JSON.toJSONString(o2)); | |||||
Integer o1Biz = o1Json.getInteger("biz"); | |||||
Integer o2Biz = o2Json.getInteger("biz"); | |||||
return o1Biz.compareTo(o2Biz); | |||||
}); | |||||
if (CollUtil.isNotEmpty(ruleArray)) { | if (CollUtil.isNotEmpty(ruleArray)) { | ||||
ruleArray.forEach(r -> { | ruleArray.forEach(r -> { | ||||
JSONObject rJson = JSON.parseObject(JSON.toJSONString(r)); | JSONObject rJson = JSON.parseObject(JSON.toJSONString(r)); | ||||
@@ -126,15 +179,16 @@ public class DelayWarningTest extends AppTests { | |||||
return; | return; | ||||
} | } | ||||
String path = flowType.getPath(); | String path = flowType.getPath(); | ||||
// 查询 所有这个单位 所配置滞后规则节点 未提交的项目 | |||||
Wrapper<Project> projectQuery = Wrappers.lambdaQuery(Project.class) | |||||
.eq(Project::getBuildOrgCode, mhUnitId) | |||||
.eq(Project::getNewest, Boolean.TRUE) | |||||
.eq(Project::getStatus, flowType.getProjectStatus().getCode()); | |||||
List<Project> needNextProjects = projectService.list(projectQuery); | |||||
List<String> projectCodes = CollUtils.fieldList(needNextProjects, Project::getProjectCode); | |||||
Map<String, ProjectStatusChange> projectStatusChangeMap = MapUtil.newHashMap(); | Map<String, ProjectStatusChange> projectStatusChangeMap = MapUtil.newHashMap(); | ||||
String stepName = null; | String stepName = null; | ||||
List<String> projectCodes = Lists.newArrayList(); | |||||
projectCodes.add(project.getProjectCode()); | |||||
// 是否进行采购&合同备案 | |||||
boolean isPurchase = false; | |||||
// 适配改造是否完成单位确认 | |||||
boolean isModified = false; | |||||
// 终验申请是否提交 | |||||
boolean isFinalInspection = false; | |||||
switch (flowType) { | switch (flowType) { | ||||
// 已立项未采购 获取 立项时间 | // 已立项未采购 获取 立项时间 | ||||
case APPROVED_PROJECT_NOT_PURCHASED:{ | case APPROVED_PROJECT_NOT_PURCHASED:{ | ||||
@@ -142,6 +196,13 @@ public class DelayWarningTest extends AppTests { | |||||
if (CollUtil.isNotEmpty(projectCodes)) { | if (CollUtil.isNotEmpty(projectCodes)) { | ||||
Map<String, ProjectStatusChange> approvedProjectNotPurchasedMap = projectStatusChangeService.listLastEventMap(projectCodes, | Map<String, ProjectStatusChange> approvedProjectNotPurchasedMap = projectStatusChangeService.listLastEventMap(projectCodes, | ||||
ProjectStateChangeEvent.DECLARED_RECORD_PASS); | ProjectStateChangeEvent.DECLARED_RECORD_PASS); | ||||
List<ProjectStateChangeEvent> events = Lists.newArrayList(); | |||||
events.add(ProjectStateChangeEvent.SUBMIT_PURCHASE_CONTRACT_RECORD); | |||||
ProjectStatusChange projectStatusChange = projectStatusChangeService.getLastOne(projectCode, events); | |||||
// 说明进行了采购&合同信息备案 | |||||
if (Objects.nonNull(projectStatusChange)) { | |||||
isPurchase = true; | |||||
} | |||||
if (CollUtil.isNotEmpty(approvedProjectNotPurchasedMap)) { | if (CollUtil.isNotEmpty(approvedProjectNotPurchasedMap)) { | ||||
projectStatusChangeMap.putAll(approvedProjectNotPurchasedMap); | projectStatusChangeMap.putAll(approvedProjectNotPurchasedMap); | ||||
} | } | ||||
@@ -157,6 +218,13 @@ public class DelayWarningTest extends AppTests { | |||||
if (CollUtil.isNotEmpty(purchasedUnmodifiedMap)) { | if (CollUtil.isNotEmpty(purchasedUnmodifiedMap)) { | ||||
projectStatusChangeMap.putAll(purchasedUnmodifiedMap); | projectStatusChangeMap.putAll(purchasedUnmodifiedMap); | ||||
} | } | ||||
List<TenderStateChangeEvent> events = Lists.newArrayList(); | |||||
events.add(TenderStateChangeEvent.SUBMIT_PURCHASE_ORG_CONFIRM); | |||||
PurchaseStatusChange purchaseStatusChange = purchaseStatusChangeService.getLastOne(projectCode, events); | |||||
// 说明进行了单位确认 | |||||
if (Objects.nonNull(purchaseStatusChange)) { | |||||
isModified = true; | |||||
} | |||||
} | } | ||||
} | } | ||||
break; | break; | ||||
@@ -170,6 +238,13 @@ public class DelayWarningTest extends AppTests { | |||||
projectStatusChangeMap.putAll(modifiedNotFinalInspectionMap); | projectStatusChangeMap.putAll(modifiedNotFinalInspectionMap); | ||||
} | } | ||||
} | } | ||||
List<ProjectStateChangeEvent> events = Lists.newArrayList(); | |||||
events.add(ProjectStateChangeEvent.FINAL_ACCEPTANCE_APPLICATION); | |||||
ProjectStatusChange projectStatusChange = projectStatusChangeService.getLastOne(projectCode, events); | |||||
// 说明提交了终验申请 | |||||
if (Objects.nonNull(projectStatusChange)) { | |||||
isFinalInspection = true; | |||||
} | |||||
} | } | ||||
break; | break; | ||||
default: | default: | ||||
@@ -179,54 +254,84 @@ public class DelayWarningTest extends AppTests { | |||||
// 获取项目 滞后(历时)时间 | // 获取项目 滞后(历时)时间 | ||||
HashMap<String, LocalDateTime> touchTimeMap = MapUtil.newHashMap(); | HashMap<String, LocalDateTime> touchTimeMap = MapUtil.newHashMap(); | ||||
String finalStepName = stepName; | String finalStepName = stepName; | ||||
List<Project> needToWaringProjects = needNextProjects.stream() | |||||
.filter(p -> { | |||||
ProjectStatusChange change = projectStatusChangeMap.get(p.getProjectCode()); | |||||
LocalDateTime touchTime = change == null ? null : change.getCreateOn(); | |||||
if (touchTime != null) { | |||||
touchTimeMap.put(p.getProjectCode() + StrPool.DASH + biz, touchTime); | |||||
long duration = getDurationTime(touchTime,LocalDateTime.now(),getTimeUnit()); | |||||
if (duration > delayTime) { | |||||
// 项目 滞后预警 | |||||
projectEarlyWarningService.earlyWarning(p, WarningRuleTypeEnum.DELAY_WARNING.getCode(), com.wflow.enums.WarningNoticeTypeEnum.DELAY.getCode(), finalStepName); | |||||
return Boolean.TRUE; | |||||
} | |||||
} | |||||
return Boolean.FALSE; | |||||
}).collect(Collectors.toList()); | |||||
ProjectStatusChange change = projectStatusChangeMap.get(projectCode); | |||||
LocalDateTime touchTime = change == null ? null : change.getCreateOn(); | |||||
// 是否进行预警 | |||||
boolean isTouch = isTouch(flowType, isPurchase, isModified, isFinalInspection); | |||||
if (touchTime != null) { | |||||
touchTimeMap.put(projectCode + StrPool.DASH + biz, touchTime); | |||||
long duration = getDurationTime(touchTime,LocalDateTime.now(),getTimeUnit()); | |||||
// 如果对应节点超期 且未提交至下一步 | |||||
if (duration > delayTime && isTouch) { | |||||
List<ProjectEarlyWarning> projectEarlyWarningList = Lists.newArrayList(); | |||||
List<WflowEarlyWarningRecords> earlyWarningRecordsList = Lists.newArrayList(); | |||||
// 项目 滞后预警 | |||||
projectEarlyWarningList = projectEarlyWarningService.earlyWarning(project, WarningRuleTypeEnum.DELAY_WARNING.getCode(), com.wflow.enums.WarningNoticeTypeEnum.DELAY.getCode(), finalStepName, projectEarlyWarningList); | |||||
projectEarlyWarnings.addAll(projectEarlyWarningList); | |||||
for (Project needToWaringProject : needToWaringProjects) { | |||||
// 目前没有通知 | |||||
// 如果去预警通知人 1.超级管理员 2.单位管理员 如果都包含 都要发 | |||||
List<String> batchEmployees = Lists.newArrayList(); | |||||
if (StringUtils.isNotBlank(notice) && notice.contains(WarningNoticeTypeEnum.SUPER_ADMIN.getCode().toString())) { | |||||
// 获取超级管理员用户信息 | |||||
List<UserInfo> superAdminUsers = userInfoHelper.getEmployeeCodesByRoleEnum(RoleEnum.SUPER_ADMIN); | |||||
List<String> superAdminEmployeeCodes = superAdminUsers.stream().map(UserInfo::getEmployeeCode).collect(Collectors.toList()); | |||||
batchEmployees.addAll(superAdminEmployeeCodes); | |||||
} | |||||
if (StringUtils.isNotBlank(notice) && notice.contains(WarningNoticeTypeEnum.UNIT_ADMIN.getCode().toString())) { | |||||
// 获取单位管理员用户信息 | |||||
List<UserInfo> unitAdminUsers = userInfoHelper.getEmployeeCodesByRoleEnum(RoleEnum.COMPANY_MANAGER); | |||||
// 过滤出当前项目所属单位的单位管理员 | |||||
List<String> unitAdminEmployeeCodes = unitAdminUsers.stream().filter(user -> Objects.equals(user.getMhUnitId().toString(), needToWaringProject.getBuildOrgCode())) | |||||
.map(UserInfo::getEmployeeCode).collect(Collectors.toList()); | |||||
batchEmployees.addAll(unitAdminEmployeeCodes); | |||||
// 目前没有通知 | |||||
// 如果去预警通知人 1.超级管理员 2.单位管理员 如果都包含 都要发 | |||||
List<String> batchEmployees = Lists.newArrayList(); | |||||
if (StringUtils.isNotBlank(notice) && notice.contains(WarningNoticeTypeEnum.SUPER_ADMIN.getCode().toString())) { | |||||
// 获取超级管理员用户信息 | |||||
List<UserInfo> superAdminUsers = userInfoHelper.getEmployeeCodesByRoleEnum(RoleEnum.SUPER_ADMIN); | |||||
List<String> superAdminEmployeeCodes = superAdminUsers.stream().map(UserInfo::getEmployeeCode).collect(Collectors.toList()); | |||||
batchEmployees.addAll(superAdminEmployeeCodes); | |||||
} | |||||
if (StringUtils.isNotBlank(notice) && notice.contains(WarningNoticeTypeEnum.UNIT_ADMIN.getCode().toString())) { | |||||
// 获取单位管理员用户信息 | |||||
List<UserInfo> unitAdminUsers = userInfoHelper.getEmployeeCodesByRoleEnum(RoleEnum.COMPANY_MANAGER); | |||||
// 过滤出当前项目所属单位的单位管理员 | |||||
List<String> unitAdminEmployeeCodes = unitAdminUsers.stream().filter(user -> Objects.equals(user.getMhUnitId().toString(), project.getBuildOrgCode())) | |||||
.map(UserInfo::getEmployeeCode).collect(Collectors.toList()); | |||||
batchEmployees.addAll(unitAdminEmployeeCodes); | |||||
} | |||||
// 保存到预警记录中 | |||||
earlyWarningRecordsList = earlyWarningManage.getEarlyWarningDelayRecords(warning.getNoticeMethod(), biz, project, | |||||
WarningRuleTypeEnum.DELAY_WARNING.getCode(), ProjectEarlyWarningStatusEnum.DELAY_TIME.getCode(), | |||||
path, touchTimeMap, earlyWarningRecordsList); | |||||
earlyWarningRecords.addAll(earlyWarningRecordsList); | |||||
}else { | |||||
// 判断是否已经存在对应节点预警 如果有 从预警信息表中移除 | |||||
if (projectEarlyWarningMap.containsKey(project.getProjectCode() + StrPool.DASH + finalStepName)) { | |||||
ProjectEarlyWarning projectEarlyWarning = projectEarlyWarningMap.get(projectCode + StrPool.DASH + finalStepName); | |||||
needRemoved.add(projectEarlyWarning); | |||||
} | |||||
} | } | ||||
// 保存到预警记录中 | |||||
earlyWarningManage.doEarlyWarningDelay(warning.getNoticeMethod(), biz, needToWaringProject, | |||||
WarningRuleTypeEnum.DELAY_WARNING.getCode(), ProjectEarlyWarningStatusEnum.DELAY_TIME.getCode(), | |||||
path, touchTimeMap); | |||||
} | } | ||||
}); | }); | ||||
} | } | ||||
} | } | ||||
} | } | ||||
// 每个规则按通知节点顺序 更新保存一次 | |||||
if (CollUtil.isNotEmpty(needRemoved)){ | |||||
projectEarlyWarningService.removeBatchByIds(needRemoved); | |||||
} | |||||
if (CollUtil.isNotEmpty(projectEarlyWarnings)){ | |||||
log.info("需要滞后预警通知的项目数:{}", projectEarlyWarnings.size()); | |||||
projectEarlyWarningService.saveOrUpdateBatch(projectEarlyWarnings); | |||||
} | |||||
if (CollUtil.isNotEmpty(earlyWarningRecords)){ | |||||
log.info("需要滞后预警通知记录数:{}", earlyWarningRecords.size()); | |||||
earlyWarningRecordsService.saveOrUpdateBatch(earlyWarningRecords); | |||||
} | |||||
stopWatch.stop(); | stopWatch.stop(); | ||||
log.info("=========== 滞后预警任务结束 耗时{}s", stopWatch.getTotalTimeSeconds()); | log.info("=========== 滞后预警任务结束 耗时{}s", stopWatch.getTotalTimeSeconds()); | ||||
} | } | ||||
private boolean isTouch(WarningFlowTypeEnum flowType, Boolean isPurchase, Boolean isModified, Boolean isFinalInspection) { | |||||
switch (flowType) { | |||||
case APPROVED_PROJECT_NOT_PURCHASED: | |||||
return !isPurchase; | |||||
case MODIFIED_NOT_FINAL_INSPECTION: | |||||
return !isModified && !isFinalInspection; | |||||
case PURCHASED_UNMODIFIED: | |||||
return isPurchase && !isModified; | |||||
default: | |||||
return false; | |||||
} | |||||
} | |||||
@Test | @Test | ||||
public void two(){ | public void two(){ | ||||
log.info("=========== 预警项目状态校验任务开始 ==========="); | log.info("=========== 预警项目状态校验任务开始 ==========="); | ||||
@@ -264,6 +369,21 @@ public class DelayWarningTest extends AppTests { | |||||
log.info("=========== 预警项目状态校验任务结束 耗时{}s", stopWatch.getTotalTimeSeconds()); | log.info("=========== 预警项目状态校验任务结束 耗时{}s", stopWatch.getTotalTimeSeconds()); | ||||
} | } | ||||
@Test | |||||
public void three(){ | |||||
List<Long> unitIdPaths = mhUnitCache.getUnitIdPaths(32L); | |||||
System.out.println(unitIdPaths); | |||||
List<String> unitIdPathsStr = CollUtils.convert(unitIdPaths, String::valueOf); | |||||
String orderSql = String.format(" order by field(region_code, %s) desc limit 1", | |||||
CollUtils.join(unitIdPaths, w -> "'" + w + "'", StrUtil.COMMA)); | |||||
System.out.println("单位ID路径:" + unitIdPathsStr); | |||||
WflowModels one = processModelService.getOne(Wrappers.lambdaQuery(WflowModels.class) | |||||
.eq(WflowModels::getProcessType, ProjectProcessType.PROJECT_RECORD_APPROVAL_PROCESS.getCode()) | |||||
.in(WflowModels::getRegionCode, unitIdPathsStr) | |||||
.last(orderSql)); | |||||
System.out.println(one); | |||||
} | |||||
private long getDurationTime(LocalDateTime touchTime, LocalDateTime now, ChronoUnit timeUnit) { | private long getDurationTime(LocalDateTime touchTime, LocalDateTime now, ChronoUnit timeUnit) { | ||||
return timeUnit.between(touchTime, now); | return timeUnit.between(touchTime, now); | ||||
} | } | ||||