diff --git a/src/main/java/com/xdap/self_development/controller/BenchmarkingReportController.java b/src/main/java/com/xdap/self_development/controller/BenchmarkingReportController.java index 53940d6..e410be7 100644 --- a/src/main/java/com/xdap/self_development/controller/BenchmarkingReportController.java +++ b/src/main/java/com/xdap/self_development/controller/BenchmarkingReportController.java @@ -5,7 +5,7 @@ import com.definesys.mpaas.query.db.PageQueryResult; import com.xdap.self_development.controller.form.*; import com.xdap.self_development.exception.CommonException; import com.xdap.self_development.pojo.BenchmarkingReport; -import com.xdap.self_development.pojo.view.ApprovalFlowView; +import com.xdap.self_development.pojo.view.ApprovalFlowNodeView; import com.xdap.self_development.pojo.view.TodoAndReportView; import com.xdap.self_development.service.BenchmarkingReportService; import org.springframework.validation.BindingResult; @@ -138,7 +138,7 @@ public class BenchmarkingReportController { public Response getReportProcess( @NotBlank String flowId ) { - ApprovalFlowView approvalFlowView = benchmarkingReportService.getReportProcess(flowId); + ApprovalFlowNodeView approvalFlowView = benchmarkingReportService.getReportProcess(flowId); return Response.ok().data(approvalFlowView); } } diff --git a/src/main/java/com/xdap/self_development/controller/TemplateApprovalController.java b/src/main/java/com/xdap/self_development/controller/TemplateApprovalController.java index 2b6f080..d61be5c 100644 --- a/src/main/java/com/xdap/self_development/controller/TemplateApprovalController.java +++ b/src/main/java/com/xdap/self_development/controller/TemplateApprovalController.java @@ -5,8 +5,7 @@ import com.definesys.mpaas.query.db.PageQueryResult; import com.xdap.runtime.service.RuntimeDatasourceService; import com.xdap.self_development.controller.form.*; import com.xdap.self_development.exception.CommonException; -import com.xdap.self_development.pojo.ApprovalFlow; -import com.xdap.self_development.pojo.view.ApprovalFlowView; +import com.xdap.self_development.pojo.view.ApprovalFlowNodeView; import com.xdap.self_development.pojo.view.DepartmentUserView; import com.xdap.self_development.pojo.view.TemplateChangeView; import com.xdap.self_development.service.TemplateApprovalService; @@ -15,7 +14,6 @@ import org.springframework.web.bind.annotation.*; import javax.annotation.Resource; import javax.validation.Valid; -import javax.validation.constraints.NotBlank; import java.util.List; @RestController @@ -122,7 +120,7 @@ public class TemplateApprovalController { throw new CommonException(error.getDefaultMessage()); }); } - ApprovalFlowView approvalFlowView = templateApprovalService.getApprovalProcess(form); + ApprovalFlowNodeView approvalFlowView = templateApprovalService.getApprovalProcess(form); return Response.ok().data(approvalFlowView); } } diff --git a/src/main/java/com/xdap/self_development/controller/form/ApprovalPersonForm.java b/src/main/java/com/xdap/self_development/controller/form/ApprovalPersonForm.java index 72f2b2c..157c4d9 100644 --- a/src/main/java/com/xdap/self_development/controller/form/ApprovalPersonForm.java +++ b/src/main/java/com/xdap/self_development/controller/form/ApprovalPersonForm.java @@ -1,5 +1,6 @@ package com.xdap.self_development.controller.form; +import com.xdap.self_development.pojo.dto.ApprovalNodeDTO; import lombok.Data; import javax.validation.constraints.NotBlank; @@ -8,19 +9,15 @@ import java.util.List; @Data public class ApprovalPersonForm { + @NotEmpty(message = "创建者不能为空") + private String userId; + @NotEmpty(message = "报告不能为空") private String reportId; @NotBlank(message = "流程标题不能为空") private String processTitle; - @NotEmpty(message = "校对人员不能为空") - private List proofreadUsers; - @NotEmpty(message = "审核人员不能为空") - private List reviewUsers; - private List countersignUsers; // 可选 - @NotEmpty(message = "批准人员不能为空") - private List approveUsers; + // 审批环节配置列表 + @NotEmpty(message = "环节不能为空") + private List nodeList; private String explanation; - - @NotEmpty(message = "创建者不能为空") - private String userId; } diff --git a/src/main/java/com/xdap/self_development/controller/form/StartApprovalRequest.java b/src/main/java/com/xdap/self_development/controller/form/StartApprovalRequest.java index 4bae01e..f933a87 100644 --- a/src/main/java/com/xdap/self_development/controller/form/StartApprovalRequest.java +++ b/src/main/java/com/xdap/self_development/controller/form/StartApprovalRequest.java @@ -1,5 +1,6 @@ package com.xdap.self_development.controller.form; +import com.xdap.self_development.pojo.dto.ApprovalNodeDTO; import lombok.Data; import javax.validation.constraints.NotBlank; @@ -15,14 +16,8 @@ public class StartApprovalRequest { private String processTitle; @NotBlank(message = "请选择审核内容") private String templateRowId; - @NotEmpty(message = "校对人员不能为空") - private List proofreadUsers; - @NotEmpty(message = "审核人员不能为空") - private List reviewUsers; - - private List countersignUsers; // 可选 - @NotEmpty(message = "批准人员不能为空") - private List approveUsers; - + // 审批环节配置列表 + @NotEmpty(message = "环节不能为空") + private List nodeList; private String explanation; } \ No newline at end of file diff --git a/src/main/java/com/xdap/self_development/pojo/ApprovalFlow.java b/src/main/java/com/xdap/self_development/pojo/ApprovalFlow.java index 93d164d..368ba11 100644 --- a/src/main/java/com/xdap/self_development/pojo/ApprovalFlow.java +++ b/src/main/java/com/xdap/self_development/pojo/ApprovalFlow.java @@ -18,15 +18,10 @@ public class ApprovalFlow extends MpaasBasePojo { private String id; private String processTitle; private String templateId; - private String currentNode; // 节点:PROOFREAD, REVIEW, COUNTERSIGN, APPROVE + private Integer currentNode; // 节点:PROOFREAD, REVIEW, COUNTERSIGN, APPROVE private String flowStatus; //DRAFT(草稿)、APPROVING(审批中)、COMPLETE(已完成)、RETURNED(已撤回)、REJECTED(已拒绝) private Integer returnNum; - private String proofreadUsers; // 校对人员 - private String reviewUsers; // 审核人员 - private String countersignUsers; // 会签人员 - private String approveUsers; // 批准人员 - private String createBy; @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") private Timestamp createdTime; diff --git a/src/main/java/com/xdap/self_development/pojo/view/FlowNode.java b/src/main/java/com/xdap/self_development/pojo/view/FlowNode.java new file mode 100644 index 0000000..bd572cb --- /dev/null +++ b/src/main/java/com/xdap/self_development/pojo/view/FlowNode.java @@ -0,0 +1,26 @@ +package com.xdap.self_development.pojo.view; + +import com.fasterxml.jackson.annotation.JsonFormat; +import lombok.Data; + +import java.sql.Timestamp; +import java.util.List; + +@Data +public class FlowNode { + // 节点名 + private String node; + // 节点处理人 + private String todoUserName; + // 节点未处理人 + private String undoUserName; + // 处理意见 + private List opinions; + // 节点状态 + private String result; // PASS, REJECT + // 节点顺序 + private Integer nodeOrder; + // 节点处理时间 + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Timestamp approvalTime; +} diff --git a/src/main/java/com/xdap/self_development/pojo/view/TodoAndReportListView.java b/src/main/java/com/xdap/self_development/pojo/view/TodoAndReportListView.java index 0400eda..c1426dc 100644 --- a/src/main/java/com/xdap/self_development/pojo/view/TodoAndReportListView.java +++ b/src/main/java/com/xdap/self_development/pojo/view/TodoAndReportListView.java @@ -11,7 +11,7 @@ import java.util.List; @SQLQuery(value = { @SQL(view = "getAllReportApprovalList", - sql = "SELECT af.id AS \"flowId\", r.id AS \"reportId\", r.title AS \"title\", af.flow_status AS \"status\", af.create_by AS \"createBy\" , xu.username AS \"username\", af.created_time AS \"createdTime\" , CASE WHEN current_node = 'PROOFREAD' THEN proofread_users WHEN current_node = 'REVIEW' THEN review_users WHEN current_node = 'COUNTERSIGN' THEN countersign_users WHEN current_node = 'APPROVE' THEN approve_users END AS current_users FROM yfsjglpt_model_approval_flow af JOIN yfsjglpt_model_benchmarking_report r ON af.template_id = r.id LEFT JOIN xdap_users xu ON xu.id = af.create_by WHERE af.flow_type = 2 AND r.title LIKE CONCAT('%', #title, '%') AND af.flow_status LIKE CONCAT('%', #status, '%') AND af.created_time LIKE CONCAT('%', #createdTime, '%') AND xu.username LIKE CONCAT('%', #username, '%') ORDER BY CASE af.flow_status WHEN 'COMPLETE' THEN 1 WHEN 'APPROVING' THEN 2 WHEN 'DRAFT' THEN 3 WHEN 'REJECTED' THEN 4 ELSE 5 END ASC, af.created_time DESC") + sql = "SELECT af.id AS \"flowId\", r.id AS \"reportId\", r.title AS \"title\", af.flow_status AS \"status\", af.create_by AS \"createBy\" , xu.username AS \"username\", af.created_time AS \"createdTime\", ac.assignees AS current_users FROM yfsjglpt_model_approval_flow af JOIN approval_config ac ON af.id = ac.approval_id AND af.current_node = ac.node_order JOIN yfsjglpt_model_benchmarking_report r ON af.template_id = r.id LEFT JOIN xdap_users xu ON xu.id = af.create_by WHERE af.flow_type = 2 AND r.title LIKE CONCAT('%', #title, '%') AND af.flow_status LIKE CONCAT('%', #status, '%') AND af.created_time LIKE CONCAT('%', #createdTime, '%') AND xu.username LIKE CONCAT('%', #username, '%') ORDER BY CASE af.flow_status WHEN 'COMPLETE' THEN 1 WHEN 'APPROVING' THEN 2 WHEN 'DRAFT' THEN 3 WHEN 'REJECTED' THEN 4 ELSE 5 END ASC, af.created_time DESC") }) @Data public class TodoAndReportListView { diff --git a/src/main/java/com/xdap/self_development/pojo/view/TodoAndTemplateView.java b/src/main/java/com/xdap/self_development/pojo/view/TodoAndTemplateView.java index 0921a87..d1fc089 100644 --- a/src/main/java/com/xdap/self_development/pojo/view/TodoAndTemplateView.java +++ b/src/main/java/com/xdap/self_development/pojo/view/TodoAndTemplateView.java @@ -11,7 +11,7 @@ import java.util.List; @SQLQuery(value = { @SQL(view = "getAllApproval", - sql = "SELECT af.id AS \"flowId\", t.id AS \"templateId\", t.template_name AS \"templateName\", t.version AS \"version\", af.flow_status AS \"status\" , af.create_by AS \"createBy\" , xu.username AS \"username\", af.created_time AS \"createdTime\" , CASE WHEN current_node = 'PROOFREAD' THEN proofread_users WHEN current_node = 'REVIEW' THEN review_users WHEN current_node = 'COUNTERSIGN' THEN countersign_users WHEN current_node = 'APPROVE' THEN approve_users END AS current_users FROM yfsjglpt_model_approval_flow af JOIN yfsjglpt_model_template t ON af.template_id = t.id LEFT JOIN xdap_users xu ON xu.id = af.create_by WHERE t.template_name LIKE CONCAT('%', #templateName, '%') AND af.flow_status LIKE CONCAT('%', #status, '%') AND af.created_time LIKE CONCAT('%', #createdTime, '%') AND xu.username LIKE CONCAT('%', #username, '%') AND af.flow_type = 1 ORDER BY CASE af.flow_status WHEN 'COMPLETE' THEN 1 WHEN 'APPROVING' THEN 2 WHEN 'DRAFT' THEN 3 WHEN 'REJECTED' THEN 4 ELSE 5 END ASC"), + sql = "SELECT af.id AS \"flowId\", t.id AS \"templateId\", t.template_name AS \"templateName\", t.version AS \"version\", af.flow_status AS \"status\" , af.create_by AS \"createBy\", xu.username AS \"username\", af.created_time AS \"createdTime\", ac.assignees AS current_users FROM yfsjglpt_model_approval_flow af JOIN approval_config ac ON af.id = ac.approval_id AND af.current_node = ac.node_order JOIN yfsjglpt_model_template t ON af.template_id = t.id LEFT JOIN xdap_users xu ON xu.id = af.create_by WHERE t.template_name LIKE CONCAT('%', #templateName, '%') AND af.flow_status LIKE CONCAT('%', #status, '%') AND af.created_time LIKE CONCAT('%', #createdTime, '%') AND xu.username LIKE CONCAT('%', #username, '%') AND af.flow_type = 1 ORDER BY CASE af.flow_status WHEN 'COMPLETE' THEN 1 WHEN 'APPROVING' THEN 2 WHEN 'DRAFT' THEN 3 WHEN 'REJECTED' THEN 4 ELSE 5 END ASC"), @SQL(view = "getApprovalByUserIdAndIds", sql = "SELECT af.id AS \"flowId\", t.id AS \"templateId\", t.template_name AS \"templateName\", t.version AS \"version\", af.flow_status AS \"status\" , af.create_by AS \"createBy\", af.created_time AS \"createdTime\" , CASE WHEN current_node = 'PROOFREAD' THEN proofread_users WHEN current_node = 'REVIEW' THEN review_users WHEN current_node = 'COUNTERSIGN' THEN countersign_users WHEN current_node = 'APPROVE' THEN approve_users END AS current_users FROM yfsjglpt_model_approval_flow af JOIN yfsjglpt_model_template t ON af.template_id = t.id WHERE t.template_name like CONCAT('%',#templateName, '%') and af.flow_status like CONCAT('%',#status, '%') and af.flow_type = 1 and af.id NOT IN (#ids) AND af.create_by = #createBy"), @SQL(view = "getTodoAndTemplate", diff --git a/src/main/java/com/xdap/self_development/service/BenchmarkingReportService.java b/src/main/java/com/xdap/self_development/service/BenchmarkingReportService.java index 14c232a..19f30c5 100644 --- a/src/main/java/com/xdap/self_development/service/BenchmarkingReportService.java +++ b/src/main/java/com/xdap/self_development/service/BenchmarkingReportService.java @@ -3,7 +3,7 @@ package com.xdap.self_development.service; import com.definesys.mpaas.query.db.PageQueryResult; import com.xdap.self_development.controller.form.*; import com.xdap.self_development.pojo.BenchmarkingReport; -import com.xdap.self_development.pojo.view.ApprovalFlowView; +import com.xdap.self_development.pojo.view.ApprovalFlowNodeView; import com.xdap.self_development.pojo.view.TodoAndReportListView; import com.xdap.self_development.pojo.view.TodoAndReportView; import org.springframework.web.multipart.MultipartFile; @@ -25,7 +25,7 @@ public interface BenchmarkingReportService { BenchmarkingReport getReportDetail(@NotBlank String reportId); - ApprovalFlowView getReportProcess(@NotBlank String flowId); + ApprovalFlowNodeView getReportProcess(@NotBlank String flowId); String uploadFile(MultipartFile file, @NotBlank String createBy); diff --git a/src/main/java/com/xdap/self_development/service/TemplateApprovalService.java b/src/main/java/com/xdap/self_development/service/TemplateApprovalService.java index 040b3cc..aecccd2 100644 --- a/src/main/java/com/xdap/self_development/service/TemplateApprovalService.java +++ b/src/main/java/com/xdap/self_development/service/TemplateApprovalService.java @@ -2,7 +2,7 @@ package com.xdap.self_development.service; import com.definesys.mpaas.query.db.PageQueryResult; import com.xdap.self_development.controller.form.*; -import com.xdap.self_development.pojo.view.ApprovalFlowView; +import com.xdap.self_development.pojo.view.ApprovalFlowNodeView; import com.xdap.self_development.pojo.view.TemplateChangeView; import com.xdap.self_development.pojo.view.TodoAndTemplateView; @@ -17,7 +17,7 @@ public interface TemplateApprovalService { PageQueryResult getTemplateChanges(@Valid ApprovalAndParameterForm form); - ApprovalFlowView getApprovalProcess(@Valid ApprovalFlowForm form); + ApprovalFlowNodeView getApprovalProcess(@Valid ApprovalFlowForm form); void handleReturn(@Valid HandleApprovalRequest request); } diff --git a/src/main/java/com/xdap/self_development/service/impl/BenchmarkingReportServiceImpl.java b/src/main/java/com/xdap/self_development/service/impl/BenchmarkingReportServiceImpl.java index 332d77f..f6d8d28 100644 --- a/src/main/java/com/xdap/self_development/service/impl/BenchmarkingReportServiceImpl.java +++ b/src/main/java/com/xdap/self_development/service/impl/BenchmarkingReportServiceImpl.java @@ -4,6 +4,7 @@ import cn.hutool.core.codec.Base64; import cn.hutool.json.JSONUtil; import com.alibaba.fastjson2.JSON; import com.definesys.mpaas.query.db.PageQueryResult; +import com.xdap.api.moudle.user.pojo.XdapUsers; import com.xdap.runtime.service.RuntimeAppContextService; import com.xdap.self_development.config.BusinessDatabase; import com.xdap.self_development.controller.form.*; @@ -13,10 +14,8 @@ import com.xdap.self_development.feign.dto.AppTokenDTO; import com.xdap.self_development.feign.dto.FileUploadDTO; import com.xdap.self_development.feign.dto.UserTokenDT0; import com.xdap.self_development.pojo.*; -import com.xdap.self_development.pojo.view.ApprovalFlowView; -import com.xdap.self_development.pojo.view.ApprovalNodeView; -import com.xdap.self_development.pojo.view.TodoAndReportListView; -import com.xdap.self_development.pojo.view.TodoAndReportView; +import com.xdap.self_development.pojo.dto.ApprovalNodeDTO; +import com.xdap.self_development.pojo.view.*; import com.xdap.self_development.service.BenchmarkingReportService; import com.xdap.self_development.service.XdapDeptUsersService; import com.xdap.self_development.utils.RedisLockUtil; @@ -56,13 +55,77 @@ public class BenchmarkingReportServiceImpl implements BenchmarkingReportService private static final String FLOW_LOCK_PREFIX = "report:lock:"; private static final int FLOW_LOCK_EXPIRE_SECONDS = 15; - private String getNodeName(String node) { - switch (node) { - case "PROOFREAD": return "校对"; - case "REVIEW": return "SE审核"; - case "APPROVE": return "部门长审核"; - default: return "-"; + @Override + @Transactional(rollbackFor = Exception.class) + public void startReportApproval(ApprovalPersonForm form) { + BenchmarkingReport report = bd.getBusinessDatabase() + .eq("id", form.getReportId()) + .doQueryFirst(BenchmarkingReport.class); + + ApprovalFlow approvalFlow = bd.getBusinessDatabase() + .eq("template_id", report.getId()) + .doQueryFirst(ApprovalFlow.class); + if (approvalFlow != null && Objects.equals(approvalFlow.getFlowStatus(), "APPROVING")) { + throw new CommonException("该报告正在审批中,请勿重复发起审批"); } + + // 创建审批流程 + ApprovalFlow flow = new ApprovalFlow(); + flow.setTemplateId(report.getId()); + flow.setCurrentNode(1); + flow.setFlowStatus("APPROVING"); + flow.setProcessTitle(form.getProcessTitle()); + flow.setCreateBy(form.getUserId()); + flow.setCreatedTime(Timestamp.valueOf(LocalDateTime.now())); + flow.setFlowType(2); // 设置为报告审批流程 + flow.setExplanation(form.getExplanation()); + flow.setProcessTitle(form.getProcessTitle()); + bd.getBusinessDatabase().doInsert(flow); + + // 创建审批配置 + List approvalConfigs = new ArrayList<>(); + ApprovalNodeDTO firstNode = new ApprovalNodeDTO(); + for (ApprovalNodeDTO node : form.getNodeList()) { + if (node.getNodeOrder() == 1) { + firstNode.setNodeOrder(1); + firstNode.setAssignees(node.getAssignees()); + firstNode.setNodeName(node.getNodeName()); + } + ApprovalConfigPojo config = new ApprovalConfigPojo(); + config.setNodeName(node.getNodeName()); + config.setNodeOrder(node.getNodeOrder()); + config.setAssignees(JSON.toJSONString(node.getAssignees())); + config.setApprovalId(flow.getId()); + approvalConfigs.add(config); + } + bd.getBusinessDatabase().doBatchInsert(approvalConfigs); + + List list = new ArrayList<>(); + for (String person : firstNode.getAssignees()) { + TodoTaskPojo todoTask = new TodoTaskPojo(); + todoTask.setCreatedById(form.getUserId()); + todoTask.setCreatedBy(xdapDeptUsersService.selectUserByID(form.getUserId()).getUsername()); + todoTask.setCurrentNode(""); + todoTask.setDataType("对标报告审核"); + todoTask.setDocumentNo(flow.getId()); + todoTask.setCreationDate(Timestamp.valueOf(LocalDateTime.now())); + todoTask.setIsDelete(0); + todoTask.setModelId(report.getId()); + todoTask.setModelName(report.getProjectName() + "对标报告"); + todoTask.setProcessTitle(form.getProcessTitle()); + todoTask.setStatusCode(flow.getFlowStatus()); + todoTask.setVersionNumber(1); + todoTask.setOwnerId(person); + todoTask.setCurrentProcessor(JSON.toJSONString(firstNode.getAssignees())); + list.add(todoTask); + } + bd.getBusinessDatabase().doBatchInsert(list); + + // 更新报告状态为校对中 + bd.getBusinessDatabase() + .eq("id", report.getId()) + .update("status", "APPROVING") + .doUpdate(BenchmarkingReport.class); } @Override @@ -161,61 +224,6 @@ public class BenchmarkingReportServiceImpl implements BenchmarkingReportService bd.getBusinessDatabase().doInsert(report); } - @Override - public void startReportApproval(ApprovalPersonForm form) { - BenchmarkingReport report = bd.getBusinessDatabase() - .eq("id", form.getReportId()) - .doQueryFirst(BenchmarkingReport.class); - - ApprovalFlow approvalFlow = bd.getBusinessDatabase() - .eq("template_id", report.getId()) - .doQueryFirst(ApprovalFlow.class); - if (approvalFlow != null && Objects.equals(approvalFlow.getFlowStatus(), "APPROVING")) { - throw new CommonException("该报告正在审批中,请勿重复发起审批"); - } - - ApprovalFlow flow = new ApprovalFlow(); - flow.setTemplateId(report.getId()); - flow.setCurrentNode("PROOFREAD"); - flow.setFlowStatus("APPROVING"); - flow.setProofreadUsers(JSON.toJSONString(form.getProofreadUsers())); - flow.setReviewUsers(JSON.toJSONString(form.getReviewUsers())); - flow.setCountersignUsers(JSON.toJSONString(form.getCountersignUsers())); - flow.setApproveUsers(JSON.toJSONString(form.getApproveUsers())); - flow.setCreateBy(form.getUserId()); - flow.setCreatedTime(Timestamp.valueOf(LocalDateTime.now())); - flow.setFlowType(2); // 设置为报告审批流程 - flow.setExplanation(form.getExplanation()); - flow.setProcessTitle(form.getProcessTitle()); - bd.getBusinessDatabase().doInsert(flow); - - bd.getBusinessDatabase() - .eq("id", report.getId()) - .update("status", "APPROVING") - .doUpdate(BenchmarkingReport.class); - - List list = new ArrayList<>(); - for (String person : form.getProofreadUsers()) { - TodoTaskPojo todoTask = new TodoTaskPojo(); - todoTask.setCreatedById(form.getUserId()); - todoTask.setCreatedBy(xdapDeptUsersService.selectUserByID(form.getUserId()).getUsername()); - todoTask.setCurrentNode(getNodeName(flow.getCurrentNode())); - todoTask.setDataType("对标报告审核"); - todoTask.setDocumentNo(flow.getId()); - todoTask.setCreationDate(Timestamp.valueOf(LocalDateTime.now())); - todoTask.setIsDelete(0); - todoTask.setModelId(report.getId()); - todoTask.setModelName(report.getProjectName()+"对标报告"); - todoTask.setProcessTitle(form.getProcessTitle()); - todoTask.setStatusCode(flow.getFlowStatus()); - todoTask.setVersionNumber(1); - todoTask.setOwnerId(person); - todoTask.setCurrentProcessor(JSON.toJSONString(getNodeUsers(flow, flow.getCurrentNode()))); - list.add(todoTask); - } - bd.getBusinessDatabase().doBatchInsert(list); - } - @Override public void updateReport(UpdateBenchmarkingReportForm form) { BenchmarkingReport report = bd.getBusinessDatabase() @@ -247,6 +255,7 @@ public class BenchmarkingReportServiceImpl implements BenchmarkingReportService @Override @Transactional(rollbackFor = Exception.class) public void handleReportApproval(HandleApprovalRequest request) { + // 验证流程状态 ApprovalFlow flow = bd.getBusinessDatabase() .eq("id", request.getFlowId()) .eq("flow_type", 2) @@ -255,10 +264,15 @@ public class BenchmarkingReportServiceImpl implements BenchmarkingReportService throw new CommonException("流程不存在或已结束"); } - String currentNode = flow.getCurrentNode(); + // 获取当前流程节点 + ApprovalConfigPojo currentNode = bd.getBusinessDatabase() + .eq("approval_id", flow.getId()) + .eq("node_order", flow.getCurrentNode()) + .doQueryFirst(ApprovalConfigPojo.class); + // 验证当前用户是否有权限处理 - if (!hasPermission(flow, currentNode, request.getUserId())) { - throw new CommonException("无权限处理"); + if (!hasPermission(currentNode, request.getUserId())) { + throw new CommonException("无权限处理或已被处理"); } String lockKey = FLOW_LOCK_PREFIX + flow.getId() + ":" + currentNode; @@ -272,7 +286,7 @@ public class BenchmarkingReportServiceImpl implements BenchmarkingReportService int processedCount = bd.getBusinessDatabase() .eq("document_no", flow.getId()) .eq("is_delete", 1) - .eq("current_node", getNodeName(flow.getCurrentNode())) + .eq("current_node", currentNode.getNodeName()) .doQuery(TodoTaskPojo.class).size(); if (processedCount > 0) { throw new CommonException("此节点已被他人处理"); @@ -283,6 +297,142 @@ public class BenchmarkingReportServiceImpl implements BenchmarkingReportService } } + // 验证是否为当前处理人 + private boolean hasPermission(ApprovalConfigPojo node, String userId) { + return JSON.parseArray(node.getAssignees()) + .toJavaList(String.class).contains(userId); + } + + public void processApprovalLogic(ApprovalFlow flow, HandleApprovalRequest request, ApprovalConfigPojo currentNode) { + // 记录审批结果 + ApprovalRecord record = new ApprovalRecord(); + record.setFlowId(flow.getId()); + record.setNode(currentNode.getNodeName()); + record.setUserId(request.getUserId()); + record.setOpinion(request.getOpinion()); + record.setResult(request.getResult()); + record.setApprovalTime(Timestamp.valueOf(LocalDateTime.now())); + bd.getBusinessDatabase().doInsert(record); + + bd.getBusinessDatabase() + .eq("document_no", flow.getId()) + .eq("owner_id", request.getUserId()) + .eq("current_node", currentNode.getNodeName()) + .update("last_update_date", Timestamp.valueOf(LocalDateTime.now())) + .update("is_delete", 1) + .doUpdate(TodoTaskPojo.class); + bd.getBusinessDatabase() + .eq("document_no", flow.getId()) + .ne("owner_id", request.getUserId()) + .eq("current_node", currentNode.getNodeName()) + .update("last_update_date", Timestamp.valueOf(LocalDateTime.now())) + .update("is_delete", 2) + .doUpdate(TodoTaskPojo.class); + + // 处理驳回逻辑 + if ("REJECT".equals(request.getResult())) { + cancelProcess(flow, "REJECTED", request.getUserId()); + return; + } + // 处理通过逻辑,流转到下一节点 + processNextNode(flow, currentNode, request.getUserId()); + } + + private void processNextNode(ApprovalFlow flow, ApprovalConfigPojo currentNode, String userId) { + // 更新报告状态 + BenchmarkingReport report = bd.getBusinessDatabase() + .eq("id", flow.getTemplateId()) + .doQueryFirst(BenchmarkingReport.class); + // 获取下一个节点 + ApprovalConfigPojo nextNode = bd.getBusinessDatabase() + .eq("approval_id", flow.getId()) + .eq("node_order", currentNode.getNodeOrder() + 1) + .doQueryFirst(ApprovalConfigPojo.class); + if (nextNode == null) { + // 流程结束 + flow.setFlowStatus("COMPLETE"); + flow.setCurrentNode(null); + report.setStatus("COMPLETE"); + bd.getBusinessDatabase() + .rowid("id", report.getRowId()) + .update("status", report.getStatus()) + .doUpdate(BenchmarkingReport.class); + // 待办环节修改 + bd.getBusinessDatabase() + .eq("document_no", flow.getId()) + .update("node", "已完成") + .doUpdate(TodoTaskPojo.class); + } else { + flow.setCurrentNode(1); + addNodeTodo(flow, nextNode, report, userId); + } + + bd.getBusinessDatabase() + .rowid("id", flow.getRowId()) + .update("flow_status", flow.getFlowStatus()) + .update("current_node", flow.getCurrentNode()) + .doUpdate(ApprovalFlow.class); + } + + private void addNodeTodo(ApprovalFlow flow, ApprovalConfigPojo node, BenchmarkingReport report, String createBy) { + List users = JSON.parseArray(node.getAssignees()).toJavaList(String.class); + // 新增待办 + List list = new ArrayList<>(); + for (String person : users) { + TodoTaskPojo todoTaskPojo = bd.getBusinessDatabase() + .eq("document_no", flow.getId()) + .eq("owner_id", person).doQueryFirst(TodoTaskPojo.class); + if (todoTaskPojo != null) { + todoTaskPojo.setCurrentNode(node.getNodeName()); + todoTaskPojo.setCurrentProcessor(JSON.toJSONString(node.getAssignees())); + bd.getBusinessDatabase().doUpdate(todoTaskPojo); + bd.getBusinessDatabase().doUpdate(todoTaskPojo); + } else { + TodoTaskPojo todoTask = new TodoTaskPojo(); + todoTask.setCreatedById(createBy); + todoTask.setCreatedBy(xdapDeptUsersService.selectUserByID(createBy).getUsername()); + todoTask.setCurrentNode("1"); + todoTask.setDataType("对标报告审核"); + todoTask.setDocumentNo(flow.getId()); + todoTask.setCreationDate(Timestamp.valueOf(LocalDateTime.now())); + todoTask.setIsDelete(0); + todoTask.setModelId(report.getId()); + todoTask.setModelName(report.getProjectName() + "对标报告"); + todoTask.setProcessTitle(flow.getProcessTitle()); + todoTask.setStatusCode(flow.getFlowStatus()); + todoTask.setVersionNumber(1); + todoTask.setOwnerId(person); + todoTask.setCurrentProcessor(JSON.toJSONString(node.getAssignees())); + list.add(todoTask); + } + } + bd.getBusinessDatabase().doBatchInsert(list); + } + + private void cancelProcess(ApprovalFlow flow, String status, String userId) { + flow.setFlowStatus(status); + bd.getBusinessDatabase() + .rowid("id", flow.getRowId()) + .update("flow_status", flow.getFlowStatus()) + .doUpdate(ApprovalFlow.class); + // 更新报告状态 + BenchmarkingReport report = bd.getBusinessDatabase() + .eq("id", flow.getTemplateId()) + .doQueryFirst(BenchmarkingReport.class); + report.setStatus(status); + bd.getBusinessDatabase() + .rowid("id", report.getRowId()) + .update("status", report.getStatus()) + .doUpdate(BenchmarkingReport.class); + + bd.getBusinessDatabase() + .eq("document_no", flow.getId()) + .update("node", "已拒绝") + .doUpdate(TodoTaskPojo.class); + // 清除所有待办 + clearAllTodo(flow, userId); + } + @Override public BenchmarkingReport getReportDetail(String reportId) { return bd.getBusinessDatabase() @@ -293,88 +443,71 @@ public class BenchmarkingReportServiceImpl implements BenchmarkingReportService } @Override - public ApprovalFlowView getReportProcess(String flowId) { - ApprovalFlowView approvalFlowView = new ApprovalFlowView(); - ApprovalFlow flow = bd.getBusinessDatabase() + public ApprovalFlowNodeView getReportProcess(String flowId) { + ApprovalFlowNodeView flowNodeView = new ApprovalFlowNodeView(); + ApprovalFlow approvalFlow = bd.getBusinessDatabase() .eq("id", flowId) - .eq("flow_type", 2) .doQueryFirst(ApprovalFlow.class); - - if (flowId == null || flowId.isEmpty() || flow == null) { - return approvalFlowView; + // 无流程创建空返回 + if (approvalFlow == null) { + return flowNodeView; } - approvalFlowView.setExplanation(flow.getExplanation()); - approvalFlowView.setFlowStatus(flow.getFlowStatus()); - if (!"APPROVING".equals(flow.getFlowStatus())) { - setAllCompletedNodes(approvalFlowView, flow); - return approvalFlowView; - } - processApprovalNodes(approvalFlowView, flow); - return approvalFlowView; + BenchmarkingReport report = bd.getBusinessDatabase() + .eq("id", approvalFlow.getTemplateId()) + .doQueryFirst(BenchmarkingReport.class); + // 获取流程信息 + flowNodeView.setProgressTitle(approvalFlow.getProcessTitle()); + flowNodeView.setContentName(report.getTitle()); + flowNodeView.setTemplateVersion(1); + flowNodeView.setExplanation(approvalFlow.getExplanation()); + flowNodeView.setFlowStatus(approvalFlow.getFlowStatus()); + // 获取节点信息 + List nodes = bd.getBusinessDatabase() + .eq("approval_id", flowId) + .doQuery(ApprovalConfigPojo.class); + List flowNodes = new ArrayList<>(); + nodes.forEach(node -> { + FlowNode nodeView = new FlowNode(); + ApprovalRecord record = bd.getBusinessDatabase() + .eq("flow_id", flowId) + .eq("node", node.getNodeName()) + .doQueryFirst(ApprovalRecord.class); + if (record != null) { + // 节点已完成 + nodeView.setNodeOrder(node.getNodeOrder()); + nodeView.setNode(node.getNodeName()); + nodeView.setResult(record.getResult()); + nodeView.setOpinions(Collections.singletonList(getUserNames(Collections.singletonList(record.getUserId())) + ":" + record.getOpinion())); + nodeView.setApprovalTime(record.getApprovalTime()); + nodeView.setTodoUserName(getUserNames(Collections.singletonList(record.getUserId()))); + nodeView.setUndoUserName(getUserNames(JSON.parseArray(node.getAssignees()).toJavaList(String.class))); + } else { + // 节点未完成 + nodeView.setNodeOrder(node.getNodeOrder()); + nodeView.setNode(node.getNodeName()); + nodeView.setResult("待审批"); + nodeView.setTodoUserName(""); + nodeView.setUndoUserName(getUserNames(JSON.parseArray(node.getAssignees()).toJavaList(String.class))); + } + flowNodes.add(nodeView); + }); + List sortedNode = flowNodes.stream().sorted(Comparator.comparing(FlowNode::getNodeOrder)).collect(Collectors.toList()); + flowNodeView.setFlowNodes(sortedNode); + return flowNodeView; } - private void setAllCompletedNodes(ApprovalFlowView view, ApprovalFlow flow) { - view.setProofreadNodes(getNodeList(flow.getId(), "PROOFREAD")); - view.setReviewNodes(getNodeList(flow.getId(), "REVIEW")); - view.setApproveNodes(getNodeList(flow.getId(), "APPROVE")); - } - - private void processApprovalNodes(ApprovalFlowView view, ApprovalFlow flow) { - // 处理校对节点 - List proofreadNodes = getNodeList(flow.getId(), "PROOFREAD"); - if (proofreadNodes.isEmpty()) { - view.setProofreadNodes(createApprovingNode(flow.getProofreadUsers())); - view.setReviewNodes(new ArrayList<>()); - view.setApproveNodes(new ArrayList<>()); - return; - } - view.setProofreadNodes(proofreadNodes); - - // 处理审核节点 - List reviewNodes = getNodeList(flow.getId(), "REVIEW"); - if (reviewNodes.isEmpty()) { - view.setReviewNodes(createApprovingNode(flow.getReviewUsers())); - view.setApproveNodes(new ArrayList<>()); - return; - } - view.setReviewNodes(reviewNodes); - - List approveNodes = getNodeList(flow.getId(), "APPROVE"); - if (approveNodes.isEmpty()) { - view.setApproveNodes(createApprovingNode(flow.getApproveUsers())); - } else { - view.setApproveNodes(approveNodes); - } - } - - private List createApprovingNode(String userJsonArray) { - List list = new ArrayList<>(); - - if (userJsonArray == null || userJsonArray.trim().isEmpty()) { - return list; - } - - List userIds = JSON.parseArray(userJsonArray).toJavaList(String.class); - if (userIds.isEmpty()) { - return list; - } - Map usersMap = batchQueryUsers(userIds); - StringBuilder usernames = new StringBuilder(); - for (String id : userIds) { - ApprovalXdapUsers user = usersMap.get(id); - if (user != null) { - usernames.append(user.getUsername()).append(" "); + private String getUserNames(List userIds) { + StringJoiner joiner = new StringJoiner(" "); + for (String userId : userIds) { + String username = bd.getBusinessDatabase().eq("id", userId).doQueryFirst(XdapUsers.class).getUsername(); + if (username != null) { + joiner.add(username); + } else { + // 处理空值情况 + joiner.add(userId); } } - if (usernames.length() > 0) { - ApprovalNodeView node = new ApprovalNodeView(); - node.setNode("APPROVING"); - node.setUserName(usernames.toString().trim()); - node.setResult("APPROVING"); - node.setApprovalTime(Timestamp.valueOf(LocalDateTime.now())); - list.add(node); - } - return list; + return joiner.toString(); } private Map batchQueryUsers(List userIds) { @@ -409,159 +542,6 @@ public class BenchmarkingReportServiceImpl implements BenchmarkingReportService return list; } - private boolean hasPermission(ApprovalFlow flow, String node, String userId) { - switch (node) { - case "PROOFREAD": - return JSON.parseArray(flow.getProofreadUsers()).toJavaList(String.class).contains(userId); - case "REVIEW": - return JSON.parseArray(flow.getReviewUsers()).toJavaList(String.class).contains(userId); - case "APPROVE": - return JSON.parseArray(flow.getApproveUsers()).toJavaList(String.class).contains(userId); - default: - return false; - } - } - - public void processApprovalLogic(ApprovalFlow flow, HandleApprovalRequest request, String currentNode) { - // 记录审批结果 - ApprovalRecord record = new ApprovalRecord(); - record.setFlowId(flow.getId()); - record.setNode(currentNode); - record.setUserId(request.getUserId()); - record.setOpinion(request.getOpinion()); - record.setResult(request.getResult()); - record.setApprovalTime(Timestamp.valueOf(LocalDateTime.now())); - bd.getBusinessDatabase().doInsert(record); - - bd.getBusinessDatabase() - .eq("document_no", flow.getId()) - .eq("owner_id", request.getUserId()) - .eq("current_node", getNodeName(flow.getCurrentNode())) - .update("last_update_date", Timestamp.valueOf(LocalDateTime.now())) - .update("is_delete", 1) - .doUpdate(TodoTaskPojo.class); - bd.getBusinessDatabase() - .eq("document_no", flow.getId()) - .ne("owner_id", request.getUserId()) - .eq("current_node", getNodeName(flow.getCurrentNode())) - .update("last_update_date", Timestamp.valueOf(LocalDateTime.now())) - .update("is_delete", 2) - .doUpdate(TodoTaskPojo.class); - - // 处理驳回逻辑 - if ("REJECT".equals(request.getResult())) { - cancelProcess(flow, "REJECTED", request.getUserId()); - return; - } - // 处理通过逻辑,流转到下一节点 - processNextNode(flow, currentNode, request.getUserId()); - } - - private void processNextNode(ApprovalFlow flow, String currentNode, String userId) { - - // 更新报告状态 - BenchmarkingReport report = bd.getBusinessDatabase() - .eq("id", flow.getTemplateId()) - .doQueryFirst(BenchmarkingReport.class); - String nextNode = getNextNode(currentNode, flow); - - if (nextNode == null) { - // 流程结束 - flow.setFlowStatus("COMPLETE"); - flow.setCurrentNode(null); - report.setStatus("COMPLETE"); - bd.getBusinessDatabase() - .rowid("id", report.getRowId()) - .update("status", report.getStatus()) - .doUpdate(BenchmarkingReport.class); - // 待办环节修改 - bd.getBusinessDatabase() - .eq("document_no", flow.getId()) - .update("node", "已完成") - .doUpdate(ApprovalNodeView.class); - } else { - flow.setCurrentNode(nextNode); - addNodeTodo(flow, nextNode, report, userId); - } - - bd.getBusinessDatabase() - .rowid("id", flow.getRowId()) - .update("flow_status", flow.getFlowStatus()) - .update("current_node", flow.getCurrentNode()) - .doUpdate(ApprovalFlow.class); - } - - private void addNodeTodo(ApprovalFlow flow, String node, BenchmarkingReport report, String createBy) { - List users = getNodeUsers(flow, node); - // 新增待办 - List list = new ArrayList<>(); - for (String person : users) { - TodoTaskPojo todoTaskPojo = bd.getBusinessDatabase() - .eq("document_no", flow.getId()) - .eq("owner_id", person).doQueryFirst(TodoTaskPojo.class); - if (todoTaskPojo != null) { - todoTaskPojo.setCurrentNode(getNodeName(node)); - todoTaskPojo.setCurrentProcessor(JSON.toJSONString(getNodeUsers(flow, node))); - bd.getBusinessDatabase().doUpdate(todoTaskPojo); - } else { - TodoTaskPojo todoTask = new TodoTaskPojo(); - todoTask.setCreatedById(createBy); - todoTask.setCreatedBy(xdapDeptUsersService.selectUserByID(createBy).getUsername()); - todoTask.setCurrentNode(getNodeName(flow.getCurrentNode())); - todoTask.setDataType("对标报告审核"); - todoTask.setDocumentNo(flow.getId()); - todoTask.setCreationDate(Timestamp.valueOf(LocalDateTime.now())); - todoTask.setIsDelete(0); - todoTask.setModelId(report.getId()); - todoTask.setModelName(report.getProjectName() + "对标报告"); - todoTask.setProcessTitle(flow.getProcessTitle()); - todoTask.setStatusCode(flow.getFlowStatus()); - todoTask.setVersionNumber(1); - todoTask.setOwnerId(person); - todoTask.setCurrentProcessor(JSON.toJSONString(getNodeUsers(flow, flow.getCurrentNode()))); - list.add(todoTask); - } - } - bd.getBusinessDatabase().doBatchInsert(list); - } - - private String getNextNode(String currentNode, ApprovalFlow flow) { - switch (currentNode) { - case "PROOFREAD": - return "REVIEW"; - case "REVIEW": - return "APPROVE"; - case "APPROVE": - return null; // 流程结束 - default: - return null; - } - } - - private void cancelProcess(ApprovalFlow flow, String status, String userId) { - flow.setFlowStatus(status); - bd.getBusinessDatabase() - .rowid("id", flow.getRowId()) - .update("flow_status", flow.getFlowStatus()) - .doUpdate(ApprovalFlow.class); - // 更新报告状态 - BenchmarkingReport report = bd.getBusinessDatabase() - .eq("id", flow.getTemplateId()) - .doQueryFirst(BenchmarkingReport.class); - report.setStatus(status); - bd.getBusinessDatabase() - .rowid("id", report.getRowId()) - .update("status", report.getStatus()) - .doUpdate(BenchmarkingReport.class); - - bd.getBusinessDatabase() - .eq("document_no", flow.getId()) - .update("node", "已拒绝") - .doUpdate(ApprovalNodeView.class); - // 清除所有待办 - clearAllTodo(flow, userId); - } - private void clearAllTodo(ApprovalFlow flow, String userId) { // 清除已有待办 bd.getBusinessDatabase() @@ -571,14 +551,4 @@ public class BenchmarkingReportServiceImpl implements BenchmarkingReportService .update("last_update_date", Timestamp.valueOf(LocalDateTime.now())) .doUpdate(TodoTaskPojo.class); } - - private List getNodeUsers(ApprovalFlow flow, String node) { - switch (node) { - case "PROOFREAD": return JSON.parseArray(flow.getProofreadUsers()).toJavaList(String.class); - case "REVIEW": return JSON.parseArray(flow.getReviewUsers()).toJavaList(String.class); - case "APPROVE": return JSON.parseArray(flow.getApproveUsers()).toJavaList(String.class); - default: return Collections.emptyList(); - } - } - } diff --git a/src/main/java/com/xdap/self_development/service/impl/TemplateApprovalServiceImpl.java b/src/main/java/com/xdap/self_development/service/impl/TemplateApprovalServiceImpl.java index 7f35a81..3d2e9e6 100644 --- a/src/main/java/com/xdap/self_development/service/impl/TemplateApprovalServiceImpl.java +++ b/src/main/java/com/xdap/self_development/service/impl/TemplateApprovalServiceImpl.java @@ -1,23 +1,21 @@ package com.xdap.self_development.service.impl; import com.alibaba.fastjson2.JSON; -import com.definesys.mpaas.log.SWordLogger; import com.definesys.mpaas.query.db.PageQueryResult; -import com.xdap.runtime.service.RuntimeDatasourceService; +import com.xdap.api.moudle.user.pojo.XdapUsers; import com.xdap.self_development.config.BusinessDatabase; import com.xdap.self_development.controller.form.*; import com.xdap.self_development.exception.CommonException; import com.xdap.self_development.pojo.*; -import com.xdap.self_development.pojo.view.ApprovalFlowView; -import com.xdap.self_development.pojo.view.ApprovalNodeView; +import com.xdap.self_development.pojo.dto.ApprovalNodeDTO; +import com.xdap.self_development.pojo.view.ApprovalFlowNodeView; +import com.xdap.self_development.pojo.view.FlowNode; import com.xdap.self_development.pojo.view.TemplateChangeView; import com.xdap.self_development.pojo.view.TodoAndTemplateView; import com.xdap.self_development.service.TemplateApprovalService; import com.xdap.self_development.service.XdapDeptUsersService; import com.xdap.self_development.utils.RedisLockUtil; import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -31,18 +29,12 @@ import java.util.stream.Collectors; @Service @Slf4j public class TemplateApprovalServiceImpl implements TemplateApprovalService { - @Autowired - private StringRedisTemplate redisTemplate; @Resource private BusinessDatabase bd; @Resource - private RuntimeDatasourceService runtimeDatasourceService; - @Resource private RedisLockUtil redisLockUtil; @Resource private XdapDeptUsersService xdapDeptUsersService; - @Autowired - private SWordLogger logger; // 分布式锁标志 private static final String FLOW_LOCK_PREFIX = "approval:lock:"; @@ -52,7 +44,7 @@ public class TemplateApprovalServiceImpl implements TemplateApprovalService { @Override @Transactional(rollbackFor = Exception.class) public String startApproval(StartApprovalRequest request) { - // 验证模板存在 + // 验证模板能否发起审批 Template template = bd.getBusinessDatabase() .rowid("id", request.getTemplateRowId()) .doQueryFirst(Template.class); @@ -80,16 +72,12 @@ public class TemplateApprovalServiceImpl implements TemplateApprovalService { throw new CommonException("空参数模板不允许发起审批"); } - // 2. 创建审批流程 + // 创建审批流程 ApprovalFlow flow = new ApprovalFlow(); flow.setTemplateId(template.getId()); - flow.setCurrentNode("PROOFREAD"); + flow.setCurrentNode(1); flow.setFlowStatus("APPROVING"); flow.setProcessTitle(request.getProcessTitle()); - flow.setProofreadUsers(JSON.toJSONString(request.getProofreadUsers())); - flow.setReviewUsers(JSON.toJSONString(request.getReviewUsers())); - flow.setCountersignUsers(JSON.toJSONString(request.getCountersignUsers())); - flow.setApproveUsers(JSON.toJSONString(request.getApproveUsers())); flow.setCreateBy(request.getUserId()); flow.setCreatedTime(Timestamp.valueOf(LocalDateTime.now())); flow.setFlowType(1); // 设置为模板审批流程 @@ -97,13 +85,43 @@ public class TemplateApprovalServiceImpl implements TemplateApprovalService { flow.setReturnNum(template.getReturnNum()); bd.getBusinessDatabase().doInsert(flow); + // 创建审批配置 + List approvalConfigs = new ArrayList<>(); + ApprovalNodeDTO firstNode = new ApprovalNodeDTO(); + boolean hasUsers = false; + int step = 0; + for (ApprovalNodeDTO node : request.getNodeList()) { + if (node.getAssignees().isEmpty()) { + hasUsers = true; + step++; + continue; + } + if (hasUsers) { + node.setNodeOrder(node.getNodeOrder() - step); + hasUsers = false; + step = 0; + } + if (node.getNodeOrder() == 1) { + firstNode.setNodeOrder(1); + firstNode.setAssignees(node.getAssignees()); + firstNode.setNodeName(node.getNodeName()); + } + ApprovalConfigPojo config = new ApprovalConfigPojo(); + config.setNodeName(node.getNodeName()); + config.setNodeOrder(node.getNodeOrder()); + config.setAssignees(JSON.toJSONString(node.getAssignees())); + config.setApprovalId(flow.getId()); + approvalConfigs.add(config); + } + bd.getBusinessDatabase().doBatchInsert(approvalConfigs); + // 新增待办 List list = new ArrayList<>(); - for (String person : request.getProofreadUsers()) { + for (String person : firstNode.getAssignees()) { TodoTaskPojo todoTask = new TodoTaskPojo(); todoTask.setCreatedById(request.getUserId()); todoTask.setCreatedBy(xdapDeptUsersService.selectUserByID(request.getUserId()).getUsername()); - todoTask.setCurrentNode(getNodeName(flow.getCurrentNode())); + todoTask.setCurrentNode(firstNode.getNodeName()); todoTask.setDataType("模板审核"); todoTask.setDocumentNo(flow.getId()); todoTask.setCreationDate(Timestamp.valueOf(LocalDateTime.now())); @@ -114,12 +132,12 @@ public class TemplateApprovalServiceImpl implements TemplateApprovalService { todoTask.setStatusCode(flow.getFlowStatus()); todoTask.setVersionNumber(template.getVersion()); todoTask.setOwnerId(person); - todoTask.setCurrentProcessor(JSON.toJSONString(getNodeUsers(flow, flow.getCurrentNode()))); + todoTask.setCurrentProcessor(JSON.toJSONString(firstNode.getAssignees())); list.add(todoTask); } bd.getBusinessDatabase().doBatchInsert(list); - // 3. 更新模板状态为校对中 + // 更新模板状态为校对中 template.setStatus("APPROVING"); bd.getBusinessDatabase() .rowid("id", template.getRowId()) @@ -128,8 +146,8 @@ public class TemplateApprovalServiceImpl implements TemplateApprovalService { return flow.getId(); } + // 查询所有流程 @Override - @Transactional public PageQueryResult getApprovalList(ApprovalListForm form) { PageQueryResult result = bd.getBusinessDatabase() .viewQueryMode(true) @@ -162,6 +180,7 @@ public class TemplateApprovalServiceImpl implements TemplateApprovalService { @Override @Transactional(rollbackFor = Exception.class) public void handleApproval(HandleApprovalRequest request) { + // 验证流程状态 ApprovalFlow flow = bd.getBusinessDatabase() .eq("id", request.getFlowId()) .eq("flow_type", 1) @@ -170,29 +189,32 @@ public class TemplateApprovalServiceImpl implements TemplateApprovalService { throw new CommonException("流程不存在或已结束"); } - String currentNode = flow.getCurrentNode(); + // 获取当前流程节点 + ApprovalConfigPojo currentNode = bd.getBusinessDatabase() + .eq("approval_id", flow.getId()) + .eq("node_order", flow.getCurrentNode()) + .doQueryFirst(ApprovalConfigPojo.class); + // 验证当前用户是否有权限处理 - if (!hasPermission(flow, currentNode, request.getUserId())) { + if (!hasPermission(currentNode, request.getUserId())) { throw new CommonException("无权限处理或已被处理"); } // 抢签节点 - if (!"COUNTERSIGN".equals(currentNode)) { - String lockKey = FLOW_LOCK_PREFIX + flow.getId() + ":" + currentNode; + if (!"会签".equals(currentNode.getNodeName())) { + String lockKey = FLOW_LOCK_PREFIX + flow.getId() + ":" + currentNode.getNodeName(); String lockValue = UUID.randomUUID().toString(); boolean lockAcquired = redisLockUtil .tryLock(lockKey, lockValue, FLOW_LOCK_EXPIRE_SECONDS, TimeUnit.SECONDS); - // 其他人正在处理 if (!lockAcquired) { throw new CommonException("当前节点正在处理,请稍后重试"); } try { int processedCount = bd.getBusinessDatabase() .eq("document_no", flow.getId()) - .eq("current_node", getNodeName(flow.getCurrentNode())) .eq("is_delete", 1) + .eq("current_node", currentNode.getNodeName()) .doQuery(TodoTaskPojo.class).size(); - // 已被其他人处理 if (processedCount > 0) { throw new CommonException("此节点已被他人处理"); } @@ -207,12 +229,18 @@ public class TemplateApprovalServiceImpl implements TemplateApprovalService { } } + // 验证是否为当前处理人 + private boolean hasPermission(ApprovalConfigPojo node, String userId) { + return JSON.parseArray(node.getAssignees()) + .toJavaList(String.class).contains(userId); + } + @Transactional(rollbackFor = Exception.class) - public void processApprovalLogic(ApprovalFlow flow, HandleApprovalRequest request, String currentNode) { + public void processApprovalLogic(ApprovalFlow flow, HandleApprovalRequest request, ApprovalConfigPojo currentNode) { // 记录审批结果 ApprovalRecord record = new ApprovalRecord(); record.setFlowId(flow.getId()); - record.setNode(currentNode); + record.setNode(currentNode.getNodeName()); record.setUserId(request.getUserId()); record.setOpinion(request.getOpinion()); record.setResult(request.getResult()); @@ -220,11 +248,11 @@ public class TemplateApprovalServiceImpl implements TemplateApprovalService { bd.getBusinessDatabase().doInsert(record); // 完成当前节点的已处理待办 - if (!"COUNTERSIGN".equals(flow.getCurrentNode())) { + if (!"会签".equals(currentNode.getNodeName())) { bd.getBusinessDatabase() .eq("document_no", flow.getId()) .ne("owner_id", request.getUserId()) - .eq("current_node", getNodeName(flow.getCurrentNode())) + .eq("current_node", currentNode.getNodeName()) .update("is_delete", 2) .update("last_update_date", Timestamp.valueOf(LocalDateTime.now())) .doUpdate(TodoTaskPojo.class); @@ -232,7 +260,7 @@ public class TemplateApprovalServiceImpl implements TemplateApprovalService { bd.getBusinessDatabase() .eq("document_no", flow.getId()) .eq("owner_id", request.getUserId()) - .eq("current_node", getNodeName(flow.getCurrentNode())) + .eq("current_node", currentNode.getNodeName()) .update("last_update_date", Timestamp.valueOf(LocalDateTime.now())) .update("is_delete", 1) .doUpdate(TodoTaskPojo.class); @@ -251,6 +279,144 @@ public class TemplateApprovalServiceImpl implements TemplateApprovalService { processNextNode(flow, currentNode, request.getUserId()); } + private void cancelProcess(ApprovalFlow flow, String status, String userId) { + // 更新流程状态 + flow.setFlowStatus(status); + bd.getBusinessDatabase() + .rowid("id", flow.getRowId()) + .update("flow_status", flow.getFlowStatus()) + .doUpdate(ApprovalFlow.class); + // 更新模板状态(重新打回草稿状态) + Template template = bd.getBusinessDatabase() + .eq("id", flow.getTemplateId()) + .doQueryFirst(Template.class); + template.setStatus("DRAFT"); + bd.getBusinessDatabase() + .rowid("id", template.getRowId()) + .update("status", template.getStatus()) + .update("return_num", template.getReturnNum() + 1) + .doUpdate(Template.class); + + bd.getBusinessDatabase() + .eq("document_no", flow.getId()) + .update("node", "已拒绝") + .doUpdate(TodoTaskPojo.class); + // 清除所有待办 + clearAllTodo(flow); + } + + private void clearAllTodo(ApprovalFlow flow) { + // 清除已有待办 + bd.getBusinessDatabase() + .eq("document_no", flow.getId()) + .eq("is_delete", 0) + .update("is_delete", 2) + .update("last_update_date", Timestamp.valueOf(LocalDateTime.now())) + .doUpdate(TodoTaskPojo.class); + } + + // 处理下一节点流转 + @Transactional(rollbackFor = Exception.class) + public void processNextNode(ApprovalFlow flow, ApprovalConfigPojo currentNode, String userId) { + // 检查当前节点是否满足流转条件 + if (!checkNodeComplete(flow, currentNode)) { + return; + } + + // 更新模板状态 + Template template = bd.getBusinessDatabase() + .eq("id", flow.getTemplateId()) + .doQueryFirst(Template.class); + // 获取下一个节点 + ApprovalConfigPojo nextNode = bd.getBusinessDatabase() + .eq("approval_id", flow.getId()) + .eq("node_order", currentNode.getNodeOrder() + 1) + .doQueryFirst(ApprovalConfigPojo.class); + if (nextNode == null) { + // 流程结束 + flow.setFlowStatus("COMPLETE"); + flow.setCurrentNode(null); + template.setStatus("COMPLETE"); + // 将同名的上一个版本的状态改为历史 + bd.getBusinessDatabase() + .eq("template_name", template.getTemplateName()) + .eq("version", template.getVersion() - 1) + .update("status", "HISTORY") + .doUpdate(Template.class); + // 将当前版本状态改为已发布 + bd.getBusinessDatabase() + .rowid("id", template.getRowId()) + .update("status", template.getStatus()) + .update("published_time", Timestamp.valueOf(LocalDateTime.now())) + .doUpdate(Template.class); + // 待办环节修改 + bd.getBusinessDatabase() + .eq("document_no", flow.getId()) + .update("node", "已完成") + .doUpdate(TodoTaskPojo.class); + // 更新机型版本 +// dataEntryEngineModelService.updateModelForNewVersion(); + } else { + flow.setCurrentNode(nextNode.getNodeOrder()); + addNodeTodo(flow, nextNode, template, userId); + } + + bd.getBusinessDatabase() + .rowid("id", flow.getRowId()) + .update("flow_status", flow.getFlowStatus()) + .update("current_node", flow.getCurrentNode()) + .doUpdate(ApprovalFlow.class); + } + + // 检查节点是否完成 + private boolean checkNodeComplete(ApprovalFlow flow, ApprovalConfigPojo node) { + Integer processedCount = bd.getBusinessDatabase() + .eq("document_no", flow.getId()) + .eq("is_delete", 1) + .eq("current_node", node.getNodeName()) + .doQuery(TodoTaskPojo.class).size(); + if ("会签".equals(node.getNodeName())) { + return processedCount.equals(JSON.parseArray(node.getAssignees()).size()); + } else { + return processedCount >= 1; + } + } + + private void addNodeTodo(ApprovalFlow flow, ApprovalConfigPojo node, Template template, String createBy) { + // 获取处理人 + List users = JSON.parseArray(node.getAssignees()).toJavaList(String.class); + // 新增待办 + List list = new ArrayList<>(); + for (String person : users) { + TodoTaskPojo todoTaskPojo = bd.getBusinessDatabase() + .eq("document_no", flow.getId()) + .eq("owner_id", person).doQueryFirst(TodoTaskPojo.class); + if (todoTaskPojo != null) { + todoTaskPojo.setCurrentNode(node.getNodeName()); + todoTaskPojo.setCurrentProcessor(JSON.toJSONString(node.getAssignees())); + bd.getBusinessDatabase().doUpdate(todoTaskPojo); + } else { + TodoTaskPojo todoTask = new TodoTaskPojo(); + todoTask.setCreatedById(createBy); + todoTask.setCreatedBy(xdapDeptUsersService.selectUserByID(createBy).getUsername()); + todoTask.setCurrentNode(node.getNodeName()); + todoTask.setDataType("模板审核"); + todoTask.setDocumentNo(flow.getId()); + todoTask.setCreationDate(Timestamp.valueOf(LocalDateTime.now())); + todoTask.setIsDelete(0); + todoTask.setModelId(template.getId()); + todoTask.setModelName(template.getTemplateName()); + todoTask.setProcessTitle(flow.getProcessTitle()); + todoTask.setStatusCode(flow.getFlowStatus()); + todoTask.setVersionNumber(template.getVersion()); + todoTask.setOwnerId(person); + todoTask.setCurrentProcessor(JSON.toJSONString(node.getAssignees())); + list.add(todoTask); + } + } + bd.getBusinessDatabase().doBatchInsert(list); + } + @Override public PageQueryResult getTemplateChanges(ApprovalAndParameterForm form) { Template template = bd.getBusinessDatabase() @@ -286,142 +452,98 @@ public class TemplateApprovalServiceImpl implements TemplateApprovalService { } @Override - public ApprovalFlowView getApprovalProcess(ApprovalFlowForm form) { - ApprovalFlowView approvalFlowView = new ApprovalFlowView(); - ApprovalFlow flow = bd.getBusinessDatabase() + public ApprovalFlowNodeView getApprovalProcess(ApprovalFlowForm form) { + ApprovalFlowNodeView flowNodeView = new ApprovalFlowNodeView(); + ApprovalFlow approvalFlow = bd.getBusinessDatabase() .eq("id", form.getFlowId()) - .eq("flow_type", 1) .doQueryFirst(ApprovalFlow.class); - - if (flow == null) { - return approvalFlowView; + // 无流程创建空返回 + if (approvalFlow == null) { + return flowNodeView; } Template template = bd.getBusinessDatabase() - .eq("id", flow.getTemplateId()) + .eq("id", approvalFlow.getTemplateId()) .doQueryFirst(Template.class); - approvalFlowView.setExplanation(flow.getExplanation()); - approvalFlowView.setFlowStatus(flow.getFlowStatus()); - if (!"APPROVING".equals(flow.getFlowStatus())) { - setAllCompletedNodes(approvalFlowView, flow); - return approvalFlowView; - } - processApprovalNodes(approvalFlowView, flow); - approvalFlowView.setProgressTitle(flow.getProcessTitle()); - approvalFlowView.setContentName(template.getTemplateName()); - approvalFlowView.setTemplateVersion(template.getVersion()); - return approvalFlowView; - } - - private void setAllCompletedNodes(ApprovalFlowView view, ApprovalFlow flow) { - view.setProofreadNodes(getNodeList(flow.getId(), "PROOFREAD")); - view.setReviewNodes(getNodeList(flow.getId(), "REVIEW")); - view.setCountersignNodes(getNodeList(flow.getId(), "COUNTERSIGN")); - view.setApproveNodes(getNodeList(flow.getId(), "APPROVE")); - } - - private void processApprovalNodes(ApprovalFlowView view, ApprovalFlow flow) { - // 处理校对节点 - List proofreadNodes = getNodeList(flow.getId(), "PROOFREAD"); - if (proofreadNodes.isEmpty()) { - view.setProofreadNodes(createApprovingNode(flow.getProofreadUsers())); - view.setReviewNodes(new ArrayList<>()); - view.setCountersignNodes(new ArrayList<>()); - view.setApproveNodes(new ArrayList<>()); - return; - } - view.setProofreadNodes(proofreadNodes); - - // 处理审核节点 - List reviewNodes = getNodeList(flow.getId(), "REVIEW"); - if (reviewNodes.isEmpty()) { - view.setReviewNodes(createApprovingNode(flow.getReviewUsers())); - view.setCountersignNodes(new ArrayList<>()); - view.setApproveNodes(new ArrayList<>()); - return; - } - view.setReviewNodes(reviewNodes); - - // 处理会签节点 - List countersignUserIds = JSON.parseArray(flow.getCountersignUsers()).toJavaList(String.class); - if (countersignUserIds.isEmpty()) { - view.setCountersignNodes(new ArrayList<>()); - } else { - List countersignNodes = getNodeList(flow.getId(), "COUNTERSIGN"); - if (countersignNodes.isEmpty()) { - view.setCountersignNodes(createApprovingNode(flow.getCountersignUsers())); - view.setApproveNodes(new ArrayList<>()); - return; - } else { - if (countersignNodes.size() == countersignUserIds.size()) { - view.setCountersignNodes(countersignNodes); + // 获取流程信息 + flowNodeView.setProgressTitle(approvalFlow.getProcessTitle()); + flowNodeView.setContentName(template.getTemplateName()); + flowNodeView.setTemplateVersion(template.getVersion()); + flowNodeView.setExplanation(approvalFlow.getExplanation()); + flowNodeView.setFlowStatus(approvalFlow.getFlowStatus()); + // 获取节点信息 + List nodes = bd.getBusinessDatabase() + .eq("approval_id", form.getFlowId()) + .doQuery(ApprovalConfigPojo.class); + List flowNodes = new ArrayList<>(); + nodes.forEach(node -> { + FlowNode nodeView = new FlowNode(); + if (Objects.equals(node.getNodeName(), "会签")) { + List records = bd.getBusinessDatabase() + .eq("flow_id", form.getFlowId()) + .eq("node", node.getNodeName()) + .doQuery(ApprovalRecord.class); + List results = records.stream() + .map(ApprovalRecord::getResult).collect(Collectors.toList()); + List reversedTime = records.stream().sorted(Comparator + .comparing(ApprovalRecord::getApprovalTime).reversed()).collect(Collectors.toList()); + if (records.size() == JSON.parseArray(node.getAssignees()).size()) { + // 节点已完成 + nodeView.setNodeOrder(node.getNodeOrder()); + nodeView.setResult(results.contains("REJECT") ? "REJECT" : "PASS"); + nodeView.setNode(node.getNodeName()); + nodeView.setUndoUserName(getUserNames(JSON.parseArray(node.getAssignees()).toJavaList(String.class))); + nodeView.setTodoUserName(getUserNames(JSON.parseArray(node.getAssignees()).toJavaList(String.class))); + nodeView.setApprovalTime(reversedTime.get(0).getApprovalTime()); + nodeView.setOpinions(records.stream().map(approvalRecord -> + getUserNames(Collections.singletonList(approvalRecord.getUserId())) + ":" + approvalRecord.getOpinion()).collect(Collectors.toList())); } else { - List completedUserIds = countersignNodes.stream() - .map(ApprovalNodeView::getUserId) - .collect(Collectors.toList()); - - List pendingUserIds = countersignUserIds.stream() - .filter(id -> !completedUserIds.contains(id)) - .collect(Collectors.toList()); - - if (!pendingUserIds.isEmpty()) { - countersignNodes.addAll(createApprovingNode(JSON.toJSONString(pendingUserIds))); - } - view.setCountersignNodes(countersignNodes); - view.setApproveNodes(new ArrayList<>()); - return; + // 节点未完成 + nodeView.setNodeOrder(node.getNodeOrder()); + nodeView.setNode(node.getNodeName()); + nodeView.setResult("待审批"); + List includedIds = records.stream().map(ApprovalRecord::getUserId).collect(Collectors.toList()); + nodeView.setTodoUserName(getUserNames(includedIds)); + nodeView.setUndoUserName(getUserNames(JSON.parseArray(node.getAssignees()).toJavaList(String.class))); } + } else { + ApprovalRecord record = bd.getBusinessDatabase() + .eq("flow_id", form.getFlowId()) + .eq("node", node.getNodeName()) + .doQueryFirst(ApprovalRecord.class); + nodeView.setNodeOrder(node.getNodeOrder()); + nodeView.setNode(node.getNodeName()); + if (record != null) { + // 节点已完成 + nodeView.setResult(record.getResult()); + nodeView.setOpinions(Collections.singletonList(getUserNames(Collections.singletonList(record.getUserId())) + ":" + record.getOpinion())); + nodeView.setApprovalTime(record.getApprovalTime()); + nodeView.setTodoUserName(getUserNames(Collections.singletonList(record.getUserId()))); + } else { + // 节点未完成 + nodeView.setResult("待审批"); + nodeView.setTodoUserName(""); + } + nodeView.setUndoUserName(getUserNames(JSON.parseArray(node.getAssignees()).toJavaList(String.class))); } - } - - List approveNodes = getNodeList(flow.getId(), "APPROVE"); - if (approveNodes.isEmpty()) { - view.setApproveNodes(createApprovingNode(flow.getApproveUsers())); - } else { - view.setApproveNodes(approveNodes); - } + flowNodes.add(nodeView); + }); + List sortedNode = flowNodes.stream().sorted(Comparator.comparing(FlowNode::getNodeOrder)).collect(Collectors.toList()); + flowNodeView.setFlowNodes(sortedNode); + return flowNodeView; } - private List createApprovingNode(String userJsonArray) { - List list = new ArrayList<>(); - - if (userJsonArray == null || userJsonArray.trim().isEmpty()) { - return list; - } - - List userIds = JSON.parseArray(userJsonArray).toJavaList(String.class); - if (userIds.isEmpty()) { - return list; - } - Map usersMap = batchQueryUsers(userIds); - StringBuilder usernames = new StringBuilder(); - for (String id : userIds) { - ApprovalXdapUsers user = usersMap.get(id); - if (user != null) { - usernames.append(user.getUsername()).append(" "); + private String getUserNames(List userIds) { + StringJoiner joiner = new StringJoiner(" "); + for (String userId : userIds) { + String username = bd.getBusinessDatabase().eq("id", userId).doQueryFirst(XdapUsers.class).getUsername(); + if (username != null) { + joiner.add(username); + } else { + // 处理空值情况 + joiner.add(userId); } } - if (usernames.length() > 0) { - ApprovalNodeView node = new ApprovalNodeView(); - node.setNode("APPROVING"); - node.setUserName(usernames.toString().trim()); - node.setResult("APPROVING"); - node.setApprovalTime(Timestamp.valueOf(LocalDateTime.now())); - list.add(node); - } - return list; - } - - private Map batchQueryUsers(List userIds) { - if (userIds == null || userIds.isEmpty()) { - return new HashMap<>(); - } - - List users = bd.getBusinessDatabase() - .in("id", userIds) - .doQuery(ApprovalXdapUsers.class); - - return users.stream() - .collect(Collectors.toMap(ApprovalXdapUsers::getId, user -> user)); + return joiner.toString(); } @Override @@ -438,10 +560,14 @@ public class TemplateApprovalServiceImpl implements TemplateApprovalService { if (!Objects.equals(flow.getFlowStatus(), "APPROVING")) { throw new CommonException("不在流程无法撤回"); } + ApprovalConfigPojo currentNode = bd.getBusinessDatabase() + .eq("approval_id", request.getFlowId()) + .eq("current_node", Integer.valueOf(flow.getCurrentNode())) + .doQueryFirst(ApprovalConfigPojo.class); if ("RETURN".equals(request.getResult())) { ApprovalRecord record = new ApprovalRecord(); record.setFlowId(flow.getId()); - record.setNode(flow.getCurrentNode()); + record.setNode(currentNode.getNodeName()); record.setUserId(request.getUserId()); record.setOpinion(request.getOpinion()); record.setResult(request.getResult()); @@ -450,215 +576,9 @@ public class TemplateApprovalServiceImpl implements TemplateApprovalService { // 申请人撤回 cancelProcess(flow, "RETURNED", request.getUserId()); - } - else { + } else { throw new CommonException("无法撤回"); } } - - private List getNodeList(String flowId, String node) { - List list = bd.getBusinessDatabase() - .viewQueryMode(true) - .view("getApprovalNodeInfo") - .setVar("flowId", flowId) - .setVar("node", node) - .doQuery(ApprovalNodeView.class); - if (list != null && !list.isEmpty()) { - list.forEach(approvalNodeView -> { - ApprovalXdapUsers user = runtimeDatasourceService.buildTenantNoSchemaMpaasQuery() - .eq("id", approvalNodeView.getUserId()) - .doQueryFirst(ApprovalXdapUsers.class); - approvalNodeView.setUserName(user.getUsername()); - }); - } - return list; - } - - // 处理下一节点流转 - @Transactional(rollbackFor = Exception.class) - public void processNextNode(ApprovalFlow flow, String currentNode, String userId) { - // 检查当前节点是否满足流转条件 - if (!checkNodeComplete(flow, currentNode)) { - return; // 未满足条件,不流转 - } - - // 更新模板状态 - Template template = bd.getBusinessDatabase() - .eq("id", flow.getTemplateId()) - .doQueryFirst(Template.class); - String nextNode = getNextNode(currentNode, flow); - - if (nextNode == null) { - // 流程结束 - flow.setFlowStatus("COMPLETE"); - flow.setCurrentNode(null); - template.setStatus("COMPLETE"); - // 将同名的上一个版本的状态改为历史 - bd.getBusinessDatabase() - .eq("template_name", template.getTemplateName()) - .eq("version", template.getVersion()-1) - .update("status", "HISTORY") - .doUpdate(Template.class); - // 将当前版本状态改为已发布 - bd.getBusinessDatabase() - .rowid("id", template.getRowId()) - .update("status", template.getStatus()) - .update("published_time", Timestamp.valueOf(LocalDateTime.now())) - .doUpdate(Template.class); - // 待办环节修改 - bd.getBusinessDatabase() - .eq("document_no", flow.getId()) - .update("node", "已完成") - .doUpdate(ApprovalNodeView.class); - // 更新机型版本 -// dataEntryEngineModelService.updateModelForNewVersion(); - } else { - flow.setCurrentNode(nextNode); - addNodeTodo(flow, nextNode, template, userId); - } - - bd.getBusinessDatabase() - .rowid("id", flow.getRowId()) - .update("flow_status", flow.getFlowStatus()) - .update("current_node", flow.getCurrentNode()) - .doUpdate(ApprovalFlow.class); - } - - // 获取下一节点 - private String getNextNode(String currentNode, ApprovalFlow flow) { - switch (currentNode) { - case "PROOFREAD": - return "REVIEW"; - case "REVIEW": - return flow.getCountersignUsers() != null && !JSON.parseArray(flow.getCountersignUsers()).isEmpty() - ? "COUNTERSIGN" : "APPROVE"; - case "COUNTERSIGN": - return "APPROVE"; - case "APPROVE": - return null; // 流程结束 - default: - return null; - } - } - - // 检查节点是否完成 - private boolean checkNodeComplete(ApprovalFlow flow, String node) { - Integer processedCount = bd.getBusinessDatabase() - .eq("document_no", flow.getId()) - .eq("is_delete", 1) - .eq("current_node", getNodeName(flow.getCurrentNode())) - .doQuery(TodoTaskPojo.class).size(); - // 会签节点需要所有人处理,其他节点只需1人 - if ("COUNTERSIGN".equals(node)) { - return processedCount.equals(JSON.parseArray(flow.getCountersignUsers()).size()); - } else { - return processedCount >= 1; - } - } - - private void cancelProcess(ApprovalFlow flow, String status, String userId) { - // 更新流程状态 - flow.setFlowStatus(status); - bd.getBusinessDatabase() - .rowid("id", flow.getRowId()) - .update("flow_status", flow.getFlowStatus()) - .doUpdate(ApprovalFlow.class); - // 更新模板状态(重新打回草稿状态) - Template template = bd.getBusinessDatabase() - .eq("id", flow.getTemplateId()) - .doQueryFirst(Template.class); - template.setStatus("DRAFT"); - bd.getBusinessDatabase() - .rowid("id", template.getRowId()) - .update("status", template.getStatus()) - .update("return_num", template.getReturnNum() + 1) - .doUpdate(Template.class); - - bd.getBusinessDatabase() - .eq("document_no", flow.getId()) - .update("node", "已拒绝") - .doUpdate(ApprovalNodeView.class); - // 清除所有待办 - clearAllTodo(flow); - } - - private boolean hasPermission(ApprovalFlow flow, String node, String userId) { - switch (node) { - case "PROOFREAD": - return JSON.parseArray(flow.getProofreadUsers()).toJavaList(String.class).contains(userId); - case "REVIEW": - return JSON.parseArray(flow.getReviewUsers()).toJavaList(String.class).contains(userId); - case "COUNTERSIGN": - return flow.getCountersignUsers() != null && JSON.parseArray(flow.getCountersignUsers()).toJavaList(String.class).contains(userId); - case "APPROVE": - return JSON.parseArray(flow.getApproveUsers()).toJavaList(String.class).contains(userId); - default: - return false; - } - } - - private void addNodeTodo(ApprovalFlow flow, String node, Template template, String createBy) { - List users = getNodeUsers(flow, node); - // 新增待办 - List list = new ArrayList<>(); - for (String person : users) { - TodoTaskPojo todoTaskPojo = bd.getBusinessDatabase() - .eq("document_no", flow.getId()) - .eq("owner_id", person).doQueryFirst(TodoTaskPojo.class); - if (todoTaskPojo != null) { - todoTaskPojo.setCurrentNode(getNodeName(node)); - todoTaskPojo.setCurrentProcessor(JSON.toJSONString(getNodeUsers(flow, node))); - bd.getBusinessDatabase().doUpdate(todoTaskPojo); - } else { - TodoTaskPojo todoTask = new TodoTaskPojo(); - todoTask.setCreatedById(createBy); - todoTask.setCreatedBy(xdapDeptUsersService.selectUserByID(createBy).getUsername()); - todoTask.setCurrentNode(getNodeName(node)); - todoTask.setDataType("模板审核"); - todoTask.setDocumentNo(flow.getId()); - todoTask.setCreationDate(Timestamp.valueOf(LocalDateTime.now())); - todoTask.setIsDelete(0); - todoTask.setModelId(template.getId()); - todoTask.setModelName(template.getTemplateName()); - todoTask.setProcessTitle(flow.getProcessTitle()); - todoTask.setStatusCode(flow.getFlowStatus()); - todoTask.setVersionNumber(template.getVersion()); - todoTask.setOwnerId(person); - todoTask.setCurrentProcessor(JSON.toJSONString(getNodeUsers(flow, flow.getCurrentNode()))); - list.add(todoTask); - } - } - bd.getBusinessDatabase().doBatchInsert(list); - } - - private void clearAllTodo(ApprovalFlow flow) { - // 清除已有待办 - bd.getBusinessDatabase() - .eq("document_no", flow.getId()) - .eq("is_delete", 0) - .update("is_delete", 2) - .update("last_update_date", Timestamp.valueOf(LocalDateTime.now())) - .doUpdate(TodoTaskPojo.class); - } - - private List getNodeUsers(ApprovalFlow flow, String node) { - switch (node) { - case "PROOFREAD": return JSON.parseArray(flow.getProofreadUsers()).toJavaList(String.class); - case "REVIEW": return JSON.parseArray(flow.getReviewUsers()).toJavaList(String.class); - case "COUNTERSIGN": return JSON.parseArray(flow.getCountersignUsers()).toJavaList(String.class); - case "APPROVE": return JSON.parseArray(flow.getApproveUsers()).toJavaList(String.class); - default: return Collections.emptyList(); - } - } - - private String getNodeName(String node) { - switch (node) { - case "PROOFREAD": return "校对"; - case "REVIEW": return "审核"; - case "COUNTERSIGN": return "会签"; - case "APPROVE": return "批准"; - default: return "-"; - } - } }