Copy UD fields from Quote header to order header when converting quote to order

How do I add messages to show what it is doing? Just a message box saying that it processed this particular chunk of data?

string body = “Here I am”;
this.PublishInfoMessage(body,Ice.Common.BusinessObjectMessageType.Information, Ice.Bpm.InfoMessageDisplayMode.Individual, “OrderDtl”, “Update”);

And you can place these throughout the code and only change the body string message

It never makes it into the foreach loop. Why is the callContextBpmData.Number01 used for the QuoteNum? Is that actually the case or was that something specific to your scenario?

I was probaby setting ccNumber01 to the specific quote num outside of the custom code. But you’re saying it doesn’t get to the foreach loop which means that order num is still 0.

sorry I misread; you’re in the loop but ccNumber01 isn’t set. That’s why its not looping, because theres no join to any meaningful information if cc isn’t set.

How can I link the quotenum without using a cc field?

So, when testing, it gets past the "if (orderNum != 0) and then loops 3 times with my message just after the if, but before the foreach.

After additional testing and modifying my code, I have it where I can see that both of the fields show my test data, but after the Quote to Order wizard completes, it does not save the data to the OrderDtl field.
I made my modifications based on the following post:

Erp.Tables.OrderDtl OrderDtl;
Erp.Tables.QuoteDtl QuoteDtl;

var orderRow = ttOrderDtl.FirstOrDefault();

foreach (var QuoteDtl_iterator in (from QuoteDtl_Row in Db.QuoteDtl where QuoteDtl_Row.Company == orderRow.Company && QuoteDtl_Row.QuoteNum == orderRow.QuoteNum && QuoteDtl_Row.QuoteLine == orderRow.QuoteLine select QuoteDtl_Row))
{
foreach (var OrderDtl_iterator in (from OrderDtl_Row in Db.OrderDtl where OrderDtl_Row.Company == orderRow.Company && OrderDtl_Row.OrderNum == orderRow.OrderNum && OrderDtl_Row.OrderLine == orderRow.OrderLine select OrderDtl_Row))
{
string body = QuoteDtl_iterator.MachineMake.ToString();
this.PublishInfoMessage(body, Ice.Common.BusinessObjectMessageType.Information, Ice.Bpm.InfoMessageDisplayMode.Individual, “OrderDtl”, “Update”);

OrderDtl_iterator.MachineMake = QuoteDtl_iterator.MachineMake;

string body2 = OrderDtl_iterator.MachineMake.ToString();
this.PublishInfoMessage(body2, Ice.Common.BusinessObjectMessageType.Information, Ice.Bpm.InfoMessageDisplayMode.Individual, "OrderDtl", "Update");

}
}

Remember that my scenario was different; I was building mine off of a method directive that had access to the quote num (it was CreateSalesOrderFromQuote or somthing). Yours is a data directive on QuoteDtl., which is just monitoring when QuoteDtl gets updated. You’ll have to find a way to query the quote in question to return a quote num, but without knowing your specific business problem it’s a little hard to tell you.

1 Like

I finally had time to go back and test this out using the Method Directive for Quote.CreateOrder and it works beautifully! Here are some more details for anyone else that may need help getting it working:

Pre-Processing Directive:

Post-Processing Directive:
image

Post-Processing Directive Code:
Erp.Tables.OrderDtl OrderDtl;
Erp.Tables.QuoteDtl QuoteDtl;

int LineNum = 1;
if (orderNum != 0)
{
//The below 2 lines will help with debugging to make sure it is processing properly
//string body = “1 - An orderNum exists.”;
//this.PublishInfoMessage(body,Ice.Common.BusinessObjectMessageType.Information, Ice.Bpm.InfoMessageDisplayMode.Individual, “Quote”, “CreateOrder”);

foreach (var QuoteDtl_iterator in (from QuoteDtl_Row in Db.QuoteDtl where QuoteDtl_Row.Company == Session.CompanyID && QuoteDtl_Row.QuoteNum == callContextBpmData.Number01 select QuoteDtl_Row))
{
//The below 2 lines will help with debugging to make sure it is processing properly
//string body2 = “2 - Starting foreach section.”;
//this.PublishInfoMessage(body2,Ice.Common.BusinessObjectMessageType.Information, Ice.Bpm.InfoMessageDisplayMode.Individual, “Quote”, “CreateOrder”);

QuoteDtl = QuoteDtl_iterator;

OrderDtl = (from OrderDtl_Row in Db.OrderDtl where OrderDtl_Row.Company == Session.CompanyID && OrderDtl_Row.OrderNum == orderNum && OrderDtl_Row.OrderLine == LineNum select OrderDtl_Row).FirstOrDefault();

if (OrderDtl != null)
{
  //The below 2 lines will help with debugging to make sure it is processing properly
  //string body3 = "3 - OrderDtl is not null.";
  //this.PublishInfoMessage(body3,Ice.Common.BusinessObjectMessageType.Information, Ice.Bpm.InfoMessageDisplayMode.Individual, "Quote", "CreateOrder");

  OrderDtl["FieldName"] = QuoteDtl["FieldName"];
  //Db.OrderDtl.Update(OrderDtl);      
  LineNum++;
}

}
}

If I read the title - havent read the whole thread - you can do that with UD Field Maps, no need for BPM, if I recall there is a QuoteHed to OrderHed Mapping you can set.

Mine was for UD fields going from QuoteDtl to OrderDtl. Also, I am on 10.2.200.15 and I was not able to find any UD Field Map for Quote to Order of any kind. Maybe I missed it?

1 Like

