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 work orders assigned to each employee changes frequently. Users can assign work orders on both the Repair Work Orders (RS301000) form and the Assign Work Orders (RS501000) form. Multiple users may assign repair work orders to the same employee at the same time. These concurrent updates of a record trigger this error: Another process has updated the record.
To avoid this error, you’ll implement a custom attribute derived from the PXAccumulator attribute. The accumulator attribute modifies the SQL query and guarantees that concurrent updates of each record are handled smoothly. In this attribute, you’ll calculate the number of repair work orders assigned to each employee and enforce a maximum of 10.
Process Overview
You will create a custom accumulator attribute to calculate 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’ll define the updating policy for the field 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 with a Custom Form that Implements a Workflow prerequisite activity.
-
Create the database table and include the creation script in the customization project as follows:
- In SQL Server Management Studio, execute the T240_DatabaseTables.sql script to
create the
RSSVEmployeeWorkOrderQtydatabase table. - On the Database Scripts page of the
Customization Project Editor, for the added table, do the following:
- On the page toolbar, click Add Custom Table Schema.
- In the dialog box that opens, select the table and click OK.
- Publish the project.
Tip:For details on designing database tables for MYOB Acumatica, see Designing the Database Structure and DACs. - In SQL Server Management Studio, execute the T240_DatabaseTables.sql script to
create the
-
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.
The
RSSVEmployeeWorkOrderQtytable will hold the number of repair work orders assigned to each employee. This table currently contains no data because you haven’t yet implemented the logic to update the data in the table. However, if any repair work orders assigned to employees, you need to complete them. As a result, none of the employees has repair work orders assigned and the table’s data 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’ll create a data access class for this
table. RSSVEmployeeWorkOrderQty DAC, you’ll perform the
following general actions:- Create the
RSSVEmployeeWorkOrderQtydata access class and define its single system field: LastModifiedDateTime. (For more information about the definition of the LastModifiedDateTime system field, see Audit Fields in the documentation.) - For the DAC, specify the
PXHiddenattribute, which indicates that the DAC won’t be used for reports or generic inquiries. - In the DAC, define the
UserIDandNbrOfAssignedOrdersfields and their attributes as follows:- Mark the
UserIDfield 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 - Don’t specify any display names for the fields because they won’t be displayed in the UI.
- Mark the
Step 2: Implementing the Accumulator Attribute
In this step, you’ll create the custom
RSSVEmployeeWorkOrderQtyAccumulator accumulator attribute for
the RSSVEmployeeWorkOrderQty DAC. For each employee, this 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. The base attribute can also be configured to calculate the values in the
RSSVEmployeeWorkOrderQty.NbrOfAssignedOrders field. You will
instead use the custom attribute because you need to specify a custom restriction
for the number of work orders assigned to an employee—a maximum of 10.
To implement the custom accumulator attribute, do the following:
- In the Messages.cs file, add the following constant with
the message that’s 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
RSSVEmployeeWorkOrderQtyAccumulatorattribute 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
RSSVEmployeeWorkOrderQtyAccumulatorattribute to theRSSVEmployeeWorkOrderQtyclass, as shown below.[PXHidden] [RSSVEmployeeWorkOrderQtyAccumulator] public class RSSVEmployeeWorkOrderQty : PXBqlTable, IBqlTable { ... }You have added the custom attribute directly to the
RSSVEmployeeWorkOrderQtyDAC because this class is updated only from code and not through the UI. - Build the project.
