diff --git a/workflow-engine-common/src/main/java/cn/axzo/workflow/common/constant/BpmnConstants.java b/workflow-engine-common/src/main/java/cn/axzo/workflow/common/constant/BpmnConstants.java
index 8e1bb6fa0..c9af21362 100644
--- a/workflow-engine-common/src/main/java/cn/axzo/workflow/common/constant/BpmnConstants.java
+++ b/workflow-engine-common/src/main/java/cn/axzo/workflow/common/constant/BpmnConstants.java
@@ -52,7 +52,7 @@ public interface BpmnConstants {
String NUMBER_OF_INSTANCES = "nrOfInstances";
String MULTI_INSTANCE_LOOP_COUNTER = "loopCounter";
-
+ String TASK_COMPLETE_OPERATION_TYPE = "_TASK_COMPLETE_TYPE";
/**
* 会签表达式
*/
diff --git a/workflow-engine-common/src/main/java/cn/axzo/workflow/common/model/request/bpmn/BpmnButtonConf.java b/workflow-engine-common/src/main/java/cn/axzo/workflow/common/model/request/bpmn/BpmnButtonConf.java
new file mode 100644
index 000000000..fdec1877d
--- /dev/null
+++ b/workflow-engine-common/src/main/java/cn/axzo/workflow/common/model/request/bpmn/BpmnButtonConf.java
@@ -0,0 +1,86 @@
+package cn.axzo.workflow.common.model.request.bpmn;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import lombok.experimental.Accessors;
+
+import javax.validation.constraints.NotBlank;
+
+/**
+ * 流程定义中的按钮配置
+ *
+ * @author wangli
+ * @since 2023/11/13 13:44
+ */
+@ApiModel("JSON 版本的 BPMN 协议模型中的按钮管理")
+@Data
+@NoArgsConstructor
+@Accessors(chain = true)
+public class BpmnButtonConf {
+
+ /**
+ * 发起人的按钮配置信息, JSON 格式
+ */
+ @ApiModelProperty(value = "发起人的按钮配置信息, JSON 格式", example = "{\"agree\": true, \"reject\": true, \"delegate\": " +
+ "true, \"cancel\": true, \"withdraw\": true, \"revoke\": true\" }")
+ @NotBlank(message = "发起人的按钮配置信息不能为空")
+ private String initiator;
+
+ /**
+ * 当前审批人的按钮配置信息, JSON 格式
+ */
+ @ApiModelProperty(value = "当前审批人的按钮配置信息, JSON 格式", example = "{\"agree\": true, \"reject\": true, \"delegate\": " +
+ "true, \"cancel\": true, \"withdraw\": true, \"revoke\": true\" }")
+ @NotBlank(message = "当前审批人的按钮配置信息不能为空")
+ private String current;
+
+ /**
+ * 历史审批人的按钮配置信息, JSON 格式
+ */
+ @ApiModelProperty(value = "历史审批人的按钮配置信息, JSON 格式", example = "{\"agree\": true, \"reject\": true, \"delegate\": " +
+ "true, \"cancel\": true, \"withdraw\": true, \"revoke\": true\" }")
+ @NotBlank(message = "历史审批人的按钮配置信息不能为空")
+ private String history;
+
+ /**
+ * 抄送人的按钮配置信息, JSON 格式
+ */
+ @ApiModelProperty(value = "抄送人的按钮配置信息, JSON 格式", example = "{\"agree\": true, \"reject\": true, \"delegate\": " +
+ "true, \"cancel\": true, \"withdraw\": true, \"revoke\": true\" }")
+ @NotBlank(message = "抄送人的按钮配置信息不能为空")
+ private String carbonCopy;
+
+ public String getInitiator() {
+ return initiator;
+ }
+
+ public void setInitiator(String initiator) {
+ this.initiator = initiator;
+ }
+
+ public String getCurrent() {
+ return current;
+ }
+
+ public void setCurrent(String current) {
+ this.current = current;
+ }
+
+ public String getHistory() {
+ return history;
+ }
+
+ public void setHistory(String history) {
+ this.history = history;
+ }
+
+ public String getCarbonCopy() {
+ return carbonCopy;
+ }
+
+ public void setCarbonCopy(String carbonCopy) {
+ this.carbonCopy = carbonCopy;
+ }
+}
diff --git a/workflow-engine-common/src/main/java/cn/axzo/workflow/common/model/request/bpmn/BpmnCondition.java b/workflow-engine-common/src/main/java/cn/axzo/workflow/common/model/request/bpmn/BpmnCondition.java
new file mode 100644
index 000000000..0a0dd0869
--- /dev/null
+++ b/workflow-engine-common/src/main/java/cn/axzo/workflow/common/model/request/bpmn/BpmnCondition.java
@@ -0,0 +1,154 @@
+package cn.axzo.workflow.common.model.request.bpmn;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import lombok.experimental.Accessors;
+
+import java.util.List;
+
+/**
+ * 条件
+ *
+ * @author wangli
+ * @since 2023/11/13 20:33
+ */
+@ApiModel("JSON 版本的 BPMN 协议模型中的条件")
+@Data
+@NoArgsConstructor
+@Accessors(chain = true)
+public class BpmnCondition {
+
+ /**
+ * string(字符串)/number(数字)/radio(单选)/checkbox(复选)
+ */
+ @ApiModelProperty(value = "基础属性:字段类型", notes = "string, number, radio, checkbox", example = "string")
+ private String filedDateType;
+
+ /**
+ * 字段 code
+ */
+ @ApiModelProperty(value = "基础属性:字段 code", notes = "字段管理中字段的 Code", example = "fieldCode")
+ private String fieldCode;
+
+ /**
+ * 操作符(与字段类型有关)
+ *
+ * 当字段类型为 string 时, 操作符为 contains, notContains
+ * 当字段类型为 number 时, 操作符为 eq, ne, gt, ge, lt, le, between
+ * 当字段类型为 radio 时, 操作符为 eq
+ * 当字段类型为 checkbox 时, 操作符为 in
+ */
+ @ApiModelProperty(value = "基础属性:操作符", notes = "操作符", example = "eq")
+ private String operator;
+
+ /**
+ * 默认的比较值
+ */
+ @ApiModelProperty(value = "基础属性:默认的比较值", notes = "同时也用于 fieldDateType = radio", example = "1")
+ private String defaultValue;
+
+
+ /**
+ * 只有 fieldDateType = checkbox 才有值
+ */
+ @ApiModelProperty(value = "当 fieldDateType = checkbox时, 选中的值")
+ private List defaultValues;
+
+ /**
+ * 只有 operator = between 才有值
+ */
+ @ApiModelProperty(value = "当 fieldDateType = number 并且 operator = between 时, 左侧操作符")
+ private String leftOperator;
+
+ /**
+ * 只有 operator = between 才有值
+ */
+ @ApiModelProperty(value = "当 fieldDateType = number 并且 operator = between 时, 右侧操作符")
+ private String rightOperator;
+
+ /**
+ * 只有 operator = between 才有值
+ */
+ @ApiModelProperty(value = "当 fieldDateType = number 并且 operator = between 时, 左侧比较值")
+ private String leftValue;
+
+ /**
+ * 只有 operator = between 才有值
+ */
+ @ApiModelProperty(value = "当 fieldDateType = number 并且 operator = between 时, 右侧比较值")
+ private String rightValue;
+
+ public String getFiledDateType() {
+ return filedDateType;
+ }
+
+ public void setFiledDateType(String filedDateType) {
+ this.filedDateType = filedDateType;
+ }
+
+ public String getFieldCode() {
+ return fieldCode;
+ }
+
+ public void setFieldCode(String fieldCode) {
+ this.fieldCode = fieldCode;
+ }
+
+ public String getOperator() {
+ return operator;
+ }
+
+ public void setOperator(String operator) {
+ this.operator = operator;
+ }
+
+ public String getDefaultValue() {
+ return defaultValue;
+ }
+
+ public void setDefaultValue(String defaultValue) {
+ this.defaultValue = defaultValue;
+ }
+
+ public List getDefaultValues() {
+ return defaultValues;
+ }
+
+ public void setDefaultValues(List defaultValues) {
+ this.defaultValues = defaultValues;
+ }
+
+ public String getLeftOperator() {
+ return leftOperator;
+ }
+
+ public void setLeftOperator(String leftOperator) {
+ this.leftOperator = leftOperator;
+ }
+
+ public String getRightOperator() {
+ return rightOperator;
+ }
+
+ public void setRightOperator(String rightOperator) {
+ this.rightOperator = rightOperator;
+ }
+
+ public String getLeftValue() {
+ return leftValue;
+ }
+
+ public void setLeftValue(String leftValue) {
+ this.leftValue = leftValue;
+ }
+
+ public String getRightValue() {
+ return rightValue;
+ }
+
+ public void setRightValue(String rightValue) {
+ this.rightValue = rightValue;
+ }
+}
diff --git a/workflow-engine-common/src/main/java/cn/axzo/workflow/common/model/request/bpmn/BpmnConditionGroup.java b/workflow-engine-common/src/main/java/cn/axzo/workflow/common/model/request/bpmn/BpmnConditionGroup.java
new file mode 100644
index 000000000..2784cd551
--- /dev/null
+++ b/workflow-engine-common/src/main/java/cn/axzo/workflow/common/model/request/bpmn/BpmnConditionGroup.java
@@ -0,0 +1,48 @@
+package cn.axzo.workflow.common.model.request.bpmn;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import lombok.experimental.Accessors;
+
+import java.util.List;
+
+/**
+ * 条件组
+ *
+ * 目前条件中的所有项都是"并且",所以没有第二个属性,如果以后有"或者"的情况,再加
+ *
+ * @author wangli
+ * @since 2023/11/13 19:58
+ */
+@ApiModel("JSON 版本的 BPMN 协议模型中的条件组")
+@Data
+@NoArgsConstructor
+@Accessors(chain = true)
+public class BpmnConditionGroup {
+
+ @ApiModelProperty(value = "条件组")
+ private List conditions;
+
+ /**
+ * 条件间模式,默认为"and"
+ */
+ private String mode = "and";
+
+ public List getConditions() {
+ return conditions;
+ }
+
+ public void setConditions(List conditions) {
+ this.conditions = conditions;
+ }
+
+ public String getMode() {
+ return mode;
+ }
+
+ public void setMode(String mode) {
+ this.mode = mode;
+ }
+}
diff --git a/workflow-engine-common/src/main/java/cn/axzo/workflow/common/model/request/bpmn/BpmnFieldConf.java b/workflow-engine-common/src/main/java/cn/axzo/workflow/common/model/request/bpmn/BpmnFieldConf.java
new file mode 100644
index 000000000..9c5a8f6a9
--- /dev/null
+++ b/workflow-engine-common/src/main/java/cn/axzo/workflow/common/model/request/bpmn/BpmnFieldConf.java
@@ -0,0 +1,91 @@
+package cn.axzo.workflow.common.model.request.bpmn;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import lombok.experimental.Accessors;
+
+import javax.validation.Valid;
+import javax.validation.constraints.NotBlank;
+import java.util.List;
+
+/**
+ * 流程定义中的字段管理
+ *
+ * @author wangli
+ * @since 2023/11/13 13:53
+ */
+@ApiModel("JSON 版本的 BPMN 协议模型中的字段管理")
+@Data
+@NoArgsConstructor
+@Accessors(chain = true)
+public class BpmnFieldConf {
+
+ /**
+ * 字段的 code
+ */
+ @ApiModelProperty(value = "字段的 code", example = "fieldCode", notes = "字段的 code 必须唯一")
+ @NotBlank(message = "字段的 code 不能为空")
+ private String code;
+
+ /**
+ * 字段的名称
+ */
+ @ApiModelProperty(value = "字段的名称", example = "字段名称")
+ @NotBlank(message = "字段的名称不能为空")
+ private String name;
+
+ /**
+ * 字段的类型
+ */
+ @ApiModelProperty(value = "字段的类型", example = "string", notes = "string, number, date, datetime, boolean, " +
+ "select, radio, checkbox, textarea, file, image, editor")
+ @NotBlank(message = "字段的类型不能为空")
+ private String type;
+
+ /**
+ * 单选或多选的下拉选择框中的数据, 只有单选或多选的时候才会有值,并且内部的属性不应该为空
+ */
+ @ApiModelProperty(value = "单选或多选的下拉选择框中的数据")
+ @Valid
+ private List options;
+}
+
+/**
+ * 单选/多选的选项配置
+ */
+@Accessors(chain = true)
+@Data
+@NoArgsConstructor
+class BpmnFieldOptionConf {
+ /**
+ * 选项的名称
+ */
+ @ApiModelProperty(value = "选项的名称", example = "选项1")
+ @NotBlank(message = "选项的名称不能为空")
+ private String name;
+
+ /**
+ * 选项的值
+ */
+ @ApiModelProperty(value = "选项的值", example = "1")
+ @NotBlank(message = "选项的值不能为空")
+ private String value;
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getValue() {
+ return value;
+ }
+
+ public void setValue(String value) {
+ this.value = value;
+ }
+}
diff --git a/workflow-engine-common/src/main/java/cn/axzo/workflow/common/model/request/bpmn/BpmnJsonNodeProperty.java b/workflow-engine-common/src/main/java/cn/axzo/workflow/common/model/request/bpmn/BpmnJsonNodeProperty.java
index cd641c177..5df5b7433 100644
--- a/workflow-engine-common/src/main/java/cn/axzo/workflow/common/model/request/bpmn/BpmnJsonNodeProperty.java
+++ b/workflow-engine-common/src/main/java/cn/axzo/workflow/common/model/request/bpmn/BpmnJsonNodeProperty.java
@@ -1,11 +1,15 @@
package cn.axzo.workflow.common.model.request.bpmn;
import cn.axzo.workflow.common.enums.BpmnFlowNodeMode;
-import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskDelegateAssigner;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotEmpty;
+import javax.validation.constraints.NotNull;
+import java.util.List;
+
/**
* JSON 版本的 BPMN 协议中 UserTask 节点的属性扩展模型
*/
@@ -13,47 +17,71 @@ import lombok.Data;
@Data
public class BpmnJsonNodeProperty {
+ //************* 审批方式Start **************//
/**
- * 发起人节点审批人规则类型
+ * 审批方式: human(人工审批), autoPassed(自动通过), autoRejection(自动拒绝), nobody(不审批[仅业务节点可能有该值])
*/
- @ApiModelProperty(value = "发起人节点: 发起人规则类型 ASSIGN_USER/POSITION/ROLE")
- private String initiatorType;
+ @ApiModelProperty(value = "任务节点: 审批方式", notes = "human: 人工审批, autoPassed: 自动通过, autoRejection: 自动拒绝, nobody: " +
+ "不审批[仅业务节点可能有该值]")
+ @NotBlank(message = "审批方式不能为空")
+ private String approvalMethod;
+ //************* 审批方式End **************//
+
+
+ //************* 审批人所在范围Start **************//
+ /**
+ * 审批人所在范围: EntWorkspace(企业工作台), projectWorkspace(项目工作台), preTaskUserEnt(上节点审批人所在单位)
+ */
+ @ApiModelProperty(value = "任务节点: 审批人所在范围", notes = "EntWorkspace: 企业工作台, projectWorkspace: 项目工作台, preTaskUserEnt:" +
+ " 上节点审批人所在单位")
+ private String approverScope;
+ //************* 审批人所在范围End **************//
+
+
+ //************* 审批人指定Start **************//
+ /**
+ * 审批人指定: position(指定岗位), role(指定角色), identity(指定身份), initiatorLeader(发起人主管)
+ */
+ @ApiModelProperty(value = "任务节点: 审批人指定", notes = "position: 指定岗位, role: 指定角色, identity: 指定身份, initiatorLeader: " +
+ "发起人主管")
+ @NotBlank(message = "审批人指定不能为空")
+ private String approverSpecify;
/**
- * 非指定人时, 发起人和任务节点审批人具体的规则值
+ * 具体的配置值
*/
- @ApiModelProperty(value = "发起人节点/任务节点: 非 ASSIGN_USER 外的规则具体表达式")
- private String assigneeExpression;
+ @ApiModelProperty(value = "任务节点: 审批人指定的具体值")
+ @NotEmpty(message = "审批人指定的具体值不能为空")
+ private List specifyValue;
+ //************* 审批人指定End **************//
+
+ //************* 多人审批时审批方式Start **************//
/**
- * 是否是多实例Task节点;
+ * 是否是多实例Task节点, 在安心筑业务中, 所有节点应该都是多实例节点
*/
- @ApiModelProperty("任务节点: 是否是多实例Task节点")
- private Boolean isMultiTask;
+ @ApiModelProperty(value = "任务节点: 是否是多实例Task节点", notes = "在安心筑业务中, 所有节点应该都是多实例节点")
+ private Boolean isMultiTask = true;
/**
* Task 多实例模式;OR:"或签",AND:"会签"
*/
@ApiModelProperty(value = "任务节点: 多实例模式;OR:或签,AND:会签")
+ @NotNull(message = "多实例模式不能为空")
private BpmnFlowNodeMode multiMode;
+ //************* 多人审批时审批方式End **************//
+
+ //************* 审批人为空时Start **************//
/**
* 审批人为空是否允许自动跳过
*/
- @ApiModelProperty(value = "任务节点: 审批人为空是否允许自动跳过")
- private Boolean allowSkip = false;
+ @ApiModelProperty(value = "任务节点: 审批人为空处理方式", notes = "autoPassed: 自动通过, autoSkipped: 自动跳过, transferToAdmin: 转交给管理员")
+ @NotBlank(message = "审批人为空处理方式不能为空")
+ private String approverEmptyHandleType;
+ //************* 审批人为空时的策略End **************//
- /**
- * 任务节点审批人规则类型
- */
- @ApiModelProperty(value = "任务节点: 审批人规则类型 ASSIGN_USER/POSITION/ROLE")
- private String assignedType;
- /**
- * 指定审批人或发起人时,传入的信息
- */
- @ApiModelProperty(value = "发起人节点/任务节点: 指定审批人")
- private BpmnTaskDelegateAssigner assigner;
/**
* 表单字段权限
@@ -67,23 +95,17 @@ public class BpmnJsonNodeProperty {
@ApiModelProperty(value = "发起人节点/任务节点: 按钮权限集合", notes = "后端不做任何解析, 前端给什么样,就返什么样")
private String buttonPermission;
+
+ //************* 条件节点Start **************//
/**
* 条件节点中是否是默认分支,可以都不传;
*/
@ApiModelProperty(value = "条件节点: 是否是默认条件分支")
private Boolean defaultBranch;
- /**
- * 条件分支的Key
- */
- @ApiModelProperty(value = "条件节点: 条件分支的Key", notes = "枢智业务使用的极简条件判断方式")
- private String conditionBranchKey;
-
- /**
- * 条件节点当ConditionKey的值是多少,走该分支
- */
- @ApiModelProperty(value = "条件节点: 当ConditionKey的值是多少,走该分支", notes = "枢智业务使用的极简条件判断方式")
- private Integer conditionBranchValue;
+ @ApiModelProperty(value = "条件节点: 条件分组集合")
+ private List groups;
+ //************* 条件节点End **************//
/**
* 发起时使用的表单 key
diff --git a/workflow-engine-common/src/main/java/cn/axzo/workflow/common/model/request/bpmn/BpmnNoticeConf.java b/workflow-engine-common/src/main/java/cn/axzo/workflow/common/model/request/bpmn/BpmnNoticeConf.java
new file mode 100644
index 000000000..955456e65
--- /dev/null
+++ b/workflow-engine-common/src/main/java/cn/axzo/workflow/common/model/request/bpmn/BpmnNoticeConf.java
@@ -0,0 +1,66 @@
+package cn.axzo.workflow.common.model.request.bpmn;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import lombok.experimental.Accessors;
+
+import javax.validation.constraints.NotBlank;
+
+/**
+ * 流程定义中的通知配置
+ *
+ * @author wangli
+ * @since 2023/11/13 13:38
+ */
+@ApiModel("JSON 版本的 BPMN 协议模型中的通知管理")
+@Data
+@NoArgsConstructor
+@Accessors(chain = true)
+public class BpmnNoticeConf {
+
+ /**
+ * 待办消息模板 ID
+ */
+ @ApiModelProperty(value = "待办消息模板 ID")
+ @NotBlank(message = "待办消息模板 ID 不能为空")
+ private String pendingMessageId;
+
+ /**
+ * 通知消息模板 ID
+ */
+ @ApiModelProperty(value = "通知消息模板 ID")
+ @NotBlank(message = "通知消息模板 ID 不能为空")
+ private String noticeMessageId;
+
+ /**
+ * 短信模板 ID
+ */
+ @ApiModelProperty(value = "短信模板 ID")
+ private String smsId;
+
+ public String getPendingMessageId() {
+ return pendingMessageId;
+ }
+
+ public void setPendingMessageId(String pendingMessageId) {
+ this.pendingMessageId = pendingMessageId;
+ }
+
+ public String getNoticeMessageId() {
+ return noticeMessageId;
+ }
+
+ public void setNoticeMessageId(String noticeMessageId) {
+ this.noticeMessageId = noticeMessageId;
+ }
+
+ public String getSmsId() {
+ return smsId;
+ }
+
+ public void setSmsId(String smsId) {
+ this.smsId = smsId;
+ }
+}
diff --git a/workflow-engine-common/src/main/java/cn/axzo/workflow/common/model/request/bpmn/model/BpmnModelCreateDTO.java b/workflow-engine-common/src/main/java/cn/axzo/workflow/common/model/request/bpmn/model/BpmnModelCreateDTO.java
index a2e151699..cc73413c8 100644
--- a/workflow-engine-common/src/main/java/cn/axzo/workflow/common/model/request/bpmn/model/BpmnModelCreateDTO.java
+++ b/workflow-engine-common/src/main/java/cn/axzo/workflow/common/model/request/bpmn/model/BpmnModelCreateDTO.java
@@ -1,12 +1,16 @@
package cn.axzo.workflow.common.model.request.bpmn.model;
+import cn.axzo.workflow.common.model.request.bpmn.BpmnButtonConf;
+import cn.axzo.workflow.common.model.request.bpmn.BpmnFieldConf;
import cn.axzo.workflow.common.model.request.bpmn.BpmnJsonNode;
+import cn.axzo.workflow.common.model.request.bpmn.BpmnNoticeConf;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.experimental.Accessors;
import org.hibernate.validator.constraints.Length;
+import javax.validation.Valid;
import javax.validation.constraints.NotBlank;
/**
@@ -33,7 +37,8 @@ public class BpmnModelCreateDTO {
/**
* 自定义分类
*/
- @ApiModelProperty(value = "自定义分类", notes = "由业务自定义", example = "1")
+ @ApiModelProperty(value = "自定义分类", notes = "由业务自定义")
+ @NotBlank(message = "自定义分类不能为空")
private String category;
/**
@@ -45,9 +50,30 @@ public class BpmnModelCreateDTO {
/**
* 流程的Json 结构
*/
- @ApiModelProperty(value = "流程的Json 结构", example = "1")
+ @ApiModelProperty(value = "流程的 Json 结构")
private BpmnJsonNode node;
+ /**
+ * 通知管理配置
+ */
+ @ApiModelProperty(value = "通知管理配置")
+ @Valid
+ private BpmnNoticeConf noticeConf;
+
+ /**
+ * 流程定义的全局默认按钮权限数据
+ */
+ @ApiModelProperty(value = "流程按钮配置")
+ @Valid
+ private BpmnButtonConf buttonConf;
+
+ /**
+ * 流程定义的全局字段管理数据
+ */
+ @ApiModelProperty(value = "流程字段配置")
+ @Valid
+ private BpmnFieldConf fieldConf;
+
/**
* 租户Id
*/
diff --git a/workflow-engine-core/src/main/java/cn/axzo/workflow/core/common/enums/BpmnErrorCode.java b/workflow-engine-core/src/main/java/cn/axzo/workflow/core/common/enums/BpmnErrorCode.java
index c2d944d64..46ecd5b88 100644
--- a/workflow-engine-core/src/main/java/cn/axzo/workflow/core/common/enums/BpmnErrorCode.java
+++ b/workflow-engine-core/src/main/java/cn/axzo/workflow/core/common/enums/BpmnErrorCode.java
@@ -43,7 +43,7 @@ public enum BpmnErrorCode implements IProjectRespCode {
PROCESS_OPERATION_PARAM_VALID_ERROR("05001", "参数缺失, 请确保传入了 ID 或 businessKey 对流程实例进行操作"),
PROCESS_INSTANCE_CANCEL_FAIL_NOT_EXISTS("05002", "流程取消失败,流程不处于运行中"),
PROCESS_INSTANCE_CANCEL_FAIL_NOT_SELF("05003", "流程取消失败,该流程不是你发起的"),
- PROCESS_INSTANCE_NOT_EXISTS("05004", "流程实例不存在"),
+ PROCESS_INSTANCE_NOT_EXISTS("05004", "流程实例不存在或已结束"),
PROCESS_INSTANCE_ID_NOT_EXISTS("05005", "流程实例【{}】不存在"),
PROCESS_INSTANCE_CANCELLED("05006", "流程实例已取消"),
// ========== bpmn task 06-001 ==========
diff --git a/workflow-engine-core/src/main/java/cn/axzo/workflow/core/engine/listener/EngineExecutionStartListener.java b/workflow-engine-core/src/main/java/cn/axzo/workflow/core/engine/listener/EngineExecutionStartListener.java
index 1c8d7fe18..c36e53b20 100644
--- a/workflow-engine-core/src/main/java/cn/axzo/workflow/core/engine/listener/EngineExecutionStartListener.java
+++ b/workflow-engine-core/src/main/java/cn/axzo/workflow/core/engine/listener/EngineExecutionStartListener.java
@@ -77,7 +77,9 @@ public class EngineExecutionStartListener implements ExecutionListener {
// UserTask 非多实例
if (!userTask.hasMultiInstanceLoopCharacteristics()) {
//TODO by zuoqinbo assigneeIdList.size==0情况
- userTask.setAssignee(assigneeIdList.get(0));
+ if (!CollectionUtils.isEmpty(assigneeIdList)) {
+ userTask.setAssignee(assigneeIdList.get(0));
+ }
// remove by wangli, 暂时去除审批人变量, 通过上面直接赋值
// execution.setVariable("assigneeUserId", assigneeIdList.get(0));
diff --git a/workflow-engine-core/src/main/java/cn/axzo/workflow/core/service/impl/BpmnProcessInstanceServiceImpl.java b/workflow-engine-core/src/main/java/cn/axzo/workflow/core/service/impl/BpmnProcessInstanceServiceImpl.java
index b3a6208d1..1a02394f8 100644
--- a/workflow-engine-core/src/main/java/cn/axzo/workflow/core/service/impl/BpmnProcessInstanceServiceImpl.java
+++ b/workflow-engine-core/src/main/java/cn/axzo/workflow/core/service/impl/BpmnProcessInstanceServiceImpl.java
@@ -285,7 +285,8 @@ public class BpmnProcessInstanceServiceImpl implements BpmnProcessInstanceServic
public Boolean cancelProcessInstance(BpmnProcessInstanceCancelDTO dto) {
HistoricProcessInstance instance = null;
if (StringUtils.isNotBlank(dto.getId())) {
- instance = getProcessInstance(dto.getId(), dto.getInitiator().getTenantId(), false);
+ instance = getProcessInstance(dto.getId(), null, false);
+ // instance = getProcessInstance(dto.getId(), dto.getInitiator().getTenantId(), false);
} else if (StringUtils.isNotBlank(dto.getBusinessKey())) {
instance = getProcessInstanceByBusinessKey(dto.getBusinessKey(), dto.getInitiator().getTenantId(), false);
} else {
diff --git a/workflow-engine-core/src/main/java/cn/axzo/workflow/core/service/impl/BpmnTaskServiceImpl.java b/workflow-engine-core/src/main/java/cn/axzo/workflow/core/service/impl/BpmnTaskServiceImpl.java
index 97821e0f3..a382dc1c8 100644
--- a/workflow-engine-core/src/main/java/cn/axzo/workflow/core/service/impl/BpmnTaskServiceImpl.java
+++ b/workflow-engine-core/src/main/java/cn/axzo/workflow/core/service/impl/BpmnTaskServiceImpl.java
@@ -1,8 +1,13 @@
package cn.axzo.workflow.core.service.impl;
-import cn.axzo.workflow.common.enums.BpmnCountersignType;
import cn.axzo.workflow.common.enums.BpmnProcessInstanceResultEnum;
-import cn.axzo.workflow.common.model.request.bpmn.task.*;
+import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskAssigneeDTO;
+import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskAttachmentDTO;
+import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskAuditDTO;
+import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskCommentDTO;
+import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskCountersignDTO;
+import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskDelegateAssigner;
+import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskPageSearchDTO;
import cn.axzo.workflow.common.model.response.BpmPageResult;
import cn.axzo.workflow.common.model.response.bpmn.task.BpmnHistoricTaskInstanceGroupVO;
import cn.axzo.workflow.common.model.response.bpmn.task.BpmnHistoricTaskInstanceVO;
@@ -72,8 +77,8 @@ import static cn.axzo.workflow.common.constant.BpmnConstants.INTERNAL_SPECIFY_NE
import static cn.axzo.workflow.common.constant.BpmnConstants.INTERNAL_TASK_RELATION_ASSIGNEE_INFO_SNAPSHOT;
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.TASK_COMPLETE_OPERATION_TYPE;
import static cn.axzo.workflow.common.enums.BpmnProcessInstanceResultEnum.APPROVED;
-import static cn.axzo.workflow.common.enums.BpmnProcessInstanceResultEnum.CANCELLED;
import static cn.axzo.workflow.common.enums.BpmnProcessInstanceResultEnum.PROCESSING;
import static cn.axzo.workflow.common.enums.BpmnProcessInstanceResultEnum.REJECTED;
import static cn.axzo.workflow.common.enums.BpmnProcessInstanceResultEnum.valueOfStatus;
@@ -204,7 +209,7 @@ public class BpmnTaskServiceImpl implements BpmnTaskService {
NativeHistoricTaskInstanceQuery nativeQuery = historyService.createNativeHistoricTaskInstanceQuery();
String tableName = managementService.getTableName(HistoricTaskInstance.class);
baseQuerySql.append("SELECT a.* FROM ").append(tableName).append(" a JOIN " +
- "ACT_HI_PROCINST b")
+ "ACT_HI_PROCINST b")
.append(" ON b.PROC_INST_ID_ = a.PROC_INST_ID_");
if (StringUtils.hasLength(dto.getTenantId())) {
@@ -286,7 +291,7 @@ public class BpmnTaskServiceImpl implements BpmnTaskService {
Task task = checkTask(dto.getApprover().getTenantId(), dto.getApprover().buildAssigneeId(), dto.getTaskId());
// 校验流程实例存在
HistoricProcessInstance instance = processInstanceService.getProcessInstance(
- task.getProcessInstanceId(), dto.getApprover().getTenantId(), true);
+ task.getProcessInstanceId(), null, true);
if (instance == null) {
throw new WorkflowEngineException(PROCESS_INSTANCE_NOT_EXISTS);
}
@@ -374,7 +379,9 @@ public class BpmnTaskServiceImpl implements BpmnTaskService {
query.taskTenantId(tenantId);
}
HistoricProcessInstanceQuery instanceQuery =
- historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId);
+ historyService.createHistoricProcessInstanceQuery()
+ .includeProcessVariables()
+ .processInstanceId(processInstanceId);
if (StringUtils.hasLength(tenantId)) {
instanceQuery.processInstanceTenantId(tenantId);
}
@@ -394,20 +401,16 @@ public class BpmnTaskServiceImpl implements BpmnTaskService {
Map variableInstanceMap =
historyService.createHistoricVariableInstanceQuery().processInstanceId(processInstanceId).list()
.stream().collect(Collectors.toMap(HistoricVariableInstance::getVariableName,
- Function.identity(), (s, t) -> s));
+ Function.identity(), (s, t) -> s));
Set taskDefinitionKeys = new HashSet<>();
int count = 0;
- BpmnProcessInstanceResultEnum finalBusinessStatus = valueOfStatus(instance.getBusinessStatus());
+ BpmnProcessInstanceResultEnum processBusinessStatus = valueOfStatus(instance.getBusinessStatus());
for (BpmnHistoricTaskInstanceVO vo : vos) {
- if (count == 0 || taskDefinitionKeys.contains(vo.getTaskDefinitionKey())) {
- vo.setResult(finalBusinessStatus);
- if (Objects.nonNull(vo.getEndTime()) && !Objects.equals(finalBusinessStatus, REJECTED)
- && !Objects.equals(finalBusinessStatus, CANCELLED)) {
- vo.setResult(APPROVED);
- }
- } else {
- vo.setResult(APPROVED);
+ vo.setResult(processBusinessStatus);
+ if (Objects.nonNull(vo.getEndTime())) {
+ // 只有拒绝时, 为指定的 taskId 设置过拒绝变量
+ vo.setResult((BpmnProcessInstanceResultEnum) instance.getProcessVariables().getOrDefault(TASK_COMPLETE_OPERATION_TYPE + vo.getTaskId(), APPROVED));
}
taskDefinitionKeys.add(vo.getTaskDefinitionKey());
List taskComments = commentByTaskIdMap.getOrDefault(vo.getTaskId(), Collections.emptyList());
@@ -482,9 +485,20 @@ public class BpmnTaskServiceImpl implements BpmnTaskService {
List vos = bpmnTaskConverter.toVos(query.list());
List snapshotTaskIds =
vos.stream().map(i -> INTERNAL_TASK_RELATION_ASSIGNEE_INFO_SNAPSHOT + i.getTaskId()).collect(Collectors.toList());
+ ProcessInstance processInstance =
+ runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
+ if (Objects.isNull(processInstance)) {
+ throw new WorkflowEngineException(PROCESS_INSTANCE_NOT_EXISTS);
+ }
Map instanceMap = runtimeService.getVariableInstances(processInstanceId,
snapshotTaskIds);
- vos.forEach(i -> i.setAssigner((BpmnTaskDelegateAssigner) instanceMap.get(INTERNAL_TASK_RELATION_ASSIGNEE_INFO_SNAPSHOT + i.getTaskId()).getValue()));
+ vos.forEach(i -> {
+ VariableInstance variableInstance =
+ instanceMap.get(INTERNAL_TASK_RELATION_ASSIGNEE_INFO_SNAPSHOT + i.getTaskId());
+ if (!Objects.isNull(variableInstance)) {
+ i.setAssigner((BpmnTaskDelegateAssigner) variableInstance.getValue());
+ }
+ });
return vos;
}
@@ -497,13 +511,11 @@ public class BpmnTaskServiceImpl implements BpmnTaskService {
* @param taskId 任务ID
*/
private Task checkTask(String tenantId, String assignee, String taskId) {
-
- Task task = getTask(taskId, assignee, tenantId);
- if (Objects.nonNull(task) && !Objects.equals(assignee, task.getAssignee())) {
- throw new WorkflowEngineException(TASK_COMPLETE_FAIL_ASSIGN_NOT_SELF);
- }
+ Task task = getTask(taskId, null, null);
if (Objects.isNull(task)) {
throw new WorkflowEngineException(TASK_COMPLETE_FAIL_NOT_EXISTS);
+ } else if (!Objects.equals(assignee, task.getAssignee()) && !Objects.equals(tenantId, task.getTenantId())) {
+ throw new WorkflowEngineException(TASK_COMPLETE_FAIL_ASSIGN_NOT_SELF);
}
return task;
}
diff --git a/workflow-engine-core/src/main/resources/test.bpmn20.xml b/workflow-engine-core/src/main/resources/test.bpmn20.xml
new file mode 100644
index 000000000..b8e5d06b8
--- /dev/null
+++ b/workflow-engine-core/src/main/resources/test.bpmn20.xml
@@ -0,0 +1,74 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/workflow-engine-server/src/main/java/cn/axzo/workflow/server/controller/delegate/BpmnDefaultTaskDelegateImpl.java b/workflow-engine-server/src/main/java/cn/axzo/workflow/server/controller/delegate/BpmnDefaultTaskDelegateImpl.java
index 537b8ded3..a53990fac 100644
--- a/workflow-engine-server/src/main/java/cn/axzo/workflow/server/controller/delegate/BpmnDefaultTaskDelegateImpl.java
+++ b/workflow-engine-server/src/main/java/cn/axzo/workflow/server/controller/delegate/BpmnDefaultTaskDelegateImpl.java
@@ -94,6 +94,27 @@ public class BpmnDefaultTaskDelegateImpl implements BpmnTaskDelegate {
assigners.add(assigner2);
}
}
+
+ if (CollectionUtils.isEmpty(assigners) && Objects.equals("69", delegateTask.getTenantId())) {
+ if (Objects.equals("NODE1639041346796_0.5413743892974803_0", delegateTask.getTaskDefinitionKey())) {
+ BpmnTaskDelegateAssigner assigner1 = new BpmnTaskDelegateAssigner();
+ assigner1.setAssignee("1");
+ assigner1.setAssigneeType("5");
+ assigner1.setAssignerName("或签人1");
+ assigner1.setPersonId("100001");
+ assigner1.setTenantId("296");
+ assigners.add(assigner1);
+ }
+ if (Objects.equals("NODE1687933854432_0.45762305710855467_1", delegateTask.getTaskDefinitionKey())) {
+ BpmnTaskDelegateAssigner assigner1 = new BpmnTaskDelegateAssigner();
+ assigner1.setAssignee("1");
+ assigner1.setAssigneeType("5");
+ assigner1.setAssignerName("或签人1");
+ assigner1.setPersonId("100001");
+ assigner1.setTenantId("296");
+ assigners.add(assigner1);
+ }
+ }
return assigners;
}
}
diff --git a/workflow-engine-server/src/main/resources/bootstrap.yml b/workflow-engine-server/src/main/resources/bootstrap.yml
index ba3bc7d89..fd86ec1a4 100644
--- a/workflow-engine-server/src/main/resources/bootstrap.yml
+++ b/workflow-engine-server/src/main/resources/bootstrap.yml
@@ -32,7 +32,7 @@ spring:
server-addr: ${NACOS_HOST:https://dev-nacos.axzo.cn}:${NACOS_PORT:443}
file-extension: yaml
# namespace: ${NACOS_NAMESPACE_ID:1b5d2a22-b340-4503-8464-7d7fc2059d39}
- namespace: ${NACOS_NAMESPACE_ID:35eada10-9574-4db8-9fea-bc6a4960b6c7}
+ namespace: ${NACOS_NAMESPACE_ID:f82179f1-81a9-41a1-a489-4f9ab5660a6e}
---
#开发环境