Blog

Movies Now App

Let's create an application in ServiceNow to store a movie collection and rent movies to customers.

Here are some screenshots of the application we can create:

Movies CMS

Movie List

Movie Checkout Age Verification

Step 1: Create "Movie Collection" Application

1. New Application

Movie Table

  • Name: Movie Collection
  • Menu: Movie Collection
  • User Role: admin

2. New Table

  • Label: Movies
  • Name: u_movies
  • User Role: admin
  • Create module: true
  • Create access controls: true
  • Auto number: false
  • Add module to menu: Movie Collection

3. New Columns for Movies table

  • Movie, String 
  • Rated, Choice
  • Critics Rating, Percent Complete
  • Audience Rating, Percent Complete
  • Synopsis, String (1000)
  • Cast, String (1000), or separate table
  • Checked Out, True/False
  • Checked Out Date, Date/Time
  • Checked Out By, Reference, User
  • Checked Out Age, Integer
  • Price, Price

4. Rated Choice List

  • Table | Element | Language | Value | Label | Sequence
  • u_movies | u_rated | en | G | G | 1
  • u_movies | u_rated | en | PG | PG | 2
  • u_movies | u_rated | en | PG-13 | PG-13 | 3
  • u_movies | u_rated | en | R | R | 4
  • u_movies | u_rated | en | NC-17 | NC-17 | 5

5. Personalize Movies Choice List

  • Movie
  • Audience Rating
  • Critics Rating
  • Rated
  • Checked Out
  • Checked Out By
  • Checked Out Date

6. Personalize Movies Form

  • <begin split>
  • Movie
  • Audience Rating
  • Critics Rating
  • Rated
  • Price
  • <split>
  • Checked Out
  • Checked Out Age
  • Checked Out By
  • Checked Out Date
  • <end split>
  • <begin split>
  • Cast
  • Synopsis

All Movies

7. Personalize Movie Field

  • Unique: true
  • Display: true

8. Add Data Policy

Table: Movies [u_movies]

My Checked Out Movies

  • Reverse if false: true
  • Add to import sets: true
  • Apply to SOAP: false
  • Use as UI Policy on client: true
  • Short Description: Required Fields
  • Condition: 
  • Movie | Mandatory: true

9. Configure Modules

  • Title | Table | Filter | Order | Link type | Roles | Image
  • All | u_movies |  | 100 | List of Records | itil | images/icons/all.gif
  • My Checked Out | u_movies | u_checked_out_by=javascript:gs.getUserID() | 200 | List of Records | itil | images/icons/assigned_tome.gif
  • Kid Friendly | u_movies | u_esrb_rating=G^EQ | 300 | List of Records | itil | images/icons/kb_star_on.gif

Step 2: Add Catalog Item: Movie Checkout

Movie Checkout

1. Click Service Catalog > Maintain Items

Movie Checkout Catalog Item

  • Name: Movie Checkout
  • Category: Can We Help You?
  • Workflow: Movie Checkout
  • Delivery Plan: DEFAULT
  • Short Description: Checkout a movie from the collection
  • Description:
    • Rental Policy

      Each item you rent from ServiceNow has a minimum rental period of one day.  That one day minimum rental period is measured from the time you first receive your rental through 9:00 p.m. the next day.  

      Each item you can rent has a daily rental charge.  To incur a single daily rental charge, you must return your rental by 9:00 p.m. the next day in the time zone where you return your rental.  For example, if the daily rental charge for a DVD is $1.00, you will be charged only $1.00. 

  • Variables
    • Type: Reference, Question: Movie, Name: movie, Reference Qual: u_checked_out=false, Mandatory: true
    • Type: Reference, Question: Requested By, Name: requested_by, Reference Qual: active=true, Mandatory: true, Default value: javascript:gs.getUserID()

2. Workflow: Movie Checkout

