MxMobile Update March 2022 Release

A3J Group is #AlwaysInnovating in order to bring state-of-the-art enhancements to the IBM Maximo community. Our 20+ years of experience in Maximo allows us to deliver end users the proper support and solutions needed to maximize efficiency. We strive to remain thought leaders in the community and we face common issues and challenges head-on. Our suite of mobile apps for IBM Maximo, MxMobile, gives users access to IBM Maximo from their mobile device. Our apps allow Maximo users the ability to create and edit work orders, generate meter readings, manage inventory and more.

As an IBM Maximo mobile solution provider, A3J Group consistently improves the functionality and features of MxMobile. Enriching the experience of MxMobile users is not only our passion, but necessary. Our users enjoy the freedom of Maximo mobility and are happy to report bugs and request interface features, and our team actively delivers on those requests. You can download MxMobile apps from the Apple App or Google Play store and enjoy a 30-day trial.

Here are the improvements that the A3J Group developers have made to MxMobile as of March 7, 2022:

MxWork:

  • Added logic that will auto-route to the login page with a toast message if the LTPA or CSRF error messages occur. Previously, some users would get force logged out of the app due to a session timeout in IBM Maximo, but the mobile app would not notify the user indicating this was the cause for the force logout. Now, users will be informed how to remedy their IBM Maximo session to resolve the issue.
  • Created a “Costs” tab within the details page of a work order with basic planned and actual information
    • Page is configurable
  • Improved the labor submission feature such that fields are configurable, not hard coded. When entering labor time, user can now input a start and end time, rather than a single number of hours worked. This improves labor time accuracy for work orders.
  • Bug fix for labor time submissions: In previous version(s), if a user input labor time then pressed the “Enter” button on their keyboard to submit the record, the labor time record would be submitted twice. This issue is resolved.
  • Priority code bug fix: in previous version(s), if a priority code look-up is categorized as value “0” in the Work Order Priority field then the priority code would not register. This has been resolved in the new update.

MxCount:

  • Upgraded to latest version of Ionic Framework
  • Bug fix for Offline mode: If a user generates a list of items to operate MxCount in Offline mode then uses the barcode scanner feature to query an item lookup, the initial list would be superseded by the item that was scanned in. In that instance, the list of items that was generated for offline use would no longer be accessible. With this update, users are now able to create their offline list, and query their offline list using the barcode scan feature without losing access to their generated list for offline mode.

 

We hope that you enjoy the new updates of A3J Group’s MxMobile suite of IBM Maximo mobile apps. If you have any suggestions, feature requests or need to report a bug, please contact support@a3jgroup.com. If you would like to be notified via email when A3J Group posts a new blog sign up in the form below.

 

 

 

Product Launch: Automated Label Printing from NinjaFix

The A3J Label Printing report solution includes a report and an automated process to print labels as items
and materials are received. The printer used by the storeroom is defined on the storeroom record. If only
a single printer is used across all storerooms, then the automation script may be adjusted to use a system
property.

The goal of the automation is to proactively notify warehouse personnel when an item or material is
received through a printed label report. The label report should contain information about the received
item or material with bar-coded fields to enable scanning. The labels can automatically be fixed to parts
(materials) that are received.

The report that prints at the storeroom will have all the information that the warehouse operations staff
will need to fulfill the request. It will also have bar codes for key fields that will enable mobile applications
to quickly scan and perform inventory transactions against the reservation. A3J recommends pairing this
report solution with its own suite of mobile applications called MxMobile.

This solution includes a report built and tested to work with a Zebra printer. Specifically, a Zebra 410 and
520 portable printers but should work with any label printer that supports a 4.09”x2.00” format.

The report label is built to print the following fields:

• Item number (with barcode)
• Item description
• Purchase Order number (with barcode)
• Purchase Order line number
• Bin number if received into a bin
• Quantity at receipt (custom field included in solution)
• Work Order number (with barcode)

