Maximo Open Forum

  • 1.  Cannot retrieve data from Interface Table, looking for solution

    Posted 03-17-2025 11:47

    x_mxinvoice database configuration setup:

    -          Object: x_mxinvoice

    -          Service: Mic (MICSERVICE)

    x_billing database configuration setup:

    -          Object: x_billing

    -          Service: CUSTAPP (Custom Application Service

    After an invoice is approved, Maximo automatically adds records into the Interface Table called X_MXINCVOICE.

    I created an automation script with an object launch point (object: invoice, executes when invoice is update, after save) where I am trying to copy data from the approved invoice into a custom table named x_billing and data from the newly added records in x_mxinvoice.

    The script only retrieves data from the approved invoice but does not retrieve any data from x_mxinvoice.

    I have also tried using a different automation script with an object launch point (object x_mxinvoice, executes when a new x_mxinvoice record is added into x_mxinvoice, after save or after commit) to get the data after a new record is added into x_mxinvoice table and still nothing is retrieved.

    Using both methods, I can still not retrieve any record from x_mxinvoice. Even though, when I run my query in sql server to see if there are records in x_mxinvoice, the newly added records are in the table.

    Its like the scripts cannot access data from x_mxinvoice after the invoice is approved because the scripts are executing before maximo creates and adds records into x_mxinvoice.

    Do you know what the issue might be? If so, what would be a possible solution? Below is both automation scripts (NOTE, both are not active at the same time. I tested both individually)

    automation script with an object launch point (object: invoice, executes when invoice is update, after save):

    from psdi.server import MXServer
    from psdi.mbo import MboConstants
     
    mxServer = MXServer.getMXServer()
    userInfo = mbo.getUserInfo()
     
    siteid = mbo.getString("SITEID")
    status = mbo.getString("STATUS")
     
    if siteid == <SITEIDGOESHERE> and status == 'APPR':
        invoice = mbo
        
        mxinvoiceSet = mxServer.getMboSet("X_MXINVOICE", userInfo)
        mxinvoiceSet.setWhere("SITEID = '{}' AND INVOICENUM = '{}'".format(siteid, mbo.getString("INVOICENUM")))
        mxinvoiceSet.reset()
        mxinvoiceMbo = mxinvoiceSet.getMbo(0)
        
        billingSet = mxServer.getMboSet("X_BILLING", userInfo)
        billingSet.setWhere("SITEID = '{}' AND INVOICENUM = '{}'".format(siteid, mbo.getString("INVOICENUM")))
        billingSet.reset()
        
        newbillingMbo = billingSet.add(MboConstants.NOACCESSCHECK)
        newbillingMbo.setValue("APPROVALNUM", invoice.getString("APPROVALNUM"), MboConstants.NOACCESSCHECK)
        newbillingMbo.setValue("BASETOTALCOST", invoice.getDouble("BASETOTALCOST"), MboConstants.NOACCESSCHECK)
        newbillingMbo.setValue("CHANGEBY", invoice.getString("CHANGEBY"), MboConstants.NOACCESSCHECK)
        newbillingMbo.setValue("CHANGEDATE", invoice.getDate("CHANGEDATE"), MboConstants.NOACCESSCHECK)
        newbillingMbo.setValue("DESCRIPTION", invoice.getString("DESCRIPTION"), MboConstants.NOACCESSCHECK)
        newbillingMbo.setValue("DOCUMENTTYPE", invoice.getString("DOCUMENTTYPE"), MboConstants.NOACCESSCHECK)
        newbillingMbo.setValue("DUEDATE", invoice.getDate("DUEDATE"), MboConstants.NOACCESSCHECK)
        newbillingMbo.setValue("ENTERBY", invoice.getString("ENTERBY"), MboConstants.NOACCESSCHECK)
        newbillingMbo.setValue("ENTERDATE", invoice.getDate("ENTERDATE"), MboConstants.NOACCESSCHECK)
        newbillingMbo.setValue("GLPOSTDATE", invoice.getDate("GLPOSTDATE"), MboConstants.NOACCESSCHECK)
        newbillingMbo.setValue("HASLD", invoice.getInt("HASLD"), MboConstants.NOACCESSCHECK)
        newbillingMbo.setValue("HISTORYFLAG", invoice.getInt("HISTORYFLAG"), MboConstants.NOACCESSCHECK)
        newbillingMbo.setValue("INVOICEDATE", invoice.getDate("INVOICEDATE"), MboConstants.NOACCESSCHECK)
        newbillingMbo.setValue("INVOICEID", invoice.getInt("INVOICEID"), MboConstants.NOACCESSCHECK)
        newbillingMbo.setValue("INVOICENUM", invoice.getString("INVOICENUM"), MboConstants.NOACCESSCHECK)
        newbillingMbo.setValue("PAYMENTTERMS", invoice.getString("PAYMENTTERMS"), MboConstants.NOACCESSCHECK)
        newbillingMbo.setValue("PONUM", invoice.getString("PONUM"), MboConstants.NOACCESSCHECK)
        newbillingMbo.setValue("POSITEID", invoice.getString("POSITEID"), MboConstants.NOACCESSCHECK)
        newbillingMbo.setValue("SITEID", invoice.getString("SITEID"), MboConstants.NOACCESSCHECK)
        newbillingMbo.setValue("STATUS", invoice.getString("STATUS"), MboConstants.NOACCESSCHECK)
        newbillingMbo.setValue("STATUSDATE", invoice.getDate("STATUSDATE"), MboConstants.NOACCESSCHECK)
        newbillingMbo.setValue("TOTALCOST", invoice.getDouble("TOTALCOST"), MboConstants.NOACCESSCHECK)
        newbillingMbo.setValue("VENDOR", invoice.getString("VENDOR"), MboConstants.NOACCESSCHECK)
        newbillingMbo.setValue("VENDORINVOICENUM", invoice.getString("VENDORINVOICENUM"), MboConstants.NOACCESSCHECK)
        newbillingMbo.setValue("X_BILLINGNUMBER", invoice.getString("INVOICENUM"), MboConstants.NOACCESSCHECK)
        
        # test to see if x_mxinvoice record exists
        if mxinvoiceMbo is not None:
            newbillingMbo.setValue("TRANSID", 1, MboConstants.NOACCESSCHECK)
        else:
            newbillingMbo.setValue("TRANSID", 0, MboConstants.NOACCESSCHECK)
            
        billingSet.save(MboConstants.NOACCESSCHECK)
    automation script with an object launch point (object x_mxinvoice, executes when a new x_mxinvoice record is added into x_mxinvoice, after save or after commit)
    from psdi.server import MXServer
    from psdi.mbo import MboConstants
     
    mxServer = MXServer.getMXServer()
    userInfo = mbo.getUserInfo()
     
    siteid = mbo.getString("SITEID")
     
    if siteid == <SITEIDGOESHERE>:
        
        billingSet = mxServer.getMboSet("X_BILLING", userInfo)
        billingSet.setWhere("SITEID = '{}' AND INVOICENUM = '{}'".format(siteid, mbo.getString("INVOICENUM")))
        billingSet.reset()
        billing = billingSet.getMbo(0)
        
        if billing is None:
            newbillingMbo = billingSet.add(MboConstants.NOACCESSCHECK)
            newbillingMbo.setValue("INVOICENUM", mbo.getString("INVOICENUM"), MboConstants.NOACCESSCHECK)
            newbillingMbo.setValue("PONUM", mbo.getString("PONUM"), MboConstants.NOACCESSCHECK)
            newbillingMbo.setValue("X_BILLINGNUMBER", mbo.getString("INVOICENUM"), MboConstants.NOACCESSCHECK)
        
     
        billingSet.save(MboConstants.NOACCESSCHECK)

    #Administration
    #Customizations
    #MaximoApplicationSuite

    ------------------------------
    Johann Wunder
    King & George LLC
    ------------------------------


  • 2.  RE: Cannot retrieve data from Interface Table, looking for solution

    Posted 03-17-2025 21:06

    Outbound messages are sent via publish channels. Publish channels are triggered during the save of the object but it writes to a JMS (or Kafka) queue that then later gets processed to send to the endpoint (HTTP, file, IFACE table, etc.) defined on the publish channel. You won't have the message available in the IFACE table until after it's processed. These are typically via sequential queue that gets processed as a cron task. And any errors that occur can block the queue for extended periods of time.

    IFACE tables are populated via SQL insert statements rather than MBOs so it won't trigger automation script events.

    I'm not understanding what you're trying to accomplish exactly here to help propose a recommended solution. Is X_BILLING another IFACETABLE? It looks like the only thing you are setting based on X_MXINVOICE is you're setting TRANSID on X_BILLING to 1 or 0 based on whether you have existing messages in the IFACE table. Beyond the technical challenges, you need to be careful because IFACE tables will be recreated when schemas change and none of your records will exist in the IFACE table when it is recreated. That means Monday invoice 1001 could find a record in the X_MXINVOICE table and Tuesday after the IFACE table is recreated invoice 1001 could not have a record in the X_MXINVOICE table. That could lead to undesired behavior. 

    I'd consider tracking something on the invoice record if you're only trying to track whether an invoice has been sent. 



    ------------------------------
    Steven Shull
    IBM
    ------------------------------



  • 3.  RE: Cannot retrieve data from Interface Table, looking for solution

    Posted 03-17-2025 23:55

    Hello Steven, I just want to be clear that this is not in production, I am just playing around and doing some testing/research with X_MXINVOICE and X_BILLING.

    In the case of my scripts above, X_MXINVOICE is an empty table, I am using a "Test" invoice to see if I was able get data from the newly added record in X_MXINVOICE after the "Test" invoice is approved. I always clear X_MXINVOICE, X_BILLING, and reopen/unapprove the "Test Invoice so I can approve it again.

    I was just setting TRANSID in X_BILLING to 1 or 0 to see if I was able to get the newly added record in X_MXINVOICE that Maximo creates after I approve the "Test" Invoice. 

    I noticed that when X_MXINVOICE table was empty, I wasn't getting anything from X_MXINVOICE (I was only able to get data from the invoice table) after approving the "Test" Invoice because the automation script with the launch point was executing before Maximo Automatically adds the new entries into X_MXINVOICE. (I guess this is where the sequential queue comes into play)

    I also noticed that if I didn't clear X_MXINVOICE and approved a different test invoice ("Test1" invoice) I was able to get data from X_MXINVOICE when adding a new entry into X_BILLING, but it was using the X_MXINVOICE record that was added after approving "Test" Invoice, not "Test1" Invoice.

    What I am trying to accomplish is this:

    After the user approves an Invoice

    Maximo automatically adds records into X_MXINVOICE (these newly added records all have the same TRANSID, identifying that these records belong in the same approved invoice transaction)

    What I need is that once the user approves an Invoice, and the new records are added into X_MXINVOICE, I also need to add one record into X_BILLING 

    1. using information from the approved invoice:

        newbillingMbo = billingSet.add(MboConstants.NOACCESSCHECK)
        newbillingMbo.setValue("APPROVALNUM", <FromApprovedInvoice>.getString("APPROVALNUM"), MboConstants.NOACCESSCHECK)
        newbillingMbo.setValue("BASETOTALCOST", <FromApprovedInvoice>.getDouble("BASETOTALCOST"), MboConstants.NOACCESSCHECK)
        newbillingMbo.setValue("CHANGEBY", <FromApprovedInvoice>.getString("CHANGEBY"), MboConstants.NOACCESSCHECK)
        newbillingMbo.setValue("CHANGEDATE", <FromApprovedInvoice>.getDate("CHANGEDATE"), MboConstants.NOACCESSCHECK)
        newbillingMbo.setValue("DESCRIPTION", <FromApprovedInvoice>.getString("DESCRIPTION"), MboConstants.NOACCESSCHECK)
        newbillingMbo.setValue("DOCUMENTTYPE", <FromApprovedInvoice>.getString("DOCUMENTTYPE"), MboConstants.NOACCESSCHECK)
        newbillingMbo.setValue("DUEDATE", <FromApprovedInvoice>.getDate("DUEDATE"), MboConstants.NOACCESSCHECK)
        newbillingMbo.setValue("ENTERBY", <FromApprovedInvoice>.getString("ENTERBY"), MboConstants.NOACCESSCHECK)
        newbillingMbo.setValue("ENTERDATE", <FromApprovedInvoice>.getDate("ENTERDATE"), MboConstants.NOACCESSCHECK)
        newbillingMbo.setValue("GLPOSTDATE", <FromApprovedInvoice>.getDate("GLPOSTDATE"), MboConstants.NOACCESSCHECK)
        newbillingMbo.setValue("HASLD", <FromApprovedInvoice>.getInt("HASLD"), MboConstants.NOACCESSCHECK)
        newbillingMbo.setValue("HISTORYFLAG", <FromApprovedInvoice>.getInt("HISTORYFLAG"), MboConstants.NOACCESSCHECK)
        newbillingMbo.setValue("INVOICEDATE", <FromApprovedInvoice>.getDate("INVOICEDATE"), MboConstants.NOACCESSCHECK)
        newbillingMbo.setValue("INVOICEID", <FromApprovedInvoice>.getInt("INVOICEID"), MboConstants.NOACCESSCHECK)
        newbillingMbo.setValue("INVOICENUM", <FromApprovedInvoice>.getString("INVOICENUM"), MboConstants.NOACCESSCHECK)
        newbillingMbo.setValue("PAYMENTTERMS", <FromApprovedInvoice>.getString("PAYMENTTERMS"), MboConstants.NOACCESSCHECK)
        newbillingMbo.setValue("PONUM", <FromApprovedInvoice>.getString("PONUM"), MboConstants.NOACCESSCHECK)
        newbillingMbo.setValue("POSITEID", <FromApprovedInvoice>.getString("POSITEID"), MboConstants.NOACCESSCHECK)
        newbillingMbo.setValue("SITEID", <FromApprovedInvoice>.getString("SITEID"), MboConstants.NOACCESSCHECK)
        newbillingMbo.setValue("STATUS", <FromApprovedInvoice>.getString("STATUS"), MboConstants.NOACCESSCHECK)
        newbillingMbo.setValue("STATUSDATE", <FromApprovedInvoice>.getDate("STATUSDATE"), MboConstants.NOACCESSCHECK)
        newbillingMbo.setValue("TOTALCOST", <FromApprovedInvoice>.getDouble("TOTALCOST"), MboConstants.NOACCESSCHECK)
        newbillingMbo.setValue("VENDOR", <FromApprovedInvoice>.getString("VENDOR"), MboConstants.NOACCESSCHECK)
        newbillingMbo.setValue("VENDORINVOICENUM", <FromApprovedInvoice>.getString("VENDORINVOICENUM"), MboConstants.NOACCESSCHECK)
        newbillingMbo.setValue("X_BILLINGNUMBER", <FromApprovedInvoice>.getString("INVOICENUM"), MboConstants.NOACCESSCHECK)

    2. and using information, the TRANSID, from one of the newly added records in X_MXINVOICE associated with the approved invoice.

        newbillingMbo.setValue("TRANSID", <FromOneOfTheNewAddedRecordsInX_MXINVOICE>.getInt("TRANSID"), MboConstants.NOACCESSCHECK)



    ------------------------------
    Johann Wunder
    King & George LLC
    ------------------------------



  • 4.  RE: Cannot retrieve data from Interface Table, looking for solution

    Posted 03-18-2025 00:53
    Hello Steven, Thank you for your response.
     
    I am just testing X_MXINVOICE and X_BILLING at the moment.
    X_MXINVOICE and X_BILLING are empty tables. I use two "test" invoices "TEST" and "TEST1".
    I set TRANSID in X_BILLING to 1 or 0 to identify if I am able to get the new record that has been added into X_MXINVOICE after approving one of the test invoices.
     
    What I am trying to accomplish is this:
     
    After the user approves an invoice, Maximo automatically adds record(s) into X_MXINVOICE associated with the approved invoice, these record(s) all have the same TRANSID - identifier that lets us know that these newly added record(s) are associated with the recently approved invoice.
     
    I also need Maximo to add one record into X_BILLING using information from the approved invoice and from the new record in X_MXINVOICE associated with the approved invoice
     
    from the approved invoice I need the following:
     
        newbillingMbo.setValue("APPROVALNUM", invoice.getString("APPROVALNUM"), MboConstants.NOACCESSCHECK)
        newbillingMbo.setValue("BASETOTALCOST", invoice.getDouble("BASETOTALCOST"), MboConstants.NOACCESSCHECK)
        newbillingMbo.setValue("CHANGEBY", invoice.getString("CHANGEBY"), MboConstants.NOACCESSCHECK)
        newbillingMbo.setValue("CHANGEDATE", invoice.getDate("CHANGEDATE"), MboConstants.NOACCESSCHECK)
        newbillingMbo.setValue("DESCRIPTION", invoice.getString("DESCRIPTION"), MboConstants.NOACCESSCHECK)
        newbillingMbo.setValue("DOCUMENTTYPE", invoice.getString("DOCUMENTTYPE"), MboConstants.NOACCESSCHECK)
        newbillingMbo.setValue("DUEDATE", invoice.getDate("DUEDATE"), MboConstants.NOACCESSCHECK)
        newbillingMbo.setValue("ENTERBY", invoice.getString("ENTERBY"), MboConstants.NOACCESSCHECK)
        newbillingMbo.setValue("ENTERDATE", invoice.getDate("ENTERDATE"), MboConstants.NOACCESSCHECK)
        newbillingMbo.setValue("GLPOSTDATE", invoice.getDate("GLPOSTDATE"), MboConstants.NOACCESSCHECK)
        newbillingMbo.setValue("HASLD", invoice.getInt("HASLD"), MboConstants.NOACCESSCHECK)
        newbillingMbo.setValue("HISTORYFLAG", invoice.getInt("HISTORYFLAG"), MboConstants.NOACCESSCHECK)
        newbillingMbo.setValue("INVOICEDATE", invoice.getDate("INVOICEDATE"), MboConstants.NOACCESSCHECK)
        newbillingMbo.setValue("INVOICEID", invoice.getInt("INVOICEID"), MboConstants.NOACCESSCHECK)
        newbillingMbo.setValue("INVOICENUM", invoice.getString("INVOICENUM"), MboConstants.NOACCESSCHECK)
        newbillingMbo.setValue("PAYMENTTERMS", invoice.getString("PAYMENTTERMS"), MboConstants.NOACCESSCHECK)
        newbillingMbo.setValue("PONUM", invoice.getString("PONUM"), MboConstants.NOACCESSCHECK)
        newbillingMbo.setValue("POSITEID", invoice.getString("POSITEID"), MboConstants.NOACCESSCHECK)
        newbillingMbo.setValue("SITEID", invoice.getString("SITEID"), MboConstants.NOACCESSCHECK)
        newbillingMbo.setValue("STATUS", invoice.getString("STATUS"), MboConstants.NOACCESSCHECK)
        newbillingMbo.setValue("STATUSDATE", invoice.getDate("STATUSDATE"), MboConstants.NOACCESSCHECK)
        newbillingMbo.setValue("TOTALCOST", invoice.getDouble("TOTALCOST"), MboConstants.NOACCESSCHECK)
        newbillingMbo.setValue("VENDOR", invoice.getString("VENDOR"), MboConstants.NOACCESSCHECK)
        newbillingMbo.setValue("VENDORINVOICENUM", invoice.getString("VENDORINVOICENUM"), MboConstants.NOACCESSCHECK)
        newbillingMbo.setValue("X_BILLINGNUMBER", invoice.getString("INVOICENUM"), MboConstants.NOACCESSCHECK)
     
    from one of the new added records in X_MXINVOICE associated with the approved invoice, i need the TRANSID associated with these X_MXINVOICE records to set the new entry in X_BILLING with the same TRANSID:
     
        newbillingMbo.setValue("TRANSID", mxinvoiceMbo.getInt("TRANSID"), MboConstants.NOACCESSCHECK)
     
     
    The idea here is to make sure the new X_BILLING entry and the new X_MXINVOICE entries all have the same transid since they are all created and added into thier tables when an invoice is approved.
     
     
    My initial approach was to use an automation script with an object launch point (OBJECT: INVOICE, EVENT: Save, when Invoice MBO is updated, AFTER COMMIT)
     
    from psdi.server import MXServer
    from psdi.mbo import MboConstants
     
    mxServer = MXServer.getMXServer()
    userInfo = mbo.getUserInfo()
     
    siteid = mbo.getString("SITEID")
    status = mbo.getString("STATUS")
     
    if siteid == 'CK005' and status == 'APPR':
        
        invoice = mbo
        
        billingSet = mxServer.getMboSet("X_BILLING", userInfo)
        billingSet.reset()
        
        newbillingMbo = billingSet.add(MboConstants.NOACCESSCHECK)
        
        newbillingMbo.setValue("APPROVALNUM", invoice.getString("APPROVALNUM"), MboConstants.NOACCESSCHECK)
        newbillingMbo.setValue("BASETOTALCOST", invoice.getDouble("BASETOTALCOST"), MboConstants.NOACCESSCHECK)
        newbillingMbo.setValue("CHANGEBY", invoice.getString("CHANGEBY"), MboConstants.NOACCESSCHECK)
        newbillingMbo.setValue("CHANGEDATE", invoice.getDate("CHANGEDATE"), MboConstants.NOACCESSCHECK)
        newbillingMbo.setValue("DESCRIPTION", invoice.getString("DESCRIPTION"), MboConstants.NOACCESSCHECK)
        newbillingMbo.setValue("DOCUMENTTYPE", invoice.getString("DOCUMENTTYPE"), MboConstants.NOACCESSCHECK)
        newbillingMbo.setValue("DUEDATE", invoice.getDate("DUEDATE"), MboConstants.NOACCESSCHECK)
        newbillingMbo.setValue("ENTERBY", invoice.getString("ENTERBY"), MboConstants.NOACCESSCHECK)
        newbillingMbo.setValue("ENTERDATE", invoice.getDate("ENTERDATE"), MboConstants.NOACCESSCHECK)
        newbillingMbo.setValue("GLPOSTDATE", invoice.getDate("GLPOSTDATE"), MboConstants.NOACCESSCHECK)
        newbillingMbo.setValue("HASLD", invoice.getInt("HASLD"), MboConstants.NOACCESSCHECK)
        newbillingMbo.setValue("HISTORYFLAG", invoice.getInt("HISTORYFLAG"), MboConstants.NOACCESSCHECK)
        newbillingMbo.setValue("INVOICEDATE", invoice.getDate("INVOICEDATE"), MboConstants.NOACCESSCHECK)
        newbillingMbo.setValue("INVOICEID", invoice.getInt("INVOICEID"), MboConstants.NOACCESSCHECK)
        newbillingMbo.setValue("INVOICENUM", invoice.getString("INVOICENUM"), MboConstants.NOACCESSCHECK)
        newbillingMbo.setValue("PAYMENTTERMS", invoice.getString("PAYMENTTERMS"), MboConstants.NOACCESSCHECK)
        newbillingMbo.setValue("PONUM", invoice.getString("PONUM"), MboConstants.NOACCESSCHECK)
        newbillingMbo.setValue("POSITEID", invoice.getString("POSITEID"), MboConstants.NOACCESSCHECK)
        newbillingMbo.setValue("SITEID", invoice.getString("SITEID"), MboConstants.NOACCESSCHECK)
        newbillingMbo.setValue("STATUS", invoice.getString("STATUS"), MboConstants.NOACCESSCHECK)
        newbillingMbo.setValue("STATUSDATE", invoice.getDate("STATUSDATE"), MboConstants.NOACCESSCHECK)
        newbillingMbo.setValue("TOTALCOST", invoice.getDouble("TOTALCOST"), MboConstants.NOACCESSCHECK)
        newbillingMbo.setValue("VENDOR", invoice.getString("VENDOR"), MboConstants.NOACCESSCHECK)
        newbillingMbo.setValue("VENDORINVOICENUM", invoice.getString("VENDORINVOICENUM"), MboConstants.NOACCESSCHECK)
        newbillingMbo.setValue("X_BILLINGNUMBER", invoice.getString("INVOICENUM"), MboConstants.NOACCESSCHECK)
        
        
        mxinvoiceSet = mxServer.getMboSet("X_MXINVOICE", userInfo)
        mxinvoiceSet.setWhere("SITEID = '{}' AND INVOICENUM = '{}' AND STATUSDATE = '{}'".format(siteid, mbo.getString("INVOICENUM"), mbo.getDate("STATUSDATE"))
        mxinvoiceSet.reset()
        mxinvoiceMbo = mxinvoiceSet.getMbo(0)
        
        newbillingMbo.setValue("TRANSID", mxinvoiceMbo.getInt("TRANSID"), MboConstants.NOACCESSCHECK)
        
        
        billingSet.save(MboConstants.NOACCESSCHECK)
     
     
    looking at your response and from my testing, I am not getting any records in X_MXINVOICE becuase the script is executing before maximo adds the new records into X_MXINOVICE. (I guess this is the queue you mentioned).
    Becuase of this i also tried to use similar automation script with an object launch point (object: x_mxinvoice, executes when a new x_mxinvoice record is added into x_mxinvoice, after save or after commit)
    from psdi.server import MXServer
    from psdi.mbo import MboConstants
     
    mxServer = MXServer.getMXServer()
    userInfo = mbo.getUserInfo()
     
    siteid = mbo.getString("SITEID")
     
    if siteid == <SITEIDGOESHERE>:
        
        billingSet = mxServer.getMboSet("X_BILLING", userInfo)
        billingSet.reset()
        
        newbillingMbo = billingSet.add(MboConstants.NOACCESSCHECK)
        newbillingMbo.setValue("TRANSID", mbo.getInt("TRANSID"), MboConstants.NOACCESSCHECK)
     
        invoiceSet = mxServer.getMboSet("X_MXINVOICE", userInfo)
        invoiceSet.setWhere("SITEID = '{}' AND INVOICENUM = '{}' AND STATUSDATE = '{}'".format(siteid, mbo.getString("INVOICENUM"), mbo.getDate("STATUSDATE"))
        invoiceSet.reset()
        invoice = invoiceSet.getMbo(0)
        
        newbillingMbo.setValue("APPROVALNUM", invoice.getString("APPROVALNUM"), MboConstants.NOACCESSCHECK)
        newbillingMbo.setValue("BASETOTALCOST", invoice.getDouble("BASETOTALCOST"), MboConstants.NOACCESSCHECK)
        newbillingMbo.setValue("CHANGEBY", invoice.getString("CHANGEBY"), MboConstants.NOACCESSCHECK)
        newbillingMbo.setValue("CHANGEDATE", invoice.getDate("CHANGEDATE"), MboConstants.NOACCESSCHECK)
        newbillingMbo.setValue("DESCRIPTION", invoice.getString("DESCRIPTION"), MboConstants.NOACCESSCHECK)
        newbillingMbo.setValue("DOCUMENTTYPE", invoice.getString("DOCUMENTTYPE"), MboConstants.NOACCESSCHECK)
        newbillingMbo.setValue("DUEDATE", invoice.getDate("DUEDATE"), MboConstants.NOACCESSCHECK)
        newbillingMbo.setValue("ENTERBY", invoice.getString("ENTERBY"), MboConstants.NOACCESSCHECK)
        newbillingMbo.setValue("ENTERDATE", invoice.getDate("ENTERDATE"), MboConstants.NOACCESSCHECK)
        newbillingMbo.setValue("GLPOSTDATE", invoice.getDate("GLPOSTDATE"), MboConstants.NOACCESSCHECK)
        newbillingMbo.setValue("HASLD", invoice.getInt("HASLD"), MboConstants.NOACCESSCHECK)
        newbillingMbo.setValue("HISTORYFLAG", invoice.getInt("HISTORYFLAG"), MboConstants.NOACCESSCHECK)
        newbillingMbo.setValue("INVOICEDATE", invoice.getDate("INVOICEDATE"), MboConstants.NOACCESSCHECK)
        newbillingMbo.setValue("INVOICEID", invoice.getInt("INVOICEID"), MboConstants.NOACCESSCHECK)
        newbillingMbo.setValue("INVOICENUM", invoice.getString("INVOICENUM"), MboConstants.NOACCESSCHECK)
        newbillingMbo.setValue("PAYMENTTERMS", invoice.getString("PAYMENTTERMS"), MboConstants.NOACCESSCHECK)
        newbillingMbo.setValue("PONUM", invoice.getString("PONUM"), MboConstants.NOACCESSCHECK)
        newbillingMbo.setValue("POSITEID", invoice.getString("POSITEID"), MboConstants.NOACCESSCHECK)
        newbillingMbo.setValue("SITEID", invoice.getString("SITEID"), MboConstants.NOACCESSCHECK)
        newbillingMbo.setValue("STATUS", invoice.getString("STATUS"), MboConstants.NOACCESSCHECK)
        newbillingMbo.setValue("STATUSDATE", invoice.getDate("STATUSDATE"), MboConstants.NOACCESSCHECK)
        newbillingMbo.setValue("TOTALCOST", invoice.getDouble("TOTALCOST"), MboConstants.NOACCESSCHECK)
        newbillingMbo.setValue("VENDOR", invoice.getString("VENDOR"), MboConstants.NOACCESSCHECK)
        newbillingMbo.setValue("VENDORINVOICENUM", invoice.getString("VENDORINVOICENUM"), MboConstants.NOACCESSCHECK)
        newbillingMbo.setValue("X_BILLINGNUMBER", invoice.getString("INVOICENUM"), MboConstants.NOACCESSCHECK)
     
        billingSet.save(MboConstants.NOACCESSCHECK)
    but this wouldnt work either. so what would be my best approach to get data from both the approved invoice and x_mxinvoice entrys after the user approves an invoice. would i need a script for integration using publish channel? instead of a script with object launch point?


    ------------------------------
    Johann Wunder
    King & George LLC
    ------------------------------



  • 5.  RE: Cannot retrieve data from Interface Table, looking for solution

    Posted 03-18-2025 08:35

    I don't need to know all the details around it but help me understand at a high level the purpose of the X_BILLING object. Every attribute you are setting appears to be coming from the invoice or in the case of the TRANSID, X_MXINVOICE. That makes the entire object seem redundant. IE what do you NOT have in X_MXINVOICE (since that can contain all the attributes from invoice you need along with containing the TRANSID you need) that you need in X_BILLING?

    You can't use an escalation on the IFACE table X_MXINVOICE because there is no unique ID on the table.

    You could write a cron task automation script that looks for records that exist in X_MXINVOICE but don't exist in X_BILLING but again, if these are both IFACE tables, it's possible for them to be recreated and all messages get lost. 

    You can't create an async job (think our change status in background functionality) because you have no way of knowing when the outbound message will be published to the IFACE table. This is normally a sequential queue that gets processed via a cron task. If there are any errors in a sequential queue, nothing will get written to the IFACE table until the error is handled (either fixed and reprocessed or deleted). Your message could be written to the IFACE table in 30 seconds, 30 minutes, 30 hours, 30 days, etc. And it could technically never be written if someone deleted it from the queue for some reason.

    The easiest path is trying to make the entry in X_MXINVOICE work without the X_BILLING object entirely. You could try and add logic in the publish channel processing to insert the X_BILLING record but there has to be something unique about the X_BILLING object that we need to capture and I'm not understanding what it is. If it depends on live invoice data from when the transaction was saved, that's not a guarantee when the publish channel fires because again, it could be any amount of time between the save and when it gets processed from the queue. Which gets back to your best bet is the X_MXINVOICE object exclusively. 



    ------------------------------
    Steven Shull
    IBM
    ------------------------------



  • 6.  RE: Cannot retrieve data from Interface Table, looking for solution

    Posted 03-18-2025 13:14
    Edited by Johann Wunder 03-18-2025 13:16
    Hello Steven,
     
    We have created a custom application named BILLING, where X_BILLING is the main object.
     
    After approving an invoice, we need to create a copy of the approved invoice as an X_BILLING MBO in the BILLING application. The user will then have the option to approve or exclude that X_BILLING MBO for payment.
     
    If approved, the X_BILLING record will be sent to the financial system.
     
    X_BILLING holds information about the approved invoice.
    X_MXINVOICE holds information about the approved invoice and its invoice lines.
     
    We need the TRANSID from X_MXINVOICE records in the X_BILLING record so that we can identify the related records in X_MXINVOICE.
     
    The X_BILLING record must have the same TRANSID as the associated X_MXINVOICE records. This ensures that when a user approves an X_BILLING record in the BILLING application, we can retrieve all X_MXINVOICE records that share that TRANSID.
     
     
     
    STEPS and EXAMPLE:
     
    1. user approves invoice
     
    2.1 one entry is added into X_BILLING (this X_BILLING record holds information from the approved invoice, TRANSID = 1)
     
    2.2 one or more entries, depending on how many lines the invoice has, is added into X_MXINVOICE (These X_MXINVOICE records holds information from the approved invoice, and each entry holds information from one individual line of the approved invoice, for all of these records TRANSID = 1)
     
    3. user will go into BILLING application to mark X_BILLING records as APPROVE or EXCLUDE to determine whether we send that record to the financial system for payment. If approved, we use the TRANSID in X_BILLING to find the records in X_MXINVOICE that have the same TRANSID.
    in this example the x_billing record marked with APPROVE has transid = 1 so we need all x_mxinvoice records that have transid = 1



    ------------------------------
    Johann Wunder
    King & George LLC
    ------------------------------