Movie Checkout Workflow

  • Begin
  • Notification
    • Name: Movie Request
    • To: ${request.requested_for}
    • Subject: Your requested item ${number} for ${cat_item} has been received
    • Message
      • Click here to view request: ${URI}
        <p>
        Number: ${number}
        Opened: ${opened_at}
        Item: ${cat_item}
        Quantity: ${quantity}
        </p>
        <p>
        Additional comments: 
        ${comments}
        </p>
  • Run Script

    • var grMovie = new GlideRecord("u_movies");
      grMovie.addQuery('sys_id',current.variables.movie);
      grMovie.query();
      gs.log('grMovie Query: ' + grMovie.getEncodedQuery() + ' = ' + grMovie.getRowCount());
      if (grMovie.next()){
         grMovie.u_checked_out_by = current.variables.requested_by;
         grMovie.u_checked_out_date = gs.nowDateTime();
         grMovie.u_checked_out = 'true';
         grMovie.u_checked_out_age = current.variables.requested_by_age;
         grMovie.update();
      }
  • Catalog Task
    • Name: Deploy Movie to Requested By
    • Stage: Deployment
    • Task Table: sc_task
    • Task Value from Fields
    • Wait for Completion: true
    • Fulfillment Group: Field Service
    • Short Description: Movie Checkout
    • Advanced: true
    • Advanced Script:
    • task.short_description = "Movie Checkout - " + current.variables.requested_by.name;
      
      var grItem = new GlideRecord("sc_req_item");
      
      grItem.addQuery("sys_id",task.request_item);
      grItem.query();
      if(grItem.next()){
       var varown = new GlideRecord('sc_item_option_mtom');
       varown.addQuery("request_item", task.request_item);
       varown.query();
       while (varown.next()){
      var visible = varown.sc_item_option.item_option_new.visible_summary;
      var question = Packages.com.glideapp.questionset.Question.getQuestion(varown.sc_item_option.item_option_new);
      question.setValue(varown.sc_item_option.value);
      
      if((question.getLabel() != '') && (question.getDisplayValue() != '') && (varown.sc_item_option.value != '') && (varown.sc_item_option.value != "0") && (varown.sc_item_option.value != "false")) {
       task.description += "\n" + " " + question.getLabel() + " = " + question.getDisplayValue();
      }
       }
      }
  • Log Message

    • Name: Movie Deployed
    • Stage: Completed
  • End

3. Catalog UI Policy

  • Name: Age Verification
  • Catalog Condition: requested_by_age is not empty
  • Catalog UI Policy Action: requested_by_age, Readonly: true, visible:false

Step 3: Add Catalog Item: Movie Return

1. Click Service Catalog > Maintain Items

Movie Return

  • Name: Movie Return
  • Category: Can We Help You?
  • Workflow: Movie Return
  • Delivery Plan: DEFAULT
  • Short Description: Return a movie from the collection
  • Description:
    • Rental Policy

      Each item you rent from ServiceNow has a minimum rental period of one day.  That one day minimum rental period is measured from the time you first receive your rental through 9:00 p.m. the next day.  

      Each item you can rent has a daily rental charge.  To incur a single daily rental charge, you must return your rental by 9:00 p.m. the next day in the time zone where you return your rental.  For example, if the daily rental charge for a DVD is $1.00, you will be charged only $1.00. 

  • Variables
    • Type: Reference, Question: Movie, Reference, u_movies Name: movie, Reference Qual: javascript:movieReturn(), Mandatory: true
    • Type: Reference, Question: Requested By, Name: requested_by, Reference: User [sys_user], Reference Qual: active=true, Mandatory: true, Default value: javascript:gs.getUserID()

2. Script Includes: movieReturn()

function movieReturn() {
if (!current.variables.requested_by.nil()){
 var answer = "u_checked_out_by=" + current.variables.requested_by;
 return answer;
}
}

3. Workflow: Movie Return

Movie Return Workflow

  • Begin
  • Notification
    • Name: Movie Return
    • To: ${request.requested_for}
    • Subject: Your requested item ${number} for ${cat_item} has been received
    • Message
      • Click here to view request: ${URI}
        <p>
        Number: ${number}
        Opened: ${opened_at}
        Item: ${cat_item}
        Quantity: ${quantity}
        </p>
        <p>
        Additional comments: 
        ${comments}
        </p>
  • Run Script

    • var grMovie = new GlideRecord("u_movies");
      grMovie.addQuery('sys_id',current.variables.movie);
      grMovie.query();
      gs.log('grMovie Query: ' + grMovie.getEncodedQuery() + ' = ' + grMovie.getRowCount());
      if (grMovie.next()){
         grMovie.u_checked_out_by = '';
         grMovie.u_checked_out_date = '';
         grMovie.u_checked_out = 'false';
         grMovie.update();
      }
  • Catalog Task
    • Name: Return Movie by Requested By
    • Stage: Deployment
    • Task Table: sc_task
    • Task Value from Fields
    • Wait for Completion: true
    • Fulfillment Group: Field Service
    • Short Description: Movie Checkout
    • Advanced: true
    • Advanced Script:
    • task.short_description = "Movie Return - " + current.variables.requested_by.name;
      
      var grItem = new GlideRecord("sc_req_item");
      
      grItem.addQuery("sys_id",task.request_item);
      grItem.query();
      if(grItem.next()){
       var varown = new GlideRecord('sc_item_option_mtom');
       varown.addQuery("request_item", task.request_item);
       varown.query();
       while (varown.next()){
      var visible = varown.sc_item_option.item_option_new.visible_summary;
      var question = Packages.com.glideapp.questionset.Question.getQuestion(varown.sc_item_option.item_option_new);
      question.setValue(varown.sc_item_option.value);
      
      if((question.getLabel() != '') && (question.getDisplayValue() != '') && (varown.sc_item_option.value != '') && (varown.sc_item_option.value != "0") && (varown.sc_item_option.value != "false")) {
       task.description += "\n" + " " + question.getLabel() + " = " + question.getDisplayValue();
      }
       }
      }
  • Log Message

    • Name: Movie Return
    • Stage: Completed
  • End

