diff --git a/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/mq/consumer/SampleEntrustRegistrationAssayCompleteConsumer.java b/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/mq/consumer/SampleEntrustRegistrationAssayCompleteConsumer.java index 5413271a..04d64a04 100644 --- a/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/mq/consumer/SampleEntrustRegistrationAssayCompleteConsumer.java +++ b/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/mq/consumer/SampleEntrustRegistrationAssayCompleteConsumer.java @@ -1,7 +1,9 @@ package com.zt.plat.module.qms.mq.consumer; +import com.zt.plat.module.qms.resource.material.constant.MaterialConstants; import org.apache.rocketmq.spring.annotation.RocketMQMessageListener; import org.apache.rocketmq.spring.core.RocketMQListener; +import org.apache.rocketmq.spring.core.RocketMQTemplate; import org.springframework.stereotype.Component; import com.zt.plat.module.qms.business.bus.controller.vo.BusinessSampleEntrustRegistrationExtendRespVO; @@ -23,7 +25,8 @@ import lombok.extern.slf4j.Slf4j; consumerGroup = SampleEntrustRegistrationAssayCompleteMessage.TOPIC + "_CONSUMER" ) public class SampleEntrustRegistrationAssayCompleteConsumer implements RocketMQListener { - + @Resource + private RocketMQTemplate rocketMQTemplate; @Resource private BusinessSampleEntrustRegistrationMapper businessSampleEntrustRegistrationMapper; @@ -36,7 +39,8 @@ public class SampleEntrustRegistrationAssayCompleteConsumer implements RocketMQL switch (businessSampleEntrustRegistration.getConfigEntrustSourceKey()) { case QmsCommonConstant.ENTRUST_SOURCE_JYWT: //检验委托 - + // 物料验收 + rocketMQTemplate.syncSend(MaterialConstants.MQ_TOPIC_MATERIAL_ACCEPT_ASSAY_COMPLETE, message); break; case QmsCommonConstant.ENTRUST_SOURCE_XNT_TEMPORARY: //西南铜临时样 diff --git a/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/resource/material/constant/MaterialConstants.java b/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/resource/material/constant/MaterialConstants.java index 51757dba..cc2dbfcf 100644 --- a/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/resource/material/constant/MaterialConstants.java +++ b/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/resource/material/constant/MaterialConstants.java @@ -4,19 +4,39 @@ package com.zt.plat.module.qms.resource.material.constant; * 物料常量 */ public class MaterialConstants { - // 字典 + // ======================== 字典 public static final String DICT_MATERIAL_FLOW_TYPE = "jy_material_lifecycle_bsn_type"; public static final String DICT_MATERIAL_INBOUND_QUANTITY_LIMIT = "materialInboundQuantityLimit"; - // 序列号 + // ======================== 序列号 public static final String SEQUENCE_BATCH_KEY = "QMS_MATERIAL_BATCH_NO"; public static final String SEQUENCE_INF_KEY = "QMS_MATERIAL_INF_NO"; public static final String SEQUENCE_ASSAY_ACCEPT_SAMPLE_KEY = "QMS_MATERIAL_ASSAY_ACCEPT_SAMPLE"; - // 外部模块 + // ======================== 外部模块 public static final String DEVICE_BURETTE_CATEGORY_NAME = "滴定管"; - // 流程 - public static final String INIT_ASSAY_FLOW = "initAssayFlow"; + // ======================== 流程 public static final String ASSAY_FLAG = "assayFlag"; + /** + * 开始检验流程 + */ + public static final String INIT_ASSAY_FLOW = "initAssayFlow"; + /** + * 等待检验结果 + */ + public static final String WAIT_ASSAY_NODE_MARK = "waitAssay"; + /** + * 检验结果已全部报出 + */ + public static final String ASSAY_RESULT_ALL_OUTPUT = "assayResultAllOutput"; + /** + * 检验结果判定节点标记 + */ + public static final String ASSAY_RESULT_ASSESSMENT_NODE_MARK = "assayResultAssessment"; + // ======================== mq + /** + * 物料验收检验完成 + */ + public static final String MQ_TOPIC_MATERIAL_ACCEPT_ASSAY_COMPLETE = "MATERIAL_ACCEPT_ASSAY_COMPLETE"; } diff --git a/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/resource/material/controller/admin/MaterialLifecycleController.java b/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/resource/material/controller/admin/MaterialLifecycleController.java index f2e52e1a..28b11f02 100644 --- a/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/resource/material/controller/admin/MaterialLifecycleController.java +++ b/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/resource/material/controller/admin/MaterialLifecycleController.java @@ -64,9 +64,9 @@ public class MaterialLifecycleController extends AbstractFileUploadController im @PutMapping("/update") @Operation(summary = "更新物料流程") // @PreAuthorize("@ss.hasPermission('qms:material-lifecycle:update')") - public CommonResult updateMaterialLifecycle(@Validated(UpdateGroup.class) @RequestBody MaterialLifecycleSaveReqVO updateReqVO) { - materialLifecycleService.updateMaterialLifecycle(updateReqVO); - return success(true); + public CommonResult updateMaterialLifecycle(@Validated(UpdateGroup.class) @RequestBody MaterialLifecycleSaveReqVO updateReqVO) { + MaterialLifecycleDO lifecycleDO = materialLifecycleService.updateMaterialLifecycle(updateReqVO); + return success(BeanUtils.toBean(lifecycleDO, MaterialLifecycleRespVO.class)); } @DeleteMapping("/delete") @@ -126,10 +126,11 @@ public class MaterialLifecycleController extends AbstractFileUploadController im return success(materialLifecycleService.inventoryCheckInfomation(inventoryReqVO)); } - @GetMapping("/test") + @PutMapping("/manual-execute-flow") + @Operation(summary = "手动执行流程,主要用于测试") @Parameter(name = "flowId", description = "流程id", required = true) public void test(@RequestParam("flowId") String flowId) { - materialAssayResultListener.bpmTest(flowId); + materialAssayResultListener.approveTask(flowId); } @GetMapping("/export-excel") diff --git a/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/resource/material/controller/vo/MaterialCorrelationAssayRespVO.java b/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/resource/material/controller/vo/MaterialCorrelationAssayRespVO.java index 539ad194..8466eae2 100644 --- a/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/resource/material/controller/vo/MaterialCorrelationAssayRespVO.java +++ b/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/resource/material/controller/vo/MaterialCorrelationAssayRespVO.java @@ -7,13 +7,16 @@ import cn.hutool.json.JSONUtil; import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; import com.alibaba.excel.annotation.ExcelProperty; import com.zt.plat.module.qms.core.aspect.annotation.Dict; +import com.zt.plat.module.qms.resource.material.controller.vo.assist.MaterialAssayResult; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import lombok.extern.slf4j.Slf4j; import java.time.LocalDateTime; import java.util.List; import java.util.Objects; +@Slf4j @Schema(description = "管理后台 - 物料检化验关联信息 Response VO") @Data @ExcelIgnoreUnannotated @@ -76,7 +79,7 @@ public class MaterialCorrelationAssayRespVO { @Schema(description = "结果,检化验结果") @ExcelProperty("结果,检化验结果") - private String result; + private MaterialAssayResult result; @Schema(description = "是否合格,字典") @ExcelProperty("是否合格,字典") diff --git a/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/resource/material/controller/vo/MaterialLifecycleSaveReqVO.java b/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/resource/material/controller/vo/MaterialLifecycleSaveReqVO.java index 17bcfa1a..4854dade 100644 --- a/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/resource/material/controller/vo/MaterialLifecycleSaveReqVO.java +++ b/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/resource/material/controller/vo/MaterialLifecycleSaveReqVO.java @@ -80,4 +80,7 @@ public class MaterialLifecycleSaveReqVO { @Schema(description = "明细列表") private List detailList; + @Schema(description = "删除的文件id") + private List deleteFileIdList; + } \ No newline at end of file diff --git a/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/resource/material/controller/vo/assist/MaterialAssayResult.java b/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/resource/material/controller/vo/assist/MaterialAssayResult.java new file mode 100644 index 00000000..5e4908ef --- /dev/null +++ b/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/resource/material/controller/vo/assist/MaterialAssayResult.java @@ -0,0 +1,16 @@ +package com.zt.plat.module.qms.resource.material.controller.vo.assist; + +import com.zt.plat.module.qms.business.bus.controller.vo.SampleProjectResultDetailRespVO; +import com.zt.plat.module.qms.business.bus.controller.vo.SampleProjectResultRespVO; +import lombok.Data; + +import java.util.List; + +@Data +public class MaterialAssayResult extends SampleProjectResultRespVO { + + /** + * 结果明细 + */ + private List detailList; +} diff --git a/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/resource/material/dal/dataobject/MaterialCorrelationAssayDO.java b/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/resource/material/dal/dataobject/MaterialCorrelationAssayDO.java index 01d37045..96d0344c 100644 --- a/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/resource/material/dal/dataobject/MaterialCorrelationAssayDO.java +++ b/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/resource/material/dal/dataobject/MaterialCorrelationAssayDO.java @@ -1,7 +1,9 @@ package com.zt.plat.module.qms.resource.material.dal.dataobject; import com.baomidou.mybatisplus.annotation.*; +import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler; import com.zt.plat.framework.mybatis.core.dataobject.BusinessBaseDO; +import com.zt.plat.module.qms.resource.material.controller.vo.assist.MaterialAssayResult; import lombok.*; /** * 物料检化验关联信息 DO @@ -86,8 +88,8 @@ public class MaterialCorrelationAssayDO extends BusinessBaseDO { /** * 结果,检化验结果 */ - @TableField("RSLT") - private String result; + @TableField(value = "RSLT", typeHandler = JacksonTypeHandler.class) + private MaterialAssayResult result; /** * 是否合格,字典 */ diff --git a/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/resource/material/dal/mapper/MaterialInfomationMapper.java b/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/resource/material/dal/mapper/MaterialInfomationMapper.java index 40fe1b37..16696cc6 100644 --- a/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/resource/material/dal/mapper/MaterialInfomationMapper.java +++ b/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/resource/material/dal/mapper/MaterialInfomationMapper.java @@ -98,6 +98,7 @@ public interface MaterialInfomationMapper extends BaseMapperX { -//public class MaterialAssayResultListener { +public class MaterialAssayResultListener implements RocketMQListener { @Autowired private BpmTaskApi bpmTaskApi; @@ -54,15 +60,33 @@ public class MaterialAssayResultListener implements RocketMQListener { private MaterialLifecycleDetailService materialLifecycleDetailService; @Autowired private MaterialLifecycleService materialLifecycleService; + @Autowired + private SampleResultQueryService sampleResultQueryService; + @Override - public void onMessage(Object message) { - MaterialCorrelationAssayDO assay = BeanUtils.toBean(message, MaterialCorrelationAssayDO.class); - if (assay == null || assay.getEntrustId() == null) return; - assay = materialCorrelationAssayService.getByEntrustId(assay.getEntrustId()); + public void onMessage(SampleEntrustRegistrationAssayCompleteMessage message) { + log.info("物料验收检验委托完成[消息内容({})]", message); + if (message == null || message.getBusinessSampleEntrustRegistrationId() == null) return; + Long entrustId = message.getBusinessSampleEntrustRegistrationId(); + MaterialCorrelationAssayDO assay = materialCorrelationAssayService.getByEntrustId(message.getBusinessSampleEntrustRegistrationId()); if (assay == null) return; + // 检化验结果 + PageResult assayResultPage = sampleResultQueryService.sampleProjectResultQuery( + new SampleProjectResultPageReqVO().setBusinessSampleEntrustRegistrationId(entrustId)); + List asyResults = assayResultPage.getList(); + if (CollUtil.isEmpty(asyResults)) return; + // 结果 + SampleProjectResultRespVO oriAsyResult = asyResults.get(0); + MaterialAssayResult assayResult = BeanUtils.toBean(oriAsyResult, MaterialAssayResult.class); + // 结果明细 + SampleProjectResultDetailReqVO detailReqVO = new SampleProjectResultDetailReqVO() + .setBusinessSubParentSampleId(oriAsyResult.getBusinessSubParentSampleId()) + .setConfigAssayMethodProjectId(oriAsyResult.getConfigAssayMethodProjectId()); + List asyResultDetail = sampleResultQueryService.sampleProjectResultDetailQuery(detailReqVO); + assayResult.setDetailList(asyResultDetail); + assay.setResult(assayResult); assay.setAssayStatus(QmsCommonConstant.COMPLETED); - // TODO 检化验结果 materialCorrelationAssayService.updateById(assay); List detailsByAsyId = materialLifecycleDetailService.getDetailListByAsyId(assay.getId()); if (CollUtil.isEmpty(detailsByAsyId)) return; @@ -79,47 +103,57 @@ public class MaterialAssayResultListener implements RocketMQListener { } // 获取到流程id String flowId = lifecycle.getFlowInstanceId(); + this.approveTask(flowId); } - public void bpmTest(String flowId) { - log.info("收到检化验结果回调:"); + + public void approveTask(String flowId) { + // 获取当前节点 CommonResult> taskListRes = bpmTaskApi.getTaskListByProcessInstanceId(flowId); List taskList = taskListRes.getData(); if (CollUtil.isEmpty(taskList)) return; - List curTasks = taskList.stream().filter(task -> task.getStatus() != null && task.getStatus() == 1).toList(); - if (CollUtil.isEmpty(curTasks)) return; - // 当前任务 - BpmTaskRespDTO curTask = curTasks.get(0); - log.info("MaterialAssayResultListener - 当前任务:{}", curTask); - // 检查是否为检化验节点 + // List curTasks = taskList.stream().filter(task -> task.getStatus() != null && task.getStatus() == 1).toList(); + BpmTaskRespDTO curTask = taskList.get(taskList.size() - 1); + log.info("当前任务:{}", curTask); + // 检查是否为等待检化验结果节点 + CommonResult bpmnModelView = bpmProcessInstanceApi.getProcessInstanceBpmnModelView(flowId); + BpmProcessInstanceBpmnModelViewRespDTO modelView = bpmnModelView.getData(); + if (modelView == null || modelView.getBpmnXml() == null) { + log.error("流程【{}】BPMN模型为空", flowId); + return; + } + log.debug("流程【{}】BPMN XML: {}", flowId, modelView.getBpmnXml()); + // 解析 BPMN XML,提取节点扩展字段 + Map> nodeFieldExtensions = BpmnXmlUtil.parseBpmnFieldExtensions(modelView.getBpmnXml()); + log.debug("流程【{}】节点扩展字段:{}", flowId, nodeFieldExtensions); + // 获取当前节点的扩展字段 + String currentTaskKey = curTask.getTaskDefinitionKey(); + Map currentFields = nodeFieldExtensions.get(currentTaskKey); + log.info("流程【{}】当前节点 {} 的扩展字段:{}", flowId, currentTaskKey, currentFields); + // 判断当前节点是否为检化验等待节点 + boolean isCurrentNodeWaitAssay = currentFields != null && "1".equals(currentFields.get(MaterialConstants.WAIT_ASSAY_NODE_MARK)); + if (!isCurrentNodeWaitAssay) log.error("流程【{}】当前节点 {} 不是等待检化验结果节点,可能存在未知异常", flowId, currentTaskKey); + // 提交当前节点 + log.info("流程【{}】的检化验已全部完成,等待检验结果节点自动执行", flowId); // 保存当前登录用户 LoginUser originalLoginUser = SecurityFrameworkUtils.getLoginUser(); - log.info("已保存登录用户上下文: user={}", originalLoginUser); - // 临时切换为任务审批人 + log.debug("已保存登录用户上下文: user={}", originalLoginUser); HttpServletRequest request = WebFrameworkUtils.getRequest(); try { + // 当前用户临时切换为任务审批人 Long assigneeUserId = curTask.getAssignee(); LoginUser loginUser = new LoginUser().setId(assigneeUserId) + .setInfo(new HashMap<>()) .setExpiresTime(LocalDateTime.now().plusMinutes(10)); SecurityFrameworkUtils.setLoginUser(loginUser, request); - // 获取这个流程 - CommonResult processInstanceRes = bpmProcessInstanceApi.getProcessInstance(flowId); - BpmProcessInstanceRespDTO instance = processInstanceRes.getData(); - log.info("流程实例:{}", instance); - // 获取下一个流程节点 2008359763063820290L 2038786007172124673L - CommonResult> nextApprovalNodes = - bpmProcessInstanceApi.getNextApprovalNodes(curTask.getAssignee(), - new BpmApprovalDetailReqDTO().setProcessDefinitionId(instance.getProcessDefinitionId()) - .setProcessInstanceId(instance.getId()) - .setTaskId(curTask.getId())); - log.info("下一个流程节点:{}", nextApprovalNodes.getData()); - if (true) return; - List nextNodes = nextApprovalNodes.getData(); - BpmTaskApproveReqDTO reqDTO = new BpmTaskApproveReqDTO().setId(curTask.getId()).setReason("已全部出检化验结果"); + log.debug("当前用户临时切换为任务审批人: user={}", loginUser); + BpmTaskApproveReqDTO reqDTO = new BpmTaskApproveReqDTO().setId(curTask.getId()) + .setReason("检化验已全部完成,节点自动提交") + .setVariables(Map.of(MaterialConstants.ASSAY_RESULT_ALL_OUTPUT, 1)); CommonResult result = bpmProcessInstanceApi.approveTask(reqDTO); if (!result.isSuccess()) { - log.error("检化验完成执行失败:{}", result.getMsg()); + log.error("流程【{}】【{}】节点执行失败:{}", flowId, curTask.getName(), result.getMsg()); } else { - log.info("检化验完成执行成功!"); + log.info("流程【{}】【{}】节点执行成功!", flowId, curTask.getName()); } } finally { if (originalLoginUser != null) { @@ -127,7 +161,7 @@ public class MaterialAssayResultListener implements RocketMQListener { } else { SecurityContextHolder.clearContext(); } - log.info("已恢复登录用户上下文: user={}", SecurityFrameworkUtils.getLoginUser()); + log.debug("已恢复登录用户上下文: user={}", SecurityFrameworkUtils.getLoginUser()); } } diff --git a/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/resource/material/service/MaterialLifecycleService.java b/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/resource/material/service/MaterialLifecycleService.java index 9a13cf24..abe21163 100644 --- a/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/resource/material/service/MaterialLifecycleService.java +++ b/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/resource/material/service/MaterialLifecycleService.java @@ -28,7 +28,7 @@ public interface MaterialLifecycleService { * * @param updateReqVO 更新信息 */ - void updateMaterialLifecycle(@Valid MaterialLifecycleSaveReqVO updateReqVO); + MaterialLifecycleDO updateMaterialLifecycle(@Valid MaterialLifecycleSaveReqVO updateReqVO); /** * 删除物料通用流程,物料验收、退换货 diff --git a/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/resource/material/service/MaterialLifecycleServiceImpl.java b/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/resource/material/service/MaterialLifecycleServiceImpl.java index b95e476b..e6dd2f5c 100644 --- a/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/resource/material/service/MaterialLifecycleServiceImpl.java +++ b/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/resource/material/service/MaterialLifecycleServiceImpl.java @@ -39,6 +39,7 @@ import com.zt.plat.module.qms.resource.material.controller.vo.*; import com.zt.plat.module.qms.resource.material.dal.dataobject.*; import com.zt.plat.module.qms.resource.material.dal.mapper.MaterialLifecycleMapper; import com.zt.plat.module.qms.resource.material.enums.*; +import com.zt.plat.module.qms.resource.material.utils.BpmnXmlUtil; import com.zt.plat.module.system.api.dept.DeptApi; import com.zt.plat.module.system.api.dept.dto.DeptRespDTO; import com.zt.plat.module.system.api.user.AdminUserApi; @@ -285,7 +286,7 @@ public class MaterialLifecycleServiceImpl implements MaterialLifecycleService , @Transactional @Override - public void updateMaterialLifecycle(MaterialLifecycleSaveReqVO updateReqVO) { + public MaterialLifecycleDO updateMaterialLifecycle(MaterialLifecycleSaveReqVO updateReqVO) { Long reqId = updateReqVO.getId(); MaterialLifecycleDO lifecycleDO = materialLifecycleMapper.selectById(reqId); if (lifecycleDO == null) throw exception(MATERIAL_LIFECYCLE_NOT_EXISTS); @@ -303,12 +304,12 @@ public class MaterialLifecycleServiceImpl implements MaterialLifecycleService , materialLifecycleMapper.updateById(mtrlLfc); List checkItemDOS = getCheckItemDOS(checkItems, mtrlLfc); materialInventoryCheckItemService.saveBatch(checkItemDOS); - return; + return mtrlLfc; } List detailList = updateReqVO.getDetailList(); if (CollUtil.isEmpty(detailList)) { materialLifecycleMapper.updateById(mtrlLfc); - return; + return mtrlLfc; } List oriDetailList = materialLifecycleDetailService.getDetailListByLfcId(reqId); @@ -332,7 +333,9 @@ public class MaterialLifecycleServiceImpl implements MaterialLifecycleService , if (flowType == MaterialFlowType.acceptance) { this.saveAssays(detailDOS, detailList); } + businessFileService.deleteBusinessFileList(updateReqVO.getDeleteFileIdList()); materialLifecycleMapper.updateById(mtrlLfc); + return mtrlLfc; } private void saveAssays(List detailDOS, List detailList) { @@ -1013,12 +1016,15 @@ public class MaterialLifecycleServiceImpl implements MaterialLifecycleService , try{ dataKeyCheckService.create(checkKey, this.getClass().getName()); } catch (Exception e){ + log.error("checkKey 创建失败:key={}", checkKey, e); log.error("checkKey 重复:key={}", checkKey); return CommonResult.success(new JSONObject()); } // 流程状态处理 1-提交(含退回) 3-拒绝 4-取消流程 String PROCESS_STATUS = variables.getString(QmsBpmConstant.PROCESS_INSTANCE_VARIABLE_STATUS); Integer assayFlag = variables.getInteger(MaterialConstants.ASSAY_FLAG); + Integer assayResultAllOutput = variables.getInteger(MaterialConstants.ASSAY_RESULT_ALL_OUTPUT); + log.info("assayResultAllOutput:{}", assayResultAllOutput); String businessKey = reqDTO.getBusinessKey(); JSONArray fieldExtensions = new JSONArray(); if(variables.containsKey(QmsBpmConstant.BPM_FIELD_EXTENSIONS)){ @@ -1030,7 +1036,7 @@ public class MaterialLifecycleServiceImpl implements MaterialLifecycleService , boolean lastActivityFlag = false; boolean firstActivityFlag = false; // 是否为需要发起检化验流程的节点 - boolean needInitAssayFlow = false; + boolean initAssayFlow = false; if(!fieldExtensions.isEmpty()){ for(int i = 0; i < fieldExtensions.size(); i++){ JSONObject fieldExtension = fieldExtensions.getJSONObject(i); @@ -1041,11 +1047,54 @@ public class MaterialLifecycleServiceImpl implements MaterialLifecycleService , firstActivityFlag = true; } if(fieldExtension.getString("fieldName").equalsIgnoreCase(MaterialConstants.INIT_ASSAY_FLOW)){ - needInitAssayFlow = true; + initAssayFlow = true; } } } MaterialFlowType flowType = MaterialFlowType.fromName(entity.getBusinessType()); + // 下一节点是检化验判定节点时,设置业务流程变量值 + if (MaterialFlowType.acceptance == flowType) { + CommonResult> taskListRes = bpmTaskApi.getTaskListByProcessInstanceId(processInsId); + List taskList = taskListRes.getData(); + if (CollUtil.isEmpty(taskList)) throw new ServiceException(1_032_160_000, "流程任务不存在"); + // List curTasks = taskList.stream().filter(task -> task.getStatus() != null && task.getStatus() == 1).toList(); + BpmTaskRespDTO curTask = taskList.get(taskList.size() - 1); + BpmApprovalDetailReqDTO approvalDetailReqDTO = new BpmApprovalDetailReqDTO() + .setProcessDefinitionId(processInsId) + .setProcessInstanceId(processInsId) + .setTaskId(curTask.getId()); + CommonResult> nextApprovalNodes = + bpmProcessInstanceApi.getNextApprovalNodes(curTask.getAssignee(), approvalDetailReqDTO); + List nextNodes = nextApprovalNodes.getData(); + log.info("流程【{}】下一个流程节点:{}", processInsId, nextNodes); + // 判断下一节点是否为检化验判定节点 + CommonResult bpmnModelView = bpmProcessInstanceApi.getProcessInstanceBpmnModelView(processInsId); + BpmProcessInstanceBpmnModelViewRespDTO modelView = bpmnModelView.getData(); + if (modelView == null || modelView.getBpmnXml() == null) + throw new ServiceException(1_032_160_000, "流程模型不存在"); + // 解析 BPMN XML,提取节点扩展字段 + Map> nodeFieldExtensions = BpmnXmlUtil.parseBpmnFieldExtensions(modelView.getBpmnXml()); + log.info("节点扩展字段:{}", nodeFieldExtensions); + boolean isNextNodeAssayAssessment = false; + if (CollUtil.isNotEmpty(nextNodes)) { + for (BpmApprovalDetailRespDTO.ActivityNode node : nextNodes) { + Map nextNodeFields = nodeFieldExtensions.get(node.getId()); + log.info("下一节点 {} 的扩展字段:{}", node.getId(), nextNodeFields); + if (nextNodeFields != null && "1".equals(nextNodeFields.get(MaterialConstants.ASSAY_RESULT_ASSESSMENT_NODE_MARK))) { + isNextNodeAssayAssessment = true; + break; + } + } + } + if(isNextNodeAssayAssessment + && assayFlag != null && assayFlag == 1 + && assayResultAllOutput != null && assayResultAllOutput == 1) { + // 当下一个节点为检化验判定节点,且当前流程为待检化验结果,则设置流程变量值为1 + entity.setAssayResultAssessment(1); + } else { + entity.setAssayResultAssessment(0); + } + } // 根据流程状态处理业务数据 if(("1").equals(returnFlag)){ // 驳回。流程需要配置退回到发起节点 @@ -1064,6 +1113,11 @@ public class MaterialLifecycleServiceImpl implements MaterialLifecycleService , if(firstActivityFlag) // 驳回后重新提交 entity.setFlowStatus(QmsCommonConstant.IN_PROGRESS); + + if(initAssayFlow && assayFlag != null && assayFlag == 1) { + // 走到检化验节点时需要发起检化验流程 + this.initAssayByLfcId(entity.getId()); + } if(lastActivityFlag) { // 结束审批 entity.setFlowStatus(QmsCommonConstant.COMPLETED); @@ -1083,10 +1137,6 @@ public class MaterialLifecycleServiceImpl implements MaterialLifecycleService , this.inventoryCheckPassHandle(entity.getId()); } } - // 走到检化验节点时需要发起检化验流程 - if(needInitAssayFlow && assayFlag != null && assayFlag == 1) { - this.initAssayByLfcId(entity.getId()); - } } materialLifecycleMapper.updateById(entity); diff --git a/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/resource/material/utils/BpmnXmlUtil.java b/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/resource/material/utils/BpmnXmlUtil.java new file mode 100644 index 00000000..2fa279e3 --- /dev/null +++ b/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/resource/material/utils/BpmnXmlUtil.java @@ -0,0 +1,96 @@ +package com.zt.plat.module.qms.resource.material.utils; + +import lombok.extern.slf4j.Slf4j; +import org.dom4j.Document; +import org.dom4j.DocumentHelper; +import org.dom4j.Element; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Slf4j +public class BpmnXmlUtil { + + /** + * 解析 BPMN XML 中的节点扩展字段 + * + * @param bpmnXml BPMN XML 字符串 + * @return Map<节点 ID, Map<字段名,字段值>> + */ + public static Map> parseBpmnFieldExtensions(String bpmnXml) { + Map> nodeFieldMap = new HashMap<>(); + + try { + Document document = DocumentHelper.parseText(bpmnXml); + Element root = document.getRootElement(); + + // 查找所有的 userTask 节点 + List userTasks = findElementsByName(root, "userTask"); + for (Element userTask : userTasks) { + String taskId = userTask.attributeValue("id"); + Map fieldMap = new HashMap<>(); + + // 查找所有 executionListener 下的 field + List executionListeners = findElementsByName(userTask, "executionListener"); + for (Element listener : executionListeners) { + List fields = listener.elements("field"); + for (Element field : fields) { + String fieldName = field.attributeValue("name"); + String fieldValue = extractFieldValue(field); + if (fieldValue != null) { + fieldMap.put(fieldName, fieldValue); + } + } + } + + if (!fieldMap.isEmpty()) { + nodeFieldMap.put(taskId, fieldMap); + } + } + } catch (Exception e) { + log.error("解析 BPMN XML 失败:{}", e.getMessage()); + } + + return nodeFieldMap; + } + + /** + * 递归查找指定名称的元素 + * + */ + private static List findElementsByName(Element root, String elementName) { + List result = new ArrayList<>(); + findElementsRecursive(root, elementName, result); + return result; + } + + private static void findElementsRecursive(Element element, String elementName, List result) { + if (element.getName().equals(elementName)) { + result.add(element); + } + for (Element child : element.elements()) { + findElementsRecursive(child, elementName, result); + } + } + + /** + * 提取 field 的值,支持 string 和 expression 两种类型 + */ + private static String extractFieldValue(Element field) { + // 尝试获取 string 类型的值 + Element stringElement = field.element("string"); + if (stringElement != null) { + return stringElement.getTextTrim(); + } + + // 尝试获取 expression 类型的值 + Element expressionElement = field.element("expression"); + if (expressionElement != null) { + return expressionElement.getTextTrim(); + } + + return null; + } +}