feat: let the current assignee reassign a pending task
Keep the same task id, move the pending inbox, and record TASK_REASSIGNED without advancing the step. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+17
-6
@@ -13,15 +13,12 @@
|
||||
- 发起人撤回 `WITHDRAWN`
|
||||
- 分页查询:任务 / 实例 / 定义
|
||||
- 审计 `ProcessEvent` / `queryHistory`;`OrdoEventListener`
|
||||
- 任务转派 `reassign` / `TASK_REASSIGNED`
|
||||
|
||||
## 开发计划(确定要做)
|
||||
|
||||
下列能力已纳入计划,尚未实现。实现顺序可按依赖调整,但范围本身不从计划中拿掉。
|
||||
|
||||
### 任务转派
|
||||
|
||||
任务创建后当前 `assignee` 不可变。计划提供委托/转派(delegate/reassign),把待办转给他人办理,并写入审计。
|
||||
|
||||
### 到期升级
|
||||
|
||||
目前无到期时间与定时器。计划支持 SLA/超时:到期后升级(改办理人、通知或进入指定步骤),即「到期升级」。
|
||||
@@ -38,13 +35,27 @@
|
||||
|
||||
当前 JDBC DDL/冲突处理面向 PostgreSQL。计划增加 MySQL 方言(及对应测试),通过 dialect 层扩展,而不是只支持一种库。
|
||||
|
||||
### 可选 REST + 目录 SPI
|
||||
|
||||
引擎入口仍是 `OrdoEngine`。计划提供**可选、极薄**的 REST 适配(例如独立 starter),带 OpenAPI,覆盖定义读写/解析校验、实例与任务查询,不包含鉴权、RBAC、业务表单。
|
||||
|
||||
配套 **目录 SPI**:宿主登记可用的 `conditionKey` / `actionKey` / 候选人(或角色)项,供 REST 与外部设计器下拉,而不是在 JSON 里写引擎无法执行的表达式。
|
||||
|
||||
`RoutingCondition` / `ActionHandler` / `AssigneeResolver` 保持全局单例;流程隔离由宿主用 key 约定(建议前缀)+ 门面分发,引擎不按流程定义拆 bean。
|
||||
|
||||
### 独立设计器(不进本仓库)
|
||||
|
||||
流程设计器是**单独产品**,消费上述 REST 与目录,不做成 ordo 模块。画布对齐引擎图(审批步、ACTION 步、边上的 `when`/`priority`,结束为 `to: null`),不引入 BPMN 网关/并行等引擎没有的语义。节点坐标等 layout 由设计器自存,不进入 `ProcessDefinition`。
|
||||
|
||||
启动时机:REST 契约、目录 SPI、定义不可变多版本落地之后。当前 `replace` + 无版本锁定不适合作为设计器保存/发布模型。
|
||||
|
||||
## 暂不在计划中
|
||||
|
||||
- **多租户**(数据模型无 tenant 隔离)
|
||||
- **官方 REST Starter**(不提供 `ordo-spring-boot-starter-web`;REST 由宿主自建)
|
||||
- **设计器 UI**(不进 ordo;见上节独立产品)
|
||||
|
||||
## 后续新特性
|
||||
|
||||
上表「确定要做」之外,仍可能立项其他能力(例如表单/UI schema、子流程、并行 fork-join)。**多租户与官方 REST 在另有明确决定前不进入计划。**
|
||||
上表「确定要做」之外,仍可能立项其他能力(例如表单/UI schema、子流程、并行 fork-join)。**多租户在另有明确决定前不进入计划。**
|
||||
|
||||
新特性立项时写入「开发计划」对应小节;完成后移到「已完成」,并更新 [usage.md](usage.md)。
|
||||
|
||||
+16
-11
@@ -10,9 +10,9 @@ Ordo 是嵌入宿主进程的审批引擎,入口是 `OrdoEngine`。
|
||||
|
||||
做:流程定义、实例推进、待办任务、条件路由、ACTION 副作用、审计事件、分页查询。
|
||||
|
||||
产品边界(不做,且暂不在开发计划):业务表单、用户体系、官方 REST、多租户。业务字段放在 `ProcessContext`(不可变 `Map<String, Object>`)。
|
||||
产品边界:不做业务表单、用户体系、多租户;不内置设计器 UI。业务字段放在 `ProcessContext`(不可变 `Map<String, Object>`)。当前也**没有** REST;HTTP 仍由宿主自建。计划中的可选 REST 与独立设计器见 [roadmap.md](roadmap.md)。
|
||||
|
||||
开发计划(尚未提供,见 [roadmap.md](roadmap.md)):任务转派、到期升级、`CANCELLED`、定义不可变多版本、MySQL 方言。
|
||||
开发计划(尚未提供,见 [roadmap.md](roadmap.md)):到期升级、`CANCELLED`、定义不可变多版本、MySQL 方言、可选 REST + 目录 SPI。
|
||||
|
||||
## 2. 模块与接入
|
||||
|
||||
@@ -189,7 +189,8 @@ ProcessInstance instance = ordo.start("leave-request", "alice",
|
||||
new ProcessContext(Map.of("requestId", "LEAVE-001", "days", 2)));
|
||||
|
||||
List<ApprovalTask> pending = ordo.findPendingTasksByInstanceId(instance.id());
|
||||
ordo.approve(pending.get(0).id(), "maria", "ok");
|
||||
ordo.reassign(pending.get(0).id(), "maria", "diana");
|
||||
ordo.approve(pending.get(0).id(), "diana", "ok");
|
||||
|
||||
ordo.reject(taskId, "maria", "额度不足");
|
||||
ordo.withdraw(instance.id(), "alice", "计划有变");
|
||||
@@ -199,11 +200,12 @@ ordo.withdraw(instance.id(), "alice", "计划有变");
|
||||
|
||||
### 4.2 权限
|
||||
|
||||
- `approve` / `reject`:`actor` 必须等于该任务当前 `assignee`,否则 `UnauthorizedTaskOperationException`。
|
||||
- `approve` / `reject` / `reassign`:`actor` 必须等于该任务当前 `assignee`,否则 `UnauthorizedTaskOperationException`。
|
||||
- `reassign`:仅 `PENDING` 任务;同一任务 id,办理人改为 `newAssignee`,不推进步骤。`newAssignee` 不可空白、不可等于当前 `assignee`,且同一步不能已有该人的 `PENDING` 任务,否则 `IllegalArgumentException`。不经过 `AssigneeResolver`。
|
||||
- 任务非 `PENDING`:`TaskAlreadyCompletedException`。
|
||||
- `withdraw`:仅 `initiator`,否则 `UnauthorizedInstanceOperationException`;实例非 `RUNNING`:`InstanceAlreadyCompletedException`。
|
||||
|
||||
没有转派、没有管理员代批、没有系统取消。
|
||||
没有管理员代批、没有系统取消。
|
||||
|
||||
### 4.3 状态
|
||||
|
||||
@@ -237,7 +239,9 @@ ordo.withdraw(instance.id(), "alice", "计划有变");
|
||||
|
||||
无条件边通常作为默认分支,`priority` 应大于带 `when` 的边。
|
||||
|
||||
`RoutingCondition` 只看到 `ProcessContext`,看不到任务意见。上下文在 `start` 时写入,运行中引擎**不会**改 context。
|
||||
`RoutingCondition` 只看到 `ProcessContext`,看不到任务意见,也**没有**流程定义 id。上下文在 `start` 时写入,运行中引擎**不会**改 context。
|
||||
|
||||
引擎只注入**一个** `RoutingCondition`(与 `ActionHandler` 相同)。Spring 下多个该类型 Bean 会冲突。宿主用一个门面按 `conditionKey` 分发到多套规则;不同流程靠 key 约定隔离(例如 `leave.days-gt-3`),不要指望引擎按定义拆 bean。
|
||||
|
||||
## 7. ACTION 步骤
|
||||
|
||||
@@ -271,10 +275,10 @@ public class MailActions implements ActionHandler {
|
||||
`ProcessEventType`:
|
||||
|
||||
- `INSTANCE_STARTED` / `INSTANCE_APPROVED` / `INSTANCE_REJECTED` / `INSTANCE_WITHDRAWN`
|
||||
- `TASK_CREATED` / `TASK_APPROVED` / `TASK_REJECTED` / `TASK_SKIPPED`
|
||||
- `TASK_CREATED` / `TASK_APPROVED` / `TASK_REJECTED` / `TASK_SKIPPED` / `TASK_REASSIGNED`
|
||||
- `ACTION_SUCCEEDED` / `ACTION_FAILED`
|
||||
|
||||
字段:`id`、`instanceId`、可选 `taskId`/`stepId`/`actor`/`detail`、`occurredAt`。系统完成类事件 `actor` 可为空。
|
||||
字段:`id`、`instanceId`、可选 `taskId`/`stepId`/`actor`/`detail`、`occurredAt`。系统完成类事件 `actor` 可为空。`TASK_REASSIGNED` 的 `actor` 为转出人,`detail` 为转入人。
|
||||
|
||||
`OrdoEventListener.onEvent(ProcessEvent)` 在**事务提交之后**按事件顺序调用(含本轮 ACTION 结果)。单个 listener 抛错只打日志,不影响流程和其他 listener。
|
||||
|
||||
@@ -307,6 +311,7 @@ ACTION 成功事件发生在提交之后,因此排在同轮事务内写入的
|
||||
| `register` / `replace` | 登记 / 整图替换定义 |
|
||||
| `start` | 发起;可选 `ProcessContext` |
|
||||
| `approve` / `reject` | 办理当前 PENDING 任务 |
|
||||
| `reassign` | 当前办理人把 PENDING 任务转给他人 |
|
||||
| `withdraw` | 发起人撤回 |
|
||||
| `find*` | 按 id / 待办索引读取 |
|
||||
| `queryTasks` / `queryInstances` / `queryDefinitions` | 分页列表 |
|
||||
@@ -325,7 +330,7 @@ ACTION 成功事件发生在提交之后,因此排在同轮事务内写入的
|
||||
| `InstanceAlreadyCompletedException` | 对非 RUNNING 实例完成/撤回 |
|
||||
| `TaskNotFoundException` | 任务 id 不存在 |
|
||||
| `TaskAlreadyCompletedException` | 重复办理或已被 SKIPPED |
|
||||
| `UnauthorizedTaskOperationException` | actor ≠ assignee |
|
||||
| `UnauthorizedTaskOperationException` | actor ≠ 当前 assignee(approve / reject / reassign) |
|
||||
| `UnauthorizedInstanceOperationException` | 非发起人撤回 |
|
||||
| `NoRouteFoundException` | 当前步没有匹配转移 |
|
||||
|
||||
@@ -339,6 +344,6 @@ Flyway 脚本在 `ordo-storage-jdbc` 的 `db/migration`(V1–V5)。表包括
|
||||
|
||||
## 13. 未提供能力
|
||||
|
||||
开发计划中(见 [roadmap.md](roadmap.md)):转派、到期升级、`CANCELLED`、定义不可变多版本、MySQL 方言。
|
||||
开发计划中(见 [roadmap.md](roadmap.md)):到期升级、`CANCELLED`、定义不可变多版本、MySQL 方言、可选 REST + 目录 SPI。独立设计器不进本仓库,等 REST、目录与多版本定义之后再做。
|
||||
|
||||
暂不在计划中:多租户、官方 REST Starter。REST 由宿主自建。
|
||||
暂不在计划中:多租户、设计器 UI。当前 REST 由宿主自建。
|
||||
|
||||
Reference in New Issue
Block a user