Fulfillment Workbench

How to allocate or reserve part through BPM?

probably, set a ud field in order hed/orderline and use it as a trigger point. below reference points from the peers.

A few things to consider:

  • There are many ways to allocate/reserve. Go through the process(es) manually while tracing. Use the trace(s) to model the code and logic. The logic may need to branch based on certain criteria and you should capture and analyze a trace of each branch.

  • Decide on a trigger to invoke the logic. This may be UI interaction or triggered by a state change or other trigger. There may be many ways to trigger.

  • Don’t rule out a customization on the FWB. The advantages are you can leverage the existing data views and adapters. Once you have a model you can form your logic in a customization or BPM. The implication being that the logic triggers from any form(or BPM or function or SC call) in a BPM, whereas in a customization you can control when it triggers more concisely.

For any of this automation, you typically have to get a Trace of the process to know what the screen is sending back to the server. Once you have that, you have to recreate that same logic as BPM widgets or code. Additionally, you can create a Function in the newer versions so there can be multiple ways to trigger the same logic.

I have pasted this code in BPM and getting an assembly reference issue for your ref screenshot is attached below

The code you pasted is for screen customization, i will share you the bpm code later today.

Thanks, @prakash. Actually, we require to Reserve parts for Orders through BPM.

order reservation is done by release level, you need to loop through each release or add all the release to SlimAlloc tableset and reserve in one go.

out of curiosity, is the standard fulfilment workbench not helpful? or whats that your end goal?

anyway , here is a rudimentary code.

Erp.Contracts.OrderAllocSvcContract od = Ice.Assemblies.ServiceRenderer.GetService<Erp.Contracts.OrderAllocSvcContract>(Db);
string ordHed = "OrderHed.OrderNum = "+ordNum.ToString();
using(od)
      {
          oatl = od.GetListOfOrders("", ordHed, "", "", "", "", "", "", "", "", "", "", 0, 0, out res, Session.CompanyID);

          foreach (var row in oatl.OrderAllocList)
          {
/* bug in my system*/
              row.RowMod = IceRow.ROWSTATE_UNCHANGED;
          }
           oat = od.OrderAllocationGetRows(oatl, 0); 
      
 if(oat != null )
         {
            foreach(var ordRel in oat.OrderAlloc.Where(i=>i.Company == Session.CompanyID  ))
            {
                Erp.Tablesets.SlimOrderAllocTableset soa = new Erp.Tablesets.SlimOrderAllocTableset();
                Ice.IceRow sR = soa.SlimOrderAlloc.NewRow();
                sR["AssemblySeq"] = 0;
                sR["Company"] = Session.CompanyID.ToString();
                sR["DemandType"] = "Order";
                sR["FulfillmentSeq"] = 1;
                sR["JobNum"] = "";
                sR["MtlSeq"] = 0;
                sR["OrderLine"] = ordLine;
                sR["OrderNum"] = ordNum;
                sR["OrderRelNum"] = relNum;
                sR["SelectedForAction"] = true;
                sR["TFOrdLine"] = 0;
                sR["TFOrdNum"] = "";
                soa.SlimOrderAlloc.Add(sR);
                try 
                  {          
                    od.AutoReserve(ref soa, "", "primaryOnly", out resreveMsg);
                  }
                  catch (Exception ex)
                  {
                    Epicor.Customization.Bpm.InfoMessage.Publish(" Reservation Error "+ ex.Message + "\n" + ex.InnerException);
                  }                
                
            }
          }
         }
3 Likes

@prakash, Your support is gratifying. Thank you for your support :+1:

@prakash, I am getting the below-mentioned error while Reserving Parts using Sales Order.

