April 19, 2016

Display bullettin board messages opened by default

A common requirement is to display the bulletin board messages in a more visible way.
A simple solution is to display the formatted message opened by default.

To achieve this you can edit the following JSP file: [SMP]\applications\maximo\maximouiweb\webmodule\webclient\components\bulletinboard.jsp

On my Maximo i have this line of code at row 335:


If you change the display attribute to 'inline' it will show the full message without clicking.


Rebuild and redeploy maximo.ear file and you are done.

April 6, 2016

Maximo Anywhere API Reference

The configuration and customization chapters of the Maximo Anywhere documentation is great for many scenarios but sometimes you need to work with Dojo scripting and Anywhere platform to implement changes to standards screens and business rules.

I have developed my own Anywhere API Reference with the objective of helping myself and the Anywhere technical community out there.

Feedback is welcome but please do not post comments with generic questions I don't have time to answer to all of you.


Package platform.model

Package ui.control

April 5, 2016

Restricting status changes in Maximo Anywhere

A common requirement in Maximo projects is to restrict work order status changes based on some internal business rules. This can be achieved on Maximo with the technique described in this article.
Unfortunately the rules set in the WOSTATUS domain on the server are not applied automatically to the Anywhere mobile applications so we need to customize the mobile apps to follow the same rules.

Lets first analyze how the status changes are managed in the Work Execution app.
The application.business.WorkOrderStatusHandler script implements a state machine where the matrix of allowed status changes are defined (state machine).

init: function(modelDataSet){
var settings = {};
settings.resourceName = "workOrder";
settings.stateToAlias = {};
settings.configuration = {
"WAPPR": ["WAPPR", "APPR", "INPRG",         "WMATL", "COMP",         "CAN"],
"APPR" : ["WAPPR", "APPR", "INPRG",         "WMATL", "COMP",         "CAN"],
"INPRG": ["WAPPR",         "INPRG",         "WMATL", "COMP"               ],
"WSCH":  ["WAPPR", "APPR", "INPRG", "WSCH", "WMATL", "COMP"               ],
"WMATL": ["WAPPR",         "INPRG",         "WMATL", "COMP",         "CAN"],
"COMP":  [                                           "COMP"               ],
"CLOSE": [                                                   "CLOSE"      ],
"CAN":   [                                                           "CAN"]

Unfortunately this script is referenced in many other scripts so the simplest may of overriding it is modifying it. This is not a best practice since this file may be overridden in an Anywhere fixpack but is a quick and dirty solution.
Another limitation of this solution is that it works only based on the domain internal values (SYNONYMDOMAIN.MAXVALUE).

Now imagine the following scenario. I have two aliases of the INPRG status: INPRG1 and INPRG2. I want to avoid a direct transition to INPRG2. Only INPRG1 to INPRG2 must be possible.

Another place where status changes are handled is the filtering rule in the WorkExecution.statusLookup lookup.

<lookup id="WorkExecution.statusLookup" label="Work Order Status" resource="domainwostatus"

If you look at the application.handlers.StatusChangeHandler.filterWOStatus(evenHandler) method you will notice it handles some logic and filters the visible status in the lookup. We can now override this method to implement our logic.

First of all create a new script custom.handlers.MyStatusChangeHandler.

[ "dojo/_base/declare",
  "application/business/WorkOrderStatusHandler" ],
function(declare, ApplicationHandlerBase, StatusChangeHandler, WorkOrderStatusHandler) {
return declare( [ApplicationHandlerBase, StatusChangeHandler], {

  // dummy method required only to ensure script loading
  dummyMethod: function(eventContext) {
  // Filter WO statuses to those available for selection
  filterWOStatus: function(eventContext) {
    // call the original filterWOStatus method

    // retrieve current status
    var currWO = eventContext.application.getResource("workOrder").getCurrentRecord();
    var currStatus = currWO.get("status");

    // retrieve wodomain resource
    var woStatusDomain = this.application.getResource('domainwostatus');

    // sets the additional filter if necessary
    if(woStatusDomain.isFiltered() && currStatus!="INPRG1"){
      woStatusDomain.filter("value!=$1", "INPRG2");


There are two important things to note here.
  1. How the original StatusChangeHandler script is extended using the (see Dojo declare tutorial for details)
  2. How the additional filter value!='INPRG2" is applied to the existing filter already set in the woStatusDomain resource.
  3. The filter is specified using JavaScript syntax not SQL (JavaScript conditions syntax).
Now you need to modify the app.xml to include your customized transition rule.
Modify the WorkExecution.statusLookup filterClass from application.handlers.StatusChangeHandler to custom.handlers.MyStatusChangeHandler.

It seems also this is not enough because the custom script is not loaded by just referencing it in the filterClass.To circumvent this problem you can add a dummy eventhandler like this.

<eventHandler event="render" 
class="custom.handlers.MyStatusChangeHandler" method="dummyMethod" />