Business Rules
Create Approval Records
Automatically create approval records and request approvals when certain conditions are met (e.g., high-cost purchases, major changes).
(function executeRule(current, previous /*null when async*/) {
// Configuration: Define approval requirements
var requiresApproval = false;
var approvers = [];
var approvalLevel = 'sequential'; // 'sequential' or 'parallel'
// Example 1: Require approval for high-risk changes
if (current.risk.toString() === '1' || current.risk.toString() === '2') { // High or Moderate risk
requiresApproval = true;
// Add CAB manager as approver
var cabManager = gs.getProperty('change.cab_manager'); // Customize property name
if (cabManager) {
approvers.push(cabManager);
}
// Add Change Manager
var changeManager = gs.getProperty('change.manager');
if (changeManager) {
approvers.push(changeManager);
}
}
// Example 2: Require approval for emergency changes
if (current.type.toString() === 'emergency') {
requiresApproval = true;
// Add VP of IT
var vpIT = gs.getProperty('it.vp_user_id');
if (vpIT) {
approvers.push(vpIT);
}
}
// Example 3: Require approval based on affected CIs
if (!current.cmdb_ci.nil()) {
var ci = current.cmdb_ci.getRefRecord();
if (ci.u_criticality.toString() === 'mission_critical') {
requiresApproval = true;
// Add CI owner as approver
if (!ci.owned_by.nil()) {
approvers.push(ci.owned_by.toString());
}
}
}
// Only process on insert or when approval is not yet requested
if (requiresApproval && (current.isNewRecord() || current.approval.toString() === 'not requested')) {
// Set approval state to requested
current.approval = 'requested';
current.update();
// Create approval records
var order = 1;
approvers.forEach(function(approverId) {
// Check if approval already exists
var grExisting = new GlideRecord('sysapproval_approver');
grExisting.addQuery('source_table', current.getTableName());
grExisting.addQuery('sysapproval', current.sys_id);
grExisting.addQuery('approver', approverId);
grExisting.setLimit(1);
grExisting.query();
if (!grExisting.hasNext()) {
// Create new approval record
var grApproval = new GlideRecord('sysapproval_approver');
grApproval.initialize();
grApproval.source_table = current.getTableName();
grApproval.sysapproval = current.sys_id;
grApproval.approver = approverId;
grApproval.state = 'requested';
// Set order for sequential approvals
if (approvalLevel === 'sequential') {
grApproval.order = order;
order++;
}
// Optional: Set due date (e.g., 24 hours from now)
var dueDate = new GlideDateTime();
dueDate.addDaysLocalTime(1);
grApproval.due_date = dueDate;
var approvalId = grApproval.insert();
if (approvalId) {
gs.info('Created approval for ' + current.number + ', approver: ' +
grApproval.approver.getDisplayValue());
}
}
});
// Add work note
if (approvers.length > 0) {
current.work_notes = 'Approval requested from ' + approvers.length + ' approver(s)';
gs.eventQueue('approval.requested', current, current.sys_id, approvers.join(','));
}
}
// Check if all approvals are complete
if (current.approval.toString() === 'requested') {
var grApprovals = new GlideRecord('sysapproval_approver');
grApprovals.addQuery('source_table', current.getTableName());
grApprovals.addQuery('sysapproval', current.sys_id);
grApprovals.query();
var allApproved = true;
var anyRejected = false;
while (grApprovals.next()) {
if (grApprovals.state.toString() === 'requested') {
allApproved = false;
}
if (grApprovals.state.toString() === 'rejected') {
anyRejected = true;
}
}
// Update parent record approval status
if (anyRejected) {
current.approval = 'rejected';
current.work_notes = 'Change request rejected by approver';
} else if (allApproved) {
current.approval = 'approved';
current.work_notes = 'All approvals completed - change approved';
}
}
})(current, previous);How to use it
1. Create an after Business Rule on your table 2. Check "Insert" and "Update" checkboxes 3. Customize the approval requirements and logic 4. Update approver sys_ids or use system properties 5. Test with various scenarios to ensure proper approval routing 6. Consider using ServiceNow's approval engine for complex workflows
Adapt the table names, fields, and conditions to your instance. Test the behavior in a development environment before using it in production.