EDI imports are creating blank DueDates in PartDtl

, ,

We have been working with Epicor support on this issue and they cannot seem to solve it so I’m asking here to see if anyone can give me any more information to go on.

We have upgraded from 9.05.702 to 10.2.400.14 on April 20, 2020. Since that time, we have had issues that started with not having the OrderRel.ReqDate being filled in for customers that have 0 delivery days. Tons of reports and other things are based on this date. We use it as the beginning of the ship window for our business (sometimes the same day, Delivery Days 0 and sometimes 2 weeks).

So, we created a BPM to copy the OrderRel.NeedByDate whenever the Customer.DeliveryDays == ‘0’ . This fixed the problem in OrderRel, but we were left with many records that had NULL/Blank in their PartDtl.DueDate records. There were also the creation of extra records for many Order Releases.

We have now created a new BPM that sets the DemandSchedule.ReqDate before they are imported into the Sales Orders. This has taken down our amount of NULL/Blank PartDtl.DueDate from 2000+ to 200+ daily. However, it did not fix the entire problem. The DemandSchedule records now have DueDates filled in as expected, but they are still creating these NULL dates in addition to their regular records that have the correct Due Date. For example, an OrderRel record that has a ReqDate of 6/15/2020 would have one PartDtl record that has a 6/15/2020 DueDate and another that matches exactly, except a NULL DueDate.

Any idea on what else could be happening with these? Or something else I can check to determine where the issue is? We do have a fairly customized import process since we are a total replace of each order on each import and this creates new OrderRels if the dates don’t match. I will post the BPMs mentioned in my first follow-up shortly.

DemandSchedule.Update/In-transaction/SetDemandScheduleReqDate

    foreach (var DemandHeadRow in (from row in ttDemandHead 
                                where row.Company   == Session.CompanyID  
                                   && row.DemandHeadSeq  >  0
                               select row))
    
      {
        using (var txScope = IceContext.CreateDefaultTransactionScope())
        {
        foreach (var CustRow in (from row in Db.Customer
              where row.Company == Session.CompanyID 
                 && row.CustNum == DemandHeadRow.CustNum
                 && row.DemandDeliveryDays == 0
              select row))
        {
          foreach (var DemandScheduleRow in (from row in Db.DemandSchedule
                where row.Company   == Session.CompanyID 
                   && row.OrderNum  == DemandHeadRow.OrderNum
                   && row.OrderRelNum  >  0
                select row))
          {
            DemandScheduleRow.ReqDate = DemandScheduleRow.NeedByDate;
          }  // orderRelRow
        }  // CustRow
        Db.Validate();
        txScope.Complete();
        txScope.Dispose();
        }
    //  }  // EDIOrder
    }  //ttOrderHed


Erp.OrderHed.Update/In-Transaction/SetReqDate



