BPM Automation - Help Needed

Just did a hot-swap on the code to use some of Joses old recommendations on the same post. I get the following error:

Server Side Exception

BPM runtime caught an unexpected exception of ‘EntityException’ type.
See more info in the Inner Exception section of Exception Details.

Exception caught in: Epicor.ServiceModel

Error Detail

Correlation ID: 752e7d57-0fd4-4758-b5a6-733e6c159a3e
Description: BPM runtime caught an unexpected exception of ‘EntityException’ type.
See more info in the Inner Exception section of Exception Details.
Inner Exception: The partner transaction manager has disabled its support for remote/network transactions. (Exception from HRESULT: 0x8004D025)
The partner transaction manager has disabled its support for remote/network transactions. (Exception from HRESULT: 0x8004D025)
Program: EntityFramework.dll
Method: EnlistTransaction
Original Exception Type: EntityException
Framework Method: SaveChanges
Framework Line Number: 352
Framework Column Number: 17
Framework Source: SaveChanges at offset 404 in file:line:column C:_Releases\ICE\ICE4.1.100.0\Source\Server\Framework\Epicor.System\Data\IceDataContext.cs:352:17

Client Stack Trace

at Epicor.ServiceModel.Channels.ImplBase`1.ShouldRethrowNonRetryableException(Exception ex, DataSet dataSets)
at Erp.Proxy.BO.SalesOrderImpl.MasterUpdate(Boolean lCheckForOrderChangedMsg, Boolean lcheckForResponse, String cTableName, Int32 iCustNum, Int32 iOrderNum, Boolean lweLicensed, Boolean& lContinue, String& cResponseMsg, String& cCreditShipAction, String& cDisplayMsg, String& cCompliantMsg, String& cResponseMsgOrdRel, String& cAgingMessage, SalesOrderDataSet ds)
at Erp.Adapters.SalesOrderAdapter.MasterUpdate(Boolean lCheckForOrderChangedMsg, Boolean lcheckForResponse, String cTableName, Int32 iCustNum, Int32 iOrderNum, Boolean lweLicensed, Boolean& lContinue, String& cResponseMsg, String& cCreditShipAction, String& cDisplayMsg, String& cCompliantMsg, String& cResponseMsgOrdRel, String& cAgingMessage)
at Erp.UI.App.SalesOrderEntry.Transaction.Update()

Inner Exception

The underlying provider failed on EnlistTransaction.

Inner Exception

The partner transaction manager has disabled its support for remote/network transactions. (Exception from HRESULT: 0x8004D025)

Inner Exception

The partner transaction manager has disabled its support for remote/network transactions. (Exception from HRESULT: 0x8004D025)

using (var txScope = IceContext.CreateDefaultTransactionScope())
{
foreach(var UD01 in (from row in Db.UD01 select row))
   {
      Db.UD01.Delete(UD01);
   }
   Db.Validate();
   txScope.Complete();
}

/* Find current record in dataset */
using(var UD01svc = Ice.Assemblies.ServiceRenderer.GetService<Ice.Contracts.UD01SvcContract>(Db))
{   
foreach (var recOrderHed in (from row in Db.OrderHed where row.OpenOrder == true select row))
        {
        /* Find all lines for Order */
        foreach (var recOrdDetail in (from row in Db.OrderDtl where row.Company == Session.CompanyID && row.OrderNum == recOrderHed.OrderNum && row.OpenLine == true select row))
            {
              foreach (var recOrdRel in (from row in Db.OrderRel where row.Company == Session.CompanyID && row.OrderNum == recOrdDetail.OrderNum && row.OrderLine == recOrdDetail.OrderLine && row.OpenRelease == true select row))
                  {            
            
                          /* Update UD Record */
                          UD01Tableset ds = new UD01Tableset();
                          UD01svc.GetaNewUD01(ref ds);
                          ds.UD01[0].Company = Session.CompanyID;
                          ds.UD01[0].Number01 = recOrdRel.OrderNum;
                          ds.UD01[0].Number02 = recOrdRel.OrderLine;
                          ds.UD01[0].Number03 = recOrdRel.OrderRelNum;
                          ds.UD01[0].Date01 = recOrdRel.ReqDate;
                          UD01svc.Update(ref ds);
   
                   }    
            }
        }
}

Does anyone have an idea what could be causing this?

Dunno if this is the answer but, on the last bit of code you posted you are not setting the Key fields on UD01

Do I have to set those key fields when writing to UD01?

Normally when creating a new record you need at least one key field filled in, something that makes the record unique

So if I set Key 1 = order number, key2 to order line, and key 3 to order release will that work?

Thats what I do in similar situations… and thats what you where doing in your earlier code

I went ahead and added the keys and made a change where the orderhed table would use sessionID company as part of the where statement, I get same message.

   using (var txScope = IceContext.CreateDefaultTransactionScope())
    {
    foreach(var UD01 in (from row in Db.UD01 select row))
       {
          Db.UD01.Delete(UD01);
       }
       Db.Validate();
       txScope.Complete();
    }

    /* Find current record in dataset */
    using(var UD01svc = Ice.Assemblies.ServiceRenderer.GetService<Ice.Contracts.UD01SvcContract>(Db))
    {   
    foreach (var recOrderHed in (from row in Db.OrderHed where row.Company == Session.CompanyID && row.OpenOrder == true select row))
            {
            /* Find all lines for Order */
            foreach (var recOrdDetail in (from row in Db.OrderDtl where row.Company == Session.CompanyID && row.OrderNum == recOrderHed.OrderNum && row.OpenLine == true select row))
                {
                  foreach (var recOrdRel in (from row in Db.OrderRel where row.Company == Session.CompanyID && row.OrderNum == recOrdDetail.OrderNum && row.OrderLine == recOrdDetail.OrderLine && row.OpenRelease == true select row))
                      {            
                
                              /* Update UD Record */
                              UD01Tableset ds = new UD01Tableset();
                              UD01svc.GetaNewUD01(ref ds);
                              ds.UD01[0].Key1 = recOrdRel.OrderNum.ToString();
                              ds.UD01[0].Key2 = recOrdRel.OrderLine.ToString();
                              ds.UD01[0].Key3 = recOrdRel.OrderRelNum.ToString();
                              ds.UD01[0].Company = Session.CompanyID;
                              ds.UD01[0].Number01 = recOrdRel.OrderNum;
                              ds.UD01[0].Number02 = recOrdRel.OrderLine;
                              ds.UD01[0].Number03 = recOrdRel.OrderRelNum;
                              ds.UD01[0].Date01 = recOrdRel.ReqDate;
                              UD01svc.Update(ref ds);
       
                       }    
                }
            }
    }

Server Side Exception

BPM runtime caught an unexpected exception of ‘EntityException’ type.
See more info in the Inner Exception section of Exception Details.

Exception caught in: Epicor.ServiceModel

Error Detail

Correlation ID: 46b45444-c73f-4a7c-9669-8dafcde49c22
Description: BPM runtime caught an unexpected exception of ‘EntityException’ type.
See more info in the Inner Exception section of Exception Details.
Inner Exception: The partner transaction manager has disabled its support for remote/network transactions. (Exception from HRESULT: 0x8004D025)
The partner transaction manager has disabled its support for remote/network transactions. (Exception from HRESULT: 0x8004D025)
Program: EntityFramework.dll
Method: EnlistTransaction
Original Exception Type: EntityException
Framework Method: SaveChanges
Framework Line Number: 352
Framework Column Number: 17
Framework Source: SaveChanges at offset 404 in file:line:column C:_Releases\ICE\ICE4.1.100.0\Source\Server\Framework\Epicor.System\Data\IceDataContext.cs:352:17

Client Stack Trace

at Epicor.ServiceModel.Channels.ImplBase`1.ShouldRethrowNonRetryableException(Exception ex, DataSet dataSets)
at Erp.Proxy.BO.SalesOrderImpl.MasterUpdate(Boolean lCheckForOrderChangedMsg, Boolean lcheckForResponse, String cTableName, Int32 iCustNum, Int32 iOrderNum, Boolean lweLicensed, Boolean& lContinue, String& cResponseMsg, String& cCreditShipAction, String& cDisplayMsg, String& cCompliantMsg, String& cResponseMsgOrdRel, String& cAgingMessage, SalesOrderDataSet ds)
at Erp.Adapters.SalesOrderAdapter.MasterUpdate(Boolean lCheckForOrderChangedMsg, Boolean lcheckForResponse, String cTableName, Int32 iCustNum, Int32 iOrderNum, Boolean lweLicensed, Boolean& lContinue, String& cResponseMsg, String& cCreditShipAction, String& cDisplayMsg, String& cCompliantMsg, String& cResponseMsgOrdRel, String& cAgingMessage)
at Erp.UI.App.SalesOrderEntry.Transaction.Update()

