BPM to Update OrderDtl from OrderRel


I’m working on a BPM where it will update the OrderDtl record when a OrderRel record changes on specified fields. When the BPM fires, of course there is nothing in the ttOrderDtl table, so I’m wondering how I can make this change so that when the data is done saving the form will have the updated information on the OrderDtl?

Which method are you trying to put the BPM against? ttOrderDtl should have values in it.

If it can’t be done with a Method Directive, then try a data directive and update the OrderDtl table when you make the change in the OrderRel. I believe the next method called when you perform a save on the sales order is the GetByID so the data should be retrieved from the database and update the form. A trace should show you the execution order, if your not using it try out the trace differ tool.

Hope that helps.

I’m catching it in MasterUpdate or Update, doesn’t matter which. If all you edit is the OrderRel part, there doesn’t seem to be any records sent to the ttOrderDtl table.

@Doug.C What were the specific fields?

When the Make or BuildToOrder is changed, we are updating a UD field in OrderDtl. This change has to be reflected on the UI form when it is saved. A DD BPM will not work for this reason.

In Post-Processing of MaterUpdate, update OrderDtl table. and use dsHolder.Attach to refresh the data in UI. Sample code.

/* Reload the entire record and replace the dataset */
			var svc = Ice.Assemblies.ServiceRenderer.GetService<Erp.Contracts.SalesOrderSvcContract>(Db);

So do this in a code block? If I update the OrderDtl table, so I have to use a BO to update it?

The other trick is to do this as a STANDARD DATA directive triggered on the OrderRel table. In the data directive you write code that updates the OrderDtl table. This is an oldschool approach and does work. BUT it does have its drawbacks as well. for example, you should probably trigger the Standard directive with an In-Trans directive. in the in-trans, make sure that the data that would be updated in OrderDtl has actually changed. Otherwise, this update will run EVERY TIME the OrderRel record is updated (including when it is shipped).
There are multiple examples of such code on this website. But it will look something like this… this will read the Modified orderDtl row, and then looks up the matching OrderDtl row where you modify it.

foreach (var oRel in ttOrderRel.Where(x => x.RowMod != "")) {

    using(var txScope = IceContext.CreateDefaultTransactionScope()) {
        //looks for OrderRel records that dont match UD12 and fixes them.

        dbODtl = Db.OrderDtl.With(LockHint.UpdLock).Where(r =>
            r.Company == oRel.Company &&
            r.OrderNum == oRel.OrderNum &&
            r.OrderDtl == oRel.OrderLine).FirstOrDefault();

        if (dbODtl != null) {
            obODtl.myfield = oRel.MyField_C; //set all your fields here

I tried something in our test instance. I don’t know if this is an “approved” way, or a dangerous way and that it should never be done…

In my pre-processing BPM, I used the Fill Table by Query block to copy over the OrderDtl line from Db.OrderDtl into ttOrderDtl changing my field and the RowMod to “U”. I then was able to process the update. I don’t like this method primarily because it would not be forward compatible if new fields were added to the table either by customization or by upgrade…

From @timshuwy and @Hally I was able to get a solution that works now and moving forward.


best way in my opinion is to invoke OrderDtl Update method on your BPM triggering event at OrderRel, using the txScope code to do so will bypass B.O. basic script