Skip to main content
Solved

Trying to save custom field from SOShipmentEntry.InvoiceShipment delegate on a new invoice


PorchlightZach
Varsity III
Forum|alt.badge.img

I have custom fields setup on DAC extensions for our sales orders and invoices.  I am trying to update our SOShipmentEntry graph to copy the custom field from the Sales Order to the Invoice that is being created.   

I haven’t added many custom fields to Invoices so I used the customization UI to create the new field.  That new field ended up being added to an extension on ARRegister.  

In the customization I’m working on we already have an InvoiceShipment Delegate setup that is responsible for copying an Address Line 4 for both Billing and Shipping addresses.  This delegate does exactly what it should and has been working for a long time.  

I’ve found a number of other posts here covering a similar concept from the SOOrderEntry side of things but so far haven’t found something that works when invoices are created from SOShipmentEntry.  Given that we’re already successfully copying Address Line 4 to the addresses on invoices, I didn’t think I’d have a big problem making this work.

My problem is that while my code is able to find the SOOrder custom field and set that same value on our ARRegister DAC Extension, the data is not saved to the database.

I’ll share some of my code in case any of that seems like it might be the issue.  For what it is worth, not all of this is my code and was created by our original implementation partner.  I’m going to omit anything not related to this direct issue

DAC Extension for ARRegister

  public class PorchlightARRegisterExt : PXCacheExtension<PX.Objects.AR.ARRegister>
  {    
    #region UsrPBCCustomerPO
    [PXString(255)]
    [PXUIField(DisplayName="Customer PO")]
    public virtual string UsrPBCCustomerPO { get; set; }
    public abstract class usrPBCCustomerPO : PX.Data.BQL.BqlString.Field<usrPBCCustomerPO> { }
    #endregion

  }

SOShipmentEntry Graph Extension
 

        public delegate void InvoiceShipmentDelegate(SOInvoiceEntry docgraph
            , SOShipment shiporder
            , DateTime invoiceDate
            , InvoiceList list
            , PXQuickProcess.ActionFlow quickProcessFlow);



        [PXOverride]
        public void InvoiceShipment(SOInvoiceEntry docgraph
            , SOShipment shiporder
            , DateTime invoiceDate
            , InvoiceList list
            , PXQuickProcess.ActionFlow quickProcessFlow
            , InvoiceShipmentDelegate baseMethod)
        {
            baseMethod(docgraph, shiporder, invoiceDate, list, quickProcessFlow);
            string pxmessagePrefix = "Sales Order -> Shipper -> Invoice Update: ";

            var doc = docgraph.CurrentDocument.Current;
            doc = SetInvoiceCustomerPOs(shiporder, doc, docgraph);
             // Address 4 code for Shipping Address

             // Address 4 code for Billing Address

        }

        private ARInvoice SetInvoiceCustomerPOs(SOShipment shiporder, ARInvoice invoice, SOInvoiceEntry docgraph)
        {
            var invoiceExt = invoice.GetExtension<PorchlightARRegisterExt>();
            if (invoiceExt == null) return invoice;

            if (!string.IsNullOrEmpty(invoiceExt?.UsrPBCCustomerPO)) return invoice;

            var customerPOs = new List<string>();

            foreach (PXResult<SOOrderShipment, SOOrder, CurrencyInfo, SOAddress, SOContact> res in
                     OrderListFromShipper.Select(shiporder.ShipmentNbr, shiporder.ShipmentType))
            {
                var order = (SOOrder)res;
                var orderExt = order.GetExtension<PorchlightSOOrderExt>();

                if (!string.IsNullOrEmpty(orderExt?.UsrPBCCustomerPO))
                {
                    customerPOs.Add(orderExt.UsrPBCCustomerPO);
                }
            }

            if (!customerPOs.Any()) return invoice;

            invoiceExt.UsrPBCCustomerPO = string.Join(", ", customerPOs);

            // This runs fine but does not save data to the ARRegister table in the DB
            invoice = docgraph.CurrentDocument.Update(invoice);
            docgraph.Save.Press();
            return invoice;
        }

Querying the ARRegister table manually with SSMS shows that the custom field is not being populated.  I’m kind of stumped here; this seems like it should work but I’m obviously missing some nuance of working with custom fields and ARRegister plus its derived implementations.

We’re currently on Acumatica 23R1, if that makes a difference.

As an aside, I know sales orders already have a CustomerOrderNbr field that could hold Customer PO numbers.  We’ve been using that field for this very purpose for years.  However, we’re about to move our main web site to Shopify and the connector wants to use CustomerOrderNbr for the Shopify web order information.  This is actually fine for the order types we’re importing from Shopify.