foreach (var orderHedRow in (from row in ttOrderHed
                            where row.Company   == Session.CompanyID  
                               && row.OrderNum  >  0
                           select row))
{
  if (orderHedRow.EDIOrder)
  {
    using (var txScope = IceContext.CreateDefaultTransactionScope())
    {
    foreach (var CustRow in (from row in Db.Customer
          where row.Company == Session.CompanyID 
             && row.CustNum == orderHedRow.CustNum
             && row.DemandDeliveryDays == 0
          select row))
    {
      foreach (var orderRelRow in (from row in Db.OrderRel
            where row.Company   == Session.CompanyID 
               && row.OrderNum  == orderHedRow.OrderNum
               && row.OrderRelNum  >  0
            select row))
      {
        orderRelRow.ReqDate = orderRelRow.NeedByDate;
      }  // orderRelRow
    }  // CustRow
    Db.Validate();
    txScope.Complete();
    txScope.Dispose();
    }

}  //ttOrderHed
'''

In your code I see you are setting the ReqDate on the Release, maybe you have to set it on the OrderDtl as well. They are grabbing it from what I can tell from OrderDtl not OrderRel. (When Syncing to PartDtl)

So, in 10.1.400 the fact that a ship by date was being populated when we had the customer date as shipping and we only populated the need by date in the file was a bug…that happened to be working in our favor.

In 10.2.300 it is corrected and we needed to do it the “proper” way by specifying ship days, the right date on the customer (in our case need by instead of shipping). If it is 0, then the ship by date needs to be mapped in the file.

You are right, if you have a Days Out: 0, it comes in blank (you must map it in file or leave it blank). If you use a real value, it actually works.

1 Like

This is excellent information, Haso. I noticed that the behavior of the ReqDate changes between 9 and 10.2, this confirms it. Most of our customers have a Days Out of 0, so this all applies and explains we are not crazy…at least not in this instance.

We cannot set it on the OrderDtl, since almost all of our OrderDtl have multiple releases, usually hundreds.

I changed my BPM to set the Req date as a Standard Data Directive, instead of a In-Process and got good results in my limited testing. Tomorrow’s import should reveal more. Anyone know the difference between and which should apply in this case?

Since you are not using the BO and you are using the LINQ Method to directly update ReqDate, you are missing out of Epicor calling “AfterUpdate” which syncs PartDtl. I didnt mean like really change it but trigger a Fake Change.

May I make a better recommendation.

I am actually doing a similar project like you, but I placed my Logic inside:
Erp.DemandImportEntry.ImportEDIPostProcessDemand

This would happen after the Order Lines and Releases have been created, either from Demand WkBench or EDI Import Process. I do stuff on the Line you can do stuff on OrderRel.

var DemandHeadRow =
  (from row in Db.DemandHead.With(LockHint.NoLock)
  where
    row.SysRowID == DemandHeadRowid
    && row.EDIOrder == true
    && row.PONum.StartsWith("SO-")
    && row.POType == string.Empty
  select row
  ).FirstOrDefault();

if (DemandHeadRow != null)
{
    var DemandDetailRows =
      (from dd in Db.DemandDetail.With(LockHint.NoLock)
        where
        dd.Company == DemandHeadRow.Company
        && dd.DemandContractNum == DemandHeadRow.DemandContractNum
        && dd.DemandHeadSeq == DemandHeadRow.DemandHeadSeq
        && dd.Posted == true
        && dd.RejectedByUser == false
        && dd.OrderNum != 0
        && dd.POType == string.Empty
        select dd
      ).ToList();

    foreach (var demandRow in DemandDetailRows)
    {
      var OrderDtlRow =
        (from od in Db.OrderDtl
        where
          od.Company == demandRow.Company
          && od.OrderNum == demandRow.OrderNum
          && od.OrderLine == demandRow.OrderLine
        select od
        ).FirstOrDefault();

      if (OrderDtlRow != null)
      {
        using (var txScope = IceContext.CreateDefaultTransactionScope())
        {
          OrderDtlRow.CustomerOwnedInventory_c = true;
          Db.Validate(OrderDtlRow);
          txScope.Complete();
        }
      }
    }
}

The method directives used in Import EDI Demand processing are as follows:

  • ImportEDIb4tran - If it exists, the Import EDI Demand Process runs the custom BPM code you associate with this method directive to manipulate inbound EDI data stored in Intermediate Demand tables before the ImportEDI routine runs and processes translations on the data.
  • ImportEDIb4val - If it exists, the Import EDI Demand Process runs the custom BPM code you associate with this method directive to manipulate translated inbound EDI data stored in Intermediate Demand tables before the ImportEDI routine runs and performs validations on the data.
  • ImportEDIpreProcessDemand - If it exists, the Import EDI Demand Process runs the custom BPM code you associate with this method directive to manipulate validated inbound EDI data stored in the regular Demand tables before the ImportEDI routine processes the demand data into actual sales orders or forecasts.
  • ImportEDIpostProcessDemand - If it exists, the Import EDI Demand Process runs the custom BPM code you associate with this method directive to manipulate inbound EDI data after the ImportEDI routine processes the demand data into actual sales orders or forecasts.
  • ImportEDIonUDImport - If it exists, the Import EDI Demand Process runs the custom BPM code you associate with this method directive when more than 95 User Defined (UD) fields exist on an inbound EDI transaction map you are importing. The ImportEDIonUDImport method directive is only available in Release 10.1.400.12 and above.

1 Like

Haso, that makes sense. Thank you! I was trying to do this on the DemandSchedule since I thought the PartDtl was being updated before the imports came to Orders. We will work on trying this on OrderRel and get back.

Haso,
You led us on the path to fix this huge issue. Thank you so much. We are trying to update OrderRel using similar code to your post, and when we created our method directive on the ImportEDIPostProcessDemand, we still were getting blanks on PartDtl.DueDate. We certainly may not have gotten the code correct, but the OrderRel.ReqDate wasn’t updating for new releases.

After several tries and iterations, we had not have eliminated the blanks, so we checked out https://www.epiusers.help/t/mrp-suggestions-for-unfirm-releases/67060/10

This let us know we could update PartDtl directly without any bad repercussions. So, we put a Data Directive on DemandHead.InTransaction that updates the DemandSchedule, OrderRel and PartDtl on each import. No more blanks, no more duplicates and all of our new Order Releases have a PartDtl that matches at ReqDate to DueDate.

I’ll post the data directive after this, in case it can help anyone.

1 Like

Code that fixed our blanks in PartDtl.Due and OrderRel.ReqDate on new inbound EDI for Order Releases:

Erp.Tables.Customer Customer;
Erp.Tables.DemandSchedule DemandSchedule;
Erp.Tables.PartDtl PartDtl;

foreach (var DemandHead_iterator in (from row in ttDemandHead 
                            where row.Company   == Session.CompanyID  
                               && row.DemandHeadSeq  >  0
                           select row))
{
    var DemandHeadRow = DemandHead_iterator;
    using (var txScope = IceContext.CreateDefaultTransactionScope())
    {
        foreach (var CustRow in (from row in Db.Customer
              where row.Company == Session.CompanyID 
                 && row.CustNum == DemandHeadRow.CustNum
                 && row.DemandDeliveryDays == 0
              select row))
        {
            Customer = CustRow;
            foreach (var DemandScheduleRow in (from row in Db.DemandSchedule
                where row.Company   == Session.CompanyID 
                   && row.OrderNum  == DemandHeadRow.OrderNum
                   && row.OrderRelNum  >  0
                select row))
            {
                DemandSchedule = DemandScheduleRow;
                
                
                
                // DemandSchedule Update
                DemandSchedule.ReqDate = DemandSchedule.NeedByDate;
                
                
                
                // PartDtl Update
                foreach (var PartDtlRow in (from row in Db.PartDtl
                    where row.Company    == Session.CompanyID
                      && row.OrderNum    == DemandScheduleRow.OrderNum
                      && row.OrderLine   == DemandScheduleRow.OrderLine
                      && row.OrderRelNum == DemandScheduleRow.OrderRelNum
                      && row.DueDate     != DemandScheduleRow.ReqDate
                      && DemandScheduleRow.CreateDate == DateTime.Today
                    select row))
                {
                    PartDtl = PartDtlRow;
                    PartDtl.DueDate = DemandScheduleRow.ReqDate;
                } // PartDtl
                
                
                
                // OrderRel Update
                foreach (var OrderRelRow in (from row in Db.OrderRel
                    where row.Company    == Session.CompanyID
                      && row.OrderNum    == DemandScheduleRow.OrderNum
                      && row.OrderLine   == DemandScheduleRow.OrderLine
                      && row.OrderRelNum == DemandScheduleRow.OrderRelNum
                      //Rows above not needed?
                      && row.NeedByDate  != row.ReqDate
                    select row))
                {
                    OrderRelRow.ReqDate = OrderRelRow.NeedByDate;
                } // OrderRel
                
                
                
           }  // DemandScheduleRow
        
        }  // CustRow
        Db.Validate();
        txScope.Complete();
        txScope.Dispose();
    } // TxScope
}  //ttOrderHed

Awesome that should work. I still find it odd that your DueDate is blank, the only thing I can think of is that you have a BPM or Data Directive setting it to blank when someone creates a OrderRel (RowMod A) and in return it is carried over during create of Demand.

But that should work :slight_smile: Awesome!

I wonder what BookRel shows when The ReqDate blanks out.

SELECT * FROM Erp.BookRel

This BPM continues to work perfectly for us, so that’s several hours out of my day saved. Awesome is right, thanks again.

The reason the DueDate is blank, based on some of what I’ve read in Epicor and on epiusers, is that if your Customer.DemandDelivery days == 0, they have taken out the base code that made the OrderRel.ReqDate = OrderRel.NeedBy date between 10.1 and 10.2. Most of our customers have 0 Delivery days, as they have a specific day we need to ship. Their orders that have new releases, without this BPM, all have PartDtl.DueDate and OrderRel.ReqDate blank.

In our test system, I will check out the BookRel and report back.

1 Like

Based on your conversation here, it appears you both are working with EDI. We have just purchased the Epicor Demand Management module + TIE KINETIX and are working toward getting our 1st customer working. Do either of you have a recommendation of a resource who can help me with the set ups in Epicor? My usual external resources don’t have experience with the demand managment module.

1 Like

SarahCrews,
We worked with Cheryl from TIE Kinetix to get everything working on eVision and then now TIE SmartBridge. I am now able to fix maps on our software for our customer, so we do some of that in-house.

On the Epicor side of EDI, we originally worked with the Epicor EDI team, who are now headed by Catherine Armbrust. They got us set for our initial launch on Epicor 9.05.702 and then provided some assistance as we went to 10.2. Between those two and after, we have done much of our changes in-house ourselves.

The best resource that we’ve had is our consultant Kevin Simon, who is on here: @SimsTrak. He helped set us up with several changes and provided advice throughout. He would likely be a good resource for your Demand Management.

1 Like

Thank you so much Michael for the direction. I really appreciate your prompt and thorough response.

1 Like

We also work with Cheryl from TIE. Great person with extensive knowledge of the product.

On the Epicor side, Cara Peterson is phenomenal.

Feel free to reach out to me if you need their contact info.

@josecgomez , Cara was the person I wanted to introduce you to at insights. She works for Epicor and is great at setting up EDI in Epicor. You had mentioned something about EDI on one of our threads.

1 Like

SarahCrews,
We have also implemented Demand Management with TIE Kinetix Smartbridge (starting May 2021).

I also agree that Cheryl from TIE is a great resource, she is always very helpful.

From my experience, Jean Montague @jmontague (http://www.jeanmontagueconsulting.com) is a good consulting resource for DM.