Skip to main content
Answer

Copying custom field data to another custom field on a generated form.

  • May 19, 2025
  • 7 replies
  • 111 views

Forum|alt.badge.img

I want two custom fields from Purchase Receipts (PR) to copy their data into two correlated custom fields on Receipts when the PR is released. 

Both fields on both forms are simple TextEdit fields.

I am trying to adapt the pseudocode from this post: 

This is the error I keep getting: 

Here is my code so far, my annotations might not be accurate:

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using PX.Common;
using PX.Data;
using PX.Data.BQL.Fluent;
using PX.Objects.CM;
using PX.Objects.CS;
using PX.Objects.GL;
using PX.Objects;
using PX.Objects.IN;
using PX.Objects.PO;

namespace PX.Objects
{
public class INReceiptEntry_Extension : PXGraphExtension<PX.Objects.IN.INReceiptEntry>
{
#region Event Handlers

public PXSelect<POReceipt, Where<INRegister.docType, Equal<Current<POReceipt.receiptType>>, And<INRegister.refNbr, Equal<Current<POReceipt.inventoryRefNbr>>>>> correlatedReceipt;

protected void INTran_RowInserted(PXCache cache, PXRowInsertedEventArgs e)
{

//this code is meant to populate the Vendor Lot/Serial custom fields of Receipts with the Vendor Lot/Serial custom fields of a released Purchase Receipt
/*pseudocode:
If POReceiptType, POReceiptNbr have a value
Parse through the correlated receipt found from a BQL query
Copy the values between the two forms, exclusivize assignment of values based on split vs. non-split.*/

var rowPR = (POReceipt)e.Row;//find current POReceipt record's header for ReceiptType and ReceiptNbr
var rowPRDetails = (POReceiptLineExt)e.Row;//find current POReceipt record's header for UsrPR_VendorLotSerialNbr
var rowPRSplit = (POReceiptLineSplitExt)e.Row;//find current POReceipt record's header for UsrPR_SplitVendorLotSerialNbr

var rowReceipt = (INRegister)e.Row;//find current Receipt record's header for DocType and RefNbr
var rowReceiptDetails = (INTran)e.Row;//find current Receipt record's header for UsrVendorLotSerialNbr
var rowReceiptSplit = (INTranSplit)e.Row;//find current Receipt record's split for UsrSplitVendorLotSerialNbr
if (rowPR == null || rowPRDetails == null || rowPRSplit == null) return;

//need two extensions variables. One for the main detail line and one for the row splits.
INTran standardReceiptItem = (INTran)Base.transactions.Current;
var standardReceiptExtVarRow = PXCache<INTran>.GetExtension<INTranExt>(standardReceiptItem );
var standardReceiptExtVarSplit = PXCache<INTranSplit>.GetExtension<INTranSplitExt>(standardReceiptItem );

/*POReceiptLine purchaseReceiptItem = POReceiptLine.transactions.Current;
var purchaseReceiptExtVarRow = PXCache<POReceiptLine>.GetExtension<POReceiptLineExt>(purchaseReceiptItem);
var purchaseReceiptExtVarSplit = PXCache<POReceiptLineSplit>.GetExtension<POReceiptLineSplitExt>(purchaseReceiptItem);*/

if (rowPR.ReceiptType != null && rowPR.ReceiptNbr != null)
{
//string standardReceiptRowVendorLot = rowPRDetails.UsrPR_VendorLotSerialNbr.ToString();
foreach (POReceipt item in correlatedReceipt.Select() )//parse through the BQL query (View) result
{
if (rowPRSplit.UsrPR_SplitVendorLotSerialNbr != null)
{
//standardReceiptExtVarSplit.UsrSplitVendorLotSerialNbr = rowPRSplit.UsrPR_SplitVendorLotSerialNbr.ToString();
cache.SetValueExt<INTranSplitExt.usrSplitVendorLotSerialNbr>(rowReceiptSplit, rowPRSplit.UsrPR_SplitVendorLotSerialNbr.ToString());
standardReceiptExtVarRow.UsrVendorLotSerialNbr = "<SPLIT>";
}else{
//standardReceiptExtVarRow.UsrVendorLotSerialNbr = rowPRDetails.UsrPR_VendorLotSerialNbr.ToString();
cache.SetValueExt<INTranExt.usrVendorLotSerialNbr>(rowReceiptDetails, rowPRDetails.UsrPR_VendorLotSerialNbr.ToString());
}
}

}

}
#endregion
}
}

 

