BPM-Method Directive Update Lead Times/Days of Supply

,

I am a BPM novice and am having some difficulty with the following situation that maybe someone can see the solution to quickly.
I currently have a post-processing BPM on ERP.VendPartPlant.Update. There are actually 2 of these BPMs (I separated them in case upper management changed their minds). The purpose is to update the PartPlant.LeadTime and the PartPlant.DaysOfSupply fields with the value in the VendPart.LeadTime field so that users only need to update the Supplier Price List Lead Time in order to populate these two fields and thus keep them in sync.
However, we do not want the PartPlant.DaysOfSupply to be updated from the VendPart.LeadTime field for anything other than PURCHASED (P) parts on the Part.TypeCode field.

How do I create a condition on the following custom code to ignore the Part.TypeCodes that are NOT ‘P’?

Any help would be greatly appreciated.
Thanks

int LTime;
string PartNum1;
int VNum;

var vendPartTt = ttVendPart.Where(item => item.Company == CompanyID).FirstOrDefault();

if(vendPartTt != null){
LTime = vendPartTt.LeadTime;
PartNum1 = vendPartTt.PartNum;
VNum = vendPartTt.VendorNum;

LTime = 0;

foreach(var vendPartDb in Db.VendPart.Where(item => item.VendorNum == VNum && item.PartNum == PartNum1 && item.Company == vendPartTt.Company).With(LockHint.NoLock)){
  LTime = vendPartDb.LeadTime;
}

foreach(var partPlantDb in Db.PartPlant
        .Where(item => item.PartNum == PartNum1 && item.VendorNum == VNum && item.Company == vendPartTt.Company)
        .With(LockHint.NoLock)){
  partPlantDb.DaysOfSupply = LTime;
}

}

@saugustine You need to check if the part is a P and then wrap the rest of the logic in an if. Here are a couple of examples from I believe @timshuwy with the Any and @hkeric.wci for just the description that should get you started.

Also wrap your code in three ` grave accents with the tilde for formatting like mine.

I would probably use the Any as it will not bring back any data, but selecting only the field you need would also be light.


//to find if a part exists:
bool partExists = Db.Part.Any(x=>x.Company == CompanyID && x.PartNum ==  myPart);

//to retrieve just the part's description:
string partDesc = Db.Part.Where(x=>x.Company == CompanyID && x.PartNum ==  myPart).Select(x=>x.PartDescription).FirstOrDefault() ?? "Not Found";
1 Like

You should adjust your code to something like I have below…

  1. you are declaring variables that are not needed
  2. you are looping through records instead of doing a select statement and then looping. (note how I selected “partPlantRecordsToUpdate” which goes and retrieves all the records at once with one SQL query instead of one at a time).
    You were not setting a transaction scope around the update.

Note that this is NOT TESTED, and may have TYPOS… I tried my best…

var vendPartTt = ttVendPart.Where(item => item.Company == CompanyID && item.RowMod != "").FirstOrDefault();

if(vendPartTt != null){

    int LTime = Db.VendPart.Where(item => 
        item.Company == vendPartTt.Company &&
        item.VendorNum == vendPartTt.VendorNum && 
        item.PartNum == vendPartTt.PartNum)
        .Select(x=>x.LeadTime).FirstOrDefault() ?? 0;

    var partPlantRecordsToUpdate = Db.PartPlant.Where(item => 
            item.Company == vendPartTt.Company &&
            item.PartNum == vendPartTt.PartNum && 
            item.VendorNum == vendPartTt.VendorNum)
                .With(LockHint.UpdLock));

    if (partPlantRecordsToUpdate != null){
        using(var txScope = IceContext.CreateDefaultTransactionScope()) {
            foreach(var partPlantDb in partPlantRecords) {
                partPlantDb.DaysOfSupply = LTime;
            }
                
            Db.Validate();
            txScope.Complete();
        }
    }
}
string partDesc = Db.Part.Where(x=>x.Company == CompanyID && x.PartNum ==  myPart).Select(x=>x.PartDescription).DefaultIfEmpty("").First();

You can ignore this if you want. Every business is different.

I would be hesitant to tie the DOS to the Lead Time. It might make sense for a lot of parts, but here is my reasoning.

DOS determines how far in the future Epicor looks forward to gather demand. So if Epicor sees that we needs a certain part tomorrow (and we don’t have any), and the DOS is set to 30… Epicor will look 30 days (7days per week) into the future (from the initial demand) and give you a PO suggestion or an MRP job to buy/make enough parts to cover the next 30 days.

If you have a “penny” part with a 5 day lead time (and no MOQ), Epicor will give you a message to buy/make more every 5 days. I would give this part a bigger DOS. Of course there are tons of factors at play, but in general I think this kind of part doesn’t need weekly attention from the Buyers.

On the flip side, if you have an imported $1000 item with a Lead Time of 180 days (oh my), then Epicor is going to give you a giant PO suggestion. But it might be more practical to set the DOS at 90 days (or less) so that you get shipments every 90 days (or less). Buyers would still get suggestions 180 days before the need by date.

Those are the two ends of the spectrum. There are a BUNCH of factors at play including squishy stuff like company culture.

Sorry. Another thing.

Days Of Supply is calculated as 7 days per week.

Lead Time is calculated by the Calendar in Epicor that is applied to that specific Vendor. If the Vendor doesn’t have a Calendar applied to it, I think it defaults to your Shop Calendar.

So if your Shop/Vendor Calendars are 5 days per week, then the DOS and Lead Time aren’t going to really match anyway.

Last thing I promise.

You can have multiple Vendors per part. So if the Buyer sets Vendor A’s price list lead time to 15 days, the BPM will update the part.plant lead time to 15 days. Then The Buyer sets up Vendor B with a price list lead time of 30 days. Now the BPM is going to update the the part.plant lead time to 30 days.

If your company uses multiple vendors for parts this might cause unexpected grief.

I might suggest building something into your BPM that checks to see if the Vendor is primary vendor, and only updating the part.plant if the Vendor is set as the primary Vendor for that part.

Take it all with a grain of salt. Good luck.

1 Like

Chris,

Thank you for the insight and explanation on this. We have been reviewing and altering our Vendor Lead Times, Part Lead Times and Days of Supply in order to Get MRP working in a manner that works best for us. Up until this past week, our purchasing dept has been using Time phase on every Purchasing suggestion to double check to see whether or not we really need to purchase a part. We have found (at least in our situation with Purchased parts) that keeping the Days of Supply the same as the VendPart.Lead time has cleared up the Buyer workbench considerably and we are (so far) been able to trust what we are seeing from our Purchasing Suggestions without quadruple checking Time Phase.

We are now moving into our own manufactured parts. However….we do not have a good handle on our own part lead times as they vary greatly for many parts as we are a bit of a custom manufacturing plant – meaning we are not producing the same parts all the time. We produce parts as made to order when they are required for the machines that are ordered. We are working on gaining better metrics to clean up our own lead times currently – unfortunately it was not something that was monitored or upkept in the past.

I will consider the Primary Vendor suggestion that you mentioned and double check functionality. But to this point, this BPM which updates the PartPlant.LeadTime from the VendPart.LeadTime has not caused the issue you described below when there are multiple vendors. I will double check though to make sure. This BPM has been in place since before my time. I have just added the DaysofSupply recently.

I really appreciate the input. This really helps.