Row not Recognized as Updated using Sales Order Update Ext. Method Directive

OK, so I run into this from time to time, and I want to figure it out. When does a row register as updated / changed in a method directive? It seems that updated rows are not always properly recognized. Here is my example:

I create a simple updatable BAQ that allows updates to the ReqDate on the Sales Order Release. To get the update to work correctly, we have to include the OrderHed, OrderDtl, and OrderRel tables.


(We add a criteria on the OrderRel to limit our selection to open releases.)

We also have to include certain columns from each of these tables:

We select the ReqDate on the OrderRelease as updatable.

We can see that the SalesOrder UpdateExt Business Object is used.

We analyze and test the BAQ, and it works like a charm.


image

We create a Pre-Processing BPM on the SalesOrder.UpdateExt Method called TEST_OrderRel
image
(The other BPM has been disabled–didn’t want to delete it for this example.)

The new BPM includes an initial message letting us know that it triggered…

and displays the Order Release ReqDate value for the Updated and Unchanged Rows…
image
image

Next is a conditional that tests whether or not the OrderRel.ReqDate value has been changed…

And we have included a message for both True and False Conditions…


We save and enable the BPM, then return to our BAQ.

In the BAQ, we change the OrderRel_ReqDate on the first row from 10/16/18 to 12/31/18.

Pressing OK, highlights the changed row, and we can see that it now has the 12/31/18 date.
image

We press the Update button and get our first Message from the BPM indicating that it triggered successfully…

Note, however, that the Updated row value for our ReqDate is blank, while the Unchanged row is reporting the 12/31/18 date. Pressing OK to dismiss the first message, we see the Message after the conditional indicating that the False branch was taken…

The BMP is not recognizing that the data on that row was changed. Nonetheless, the update completes and when the BAQ is refreshed, the 12/31/18 date persists.

So what am I missing here? Shouldn’t the BPM recognize this row as being updated and changed?

UpdateExt is a funky beast. Out of curiosity, does Added rows display any data?

Chris,

Thanks for chiming in. If I am not mistaken, in most cases UpdateExt is the default and primary option for updatable BAQs. Learning that it is “funky” does not inspire confidence. Perhaps someone from Epicor will see this thread and can clarify.

In terms of the Added Row, no data shows up for that either…
image

I would assume that is the case as the BAQ does not allow for new rows.

What I meant is that it works differently than a normal Update. I dont think that it follows the same RowMod rules (i.e.only update if RowMod == “U”)

My assumption is that when you make a change in the updatable baq grid, it only marks the head as updated then passes it to UpdateExt which handles the whole TableSet.

If your assumption is true, that is totally unexpected. Looks like I will have to write some custom code so that I can compare the data from the Erp table with the data on the tt table in order to determine whether the row / column has been updated.

Thanks, again for your help.

You can also use a widget to invoke the BO and do a GetByID.

To be clear, even the header does not appear to show as modified. The following mod values show up after changing the date field on added, modified or unchanged rows:
image

I like the idea of invoking the GetByID. I’ll give that a try.

I’d be interested in hearing what you find out on this.

Service Connect also uses UpdateExt, and from my work with that and UBAQs I conclude that this method is built around minimal data transfer for the sheer number of things it’s meant to make possible. What that seems to mean in practice is that if a row is not being changed in any way it simply isn’t included in the tableset at all. If that is the case then it would kind of make sense that RowMod is ignored.

Not to confuse any further, but I remain puzzled by how the BPM side of things works for some of these cases, too. I have had conditionals respond differently depending ONLY on whether a widget is in line before them or not, even if the widget appears to do nothing related. I suspect the logic of the code resulting from BPM creation isn’t quite the logic the diagram would suggest in all cases.

Not very helpful, sorry, but mine is another voice added to your wish for someone from Epicor to clarify a bit!

@dhewi Along those same lines, I’ve run into confusion with expected row changes to find that other helper methods were actually handling certain things before the actual update, things like ChangeJobSeq, ChangePartNum . With that said - I would only expect that to be the case in the UI, not in an UpdateExt. Maybe UpdateExt calls some of those helpers in the PRE process, which is why you dont see the change - in some cases I’ve seen where internal calls to other BO methods are called, and they dont seem to hit the trace log.

Alright, I am back on this issue. I am exploring Chris’ recommendation to retrieve the row data using an Invoke BO Method widget to call a GetByID method. In this case, I try the OrderRelSearch.GetByID method from within the SalesOrder.UpdateExt method. When I configure the method, I use values from the OrderRelRow temporary table and add a variable to store the data set.

It all appears OK, until I attempt to validate the workflow design at which point I get a series of data type errors that need to be addressed.
image

I use the Convert.ToInt32() function, which appears to solve the problem and the BMP validates. When I attempt to enable the BPM, however, I get this server side error:

There is at least one compilation error.

UpdateExt.CommonTypes.cs(254,33): error CS0433: The type ‘OrderRelTable’ exists in both ‘Erp.Contracts.BO.OrderRelSearch, Version=10.1.600.0, Culture=neutral, PublicKeyToken=5d3fa3c7105d7992’ and ‘Erp.Contracts.BO.SalesOrder, Version=10.1.600.0, Culture=neutral, PublicKeyToken=5d3fa3c7105d7992’

