Maximo Open Forum

 View Only

 PO Escalation not saving changes when Action executes Automation Script

  • Administration
  • Everything Maximo
Jared Schrag's profile image
Jared Schrag posted 06-29-2023 20:07

I've created an Escalation on the PO object that executes an Action that launch an Automation Script. This AutoScript modifies a couple of attributes on the PO and also creates two related MboSets on the fly and adds two new, child Objects (one a custom object and one is the DOCLINKS object). With these two related MboSets, the AutoScript calls MboSet.add() and then it fills in attributes on the newly added Mbos.

At the end of the AutoScript, it logs out: mbo.isModified(), mboSet1.count(), mboSet1.count() and the logging confirms that the mbo in the script (which is the PO object picked up by the Escalation) is modified and, also, mboSet1.count is 1 and mboSet2.count also indicates 1. These are the new Mbo objects, one in each set.

The AutoScript completes execution without error and the Escalation records no error. However, afterwards, I pull up the PO in the PO app and find that the attributes that should have been modified are still not modified and the two related MboSets never saved to the database any new records.

What could possibly explain the successful execution during the Escalation Action, but nothing actually saved to the database?

Allow me to clarify what I've noted above when I say "creates related MboSets on the fly". I mean that I called: set1 = mbo.getMboSet('$_DOCLINKS_$', 'DOCLINKS', '1 = 2'). Then, I call set1.add(). I'm expecting the automatic Save on the PO (by the Escalation) to cause all related MboSets in memory that are marked as modified to also get saved.

Here is a summary of the code in question:

# ...

# Create custom record KAES_POECOMSTATUS
pesSet = poMbo.getMboSet('$_PES_$', 'KAES_POECOMSTATUS', '1 = 2')
pesSet.reset()
pesMbo = pesSet.add(MboConstants.NOACCESSCHECK)
# ... set values on pesMbo

# Create DOCLINKS/DOCINFO attachment to PO
logger.debug('Creating DOCLINKS data...')
docLinksSet = mbo.getMboSet('$_DOCLINKS_$', 'DOCLINKS', '1 = 2')
docLinksSet.reset()
docLinksMbo = docLinksSet.add(MboConstants.NOACCESSCHECK)
docLinksMbo.setValue('URLTYPE', 'FILE')
docLinksMbo.setValue('URLNAME', outputFileName)
docLinksMbo.setValue('NEWURLNAME', outputFileName)
docLinksMbo.setValue('DOCTYPE', attachFolder)
docLinksMbo.setValue('ADDINFO', True)
docLinksMbo.setValue('DESCRIPTION', attachDesc)

# ...

logger.debug('mbo isModified: %s' % (str(mbo.isModified())))
s1 = mbo.getMboSet('$_DOCLINKS_$', 'DOCLINKS', '1 = 2')
s2 = mbo.getMboSet('$_PES_$', 'KAES_POECOMSTATUS', '1 = 2')
logger.debug('mboSet Count ($_DOCLINKS_$): %d' % (s1.count()))
logger.debug('mboSet Count ($_PES_$): %d' % (s2.count()))
# End of Script

And here is a snippet of the server logs for the last few logger statements (indicates there are modifications and new objects ready to save in memory):

29 Jun 2023 18:30:58:744 [DEBUG] getting logger
29 Jun 2023 18:30:58:744 [DEBUG] getting mbo
29 Jun 2023 18:30:58:744 [DEBUG] [K_EMAILPO_TOVENDOR:EMAILPO2VEND:POID 952610]    mbo isModified: True
29 Jun 2023 18:30:58:744 [DEBUG] getting mbo
29 Jun 2023 18:30:58:744 [DEBUG] getting mbo
29 Jun 2023 18:30:58:744 [DEBUG] getting logger
29 Jun 2023 18:30:58:744 [DEBUG] getting s1
29 Jun 2023 18:30:58:744 [DEBUG] [K_EMAILPO_TOVENDOR:EMAILPO2VEND:POID 952610]    mboSet Count ($_DOCLINKS_$): 1
29 Jun 2023 18:30:58:744 [DEBUG] getting logger
29 Jun 2023 18:30:58:744 [DEBUG] getting s2
29 Jun 2023 18:30:58:744 [DEBUG] [K_EMAILPO_TOVENDOR:EMAILPO2VEND:POID 952610]    mboSet Count ($_PES_$): 1
29 Jun 2023 18:30:58:744 [DEBUG] execution completed for cached compiled script K_EMAILPO_TOVENDOR for launch point EMAILPO2VEND
...
29 Jun 2023 18:30:58:744 [DEBUG] The total time taken to execute the K_EMAILPO_TOVENDOR script for the EMAILPO2VEND launch point is +4479 ms.
29 Jun 2023 18:30:58:744 [DEBUG] ScriptAction call ended for scriptName K_EMAILPO_TOVENDOR and launch point EMAILPO2VEND