If either item number or work order number fields are blank the label rows will be blank saving space for
additional information. To purchase click here!

MxMobile: Using Saved Queries with A3J Group’s Mobile Apps for IBM Maximo

As we all know, saved queries can make our workload much easier to manage when you’re having to sort through hundreds of records in Maximo.  However, have you ever created a saved query in Maximo and you weren’t able to find that query on one of A3J Group’s mobile apps?  You’re not alone, it’s happened to me too and the solution is very simple to follow.

 

For this example, I will use MxWork as the mobile app. In Maximo, I created a query on the Work Order Tracking application called “Environmental Group WOs” that displays all of the work orders with a person group of “ENV” and with a status of “APPR” and “INPRG”.

 

saved queries MxMobile IBM Maximo Mobile App

 

When I save this query and log into the MxWork mobile application and navigate to the Saved Queries list, I won’t see this query.  Why is that?  Well, the saved query has to be available in the API in order to access it from the mobile apps.  So, with the addition of Query Definitions in Maximo 7.6.0.3, we can select the query in the Object Structure for that specific application which will then allow the query to be accessible from the API.

 

If you open the details of the Object Structure, in this example we’re looking at MXWODETAIL, you’ll see Query Definitions listed under More Actions.  This is where you will add your query.  If you do not see your query in the lookup, you may need to make your query public by accessing View/Manage Queries and checking the box underneath Public.  Below are the three fields that are required:

  • Query Type: appclause
  • App Name: WOTRACK
  • Query Clause Name: Environmental Group WOs

asset management saved queries MxMobile IBM Maximo Mobile App

 

After I click OK and reload the Saved Queries list in MxWork, I now see the Environmental Group WOs query.  What’s also great about this solution is that the same process applies to all of A3J Group’s mobile apps!

using saved queries MxMobile IBM Maximo Mobile App

Maximo Mobile App saved queries used in MxMobile A3J Group asset management

MBOs in Automation Scripts: Long Descriptions

Maximo provides a facility whereby unlimited text may be associated with an attribute. This text is stored in an additional table called the LONGDESCRIPTION table. The relationship between the long description and the associated object isn’t straightforward. Fortunately, the MBOs provide a facility to hide this complexity and make it easy to set and get such special attributes.

Certain attributes of certain objects have been designated as the owners of long descriptions. The ISLDOWNER column in the MAXATTRIBUTE table indicates whether an attribute can have an associated long description. In such cases, the effect is that of a new attribute being added to the object, an attribute whose name is attributename_longdescription. For example, in the WO object there is an attribute called “description”. This is an owner of a long description, so an attribute called description_longdescription is available for use. The setValue() and getString() methods, among others, may be used to alter or retrieve the value of the attribute. It is not currently possible to use the QBE mechanism on a long description.

mbo.setValue("description_ longdescription", "This sentence is a long description.") logger.debug(mbo.getString("description_ longdescription"))

It should be noted that in performance terms it is more expensive to retrieve a long description than a normal attribute.

MBOs in Automation Scripts: Query by Example

As mentioned our Working with MBO Collections article, it is possible to call the setWhere() method to restrict the members of the collection. There is an alternative method for those folks that might be uncomfortable writing SQL clauses. This feature is called Query By Example or QBE. To access it, use the setQbe() method as shown in the following example:

mboSet.setQbe("wonum", "1%")

This applies a restriction such that for each member of the resulting work order collection the WONUM attribute will begin with the character “1”. As discussed earlier, such a filter is effective only when the collection is first retrieved, so it may be necessary to call the reset() method.

The above example is very simple, but it is possible to make successive calls to setQbe() on different attributes – the result is the concatenating together of the set of restrictions with AND logical connectors. A second version of setQbe() concatenates the restrictions together with OR logical connectors – in this version the arguments are passed in a slightly different format. It is not possible to set more than one restriction on a given attribute, nor is it possible to perform a QBE on an attribute of a related object rather than on attributes of the objects in the collection themselves. Thus, for example, selecting work orders based on whether the Asset is rotating would not work, because the attribute in question is a member of the Asset object, not the WO object. To fulfill the request would require accessing related objects of a type different from the ones that make up the collection. Such actions are not permitted. If this is too restrictive, use the setWhere() method.