Inner Exception

The underlying provider failed on EnlistTransaction.

Inner Exception

The partner transaction manager has disabled its support for remote/network transactions. (Exception from HRESULT: 0x8004D025)

Inner Exception

The partner transaction manager has disabled its support for remote/network transactions. (Exception from HRESULT: 0x8004D025)

Sorry I’m not much help, I just googled the text of the last Inner Exception, there is a lot of results…

Any and all help is accepted here, man! Thanks for taking the time to poke around and offer some advice!

Went back to the original code and made a few slight modifications. Now I get the exact results I was after.

using (var txScope = IceContext.CreateDefaultTransactionScope())
{
foreach(var UD01 in (from row in Db.UD01 select row))
   {
      Db.UD01.Delete(UD01);
   }
   Db.Validate();
txScope.Complete();

}

/* Find current record in dataset */
using (var txScope = IceContext.CreateDefaultTransactionScope())
{    
foreach (var recOrderHed in (from row in Db.OrderHed where row.Company == Session.CompanyID && row.OpenOrder == true select row))
        {
        /* Find all lines for Order */
        foreach (var recOrdDetail in (from row in Db.OrderDtl where row.Company == Session.CompanyID && row.OrderNum == recOrderHed.OrderNum && row.OpenLine == true select row))
            {
              foreach (var recOrdRel in (from row in Db.OrderRel where row.Company == Session.CompanyID && row.OrderNum == recOrdDetail.OrderNum && row.OrderLine == recOrdDetail.OrderLine && row.OpenRelease == true select row))
                  {            
            
                          /* Update UD Record */
                         UD01 newRow = new UD01();
                         Db.UD01.Insert(newRow);
                         newRow.Company = Session.CompanyID;
                         newRow.Key1 = recOrdRel.OrderNum.ToString();
                         newRow.Key2 = recOrdRel.OrderLine.ToString();
                         newRow.Key3 = recOrdRel.OrderRelNum.ToString();
                         newRow.Number01 = recOrdRel.OrderNum;
                         newRow.Number02 = recOrdRel.OrderLine;   
                         newRow.Number03 = recOrdRel.OrderRelNum;
                         newRow.Date01 = recOrdRel.ReqDate;   
                   }    
            }
        }
Db.Validate();
txScope.Complete();

}