Auto Reservation Error The underlying provider failed on EnlistTransaction.
System.Data.SqlClient.SqlException (0x80131904): The operation failed because the session is not single threaded.
at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection, Action1 wrapCloseInAction) at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose) at System.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj, Boolean& dataReady) at System.Data.SqlClient.TdsParser.Run(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj) at System.Data.SqlClient.TdsParser.TdsExecuteTransactionManagerRequest(Byte[] buffer, TransactionManagerRequestType request, String transactionName, TransactionManagerIsolationLevel isoLevel, Int32 timeout, SqlInternalTransaction transaction, TdsParserStateObject stateObj, Boolean isDelegateControlRequest) at System.Data.SqlClient.SqlInternalConnectionTds.PropagateTransactionCookie(Byte[] cookie) at System.Data.SqlClient.SqlInternalConnection.EnlistNonNull(Transaction tx) at System.Data.SqlClient.SqlInternalConnection.Enlist(Transaction tx) at System.Data.SqlClient.SqlInternalConnection.EnlistTransaction(Transaction transaction) at System.Data.SqlClient.SqlConnection.EnlistTransaction(Transaction transaction) at Epicor.Data.Provider.EpiConnection.EnlistTransaction(Transaction transaction) in C:\_Releases\ICE\ICE3.2.200.16\Source\Framework\Epicor.System\Data\EpiProvider2\EpiConnection.cs:line 208 at System.Data.Entity.Infrastructure.Interception.InternalDispatcher1.Dispatch[TTarget,TInterceptionContext](TTarget target, Action2 operation, TInterceptionContext interceptionContext, Action3 executing, Action`3 executed)
at System.Data.Entity.Infrastructure.Interception.DbConnectionDispatcher.EnlistTransaction(DbConnection connection, EnlistTransactionInterceptionContext interceptionContext)
at System.Data.Entity.Core.EntityClient.EntityConnection.EnlistTransaction(Transaction transaction)
ClientConnectionId:2ddc0e58-4dc6-4bcd-91c6-8bfc45ac51a3
Error Number:3983,State:2,Class:16

1 Like

share your code here, this happens if you used outer for loop and change the dataset.

 OrderAllocTableset      objOrderAlloc      = new OrderAllocTableset();
        OrderAllocListTableset  objOrderAllocList  = new OrderAllocListTableset();
        Erp.Contracts.OrderAllocSvcContract   objOrderAllocSvc   = null;
              
        var ttOrderHed_xRow = (from ttOrderHed_Row in ttOrderHed  where ttOrderHed_Row.Company == Session.CompanyID select ttOrderHed_Row).FirstOrDefault();
        if (ttOrderHed_xRow != null)
        {            
            if(!ttOrderHed_xRow.Linked && ttOrderHed_xRow.UDField<System.Boolean>("Reserve_c"))
            {
                //InfoMessage.Publish("ttOrderHed_xRow Reserve");
                
                foreach (var OrderDtl_xRow in (from OrderDtl_Row in Db.OrderDtl where OrderDtl_Row.Company == ttOrderHed_xRow.Company && OrderDtl_Row.OrderNum == ttOrderHed_xRow.OrderNum select OrderDtl_Row)) 
                {
                     //InfoMessage.Publish("Order Detail Line- " +  OrderDtl_xRow.OrderLine);
                      
                      objOrderAllocSvc = Ice.Assemblies.ServiceRenderer.GetService<Erp.Contracts.OrderAllocSvcContract>(Db);
                      string waveWhereClause      = String.Empty;
                      string orderHedWhereClause  = "OrderHed.OrderNum = " + ttOrderHed_xRow.OrderNum.ToString();
                      string orderDtlWhereClause  = String.Empty;
                      string orderRelWhereClause  = String.Empty;
                      string customerWhereClause  = String.Empty;
                      string partAllocWhereClause = "NoFilter,NoFilter,NoFilter,NoFilter";
                      string countryWhereClause   = String.Empty;
                      string shipToWhereClause    = String.Empty;
                      string creditHoldClause     = "NoFilter";
                      string i_SortByOrder        = String.Empty;
                      string i_SortByWarehouse    = String.Empty;
                      string i_SortByAllocation   = String.Empty;
                
                      int pageSize     = 0;
                      int absolutePage = 0;
                      bool morePages   = false;
                      string NO_Company = Session.CompanyID;
                    
                      using(objOrderAllocSvc)
                      {
                          objOrderAllocList = objOrderAllocSvc.GetListOfOrders(waveWhereClause, orderHedWhereClause, orderDtlWhereClause , orderRelWhereClause, customerWhereClause, partAllocWhereClause,countryWhereClause, shipToWhereClause, creditHoldClause, i_SortByOrder, i_SortByWarehouse, i_SortByAllocation, pageSize, absolutePage, 
                          out morePages, NO_Company);
                        
                          foreach (var row in objOrderAllocList.OrderAllocList)
                          {
                             row.RowMod = IceRow.ROWSTATE_UNCHANGED;
                          }
                          
                          objOrderAlloc = objOrderAllocSvc.OrderAllocationGetRows(objOrderAllocList, 0);
                          if(objOrderAlloc != null)
                          {                             
                              foreach (var OrderRel_xRow in (from OrderRel_Row in Db.OrderRel where OrderRel_Row.Company == ttOrderHed_xRow.Company && OrderRel_Row.OrderNum == ttOrderHed_xRow.OrderNum  select OrderRel_Row)) 
                              {                                                                    
                                  if(!OrderRel_xRow.BuyToOrder)
                                  { 
                                         SlimOrderAllocTableset objSlimOrderAlloc = new SlimOrderAllocTableset(); 
                                         string resreveMsg   = string.Empty;                                     
                                         Ice.IceRow objIceRow = objSlimOrderAlloc.SlimOrderAlloc.NewRow();
                                         objIceRow["AssemblySeq"] = 0;
                                         objIceRow["Company"]     = Session.CompanyID.ToString();
                                         objIceRow["DemandType"]  = "Order";
                                         objIceRow["FulfillmentSeq"] = 1;
                                         objIceRow["JobNum"]      = "";
                                         objIceRow["MtlSeq"]      = 0;
                                         objIceRow["OrderLine"]   = OrderRel_xRow.OrderLine;
                                         objIceRow["OrderNum"]    = OrderRel_xRow.OrderNum;
                                         objIceRow["OrderRelNum"] = OrderRel_xRow.OrderRelNum;
                                         objIceRow["SelectedForAction"] = true;
                                         objIceRow["TFOrdLine"]   = 0;
                                         objIceRow["TFOrdNum"]    = "";
                                         objIceRow["RowMod"]      = "U";
                                         objSlimOrderAlloc.SlimOrderAlloc.Add(objIceRow);
                                         try
                                         { 
                                             objOrderAllocSvc.AutoReserve(ref objSlimOrderAlloc, "", "primaryOnly", out resreveMsg);
                                         }                 
                                         catch(Exception ex)
                                         {
                                          InfoMessage.Publish("Auto Reservation Error "+ ex.Message + "\n" + ex.InnerException);
                                         }
                                                                              
                                  }// Buy To Order
                                  
                              }// Order Release                                                                 
                              
                          }//objOrderAlloc
                          else
                          {
                              // InfoMessage.Publish("objOrderAlloc Null");
                          }// objOrderAlloc                 
                     }// using objOrderAllocSvc
                } 
            }            
       }

just moved your try catch block out of loop. try below.

    OrderAllocTableset      objOrderAlloc      = new OrderAllocTableset();
    OrderAllocListTableset  objOrderAllocList  = new OrderAllocListTableset();
    Erp.Contracts.OrderAllocSvcContract   objOrderAllocSvc   = null;
          
    var ttOrderHed_xRow = (from ttOrderHed_Row in ttOrderHed  where ttOrderHed_Row.Company == Session.CompanyID select ttOrderHed_Row).FirstOrDefault();
    if (ttOrderHed_xRow != null)
    {            
        if(!ttOrderHed_xRow.Linked && ttOrderHed_xRow.UDField<System.Boolean>("Reserve_c"))
        {
            //InfoMessage.Publish("ttOrderHed_xRow Reserve");
            
            foreach (var OrderDtl_xRow in (from OrderDtl_Row in Db.OrderDtl where OrderDtl_Row.Company == ttOrderHed_xRow.Company && OrderDtl_Row.OrderNum == ttOrderHed_xRow.OrderNum select OrderDtl_Row)) 
            {
                 //InfoMessage.Publish("Order Detail Line- " +  OrderDtl_xRow.OrderLine);
                  
                  objOrderAllocSvc = Ice.Assemblies.ServiceRenderer.GetService<Erp.Contracts.OrderAllocSvcContract>(Db);
                  string waveWhereClause      = String.Empty;
                  string orderHedWhereClause  = "OrderHed.OrderNum = " + ttOrderHed_xRow.OrderNum.ToString();
                  string orderDtlWhereClause  = String.Empty;
                  string orderRelWhereClause  = String.Empty;
                  string customerWhereClause  = String.Empty;
                  string partAllocWhereClause = "NoFilter,NoFilter,NoFilter,NoFilter";
                  string countryWhereClause   = String.Empty;
                  string shipToWhereClause    = String.Empty;
                  string creditHoldClause     = "NoFilter";
                  string i_SortByOrder        = String.Empty;
                  string i_SortByWarehouse    = String.Empty;
                  string i_SortByAllocation   = String.Empty;
            
                  int pageSize     = 0;
                  int absolutePage = 0;
                  bool morePages   = false;
                  string NO_Company = Session.CompanyID;
                
                  using(objOrderAllocSvc)
                  {
                      objOrderAllocList = objOrderAllocSvc.GetListOfOrders(waveWhereClause, orderHedWhereClause, orderDtlWhereClause , orderRelWhereClause, customerWhereClause, partAllocWhereClause,countryWhereClause, shipToWhereClause, creditHoldClause, i_SortByOrder, i_SortByWarehouse, i_SortByAllocation, pageSize, absolutePage, 
                      out morePages, NO_Company);
                    
                      foreach (var row in objOrderAllocList.OrderAllocList)
                      {
                         row.RowMod = IceRow.ROWSTATE_UNCHANGED;
                      }
                      
                      objOrderAlloc = objOrderAllocSvc.OrderAllocationGetRows(objOrderAllocList, 0);
                      if(objOrderAlloc != null)
                      {                             
                          foreach (var OrderRel_xRow in (from OrderRel_Row in Db.OrderRel where OrderRel_Row.Company == ttOrderHed_xRow.Company && OrderRel_Row.OrderNum == ttOrderHed_xRow.OrderNum  select OrderRel_Row)) 
                          {                                                                    
                              if(!OrderRel_xRow.BuyToOrder)
                              { 
                                     SlimOrderAllocTableset objSlimOrderAlloc = new SlimOrderAllocTableset(); 
                                     string resreveMsg   = string.Empty;                                     
                                     Ice.IceRow objIceRow = objSlimOrderAlloc.SlimOrderAlloc.NewRow();
                                     objIceRow["AssemblySeq"] = 0;
                                     objIceRow["Company"]     = Session.CompanyID.ToString();
                                     objIceRow["DemandType"]  = "Order";
                                     objIceRow["FulfillmentSeq"] = 1;
                                     objIceRow["JobNum"]      = "";
                                     objIceRow["MtlSeq"]      = 0;
                                     objIceRow["OrderLine"]   = OrderRel_xRow.OrderLine;
                                     objIceRow["OrderNum"]    = OrderRel_xRow.OrderNum;
                                     objIceRow["OrderRelNum"] = OrderRel_xRow.OrderRelNum;
                                     objIceRow["SelectedForAction"] = true;
                                     objIceRow["TFOrdLine"]   = 0;
                                     objIceRow["TFOrdNum"]    = "";
                                     objIceRow["RowMod"]      = "U";
                                     objSlimOrderAlloc.SlimOrderAlloc.Add(objIceRow);
                                     
                                                                          
                              }// Buy To Order
                              
                          }// Order Release                                                                 
                          
                      }//objOrderAlloc
                      else
                      {
                          // InfoMessage.Publish("objOrderAlloc Null");
                      }// objOrderAlloc                 
                 }// using objOrderAllocSvc
            } 
			try
			 { 
				 objOrderAllocSvc.AutoReserve(ref objSlimOrderAlloc, "", "primaryOnly", out resreveMsg);
			 }                 
			 catch(Exception ex)
			 {
			  InfoMessage.Publish("Auto Reservation Error "+ ex.Message + "\n" + ex.InnerException);
			 }
        }            
   }
1 Like

I am getting below mentioned error

Try catch block are outside the SlimOrderAllocTableset.

move
SlimOrderAllocTableset objSlimOrderAlloc = new SlimOrderAllocTableset();

under

Erp.Contracts.OrderAllocSvcContract objOrderAllocSvc = null;

define string variable reserveMsg as well.

you need to dispose all the objects.
good practice is to apply the using block

1 Like

I did the same as you mentioned above but getting the same error

what is the trigger for this bpm?

Try wrapping the whole thing in a Transaction Scope.

You can also do this with widgets. If you are wanting to iterate over a list, may be better in code though. Just figured I would include which widgets are working for me.

I’m using the Widgets for the following bo methods:

OrderAlloc.GetList → output to OrderAllocListTableset variable. Search for the orders you want using where string

OrderAlloc.OrderAllocationGetRows → ds input uses the OrderAllocListTableset from above, returns OrderAllocTableset variable

Set this OrderAllocTableset.OrderAlloc.SelectedForAction field to True

Create a SlimOrderAllocTableset variable and use a query to fill it from the OrderAllocTableset above

OrderAlloc.CheckDates → using SlimOrderAllocTableset as the ds

OrderAlloc.AutoReserve → using the SlimOrderAllocTableset as the ds. This outputs a result message which you may want to store in a UD table or elsewhere. I write it back to a field on the order release.