However, it seems that when an export only order type gets sent to Shopify, the CustomerOrderNbr field on the sales order gets overwritten with the Shopify order number, just like the import order type.  This means that for non-web orders we want people to see status updates of on Shopify, any customer PO numbers get overwritten which will be a problem for our corporate customers being billed on account.   So, we need this new alternate field to hold our customer provided PO numbers so they can be exported to the site and still show the customer that number on invoice reports.

Best answer by Django

Hi Zach,

That one is easier. You’re not persisting the field to the database:

[PXString(255)]

Should be:

[PXDBString(255)]

Edit: You should look at Daryl’s post - it’s the better routine to use.

View original
Did this topic help you find an answer to your question?

6 replies

PorchlightZach
Varsity III
Forum|alt.badge.img
  • Author
  • Varsity III
  • 44 replies
  • January 2, 2025

I realized I forgot to include some code used in the example above.  There is a select responsible for loading the orders for a shipment that I will include below:

public PXSelectJoin<SOOrderShipment,
    InnerJoin<SOOrder,
    On<SOOrder.orderType, Equal<SOOrderShipment.orderType>, And<SOOrder.orderNbr, Equal<SOOrderShipment.orderNbr>>>,
    InnerJoin<CurrencyInfo, On<CurrencyInfo.curyInfoID, Equal<SOOrder.curyInfoID>>,
    InnerJoin<SOAddress, On<SOAddress.addressID, Equal<SOOrder.billAddressID>>,
    InnerJoin<SOContact, On<SOContact.contactID, Equal<SOOrder.billContactID>>>>>>,
    Where<SOOrderShipment.shipmentNbr, Equal<Required<SOShipment.shipmentNbr>>,
    And<SOOrderShipment.shipmentType, Equal<Required<SOShipment.shipmentType>>>>> OrderListFromShipper;

OrderListFromShipper and the omitted code related to setting address line 4 were originally written by our implementation partner before we went live with Acumatica (early 2019).


Forum|alt.badge.img+6
  • Captain II
  • 580 replies
  • January 3, 2025

I had a longer reply but it vaporized upon pressing send.

I think the issues is that you want to update Document, not CurrentDocument:

var doc = docgraph.CurrentDocument.Current;

Change that to:

var doc = docgraph.Document.Current;

And then this line:

invoice = docgraph.CurrentDocument.Update(invoice);

Change to:

invoice = docgraph.Document.Update(invoice);

My preference for updating would be:

docgraph.Caches[typeof(ARInvoice)].Update(invoice);

 

Hopefully that’s it!


darylbowman
Captain II
Forum|alt.badge.img+13
PorchlightZach wrote:

...

I’ve found a number of other posts here covering a similar concept from the SOOrderEntry side of things but so far haven’t found something that works when invoices are created from SOShipmentEntry...

 

It is possible to do this for Invoices created from both Orders and Shipments. You need to tap into a method called by both (see here)


PorchlightZach
Varsity III
Forum|alt.badge.img
  • Author
  • Varsity III
  • 44 replies
  • January 3, 2025

@Django Thank you for the reply.  The last bit about using docgraph.Caches was actually something I tried originally but didn’t have luck. 

As it happens, I think I have something else causing my problem.  Last night during testing I noticed that this custom field would not save even if I edited it manually on the Invoices screen (SO303000).  

After I get to the bottom of why this field will not save when edited manually, I’ll retest your suggestion and if it works, I’ll mark it as the best answer. 


Forum|alt.badge.img+6
  • Captain II
  • 580 replies
  • Answer
  • January 3, 2025

Hi Zach,

That one is easier. You’re not persisting the field to the database:

[PXString(255)]

Should be:

[PXDBString(255)]

Edit: You should look at Daryl’s post - it’s the better routine to use.


PorchlightZach
Varsity III
Forum|alt.badge.img
  • Author
  • Varsity III
  • 44 replies
  • January 3, 2025
Django wrote:

Hi Zach,

That one is easier. You’re not persisting the field to the database:

[PXString(255)]

Should be:

[PXDBString(255)]

Edit: You should look at Daryl’s post - it’s the better routine to use.

Wow, I feel a little foolish, I can’t believe I missed this.  I must have copied this custom field definition from one of the unbound DACs in my customization and neglected to fix the PX type definition when renaming the property.  That is what I get for trying to save time, ended up costing me way more than if I had just typed it up by hand.  Sigh.

I had the approach from the link in your earlier reply commented out in my SOInvoiceEntry.  I’ve tried so many different approaches to this, so it was sitting there ready to go.  I uncommented it, recompiled and after a quick test it worked exactly as expected.  Now I have to go clean up all of the other things I’ve tried and commented out.

Thank you so much for your help on this, who knows how long I would have kept trying other approaches before I noticed the simple mistake of not using PXDBString.


Reply


Cookie policy

We use cookies to enhance and personalize your experience. If you accept you agree to our full cookie policy. Learn more about our cookies.

 
Cookie settings