I am creating a method directive on Update to add a Miscellaneous Charge at Header when the Ship Via is set to a certain code, for both New Quote and if the Ship Via is updated, removed when not that ship via code.
I thought there was a way to prevent the directives of a BPM to not fire if that BO was called inside another BPM. What is happening is I am adding the misc. charge and the final step is to Update and the update BPMs fire again and I hit an error.
Thanks. I have done that a thousands times. Here is my quandary, and maybe I am over-thinking it. I need to add this Misc. Charge even on a new Quote Header and I did not believe it was possible because the actual quote does not exist until after Pre and Base processing.
Are you stating it is possible to add this to the Quote TableSet when the record is in a “A” RowMod state when no Quote Header exists just yet.
// The true parameter in this constructure instructs Epicor to bypass the facade (no BPMs and or related events are triggered)
using(Erp.Contracts.QuoteSvcContract hQuoteSvcContract = Ice.Assemblies.ServiceRenderer.GetService<Erp.Contracts.QuoteSvcContract>(Db, true))
{
// any calls to hQuoteSvcContract here bypass the facade
}
Just put this in post, no need to bypass the facade:
foreach(QuoteHedRow qhRow in ds.QuoteHed)
{
int quoteNum = qhRow.QuoteNum;
int quoteLine = 0;
int qtyNum = 0;
string miscCode = "DIS"; //NOTE MINE IS DIFFERENT
string miscDesc = "Disposal Fee";
string miscFreq = "L";
decimal amt = 100M;
bool codeExists = ds.QuoteHedMsc.Any(x => x.QuoteNum == quoteNum && x.QuoteLine == quoteLine && x.MiscCode == miscCode);
if(!codeExists)
{
CallService<Erp.Contracts.QuoteSvcContract>(quoteBO =>
{
QuoteTableset quoteTS = quoteBO.GetByID(quoteNum);
quoteBO.GetNewQuoteHedMsc(ref quoteTS, quoteNum, quoteLine, qtyNum);
//Edit: Removed this line
//QuoteHedMscRow newQuoteHedMscRow = quoteTS.QuoteHedMsc.FirstOrDefault();
//Replaced with this one, so we know we get the new one
QuoteHedMscRow newQuoteHedMscRow = quoteTS.QuoteHedMsc.Where(x => x.SysRowID == Guid.Empty).FirstOrDefault();
newQuoteHedMscRow.MiscCode = miscCode;
newQuoteHedMscRow.Description = miscDesc;
quoteBO.GetMiscChrgDefaults(ref quoteTS, "QuoteHedMsc");
newQuoteHedMscRow.FreqCode = miscFreq;
newQuoteHedMscRow.MiscAmt = amt;
newQuoteHedMscRow.DocMiscAmt = amt;
newQuoteHedMscRow.RowMod = "A";
quoteBO.Update(ref quoteTS);
dsHolder.Attach(quoteTS);
});
}
}
Edit:
//Edit: Removed this line
//QuoteHedMscRow newQuoteHedMscRow = quoteTS.QuoteHedMsc.FirstOrDefault();
//Replaced with this one, so we know we get the new one
QuoteHedMscRow newQuoteHedMscRow = quoteTS.QuoteHedMsc.Where(x => x.SysRowID == Guid.Empty).FirstOrDefault();
@josecgomez , this is the first I’m learning of bypass facade option and it seems very promising. For years I have been littering my bpms with call contextBpmData flags to prevent looping when calling an Update from a Post proc. It’s becoming too much to keep track of all of them.
In researching, I did see Sergey seem to badmouth using this in this thread with @hkeric.wci though… What do you make of that? Is this “safe”?