Merge branch 'feature/countersign_ext' into dev
This commit is contained in:
commit
8b1fc0e108
@ -252,6 +252,14 @@ public interface BpmnConstants {
|
||||
* 签署业务发起流程实例时,重新选择的文档tag 集合
|
||||
*/
|
||||
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.model.dto.CooperationOrgDTO;
|
||||
import cn.axzo.workflow.common.model.dto.CustomDocDTO;
|
||||
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskDelegateAssigner;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
@ -120,6 +121,22 @@ public class BpmnProcessInstanceCreateDTO extends BpmnProcessInstanceCreateWithF
|
||||
@ApiModelProperty(value = "签署业务发起时,选择的文档")
|
||||
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 } 获取
|
||||
*/
|
||||
|
||||
@ -14,6 +14,7 @@ import cn.axzo.workflow.common.enums.BusinessTypeEnum;
|
||||
import cn.axzo.workflow.common.enums.ButtonVisibleScopeEnum;
|
||||
import cn.axzo.workflow.common.enums.WorkspaceType;
|
||||
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.SimpleDocDTO;
|
||||
import cn.axzo.workflow.common.model.request.BpmnApproveConf;
|
||||
@ -152,8 +153,10 @@ import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.function.Function;
|
||||
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.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.PROCESS_OWNERSHIP_APPLICATION;
|
||||
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_VARIABLE;
|
||||
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_VARIABLE, dto.getBizCustomVariables());
|
||||
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());
|
||||
@ -1873,6 +1880,9 @@ public class BpmnProcessInstanceServiceImpl implements BpmnProcessInstanceServic
|
||||
CommandExecutor commandExecutor = springProcessEngineConfiguration.getCommandExecutor();
|
||||
List<DocBaseVO> docs = commandExecutor.execute(new CustomGetModelDocsCmd(dto.getProcessInstanceId(), true, extAxModelDocMapper, extAxReModelService));
|
||||
|
||||
// 获取业务自定义传入的文档
|
||||
getAndAddBizCustomDocs(dto.getProcessInstanceId(), docs);
|
||||
|
||||
Map<Long, Boolean> readStatusMap = new HashMap<>();
|
||||
if (Objects.nonNull(dto.getAssigner())) {
|
||||
readStatusMap.putAll(extAxReadRecordService.queryReadStatus(ApproverReadStatusDTO.builder()
|
||||
@ -1895,4 +1905,44 @@ public class BpmnProcessInstanceServiceImpl implements BpmnProcessInstanceServic
|
||||
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.index.request.CopyNodeRequest;
|
||||
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.VariableObjectDTO;
|
||||
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 org.flowable.bpmn.model.Process;
|
||||
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.util.CommandContextUtil;
|
||||
import org.flowable.engine.impl.util.ProcessDefinitionUtil;
|
||||
@ -39,6 +41,8 @@ import java.util.List;
|
||||
import java.util.Objects;
|
||||
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;
|
||||
|
||||
/**
|
||||
@ -96,6 +100,27 @@ public class FirstCopyTemplateFileTaskEvent_105_Listener extends AbstractBpmnEve
|
||||
} else {
|
||||
// 复制基础模板
|
||||
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);
|
||||
|
||||
List<SignFileDTO> archives = replaceTemplateVariable(docTemplates, processEngineConfiguration, processInstanceId);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user