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:
- Add a persistent attribute TIMESPENT to the TICKET business object
- Modify the Service Request presentation to expose a Time Spent field alongside the out of the box Actual Start and Actual Finish fields
- Create an Object launch point against the Service Request business object. This launch point is executed whenever an existing Service Request record is modified.
- 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.
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.
Object Launchpoint
I open the Script with Object Launch Point wizard in the Automation Script application.
In Step 1, I provide the following values:
- Launch Point: CALCELAPSEDTIME
- Object: SR
- Active: Checked
- Update: Checked
In Step 2, I provide the following values:
- Script: CALCELAPSEDTIME
- Script Language: jython
- Log Level: ERROR
- Input variable ‘actualfinish’, bound to SR.ACTUALFINISH attribute
- Input variable ‘actualstart’, bound to SR.ACTUALSTART attribute
- 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"
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:
A test on a different service request record yields this output into the Time Spent field:
Let us take a quick look at the script. There are two parts to it:
- 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.
- 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.
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 Timestamp class and methods
Java BigInteger class and methods
Working with Java Date objects – good introduction with examples
Maximo 7.5 scripting cookbookUID
ibm11134741