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 with a Custom Form that Implements a Workflow prerequisite activity.
-
Create the database table and include the script for table creation 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 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 of the
RSSVEmployeeWorkOrderQty database table 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
RSSVEmployeeWorkOrderQtydata 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
PXHiddenattribute, which indicates that the DAC will not be used for reports or generic inquiries. - In the
RSSVEmployeeWorkOrderQtyDAC, you will define theUserIDandNbrOfAssignedOrdersfields 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 - 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
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.
