August 9, 2019

The hidden features of Work Logs

Work Logs are a very useful feature in Maximo and Control Desk products to allow users to keep notes of the progress of work.

A very nice feature of work logs is that Maximo displays all work logs for the current record an related ones. Lets make an example. If there is a work log on a work order originated from a Service Request, Maximo will display both SR logs and Work Order logs in the Work Order Tracking application.
In the example below we are in the Work Order Tracking application displaying work logs on work order 1019. The first work log has been added to the work order but the second one is attached to the originating service request 1214.

To go in details, Maximo will display records on the Work Logs tab with the following logic:

  • Work logs attached to the current record
  • Work logs for the originating and follow up records
  • If the ticket is global, all work logs in related to this global
  • If it is 'View SR App' (VIEWSR) or cloned by it, display only work logs which are marked as 'Client Viewable'

These rules seem pretty reasonable but in some cases we may prefer to adopt different rules. In such cases we can use a well hidden feature.

  • The system property psdi.worklog.workorder.useWOrelationship allows to specify a custom rule in the CUSTOMWOWORKLOG relationship of the WORKORDER object.
  • The system property psdi.worklog.ticket.useTKrelationship allows to specify a custom rule in the CUSTOMTKWORKLOG relationship of the TICKET object.

For example if we want to display only work logs related to the currently displayed work order we can configure Maximo as follows.
Open the System Properties application and set psdi.worklog.workorder.useWOrelationship to 1. Then apply configuration changes by selecting the record and clicking on 'Live Refresh' action.

Now open Database Configuration application, open WORKORDER object and go to the Relationships tab. Search for CUSTOMWOWORKLOG relationship and set it to:

recordkey=:wonum and class=:woclass and siteid=:siteid

This is how the configuration should look.

If we now open work order we will not see the work log on the service request.

August 4, 2019

Tracking elapsed time in work order status history

A common requirement from my clients is to track how much time work orders have been in each status.
IBM Maximo already has the Work Order History dialog that displays the date and time of each status change. Unfortunately it may be not straightforward for a user to calculate the time spent in each step of the process or to develop a KPI to set processing time goals in your work management flow.

What I usually implement is a very simple time-tracking feature that just displays the elapsed time (time spent) attribute for each row. Note how the new history dialog is much more readable now.

To achieve this result we just need three configurations:

  1. A new attribute to store the 'elapsed time' value in the WOSTATUS table.
  2. An automation script to calculate and set the value in the custom attribute.
  3. Modify the Work Order history dialog to display the new attribute.
Note that he same technique can be implemented for tickets (service requests) with very few modifications.

Elapsed Time attribute

Open Database Configuration application and create a new field like this:

  • Object: WOSTATUS
  • Attribute: XXXELAPSEDTIME (replace XXX with your own custom prefix)
  • Title: Time spent (or Elapsed Time)
  • Type: DURATION

Apply database configuration changes to create the new field in the database.

Automation Script

Open Automation Scripts Applications and create the following script.

# Launch Point: Object (Save - Add - After Save)
# Object: WOSTATUS
# Calculate the time spent in previous status and update XXXELAPSEDTIME

from psdi.mbo import Mbo
from psdi.mbo import MboConstants

# Perform calculation only on interactive sessions to avoid the following error when generating PMs in the background.
# BMXAA3212E - Error while generating work order for PM. BMXAA8229W - Record WOSTATUS has been updated by another user.
if interactive:
  # get latest status history records
  shSet = mbo.getMboSet("$WOSTATUS$", "WOSTATUS", "wonum=:wonum and siteid=:siteid")
  shSet.setOrderBy("changedate desc")

  # calculate elapsed time
  if shSet is not None:
    lastSh = shSet.getMbo(1)
    thisSh = shSet.getMbo(0)
    if lastSh is not None and thisSh is not None:
      diff = (thisSh.getDate('CHANGEDATE').getTime() - lastSh.getDate('CHANGEDATE').getTime()) / float(3600000)
      lastSh.setValue("XXXELAPSEDTIME", diff, MboConstants.NOACCESSCHECK+MboConstants.NOVALIDATION)