There is not a field mapping for QuoteHed to OrderHed. You would think there was but there is not. I opened a case, & they converted to a problem but in the end they (Epicor development) closed the problem without resolution. I have to look back to see what there official answer was. I have not persured it further, but will be looking at writing the custom code solution to bring about 6 UD fields over from QuoteHed to OrderHed. When We first looked at this project we were on 10.1.400.38, we are now on 10.2.300.15 still no predefiend mapping from Epicor.

1 Like

Hello Bart, did this ever get added, I’m using 10.2.400.13 and can’t see it

Lawson, We reported this, it got escalated to a problem (PRB0191667) but was then “rejected” without any further correspondence or reasons given (reminding me of the soup Nazi on Seinfeld…NO SOLUTION FOR YOU…lol) We are testing 10.2.600.4 not there either. I ended up adding custom code to copy the fields over from quote to sales order when converting the quote.

hmm sounds like a good place for a function… one that could even be shared.

Andrew, I think it’s maybe because most things in Epicor are based on individual lines…
Although we can convert a quote to a sales order we can also pull in lines from multibale quotes to the same sales order

Andrew, I’d also be interested in having a look at your custom code, the ttOrder doesn’t seem to be available in the pre and post method directives when using the CreateOrder directive

Sorry for the delay. here is the Custom Code I have inserted in (2) method directives:

Code Block

Erp.Tables.OrderHed OrderHed;
Erp.Tables.QuoteHed QuoteHed;
var ttOrderHedRow = (from ttOrderHed_Row in ttOrderHed
            where string.Compare(ttOrderHed_Row.Company, Session.CompanyID, true) == 0
            select ttOrderHed_Row).FirstOrDefault();
if (ttOrderHedRow != null)
{
    OrderHed = (from OrderHed_Row in Db.OrderHed
                where string.Compare(OrderHed_Row.Company, Session.CompanyID, true) == 0
                  && OrderHed_Row.OrderNum == ttOrderHedRow.OrderNum
                select OrderHed_Row).FirstOrDefault();
    if (OrderHed != null)
    {
        QuoteHed = (from QuoteHed_Row in Db.QuoteHed
                    where string.Compare(QuoteHed_Row.Company, Session.CompanyID, true) == 0
                      && QuoteHed_Row.QuoteNum == iQuoteNum
                    select QuoteHed_Row).FirstOrDefault();
        if (QuoteHed != null)
        {
            OrderHed.Industry_Type_c = QuoteHed.Industry_Type_c;
            OrderHed.Industry_Seg_c = QuoteHed.Industry_Seg_c;
            OrderHed.Character01 = QuoteHed.Character01;
            OrderHed.Character02 = QuoteHed.QuotedTo_c;
            OrderHed.Character03 = QuoteHed.QuoteToEmail_c;
            OrderHed.Character04 = QuoteHed.ModelNoRef_c;
            OrderHed.Character05 = QuoteHed.SerialNoRef_c;
            OrderHed.Forecasted_c = QuoteHed.Forecasted_c;
            //OrderHed.MkgtDiscvrExt_c = QuoteHed.MkgtDiscvrExt_c;
            OrderHed.CheckBox03 = QuoteHed.NewProj_c;
            OrderHed.CheckBox04 = QuoteHed.RepProj_c;
        }
    }
}

I have that cusotm code on these two method directives:
Erp.Quote.CreateOrder
and Erp.SalesOrder.CreateOrderFromQuote.

I use the below code as an In Transaction Data Directive on the OrderDtl to copy UD fields from the quote when creating an order. You can adjust it to your needs. It may not be the best way but it works for me.

Erp.Tables.QuoteDtl QuoteDtl;
foreach (var ttOrderDtl_iterator in (from ttOrderDtl_Row in ttOrderDtl
         where ttOrderDtl_Row.Company == Session.CompanyID
					&& string.Equals(ttOrderDtl_Row.RowMod, IceRow.ROWSTATE_ADDED, StringComparison.OrdinalIgnoreCase)
					&& ttOrderDtl_Row.QuoteNum != 0
					&& ttOrderDtl_Row.QuoteLine != 0
          select ttOrderDtl_Row))
{
    var ttOrderDtlRow = ttOrderDtl_iterator;
    QuoteDtl = (from QuoteDtl_Row in Db.QuoteDtl
         where QuoteDtl_Row.Company == Session.CompanyID
					&& QuoteDtl_Row.QuoteNum == ttOrderDtlRow.QuoteNum
					&& QuoteDtl_Row.QuoteLine == ttOrderDtlRow.QuoteLine
          select QuoteDtl_Row).FirstOrDefault();
		if (QuoteDtl != null)
			{
			ttOrderDtlRow["Character01"] = (string)QuoteDtl["Character01"];
			ttOrderDtlRow["Character02"] = (string)QuoteDtl["Character02"];
			ttOrderDtlRow["Character03"] = (string)QuoteDtl["Character03"];
			ttOrderDtlRow["FormattedRefs_c"] = (string)QuoteDtl["FormattedRefs_c"];
			ttOrderDtlRow["Number04"] = QuoteDtl["Number04"];
			ttOrderDtlRow.ShipComment = (string)QuoteDtl["FormattedRefs_c"];
			if (QuoteDtl.AnalysisCode == "RWK")
				{
					ttOrderDtlRow.Rework = true;
				}
			ttOrderDtlRow["CheckBox03"] = (bool)QuoteDtl["CheckBox03"];        
			ttOrderDtlRow["Character05"] = QuoteDtl.OriginalPartNo_c;        
			ttOrderDtlRow["DrawingNumber_c"] = (string)QuoteDtl.DrawNum;
			ttOrderDtlRow["CheckBox02"] = (bool)QuoteDtl["CheckBox02"];				       
			QuoteDtl["CheckBox06"] = true;
			Db.Validate();
			}
}

Best regards
Adrian.

2 Likes