0

I have been asked to add a new tab that displays a list of items linked to a project quote on the Project Quote Screen (PM304500). I need some help in how to tackle this, since I am struggling to identify the graph (or DAC) I need to extend to be able to add my custom view.

I want to add my new tab here

This is my DAC of the items I want to display on the new tab, which still needs to be worked on.

using System;
using PX.Data;

namespace *******
{
  [Serializable]
  [PXCacheName("BOQUMaster")]
  public class BOQUMaster : IBqlTable
  {
    #region MasterID
    [PXDBIdentity(IsKey = true)]
    public virtual int? MasterID { get; set; }
    public abstract class masterID : PX.Data.BQL.BqlInt.Field<masterID> { }
    #endregion

    #region MasterCD
    [PXDBString(20, IsUnicode = true, InputMask = "")]
    [PXUIField(DisplayName = "Master CD")]
    public virtual string MasterCD { get; set; }
    public abstract class masterCD : PX.Data.BQL.BqlString.Field<masterCD> { }
    #endregion

    #region Description
    [PXDBString(100, IsUnicode = true, InputMask = "")]
    [PXUIField(DisplayName = "Description")]
    public virtual string Description { get; set; }
    public abstract class description : PX.Data.BQL.BqlString.Field<description> { }
    #endregion

    #region MasterOnProjectStatus
    [PXDBString(20, IsUnicode = true, InputMask = "")]
    [PXUIField(DisplayName = "Master On Project Status")]
    public virtual string MasterOnProjectStatus { get; set; }
    public abstract class masterOnProjectStatus : PX.Data.BQL.BqlString.Field<masterOnProjectStatus> { }
    #endregion

    #region DefaultInstallRatio
    [PXDBDecimal()]
    [PXUIField(DisplayName = "Default Install Ratio")]
    public virtual Decimal? DefaultInstallRatio { get; set; }
    public abstract class defaultInstallRatio : PX.Data.BQL.BqlDecimal.Field<defaultInstallRatio> { }
    #endregion

    #region ContractID
    [PXDBInt()]
    [PXUIField(DisplayName = "Contract ID")]
    public virtual int? ContractID { get; set; }
    public abstract class contractID : PX.Data.BQL.BqlInt.Field<contractID> { }
    #endregion

    #region QuoteID
    [PXDBGuid()]
    [PXUIField(DisplayName = "Quote ID")]
    public virtual Guid? QuoteID { get; set; }
    public abstract class quoteID : PX.Data.BQL.BqlGuid.Field<quoteID> { }
    #endregion

    #region Tstamp
    [PXDBTimestamp()]
    [PXUIField(DisplayName = "Tstamp")]
    public virtual byte[] Tstamp { get; set; }
    public abstract class tstamp : PX.Data.BQL.BqlByteArray.Field<tstamp> { }
    #endregion

    #region CreatedByID
    [PXDBCreatedByID()]
    public virtual Guid? CreatedByID { get; set; }
    public abstract class createdByID : PX.Data.BQL.BqlGuid.Field<createdByID> { }
    #endregion

    #region CreatedByScreenID
    [PXDBCreatedByScreenID()]
    public virtual string CreatedByScreenID { get; set; }
    public abstract class createdByScreenID : PX.Data.BQL.BqlString.Field<createdByScreenID> { }
    #endregion

    #region CreatedDateTime
    [PXDBCreatedDateTime()]
    public virtual DateTime? CreatedDateTime { get; set; }
    public abstract class createdDateTime : PX.Data.BQL.BqlDateTime.Field<createdDateTime> { }
    #endregion

    #region LastModifiedByID
    [PXDBLastModifiedByID()]
    public virtual Guid? LastModifiedByID { get; set; }
    public abstract class lastModifiedByID : PX.Data.BQL.BqlGuid.Field<lastModifiedByID> { }
    #endregion

    #region LastModifiedByScreenID
    [PXDBLastModifiedByScreenID()]
    public virtual string LastModifiedByScreenID { get; set; }
    public abstract class lastModifiedByScreenID : PX.Data.BQL.BqlString.Field<lastModifiedByScreenID> { }
    #endregion

