Skip to main content
Solved

Copy UDF from PO Line to AP Invoice when entering AP Bill from PO


Forum|alt.badge.img
  • Freshman I
  • 12 replies

Could someone please help in providing a solution of moving the UDF from PO into AP Invoice?

I am new to developing in acumatica. I have created the user defined fields in POLine and APTran.

While reviewing the source of APInvoiceEntry, I looked at overriding the method CopyCustomizationFieldsToAPTran.

Code I added is below.

public void CopyCustomizationFieldsToAPTran(APTran apTranToFill, IAPTranSource poSourceLine, Boolean areCurrenciesSame, CopyCustomizationFieldsToAPTranDelegate baseMethod)
    {
  
      baseMethod(apTranToFill,poSourceLine,areCurrenciesSame);

      var portID = poSourceLine.GetExtension<POLineExt>()?.UsrPortID;
      var tranline = apTranToFill?.GetExtension<APTranExt>()?.UsrPortID;         
      
      if (tranline != null && portID != null ) tranline.UsrPortID = portID;

    }

I am getting validation errors when I try to publish.

error CS1929: 'IAPTranSource' does not contain a definition for 'GetExtension' and the best extension method overload 'PXCacheEx.GetExtension<POLineExt>(IBqlTable)' requires a receiver of type 'IBqlTable'
error CS1061: 'string' does not contain a definition for 'UsrPortID' and no accessible extension method 'UsrPortID' accepting a first argument of type 'string' could be found (are you missing a using directive or an assembly reference?)
error CS1929: 'IAPTranSource' does not contain a definition for 'GetExtension' and the best extension method overload 'PXCacheEx.GetExtension<POLineExt>(IBqlTable)' requires a receiver of type 'IBqlTable'

Am I using the correct method to accomplish the task?

Best answer by Vignesh Ponnusamy

Hi @lnd74,

Adding to @darylbowman suggestions.

You can also override the CreateAPInvoice method and add the RowInserting event handler for APTran DAC like below copy the custom fields,

 public class POOrderEntry_Extension : PXGraphExtension<PX.Objects.PO.POOrderEntry>
    {
        #region Event Handlers
        public delegate IEnumerable CreateAPInvoiceDelegate(PXAdapter adapter);
        [PXOverride]
        public IEnumerable CreateAPInvoice(PXAdapter adapter, CreateAPInvoiceDelegate baseMethod)
        {
            PXGraph.InstanceCreated.AddHandler<APInvoiceEntry>((invoiceEntryGraph) =>
            {
                invoiceEntryGraph.RowInserting.AddHandler<APTran>((sender, e) =>
                {
                    APTran apTran = (APTran)e.Row;
                    APTranExt apTranExt = apTran.GetExtension<APTranExt>();
                    POLine poLine = PXSelect<POLine, Where<POLine.orderType, Equal<Required<APTran.pOOrderType>>,
                        And<POLine.orderNbr, Equal<Required<APTran.pONbr>>,
                        And<POLine.lineNbr, Equal<Required<APTran.pOLineNbr>>>>>>.Select(Base, apTran.POOrderType, apTran.PONbr, apTran.POLineNbr);
                    if (poLine != null)
                    {
                        POLineExt poLineExt = poLine.GetExtension<POLineExt>();
                        apTranExt.UsrPortID = poLineExt.UsrPortID;
                    }
                });
            }
            );
            return baseMethod(adapter);
        }
        #endregion
    }

Feel free to post back if you have any questions. Happy coding.!

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

27 replies

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

Try casting poSourceLine as POLine:

POLine sourceLine = poSourceLine as POLine;

var portID = sourceLine.GetExtension<POLineExt>()?.UsrPortID;

 


Forum|alt.badge.img
  • Author
  • Freshman I
  • 12 replies
  • August 6, 2024

Thank you!

Now I am getting the error below.

error CS1061: 'string' does not contain a definition for 'UsrPortID' and no accessible extension method 'UsrPortID' accepting a first argument of type 'string' could be found (are you missing a using directive or an assembly reference?)

