← Script library

Business Rules

Auto-numbering with Custom Prefix

Generate custom record numbers with prefixes based on category, type, or other fields (e.g., HW0001, SW0002, NET0003).

JavaScript
(function executeRule(current, previous /*null when async*/) {

  // Configuration: Define number prefixes based on category
  var prefixMap = {
    'hardware': 'HW',
    'software': 'SW',
    'network': 'NET',
    'database': 'DB',
    'inquiry': 'INQ',
    'default': 'INC'  // Default prefix if category not found
  };

  try {
    // Get category to determine prefix
    var category = current.getValue('category') || 'default';
    var prefix = prefixMap[category] || prefixMap['default'];

    // Alternative: Use different field for prefix determination
    // var type = current.getValue('u_type');
    // var prefix = prefixMap[type] || prefixMap['default'];

    // Get current year for prefix (optional)
    var year = new GlideDateTime().getYear().toString().substring(2);  // Last 2 digits
    prefix = prefix + year;  // e.g., HW24

    // Query for the highest number with this prefix
    var ga = new GlideAggregate('incident');
    ga.addQuery('number', 'STARTSWITH', prefix);
    ga.addAggregate('MAX', 'number');
    ga.query();

    var nextNumber = 1;

    if (ga.next()) {
      var maxNumber = ga.getAggregate('MAX', 'number');

      if (maxNumber) {
        // Extract numeric part from the number
        // Assumes format: PREFIX-NNNN (e.g., HW24-0001)
        var parts = maxNumber.split('-');
        if (parts.length > 1) {
          var numericPart = parseInt(parts[1], 10);
          if (!isNaN(numericPart)) {
            nextNumber = numericPart + 1;
          }
        }
      }
    }

    // Format number with leading zeros (e.g., 0001, 0042, 1234)
    var paddedNumber = String(nextNumber).padStart(4, '0');

    // Construct final number
    var customNumber = prefix + '-' + paddedNumber;

    // Set the number
    current.setValue('number', customNumber);

    gs.info('Auto-numbering: Generated number ' + customNumber + 
            ' for category: ' + category);

    // Optional: Set a display number field if you want to keep standard number
    // current.setValue('u_custom_number', customNumber);

  } catch (e) {
    gs.error('Auto-numbering BR error: ' + e.message);

    // Fallback to default numbering
    // Let ServiceNow handle the number generation
  }

  // Alternative approach: Use number maintenance records
  /*
  function getNextNumber(prefix) {
    // Create/use a custom table to track number sequences
    var grCounter = new GlideRecord('u_number_counter');
    grCounter.addQuery('prefix', prefix);
    grCounter.query();

    var nextNum = 1;

    if (grCounter.next()) {
      nextNum = parseInt(grCounter.current_number) + 1;
      grCounter.current_number = nextNum;
      grCounter.update();
    } else {
      // Create new counter record
      grCounter.initialize();
      grCounter.prefix = prefix;
      grCounter.current_number = nextNum;
      grCounter.insert();
    }

    return nextNum;
  }

  var nextNum = getNextNumber(prefix);
  var paddedNumber = String(nextNum).padStart(4, '0');
  current.setValue('number', prefix + '-' + paddedNumber);
  */

})(current, previous);

How to use it

1. Create a before Business Rule on your table 2. Check "Insert" checkbox only 3. Set Order to 100 to run early 4. Customize prefixMap with your categories and prefixes 5. Decide on number format (with/without year, padding length) 6. Test number generation across different categories 7. Verify uniqueness and sequence continuity 8. Consider concurrency issues in high-volume environments 9. Alternative: Create custom counter table for better control 10. Document numbering scheme for users

Adapt the table names, fields, and conditions to your instance. Test the behavior in a development environment before using it in production.