    #region LastModifiedDateTime
    [PXDBLastModifiedDateTime()]
    public virtual DateTime? LastModifiedDateTime { get; set; }
    public abstract class lastModifiedDateTime : PX.Data.BQL.BqlDateTime.Field<lastModifiedDateTime> { }
    #endregion

    #region Noteid
    [PXNote()]
    public virtual Guid? Noteid { get; set; }
    public abstract class noteid : PX.Data.BQL.BqlGuid.Field<noteid> { }
    #endregion
  }
}

enter image description here

The view I want will look something like this, but obviously I need to modify the graph I am extending

using PX.Data.BQL.Fluent;
using PX.Objects.CR;
using PX.Objects.PM;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace *******
{
    //What graph do I need to extend here or do I need to think about another approach?
    public class PMQuoteMaint_Extension : PXGraphExtension<PMQuoteMaint>
    {
        // The data view I will need to add to the extend class will look something like this
        //public SelectFrom<BOQUMaster>.Where<BOQUMaster.quoteID.IsEqual<PMQuoteMaint.quoteID.FromCurrent>>.View BillOfQuantities;
    }
}

Please feel free to add any helpful articles or links in the comments.

Ruaan Volschenk
  • 717
  • 2
  • 11
  • 23

1 Answers1

1

As Rick noted, you seem to be in the right place. However, your defined view (commented out) tries to access quoteID from PMQuoteMaint which is a graph. You need to pull from PMQuote instead as that is the primary DAC of the graph.

Your code (commented out):

public SelectFrom<BOQUMaster>
    .Where<BOQUMaster.quoteID.IsEqual<PMQuoteMaint.quoteID.FromCurrent>>
    .View BillOfQuantities;

Corrected code:

public SelectFrom<BOQUMaster>
    .Where<BOQUMaster.quoteID.IsEqual<PMQuote.quoteID.FromCurrent>>
    .View BillOfQuantities;

When doing this type of work, there are 2 different types of data structures that can be leveraged. One is a child record (master-detail relationship) which uses a [PXParent] attribute in conjunction with [PXDBDefault] to populate the field with the related value in the parent table. If your data were to be "Items of this quote" then you need to something in your DAC similar to PMQuoteTask...

public partial class PMQuoteTask : PX.Data.IBqlTable
{
    #region QuoteID
    public abstract class quoteID : PX.Data.BQL.BqlGuid.Field<quoteID> { }
    [PXDBGuid(IsKey = true)]
    [PXDBDefault(typeof(PMQuote.quoteID))]
    [PXParent(typeof(Select<PMQuote, Where<PMQuote.quoteID, Equal<Current<quoteID>>>>))]
    public virtual Guid? QuoteID { get; set; }
    #endregion

    #region TaskCD
    public abstract class taskCD : PX.Data.BQL.BqlString.Field<taskCD> { }
    [PXDimension(ProjectTaskAttribute.DimensionName)]
    [PXDBString(IsUnicode = true, IsKey = true, InputMask = "")]
    [PXDefault()]
    [PXUIField(DisplayName = "Project Task", Visibility = PXUIVisibility.SelectorVisible)]
    public virtual String TaskCD { get; set; }
    #endregion
...
}

Notice that the DAC has a key of QuoteID and TaskCD. QuoteID defines a parent of PMQuote, which is the primary DAC of the graph. Use of QuoteID in your DAC leads me to believe that this is a critical link, and that you will not be referencing the same record to other quotes. This methodology causes the child record to be deleted when you delete the parent PMQuote record.

However, it appears that your record is the other type... related data. This, in effect, is use of a tab to show data that typically would have been in a GI shown from the Inquiry menu. When the business case requires it, you certainly can do this in a tab. While the data can be retrieved into a view for a new tab here, I would suggest that you use .View.ReadOnly since it is reference data only. This will prevent changing the data on this screen since this would not be the primary graph of that DAC. The reason for preventing changes outside of a DAC's primary graph is that the use of event handlers in the primary graph are not fired from this (non-primary) graph. You might consider making a link of BOQUMaster.MasterCD in the tab so that changes can be made from the primary graph of BOQUMaster.

Brian Stevens
  • 1,826
  • 1
  • 7
  • 16