Am I missing something in my DAC?

public class POLineExt : PXCacheExtension<PX.Objects.PO.POLine>
    {
        #region UsrPortID
        [PXSelector(typeof(Search<XY_Ports.XY_Port.name,Where<XY_Ports.XY_Port.isActive, Equal<True>>>),typeof(XY_Ports.XY_Port.description))]
        [PXDBString(10)]
        [PXUIField(DisplayName="Port")]
        public virtual string UsrPortID { get; set; }
        public abstract class usrPortID : PX.Data.BQL.BqlString.Field<usrPortID> { }
        #endregion
    }

public class APTranExt : PXCacheExtension<PX.Objects.AP.APTran>
    {
        #region UsrPortID
        [PXSelector(typeof(Search<XY_Ports.XY_Port.name,Where<XY_Ports.XY_Port.isActive, Equal<True>>>),typeof(XY_Ports.XY_Port.description))]
        [PXDBString(10)]
        [PXUIField(DisplayName="Port")]
        public virtual string UsrPortID { get; set; }
        public abstract class usrPortID : PX.Data.BQL.BqlString.Field<usrPortID> { }
        #endregion
    }


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

Do

var tranline = apTranToFill?.GetExtension<APTranExt>();

instead of 

var tranline = apTranToFill?.GetExtension<APTranExt>()?.UsrPortID;

 


Forum|alt.badge.img
  • Author
  • Freshman I
  • 12 replies
  • August 6, 2024

Thanks!

I really appreciate you help.

I am getting the following GetItemExtension failed on trace.

 

 


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

Could you post your code please?


Forum|alt.badge.img
  • Author
  • Freshman I
  • 12 replies
  • August 6, 2024

 public class APInvoiceEntry_Extension : PXGraphExtension<PX.Objects.AP.APInvoiceEntry>
  {
    public delegate void CopyCustomizationFieldsToAPTranDelegate(APTran apTranToFill, IAPTranSource poSourceLine, Boolean areCurrenciesSame);
    [PXOverride]
    public void CopyCustomizationFieldsToAPTran(APTran apTranToFill, IAPTranSource poSourceLine, Boolean areCurrenciesSame, CopyCustomizationFieldsToAPTranDelegate baseMethod)
    {
  
  
      baseMethod(apTranToFill,poSourceLine,areCurrenciesSame);

      POLine sourceLine = poSourceLine as POLine;

      var portID = sourceLine.GetExtension<POLineExt>()?.UsrPortID;

      var tranline = apTranToFill?.GetExtension<APTranExt>();       
      
      if (tranline != null && portID != null ) tranline.UsrPortID = portID;

    }
 
  }


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

Use this instead:

var portID = sourceLine?.GetExtension<POLineExt>()?.UsrPortID;

 


Vignesh Ponnusamy
Acumatica Moderator
Forum|alt.badge.img+5

Hi @lnd74,

Adding to @darylbowman suggestions.

You can also override the CreateAPInvoice method and add the RowInserting event handler for APTran DAC like below copy the custom fields,

 public class POOrderEntry_Extension : PXGraphExtension<PX.Objects.PO.POOrderEntry>
    {
        #region Event Handlers
        public delegate IEnumerable CreateAPInvoiceDelegate(PXAdapter adapter);
        [PXOverride]
        public IEnumerable CreateAPInvoice(PXAdapter adapter, CreateAPInvoiceDelegate baseMethod)
        {
            PXGraph.InstanceCreated.AddHandler<APInvoiceEntry>((invoiceEntryGraph) =>
            {
                invoiceEntryGraph.RowInserting.AddHandler<APTran>((sender, e) =>
                {
                    APTran apTran = (APTran)e.Row;
                    APTranExt apTranExt = apTran.GetExtension<APTranExt>();
                    POLine poLine = PXSelect<POLine, Where<POLine.orderType, Equal<Required<APTran.pOOrderType>>,
                        And<POLine.orderNbr, Equal<Required<APTran.pONbr>>,
                        And<POLine.lineNbr, Equal<Required<APTran.pOLineNbr>>>>>>.Select(Base, apTran.POOrderType, apTran.PONbr, apTran.POLineNbr);
                    if (poLine != null)
                    {
                        POLineExt poLineExt = poLine.GetExtension<POLineExt>();
                        apTranExt.UsrPortID = poLineExt.UsrPortID;
                    }
                });
            }
            );
            return baseMethod(adapter);
        }
        #endregion
    }

