package jnpf.limsService.impl; import jnpf.audit.sdk.annotation.AuditLog; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import jnpf.base.UserInfo; import jnpf.exception.DataException; import jnpf.limsEntity.BizStatus; import jnpf.limsEntity.LimsQingyandanEntity; import jnpf.limsEntity.LimsSxtQuyangJihuaEntity; import jnpf.limsEntity.LimsSxtQuyangJihuaZhongzhiEntity; import jnpf.limsEntity.LimsSxtQuyangZhongzhiShenqingEntity; import jnpf.limsEntity.LimsSxtQuyangZhongzhiShenqingZixiangEntity; import jnpf.limsMapper.LimsSxtQuyangJihuaMapper; import jnpf.limsMapper.LimsSxtQuyangJihuaZhongzhiMapper; import jnpf.limsMapper.LimsSxtQuyangZhongzhiShenqingMapper; import jnpf.limsMapper.LimsSxtQuyangZhongzhiShenqingZixiangMapper; import jnpf.limsMapper.LimsQingyandanMapper; import jnpf.limsService.LimsQingyandanService; import jnpf.limsService.LimsSxtJihuaService; import jnpf.limsService.LimsSxtQuyangJihuaRenwuService; import jnpf.limsService.event.LimsSxtPlanApprovedEvent; import jnpf.limsService.support.LimsSxtFlowStatusResolver; import jnpf.limsService.support.LimsSxtPlanStatusResolver; import jnpf.util.UserProvider; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationEventPublisher; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.StringUtils; import java.time.LocalDate; import java.util.List; import java.util.Objects; /** * 水系统取样计划定时任务,结构照搬 LimsJianceTaskRemindServiceImpl。 * *

注意:@Scheduled 是进程内定时器,多实例部署会每个实例各触发一次(重复发)。 * 当前按单实例部署,无此问题;若将来横向扩容,需在 cronTrigger 入口加分布式锁 * (如 Redis SETNX 当天 key)保证单点执行。 */ @Slf4j @Service public class LimsSxtJihuaServiceImpl implements LimsSxtJihuaService { private static final Integer FLOW_STATE_APPROVED = 2; private final ApplicationEventPublisher eventPublisher; @Autowired public LimsSxtJihuaServiceImpl(ApplicationEventPublisher eventPublisher) { this.eventPublisher = eventPublisher; } @Autowired private LimsSxtQuyangJihuaMapper jihuaMapper; @Autowired private LimsSxtQuyangJihuaZhongzhiMapper zhongzhiMapper; @Autowired private LimsSxtQuyangZhongzhiShenqingMapper quyangZhongzhiShenqingMapper; @Autowired private LimsSxtQuyangZhongzhiShenqingZixiangMapper quyangZhongzhiShenqingZixiangMapper; @Autowired private LimsQingyandanMapper qingyandanMapper; @Autowired private LimsQingyandanService qingyandanService; @Autowired private LimsSxtRenwuQingyandanZhuangtaiTongbuService renwuQingyandanZhuangtaiTongbuService; @Autowired private LimsSxtQuyangJihuaRenwuService renwuService; @Override public void runTodayJihua(boolean dryRun) { shengchengDangriQingyandan(LocalDate.now(), dryRun); } @Override @AuditLog(action = "PLAN_RUN", label = "执行水系统当天计划", bizType = "SXT", bizCodeExpr = "#dryRun ? '' : 'SXT_PLAN_RUN'", targetTable = "lims_sxt_quyang_jihua_renwu") public void runDailyJihua(LocalDate date, boolean dryRun) { shengchengDangriQingyandan(date, dryRun); } @Override @AuditLog(action = "PLAN_RUN", label = "执行指定水系统计划", bizType = "SXT", bizCodeExpr = "#jihuaId", bizCodeRequired = false, targetTable = "lims_sxt_quyang_jihua") public void runJihua(String jihuaId) { UserInfo user = UserProvider.getUser(); String tenantId = user == null || !StringUtils.hasText(user.getTenantId()) ? "0" : user.getTenantId(); int generated = renwuService.shengchengDaishengchengQingyandanByJihua(jihuaId, tenantId, LocalDate.now()); log.info("水系统:手动执行计划 {},生成 {} 张请验单", jihuaId, generated); } private void shengchengDangriQingyandan(LocalDate date, boolean dryRun) { if (dryRun) { log.info("水系统:dry run 跳过 {} 的待办任务生成", date); return; } int generated = renwuService.shengchengDaishengchengQingyandan(date); log.info("水系统:执行 {} 的待办任务,生成 {} 张请验单,dryRun={}", date, generated, dryRun); } @Override public void createJihuaQuyangDan(LimsQingyandanEntity qingyandan) { qingyandanService.sxtAutoSubmit(qingyandan); } @Override public List chaxunDaiquyangQingyandan(String jianyanLiushuihao, String quyangDidian) { UserInfo user = UserProvider.getUser(); String tenantId = user == null || !StringUtils.hasText(user.getTenantId()) ? "0" : user.getTenantId(); LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); wrapper.eq(LimsQingyandanEntity::getTenantId, tenantId) .eq(LimsQingyandanEntity::getBizType, "SXT") .eq(LimsQingyandanEntity::getQuyangStatus, BizStatus.PENDING_FETCH.getCode()) .and(item -> item.isNull(LimsQingyandanEntity::getDeleteMark) .or().ne(LimsQingyandanEntity::getDeleteMark, 1)); if (StringUtils.hasText(jianyanLiushuihao)) { wrapper.like(LimsQingyandanEntity::getJianyanLiushuihao, jianyanLiushuihao.trim()); } if (StringUtils.hasText(quyangDidian)) { wrapper.like(LimsQingyandanEntity::getQuyangDidian, quyangDidian.trim()); } wrapper.orderByAsc(LimsQingyandanEntity::getCreatorTime) .orderByAsc(LimsQingyandanEntity::getId); return qingyandanMapper.selectList(wrapper); } @Override @Transactional(rollbackFor = Exception.class) @AuditLog(action = "FLOW_START", label = "水系统计划流程发起", bizType = "SXT", bizCodeExpr = "#flowId", bizCodeRequired = false, targetTable = "lims_sxt_quyang_jihua") public void syncFlowStarted(String flowId, String taskId) { validateFlowKey(flowId, taskId); LimsSxtQuyangJihuaEntity jihua = findJihuaByFlow(flowId, taskId); LimsSxtQuyangJihuaZhongzhiEntity zhongzhi = findZhongzhiByFlow(flowId, taskId); LimsSxtQuyangZhongzhiShenqingEntity quyangZhongzhiShenqing = findQuyangZhongzhiShenqingByFlow(flowId, taskId); ensureSingleBusiness(jihua, zhongzhi, quyangZhongzhiShenqing, flowId, taskId); if (jihua != null) { syncJihuaStarted(jihua, flowId, taskId); } else if (zhongzhi != null) { syncZhongzhiStarted(zhongzhi, flowId, taskId); } else { syncQuyangZhongzhiShenqingStarted(quyangZhongzhiShenqing); } } @Override @Transactional(rollbackFor = Exception.class) @AuditLog(action = "FLOW_END", label = "水系统计划流程结束", bizType = "SXT", bizCodeExpr = "#flowId", bizCodeRequired = false, targetTable = "lims_sxt_quyang_jihua") public void syncFlowEnded(String flowId, String taskId, Integer flowState) { syncFlowEndedStatus(flowId, taskId, flowState); } private void syncFlowEndedStatus(String flowId, String taskId, Integer flowState) { validateFlowKey(flowId, taskId); String targetStatus = LimsSxtFlowStatusResolver.resolveBizStatus(flowState) .orElseThrow(() -> new DataException("未知的工作流状态:" + flowState)); if (!LimsSxtFlowStatusResolver.COMPLETED.equals(targetStatus)) { throw new DataException("流程尚未结束,当前状态:" + flowState); } LimsSxtQuyangJihuaEntity jihua = findJihuaByFlow(flowId, taskId); LimsSxtQuyangJihuaZhongzhiEntity zhongzhi = findZhongzhiByFlow(flowId, taskId); LimsSxtQuyangZhongzhiShenqingEntity quyangZhongzhiShenqing = findQuyangZhongzhiShenqingByFlow(flowId, taskId); ensureSingleBusiness(jihua, zhongzhi, quyangZhongzhiShenqing, flowId, taskId); if (jihua != null) { syncJihuaEnded(jihua, flowId, taskId, flowState, targetStatus); } else if (zhongzhi != null) { syncZhongzhiEnded(zhongzhi, flowId, taskId, flowState, targetStatus); } else { syncQuyangZhongzhiShenqingEnded(quyangZhongzhiShenqing, flowState, targetStatus); } } private void syncJihuaStarted(LimsSxtQuyangJihuaEntity jihua, String flowId, String taskId) { if (LimsSxtFlowStatusResolver.COMPLETED.equals(jihua.getBizStatus())) { return; } boolean changed = !Objects.equals(jihua.getBizStatus(), LimsSxtFlowStatusResolver.PROCESSING) || !Objects.equals(jihua.getPlanStatus(), LimsSxtPlanStatusResolver.DISABLED); if (!changed) { return; } if (!markJihuaStarted(jihua.getId())) { return; } } private void syncZhongzhiStarted(LimsSxtQuyangJihuaZhongzhiEntity zhongzhi, String flowId, String taskId) { if (LimsSxtFlowStatusResolver.COMPLETED.equals(zhongzhi.getBizStatus())) { return; } if (!Objects.equals(zhongzhi.getBizStatus(), LimsSxtFlowStatusResolver.PROCESSING)) { if (!markZhongzhiStarted(zhongzhi.getId())) { return; } } markApprovedJihuaTerminating(zhongzhi, flowId, taskId); } private void syncJihuaEnded(LimsSxtQuyangJihuaEntity jihua, String flowId, String taskId, Integer flowState, String targetStatus) { boolean passed = LimsSxtFlowStatusResolver.isApproved(flowState); String targetPlanStatus = passed ? LimsSxtPlanStatusResolver.AVAILABLE : LimsSxtPlanStatusResolver.DISABLED; boolean changed = !Objects.equals(jihua.getBizStatus(), targetStatus) || !Objects.equals(jihua.getPlanStatus(), targetPlanStatus); if (changed) { updateJihua(jihua.getId(), targetStatus, targetPlanStatus); } if (passed) { eventPublisher.publishEvent(new LimsSxtPlanApprovedEvent(jihua.getId(), jihua.getFTenantId())); } } private void syncZhongzhiEnded(LimsSxtQuyangJihuaZhongzhiEntity zhongzhi, String flowId, String taskId, Integer flowState, String targetStatus) { if (!Objects.equals(zhongzhi.getBizStatus(), targetStatus)) { updateZhongzhi(zhongzhi.getId(), targetStatus); } syncApprovedJihuaTerminationStatus(zhongzhi, flowId, taskId, flowState); } private void syncQuyangZhongzhiShenqingStarted(LimsSxtQuyangZhongzhiShenqingEntity shenqing) { if (LimsSxtFlowStatusResolver.COMPLETED.equals(shenqing.getBizStatus()) || Objects.equals(shenqing.getBizStatus(), LimsSxtFlowStatusResolver.PROCESSING)) { return; } if (!markQuyangZhongzhiShenqingStarted(shenqing)) { return; } } private void syncQuyangZhongzhiShenqingEnded(LimsSxtQuyangZhongzhiShenqingEntity shenqing, Integer flowState, String targetStatus) { if (!Objects.equals(shenqing.getBizStatus(), targetStatus)) { updateQuyangZhongzhiShenqing(shenqing, targetStatus); } if (LimsSxtFlowStatusResolver.isApproved(flowState)) { syncApprovedQuyangTerminationStatus(shenqing); } } private void syncApprovedQuyangTerminationStatus(LimsSxtQuyangZhongzhiShenqingEntity shenqing) { List children = listActiveQuyangZhongzhiChildren( shenqing.getId(), shenqing.getFTenantId()); int updated = 0; for (LimsSxtQuyangZhongzhiShenqingZixiangEntity child : children) { if (!StringUtils.hasText(child.getQingyandanId())) { log.warn("取样终止申请子表未关联请验单,childId={}", child.getId()); continue; } if (terminatePendingQingyandan(child)) { updated++; } } log.info("取样终止申请审批通过,同步终止 {} 张待取样请验单,terminationId={}", updated, shenqing.getId()); } private void markApprovedJihuaTerminating(LimsSxtQuyangJihuaZhongzhiEntity zhongzhi, String flowId, String taskId) { if (!StringUtils.hasText(zhongzhi.getJihuaMingcheng())) { log.warn("计划终止申请已发起但未关联原取样计划,terminationId={}", zhongzhi.getId()); return; } LimsSxtQuyangJihuaEntity jihua = findApprovedJihua(zhongzhi.getJihuaMingcheng(), zhongzhi.getFTenantId()); if (jihua == null) { log.warn("计划终止申请已发起,但原取样计划不是已审批通过状态,terminationId={}, jihuaId={}", zhongzhi.getId(), zhongzhi.getJihuaMingcheng()); return; } if (!Objects.equals(jihua.getPlanStatus(), LimsSxtPlanStatusResolver.AVAILABLE)) { return; } if (!updateJihuaPlanStatus(jihua.getId(), jihua.getPlanStatus(), LimsSxtPlanStatusResolver.TERMINATING)) { return; } } private void syncApprovedJihuaTerminationStatus(LimsSxtQuyangJihuaZhongzhiEntity zhongzhi, String flowId, String taskId, Integer flowState) { if (!StringUtils.hasText(zhongzhi.getJihuaMingcheng())) { log.warn("计划终止申请已办结但未关联原取样计划,terminationId={}", zhongzhi.getId()); return; } LimsSxtQuyangJihuaEntity jihua = findApprovedJihua(zhongzhi.getJihuaMingcheng(), zhongzhi.getFTenantId()); if (jihua == null) { log.warn("计划终止申请已办结,但原取样计划不是已审批通过状态,terminationId={}, jihuaId={}", zhongzhi.getId(), zhongzhi.getJihuaMingcheng()); return; } String targetPlanStatus = LimsSxtPlanStatusResolver.resolveTerminationStatus(jihua.getPlanStatus(), flowState); if (Objects.equals(jihua.getPlanStatus(), targetPlanStatus)) { return; } if (!updateJihuaPlanStatus(jihua.getId(), jihua.getPlanStatus(), targetPlanStatus)) { return; } boolean passed = LimsSxtFlowStatusResolver.isApproved(flowState); if (passed && LimsSxtPlanStatusResolver.TERMINATED.equals(targetPlanStatus)) { renwuService.quxiaoWeishengchengRenwuByJihua( jihua.getId(), jihua.getFTenantId(), "plan_terminated"); } } private void updateJihua(String id, String bizStatus, String planStatus) { LambdaUpdateWrapper wrapper = new LambdaUpdateWrapper<>(); wrapper.eq(LimsSxtQuyangJihuaEntity::getId, id) .and(item -> item.isNull(LimsSxtQuyangJihuaEntity::getFDeleteMark) .or().ne(LimsSxtQuyangJihuaEntity::getFDeleteMark, 1)) .set(LimsSxtQuyangJihuaEntity::getBizStatus, bizStatus) .set(LimsSxtQuyangJihuaEntity::getPlanStatus, planStatus); if (jihuaMapper.update(null, wrapper) != 1) { throw new DataException("更新取样计划状态失败"); } } private boolean updateJihuaPlanStatus(String id, String currentPlanStatus, String targetPlanStatus) { LambdaUpdateWrapper wrapper = new LambdaUpdateWrapper<>(); wrapper.eq(LimsSxtQuyangJihuaEntity::getId, id) .and(item -> item.isNull(LimsSxtQuyangJihuaEntity::getFDeleteMark) .or().ne(LimsSxtQuyangJihuaEntity::getFDeleteMark, 1)) .eq(LimsSxtQuyangJihuaEntity::getPlanStatus, currentPlanStatus) .set(LimsSxtQuyangJihuaEntity::getPlanStatus, targetPlanStatus); return jihuaMapper.update(null, wrapper) == 1; } /** * 起始事件只能把未办结记录推进到在办,避免延迟/重放事件覆盖结束事件的最终结果。 */ private boolean markJihuaStarted(String id) { LambdaUpdateWrapper wrapper = new LambdaUpdateWrapper<>(); wrapper.eq(LimsSxtQuyangJihuaEntity::getId, id) .and(item -> item.isNull(LimsSxtQuyangJihuaEntity::getFDeleteMark) .or().ne(LimsSxtQuyangJihuaEntity::getFDeleteMark, 1)) .and(item -> item.isNull(LimsSxtQuyangJihuaEntity::getBizStatus) .or().ne(LimsSxtQuyangJihuaEntity::getBizStatus, LimsSxtFlowStatusResolver.COMPLETED)) .set(LimsSxtQuyangJihuaEntity::getBizStatus, LimsSxtFlowStatusResolver.PROCESSING) .set(LimsSxtQuyangJihuaEntity::getPlanStatus, LimsSxtPlanStatusResolver.DISABLED); return jihuaMapper.update(null, wrapper) > 0; } private void updateZhongzhi(String id, String bizStatus) { LambdaUpdateWrapper wrapper = new LambdaUpdateWrapper<>(); wrapper.eq(LimsSxtQuyangJihuaZhongzhiEntity::getId, id) .set(LimsSxtQuyangJihuaZhongzhiEntity::getBizStatus, bizStatus); if (zhongzhiMapper.update(null, wrapper) != 1) { throw new DataException("更新计划终止申请状态失败"); } } private boolean markZhongzhiStarted(String id) { LambdaUpdateWrapper wrapper = new LambdaUpdateWrapper<>(); wrapper.eq(LimsSxtQuyangJihuaZhongzhiEntity::getId, id) .and(item -> item.isNull(LimsSxtQuyangJihuaZhongzhiEntity::getBizStatus) .or().ne(LimsSxtQuyangJihuaZhongzhiEntity::getBizStatus, LimsSxtFlowStatusResolver.COMPLETED)) .set(LimsSxtQuyangJihuaZhongzhiEntity::getBizStatus, LimsSxtFlowStatusResolver.PROCESSING); return zhongzhiMapper.update(null, wrapper) > 0; } private void updateQuyangZhongzhiShenqing(LimsSxtQuyangZhongzhiShenqingEntity shenqing, String bizStatus) { LambdaUpdateWrapper wrapper = new LambdaUpdateWrapper<>(); wrapper.eq(LimsSxtQuyangZhongzhiShenqingEntity::getId, shenqing.getId()) .eq(LimsSxtQuyangZhongzhiShenqingEntity::getFTenantId, shenqing.getFTenantId()) .and(item -> item.isNull(LimsSxtQuyangZhongzhiShenqingEntity::getFDeleteMark) .or().ne(LimsSxtQuyangZhongzhiShenqingEntity::getFDeleteMark, 1)) .set(LimsSxtQuyangZhongzhiShenqingEntity::getBizStatus, bizStatus); if (quyangZhongzhiShenqingMapper.update(null, wrapper) != 1) { throw new DataException("更新取样终止申请状态失败"); } } private boolean markQuyangZhongzhiShenqingStarted(LimsSxtQuyangZhongzhiShenqingEntity shenqing) { LambdaUpdateWrapper wrapper = new LambdaUpdateWrapper<>(); wrapper.eq(LimsSxtQuyangZhongzhiShenqingEntity::getId, shenqing.getId()) .eq(LimsSxtQuyangZhongzhiShenqingEntity::getFTenantId, shenqing.getFTenantId()) .and(item -> item.isNull(LimsSxtQuyangZhongzhiShenqingEntity::getFDeleteMark) .or().ne(LimsSxtQuyangZhongzhiShenqingEntity::getFDeleteMark, 1)) .and(item -> item.isNull(LimsSxtQuyangZhongzhiShenqingEntity::getBizStatus) .or().ne(LimsSxtQuyangZhongzhiShenqingEntity::getBizStatus, LimsSxtFlowStatusResolver.COMPLETED)) .set(LimsSxtQuyangZhongzhiShenqingEntity::getBizStatus, LimsSxtFlowStatusResolver.PROCESSING); return quyangZhongzhiShenqingMapper.update(null, wrapper) > 0; } private List listActiveQuyangZhongzhiChildren(String shenqingId, String tenantId) { LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); wrapper.eq(LimsSxtQuyangZhongzhiShenqingZixiangEntity::getFForeignId, shenqingId) .eq(LimsSxtQuyangZhongzhiShenqingZixiangEntity::getFTenantId, tenantId) .and(item -> item.isNull(LimsSxtQuyangZhongzhiShenqingZixiangEntity::getFDeleteMark) .or().ne(LimsSxtQuyangZhongzhiShenqingZixiangEntity::getFDeleteMark, 1)); return quyangZhongzhiShenqingZixiangMapper.selectList(wrapper); } private boolean terminatePendingQingyandan(LimsSxtQuyangZhongzhiShenqingZixiangEntity child) { LimsQingyandanEntity qingyandan = qingyandanMapper.selectById(child.getQingyandanId()); if (qingyandan == null) { return false; } LambdaUpdateWrapper wrapper = new LambdaUpdateWrapper<>(); wrapper.eq(LimsQingyandanEntity::getId, child.getQingyandanId()) .eq(LimsQingyandanEntity::getTenantId, child.getFTenantId()) .eq(LimsQingyandanEntity::getBizType, "SXT") .eq(LimsQingyandanEntity::getQuyangStatus, BizStatus.PENDING_FETCH.getCode()) .and(item -> item.isNull(LimsQingyandanEntity::getDeleteMark) .or().ne(LimsQingyandanEntity::getDeleteMark, 1)) .set(LimsQingyandanEntity::getQuyangStatus, BizStatus.DELETED.getCode()); if (qingyandanMapper.update(null, wrapper) != 1) { return false; } qingyandan.setQuyangStatus(BizStatus.DELETED.getCode()); renwuQingyandanZhuangtaiTongbuService.tongbu(qingyandan, "quyang_zhongzhi_tongguo"); return true; } private LimsSxtQuyangJihuaEntity findJihuaByFlow(String flowId, String taskId) { LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); wrapper.eq(LimsSxtQuyangJihuaEntity::getFFlowId, flowId) .eq(LimsSxtQuyangJihuaEntity::getFFlowTaskId, taskId) .and(item -> item.isNull(LimsSxtQuyangJihuaEntity::getFDeleteMark) .or().ne(LimsSxtQuyangJihuaEntity::getFDeleteMark, 1)); List list = jihuaMapper.selectList(wrapper); if (list.size() > 1) { throw new DataException("多个取样计划关联同一流程任务:task_id=" + taskId); } return list.isEmpty() ? null : list.get(0); } private LimsSxtQuyangJihuaZhongzhiEntity findZhongzhiByFlow(String flowId, String taskId) { LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); wrapper.eq(LimsSxtQuyangJihuaZhongzhiEntity::getFFlowId, flowId) .eq(LimsSxtQuyangJihuaZhongzhiEntity::getFFlowTaskId, taskId); List list = zhongzhiMapper.selectList(wrapper); if (list.size() > 1) { throw new DataException("多个计划终止申请关联同一流程任务:task_id=" + taskId); } return list.isEmpty() ? null : list.get(0); } private LimsSxtQuyangZhongzhiShenqingEntity findQuyangZhongzhiShenqingByFlow(String flowId, String taskId) { LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); wrapper.eq(LimsSxtQuyangZhongzhiShenqingEntity::getFFlowId, flowId) .eq(LimsSxtQuyangZhongzhiShenqingEntity::getFFlowTaskId, taskId) .and(item -> item.isNull(LimsSxtQuyangZhongzhiShenqingEntity::getFDeleteMark) .or().ne(LimsSxtQuyangZhongzhiShenqingEntity::getFDeleteMark, 1)); List list = quyangZhongzhiShenqingMapper.selectList(wrapper); if (list.size() > 1) { throw new DataException("多个取样终止申请关联同一流程任务:task_id=" + taskId); } return list.isEmpty() ? null : list.get(0); } private LimsSxtQuyangJihuaEntity findApprovedJihua(String jihuaId, String tenantId) { LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); wrapper.eq(LimsSxtQuyangJihuaEntity::getId, jihuaId) .eq(LimsSxtQuyangJihuaEntity::getFFlowState, FLOW_STATE_APPROVED) .and(item -> item.isNull(LimsSxtQuyangJihuaEntity::getFDeleteMark) .or().ne(LimsSxtQuyangJihuaEntity::getFDeleteMark, 1)); if (StringUtils.hasText(tenantId)) { wrapper.eq(LimsSxtQuyangJihuaEntity::getFTenantId, tenantId); } List list = jihuaMapper.selectList(wrapper); if (list.size() > 1) { throw new DataException("多个已审批取样计划使用相同主键:jihuaId=" + jihuaId); } return list.isEmpty() ? null : list.get(0); } private void ensureSingleBusiness(LimsSxtQuyangJihuaEntity jihua, LimsSxtQuyangJihuaZhongzhiEntity zhongzhi, LimsSxtQuyangZhongzhiShenqingEntity quyangZhongzhiShenqing, String flowId, String taskId) { int businessCount = (jihua == null ? 0 : 1) + (zhongzhi == null ? 0 : 1) + (quyangZhongzhiShenqing == null ? 0 : 1); if (businessCount == 0) { throw new DataException("未找到流程关联的取样计划、计划终止申请或取样终止申请:flow_id=" + flowId + ", task_id=" + taskId); } if (businessCount > 1) { throw new DataException("流程任务关联了多个水系统业务记录:task_id=" + taskId); } } private void validateFlowKey(String flowId, String taskId) { if (!StringUtils.hasText(flowId)) { throw new DataException("流程id(flow_id)不能为空"); } if (!StringUtils.hasText(taskId)) { throw new DataException("流程任务id(task_id)不能为空"); } } }