I’ve seen various question on loops in ION Connect. Here is a solution I came up with for looping through elements of a BOD, making API calls, and updating the BOD with data. The core method of this process can be used for any looping operation that you need that can’t be done in Python. It’s not as clean as I would want, but maybe it will help others on their journey into the mixed blessings of ION.
The Need:
I have a business need where I have an incoming document, and I need to process an API call for each of the order lines in the document. I’m working in a Multi-Tenant environment, and I want to avoid any changes to the inbound MEC/IEC map for this document.
Some suggested solutions to this have been:
- Use the Splitter function in a Document Flow to make an API call for each element.
The biggest problem I have with this choice, is it makes different documents for each line, and would cause the order to be broken into several
Use an ION API call to an external service to update the BOD XML and return it
The issue with this one is most customers I’m doing work for in Multi-Tenant want no infrastructure to maintain at all, and I’ve yet to have one allow this kind of solution.
This might work well if I could setup a service to do this, I’ve tested this, but no one wants a server to host it.
Use a Mongoose Application to make the calls and transform
I’ve just be flat unable to figure this out in MT
Other people on my team have this working in ST, but MT has blocked some of the access they need to get it working
If someone has an example of doing this, please share the steps
Use a Workflow Loop to process the API call for each child line in the document
Loops are Only Available in Workflows
Why are loops only in Workflows? *Just wondering
I can only pass a structure, or single variables into or out of a Workflow
No way to update the Structure I’m passing in to pass back out
No way to update the BOD directly if a Structure was available as output
No direct way to update the BOD
I came up with a way to perform this task, even though I’ve yet to find a document from Infor explaining using Structures this way in a Workflow. Perhaps I’m missing one of the key documents on how to properly do a loop for an API call. This is a long read, and it’s not as clean as I would like, but it works. I’m sharing so that others will have a head start on their work, please share any ways you find to make this cleaner or easier!
Proof of Concept
In my test concept, I want to take a Process.SalesOrder BOD, make a sample API call, add information to the BOD, and pass it on for further processing. Due to some of the limitations listed above I’m going to use the SalesOrder=>SalesOrderHeader=>UserArea element to store the information I need. It can be moved to the Sales Order Line => User Area or another element with XSLT once completed. I will not show the XSLT transform in this example, as once the data is in the BOD, moving it around is simpler. *And there are several qualified people speaking on XSLT available. I will write records to the M3 system via an API during the example to show the success of the looping.
I’m going to start with a simple Document Flow. This Document Flow will read the document, send it to a Workflow, run a Python Script to translate the delimited information to the User Area XML, and then write the updated document.

The Workflow will have a structure for the information I want to use in my API calls, and a variable to pass the data back out. The variable name says JSON, but it’s not JSON, it’s just a delimited string in my example. The Structure must have a Header Level with a Detail Level to loop correctly.
Example Structure
Parameters for output
Workflow

My workflow is going to write some data to the database using an API call. You can use any API call to pull data or write to M3.
The key to this process is the Workflow Loop and the Structure. You will need two Parameters to access the children successfully in a loop. One will be the child number(LINE), and the count of all the children (COUNT).

The first step in the Loop is to set the Line # to 1 and get the count, in my case 3 records. The Integer variable (LINE) defaults to 0, so adding one on the first loop gives us an index of 1 for the first record.

Note the path to the count is the structure, not the BOD

In the next step in the Workflow, I’m getting the information I need from the child element and storing it in variables to use further in the Workflow for the API call. The make it work magic is the LINE INDEX in the Path.

To get the index, you have to change it from (ALL) to (Parameter:LINE) in the Structure when you select the path.

Then, it used the LINE parameter as an Index to which Element in the Structure you are accessing.
Next in the Workflow, I make the API call. I’m just adding a field for this proof. Use the Parameters you set in the previous steps to make the API call.

For the output, I’m only storing the Response of the API call to a Parameter for passing back out. You can store anything you get as a result, within the limits provide by the Path parameters in the result.

The last step of the Loop is to update the Parameter I’m using to pass the data out. Since I can not use structures, the only method I could come up with was building a delimited string of information. In this case, I used a pipe for new record, a tilde for field delimiting, and a colon for the Key / Value pair. This is a messy solution, and would require using characters not normally found in the output data. I considered writing every record via an API call and the retrieving it later, but this is just a proof.

As you can see, I’m appending the previous value of the parameter (It’s NOT JSON) to return all records.
Formula: [JSONCustomData]&"Line:"&[LINE]&"~Style:"&[Style]&"~Description:"&[DESC]&"~ReturnCode:"&[CustomCodeHolder]&"~|"
In this case, each “record” contains the Line #, the Style, the Description, and the Return Code from the API call.
I have a concern there may be a limit on string parameters length using this method, test all use cases! Use another method or API to store if string is too long.
Then, the last step of the loop is to check if we have more records to process.

When this is complete. It returns to the Document Flow. Because I had mapped the Output Parameter to the UserArea=>Property, the element now contains the string data. This is in the Header area, because I only get a string (or strings) back from the Workflow, but no way to assign them to different elements. So, one string returned to the User Area. I set the name and use the same name in Python to find it. You could standardize this and use it for multiple documents.

I want to transform this to usable XML for my next processes to use, so I forward this Document to a Python script to transform it.

The script parses the string and turns it into UserArea =>Property elements per line. (Somewhere I’m picking up the Name Space ns0)

This output is now consistent with the BOD Schema, and more importantly can use the element attributes to map any of the data to lines in the BOD with XSLT. I will not be showing mapping of the data to different lines since you can map it anywhere you need in the BOD using the Mapper tool, or XSLT.
The results of the API call show the data in M3, see via ExportMI.


You can write a Python Script to use the delimiters or format you need, or you may download my Proof Script here: http://billywilloughby.com/downloads/Python/UserArea%20Delimiter%20Convert.py

I know this was a long post, and it’s not the kind of clean solution I like, but it gets me through the issue I have with the limits placed upon me for this task. Please reply if you find this helpful and let me know of any ways to make this better. I hope this helps,
Thanks;
Billy