T190 QuickStartInCustomization 2023R2
T190 QuickStartInCustomization 2023R2
Customization
Revision: 11/7/2023
Contents | 2
Contents
Copyright...............................................................................................................................................4
How to Use This Course.......................................................................................................................... 5
Company Story and Customization Description........................................................................................ 7
Initial Configuration............................................................................................................................... 8
Step 1: Preparing the Environment.................................................................................................................. 8
Step 2: Preparing the Needed Acumatica ERP Instance for the Training Course........................................... 8
Lesson 1: Creating a Customization Project............................................................................................ 10
Step 1.1: Creating a Customization Project....................................................................................................10
Step 1.2: Loading Items to the Customization Project.................................................................................. 10
Step 1.3: Binding the Extension Library......................................................................................................... 12
Step 1.4: Publishing the Customization Project.............................................................................................12
Step 1.5: Reviewing the Changes in Acumatica ERP......................................................................................13
Lesson Summary............................................................................................................................................. 14
Additional Information: Customization Project Management...................................................................... 15
Lesson 2: Creating Custom Fields...........................................................................................................16
Step 2.1: Creating a Custom Column and Field with the Project Editor....................................................... 17
Step 2.2: Creating a Control for the Custom Field......................................................................................... 20
Step 2.3: Creating a Custom Column with the Project Editor and a Custom Field with Visual Studio.......23
Step 2.4: Creating a Control for the Custom Field—Self-Guided Exercise.................................................... 25
Step 2.5: Making the Custom Field Conditionally Available (with RowSelected)......................................... 26
Step 2.6: Testing the Customized Form..........................................................................................................30
Lesson Summary............................................................................................................................................. 30
Additional Information: DAC Extensions........................................................................................................ 31
Additional Information: Custom Elements.....................................................................................................32
Lesson 3: Implementing the Update and Validation of Field Values........................................................... 33
Step 3.1: Updating Fields of a Record on Update of a Field of This Record (with FieldUpdated and
FieldDefaulting)................................................................................................................................................33
Step 3.2: Validating an Independent Field Value (with FieldVerifying).........................................................35
Lesson Summary............................................................................................................................................. 39
Additional Information: Data Querying..........................................................................................................40
Additional Information: Use of Event Handlers............................................................................................. 40
Lesson 4: Creating an Acumatica ERP Entity Corresponding to a Custom Entity......................................... 41
Step 4.1: Performing Preliminary Steps......................................................................................................... 41
Step 4.2: Defining the Logic of Creating an SO Invoice................................................................................. 42
Contents | 3
Copyright
No part of this document may be reproduced, copied, or transmitted without the express prior consent of
Acumatica, Inc.
3933 Lake Washington Blvd NE, # 350, Kirkland, WA 98033
Restricted Rights
The product is provided with restricted rights. Use, duplication, or disclosure by the United States Government is
subject to restrictions as set forth in the applicable License and Services Agreement and in subparagraph (c)(1)(ii)
of the Rights in Technical Data and Computer Soware clause at DFARS 252.227-7013 or subparagraphs (c)(1) and
(c)(2) of the Commercial Computer Soware-Restricted Rights at 48 CFR 52.227-19, as applicable.
Disclaimer
Acumatica, Inc. makes no representations or warranties with respect to the contents or use of this document, and
specifically disclaims any express or implied warranties of merchantability or fitness for any particular purpose.
Further, Acumatica, Inc. reserves the right to revise this document and make changes in its content at any time,
without obligation to notify any person or entity of such revisions or changes.
Trademarks
Acumatica is a registered trademark of Acumatica, Inc. HubSpot is a registered trademark of HubSpot, Inc.
Microso Exchange and Microso Exchange Server are registered trademarks of Microso Corporation. All other
product names and services herein are trademarks or service marks of their respective companies.
We recommend that you complete the examples in the order in which they are provided in the course,
because some examples use the results of previous ones.
What Is in a Lesson
Each lesson is dedicated to a particular development scenario that you can implement by using Acumatica ERP
customization tools and Acumatica Framework. Each lesson consists of a brief description of the scenario and an
example of the implementation of this scenario.
The lesson may also include Additional Information topics, which are outside of the scope of this course but may be
useful to some readers.
Each lesson ends with a Lesson Summary topic, which summarizes the development techniques used during the
implementation of the scenario.
Company Story
The Smart Fix company specializes in repairing cell phones of several types. The company provides the following
services:
• Battery replacement: This service is provided on customer request and does not require any preliminary
diagnostic checks.
• Repair of liquid damage: This service requires a preliminary diagnostic check and a prepayment.
• Screen repair: This service is provided on customer request and does not require any preliminary diagnostic
checks.
In this course, you will implement particular customization scenarios to support the cell phone repair shop of the
Smart Fix company. The full implementation of the customization for the cell phone repair shop is described in the
following training courses: T200 Maintenance Forms, T210 Customized Forms and Master-Detail Relationship, T220
Data Entry and Setup Forms, T230 Actions, T240 Processing Forms, and T250 Inquiry Forms.
We recommend that you complete these training courses to have a better understanding of
Acumatica Framework and Acumatica ERP customization tools. If you are going to complete these
courses, you can skip T190 Quick Start in Customization.
Customization Description
In this course, you will customize the Stock Items (IN202500) form of Acumatica ERP to mark particular stock items
as repair items—that is, items that are used for repair services.
You will also implement the following scenarios as you complete this course:
• Update of a field value that depends on another field value on the Services and Prices custom maintenance
form
• Validation of a field value on the Repair Work Orders custom data entry form
• Creation of an SO invoice for a repair work order on the Repair Work Orders form
You will also learn how to debug the customization code and the source code of Acumatica ERP.
Initial Configuration | 8
Initial Configuration
You need to perform the prerequisite actions before you start to complete the course.
You should prepare the environment for the training course as follows:
1. Make sure that the environment that you are going to use conforms to the System Requirements for
Acumatica ERP 2023 R2.
2. Make sure that the Web Server (IIS) features that are listed in Configuring Web Server (IIS) Features are
turned on.
3. Install the Acuminator extension for Visual Studio.
4. Clone or download the customization project and the source code of the extension library from the Help-
and-Training-Examples repository in Acumatica GitHub to a folder on your computer.
5. Install Acumatica ERP. On the Main Soware Configuration page of the Acumatica ERP Setup Wizard, select
the Install Acumatica ERP and Install Debugger Tools check boxes.
If you have already installed Acumatica ERP without debugger tools, you should remove
Acumatica ERP and install it again with the Install Debugger Tools check box selected. The
reinstallation of Acumatica ERP does not affect existing Acumatica ERP instances. For details,
see To Install the Acumatica ERP Tools.
Step 2: Preparing the Needed Acumatica ERP Instance for the Training Course
Lesson Objectives
As you complete this lesson, you will learn how to do the following:
• Create a customization project
• Load a customization project from a local folder
• Bind a customization project to an extension library
• Publish a customization project
The creation of a customization project is a first step in the customization of Acumatica ERP. To create the
customization project you will use in this course, do the following:
1. In Acumatica ERP, open the Customization Projects (SM204505) form.
2. On the form toolbar, click Add Row.
3. In the Project Name column, enter the customization project name: PhoneRepairShop.
4. On the form toolbar, click Save.
You have created the customization project. In the next step, you will open the Customization Project Editor and
begin the customization.
Related Links
• Customization Projects: To Create a Customization Project
In this step, you will begin working in the Customization Project Editor and will load customization items from the
customization project that has been prepared for this training course into the customization project created in the
previous lesson. The customization project that has been prepared for this training course contains the changes
that have been implemented for the customization of Acumatica ERP for the Smart Fix company. (These changes
are described in Company Story and Customization Description.)
Lesson 1: Creating a Customization Project | 11
The items of the customization project have been loaded, as shown in the following screenshot.
The Customized Screens page can contain rows with empty Screen ID and Title because the
customization project has not been published yet.
Related Links
• To Update the Content of a Project from a Local Folder
Lesson 1: Creating a Customization Project | 12
In this step, you will bind the PhoneRepairShop customization project to the extension library that contains source
code of customization items you have loaded to the customization project.
By default, the system uses the App_Data\Projects folder of the website as the parent
folder for the solution projects of extension libraries.
If the website folder is outside of the C:\Program Files (x86), C:\Program Files,
and C:\Users folders, we recommend that you use the App_Data\Projects folder for
the project of the extension library.
If the website folder is in the C:\Program Files (x86), C:\Program Files, or C:
\Users folder, we recommend that you store the project outside of these folders to avoid an
issue with permission to work in these folders. In this case, you need to update the links to the
website and library references in the project.
2. On the menu of the Customization Project Editor, click Extension Library > Bind to Existing.
3. In the dialog box that opens, specify the path to the App_Data\Projects\PhoneRepairShop_Code
folder, and click OK.
4. Open the Visual Studio solution and build the PhoneRepairShop_Code project.
Related Links
• Extension Library (DLL) Versus Code in a Customization Project
In this step, you will publish the PhoneRepairShop customization project to apply the changes in this project to the
Acumatica ERP instance.
6. On the menu of the Customization Project Editor, click Publish > Publish Current Project.
The Compilation panel opens, which shows the progress of the publication.
7. Close the Compilation panel when the publication has completed and the Website updated message is
displayed.
Related Links
• Publishing Customization Projects
In this step, you will review the changes to the Acumatica ERP instance that have been applied as a result of the
publication of the PhoneRepairShop customization project.
3. Open the Repair Services (RS201000) form, and review its content and functionality, which is shown in the
following screenshot.
Lesson 1: Creating a Customization Project | 14
4. Open any other forms in the Phone Repair Shop workspace, and review their content and functionality.
5. In Microso SQL Server Management Studio, connect to the database of your Acumatica ERP instance for
the training course. Find the database tables with names that start with RSSV. These are the custom tables
that have been added during the publication of the customization project.
6. Open the Acumatica ERP instance folder in the file system. Notice the following files and folders:
• Pages\RS: Contains the ASPX code of the custom forms. The forms have the RS prefix in their IDs;
therefore, they are placed in the custom RS subfolder.
• InputData: Contains CSV files with the data for the custom tables. This data is inserted in the database
by the InputData customization plug-in, which is included in the customization project.
• CstPublished\pages_RS: Contains the published code of the custom ASPX pages.
• Bin\PhoneRepairShop_Code.dll: Contains the customization source code in an extension library.
Lesson Summary
In this lesson, you have learned how to create a customization project, load content to a customization project from
a local folder, bind the project to an extension library, and publish the project.
The following diagram shows the changes that have been applied to the Acumatica ERP instance for the training
course aer the customization project has been published.
Lesson 1: Creating a Customization Project | 15
In this lesson, you have created and published a customization project. Other ways to manage customization
projects is outside of the scope of this course, as is the management of different types of items in customization
projects.
You can find examples of ways to work with customization projects and to include different types of items in a
customization project in the following training courses:
• T200 Maintenance Forms
• T210 Customized Forms and Master-Detail Relationship
• T220 Data Entry and Setup Forms
• T240 Processing Forms
• W140 Customization Projects
• Customization Projects: To Create a Customization Project
• Customization Items: To Add Items to the Customization Project
• Project Publication: To Deploy a Customization Project
• Project Publication: To Publish Two Customization Projects
Lesson 2: Creating Custom Fields | 16
UI Changes
In this lesson, you will add the following custom controls to the Stock Items (IN202500) form of Acumatica ERP:
• Repair Item: A check box that indicates (if selected) that the stock item can be used during the provision of
the repair services of the Smart Fix company
• Repair Item Type: A drop-down list box for the repair item type, which is one of the following:
• Battery
• Screen
• Screen Cover
• Back Cover
• Motherboard
You will add these controls to the Item Defaults section of the General tab of the form (see the following
screenshot).
Database Changes
The General tab displays the stock item's general information, which is stored in the data record of the
IN.InventoryItem data access class. Hence, you will add the custom fields to this class. To be able to save the
repair item data to the database, you will add the database columns for the new values. The IN.InventoryItem
class records are stored in the InventoryItem database table; therefore, you will add columns for the new fields
to this table.
Lesson Objectives
As you complete this lesson, you will learn how to do the following:
• Add a custom column to an Acumatica ERP database table
• Add a custom field to an Acumatica ERP data access class
• Add the control for the custom field to the form
Step 2.1: Creating a Custom Column and Field with the Project Editor
In this step, you will create a custom column in the InventoryItem database table and a custom field in the
IN.InventoryItem data access class for this column. This column and field will be used to store and edit the
value of the Repair Item check box. You will use the Customization Project Editor to add the column and field.
The approach described in this step is the easiest way to create both the column in the database and
the bound field in the corresponding data access class.
We recommend that you not write custom SQL scripts to add changes to the database schema. If
you add a custom SQL script, you must adhere to platform requirements that apply to custom SQL
scripts, such as the support of multitenancy and the support of SQL dialects of the target database
management systems. If you use the approach described in this topic, during the publication of the
customization project, the platform generates SQL statements to alter the existing table so that this
statement conforms to all platform requirements.
You will create an extension of the IN.InventoryItem DAC to hold custom fields (which is referred to as a DAC
extension or cache extension). Acumatica Customization Platform creates an extension for every customized DAC to
hold custom fields and customized attributes. At runtime, during the first initialization of a base class, the platform
automatically finds the extension for the class and applies the customization by replacing the base class with
the merged result of the base class and the extension it found. For more information about DAC extensions, see
Changes in the Application Code (C#).
You will also move the generated code to the extension library and adjust it with Acuminator.
b. Click the name of the General tab to open the Element Properties dialog box for the tab control, as
shown in the following screenshot. In the dialog box, notice the following:
• Tab (the PXTab control) is the type of UI container whose area you have clicked for inspection.
• The InventoryItem data access class provides the data fields for the controls on the inspected
tab.
By clicking the link with the name of the DAC you can view details about this DAC in the
DAC Schema Browser.
c. Click Customize.
d. In the Select Customization Project dialog box, which opens, select the PhoneRepairShop
customization project, and click OK.
Lesson 2: Creating Custom Fields | 19
The Customization Project Editor opens for the PhoneRepairShop project; the Screen Editor is displayed
for the Tab: ItemSettings node, which is selected in the control tree.
2. To add a custom field for the Repair Item check box in the customization project, do the following:
a. On the Screen Editor page, click the Add Data Fields tab.
b. On the table toolbar, click New Field.
c. In the Create New Field dialog box, which opens, specify the following settings for the new field:
• Field Name: RepairItem
As soon as you move the focus out of the Field Name box, the system adds the Usr
prefix to the field name, which provides a distinction between the original fields and the
new custom fields that you add to the class. Keep the prefix in the field name.
For details how to move a DAC to an extension library, see To Move a DAC Item to an Extension
Library in the documentation.
c. Place the cursor to the InventoryItemExt class name and in the Quick Actions menu select Mark
the type as sealed, as the following screenshot shows. Acuminator adds the sealed modifier.
[PXDBBool]
[PXUIField(DisplayName="Repair Item")]
f. Add the PXDefault attribute as shown in the following code. The check box that will correspond to the
field will be cleared by default and the value of the field will not be required.
Related Links
• To Add a Custom Data Field
• To Move a DAC Item to an Extension Library
• To Publish the Current Project
• Changes in the Application Code (C#)
• To Enable a DAC Extension Conditionally (IsActive)
Now you will create a control for the custom field that you added to the PhoneRepairShop customization project in
the previous step.
For you to create a control for a field on a form in an application instance, both of the following conditions must be
met:
• The field exists in the instance.
Lesson 2: Creating Custom Fields | 21
• The field is available through a data view that refers to the data access class containing the field declaration.
b. On the Add Data Fields tab, select the unlabeled check box for the row with the custom field.
c. On the table toolbar, click Create Controls to create the control for the selected field.
The control appears in the control tree of the Screen Editor beneath the Type node (see the following
screenshot). Notice that the Used check box has been selected for the field, meaning that a control for
this field has been added to the layout.
Lesson 2: Creating Custom Fields | 22
5. On the menu of the Customization Project Editor, click Publish > Publish Current Project to apply the
customization to the site.
The Modified Files Detected dialog box opens before publication because you have rebuilt
the extension library in the PhoneRepairShop_Code Visual Studio project. The Bin
\PhoneRepairShop_Code.dll file has been modified and you need to update it in the
project before the publication.
As the system applies the customization to the website, the system generates the proper SQL script by using
the definition of the new database column added to the project; it then executes the script on the database.
The system also generates ASPX code for the custom control.
If you unpublish the project, the changes to the database schema and any custom data
already entered remain in the database; the UI changes are removed.
Related Links
• To Add a Box for a Data Field
• Changes in Webpages (ASPX)
Step 2.3: Creating a Custom Column with the Project Editor and a Custom Field
with Visual Studio
In this step, you will create a custom column in the InventoryItem database table and a custom field in the
IN.InventoryItem data access class for this column. This column will hold the value of the Repair Item Type
box of the Stock Items (IN202500) form, which corresponds to the field. You will use Visual Studio to add the DAC
field and the Customization Project Editor to add the database column.
We recommend that you not write custom SQL scripts to add changes to the database schema. If
you add a custom SQL script, you must adhere to platform requirements that apply to custom SQL
scripts, such as the support of multitenancy and the support of SQL dialects of the target database
management systems. If you use the approach described in this topic, during the publication of the
customization project, the platform generates SQL statements to alter the existing table so that this
statement conforms to all platform requirements.
You will define the UsrRepairItemType data field in the InventoryItemExt DAC extension. The fields in the
DAC extensions are defined in the same way as they are in DACs. For details about the definition of DACs, see Data
Access Classes.
You will define the Repair Item Type combo box as the input control for the UsrRepairItemType data field
by adding the PXStringList attribute to the field. The control will give the user the ability to select one of the
following repair item types: Battery, Screen, Screen Cover, Back Cover, or Motherboard.
Lesson 2: Creating Custom Fields | 24
The InventoryItem database script is already present on the page. So, alternatively, you can
click on the InventoryItem row, and in the Edit Table Columns dialog box which appears,
click Add > Add New Column.
3. In the Helper\Messages.cs file, add the constants for the repair item types (if they have not been
added yet) to the Messages class, as shown in the following code.
4. In the InventoryItemExt class of the InventoryItemExtensions.cs file, add a custom field for
the Repair Item Type box, as the following code shows.
#region UsrRepairItemType
[PXDBString(2, IsFixed = true)]
[PXStringList(
new string[]
{
Lesson 2: Creating Custom Fields | 25
PhoneRepairShop.RepairItemTypeConstants.Battery,
PhoneRepairShop.RepairItemTypeConstants.Screen,
PhoneRepairShop.RepairItemTypeConstants.ScreenCover,
PhoneRepairShop.RepairItemTypeConstants.BackCover,
PhoneRepairShop.RepairItemTypeConstants.Motherboard
},
new string[]
{
PhoneRepairShop.Messages.Battery,
PhoneRepairShop.Messages.Screen,
PhoneRepairShop.Messages.ScreenCover,
PhoneRepairShop.Messages.BackCover,
PhoneRepairShop.Messages.Motherboard
})]
[PXUIField(DisplayName = "Repair Item Type")]
public string UsrRepairItemType { get; set; }
public abstract class usrRepairItemType :
PX.Data.BQL.BqlString.Field<usrRepairItemType>
{ }
#endregion
In the first parameter of the PXStringList constructor, you specify the list of possible values for the field,
while in the second parameter, you specify the labels that correspond to the values and are displayed on
the form. Because the possible values for the field have a fixed two-character length, you have specified the
IsFixed = true and the length equal to 2 for the PXDBString attribute.
5. Build the project.
Related Links
• To Add a Custom Column to an Existing Table
• PXStringListAttribute Class
• Data Access Classes
Now you will create a control on your own for the Repair Item Type custom field, which you added to the
PhoneRepairShop customization project in the previous step. The addition of a control for the field was described
earlier in this lesson.
For custom forms (that is, the forms that have been created from scratch and added to the
customization project), you can edit the ASPX code in the Pages folder of the site. For customized
forms, the Pages folder of the site contains the original version of the ASPX code for this form; the
customized version is available only in the CstPublished folder of the site. You can edit ASPX in
the CstPublished folder to speed up development and testing of the UI changes because these
changes are displayed in the UI without publishing of the customization project. However, these
changes will be overridden once you publish the customization project.
Once you complete this step, the Stock Items (IN202500) form will look as shown in the following screenshot. The
InventoryItem database table contains the UsrRepairItemType column of the nvarchar(2) type.
Lesson 2: Creating Custom Fields | 26
Related Links
• To Add a Box for a Data Field
• Changes in Webpages (ASPX)
Step 2.5: Making the Custom Field Conditionally Available (with RowSelected)
In this step, you will learn how to work with a custom control that is available only conditionally. The Repair Item
Type box should be unavailable on the Stock Items (IN202500) form unless the Repair Item check box is selected.
The user can edit a field value in the UI if the control for the field is available on the form. You can
make a control available or unavailable by specifying the Enabled parameter of the PXUIField
attribute in the data access class, or by specifying the Enabled property of the control in the
ASPX page. Generally, for a data field that should be unconditionally unavailable in the UI, you
set the Enabled property of the control to False in the ASPX page. For example, you use this
approach for calculated fields with totals that users will never edit. As the result, the UI controls are
unconditionally unavailable, regardless of the logic implemented in event handlers.
Lesson 2: Creating Custom Fields | 27
The platform creates a template for the InventoryItem_RowSelected event handler in the
extension for the InventoryItemMaint graph. The platform opens the InventoryItemMaint
Code item in the Code Editor of the Customization Project Editor.
e. To move the generated template to the extension library, click Move to Extension Lib on the toolbar of
the Code Editor.
Alternatively, you can add the InventoryItemMaint.cs file in Visual Studio and add the
event handler in the file.
For details about generic event handlers, see Types of Graph Event Handlers.
The code above makes the usrRepairItemType custom field available for editing if the value of
the UsrRepairItem field of the row in PXCache is true. Otherwise, it makes the custom field
unavailable.
f. Build the project.
4. Update the customization project with the changes you have made in this lesson, and publish the project.
5. Open the Screen Editor for the Stock Items (IN202500) form.
6. Set the CommitChanges property to True for the UsrRepairItem data field, as the following
screenshot shows.
Related Links
• PXUIFieldAttribute Class
• Use of the CommitChanges Property of Boxes
• Access to a Custom Field
• Configuration of the User Interface in Code
Lesson 2: Creating Custom Fields | 30
Now you will modify the BAT3310, BAT3310EX, and BCOV3310 stock item records to indicate that they are repair
items. To do this, perform the following actions:
1. On the Stock Items (IN202500) form, select the BAT3310 stock item.
2. Notice that the Repair Item Type box in the Item Defaults section of the General tab is unavailable
because the Repair Item check box is cleared.
3. In the Item Defaults section of the General tab, specify the following settings:
• Repair Item: Selected
Notice that once you select the check box, the Repair Item Type box becomes available.
• Repair Item Type: Battery
4. On the form toolbar, click Save to save the record in the database.
5. Repeat the previous instructions to modify the BAT3310EX and BCOV3310 stock item records as specified in
the following table.
To ensure that the InventoryItem table of the database contains the custom columns and the data
entered, you can review the table by using SQL Server Management Studio.
Lesson Summary
In this lesson, you have learned how to create a control so that you can display on a form a custom field bound
to the database. To implement this customization, you have learned how to add the necessary modifications to a
customization project and how to publish the project to apply the changes to the system.
As you have completed the lesson, you have added the following elements to the PhoneRepairShop customization
project:
• Two column definitions in the InventoryItem table of the database.
• Two custom field declarations in the extension of the IN.InventoryItem data access class (in the
PhoneRepairShop_Code extension library).
• Two controls to display the custom fields on the Stock Items (IN202500) form.
• One custom event handler, which you have added to the InventoryItemMaint graph. You have used
the RowSelected event handler to configure the UI presentation logic.
The following diagram shows the results of the lesson.
Lesson 2: Creating Custom Fields | 31
You can not only create custom fields but also customize existing Acumatica ERP fields and include your
customizations in DAC extensions of different levels. These scenarios are outside of the scope of this course but
may be useful to some readers.
In this lesson, you have learned how to create a custom check box and drop-down list on an Acumatica ERP form.
The creation of other custom elements, such as tabs, is outside of the scope of this course.
You can find information about the creation of custom elements, along with examples, in the lessons of the T210
Customized Forms and Master-Detail Relationship training course.
Lesson 3: Implementing the Update and Validation of Field Values | 33
Lesson Objectives
As you complete this lesson, you will learn how to do the following:
• Update the fields of a data record on update of a field of this record
• Validate the value of a field that does not depend on the values of other fields of the same record
Step 3.1: Updating Fields of a Record on Update of a Field of This Record (with
FieldUpdated and FieldDefaulting)
In this step, you will add code that does the following when the RSSVRepairItem.InventoryID value is
changed: It copies the RSSVRepairItem.BasePrice and RSSVRepairItem.RepairItemType values
from the stock item record that has the ID equal to the new RSSVRepairItem.InventoryID value.
You will use the FieldUpdated event handler for the RSSVRepairItem.InventoryID field to update the
values of the following fields of the same record:
• RSSVRepairItem.RepairItemType: Instead of directly assigning the value to this field, you will call
the SetValueExt<field> method to assign the value and invoke the FieldUpdated event handler
for this field.
• RSSVRepairItem.BasePrice: You will trigger the FieldDefaulting event for this field
by using the SetDefaultExt<field> method of PXCache. You will assign the value of the
RSSVRepairItem.BasePrice field in the FieldDefaulting event handler.
Lesson 3: Implementing the Update and Validation of Field Values | 34
You will not assign the value of the RSSVRepairItem.BasePrice field in the
FieldUpdated event handler, because this field may depend on multiple fields of the same
record. For example, the price can depend on not only the item selected in the line but also the
discount specified for this line. In this example, the RSSVRepairItem.BasePrice field
depends only on the RSSVRepairItem.InventoryID value, but we recommend that you
use this approach for the fields that may depend on multiple fields of the same record.
//Update the price and repair item type when the inventory ID of
//the repair item is updated.
protected void _(Events.FieldUpdated<RSSVRepairItem,
RSSVRepairItem.inventoryID> e)
{
RSSVRepairItem row = e.Row;
3. Define the FieldDefaulting event handler for the RSSVRepairItem.basePrice field in the
RSSVRepairPriceMaint class as follows to calculate the default value of the field.
Related Links
• Access to a Custom Field
• PXSelectorAttribute Class
In this step, you will implement the validation of the value in the Quantity column on the Labor tab of the Repair
Work Orders (RS301000) form. For each row on this tab, the value in the Quantity column must be greater than or
equal to 0. The value also must be greater than or equal to the value specified for the corresponding record on the
Labor tab of the Services and Prices (RS203000) form (that is, the record that has the same inventory ID, service ID,
and device ID on the Services and Prices form as the current row on the Labor tab of the Repair Work Orders form).
Thus, a nonnegative quantity must be specified for each row, and the value specified for the labor on the Labor tab
of the Services and Prices form (for the same service and device as those selected on the Repair Work Orders form)
will function as a minimum quantity.
You will implement the FieldVerifying event handler for the Quantity field of the RSSVWorkOrderLabor
DAC. This event handler is intended for field validation that is independent of other fields in the same data record.
For details about the validation of independent field values, see Validation of Field Values.
In the event handler, you will do the following:
• When the new value in the Quantity column is negative, you will throw an exception (by using
PXSetPropertyException) to cancel the assignment of the new value to the Quantity field.
Lesson 3: Implementing the Update and Validation of Field Values | 36
• When the value is not negative but is smaller than the default quantity specified on the Services and
Prices form (in the RSSVLabor.Quantity field), you will attach the exception to the field by using
the RaiseExceptionHandling method and exit the method normally. This method will display a
warning for the validated data field but will not raise an exception, so that the method finishes normally and
e.NewValue is set.
To attach a warning to the control, you will specify PXErrorLevel.Warning in the
PXSetPropertyException constructor.
To select the default data record from the RSSVLabor DAC, you will configure a fluent BQL query with
three required parameters. In the fluent BQL statement, you will refer to each required parameter by
using the P.As[Type] class, where [Type] is Int for an integer parameter. In the Select() method
that executes the query, as the parameters, you will pass the values of RSSVWorkOrder.ServiceID,
RSSVWorkOrder.DeviceID, and RSSVWorkOrderLabor.InventoryID from the row for which the event
is triggered. To use parameters in a fluent BQL query, you need to add the PX.Data.BQL using directive to the
code. For details about the parameters in fluent BQL, see Parameters in Fluent BQL.
2. In the RSSVWorkOrderEntry.cs file, add the following using directive (if it has not been added yet).
using PX.Data.BQL;
if ((decimal)e.NewValue < 0)
{
//Throwing an exception to cancel the assignment
//of the new value to the field
throw new PXSetPropertyException(
Messages.QuantityCannotBeNegative);
}
3. Change the value to 0.5, which is smaller than the default value of 1. Make sure that the warning message
is generated on the control and the value is corrected to 1, as shown in the following screenshot.
Related Links
• Validation of Field Values
• Validation of a Data Record
Lesson 3: Implementing the Update and Validation of Field Values | 39
Lesson Summary
In this lesson, you have defined the business logic scenarios on the Repair Items tab of the Services and Prices
(RS203000) form and on the Labor tab of the Repair Work Orders (RS301000) form.
You have used the FieldUpdated and FieldDefaulting event handlers to modify the values of a detail
record on update of the Inventory ID column of this detail record. In the FieldUpdated event handler, you have
used the PXSelectorAttribute.Select<>() method to obtain the stock item record with the inventory ID
selected in the updated field.
To verify the value of a field that does not depend on other fields of the same record, you have used
the FieldVerifying event handler. In this event handler, you have thrown an exception by using
PXSetPropertyException to display an error and cancel the assignment of the new value. To display a
warning, you have attached the exception to the field by using the RaiseExceptionHandling method.
The implementation of this business logic is shown in the following diagram.
Lesson 3: Implementing the Update and Validation of Field Values | 40
In this lesson, you have used fluent BQL for data querying. Details about the data querying in Acumatica
Framework are outside of the scope of this course but may be useful to some readers.
In this lesson, you have learned in which situations you can use the FieldUpdated and FieldVerifying
event handlers.
Although the use of other event handlers is outside of the scope of this course, you can find information about how
to use other event handlers, along with examples, in the following training courses:
• T200 Maintenance Forms
• T210 Customized Forms and Master-Detail Relationship
• T220 Data Entry and Setup Forms
• T230 Actions
• Action Definition: To Define an Action for a Form
• Action Definition: To Define an Action for a Table
• T240 Processing Forms
• Activity 2.2.2: To Define the External Presentation of Field Values (in FieldSelecting)
Lesson 4: Creating an Acumatica ERP Entity Corresponding to a Custom Entity | 41
Lesson Objectives
In this lesson, you will learn how to implement an asynchronous operation by using the PXLongOperation
class.
In the Smart Fix company, there are no shipments or sales orders associated with repair work orders. Thus, you
need to enable the Advanced SO Invoices feature on the Enable/Disable Features (CS100000) form so that during the
creation of an SO invoice, stock items can be added directly to the SO invoice without sales orders and shipments
being processed.
To turn on the feature, do the following:
1. On the form toolbar of the Enable/Disable Features (CS100000) form, click Modify.
2. Select the Advanced SO Invoices check box (under Inventory and Order Management), and click Enable
on the form toolbar.
3. On the Item Classes (IN201000) form, in the Item Class Tree, select STOCKITEM. All the stock items used in
this lesson belong to this class.
4. On the General tab (General Settings section), select the Allow Negative Quantity check box, as shown in
the following screenshot.
Lesson 4: Creating an Acumatica ERP Entity Corresponding to a Custom Entity | 42
You should define the method in which an invoice is created, and then you can call this method in the
PXLongOperation.StartOperation method.
You will use multiple graphs in the method that creates an invoice. To save all changes from multiple graphs to the
database, you will use a single PXTransactionScope object. It gives you the ability to avoid incomplete data
being saved to the database if an error occurs in the middle of the method.
In Acumatica ERP, there are two types of invoices that can be created for a customer: SO and AR. An
SO invoice, which can include stock items, is an extension of an AR invoice, which cannot include
stock items. Repair work orders usually have stock items; therefore, you will implement the creation
of an SO invoice. However, regardless of your implementation, if an order does not include stock
items, the system will create an AR invoice, and if an order includes stock items, the system will create
an SO invoice.
using PX.Objects.SO;
using PX.Objects.AR;
using System.Collections;
using System.Collections.Generic;
Instead of adding the using directives manually, you can add them with the help of the
Quick Actions and Refactorings feature of Visual Studio aer you define the method in the next
instruction.
Lesson 4: Creating an Acumatica ERP Entity Corresponding to a Custom Entity | 43
2. Add the following static method, CreateInvoice, to the RSSVWorkOrderEntry graph. The
CreateInvoice method creates the SO invoice for the current work order.
ts.Complete();
}
}
Lesson 4: Creating an Acumatica ERP Entity Corresponding to a Custom Entity | 44
In the method above, you first create an instance of the SOInvoiceEntry graph. This graph works with SO
invoices.
To instantiate graphs from code, use the PXGraph.CreateInstance<T>() method. Do not use
the graph constructor new T(), because in this case, no extensions or overrides of the graph are
initialized.
You then initialize the summary of the invoice by using the ARInvoice class. You assign a value to the
CustomerID field, which is required to create an invoice. Aer that you update the ARInvoice instance in
cache.
Then you create an instance of the RSSVWorkOrderEntry graph, which you need to get access to the current
work order and to save the generated invoice number to the current work order.
Aer creating all needed graph instances, you select the repair and labor items specified on the Repair Work Orders
form by using the instance of the RSSVWorkOrderEntry graph. Then you add lines to the invoice by adding
instances of the ARTran class: the lines associated with repair items, followed by the lines associated with labor
items.
To save the created invoice in the database, you call the PressSave() method of the SOInvoiceEntry graph.
Aer you have created an invoice, you save the number of the generated invoice to the work order and update its
value in the cache. Then you save the changes to the database by invoking the Actions.PressSave() method.
At the end of the method, you complete the transaction.
In the RSSVWorkOrderEntry graph, define the CreateInvoiceAction action, which adds the Create
Invoice command to the More menu (under Other), adds the button with the same name on the form toolbar, and
invokes the PXLongOperation.StartOperation method, as shown in the following code.
To perform a background operation, an action method needs to have a parameter of the PXAdapter
type and return IEnumerable.
return list;
}
In the createInvoiceAction method, you compose a list of work orders by using the adapter.Get method,
and invoke the Actions.PressSave action. Because the return of the adapter.Get method does not include
data that has not been saved on the form, by calling the PressSave method, you update the workOrders in the
composed list.
Then you use the PXLongOperation.StartOperation() method to create an invoice. Within the method
that you pass to StartOperation(), you invoke the CreateInvoice method, which creates the invoice for
the current work order.
Inside the delegate method of the StartOperation method, you cannot use members of the
current graph.
Step 4.4: Defining the Visibility and Availability of the Create Invoice Action
According to the workflow for a repair work order, a user should be able to create an invoice only aer the work
order has been completed. This means that the Create Invoice button and command should be visible for only a
work order with the Completed status. Only one invoice can be created for a single work order, so aer a user has
clicked Create Invoice and the invoice has been created successfully, the button and command should become
unavailable.
You configure the availability and visibility of the Create Invoice command in the RowSelected event handler
of the RSSVWorkOrderEntry graph. To configure the visibility of the command, you use the SetVisible
method. To configure the availability of the command, you use the SetEnabled method.
To configure the command as described above, do the following:
1. Add the following code to the _(Events.RowSelected<RSSVWorkOrder> e) method of the
RSSVWorkOrderEntry class.
CreateInvoiceAction.SetVisible(
WorkOrders.Current.Status == WorkOrderStatusConstants.Completed);
CreateInvoiceAction.SetEnabled(WorkOrders.Current.InvoiceNbr == null &&
WorkOrders.Current.Status == WorkOrderStatusConstants.Completed);
2. To apply changes in the RSSVWorkOrderEntry class, rebuild the Visual Studio project.
To test the Create Invoice button and the corresponding action, do the following:
1. In Acumatica ERP, open the Repair Work Orders (RS301000) form.
2. Open the 000001 repair work order.
Creation of an invoice is available for completed work orders. To change the status of the order to
Completed, do the following:
a. On the form toolbar, click Remove Hold.
Lesson 4: Creating an Acumatica ERP Entity Corresponding to a Custom Entity | 46
When the process is complete, the number of the created invoice is displayed in the Invoice Nbr. box, as
shown in the following screenshot.
Lesson 4: Creating an Acumatica ERP Entity Corresponding to a Custom Entity | 47
Lesson Summary
In this lesson, you have learned how to initiate an asynchronous operation inside an action method by using the
PXLongOperation class. Also, you have implemented the creation of an SO invoice based on a repair work order
by doing the following in the RSSVWorkOrderEntry graph:
• Defining the static CreateInvoice method, which creates an instance of the SOInvoiceEntry graph
• Defining the Create Invoice button on the form toolbar and the command with the same name on the More
menu; the underlying action initiates the asynchronous execution of the CreateInvoice method by
using the PXLongOperation class
• Specifying the availability of the Create Invoice action in the RowSelected event handler so that
only a single invoice can be created for a repair work order
The following diagram shows the changes that you have made in this lesson.
Lesson 4: Creating an Acumatica ERP Entity Corresponding to a Custom Entity | 48
In this lesson, you have learned how to implement an action that creates an Acumatica ERP entity (an SO invoice)
that corresponds to a custom entity (a repair work order). The implementation of other kinds of actions is outside
of the scope of this course but may be useful to some readers. You can find information about how to implement
other kinds of actions, along with examples, in the following training courses:
• T230 Actions
• Action Definition: To Define an Action for a Form
• Action Definition: To Define an Action for a Table
• Asynchronous Operations: To Implement an Asynchronous Operation
• T240 Processing Forms
• Activity 1.1.1: To Create a Simple Processing Form
• Activity 2.2.3: To Modify the Processing Form to Use the Field Updated by PXAccumulator
• Activity 3.1.1: To Add Redirection to a Report at the End of Processing
Lesson 5: Deriving the Value of a Custom Field from Another Entity | 49
Lesson Objectives
In this lesson, you will learn how to do derive the value for a custom field from another form.
Step 5.1: Adding a Custom Field to the Payments and Applications Form—Self-
Guided Exercise
To display and modify the prepayment percentage on the Payments and Applications (AR302000) form, you need to
add the Prepayment Percent box to the form. Complete the following general tasks:
1. By using the Element Inspector, learn the name of the DAC and graph that define the Summary area of the
Payments and Applications form. In this case, the DAC is ARPayment and the graph is ARPaymentEntry.
You need the DAC name to know which database table and DAC to extend. You will need the graph name in
the next step.
2. Add a column named UsrPrepaymentPercent to the ARPayment table with the same parameters as
are specified for the PrepaymentPercent field of the RSSVSetup table. The data type of the column is
decimal(9, 6).
3. Create an extension of the ARPayment DAC, and add the UsrPrepaymentPercent field to the
extension.
If you create a DAC extension by using the Customization Project Editor, it creates an extension
of the base DAC. So in this case, the system will create an extension of the ARRegister DAC
because the ARRegister DAC is the base DAC for the ARPayment DAC.
#region PrepaymentPercent
[PXDBDecimal()]
[PXDefault(TypeCode.Decimal, "0.0", PersistingCheck = PXPersistingCheck.Nothing)]
[PXUIField(DisplayName = "Prepayment Percent")]
public Decimal? UsrPrepaymentPercent { get; set; }
public abstract class usrPrepaymentPercent :
PX.Data.BQL.BqlDecimal.Field<usrPrepaymentPercent> { }
Lesson 5: Deriving the Value of a Custom Field from Another Entity | 50
#endregion
4. Add a box for the UsrPrepaymentPercent field to the Summary area of the Payments and Applications
form. On the Customized Screens page, the location of the element appears as shown in the following
screenshot.
5. Correct the width for the Prepayment Percent label. To do this, in the Column element that is the parent
to the Prepayment Percent element, for the LabelsWidth property, specify the M value.
6. Publish the customization project.
You can implement the deriving of a field value from the RSSVSetup DAC and the copying of it to the ARPayment
DAC by using one of the following:
• The FieldDefaulting event
• The PXDefault attribute
To populate the UsrPrepaymentPercent field of the ARPayment extension when a payment is created, you
can use the FieldDefaulting event. Do the following:
1. Create an extension of the ARPaymentEntry graph, as shown in the following code.
You learned the name of the graph to extend in Instruction 1 of the previous step.
namespace PhoneRepairShop
{
Lesson 5: Deriving the Value of a Custom Field from Another Entity | 51
using PX.Data;
using PX.Data.BQL.Fluent;
using PX.Objects.AR;
3. Use Acuminator to suppress the PX1016 error in a comment. In this course, for simplicity, the extension is
always active.
4. Define the FieldDefaulting event handler for the UsrPrepaymentPercent field of the
ARPayment extension, as shown in the following code.
In the code above, you have selected the record with the repair work order preferences and assigned the
PrepaymentPercent field value to the UsrPrepaymentPercent field of the ARPayment DAC. You
have checked for the null value of setupRecord so that the NullReferenceException exception is
not thrown if the data on the form has not been filled in yet.
Another way to derive the default value is to use the PXDefault attribute, which performs the same logic. If you
use this approach, the PXDefault attribute for the UsrPrepaymentPercent field should look as follows.
You need to specify the SourceField parameter if the field names are not identical.
To test that the value of the Prepayment Percent box on the Payments and Applications (AR302000) form is
correctly specified for payments, rebuild the Visual Studio project and do the following:
Lesson 5: Deriving the Value of a Custom Field from Another Entity | 52
1. On the Invoices (SO303000) form, open the INV000049 invoice, which you created in Step 4.5: Testing the
Create Invoice Action
2. Release the invoice by doing the following:
a. Type 40 in the Amount box of the Summary area.
b. On the form toolbar, click Remove Hold.
c. Release the invoice by clicking Release on the form toolbar.
3. On the More menu (under Processing), click Pay.
The Payments and Applications (AR302000) form opens. In the Summary area, notice that the Prepayment
Percent box has the 10.00 value (see the following screenshot), which has been copied from the Repair Work
Order Preferences (RS101000) form.
Lesson Summary
In this lesson, you created a custom field on the Payments and Applications (AR302000) form and learned how to
assign its default value, which is derived from another entity. To assign a default value for a custom entity, you have
done the following:
1. Defined the extension of a graph in which the field is initialized
2. In the graph extension, defined the FieldDefaulting event handler for the custom field
The following diagram shows the changes that you have performed in this lesson.
Lesson 5: Deriving the Value of a Custom Field from Another Entity | 53
Lesson 6: Debugging Customization Code | 54
Lesson Objectives
As you complete this lesson, you will learn how to debug the source code of Acumatica ERP.
Acumatica ERP has open source code, which you can easily view with the Source Code browser.
However, in order to find a method that you need to override, it is helpful to debug Acumatica ERP source code
with breakpoints and see which breakpoint is hit in which scenario. To prepare the PhoneRepairShop_Code
Visual Studio project for the debugging of Acumatica ERP code, you should do the following:
1. Make sure the Acumatica program database (PDB) files are located in the Bin folder of the Acumatica ERP
instance folder that you use for the training course (for example, in SmartFix_T190\Bin).
The PDB files are copied to the Files\Bin folder of the Acumatica ERP installation folder (such as C:
\Program Files\Acumatica ERP\Files\Bin) during the installation process if the Install
Debugger Tools option is selected in the Acumatica ERP Installation wizard. When you create a new
instance or update an existing one, the PDB files are copied to the Bin folder of the instance. If you haven’t
selected the Install Debugger Tools option during installation, you should remove Acumatica ERP and
install it again with the Install Debugger Tools option selected. For details, see To Install the Acumatica ERP
Tools.
A PDB file holds debugging and project state information that allows incremental linking of a
debug configuration of your program. In general, a PDB file contains the link between compiler
instructions and some lines in source code.
<system.web>
<compilation debug="True" ...>
c. In the Debugging > General section, clear the Enable Just My Code check box, as shown in the
following screenshot.
d. In the Debugging > Symbols section, in the Symbols file (.pdb) locations list, add the path to the
location of the PDB files that you discovered in Instruction 1 of this step. See the following example.
C:\Training\SmartFix_T190\Bin
e. Click OK.
4. In Visual Studio, open the Acumatica ERP source code files. In the instance that you use for the training
course, all files are located in the .../App_Data/CodeRepository folder. For example, if you created
an instance for the T190 Quick Start in Customization course, the source code files could be found in the
SmartFix_T190/App_Data/CodeRepository folder.
5. To view the source code of the Release action of the Payments and Applications (AR302000) form, open
the PX.Objects.AR.ARPaymentEntry graph: In the Solution Explorer, select PhoneRepairShop >
App_Data > CodeRepository > PX.Objects > AR > ARPaymentEntry.cs, and go to the definition of the
IEnumerable Release(PXAdapter adapter) method. The code should look as shown in the
following screenshot.
Lesson 6: Debugging Customization Code | 56
6. Add a breakpoint inside the Release method, as shown in the screenshot above.
7. Attach the Visual Studio debugger to the w3wp.exe process.
8. Start debugging by doing the following:
a. In Acumatica ERP, open the Payments and Applications form.
b. Create a payment.
c. On the form toolbar, click the Release button.
Wait until the breakpoint is hit.
d. In Visual Studio, view the debug information for the Release method.
If an invoice was created for a repair work order with only non-stock items, by default, an AR invoice
is created instead of the SO invoice. There is no difference for the release of a payment for AR and SO
invoices, so you don't need to customize the closing of AR invoices as well.
Related Links
• To View and Debug Acumatica ERP Source Code
Lesson Summary
In this lesson, you have learned how to debug the code of Acumatica ERP by using program database (PDB) files.
In this lesson, you have learned how to debug the code of Acumatica ERP.
Lesson 6: Debugging Customization Code | 57
The debugging of customization code that is created in the Customization Project Editor and is located in the
App_RuntimeCode folder is outside of the scope of this course. You can find information about how to debug
this code along with an example in the T200 Maintenance Forms training course.