关于 approval-workflows
面向 ServiceNow 的审批工作流技能,用于为记录设计和管理审批链。内容涵盖审批规则、个人与群组审批、委派、通知及相关 MCP 工具,并提供 ES5 示例。
主要功能
- 01可配置审批规则
- 02个人与群组审批
- 03审批委派
- 04处理决定并更新父记录
- 05审批通知
- 06ES5 脚本示例
适用场景
- 01为变更请求设置审批流程
- 02配置群组审批门槛
- 03缺勤期间委派审批
- 04检查并测试审批脚本
MCP 相关
文档列出用于查询审批记录、定义审批链、查找相关业务规则、测试脚本及创建审批触发器的 MCP 工具。
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ serac-labs/ serac --skill approval-workflows安装后在 Claude Code 中输入/approval-workflows确认已加载。
详细介绍
ServiceNow 的审批工作流
审批工作流会通过可配置的审批链路由记录。
审批架构
Record (change_request, sc_req_item, etc.)
↓
Approval Rules (sysapproval_rule)
↓
Approval Records (sysapproval_approver)
↓ Approve/Reject
Record State Updated
关键表
| 表 | 用途 |
|---|---|
sysapproval_approver | 单条审批记录 |
sysapproval_group | 群组审批配置 |
sysapproval_rule | 审批规则 |
sys_approval_workflow | 审批工作流阶段 |
审批规则(ES5)
创建审批规则
// Create approval rule (ES5 ONLY!)
var rule = new GlideRecord("sysapproval_rule")
rule.initialize()
// Rule identification
rule.setValue("name", "Change Request Manager Approval")
rule.setValue("table", "change_request")
rule.setValue("order", 100)
rule.setValue("active", true)
// Conditions - when rule applies
rule.setValue("conditions", "type=normal^priority<=2")
// Approver type
rule.setValue("approver", "manager") // manager, group, user, script
// For user: rule.setValue('approver_user', userSysId);
// For group: rule.setValue('approver_group', groupSysId);
// Approval type
rule.setValue("approval_type", "and") // and (all must approve), or (any can approve)
// Wait for previous level
rule.setValue("wait_for", true)
rule.insert()
基于脚本选择审批人
// Approval rule with script (ES5 ONLY!)
var rule = new GlideRecord("sysapproval_rule")
rule.initialize()
rule.setValue("name", "Cost-Based Approval")
rule.setValue("table", "sc_req_item")
rule.setValue("approver", "script")
// Script to determine approvers (ES5 ONLY!)
rule.setValue(
"script",
"(function getApprovers(current) {\n" +
" var approvers = [];\n" +
' var cost = parseFloat(current.getValue("estimated_cost")) || 0;\n' +
" \n" +
" // Manager approval for all\n" +
" var caller = current.requested_for.getRefRecord();\n" +
" if (caller.manager) {\n" +
" approvers.push(caller.manager.toString());\n" +
" }\n" +
" \n" +
" // Director approval for > $5000\n" +
" if (cost > 5000) {\n" +
" var director = getDirector(caller);\n" +
" if (director) approvers.push(director);\n" +
" }\n" +
" \n" +
" // VP approval for > $25000\n" +
" if (cost > 25000) {\n" +
" var vp = getVP(caller);\n" +
" if (vp) approvers.push(vp);\n" +
" }\n" +
" \n" +
" return approvers;\n" +
"})(current);",
)
rule.insert()
管理审批(ES5)
手动创建审批
// Create approval record (ES5 ONLY!)
function createApproval(recordSysId, approverSysId, source) {
var approval = new GlideRecord("sysapproval_approver")
approval.initialize()
approval.setValue("sysapproval", recordSysId)
approval.setValue("approver", approverSysId)
approval.setValue("state", "requested")
approval.setValue("source_table", source.table || "")
return approval.insert()
}
处理审批决定
// Approve or reject (ES5 ONLY!)
function processApprovalDecision(approvalSysId, decision, comments) {
var approval = new GlideRecord("sysapproval_approver")
if (!approval.get(approvalSysId)) {
return { success: false, message: "Approval not found" }
}
// Validate current state
if (approval.getValue("state") !== "requested") {
return { success: false, message: "Approval already processed" }
}
// Validate approver
if (approval.getValue("approver") !== gs.getUserID()) {
if (!canActOnBehalf(approval.getValue("approver"))) {
return { success: false, message: "Not authorized to approve" }
}
}
// Set decision
approval.setValue("state", decision) // 'approved' or 'rejected'
approval.setValue("comments", comments)
approval.setValue("actual_approver", gs.getUserID())
approval.update()
// Update parent record approval status
updateParentApprovalStatus(approval.getValue("sysapproval"))
return {
success: true,
decision: decision,
record: approval.sysapproval.getDisplayValue(),
}
}
function canActOnBehalf(originalApproverId) {
// Check delegation
var delegation = new GlideRecord("sys_user_delegate")
delegation.addQuery("user", originalApproverId)
delegation.addQuery("delegate", gs.getUserID())
delegation.addQuery("starts", "<=", new GlideDateTime())
delegation.addQuery("ends", ">=", new GlideDateTime())
delegation.addQuery("approvals", true)
delegation.query()
return delegation.hasNext()
}
更新父记录
// Update approval status on parent record (ES5 ONLY!)
function updateParentApprovalStatus(recordSysId) {
// Get all approvals for this record
var approvals = new GlideRecord("sysapproval_approver")
approvals.addQuery("sysapproval", recordSysId)
approvals.query()
var requested = 0
var approved = 0
var rejected = 0
while (approvals.next()) {
var state = approvals.getValue("state")
if (state === "requested") requested++
else if (state === "approved") approved++
else if (state === "rejected") rejected++
}
// Determine overall status
var overallStatus = "not requested"
if (rejected > 0) {
overallStatus = "rejected"
} else if (requested > 0) {
overallStatus = "requested"
} else if (approved > 0) {
overallStatus = "approved"
}
// Update parent record
var parent = new GlideRecord("change_request")
if (parent.get(recordSysId)) {
parent.setValue("approval", overallStatus)
parent.update()
}
}
群组审批(ES5)
配置群组审批
// Create group approval configuration (ES5 ONLY!)
var groupApproval = new GlideRecord("sysapproval_group")
groupApproval.initialize()
groupApproval.setValue("parent", recordSysId)
groupApproval.setValue("group", groupSysId)
// Approval requirement
groupApproval.setValue("approval", "any") // any, all, specific_count
groupApproval.setValue("specific_count", 2) // If specific_count
groupApproval.insert()
设置最低人数的群组审批
// Check if group approval threshold met (ES5 ONLY!)
function checkGroupApprovalThreshold(groupApprovalSysId) {
var groupConfig = new GlideRecord("sysapproval_group")
if (!groupConfig.get(groupApprovalSysId)) {
return false
}
var approvalType = groupConfig.getValue("approval")
var groupId = groupConfig.getValue("group")
var parentId = groupConfig.getValue("parent")
// Count approvals from group members
var ga = new GlideAggregate("sysapproval_approver")
ga.addQuery("sysapproval", parentId)
ga.addQuery("approver.sys_id", "IN", getGroupMembers(groupId))
ga.addQuery("state", "approved")
ga.addAggregate("COUNT")
ga.query()
var approvedCount = 0
if (ga.next()) {
approvedCount = parseInt(ga.getAggregate("COUNT"), 10)
}
// Check based on type
if (approvalType === "any") {
return approvedCount >= 1
} else if (approvalType === "all") {
var memberCount = getGroupMemberCount(groupId)
return approvedCount >= memberCount
} else if (approvalType === "specific_count") {
var required = parseInt(groupConfig.getValue("specific_count"), 10)
return approvedCount >= required
}
return false
}
审批委派(ES5)
创建委派
// Create approval delegation (ES5 ONLY!)
function createDelegation(userId, delegateId, startDate, endDate) {
var delegation = new GlideRecord("sys_user_delegate")
delegation.initialize()
delegation.setValue("user", userId)
delegation.setValue("delegate", delegateId)
delegation.setValue("starts", startDate)
delegation.setValue("ends", endDate)
delegation.setValue("approvals", true)
delegation.setValue("assignments", false)
return delegation.insert()
}
查找活跃的受委派人
// Get delegates who can approve for a user (ES5 ONLY!)
function getActiveDelegates(userId) {
var delegates = []
var now = new GlideDateTime()
var delegation = new GlideRecord("sys_user_delegate")
delegation.addQuery("user", userId)
delegation.addQuery("approvals", true)
delegation.addQuery("starts", "<=", now)
delegation.addQuery("ends", ">=", now)
delegation.query()
while (delegation.next()) {
delegates.push({
delegate: delegation.delegate.getDisplayValue(),
delegate_id: delegation.getValue("delegate"),
ends: delegation.getValue("ends"),
})
}
return delegates
}
审批通知(ES5)
发送审批请求
// Trigger approval notification (ES5 ONLY!)
function sendApprovalNotification(approvalSysId) {
var approval = new GlideRecord("sysapproval_approver")
if (!approval.get(approvalSysId)) return
var parent = new GlideRecord(approval.source_table)
if (parent.get(approval.getValue("sysapproval"))) {
gs.eventQueue("approval.request", approval, approval.getValue("approver"), "")
}
}
MCP 工具集成
可用工具
| 工具 | 用途 |
|---|---|
snow_query_table | 查询审批和审批规则 |
snow_approval_chain_manage | 定义多步骤审批链(define_chain) |
snow_artifact_manage | 查找审批业务规则(action='find') |
snow_execute_script | 测试审批脚本 |
snow_create_business_rule | 创建审批触发器 |
示例工作流
// 1. Query pending approvals
await snow_query_table({
table: "sysapproval_approver",
query: "state=requested^approver=javascript:gs.getUserID()",
fields: "sysapproval,state,sys_created_on",
})
// 2. Find approval rules
await snow_query_table({
table: "sysapproval_rule",
query: "table=change_request^active=true",
fields: "name,conditions,approver,approval_type",
})
// 3. Check delegations
await snow_execute_script({
script: `
var delegates = getActiveDelegates(gs.getUserID());
gs.info('Active delegates: ' + JSON.stringify(delegates));
`,
})
最佳实践
- 明确条件 - 使用具体的规则条件
- 逻辑顺序 - 规则顺序很重要
- 升级处理 - 处理未响应的情况
- 委派 - 支持不在岗时的委派
- 通知 - 及时发送提醒
- 审计跟踪 - 跟踪所有决定
- 测试 - 测试所有审批路径
- 仅限 ES5 - 不使用现代 JavaScript 语法
评论
支持 Markdown