|
|
@ -587,160 +587,160 @@ public class EfcodeCpPlanServiceImpl implements IEfcodeCpPlanService { |
|
|
* @param insertReserve 是否将预约记录插入数据库;为false时仅计算匹配结果不落库 |
|
|
* @param insertReserve 是否将预约记录插入数据库;为false时仅计算匹配结果不落库 |
|
|
* @return 按 planGroupId 分组的预约记录列表 |
|
|
* @return 按 planGroupId 分组的预约记录列表 |
|
|
*/ |
|
|
*/ |
|
|
@Transactional(rollbackFor = Exception.class) |
|
|
// @Transactional(rollbackFor = Exception.class)
|
|
|
@Override |
|
|
// @Override
|
|
|
public Map<String, List<EfcodeCpReserve>> autoMatchReserve(boolean forceMatch, boolean updatePlan, boolean insertReserve) { |
|
|
// public Map<String, List<EfcodeCpReserve>> autoMatchReserve(boolean forceMatch, boolean updatePlan, boolean insertReserve) {
|
|
|
log.info("[CpPlan] 开始执行计划自动匹配预约, forceMatch={}, updatePlan={}, insertReserve={}", forceMatch, updatePlan, insertReserve); |
|
|
// log.info("[CpPlan] 开始执行计划自动匹配预约, forceMatch={}, updatePlan={}, insertReserve={}", forceMatch, updatePlan, insertReserve);
|
|
|
Map<String, List<EfcodeCpReserve>> resultMap = new HashMap<>(); |
|
|
// Map<String, List<EfcodeCpReserve>> resultMap = new HashMap<>();
|
|
|
|
|
|
//
|
|
|
// 1. 日期校验:如果不是强制匹配,则判断当前天数是否等于 CP_SETTING_AUTO_MATCH_START
|
|
|
// // 1. 日期校验:如果不是强制匹配,则判断当前天数是否等于 CP_SETTING_AUTO_MATCH_START
|
|
|
if (!forceMatch) { |
|
|
// if (!forceMatch) {
|
|
|
int autoMatchStart = cpSettingService.getAutoMatchStart(); |
|
|
// int autoMatchStart = cpSettingService.getAutoMatchStart();
|
|
|
int today = LocalDate.now().getDayOfMonth(); |
|
|
// int today = LocalDate.now().getDayOfMonth();
|
|
|
if (today != autoMatchStart) { |
|
|
// if (today != autoMatchStart) {
|
|
|
log.info("[CpPlan] 当前日期{}号,不等于设定的自动匹配日期{}号,跳过执行", today, autoMatchStart); |
|
|
// log.info("[CpPlan] 当前日期{}号,不等于设定的自动匹配日期{}号,跳过执行", today, autoMatchStart);
|
|
|
return resultMap; |
|
|
// return resultMap;
|
|
|
} |
|
|
// }
|
|
|
} |
|
|
// }
|
|
|
|
|
|
//
|
|
|
// 2. 获取最大联合单位数量
|
|
|
// // 2. 获取最大联合单位数量
|
|
|
int maxAutoMatchUnionUnit = cpSettingService.getMaxAutoMatchUnionUnit(); |
|
|
// int maxAutoMatchUnionUnit = cpSettingService.getMaxAutoMatchUnionUnit();
|
|
|
|
|
|
//
|
|
|
// 3. 查询待匹配的计划:plan_date > 当前时间 且 system_reserved=0, reserve_status=1, is_public=1, is_union=1
|
|
|
// // 3. 查询待匹配的计划:plan_date > 当前时间 且 system_reserved=0, reserve_status=1, is_public=1, is_union=1
|
|
|
Date now = new Date(); |
|
|
// Date now = new Date();
|
|
|
LambdaQueryWrapper<EfcodeCpPlan> lqw = Wrappers.lambdaQuery(); |
|
|
// LambdaQueryWrapper<EfcodeCpPlan> lqw = Wrappers.lambdaQuery();
|
|
|
lqw.gt(EfcodeCpPlan::getPlanDate, now); |
|
|
// lqw.gt(EfcodeCpPlan::getPlanDate, now);
|
|
|
lqw.eq(EfcodeCpPlan::getSystemReserved, 0L); |
|
|
// lqw.eq(EfcodeCpPlan::getSystemReserved, 0L);
|
|
|
lqw.eq(EfcodeCpPlan::getReserveStatus, 1L); |
|
|
// lqw.eq(EfcodeCpPlan::getReserveStatus, 1L);
|
|
|
lqw.eq(EfcodeCpPlan::getIsPublic, 1L); |
|
|
// lqw.eq(EfcodeCpPlan::getIsPublic, 1L);
|
|
|
lqw.eq(EfcodeCpPlan::getIsUnion, 1L); |
|
|
// lqw.eq(EfcodeCpPlan::getIsUnion, 1L);
|
|
|
lqw.eq(EfcodeCpPlan::getIsDelete, 0L); |
|
|
// lqw.eq(EfcodeCpPlan::getIsDelete, 0L);
|
|
|
lqw.orderByAsc(EfcodeCpPlan::getPlanDate); |
|
|
// lqw.orderByAsc(EfcodeCpPlan::getPlanDate);
|
|
|
List<EfcodeCpPlan> pendingPlans = baseMapper.selectList(lqw); |
|
|
// List<EfcodeCpPlan> pendingPlans = baseMapper.selectList(lqw);
|
|
|
|
|
|
//
|
|
|
if (pendingPlans.isEmpty()) { |
|
|
// if (pendingPlans.isEmpty()) {
|
|
|
log.info("[CpPlan] 没有找到待匹配的计划记录,执行结束"); |
|
|
// log.info("[CpPlan] 没有找到待匹配的计划记录,执行结束");
|
|
|
return resultMap; |
|
|
// return resultMap;
|
|
|
} |
|
|
// }
|
|
|
log.info("[CpPlan] 共查询到{}条待匹配计划", pendingPlans.size()); |
|
|
// log.info("[CpPlan] 共查询到{}条待匹配计划", pendingPlans.size());
|
|
|
|
|
|
//
|
|
|
// 4. 已处理过的“企业+周”组合(同一轮中同企业同周不重复处理,但不同周分别匹配)
|
|
|
// // 4. 已处理过的“企业+周”组合(同一轮中同企业同周不重复处理,但不同周分别匹配)
|
|
|
Set<String> processedKeys = new HashSet<>(); |
|
|
// Set<String> processedKeys = new HashSet<>();
|
|
|
int matchedCount = 0; |
|
|
// int matchedCount = 0;
|
|
|
|
|
|
//
|
|
|
for (EfcodeCpPlan plan : pendingPlans) { |
|
|
// for (EfcodeCpPlan plan : pendingPlans) {
|
|
|
String enterpriseNumber = plan.getEnterpriseNumber(); |
|
|
// String enterpriseNumber = plan.getEnterpriseNumber();
|
|
|
if (StringUtils.isBlank(enterpriseNumber)) { |
|
|
// if (StringUtils.isBlank(enterpriseNumber)) {
|
|
|
continue; |
|
|
// continue;
|
|
|
} |
|
|
// }
|
|
|
|
|
|
//
|
|
|
// 5. 查找计划所在自然周(周一~周日)内同企业、不同执法单位的其他待匹配计划
|
|
|
// // 5. 查找计划所在自然周(周一~周日)内同企业、不同执法单位的其他待匹配计划
|
|
|
LocalDate planLocalDate = plan.getPlanDate().toInstant().atZone(ZoneId.systemDefault()).toLocalDate(); |
|
|
// LocalDate planLocalDate = plan.getPlanDate().toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
|
|
|
LocalDate weekStartDate = planLocalDate.with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY)); |
|
|
// LocalDate weekStartDate = planLocalDate.with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY));
|
|
|
LocalDate weekEndDate = planLocalDate.with(TemporalAdjusters.nextOrSame(DayOfWeek.SUNDAY)); |
|
|
// LocalDate weekEndDate = planLocalDate.with(TemporalAdjusters.nextOrSame(DayOfWeek.SUNDAY));
|
|
|
|
|
|
//
|
|
|
// 按“企业+周起始日”去重,同企业同周只处理一次
|
|
|
// // 按“企业+周起始日”去重,同企业同周只处理一次
|
|
|
String processKey = enterpriseNumber + "_" + weekStartDate; |
|
|
// String processKey = enterpriseNumber + "_" + weekStartDate;
|
|
|
if (processedKeys.contains(processKey)) { |
|
|
// if (processedKeys.contains(processKey)) {
|
|
|
continue; |
|
|
// continue;
|
|
|
} |
|
|
// }
|
|
|
Date weekStart = Date.from(weekStartDate.atStartOfDay(ZoneId.systemDefault()).toInstant()); |
|
|
// Date weekStart = Date.from(weekStartDate.atStartOfDay(ZoneId.systemDefault()).toInstant());
|
|
|
Date weekEnd = Date.from(weekEndDate.atStartOfDay(ZoneId.systemDefault()).toInstant()); |
|
|
// Date weekEnd = Date.from(weekEndDate.atStartOfDay(ZoneId.systemDefault()).toInstant());
|
|
|
|
|
|
//
|
|
|
LambdaQueryWrapper<EfcodeCpPlan> weekLqw = Wrappers.lambdaQuery(); |
|
|
// LambdaQueryWrapper<EfcodeCpPlan> weekLqw = Wrappers.lambdaQuery();
|
|
|
weekLqw.ge(EfcodeCpPlan::getPlanDate, weekStart); |
|
|
// weekLqw.ge(EfcodeCpPlan::getPlanDate, weekStart);
|
|
|
weekLqw.le(EfcodeCpPlan::getPlanDate, weekEnd); |
|
|
// weekLqw.le(EfcodeCpPlan::getPlanDate, weekEnd);
|
|
|
weekLqw.eq(EfcodeCpPlan::getEnterpriseNumber, enterpriseNumber); |
|
|
// weekLqw.eq(EfcodeCpPlan::getEnterpriseNumber, enterpriseNumber);
|
|
|
weekLqw.eq(EfcodeCpPlan::getSystemReserved, 0L); |
|
|
// weekLqw.eq(EfcodeCpPlan::getSystemReserved, 0L);
|
|
|
weekLqw.eq(EfcodeCpPlan::getReserveStatus, 1L); |
|
|
// weekLqw.eq(EfcodeCpPlan::getReserveStatus, 1L);
|
|
|
weekLqw.eq(EfcodeCpPlan::getIsPublic, 1L); |
|
|
// weekLqw.eq(EfcodeCpPlan::getIsPublic, 1L);
|
|
|
weekLqw.eq(EfcodeCpPlan::getIsUnion, 1L); |
|
|
// weekLqw.eq(EfcodeCpPlan::getIsUnion, 1L);
|
|
|
weekLqw.eq(EfcodeCpPlan::getIsDelete, 0L); |
|
|
// weekLqw.eq(EfcodeCpPlan::getIsDelete, 0L);
|
|
|
weekLqw.orderByAsc(EfcodeCpPlan::getPlanDate); |
|
|
// weekLqw.orderByAsc(EfcodeCpPlan::getPlanDate);
|
|
|
List<EfcodeCpPlan> samePlans = baseMapper.selectList(weekLqw); |
|
|
// List<EfcodeCpPlan> samePlans = baseMapper.selectList(weekLqw);
|
|
|
|
|
|
//
|
|
|
// 6. 按不同执法单位去重,取不同 bureau_dept_id 的计划
|
|
|
// // 6. 按不同执法单位去重,取不同 bureau_dept_id 的计划
|
|
|
List<EfcodeCpPlan> distinctUnitPlans = new ArrayList<>(); |
|
|
// List<EfcodeCpPlan> distinctUnitPlans = new ArrayList<>();
|
|
|
Set<String> seenBureauDeptIds = new HashSet<>(); |
|
|
// Set<String> seenBureauDeptIds = new HashSet<>();
|
|
|
for (EfcodeCpPlan sp : samePlans) { |
|
|
// for (EfcodeCpPlan sp : samePlans) {
|
|
|
if (!seenBureauDeptIds.contains(sp.getBureauDeptId())) { |
|
|
// if (!seenBureauDeptIds.contains(sp.getBureauDeptId())) {
|
|
|
seenBureauDeptIds.add(sp.getBureauDeptId()); |
|
|
// seenBureauDeptIds.add(sp.getBureauDeptId());
|
|
|
distinctUnitPlans.add(sp); |
|
|
// distinctUnitPlans.add(sp);
|
|
|
} |
|
|
// }
|
|
|
// 限制最大联合数量
|
|
|
// // 限制最大联合数量
|
|
|
if (distinctUnitPlans.size() >= maxAutoMatchUnionUnit) { |
|
|
// if (distinctUnitPlans.size() >= maxAutoMatchUnionUnit) {
|
|
|
break; |
|
|
// break;
|
|
|
} |
|
|
// }
|
|
|
} |
|
|
// }
|
|
|
|
|
|
//
|
|
|
// 7. 如果只有一个单位的计划,说明没有可联合的,跳过
|
|
|
// // 7. 如果只有一个单位的计划,说明没有可联合的,跳过
|
|
|
if (distinctUnitPlans.size() <= 1) { |
|
|
// if (distinctUnitPlans.size() <= 1) {
|
|
|
log.debug("[CpPlan] 企业[{}]一周内只有1个单位的计划,跳过", enterpriseNumber); |
|
|
// log.debug("[CpPlan] 企业[{}]一周内只有1个单位的计划,跳过", enterpriseNumber);
|
|
|
continue; |
|
|
// continue;
|
|
|
} |
|
|
// }
|
|
|
|
|
|
//
|
|
|
// 8. 生成预约记录 - 使用同一个 plan_group_id
|
|
|
// // 8. 生成预约记录 - 使用同一个 plan_group_id
|
|
|
String planGroupId = "Temp"+"_"+UUID.randomUUID().toString().replace("-", ""); |
|
|
// String planGroupId = "Temp"+"_"+UUID.randomUUID().toString().replace("-", "");
|
|
|
Date reserveTime = new Date(); |
|
|
// Date reserveTime = new Date();
|
|
|
List<EfcodeCpReserve> groupReserves = new ArrayList<>(); |
|
|
// List<EfcodeCpReserve> groupReserves = new ArrayList<>();
|
|
|
|
|
|
//
|
|
|
// 拼接参与单位名称,用于 opMessage
|
|
|
// // 拼接参与单位名称,用于 opMessage
|
|
|
String unitNames = distinctUnitPlans.stream() |
|
|
// String unitNames = distinctUnitPlans.stream()
|
|
|
.map(EfcodeCpPlan::getBureauDeptName) |
|
|
// .map(EfcodeCpPlan::getBureauDeptName)
|
|
|
.filter(StringUtils::isNotBlank) |
|
|
// .filter(StringUtils::isNotBlank)
|
|
|
.collect(Collectors.joining(",")); |
|
|
// .collect(Collectors.joining(","));
|
|
|
String opMessage = "由于计划执法时间安排较近,系统推荐进行联合,参与单位为:" + unitNames + ".请确认."; |
|
|
// String opMessage = "由于计划执法时间安排较近,系统推荐进行联合,参与单位为:" + unitNames + ".请确认.";
|
|
|
|
|
|
//
|
|
|
for (int i = 0; i < distinctUnitPlans.size(); i++) { |
|
|
// for (int i = 0; i < distinctUnitPlans.size(); i++) {
|
|
|
EfcodeCpPlan matchedPlan = distinctUnitPlans.get(i); |
|
|
// EfcodeCpPlan matchedPlan = distinctUnitPlans.get(i);
|
|
|
EfcodeCpReserve reserve = new EfcodeCpReserve(); |
|
|
// EfcodeCpReserve reserve = new EfcodeCpReserve();
|
|
|
reserve.setPlanId(matchedPlan.getId()); |
|
|
// reserve.setPlanId(matchedPlan.getId());
|
|
|
reserve.setPlanGroupId(planGroupId); |
|
|
// reserve.setPlanGroupId(planGroupId);
|
|
|
reserve.setReserveTime(reserveTime); |
|
|
// reserve.setReserveTime(reserveTime);
|
|
|
reserve.setOpStatus(3L); // 待确认
|
|
|
// reserve.setOpStatus(3L); // 待确认
|
|
|
reserve.setOpOrder(0L); // 系统匹配默认为0
|
|
|
// reserve.setOpOrder(0L); // 系统匹配默认为0
|
|
|
reserve.setOpMessage(opMessage); |
|
|
// reserve.setOpMessage(opMessage);
|
|
|
reserve.setOpSetDate(matchedPlan.getPlanDate()); |
|
|
// reserve.setOpSetDate(matchedPlan.getPlanDate());
|
|
|
reserve.setOpSetTime(matchedPlan.getPlanTime()); |
|
|
// reserve.setOpSetTime(matchedPlan.getPlanTime());
|
|
|
reserve.setResFrom(1L); // 系统匹配
|
|
|
// reserve.setResFrom(1L); // 系统匹配
|
|
|
reserve.setSenderId("from_system"); |
|
|
// reserve.setSenderId("from_system");
|
|
|
reserve.setReceiverId(String.valueOf(matchedPlan.getCreateBy())); |
|
|
// reserve.setReceiverId(String.valueOf(matchedPlan.getCreateBy()));
|
|
|
|
|
|
//
|
|
|
if (insertReserve) { |
|
|
// if (insertReserve) {
|
|
|
efcodeCpReserveMapper.insert(reserve); |
|
|
// efcodeCpReserveMapper.insert(reserve);
|
|
|
} |
|
|
// }
|
|
|
groupReserves.add(reserve); |
|
|
// groupReserves.add(reserve);
|
|
|
} |
|
|
// }
|
|
|
|
|
|
//
|
|
|
// 9. 更新计划: 将同企业一周内所有待匹配计划标记为已系统匹配,防止重复匹配
|
|
|
// // 9. 更新计划: 将同企业一周内所有待匹配计划标记为已系统匹配,防止重复匹配
|
|
|
if (updatePlan) { |
|
|
// if (updatePlan) {
|
|
|
for (EfcodeCpPlan sp : samePlans) { |
|
|
// for (EfcodeCpPlan sp : samePlans) {
|
|
|
EfcodeCpPlan planUpdate = new EfcodeCpPlan(); |
|
|
// EfcodeCpPlan planUpdate = new EfcodeCpPlan();
|
|
|
planUpdate.setId(sp.getId()); |
|
|
// planUpdate.setId(sp.getId());
|
|
|
planUpdate.setSystemReserved(1L); |
|
|
// planUpdate.setSystemReserved(1L);
|
|
|
baseMapper.updateById(planUpdate); |
|
|
// baseMapper.updateById(planUpdate);
|
|
|
} |
|
|
// }
|
|
|
// 被选中参与联合的计划额外更新 reserve_status=2(预约中)
|
|
|
// // 被选中参与联合的计划额外更新 reserve_status=2(预约中)
|
|
|
for (EfcodeCpPlan dp : distinctUnitPlans) { |
|
|
// for (EfcodeCpPlan dp : distinctUnitPlans) {
|
|
|
EfcodeCpPlan planUpdate = new EfcodeCpPlan(); |
|
|
// EfcodeCpPlan planUpdate = new EfcodeCpPlan();
|
|
|
planUpdate.setId(dp.getId()); |
|
|
// planUpdate.setId(dp.getId());
|
|
|
planUpdate.setReserveStatus(2L); |
|
|
// planUpdate.setReserveStatus(2L);
|
|
|
baseMapper.updateById(planUpdate); |
|
|
// baseMapper.updateById(planUpdate);
|
|
|
} |
|
|
// }
|
|
|
} |
|
|
// }
|
|
|
|
|
|
//
|
|
|
resultMap.put(planGroupId, groupReserves); |
|
|
// resultMap.put(planGroupId, groupReserves);
|
|
|
|
|
|
//
|
|
|
// 标记该企业已处理
|
|
|
// // 标记该企业已处理
|
|
|
processedKeys.add(enterpriseNumber); |
|
|
// processedKeys.add(enterpriseNumber);
|
|
|
matchedCount++; |
|
|
// matchedCount++;
|
|
|
log.info("[CpPlan] 企业[{}]匹配成功,联合{}个单位,planGroupId={}", |
|
|
// log.info("[CpPlan] 企业[{}]匹配成功,联合{}个单位,planGroupId={}",
|
|
|
enterpriseNumber, distinctUnitPlans.size(), planGroupId); |
|
|
// enterpriseNumber, distinctUnitPlans.size(), planGroupId);
|
|
|
} |
|
|
// }
|
|
|
|
|
|
//
|
|
|
log.info("[CpPlan] 计划自动匹配预约执行完毕,共匹配{}组联合预约", matchedCount); |
|
|
// log.info("[CpPlan] 计划自动匹配预约执行完毕,共匹配{}组联合预约", matchedCount);
|
|
|
return resultMap; |
|
|
// return resultMap;
|
|
|
} |
|
|
// }
|
|
|
|
|
|
|
|
|
@Transactional(rollbackFor = Exception.class) |
|
|
@Transactional(rollbackFor = Exception.class) |
|
|
@Override |
|
|
@Override |
|
|
@ -1003,188 +1003,188 @@ public class EfcodeCpPlanServiceImpl implements IEfcodeCpPlanService { |
|
|
* @param insertReserve 是否将预约记录插入数据库;为false时仅计算匹配结果不落库 |
|
|
* @param insertReserve 是否将预约记录插入数据库;为false时仅计算匹配结果不落库 |
|
|
* @return 按 planGroupId 分组的预约记录列表 |
|
|
* @return 按 planGroupId 分组的预约记录列表 |
|
|
*/ |
|
|
*/ |
|
|
@Transactional(rollbackFor = Exception.class) |
|
|
// @Transactional(rollbackFor = Exception.class)
|
|
|
@Override |
|
|
// @Override
|
|
|
public Map<String, List<EfcodeCpReserve>> autoMatchReserveV2(boolean forceMatch, boolean updatePlan, boolean insertReserve) { |
|
|
// public Map<String, List<EfcodeCpReserve>> autoMatchReserveV2(boolean forceMatch, boolean updatePlan, boolean insertReserve) {
|
|
|
log.info("[CpPlan-V2] 开始执行计划自动匹配预约, forceMatch={}, updatePlan={}, insertReserve={}", forceMatch, updatePlan, insertReserve); |
|
|
// log.info("[CpPlan-V2] 开始执行计划自动匹配预约, forceMatch={}, updatePlan={}, insertReserve={}", forceMatch, updatePlan, insertReserve);
|
|
|
Map<String, List<EfcodeCpReserve>> resultMap = new HashMap<>(); |
|
|
// Map<String, List<EfcodeCpReserve>> resultMap = new HashMap<>();
|
|
|
|
|
|
//
|
|
|
// 1. 日期校验:如果不是强制匹配,则判断当前天数是否等于 CP_SETTING_AUTO_MATCH_START
|
|
|
// // 1. 日期校验:如果不是强制匹配,则判断当前天数是否等于 CP_SETTING_AUTO_MATCH_START
|
|
|
if (!forceMatch) { |
|
|
// if (!forceMatch) {
|
|
|
int autoMatchStart = cpSettingService.getAutoMatchStart(); |
|
|
// int autoMatchStart = cpSettingService.getAutoMatchStart();
|
|
|
int today = LocalDate.now().getDayOfMonth(); |
|
|
// int today = LocalDate.now().getDayOfMonth();
|
|
|
if (today != autoMatchStart) { |
|
|
// if (today != autoMatchStart) {
|
|
|
log.info("[CpPlan-V2] 当前日期{}号,不等于设定的自动匹配日期{}号,跳过执行", today, autoMatchStart); |
|
|
// log.info("[CpPlan-V2] 当前日期{}号,不等于设定的自动匹配日期{}号,跳过执行", today, autoMatchStart);
|
|
|
return resultMap; |
|
|
// return resultMap;
|
|
|
} |
|
|
// }
|
|
|
} |
|
|
// }
|
|
|
|
|
|
//
|
|
|
// 2. 获取最大联合单位数量
|
|
|
// // 2. 获取最大联合单位数量
|
|
|
int maxUnionUnit = cpSettingService.getMaxUnionUnit(); |
|
|
// int maxUnionUnit = cpSettingService.getMaxUnionUnit();
|
|
|
|
|
|
//
|
|
|
// 2.1 获取系统匹配预约周数范围
|
|
|
// // 2.1 获取系统匹配预约周数范围
|
|
|
int systemMatchWeeks = cpSettingService.getSystemMatchWeeks(); |
|
|
// int systemMatchWeeks = cpSettingService.getSystemMatchWeeks();
|
|
|
log.info("[CpPlan-V2] 系统匹配周数范围={}", systemMatchWeeks); |
|
|
// log.info("[CpPlan-V2] 系统匹配周数范围={}", systemMatchWeeks);
|
|
|
|
|
|
//
|
|
|
// 3. 查询待匹配的计划:plan_date > 当前时间 且 system_reserved=0, manual_reserved=0, reserve_status=1, is_public=1, is_union=1
|
|
|
// // 3. 查询待匹配的计划:plan_date > 当前时间 且 system_reserved=0, manual_reserved=0, reserve_status=1, is_public=1, is_union=1
|
|
|
Date now = new Date(); |
|
|
// Date now = new Date();
|
|
|
LambdaQueryWrapper<EfcodeCpPlan> lqw = Wrappers.lambdaQuery(); |
|
|
// LambdaQueryWrapper<EfcodeCpPlan> lqw = Wrappers.lambdaQuery();
|
|
|
lqw.gt(EfcodeCpPlan::getPlanDate, now); |
|
|
// lqw.gt(EfcodeCpPlan::getPlanDate, now);
|
|
|
lqw.eq(EfcodeCpPlan::getSystemReserved, 0L); |
|
|
// lqw.eq(EfcodeCpPlan::getSystemReserved, 0L);
|
|
|
lqw.eq(EfcodeCpPlan::getManualReserved, 0L); |
|
|
// lqw.eq(EfcodeCpPlan::getManualReserved, 0L);
|
|
|
lqw.eq(EfcodeCpPlan::getReserveStatus, 1L); |
|
|
// lqw.eq(EfcodeCpPlan::getReserveStatus, 1L);
|
|
|
lqw.eq(EfcodeCpPlan::getIsPublic, 1L); |
|
|
// lqw.eq(EfcodeCpPlan::getIsPublic, 1L);
|
|
|
lqw.eq(EfcodeCpPlan::getIsUnion, 1L); |
|
|
// lqw.eq(EfcodeCpPlan::getIsUnion, 1L);
|
|
|
lqw.eq(EfcodeCpPlan::getIsDelete, 0L); |
|
|
// lqw.eq(EfcodeCpPlan::getIsDelete, 0L);
|
|
|
lqw.orderByAsc(EfcodeCpPlan::getPlanDate); |
|
|
// lqw.orderByAsc(EfcodeCpPlan::getPlanDate);
|
|
|
List<EfcodeCpPlan> pendingPlans = baseMapper.selectList(lqw); |
|
|
// List<EfcodeCpPlan> pendingPlans = baseMapper.selectList(lqw);
|
|
|
|
|
|
//
|
|
|
if (pendingPlans.isEmpty()) { |
|
|
// if (pendingPlans.isEmpty()) {
|
|
|
log.info("[CpPlan-V2] 没有找到待匹配的计划记录,执行结束"); |
|
|
// log.info("[CpPlan-V2] 没有找到待匹配的计划记录,执行结束");
|
|
|
return resultMap; |
|
|
// return resultMap;
|
|
|
} |
|
|
// }
|
|
|
log.info("[CpPlan-V2] 共查询到{}条待匹配计划", pendingPlans.size()); |
|
|
// log.info("[CpPlan-V2] 共查询到{}条待匹配计划", pendingPlans.size());
|
|
|
|
|
|
//
|
|
|
// 4. 已处理过的"企业+周"组合,同企业同周只处理一次
|
|
|
// // 4. 已处理过的"企业+周"组合,同企业同周只处理一次
|
|
|
Set<String> processedKeys = new HashSet<>(); |
|
|
// Set<String> processedKeys = new HashSet<>();
|
|
|
int matchedCount = 0; |
|
|
// int matchedCount = 0;
|
|
|
|
|
|
//
|
|
|
for (EfcodeCpPlan plan : pendingPlans) { |
|
|
// for (EfcodeCpPlan plan : pendingPlans) {
|
|
|
String enterpriseNumber = plan.getEnterpriseNumber(); |
|
|
// String enterpriseNumber = plan.getEnterpriseNumber();
|
|
|
if (StringUtils.isBlank(enterpriseNumber)) { |
|
|
// if (StringUtils.isBlank(enterpriseNumber)) {
|
|
|
continue; |
|
|
// continue;
|
|
|
} |
|
|
// }
|
|
|
|
|
|
//
|
|
|
// 5. 计算计划所在的时间范围:以计划所在自然周的周一为起始,向后扩展 systemMatchWeeks 周
|
|
|
// // 5. 计算计划所在的时间范围:以计划所在自然周的周一为起始,向后扩展 systemMatchWeeks 周
|
|
|
LocalDate planLocalDate = plan.getPlanDate().toInstant().atZone(ZoneId.systemDefault()).toLocalDate(); |
|
|
// LocalDate planLocalDate = plan.getPlanDate().toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
|
|
|
LocalDate weekStartDate = planLocalDate.with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY)); |
|
|
// LocalDate weekStartDate = planLocalDate.with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY));
|
|
|
LocalDate weekEndDate = weekStartDate.plusWeeks(systemMatchWeeks).minusDays(1); // 扩展N周后的周日
|
|
|
// LocalDate weekEndDate = weekStartDate.plusWeeks(systemMatchWeeks).minusDays(1); // 扩展N周后的周日
|
|
|
|
|
|
//
|
|
|
// 按"企业+周起始日"去重,同企业同周只处理一次
|
|
|
// // 按"企业+周起始日"去重,同企业同周只处理一次
|
|
|
String processKey = enterpriseNumber + "_" + weekStartDate; |
|
|
// String processKey = enterpriseNumber + "_" + weekStartDate;
|
|
|
if (processedKeys.contains(processKey)) { |
|
|
// if (processedKeys.contains(processKey)) {
|
|
|
continue; |
|
|
// continue;
|
|
|
} |
|
|
// }
|
|
|
processedKeys.add(processKey); |
|
|
// processedKeys.add(processKey);
|
|
|
|
|
|
//
|
|
|
// 6. 查找该自然周内同企业的所有待匹配计划
|
|
|
// // 6. 查找该自然周内同企业的所有待匹配计划
|
|
|
Date weekStart = Date.from(weekStartDate.atStartOfDay(ZoneId.systemDefault()).toInstant()); |
|
|
// Date weekStart = Date.from(weekStartDate.atStartOfDay(ZoneId.systemDefault()).toInstant());
|
|
|
Date weekEnd = Date.from(weekEndDate.atStartOfDay(ZoneId.systemDefault()).toInstant()); |
|
|
// Date weekEnd = Date.from(weekEndDate.atStartOfDay(ZoneId.systemDefault()).toInstant());
|
|
|
|
|
|
//
|
|
|
LambdaQueryWrapper<EfcodeCpPlan> weekLqw = Wrappers.lambdaQuery(); |
|
|
// LambdaQueryWrapper<EfcodeCpPlan> weekLqw = Wrappers.lambdaQuery();
|
|
|
weekLqw.ge(EfcodeCpPlan::getPlanDate, weekStart); |
|
|
// weekLqw.ge(EfcodeCpPlan::getPlanDate, weekStart);
|
|
|
weekLqw.le(EfcodeCpPlan::getPlanDate, weekEnd); |
|
|
// weekLqw.le(EfcodeCpPlan::getPlanDate, weekEnd);
|
|
|
weekLqw.eq(EfcodeCpPlan::getEnterpriseNumber, enterpriseNumber); |
|
|
// weekLqw.eq(EfcodeCpPlan::getEnterpriseNumber, enterpriseNumber);
|
|
|
weekLqw.eq(EfcodeCpPlan::getSystemReserved, 0L); |
|
|
// weekLqw.eq(EfcodeCpPlan::getSystemReserved, 0L);
|
|
|
weekLqw.eq(EfcodeCpPlan::getManualReserved, 0L); |
|
|
// weekLqw.eq(EfcodeCpPlan::getManualReserved, 0L);
|
|
|
weekLqw.eq(EfcodeCpPlan::getReserveStatus, 1L); |
|
|
// weekLqw.eq(EfcodeCpPlan::getReserveStatus, 1L);
|
|
|
weekLqw.eq(EfcodeCpPlan::getIsPublic, 1L); |
|
|
// weekLqw.eq(EfcodeCpPlan::getIsPublic, 1L);
|
|
|
weekLqw.eq(EfcodeCpPlan::getIsUnion, 1L); |
|
|
// weekLqw.eq(EfcodeCpPlan::getIsUnion, 1L);
|
|
|
weekLqw.eq(EfcodeCpPlan::getIsDelete, 0L); |
|
|
// weekLqw.eq(EfcodeCpPlan::getIsDelete, 0L);
|
|
|
weekLqw.orderByAsc(EfcodeCpPlan::getPlanDate); |
|
|
// weekLqw.orderByAsc(EfcodeCpPlan::getPlanDate);
|
|
|
List<EfcodeCpPlan> samePlans = baseMapper.selectList(weekLqw); |
|
|
// List<EfcodeCpPlan> samePlans = baseMapper.selectList(weekLqw);
|
|
|
|
|
|
//
|
|
|
// 7. 按 bureau_dept_id 去重,每个单位取一条代表计划
|
|
|
// // 7. 按 bureau_dept_id 去重,每个单位取一条代表计划
|
|
|
List<EfcodeCpPlan> distinctUnitPlans = new ArrayList<>(); |
|
|
// List<EfcodeCpPlan> distinctUnitPlans = new ArrayList<>();
|
|
|
Set<String> seenBureauDeptIds = new HashSet<>(); |
|
|
// Set<String> seenBureauDeptIds = new HashSet<>();
|
|
|
for (EfcodeCpPlan sp : samePlans) { |
|
|
// for (EfcodeCpPlan sp : samePlans) {
|
|
|
String deptId = sp.getBureauDeptId(); |
|
|
// String deptId = sp.getBureauDeptId();
|
|
|
if (StringUtils.isNotBlank(deptId) && !seenBureauDeptIds.contains(deptId)) { |
|
|
// if (StringUtils.isNotBlank(deptId) && !seenBureauDeptIds.contains(deptId)) {
|
|
|
seenBureauDeptIds.add(deptId); |
|
|
// seenBureauDeptIds.add(deptId);
|
|
|
distinctUnitPlans.add(sp); |
|
|
// distinctUnitPlans.add(sp);
|
|
|
} |
|
|
// }
|
|
|
} |
|
|
// }
|
|
|
|
|
|
//
|
|
|
// 8. 只有1个单位的计划,无法联合,跳过
|
|
|
// // 8. 只有1个单位的计划,无法联合,跳过
|
|
|
if (distinctUnitPlans.size() <= 1) { |
|
|
// if (distinctUnitPlans.size() <= 1) {
|
|
|
log.debug("[CpPlan-V2] 企业[{}] 周[{}~{}]内只有1个单位的计划,跳过", enterpriseNumber, weekStartDate, weekEndDate); |
|
|
// log.debug("[CpPlan-V2] 企业[{}] 周[{}~{}]内只有1个单位的计划,跳过", enterpriseNumber, weekStartDate, weekEndDate);
|
|
|
continue; |
|
|
// continue;
|
|
|
} |
|
|
// }
|
|
|
|
|
|
//
|
|
|
// 9. 按最大联合单位数量分组
|
|
|
// // 9. 按最大联合单位数量分组
|
|
|
List<List<EfcodeCpPlan>> groups = new ArrayList<>(); |
|
|
// List<List<EfcodeCpPlan>> groups = new ArrayList<>();
|
|
|
for (int i = 0; i < distinctUnitPlans.size(); i += maxUnionUnit) { |
|
|
// for (int i = 0; i < distinctUnitPlans.size(); i += maxUnionUnit) {
|
|
|
int end = Math.min(i + maxUnionUnit, distinctUnitPlans.size()); |
|
|
// int end = Math.min(i + maxUnionUnit, distinctUnitPlans.size());
|
|
|
List<EfcodeCpPlan> group = distinctUnitPlans.subList(i, end); |
|
|
// List<EfcodeCpPlan> group = distinctUnitPlans.subList(i, end);
|
|
|
if (group.size() >= 2) { |
|
|
// if (group.size() >= 2) {
|
|
|
groups.add(new ArrayList<>(group)); |
|
|
// groups.add(new ArrayList<>(group));
|
|
|
} |
|
|
// }
|
|
|
} |
|
|
// }
|
|
|
|
|
|
//
|
|
|
if (groups.isEmpty()) { |
|
|
// if (groups.isEmpty()) {
|
|
|
continue; |
|
|
// continue;
|
|
|
} |
|
|
// }
|
|
|
|
|
|
//
|
|
|
// 10. 为每组生成预约记录
|
|
|
// // 10. 为每组生成预约记录
|
|
|
Set<String> matchedPlanIds = new HashSet<>(); |
|
|
// Set<String> matchedPlanIds = new HashSet<>();
|
|
|
for (List<EfcodeCpPlan> group : groups) { |
|
|
// for (List<EfcodeCpPlan> group : groups) {
|
|
|
String planGroupId = "Temp" + "_" + UUID.randomUUID().toString().replace("-", ""); |
|
|
// String planGroupId = "Temp" + "_" + UUID.randomUUID().toString().replace("-", "");
|
|
|
Date reserveTime = new Date(); |
|
|
// Date reserveTime = new Date();
|
|
|
List<EfcodeCpReserve> groupReserves = new ArrayList<>(); |
|
|
// List<EfcodeCpReserve> groupReserves = new ArrayList<>();
|
|
|
|
|
|
//
|
|
|
String unitNames = group.stream() |
|
|
// String unitNames = group.stream()
|
|
|
.map(EfcodeCpPlan::getBureauDeptName) |
|
|
// .map(EfcodeCpPlan::getBureauDeptName)
|
|
|
.filter(StringUtils::isNotBlank) |
|
|
// .filter(StringUtils::isNotBlank)
|
|
|
.collect(Collectors.joining(",")); |
|
|
// .collect(Collectors.joining(","));
|
|
|
String opMessage = "由于计划执法时间安排较近,系统推荐进行联合,参与单位为:" + unitNames + ".请确认."; |
|
|
// String opMessage = "由于计划执法时间安排较近,系统推荐进行联合,参与单位为:" + unitNames + ".请确认.";
|
|
|
|
|
|
//
|
|
|
for (EfcodeCpPlan matchedPlan : group) { |
|
|
// for (EfcodeCpPlan matchedPlan : group) {
|
|
|
EfcodeCpReserve reserve = new EfcodeCpReserve(); |
|
|
// EfcodeCpReserve reserve = new EfcodeCpReserve();
|
|
|
reserve.setPlanId(matchedPlan.getId()); |
|
|
// reserve.setPlanId(matchedPlan.getId());
|
|
|
reserve.setPlanGroupId(planGroupId); |
|
|
// reserve.setPlanGroupId(planGroupId);
|
|
|
reserve.setReserveTime(reserveTime); |
|
|
// reserve.setReserveTime(reserveTime);
|
|
|
reserve.setOpStatus(3L); // 待确认
|
|
|
// reserve.setOpStatus(3L); // 待确认
|
|
|
reserve.setOpOrder(0L); // 系统匹配默认为0
|
|
|
// reserve.setOpOrder(0L); // 系统匹配默认为0
|
|
|
reserve.setOpMessage(opMessage); |
|
|
// reserve.setOpMessage(opMessage);
|
|
|
reserve.setOpSetDate(matchedPlan.getPlanDate()); |
|
|
// reserve.setOpSetDate(matchedPlan.getPlanDate());
|
|
|
reserve.setOpSetTime(matchedPlan.getPlanTime()); |
|
|
// reserve.setOpSetTime(matchedPlan.getPlanTime());
|
|
|
reserve.setResFrom(1L); // 系统匹配
|
|
|
// reserve.setResFrom(1L); // 系统匹配
|
|
|
reserve.setSenderId("from_system"); |
|
|
// reserve.setSenderId("from_system");
|
|
|
reserve.setReceiverId(String.valueOf(matchedPlan.getCreateBy())); |
|
|
// reserve.setReceiverId(String.valueOf(matchedPlan.getCreateBy()));
|
|
|
|
|
|
//
|
|
|
if (insertReserve) { |
|
|
// if (insertReserve) {
|
|
|
efcodeCpReserveMapper.insert(reserve); |
|
|
// efcodeCpReserveMapper.insert(reserve);
|
|
|
} |
|
|
// }
|
|
|
groupReserves.add(reserve); |
|
|
// groupReserves.add(reserve);
|
|
|
} |
|
|
// }
|
|
|
|
|
|
//
|
|
|
// 更新被选中参与联合的计划: reserve_status=2(预约中), system_reserved=1
|
|
|
// // 更新被选中参与联合的计划: reserve_status=2(预约中), system_reserved=1
|
|
|
if (updatePlan) { |
|
|
// if (updatePlan) {
|
|
|
for (EfcodeCpPlan dp : group) { |
|
|
// for (EfcodeCpPlan dp : group) {
|
|
|
EfcodeCpPlan planUpdate = new EfcodeCpPlan(); |
|
|
// EfcodeCpPlan planUpdate = new EfcodeCpPlan();
|
|
|
planUpdate.setId(dp.getId()); |
|
|
// planUpdate.setId(dp.getId());
|
|
|
planUpdate.setReserveStatus(2L); |
|
|
// planUpdate.setReserveStatus(2L);
|
|
|
planUpdate.setSystemReserved(1L); |
|
|
// planUpdate.setSystemReserved(1L);
|
|
|
baseMapper.updateById(planUpdate); |
|
|
// baseMapper.updateById(planUpdate);
|
|
|
matchedPlanIds.add(dp.getId()); |
|
|
// matchedPlanIds.add(dp.getId());
|
|
|
} |
|
|
// }
|
|
|
} |
|
|
// }
|
|
|
|
|
|
//
|
|
|
resultMap.put(planGroupId, groupReserves); |
|
|
// resultMap.put(planGroupId, groupReserves);
|
|
|
matchedCount++; |
|
|
// matchedCount++;
|
|
|
log.info("[CpPlan-V2] 企业[{}] 周[{}~{}] 匹配成功,联合{}个单位,planGroupId={}", |
|
|
// log.info("[CpPlan-V2] 企业[{}] 周[{}~{}] 匹配成功,联合{}个单位,planGroupId={}",
|
|
|
enterpriseNumber, weekStartDate, weekEndDate, group.size(), planGroupId); |
|
|
// enterpriseNumber, weekStartDate, weekEndDate, group.size(), planGroupId);
|
|
|
} |
|
|
// }
|
|
|
|
|
|
//
|
|
|
// 11. 将已成功匹配的单位在该企业该周内的所有计划标记为 system_reserved=1,防止重复匹配
|
|
|
// // 11. 将已成功匹配的单位在该企业该周内的所有计划标记为 system_reserved=1,防止重复匹配
|
|
|
if (updatePlan && !groups.isEmpty()) { |
|
|
// if (updatePlan && !groups.isEmpty()) {
|
|
|
for (EfcodeCpPlan sp : samePlans) { |
|
|
// for (EfcodeCpPlan sp : samePlans) {
|
|
|
if (matchedPlanIds.contains(sp.getId())) { |
|
|
// if (matchedPlanIds.contains(sp.getId())) {
|
|
|
continue; |
|
|
// continue;
|
|
|
} |
|
|
// }
|
|
|
if (seenBureauDeptIds.contains(sp.getBureauDeptId())) { |
|
|
// if (seenBureauDeptIds.contains(sp.getBureauDeptId())) {
|
|
|
EfcodeCpPlan planUpdate = new EfcodeCpPlan(); |
|
|
// EfcodeCpPlan planUpdate = new EfcodeCpPlan();
|
|
|
planUpdate.setId(sp.getId()); |
|
|
// planUpdate.setId(sp.getId());
|
|
|
planUpdate.setSystemReserved(1L); |
|
|
// planUpdate.setSystemReserved(1L);
|
|
|
baseMapper.updateById(planUpdate); |
|
|
// baseMapper.updateById(planUpdate);
|
|
|
} |
|
|
// }
|
|
|
} |
|
|
// }
|
|
|
} |
|
|
// }
|
|
|
} |
|
|
// }
|
|
|
|
|
|
//
|
|
|
log.info("[CpPlan-V2] 计划自动匹配预约执行完毕,共匹配{}组联合预约", matchedCount); |
|
|
// log.info("[CpPlan-V2] 计划自动匹配预约执行完毕,共匹配{}组联合预约", matchedCount);
|
|
|
return resultMap; |
|
|
// return resultMap;
|
|
|
} |
|
|
// }
|
|
|
|
|
|
|
|
|
/** |
|
|
/** |
|
|
* 计划到期自动生成任务 |
|
|
* 计划到期自动生成任务 |
|
|
|