Feel free to post back if you have any questions. Happy coding.!


Forum|alt.badge.img
  • Author
  • Freshman I
  • 12 replies
  • August 6, 2024

To @darylbowman  I am still having the same issue with GetExtension Failed. Code is below.

 public class APInvoiceEntry_Extension : PXGraphExtension<PX.Objects.AP.APInvoiceEntry>
  {
    public delegate void CopyCustomizationFieldsToAPTranDelegate(APTran apTranToFill, IAPTranSource poSourceLine, Boolean areCurrenciesSame);
    [PXOverride]
    public void CopyCustomizationFieldsToAPTran(APTran apTranToFill, IAPTranSource poSourceLine, Boolean areCurrenciesSame, CopyCustomizationFieldsToAPTranDelegate baseMethod)
    {
  
  
      baseMethod(apTranToFill,poSourceLine,areCurrenciesSame);

      POLine sourceLine = poSourceLine as POLine;

      var portID = sourceLine?.GetExtension<POLineExt>()?.UsrPortID;
      
      var tranline = apTranToFill?.GetExtension<APTranExt>();       
      
      if (tranline != null && portID != null ) tranline.UsrPortID = portID;

    }
 
  }

To @Vignesh Ponnusamy I will also try your solution.

 

 


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

Sorry, I led you astray in several ways. POLine is not a IAPTranSource, neither is POReceiptLine. But POReceiptLineS is and you should be able to get the POLine from there.

Update, see below:

 


darylbowman
Captain II
Forum|alt.badge.img+13
public class APInvoiceEntry_Extension : PXGraphExtension<PX.Objects.AP.APInvoiceEntry>
{
    public delegate void CopyCustomizationFieldsToAPTranDelegate(APTran apTranToFill, IAPTranSource poSourceLine, Boolean areCurrenciesSame);
    [PXOverride]
    public void CopyCustomizationFieldsToAPTran(APTran apTranToFill, IAPTranSource poSourceLine, Boolean areCurrenciesSame, CopyCustomizationFieldsToAPTranDelegate baseMethod)
    {  
        baseMethod(apTranToFill,poSourceLine,areCurrenciesSame);

        POReceiptLineS sourceLineS = poSourceLine as POReceiptLineS;
        POLine sourceLine = POLine.PK.Find(this, sourceLineS?.POType, sourceLineS?.PONbr, sourceLineS?.POLineNbr);

        var portID = sourceLine?.GetExtension<POLineExt>()?.UsrPortID;

        var tranline = apTranToFill?.GetExtension<APTranExt>();       

        if (tranline != null && portID != null ) tranline.UsrPortID = portID;
    }
}

 


Forum|alt.badge.img
  • Author
  • Freshman I
  • 12 replies
  • August 6, 2024

I get a different validation error from the following code.

 

public class APInvoiceEntry_Extension : PXGraphExtension<PX.Objects.AP.APInvoiceEntry>
  {
    #region Event Handlers
    public delegate void CopyCustomizationFieldsToAPTranDelegate(APTran apTranToFill, IAPTranSource poSourceLine, Boolean areCurrenciesSame);
    [PXOverride]
    public void CopyCustomizationFieldsToAPTran(APTran apTranToFill, IAPTranSource poSourceLine, Boolean areCurrenciesSame, CopyCustomizationFieldsToAPTranDelegate baseMethod)
    {
      baseMethod(apTranToFill,poSourceLine,areCurrenciesSame);

        POReceiptLineS sourceLineS = poSourceLine as POReceiptLineS;
        POLine sourceLine = POLine.PK.Find(this, sourceLineS?.POType, sourceLineS?.PONbr, sourceLineS?.POLineNbr);

        var portID = sourceLine?.GetExtension<POLineExt>()?.UsrPortID;

        var tranline = apTranToFill?.GetExtension<APTranExt>();       

        if (tranline != null && portID != null ) tranline.UsrPortID = portID;


    }


    #endregion
  }

 

 

