0
votes

I am struggling with this, it seems so simple and im probably missing something stupid but I need some help.

I am trying to add another field to the Details grid under the Print Statement screen in AR503500. The field is just the parentAccountId on the customer. DetailsResult already contains the CustomerID.

I have extended the AR.ARStatementPrint.DetailsResult DAC and added the following

        public abstract class parentAccountTest2 : IBqlField
    {
    }

    #region Parent Account test 2
    [PXString]
    [PXUIField(DisplayName = "Parent Account test 2")]
    [PXDBScalar(typeof(Search<Customer.parentBAccountID,
                                 Where<Customer.bAccountID, Equal<DetailsResult.customerID>>>))]
    public string ParentAccountTest2 { get; set; }
    #endregion

But I cant get any values to show up on the grid.

I notice on the graph there is a method details() which calls the copy method on DetailsResult - do I need to override this somehow and set the parentAccountId that way?

Here is details method in the graph

protected virtual IEnumerable details()
{
    ARSetup setup = ARSetup.Current;

    PrintParameters header = Filter.Current;
    List<DetailsResult> result = new List<DetailsResult>();
    if (header == null)
        yield break;

    GL.Company company = PXSelect<GL.Company>.Select(this);
    foreach (PXResult<ARStatement, Customer> it in PXSelectJoin<ARStatement,
            InnerJoin<Customer, On<Customer.bAccountID, Equal<ARStatement.statementCustomerID>>>,
            Where<ARStatement.statementDate, Equal<Required<ARStatement.statementDate>>,
                And<ARStatement.statementCycleId, Equal<Required<ARStatement.statementCycleId>>>>,
            OrderBy<Asc<ARStatement.statementCustomerID, Asc<ARStatement.curyID>>>>
            .Select(this, header.StatementDate, header.StatementCycleId))
    {
        DetailsResult res = new DetailsResult();
        ARStatement st = it;
        Customer cust = it;
        res.Copy(st, cust);

        if (setup.ConsolidatedStatement != true && st.BranchID != header.BranchID)
                continue;

        if (Filter.Current.Action == 0 &&
            header.ShowAll != true &&
            (st.DontPrint == true || st.Printed == true))
                continue;

        if ((Filter.Current.Action == 1 || Filter.Current.Action == 2) &&
            header.ShowAll != true &&
            (st.DontEmail == true || st.Emailed == true))
                continue;

        if (cust.PrintCuryStatements == true)
        {
            if (Filter.Current.CuryStatements != true)
                continue;

            DetailsResult last = result.Count > 0 ? result[result.Count - 1] : null;
            if (last?.CustomerID == res.CustomerID && last?.CuryID == res.CuryID)
            {
                last.Append(res);
            }
            else
            {
                result.Add(res);
            }
        }
        else
        {
            if (Filter.Current.CuryStatements == true)
                continue;

            res.ResetToBaseCury(company.BaseCuryID);

            DetailsResult last = result.Count > 0 ? result[result.Count - 1] : null;
            if (last?.CustomerID == res.CustomerID)
            {
                last.Append(res);
            }
            else
            {
                result.Add(res);
            }
        }
    }

    foreach (var item in result)
    {
        var located = Details.Cache.Locate(item);
        if (located != null)
        {
            yield return located;
        }
        else
        {
            Details.Cache.SetStatus(item, PXEntryStatus.Held);
            yield return item;
        }
    }

    Details.Cache.IsDirty = false;
}

And is that copy method on the PX.Objects.AR.ARStatementPrint.DetailsResult class

    public virtual void Copy(ARStatement aSrc, Customer cust)
{
    this.CustomerID = cust.BAccountID;
    this.UseCurrency = cust.PrintCuryStatements;
    this.StatementBalance = aSrc.EndBalance ?? decimal.Zero;
    this.AgeBalance00 = aSrc.AgeBalance00 ?? decimal.Zero;
    this.CuryID = aSrc.CuryID;
    this.CuryStatementBalance = aSrc.CuryEndBalance ?? decimal.Zero;
    this.CuryAgeBalance00 = aSrc.CuryAgeBalance00 ?? decimal.Zero;
    this.DontEmail = aSrc.DontEmail;
    this.DontPrint = aSrc.DontPrint;
    this.Emailed = aSrc.Emailed;
    this.Printed = aSrc.Printed;
            this.BranchID = aSrc.BranchID;
}
1
There are two abstract classes how they are related to each other. Property ParentAccountTest2 belongs to which class? Can you share code of Details and Copy methods? Where is DetailsResult class? - Chetan
ParentAccountTest2 is my field I added to my DetailsResult Extension. Updated post with those methods.DetailsResult is on PX.Objects.AR.AR.StatementPrint - GrayFoxNZ

1 Answers

1
votes

The 'details' method is called the DataView Delegate. In it's definition you return the records list of the DataView. It's often used for unbound DAC and custom logic that wouldn't be a good fit for a single BQL query. In 'details' DataView delegate, new Records are created blank and then values are copied in it.

I suspect CustomerID is null at the time your PXDBScalar is executed because the DAC record was created blank.

For such cases where values are computed in the DataView delegate instead of the DAC, you can use FieldSelecting event handler to compute the value of the custom field after the delegate has been executed.

Notice DAC Extension doesn't contain the BQL Query:

public class DetailsResultExt: PXCacheExtension<ARStatementPrint.DetailsResult>
{
    #region Parent Account  
    public abstract class parentAccount : IBqlField { }

    [PXString(60, IsUnicode = true)]
    [PXUIField(DisplayName = "Parent Account")]
    public virtual string ParentAccount { get; set; }
    #endregion
}

Query is executed in the FieldSelecting event handler of Print Statement graph extension after CustomerID has been copied in the DataView delegate:

public class ARStatementPrint_Extension : PXGraphExtension<ARStatementPrint>
{
    #region Event Handlers
    protected virtual void DetailsResult_ParentAccount_FieldSelecting(PXCache sender, PXFieldSelectingEventArgs e)
    {
        ARStatementPrint.DetailsResult detailsResult = e.Row as ARStatementPrint.DetailsResult;

        if (detailsResult != null)
        {
            BAccount2 bAccount = PXSelectJoin<BAccount2,
                                 InnerJoin<Customer, On<Customer.bAccountID, Equal<Required<ARStatementPrint.DetailsResult.customerID>>>>,
                                 Where<BAccount2.bAccountID, Equal<Customer.parentBAccountID>>>.Select(Base, detailsResult.CustomerID);

            if (bAccount != null)
            {
                e.ReturnValue = bAccount.AcctName;
            }
        }
    }
    #endregion
}

Add unbound custom field to screen in project editor: enter image description here

Custom field will show Parent Business Account name: enter image description here