Maximo Open Forum

 View Only
  • 1.  Parent/Child Work Order creation via integration

    Posted 4 days ago

    Hello,

    I am currently working on the integration between MPOWER (as an external system) and IBM Maximo. One of the integration scenarios involves group connections (GL), where a single request (REGNUM) from MPOWER represents a group that contains multiple sub-connections. In Maximo, this is expected to be reflected as one parent Work Order with multiple child Work Orders. From a business perspective, a GL represents a single grouped request containing one parent and multiple child elements, and ideally this should be handled as a single payload.

    In Maximo, we are using the object structures MXWO (Definition of Work Order) and MXWOHIER (Work Order Hierarchy Definition) for integrations with external systems related to Work Orders. I have tested in multiple ways via Postman to create both the parent Work Order and its child Work Orders within a single payload, but in all cases only the parent Work Order is created and the children are not. However, when I create the GL Work Order (parent) first, then retrieve the WONUM as the identifier, and in a second step create the child Work Orders by specifying the parent WONUM, this approach works correctly and the children are properly linked. 

    Despite this, this approach becomes quite complex and inefficient for large volumes (hundreds of child records per GL).

    I would appreciate your guidance on this:

    • Is there a recommended way in Maximo to handle parent-child Work Order creation in a single request or batch?
    • Is MXWOHIER expected to support this scenario, and if so, are we missing a specific configuration or payload structure?
    • From your experience, what is the best practice for handling large hierarchical Work Order creation in integrations?

    Below, I am sending the payload that creates only the parent wo:

    {
      "spi:siteid": "XXX",
      "spi:orgid": "ORGXXX",
      "spi:worktype": "MPOWER",
      "spi:status": "WAPPR",
      "spi:regnum": "GLTEST1001",
      "spi:extgroupnum": "GLTEST1001",
      "spi:description": "GROUP GLTEST1001",
      "spi:firstname": "Test",
      "spi:lastname": "User",
      "spi:fathername": "Demo",
      "spi:mobilenumber": "0690000000",
      "spi:address": "Test Address",
      "spi:office": "Office",
      "spi:zone": "Zone-1",
      "spi:category": "Residential",
      "spi:requestedload": "15kw",
      "spi:phase": "1",
      "spi:voltage": "220v",
      "spi:registeredon": "2026-03-30",
      "spi:connectiontype": "TU",
      "spi:cabin": "Cabin-01",
      "spi:feeder": "FDR-01",
      "spi:substation": "SS-01",
      "spi:metertype": "Digital",
      "spi:supervisor": "MXOSUSER",

      "spi:workorder": [
        {
          "spi:siteid": "XXX",
          "spi:orgid": "ORGXXX",
          "spi:worktype": "MPOWER",
          "spi:status": "WAPPR",
          "spi:regnum": "GLTEST1001-1",
          "spi:extgroupnum": "GLTEST1001",
          "spi:description": "CHILD 1",
          "spi:supervisor": "MXOSUSER"
        },
        {
          "spi:siteid": "XXX",
          "spi:orgid": "ORGXXX",
          "spi:worktype": "MPOWER",
          "spi:status": "WAPPR",
          "spi:regnum": "GLTEST1001-2",
          "spi:extgroupnum": "GLTEST1001",
          "spi:description": "CHILD 2",
          "spi:supervisor": "MXOSUSER"
        }
      ]
    }

    As seen below, the work order is created without the children:

    Thanks!


    #Customizations
    #Integrations
    #MaximoApplicationSuite

    ------------------------------
    Raziela Avdylaj
    InfoSoft Business Solutions
    ------------------------------


  • 2.  RE: Parent/Child Work Order creation via integration

    Posted 13 hours ago

    Hey Raziela, great write-up and you've clearly done solid groundwork already - the two-step approach working but being impractical at scale is a classic Maximo integration puzzle. Let me break down exactly what's happening and give you a few paths forward.

    First, what's actually going wrong with your current payload

    The root cause is a chicken-and-egg problem that's fundamental to how Maximo's integration framework processes hierarchical work orders. When you POST to MXWO, Maximo generates the parent WONUM at save time using its internal autonumber sequence. The child work orders, to be properly linked, need that WONUM in their spi:parent field - but that value doesn't exist yet at the time your payload is being parsed. So Maximo either silently drops the children or ignores the nested spi:workorder array entirely because it can't resolve the hierarchy relationship at the point of object construction.

    The nested spi:workorder array structure you're using is also the wrong relationship path for MXWO. MXWO's object structure doesn't define WORKORDER as a child of WORKORDER - it's essentially a flat structure. MXWOHIER does define the hierarchy relationship, but even there, the children need a resolvable spi:parent value at parse time, which brings you back to the same wall.

     - Automation Script with Object Launch Point on WORKORDER (recommended for your scenario)

    This is the cleanest solution for your use case, especially with hundreds of children per GL. Instead of fighting the framework's two-pass limitation, you let the parent get created normally and then handle child creation programmatically in a script that fires within the same transaction.

    In Maximo, go to Automation Scripts → Create → Script with Object Launch Point, set the object to WORKORDER, and the event to After Save. This script fires whenever a WORKORDER is saved - including when created via integration through MXWO - and by that point the parent WONUM is already assigned and fully available to your script logic.

    Add a condition so the script only fires for MPOWER-originated GL work orders and not every single WO save across the entire system - something like checking that EXTGROUPNUM is not null, or a dedicated flag field you set in the inbound payload.

    For obtaining the child WO set inside the script, the correct approach is to use mbo.getMboSet() with a dynamic relationship rather than going through MXServer. The reason this matters: an MboSet obtained via MXServer runs in its own independent transaction context, requires a separate explicit save() call, and critically - if the parent transaction rolls back for any reason, those children will not roll back with it, leaving you with orphaned records and inconsistent data. Using mbo.getMboSet() instead keeps everything within the same transaction boundary automatically, no separate save needed.

    A Jython example of what this looks like:

    from psdi.mbo import MboConstants
    import json
     
    # mbo is the saved parent WORKORDER - WONUM is already assigned at this point
    parentWonum = mbo.getString("WONUM")
    siteid      = mbo.getString("SITEID")
    orgid       = mbo.getString("ORGID")
    extGroupNum = mbo.getString("EXTGROUPNUM")
     
    # Child definitions passed via a custom CLOB field in the inbound payload
    childDataJson = mbo.getString("CHILDPAYLOAD")
    if not childDataJson:
        return
     
    children = json.loads(childDataJson)
     
    # Correct approach - dynamic relationship through the parent mbo,
    # shares the same transaction, no explicit save() required or desired
    #childWoSet = mbo.getMboSet("<WORKORDER>", "parent = :wonum and siteid = :siteid")
    childWoSet = mbo.getMboSet("WOCHILDREN")
     
    try:
        for child in children:
            newWo = childWoSet.add(MboConstants.NOACCESSCHECK)
            newWo.setValue("SITEID", siteid)
            newWo.setValue("ORGID", orgid)
            newWo.setValue("PARENT", parentWonum)  # now fully resolved
            newWo.setValue("WORKTYPE", child.get("worktype", "MPOWER"))
            newWo.setValue("DESCRIPTION", child.get("description"))
            newWo.setValue("REGNUM", child.get("regnum"))
            newWo.setValue("EXTGROUPNUM", extGroupNum)
            newWo.setValue("STATUS", "WAPPR", MboConstants.NOACCESSCHECK)
        # Children commit together with the parent - no separate save() call
    finally:
        childWoSet.close()



    ------------------------------
    Prashant Bavane
    Principal Architect
    ------------------------------