Showing posts with label Automation Script. Show all posts
Showing posts with label Automation Script. Show all posts

Tuesday, 18 November 2025

Improving SLA Accuracy by Aligning Work Order Reported Date with PM Seasonal Start Time | Maximo

Why This Is Needed (in base Maximo)

By default, PM work orders are created with a REPORTDATE based on the PMWoGenCronTask run time.

This causes SLA targets (response, resolution, target start/finish) to be calculated from the wrong date.

Seasonal PMs often require SLAs to start from the seasonal start time defined in PM.TARGSTARTTIME.

By merging that time into the REPORTDATE, SLA calculations become accurate and fully aligned with the seasonal schedule—instead of the cron generation timestamp.



To ensure SLAs calculate correctly from the intended seasonal start time, I added an Object Launch Point automation script on WORKORDER with:

Condition: pmnum is not null

Events: Add, Save, Before Save

The script takes the time from PM.TARGSTARTTIME and applies it to the date in REPORTDATE, ensuring the work order uses the correct seasonal seed date before any SLA is applied.

Sunday, 11 August 2024

Run SQL directly from Automation script - Calling a Script Using Rest API

1.create a Script RUNSQL with below code

2. all this script with the sql in the end for instance:

https://[MAXIMO_URL]/maximo/oslc/script/runsql?method=SELECT&sql=SELECT assetnum,description,status FROM asset WHERE status='OPERATING' limit 5



from psdi.server.MXServer import getMXServer as MXS

def getHeader(rs):

    headerStr = ""    

    for i in range(rs.getMetaData().getColumnCount()):

        headerStr = headerStr + rs.getMetaData().getColumnName(i+1) + ","

    headerStr = headerStr[:-1] + "\r\n"                     # Remove the last "," and add a line break

    return headerStr


def getData(rs):

    dataStr = ""

    while (rs.next()):                                      #Loop through rows

        for i in range(rs.getMetaData().getColumnCount()):  #Loop through columns

            dataStr = dataStr + (rs.getString(i+1) or 'null') + ","

        dataStr = dataStr[:-1] + "\r\n"                     # Remove the last "," and add a line break

    return dataStr


### MAIN ###

connKey = MXS().getSystemUserInfo().getConnectionKey()

conn = MXS().getDBManager().getConnection(connKey)

method = request.getQueryParam("method").upper()            # SELECT or UPDATE,DELETE,INSERT

sql = request.getQueryParam("sql").upper()

stmt = conn.createStatement()


try:

    if method != 'SELECT':

        stmt.execute(sql)

        responseBody = "Done"

    else:

        rs = stmt.executeQuery(sql)

        headerStr = getHeader(rs)

        dataStr = getData(rs)

        responseBody = headerStr + dataStr

        rs.close()

finally:

    stmt.close()

    conn.commit()

    MXS().getDBManager().freeConnection(connKey)

#    https://[MAXIMO_URL]/maximo/oslc/script/runsql?method=SELECT&sql=SELECT assetnum,description,status FROM asset WHERE status='OPERATING' limit 5

######


maximo-runsql-automation/runsql.py at main · abdulqadeerel/maximo-runsql-automation

Tuesday, 1 November 2022

Restrict a User to Delete an Attachment from an Approved PO | Maximo

The requirement is to lock the record so that nobody can delete a record if the purchase order is approved.

And the solution is with a small automation script on DOCLINKS object:


object: DOCLINKS

event: BEFORE SAVE

Type: Object Launch Point

Script: Jython


owner=mbo.getOwner()

if owner and owner.getName()=="PO" and owner.getInternalStatus()=="APPR" 

    service.error("","Purchase Order is approved. ")



Also ideal to control it via the signature option, create a new signature option from the application designer and grant access using the relevant security groups then just use it in your code. thanks to Steven Shull.

owner.sigopGranted("DELETEATTACH"): 



Monday, 24 May 2021

Call Maximo Script from Rest API (http call) (Create SR Example) | Maximo

 Create a simple script in Maximo and Call the Maximo Rest API request to post/get the data.

Let's create a simple automation script, it will create an SR with minimal information. 

1. create a script in automation script application with below code:

from psdi.server import MXServer;
srSet = MXServer.getMXServer().getMboSet("SR", MXServer.getMXServer().getSystemUserInfo());
newSR = srSet.add();
newSR.setValue("TICKETID", request.getQueryParam("ticketid"));
newSR.setValue("DESCRIPTION", request.getQueryParam("description"));
srSet.save();


2. Now send below  request from Postman or any other tool:

