Skip to main content
Question

Opening a custom field in new window clicking on a field ina form

  • October 15, 2024
  • 17 replies
  • 161 views

Forum|alt.badge.img+1

I need to handle a new status on ARIncoice for legacy reasons and added therefore a custom field called cegEStatus in a DAC extension of ARInvoice.

 

 [PXCopyPasteHiddenFields(typeof(cegEStatus))]

 public class ARInvoiceEIExtBase : PXCacheExtension<ARInvoice>

 {

     #region CegEStatus

     [PXDBString(50, IsUnicode = true)]

     [PXDefault(PersistingCheck = PXPersistingCheck.Nothing)]

     [PXUIField(DisplayName = "Electronic Status", IsReadOnly = true)]

     [EiStatuses.List]

     public virtual string CegEStatus { get; set; }

     public abstract class cegEStatus : BqlString.Field<cegEStatus> { }

     #endregion

 }

 

This field was also added to AR301000.

A new DAC has then been created to store the values assigned to the status of a given ARInvoice over time.

    public class EiInvoiceRegisteredStatus : IBqlTable

    {

        public static bool IsActive() => PXAccess.FeatureInstalled<FeaturesSetExt.cegEInvoicingOutgoing>() || PXAccess.FeatureInstalled<FeaturesSetExt.cegEInvoicingIncoming>();

        #region DocType        

        public abstract class docType : BqlString.Field<docType> { }

        /// <summary>

        /// [key] Type of the document.

        /// </summary>

        /// <value>

        /// Possible values are: "INV" - Invoice, "ACR" - Credit Adjustment, "ADR" - Debit Adjustment,

        /// "CHK" - Check, "VCK" - Void Check, "PPM" - Prepayment, "REF" - Vendor Refund,

        /// "QCK" - Quick Check, "VQC" - Void Quick Check.

        /// </value>

        [PXDBString(3, IsKey = true, IsFixed = true)]

        [PXDefault()]

        [ARDocType.List()]

        [PXUIField(DisplayName = "Type", Visibility = PXUIVisibility.SelectorVisible, Enabled = false, TabOrder = 0)]

        [PXFieldDescription]

        public virtual String DocType { get; set; }

        #endregion

        #region RefNbr

        public abstract class refNbr : BqlString.Field<refNbr> { }

        /// <summary>

        /// [key] Reference number of the document.

        /// </summary>

        [PXDBString(20, IsUnicode = true, IsKey = true, InputMask = "")]

        [PXDefault()]

        [PXUIField(DisplayName = "Reference Nbr.", Visibility = PXUIVisibility.SelectorVisible, TabOrder = 1)]

        [PXSelector(typeof(Search<ARInvoice.refNbr, Where<ARInvoice.docType, Equal<Optional<docType>>>>), Filterable = true)]

        //[PXFieldDescription]

        public virtual String RefNbr { get; set; }

        #endregion

        #region Code

        [PXDBString(50, IsUnicode = true, IsKey = true, InputMask = "")]

        [EiStatuses.List]

        [PXUIField(DisplayName = "Electronic Status")]

        public string Code { get; set; }

        public abstract class code : BqlString.Field<code> { }

        #endregion

        #region RegisteredDateTime

        public abstract class registeredDateTime : BqlDateTime.Field<registeredDateTime> { }

        [PXDBDateAndTime(IsKey = true, DisplayMask ="G", UseTimeZone = true)]

        [PXUIField(DisplayName = "Registered Date")]

        public virtual DateTime? RegisteredDateTime { get; set; }

        #endregion

        #region RegisteredByID

        public abstract class registeredByID : BqlGuid.Field<registeredByID> { }

        [PXDBGuid()]

        [PXUIField(DisplayName = "Registered By")]

        [PXSelector(

                    typeof(Search<Users.pKID>),

                    typeof(Users.username),

                    typeof(Users.displayName),

                    SubstituteKey = typeof(Users.username),

                    DescriptionField = typeof(Users.displayName)

        )]

        public virtual Guid? RegisteredByID { get; set; }

        #endregion

 

//+Audit fields

}

