← Script library

Business Rules

Create Approval Records

Automatically create approval records and request approvals when certain conditions are met (e.g., high-cost purchases, major changes).

JavaScript
(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.