Showing posts with label jython. Show all posts
Showing posts with label jython. Show all posts

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 

Monday, 25 January 2021

Elapsed Time in View Status Dialog - Jython | Maximo

Add an additional column in View History Dialog to see the time elapsed for each status. 

This is a modified version of the solution written by Bruno for the same topic. 

We will accomplish this task with an attribute in the status table and an object-level launch point script written in Jython. 


1. Add a column in PRSTATUS table,  Name: ELAPSEDTIME, Type: Duration.

2. Display this column into View History Dialog using the application designer of the PR application.

2. Write an Object Launch Point Script: Object: PRSTATUS , Save, Add, AfterSave. Copy below the body and paste it. 

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, 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()

Sunday, 29 November 2020

Refresh/Update Start Center for All Users in a specific Security Group | Maximo

 Create an automation script to delete the records from the respected table to refresh the start centers displayed on the user's screen

or delete the records from the tables using SQL.

Today we are going to make an automation script and attached it to a signature option on the toolbar. 

So that whenever the user clicks on this button on the security group application, all the respected records will be deleted, and the start center will try to create new records, which means our records will be updated. 


This:

1. Create an Action Launch Point Automation Script with a name like( STARTCENTER_REFRESH ).

Copy the below code in the script section, use jython as language. 

from psdi.server import MXServer

from psdi.mbo import MboConstants

from psdi.util.logging import MXLoggerFactory


logger = MXLoggerFactory.getLogger("maximo.maximodev")

logger.info("Entering MXD_RESETSC")


def deleteSc(objectName, where):

    scSet = MXServer.getMXServer().getMboSet(objectName, mbo.getUserInfo())

    scSet.setWhere(where)

    logger.debug("Deleting " + str(scSet.count()) + " rows from " + objectName)

    # disable logging of large fetch result set to avoid FetchResultLogLimit errors

    scSet.setLogLargFetchResultDisabled(True)

    scSet.deleteAll()

    scSet.save()

Saturday, 28 November 2020

Copy WF Memo to Status Memo in View History of Status dialog | Maximo

Copy the Memo from the MANUAL INPUT of the workflow dialog into Memo field of CHANGE STATUS in View History Dialog of any application. 

Both Memos are different , one is coming from wftransaction, and the other one is in the xxstatus table. 

We were trying to cross over the memo from Wftrancation to status table's memo. 

here is the solution we developed using automation script in jyton. 
In my example i am using PR object and PRSTATUS table.

1. Make a relationship from WFTRANSACTION to PR
RelationShip Name: PR
Child Object: PR
Where Clause: prid = :ownerid and :ownertable = 'PR'

1. Object Launch Point 
Object : WFTRANSACTION
Events: SAVE, Add, After Save
wftmemo = mbo.getString("memo")
if (wftmemo!=''):
    prset = mbo.getMboSet("pr")
    pr = prset.moveFirst()
    if pr is not None:
        prstatusset = pr.getMboSet("prstatus")
        prstatus = prstatusset.moveLast()
        prstatus.setValue("memo",wftmemo,2L)
        #prstatusset.save()

 

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") 

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

Enabling and Configuring your Maximo system to use the SAML web single sign-on (SSO) | IBM Maximo

Install the SAML ACS application.
Choose one of the following approaches:

Using the administrative console, install the app_server_root/installableApps/WebSphereSamlSP.ear file to your application server or cluster.

Install the SAML ACS application by using the python script.
    
Navigate to the app_server_root/bin directory.
    
Run the installSamlACS.py script.

wsadmin -f installSamlACS.py install <nodeName> <serverName>
 or
wsadmin -f installSamlACS.py install <clusterName>

Copy where node Name is the node name of the target application server, server Name is the server name of the target application server, and cluster Name is the name of the application server cluster.

Enable SAML

You can enable SAML by using either the wsadmin command utility or the administrative console.

 Enable SAML using the wsadmin command utility.

Start the WebSphere Application Server.

Start the wsadmin command utility from the app_server_root/bin directory by entering the command:
wsadmin -lang jython.

At the wsadmin prompt, enter the following command: AdminTask.addSAMLTAISSO('-enable true -acsUrl https://<hostname>:<sslport>/samlsps/<any URI pattern string>')

where host name is the host name of the system where WebSphere Application is installed and SSL port is the web server SSL port number (WC_defaulthost_secure).

 Save the configuration by entering the following command: AdminConfig.save().

Exit the wsadmin command utility by entering the following command: quit.
    
Restart the WebSphere Application Server.

 Enable SAML using the administrative console.
    
Log on to the WebSphere Application Server administrative console.
    
Click SecurityGlobal security.
    
Expand Web and SIP security and click Trust association.
    
Under the General Properties heading, select the Enable trust association check box and click Interceptors.
   
Click New and enter com.ibm.ws.security.web.saml.ACSTrustAssociationInterceptor in the Interceptor class name field.

Under Custom properties, fill in the following custom property information:

Name: sso_1.sp.acsUrl and
Value: https://<hostname>:<sslport>/samlsps/<any URI pattern string>
where host name is the host name of the system where WebSphere Application is installed and sslport is the web server SSL port number (WC_defaulthost_secure).