UpdateExt.CommonTypes.cs(100,55): error CS0433: The type ‘OrderRelRow’ exists in both ‘Erp.Contracts.BO.OrderRelSearch, Version=10.1.600.0, Culture=neutral, PublicKeyToken=5d3fa3c7105d7992’ and ‘Erp.Contracts.BO.SalesOrder, Version=10.1.600.0, Culture=neutral, PublicKeyToken=5d3fa3c7105d7992’

This makes me think that I cannot use the OrderRelSearch.GetByID method within the SalesOrder.UpdateExt method. In this case, there does not appear to be another BO Method that will do the trick.

What am I missing?

Can you run a trace log?

Looks like an ambiguity issue - they have since solved this 10.2 using externs.

You could always hop over to code

foreach(var tor in ttOrderRel)
{
 var myOrderRel = Db.OrderRel.Where(r => r.Company == tor.Company && r.OrderNum == tor.OrderNum && r.OrderLine == tor.OrderLine && r.OrderRelNum == tor.OrderRelNum).FirstOrDefault();
if(myOrderRel != null)
{
  //you can look at the order rel record in the db
//or you can assign it to your var you already have setup and use the same widget logic
}
}

I see Rich is replying, he probably has a better solution

Hold on - this is complicated but not that mysterious.

UpdateExt processing:
UpdateExt (Update External) was created to allow records with partial data values to be accepted and processed. Clearly all the Key Fields for a record and all the Mandatory fields for a record are required and unlike Update, multiple different tables (and multiple different records) can be updated with a single call. All the records passed in to UpdateExt will cause an update to occur - while BPM may have the concept of Original Record and Updated record, UpdateExt itself does not.

Internally, UpdateExt acts like the UI Client - It find the first header record, gets the key(s) and then runs GetByID. If a record is returned, the values passed in to UpdateExt are used to update that record and then Update is called. If there is a record hierarchy - Header, Lines, Releases - and child data records were included on the call to UpdateExt, the data tree is walked and Update is called for each record “touched”.

If the GetByID does not return a record, UpdateExt calls GetNew for the header and then does the Update as above. If child records were included in the initial UpdateExt call, GetNew is called for each of those records found to be new and they are also processed as above.

As the UpdateExt logic calls the other Base Methods - GetByID, GetNew, Update - BPM on those methods will fire. In the case of calls to Update, the standard Client called pattern of an Original row and a Changed row will exist as UpdateExt is acting like a Client. There are several ways to leverage this behavior in a BPM on Update - one way is to set a BPMData variable in the UpdateExt BPM processing and then have a condition triggered by that value in the BPM on the Update method. Move your code trying to compare Original with Changed to the standard Update Method.

UBAQ Processing:
When a UBAQ is processing, it runs the UBAQ Framework. Each UBAQ is considered to be a Mini BO and on the Update Processing Sheet in the UBAQ Designer, you will see the “BPM Directive Configuration” button. When you click that, it opens a slimmed down version of the BPM Designer - already prepopulated with the Names of the Methods associated with THAT instance of the UBAQ. One of those Methods is Update and that is the Method that is called prior to the UBAQ framework calling UpdateExt. This is another possible location for your BPM Original to Changed logic (there is currently a bug where Added rows are not properly identified in this timing).

When the Mini BO Update logic of the UBAQ framework calls UpdateExt, it is only passing the data values Mapped in the “Query to Object Column Mapping” section. In this processing there is no concept of Original Record or Original Value - it is just the data to be updated by UpdateExt - one record per Updated row of the UBAQ Result set.

Wrap it up Rich -
Okay. As you can see, UBAQ processing is complicated but quite elegant. Each UBAQ has the possibility of BPM on the Methods called while processing the UBAQ. The UpdateExt method itself is also fairly elegant in that it is applying the standard UI style processing to the data it is given and each method called by UpdateExt goes through BPM - just like a client caller would. This provides you with numerous BPM Touch points - both before and after - while the UBAQ is processing.

7 Likes

Rich,

As always, thanks for responding. Though I do not always immediately understand the big picture, your thoroughness allows me to piece quite a bit of it together with some thought along with good old fashioned trial and error.

I did notice that only the updatable values from the BAQ were available in the UpdateExt–I now better understand why. I ran a quick test and I see that the other methods–GetByID, GetNew, etc.–are triggered when I send an update from by UBAQ. I also see the possibility in performing some of the BPM logic though configuring the BPM Directive in the BAQ–I have not explored that feature. So there is a lot for me to digest here and try. I will update this thread, once I figure it out.

Alright, here is my latest update:

Thank to Rich’s input, I was able to use the BPM Directive Configuration to help accomplish my objective. I added a preprocessing BPM on the Update method.

Within the context of this method, the field changes were detectable and I was able to use conditional widgets to set BAQ Data fields to pass to the subsequent methods–specifically the SalesOrder.UpdateExt method.

There is quite a bit going on in this BPM…

Nonetheless, it does appear to work…with one exception. I can make updates to any number of rows in my dashboard, and I confirm that the changes on each row are committed to the database. If I change the same row more than once without refreshing the dashboard, however, the changed row turns bright red and the tool tip indicates that the row has been modified by another user and cannot be updated–this is not possible as I am the only one using this Development environment.

My guess is that others have seen this issue before with updatable dashboards. Anyone have any suggestions as to how to resolve it?

Thanks!
Michael

Hi Michael,
Did you ever get an answer or determine the answer on this last question in this thread? It is a long and as yet unsatisfied cliffhanger otherwise. I’ve encountered this on UBAQs as well and would welcome a solution, like a ‘refresh after complete’ command.