http://localhost/maximo/oslc/script/createjsonsr?_lid=maxadmin&_lpwd=maxadmin&ticketid=123&description=test ticket


or We also can send the data in payload

POST http://localhost/maximo/oslc/script/createjsonsr

MAXAUTH <encoded 64bit>

{
    "ticketid" : "123456",
    "siteid" : "BEDFORD",
    "description" : "test SR from http call"
}


 

parameter appended in query string after (?)

request.getQueryParam("variable")

To get the user info from the request

request.getUserInfo()

read and parse the request to get the payload. 

res = JSONObject.parse(output)
vId = res.get("id")
mbo.setValue("description",vId)


Tuesday, 11 May 2021

Send SurveyMonkey from Maximo using Zapier (Call a query string from Automation Script)

Calling an external URL from Maximo Automation scirpt to achieve this requirement. 

Requirement was; To send SurveyMonkey's survey to the EndUser/Customer when the  status of Service Request is Resolved.

3 things we needs for this excerise:

  1. Maximo Automation 
  2. Zapier Webhook
  3. Survey Email in Survey Monkey

1. Design a survey in Survey Monkey, Create Collector as Email. 

2. In Zapier make a Catch Hook, get the API  and append any parameter as query string (&ownerid) etc.

3. In Zapier make an Action to connect with Survey Monkey and trigger Contact Send.

Thursday, 11 February 2021

Overdue Duration Calculation Between Two Dates (Excluding Weekends) using Automation Scripts | Maximo

We have two dates, the status date: rcareviewdate and Etc date:rcainprgdate. The script below calculates the duration in Hours excluding weekends between these two dates based on attribute status date change. 

When we change the status it will calculate overdue for previous status ETC date and current status change date.

Launch Point Type:     Attribute Launch Point

Attribute:                     CHANGEDATE

  #Imports


from java.util import Date 

from java.text import SimpleDateFormat

from psdi.mbo import MboConstants 

from psdi.server import MXServer

from java.util import Calendar

from psdi.app.common import DateUtility



#Milliseconds Constants

MILLISECONDS_DAY= 86400000 

MILLISECONDS_HOUR = 3600000

MILLISECONDS_MINUTE = 60000 


#Default hours and minutes values

days = 0

hours = 0

minutes = 0 

Tuesday, 19 January 2021

Python Function - Find the Next Business Days After n Days | Maximo

You have 15 business days (exclude weekends) to complete the task, what will be the 15thday?


from java.util import Calendar

#Function definition
def getNextBusinessDday(d, n ):
    cal = Calendar.getInstance();
    cal.setTime(d)
    loop=1
    while(loop<=n) :
        cal.add(cal.DATE, +1)
        if (cal.get(cal.DAY_OF_WEEK)) not in [cal.FRIDAY,cal.SATURDAY] : 
            loop=loop+1
        vserial = loop
    calculatedetc = cal.getTime()
    return calculatedetc

#variables for input
d = mbo.getDate("changedate")
n = 15

#function call whereever you want in the same script
getNextBusinessDday(d,n)

Monday, 4 January 2021

Create Purchase Requisition from Inventory Usage using Action Script (Customized Option) | IBM Maximo

Recently we had the requirement to disable the direct MR to PR automation. so instead of

creating direct PR from MR, the users will select a store on material requisition to reserve material

from store. When the MR is approved, the inventory usage is created from MR.

If the material is available in-store, storeroom will issue the material otherwise he clicks the option

to create Purchase Requisition (PR) from inventory usage.

So we developed this new functionality.

Note: This script contains a few custom attributes. I have commented those line, In your case please remove them.

Step 1:

First Add new Status for Inventory Usage Application: PR_CREATED

Step 2: Create Automation Script

Launch Point:        ACTION

Object:                  INVUSE

Variable:                v_mr

Binding Value:      INVUSELINE[MRNUM is null].MRNUM*

Relations:              INVUSE --> INVUSELINE -->MRNUM (child object:MR, mrnum=:mrnum)

Sunday, 27 December 2020

Delete a Person from a list of Person Groups (Dialog, Automation Script) | Maximo

A revised version of the existing post Delete a Person from Person Groups (LIST VIEW QUERY) using Automation Script | Maximo.

We are going to add a dialog box on the list view of Person Group Application to choose the Person to be deleted. 




1. New Non-Persistent Object with one attribute Personid

  • Object Name: NP_DELETE_PERSONID
  • Attribute:        NP_personid

Sunday, 20 December 2020

Workflow Handling from Automation Script | IBM Maximo

