Skip to main content

Use Case : ServiceNow Development Practice Scenarios

This document outlines a series of practice scenarios to improve your ServiceNow development skills, covering Business Rules, Transformation Maps, UI/UX customization, Service Catalog, SLAs, and Reporting.

SECTION 1: Business Rules

Assignment #1: Creating 'incident_temp' Records

  1. Table Creation:

    • Create a new table named incident_temp.
    • Add the following fields:
      • Incident Number (Type: String) -- Consider using a Reference field to the Incident table for better data integrity.
      • Short Description (Type: String)
  2. Business Rule:

    • Name: Create Incident Temp Record (or similar)
    • Table: Incident (incident)
    • When to run:
      • When: after
      • Insert: true
      • Update: false
      • Delete: false
      • Query: false
      • Advanced: true (to write the script)
    • Script:
    (function executeRule(current, previous /*null when async*/) {
    
        // Create a new record in the incident_temp table
        var incTemp = new GlideRecord('incident_temp');
        incTemp.initialize();
    
        // Set values from the newly created Incident record
        incTemp.u_incident_number = current.number; // Assuming 'u_incident_number' is the field name.  If you used a Reference field, it would be something like incTemp.incident = current.sys_id;
        incTemp.u_short_description = current.short_description; // Assuming 'u_short_description' is the field name.
    
        // Insert the record into the incident_temp table
        incTemp.insert();
    
    })(current, previous);
    

