Inquiry Forms: To Set Up an Inquiry Form

The following activity will walk you through the process of creating an inquiry form without any filtering parameters.

Story

Suppose that you need to create an inquiry form in the PhoneRepairShop customization project that will display all repair work orders that have not yet been paid in full, along with information about the invoices that have been created for these orders.

Process Overview

In this activity, you will create the Open Payment Summary (RS401000) custom inquiry form and define and configure its components by performing the following steps:
  1. Creating the inquiry form
  2. Defining the DAC for the grid view of the inquiry form
  3. Calculating a value of the field in the RowSelecting event handler
  4. Defining the data view for the inquiry form

System Preparation

Make sure that you have configured your instance as described in Test Instance for Customization: To Deploy an Instance with a Custom Form that Implements a Workflow.

Step 1: Creating the Form—Self-Guided Exercise

In this self-guided exercise, you will create the Open Payment Summary (RS401000) form on your own. Although this is a self-guided exercise, you can use the details and suggestions in this topic as you create the form. The creation of a form is described in detail in the T200 Maintenance Forms training course.

If you are using the Customization Project Editor to complete the self-guided exercise, you can perform the following instructions:

  1. On the Customization Projects (SM204505) form, click the name of your customization project.

    The Screens page of the Customization Project Editor opens.

  2. On the page toolbar of the Screens page of the Customization Project Editor, click Create Screen.
  3. In the Create Screen dialog box, which opens, specify the following values:
    • Screen ID: RS.40.10.00
    • Graph Name: RSSVPaymentPlanInq
    • Graph Namespace: PhoneRepairShop
    • Page Title: Open Payment Summary
    • Template: FormGrid (FormDetail)
  4. Move the RSSVPaymentPlanInq graph, which has been generated, to the extension library.
    Tip:
    • Do not make any standard system actions available.
    • Do not define any data views. You will define the data view later in this activity.
  5. Make sure that the RSSVWorkOrder DAC is defined in the PhoneRepairShop_Code Visual Studio project.

    Do not define any new DACs; you will define a new DAC in the next step.

  6. Build the project in Visual Studio.
  7. Update the customization project with a new version of PhoneRepairShop_Code.dll, and publish the customization project.
  8. Add a link to the Open Payment Summary form to the Inquiries category of the Phone Repair Shop workspace, and make it available in the quick menu.
  9. In the Customization Project Editor, update the SiteMapNode item for the Open Payment Summary form.

Step 2: Defining the DAC for the Grid View of the Form

The Open Payment Summary (RS401000) form displays information about repair work orders (including the details of the invoice created for each order). All fields on this form are unbound, and you do not need to work with the fields on the Repair Work Orders (RS301000) form, which works with the RSSVWorkOrder DAC.

In this step, for the grid view of the Open Payment Summary form, you will derive the new RSSVWorkOrderToPay class from RSSVWorkOrder and extend the new class with additional DAC fields that are specific to the inquiry form. In the derived DAC, you will add the OrderNbr, InvoiceNbr, and Status abstract classes (which are defined in the base RSSVWorkOrder DAC) with the new modifier. You need to define new abstract classes because you will use the data fields of the derived class in BQL statements (such as the BQL statements in the data view of a processing form and in attributes).

To define the RSSVWorkOrderToPay DAC, do the following:

  1. In the Helper/Messages.cs file, add the RSSVWorkOrderToPay string to the Messages class as shown in the following code. This message will be used in the PXCacheName attribute for the new DAC.
            public const string RSSVWorkOrderToPay = "Repair Work Order to Pay";
  2. In the RSSVWorkOrder.cs file, declare the RSSVWorkOrderToPay DAC: Derive the RSSVWorkOrderToPay class from RSSVWorkOrder, as shown in the following code.
        [PXCacheName(Messages.RSSVWorkOrderToPay)]
        public class RSSVWorkOrderToPay : RSSVWorkOrder
        {
        }
  3. In the RSSVWorkOrderToPay class, define the OrderNbr, InvoiceNbr, and Status abstract classes with the new modifier, as shown in the following code.
            #region InvoiceNbr
            public new abstract class invoiceNbr :
                PX.Data.BQL.BqlString.Field<invoiceNbr>
            { }
            #endregion
    
            #region Status
            public new abstract class status :
                PX.Data.BQL.BqlString.Field<status>
            { }
            #endregion
    
            #region OrderNbr
            public new abstract class orderNbr :
                PX.Data.BQL.BqlString.Field<orderNbr>
            { }
            #endregion
  4. In the RSSVWorkOrderToPay class, define the PercentPaid field, as shown in the following code.
            #region PercentPaid
            [PXDecimal]
            [PXUIField(DisplayName = "Percent Paid")]
            public virtual Decimal? PercentPaid { get; set; }
            public abstract class percentPaid :
                PX.Data.BQL.BqlDecimal.Field<percentPaid>
            { }
            #endregion