Initiate a workflow from an Automation Script. 

from psdi.server import MXServer

mxs = MXServer.getMXServer()

wfstart = mxs.lookup('WORKFLOW')

wfstart.initiateWorkflow('CSPREIMB',mbo)

 

-------------------------

Or define a function in your script and call it whenever needed as below:

Function Defination:

def startwf(a):
   actionSet = MXServer.getMXServer().getMboSet("action", a.getUserInfo());
   sqf = SqlFormat("action = :1")
   sqf.setObject(1, "action", "action", "STWFEUNRI")
   actionSet.setWhere(sqf.format())
   actionSet.reset()
   actionSet.getMbo(0).executeAction(a)

 

Function Call:

startwf(MboVariable)

 2. Stop an active workflow from the Automation Script. 

from psdi.server import MXServer

mxs = MXServer.getMXServer().lookup('WORKFLOW') 

wfstop = mxs.getActiveInstances(mbo)

         wfstart.getMbo(0).stopWorkflow('Stopped')

 or 

    wfInstanceSet=mbo.getMboSet("$wfInstanceSet","WFINSTANCE","processname='IBMMAINWF' and ownertable='WORKORDER' and ownerid=:workorderid and active=1")

wfInstanceMbo=wfInstanceSet.moveFirst()

if wfInstanceMbo:

        wfInstanceMbo.stopWorkflow("Stopped because Type becomes DLP")


Invoke Action from Automation Script | IBM Maximo

from psdi.common.action import Action, ActionRemote

from psdi.security import UserInfo

from psdi.server import MXServer


mxServer = MXServer.getMXServer()

userInfo = mbo.getUserInfo()


actionSet = mxServer.getMboSet("ACTION", userInfo)

actionSet.reset()

actionSet.setWhere("action = 'INV_RUN_REP'")


if(not actionSet.isEmpty()):

action = actionSet.getMbo(0)

action.executeAction(mbo)

actionSet.close()

Tuesday, 20 October 2020

Object Lauch Point - Allow Objet Creation/Deletion (CanAdd/CanDelete) | Maximo

These 2 events fire immediate and do not even wait for the framework to save/insert the record.


Allow Object Creation - canAdd() method of mbo framework

Creation is bit tricky because it runs when there is no record. And because there is no record there is no mbo the implicit variable. In that case, we use "mboset" as 

if mboset.getOwner() is not None and mboset.getOwner().getName()=="PO" and mboset.getOwner().isNull("vendor"): 

   service.error("PO", "vendor is null") 


Allow Object Delete - canDelete() method of mbo framework

Deletion is simple if we throw an error, the system will prompt with an error and stop further processing, and the record will not be deleted.  


if mbo.getOwner() is not None and mbo.getOwner().getName()=="PO" and !mbo.getOwner().isNull("vendor"): 

   service.error("PO", "vendor is not null") 

Thursday, 17 September 2020

Get PersonID of the Logged in User in Automation Script | Maximo

There are multiple ways  to get the person id in Automation script, one of the them is as below:

PersonSet = MXServer.getMXServer().getMboSet("MAXUSER", mbo.getUserInfo())

    PersonSet.setWhere("PERSONID=:&PERSONID&")

    vPerson = PersonSet.getMbo(0)

    service.error(user,vPerson.getString("personid"))

    PersonSet.save()

 

For Person ID: -                 :&PERSONID&

For Username  -                   :&USERNAME&

 

or we can also use the one of the implicit variable ( USER )fo the logged in user:

PersonSet = MXServer.getMXServer().getMboSet("MAXUSER", mbo.getUserInfo())

    PersonSet.setWhere("userID='" + user + "'");

    vPerson = PersonSet.getMbo(0)

    service.error(user,vPerson.getString("personid"))

    PersonSet.save()

Tuesday, 15 September 2020

Automation for Restriction on Increasing PO Quantity for the PO Revision but Allow the Quantity Decrease || IBM Maximo

Recently we had a requirement of Increasing the PO quantity on the PO revision but allow the quantity increase. So, We used the automation script getPreviousValue() and getCurrentValue() functions in order to resolve this requirement.

Create Database Error Message on Database Config Application.

Object :         POLINE

Attribute:      ORDERQTY

Events:          Validate

Type:             Attribute Type Launch Point

Body:

Saturday, 15 August 2020

Conditional Lookup Functionality for List View Search using Automation Script isZombie() Method || IBM Maximo

Recently we had a requirement of conditional lookup for Maximo list view search. We have a custom column called sub-work type which is based on the value selected on the main work type attribute. This functionality on the application was working fine using table domain but it wasn't working on the list view in Maximo.