Best answer by DipakNilkanth

Hi ​@u662, oh, I missed that.

Try below code snippet once.
 

  protected void INTranSplit_RowInserting(PXCache sender, PXRowInsertingEventArgs e)
{
var split = e.Row as INTranSplit;
if (split == null)
return;

INTran inTran = PXSelect<INTran,
Where<INTran.docType, Equal<Required<INTran.docType>>,
And<INTran.refNbr, Equal<Required<INTran.refNbr>>,
And<INTran.lineNbr, Equal<Required<INTran.lineNbr>>>>>>
.Select(Base, split.DocType, split.RefNbr, split.LineNbr);

if (inTran?.POReceiptNbr == null || inTran.POReceiptLineNbr == null)
return;

// Match the Receipt Line first
POReceiptLine poLine = PXSelect<POReceiptLine,
Where<POReceiptLine.receiptNbr, Equal<Required<POReceiptLine.receiptNbr>>,
And<POReceiptLine.lineNbr, Equal<Required<POReceiptLine.lineNbr>>>>>
.Select(Base, inTran.POReceiptNbr, inTran.POReceiptLineNbr);

if (poLine == null)
return;

// Now attempt to find a matching POReceiptLineSplit
POReceiptLineSplit poSplit = PXSelect<POReceiptLineSplit,
Where<POReceiptLineSplit.receiptNbr, Equal<Required<POReceiptLineSplit.receiptNbr>>,
And<POReceiptLineSplit.lineNbr, Equal<Required<POReceiptLineSplit.lineNbr>>>>>
.Select(Base, poLine.ReceiptNbr, poLine.LineNbr);

if (poSplit != null)
{
var splitExt = PXCache<INTranSplit>.GetExtension<INTranSplitExt>(split);
var poSplitExt = PXCache<POReceiptLineSplit>.GetExtension<POReceiptLineSplitExt>(poSplit);

splitExt.UsrSplitVendorLotSerialNbr = poSplitExt.UsrPR_SplitVendorLotSerialNbr;
}
}

 

7 replies

Forum|alt.badge.img+1
  • Semi-Pro III
  • May 20, 2025

Hi ​@u662 

If you only need to copy custom field values when the Purchase Receipt is released, customize the Release button in the Purchase Receipts graph.
Create a PXGraphExtension of Purchase Receipts screen, override the Release method, and after the base call, get the custom records copy to Receipts screen.

Try with the below override sample code

 public delegate IEnumerable ReleaseDelegate(PXAdapter adapter);
[PXOverride]
public virtual IEnumerable Release(PXAdapter adapter, ReleaseDelegate baseMehod)
{
baseMehod(adapter);
//Custom logic
return adapter.Get();
}

Thanks,


DipakNilkanth
Pro III
Forum|alt.badge.img+13

Hi ​@u662,

You're encountering the error because you're trying to cast INTran  to POReceipt, which are unrelated DACs. That cast is invalid and causes the runtime error.

You can use below code snippet.

 protected void INTran_RowInserting(PXCache sender, PXRowInsertingEventArgs e)
{
INTran intran = (INTran)e.Row;
if (intran?.POReceiptNbr == null || intran.POReceiptLineNbr == null)
return;

// Fetch the POReceiptLine based on POReceiptNbr and POReceiptLineNbr
POReceiptLine poLine = PXSelect<POReceiptLine,
Where<POReceiptLine.receiptNbr, Equal<Required<POReceiptLine.receiptNbr>>,
And<POReceiptLine.lineNbr, Equal<Required<POReceiptLine.lineNbr>>>>>
.Select(Base, intran.POReceiptNbr, intran.POReceiptLineNbr);

if (poLine != null)
{
var intranExt = sender.GetExtension<INTranExt>(intran);
var poLineExt = PXCache<POReceiptLine>.GetExtension<POReceiptLineExt>(poLine);

// Copy the custom field values
intranExt.UsrVendorLotSerialNbr = poLineExt.UsrPR_VendorLotSerialNbr;
}
}

