Good afternoon good people. What I’m trying to do is when a user creates a new quote, a new line item is automatically added through a BPM Method Directive. I’ve created the directive on Erp.Quote.GetNewQuoteHed in Post-Processing. That way the quote would be created and I could use that number to populate the new line in the QuoteDtl table. But, after I create a new Quote, nothing happens. My code is below. Can anyone point me in a direction with this? Thank you for your time and any help you can provide!
var quotHed = (from row in ttQuoteHed
where row.Added() || row.Updated()
select row).FirstOrDefault();
if (quotHed == null)
return;
var proj = (from row in Db.Project
where row.ProjectID == quotHed["ProjectID_c"]
select row).FirstOrDefault();
var ts = new Erp.Tablesets.QuoteTableset();
// Insert "Code Research" line with $75 price into the QuoteDtl table...
using(var svc = Ice.Assemblies.ServiceRenderer.GetService<Erp.Contracts.QuoteSvcContract>(Db))
{
var newPart = (from row in Db.Part
where row.PartNum == "CODE_RESEARCH"
select row).FirstOrDefault();
svc.GetNewQuoteDtl(ref ts, quotHed.QuoteNum);
var quoteNew = ts.QuoteDtl.FirstOrDefault();
quoteNew.QuoteNum = quotHed.QuoteNum;
quoteNew.PartNum = newPart.PartNum;
quoteNew.LineDesc = newPart.PartDescription;
quoteNew.ProdCode = newPart.ProdCode;
quoteNew.TaxCatID = newPart.TaxCatID;
quoteNew.CustNum = quotHed.CustNum;
quoteNew.SellingExpectedQty = 1;
quoteNew.SellingExpectedUM = "EA";
quoteNew.LastUpdate = DateTime.Now;
quoteNew.LastDcdUserID = callContextClient.CurrentUserId;
quoteNew.OrderQty = 1;
quoteNew.SellingExpFactor = 1;
quoteNew.SalesCatID = proj.SalesCatID;
quoteNew.TerritoryID = quotHed.TerritoryID;
quoteNew.CurrentStage = quotHed.CurrentStage;
quoteNew.CreatedFrom = "QUOTE";
quoteNew.ExpPricePerCode = "E";
quoteNew.MiscQtyNum = 1;
//quoteNew.KitParentLine = ;
//quoteNew.DisplaySeq = ;
quoteNew.ProjectID = proj.ProjectID;
//quoteNew.SellingFactorDirection = ;
quoteNew.ChangedBy = quotHed.ChangedBy;
quoteNew.ChangeDate = quotHed.ChangeDate;
quoteNew.ChangeTime = quotHed.ChangeTime;
quoteNew.LineType = "PART";
quoteNew.Warranty = true;
quoteNew.ProcessMode = "S";
svc.Update(ref ts);
}
Thank you @TomAlexander! I switched over to Quote.Update and added a small directive on the pre-proc side that looked for “at least one added row in the ttQuoteTable” and then enabled the Post Directive. On the post proc side, I added a “Set BPM Data Field” module that assigned the new QuoteNum to Number01. I did this because in my code, it was assigning the previous QuoteNum and not the current one in this block of code…
var quotHed = (from row in ttQuoteHed
where row.Added() || row.Updated()
select row).FirstOrDefault();
I changed the code a little (see below) to handle the changes above.
var quotHed = (from row in Db.QuoteHed
where row.QuoteNum == callContextBpmData.Number01
select row).FirstOrDefault();
if (quotHed == null)
return;
string projid = quotHed["ProjectID_c"].ToString();//Assign custom field to variable to avoid errors
var proj = (from row in Db.Project
where row.ProjectID == projid
select row).FirstOrDefault();
var ts = new Erp.Tablesets.QuoteTableset();
// Insert "Code Research" line with $75 price into the QuoteDtl table...
using(var svc = Ice.Assemblies.ServiceRenderer.GetService<Erp.Contracts.QuoteSvcContract>(Db))
{
var newPart = (from row in Db.Part
where row.PartNum == "CODE_RESEARCH"
select row).FirstOrDefault();
svc.GetNewQuoteDtl(ref ts, quotHed.QuoteNum);
var quoteNew = ts.QuoteDtl.FirstOrDefault();
quoteNew.QuoteNum = quotHed.QuoteNum;
quoteNew.PartNum = newPart.PartNum;
quoteNew.LineDesc = newPart.PartDescription;
quoteNew.ProdCode = newPart.ProdCode;
quoteNew.TaxCatID = newPart.TaxCatID;
quoteNew.CustNum = quotHed.CustNum;
quoteNew.SellingExpectedQty = 1;
quoteNew.SellingExpectedUM = "EA";
quoteNew.LastUpdate = DateTime.Now;
quoteNew.LastDcdUserID = callContextClient.CurrentUserId;
quoteNew.OrderQty = 1;
quoteNew.SellingExpFactor = 1;
quoteNew.SalesCatID = proj.SalesCatID;
quoteNew.TerritoryID = quotHed.TerritoryID;
quoteNew.CurrentStage = quotHed.CurrentStage;
quoteNew.CreatedFrom = "QUOTE";
quoteNew.ExpPricePerCode = "E";
quoteNew.MiscQtyNum = 1;
quoteNew.ProjectID = proj.ProjectID;
quoteNew.ChangedBy = quotHed.ChangedBy;
quoteNew.ChangeDate = quotHed.ChangeDate;
quoteNew.ChangeTime = quotHed.ChangeTime;
quoteNew.LineType = "PART";
quoteNew.Warranty = true;
quoteNew.ProcessMode = "S";
svc.Update(ref ts);
}
This worked perfectly! But now I need to find a way to auto-refresh the Quote Entry form so show the newly added line item.
Awesome! The refresh part is easy. I am on mobile and forget the exact syntax, but search this site for “this.dsholder.attach” or something like that. You will find many examples of how to use it
@TomAlexander I tried using “this.dsHolder.Attach(ts);”, along with similar code I used above, in a Data Directive for QuoteDtl in the In-Transaction. Everything checks out when I click the Check Syntax button, except it gives the following error for the dsHolder portion…
CS1061 'FakeDirective' does not contain a definition for 'dsHolder' and no extension method 'dsHolder' accepting a first argument of type 'FakeDirective' could be found (are you missing a using directive or an assembly reference?)
Any ideas why this works in a Method Directive and not a Data Directive?
I’m not sure I have a strong enough understanding of dsHolder to articulate why it seems to work in method directives but not data directives. But at a very vague/high level I would say it’s because method directives are more intertwined with the client. Data directives are more like database triggers.
You are correct.
There is no DSHolder that can be replaced on a DataDirective
Data Directive rows lower Level (DB Level) while DS holder refers to the Epicor DataSet (business object data set)