\App_RuntimeCode\APInvoiceEntry.cs(64): error CS1503: Argument 1: cannot convert from 'PX.Objects.AP.APInvoiceEntry_Extension' to 'PX.Data.PXGraph'

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

Change 'this' to 'Base' in 

POLine sourceLine = POLine.PK.Find(this, sourceLineS?.POType, sourceLineS?.PONbr, sourceLineS?.POLineNbr);


Forum|alt.badge.img
  • Author
  • Freshman I
  • 12 replies
  • August 6, 2024

It now compliles properly, but still gets the GetItemExtension Error.

 

Code below.

#region Event Handlers
    public delegate void CopyCustomizationFieldsToAPTranDelegate(APTran apTranToFill, IAPTranSource poSourceLine, Boolean areCurrenciesSame);
    [PXOverride]
    public void CopyCustomizationFieldsToAPTran(APTran apTranToFill, IAPTranSource poSourceLine, Boolean areCurrenciesSame, CopyCustomizationFieldsToAPTranDelegate baseMethod)
    {
      baseMethod(apTranToFill,poSourceLine,areCurrenciesSame);

        POReceiptLineS sourceLineS = poSourceLine as POReceiptLineS;
        POLine sourceLine = POLine.PK.Find(Base, sourceLineS?.POType, sourceLineS?.PONbr, sourceLineS?.POLineNbr);

        var portID = sourceLine?.GetExtension<POLineExt>()?.UsrPortID;

        var tranline = apTranToFill?.GetExtension<APTranExt>();       

        if (tranline != null && portID != null ) tranline.UsrPortID = portID;


    }


    #endregion

 

 

Trace 

 


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

Maybe go with Vignesh's code. That's how I would do it if I was starting from scratch.


Forum|alt.badge.img
  • Author
  • Freshman I
  • 12 replies
  • August 7, 2024

Ok, started from scratch with Vignesh’s and added warning to see if I am getting the UDF.

I am having an issue of it not saving on the line.

On the trace below it is getting the UDF but not saving.

Code below

  #region Event Handlers
        public delegate IEnumerable CreateAPInvoiceDelegate(PXAdapter adapter);
        [PXOverride]
        public IEnumerable CreateAPInvoice(PXAdapter adapter, CreateAPInvoiceDelegate baseMethod)
        {
            PXGraph.InstanceCreated.AddHandler<APInvoiceEntry>((invoiceEntryGraph) =>
            {
                invoiceEntryGraph.RowInserting.AddHandler<APTran>((sender, e) =>
                {
                    APTran apTran = (APTran)e.Row;

                    if (apTran == null) return;
 
                    APTranExt apTranExt = apTran.GetExtension<APTranExt>();
                    
                    POLine poLine = new PXSelect<POLine, Where<POLine.orderType, Equal<Required<APTran.pOOrderType>>,
                        And<POLine.orderNbr, Equal<Required<APTran.pONbr>>,
                        And<POLine.lineNbr, Equal<Required<APTran.pOLineNbr>>>>>>(Base).SelectSingle(apTran.POOrderType, apTran.PONbr, apTran.POLineNbr);
                   
                    if (poLine != null)
                    {
                        POLineExt poLineExt = poLine.GetExtension<POLineExt>();
                      
                         PXTrace.WriteWarning("POLine Port ID:"+poLineExt.UsrPortID);
                      
                        apTranExt.UsrPortID = poLineExt.UsrPortID;
                      
                         PXTrace.WriteWarning("APTran Port ID:"+apTranExt.UsrPortID);
                    
                    } else {
                      
                       PXTrace.WriteWarning("poLine is null");
                      
                    }
                });
            }
            );
            return baseMethod(adapter);
        }
        #endregion


