Skip to main content
Answer

Copy Custom Field From Sales Order To Invoice When Invoice Created

  • September 11, 2023
  • 7 replies
  • 504 views

I have created a custom field called GTRInvoice in my sales orders table and my invoices table and I would like that field to copy to the invoice when it is created from the sales order. I Cannot find any existing examples of how to do this that show the working code.

I did override the  SOInvoiceEntry InvoiceOrder method but it is not the same as the old examples.

This is what I have

    public delegate void InvoiceOrderDelegate(InvoiceOrderDelegateArgs args);
    [PXOverride]
    public void InvoiceOrder(InvoiceOrderArgs args, InvoiceOrderDelegate baseMethod)
    {
      baseMethod(args);
    }

 

Any help is greatly appreciated.

Best answer by Vignesh Ponnusamy

Hi @TimMarkiw,

You can override the PrepareInvoice method in the SOOrderEntry and AddHandler(from PXGraph) then inject the code to copy the custom field. 

Below is a quick example,

    public class SOOrderEntry_Extension : PXGraphExtension<PX.Objects.SO.SOOrderEntry>
{
#region Event Handlers
public delegate IEnumerable PrepareInvoiceDelegate(PXAdapter adapter);
[PXOverride]
public IEnumerable PrepareInvoice(PXAdapter adapter, PrepareInvoiceDelegate baseMethod)
{
PXGraph.InstanceCreated.AddHandler<SOInvoiceEntry>((invoiceGraph) =>
{
invoiceGraph.RowPersisting.AddHandler<ARRegister>((sender, e) =>
{
ARRegister currentInvoice = (ARRegister)e.Row;
ARRegisterExt registerExt = currentInvoice.GetExtension<ARRegisterExt>();
SOOrderExt orderExt = Base.Document.Cache.GetExtension<SOOrderExt>(Base.Document.Current);
registerExt.UsrGTRInvoice = orderExt.UsrGTRInvoice;
});
});
return baseMethod(adapter);
}
#endregion
}

I have also attached the customization package for reference. 

Good Luck.!

7 replies

Naveen Boga
Captain II
Forum|alt.badge.img+19
  • Captain II
  • September 12, 2023

Hi @TimMarkiw  In the Invoices screen, we have a feasibility to add the Multiple Orders to the Single Invoice. In this case, you wanted to display comma-separated values in the Invoice header section.

 

 


  • Author
  • Freshman I
  • September 12, 2023

Hello Naveen,

 

We will always only put a single sales order on a single invoice so i only need to know how to copy the GTRInvoice field exactly as it is in the sales order being invoiced. 

Thanks

 


Forum|alt.badge.img+9
  • Semi-Pro III
  • September 12, 2023

Hi @TimMarkiw ,

You can use below code snippet to pass custom field from SO to invoice.

    public delegate void PersistDelegate();

[PXOverride]
public void Persist(PersistDelegate baseMethod)
{
baseMethod();
SOOrderEntry soOrderEntryGraph = PXGraph.CreateInstance<SOOrderEntry>();

SOOrder soOrder = soOrderEntryGraph.Document.Current;

if (soOrder != null)
{
ARInvoice arInvoice = new ARInvoice();

// Copy the custom field value from Sales Order to Invoice
arInvoice.GetExtension<ARRegisterExt>().UsrCustomField = soOrder.GetExtension<SOOrderExt>().UsrCustomField ;

Base.ARInvoice_CustomerID_DocType_RefNbr.Cache.Insert(arInvoice);
}
}

Hope, it helps!

Regards,

Sweta


  • Author
  • Freshman I
  • September 13, 2023

@sweta68 

 

Hello Sweta,

I haven’t gotten this to work yet but I wanted to give you an update.

When I add this code

   public delegate void PersistDelegate();

