BPM Needed

I am new to BPM’s in Epicor and I am not a strong C# developer. I am looking for some assistance, preferably using the widgets to get this done. I have to create a BPM that needs to check each line in Sales Order Entry that corresponds to the received line in Receipt Entry that contains the same part number. Now the only way the part number matters is if in Sales Order Entry it is marked with a back order checkbox. As shown in the screenshot.

Once the corresponding items are found, an email needs to be generated to a specific email address with an email that states, “Part #_________ has been received and is a backorder part” I need to combine parts that are on the same Pack ID into one email.

A low code solution to this would be, roughly, as follows (apologies for typos, but not for basically punting on #7):

  1. Build a BAQ that takes your receipt pack as an input parameter. Have it look through your orders using whatever logic you need to collect relevant info.

  2. Create a function library for Receipts. Add ICE.BO.DynamicQuery to the list of services on the library. Enable it for your company. Save.

  3. Create a function that also takes your pack as an input. No outputs. Save.

  4. Add a Invoke BO Method widget. Use it to Invoke Ice.DynamicQuery.GetQueryExecutionParametersByID. On the Parameters, input your BAQ from earlier and create a new QueryExecutionTableSet

  5. Add a Set Field Widget. Set field to ExecutionParameter.ParameterValue of all rows (because we only have 1 input parameter, there should only be 1 row). The specified expression should be the input string from step#3. You’re passing this to the BAQ.

  6. Add a Invoke BO Method widget. Use it to Invoke Ice.DynamicQuery.ExecuteByID. plug in your BAQ again, the QueryExecTS from before, and create a DataSet for the output.

  7. At this point, I’d call my email library that would take the dataset from above and format it as a nice HTML email and fire it off to whomever it may concern, whose address I’d have pulled into the BAQ from step 1. I’d search this site for examples of that. You are not likely to get something that’s both good and code free, as the canned email widgets are extremely basic and inflexible and not something I’d let customers or other external stakeholders see.

  8. Open BPM Method Directive. Find Erp.BO.Receipt.UpdateMaster. Create a new Post-Processing directive.

  9. Add an Invoke Function widget to your directive. Point it to your library and function and add your packNum as the input. That’s it. One widget.

Note that you can do this entirely in your BPM, but personally I don’t like having the breakable stuff spread around the system. It’s much better to have it all in one place.

1 Like

Max,

Do you want to try through c#?. It is almost 50 lines of code but will get you through with a simple Post-Processing at Receipt.Update using a custom code widget. This code will send email as well.

Here is the snapshot:

and here is the code:

var _RcvHed = (from Row in ttRcvHead where Row.Company == Session.CompanyID && Row.Received select Row).FirstOrDefault(); //Looks for the Received field in RcvHead table. This helps to loop all the lines in the PS.
if (_RcvHed != null)
{
var emailBody = new StringBuilder(); //helps accumulate all the details in single email body.
foreach (var result in
from ttRcvDtl_Row in ttRcvDtl
join ttOrderRel_Row in Db.OrderRel on new
{ ttRcvDtl_Row.Company, ttRcvDtl_Row.OrderNum, ttRcvDtl_Row.OrderLine, ttRcvDtl_Row.OrderRelNum } equals new { ttOrderRel_Row.Company, ttOrderRel_Row.OrderNum, ttOrderRel_Row.OrderLine, ttOrderRel_Row.OrderRelNum }
where ttRcvDtl_Row.Received
select new { ttRcvDtl_Row, ttOrderRel_Row })
{
var checkBackOrdered = Db.OrderDtl
.Where(ttOrderDtl_Row =>
ttOrderDtl_Row.Company == result.ttOrderRel_Row.Company &&
ttOrderDtl_Row.OrderNum == result.ttOrderRel_Row.OrderNum &&
ttOrderDtl_Row.OrderLine == result.ttOrderRel_Row.OrderLine
// && ttOrderDtl_Row.BackOrder (Your backorder field condition goes here, I don’t have that field…)
)
.FirstOrDefault();
if (checkBackOrdered != null)
{
var OrderDetails = $“{result.ttOrderRel_Row.OrderNum},{result.ttOrderRel_Row.OrderLine},{result.ttOrderRel_Row.OrderRelNum}”;
// Accumulate information in the email body, if there are multiple lines
emailBody.AppendLine($“PartNum:{result.ttRcvDtl_Row.PartNum} of PS:{result.ttRcvDtl_Row.PackSlip} has been received for Order:{OrderDetails} and is a back-ordered part”);
}
}
// Check if there is any information to send
if (emailBody.Length > 0)
{
// Send a single email with all the accumulated information
var body = emailBody.ToString();
var mailer = this.GetMailer(async: true);
var message = new Ice.Mail.SmtpMail();
message.SetSubject(“New Parts have been received”);
message.SetFrom(“Epicor.Admin@yourcompanydomain”);
message.SetTo(“SendTO@yourcompanydomain”);
message.SetBody(body);
mailer.Send(message);
}
}

You can even set CC and BCC if needed.

1 Like

Thank you so much for the examples here. I greatly appreciate both! I will keep this documented so that in the future, I can fully utilize what you have provided.

I did end up solving the issue with a combination of code and widgets. So again, thank you!!

Best Regards,
Max Delgado