Assignment #2: Removing 'incident_temp' Records

  1. Business Rule:

    • Name: Remove Temp Incident Rule
    • Table: Incident (incident)
    • When to run:
      • When: before (or after - before is generally preferred for delete operations to ensure you have access to the record's data)
      • Insert: false
      • Update: false
      • Delete: true
      • Query: false
      • Advanced: true
    • Script:
    (function executeRule(current, previous /*null when async*/) {
    
        // Query the incident_temp table for a matching record
        var incTemp = new GlideRecord('incident_temp');
        incTemp.addQuery('u_incident_number', current.number); // Or, if using a Reference field: incTemp.addQuery('incident', current.sys_id);
        incTemp.query();
    
        // If a matching record is found, delete it
        if (incTemp.next()) {
            incTemp.deleteRecord();
        }
    
    })(current, previous);
    

Assignment #3: Updating 'incident_temp' Records

  1. Business Rule:

    • Name: Update Temp Incident Rule
    • Table: Incident (incident)
    • When to run:
      • When: after
      • Insert: false
      • Update: true
      • Delete: false
      • Query: false
      • Advanced: true
    • Script:
    (function executeRule(current, previous /*null when async*/) {
    
        // Query the incident_temp table for a matching record
        var incTemp = new GlideRecord('incident_temp');
        incTemp.addQuery('u_incident_number', current.number);  // Or, if using a Reference field: incTemp.addQuery('incident', current.sys_id);
        incTemp.query();
    
        // If a matching record is found, update its short description
        if (incTemp.next()) {
            incTemp.u_short_description = current.short_description;
            incTemp.update();
        }
    
    })(current, previous);
    

TRANSFORMATION MAPS

Assignment #1: Updating Group Parent Relationships

  1. Customize Group Form:

    • Navigate to System Definition -> Dictionary.
    • Search for Table: sys_user_group (Group).
    • Create a new field:
      • Column label: Parent Group
      • Column name: u_parent_group (or similar)
      • Type: Reference
      • Reference: sys_user_group (Group)
  2. Export Existing Groups:

    • Navigate to the User Administration -> Groups list.
    • Right-click on the list header and choose Export -> CSV.
  3. Update CSV File:

    • Open the downloaded CSV file.
    • Locate the u_parent_group column (or whatever you named the field).
    • Populate this column with the sys_id of the desired parent group for each group. You can find the sys_id of a group by opening the group record and copying it from the URL (the part after sys_id=). Do not use the group name; use the sys_id.
  4. Create Transformation Map:

    • Navigate to System Import Sets -> Load Data.
    • Create a new Import Set:
      • Label: Import Groups with Parent (or similar)
      • Table name: Select an existing Import Set table, or create a new one (recommended) specifically for this import. The Import Set table acts as a staging area.
      • Source: File
      • File: Upload the modified CSV file.
      • Click Submit.
    • After the file is loaded, click Create transform map.
    • Name: Group Parent Transform (or similar)
    • Source table: Your Import Set table (e.g., u_import_groups_with_parent).
    • Target table: sys_user_group (Group)
    • Run business rules: true (This is generally recommended unless you have a specific reason to disable them)
    • Enforce mandatory fields: true (or as needed for your requirements)
    • Copy empty fields: false (Since we only want to update the parent group)
  5. Field Mapping:

    • In the Field Maps related list, click New.
    • You may see some fields auto-mapped. Delete any mappings you don't need. We only want to map the u_parent_group field.
    • Source field: Select the u_parent_group field from your Import Set table.
    • Target field: Select the u_parent_group field from the sys_user_group table.
    • Use source script: false (We don't need any scripting for this simple mapping).
    • Coalesce: false. Crucially, do NOT coalesce on the parent group. Coalescing is used to prevent duplicate records. We are updating existing records, so we need to identify them by their sys_id.
    • Auto Map Matching Fields: You can use it. *Click on Mapping Assist. *Drag and Drop only 'Parent Group' field from Source to Target. *Click on Save.
  6. Run Transform:

    • Click the Transform related link.
    • Select your Import Set.
    • Click Transform.
  7. Verification:

    • Navigate back to User Administration -> Groups.
    • Open a group record that you updated.
    • Verify that the Parent Group field is populated correctly, referencing the intended parent group.

SECTION 1 (Continued - Additional Tasks)

  1. Import Data from Excel:

    • Create an Excel spreadsheet with 6 columns and 20 records of sample data (e.g., User data).
    • In ServiceNow, navigate to System Import Sets -> Load Data.
    • Follow the steps to create a new Import Set, specifying the file source and uploading your Excel file.
    • Create a new table to load.
    • ServiceNow will attempt to automatically map the columns. Review and adjust the mappings as needed. Use "auto map matching fields".
    • Run the transformation. *Click on Mapping Assist *Create Transform Map. *Run the transformation.
    • Verify the data in the target table.
  2. LDAP User Import Steps:

    • LDAP Server Configuration: Configure the LDAP server connection in ServiceNow (System LDAP -> Create New Server). This includes details like server address, port, credentials, and search base.
    • LDAP OU Definitions: Define the Organizational Units (OUs) in LDAP that contain the users you want to import.
    • Data Source: Create a Data Source to connect to the LDAP server.
    • Transform Map: Create a Transform Map to map LDAP attributes to ServiceNow user fields (e.g., LDAP sAMAccountName to ServiceNow user_name).
    • Scheduled Import: Set up a scheduled job to regularly import users from LDAP.
  3. CMS Header and Footer:

    • ServiceNow CMS is deprecated. The modern approach is to use Service Portal.
    • Service Portal: Use the Service Portal configuration and widgets to create headers and footers. You'd create new widgets (HTML, CSS, and optionally client/server scripts) and add them to the header/footer areas of your portal theme.
  4. UI Page with Username Input:

    • Navigate to System UI -> UI Pages.
    • Create a new UI Page.
    • HTML:
    <?xml version="1.0" encoding="utf-8" ?>
    <j:jelly trim="false" xmlns:j="jelly:core" xmlns:g="glide" xmlns:j2="null" xmlns:g2="null">
        <g:ui_form>
            <g:evaluate var="jvar_greeting" expression="'Please enter your username:'" />
             <h1>${jvar_greeting}</h1>
            <input type="text" id="username" name="username" />
            <g:dialog_button type="button" onclick="submitUsername()">Submit</g:dialog_button>
        </g:ui_form>
    
        <script>
            function submitUsername() {
                var username = gel('username').value;
                alert('You entered: ' + username); 
                // Replace the alert with your desired action, e.g.,
                // g_form.setValue('some_field', username);  // If you want to set a field on a form
                // Or, make a GlideAjax call to a server-side script.
            }
        </script>
    </j:jelly>
    
    • Client Script: (Optional - you can put the JavaScript directly in the HTML as shown above). The example above shows a simple alert. You would likely replace this with code to interact with the server or a form.
  5. Employee and Department Tables:

    • Create a table named Employee (e.g., u_employee).
      • Add at least five fields (e.g., Name, Employee ID, Email, Department (reference), Manager).
    • Create a table named Employee Department (e.g., u_employee_department).
      • Add fields for the department information (e.g., Department Name, Location, Head of Department).
    • On the Employee table, create a Reference field named Department that references the Employee Department table. This establishes the relationship.
  6. Business Service Map:

    • Navigate to Configuration -> Business Services -> Business Service Map.
    • Select the Business Service you want to view. The map will display the CIs and their relationships.
  7. GlideRecord Example:

    • This can be used in a Business Rule, Script Include, or other server-side script:
    var gr = new GlideRecord('incident');
    gr.addQuery('active', true);
    gr.query();
    while (gr.next()) {
        gs.info('Incident Number: ' + gr.number + ', Short Description: ' + gr.short_description);
    }
    
  8. GlideAggregate Example:

    var count = new GlideAggregate('incident');
    count.addAggregate('COUNT');
    count.addQuery('active', true);
    count.query();
    if (count.next()) {
        gs.info('Total active incidents: ' + count.getAggregate('COUNT'));
    }
    
  9. GlideForm Example (Client Script):

    // OnLoad Client Script for the Incident form
    function onLoad() {
       // Make the 'short_description' field mandatory
       g_form.setMandatory('short_description', true);
    
       // Hide the 'close_notes' field
       g_form.setVisible('close_notes', false);
    
       // Set the value of the 'caller_id' field to the current user
       g_form.setValue('caller_id', g_user.userID);
    }
    
  10. Metrics vs. SLAs:

    • Metrics: Capture and track data about how a process is performing. They are general measurements, not tied to specific agreements. Example: Number of incidents resolved per day.
    • SLAs (Service Level Agreements): Define agreed-upon levels of service. They include targets, conditions, and often consequences for not meeting the targets. Example: Resolve Priority 1 incidents within 4 hours.

SECTION 2

SECTION 3: Service Catalog

Service Catalog Assignment 1 was empty in the prompt. I'll provide a basic example:

Create a "Request New Hardware" Catalog Item:

  1. Catalog Item:

    • Navigate to Service Catalog -> Catalog Definitions -> Maintain Items.
    • Create a new item.
    • Name: Request New Hardware
    • Catalog: Choose the appropriate catalog (e.g., Service Catalog).
    • Category: Choose a category (e.g., Hardware).
    • Short description: Briefly describe the item.
    • Description: Provide more details.
    • Picture: (Optional) Add an image.
  2. Variables:

    • In the Variables related list, create variables to capture information from the user:
      • Requested for (Type: Reference, Reference: sys_user)
      • Hardware type (Type: Select Box, with options like "Laptop", "Desktop", "Monitor")
      • Justification (Type: Multi Line Text)
  3. Workflow: (Optional)

    • Create a workflow to handle the request fulfillment process (e.g., approvals, tasks).
    • Attach the workflow to the catalog item.

SECTION 4: SLA

SLA for Priority 1 Incidents (No Schedule):

  1. SLA Definition:

    • Navigate to Service Level Management -> SLA -> SLA Definitions.
    • Create two new SLA Definitions (one for Responsive, one for Resolution).
  2. Responsive SLA:

    • Name: P1 Incident Responsive - No Schedule
    • Table: incident
    • Type: SLA
    • Target: Response
    • Duration: 30 Minutes (for the 30-minute requirement), and a second one with 1 Day.
    • Start Condition:
      • Active is true
      • Priority is 1
      • Assignment group is (select your group)
    • Stop Condition:
      • Assigned to is not empty
    • Pause Condition:
      • Incident state is one of On Hold
  3. Resolution SLA:

    • Name: P1 Incident Resolution - No Schedule
    • Table: incident
    • Type: SLA
    • Target: Resolution
    • Duration:30 Minutes (for the 30-minute requirement), and a second one with 1 Day.
    • Start Condition:
      • Active is true
      • Priority is 1
      • Assignment group is (select your group)
    • Stop Condition:
      • Incident state is one of Resolved
    • Pause Condition:
      • Incident state is one of On Hold

SLA for Priority 4 Incidents (With Schedule):

  1. Schedule:

    • Navigate to System Scheduler -> Schedules -> Schedules.
    • Create a new schedule:
      • Name: Mon-Fri 9-5
      • Add schedule entries for each day (Monday to Friday), setting the time from 9:00 AM to 5:00 PM.
  2. Responsive SLA:

    • Name: P4 Incident Responsive - With Schedule
    • Table: incident
    • Type: SLA
    • Target: Response
    • Duration: 4 Hours (for the 4 hours requirement), and a second one with 5 Days.
    • Schedule Source: SLA Definition
    • Schedule: Mon-Fri 9-5 (the schedule you created)
    • Start Condition:
      • Active is true
      • Priority is 4
      • Assignment group is (select your group)
    • Stop Condition:
      • Assigned to is not empty
    • Pause Condition:
      • Incident state is one of On Hold
  3. Resolution SLA:

    • Name: P4 Incident Resolution - With Schedule
    • Table: incident
    • Type: SLA
    • Target: Resolution
    • Duration: 4 Hours (for the 4 hours requirement), and a second one with 5 Days.
    • Schedule Source: SLA Definition
    • Schedule: Mon-Fri 9-5
    • Start Condition:
      • Active is true
      • Priority is 4
      • Assignment group is (select your group)
    • Stop Condition:
      • Incident state is one of Resolved
    • Pause Condition:
      • Incident state is one of On Hold

Handling Public Holidays:

  • Holiday Schedules: ServiceNow has a built-in feature for managing holidays. Navigate to System Scheduler -> Schedules -> Holidays. Create holiday records for each public holiday.
  • Associate with Schedule: In your Mon-Fri 9-5 schedule, there's a related list for Holidays. Add the holidays you created to this related list. The schedule will automatically exclude these holidays.

SLA Breach Notification:

  1. SLA Workflow: The best way to handle this is within an SLA Workflow. You can create a workflow that runs on the task_sla table.
  2. Workflow Activities:
    • Add a Timer activity to your workflow. Set the timer to 50% of the SLA duration, based on the task_sla.duration. Use "Wait for percentage of SLA duration".
    • After the timer, add a Notification activity.
    • Who will receive: Use script to dynamically determine the recipients:
      // Get the assigned to user, their manager, and the assignment group manager
      var assignedTo = current.task.assigned_to;
      var assignedToManager = assignedTo.manager;
      var assignmentGroupManager = current.task.assignment_group.manager;
      
      // Add the users to the recipients list
      answer = []; // Initialize the answer array
      if (assignedTo) {
          answer.push(assignedTo.sys_id);
      }
      if (assignedToManager) {
          answer.push(assignedToManager.sys_id);
      }
      if (assignmentGroupManager) {
          answer.push(assignmentGroupManager.sys_id);
      }
      
      
    • What it will contain: Create the notification message.

SLA Breach Report:

  1. Report:
    • Create a new report on the task_sla table.
    • Filter Conditions:
      • Has breached is true
      • Task.Assignment group is (your group)
      • Task is (dynamic) Me -- This part is tricky. You might need a report script or a database view to filter the task_sla records based on the currently logged-in user and their group memberships, to show only the breached SLAs for their assigned incidents. A simple "My Groups" filter on the task table might be sufficient.
    • Group by: Task (to show each incident separately).
    • Columns: Include relevant fields like Task.Number, Task.Short description, SLA, Time left, etc.

SECTION 5: Form Customizations ("NeedIT" Application)

  1. Application Creation:

    • In Studio, create a new application named NeedIT.
    • Set the scope and access permissions (visible to ITIL users).
  2. Table Creation:

    • In Studio, create a new table named NeedIT within the NeedIT application.
    • Add the following fields:
    Field Label Column Name Type Reference/Choice Options
    Number number String (Leave blank - will be auto-numbered)
    Impact impact Choice (Use the same choice list as the Incident table's impact field)
    Urgency urgency Choice (Use the same choice list as the Incident table's urgency field)
    Priority priority Choice (Use the same choice list as the Incident table's priority field)
    Requested For requested_for Reference sys_user (User)
    What needed what_needed Choice Notepad++, Clarity, CoreDB
    When needed when_needed Date/Time
    State state Choice New, Work In Progress, Pending, Resolved, Closed
    Assignment Group assignment_group Reference sys_user_group (Group)
    Assigned to assigned_to Reference sys_user (User)
    Short Description short_description String
    Description description String
    Additional Notes Additional String
  3. Form Layout:

    • Open the NeedIT table form.
    • Configure the form layout to create three sections:
      • Note It: Add Work notes and Additional comments.
      • Related Time: Add Opened (Date/Time - automatically populated on creation) and Closed (Date/Time - populated when the state is Closed).
      • Close Notes: Add a Closure notes field (Multi Line Text) – make this mandatory when the state is changed to Closed.
  4. Field Attributes and UI Policies:

    • Number: Make the number field read-only (either through the Dictionary or a UI Policy). Set it to auto-number.
    • Priority: Create a UI Policy (or use the Dictionary's Calculated field option) to set the priority based on the selected impact and urgency values (use the same logic as the Incident table). Make the field Read Only.
    • State: Make the state field read-only (controlled by buttons, below).
    • Opened: Add Opend field with Read Only.
  5. Related List

  • Right Click -> Configure -> Related Lists.
  • Active Incidents.
  1. UI Actions (Buttons):

    • Work In Progress:

      • Action name: work_in_progress
      • Form button: true
      • Condition: current.state == 'new' && gs.getUser().isMemberOf(current.assignment_group) (Visible only when the state is New and the user is a member of the assignment group)
      • Script:
      current.state = 'work_in_progress';
      current.update();
      action.setRedirectURL(current);
      
    • Pending:

      • Action name: pending
      • Form button: true
      • Condition: current.state == 'work_in_progress'
      • Onclick: pendingAndMandatory()
      • Client: true
      • Script:
      //Client-side script
      function pendingAndMandatory() {
        if (g_form.getValue('work_notes') == '') {
          g_form.addErrorMessage('Work notes are mandatory when moving to Pending.');
          return false; // Prevent form submission
       }
        g_form.setValue('state','pending');
        gsftSubmit(null, g_form.getFormElement(), 'pending'); //FOR UI16
      
      }
      
      //Server-side script
      if(typeof window == 'undefined')
         serverCode();
      
      function serverCode(){
         current.update();
         action.setRedirectURL(current);
      }
      
      
    • Resolve:

      • Action name: resolve
      • Form button: true
      • Condition: current.state == 'work_in_progress' || current.state == 'pending'
      • Onclick: resolveAndMandatory()
      • Client: true
      • Script:
        //Client Side Script
        function resolveAndMandatory(){
          if(g_form.getValue('comments') == ''){ //comments is the backend name of Additional comments
             g_form.addErrorMessage('Additional comments are mandatory when resolving.');
             return false; // Prevent form submission
           }
           g_form.setValue('state','resolved');
           gsftSubmit(null, g_form.getFormElement(), 'resolve');
        }
        
        //Server Side script
        if(typeof window == 'undefined')
           resolveServer();
        
        function resolveServer(){
          current.update();
          action.setRedirectURL(current);
        }
        
    • Back to Progress (from Pending)

      • Action Name: back_to_progress_pending
      • Form Button: true
      • Condition: current.state == 'pending'
      • Script:
       current.state = 'work_in_progress';
       current.update();
       action.setRedirectURL(current);
      
    • Back to Progress (from Resolved)

    • Action Name: back_to_progress_resolved

    • Form Button: true

    • Condition: current.state == 'resolved'

      • Script:
      current.state = 'work_in_progress';
      current.update();
      action.setRedirectURL(current);
      
    • Close:

      • Action name: close
      • Form button: true
      • Condition: current.state == 'resolved'
      • Onclick: closeAndMandatory()
      • Client: true
      • Script:
      function closeAndMandatory() {
       if (g_form.getValue('u_closure_notes') == '') {
          g_form.addErrorMessage('Closure notes are mandatory when closing.');
          return false;
       }
         g_form.setValue('state', 'closed');
        gsftSubmit(null, g_form.getFormElement(), 'close'); //FOR UI16
      
      }
        if(typeof window == 'undefined')
           closeServer();
      
        function closeServer(){
          current.closed_at = new GlideDateTime(); // Set the closed_at field
          current.update();
          action.setRedirectURL(current);
        }
      
      
  2. Client Script (for additional validations - optional):

    • You might add an onChange client script for the Assignment Group field to filter the Assigned to field based on the selected group (using g_form.getReference() and addQuery()).

SECTION 6: Order Guide

  1. Order Guide Creation:

    • Navigate to Service Catalog -> Catalog Definitions -> Order Guides.
    • Create a new Order Guide.
    • Name: Software Request
    • Short description: Describe the purpose of the order guide.
  2. Variables:

    • Add the following variables:
    Variable Name Type Reference/Choice Options Read Only Mandatory Other Attributes
    Requested by Single Line Text (Auto-populated - see script below) Yes Yes
    Requested for Reference sys_user (User) No Yes
    Location Single Line Text (Auto-populated based on Requested by - see script below) Yes Yes
    Location of requested for Single Line Text (Auto-populated based on Requested for - see script below) Yes Yes
    Software required Select Box Notepad++, Clarity, Visual Studio, Pulse Secure No Yes
    Version Select Box (Only visible if Notepad++ is selected - see Rule Base) Older, Latest No Yes Displayed conditionally, based on "Software required"
  3. Variable Sets (Optional): Consider creating variable sets if you have groups of variables that are reused across multiple catalog items or order guides.

  4. Catalog Items:

    • Create at least one catalog item for Notepad++. You might create others for the other software options as well, if you want to fully implement the order guide. The key is to have a separate item for Notepad++.
    • Include relevant variables within the Notepad++ catalog item (e.g., the Version variable could also be part of the Notepad++ item itself).
  5. Rule Base:

    • In the Order Guide, navigate to the Rule Base related list.
    • Create a new rule:
      • Applies to: A specific item
      • Item: Select your Notepad++ catalog item.
      • Condition: Software required is Notepad++
      • Always Apply: false.