IBM Support

Maximo Scripting: Date Dizziness – Part I

Technical Blog Post


Abstract

Maximo Scripting: Date Dizziness – Part I

Body

Introduction


Many Maximo business objects, processes and applications record date and time measurements. Such measurements can be utilized to compute the total time spent by operators on particular tasks. For example, in the Service Request application, finding the elapsed time difference between Actual Finish and Actual Start date and time can help measure the time spent by service desk agents in completing and closing a ticket. This computed information can then be utilized in ad hoc reporting to gain insights into the efficiency of the service desk.

 

Date and time processing with scripts


I have picked this scenario today to illustrate how Maximo scripting can be exploited to calculate the elapsed time. My goal is to calculate elapsed time and present it in the Service Request application user interface formatted in an easy-to-read manner. For example, if the Actual Start time for a service request was 9/2/04 12:04 PM and the Actual Finish time was 9/2/04 12:14 PM, then the time spent in resolving the service request is 10 minutes.

Note: For a more complete and conceptual introduction to Maximo scripting, please follow the Maximo 7.5 scripting link provided in the Useful Links section of this blog.

Note: In Maximo, time spent on a service request is tracked in the form of labor transaction records. These records are generated whenever a service desk agent starts a timer and then stops it thereby capturing time spent. An agent may also manually enter Actual Start and Finish information directly into the service request record. Various totals for a service request can be viewed under different categories such as Total Labor Hours and Total Costs. My goal with this scripting scenario is not to supplant these capabilities. My goal is simple: Illustrate script-based time calculations using Service Request application as the backdrop.

 

Ingredients to build the scenario


I use the following ingredients to put together the desired functionality:

  1. Add a persistent attribute TIMESPENT to the TICKET business object
  2. Modify the Service Request presentation to expose a Time Spent field alongside the out of the box Actual Start and Actual Finish fields
  3. Create an Object launch point against the Service Request business object. This launch point is executed whenever an existing Service Request record is modified.
  4. Create a Jython script that is associated with the Object launch point. This script performs the desired elapsed time computation.

TIMESPENT attribute

The purpose of this attribute is to persist the computed elapsed time in an end-user friendly form in the product database. Using Database Configuration application, I created the persistent TIMESPENT attribute against the TICKET business object. The data type is ALN and its length is 20 characters. Configure the product so that this new attribute takes effect. Notice that the attribute is inherited by the SR business object. For the reminder of our discussion, we will work only with the SR business object. Here is a screen capture of what one would see in the Database Configuration application.

 image

 

 
 

SR application presentation

Using the Application Designer, I open the SR application presentation. I locate the Dates section on the Service Request tab. I add a text box just below the Actual Finish field. I configure the text box by binding the field with the newly created TIMESPENT attribute of the SR business object. In the Textbox Properties dialog, I specify a label and select the SR.TIMESPENT attribute through the Attribute look up. I then save the presentation. Here is a screen capture of what one would see in the Application Designer application.

 image

 

 
 
 
 
 
 
 
 
 
 
 

Object Launchpoint

I open the Script with Object Launch Point wizard in the Automation Script application.

In Step 1, I provide the following values:

  1. Launch Point: CALCELAPSEDTIME
  2. Object: SR
  3. Active: Checked
  4. Update: Checked

In Step 2, I provide the following values:

  1. Script: CALCELAPSEDTIME
  2. Script Language: jython
  3. Log Level: ERROR
  4. Input variable ‘actualfinish’, bound to SR.ACTUALFINISH attribute
  5. Input variable ‘actualstart’, bound to SR.ACTUALSTART attribute
  6. Output variable ‘timespent’, bound to SR.TIMESPENT attribute

In Step 3, I provide the following script:

timediff = actualfinish - actualstart

timespent = elapsedtime(msdiff)

In Step 3, I click the Create button to create the object launch point and save the script.


Dealing with dates


To test this configuration I navigate to the Service Request application, select a service request record that’s in RESOLVED state, has actual start and finish date and time, edit the long description and save the record. The following error is displayed:

BMXAA7837E - An error occured that prevented the CALCELAPSEDTIME script for the CALCELAPSEDTIME launch point from running.

TypeError: unsupported operand type(s) for -: 'java.sql.Timestamp' and 'java.sql.Timestamp' in <script> at line number 1