To clear the contents of the entire QBE, call the resetQbe() method.

It is important to understand the relationship between setWhere() and setQbe(). Internally, there is a complete where clause that is used for fetching records to the collection. The complete where clause is built by calls to both setWhere() and setQbe(). New restrictions set by calling setQbe() are AND’ed to existing restrictions that were set using setWhere(), and vice-versa. The resetQbe() method clears only those restrictions set by setQbe() calls. The setWhere() method can clear restrictions by passing an empty string:

mboSet.setWhere("")

This call, however, clears only those restrictions set by a setWhere() call. Thus, if it is necessary to start with an totally empty where clause, both setWhere(“”) and resetQbe() must be invoked.

At first glance it may not be obvious why one should use the setQbe() method and not setWhere(). The setQbe() method hides many of the database sensitivities from the programmer. It places literals in the quote characters as necessary and adds any appropriate database function calls to support querying on date, time and timestamp fields. Case insensitive queries can also be handled more easily using this mechanism. The programmer has better control over the treatment of a search string because two methods have been provided for this purpose: setQbeExactMatch() and setQbeCaseSensitive().

woSet.setQbeExactMatch(True) woSet.setQbeCaseSensitive(True)

MBOs in Automation Scripts: Object Relationships

In our previous posts in this series, we talked about how an MboSet is a collection of Mbo objects. This is analogous to a spreadsheet of data representing an MboSet, and a single row within that spreadsheet representing an Mbo. This article will discuss how to work with records related to an Mbo or MboSet.

All examples so far in this series have dealt with individual objects. It is possible to use an object as a starting point for traversing to other objects that are related in some way to retrieve, for example, the planned labor or the asset associated with a work order. There are two possible approaches to achieve this. The more general one is to use the getMboSet() method of a Mbo as shown in the following examples.

# Get the planned labor objects associated with the work order

wpLaborSet = mbo.getMboSet("WPLABOR")

wpLaborCount = wpLaborSet.count()

# Get the associated asset along with some of its data

assetList = mbo.getMboSet("ASSET")

asset = assetList.moveFirst()

serialNumber = asset.getString("SERIALNUM")

The mbo.getMboSet(“WPLABOR”) method call above returns a collection of WPLabor objects, specifically, those labor requirements associated with the first work order on the current work order Mbo. There is a 1:N relationship between work orders and Work Plan Labor objects as a given work order may have multiple labor requirements associated with it. Thus, the wpLaborSet may have from 1 to N members. Note that wpLaborSet is a standard MboSet object, containing all the standard member methods, any of which may be called in the standard way.

In some cases, related objects are in a 1:1 relationship such as work order to asset (mostly… except in multi-asset cases). A given work order only has one asset associated with it at a time in most cases. Thus, when getMboSet(“ASSET”) is called on a work order, the returned MboSet will contains a single object if the ASSETNUM field is populated on the work order.

A list of objects with relationships to other objects (including the relationship name, which is the argument to be passed to the getMboSet() method, the type of objects in the returned MboSet, and the nature of the numerical relationship, i.e. 1:N vs. 1:1) is provided in the Relationships tab of the Database Configuration application in Maximo.

The second approach to working with associated objects amounts to a shortcut which can be used when only the data value of some attribute of a related object is needed. This approach is referred to as “dot notation” and it allows the retrieval of an object’s data without retrieving the object itself. It is most convenient in cases where the relationship is of the 1:1 type. While it does work for 1:N relationships, its usefulness is somewhat restricted.

The following code illustrates how the dot notation is used:

woSet = mbo.getMboSet("WORKORDER")

wo = woSet.getMbo(0)

serialNumber = wo.getString("ASSET.SERIALNUM")