Please let me know if I need to clarify my question.

Steven Shull's profile image
Steven Shull

You need to explicitly save when you have an action launch point automation script invoked via an escalation. I'm not sure how your poMbo is established and if it's identical to mbo (I think it is looking at your count at the end) but if you use something like MXServer.getMXServer().getMboSet(), then the set you open will be its own transaction. Assuming everything is a child of mbo you can call:

mbo.getThisMboSet().save()

And that will save any changes you made to that MBO and the child objects. 

Jared Schrag's profile image
Jared Schrag

@Steven Shull  thank you for your quick reply! The "poMbo" in the code snippet above is actually the variable in the function def in which I've passed 'mbo' (the automatic context python variable "mbo" in all AutoScripts) as a function parameter (I do apologize for the unclear snippet there). The reset of the code snippets are in the main script.

I intended that the automatic save of the PO by the Escalation to save all in-memory, related MboSets (which I've created two in my code). I wanted all of the changes to be in the same transaction so that if there is an interrupting error after one of the MboSet.add(), we don't have a half-saved transaction.

I actually have tried the 'mbo.getThisMboSet().save()' approach at the end of my script; however, that always results in a "BMXAA8229W - Record PO :  Site=xx PO=xx Revision=x has been updated by another user" error.

I suppose I'm failing to understand why an Action launch point executed in an Escalation exhibits this behavior.

Steven Shull's profile image
Steven Shull

Regarding needing to save, the out of the box Actions (like Set Value) are written to explicitly call a save. Action automation scripts do not automatically save because they can be used in places outside of escalation (such as a push button in an application) where we expect the developer to make the appropriate choice (should it save or should we make the user explicitly save).  

Regarding updated by another user error, there's not enough to identify the culprit here. I assume there is not some other background process updating the PO which means something about the save is triggering it. Assuming you're not retrieving the PO MBO another time in the script, I'd look to see if any other scripts are firing. For example, a launch point on the KAES_POECOMSTATUS object. If you have other scripts firing, make sure that if it retrieves PO it's doing it via mbo.getOwner() and not something like mbo.getMboSet("PO") since that will open a new set and cause the record updated by another user error. 

Sometimes it's helpful to turn SQL logging to INFO because in a scenario like this you will see the two updates that tried to execute and can see what fields were changed in each. That may make it easier to understand where it's coming from based on what was modified. 

Pavan Uppalanchu's profile image
Pavan Uppalanchu

@Steven Shull  I have the same question but in a different way. 

I have an escalation on INVENTORY and below action script asscoaited to escalation with below logic. 

mbo.setValue('MINLEVEL',29)
invvendorSet=mbo.getMboSet('INVVENDOR')
if not invvendorSet.isEmpty():
    invvendor=invvendorSet.moveFirst()
    while invvendor:
        invvendor.setValue("ATTRIBUTE",0)
        invvendor=invvendorSet.moveNext()

Does invvendor should be saved explicitly? 

Steven Shull's profile image
Steven Shull

@Pavan Uppalanchu Since it's a child of inventory, you should be able to save the inventory set and it should save any child sets that were modified as well. But you would need to call a save if this is an action launch point since your automation script is supposed to be handling any necessary logic.

Unrelated to the question, you don't need to check whether records exist if you plan to traverse the set. IE you can delete the line "if not invvendorSet.isEmpty():" entirely. If no records exist, when you get your first MBO it'll be null and skip the while loop.