[PXOverride]
public void Persist(PersistDelegate baseMethod)
{
baseMethod();
SOOrderEntry soOrderEntryGraph = PXGraph.CreateInstance<SOOrderEntry>();

SOOrder soOrder = soOrderEntryGraph.Document.Current;

if (soOrder != null)
{
ARInvoice arInvoice = new ARInvoice();

// Copy the custom field value from Sales Order to Invoice
arInvoice.GetExtension<ARRegisterExt>().UsrGTRInvoice = soOrder.GetExtension<SOOrderExt>().UsrGTRInvoice ;

Base.ARInvoice_CustomerID_DocType_RefNbr.Cache.Insert(arInvoice);
} else
{

}
}

to the SOInvoiceEntry the code compiles, published and runs, however the GTRInvoice was not copied across and the soOrder is always null so the if condition is never fulfilled. I added the else for testing and the code within it was always the code that was executed.

I am going to continue to try more things this afternoon and I will let you know if works or if I need further help.

 

Thank You!

 


darylbowman
Captain II
Forum|alt.badge.img+15

Your SOOrder will always be null because soOrderEntryGraph.Document.Current is null in a newly created graph instance.

 

Use:

SOOrder order = soOrderEntryGraph.Document.Search<SOOrder.orderType, SOOrder.orderNbr>(order.OrderType, order.OrderNbr, order.OrderType);

 


Vignesh Ponnusamy
Acumatica Moderator
Forum|alt.badge.img+5
  • Acumatica Moderator
  • Answer
  • September 13, 2023

Hi @TimMarkiw,

You can override the PrepareInvoice method in the SOOrderEntry and AddHandler(from PXGraph) then inject the code to copy the custom field. 

Below is a quick example,

    public class SOOrderEntry_Extension : PXGraphExtension<PX.Objects.SO.SOOrderEntry>
{
#region Event Handlers
public delegate IEnumerable PrepareInvoiceDelegate(PXAdapter adapter);
[PXOverride]
public IEnumerable PrepareInvoice(PXAdapter adapter, PrepareInvoiceDelegate baseMethod)
{
PXGraph.InstanceCreated.AddHandler<SOInvoiceEntry>((invoiceGraph) =>
{
invoiceGraph.RowPersisting.AddHandler<ARRegister>((sender, e) =>
{
ARRegister currentInvoice = (ARRegister)e.Row;
ARRegisterExt registerExt = currentInvoice.GetExtension<ARRegisterExt>();
SOOrderExt orderExt = Base.Document.Cache.GetExtension<SOOrderExt>(Base.Document.Current);
registerExt.UsrGTRInvoice = orderExt.UsrGTRInvoice;
});
});
return baseMethod(adapter);
}
#endregion
}

I have also attached the customization package for reference. 

Good Luck.!


  • Author
  • Freshman I
  • September 21, 2023

Here is my final code mostly taken from a post by @darylbowman  

 

  public static string GTRInvoiceNumber = "";
#region Event Handlers
public delegate IEnumerable PrepareInvoiceDelegate(PXAdapter adapter);

[PXOverride]
public IEnumerable PrepareInvoice(PXAdapter adapter, PrepareInvoiceDelegate baseMethod)
{
PXGraph.InstanceCreated.AddHandler<SOInvoiceEntry>((graph) =>
{
graph.RowPersisting.AddHandler<ARInvoice>((cache, e) =>
{
var invoice = e.Row as ARInvoice;
if (invoice is null) return;
string gtrInvoiceNumber = GTRInvoiceNumber;
cache.SetValue<ARRegisterExt.usrGTRInvoice>(invoice, gtrInvoiceNumber);
cache.Update(invoice);
});
graph.RowInserted.AddHandler<ARTran>((cache, e) =>
{
var tran = e.Row as ARTran;
if (tran is null) return;
var invoice = graph.Caches[typeof(ARInvoice)].Current as ARInvoice;
ARRegisterExt registerExt = invoice.GetExtension<ARRegisterExt>();
SOOrderExt orderExt = Base.Document.Cache.GetExtension<SOOrderExt>(Base.Document.Current);
GTRInvoiceNumber = orderExt.UsrGTRInvoice;
});
});
return baseMethod(adapter);
}
#endregion

 

 

Thank you all for your help.