Browse Source

执法端-计划

dev-V1.0.1
庄锐波 3 months ago
parent
commit
2087d3a68d
  1. 8
      zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/service/IEfcodeCpNoticeService.java
  2. 9
      zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/service/IEfcodeCpPlanService.java
  3. 29
      zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/service/impl/EfcodeCpNoticeServiceImpl.java
  4. 157
      zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/service/impl/EfcodeCpPlanServiceImpl.java
  5. 4
      zdxt-web-client/zdxt-efcode-enforcement-app/src/views/enforcement/my/plan/cp_plan_mine.vue

8
zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/service/IEfcodeCpNoticeService.java

@ -85,4 +85,12 @@ public interface IEfcodeCpNoticeService {
* 删除预告仅草稿可删除
*/
String deleteNotice(Collection<String> ids);
/**
* 预告到期自动标记已执行
* <p>enforce_date 23:59:59 < 当前时间 status=1(已发布) 的预告状态更新为 3=已执行</p>
*
* @return 处理的记录数
*/
int markExpiredNoticesAsExecuted();
}

9
zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/service/IEfcodeCpPlanService.java

@ -103,4 +103,13 @@ public interface IEfcodeCpPlanService {
* @return planGroupId 分组的预约记录列表
*/
Map<String, List<EfcodeCpReserve>> autoMatchReserveV2(boolean forceMatch, boolean updatePlan, boolean insertReserve);
/**
* 计划到期自动生成任务
* <p>距计划执行日期 <= CP_SETTING_MANUAL_MATCH_DAYS 天时
* 系统自动取消剩余未处理的预约含系统匹配与手动预约并为计划生成任务</p>
*
* @return 处理的计划数量
*/
int processPlanDeadlineAutoGenTask();
}

29
zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/service/impl/EfcodeCpNoticeServiceImpl.java

@ -275,4 +275,33 @@ public class EfcodeCpNoticeServiceImpl implements IEfcodeCpNoticeService {
}
return baseMapper.deleteByIds(ids) > 0;
}
/**
* 预告到期自动标记已执行
* <p> enforce_date 23:59:59 < 当前时间 status=1(已发布) 的预告状态更新为 3=已执行</p>
*/
@Override
public int markExpiredNoticesAsExecuted() {
// 查找已发布(status=1)且执法日期已过期的预告
LambdaQueryWrapper<EfcodeCpNotice> lqw = Wrappers.lambdaQuery();
lqw.eq(EfcodeCpNotice::getStatus, 1L);
lqw.eq(EfcodeCpNotice::getIsDelete, 0L);
lqw.apply("CONCAT(enforce_date, ' 23:59:59') < NOW()");
List<EfcodeCpNotice> expiredList = baseMapper.selectList(lqw);
if (expiredList.isEmpty()) {
return 0;
}
// 批量更新状态为 3=已执行
for (EfcodeCpNotice notice : expiredList) {
EfcodeCpNotice update = new EfcodeCpNotice();
update.setId(notice.getId());
update.setStatus(3L);
baseMapper.updateById(update);
}
log.info("[markExpiredNoticesAsExecuted] 共标记{}条预告为已执行", expiredList.size());
return expiredList.size();
}
}

157
zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/service/impl/EfcodeCpPlanServiceImpl.java

