BPM Custom Code to update OrderDtl rows on upates to OrderHed or OrderDtl

I am writing a custom code BPM to set the OrderDtl.DocUnitPrice based off of criteria on the OrderHed and OrderDtl Rows. I have a pre-processing BPM on MasterUpdate like this:

var lines = ds.OrderDtl.Where(l=>l.OrderNum == this.iOrderNum && l.RowMod=="U");
var order = Db.OrderHed.Where(p => p.OrderNum == this.iOrderNum).FirstOrDefault();

foreach(var line in lines){
    // Look up stuff of line and order to set line.DocUnitPrice
}

This works fine if the row being saved is an orderdtl row as it looks at the orderhed row from the db call.
When I change the OrderHed row and want to update the child OrderDtl rows, how can I do so in a way that still triggers things like tax calculations on those rows? Will getting the rows through db, updating and validating them work? I kinda thought that would circumvent the update logic.

Use the Business Objects like the client does. Do a trace of some sample transactions and it will show you the datasets and methods called.

1 Like

Yes, please.

You can use the Db context object to do reads, simple writes, and occasionally with proper
knowledge, some fixes.

Don’t use it for normal operations to add or edit data. Learn the business objects, and how to trace
properly.

That sounds reasonable. So, would this workflow be correct?

image

This is the shell of what I ended up with using BOs.

this.CallService<Erp.Contracts.SalesOrderSvcContract>(bo =>
{
  var ds2 = bo.GetByID(this.iOrderNum);

  foreach(var line in ds2.OrderDtl){  
    // Logic to calculate and set line.DocUnitPrice and line.RowMod
  }

  bo.Update(ref ds2); 
});

Interesting, I use CallService in functions, and ServiceRenderer in BPMs.
I didn’t know CallService was available in BPMs.

The reverse isn’t true, unless you make your own context, which is frowned upon and
not guaranteed to work in the future.

This is a pattern that I saw in one of our CSG customizations.

There are some great coders in Professional Services who, like many others, will code to get the job done quickly and not really consider future changes in the framework. For others out there…
Schitts Creek Comedy GIF by CBC

In general, if you haven’t beaten your head into your keyboard yet, playing with pricing (and discounts) on the order (and especially the quote) can be frustrating. There are numerous reasons why Epicor logic will recalculate things and you have to take those into account when trying to force pricing or discounts to do something that they don’t normally do. The list of things to consider seems to be never-ending. Here’s a few of the pitfalls you will want to look out for:

  • Even though you lock pricing, if a part number changes it will still update the price
  • There are often several fields that “look the same” but are used by different parts of Epicor. i.e. UnitPrice, DocUnitPrice, and even others that exist on the form/temp-table that don’t make it into the actual DB like DspDocUnitPrice and so on. When forcing a change, be sure to turn on user tracing (with track changes only selected) and then run through the UI and manually do what you want to do in code. Study the changed values. That will help you find all the “extra/duplicates” of the same field that also need to be updated.
  • As order detail pricing/discounts are updated, so too are the order header summaries. If you’re not careful, you can get them out of sync and the only way to recover is to re-write the order. Not hitting all the fields will also cause things to get out of sync. You’ll know if it happens, trust me.
  • Ship To updates will cause a re-calc.
  • Date changes will cause a re-calc.
  • Qty changes will cause a re-calc.
  • The printed reports (like acknowledgement and quote form) are even another layer to consider and make sure display properly. This is another way not having all the fields updated will showup in a bad way.

Great summary, I have issue also with lock pricing changing when part number changes. We added a bpm to log the old price into a user field just to monitor/manage accidental price changes. Even tho the price is locked.