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.
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);
}
}
}
}
@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.InternalDispatcher
1.Dispatch[TTarget,TInterceptionContext](TTarget target, Action2 operation, TInterceptionContext interceptionContext, Action
3 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
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);
}
}
}
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
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.