@ -26,6 +26,7 @@ import java.time.temporal.ChronoUnit;
import java.time.DayOfWeek;
import java.time.temporal.TemporalAdjusters;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
@ -1107,4 +1108,160 @@ public class EfcodeCpPlanServiceImpl implements IEfcodeCpPlanService {
log.info("[CpPlan-V2] 计划自动匹配预约执行完毕,共匹配{}组联合预约", matchedCount);
return resultMap;
}
/**
* 计划到期自动生成任务
* <p>距计划执行日期 <= CP_SETTING_MANUAL_MATCH_DAYS 天时
* 系统自动取消剩余未处理的预约含系统匹配与手动预约并为计划生成任务</p>
* <ul>
* <li>部分联合有已同意的预约取消剩余待确认预约已同意的计划共享生成任务</li>
* <li>完全没有联合记录直接为计划生成任务</li>
* <li>全部待确认无人同意取消全部待确认预约为每个计划各自生成任务</li>
* </ul>
*/
@Transactional(rollbackFor = Exception.class)
@Override
public int processPlanDeadlineAutoGenTask() {
int manualMatchDays = cpSettingService.getManualMatchDays();
LocalDate today = LocalDate.now();
LocalDate deadlineDate = today.plusDays(manualMatchDays);
// 1. 查找即将到期的计划:plan_date <= today + manualMatchDays,且未生成任务
LambdaQueryWrapper<EfcodeCpPlan> lqw = Wrappers.lambdaQuery();
lqw.le(EfcodeCpPlan::getPlanDate, java.sql.Date.valueOf(deadlineDate));
lqw.ge(EfcodeCpPlan::getPlanDate, java.sql.Date.valueOf(today));
lqw.eq(EfcodeCpPlan::getIsDelete, 0L);
lqw.and(w -> w.isNull(EfcodeCpPlan::getTaskId).or().eq(EfcodeCpPlan::getTaskId, ""));
lqw.in(EfcodeCpPlan::getReserveStatus, Arrays.asList(1L, 2L, 4L, 5L, 6L));
List<EfcodeCpPlan> plans = baseMapper.selectList(lqw);
if (plans.isEmpty()) {
log.info("[processPlanDeadlineAutoGenTask] 无即将到期的计划需要处理");
return 0;
}
log.info("[processPlanDeadlineAutoGenTask] 找到{}条即将到期的计划(截止日期={})", plans.size(), deadlineDate);
// 2. 查找这些计划的预约记录
List<String> planIds = plans.stream().map(EfcodeCpPlan::getId).collect(Collectors.toList());
List<EfcodeCpReserve> reserves = efcodeCpReserveMapper.selectList(
Wrappers.<EfcodeCpReserve>lambdaQuery().in(EfcodeCpReserve::getPlanId, planIds)
);
// 建立 planId → reserves 映射
Map<String, List<EfcodeCpReserve>> planReserveMap = reserves.stream()
.collect(Collectors.groupingBy(EfcodeCpReserve::getPlanId));
// 记录已处理的 plan_group_id,避免重复处理同一分组
Set<String> processedGroups = new HashSet<>();
int processedCount = 0;
for (EfcodeCpPlan plan : plans) {
// 跳过已经在分组处理中被赋予了 taskId 的计划
if (StringUtils.isNotBlank(plan.getTaskId())) {
continue;
}
List<EfcodeCpReserve> planReserves = planReserveMap.get(plan.getId());
if (planReserves == null || planReserves.isEmpty()) {
// Case B: 完全没有联合记录 → 直接生成任务
log.info("[processPlanDeadlineAutoGenTask] 计划[{}]无联合记录,直接生成任务, 企业={}",
plan.getId(), plan.getEnterpriseName());
cpTaskService.forceGenerateTask(plan);
processedCount++;
} else {
// Case A: 有联合记录 → 按 plan_group_id 处理
for (EfcodeCpReserve reserve : planReserves) {
String groupId = reserve.getPlanGroupId();
if (StringUtils.isBlank(groupId) || processedGroups.contains(groupId)) {
continue;
}
processedGroups.add(groupId);
processedCount += processDeadlineGroup(groupId);
}
}
}
log.info("[processPlanDeadlineAutoGenTask] 处理完毕,共处理{}条计划", processedCount);
return processedCount;
}
/**
* 处理一个预约分组的截止逻辑
* 1. 取消所有待确认(opStatus=3)的预约 设为超期取消(4)
* 2. 为已同意(opStatus=1)的计划生成共享任务
* 3. 为被取消的计划各自生成独立任务
*
* @param groupId 预约分组ID
* @return 处理的计划数量
*/
private int processDeadlineGroup(String groupId) {
// 查询分组内所有预约记录
List<EfcodeCpReserve> groupReserves = efcodeCpReserveMapper.selectList(
Wrappers.<EfcodeCpReserve>lambdaQuery().eq(EfcodeCpReserve::getPlanGroupId, groupId)
);
if (groupReserves.isEmpty()) {
return 0;
}
// 1. 取消所有待确认的预约 (opStatus=3 → 4)
List<EfcodeCpReserve> pendingReserves = groupReserves.stream()
.filter(r -> Long.valueOf(3L).equals(r.getOpStatus()))
.collect(Collectors.toList());
for (EfcodeCpReserve pending : pendingReserves) {
EfcodeCpReserve update = new EfcodeCpReserve();
update.setId(pending.getId());
update.setOpStatus(4L); // 超期取消
update.setOpTime(new Date());
efcodeCpReserveMapper.updateById(update);
log.info("[processDeadlineGroup] 取消待确认预约: reserveId={}, planId={}, groupId={}",
pending.getId(), pending.getPlanId(), groupId);
}
// 2. 找出已同意的预约 (opStatus=1)
List<EfcodeCpReserve> approvedReserves = groupReserves.stream()
.filter(r -> Long.valueOf(1L).equals(r.getOpStatus()))
.collect(Collectors.toList());
int processedCount = 0;
if (!approvedReserves.isEmpty()) {
// 有部分或全部同意 → 为同意的计划生成共享任务
String sharedTaskId = null;
for (EfcodeCpReserve approved : approvedReserves) {
EfcodeCpPlan approvedPlan = baseMapper.selectById(approved.getPlanId());
if (approvedPlan == null || StringUtils.isNotBlank(approvedPlan.getTaskId())) {
continue;
}
if (sharedTaskId == null) {
sharedTaskId = cpTaskService.forceGenerateTask(approvedPlan);
log.info("[processDeadlineGroup] 已同意计划[{}]生成共享任务taskId={}",
approvedPlan.getId(), sharedTaskId);
} else {
EfcodeCpPlan planUpdate = new EfcodeCpPlan();
planUpdate.setId(approvedPlan.getId());
planUpdate.setTaskId(sharedTaskId);
planUpdate.setReserveStatus(3L);
baseMapper.updateById(planUpdate);
log.info("[processDeadlineGroup] 已同意计划[{}]加入共享任务taskId={}",
approvedPlan.getId(), sharedTaskId);
}
processedCount++;
}
}
// 3. 为被取消的计划各自生成独立任务
for (EfcodeCpReserve pending : pendingReserves) {
EfcodeCpPlan pendingPlan = baseMapper.selectById(pending.getPlanId());
if (pendingPlan == null || StringUtils.isNotBlank(pendingPlan.getTaskId())) {
continue;
}
cpTaskService.forceGenerateTask(pendingPlan);
log.info("[processDeadlineGroup] 被取消计划[{}]生成独立任务, 企业={}",
pendingPlan.getId(), pendingPlan.getEnterpriseName());
processedCount++;
}
return processedCount;
}
}

4
zdxt-web-client/zdxt-efcode-enforcement-app/src/views/enforcement/my/plan/cp_plan_mine.vue

@ -216,9 +216,9 @@ const emit = defineEmits(['edit']);
const filterStatus = ref(null);
const filterOptions = [
{ label: '全部', value: null },
{ label: '待预约', value: '1,4,5' },
{ label: '待预约', value: '1,4,5,6' },
{ label: '预约中', value: '2' },
{ label: '预约完成', value: '3,6,7' },
{ label: '预约完成', value: '3,7' },
];
const onFilterChange = (val) => {

Loading…
Cancel
Save