Vignesh Ponnusamy
Acumatica Moderator
Forum|alt.badge.img+5

Hi @lnd74,

To clarify, so the field is inserted in cache, displayed and when you save the document the value isn’t persisted?


Forum|alt.badge.img
  • Author
  • Freshman I
  • 12 replies
  • August 7, 2024

Port ID from PO

Port ID is blank on AP Invoice

 


Vignesh Ponnusamy
Acumatica Moderator
Forum|alt.badge.img+5

@lnd74,

The looks good to me, from my testing with your code I was able to reproduce the issue once. Then again it works as expected. Try removing the PXTrace.WriteWarning in the if condition to see if that helps.

I am testing the in 24R106. If the issue still persists, share the build number you are using.


Forum|alt.badge.img
  • Author
  • Freshman I
  • 12 replies
  • August 7, 2024

@Vignesh Ponnusamy ,

 

I removed the trace, I tested with a dropship and regular PO as well and it is not working for me. Our version  of Acumatica 2023 R2 Build 23.204.0031.


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

I use this framework convention frequently and have found that when adding an event handler, it is also a good idea to remove it after the baseMethod runs. It seems to help with consistency issues.

You could try something like this:

public delegate IEnumerable CreateAPInvoiceDelegate(PXAdapter adapter);
[PXOverride]
public IEnumerable CreateAPInvoice(PXAdapter adapter, CreateAPInvoiceDelegate baseMethod)
{
    // Handler
    void APInvoiceEntryInstanceCreated(APInvoiceEntry graph)
    {
        graph.RowInserted.AddHandler<APTran>((cache, e) =>
        {
            APTran apTran = (APTran)e.Row;
            if (apTran == null) return;

            APTranExt apTranExt = apTran?.GetExtension<APTranExt>();

            POLine poLine = new PXSelect<POLine, Where<POLine.orderType, Equal<Required<APTran.pOOrderType>>,
                And<POLine.orderNbr, Equal<Required<APTran.pONbr>>,
                And<POLine.lineNbr, Equal<Required<APTran.pOLineNbr>>>>>>(Base).SelectSingle(apTran.POOrderType, apTran.PONbr, apTran.POLineNbr);

            if (poLine != null)
            {
                POLineExt poLineExt = poLine?.GetExtension<POLineExt>();

                PXTrace.WriteWarning("POLine Port ID:" + poLineExt.UsrPortID);

                apTranExt.UsrPortID = poLineExt?.UsrPortID;

                PXTrace.WriteWarning("APTran Port ID:" + apTranExt.UsrPortID);
            }
            else
                PXTrace.WriteWarning("poLine is null");
        });
    }

    PXGraph.InstanceCreated.AddHandler<APInvoiceEntry>(APInvoiceEntryInstanceCreated);
    var result = baseMethod(adapter);
    PXGraph.InstanceCreated.RemoveHandler<APInvoiceEntry>(APInvoiceEntryInstanceCreated);

    return result;
}

 


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

Also, @Chris Hackett, what is up with the formatting?


Chris Hackett
Community Manager
Forum|alt.badge.img
  • Acumatica Community Manager
  • 2810 replies
  • August 7, 2024

@darylbowman? formatting? not sure what you’re asking about...formatting on the site? need more specifics if it needs to be brought to Gainsight’s attention.


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

Yeah, for the code formatting. There are times when it’s really wonky:

There’s no reason this should be bold.


Chris Hackett
Community Manager
Forum|alt.badge.img
  • Acumatica Community Manager
  • 2810 replies
  • August 7, 2024

@darylbowman  - well I can post out to their community with this feedback...don’t hold your breath on it changing anytime soon


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