Very good, I see you are now setting Key3 to the order rel, probably why you were getting duplicate entries on your earlier code

1 Like

Now for the fun part of the project, functions. The way that the integrator decided to delete out our sales order releases was to do it one line at a time. This means that there will be multiple UpdateExt Calls by their user account with RowMods = “D”. I want to push the data from OrderRel to UD01 only once when they initialize the first Delete call, not ever one they make. The way I though this could be done would be to make a scheduled program that toggles a little before their program is scheduled to run. This can then be called on a condition statement allowing for the data push to be run. After the data push I want that toggle to be set to false and only tick back to true three to four hours later. This will ensure that their program is done running its delete calls before toggling back. Does anyone have any expertise on this?

Thanks!

Delete all SO Releases? Seems awfully aggressive, and they might run into an issue with that since I didn’t think Epicor would allow all Releases to be deleted. Anyways, sounds like a ‘nuclear option.’

A few thoughts:

  1. Demand Management instead, this would mean the PO data would feed into Epicor through Demand Management and then someone can mass manage the updates to the Sales Orders… might not be as ‘integrated’ but it might be safer and more elegant.
  2. You could manage the whole thing with PowerShell and DMT. Before the Update (or bomb and rebuild) comes through, your can have a PowerShell run that will call a BAQ for all the current state Releases with the relevant data (OrderNum, LineNum, Rel, Promise Date, etc). That will put the BAQ results in a CSV. You can then use PowerShell to manipulate the CSV if needed. Then after the Rest Update, have the PowerShell run a SalesOrder Release Update with the CSV to update the Promise Dates back. Might be easier than trying to pick up on the right trigger in a BPM.
  3. As you stated REST goes both ways, I would push a solution that will just Update the data that needs to be updated somehow.
  4. Might be better to ‘capture’ the Load into a CSV and then use PowerShell DMT to to just update what is needed.