Hope, it helps!


Forum|alt.badge.img
  • Author
  • Jr Varsity III
  • May 20, 2025

Hi ​@u662,

You're encountering the error because you're trying to cast INTran  to POReceipt, which are unrelated DACs. That cast is invalid and causes the runtime error.

You can use below code snippet.

 protected void INTran_RowInserting(PXCache sender, PXRowInsertingEventArgs e)
{
INTran intran = (INTran)e.Row;
if (intran?.POReceiptNbr == null || intran.POReceiptLineNbr == null)
return;

// Fetch the POReceiptLine based on POReceiptNbr and POReceiptLineNbr
POReceiptLine poLine = PXSelect<POReceiptLine,
Where<POReceiptLine.receiptNbr, Equal<Required<POReceiptLine.receiptNbr>>,
And<POReceiptLine.lineNbr, Equal<Required<POReceiptLine.lineNbr>>>>>
.Select(Base, intran.POReceiptNbr, intran.POReceiptLineNbr);

if (poLine != null)
{
var intranExt = sender.GetExtension<INTranExt>(intran);
var poLineExt = PXCache<POReceiptLine>.GetExtension<POReceiptLineExt>(poLine);

// Copy the custom field values
intranExt.UsrVendorLotSerialNbr = poLineExt.UsrPR_VendorLotSerialNbr;
}
}

Hope, it helps!

This worked great. I got it to work correctly for the row-level fields, now I’m working on the line split fields. I believe now I’m stuck on a BQL query that would work for this. This is the code/query I’ve just tested unsuccessfully. Do you have any suggestions?

protected void INTranSplit_RowInserting(PXCache cache, PXRowInsertingEventArgs e)
{
INTranSplit inTranSplit = (INTranSplit)e.Row;
if (inTranSplit?.RefNbr == null ) return;

//fetch the POReceiptLineSplit based on POReceiptNbr, POReceiptLineNbr, and POReceiptLineSplit.splitLineNbr
POReceiptLineSplit poLineSplit = PXSelect<POReceiptLineSplit,Where<POReceiptLineSplit.receiptNbr, Equal<Required<POReceiptLineSplit.receiptNbr>>,And<POReceiptLineSplit.lineNbr, Equal<Required<POReceiptLineSplit.lineNbr>>,And<POReceiptLineSplit.splitLineNbr, Equal<Required<POReceiptLineSplit.splitLineNbr>>>>>>.Select(Base, inTranSplit.RefNbr, inTranSplit.LineNbr, inTranSplit.SplitLineNbr);

if (poLineSplit != null)
{
var intranSplitExt = PXCache<INTranSplit>.GetExtension<INTranSplitExt>(inTranSplit);
var poLineSplitExt = PXCache<POReceiptLineSplit>.GetExtension<POReceiptLineSplitExt>(poLineSplit);

intranSplitExt.UsrSplitVendorLotSerialNbr = poLineSplitExt.UsrPR_SplitVendorLotSerialNbr;//split row values
}
}

 


DipakNilkanth
Pro III
Forum|alt.badge.img+13

Hi ​@u662,

Try below code snippet.

 protected void INTranSplit_RowInserting(PXCache sender, PXRowInsertingEventArgs e)
{
INTranSplit split = (INTranSplit)e.Row;
if (split?.POReceiptNbr == null || split.POReceiptLineNbr == null)
return;

// Fetch POReceiptLineSplit — you may need a custom link or join logic here
POReceiptLineSplit poSplit = PXSelect<POReceiptLineSplit,
Where<POReceiptLineSplit.receiptNbr, Equal<Required<POReceiptLineSplit.receiptNbr>>,
And<POReceiptLineSplit.lineNbr, Equal<Required<POReceiptLineSplit.lineNbr>>>>>
.Select(Base, split.POReceiptNbr, split.POReceiptLineNbr);

if (poSplit != null)
{
var splitExt = sender.GetExtension<INTranSplitExt>(split);
var poSplitExt = PXCache<POReceiptLineSplit>.GetExtension<POReceiptLineSplitExt>(poSplit);

splitExt.UsrSplitVendorLotSerialNbr = poSplitExt.UsrPR_SplitVendorLotSerialNbr;
}
}

