R5-M1-M5 收口正式审批规则与移动反馈
这个提交包含在:
+28
-1
@@ -2,6 +2,13 @@ const { AppError } = require("./AppError");
|
||||
|
||||
const UUID_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
||||
const MAX_MANAGER_DEPTH = 10;
|
||||
const BLOCKING_ASSIGNEE_SKIP_REASONS = new Set([
|
||||
"no_manager_found",
|
||||
"chain_broken",
|
||||
"self_loop",
|
||||
"cycle_detected",
|
||||
"max_depth_exceeded",
|
||||
]);
|
||||
|
||||
function parseWorkflowSteps(definitionJson) {
|
||||
const steps = definitionJson?.steps;
|
||||
@@ -233,7 +240,14 @@ async function resolveAssigneeFromRule(rule, options = {}) {
|
||||
});
|
||||
}
|
||||
|
||||
async function resolveActionableStep({ tx, steps, startIndex, ownerId, logger }) {
|
||||
async function resolveActionableStep({
|
||||
tx,
|
||||
steps,
|
||||
startIndex,
|
||||
ownerId,
|
||||
logger,
|
||||
blockOnUnresolvedAssignee = false,
|
||||
}) {
|
||||
const skipped = [];
|
||||
|
||||
for (let index = startIndex; index < steps.length; index += 1) {
|
||||
@@ -257,6 +271,19 @@ async function resolveActionableStep({ tx, steps, startIndex, ownerId, logger })
|
||||
}
|
||||
|
||||
if (resolved.skipReason) {
|
||||
if (blockOnUnresolvedAssignee && BLOCKING_ASSIGNEE_SKIP_REASONS.has(resolved.skipReason)) {
|
||||
throw new AppError({
|
||||
code: "VALID_001",
|
||||
message: "参数校验失败",
|
||||
statusCode: 409,
|
||||
details: {
|
||||
workflow: "no_actionable_approver",
|
||||
reason: resolved.skipReason,
|
||||
stepId: step.id,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
skipped.push({
|
||||
index,
|
||||
step,
|
||||
|
||||
在新工单中引用
屏蔽一个用户