Merge branch 'feature/countersign_ext' into dev
This commit is contained in:
commit
8b1fc0e108
@ -252,6 +252,14 @@ public interface BpmnConstants {
|
|||||||
* 签署业务发起流程实例时,重新选择的文档tag 集合
|
* 签署业务发起流程实例时,重新选择的文档tag 集合
|
||||||
*/
|
*/
|
||||||
String SIGN_PROCESS_ENABLE_DOC_IDS = "[_SIGN_PROCESS_ENABLE_DOC_IDS_]";
|
String SIGN_PROCESS_ENABLE_DOC_IDS = "[_SIGN_PROCESS_ENABLE_DOC_IDS_]";
|
||||||
|
/**
|
||||||
|
* 签署业务自定义业务传入的文档集合
|
||||||
|
*/
|
||||||
|
String SIGN_BIZ_CUSTOM_DOCS = "[_SIGN_BIZ_CUSTOM_DOCS_]";
|
||||||
|
/**
|
||||||
|
* 签署业务自定义文档的顺序位置类型
|
||||||
|
*/
|
||||||
|
String SIGN_BIZ_CUSTOM_DOC_ADD_TYPE = "[_SIGN_BIZ_CUSTOM_DOC_ADD_TYPE_]";
|
||||||
/**
|
/**
|
||||||
* 签署业务,基于业务自定义变量的传入
|
* 签署业务,基于业务自定义变量的传入
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -0,0 +1,49 @@
|
|||||||
|
package cn.axzo.workflow.common.model.dto;
|
||||||
|
|
||||||
|
import cn.axzo.workflow.common.enums.FileTypeEnum;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.experimental.Accessors;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 签署文件记录信息
|
||||||
|
*
|
||||||
|
* @author wangli
|
||||||
|
* @since 2025-04-03 11:21
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Accessors(chain = true)
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
@Builder
|
||||||
|
public class CustomDocDTO implements Serializable {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = -8709597975507074853L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 文件名称,可能会包含变量
|
||||||
|
*/
|
||||||
|
private String fileName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 文件的标签
|
||||||
|
*/
|
||||||
|
private String fileTag;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 文件 wps code
|
||||||
|
* <p>
|
||||||
|
* wps 文件的标识,通过{@link cn.axzo.nanopart.doc.api.anonymous.DocAnonymousDatabaseApi#createFile(cn.axzo.nanopart.doc.api.anonymous.request.AnonymousCreateFileRequest)} 接口创建文件后返回的 fileCode
|
||||||
|
*/
|
||||||
|
private String fileCode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 文件的类型
|
||||||
|
*/
|
||||||
|
private FileTypeEnum fileType;
|
||||||
|
|
||||||
|
}
|
||||||
@ -2,6 +2,7 @@ package cn.axzo.workflow.common.model.request.bpmn.process;
|
|||||||
|
|
||||||
import cn.axzo.workflow.common.constant.BpmnConstants;
|
import cn.axzo.workflow.common.constant.BpmnConstants;
|
||||||
import cn.axzo.workflow.common.model.dto.CooperationOrgDTO;
|
import cn.axzo.workflow.common.model.dto.CooperationOrgDTO;
|
||||||
|
import cn.axzo.workflow.common.model.dto.CustomDocDTO;
|
||||||
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskDelegateAssigner;
|
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskDelegateAssigner;
|
||||||
import io.swagger.annotations.ApiModel;
|
import io.swagger.annotations.ApiModel;
|
||||||
import io.swagger.annotations.ApiModelProperty;
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
@ -120,6 +121,22 @@ public class BpmnProcessInstanceCreateDTO extends BpmnProcessInstanceCreateWithF
|
|||||||
@ApiModelProperty(value = "签署业务发起时,选择的文档")
|
@ApiModelProperty(value = "签署业务发起时,选择的文档")
|
||||||
private List<Long> docIds;
|
private List<Long> docIds;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* "签字业务"专用
|
||||||
|
* <p>
|
||||||
|
* 业务自定义的文档
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "业务自定义文档")
|
||||||
|
private List<CustomDocDTO> customDocs;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* "签字业务"专用,自定义文档的顺序位置信息,在流程模板配置文档之前还是之后
|
||||||
|
* <p>
|
||||||
|
* 可选值:first(之前)、last(之后), 如果为空,默认为 last
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "自定义文档顺序位置", notes = "可选值:first(之前)、last(之后), 如果为空,默认为 last")
|
||||||
|
private String docAddType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 仅针对签署业务,设置审批完成后的最终签署人列表,该属性仅为透传,业务消费时,请从 MQ 广播事件中的 variables 中通过 key= {@link BpmnConstants#SIGNATORIES } 获取
|
* 仅针对签署业务,设置审批完成后的最终签署人列表,该属性仅为透传,业务消费时,请从 MQ 广播事件中的 variables 中通过 key= {@link BpmnConstants#SIGNATORIES } 获取
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -14,6 +14,7 @@ import cn.axzo.workflow.common.enums.BusinessTypeEnum;
|
|||||||
import cn.axzo.workflow.common.enums.ButtonVisibleScopeEnum;
|
import cn.axzo.workflow.common.enums.ButtonVisibleScopeEnum;
|
||||||
import cn.axzo.workflow.common.enums.WorkspaceType;
|
import cn.axzo.workflow.common.enums.WorkspaceType;
|
||||||
import cn.axzo.workflow.common.exception.WorkflowEngineException;
|
import cn.axzo.workflow.common.exception.WorkflowEngineException;
|
||||||
|
import cn.axzo.workflow.common.model.dto.CustomDocDTO;
|
||||||
import cn.axzo.workflow.common.model.dto.SignFileDTO;
|
import cn.axzo.workflow.common.model.dto.SignFileDTO;
|
||||||
import cn.axzo.workflow.common.model.dto.SimpleDocDTO;
|
import cn.axzo.workflow.common.model.dto.SimpleDocDTO;
|
||||||
import cn.axzo.workflow.common.model.request.BpmnApproveConf;
|
import cn.axzo.workflow.common.model.request.BpmnApproveConf;
|
||||||
@ -152,8 +153,10 @@ import java.util.Objects;
|
|||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
import static cn.axzo.workflow.client.config.WorkflowRequestInterceptor.HEADER_SERVER_NAME;
|
import static cn.axzo.workflow.client.config.WorkflowRequestInterceptor.HEADER_SERVER_NAME;
|
||||||
import static cn.axzo.workflow.common.code.BpmnInstanceRespCode.PROCESS_INSTANCE_CREATE_PARAM_ERROR;
|
import static cn.axzo.workflow.common.code.BpmnInstanceRespCode.PROCESS_INSTANCE_CREATE_PARAM_ERROR;
|
||||||
@ -187,6 +190,8 @@ import static cn.axzo.workflow.common.constant.BpmnConstants.OLD_INTERNAL_INITIA
|
|||||||
import static cn.axzo.workflow.common.constant.BpmnConstants.PENDING_TEMPLATE_VARIABLE;
|
import static cn.axzo.workflow.common.constant.BpmnConstants.PENDING_TEMPLATE_VARIABLE;
|
||||||
import static cn.axzo.workflow.common.constant.BpmnConstants.PROCESS_OWNERSHIP_APPLICATION;
|
import static cn.axzo.workflow.common.constant.BpmnConstants.PROCESS_OWNERSHIP_APPLICATION;
|
||||||
import static cn.axzo.workflow.common.constant.BpmnConstants.SIGNATORIES;
|
import static cn.axzo.workflow.common.constant.BpmnConstants.SIGNATORIES;
|
||||||
|
import static cn.axzo.workflow.common.constant.BpmnConstants.SIGN_BIZ_CUSTOM_DOCS;
|
||||||
|
import static cn.axzo.workflow.common.constant.BpmnConstants.SIGN_BIZ_CUSTOM_DOC_ADD_TYPE;
|
||||||
import static cn.axzo.workflow.common.constant.BpmnConstants.SIGN_PROCESS_ENABLE_DOC_IDS;
|
import static cn.axzo.workflow.common.constant.BpmnConstants.SIGN_PROCESS_ENABLE_DOC_IDS;
|
||||||
import static cn.axzo.workflow.common.constant.BpmnConstants.SIGN_VARIABLE;
|
import static cn.axzo.workflow.common.constant.BpmnConstants.SIGN_VARIABLE;
|
||||||
import static cn.axzo.workflow.common.constant.BpmnConstants.WORKFLOW_ENGINE_VERSION;
|
import static cn.axzo.workflow.common.constant.BpmnConstants.WORKFLOW_ENGINE_VERSION;
|
||||||
@ -495,6 +500,8 @@ public class BpmnProcessInstanceServiceImpl implements BpmnProcessInstanceServic
|
|||||||
dto.getVariables().put(SIGN_PROCESS_ENABLE_DOC_IDS, dto.getDocIds());
|
dto.getVariables().put(SIGN_PROCESS_ENABLE_DOC_IDS, dto.getDocIds());
|
||||||
dto.getVariables().put(SIGN_VARIABLE, dto.getBizCustomVariables());
|
dto.getVariables().put(SIGN_VARIABLE, dto.getBizCustomVariables());
|
||||||
dto.getVariables().put(SIGNATORIES, dto.getSignatories());
|
dto.getVariables().put(SIGNATORIES, dto.getSignatories());
|
||||||
|
dto.getVariables().put(SIGN_BIZ_CUSTOM_DOCS, dto.getCustomDocs());
|
||||||
|
dto.getVariables().put(SIGN_BIZ_CUSTOM_DOC_ADD_TYPE, StringUtils.hasText(dto.getDocAddType()) ? dto.getDocAddType() : "last");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
dto.getVariables().put(INTERNAL_INITIATOR, dto.getInitiator().toJson());
|
dto.getVariables().put(INTERNAL_INITIATOR, dto.getInitiator().toJson());
|
||||||
@ -1873,6 +1880,9 @@ public class BpmnProcessInstanceServiceImpl implements BpmnProcessInstanceServic
|
|||||||
CommandExecutor commandExecutor = springProcessEngineConfiguration.getCommandExecutor();
|
CommandExecutor commandExecutor = springProcessEngineConfiguration.getCommandExecutor();
|
||||||
List<DocBaseVO> docs = commandExecutor.execute(new CustomGetModelDocsCmd(dto.getProcessInstanceId(), true, extAxModelDocMapper, extAxReModelService));
|
List<DocBaseVO> docs = commandExecutor.execute(new CustomGetModelDocsCmd(dto.getProcessInstanceId(), true, extAxModelDocMapper, extAxReModelService));
|
||||||
|
|
||||||
|
// 获取业务自定义传入的文档
|
||||||
|
getAndAddBizCustomDocs(dto.getProcessInstanceId(), docs);
|
||||||
|
|
||||||
Map<Long, Boolean> readStatusMap = new HashMap<>();
|
Map<Long, Boolean> readStatusMap = new HashMap<>();
|
||||||
if (Objects.nonNull(dto.getAssigner())) {
|
if (Objects.nonNull(dto.getAssigner())) {
|
||||||
readStatusMap.putAll(extAxReadRecordService.queryReadStatus(ApproverReadStatusDTO.builder()
|
readStatusMap.putAll(extAxReadRecordService.queryReadStatus(ApproverReadStatusDTO.builder()
|
||||||
@ -1895,4 +1905,44 @@ public class BpmnProcessInstanceServiceImpl implements BpmnProcessInstanceServic
|
|||||||
t.setReadStatus(readStatusMap.getOrDefault(t.getId(), false));
|
t.setReadStatus(readStatusMap.getOrDefault(t.getId(), false));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private List<DocBaseVO> getAndAddBizCustomDocs(String processInstanceId, List<DocBaseVO> docs) {
|
||||||
|
List<CustomDocDTO> bizCustomDocs = Optional.ofNullable(
|
||||||
|
runtimeService.getVariable(processInstanceId, SIGN_BIZ_CUSTOM_DOCS, List.class))
|
||||||
|
.orElse(Collections.emptyList());
|
||||||
|
String customAddType = runtimeService.getVariable(processInstanceId, SIGN_BIZ_CUSTOM_DOC_ADD_TYPE, String.class);
|
||||||
|
|
||||||
|
boolean appendLast = "last".equals(customAddType);
|
||||||
|
Comparator<DocBaseVO> orderComparator = Comparator.comparing(
|
||||||
|
DocBaseVO::getOrder, Comparator.nullsFirst(Comparator.naturalOrder()));
|
||||||
|
|
||||||
|
Optional<DocBaseVO> baseOpt;
|
||||||
|
Stream<DocBaseVO> filtered = docs.stream().filter(Objects::nonNull);
|
||||||
|
if (appendLast) {
|
||||||
|
baseOpt = filtered.max(orderComparator);
|
||||||
|
} else {
|
||||||
|
baseOpt = filtered.min(orderComparator);
|
||||||
|
}
|
||||||
|
|
||||||
|
int baseOrder = baseOpt.map(DocBaseVO::getOrder).orElse(0);
|
||||||
|
String tenantId = baseOpt.map(DocBaseVO::getTenantId).orElse(null);
|
||||||
|
|
||||||
|
AtomicInteger orderCounter = new AtomicInteger(baseOrder);
|
||||||
|
int delta = appendLast ? 1 : -1;
|
||||||
|
|
||||||
|
List<DocBaseVO> docBaseVOS = BeanMapper.copyList(bizCustomDocs, DocBaseVO.class, (s, t) -> {
|
||||||
|
t.setStatus(true);
|
||||||
|
t.setTempFile(false);
|
||||||
|
t.setOrder(orderCounter.addAndGet(delta));
|
||||||
|
t.setTenantId(tenantId);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (appendLast) {
|
||||||
|
docs.addAll(docBaseVOS);
|
||||||
|
} else {
|
||||||
|
docs.addAll(0, docBaseVOS);
|
||||||
|
}
|
||||||
|
return docs;
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,6 +3,7 @@ package cn.axzo.workflow.server.controller.listener.task;
|
|||||||
import cn.axzo.nanopart.doc.api.anonymous.DocAnonymousDatabaseApi;
|
import cn.axzo.nanopart.doc.api.anonymous.DocAnonymousDatabaseApi;
|
||||||
import cn.axzo.nanopart.doc.api.index.request.CopyNodeRequest;
|
import cn.axzo.nanopart.doc.api.index.request.CopyNodeRequest;
|
||||||
import cn.axzo.workflow.common.enums.FileTypeEnum;
|
import cn.axzo.workflow.common.enums.FileTypeEnum;
|
||||||
|
import cn.axzo.workflow.common.model.dto.CustomDocDTO;
|
||||||
import cn.axzo.workflow.common.model.dto.SignFileDTO;
|
import cn.axzo.workflow.common.model.dto.SignFileDTO;
|
||||||
import cn.axzo.workflow.common.model.dto.VariableObjectDTO;
|
import cn.axzo.workflow.common.model.dto.VariableObjectDTO;
|
||||||
import cn.axzo.workflow.common.model.request.bpmn.BpmnSignConf;
|
import cn.axzo.workflow.common.model.request.bpmn.BpmnSignConf;
|
||||||
@ -23,6 +24,7 @@ import cn.axzo.workflow.server.common.util.WpsUtil;
|
|||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.flowable.bpmn.model.Process;
|
import org.flowable.bpmn.model.Process;
|
||||||
import org.flowable.common.engine.impl.interceptor.CommandExecutor;
|
import org.flowable.common.engine.impl.interceptor.CommandExecutor;
|
||||||
|
import org.flowable.engine.RuntimeService;
|
||||||
import org.flowable.engine.impl.cfg.ProcessEngineConfigurationImpl;
|
import org.flowable.engine.impl.cfg.ProcessEngineConfigurationImpl;
|
||||||
import org.flowable.engine.impl.util.CommandContextUtil;
|
import org.flowable.engine.impl.util.CommandContextUtil;
|
||||||
import org.flowable.engine.impl.util.ProcessDefinitionUtil;
|
import org.flowable.engine.impl.util.ProcessDefinitionUtil;
|
||||||
@ -39,6 +41,8 @@ import java.util.List;
|
|||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
|
import static cn.axzo.workflow.common.constant.BpmnConstants.SIGN_BIZ_CUSTOM_DOCS;
|
||||||
|
import static cn.axzo.workflow.common.constant.BpmnConstants.SIGN_BIZ_CUSTOM_DOC_ADD_TYPE;
|
||||||
import static cn.axzo.workflow.common.enums.BpmnFlowNodeType.NODE_STARTER;
|
import static cn.axzo.workflow.common.enums.BpmnFlowNodeType.NODE_STARTER;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -96,6 +100,27 @@ public class FirstCopyTemplateFileTaskEvent_105_Listener extends AbstractBpmnEve
|
|||||||
} else {
|
} else {
|
||||||
// 复制基础模板
|
// 复制基础模板
|
||||||
List<SignFileDTO> docTemplates = copyTempTemplate(docs);
|
List<SignFileDTO> docTemplates = copyTempTemplate(docs);
|
||||||
|
// 处理业务自定义文档
|
||||||
|
RuntimeService runtimeService = processEngineConfiguration.getRuntimeService();
|
||||||
|
List<CustomDocDTO> customDocs = runtimeService.getVariable(processInstanceId, SIGN_BIZ_CUSTOM_DOCS, List.class);
|
||||||
|
List<SignFileDTO> customDocTemplates = new ArrayList<>();
|
||||||
|
for (int i = 0; i < customDocs.size(); i++) {
|
||||||
|
customDocTemplates.add(SignFileDTO.builder()
|
||||||
|
.id(i - (i + 1L)) // 负数 ID,避免冲突
|
||||||
|
.fileName(customDocs.get(i).getFileName())
|
||||||
|
.templateName(customDocs.get(i).getFileName())
|
||||||
|
.fileTag(customDocs.get(i).getFileTag())
|
||||||
|
.fileCode(customDocs.get(i).getFileCode())
|
||||||
|
.fileType(customDocs.get(i).getFileType())
|
||||||
|
.build());
|
||||||
|
}
|
||||||
|
|
||||||
|
String customAddType = runtimeService.getVariable(processInstanceId, SIGN_BIZ_CUSTOM_DOC_ADD_TYPE, String.class);
|
||||||
|
if (Objects.equals("last", customAddType)) {
|
||||||
|
docTemplates.addAll(customDocTemplates);
|
||||||
|
} else {
|
||||||
|
docTemplates.addAll(0, customDocTemplates);
|
||||||
|
}
|
||||||
processSign.setDocTemplate(docTemplates);
|
processSign.setDocTemplate(docTemplates);
|
||||||
|
|
||||||
List<SignFileDTO> archives = replaceTemplateVariable(docTemplates, processEngineConfiguration, processInstanceId);
|
List<SignFileDTO> archives = replaceTemplateVariable(docTemplates, processEngineConfiguration, processInstanceId);
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user