assetLongDescription = wo.getString("ASSET.DESCRIPTION_LONGDESCRIPTION")

problemDescription = wo.getString("PROBLEM.DESCRIPTION")

Dot notation is therefore a call to a WO’s (or, more generally, a Mbo’s) getString() method with a special argument. The argument has two parts, separated by the dot. The first is the relationship name; the second is the name of the associated object’s attribute whose value is being retrieved. Please note that relationships can also be chained together using more than two parts (e.g. “LABOR.PERSON.DISPLAYNAME”), however the majority of cases will be two strings separated by a dot. It’s also important to note that the relationship name is just that; oftentimes Maximo uses the object name itself as the relationship name, but in some cases the relationship name is different than the object name. This is especially true where one object relates to another object via multiple fields (e.g. CHANGEBY and REPORTEDBY both refer to the PERSON object, therefore two different relationship names are needed to distinguish the PERSON.DISPLAYNAME field as the values may be different).

The first part in the above example retrieves a reference to a specific WO object. The next three lines call its getString() method with different examples of the dot notation. The call to wo.getString(“ASSET.SERIALNUM”) retrieves the value of the serialNum attribute for the associated Asset object. This line achieves the same result as in the general example at the start of this article but without accessing the Asset object itself at all.

The call to wo.getString(“ASSET.DESCRIPTION_LONGDESCRIPTION”) illustrates how the dot notation also works for more unusual attributes like long descriptions.

The call to wo.getString(“PROBLEM.DESCRIPTION”) is a somewhat more complicated example. The relationship name is “problem”, but the type of associated object being accessed is not a hypothetical “Problem” object (which in fact does not exist) but rather a Failure object. Thus, the “description” attribute being specified is actually the “description” attribute of a Failure object (specifically, that Failure object specified by the value in the WO object’s “problemcode” attribute). This example illustrates how the dot notation can be used even when the relationship name is different from the name of the associated object.

If the dot notation is used when the relationship is 1:N then the data value of the first object’s attribute is returned. This can be a serious limitation since there is no guarantee as to which associated object is the first one. The only way to find out is to check explicitly.

If the dot notation is used in a case where there is no associated object, e.g. if the “ASSET.SERIALNUM” is requested for a work order which has no Asset associated with it, an MxApplicationException is thrown.

MBOs in Automation Scripts: Changing Status

In our previous posts in this series, we talked about how an MboSet is a collection of Mbo objects. This is analogous to a spreadsheet of data representing an MboSet, and a single row within that spreadsheet representing an Mbo. This article will discuss how to change the status of an Mbo that is stateful.

There are a number of objects that are able to perform status changes. These status changes control the flow of the object through a lifecycle or business process. For example, a work order flows from Waiting Approval to Approved to In Progress to Completed to Closed. Each one on these stages is a status in the application’s terms. As a result of transitioning from one status to another, certain business rules may be invoked that update other parts of the system. As an example, when a work order is approved, all parts required for that work order are reserved in Inventory.

Objects that have the ability to change state implement the StatefulMboRemote interface.

To change the status of an object, the changeStatus() method is called through the Mbo. For example:

# Change the status as of the given date
 
from psdi.server import MXServer
 
mbo.changeStatus("APPR", MXServer.getMXServer().getDate(), "A reason or memo")

The MXServer.getMXServer().getDate() variable in the changeStatus() call above is a Java Date and represents the date at which the newly set status is to take effect. The third argument is a string variable which allows the user to include a short note about this particular status change. The memo argument is optional – a null value may be passed. If an error occurs at any point, an MXException is thrown.

The caller does not need to understand what business rules are invoked within the object – the goal is to hide such details and make it easy to perform the status change operation.

Depending on the business rules coded into the object, it may not be possible to perform certain status changes. For example, it is not possible to move from CLOSE to WAPPR.

A list of available statuses for an object can be retrieved by calling the getStatusList() method.

MBOs in Automation Scripts: Attributes with Value Lists