Finally, I created new custom graph and screen (ARInvoiceRegisteredStatusEntry) that displays the status history for an invoice. So far so good.

 public class ARInvoiceRegisteredStatusEntry : PXGraph<ARInvoiceRegisteredStatusEntry>

 {

        #region Views

        public PXFilter<EiInvoiceRegisteredStatusFilter> Filter;

        [PXFilterable]

        public SelectFrom<EiInvoiceRegisteredStatus>

                .Where<EiInvoiceRegisteredStatus.docType.IsEqual<EiInvoiceRegisteredStatusFilter.docType.FromCurrent>

                .And<EiInvoiceRegisteredStatus.refNbr.IsEqual<EiInvoiceRegisteredStatusFilter.refNbr.FromCurrent>>>

                .OrderBy<EiInvoiceRegisteredStatus.registeredDateTime.Desc>

                .View.ReadOnly RegisteredStatus;

        #endregion

 

    public class EiInvoiceRegisteredStatusFilter : IBqlTable

    {

        #region DocType        

        public abstract class docType : BqlString.Field<docType> { }

        /// <summary>

        /// [key] Type of the document.

        /// </summary>

        /// <value>

        /// Possible values are: "INV" - Invoice, "ACR" - Credit Adjustment, "ADR" - Debit Adjustment,

        /// "CHK" - Check, "VCK" - Void Check, "PPM" - Prepayment, "REF" - Vendor Refund,

        /// "QCK" - Quick Check, "VQC" - Void Quick Check.

        /// </value>

        [PXString(3, IsKey = true, IsFixed = true)]

        [PXDefault()]

        [ARDocType.List()]

        [PXUIField(DisplayName = "Type", Visibility = PXUIVisibility.SelectorVisible, TabOrder = 0, IsReadOnly = true)]

        [PXFieldDescription]

        public virtual String DocType { get; set; }

        #endregion

        #region RefNbr

        public abstract class refNbr : BqlString.Field<refNbr> { }

        /// <summary>

        /// [key] Reference number of the document.

        /// </summary>

        [PXString(20, IsUnicode = true, IsKey = true, InputMask = "")]

        [PXDefault()]

        [PXUIField(DisplayName = "Reference Nbr.", Visibility = PXUIVisibility.SelectorVisible, TabOrder = 1, IsReadOnly =true)]

        public virtual String RefNbr { get; set; }

        #endregion

    }

}

What I would like to implement is the possibility for the user to open my new screen from the AR301000 screen, by clicking on the new field. Therefore, I wrote an action that do the job.

        public PXAction<ARInvoice> DisplayEStatuses;

        [PXButton(Category = Messages.ElectronicInvoicing, DisplayOnMainToolbar = false)]

        [PXUIField(DisplayName = "Display E-statuses")]

        protected virtual void displayEStatuses()

        {

            ARInvoice arInvoice = Base.Document.Current;

            using (IFlexLog logger = new EiInvoiceActionLog("refreshStatus", arInvoice))

            using (logger.NewParagraph($"DISPLAY STATUSES: Invoice {arInvoice.DocType}.{arInvoice.RefNbr}"))

            {

               graph = PXGraph.CreateInstance<ARInvoiceRegisteredStatusEntry>();

                graph.Filter.Current = CreateEiStatusesFilter(arInvoice);

                Dictionary<string, object> parameters = new Dictionary<string, object>();

                parameters[nameof(EiInvoiceRegisteredStatusFilter.DocType)] = arInvoice.DocType;

                parameters[nameof(EiInvoiceRegisteredStatusFilter.RefNbr)] = arInvoice.RefNbr;

                throw new PXRedirectRequiredException(graph, true, "Electronic statuses", parameters) { Mode = PXBaseRedirectException.WindowMode.NewWindow };

            }

        }

 

        private static EiInvoiceRegisteredStatusFilter CreateEiStatusesFilter(ARInvoice arInvoice)

        {

            return new EiInvoiceRegisteredStatusFilter()

            {

                DocType = arInvoice.DocType,

                RefNbr = arInvoice.RefNbr,

            };

        }

Is there any way to trigger this action clicking on my custom field in AR301000 ?

 

17 replies

Forum|alt.badge.img+8
  • Captain II
  • October 16, 2024

Hi @ygagnaire12 

 

Not sure how it would work in your use case, but have you tried to add AllowEdit=”True” to your .aspx page for the field?

 

Hope this helps,

Aleks


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

