Customization issues with Customer Shipment Entry

Haha well, that sounds accurate. Can you try putting this BPM on that method so that it doesn’t get overwritten?

1 Like

I tried but unfortunately it doesn’t work unless it’s on the base process of GetOrderRelInfo… I understand that you shouldn’t mess with the base processing for most methods, but in this context do you think it’s fine?

Definitely don’t do that. My understanding is that a base processing directive will replace the standard logic that the method performs. This can result in major data issues, so I can’t recommend doing this.

Let’s get back to what you’re trying to do. Are you’re just setting a qty right now, correct?

No I’m setting the PkgCode to “wt” for now. I do aim to add more set fields on this, but I need to actually get it working on post/pre processing first…

My condition-

My setfield when true-
image

This is on Pre-Processing of CustShip.GetOrderRelInfo correct?
Can you change your set field action to “all rows” instead of changed row?

That is correct. I tried it on both pre and post processing.

I changed both condition and set field to “all rows” instead of changed row and that didn’t work. I also tried just the set field to “all rows” but that didn’t work either.

You know, we had a similar issue with a ShipHead UD field being stubborn to set as we wanted it to be in a Method. Like you, we tried both Pre or Post methods but it wouldn’t work for us.

We had to move it to a In-Trans Data Directive

1 Like

How did you end up monitoring ShipDtl and then updating ShipHead on a data directive built on ShipDtl? Did you end up using a custom code block? I’m trying to see if it’s possible with the “SetByQuery” node, but I’ve never used that.

Our situation was comparing a field on the ShipHead and setting the UD on the ShipHead accordingly so not an exact match to his situation.

Looping through the ShipDtl records via code could work. As a non-Coder I usually try with a BAQ first myself as I know queries better than C#. Also have you thought of a data directive on ShipDtl table instead.

I think you’d have to build it on ShipDtl if you wanted to check the record at the time of it changing, but I’m trying to help Caleb think of a way to update that field on ShipHead. If it were me, I’d write the code to do this, but I doubt Caleb wants to maintain/debug some custom code if he’s not familiar with C#.

It might be the only way at this point, unfortunately.

Yea after looking at it, it seems like data directives can only change the fields of the table that you’re using, so I wouldn’t be able to change the ShipHead.PkgCode field while using a condition on the ShipDtl table…

I’m not familiar with C# at all really… But coding is something I find ‘fun’ actually. Do you think this would get too complicated for a beginner or is it possible for me to do it? I think if I found a proper example of this then I could just play around with the code but I don’t think there’s any examples of this situation out there

edit: I’m guessing it would be an in-transaction BPM with a condition on the PartNum field just like before, but instead of a Set Field it would be the Execute Custom Code and that would be setting the ShipHead fields some how

edit2: If I’m correct in my above edit, do you know the syntax for other tables in the custom code screen? It keeps telling me ShipHead doesn’t exist in the current context - which makes sense.

I’m working on getting you an example, hang tight! There’s some technique to this :slight_smile:

1 Like

Oh wow, thanks Aaron! I’ll sit tight then :slight_smile:

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.

4 Likes

I was going to jump in too with a code example. I’m playing catch up with forum posts after a couple of weeks holiday.

I use this one to update the ShipDate on ShipHead, based upon the OrderNum that’s been added to the ShipDtl. This code is on a Standard Data Directive.

foreach (var sd in ttShipDtl)
{

var oh = Db.OrderHed.Where(o=> o.Company == callContextClient.CurrentCompany && o.OrderNum == sd.OrderNum).FirstOrDefault() ;
if (oh != null)
{
var sh = Db.ShipHead.Where(h=> h.Company == callContextClient.CurrentCompany && h.PackNum == sd.PackNum && h.ShipDate != oh.NeedByDate).FirstOrDefault() ;
if (sh != null)
{
sh.ShipDate = oh.NeedByDate ;
}
}
}

It was written with the help of an Epicor consultant. It uses a different style of Linq statement.

2 Likes

Hey Aaron, I got another question or two for you relating to this.

How can I set some ShipDtl fields? I figured I could set up another reference for it and put it under "Erp.Tables.ShipHead ShipHead; " like "Erp.Tables.ShipDtl ShipDtl; "

Then I try setting the WareHouseCode and BinNum fields but it continues to give me the compilation error
"Error CS1061: 'Erp.Tables.ShipDtl' does not contain a definition for 'WareHouseCode' and no extension method 'WareHouseCode' accepting a first argument of type 'Erp.Tables.ShipDtl' could be found (are you missing a using directive or an assembly reference?) "

It looks like ShipDtl doesn’t have a definition for WareHouseCode which doesn’t make sense to me…

EDIT - I think I found it out. Nevermind this post

Check the spelling of that field, it might be something like whsecode

I checked in BAQ and it says it’s WareHouseCode… I’m actually getting a little irritated with this. I changed the set field for the weight from 0.27 to 0.9326 (and the ShipDtl fields still aren’t working) -
image

And for some reason it’s still setting that field to 0.27 instead of 0.9326. I figured these things were pretty quick (almost instant) when you hit save on the Data Directive then it’s setup in the system right away… So why the heck is it still holding onto the 0.27?!

Check in the actual bpm by looking at what the temp table name for that field is, sometimes the baq view vs the temp table view is different.
Let me help when I get back from vacation :slight_smile:

I got it to work with just regular Method Directives on the GetOrderRelInfo method (post-processing). Now I gotta figure out why the 0.27 is sticking and sometimes it isn’t…

We just shipped one that said 0.27 and so we changed it to 0.9326 and then the next one actually came in correctly as 0.9326, but I’m pretty sure it’s still coming up as 0.27 for some of them.

Very odd

Edit - It was the package settings that were holding onto the 0.27. Now everything should be working properly. Ugh!