In our previous posts in this series, we talked about how an MboSet is a collection of Mbo objects. This is analogous to a spreadsheet of data representing an MboSet, and a single row within that spreadsheet representing an Mbo. This article will discuss how to work with attributes on an Mbo that have an associated value list.

A given attribute of an object may have a list of valid values associated with it. This is typically used to display a drop down or value list to the user from which a specific value may be selected. A method called getList() has been provided to allow retrieval of this kind of list for those attributes that support one. The method returns a MboSet object from which values can be extracted for display to the user.

Suppose the desired result is a list of valid asset identifiers for the “assetnum” attribute on a work order object. The following code could be used to retrieve this information:

assetList = mbo.getList("assetnum")

The call to the getList() method with the attribute name “assetnum” as its argument returns a MboSet object with an MboSet of valid asset objects for this work order. The list of valid values for the work order object’s “assetnum” attribute can be built by extracting the “assetnum” value from each of the objects in the assetList variable. This would be accomplished via standard mbo.getString(“assetnum”) calls on each of the objects in the list. Note that assetList is a fully functional collection object, any of whose member methods may be called in the usual way. For example, it is possible to add new members to the collection or modify member attributes.

If the specified attribute passed to getList(attribute) does not support a value list, a null is returned. To determine whether a given attribute does support a list, the hasList(attribute) method in the MboValueData class should be called – see the previous article on Reading Multiple Attributes of an Object in the Collection.

The getList(attribute) method is available for both MboSets and Mbo classes. Even in an empty collection object the getList(attribute) method can be called successfully, with some exceptions. For example, whether or not the “problemcode” attribute has a value list depends on whether a value has been selected in the “failurecode” attribute of the given work order. Thus, if the getList(attribute) method is being accessed through a MboSet object, in the case of the “problemcode” it does matter what the current object is.

Unable to Find Records in IBM Maximo

If you are searching for items and your descriptions do not present any search returns then you may need to read this article…

IBM Maximo attributes such as the Description field are natively configured to use TEXT search instead of WILDCARD.  A text search will use the database’s text search engine.  This is important because text searches are more efficient due to the database using indexes to locate records.  In addition, a text search is not case-sensitive so users typically prefer this type of search over WILDCARD.

I recently had an experience where an IBM Maximo environment using a Microsoft SQL Server database was unable to locate item records using the search term ‘WELL PUMP’ on the Description field.  A search for ‘WELL’, ‘%WELL%’, or ‘WELL PUMP’ brought back zero records.  The pump could only be found by searching for ‘PUMP’.

Since ITEM.DESCRIPTION is a text search enabled attribute, I knew it had to be full text search related. However I was unsure how it was related.  I first rebuilt the text catalog located under Databases > [database_name] > Storage > Full Text Catalogs > [text_catalog_name].

Maximo-Object-Explorer

A rebuild of the catalog had no effect.  Next I increased logging on the ITEM object so I could get the exact query IBM Maximo was sending to the Microsoft SQL Server.  This produced the following query:

select *

from item 

where ((status != 'OBSOLETE' and contains(description , 'FORMSOF(INFLECTIONAL,"WELL")') 

and itemsetid = ITEMSET1))

and (itemtype in (select value from synonymdomain where domainid='ITEMTYPE' and maxvalue = 'ITEM'))

Running the above query in SQL Server Management Studio produces zero records.  I was getting closer! The complexity of some of IBM Maximo enterprise asset management system requires much patience, and thoroughness, especially when troubleshooting…

The downside is that there is no shortage of articles on the Web discussing SQL Servers Full Text search capabilities.  I found myself down quite the rabbit hole.  My esteemed coworker, Kelly Nimmo, dropped in to set me down the correct path as she so often does.  She suggested I look into something called a Stop List.

A Stop List in SQL Server is a list of commonly occurring words that SQL Server will discard while searching.  These words are omitted from the full-text index.  A query of the SYS.FULLTEXT_SYSTEM_STOPWORDS table