Step 3: Calculating the PercentPaid Field in RowSelecting

In the derived DAC, you have added the PercentPaid field. During the retrieval of each of the RSSVWorkOrder records, the value of the PercentPaid field will be calculated from the database as the percentage of invoice amount that has been paid. Add this logic as follows:

  1. In the RSSVPaymentPlanInq.cs file, in the RSSVPaymentPlanInq graph, add the calculation of the PercentPaid field value in the RowSelecting event, as shown in the following code.
            protected virtual void _(Events.RowSelecting<RSSVWorkOrderToPay> e)
            {
                if (e.Row == null) return;
                if (e.Row.OrderTotal == 0) return;
                RSSVWorkOrderToPay order = e.Row;
                var invoices = 
                    SelectFrom<ARInvoice>.
                    Where<ARInvoice.refNbr.IsEqual<@P.AsString>>.
                    View.Select(this, order.InvoiceNbr);
                if (invoices.Count == 0)
                    return;
                ARInvoice first = invoices[0];
                e.Row.PercentPaid = (order.OrderTotal - first.CuryDocBal) /
                    order.OrderTotal * 100;
            }

    In the event handler, you are selecting the invoice with the same number as the one specified in the repair work order; you are then calculating the percentage.

    Tip: In Visual Studio, Acuminator incorrectly shows a warning that PXConnectionScope() should be used in a RowSelecting event handler. This is a known issue, and it will be fixed in a future release of Acuminator.

    You need to use an event handler instead of attributes because you cannot check for 0 values by using attributes.

    Tip: If you have generated the RSSVPaymentPlanInq graph from the Code Editor, you can remove the Save and Cancel actions defined in the graph.
  2. In the RSSVPaymentPlanInq.cs file, add the required using directives, which are shown in the following code.
    using PX.Data.BQL.Fluent;
    using PX.Data.BQL;
    using PX.Objects.AR;
  3. Build the project.

Step 4: Defining the Data View of the Form

In this step, you will add the data view to the RSSVPaymentPlanInq graph, which works with the Open Payment Summary (RS401000) form. In this data view that provides data for the grid (table) of the inquiry form, you should select only those repair work orders that are not yet paid and the invoices for these orders.

To define the data view of the form in the RSSVPaymentPlanInq graph, do the following:

  1. In the RSSVPaymentPlanInq.cs graph, add the following member. (Replace the automatically generated DetailsView member if you have used the Customization Project Editor to create the graph.)
            [PXFilterable]
            public SelectFrom<RSSVWorkOrderToPay>.
                InnerJoin<ARInvoice>.On<ARInvoice.refNbr.
                    IsEqual<RSSVWorkOrderToPay.invoiceNbr>>.
                Where<RSSVWorkOrderToPay.status.
                    IsNotEqual<RSSVWorkOrderEntry_Workflow.States.paid>>.
                View.ReadOnly DetailsView = null!;

    The InnerJoin clause adds information from the invoice that was created for the repair work order so that you can display the due date and balance of the invoice on the page.

    The Where clause excludes all orders with the Paid status from the results of the query.

    Because users do not need to edit any records on the inquiry form, you have used the ReadOnly view type, which defines the selection of records in read-only mode. In the UI, MYOB Acumatica Framework automatically disables the editing of data records that were retrieved through a read-only data view.

  2. If you have generated the RSSVPaymentPlanInq graph from the Code Editor, remove the MasterView view and the MasterTable and DetailsTable classes.
  3. Build the project.

After you have defined the backend of the form, you can proceed with creating the UI of the form, as described in Inquiry Forms: To Create the UI of an Inquiry Form That Includes Only a Grid.