feat(REQ-4468) - 增加审批人的组织架构快照数据保存

This commit is contained in:
wangli 2025-06-28 15:25:10 +08:00
parent 6b5099e0de
commit 289a6e22b6
18 changed files with 430 additions and 12 deletions

View File

@ -80,6 +80,9 @@ public interface BpmnConstants {
String TEMPLATE_SIGN_PENDING_MESSAGE_ID = "signPendingMessageId";
String TEMPLATE_CARBON_COPY_MESSAGE_ID = "carbonCopyMessageId";
String TEMPLATE_SMS_MESSAGE_ID = "smsMessageId";
String TEMPLATE_UPGRADE_APPROVAL_CONF = "upgradeApprovalConf";
String TEMPLATE_UPGRADE_APPROVAL_LIMIT_CONF = "limitConfig";
String TEMPLATE_UPGRADE_APPROVAL_SPECIFY_VALUE = "specifyValue";
String APPROVE_SUPPORT_BATCH_OPERATION = "supportBatchOperation";
String APPROVE_USER_AGREE_SIGNATURE = "userAgreeSignature";
String CONFIG_BUTTON = "buttonConfig";
@ -117,6 +120,8 @@ public interface BpmnConstants {
String ELEMENT_ATTRIBUTE_CHECKED = "checked";
String ELEMENT_ATTRIBUTE_DISABLED = "disabled";
String ELEMENT_ATTRIBUTE_TYPE = "type";
String ELEMENT_ATTRIBUTE_ORG_LIMIT = "orgLimit";
String ELEMENT_ATTRIBUTE_APPROVER_SPECIFY = "approverSpecify";
String START_EVENT_ID = "startEventNode";
String SEQUENCE_FLOW_ID = "SequenceFlowId";
String END_EVENT_ID = "endEventNode";
@ -236,4 +241,8 @@ public interface BpmnConstants {
*/
String SIGNATORIES = "[_SIGNATORIES_]";
String TASK_SUBMIT_FORM_VARIABLE = "[_TASK_SUBMIT_FORM_VARIABLE_]";
/**
* 提级审批变量标识
*/
String SUPPORT_UPGRADE_VARIABLE = "[_SUPPORT_UPGRADE_]";
}

View File

@ -55,10 +55,14 @@ public enum BpmnButtonEnum {
* 抄送按钮
*/
BPMN_COPY(10, "BPMN_COPY", "抄送", Lists.newArrayList(APPROVAL, SIGN)),
/**
* 提级审批按钮
*/
BPMN_UPGRADE(12, "BPMN_UPGRADE", "提级审批", Lists.newArrayList(APPROVAL, SIGN)),
/**
* 管理员转交按钮
*/
BPMN_ADMIN_TRANSFER(11, "BPMN_ADMIN_TRANSFER", "管理员转交", Lists.newArrayList());
BPMN_ADMIN_TRANSFER(99, "BPMN_ADMIN_TRANSFER", "管理员转交", Lists.newArrayList());
public int getOrder() {

View File

@ -16,6 +16,7 @@ public enum SignApproverOrgLimitEnum {
LV_3("LV_3", "上3级组织", 3),
LV_4("LV_4", "上4级组织", 4),
LV_5("LV_5", "上5级组织", 5),
LV_ALL("LV_ALL", "所有组织", -1),
;
private final String type;

View File

@ -0,0 +1,28 @@
package cn.axzo.workflow.common.model.dto;
import lombok.Builder;
import lombok.Data;
import java.io.Serializable;
/**
* 岗位信息
*
* @author wangli
* @since 2025-06-23 19:35
*/
@Data
@Builder
public class JobInfo implements Serializable {
private static final long serialVersionUID = -6092011348559752255L;
/**
* 岗位名称
*/
private String jobName;
/**
* 岗位编码
*/
private String jobCode;
}

View File

@ -0,0 +1,59 @@
package cn.axzo.workflow.common.model.dto;
import lombok.Builder;
import lombok.Data;
import java.io.Serializable;
/**
* 组织架构中的项目快照信息
*
* @author wangli
* @since 2025-06-23 18:31
*/
@Data
@Builder
public class OrgSnapshotInfo implements Serializable {
private static final long serialVersionUID = -2898438378034300663L;
/**
* 工作台名称
*/
private String workspaceName;
/**
* 工作台 ID
*/
private String workspaceId;
/**
* 工作台类型
*/
private Integer workspaceType;
/**
* 参建单位类型
*/
private Integer cooperationType;
/**
* 参建单位名称
*/
private String ouName;
/**
* 参建单位 ID
*/
private String ouId;
/**
* 顶级节点 ID
*/
private String topNodeId;
/**
* 别名
*/
private String alias;
}

View File

@ -0,0 +1,45 @@
package cn.axzo.workflow.common.model.dto;
import lombok.Builder;
import lombok.Data;
import java.io.Serializable;
import java.util.List;
/**
* 审批人员的组织架构信息
*
* @author wangli
* @since 2025-06-23 18:23
*/
@Data
@Builder
public class OrgStructureSnapshotInfo implements Serializable {
private static final long serialVersionUID = 4199079714585922731L;
/**
* 审批人姓名
*/
private String personName;
/**
* 审批人顶级节点 ID
*/
private Long topNodeId;
/**
* 项目快照信息
*/
private OrgSnapshotInfo projectInfo;
/**
* 企业快照信息
*/
private OrgSnapshotInfo entInfo;
/**
* 岗位快照信息集合
*/
private List<JobInfo> jobInfos;
}

View File

@ -47,6 +47,10 @@ public class BpmnButtonMetaInfo implements Serializable {
* 是否禁用勾选
*/
private Boolean disabled;
/**
* 是否隐藏按钮
*/
private Boolean hidden = false;
/**
* 按钮类型 SYSTEM/CUSTOM

View File

@ -0,0 +1,45 @@
package cn.axzo.workflow.common.model.request.bpmn;
import cn.axzo.workflow.common.enums.ApproverSpecifyEnum;
import cn.axzo.workflow.common.enums.SignApproverOrgLimitEnum;
import io.swagger.annotations.ApiModel;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import java.io.Serializable;
/**
* JSON 版本的 BPMN 协议模型中的提级审批配置模型
*
* @author wangli
* @since 2025-06-20 11:32
*/
@ApiModel("JSON 版本的 BPMN 协议模型中的提级审批配置模型")
@Data
@NoArgsConstructor
@Accessors(chain = true)
public class BpmnUpgradeApprovalConf implements Serializable {
private static final long serialVersionUID = 36282987684860776L;
/**
* 是否已开启
*/
private Boolean enabled;
/**
* 提级审批的审批人层级范围限制
*/
private SignApproverOrgLimitEnum orgLimit;
/**
* 提级审批的审批人指定方式
*/
private ApproverSpecifyEnum approverSpecify;
/**
* 提级审批的审批人指定具体值
*/
private String specifyValue;
}

View File

@ -0,0 +1,30 @@
package cn.axzo.workflow.common.model.request.bpmn.task;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
/**
* 一些审批人模型的扩展信息
*
* @author wangli
* @since 2025-06-28 13:17
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
@Accessors(chain = true)
public abstract class BaseBpmnTaskDelegateAssigner {
/**
* 人员标签
* 0: 注销 1离场 2: 离职
*/
private Integer tag;
/**
* 是否能提级审批
*/
private Boolean supportUpgradeApproval;
}

View File

@ -5,6 +5,7 @@ import com.google.common.collect.Lists;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import lombok.extern.slf4j.Slf4j;
@ -34,6 +35,7 @@ import static cn.axzo.workflow.common.constant.BpmnConstants.ROBOT_ASSIGNEE_ID;
*
* @author wangli
*/
@EqualsAndHashCode(callSuper = true)
@Data
@Builder
@NoArgsConstructor
@ -41,7 +43,7 @@ import static cn.axzo.workflow.common.constant.BpmnConstants.ROBOT_ASSIGNEE_ID;
@Accessors(chain = true)
@Validated
@Slf4j
public class BpmnTaskDelegateAssigner implements Serializable {
public class BpmnTaskDelegateAssigner extends BaseBpmnTaskDelegateAssigner implements Serializable {
private static final long serialVersionUID = -8106887960942113552L;

View File

@ -9,6 +9,7 @@ import java.util.Arrays;
* @since 2023/9/18 17:11
*/
public enum BpmnProcessTaskResultEnum {
HANDLING("HANDLING", "审批中"), // 修改这里
PENDING("PENDING", "待处理"),
PROCESSED("PROCESSED", "已处理"),
AUTO_SKIP("AUTO_SKIP", "任务自动跳过"),

View File

@ -26,6 +26,7 @@ import cn.axzo.workflow.common.model.request.bpmn.BpmnSignApproverLimit;
import cn.axzo.workflow.common.model.request.bpmn.BpmnSignConf;
import cn.axzo.workflow.common.model.request.bpmn.BpmnSignPendingProperty;
import cn.axzo.workflow.common.model.request.bpmn.BpmnSmsProperty;
import cn.axzo.workflow.common.model.request.bpmn.BpmnUpgradeApprovalConf;
import cn.axzo.workflow.common.model.request.form.FormPermissionMetaInfo;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
@ -83,12 +84,14 @@ import static cn.axzo.workflow.common.constant.BpmnConstants.CONFIG_SIGN_APPROVE
import static cn.axzo.workflow.common.constant.BpmnConstants.CONFIG_SIGN_APPROVER_ORG_LIMIT;
import static cn.axzo.workflow.common.constant.BpmnConstants.CONFIG_SIGN_APPROVER_ROLE_LIMIT;
import static cn.axzo.workflow.common.constant.BpmnConstants.CONFIG_SIGN_TYPE;
import static cn.axzo.workflow.common.constant.BpmnConstants.ELEMENT_ATTRIBUTE_APPROVER_SPECIFY;
import static cn.axzo.workflow.common.constant.BpmnConstants.ELEMENT_ATTRIBUTE_CHECKED;
import static cn.axzo.workflow.common.constant.BpmnConstants.ELEMENT_ATTRIBUTE_CODE;
import static cn.axzo.workflow.common.constant.BpmnConstants.ELEMENT_ATTRIBUTE_DISABLED;
import static cn.axzo.workflow.common.constant.BpmnConstants.ELEMENT_ATTRIBUTE_KEY;
import static cn.axzo.workflow.common.constant.BpmnConstants.ELEMENT_ATTRIBUTE_NAME;
import static cn.axzo.workflow.common.constant.BpmnConstants.ELEMENT_ATTRIBUTE_ORDER;
import static cn.axzo.workflow.common.constant.BpmnConstants.ELEMENT_ATTRIBUTE_ORG_LIMIT;
import static cn.axzo.workflow.common.constant.BpmnConstants.ELEMENT_ATTRIBUTE_TYPE;
import static cn.axzo.workflow.common.constant.BpmnConstants.ELEMENT_ATTRIBUTE_VALUE;
import static cn.axzo.workflow.common.constant.BpmnConstants.FLOW_SERVER_VERSION;
@ -105,6 +108,9 @@ import static cn.axzo.workflow.common.constant.BpmnConstants.TEMPLATE_NOTICE_MES
import static cn.axzo.workflow.common.constant.BpmnConstants.TEMPLATE_PENDING_MESSAGE_ID;
import static cn.axzo.workflow.common.constant.BpmnConstants.TEMPLATE_SIGN_PENDING_MESSAGE_ID;
import static cn.axzo.workflow.common.constant.BpmnConstants.TEMPLATE_SMS_MESSAGE_ID;
import static cn.axzo.workflow.common.constant.BpmnConstants.TEMPLATE_UPGRADE_APPROVAL_CONF;
import static cn.axzo.workflow.common.constant.BpmnConstants.TEMPLATE_UPGRADE_APPROVAL_LIMIT_CONF;
import static cn.axzo.workflow.common.constant.BpmnConstants.TEMPLATE_UPGRADE_APPROVAL_SPECIFY_VALUE;
import static cn.axzo.workflow.common.constant.BpmnConstants.USER_AGREE_SIGNATURE_DEFAULT_VALUE;
/**
@ -570,6 +576,26 @@ public final class BpmnMetaParserHelper {
return permissionResult;
}
public static Optional<BpmnUpgradeApprovalConf> getUpgradeApprovalConf(FlowElement flowElement) {
if (Objects.isNull(flowElement) || !(flowElement instanceof UserTask)) {
return Optional.empty();
}
return getUpgradeApprovalConf((UserTask) flowElement);
}
public static Optional<BpmnUpgradeApprovalConf> getUpgradeApprovalConf(UserTask userTask) {
return defaultValid(userTask, TEMPLATE_UPGRADE_APPROVAL_CONF).map(element -> {
BpmnUpgradeApprovalConf conf = new BpmnUpgradeApprovalConf();
Boolean enabled = Boolean.valueOf(element.getAttributeValue(null, ELEMENT_ATTRIBUTE_CHECKED));
conf.setEnabled(enabled);
if(Objects.equals(Boolean.TRUE, enabled)) {
conf.setOrgLimit(SignApproverOrgLimitEnum.valueOfType(element.getChildElements().get(TEMPLATE_UPGRADE_APPROVAL_LIMIT_CONF).get(0).getAttributeValue(null, ELEMENT_ATTRIBUTE_ORG_LIMIT)));
conf.setApproverSpecify(ApproverSpecifyEnum.valueOf(element.getChildElements().get(TEMPLATE_UPGRADE_APPROVAL_LIMIT_CONF).get(0).getAttributeValue(null, ELEMENT_ATTRIBUTE_APPROVER_SPECIFY)));
conf.setSpecifyValue(element.getChildElements().get(TEMPLATE_UPGRADE_APPROVAL_SPECIFY_VALUE).get(0).getElementText());
}
return conf;
});
}
private static int performBitwiseOr(int... numbers) {
int result = 0;

View File

@ -1,6 +1,7 @@
package cn.axzo.workflow.core.repository.entity;
import cn.axzo.framework.data.mybatisplus.model.BaseEntity;
import cn.axzo.workflow.common.model.dto.OrgStructureSnapshotInfo;
import cn.axzo.workflow.common.model.request.bpmn.BpmnButtonConf;
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskDelegateAssigner;
import cn.axzo.workflow.common.model.request.form.FormPermissionMetaInfo;
@ -124,5 +125,5 @@ public class ExtAxProcessLog extends BaseEntity<ExtAxProcessLog> {
* 扩展字段
*/
@TableField(typeHandler = JacksonTypeHandler.class)
private JSONObject extra;
private OrgStructureSnapshotInfo extra;
}

View File

@ -1,5 +1,6 @@
package cn.axzo.workflow.core.service;
import cn.axzo.workflow.common.model.dto.OrgStructureSnapshotInfo;
import cn.axzo.workflow.common.model.dto.SimpleTaskDTO;
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskDelegateAssigner;
import cn.axzo.workflow.core.repository.entity.ExtAxProcessLog;
@ -49,9 +50,9 @@ public interface ExtAxProcessLogService {
* @param updateLog
* @param assignee
*/
void updateAssignee(ExtAxProcessLog updateLog, BpmnTaskDelegateAssigner assignee);
void updateAssigneeAndSnapshot(ExtAxProcessLog updateLog, BpmnTaskDelegateAssigner assignee, OrgStructureSnapshotInfo snapshotInfo);
void updateAssignee(ExtAxProcessLog updateLog, BpmnTaskDelegateAssigner assignee, String operationDesc);
void updateAssigneeAndSnapshot(ExtAxProcessLog updateLog, BpmnTaskDelegateAssigner assignee, OrgStructureSnapshotInfo snapshotInfo, String operationDesc);
List<ExtAxProcessLog> genericQuery(ExtAxProcessLog query);

View File

@ -1,10 +1,12 @@
package cn.axzo.workflow.core.service.impl;
import cn.axzo.workflow.common.model.dto.OrgStructureSnapshotInfo;
import cn.axzo.workflow.common.model.dto.SimpleTaskDTO;
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskDelegateAssigner;
import cn.axzo.workflow.core.repository.entity.ExtAxProcessLog;
import cn.axzo.workflow.core.repository.mapper.ExtAxProcessLogMapper;
import cn.axzo.workflow.core.service.ExtAxProcessLogService;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
@ -50,13 +52,12 @@ public class ExtAxProcessLogServiceImpl implements ExtAxProcessLogService {
}
@Override
public void updateAssignee(ExtAxProcessLog queryLog, BpmnTaskDelegateAssigner assignee) {
updateAssignee(queryLog, assignee, assignee.getAssignerName());
public void updateAssigneeAndSnapshot(ExtAxProcessLog queryLog, BpmnTaskDelegateAssigner assignee, OrgStructureSnapshotInfo snapshotInfo) {
updateAssigneeAndSnapshot(queryLog, assignee, snapshotInfo, assignee.getAssignerName());
}
@Override
public void updateAssignee(ExtAxProcessLog queryLog, BpmnTaskDelegateAssigner assignee, String operationDesc) {
public void updateAssigneeAndSnapshot(ExtAxProcessLog queryLog, BpmnTaskDelegateAssigner assignee, OrgStructureSnapshotInfo snapshotInfo, String operationDesc) {
List<String> filterAssignee = Lists.newArrayList(NO_ASSIGNEE, HIDDEN_ASSIGNEE_ID, ROBOT_ASSIGNEE_ID,
DUMMY_ASSIGNEE_ID);
if (Objects.isNull(assignee) || filterAssignee.contains(assignee.buildAssigneeId())) {
@ -69,6 +70,7 @@ public class ExtAxProcessLogServiceImpl implements ExtAxProcessLogService {
update.setAssigneeTenantId(assignee.getTenantId());
update.setAssigneeOuId(assignee.getOuId());
update.setAssigneeName(assignee.getAssignerName());
update.setExtra(snapshotInfo);
extAxProcessLogMapper.update(update, buildQueryWrapper(queryLog));
}
@ -79,7 +81,7 @@ public class ExtAxProcessLogServiceImpl implements ExtAxProcessLogService {
@Override
public ExtAxProcessLog findByProcessIdAndTaskIdWithDeleted(String processId, String taskId) {
return extAxProcessLogMapper.findByProcessIdAndTaskIdWithDeleted(processId,taskId);
return extAxProcessLogMapper.findByProcessIdAndTaskIdWithDeleted(processId, taskId);
}
@Override

View File

@ -23,9 +23,12 @@ import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.flowable.bpmn.model.Process;
import org.flowable.engine.HistoryService;
import org.flowable.engine.TaskService;
import org.flowable.engine.impl.util.CommandContextUtil;
import org.flowable.engine.impl.util.ProcessDefinitionUtil;
import org.flowable.task.api.Task;
import org.flowable.task.api.history.HistoricTaskInstance;
import org.flowable.task.service.impl.persistence.entity.TaskEntity;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Scope;
import org.springframework.core.Ordered;
@ -62,6 +65,7 @@ import static cn.axzo.workflow.common.constant.BpmnConstants.MQ_OWNERSHIP_PROCES
import static cn.axzo.workflow.common.constant.BpmnConstants.MULTI_INSTANCE_LOOP_COUNTER;
import static cn.axzo.workflow.common.constant.BpmnConstants.NUMBER_OF_INSTANCES;
import static cn.axzo.workflow.common.constant.BpmnConstants.PROCESS_OWNERSHIP_APPLICATION;
import static cn.axzo.workflow.common.constant.BpmnConstants.SUPPORT_UPGRADE_VARIABLE;
import static cn.axzo.workflow.common.constant.BpmnConstants.TASK_COMPLETE_OPERATION_TYPE;
import static cn.axzo.workflow.common.constant.VariableConstants.VAR_ACTIVITY_ID;
import static cn.axzo.workflow.common.constant.VariableConstants.VAR_ACTIVITY_NAME;
@ -78,6 +82,7 @@ import static cn.axzo.workflow.common.constant.VariableConstants.VAR_PROCESS_TEN
import static cn.axzo.workflow.common.constant.VariableConstants.VAR_TASK_ID;
import static cn.axzo.workflow.common.constant.VariableConstants.VAR_TASK_START_TIME;
import static cn.axzo.workflow.common.constant.VariableConstants.VAR_TASK_USER_NAME;
import static cn.axzo.workflow.common.enums.BpmnButtonEnum.BPMN_UPGRADE;
import static cn.axzo.workflow.common.enums.ProcessMessagePushEventEnum.PROCESS_CARBON_COPY;
import static cn.axzo.workflow.common.enums.ProcessMessagePushEventEnum.PROCESS_CARBON_COPY_COMPLETE;
import static cn.axzo.workflow.common.enums.ProcessMessagePushEventEnum.PROCESS_PUSH_NOTICE;
@ -102,6 +107,8 @@ public class RocketMqMessagePushEventListener extends AbstractBpmnEventListener<
private BpmnProcessInstanceService processInstanceService;
@Resource
private HistoryService historyService;
@Resource
private TaskService taskService;
@Value("${sendMq:true}")
private Boolean sendMQ;
@Resource
@ -184,6 +191,13 @@ public class RocketMqMessagePushEventListener extends AbstractBpmnEventListener<
}
});
}
// 如果提级审批的变量未 false
TaskEntity task = (TaskEntity) taskService.createTaskQuery().taskId(event.getTaskId()).singleResult();
Boolean supportUpgrade = (Boolean) task.getTransientVariablesLocal().getOrDefault(SUPPORT_UPGRADE_VARIABLE, false);
if (!supportUpgrade) {
buttons.removeIf(button-> Objects.equals(button.getBtnKey(), BPMN_UPGRADE.getBtnKey()));
}
dto.setButtons(buttons);
sendMessageQueue(dto, PROCESS_PUSH_PENDING);
}

View File

@ -47,6 +47,7 @@ public class ProcessConfigController implements ProcessConfigApi {
.setBtnName(buttonEnum.getBtnName())
.setChecked(false)
.setDisabled(false)
.setHidden(false)
.setSupportBizType(buttonEnum.getSupportBizType())
)
.collect(Collectors.toList()));

View File

@ -1,12 +1,28 @@
package cn.axzo.workflow.core.engine.listener.entity.type;
package cn.axzo.workflow.server.engine.ext.listener;
import cn.axzo.basics.common.util.NumberUtil;
import cn.axzo.foundation.page.PageResp;
import cn.axzo.orggateway.api.cooperateship.CooperateShipHierarchicalQueryApi;
import cn.axzo.orggateway.api.cooperateship.req.ListCooperateShipAncestorReq;
import cn.axzo.orggateway.api.cooperateship.resp.ListCooperateShipResp;
import cn.axzo.orggateway.api.nodeuser.OrgNodeUserApi;
import cn.axzo.orggateway.api.nodeuser.dto.OrgNodeUserDTO;
import cn.axzo.orggateway.api.nodeuser.req.ListOrgNodeUserReq;
import cn.axzo.orgmanax.dto.common.WorkspaceOuPair;
import cn.axzo.orgmanax.dto.nodeuser.req.ListNodeUserReq;
import cn.axzo.workflow.common.enums.BpmnFlowNodeMode;
import cn.axzo.workflow.common.enums.BpmnFlowNodeType;
import cn.axzo.workflow.common.enums.SignApproverOrgLimitEnum;
import cn.axzo.workflow.common.model.dto.JobInfo;
import cn.axzo.workflow.common.model.dto.OrgSnapshotInfo;
import cn.axzo.workflow.common.model.dto.OrgStructureSnapshotInfo;
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskDelegateAssigner;
import cn.axzo.workflow.core.common.utils.BpmnCollectionUtils;
import cn.axzo.workflow.core.common.utils.BpmnMetaParserHelper;
import cn.axzo.workflow.core.engine.listener.entity.EntityEventHandle;
import cn.axzo.workflow.core.repository.entity.ExtAxProcessLog;
import cn.axzo.workflow.core.service.ExtAxProcessLogService;
import com.alibaba.fastjson.JSON;
import com.google.common.collect.Lists;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@ -26,9 +42,12 @@ import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import javax.annotation.Resource;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
import static cn.axzo.workflow.common.constant.BpmnConstants.AND_SIGN_EXPRESSION;
import static cn.axzo.workflow.common.constant.BpmnConstants.COMMENT_TYPE_ADVICE;
@ -37,6 +56,7 @@ import static cn.axzo.workflow.common.constant.BpmnConstants.HIDDEN_ASSIGNEE_ID;
import static cn.axzo.workflow.common.constant.BpmnConstants.INTERNAL_ACTIVITY_RELATION_ASSIGNEE_LIST_INFO_SNAPSHOT;
import static cn.axzo.workflow.common.constant.BpmnConstants.INTERNAL_TASK_RELATION_ASSIGNEE_INFO;
import static cn.axzo.workflow.common.constant.BpmnConstants.NO_ASSIGNEE;
import static cn.axzo.workflow.common.constant.BpmnConstants.SUPPORT_UPGRADE_VARIABLE;
import static cn.axzo.workflow.common.constant.BpmnConstants.TASK_COMPLETE_OPERATION_TYPE;
import static cn.axzo.workflow.common.enums.ApprovalMethodEnum.nobody;
import static cn.axzo.workflow.common.enums.BpmnFlowNodeMode.AND;
@ -64,6 +84,8 @@ import static cn.axzo.workflow.core.common.utils.BpmnMetaParserHelper.getNodeTyp
@AllArgsConstructor
public class TaskEntityEventHandle implements EntityEventHandle<TaskEntity> {
private final ExtAxProcessLogService processLogService;
private final OrgNodeUserApi orgNodeUserApi;
private final CooperateShipHierarchicalQueryApi cooperateShipHierarchicalQueryApi;
@Override
public boolean support(Object entity) {
@ -133,11 +155,74 @@ public class TaskEntityEventHandle implements EntityEventHandle<TaskEntity> {
ExtAxProcessLog queryLog = new ExtAxProcessLog();
queryLog.setProcessInstanceId(taskEntity.getProcessInstanceId());
queryLog.setTaskId(taskEntity.getId());
processLogService.updateAssignee(queryLog, assignee);
// 快照审批人的组织架构信息
OrgStructureSnapshotInfo snapshotInfo = buildApproverOrgStructureInfo(assignee, taskEntity);
processLogService.updateAssigneeAndSnapshot(queryLog, assignee, snapshotInfo);
});
}
}
private OrgStructureSnapshotInfo buildApproverOrgStructureInfo(BpmnTaskDelegateAssigner assignee, TaskEntity taskEntity) {
List<OrgNodeUserDTO> nodeUsers = fetchUserExtInfo(assignee);
OrgStructureSnapshotInfo.OrgStructureSnapshotInfoBuilder builder = OrgStructureSnapshotInfo.builder();
if (CollectionUtils.isEmpty(nodeUsers)) {
return builder.build();
}
OrgNodeUserDTO firstNodeUser = nodeUsers.get(0);
assignee.setNodeId(String.valueOf(firstNodeUser.getTopNodeId()));
OrgStructureSnapshotInfo snapshotInfo = builder.personName(firstNodeUser.getRealName())
.topNodeId(firstNodeUser.getTopNodeId())
.projectInfo(Objects.nonNull(firstNodeUser.getCooperateShip()) ? OrgSnapshotInfo.builder()
.workspaceName(firstNodeUser.getCooperateShip().getWorkspaceName())
.workspaceId(String.valueOf(firstNodeUser.getCooperateShip().getWorkspaceId()))
.workspaceType(firstNodeUser.getCooperateShip().getWorkspaceType())
.cooperationType(firstNodeUser.getCooperateShip().getCooperateType())
.ouName(firstNodeUser.getCooperateShip().getOrganizationalUnitName())
.ouId(String.valueOf(firstNodeUser.getCooperateShip().getOrganizationalUnitId()))
.topNodeId(String.valueOf(firstNodeUser.getTopNodeId()))
.alias("")
.build() : null)
.entInfo(Objects.nonNull(firstNodeUser.getEntCooperateShip()) ? OrgSnapshotInfo.builder()
.workspaceName(firstNodeUser.getEntCooperateShip().getWorkspaceName())
.workspaceId(String.valueOf(firstNodeUser.getEntCooperateShip().getWorkspaceId()))
.workspaceType(firstNodeUser.getEntCooperateShip().getWorkspaceType())
.cooperationType(firstNodeUser.getEntCooperateShip().getCooperateType())
.ouName(firstNodeUser.getEntCooperateShip().getOrganizationalUnitName())
.ouId(String.valueOf(firstNodeUser.getEntCooperateShip().getOrganizationalUnitId()))
.topNodeId(String.valueOf(firstNodeUser.getTopNodeId()))
.alias("")
.build() : null)
.jobInfos(nodeUsers.stream().map(i -> JobInfo.builder()
.jobCode(i.getJob().getCode())
.jobName(i.getJob().getName())
.build()).collect(Collectors.toList()))
.build();
FlowElement flowElement = ProcessDefinitionUtil.getBpmnModel(taskEntity.getProcessDefinitionId()).getFlowElement(taskEntity.getTaskDefinitionKey());
BpmnMetaParserHelper.getUpgradeApprovalConf(flowElement).ifPresent(conf -> {
Boolean supportUpgradeApproval;
if (Objects.equals(Boolean.TRUE, conf.getEnabled())) {
if (Objects.equals(SignApproverOrgLimitEnum.LV_ALL, conf.getOrgLimit())) {
supportUpgradeApproval = true;
} else {
ListCooperateShipAncestorReq build = ListCooperateShipAncestorReq.builder()
.upLevel(conf.getOrgLimit().getCode())
.organizationNodeId(Long.parseLong(assignee.getNodeId()))
.includeCurrentNode(false)
.build();
List<ListCooperateShipResp> result = listAncestors(build);
supportUpgradeApproval = !CollectionUtils.isEmpty(result);
}
assignee.setSupportUpgradeApproval(supportUpgradeApproval);
taskEntity.setTransientVariableLocal(SUPPORT_UPGRADE_VARIABLE, supportUpgradeApproval);
}
});
return snapshotInfo;
}
@Override
public void onDeleted(TaskEntity taskEntity) {
ExtAxProcessLog queryLog = new ExtAxProcessLog();
@ -230,4 +315,64 @@ public class TaskEntityEventHandle implements EntityEventHandle<TaskEntity> {
return node;
}
private List<OrgNodeUserDTO> fetchUserExtInfo(BpmnTaskDelegateAssigner assigner) {
String personId = assigner.getPersonId();
String tenantId = assigner.getTenantId();
String ouId = assigner.getOuId();
if (NumberUtils.isDigits(personId) && NumberUtils.isDigits(tenantId) && NumberUtils.isDigits(ouId)) {
ListOrgNodeUserReq build = ListOrgNodeUserReq.builder()
.personIds(Lists.newArrayList(Long.parseLong(personId)))
.workspaceOuPairs(Lists.newArrayList(WorkspaceOuPair.builder()
.workspaceId(Long.parseLong(tenantId))
.ouId(Long.parseLong(ouId))
.build()))
.needs(ListNodeUserReq.Needs.builder()
.job(true)
.unit(true)
.cooperateShip(true)
.personProfile(true)
.workspace(true)
.entCooperateShip(true)
.build())
.pageSize(Integer.MAX_VALUE)
.build();
return orgNodeUserList(build).getData();
}
return Collections.emptyList();
}
/**
* 查询orgNodeUser
*/
public PageResp<OrgNodeUserDTO> orgNodeUserList(ListOrgNodeUserReq listOrgNodeUserReq) {
try {
log.info("orgNodeUserList,params:{}", JSON.toJSONString(listOrgNodeUserReq));
cn.axzo.foundation.result.ApiResult<PageResp<OrgNodeUserDTO>> apiResult = orgNodeUserApi.list(listOrgNodeUserReq);
log.info("orgNodeUserList,result:{}", JSON.toJSONString(apiResult));
if (Objects.isNull(apiResult) || !apiResult.isSuccess() || Objects.isNull(apiResult.getData()) || org.apache.commons.collections.CollectionUtils.isEmpty(apiResult.getData().getData())) {
return new PageResp<>(0, listOrgNodeUserReq.getPageSize(), listOrgNodeUserReq.getPage(), org.apache.commons.compress.utils.Lists.newArrayList());
}
return apiResult.getData();
} catch (Exception e) {
log.warn("orgNodeUserList,exception", e);
throw e;
}
}
public List<ListCooperateShipResp> listAncestors(ListCooperateShipAncestorReq req) {
try {
log.info("listAncestors,params:{}", JSON.toJSONString(req));
cn.axzo.foundation.result.ApiResult<List<ListCooperateShipResp>> listApiResult = cooperateShipHierarchicalQueryApi.listAncestors(req);
log.info("listAncestors,result:{}", JSON.toJSONString(listApiResult));
if (Objects.isNull(listApiResult) || !listApiResult.isSuccess() || Objects.isNull(listApiResult.getData()) || org.apache.commons.collections.CollectionUtils.isEmpty(listApiResult.getData())) {
return org.apache.commons.compress.utils.Lists.newArrayList();
}
return listApiResult.getData();
} catch (Exception e) {
log.warn("orgNodeUserList,exception", e);
throw e;
}
}
}