diff --git a/zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/controller/externalInterface/LongGangInterfaceController.java b/zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/controller/externalInterface/LongGangInterfaceController.java index 3a4fb397..d721403c 100644 --- a/zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/controller/externalInterface/LongGangInterfaceController.java +++ b/zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/controller/externalInterface/LongGangInterfaceController.java @@ -23,11 +23,14 @@ import org.dromara.common.log.annotation.Log; import org.dromara.common.log.enums.BusinessType; import org.dromara.system.domain.vo.SysDeptVo; import org.dromara.system.service.ISysDeptService; +import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import java.util.ArrayList; import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; @Slf4j @SaIgnore @@ -244,6 +247,7 @@ public class LongGangInterfaceController { */ @SaIgnore @RepeatSubmit() + @Transactional(rollbackFor = Exception.class) @Log(title = "外部接口-绑定计划", businessType = BusinessType.OTHER) @PostMapping("/plan/bindPlan") public R bindPlan( @@ -261,34 +265,24 @@ public class LongGangInterfaceController { return R.fail("新计划流水号不能为空"); } - // ========== 3. 批量查询绑定列表中的计划,校验是否均存在 ========== + // ========== 3. 逐个查询绑定计划(outSerialNo + channelNo 唯一确定一条计划) ========== List bindOutSerialNos = bo.getBindOutSerialNos(); List missingSerialNos = new ArrayList<>(); + List boundPlans = new ArrayList<>(); + List oldTaskIds = new ArrayList<>(); for (String serialNo : bindOutSerialNos) { - EfcodeCpPlanBo queryBo = new EfcodeCpPlanBo(); - queryBo.setOutSerialNo(serialNo); - queryBo.setChannelNo(channelNo); - List found = outEfcodeCpPlanService.queryList(queryBo); - if (found.isEmpty()) { + EfcodeCpPlanVo plan = outEfcodeCpPlanService.queryByOutSerialNoAndChannelNo(serialNo, channelNo); + if (plan == null) { missingSerialNos.add(serialNo); + } else { + boundPlans.add(plan); + oldTaskIds.add(plan.getTaskId()); } } if (!missingSerialNos.isEmpty()) { return R.fail("以下计划流水号不存在: " + String.join(", ", missingSerialNos)); } - // ========== 4. 查询绑定计划,取第一条的执法单位信息 ========== - List boundPlans = new ArrayList<>(); - for (String serialNo : bindOutSerialNos) { - EfcodeCpPlanBo q = new EfcodeCpPlanBo(); - q.setOutSerialNo(serialNo); - q.setChannelNo(channelNo); - boundPlans.addAll(outEfcodeCpPlanService.queryList(q)); - } - if (boundPlans.isEmpty()) { - return R.fail("绑定计划不存在"); - } - // ========== 5. 直接生成新任务(基于企业信息 + 绑定计划的执法单位) ========== EfcodeCpTaskBo taskBo = new EfcodeCpTaskBo(); taskBo.setTaskName(bo.getEnterpriseName() + " - 执法检查任务"); @@ -298,14 +292,21 @@ public class LongGangInterfaceController { outEfcodeCpTaskService.insertByBo(taskBo); String taskId = taskBo.getId(); - // ========== 6. 将新任务ID回写到所有绑定的计划 ========== - EfcodeCpPlanBo taskUpdateBo = new EfcodeCpPlanBo(); - taskUpdateBo.setTaskId(taskId); - taskUpdateBo.setIsUnion(1L); - taskUpdateBo.setReserveStatus(3L); - for (EfcodeCpPlanVo boundPlan : boundPlans) { - taskUpdateBo.setId(boundPlan.getId()); - outEfcodeCpPlanService.updateByBo(taskUpdateBo); + // ========== 7. 将新任务ID批量回写到所有绑定的计划(轻量级更新,不触发 checkDuplicate/syncPlanUsers) ========== + List boundPlanIds = boundPlans.stream() + .map(EfcodeCpPlanVo::getId) + .collect(Collectors.toList()); + outEfcodeCpPlanService.updateTaskBinding(boundPlanIds, taskId, 1L, 3L); + + // ========== 8. 检查旧任务是否还有其他计划关联,若无则删除 ========== + for (String oldTaskId : oldTaskIds) { + EfcodeCpPlanBo checkQuery = new EfcodeCpPlanBo(); + checkQuery.setTaskId(oldTaskId); + List remainingPlans = outEfcodeCpPlanService.queryList(checkQuery); + if (remainingPlans.isEmpty()) { + outEfcodeCpTaskService.deleteWithValidByIds(List.of(oldTaskId), false); + log.info("[外部接口] 绑定计划-旧任务无其他计划关联,已删除, oldTaskId={}", oldTaskId); + } } log.info("[外部接口] 绑定计划, appKey={}, channelNo={}, outSerialNo={}, taskId={}, bindCount={}, enterprise={}", diff --git a/zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/service/IOutEfcodeCpPlanService.java b/zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/service/IOutEfcodeCpPlanService.java index 51d0a0f1..2d6bd9cc 100644 --- a/zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/service/IOutEfcodeCpPlanService.java +++ b/zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/service/IOutEfcodeCpPlanService.java @@ -44,6 +44,15 @@ public interface IOutEfcodeCpPlanService { */ List queryList(EfcodeCpPlanBo bo); + /** + * 根据外部流水号 + 渠道编号查询唯一计划 + * + * @param outSerialNo 外部流水号 + * @param channelNo 渠道编号 + * @return 计划实体,不存在返回 null + */ + EfcodeCpPlanVo queryByOutSerialNoAndChannelNo(String outSerialNo, String channelNo); + /** * 新增行政执法检查计划-计划 * @@ -68,6 +77,18 @@ public interface IOutEfcodeCpPlanService { */ Boolean updateByBo(EfcodeCpPlanBo bo); + /** + * 轻量级任务绑定更新:仅更新 taskId、isUnion、reserveStatus 字段 + *

不触发 checkDuplicate 和 syncPlanUsers,适用于外部接口绑定计划场景

+ * + * @param planId 计划ID + * @param taskId 新任务ID + * @param isUnion 是否联合执法 + * @param reserveStatus 预约状态 + * @return 是否更新成功 + */ + Boolean updateTaskBinding(List planIds, String taskId, Long isUnion, Long reserveStatus); + /** * 分页查询其他计划列表(本单位公开+不公开计划 + 其他单位公开计划,仅待预约状态) * diff --git a/zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/service/impl/OutEfcodeCpPlanServiceImpl.java b/zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/service/impl/OutEfcodeCpPlanServiceImpl.java index 78a66ff4..218892f5 100644 --- a/zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/service/impl/OutEfcodeCpPlanServiceImpl.java +++ b/zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/service/impl/OutEfcodeCpPlanServiceImpl.java @@ -1,6 +1,7 @@ package com.zdxt.enforcementcode.service.impl; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.zdxt.enforcementcode.common.commonenum.ChannelNoEnums; @@ -1403,4 +1404,29 @@ public class OutEfcodeCpPlanServiceImpl implements IOutEfcodeCpPlanService { log.info("[updateIsUnion] 执行完成:共取消{}条联合执法计划", cancelledCount); return cancelledCount; } + + + @Override + public Boolean updateTaskBinding(List planIds, String taskId, Long isUnion, Long reserveStatus) { + if (planIds == null || planIds.isEmpty()) { + return false; + } + LambdaUpdateWrapper wrapper = Wrappers.lambdaUpdate(); + wrapper.in(EfcodeCpPlan::getId, planIds) + .set(EfcodeCpPlan::getTaskId, taskId) + .set(EfcodeCpPlan::getIsUnion, isUnion) + .set(EfcodeCpPlan::getReserveStatus, reserveStatus); + return baseMapper.update(null, wrapper) > 0; + } + + + @Override + public EfcodeCpPlanVo queryByOutSerialNoAndChannelNo(String outSerialNo, String channelNo) { + LambdaQueryWrapper lqw = Wrappers.lambdaQuery(); + lqw.eq(EfcodeCpPlan::getOutSerialNo, outSerialNo) + .eq(EfcodeCpPlan::getChannelNo, channelNo) + .last("LIMIT 1"); + return baseMapper.selectVoOne(lqw); + } + }