I’m working on a BPM that sends out an email to all the individuals in a specific BU within our sales team when the Need By date changes in an order. I have no problem setting up the email to trigger when the method is performed. However, I run into problems when I try to specify which BU in the sales team to send the email to. The Need By date is in the order head, while the product group (where I determine the sales team BU) is in the order detail. As far as I know, I don’t have a way to have the BPM tell which BU to send the email to.
Has anyone created a BPM similar to this? Thank you in advance for any assistance.
First off, a couple of warnings about some things that can trip up your initial logic.
There is a NeedBy date on each of the tables: OrderHed, OrderDtl, and OrderRel.
The values in OrderRel will be blank if not explicitly set. This means they will use the need by of their related OrderDtl.
Similarly, the values in OrderDtl will be blank if not explicitly set. This means they will use the need by of their related OrderHed.
So if someone updates the NeedBy on a Order Line or Release, it would not reflect as a change in the OrderHed.NeedBy.
Secondly, if your basing the BU on the product group, there can be different ProdGrp’s specified on an order, as each line can have a different PG. In this case would you want the email to go out to all BU’s for each different PG in the order?
Assuming you’re aware of all the above, and just want to get the PG from the first line on the Order, you could use a Variable and a Set Variable widget to fetch that PG.
Create variable: PG
Set Variable/Argument widget to set PG with the following code
.Where( r =>r.Company == callContextClient.CurrentCompany && r.OrderNum == ttOrderHedRow.OrderNum)
.Select( r =>r.ProdCode).DefaultIfEmpty("").FirstOrDefault()
Now you have the ProdGrp in variable PG.
The reference to ttOrderHedRow.OrderNum in the above should actually be dsOrderHedRow.OrderNum
That was off the top of my head, so I probably have a typo on the convention for that reference. When you’re in the expression builder of the Set Variable widget, a pane on the left will give you access to the data passed to the BPM. Find the dataset, table and field for OrderNum and double click it. That will insert it into your code.
What BO and method are you using? SalesOrder.Update?
And what I described above will only get you the PrdGrp code. You still need to use that to get your list of peopl that need to be emailed. How do you plan to do that? More spceifcially, where are the users/email addresses for the BU, and how is that related to the PG?
Db.OrderDtl .Where( r =>r.Company == callContextClient.CurrentCompany && r.OrderNum == dsOrderHedRow.OrderNum) .Select( r =>r.ProdCode).DefaultIfEmpty("").FirstOrDefault()
The only difference was I needed dsOrderHedRow, not ttOrderHedRow. But for being off the top of your head, the rest of the code was abosolutely spot-on. Thank you so much for that!
In regards to this, I’m going to start by just entering each team member’s email manually in the Send Email part of the workflow. However, I eventually want to pull the email from the user/users making/splitting the sale.
At this point, test emails to myself are working properly. Thank you again for the code snippet!
If there is nothing already in place, I would do the following:
Create a UD code type of BU
Add a UD Code (of type BU) for each ProdGrp.
Make the UD Code the same as the ProdCode (for easier relating).
Set the LongDescription to be a list of email addresses for that BU. Use a semicolon to separate addresses, like: firstname.lastname@example.org; email@example.com; firstname.lastname@example.org;
You may have to play with whether or not a trailing semicoln causes issues. And don’t try to include the display names like: Alice Cooper<email@example.com>; Bob Seager<firstname.lastname@example.org>;
Then in your BPM, query the UD Codes like:
.Where( r =>r.Company == callContextClient.CurrentCompany
&& r.CodeType == 'BU' && r.CodeID == PG)
.Select( r =>r.LongDesc)
.DefaultIfEmpty("your email address to catch faults").FirstOrDefault()