Not sure how it would work in your use case, but have you tried to add AllowEdit=”True” to your .aspx page for the field?

More on this here. (note the PXPrimaryGraph attribute)


Forum|alt.badge.img+1
  • Author
  • Semi-Pro I
  • October 22, 2024

 @aiwan,

Below what I did :

1°) Set the PXSelector attribute on my field CegEStatus :

        #region CegEStatus

        [PXDBString(50, IsUnicode = true)]

        [PXDefault(PersistingCheck = PXPersistingCheck.Nothing)]

        //[PXUIField(DisplayName = "Electronic Status", IsReadOnly = true)]

        //[EiStatuses.List]

        [PXUIField(DisplayName = "Electronic Status")]

        [PXSelector(typeof(Search<EiInvoiceRegisteredStatus.code,

            Where<EiInvoiceRegisteredStatus.docType, Equal<Current<ARInvoice.docType>>,

                And<EiInvoiceRegisteredStatus.refNbr, Equal<Current<ARInvoice.refNbr>>>>>),

            Filterable = true)]


        public virtual string CegEStatus { get; set; }

        public abstract class cegEStatus : BqlString.Field<cegEStatus> { }

        #endregion

 

2°) In the customization project Editor, I removed and created again the control. Then, I set its property ‘AllowEdit’ to True. After publishing the projet, a little pen appeared at the right side of the control.

 