Note: 
If you need to have multiple, similar entry points for your SAML workflows, you can specify a wildcard value instead of a specific URI pattern string at the end of the URL specified as the value of this property.
Specifying a wildcard as part of the value of this property eliminates the need to separately configure each of the similar entry points.
Following are some examples of valid ways to include a wildcard as part of the value for this property:
https://<server>/<context_root>/ep1/path1/p*
https://<server>/<context_root>/ep1/path1/*
https://<server>/<context_root>/ep1/*


Warning: 


If you are using metadata to configure your SSO, wildcards cannot be used in the acsUrl definition.

Click New and enter the following custom property information:
Name: sso_1.sp.idMap and Value: idAssertion.
Click OK.

Go back to SecurityGlobal security and click Custom properties.

Click New and define the following custom property information under General properties:
Name: com.ibm.websphere.security.DeferTAItoSSO and
Value: com.ibm.ws.security.web.saml.ACSTrustAssociationInterceptor.

Warning:

The property com.ibm.websphere.security.DeferTAItoSSO,
was previously used in the default configuration of all installed servers.
Now it is only used as part of the SAML configuration. Therefore, even if this property already exists in your system configuration,
you must change its value to com.ibm.ws.security.web.saml.ACSTrustAssociationInterceptor.

Multiple values, separated with commas, cannot be specified for this property. It must be set to a single SAML

Click New and define the following custom property information under General properties:
Name: com.ibm.websphere.security.InvokeTAIbeforeSSO and
Value: com.ibm.ws.security.web.saml.ACSTrustAssociationInterceptor.
Click OK.


Restart WebSphere Application Server.

The SAML is now enabled for WebSphere Application Server.


For Reference Please visit: IBM Knowledge center 

https://www.ibm.com/support/knowledgecenter/SS7K4U_9.0.5/com.ibm.websphere.zseries.doc/ae/twbs_enablesamlsso.html 








Exception Handling in Jython | IBM Maximo

from psdi.util.logging import MXLoggerFactory
from psdi.util.logging import MXLogger


try:
       
    log = MXLoggerFactory.getLogger("maximo.application.AUTOSCRIPT")
    scriptname="<script name>"
    log.info("******Entering Autoscript : " +scriptname +"******")
       
   
    log.debug("[DEBUG] script "+scriptname+" <Message>")
   
    log.info("******Existing Autoscript : " +scriptname +"******")   

Exceptions Handling

except Exception, e:
    print >> sys.stderr, "[ERROR] script "+scriptname+" failed: ",e.message
    print >> sys.stdout, "[ERROR] script "+scriptname+" failed: ",e.message
    log.error("[ERROR] script "+scriptname+" failed: " +e.message)

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

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

Monday, 30 December 2019

Add Estimated Duration into Start Date to Caluclate Finish Date | IBM Maximo

Write and Attribute Launch point on Schedule Start Date on Workorder, 

Script will take 2 inputs: Schedule Start date and Estimated Duration.
Add duration into start date and save the final output in schedule finish date.

Object: Workorder
Attribute: SCHEDSTART, Event: Validate


Script:
from java.util import Calendar
appName = mbo.getThisMboSet().getParentApp()
if appName == 'PLUSPWO' and mbo.getString("sp")  =='01' and mbo.getString("spcontract") == '005' and mbo.getInt("istask")  == 0 and mbo.getInt("historyflag") == 0 and mbo.getString("woclass") == 'WORKORDER' :
    if not mbo.isNull('SCHEDSTART'):
        vSSD = mbo.getDate("SCHEDSTART")
     
        #estduration in minutes
        vEstDuration = mbo.getFloat("ESTDUR")*60
   
        cal=Calendar.getInstance()
        cal.setTime(vSSD)
        cal.add(Calendar.MINUTE, long(vEstDuration))
        vNewSFD =  cal.getTime()
        mbo.setValue("SCHEDFINISH",vNewSFD,2L )

Monday, 8 April 2019

Populate GL attribute in All Lines at ONCE from Header | IBM Maximo

Update all lines in Inventory Usage application from header level.

for instance in this example we are using a GL Debit account field on header level, and when we enter values in it; it will be copied into all lines.

To do this we will run a simple automation script using jython:

Attribute Launch Point:

Script: GLDEBIT_INVUSAGE
Langauge: jython

Launch Point:
Object: INVUSE
Attribute: CUXGLDEBIT
Event: Validate

Script Code:
lineSet= mbo.getMboSet('INVUSELINE')
line= lineSet.moveFirst()
while (line):
    line.setValue("GLDEBITACCT",mbo.getString("CUXGLDEBIT"))
    line = lineSet.moveNext()

Sunday, 17 March 2019

Rollup Cost from all Child lines into Parent as Total Cost | Maximo

Create a Object Launch Point


Object: ParentObject
Language: jython
Event:     Validate Application

Variables:
vSumLine    Rel_ChildObject.LINECOST*       
vtotalcost    TOTALCOST

Script:
if vSumLine is not None:
    vtotalcost = sum(vSumLine)
else:
    vtotalcost = 0.0