I realize a number of things:

  • Jython does not directly support applying the subtraction operator against java.sql.Timestamp operands.
  • I am dealing with objects of the java.sql.Timestamp class which extends from java.util.Date class.
  • Subtracting Java Date object instances is not straightforward

The Tpae scripting framework returns Java Date object instances for those variables that are bound to business object attributes of Maximo data type DATE, TIME and DATETIME. With all this information I make the following changes to the script:

def calcelapsedtime(msdiff):

        secondinmillis = 1000

        minuteinmillis = secondinmillis  * 60

        hourinmillis = minuteinmillis * 60

        dayinmillis = hourinmillis * 24

        elapseddays = msdiff / dayinmillis

        elapsedhours = msdiff / hourinmillis

        elapsedminutes = msdiff / minuteinmillis

        if(elapseddays !=0):

                 return str(elapseddays) + " days"

        if(elapsedhours !=0):

                return str(elapsedhours) + " hours"

        if(elapsedminutes !=0):

                return str(elapsedminutes) + " minutes"

timediff = actualfinish.getTime() - actualstart.getTime()

                  timespent = calcelapsedtime(timediff)

I test the revised script by navigating to the Service Request application and saving the updated description on the same record I used previously. The following error is displayed:

BMXAA7837E - An error occured that prevented the CALCELAPSEDTIME script for the CALCELAPSEDTIME launch point from running.
TypeError: unsupported operand type(s) for /: 'java.math.BigInteger' and 'int' in <script> at line number 20

Line 20 is the invocation of the calcelapsedtime() function. Yet the error message specifies an ‘unsupported operand type for /’ indicating the operation being attempted is a division. The problem lies in the first division operation occurring on line 7 of the script:

 elapseddays = msdiff / dayinmillis

The parameter being passed into the calcelapsedtime() function is not a long value but a java.math.BigInteger object. Jython does not support automatic conversion of the Java BigInteger object to a long value. So I revise the script by converting the BigInteger object myself to a long value and pass the long value to the calcelapsedtime() function. Here’s the final script:

def calcelapsedtime(msdiff):

        secondinmillis = 1000

        minuteinmillis = secondinmillis  * 60

        hourinmillis = minuteinmillis * 60

        dayinmillis = hourinmillis * 24

        elapseddays = msdiff / dayinmillis

        elapsedhours = msdiff / hourinmillis

        elapsedminutes = msdiff / minuteinmillis

        if(elapseddays !=0):

                 return str(elapseddays) + " days"

        if(elapsedhours !=0):

                return str(elapsedhours) + " hours"

        if(elapsedminutes !=0):

                return str(elapsedminutes) + " minutes"

                                     timediff = actualfinish.getTime() - actualstart.getTime()
                                     timespent = calcelapsedtime(timediff.longValue())

I test the final script against the service request record and, this time, the elapsed time is successfully written into the Time Spent field:

 image

 

 
 
 
 
 
 

A test on a different service request record yields this output into the Time Spent field:

 image


 

 
 
 
 

Let us take a quick look at the script. There are two parts to it:

    1. Function calcelapsedtime() that accepts a long value representing elapsed time in milliseconds and dividing it using various factors to establish human-readable elapsed time measured in days, hours or minutes. This function returns a string back to the main script representing a nicely formatted elapsed time period.
    2. The main body of the script that accepts the two input variables – actualfinish and actual start; executes the subtraction and invokes the function with the time difference passed in as a long value.
The logic within the calcelapsedtime() function is simple. The passed in long value (which is in milliseconds) is progressively divided by a number that represents a time conversion in days, hours or minutes. Only one of the operations will result in a non-zero result. That result is returned to the main script.

Summary


Dates-based calculations in Maximo scripting are not difficult to author. It is important to understand what Maximo data type you are working with and how the script framework passes a representation to the script. With that insight, useful scripts can be authored that deliver application enhancements rapidly to end users. You can find copy of the script as a ZIP file at this link.

Useful Links


Java Date class and methods

Java Timestamp class and methods

Java BigInteger class and methods

Jython operators

Jython functions

Working with Java Date objects – good introduction with examples

Maximo 7.5 scripting cookbook

[{"Business Unit":{"code":"BU059","label":"IBM Software w\/o TPS"},"Product":{"code":"SSLKT6","label":"IBM Maximo Asset Management"},"Component":"","Platform":[{"code":"PF025","label":"Platform Independent"}],"Version":"","Edition":"","Line of Business":{"code":"LOB59","label":"Sustainability Software"}}]

UID

ibm11134741