Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions backend/crm/src/main/java/cn/cordys/common/constants/FormKey.java
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
package cn.cordys.common.constants;

import lombok.Getter;
import org.apache.commons.lang3.Strings;

import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
Expand Down Expand Up @@ -79,4 +81,17 @@ public enum FormKey {
public static List<String> allKeys() {
return Arrays.stream(FormKey.values()).map(FormKey::getKey).collect(Collectors.toList());
}

public static FormKey ofKey(String key) {
for (FormKey formKey : FormKey.values()) {
if (Strings.CI.equals(formKey.getKey(), key)) {
return formKey;
}
}
return null;
}

public boolean hasSnapshot() {
return Strings.CI.equalsAny(this.key, CONTRACT.getKey(), INVOICE.getKey(), QUOTATION.getKey());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ public void handleHitApproval(JoinPoint joinPoint, Object retValue) {

if (hit) {
// 命中审批流, 修改业务资源审批状态为待提审
approvalResourceService.updateApprovalStatus(annotation.formKey(), resourceId, ApprovalStatus.PENDING.name());
approvalResourceService.updateResourceApprovalStatus(annotation.formKey(), resourceId, ApprovalStatus.PENDING.name());
}
} catch (Exception e) {
log.error("审批流执行时机匹配失败,error:{}", e.getMessage(), e);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ public class ApprovalRecord extends BaseModel {
@Schema(description = "任务ID")
private String taskId;

@Schema(description = "节点轮次")
private Integer nodeRound;

@Schema(description = "节点ID")
private String nodeId;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ public class ApprovalTask extends BaseModel {
@Schema(description = "节点ID")
private String nodeId;

@Schema(description = "节点轮次")
private Integer nodeRound;

@Schema(description = "审批实例ID")
private String instanceId;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,16 @@ public class ApprovalInstanceDetail {
@Schema(description = "提交人ID")
private String submitterId;

@Schema(description = "提交人头像")
private String submitAvatar;

@Schema(description = "提交人")
private String submitter;

@Schema(description = "提交时间")
private Long submitTime;

@Schema(description = "审批结果")
private String result;

@Schema(description = "审批实例状态")
@Schema(description = "审批状态")
private String approvalStatus;

@Schema(description = "当前节点ID")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ public class ApprovalRecordNode {
@Schema(description = "节点ID")
private String nodeId;

@Schema(description = "节点轮次")
private Integer nodeRound;

@Schema(description = "审批状态")
private String approvalStatus;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,5 +43,5 @@ public class ApprovalTaskNode {
private Long approvalTime;

@Schema(description = "是否加签任务")
private boolean isAddSign;
private boolean sign;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package cn.cordys.crm.approval.dto;

import lombok.Builder;
import lombok.Data;

@Data
@Builder
public class ResourceSnapshotApprovalParam {

private String resourceId;
private String approvalStatus;
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,14 @@ void updateApprovalStatus(@Param("sourceTable") String sourceTable, @Param("id")
String selectBusinessName(@Param("sourceTable") String sourceTable, @Param("id") String id);

String getResourceOwner(@Param("sourceTable")String sourceTable, @Param("id")String id);

/**
* 获取节点下一个执行轮次
* 从 approval_task 和 approval_record 中一起获取,取最大轮次 +1
*
* @param instanceId 审批实例ID
* @param nodeId 节点ID
* @return 下一个轮次
*/
Integer getNextNodeRound(@Param("instanceId") String instanceId, @Param("nodeId") String nodeId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,11 @@
<select id="getResourceOwner" resultType="java.lang.String">
select owner from ${sourceTable} where id = #{id}
</select>

<select id="getNextNodeRound" resultType="java.lang.Integer">
SELECT IFNULL(GREATEST(
(SELECT MAX(node_round) FROM approval_task WHERE instance_id = #{instanceId} AND node_id = #{nodeId}),
(SELECT MAX(node_round) FROM approval_record WHERE instance_id = #{instanceId} AND node_id = #{nodeId})
), 0) + 1
</select>
</mapper>
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import cn.cordys.common.exception.GenericException;
import cn.cordys.common.uid.IDGenerator;
import cn.cordys.common.util.BeanUtils;
import cn.cordys.common.util.CommonBeanFactory;
import cn.cordys.common.util.Translator;
import cn.cordys.crm.approval.constants.*;
import cn.cordys.crm.approval.domain.*;
Expand Down Expand Up @@ -92,11 +93,11 @@ public void sign(ApprovalAddSignRequest request, String userId, String orgId) {
throw new GenericException(Translator.get("no.operation.permission"));
}
ApprovalInstance instance = approvalInstanceMapper.selectByPrimaryKey(request.getInstanceId());
// 刷新被加签任务状态 && 插入审批记录
ApprovalTask currentTask = saveActionTask(request, ApprovalAction.SIGN, userId, orgId, ApprovalAddSignType.valueOf(request.getType()));
// 加签操作的待办任务
ApprovalTask appendActionTask = appendSignTask(request, userId);
ApprovalTask appendActionTask = appendSignTask(request, userId, currentTask.getNodeRound());
ApprovalAddSignTask addSignTask = saveAddSignTask(request, appendActionTask.getId());
// 刷新被加签任务状态 && 插入审批记录
saveActionTask(request, ApprovalAction.SIGN, userId, orgId, ApprovalAddSignType.valueOf(request.getType()));
// 之后加签(多人或签), 需要刷新实例当前审批节点
if (ApprovalAddSignType.valueOf(request.getType()) == ApprovalAddSignType.AFTER && isMultiAnyMode(appendActionTask.getNodeId(), userId, orgId)) {
ApprovalNodeResponse nextNode = approvalFlowService.getTaskNextNode(appendActionTask, instance, orgId);
Expand Down Expand Up @@ -231,10 +232,11 @@ private void saveInstanceAttachment(List<String> attachmentIds, String instanceI
* @param request 加签参数
* @param userId 当前用户
*/
private ApprovalTask appendSignTask(ApprovalActionRequest request, String userId) {
private ApprovalTask appendSignTask(ApprovalActionRequest request, String userId, int round) {
ApprovalTask approvalTask = new ApprovalTask();
BeanUtils.copyBean(approvalTask, request);
approvalTask.setId(IDGenerator.nextStr());
approvalTask.setNodeRound(round);
approvalTask.setCreateTime(System.currentTimeMillis());
approvalTask.setUpdateTime(System.currentTimeMillis());
approvalTask.setCreateUser(userId);
Expand Down Expand Up @@ -287,6 +289,7 @@ private void saveApprovalRecord(ApprovalTask currentTask, String comment, List<S
record.setId(IDGenerator.nextStr());
record.setInstanceId(currentTask.getInstanceId());
record.setTaskId(currentTask.getId());
record.setNodeRound(currentTask.getNodeRound());
record.setNodeId(currentTask.getNodeId());
record.setComment(comment);
record.setCreateTime(System.currentTimeMillis());
Expand Down Expand Up @@ -334,7 +337,7 @@ private void approvedProcess(ApprovalTask currentTask, String currentUserId, Str
if (approvingTasks.isEmpty()) {
User nextUser = getMultiSeqNextOne(currentTask.getNodeId(), currentTask.getInstanceId(), currentOrgId);
if (nextUser != null) {
ApprovalTask multiSeqNextTask = buildTask(currentTask.getNodeId(), currentTask.getInstanceId(), nextUser.getId(), ApprovalTaskType.NL.name(), currentUserId);
ApprovalTask multiSeqNextTask = buildTask(currentTask.getNodeId(), currentTask.getInstanceId(), nextUser.getId(), ApprovalTaskType.NL.name(), currentUserId, currentTask.getNodeRound());
approvalTaskMapper.insert(multiSeqNextTask);
}
}
Expand Down Expand Up @@ -374,6 +377,10 @@ private void rejectProcess(ApprovalTask currentTask, String currentUserId, Strin
if (!multiNode || nodeRejected) {
// 单人审批或者多人审批但节点流转失败, 实例直接驳回结束
approvalInstanceService.rejectApprovalInstance(instance, currentUserId);
ApprovalResourceService resourceService = CommonBeanFactory.getBean(ApprovalResourceService.class);
if (resourceService != null) {
resourceService.updateResourceApprovalStatus(FormKey.ofKey(instance.getType()), instance.getResourceId(), instance.getApprovalStatus());
}
}
}

Expand Down Expand Up @@ -833,6 +840,10 @@ private void handleNextApprovalNode(ApprovalNodeResponse node, ApprovalInstance
instance.setApprovalTime(System.currentTimeMillis());
}
approvalInstanceMapper.updateById(instance);
ApprovalResourceService resourceService = CommonBeanFactory.getBean(ApprovalResourceService.class);
if (resourceService != null) {
resourceService.updateResourceApprovalStatus(FormKey.ofKey(instance.getType()), instance.getResourceId(), instance.getApprovalStatus());
}
if (ApprovalNodeTypeEnum.valueOf(node.getNodeType()) == ApprovalNodeTypeEnum.APPROVER) {
List<ApprovalTask> approvalTasks = getNodeApproverTasks((ApprovalNodeApproverResponse) node, instance.getId(), currentUserId, ApprovalTaskType.NL.name());
List<ApprovalTask> ccTasks = getNodeCcTasks((ApprovalNodeApproverResponse) node, instance.getId(), currentUserId);
Expand Down Expand Up @@ -882,9 +893,10 @@ public List<ApprovalTask> getNodeApproverTasks(ApprovalNodeApproverResponse appr
if (approverNode == null) {
return approvalTasks;
}
Integer nextRound = extApprovalInstanceMapper.getNextNodeRound(instanceId, approverNode.getId());
if (org.apache.commons.collections4.CollectionUtils.isNotEmpty(approverNode.getApproverList())) {
approverNode.getApproverList().forEach(approver -> {
ApprovalTask approvalTask = buildTask(approverNode.getId(), instanceId, approver, taskType, userId);
ApprovalTask approvalTask = buildTask(approverNode.getId(), instanceId, approver, taskType, userId, nextRound);
approvalTasks.add(approvalTask);
});
}
Expand All @@ -896,19 +908,21 @@ public List<ApprovalTask> getNodeCcTasks(ApprovalNodeApproverResponse approverNo
if (approverNode == null) {
return approvalTasks;
}
Integer nextRound = extApprovalInstanceMapper.getNextNodeRound(instanceId, approverNode.getId());
if (org.apache.commons.collections4.CollectionUtils.isNotEmpty(approverNode.getCcList())) {
approverNode.getCcList().forEach(cc -> {
ApprovalTask approvalTask = buildTask(approverNode.getId(), instanceId, cc, ApprovalTaskType.CC.name(), userId);
ApprovalTask approvalTask = buildTask(approverNode.getId(), instanceId, cc, ApprovalTaskType.CC.name(), userId, nextRound);
approvalTasks.add(approvalTask);
});
}
return approvalTasks;
}

public ApprovalTask buildTask(String nodeId, String instanceId, String approverId, String taskType, String currentUserId) {
public ApprovalTask buildTask(String nodeId, String instanceId, String approverId, String taskType, String currentUserId, Integer round) {
ApprovalTask approvalTask = new ApprovalTask();
approvalTask.setId(IDGenerator.nextStr());
approvalTask.setNodeId(nodeId);
approvalTask.setNodeRound(round);
approvalTask.setInstanceId(instanceId);
approvalTask.setApproverId(approverId);
approvalTask.setStatus(ApprovalStatus.APPROVING.name());
Expand All @@ -934,14 +948,15 @@ private List<ApprovalTask> getNodeApproverTasks(String currentNodeId, String ins
List<ApprovalTask> approvalTasks = new ArrayList<>();
ApprovalNodeApprover approvalNodeApprover = approvalNodeApproverMapper.selectByPrimaryKey(currentNodeId);
List<User> approvers = approvalFlowService.getCurrentNodeApproverList(currentNodeId, userId, currentOrgId);
Integer nextRound = extApprovalInstanceMapper.getNextNodeRound(instanceId, currentNodeId);
if (Strings.CI.equals(approvalNodeApprover.getMultiApproverMode(), MultiApproverModeEnum.SEQUENTIAL.name()) || approvers.size() == 1) {
// 单人或者依次审批, 只会产生一条待办任务
User approverUser = approvers.getFirst();
approvalTasks.add(buildTask(currentNodeId, instanceId, approverUser.getId(), taskType, userId));
approvalTasks.add(buildTask(currentNodeId, instanceId, approverUser.getId(), taskType, userId, nextRound));
} else {
// 多人审批, 且为会签或签方式
approvers.forEach(approver -> {
ApprovalTask approvalTask = buildTask(currentNodeId, instanceId, approver.getId(), taskType, userId);
ApprovalTask approvalTask = buildTask(currentNodeId, instanceId, approver.getId(), taskType, userId, nextRound);
approvalTasks.add(approvalTask);
});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
import cn.cordys.crm.approval.dto.response.*;
import cn.cordys.crm.approval.log.ApprovalFlowLogDTO;
import cn.cordys.crm.approval.mapper.ExtApprovalFlowMapper;
import cn.cordys.crm.approval.mapper.ExtApprovalInstanceMapper;
import cn.cordys.crm.system.domain.Department;
import cn.cordys.crm.system.domain.OrganizationUser;
import cn.cordys.crm.system.domain.User;
Expand Down Expand Up @@ -99,7 +100,7 @@ public class ApprovalFlowService {
@Resource
private UserViewService userViewService;
@Resource
private BaseMapper<ApprovalTask> approvalTaskMapper;
private ExtApprovalInstanceMapper extApprovalInstanceMapper;

/**
* 根据表单类型获取审批流状态权限配置
Expand Down Expand Up @@ -1653,7 +1654,7 @@ private ApprovalNodeResponse getNextNodeWithExceptionHandler(ApprovalInstance in
return getNextNodeWithExceptionHandler(instance, nodeId, fieldValues, currentOrgId);
}
if (ApprovalTypeEnum.valueOf(nextApproverNode.getApprovalType()) == ApprovalTypeEnum.AUTO_REJECT) {
// 自动驳回, 插入审批记录,
// 自动驳回, 插入审批记录
saveAutoRecord(instance.getId(), nodeId, ApprovalStatus.UNAPPROVED, null);
ApprovalNodeExceptionResponse exNode = BeanUtils.copyBean(new ApprovalNodeExceptionResponse(), nextApproverNode);
exNode.setNodeType(ApprovalNodeTypeEnum.EXCEPTION.name());
Expand Down Expand Up @@ -1706,10 +1707,12 @@ private ApprovalNodeResponse getNextNodeWithExceptionHandler(ApprovalInstance in
* @param approvalStatus 审批状态
*/
private void saveAutoRecord(String instanceId, String nodeId, ApprovalStatus approvalStatus, String comment) {
Integer nextRound = extApprovalInstanceMapper.getNextNodeRound(instanceId, nodeId);
ApprovalRecord record = new ApprovalRecord();
record.setId(IDGenerator.nextStr());
record.setInstanceId(instanceId);
record.setNodeId(nodeId);
record.setNodeRound(nextRound);
record.setResult(approvalStatus.name());
if (StringUtils.isBlank(comment)) {
record.setComment(approvalStatus == ApprovalStatus.APPROVED ? Translator.get("auto.approval.passed") : Translator.get("auto.approval.rejected"));
Expand Down
Loading
Loading