Application dialog

The new WOSTATUS.XXXELAPSEDTIME attribute is now automatically updated by the script so we just have to display it in the application dialog.
Open Application Designer and search for WOTRACK application.
Edit the viewhist dialog and add the XXXELAPSEDTIME attribute in the first table.

August 3, 2019

Disable default attachment folder

One of the fist lessons I have learned through all these years as Maximo consultant is that every time there is a default value for a field the user will not change it. A very common example of this is the Folder field of the Add Attachment dialog.

The value of this field will always default to the first folder available in alphabetical order. If we want to force the user to select the most appropriate folder for the attachment, then we have to remove that default value.
The attribute we want to change is DOCLINKS.DOCTYPE. Unfortunately, setting a default value for this field in Database Configuration will not work (believe me I have tried) so we have use a more powerful feature to control the behavior of this attribute. The solution I have found is to use a very simple automation script. Here it is.

Open the Automation Scrips application and create a new record with the following data:
  • Type: Script with Attribute Launch Point
  • Launch Point: DOCTYPEDEFAULT
  • Description: Reset default Attachment Folder for application WOTRACK
  • Object DOCLINKS
  • Attribute: DOCTYPE
  • Event: Run Action
  • Script Language: python
  • Source: paste code below

# Launch Point: DOCLINKS.DOCTYPE - Run Action
# Reset default Attachment Folder for application WOTRACK
from psdi.mbo import MboConstants

if mbo.getOwner() is not None:
  # reset the default value only for a specific set of applications
  if mbo.getOwner().getThisMboSet().getApp() in ("WOTRACK", "ASSET"):
    if mbo.getMboValue("DOCTYPE").getPreviousValue().asString()=="":
      # set an invalid value so the user is forced to set a correct value
      mbo.setValue("DOCTYPE", "-", MboConstants.NOVALIDATION)

The script is quite simple.

  1. It first checks if the owner application is in a specific set. This is because we may need to override the default behavior only for a specific set of applications. In the example it work only for Assets and Work Order Tracking applications.
  2. Verifies that the previous value of the DOCTYPE field is not already set. I have used this trick to detect if the attribute was just initialized or the user already set the value.
  3. Sets an invalid value '-' so the user is forced to set an appropriate folder.

April 26, 2019

Where was an asset located at a certain time in the past?

Maximo has a well known feature to display the history of where an asset was located. It is accessible from View Asset Move History from the Asset application.
In the following example the asset DS01-A-002 was created in location DS01-S-SA-01 and then moved to other two locations.

The data displayed in this dialog is stored in the ASSETTRANS database table.
By querying this table we can answer questions like this:
  • Where was my asset located at a specific point in time?
  • What assets were in a specific location at a specific point in time?

Now lets start reading date from the ASSETTRANS table for asset DS01-A-002. We will get the same results displayed in the dialog above.

select assetnum, toloc, datemoved
from assettrans
where assetnum='DS01-A-002'
order by datemoved;

If we want to know where the asset was the 20th of April we need to know the largest DATEMOVED before that date.

select assetnum, max(datemoved)
from assettrans
where datemoved<TO_TIMESTAMP('2019-04-20', 'YYYY-MM-DD')
and assetnum='DS01-A-002'
group by assetnum;

Now we can join this result in the following way to retrieve the list of asset's locations 'as of' 20th of April at 11AM.

select a.assetnum, a.siteid, a.toloc
from assettrans a
(select assetnum, siteid, max(datemoved) d
 from assettrans
 where datemoved<TO_TIMESTAMP('2019-04-20 11:00:00', 'YYYY-MM-DD HH24:MI:SS')
 group by assetnum, siteid
) h on h.assetnum=a.assetnum and h.siteid=a.siteid and h.d=a.datemoved
order by a.assetnum;

We can now see that asset DS01-A-002 was located in DS01-S-SA-02 as expected. The query includes all the assets and can be filtered by asset or location.

Note that in this last query we have added the SITEID field since ASSETNUM/SITEID is the primary key of the ASSET table.