2 Likes

@Rick_Bird ,

I like the idea of doing that. Before our company decided to implement with the integrator, at one of our customers’ request, I had an excel sheet with a couple of rest calls and a lot of macros that did almost exactly what you call for in step 2. Unfortunately, my hands are tied for the most part on this integration. Their system blows up our sales order releases then calculates new sales orders by looking at what is in the customers portal and then forces over new releases based on the sales order and line number. From what I’ve seen they have to have their system to work this way as they also handle asn’s and a plethora of other things that I’m not well versed in. and with go live first thing next week I have little time to come up with an automated process. I do agree with you though. I wish I had more of a say in how this thing was put together and how it handles my system.

Does anyone have experience with Functions and would be willing to give me a quick rundown on how they work?

There’s a whole post about. Did you read that?

Not yet but I am now! Thanks Brandon!

Back to the bpm, I have an issue with how I’m detecting a change. I need to be able to grab the data before it is deleted hence why I chose a preprocess. However, I have not come to the realization that I cannot use the ChangedBy field as it won’t grab the user of the person initiating the change, but the user of whoever worked on it last. I need a way of saying if user x is deleting a row then grab everything before it is deleted. Does anyone have a quick trick to accomplish this?

Found an old post by @ckrusen that answered my question. Turns out there is a "Method Called By ______ option in the condition statement selection. Credit do here:

Next problem. I have noticed that the dates being captured in UD01 are not the dates that should be going in. In my manual tests the table populated the OrderRel.ReqDates into UD01.Date01. When we let the program run it seems to be catching dates after they have been deleted and new ones are uploaded by the integrator.

According to their process they are supposed to close all shipped/partially shipped order releases, then delete all other releases with no shipping data. Once that is done they do their calculations based on our customers portal and place those results back in as new releases.

My program runs off of a trigger with two trips. The first trip happens on their first deletion call, and simply writes all open sales orders,open lines, open releases, and OrderRel.ReqDate to UD01. The second trigger trips on their first upload resetting the trigger for next deletion from that user and allows for my other program to begin shuffling in dates from UD01 to OrderRel if they existed.

My best guess is that there is some cross talk somewhere on the first trip. I can confirm that while the integrators process is running that the first and second trip happen at least once as the dates in UD01 do not match the ones that I force in on my manual process. Does anyone have any ideas on what could be causing this to trigger more than once and how it would choose to overwrite with dates that werent capable of being in OrderRel until after the last deletion call was made?

Found the issue I was accidentally creating an infinite loop with my toggle. Does anyone know how Epicor determines when a user is to be timed out? Or what specifically triggers the time out event?