Solved

Easiest way to set ARInvoice custom field value upon creation from multiple source modules

  • 29 March 2023
  • 9 replies
  • 254 views

Badge +11

I am trying to set a custom field during the creation of an ARInvoice from the Sales Order module and the Service Management module. Invoices are created in very different ways in both of these, and I’ve been messing with overriding / extending the methods that perform this process, but it’s not going that well and I’m feeling like I have to be missing something easy.

I thought of doing it in an event on the ARInvoiceEntry page, but I don’t think that really accomplishes the need. I think I could use inserted events on several entry screens, but that doesn’t seem like a shortcut either.

Does anyone have an idea of a better way?

icon

Best answer by darylbowman 31 March 2023, 20:48

View original

9 replies

Userlevel 7
Badge +8

@darylbowman 

I am not familiar with Service Mgmt, what DocType does it generate for ARInvoice?

Badge +11

'INV' but the code is poorly written and it usually needs a .Trim()

Userlevel 7
Badge +8

Do you (I mean Acumatica) have any differentiator in the ARInvoice which is different between Service and SO? For Example, is the InvoiceNbr of both SO and FS following the same numbering sequence or different? If we find a differentiator, we can make it work much easier.

Badge +11

Ah, I see where you're coming from. No, they are the same. And the field value is dependent upon another custom value set for the Order Type for SOs and Service Order Type for Service Orders. So it needs to be connected back to the source document.

Userlevel 7
Badge +8

In this case, your best bet is the SOOrder and Service Order RowPersisted Event (or Persist method). Let the platform do its work and create the Invoice. Then in your Current SO or FS document find the Ref to AR Invoice and update the AR Invoice. If you just to update some fields in ARInvoice from originating docs, you do not need to override the ARInvoice creating methods. 

Badge +11

This is a great idea, but in Events.RowPersisted<SOOrder>, no SOInvoice exists, which is what I need to find the ARInvoice.

I was finding the same thing extending the PrepareInvoice method.

Userlevel 7
Badge +8

What I read from your original post, your actions create the invoice. This means before finally your existing SO or FS documents are saved the invoices are created and the reference is returned to source document and you have the required references.

what is the Action name you want to customize on SO that I can have look with a sample custom field myself. What version you are on?

Badge +11

I am trying to set a custom field during the creation of an ARInvoice from the Sales Order module and the Service Management module.

 

My actions are not creating the Invoices. The Invoices are created during the standard processing. I simply need to set a custom field after the Invoice has been created, but using information from the source document.

Badge +11

After spending much more time on this than I was hoping, here’s my end result:

  1. Override / extend ‘PrepareInvoice’ on SOOrderEntry, adding event handlers on the SOInvoiceEntry graph for ARTran RowInserted and ARInvoice RowPersisting. This allows me to handle events that originate from the SOOrderEntry graph that actually take place in the SOInvoiceEntry graph (code block 1)
  2. I can get the information I need from the inserted (but not yet persisted) ARTran, which I can then set in the RowInserting event of ARInvoice

This all was required because I needed to set a value of an ARInvoice originating from an SOOrder but that had not yet been saved, and therefore couldn’t be found.

public delegate IEnumerable PrepareInvoiceDelegate(PXAdapter adapter);

[PXOverride]
public IEnumerable PrepareInvoice(PXAdapter adapter, PrepareInvoiceDelegate baseMethod)
{
// Adds handlers for SOInvoiceEntry events which orginate from SOOrderEntry
PXGraph.InstanceCreated.AddHandler<SOInvoiceEntry>((graph) =>
{
graph.RowPersisting.AddHandler<ARInvoice>((cache, e) =>
{
var invoice = e.Row as ARInvoice;
if (invoice is null) return;

string invoiceStyle = InvoiceStyle;
cache.SetValue<DSAssignInvoiceStyle_SOOrderType_Ext.usrDSInvoiceStyle>(invoice, invoiceStyle);
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;
string invoiceStyle = GetInvoiceStyle(tran.SOOrderType);
InvoiceStyle = invoiceStyle;
});
});

return baseMethod(adapter);
}

 

Reply


About Acumatica ERP system
Acumatica Cloud ERP provides the best business management solution for transforming your company to thrive in the new digital economy. Built on a future-proof platform with open architecture for rapid integrations, scalability, and ease of use, Acumatica delivers unparalleled value to small and midmarket organizations. Connected Business. Delivered.
© 2008 — 2024  Acumatica, Inc. All rights reserved