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.
- 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:
- Prepare an MYOB Acumatica instance by performing the Test Instance for Customization: To Deploy an Instance for Developing Processing Forms prerequisite activity.
- Create a processing form without filtering parameters by performing the Processing Forms: To Create a Simple Processing Form prerequisite activity.
- Add filtering parameter to the form by performing the Filtering Parameters: To Add a Filter for a Processing Form prerequisite activity.
-
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:
- Open the repair work order.
- 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)
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. RSSVEmployeeWorkOrderQty
DAC, you will perform the
following general actions:- 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. - For the DAC, you will specify the
PXHidden
attribute, which indicates that the DAC will not be used for reports or generic inquiries. - In the
RSSVEmployeeWorkOrderQty
DAC, you will define theUserID
andNbrOfAssignedOrders
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.
- Mark the
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:
- 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.";
- 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; } }
- Add the
RSSVEmployeeWorkOrderQtyAccumulator
attribute to theRSSVEmployeeWorkOrderQty
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. - Build the project.