3°) Finally, I set the graph I want to be displayed after redirection as the primary graph of the DAC used by my PXSelecor.

    [PXPrimaryGraph(typeof(ARInvoiceRegisteredStatusEntry))]
    public class EiInvoiceRegisteredStatus : IBqlTable
    {

 

Unfortunately, when the little pen is clicked, the following error message is now provided :

I don’t understand what’s wrong. In the EiInvoiceRegisteredStatus table, a record exists for this invoice and the code ‘validationFailed’...


Forum|alt.badge.img+8
  • Captain II
  • October 22, 2024

@ygagnaire12 

 

In your PXSelector, could you try to add the fields that hold the value e.g. ARInvocice.refNbr & ARInvoice.docType.

Like this : [PXSelector(typeof(AMBatch.batNbr),

    typeof(AMBatch.docType))]

These will act as the parameters in the redirection I believe.

 

Hope this helps,

Aleks


Forum|alt.badge.img+8
  • Captain II
  • October 22, 2024

Also, What are the key fields on your custom DAC?


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

Can you post the trace?


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

Oh, I see now what your problem is. AllowEdit is for selectors. Your ‘Electronic Status’ field is not a selector. It’s trying to navigate to the value contained, but it’s not a record.

The accepted answer from the link I shared previously (here) should work better for you.


Forum|alt.badge.img+1
  • Author
  • Semi-Pro I
  • October 22, 2024

@aiwan,

The key fields of the DAC EiInvoiceRegisteredStatus is constituted by the 3 fields (docType, refNbr and code).

I attempted the following code, but the issue is still here.

 

        #region CegEStatus

        [PXDBString(50, IsUnicode = true)]

        [PXDefault(PersistingCheck = PXPersistingCheck.Nothing)]

        [PXUIField(DisplayName = "Electronic Status", Visibility = PXUIVisibility.Visible, Enabled = false)]

        [PXSelector(typeof(Search<EiInvoiceRegisteredStatus.code,

            Where<EiInvoiceRegisteredStatus.docType, Equal<Current<ARInvoice.docType>>,

                And<EiInvoiceRegisteredStatus.refNbr, Equal<Current<ARInvoice.refNbr>>>>>), typeof(ARInvoice.docType), typeof(ARInvoice.refNbr))]


        public virtual string CegEStatus { get; set; }

        public abstract class cegEStatus : BqlString.Field<cegEStatus> { }

        #endregion

@darylbowman 

Thank you for your suggestion. I have two problems with ot :

  • The field I’d like to behave as a link is a PXSelector,
  • This field is not in a grid and that is the point.

Unfortulately, the traces are not very usefull for me.

 

Error: Electronic Status 'ValidationFailed' cannot be found in the system. Please verify whether you have proper access rights to this object.

   at PX.Data.PXRedirectHelper.TryRedirect(PXCache cache, Object row, String message, WindowMode mode, Type preferedType) in C:\build\code_repo\NetTools\PX.Data\Graph\Redirect.cs:line 614

   at PX.Web.UI.PXBaseDataSource.GetEditUrl(String viewName, Object row) in C:\build\code_repo\NetTools\PX.Web.UI\Controls\Data\DataSource.cs:line 7337

   at PX.Web.UI.PXSelectorBase.GetCallbackResult(PXCallbackCommand cmd) in C:\build\code_repo\NetTools\PX.Web.UI\Controls\Editors\SelectorBase.cs:line 3699

   at PX.Web.UI.PXCallbackManager.RenderControlsData(PXCallbackResultMethod resultMethod, XmlWriter writer) in C:\build\code_repo\NetTools\PX.Web.UI\Tools\Callback.cs:line 611

   at PX.Web.UI.PXCallbackManager.GetCallbackResultInternal(PXCallbackResultMethod resultMethod) in C:\build\code_repo\NetTools\PX.Web.UI\Tools\Callback.cs:line 490


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

Thank you for your suggestion. I have two problems with ot :

  • The field I’d like to behave as a link is a PXSelector,
  • This field is not in a grid and that is the point.

Sorry, I see it is a selector. Lack of observation on my part.

Try this:

[PXPrimaryGraph(
new Type[] {
typeof(ARInvoiceRegisteredStatusEntry)
},
new Type[] {
typeof(Select<EiInvoiceRegisteredStatus,
Where2<
Where<EiInvoiceRegisteredStatus.docType, Equal<Current<EiInvoiceRegisteredStatus.docType>>,
And<EiInvoiceRegisteredStatus.refNbr, Equal<Current<EiInvoiceRegisteredStatus.refNbr>>>>,
And<EiInvoiceRegisteredStatus.code, Equal<Current<EiInvoiceRegisteredStatus.code>>>>>)
})]

 


Forum|alt.badge.img+1
  • Author
  • Semi-Pro I
  • October 22, 2024

@darylbowman, that’s an interesting idea. I tried first with the code you suggested and then with the following one.

    [PXPrimaryGraph(

    new Type[] {

        typeof(ARInvoiceRegisteredStatusEntry)

    },

    new Type[] {

        typeof(Select<EiInvoiceRegisteredStatus,

                Where<docType, Equal<Current<ARInvoice.docType>>,

                    And<refNbr, Equal<Current<ARInvoice.refNbr>>>>>)

    })]

    public class EiInvoiceRegisteredStatus : IBqlTable

None of this solution works 🙄.

In fact, the track of a PXSelector with AllowEdit property set to true seems to be the right one. It is used for instance on AR301000, tab “Financial”, where the BatchNbr field does exactly what I’d like to do (but of course for an other DAC and an other screen). I don’t understand how, in this case, the redirection is done to screen gl301000...


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

Just out of curiosity, have you tried adding AllowEdit to a key field selector (perhaps Code)? I’m suspicious that the selector may need to be part of the ‘key’.


Forum|alt.badge.img+1
  • Author
  • Semi-Pro I
  • October 22, 2024

Do you mean in the AR301000 screen ?


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

No, I mean on your current screen. Instead of the link being on CegEStatus, put it on Code instead, since Code is part of the key. I’m just curious of it changes anything.


Forum|alt.badge.img+8
  • Captain II
  • October 23, 2024

Hi @ygagnaire12 

 

In your Selector, could you please try to put your custom DAC key fields (the screen you want to go to)?

In my selectors in which the redirect works, I have the key fields.

 

Aleks


Forum|alt.badge.img+1
  • Author
  • Semi-Pro I
  • October 23, 2024

@darylbowman , @aiwan , thank you for your suggestions. I try them as soon as possible and I will keep you informed.


Forum|alt.badge.img+8
  • Captain II
  • November 20, 2024

Hi ​@ygagnaire12 

 

Any luck?


Forum|alt.badge.img+1
  • Author
  • Semi-Pro I
  • January 16, 2025

@aiwan, sorry for the delay, I had to attend to a more important development and left this one aside for a while. I came back to it earlier this week and put something in place that almost works (the link works fine now but I have yet a minor issue – see at the end of the post).

Following your idea and assuming that the system failed to find the expected records because I had two columns in the primary my target DAC ‘s key, I changed my code a little bit. The aim was  to have only one column in the primary key. To do that, I splitted my initial history table into two tables : one is the master (EIStatusesHistory) and the second one stands for the details (EIStatusesHistoryItem).

In the ARInvoiceEIExt DAC (extension of the ARInvoice DAC)

  

The field CegHistory is defined as a PXSelector :

 

[PXDBString(25, IsUnicode = true, InputMask = "")]

[PXUIField(DisplayName = "History ID")]

[PXSelector(typeof(Search<EIStatusesHistory.historyID>))]

public string CegHistoryID { get; set; }

public abstract class cegHistoryID : BqlString.Field<cegHistoryID> { }

 

In AR301000.aspx, from the customization editor :

 

The CegHistoryID field is added, and its property AllowEdit is set to True. As I prefer to display here a link better than the pen button, I also set the propery Enabled to False.

 

 

In ths EIStatuesHistory DAC :

 

The field History is defined as a PXSelector :

 

[PXDBString(25, IsKey = true, IsUnicode = true, InputMask = "")]

[PXUIField(DisplayName = "History ID")]

[PXSelector(typeof(Search<historyID>), ValidateValue = false)]

public virtual string HistoryID { get; set; }

public abstract class historyID : BqlString.Field<historyID> { }

 

In the EIStatuesHistoryItem DAC :

[PXDBString(25, IsKey = true, IsUnicode = true, InputMask = "")]

[PXUIField(DisplayName = "History ID")]

[PXDBDefault(typeof(EIStatusesHistory.historyID))]

[PXParent(typeof(Select<EIStatusesHistory, Where<EIStatusesHistory.historyID, Equal<Current<historyID>>>>))]

public virtual string HistoryID { get; set; }

public abstract class historyID : BqlString.Field<historyID> { }

 

In the graph that is used to display the history details for a given invoice :

 

1°) The following filter DAC class was created :

 