SO we developed a solution using conditional lookup automation script in Maximo list view search fields. First, we got the where clause of the current APP from memory in wclause variable, and then we got the work type i.e. CM or PM value using the split function. Then by using the zombie() method we set the work type value for a list where clause.

Object

WORKORDER

Type

ATTRIBUTE LAUNCH POINT (Jython)

Attribute

WOSUBTYPE

Name

WOSUBTYPE

Body

from psdi.common.context import UIContext

appName = mbo.getThisMboSet().getParentApp()

if appName in ('PLUSPWO','PLUSPWOCMP'):

#Get Where clause for list view search

    wclause = service.webclientsession().getCurrentApp().getResultsBean().getMboSet().getUserAndQbeWhere() 

 #Search worktype value of list view

    if mbo.isZombie():

         clause=wclause.split("worktype")[1].split("'")[1]

         listWhere="worktype='"+clause+"'"

Sunday, 31 May 2020

Retrieve Saved Password from System Properties in Jython | Maximo

from psdi.server import MXServer

if mbo.getString("ASSETNUM") == '10002':

    service.error("cust",MXServer.getMXServer().getProperty("mxe.db.password"))


Original Post: http://vietmaximo.blogspot.com/2020/07/display-password-stored-in-system.html 

Tuesday, 19 May 2020

How to use Maximo Logger in Jython Script to capture Logs of script | IBM Maximo

Define libraries

from psdi.util.logging import MXLoggerFactory

from psdi.util.logging import MXLogger


call logs

   
log = MXLoggerFactory.getLogger("maximo.application.AUTOSCRIPT")
scriptname="<script_name>"
log.info("******Entering Autoscript : " +scriptname +"******")






<Script body>



log.info("******Exiting Autoscript : " +scriptname +"******")

Sunday, 17 May 2020

mboSet() in Automation Script, getMboSet() vs getThisMboSet() | Maximo

Most of the time automation script creates an implicit variable "mbo". It represents the current record on which the script was triggered. 

let say we open one workorder: 123. in this case, our mbo is 123. 

what If we want to get the MboSet of this mbo. (like we are going back to the list tab :)
here you go. 

mboSet = mbo.getThisMboSet()

2. Most common way to call an mboset is using famous method , which is
mbo.getMboSet("PR")
where PR is the Relation Name already exists in database configuration from this record. 

3. or we can create at run time a new relation with WhereClause, like this:
 woSet = mbo.getMboSet("woSet ", "WORKORDER", "status = 'APPR' and siteid = 'BEDFORD'")

4th and last is get any MBO from the system, which is the least recommended if the things can be handled with first 3 methods.  
If the "mbo" implicit variable is not exists then you need this:
woSet = MXServer.getMXServer().getMboSet("WORKORDER", userInfo)


Invoke/Call a Publish Channel Conditionally - Automation Script | Maximo


Normally trigger point for the Publish channels is Event Listener, which is save/update any record. 

Question: Can we send the data using publish channel with a custom trigger point /condition ??

Answer: Yes you can. by using Maximo Automation Script. 
Below is the simple tricks to call a publish channel 

server = MXServer.getMXServer()
userInfo = mbo.getUserInfo()
whereClause = <CONDITION>
server.lookup("MIC").exportData("<Publish Channel Name>", "<External System Name>", whereClause, userInfo, 1000)
---------------------------------
Another example:
micSrv = MXServer.getMXServer().lookup("MIC")
server.lookup("MIC").exportData("MXPO", "LegecyApp", " ponum='"+vPONum+"' and revisionnum="+vREVNUM , micSrv.getNewUserInfo() , 1)


Note:

Mic is old service name for MIF, but still the same name


Sunday, 10 May 2020

Creation of Yes / No User Input Dialog Validation for Custom Status using Automation Script || IBM Maximo

Today we are going to show you the creation of user user input dialog box for the custom status field. We have a custom application which has the custom status field, it changes the status of work order tasks based on this custom status. The requirement came when there was no validation when the user changed the status. We will show you how created validation dialog box using automation script.


1. Go to Database Configuration and create a message for user input

      Message Group:  os_taskstatus

      Message Key:      os_taskstatus

      Value:                Do you really want to change the status?

      Buttons:              Yes, No


2. Create Automation Script:

      Launch Point:    Attribute

      Events:          Validate

      Object:               WOACTIVITY

      Attribute:            ZZOSACTIVITYSTATUS

      Script:                  Jython