SELECT * FROM sys.fulltext_system_stopwords where stopword = 'WELL'

for the word ‘WELL’ reveals the following entries:

Search-feature-Stopword

Bingo!  I now had a decision to make.  I could look at removing these entries from the table. Instead, I chose to omit the ITEM table from using the Stop Word list via the following statement:

ALTER FULLTEXT INDEX ON dbo.item SET STOPLIST = OFF

I will roll this out to other tables where WELL may be used to prevent this behavior in the future.

Editing Font Sizes in IBM Maximo – Long Description and Log Defaults

How to change the Long Description and Log Default font sizes for all apps in IBM Maximo:

If you’re like me, you might not have the greatest eyesight in the world. Logs and long descriptions in IBM Maximo are a very useful way to let your co-workers know:

  1. What’s going on with a particular Work Order
  2. Asset, Purchase Order, Item or any of the various applications that would need more description, or a log information put onto it.

IBM Maximo defaults the size for the Long Descriptions and Logs to xx-small type. It’s great for fitting a lot more on a little page. However, it’s very hard to read and for the majority of the world’s population, we need glasses to do so. This begs the question, “Can I customize my Maximo user interface to improve these issues?” The Short

 

How do we go about making the font size larger?

Open the Long Description or Log. From the middle drop-down column (size) you can choose your font size.

The catch…

You must go into system properties and make a change to the global property (webcient.richtext.blocknode.)

If you do not take the step above, each carriage return (geek speak for hitting enter) makes the font size small again. Every subsequent Log or Description that you edit will also need to be changed when you open it to edit.

Is there a way to just have the font size bigger than xx-small in when you open any new or old log or long description in IBM Maximo?

The answer is yes, but you’ll have to roll your sleeves up and do a little bit of work to make it so.

Font sizes in IBM Maximo’s Long Descriptions and Logs revolve around the rich text editor. The rich text editor does not allow for sizing fonts easily. With some determination, you can get those fonts changed into something you won’t have to strain your eyes to read. If you want to make those Long Descriptions and Logs readable then you’re going to have to edit some CSS (cascading style sheets) files. CSS allows for bulk “styles” to re-occur across the website that they are applied to. IBM Maximo is a web application, so this is where we start.

Here’s how…

Buried in the IBM Maximo directories are files that make Maximo work. The ear file will be our focus, but there are others that also assist in Maximo’s functionality. On the application server (the machine that hosts IBM Maximo), you will have a directory that gets installed that contains the CSS information to display Maximo. Navigate to [maximo-folder]\applications\maximo\maximouiweb\webmodule\webclient\css and search for the ‘extended.css’ file. Open it and add the following lines of code to the end of the page.

#dijitEditorBody {

Font-size: 20px

}

 

The second location of an extended.css file that needs to be edited is in the following path, [maximo-folder]\applications\maximo\maximouiweb\webmodule\webclient\skins\iot18\css.

For the latest versions of IBM Maximo (7.6+), the iot18 folder is significant. The reason for this is, other articles mention to add the edited extended.css file to a folder called tivoli09. To save time, understand that the Tivoli directories were made for older versions of Maximo like 7.5 and prior. If you are using a newer version of Maximo look for the iot18 directory. You will edit this extended.css file in the same manner as the last one by adding the lines below to the end of the css file:

#dijitEditorBody {

Font-size: 20px

}

Next, you will need to rebuild the ear file for IBM Maximo and re-deploy it to your Maximo user interface. The 20px setting will default the text to medium in the logs and Long Descriptions.

Originally there were some hesitations on using CSS to fix this problem. It was thought that the change could affect the reports and the way they looked when generated. We have not seen that happen after making these changes.

We want to hear your thoughts about our helpful guide. Please comment below or send your inquiries to:

info@a3jgroup.com

Stay tuned for more helpful articles that will #MaximizeYourMaximo experience and the capabilities of your user interface!