public class EIStatusesHistoryInqFilter : IBqlTable

{

#region HistoryID

[PXDBString(25, IsKey = true, IsUnicode = true, InputMask = "")]

[PXUIField(DisplayName = "History ID")]

[PXDBDefault(typeof(EIStatusesHistory.historyID))]

public virtual string HistoryID { get; set; }

public abstract class historyID : BqlString.Field<historyID> { }

#endregion


#region DocType

public abstract class docType : BqlString.Field<docType> { }


/// <summary>

/// [key] Type of the document.

/// </summary>

/// <value>

/// Possible values are: "INV" - Invoice, "ACR" - Credit Adjustment, "ADR" - Debit Adjustment,

/// "CHK" - Check, "VCK" - Void Check, "PPM" - Prepayment, "REF" - Vendor Refund,

/// "QCK" - Quick Check, "VQC" - Void Quick Check.

/// </value>

[PXString(3, IsKey = true, IsFixed = true)]

[PXDefault()]

[PXUIField(DisplayName = "Type", Visibility = PXUIVisibility.SelectorVisible, TabOrder = 0, IsReadOnly = true)]

[PXFieldDescription]

public virtual string DocType { get; set; }


#endregion


#region RefNbr

public abstract class refNbr : BqlString.Field<refNbr> { }


/// <summary>

/// [key] Reference number of the document.

/// </summary>

[PXString(20, IsUnicode = true, IsKey = true, InputMask = "")]

[PXDefault()]

[PXUIField(DisplayName = "Reference Nbr.", Visibility = PXUIVisibility.SelectorVisible, TabOrder = 1, IsReadOnly = true)]

public virtual string RefNbr { get; set; }

#endregion

}

 

And the views below were defined :

 

#region Views


public PXFilter<EIStatusesHistoryInqFilter> Filter;


[PXFilterable]

public SelectFrom<EIStatusesHistoryItem>

.InnerJoin<EIStatusesHistory>.On<EIStatusesHistory.historyID.IsEqual<EIStatusesHistoryItem.historyID>>

.Where<EIStatusesHistoryItem.historyID.IsEqual<EIStatusesHistoryInqFilter.historyID.FromCurrent>>

.OrderBy<EIStatusesHistoryItem.status.Desc>

.View.ReadOnly StatusesHistory;


#endregion

 

One thing I’d like to improve : if I refresh the screen (using F5 for instance), all my data is lost and the grid that however was previously filled correctly is emptied !