Transferring BasePart_c and Dimension_c from Quotes to Sales Order when creating Order from Quote

Hi everyone,

I am hoping someone can help me with an issue I am experiencing in Epicor Kinetic (SaaS/Cloud environment).

Background

We have two custom UD fields on our Quote lines — BasePart_c and Dimension_c — that were added as part of our system customization. These fields are stored directly on QuoteDtl and displayed on the form. We also have the same fields on OrderDtl for display on the Sales Order lines.

The values for these fields are selected by users from a dropdown that pulls from a UD04 lookup table, but once selected, the values are stored directly on QuoteDtl.

The Problem

When a Sales Order is created from a Quote using our Quote Order Wizard (a custom App Studio implementation), BasePart_c and Dimension_c are blank on the newly created Sales Order lines. We confirmed this by querying OrderDtl directly in a BAQ — the fields are empty after order creation.

We understand this is because Epicor’s native quote-to-order conversion only copies standard fields and has no awareness of custom UD fields.

What We Have Investigated

  • The Quote Order Wizard is a locked App Studio customization — we cannot edit it directly
  • There are no existing Method Directives on Erp.QuoteOrder or any CreateOrder method in our BPM list
  • The wizard calls Epicor’s standard REST endpoints (Quote.CreateOrderFromQuote and Quote.CreateOrderFromQuoteSaveOTS) behind the scenes
  • We found the following code that looks promising as a Post-Processing Method Directive on Erp.BO.SalesOrder.Update:

c#

foreach (var od in ttOrderDtl.Where(x => x.RowMod == "A" && x.QuoteNum != 0))
{
    var qd = Db.QuoteDtl.FirstOrDefault(x => 
        x.Company == CompanyID &&
        x.QuoteNum == od.QuoteNum &&
        x.QuoteLine == od.QuoteLine);

    if (qd != null)
    {
        Action<string> udCopy = col =>
        {
            if (col.EndsWith("_c"))
            {
                od[col] = qd[col];
            }
        };

        qd.GetType()
          .GetProperties()
          .Select(s => s.Name)
          .ToList()
          .ForEach(udCopy);
    }
}

My Questions

  1. Is a Post-Processing Method Directive on Erp.BO.SalesOrder.Update the right approach for this, or is there a better method to hook into?
  2. Is the code above correct and complete for this use case, or does it need any adjustments?
  3. Are there any known gotchas with copying UD fields this way in a SaaS/Cloud environment?
  4. Has anyone solved a similar issue and can share what worked for them?

Any guidance would be greatly appreciated. Thank you in advance!

Try this link

Ok, Thanks very much, I will try this out

That looks familiar, I believe that code was designed for an In-Tran Data Directive though.

That code specifically copies UD Fields in QuoteDtl & OrderDtl with identical names. As long as the UD Fields have the same name (e.g. QuoteDtl.BasePart_c to OrderDtl.OrigPart_c won’t work).

So in my original post where I wrote that script, I was running into an issue that if a field existed in QuoteDtlUD but not OrderDtlUD, it would throw an error. It should work without issue if you add a try/catch around the copy.

var odList = ttOrderDtl.Where( x => x.RowMod=="A" && x.QuoteNum!=0 );

foreach ( var od in odList ) 
{
    var qd = Db.QuoteDtl
        .Where(x => x.Company == CompanyID
                && x.QuoteNum == od.QuoteNum
                && x.QuoteLine == od.QuoteLine)
        .FirstOrDefault();


    if ( od != null && qd != null ) 
    {

        Action<string> udCopy = col => 
        {
            if ( col.EndsWith("_c") )
            {
                try 
                {
                    od[col] = qd[col];
                }
                catch {}
            } 
        };

        qd.GetType().GetProperties().Select(s => s.Name).ToList().ForEach(udCopy);
    }
}

Thanks so much, So in my case, I have the same column names both in Quote and OrderDtl

This script should work then. That’s exactly what I used it for; I had dozens of UD fields with matching names in Quote and OrderDtl. Putting it on the data directive makes sure it gets copied any time an OrderDtl record is created from a QuoteDtl record.