PXAccumulator: To Implement a Custom Accumulator Attribute

The following activity will walk you through the process of implementing a custom accumulator attribute.

Story

In the Smart Fix company, the number of assigned work orders may be updated very often. Users can assign work orders on the Repair Work Orders (RS301000) form and the Assign Work Orders (RS501000) form Also, multiple users may assign repair work orders to the same employee at the same time. Because this causes concurrent updates of one record in the database, the system may display the Another process has updated the record error.

To avoid this error, you will implement a custom attribute derived from the PXAccumulator attribute. In this attribute, you will calculate the number of repair work orders assigned to a particular employee. This attribute will compute the total of the number of repair work orders assigned to each employee and implement a maximum of 10 for this number. The accumulator attribute modifies the SQL query and guarantees that concurrent updates of each record are handled smoothly.

Process Overview

You will create a custom accumulator attribute to add up the numbers of assigned work orders for each employee during the assignment or completion of work orders.

In the custom attribute, you will define the following elements:
  • The constructor, in which you will specify the update mode for the records
  • The PrepareInsert() method, in which you will define the updating policy for the particular field (the values of this field are added) and specify the restriction for the values of this field

You will also assign to the DAC the custom accumulator attribute that stores the field to be updated by the accumulator attribute.

System Preparation

Before you begin implementing a custom PXAccumulator attribute, do the following:

  1. Prepare an MYOB Acumatica instance by performing the Test Instance for Customization: To Deploy an Instance for Developing Processing Forms prerequisite activity.
  2. Create a processing form without filtering parameters by performing the Processing Forms: To Create a Simple Processing Form prerequisite activity.
  3. Add filtering parameter to the form by performing the Filtering Parameters: To Add a Filter for a Processing Form prerequisite activity.
  4. In the system, indicate the completion of all repair work orders that have the Assigned status on the Repair Work Orders (RS301000) form. Do the following for each of the repair work orders that has the Assigned status:

    1. Open the repair work order.
    2. Click Complete on the form toolbar.

    In the database, you have the RSSVEmployeeWorkOrderQty table, which you have added in the Test Instance for Customization: To Deploy an Instance for Developing Processing Forms activity. This table will hold the number of repair work orders assigned to each employee. This table currently contains no data because you have not yet implemented the logic to update the data in the table. However, you may have particular repair work orders assigned to employees. Therefore, you need to complete these repair work orders so that none of the employees has repair work orders assigned and the database table contains the data that correctly reflects the current state of the system.

Step 1: Creating a DAC (Self-Guided Exercise)

As you completed the Test Instance for Customization: To Deploy an Instance for Developing Processing Forms activity, you created the RSSVEmployeeWorkOrderQty database table, whose NbrOfAssignedOrders column will be updated by the custom accumulator attribute. In this step, you will create a data access class for this table.
Tip: The ways to create a DAC are described in detail in the T200 Maintenance Forms training course.
As you add the RSSVEmployeeWorkOrderQty DAC, you will perform the following general actions:
  1. You will create the RSSVEmployeeWorkOrderQty data access class and define its single system field: LastModifiedDateTime. For more information about definition of the LastModifiedDateTime system field, see Audit Fields in the documentation.
  2. For the DAC, you will specify the PXHidden attribute, which indicates that the DAC will not be used for reports or generic inquiries.
  3. In the RSSVEmployeeWorkOrderQty DAC, you will define the UserID and NbrOfAssignedOrders fields and their attributes as follows:
    • Mark the UserID field as the key field, as shown in the following code.
              #region UserID
              [PXDBInt(IsKey = true)]
              public virtual int? UserID { get; set; }
              public abstract class userID : PX.Data.BQL.BqlInt.Field<userID> { }
              #endregion
    • Do not specify any display names for the fields because they will not be displayed in the UI.

Step 2: Implementing the Accumulator Attribute

In this step, you will create the custom RSSVEmployeeWorkOrderQtyAccumulator accumulator attribute for the RSSVEmployeeWorkOrderQty DAC. For each employee, the custom attribute will compute the total of the number of assigned work orders and save the value in the RSSVEmployeeWorkOrderQty.NbrOfAssignedOrders field. The attribute will be derived from the PXAccumulator system attribute. Although the base attribute can also be configured to add up the values in the RSSVEmployeeWorkOrderQty.NbrOfAssignedOrders field, you will use the custom attribute instead of the base one because you need to specify a custom restriction for the number of work orders assigned to an employee (no more than 10 work orders per employee).

To implement the custom accumulator attribute, do the following:

  1. In the Messages.cs file, add the following constant with the message that is displayed when the restriction specified in the accumulator attribute is violated.
            public const string ExceedingMaximumNumberOfAssignedWorkOrders =
                @"Updating the number of assigned work orders for the employee 
                will lead to exceeding of the maximum number of assigned work orders, 
                which is 10.";
  2. In the RSSVEmployeeWorkOrderQty.cs file, define the RSSVEmployeeWorkOrderQtyAccumulator attribute as follows.
        public class RSSVEmployeeWorkOrderQtyAccumulator :
            PXAccumulatorAttribute
        {
            //Specify the single-record mode of update in the constructor.
            public RSSVEmployeeWorkOrderQtyAccumulator()
            {
                _SingleRecord = true;
            }
            //Override the PrepareInsert method.
            protected override bool PrepareInsert(PXCache sender, object row,
                PXAccumulatorCollection columns)
            {
                if (!base.PrepareInsert(sender, row, columns)) return false;
                RSSVEmployeeWorkOrderQty newQty = (RSSVEmployeeWorkOrderQty)row;
                if (newQty.NbrOfAssignedOrders != null)
                {
                    // Add the restriction for the value of 
                    // RSSVEmployeeWorkOrderQty.NbrOfAssignedOrders.
                    columns.AppendException(
                        Messages.ExceedingMaximumNumberOfAssignedWorkOrders,
                    new PXAccumulatorRestriction<
                        RSSVEmployeeWorkOrderQty.nbrOfAssignedOrders>(
                        PXComp.LE, 10));
                }
                // Update NbrOfAssignedOrders by using Summarize.
                columns.Update<RSSVEmployeeWorkOrderQty.nbrOfAssignedOrders>(
                    newQty.NbrOfAssignedOrders,
                    PXDataFieldAssign.AssignBehavior.Summarize);
                return true;
            }
        }
  3. Add the RSSVEmployeeWorkOrderQtyAccumulator attribute to the RSSVEmployeeWorkOrderQty class, as shown below.
        [PXHidden]
        [RSSVEmployeeWorkOrderQtyAccumulator]
        public class RSSVEmployeeWorkOrderQty : PXBqlTable, IBqlTable
        {        ...
        }

    You have added the custom attribute directly to the RSSVEmployeeWorkOrderQty DAC, because this class is updated only from code and not through the UI.

  4. Build the project.