Customization issues with Customer Shipment Entry

Ok, incoming wall of text.
BPM coding is one of my most favorite things in Epicor, simply because it’s extraordinarily powerful to be able to control server side behavior from a single location. It’s certainly not always the tool for every job, but it’s good to know how/when to use.

I created an In-Transaction Data Directive BPM on ShipDtl. Remember, data directives monitor table actions (read: updates, deletes, additions) and the “in-transaction” flavor means it get assessed before the action happens to the table.

The name is up to you as is the group, but keep in mind the scope. If you have multiple companies, you will want to be aware that this specificity will potentially affect other companies in this environment. Click the Design button to go into design mode.


My condition checks the value of the part num on the ttShipDtl record. “tt” stands for temp table, and is used throughout Epicor to store temporary data for transaction use. I don’t believe it’s the same thing as a SQL temp table.

In this example, I’ve also routed a “Show Message” node off of the False path of the conditional node to tell the user (me) that the condition was not met. I’d obviously remove this before going into production.

In my custom code block coming off of the True path from the conditional node, notice first that I have selected “Synchronously”. This is the default, but the other option is to run the code asynchronously. That means it will fire when the application pool decides it’s a good time to fire, but I don’t want that in this case.

Below is my code. I’ve commented the hell out of it in hopes that I could minimize the amount of text I would need to explain.

//This code will update the Pack Code on ShipHead.
//this uses a technique called LINQ (Language Integrated Query) to have SQL-like syntax in C#

//Define your tables that we will reference below
//Ice/Erp tables can look like this
//the first part is the type, the second is the variable name
Erp.Tables.ShipHead ShipHead; 

//BPM temp table rows can look like this. In this case, we are choosing the first or default row in the temp table, so this LINQ syntax is fine. 
var ShipDtlRow = ttShipDtl.FirstOrDefault();


//set a variables so we can go look up our data in the database for ShipHead to match this ShipDtl record
// I know pack num is an interger value, so below is an explicit conversion. 
int packNum = (int)ShipDtlRow.PackNum;

//now we are going to look for the ShipHead record that matches this ShipDtl pack num. Make sure to also search by company, like any SQL query. The Session object is good for this. 
//this will select, in this case, a single ShipHead record from the database
ShipHead = (from ShipHead_row in Db.ShipHead
where ShipHead_row.Company == Session.CompanyID
&& ShipHead_row.PackNum == packNum
select ShipHead_row).FirstOrDefault();

//if the record is not null, we will continue
if(ShipHead !=null)
{
	//now we will set the field on the ShipHead record
	//I don't have a package code in my system called WT, but I'll use what I have
	ShipHead.PkgCode = "Box1";
}

The practical use of this is that when I created a line on a pack, entered the Order/Line/Release info and saved, the Pack Code on the Header was updated.

Let me know if that helps.