Step 4: Age Verification

1. Catalog Client Script

function onLoad() {

 var gDialog = new GlideDialogWindow('age_verification');
 gDialog.setTitle('Age Verification');
 gDialog.setSize(700,700);
 gDialog.render();
}

2. Reference Qualifier for movie on Movie Checkout Form

  • javascript:ageVerify()

 3. Script Includes for ageVerify

function ageVerify() {
    if (!current.variables.requested_by_age.nil()){
        var answer = '';
        if (current.variables.requested_by_age > 17) {
            answer = "u_checked_out=false";
        }
        else {
            answer = "u_esrb_rating=G^ORu_esrb_rating=PG^u_checked_out=false";
        }
        return answer;
    }
}


3. UI Page (HTML)

<?xml version="1.0" encoding="utf-8"?>
<j:jelly xmlns:j="jelly:core" xmlns:g="glide" xmlns:j2="null" xmlns:g2="null" trim="false">
 <form action="ui_page_process.do">
  <input type="hidden" name="name" value="age_verification"/>
  <table table-layout="fixed" width="300px">
      <tr>
         <td id="my_label" class="label" nowrap="true" type="string" choice="0"><label>Age:</label></td>
         <td nowrap="true">
            <input id="user_age" type="input" maxlength="3" size="2"/>
         </td>
      </tr>
      <tr>
         <td colspan="q" nowrap="true" id="my_label" class="label" type="string" choice="0"><label>I have read and agree to the privacy policy:</label></td>
         <td>
            <input id="privacy_check" type="checkbox"/>
         </td>
      </tr>
      <tr>
         <td colspan="1"><br /><strong>Privacy Policy</strong></td>
      </tr>
      <tr>
         <td colspan="2" word-wrap="break-word">Movies are rated G, PG, PG-13, R, and NC-17.  Some rated movies are only appropriate for certain ages.  
We require you to verify your age before accessing this account.  We may use this information for tracking movie views and to promote movies in your interests.</td>
      </tr>
      <tr>
         <td align="right" colspan="2">
            <br />
            <g:dialog_buttons_ok_cancel ok="return validateForm();" cancel="return onCancel();" />
         </td>
      </tr>
  </table>
 </form>
</j:jelly>

3. UI Page (Client Script)

function validateForm() {
   if ($('privacy_check').checked && gel('user_age').value != '') {
      var myAge = gel('user_age').value;
      g_form.setValue('requested_by_age',myAge);
      GlideDialogWindow.get().destroy();
      return false;
   }
   else {
      alert("${JS:gs.getMessage('Please input Age and agree to Privacy Policy')}");
      return false;
   }
}

function onCancel() {
   GlideDialogWindow.get().destroy();
   return false;
}


Step 5: Add CMS

1. Create Site

movies now CMS

movies now CMS

  • Copy Site: Employee Self Service
  • Name: MoviesNow
  • URL Suffix: moviesnow
  • Default Layout: CMS 2 Column Narrow Left
  • Default theme: Grey
  • Remove Search Page
  • Remove Gauge Target Page

2. Header

  • Name: Movies Now - Portal - Header
  • Add Logo
  • Turn off Search
  • Remove Portal Footer

3. Navigation Menu

  • Movies Now - Portal - Header Menu
  • Deactivate all menu sections except for home

4. Navigation Menu

  • Movies Now - Portal - Block Menu
  • Deactivate all menu sections except for Order Things

5. Menu Section

  • Rename Order Things to My Movies
  • Second Level Text: Checkout and Return Movies

6. CSS Adjustments

  • Use Google Chrome "Inspect Element" to and adjust ServiceNow style sheets

7. Portal Pages

  • Remove Portal Pages not used