Hope, it helps!

Note :

It's recommended not to include underscores in the names of your custom fields. Using underscores can cause issues during customization upgrades in newer Acumatica versions.

As a best practice, define custom field names without underscores to ensure better compatibility and smoother upgrade paths.


Forum|alt.badge.img
  • Author
  • Jr Varsity III
  • May 20, 2025

@Nilkanth Dipak 

The INTranSplit DAC doesn’t have the POReceiptNbr or POReceiptLineNbr fields. 

From the DAC browser, INTranSplit and POReceiptLineSplit do share LineNbr, DocType/ReceiptType, and SplitLineNbr fields. 

The query I tried to use with these fields also didn’t work.

POReceiptLineSplit poLineSplit = PXSelect<POReceiptLineSplit,Where<POReceiptLineSplit.lineNbr, Equal<Required<POReceiptLineSplit.lineNbr>>,And<POReceiptLineSplit.receiptType, Equal<Required<POReceiptLineSplit.receiptType>>,And<POReceiptLineSplit.splitLineNbr, Equal<Required<POReceiptLineSplit.splitLineNbr>>, And<POReceipt.invtRefNbr, Equal<Required<INTranSplit.refNbr>>>>>>>.Select(Base, inTranSplit.LineNbr, inTranSplit.DocType, inTranSplit.SplitLineNbr, inTranSplit.RefNbr);

 


DipakNilkanth
Pro III
Forum|alt.badge.img+13

Hi ​@u662, oh, I missed that.

Try below code snippet once.
 

  protected void INTranSplit_RowInserting(PXCache sender, PXRowInsertingEventArgs e)
{
var split = e.Row as INTranSplit;
if (split == null)
return;

INTran inTran = PXSelect<INTran,
Where<INTran.docType, Equal<Required<INTran.docType>>,
And<INTran.refNbr, Equal<Required<INTran.refNbr>>,
And<INTran.lineNbr, Equal<Required<INTran.lineNbr>>>>>>
.Select(Base, split.DocType, split.RefNbr, split.LineNbr);

if (inTran?.POReceiptNbr == null || inTran.POReceiptLineNbr == null)
return;

// Match the Receipt Line first
POReceiptLine poLine = PXSelect<POReceiptLine,
Where<POReceiptLine.receiptNbr, Equal<Required<POReceiptLine.receiptNbr>>,
And<POReceiptLine.lineNbr, Equal<Required<POReceiptLine.lineNbr>>>>>
.Select(Base, inTran.POReceiptNbr, inTran.POReceiptLineNbr);

if (poLine == null)
return;

// Now attempt to find a matching POReceiptLineSplit
POReceiptLineSplit poSplit = PXSelect<POReceiptLineSplit,
Where<POReceiptLineSplit.receiptNbr, Equal<Required<POReceiptLineSplit.receiptNbr>>,
And<POReceiptLineSplit.lineNbr, Equal<Required<POReceiptLineSplit.lineNbr>>>>>
.Select(Base, poLine.ReceiptNbr, poLine.LineNbr);

if (poSplit != null)
{
var splitExt = PXCache<INTranSplit>.GetExtension<INTranSplitExt>(split);
var poSplitExt = PXCache<POReceiptLineSplit>.GetExtension<POReceiptLineSplitExt>(poSplit);

splitExt.UsrSplitVendorLotSerialNbr = poSplitExt.UsrPR_SplitVendorLotSerialNbr;
}
}

 


Forum|alt.badge.img
  • Author
  • Jr Varsity III
  • May 20, 2025

@Nilkanth Dipak 

These queries worked.

I think I understand what’s happening now. Each DAC seems to be receiving the results of each query as defined by the Select() method.

The extensions then reference these filtered DACs to allow the custom fields to receive specific values based on the rows the queries returned.