t100 introduction to acumatica framework€¦ · functional requirements ... • on the website of...

138

Click here to load reader

Upload: hoangngoc

Post on 08-Jun-2018

263 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: T100 Introduction to Acumatica Framework€¦ · Functional Requirements ... • On the website of the Acumatica Framework-based application template that you will ... BQL is written

Introductionto Acumatica Framework Training Guide

T100 Introduction to Acumatica Framework 5.0

Page 2: T100 Introduction to Acumatica Framework€¦ · Functional Requirements ... • On the website of the Acumatica Framework-based application template that you will ... BQL is written

| Contents | 2

Contents

Copyright......................................................................................................4

Introduction................................................................................................. 5

Getting Started.............................................................................................7Application Programming Overview.................................................................................... 8

Querying the Data................................................................................................ 10Entity Model Declaration........................................................................................ 12

RapidByte Application Overview....................................................................................... 22Functional Requirements........................................................................................ 23Application Pages.................................................................................................. 24Preparation of the Development Environment........................................................... 28

Summary: Application Overview and Preparations..............................................................30

Part 1: Maintenance Pages........................................................................ 31Lesson 1: Creating the First Page—Countries.....................................................................32

Adding the CountryMaint Graph..............................................................................33Adding Page RB201000......................................................................................... 34Adding the Country Class...................................................................................... 36Modifying the CountryMaint Graph.......................................................................... 41Configuring the Grid on the Page............................................................................42Adding the Page to the Site Map............................................................................ 44Conclusion: Creation of Pages................................................................................ 47

Lesson 2: Creating the Customers Maintenance Page......................................................... 48Adding the CustomerMaint Graph and Page RB202000.............................................. 49Adding the Customer Class.................................................................................... 50Configuring the CustomerMaint Graph and Page RB202000........................................ 51Adding Selectors to the Page................................................................................. 53Conclusion: Simple Form Edit Pages........................................................................56

Lesson 3: Adding Simple Business Logic to the Customers Page...........................................57Adding Logic on Update of the CountryCD Field........................................................58Conclusion: Business Logic.....................................................................................60

Part 2: Data Entry Pages........................................................................... 61Lesson 4: Creating the Sales Order Data Entry Page.......................................................... 62

Adding the SalesOrderEntry Graph and Page RB301000.............................................63Adding the Product Class....................................................................................... 64Adding the SalesOrder Class.................................................................................. 65Adding the OrderLine Class.................................................................................... 68Configuring the SalesOrderEntry Graph....................................................................70Configuring Page RB301000................................................................................... 71Conclusion: Master-Detail Pages............................................................................. 75

Lesson 5: Adding Simple Business Logic to the Sales Orders Page........................................76Configuring a Combo Box...................................................................................... 77Setting the Combo Box Value at Run Time.............................................................. 79Inserting Product Details into an Order Line.............................................................81Conclusion: Usage of Combo Boxes and Autoinsertion of Values..................................83

Lesson 6: Calculating Totals............................................................................................ 84Calculating the Extended Price of an Order Line....................................................... 85Calculating the Lines Total and Tax Total of a Sales Order.......................................... 87Calculating the Order Total.....................................................................................90

Page 3: T100 Introduction to Acumatica Framework€¦ · Functional Requirements ... • On the website of the Acumatica Framework-based application template that you will ... BQL is written

| Contents | 3

Conclusion: Calculations.........................................................................................91

Part 3: Inquiry Pages.................................................................................92Lesson 7: Creating the Sales Order Inquiry Page............................................................... 93

Adding the SalesOrderInq Graph.............................................................................94Adding Page RB401000......................................................................................... 97Conclusion: Inquiry Pages......................................................................................99

Part 4: Processing Pages......................................................................... 100Lesson 8: Creating the Approve Sales Orders Page.......................................................... 101

Implementing the Approval Operation....................................................................102Adding the SalesOrderProcess Graph..................................................................... 104Adding Page RB501000........................................................................................105Conclusion: Processing Pages............................................................................... 107

Lesson 9: Setting Up the UI for Approved Sales Orders.................................................... 108Making Approved Sales Orders Read-only in the UI................................................. 109Conclusion: UI Setup...........................................................................................111

Part 5: Reports.........................................................................................112Lesson 10: Creating the Sales Orders Printable Form........................................................113

Preparing Data for the Report...............................................................................114Adding a Variable to the Report............................................................................119Configuring the Printable Page Layout................................................................... 120Adding the Report URL to the Site Map................................................................. 126Running the Report Form..................................................................................... 127Conclusion: Reports.............................................................................................129

Appendix: Application Design...................................................................130Database Schema.........................................................................................................131Data Access Classes..................................................................................................... 134Application Pages......................................................................................................... 135Business Logic............................................................................................................. 138

Page 4: T100 Introduction to Acumatica Framework€¦ · Functional Requirements ... • On the website of the Acumatica Framework-based application template that you will ... BQL is written

| Copyright | 4

Copyright

© 2015 Acumatica, Inc.ALL RIGHTS RESERVED.

No part of this document may be reproduced, copied, or transmitted without the express prior consentof Acumatica, Inc.

4030 Lake Washington Blvd NE, Suite 100Kirkland, WA 98033

Restricted Rights

The product is provided with restricted rights. Use, duplication, or disclosure by the United StatesGovernment is subject to restrictions as set forth in the applicable License and Services Agreementand in subparagraph (c)(1)(ii) of the Rights in Technical Data and Computer Software clause at DFARS252.227-7013 or subparagraphs (c)(1) and (c)(2) of the Commercial Computer Software-RestrictedRights at 48 CFR 52.227-19, as applicable.

Disclaimer

Acumatica, Inc. makes no representations or warranties with respect to the contents or use of thisdocument, and specifically disclaims any express or implied warranties of merchantability or fitness forany particular purpose. Further, Acumatica, Inc. reserves the right to revise this document and makechanges in its content at any time, without obligation to notify any person or entity of such revisions orchanges.

Trademarks

Acumatica is a registered trademark of Acumatica, Inc. All other product names and services herein aretrademarks or service marks of their respective companies.

Software Version - 5.0

Last updated: January 28, 2015

Page 5: T100 Introduction to Acumatica Framework€¦ · Functional Requirements ... • On the website of the Acumatica Framework-based application template that you will ... BQL is written

| Introduction | 5

Introduction

The course consists of step-by-step lessons in which you develop a complete Acumatica Framework-based application. The course gives you an idea of how to develop your own applications by usingAcumatica Framework. It demonstrates key components of the platform and their usage for typicaltasks in application development. As you go through the course, you will create pages of all main typesthat are used in Acumatica Framework. After you complete all the lessons, you will be acquainted withbasic techniques of programming with Acumatica Framework, such as working with data, implementingbusiness logic and processing operations, and building reports.

We recommend that you follow the lessons in the order in which they are provided in the course,because some lessons use the result of the previous ones.

System Requirements

For detailed system and browser requirements, see ConfiguringDevEnvironment.pdf attached to thetraining materials.

To develop and debug your application, use Internet Information Services (IIS) hosted locally on yourmachine. You can debug an application running on IIS by attaching the Visual Studio debugger tothe server process. For more information on how to debug Acumatica Framework applications, seeAcumatica Framework > Debugging Applications in the documentation.

Required Knowledge and Background

To complete the course successfully, you should have the required knowledge:

1. Proficiency with C# language, including but not limited to the following language features:

• Class structure

• OOP (inheritance, interfaces, polymorphism)

• Usage and creation of attributes

• Generics

• Delegates, anonymous methods and lambda expressions

2. Knowledge of the main concepts of ASP.NET and Web Development:

• Application State

• Debugging ASP.NET Applications Using Visual Studio

• Attaching to IIS using Visual Studio Debugging Tools

• Client and Server-Side development

• Web Forms Structure

• Web Services

3. Experience with SQL Server:

• Writing and debugging complex SQL queries (Where Clause, Aggregates, Subqueries)

• Understanding of database structure (Primary Keys, Data Types, Denormalization)

4. Expericence with IIS:

• Configuration and deployment of ASP.NET websites

• Configuring and Securing IIS

Page 6: T100 Introduction to Acumatica Framework€¦ · Functional Requirements ... • On the website of the Acumatica Framework-based application template that you will ... BQL is written

| Introduction | 6

Review the following Microsoft Training Classes to see what training is covered or get up to speed withthese technologies

• Programming in C#

• Querying Microsoft SQL Server 2012

• Developing Microsoft SQL Server 2012 Databases

• Introduction to Web Development with Microsoft Visual Studio 2010

Acumatica Framework Documentation

You can find the framework documentation:

• Online at the http://partner.acumatica.com portal in the Documentation section.

• On the website of the Acumatica Framework-based application template that you will install locallyas you go through this course.

• In the single AcumaticaFramework_DevelopmentGuide.pdf PDF documentation file, which islocated in the folder where Acumatica Framework is installed. By default, the folder is C:\ProgramFiles (x86)\Acumatica Framework.

Page 7: T100 Introduction to Acumatica Framework€¦ · Functional Requirements ... • On the website of the Acumatica Framework-based application template that you will ... BQL is written

| Getting Started | 7

Getting Started

In this part of the course, you will get an overview of application programming with AcumaticaFramework and prepare to build the RapidByte application. After you see the requirements of theRapidByte application, you will set up the template to start programming the application. The AcumaticaFramework application template includes the default database schema, which contains only systemtables, the website, the Visual Studio solution, and an empty Class Library project for your applicationcode. However, you will install the template for the T100 Introduction to Acumatica Framework course,which also adds application tables for RapidByte. Thus, after you complete the first part of the course,you will have the initial web application that is ready for development of a new business module.

Page 8: T100 Introduction to Acumatica Framework€¦ · Functional Requirements ... • On the website of the Acumatica Framework-based application template that you will ... BQL is written

| Getting Started | 8

Application Programming OverviewAcumatica Framework provides the platform and tools for developing cloud business applications.This document explains Acumatica Framework runtime structure, introduces main components, andillustrates their relationships on simple examples.

The chapter is a starting point for application developers who are going to develop and customizeapplications with the help of Acumatica Framework. This document is a mandatory reading beforestarting the Acumatica Framework Tutorial.

Runtime Structure and Components

An application written with Acumatica Framework has n-tier architecture with a clear separation of thepresentation, business, and data access layers. The picture below illustrates the application componentmodel from the point of view of the application programmer.

Figure: Application architecture.

Data Access Layer

Acumatica Framework relies on object relationship mapping (ORM) technology to access the databasefrom the business logic. Acumatica Framework implements own, proprietary ORM technology. Thistechnology provides an application developer with a set of standard CRUD operations to execute ondatabase tables and methods to execute complex SQL queries.

An important feature of the Acumatica ORM technology is a high-performance serialization mechanismthat stores modified but not persisted database records in the session state. Modified data are mergedwith the result of the query execution to emulate stateful data access behavior for the applicationdeveloper and minimize the amount of data stored in the session.

Page 9: T100 Introduction to Acumatica Framework€¦ · Functional Requirements ... • On the website of the Acumatica Framework-based application template that you will ... BQL is written

| Getting Started | 9

Business Logic Layer

Business Logic Layer is implemented as a set of business logic controllers (graphs).

Each business logic controller consists of two parts:

• Entity Model that declares data access classes the entities are stored in, their relationships, andactions that can be executed over the entities

• Entity Business Logic that implements the business logic of the actions and events associated withmodifying entity data

Business logic controllers implement the interfaces for Presentation Layer to retrieve the entity data andexecute the actions over the entity. Business Logic Layer relies on Data Access Layer to retrieve datafrom the database and execute CRUD operation.

Presentation Layer

Presentation Layer is responsible for providing:

• The user interface based on the ASPX technology and implemented as a set of declarative WebForms

• The alternative interface for accessing the business logic in the form of auto-generated WebService API

Presentation Layer is completely declarative and contains no business logic.

Related LinksQuerying the DataEntity Model DeclarationHandling Entity DataImplementing Business Logic

Page 10: T100 Introduction to Acumatica Framework€¦ · Functional Requirements ... • On the website of the Acumatica Framework-based application template that you will ... BQL is written

| Getting Started | 10

Querying the DataThis system implements a custom language for writing database queries called BQL (business querylanguage). It is not LINQ and doesn't use it. BQL is written in C# and based on generic classes syntax,but still is very similar to SQL syntax. It has almost the same keywords placed in the order they areused in SQL. For example:

PXSelect<Product, Where<Product.availQty, IsNotNull, And<Product.availQty, Greater<Product.bookedQty>>>>

If the database provider is MS SQL Server, the framework will translate this expression into thefollowing SQL query:

SELECT * FROM ProductWHERE Product.AvailQty IS NOT NULL AND Product.AvailQty > Product.BookedQty

BQL gives several benefits to the application developer. It does not depend on database-providerspecifics, is object-oriented and extendable. An important benefit is compile-time syntax validation,which helps to prevent SQL syntax errors.

Since BQL is implemented on top of generic classes, you need types that would represent databasetables. In the context of Acumatica Framework, they are called data access classes (DACs).

For example, to execute the SQL query from the example above, you should define the Product dataaccess class as:

using System;using PX.Data;

// Types used in BQL statements should derive from special interfaces:// table - IBqlTable, column - IBqlField.[System.SerializableAttribute()]public class Product : PX.Data.IBqlTable{ // The type used in BQL statements to reference the ProductID column public abstract class productID : PX.Data.IBqlField { } // The property holding ProductID value in a record [PXDBIdentity(IsKey = true)] public virtual int? ProductID { get; set; }

// The type used in BQL statements to reference the AvailQty column public abstract class availQty : PX.Data.IBqlField { } // The property holding AvailQty value in a record [PXDBDecimal(2)] public virtual decimal? AvailQty { get; set; }

// The type used in BQL statements to reference the BookedQty column public abstract class bookedQty : PX.Data.IBqlField { } // The property holding BookedQty value in a record [PXDBDecimal(2)] public virtual decimal? BookedQty { get; set; }}

Each table field is declared in a data access class twice:

• As a type to reference a field in the BQL command

• As a value to hold the table field data

Page 11: T100 Introduction to Acumatica Framework€¦ · Functional Requirements ... • On the website of the Acumatica Framework-based application template that you will ... BQL is written

| Getting Started | 11

If the DAC is bound to the database, it must have the same class name as the database table.Fields are bound to the database by means of data mapping attributes (such as PXDBIdentity andPXDBDecimal), using the same naming convention.

A complete code sample that queries the database is given below:

using System;using System.Collections;using PX.Data;

public static void Main(){ // Select Product records PXResultSet<Product> res = PXSelect<Product, Where<Product.availQty, IsNotNull, And<Product.availQty, Greater<Product.bookedQty>>>> .Select(new PXGraph());

// You can iterate through the result set foreach(PXResult<Product> rec in res) { // A record from the result set can be cast to the DAC Product p = (Product)rec; Console.WriteLine("ID: {0}, available: {0}, booked: {0}", p.ProductID, p.AvailQty, p.BookedQty); }}

BQL library also supports such advanced features as:

• DACs that are not bound to the database

• Virtual fields that are not bound to the database

• Scalar sub-selects

• Projections

• Stored procedures execution

• Server-side calculated fields

• Non-blocking updates of statistical data records

Page 12: T100 Introduction to Acumatica Framework€¦ · Functional Requirements ... • On the website of the Acumatica Framework-based application template that you will ... BQL is written

| Getting Started | 12

Entity Model DeclarationBusiness Entity or simply Entity in Acumatica Framework represents an individual instance of theobjects (such as Product, Order) to which the information pertains. Entity can be simple, where thedata are represented with a single database record in a single table, or complex. With the complexentity, data are typically held in multiple tables and associated through a complex hierarchy andrelationship rules.

Working with the business entities in Acumatica Framework is implemented through the business logiccontroller object also referred as graph (graph is a mathematical term for a set of objects where somepairs of objects are connected by links).

A graph provides the interface for the presentation logic to operate with the business entity and relieson Data Access Layer components to store and retrieve the business entity from the database.

Let’s first take a look at the declaration of a simple business entity:

//Declaration of the graphpublic class ProductMaint : PXGraph<ProductMaint>{ //Declaraion of the data view public PXSelect<Product> Products;

//Declaration of the actions public PXCancel<Product> Cancel; public PXSave<Product> Save;}

In this example the graph implements the following interfaces:

• Products – the data view that can be used for querying and modifying entity data

• Cancel – the action that discard all the changes made to the entity and reloads it from thedatabase

• Save – the action that commits the changes made to the entity to the database and then reloadsthe committed data

Handling Entity Data

Data View and Entity Cache

Data views implement the interfaces for querying entity data from the business logic controller andsubmitting modified data back to the entity.

Data views are declared as public fields of PXSelect command type:

public PXSelect<Product> Products;

Based on this declaration, the system automatically instantiates the DAC entity cache.

An entity cache object in the Acumatica Framework is the primary interface for working with individualentity records from the graph business logic. It has two components and two primary responsibilities:

• The Cached collection – in-memory cache that contains modified entity records. The Cachedcollecton is instantiated based on the corresponding DAC declaration and managed by the cache.

• The controller – the cache component that implements basic CRUD operations on the Cachedcollection and triggers a sequence of data manipulation events when modifying or accessing thedata in the Cached collection. These events can be later subscribed from the graph to implementthe business logic associated with entity data modification.

The diagram below helps to understand the internal graph structure and responsibilities of the dataview and the entity cache.

Page 13: T100 Introduction to Acumatica Framework€¦ · Functional Requirements ... • On the website of the Acumatica Framework-based application template that you will ... BQL is written

| Getting Started | 13

Figure: The graph structure – a data view and an entity cache.

Data Modification Scenarios

Now lets consider basic entitiy data manipulation scenarious that can be executed from the graphbusiness logic or from the user interface. Entity data manupulation through the user interface indirectlyinvokes the same methods as the direct call from the business logic.

Querying Entity Data for the First Time

Entity data can be requested through the Products.Select() method. During this operation, the systemswill execute BQL command from the data view declaration. Data returned by the BQL command will bereturned to the requestor. See the diagram below.

Figure: Querying entity data for the first time.

Updating an Existing Entity Record

An existing business entity record can be updated through the Products.Update(record) method. Thismethod places the modified record into the cache.

If the data record is not found in the Cached collection, the cache controller will load the data recordfrom the database, add it to the Cached collection, mark it as updated, and update it with the newvalues. The search of the data record in the Cached collection and loading of the data record from thedatabase is based on the DAC key fields. The diagram below illustrates this scenario.

Page 14: T100 Introduction to Acumatica Framework€¦ · Functional Requirements ... • On the website of the Acumatica Framework-based application template that you will ... BQL is written

| Getting Started | 14

Figure: Updating the entity record for the first time.

If the updated record exists in the Cached collection the cache controller will locate it and update it withthe new values. The diagram below illustrates this scenario.

Page 15: T100 Introduction to Acumatica Framework€¦ · Functional Requirements ... • On the website of the Acumatica Framework-based application template that you will ... BQL is written

| Getting Started | 15

Figure: Updating the cached (previously modified) entity record.

Inserting a New Entity Record

A new record can be inserted into the business entity through the Products.Insert(record) method. Thenew inserted record will be added to the Cached collection and marked as inserted. The diagram belowillustrates this scenario.

Page 16: T100 Introduction to Acumatica Framework€¦ · Functional Requirements ... • On the website of the Acumatica Framework-based application template that you will ... BQL is written

| Getting Started | 16

Figure: Inserting the new entity record.

Deleting an Existing Entity Record

An existing record can be deleted from the business entity using the Products.Delete(record) method.

If the data record is not found in the Cached collection, the cache controller will load the data recordfrom the database, add it to the Cached collection, and mark it as deleted. The search of the datarecord in the Cached collection and loading of the data record from the database is based on the DACkey fields. The diagram below illustrates this scenario.

Page 17: T100 Introduction to Acumatica Framework€¦ · Functional Requirements ... • On the website of the Acumatica Framework-based application template that you will ... BQL is written

| Getting Started | 17

Figure: Deleting the non-cached (unmodified) entity record.

If the deleted record is found in the Cached collection, the cache controller will locate it and mark asdeleted. The diagram below illustrates this scenario.

Figure: Deleting of the cached (previously modified) entity record.

Page 18: T100 Introduction to Acumatica Framework€¦ · Functional Requirements ... • On the website of the Acumatica Framework-based application template that you will ... BQL is written

| Getting Started | 18

Querying an Updated Entity Data

Entity data can be modified and then queried again. In this scenario, the data records stored in thecaches memory will be merged with the result of the BQL command execution. Data records merge isbased on DAC key fields. The final result of the Select() execution will incorporate all the earlier entityrecords modifications that has not been preserved to the database yet. The diagram below illustratesthis scenario.

Figure: Querying the modified entity data – reading and merging with the cached data.

Persisting Entity Changes to the Database

When entity data are modified, the system has two different entity versions, the new one stored in thecaches memory and the original one persisted in the database. At this point a programmer has twooptions:

• Save the new entity version to the database using the Persist() method of the graph

• Discard all in-memory changes and load the original entity version using the Clear() method ofthe graph

From the Presentation Layer these methods are called by invocation of the Save and Cancel actions.These actions are predefined and mapped to the Persist() and Clear() methods.

The diagram below illustrated saving of entity changes to to the database.

Page 19: T100 Introduction to Acumatica Framework€¦ · Functional Requirements ... • On the website of the Acumatica Framework-based application template that you will ... BQL is written

| Getting Started | 19

Figure: Saving the entity changes to the database.

The diagram below illustrated discarding of all in-memory entity changes.

Figure: Discarding the changes and loading the original entity data.

Page 20: T100 Introduction to Acumatica Framework€¦ · Functional Requirements ... • On the website of the Acumatica Framework-based application template that you will ... BQL is written

| Getting Started | 20

Preserving the Entity Version Between the Round Trips and Handling the Subsequent Selectsfrom the Views

It is important to understand that a graph is a stateless object. It is discarded after each data request.In order to preserve the modified entity version between the requests, the cache controller serializesthe Cached collection into the session state and restores it later when the graph is instantiated on thesubsequent request. In this scenario, it is very important that the cache contains only the modifiedentity records, not the complete entity record set.

Implementing Business LogicBusiness logic is implemented by overloading certain methods invoked by the system in the processof manipulating data. For such procedures as inserting a data record or updating a data record, thePXCache controllers generate series of events causing invocation of the methods called event handlers.The application is able to interfere in the series of events on different stages. For this purpose, theapplication impements methods that are executed as event handlers.

There are 18 events raised on all stages of data processing.

Business logic can be divided into common logic relevant to different parts of the application and thelogic specific to an application screen (web page). The common logic is implemented through eventhandler methods defined in attributes, while the screen-specific logic is implemented as methods in theassociated graph.

Common Business Logic

The common business logic is implemented by defining event handlers in attributes. If such attribute isadded to the declaration of a data access class, attribute logic is applied to the data records of this typefor any graph used to access this table.

There are a number of predefined attributes implemented in the framework. For example, in thefollowing declaration of a data field for a column

[PXDBDecimal(2)]public virtual string AvailQty { get; set; }

PXDBDecimal is an attribute binding this field to a database column of the decimal type. The attributesof this form exist for most database data types.

Another typical example of an attribute is PXUIField. It is used to configure the input control for thecolumn in the user interface. This allows having the same visual representation of the column on allapplication screens (unless a screen redefines it). For example:

[PXDBDecimal(2)][PXUIField(DisplayName = "Available Qty", Enabled = false)]public virtual string AvailQty { get; set; }

Application can also define its own attributes, in the following way:

// Application-defined attribute implementing common business logicpublic class MyAttribute : PXEventSubscriberAttribute, IPXEventNameSubscriber{ // An event handler protected virtual void EventName(PXCache sender, PXRowEventNameEventArgs e) { ... } ...}

Page 21: T100 Introduction to Acumatica Framework€¦ · Functional Requirements ... • On the website of the Acumatica Framework-based application template that you will ... BQL is written

| Getting Started | 21

Such attributes are also added to the DAC declaration:

[PXDBDecimal(2)][PXUIField(DisplayName = "Available Qty", Enabled = false)][MyAttribute]public virtual string AvailQty { get; set; }

Screen-Specific Business Logic

For a specific screen, the application can redefine the common logic or extend it. For this purpose, youshould define event handlers in the graph associated with the screen. Each event hanlder method is tiedto a particular table or a table field via the naming convention.

For example, you can verify a value of a column:

public class ProductRecalc : PXGraph<ProductRecalc>{ ... // Event handler verifying that the value of the AvailQty column // in Product records is greater than 0. // It is triggered when, for instance, a Product record is updated. protected virtual void Product_AvailQty_FieldVerifying( PXCache sender, PXFieldVerifyingEventArgs e) { Product p = (Product)e.Row; if (p != null && p.AvailQty != null) { if (p.AvailQty < 0) throw new PXSetPropertyException<Product.availQty>( "Value must be greater than 0."); } }}

Page 22: T100 Introduction to Acumatica Framework€¦ · Functional Requirements ... • On the website of the Acumatica Framework-based application template that you will ... BQL is written

| Getting Started | 22

RapidByte Application OverviewIn this section, you will get an overview of the RapidByte application that you will build as you completethe course. You will see the application requirements and the webpages that you will create in furtherlessons.

Page 23: T100 Introduction to Acumatica Framework€¦ · Functional Requirements ... • On the website of the Acumatica Framework-based application template that you will ... BQL is written

| Getting Started | 23

Functional RequirementsThe RapidByte application should provide the following functionality for working with sales orders:

1. A user should be able to enter sales orders and add products to them.

A sales order is a document that contains the information about the products ordered by aparticular customer. Each sales order has a unique number, a reference to the customer, and areference to the company that provides the shipment of the order. The products added to a salesorder (which can be only active products) are the order details.

For each sales order, the application should also provide the following features:

a. Calculation of the sales order totals:

• The tax total is the sum of the tax amounts of all order details (products added tothe order).

• The lines total is the sum of the extended prices of all order details.

• The order total is the sum of the lines total, tax total, and freight amount specifiedin the order.

b. Calculation of the extended price of an order detail: extended price = product quantity *unit price * (1 - discount / 100), where thediscount is specified as a percent in each orderdetail individually.

The calculated values should be saved to the database.

2. The user should be able to get the list of all existing sales orders and the list of sales ordersfiltered by a particular customer.

3. The user should be able to approve sales orders. Once approved, a sales order becomes read-only and cannot be deleted from the database.

4. The user should be able to print sales orders.

5. The user should be able to edit customers. Each sales order should be associated with acustomer.

By using the listed requirements, we can plan the application pages that we will create in this course.

For more information about the database structure and application classes, see Appendix: ApplicationDesign.

Page 24: T100 Introduction to Acumatica Framework€¦ · Functional Requirements ... • On the website of the Acumatica Framework-based application template that you will ... BQL is written

| Getting Started | 24

Application PagesIn the RapidByte application, users must be able to enter sales orders, select them by the specifiedcriteria, and approve them. We will create a separate page for each of these activities: a data entrypage, an inquiry page, and a processing page for working with sales orders in the application. Basedon the requirements, we also see that we need a page for sales order printing and a helper page forediting products. To start with a very simple Acumatica Framework page as an example, we will createthe Countries page, which provides editing of the list of countries. In summary, we will create thefollowing application pages:

1. Countries

2. Customers

3. Sales Orders

4. Sales Order Approval

5. Sales Order Inquiry

6. Sales Order Printing

See below for the screenshots and brief descriptions of of the pages (including their FunctionalRequirements, where applicable):

1. Countries (no specific functional requirement)

By using this page (shown below), users can edit the list of countries. The instructions forcreating this application page demonstrate how to start building the application. In theapplication, the list of countries would help if you created a page for working with customers,because each customer has a country attribute.

Figure: The Countries page

2. Customers (functional requirement #5)

This helper page, as shown in the following screenshot, gives users the ability to add newcustomers and edit their parameters.

Page 25: T100 Introduction to Acumatica Framework€¦ · Functional Requirements ... • On the website of the Acumatica Framework-based application template that you will ... BQL is written

| Getting Started | 25

Figure: The Customers page

3. Sales Orders (functional requirement #1)

The main page of the application, which should look like it does in the following screenshot, isthis data entry page for sales orders. On this page, the user enters the sales order parametersand adds products to the sales order. The page should have the Approve button, which can beinvoked to change the sales order status to Approved.

Figure: The Sales Orders page

4. Approve Sales Orders (functional requirement #3)

On this processing page (which is shown below), the user can select one sales order or multipleorders and run the approval operation for the selected orders or all listed orders.

Figure: The Approve Sales Orders page

5. Sales Order Inquiry (functional requirement #2)

Page 26: T100 Introduction to Acumatica Framework€¦ · Functional Requirements ... • On the website of the Acumatica Framework-based application template that you will ... BQL is written

| Getting Started | 26

The page will display the list of sales orders, as shown below. The user can view all sales ordersor only those of the selected customer.

Figure: The Sales Order Inquiry page

6. Sales Orders printable form (functional requirement #4)

The printable version of the sales order must include all sales order parameters and the list oforder details, as the following screenshot illustrates.

Page 27: T100 Introduction to Acumatica Framework€¦ · Functional Requirements ... • On the website of the Acumatica Framework-based application template that you will ... BQL is written

| Getting Started | 27

Figure: The Sales Order printable document

Users will be able to navigate to these pages from the application menu. To provide a completenavigation menu in the application, you will add these pages to the site map as you create them.

Now that you understand what pages should be implemented in the application, go to the next lessonto set up the application template that will be used for creating of the application pages.

Related LinksApplication PagesAppendix: Application Design

Page 28: T100 Introduction to Acumatica Framework€¦ · Functional Requirements ... • On the website of the Acumatica Framework-based application template that you will ... BQL is written

| Getting Started | 28

Preparation of the Development EnvironmentYou will now create the RapidByte application from the application template that is provided withAcumatica Framework.

Do the following by instructions given in the ConfiguringDevEnvironment.pdf attached to the trainingmaterials:

1. Install Acumatica Framework.

2. Deploy a new application instance for a training course. On the Instance Configuration screen,specify the following values (see the screenshot below):

• Instance Name: RapidByte

• Visual Studio Solution Name: RB

• Select the training course: Introduction to Acumatica Framework

Figure: Instance Configuration screen

3. Install the Visual Studio Templates.

4. Prepare the solution in Visual Studio by creating additional folders (see the screenshot below):

• Create the RapidByte folder in the Site\Pages folder (1)

• Create the RapidByte and RapidByte > DAC folders in the RB application project (2)

The existing SM folder in the Site project contains system pages of the website; do not modify thisfolder or the files in it.

Page 29: T100 Introduction to Acumatica Framework€¦ · Functional Requirements ... • On the website of the Acumatica Framework-based application template that you will ... BQL is written

| Getting Started | 29

Figure: Solution structure for the RapidByte application

To find the location of the solution, you can go to the Application Maintenance screen of theAcumatica Framework Configuration Wizard and see the SitePath column for the RapidByteinstance.

Now you are ready to start application development.

Page 30: T100 Introduction to Acumatica Framework€¦ · Functional Requirements ... • On the website of the Acumatica Framework-based application template that you will ... BQL is written

| Getting Started | 30

Summary: Application Overview and PreparationsIn this part of the course, you have learned that you will create the RapidByte demo application, whichconsists of six pages:

1. The Countries maintenance page

2. The Customers maintenance page

3. The Sales Orders data entry page

4. The Approve Sales Orders processing page

5. The Sales Order Inquiry inquiry page

6. The Sales Order Printable Form report form

Based on the requirements identified in this lesson, you will design the application, which includesthe database schema, the application classes, and the UI. In this course, we have designed the demoapplication for you; you can see the detailed description of the application components in Appendix:Application Design.

To deploy a new instance of the Acumatica Framework-based application template and then maintainthe deployed applications, you use the Acumatica Framework Configuration Wizard. The wizard alsoprovides installation of specific Visual Studio templates that are used for creating ASP.NET pages in thesite and classes in the application project.

Now you have the template application ready for development of RapidByte pages. In the next lesson,you will create your first Acumatica Framework application page and test it on the website.

Page 31: T100 Introduction to Acumatica Framework€¦ · Functional Requirements ... • On the website of the Acumatica Framework-based application template that you will ... BQL is written

| Part 1: Maintenance Pages | 31

Part 1: Maintenance Pages

In this part of the course, you will start with creating the first very simple pages of the application. Youwill create the maintenance pages that are helper pages used for the input of data on the main pagesof the application, data entry and processing pages. The pages of these types will be created further inthis course.

Page 32: T100 Introduction to Acumatica Framework€¦ · Functional Requirements ... • On the website of the Acumatica Framework-based application template that you will ... BQL is written

| Part 1: Maintenance Pages | 32

Lesson 1: Creating the First Page—CountriesIn this lesson, you will create the first and simplest page in the application. The Countries maintenancepage holds the list of countries that can be used for specifying the country attribute of customers. Youwill start with preparing the generator that produces DAC code from the specified database table. Asyou advance through this lesson, you will create the CountryMaint business logic controller (BLC, alsoreferred to as graph), add the Countries webpage associated with this graph, and generate the Countrydata access class (DAC). As a result you will get a page that displays a list of countries in a grid (seethe screenshot below). Finally, you will configure navigation to the created page on the website.

Figure: The Countries page on the website

We recommend that you use the Data Access Class Generator to generate the initial code of data accessclasses (DACs) in the application. The generator helps you to create the declaration of data accessclasses, which may have multiple fields and, thus, be time-consuming to code manually. The DataAccess Class Generator saves you from typos and confusion. You can then easily maintain the DACdeclaration manually once it has been generated. To use the Data Access Class Generator, you need apage with a business logic controller specified in its data source. This lesson provides detailed steps onhow to prepare the generator.

Once you complete the lesson, you will have the first page added to the RapidByte website. The pageprovides standard functionality for working with data records, including selection, insertion, edit, anddeletion of data records through the grid.

Lesson Objective

In this lesson, you will create and test the first page of the RapidByte application, which displays a listof countries in the grid.

You will see how to generate the initial declaration of a data access class by the table description inthe database. You will also know how to configure the application page and create the business logiccontroller for it.

Page 33: T100 Introduction to Acumatica Framework€¦ · Functional Requirements ... • On the website of the Acumatica Framework-based application template that you will ... BQL is written

| Part 1: Maintenance Pages | 33

Adding the CountryMaint GraphTo get access to the Data Access Class Generator tool in your application project, you need anapplication page linked to a business logic controller, so-called graph. In this step, you will start withcreating the CountryMaint graph for the Countries page. Do the following:

1. In the RB application project, right-click the RapidByte folder and select Add > New Item.

2. In the window, select the PXGraph template.

3. Type the name of the created class, CountryMaint.cs, and click Add. The definition of theCountryMaint graph will be added to the project.

The CountryMaint graph is empty for now, because at this moment it is just needed to linkthe application page that you will create on the next step to the application project. The DataAccess Class Generator opens from the application page in design mode from any applicationpage linked to a graph from the application project where the code should be generated. Lateryou will add the graph members that provide data and actions for the page.

4. Rebuild the project to be able to specify the graph for an application page.

Now create an application page and set the CountryMaint graph in the datasource control on thepage.

Page 34: T100 Introduction to Acumatica Framework€¦ · Functional Requirements ... • On the website of the Acumatica Framework-based application template that you will ... BQL is written

| Part 1: Maintenance Pages | 34

Adding Page RB201000In this step, you will add the first ASP.NET page to be able to open the Data Access Class Generator. Toadd the page, perform the following instructions:

1. In the Pages folder of Site, right-click RapidByte and select Add New Item.

2. In the window, select the ListView template.

All application pages must be created from one of the special Acumatica Framework templates. TheListView template has the only grid container to represent a list of data records.

3. Type the name of the new page, RB201000.aspx, and click Add. The new page will be added tothe Site > Pages > RapidByte folder and opened in source mode.

The page name complies with the Acumatica Framework convention where RB is a two-lettermodule identifier, 20 means maintenance type of the page, and 10 is the starting sequentialnumber of the maintenance page in the module. For more information on naming conventions,see Acumatica Framework > Design Guidelines > Application Design Guidelines in thedocumentation.

4. Click the Design button to switch to design mode.

Figure: Switch to design mode in Visual Studio

By clicking the Source button, you can switch back to source mode.

Page 35: T100 Introduction to Acumatica Framework€¦ · Functional Requirements ... • On the website of the Acumatica Framework-based application template that you will ... BQL is written

| Part 1: Maintenance Pages | 35

Figure: View the page in design mode

5. When the visual elements appear, select the ds PXDataSource control.

6. In the Properties window, set TypeName:RB.RapidByte.CountryMaint.

Every page should be associated with a graph. If you do not see RB.RapidByte.CountryMaint in theTypeName combo box, make sure that you have built the project before switching to design mode.If the graph is still not visible, right-click any page area and click Refresh to again render the page.

7. Save changes on the pages.

Page 36: T100 Introduction to Acumatica Framework€¦ · Functional Requirements ... • On the website of the Acumatica Framework-based application template that you will ... BQL is written

| Part 1: Maintenance Pages | 36

Adding the Country ClassIn this step, you will generate the first data access class in the project, Country. To add the class,you need to open the Data Access Class Generator, select the database table, select fields, and thengenerate the class declaration. Proceed as follows:

1. Open RB201000.aspx in design mode.

2. After the visual elements appear, select the ds datasource control.

3. Click the smart tag at the top right corner of the datasource control, as shown below.

Figure: Click the datasource control smart tag

The Acumatica Framework code generator and layout editors for controls are opened from thesmart tag menu of the control. Sometimes it is difficult to click the proper tag. In this case, you cantry the following alternative way of opening the smart tag menu:

• Select the control in the Properties window (see 1 on the screenshot below).

• Right-click the control header in the design area to open the context menu related to thecontrol (2).

• Select Show Smart Tag from the menu (3).

Page 37: T100 Introduction to Acumatica Framework€¦ · Functional Requirements ... • On the website of the Acumatica Framework-based application template that you will ... BQL is written

| Part 1: Maintenance Pages | 37

Figure: Open smart tag menu

4. In the PXDataSource Tasks dialog box, click Generate Class to open the Data Access ClassGenerator dialog box.

Figure: Open the Data Access Class Generator

5. In the dialog box, select Country in the Name combo box (see 1 on the screenshot below).

The list of columns available in the Country database table appears.

You have created all database tables used in the RapidByte application when you deployed thetraining application template.

6. Make sure all columns are selected (2), and click Generate (3).

The Country data access class (DAC) is added to the project in the RapidByte\DAC\Country.csfile.

Page 38: T100 Introduction to Acumatica Framework€¦ · Functional Requirements ... • On the website of the Acumatica Framework-based application template that you will ... BQL is written

| Part 1: Maintenance Pages | 38

Figure: Generate the Country data access class

7. Open Country.cs to view the generated code, which is shown below.

namespace RB.RapidByte{ using System; using PX.Data; [System.SerializableAttribute()] public class Country : PX.Data.IBqlTable { #region CountryCD public abstract class countryCD : PX.Data.IBqlField { } protected string _CountryCD; [PXDBString(2, IsKey = true, IsUnicode = true)] [PXDefault()] [PXUIField(DisplayName = "CountryCD")] public virtual string CountryCD { get { return this._CountryCD; } set { this._CountryCD = value; } } #endregion #region Description public abstract class description : PX.Data.IBqlField { } protected string _Description; [PXDBString(50, IsUnicode = true)]

Page 39: T100 Introduction to Acumatica Framework€¦ · Functional Requirements ... • On the website of the Acumatica Framework-based application template that you will ... BQL is written

| Part 1: Maintenance Pages | 39

[PXUIField(DisplayName = "Description")] public virtual string Description { get { return this._Description; } set { this._Description = value; } } #endregion }}

8. Correct DisplayName in the CountryCD property annotation to Country ID. TheDisplayName parameter of PXUIField defines the label text that is displayed for the data fieldin the UI. CountryCD is the key field for the class, which is defined by the IsKey=trueparameter of the PXDBString attribute as shown below. The PXDefault attribute here marks thefield as mandatory.

[PXDBString(2, IsKey = true, IsUnicode = true)][PXDefault()][PXUIField(DisplayName = "Country ID")]public virtual string CountryCD{...}

In Acumatica ERP, CD is used for natural keys (such as CountryCD), which means keys thatare human-readable and can have additional meaning. ID is used for surrogate keys (suchas CountryID), which are pure identifiers. You typically display CD keys in the UI and hideID keys. However, to avoid confusing users with differences between CD and ID keys, werecommend you to specify ID in the label of any key field.

9. Save changes and rebuild the project.

Now the data access class that represents countries is ready. In the next step, you will modify theCountryMaint graph for working with Country data records on the application page.

Declaration of Data Access Classes

Every data access class (DAC) is declared as implementing the PX.Data.IBqlTable interface. Each dataaccess class must have the System.SerializableAttribute attribute.

The Country data access class contains two DAC fields: CountryCD and Description. The DAC fielddeclaration consists of two members:

• A public abstract class that implements the PX.Data.IBqlField interface. This abstract class isused in BQL statements specified in views and attributes added to data field declarations.

• A public virtual property of a nullable data type that corresponds to the data type of this field.This property keeps the value of the data field. The attributes are added to the property and notto the abstract class of the data field declaration.

The abstract class and property have the same name that differ by the case of the first letter. Byconvention, the abstract class name starts with a lowercase letter, while the property name starts withthe same uppercase letter. In BQL statements, the data field is referred to by the abstract class name,while in generated SQL, the columns are referred by the property name.

The attributes are specified for properties and not for abstract classes. Use of attributes is one of keytechniques in Acumatica Framework-based applications. On DAC fields, you use attributes to definethe data field specification that includes multiple parameters such as the data type, default value, and

Page 40: T100 Introduction to Acumatica Framework€¦ · Functional Requirements ... • On the website of the Acumatica Framework-based application template that you will ... BQL is written

| Part 1: Maintenance Pages | 40

field caption in the UI. The type attribute, such as PXDBString on the Country.CountryCD field fromthe code above, is the required attribute of a DAC field. For more information about attributes, seeAcumatica Framework > API Reference > Attributes in the documentation.

Page 41: T100 Introduction to Acumatica Framework€¦ · Functional Requirements ... • On the website of the Acumatica Framework-based application template that you will ... BQL is written

| Part 1: Maintenance Pages | 41

Modifying the CountryMaint GraphIn this lesson, you will add members to the graph that provide data and actions for the Countriesmaintenance page. Do the following:

1. Open the CountryMaint.cs file.

2. In the CountryMaint business logic controller, declare the Cancel and Save data manipulationactions and the Countries data view, as shown below.

public class CountryMaint : PXGraph<CountryMaint>{ public PXCancel<Country> Cancel; public PXSave<Country> Save;

public PXSelect<Country> Countries;}

Since the Countries page is intended for working with a country list, the Countries data view,which selects Country records from the database, will be specified as the primary data viewfor the page. The first type parameter of a data view specifies the main DAC. So, Countryis the main DAC of the Countries data view. If you set the type parameter of an action tothe main DAC of the primary view, the system automatically adds the button correspondingto this action to the page toolbar. So the Cancel and Save buttons will appear on the pagetoolbar.

3. Save changes and rebuild the project.

Data views, which are declared in a graph, provide data for displaying in the container controls on thepage. Now you can configure the page to display the list of countries obtained through the Countriesdata view.

Data Views

A data view is a graph member of one of PXSelectBase-derived types, such as PXSelect. The dataview type is a BQL statement that selects data to be manipulated through the data view. The mainDAC of a data view is the first type parameter in the declaration. The data view that is specified asthe primary view for the page must be defined the first one in the graph. For more information onPXSelectBase types and BQL, see Acumatica Framework > API Reference > Core Classes >PXSelectBase and Acumatica Framework > API Reference > BQL in the documentation.

Page 42: T100 Introduction to Acumatica Framework€¦ · Functional Requirements ... • On the website of the Acumatica Framework-based application template that you will ... BQL is written

| Part 1: Maintenance Pages | 42

Configuring the Grid on the PageIn this step, you will add columns to the grid on the page that displays the country list. Do thefollowing:

1. Open the RB201000.aspx page in design mode.

2. Select the ds PXDataSource control.

3. In the Properties window, set the following properties for the ds control:

• PrimaryView:Countries

The TypeName and PrimaryView properties are the only required properties of the control(TypeName has been earlier specified for ds). The buttons are automatically added to the toolbarby the definition of graph actions that have the type parameter set to the main DAC of theprimary view. The CountryMaint graph contains the declaration of two buttons, Save andCancel, so these buttons appears on the page toolbar.

If you do not see Countries in the PrimaryView combo box, make sure that you have built theproject before switching to design mode. If the view is still not visible, right-click any page area andselect Refresh to refresh controls on the page.

Now you can configure the data source for the grid and generate columns to the control.

4. Select the grid PXGrid control.

5. In the Properties window, set the following property for the grid PXGrid control:

• DataMember:Countries

DataMember and DataSourceID are two required properties of container controls. TheDataMember property specifies the data view to obtain data records into the grid.

6. Click the smart tag of the grid, at the top right corner of the control, as shown below.

Figure: Click the Smart Tag of the Grid

7. In the PXGrid Tasks window, click Edit Content Layout, as shown below. The Layout Editorwindow appears.

Figure: Open the Grid Layout Editor

8. In Layout Editor, switch to the Fields tab at the right side of the window. The list of the datafields available through the data view appears.

9. Check both CountryCD and Description (see 1 on the screenshot below), and select the onlyColumns check box at the bottom of the window (2).

Page 43: T100 Introduction to Acumatica Framework€¦ · Functional Requirements ... • On the website of the Acumatica Framework-based application template that you will ... BQL is written

| Part 1: Maintenance Pages | 43

10. Click Generate (3).

The columns corresponding to the selected data fields are added to the bottom left GridColumns list. Columns are required elements of a grid. When a user edits a row in a grid, theywork with default controls generated automatically according the data field definition.

11. Click Ok to save changes to the grid and close Layout Editor.

Figure: Generate Columns for the Grid

12. Save changes and refresh the page if the grid is not displayed correctly.

Now you can add the URL of the Countries application page to the site map.

Page 44: T100 Introduction to Acumatica Framework€¦ · Functional Requirements ... • On the website of the Acumatica Framework-based application template that you will ... BQL is written

| Part 1: Maintenance Pages | 44

Adding the Page to the Site MapIn this step, you will prepare the initial site map of the application and add navigation to the createdRB201000.aspx page by using the System > Customization > Site Map page. The site map alreadyincludes the top-level nodes for the RapidByte application as the following screenshot shows.

Figure: Top-level menu nodes in the site map

Proceed as follows:

1. Add the grouping nodes to the site map:

a. Select the RapidByte > RapidByte > Configuration node in the tree and add thefollowing nodes to it, by clicking Add Row (+):

• Setup

• Manage

These are the grouping headers for the Work Area tab of the navigation pane, asplanned in Application Pages. These headers are nodes to which you will add pages in thefollowing lessons.

b. For each of these grouping nodes, select the Expanded check box (the rightmost columnin the grid) and leave other parameters by default. The Expanded check box controlswhether the given node in the application menu is expanded or collapsed.

In this step, you prepare the initial site map for further addition of application pages.You don't add all the application pages to the site map, because they don't exist at themoment. You will add the pages to the site map one by one as you create them whileworking through the lessons. In your own application, you are free to create any number oftabs and name them as you need.

c. Click Save to save changes to the site map.

You can see the resulting site map (that you get after the completion of the course) inApplication Pages.

2. Now you can add the Countries page (RB201000) to the site map.

a. Select the RapidByte > RapidByte > Configuration > Manage node and click AddRow(+) to add a new nested node.

Page 45: T100 Introduction to Acumatica Framework€¦ · Functional Requirements ... • On the website of the Acumatica Framework-based application template that you will ... BQL is written

| Part 1: Maintenance Pages | 45

b. Specify the following parameters for the new node:

• Screen ID: RB.20.10.00

• Title: Countries

• Icon: Empty

• URL: ~/Pages/RapidByte/RB201000.aspx

• Expanded: Cleared

Leave the default settings for the other columns, and click Save (see the screenshotbelow).

Figure: Add the URL of the Countries page to the site map

Now the Countries maintenance page is added to the site, and you can find the page on theConfiguration tab of the RapidByte navigation pane (see the screenshot below).

Figure: Open the Countries page on the website

You can open the Countries page. Notice that the Save and Cancel buttons appear at the top of thepage. These buttons correspond to the actions declared in the CountryMaint BLC.

Page 46: T100 Introduction to Acumatica Framework€¦ · Functional Requirements ... • On the website of the Acumatica Framework-based application template that you will ... BQL is written

| Part 1: Maintenance Pages | 46

To apply changes to the row that you are editing in a grid, press Ctrl+Enter. On pressing of thiscombination, the modified row is saved to the current session but not yet to the database. To save thechanges to the database, click Save on the page toolbar.

Page 47: T100 Introduction to Acumatica Framework€¦ · Functional Requirements ... • On the website of the Acumatica Framework-based application template that you will ... BQL is written

| Part 1: Maintenance Pages | 47

Conclusion: Creation of PagesTo create an Acumatica Framework application page, you have to:

• In the application project, define the data access classes that are used on the application page.

• In the application project, define the business logic controller (graph) that serves as the controllerfor the application page. The graph contains the definition of data views and actions that can beused on the application page.

• In the Site\Pages\<Module folder> folder, from one of provided templates, create the ASP.NETpage and configure it for working with data provided by the graph.

• On the System > Customization > Site Map page of the website, add the page URL to the sitemap, which provides navigation to the page for users.

Data access classes (DAC) consist of definition of data fields annotated with attributes. Attributesconfigure DAC fields in the object model of the application, including the data type, default value, andUI presentation. To generate the initial declaration of a data access class, you can use the Data AccessClass Generator provided by Acumatica Framework. You can open the generator from any ASP.NETapplication page with the TypeName property specified, from the smart tag menu of the datasourcecontrol.

Graphs, which are application classes derived from PXGraph, provide controllers for logic performedon application pages. A graph contains the definition of data views that provide data retrieval andmanipulation and the definition of actions represented by toolbar buttons on the page.

To configure ASP.NET container controls on a page, such as forms and grids, you can use the LayoutEditor provided by Acumatica Framework. You can open the Layout Editor from the smart tag menu ofthe control. Layout Editor is the visual editor for the source code of the page.

Now you have the first page of the RapidByte application, which represents the list of countries in agrid. In the next lesson, you will create a form for editing of customers.

Page 48: T100 Introduction to Acumatica Framework€¦ · Functional Requirements ... • On the website of the Acumatica Framework-based application template that you will ... BQL is written

| Part 1: Maintenance Pages | 48

Lesson 2: Creating the Customers Maintenance PageIn this lesson, you will add another maintenance page, a page with a single form for working withcustomers. To create the page, you will define the Customer data access class and controller thatprovides data and actions to be used on the page, and then create the ASPX page that providesthe user interface for working with Customer data records. The screenshot below shows the finalCustomers page on the RapidByte website.

Figure: The Customers page on the website

Lesson Objective

In this lesson, you will create a form for editing of customers that can be selected for a sales order. Youwill also configure the very simple layout by arranging the controls into two columns on the form.

Page 49: T100 Introduction to Acumatica Framework€¦ · Functional Requirements ... • On the website of the Acumatica Framework-based application template that you will ... BQL is written

| Part 1: Maintenance Pages | 49

Adding the CustomerMaint Graph and Page RB202000In this step, you will create a new ASP.NET page to work with customers in the application and thebusiness logic controller (graph) that works with this page. Do the following:

1. In the RapidByte folder of the application project, create the new CustomerMaint.cs file fromthe PXGraph template.

namespace RB.RapidByte{ public class CustomerMaint : PXGraph<CustomerMaint> { }}

2. Build the project.

3. In the Pages > RapidByte folder of Site, create the new RB202000.aspx page from theFormView template.

4. Open the page in the design mode.

5. Specify the following property for the ds datasource control to bind the page to the gpaph:

• TypeName:RB.RapidByte.CustomerMaint

Now you are ready to generate data access classes to work with the page.

Page 50: T100 Introduction to Acumatica Framework€¦ · Functional Requirements ... • On the website of the Acumatica Framework-based application template that you will ... BQL is written

| Part 1: Maintenance Pages | 50

Adding the Customer ClassIn this step, you will add the new Customer data access class (DAC) to the project.

1. Open Data Access Class Generator and select the Customer table (see the screenshot below).

2. Click CustomerID in the Columns And Attributes list and modify the attributes of this field:

a. Remove IsKey = true from the constructor of the DB Identity attribute.

b. Delete the UI Field attribute. The CustomerID field is not intended for the user.

Figure: Configuring the Customer class in Data Access Class Generator

3. Click CustomerCD in the Columns And Attributes list and modify the following attributes:

a. Add IsKey = true to the constructor of the DB String attribute.

b. Remove the empty string from the constructor of the Default attribute to preventinsertion of empty strings into the database table.

c. Change the display name in the constructor of the UI Field attribute to Customer ID.

4. Click CompanyName and change the display name in the UI Field attribute to Company Name.

5. Click ContactName and change the display name in the UI Field attribute to Contact Name.

6. Click CountryCD and change the display name in the UI Field attribute to Country ID.

7. Click PostalCode and change the display name in the UI Field attribute to Postal Code.

8. Click Generate. The new DAC will be added to DAC\Customer.cs.

DAC fields will have the attributes that you have configured in Data Access Class Generator. Youcould click Generate at once and modify the attributes in code.

The PXDefault attribute (the Default attribute in the Data Access Class Generator) specifiesthe default value for the data field. In PXDefault, you can also specify whether the data field isrequired for input. By default, the PXDefault attribute makes the field required. You can makethe field optional by specifying the PersistentCheck = PXPersistentCheck.Nothingparameter in the attribute constructor. For more information on PXDefault, see AcumaticaFramework > API Reference > Attributes > Default Values in the documentation.

9. Rebuild the project.

The Customer DAC is ready for now. Go to the next step to add a data view to select data.

Page 51: T100 Introduction to Acumatica Framework€¦ · Functional Requirements ... • On the website of the Acumatica Framework-based application template that you will ... BQL is written

| Part 1: Maintenance Pages | 51

Configuring the CustomerMaint Graph and Page RB202000In this step, you will create a new ASP.NET page to work with products in the application. To add thepage, perform the following instructions:

1. In the CustomerMaint class, declare the Customers data view that selects data to berepresented on the page (see the code below).

public PXSelect<Customer> Customers;

The Customers data view provides retrieval and manipulation with instances of the Customerdata access class and is used for the form control on the page.

2. Save changes to the file and rebuild the project.

3. Open the RB202000 page in design mode.

4. Specify the following property for the ds datasource control:

• PrimaryView:Customers

5. Select the form PXFormView control on the page.

6. In the Properties window, set DataMember:Customers for the form control.

7. Save the changes you've made to the page.

8. Open the Layout Editor for the form control (by clicking the smart tag at the top right corner ofthe control and selecting Edit Content Layout).

9. On the Fields tab, select all fields.

10. Click Generate. The controls are added to the form under the form node.

11. Set the following properties for the Row PXLayoutRule object:

• ControlSize: XM

• LabelsWidth: S

The Row layout rule adjusts the size and position of controls on the form and arranges thecontrols into a column. The Row layout rule should start any form layout.

12. Add the Column PXLayoutRule object as follows:

a. Select the Row node in the tree and click Layout Rule on the toolbar.

b. Move the new LayoutRule node up under the edFax node.

c. Set the following properties for the LayoutRule node:

• StartColumn: True

• ControlSize: M

• LabelsWidth: S

The resulting layout of the form looks as follows.

Page 52: T100 Introduction to Acumatica Framework€¦ · Functional Requirements ... • On the website of the Acumatica Framework-based application template that you will ... BQL is written

| Part 1: Maintenance Pages | 52

Figure: Review the resulting form layout

13. Click Ok to close Layout Editor. Save your changes to the page.

14. Add the page to the site map. To do this, open the System > Customization > Site Mappage and add the RB202000.aspx page under the Acumatica Company > RapidByte >RapidByte > Work Area > Manage node with the following parameters:

• Screen ID: RB.20.20.00

• Title: Customers

• Icon: Empty

• URL: ~/Pages/RapidByte/RB202000.aspx

• Graph Type: Completed automatically

• Expanded: Cleared

Now the page is ready. Open the Customers page in the RapidByte application in web browser to seehow the form looks. The page doesn't include any toolbar buttons and all input controls are text boxes.In the next step, you will modify the graph and page to add standard toolbar buttons and selectorcontrols.

Figure: View the Customers page in a web browser

Page 53: T100 Introduction to Acumatica Framework€¦ · Functional Requirements ... • On the website of the Acumatica Framework-based application template that you will ... BQL is written

| Part 1: Maintenance Pages | 53

Adding Selectors to the PageIn this step, you will modify the business logic controller (graph) of the Customers page and the pageitself to add standard buttons to the page and add selector controls. Do the following:

1. In the declaration of the CustomerMaint class, specify Customer as the second typeparameter of PXGraph as the following code shows.

public class CustomerMaint : PXGraph<CustomerMaint, Customer>{ public PXSelect<Customer> Customers;}

Specifying a data access class in this way implicitly adds definition of stadard actions to thegraph. For more details, see Standard Buttons of the Page Toolbar.

2. Save changes to the file and rebuild the project. Open the Customers page in the browser. Nowit includes a toolbar with the buttons that can be used to save or revert changes, add and deletedata records, and navigate back and forth over existing customers. See the screenshot below.

Figure: The Customers page with the standard toolbar

3. In the Customer class, add the PXSelector attribute to the CustomerCD field as follows.

[PXDBString(15, IsUnicode = true, IsKey = true)][PXDefault][PXUIField(DisplayName = "Customer ID")][PXSelector( typeof(Search<Customer.customerCD>), typeof(Customer.customerCD), typeof(Customer.companyName))]public virtual string CustomerCD...

The PXSelector attribute configures a lookup (selector) control that will let the user selectexisting customers and load them into the form.

In the first parameter of the PXSelector attribute, you specify the key value that is inserted intothe field. The next positional parameters is the list of data fields that should be displayed in thelookup. Since the application object model is represented by classes that are complex types, youspecify the data fields by using the typeof operator. You can list any data fields retrieved by theSearch<> BQL query specified in the first parameter of the attribute.

[PXSelector(typeof(SalesOrder.orderNbr))] and[PXSelector(typeof(Search<SalesOrder.orderNbr>))] are equivalent definitions.

4. In the Customer class, add the PXSelector attribute to the CountryCD field as follows.

[PXDBString(2, IsUnicode = true)]

Page 54: T100 Introduction to Acumatica Framework€¦ · Functional Requirements ... • On the website of the Acumatica Framework-based application template that you will ... BQL is written

| Part 1: Maintenance Pages | 54

[PXUIField(DisplayName = "Country ID")][PXSelector( typeof(Search<Country.countryCD>), typeof(Country.countryCD), typeof(Country.description), DescriptionField = typeof(Country.description))]public virtual string CountryCD...

The PXSelector attribute here configures a selector that can be used to select from the list ofexisting Country data records. Here you additionally specify the DescriptionField property. Thecombination of DescriptionField and SelectorMode values defines the UI presentation of thevalue in the control. In the given case, the Description value is displayed in the UI next to thevalue that is assigned to the field.

5. Rebuild the project.

6. Open the RB202000 page in design mode, click the form, and open Layout Editor.

7. Delete the edCustomerCD and edCountryCD nodes from the tree.

The corresponding fields will appear on the Fields tab. The value in the Control type column isSelector now because of the PXSelector attribute.

8. Select both CustomerCD and CountryCD field on the Fields tab and click Generate.

9. Position the new CustomerCD and CountryCD nodes in the tree as they were positioned before(CustomerCD under Row and CountryCD under edCity).

10. Click Ok and save changes to the page.

If you open the Customers page in the browser, you will see that the Customer ID and Country IDfields are selectors now. You can click the search button to open a window with the list of data records,customers or countries. When you select a customer data record in the Customer ID selector, thefields of the selected customer are loaded into the form.

Figure: Final look of the Customers page

Standard Buttons of the Page Toolbar

The standard page toolbar buttons include data manipulation (Insert, Delete, Save, Cancel), navigation(Next, Previous, First, Last), and clipboard buttons (Copy/Paste). Every toolbar button corresponds tothe action declared in the graph. You can use explicit or implicit declaration of actions to add standardbuttons to the toolbar.

Page 55: T100 Introduction to Acumatica Framework€¦ · Functional Requirements ... • On the website of the Acumatica Framework-based application template that you will ... BQL is written

| Part 1: Maintenance Pages | 55

In any declaration, the DAC that you specify for actions must be the same as the main DAC of theprimary view of the page. The page toolbar manipulates with data records of the main DAC of theprimary view. If an action has the DAC other than the main DAC of the primary view, the button will notappear on the toolbar.

In the example of the CountryMaint graph, we used the explicit declaration of two actions thatcorrespond to the standard toolbar buttons, Cancel and Save (see the code below). Users need onlythese two buttons on the Countries page. The users work with a table of records on the page and don'tneed the other standard buttons, such as Previous and Next for navigation.

// Explicit definition of the needed standard buttonspublic class CountryMaint : PXGraph<CountryMaint>{ public PXCancel<Country> Cancel; public PXSave<Country> Save; ...}

To add an implicit declaration of standard buttons, specify the second type parameter in the basePXGraph class as the following code shows. By this declaration, the system automatically adds thestandard buttons for manipulating the Customer records to the page toolbar, if the main DAC ofthe primary view specified in the datasource control on the page is also Customer. Below are twoequivalent declarations of actions for standard buttons that work with data records of the CustomerDAC. All standard buttons are usually used on form edit pages.

// Implicit declaration of standard actionspublic class CustomerMaint : PXGraph<CustomerMaint, Customer>{ public PXSelect<Customer> Customers;}

// Explicit declaration of standard actionspublic class CustomerMaint : PXGraph<CustomerMaint>{ public PXSave<Customer> Save; public PXCancel<Customer> Cancel; public PXInsert<Customer> Insert; public PXCopyPasteAction<Customer> CopyPaste; public PXDelete<Customer> Delete; public PXFirst<Customer> First; public PXPrevious<Customer> Previous; public PXNext<Customer> Next; public PXLast<Customer> Last; public PXSelect<Customer> Customers;}

The standard buttons on the page toolbar look like as the following screenshot shows.

Figure: Standard buttons on the page toolbar

Page 56: T100 Introduction to Acumatica Framework€¦ · Functional Requirements ... • On the website of the Acumatica Framework-based application template that you will ... BQL is written

| Part 1: Maintenance Pages | 56

Conclusion: Simple Form Edit PagesNow you have one more application page, which is a form for editing of customers.

You can configure form layout by using Layout Editor for the form. In Layout Editor, add layout rules tothe tree of controls that define the size and positions of controls relatively to each other.

Start any layout with a Row layout rule added to the topmost position in the tree of controls. Each Rowstarts a group of controls that are aligned in a column by default. You can add nested layout rules toget more complex layout and override size and positions of controls.

In the next lesson, you will add code that clears the Region field once the CountryCD field changes.

Page 57: T100 Introduction to Acumatica Framework€¦ · Functional Requirements ... • On the website of the Acumatica Framework-based application template that you will ... BQL is written

| Part 1: Maintenance Pages | 57

Lesson 3: Adding Simple Business Logic to the Customers PageUntil now, you've been implementing the application logic only declaratively, by adding attributes toDAC fields, defining graph members, and configuring properties of ASPX controls. For the first time, inthis lesson, you will add procedural logic that modifies the current data record when a user modifies itsCountry ID field. Procedural logic is implemented in event handlers that are triggered by the systemwhen the client posts new or modified data to the server.

Lesson Objective

• Get acquainted with the way you implement business logic in Acumatica Framework-basedapplications

• Learn how to use the FieldUpdated event to modify values of the same data record.

• Get the first introduction to cache objects, which store the data modified by the user betweenround-trips

Page 58: T100 Introduction to Acumatica Framework€¦ · Functional Requirements ... • On the website of the Acumatica Framework-based application template that you will ... BQL is written

| Part 1: Maintenance Pages | 58

Adding Logic on Update of the CountryCD FieldIn this step, you will add code that clears the Customer.Region value when theCustomer.CountryCD value changes. Do the following:

1. In the CustomerMaint.cs file, define the Customer_CountryCD_FieldUpdated() method inthe CustomerMaint class as follows.

protected void Customer_CountryCD_FieldUpdated( PXCache sender, PXFieldUpdatedEventArgs e){ Customer row = (Customer)e.Row; row.Region = null;}

The Customer_CountryCD_FieldUpdated() method is an event handler that meets thedelegate type and complies with the event handler naming convention. At run time, the platformanalyzes the method name and adds it as a handler of the FieldUpdated event raised on theCustomer.CountryCD data field.

For more information about events, see Acumatica Framework > API Reference > EventModel in the documentation.

The platform triggers events when the data is committed to the server. Events are raised oncache objects each of which works with data records of a certain DAC. The cache object iscreated by the platform within the graph and provides the intermediate storage of data that isbeing viewed or modified by the user before it is updated in the database. The data stored in thecache object is preserved between the round-trips of client-server interaction.

The cache object on which the event is raised is one of input parameters of the event handler(the PXCache Sender object). FieldUpdated is raised in a chain of row insertion and rowupdating events and intended for modification of other fields of the same data record.

In Customer_CountryCD_FieldUpdated(), you get the currently processed Customerdata record from the e.Row property and set its Region field to null.

2. Rebuild the project.

3. On the RB202000.aspx page, select the form control and open Layout Editor for it. Set theCommitChanges:true property for CountryCD to enable callback for the control.

When the callback is enabled, the page posts the updated data immediately after the userchanges the value in the control and moves focus out of the control. The server gets the updateddata from the UI and triggers the events according to the event model.

4. Save your changes to the page.

Run the Customers page in a web browser.

To test the added business logic, open an existing customer, see that the Region value is not null, andselect a new Country ID value. The Region value is immediately cleared (see the screenshot below).

Page 59: T100 Introduction to Acumatica Framework€¦ · Functional Requirements ... • On the website of the Acumatica Framework-based application template that you will ... BQL is written

| Part 1: Maintenance Pages | 59

Figure: Test the business logic on the Customers page

If you do not enable callback for the Country ID control on the form, the platform will not raise theFieldUpdated event when the user updates the value in the control, because the page doesn't submitthe data to the server. In this case, the logic will be executed when a user changes a value in anothercontrol with the enabled callback (all data from the form is posted to the server on callback), or initiatessaving the row to the database (clicks the Save button on the page toolbar).

Page 60: T100 Introduction to Acumatica Framework€¦ · Functional Requirements ... • On the website of the Acumatica Framework-based application template that you will ... BQL is written

| Part 1: Maintenance Pages | 60

Conclusion: Business LogicAcumatica Framework-based applications work by the event-driven model. To implement procedurallogic (validation of values, processing of data records), you have to handle the appropriate events.

On the FieldUpdated event for Customer.CountryCD, you clear the Customer.Region value.Field events are used for validation and insertion of default values. Row events are used for controllingof UI presentation, calculations and complex validation of dependent values of the same row. A chainof events is raised on the server when the client submits the specific data. For more information onevents, see Acumatica Framework > API Reference > Event Model in the documentation.

In the next lesson, you will create the Sales Orders data entry page, which is the main page of theapplication.

Page 61: T100 Introduction to Acumatica Framework€¦ · Functional Requirements ... • On the website of the Acumatica Framework-based application template that you will ... BQL is written

| Part 2: Data Entry Pages | 61

Part 2: Data Entry Pages

In this part of the course, you will create the main data entry page of the application, Sales Orders.On the page, you will add the logic of calculation of sales order totals and insertion the shipmentinformation as soon the customer is specified for the sales order.

Page 62: T100 Introduction to Acumatica Framework€¦ · Functional Requirements ... • On the website of the Acumatica Framework-based application template that you will ... BQL is written

| Part 2: Data Entry Pages | 62

Lesson 4: Creating the Sales Order Data Entry PageIn this lesson, you will create the Sales Orders page with basic functionality for working with salesorders. The screenshot below shows the final look of the Sales Orders webpage.

Figure: The Sales Orders page on the website

Lesson Objective

• Get acquainted with more attributes on DAC fields, PXDBDefault and PXParent, and learn moreabout PXSelector.

• Learn how to create master-detail pages based on the FormDetail template.

• Learn how to define data views that return master-detail data records.

Page 63: T100 Introduction to Acumatica Framework€¦ · Functional Requirements ... • On the website of the Acumatica Framework-based application template that you will ... BQL is written

| Part 2: Data Entry Pages | 63

Adding the SalesOrderEntry Graph and Page RB301000In this step, you will create a new ASP.NET page to work with sales orders in the application and thebusiness logic controller that works with this page. Do the following:

1. In the RapidByte folder of the application project, create the new SalesOrderEntry.cs file fromthe PXGraph template.

namespace RB.RapidByte{ public class SalesOrderEntry : PXGraph<SalesOrderEntry> { }}

2. Build the project.

3. In the Pages > RapidByte folder of Site, create the new RB301000.aspx page from theFormDetail template.

The Acumatica Framework provides the following default Visual Studio templates for .aspx pages:

Name Description

FormDetail The master-detail editing page with FormView and Grid controls

FormTab The record-editing page with FormView and Tab controls

FormView The record-editing page with one FormView control

ListView The record-editing page with one Grid control

TabDetail The master-detail page with Tab and Grid controls

TabView The record-editing page with one Tab control

4. Open the page in design mode.

5. Specify the following property for the ds datasource control to bind the page to the graph:

• TypeName:RB.RapidByte.SalesOrderEntry

Now you are ready to generate data access classes to work with the page.

Page 64: T100 Introduction to Acumatica Framework€¦ · Functional Requirements ... • On the website of the Acumatica Framework-based application template that you will ... BQL is written

| Part 2: Data Entry Pages | 64

Adding the Product ClassIn this step, you will add the new Product data access class (DAC) to the project. The procedure is thesame as for the Customer DAC. Do the following:

1. Open Data Access Class Generator and select the Product table.

2. Click ProductID (2) in the Columns And Attributes list and modify the attributes of this field:

a. Remove IsKey = true from the constructor of the DB Identity attribute (3).

b. Delete the UI Field attribute. The ProductID field is not intended for the user.

3. Click ProductCD in the Columns And Attributes list and modify the following attributes:

a. Add IsKey = true to the constructor of the DB String attribute.

b. Remove the empty string from the constructor of the Default attribute to preventinsertion of empty strings into the database table.

c. Change the display name in the constructor of the UI Field attribute to Product ID.

4. Click ProductName in the Columns And Attributes list and modify the following attributes.

a. Remove the empty string from the constructor of the Default attribute to preventinsertion of empty strings into the database table.

b. Change the display name in the constructor of the UI Field attribute to Product Name.

5. Click Active in the Columns And Attributes list, change the parameter value to true and addPersistingCheck = PXPersistingCheck.Nothing to the constructor of the Default attribute.

6. Click StockUnit in the Columns And Attributes list and modify the following attributes.

a. Remove the empty string from the constructor of the Default attribute to preventinsertion of empty strings into the database table.

b. Change the display name in the constructor of the UI Field attribute to Stock Unit.

7. Click UnitPrice in the Columns And Attributes list and modify the following attributes:

a. Change the parameter value in the constructor of the DB Decimal attribute to 2.

b. Change the display name in the constructor of the UI Field attribute to Unit Price.

8. Click MinAvailQty in the Columns And Attributes list and modify the following attributes:

a. Change the parameter value in the constructor of the DB Decimal attribute to 2.

b. Change the display name in the constructor of the UI Field attribute to Min. Avail. Qty.

9. Click Generate. The new DAC will be added to DAC\Product.cs.

Now the Product class is ready. In the following parts of the lesson, you will modify attributes of DACfields in code.

Page 65: T100 Introduction to Acumatica Framework€¦ · Functional Requirements ... • On the website of the Acumatica Framework-based application template that you will ... BQL is written

| Part 2: Data Entry Pages | 65

Adding the SalesOrder ClassIn this step, you will add the SalesOrder data access class, which provide the master data for theSales Orders page.

1. Open the Data Access Class Generator, and generate the SalesOrder DAC with all fields fromthe SalesOrder table.

The new class is added in the DAC\SalesOrder.cs file.

2. In the SalesOrder.cs file, add the PXSelector attribute to the OrderNbr data field and changethe field display name to Order Nbr. as follows.

[PXDBString(15, IsKey = true, IsUnicode = true, InputMask=">CCCCCCCCCCCCCCC")][PXDefault()][PXUIField(DisplayName = "Order Nbr.")][PXSelector( typeof(Search<SalesOrder.orderNbr>), typeof(SalesOrder.orderNbr), typeof(SalesOrder.orderDate), typeof(SalesOrder.status), typeof(SalesOrder.customerID))]public virtual string OrderNbr{...}

The PXSelector attribute defines the selection of data to be displayed in the Order Nbr.lookup control. In the first parameter, you specify the key field whose value is inserted into theSalesOrder.OrderNbr data field.

3. Modify the PXDefault attribute for the OrderDate data field with thetypeof(AccessInfo.businessDate) parameter, which enables insertion of the current businessdate for each new sales order. The OrderDate data field holds the creation date of the salesorder.

[PXDBDate()][PXDefault(typeof(AccessInfo.businessDate))][PXUIField(DisplayName = "Order Date")]public virtual DateTime? OrderDate{...}

4. For the PXDefault attribute of the Hold data field, set the PersistingCheck property toPXPersistingCheck.Nothing, so that the data field has a default value, but is not required forinput.

[PXDBBool()][PXDefault(false, PersistingCheck = PXPersistingCheck.Nothing)][PXUIField(DisplayName = "Hold")]public virtual bool? Hold{...}

By default, the PersistentCheck parameter is set to PXPersistingCheck.Null and doesn'tallow saving the null value in the field.

5. On the CustomerID data field, add the PXDefault and PXSelector attributes as shown below.

[PXDBInt()][PXDefault][PXUIField(DisplayName = "Customer ID")]

Page 66: T100 Introduction to Acumatica Framework€¦ · Functional Requirements ... • On the website of the Acumatica Framework-based application template that you will ... BQL is written

| Part 2: Data Entry Pages | 66

[PXSelector( typeof(Customer.customerID), typeof(Customer.customerCD), typeof(Customer.companyName), SubstituteKey = typeof(Customer.customerCD))]public virtual int? CustomerID{...}

6. Add the PXDefault attribute with the PersistingCheck = PXPersistingCheck.Nothingparameter to the RequiredDate data field, to specify the default value without making thedata field required for input. The Required Date contains the expected date of the orderdelivery.

[PXDBDate()][PXDefault( typeof(AccessInfo.businessDate), PersistingCheck = PXPersistingCheck.Nothing)][PXUIField(DisplayName = "Required Date")]public virtual DateTime? RequiredDate{...}

Since the PXPersistingCheck.Nothing is specified for the data field, the user can delete thevalue from the field, which is equal to the current date but default, and then save the sales orderwithout the required date specified.

The PersistingCheck parameter can be set to one of the following values:

• Null - Used to check that the field value is not null.

• NullOrBlank - Used to check that the field value is not null and is not a string that containsonly whitespace characters.

• Nothing - Used to do not check the field value.

By default, the PersistentCheck parameter is set to PXPersistingCheck.Null and doesn'tallow to save the null value in the field.

7. Change the display name of the ShippedDate field to Shipped Date.

[PXDBDate()][PXUIField(DisplayName = "Shipped Date")]public virtual DateTime? ShippedDate{...}

8. Set the decimal scale to 2, default value to 0.0, and disable editing of the LinesTotal andTaxTotal data fields.

[PXDBDecimal(2)][PXDefault(TypeCode.Decimal, "0.0")][PXUIField(DisplayName = "Lines Total")]public virtual decimal? LinesTotal{...}[PXDBDecimal(2)][PXDefault(TypeCode.Decimal, "0.0")][PXUIField(DisplayName = "Tax Total")]public virtual decimal? TaxTotal{...}

Page 67: T100 Introduction to Acumatica Framework€¦ · Functional Requirements ... • On the website of the Acumatica Framework-based application template that you will ... BQL is written

| Part 2: Data Entry Pages | 67

The LinesTotal data field contains the total sales order cost without taxes. The TaxTotaldata field contains the sum of taxes in the sales order.

9. On the OrderTotal data field, set the decimal scale to 2 and add the PXDefault attributewith the default value equal to 0.0. The default value simplifies handling of the null value in theOrderTotal field, which is the decimal field used in calculations.

[PXDBDecimal(2)][PXDefault(TypeCode.Decimal, "0.0")][PXUIField(DisplayName = "Order Total")]public virtual decimal? OrderTotal{...}

10. Save changes and rebuild the project.

Now the SalesOrder data access class is ready and you can go to the next step to add theOrderLine DAC to the project.

Page 68: T100 Introduction to Acumatica Framework€¦ · Functional Requirements ... • On the website of the Acumatica Framework-based application template that you will ... BQL is written

| Part 2: Data Entry Pages | 68

Adding the OrderLine ClassIn this step, you will add the OrderLine DAC that provides detail records for a sales order. Do thefollowing:

1. In Data Access Class Generator, select the OrderLine table and generate the class with allfields from the table.

The new class is added in the DAC\OrderLine.cs file.

2. Delete the UI Field attribute and add the PXDBDefault and PXParent attributes to theOrderNbr data field as shown below.

[PXDBString(15, IsKey = true, IsUnicode = true)][PXDBDefault(typeof(SalesOrder.orderNbr))][PXParent(typeof(Select<SalesOrder, Where<SalesOrder.orderNbr, Equal<Current<OrderLine.orderNbr>>>>))]public virtual string OrderNbr{...}

The PXDBDefault attribute specifies the value that is inserted into the OrderLine.OrderNbrfield obtained from the SalesOrder.OrderNbr field of the master data record, from the onethat is current at run time. Without the attribute, the user gets an error on insertion of an orderdetail, which says that the required OrderNbr value isn't specified.

The PXParent attribute defines the master-detail relationship between the data access classes.In particular, the attribute enables cascade deletion of the detail records when the master datarecord is deleted. When a sales order is deleted, the corresponding order detail records thatmatch the specified query will also be deleted. The PXParent attribute can be added to any datafield of the class. However, we recommend to add it to the declaration of the first foreign key.

3. Add the PXSelector attribute to the ProductID data field that selects only active products, asshown below.

[PXDBInt(IsKey = true)][PXDefault][PXUIField(DisplayName = "Product ID")][PXSelector( typeof(Search<Product.productID, Where<Product.active, Equal<True>>>), typeof(Product.productCD), typeof(Product.productName), typeof(Product.stockUnit), typeof(Product.unitPrice), SubstituteKey = typeof(Product.productCD))]public virtual int? ProductID{...}

The SubstituteKey property specifies the field whose value should be shown in the control in theUI instead of the field that is specified in the Search<> command. Usually the property is used toreplace a surrogate key for the corresponding natural key, which is presented in the user interface.

4. Specify 0.0 as the default value for the UnitPrice data field, since it is a decimal field used incalculations.

[PXDBDecimal(6)][PXDefault(TypeCode.Decimal, "0.0")][PXUIField(DisplayName = "Unit Price")]

Page 69: T100 Introduction to Acumatica Framework€¦ · Functional Requirements ... • On the website of the Acumatica Framework-based application template that you will ... BQL is written

| Part 2: Data Entry Pages | 69

public virtual decimal? UnitPrice{...}

5. Specify 0.0 as the default value and reduce the decimal scale to 2 for the OrderQty data fieldas shown below.

[PXDBDecimal(2)][PXDefault(TypeCode.Decimal, "0.0")][PXUIField(DisplayName = "Quantity")]public virtual decimal? OrderQty{...}

6. Change the display name of the StockUnit field to Stock Unit.

[PXDBString(20, IsUnicode = true)][PXUIField(DisplayName = "Stock Unit")]public virtual string StockUnit{...}

7. Specify 0.0 as the default value and reduce the decimal scale to 2 for the TaxAmt data field asshown below.

[PXDBDecimal(2)][PXDefault(TypeCode.Decimal, "0.0")][PXUIField(DisplayName = "Tax Amount")]public virtual decimal? TaxAmt{...}

8. Specify 0.0 as the default value for the DiscPct data field as shown below.

[PXDBDecimal(6)][PXDefault(TypeCode.Decimal, "0.0")][PXUIField(DisplayName = "Discount")]public virtual decimal? DiscPct{...}

9. Specify 0.0 as the default value, reduce the decimal scale to 2, and disable editing of theLinePrice data field in the UI, because the data field will be calculated automatically.

[PXDBDecimal(2)][PXDefault(TypeCode.Decimal, "0.0")][PXUIField(DisplayName = "Ext. Price", Enabled = false)]public virtual decimal? LinePrice{...}

10. Rebuild the project.

Now the two classes representing the master-detail data of a sales order are ready. Go to the next step,to configure a graph for working with sales orders.

Page 70: T100 Introduction to Acumatica Framework€¦ · Functional Requirements ... • On the website of the Acumatica Framework-based application template that you will ... BQL is written

| Part 2: Data Entry Pages | 70

Configuring the SalesOrderEntry GraphIn this step, you will modify the business logic controller (graph) that works with the Sales Orders page.Do the following:

1. In the declaration of the SalesOrderEntry class, specify SalesOrder as the second typeparameter of PXGraph as the following code shows.

public class SalesOrderEntry : PXGraph<SalesOrderEntry, SalesOrder>{}

2. Define the Orders and OrderDetails data views in the graph as shown below. These dataviews will be used as data members for the form and grid controls on the application page.

public PXSelect<SalesOrder> Orders;public PXSelect<OrderLine, Where<OrderLine.orderNbr, Equal<Current<SalesOrder.orderNbr>>>> OrderDetails;

The framework automatically executes each data view that returns the selected data when thedata view is requested from the UI. The Orders data view returns the master record, whilethe OrderDetails returns the list of details by the specified key, OrderNbr. The relationshipbetween the data sets is defined by the Current<> BQL query parameter. The OrderDetailsdata view returns the detail data records for the current sales order obtained through the firstdata view. For more information, see the section below.

Now the graph is ready for working with the application page. Go to the next step, to configure theASP.NET page.

Master-Detail Relationship Between Data Views

The framework executes data views in the order requested by the webpage. You don't have to executea data view to retrieve data for the UI.

In case of the Sales Orders page, the framework first executes the Orders data view to retrieve themaster data record, and then executes the OrderDetails data view. To pass the OrderNbr fieldvalue as a parameter to the OrderDetails data view, we use the Current property value of theOrders data view. The last data record retrieved by the Orders data view is available through theCurrent property of the data view. (We expect to have only one master record available at a time.)Also, when you create the new master data record, it also gets available through the Current propertyvalue of the Orders data view.

Page 71: T100 Introduction to Acumatica Framework€¦ · Functional Requirements ... • On the website of the Acumatica Framework-based application template that you will ... BQL is written

| Part 2: Data Entry Pages | 71

Configuring Page RB301000In this step, you will configure the ASP.NET page that works with sales orders in the application. To addthe page, perform the following instructions:

1. Open the RB301000.aspx page in design mode.

2. Specify the following property for the ds datasource control:

• PrimaryView:Orders

3. Select the form PXFormView control on the page.

4. In the Properties window, set DataMember:Orders.

Now you can generate the controls for the form control.

5. Open Layout Editor for the form PXFormView control (by clicking the smart tag in the top rightcorner of the control and selecting Edit Content Layout).

6. On the Fields tab, select all fields and then click Generate. The corresponding controls will beadded to form.

7. Organize the controls into three columns, as the screenshot below shows.

Figure: Organize controls on the form

To organize the controls into three columns, you have to add a row and two column layoutrules to the tree of controls and split the data fields between them. The first column starts withthe Row layout rule. To add a column, click Layout Rule and set StartColumn:True for theappeared LayoutRule. Drag and drop the controls into the columns or move the controls by usingthe Up and Down arrow buttons on the toolbar (see the screenshot below).

Figure: Click Up or Down buttons to Move a control in the tree

8. Set the following additional properties for Row:

Page 72: T100 Introduction to Acumatica Framework€¦ · Functional Requirements ... • On the website of the Acumatica Framework-based application template that you will ... BQL is written

| Part 2: Data Entry Pages | 72

• ControlSize: S

• LabelsWidth: S

9. Set the following additional properties for both Column node:

• ControlSize: XM

• LabelsWidth: S

10. Add one more LayoutRule object, place it above the edDescription node, and set theColumnSpan property to 2 (see the screenshot below).

Figure: Adding the ColumnSpan object

A LayoutRule object with ColumnSpan set to 2 stretches the following control onto two columns.

11. Set the following property for the edShippedDate, edLinesTotal, edTaxTotal and edOrderTotalnodes:

• Enabled: False

12. Click Ok to save the generated controls and to close Layout Editor.

Now you can generate the columns and controls for the grid.

13. Select the grid PXGrid control at the bottom of the page. In the Properties window, setDataMember:OrderDetails.

14. Open Layout Editor for the grid PXGrid control.

15. On the Fields tab (see the screenshot below), select all fields by clicking Select All (a) andselect the Columns check box below the field list (b). Clear the Controls check box (c),because we don't need to generate controls for this grid. Click Generate (d).

Page 73: T100 Introduction to Acumatica Framework€¦ · Functional Requirements ... • On the website of the Acumatica Framework-based application template that you will ... BQL is written

| Part 2: Data Entry Pages | 73

Figure: Adding columns to the grid

Columns are the only required items for a grid. Controls are needed in certain cases. You can learnmore about columns and controls of the grid in the T200 Acumatica Framework Fundamentalscourse.

16. Click Ok to save the generated controls and to close Layout Editor. Save changes.

17. Add the page to the site map. To do this, open the System > Customization > Site Mappage and add the RB301000.aspx page under the Acumatica Company > RapidByte >RapidByte > Work Area > Enter node with the following parameters:

• Screen ID: RB.30.10.00

• Title: Sales Orders

• Icon: Empty

• URL: ~/Pages/RapidByte/RB301000.aspx

• Graph Type: Completed automatically

• Expanded: Cleared

Now the page is ready and you can view it in a web browser. The Sales Orders data entry page providesonly basic functionality. It allows a user to create new sales orders, edit or delete them, and addproducts to the order as order details.

Page 74: T100 Introduction to Acumatica Framework€¦ · Functional Requirements ... • On the website of the Acumatica Framework-based application template that you will ... BQL is written

| Part 2: Data Entry Pages | 74

Figure: The Sales Orders data entry page

Page 75: T100 Introduction to Acumatica Framework€¦ · Functional Requirements ... • On the website of the Acumatica Framework-based application template that you will ... BQL is written

| Part 2: Data Entry Pages | 75

Conclusion: Master-Detail PagesWhen you work with master-detail data access classes, the master key field is specified in thePXDBDefault attribute on the foreign key field of the detail class. To enable cascade deletion of detailrecords when a master record is being deleted, you have to add the PXParent attribute to one offoreign key fields of the detail class.

For the page, the master-detail data is provided by two data views, in which the data view thatretrieves the details is linked to the master data record by the Current parameter of the BQL query.

Now you have created the Sales Orders page with two containers bound to data views of theSalesOrderEntry graph, as the figure below shows.

Figure: Configuring the Sales Orders page

The Orders is the first view in the SalesOrderEntry graph, so it is the primary data view. TheSalesOrder is the main DAC of the Orders data view and the OrderLine is the main DAC of theOrderDetails data view.

In the next lesson, you will add automatic insertion of product data taken from the product parametersspecified for an order line.

Page 76: T100 Introduction to Acumatica Framework€¦ · Functional Requirements ... • On the website of the Acumatica Framework-based application template that you will ... BQL is written

| Part 2: Data Entry Pages | 76

Lesson 5: Adding Simple Business Logic to the Sales OrdersPage

In this short lesson, you will implement automatic insertion and update of product data, which isexecuted every time a user specifies the product for an order line.

Lesson Objective

• Get aquainted how to configure a combo box by using the PXStringList attribute

• See once more how to use FieldUpdated event to autocomplete values of the same data record.

• Learn one of possible ways to retrieve a data record from the database in code by using the staticPXSelectorAttribute.Select<>() method.

Page 77: T100 Introduction to Acumatica Framework€¦ · Functional Requirements ... • On the website of the Acumatica Framework-based application template that you will ... BQL is written

| Part 2: Data Entry Pages | 77

Configuring a Combo BoxIn this step, you will configure a combo box control for the Status field. Do the following:

1. In the SalesOrder.cs file, add the following OrderStatus class, which defines possible value forthe status of a sales order, below the SalesOrder class.

public class OrderStatus{ public const string Open = "O"; public const string Hold = "H"; public const string Approved = "A"; public const string Completed = "C";

public class UI { public const string Open = "Open"; public const string Hold = "On Hold"; public const string Approved = "Approved"; public const string Completed = "Completed"; }}

2. Add the PXStringList attribute to the Status field of the SalesOrder data access class(DAC) and set the default value to OrderStatus.Open as follows.

[PXDBString(1, IsFixed = true)][PXDefault(OrderStatus.Open)][PXUIField(DisplayName = "Status")][PXStringList( new string[] { OrderStatus.Open, OrderStatus.Hold, OrderStatus.Approved, OrderStatus.Completed }, new string[] { OrderStatus.UI.Open, OrderStatus.UI.Hold, OrderStatus.UI.Approved, OrderStatus.UI.Completed})]public virtual string Status{...}

In the first parameter of the PXStringList constructor, you specify the list of possible values forthe field, while in the second parameter, you specify the labels corresponding to the values anddisplayed in the UI.

3. Rebuild the project.

4. Open Layout Editor for the form control on the RB301000.aspx page to regenerate the inputcontrol for the Status field.

5. Delete the edStatus node from the tree, check the box for the Status field on the Fields tab, andclick Generate.

6. Move the new edStatus node in the tree to its former position and click Ok.

7. Save the changes to the page.

Page 78: T100 Introduction to Acumatica Framework€¦ · Functional Requirements ... • On the website of the Acumatica Framework-based application template that you will ... BQL is written

| Part 2: Data Entry Pages | 78

If you open the Sales Orders page in the browser now, you will see that the input control for the Statusfield is a combo box. You can select a value from Open, On Hold, Approved, and Completed (see thescreenshot below).

Figure: The combo box control for the Status field on the Sales Orders page

Page 79: T100 Introduction to Acumatica Framework€¦ · Functional Requirements ... • On the website of the Acumatica Framework-based application template that you will ... BQL is written

| Part 2: Data Entry Pages | 79

Setting the Combo Box Value at Run TimeIn this step, you will disable the Status field on the Sales Orders page and define an event handler thatautomatically sets the Status value when a user changes the Hold value. Do the following:

1. In the SalesOrderEntry.cs file, add the following SalesOrder_Hold_FieldUpdated()method to the SalesOrderEntry class.

protected virtual void SalesOrder_Hold_FieldUpdated( PXCache sender, PXFieldUpdatedEventArgs e){ SalesOrder order = (SalesOrder)e.Row; if (order.Hold == true) { order.Status = OrderStatus.Hold; } else { order.Status = OrderStatus.Open; }}

The SalesOrder_Hold_FieldUpdated() method is a handler of the FieldUpdated eventraised for the Hold field. The method is executed each time the Hold value changes, and thechanges are committed to the server from the page.

The framework treats the SalesOrder_Hold_FieldUpdated() method as the event handlerby the method name and definition. The event triggers on the model level— on the DAC fieldin the cache object that holds the SalesOrder records—and not on the ASP.NET control.FieldUpdated is one of events raised in a chain according to the 'Updating a data record'scenario. The FieldUpdated event is used to insert values into the fields that depend from afield of the same DAC. When the server obtains the updated record from the UI, the applicationtriggers the events according to the 'Updating a data record' scenario.

For the event scenarios and the description of events, see in Acumatica Framework > APIReference > Event Model in the documentation.

2. Build the project.

3. Open Layout Editor for the form control on the RB301000.aspx page.

4. Select the edHold node in the tree and set the CommitChanges property to True on theProperties tab.

5. Select the edStatus node in the tree and set the Enabled property to False.

6. Click Ok and save the changes to the page.

Because you've set the CommitChanges property to true for the Hold field, each time you change theHold value in the UI and move focus from the field the page sends a callback to the server. As a result,the FieldUpdated event handler is executed and sets the Status value (see the screenshot below).Notice that the Status field is disabled and you can't change its value manually.

Page 80: T100 Introduction to Acumatica Framework€¦ · Functional Requirements ... • On the website of the Acumatica Framework-based application template that you will ... BQL is written

| Part 2: Data Entry Pages | 80

Figure: Setting the status by changing the Hold value on the Sales Orders page

Page 81: T100 Introduction to Acumatica Framework€¦ · Functional Requirements ... • On the website of the Acumatica Framework-based application template that you will ... BQL is written

| Part 2: Data Entry Pages | 81

Inserting Product Details into an Order LineIn this step, you will implement insertion of product data taken from the product parameters everytime a user updates Product ID in an order line on the Sales Orders page. To do this, you will add theOrderLine_ProductID_FieldUpdated() event handler. Do the following:

1. In SalesOrderEntry.cs, add the OrderLine_ProductID_FieldUpdated() event handler tothe SalesOrderEntry class as follows.

protected virtual void OrderLine_ProductID_FieldUpdated( PXCache sender, PXFieldUpdatedEventArgs e){ OrderLine line = (OrderLine)e.Row; Product product = PXSelectorAttribute.Select<OrderLine.productID>( sender, line) as Product; if (product != null) { line.UnitPrice = product.UnitPrice; line.StockUnit = product.StockUnit; } else { line.UnitPrice = null; line.StockUnit = null; }}

In the OrderLine_ProductID_FieldUpdated() method, you update the fields with valuesobtained from the database.

In the method, you obtain the data record, which is being updated, from the event argumentspassed in the e object. To get the product unit price and stock unit values, you invokethe static Select<>() method of the PXSelector attribute that executes the databasequery. In the type parameter of the method, you specify the OrderLine.productIDdata field, whose value is taken from the order object and passed to the SELECTquery. On PXSelectorAttribute.Select<>(), the framework selects the data recordfrom the database, where Product.productID (the key field of the selector onOrderLine.productID), is equal to the value obtained from the same field of the line datarecord. The PXSelectorAttribute.Select<>() method retrieves the data record as an objectthat you have to cast to the needed DAC, which is Product here. If no data record has beenfound in the database, the method returns null, and you also insert nulls into the shipmentdetails. On the FieldUpdated event, you modify the data record in memory before it is updatedin the cache object (see the 'Updating a data record' scenario) and do not save anything to thedatabase.

2. Rebuild the project.

3. On the RB301000.aspx page, select the grid control and open Layout Editor for it. Set theCommitChanges:true property for ProductID to enable callback for the column. This enablesthe event to trigger every time the user changes the value within the column and moves focusout of it.

4. Save the changes.

Open the Sales Orders page in a web browser. Create a new sales order (see item 1 on the screenshotbelow), insert a new order line (2), and select the product for it (3). Check whether the product detailsare inserted correctly: unit price and stock unit. Select a different product in the Product ID columnand check whether the order line details have been updated.

Page 82: T100 Introduction to Acumatica Framework€¦ · Functional Requirements ... • On the website of the Acumatica Framework-based application template that you will ... BQL is written

| Part 2: Data Entry Pages | 82

Figure: Compare the inserted values with values displayed in the selector

Page 83: T100 Introduction to Acumatica Framework€¦ · Functional Requirements ... • On the website of the Acumatica Framework-based application template that you will ... BQL is written

| Part 2: Data Entry Pages | 83

Conclusion: Usage of Combo Boxes and Autoinsertion of ValuesTo configure a combo box as an input control for a data field, you use the PXStringList attribute. Youplace the attribute on the definition of the data field in the data access class. You specify the list ofpossible value assigned to the field and the list of labels that are displayed in the UI.

Acumatica Framework events are raised at the model level and not on the UI. The events are raised onDAC fields and rows in cache objects of the graph, and have nothing to do with ASP.NET controls.

To update fields of the same data record, you can handle the FieldUpdated event for the data fieldfrom which the other ones depend. The FieldUpdated event is raised in the data record insertion andupdate event chains before the row events are raised and the data record is updated in the cacheobject.

If you want the event to trigger immediately after the user changes the value in the UI, enable thecallback for the control or column by specifying the CommitChanges property to True for the control orcolumn on the ASP.NET page.

To obtain a data record in an event handler, you can invoke the PXSelectorAttribute.Select<>()method that uses the BQL query from PXSelector on the specified field. This method enables you toreuse the BQL query defined on the data field and supports maintainability of the code. You can alsoselect a data record by using the Select() method on a data view, or the static Select<>() method ofthe needed data view type. You can learn more about retrieving data records from the database in codein the T200 Acumatica Framework Fundamentals course.

In the next lesson, you will add calculation of sales order and detail totals that is automatically executedwhile the user edits the document.

Page 84: T100 Introduction to Acumatica Framework€¦ · Functional Requirements ... • On the website of the Acumatica Framework-based application template that you will ... BQL is written

| Part 2: Data Entry Pages | 84

Lesson 6: Calculating TotalsIn this lesson, you will implement automatic calculation of sales order and detail totals displayed on theSales Orders page.

Course Objective

• Get the basic understanding of the events to handle for calculation and update of data fields fromcode.

Page 85: T100 Introduction to Acumatica Framework€¦ · Functional Requirements ... • On the website of the Acumatica Framework-based application template that you will ... BQL is written

| Part 2: Data Entry Pages | 85

Calculating the Extended Price of an Order LineIn this step, you will add calculation of the extended price of a order line by the given formula:

extended price = product quantity * unit price * (1 - discount / 100).

Since you need to update the LinePrice data field that depends on the data fields of the samerecord, UnitPrice, OrderQty, and DiscPct, you will recalculate the extended price onFieldUpdated events for the latter fields. Do the following:

1. In the SalesOrderEntry graph, define the CalcLinePrice() method as follows.

protected decimal? CalcLinePrice(decimal? unitPrice, decimal? qty, decimal? discount){ return unitPrice * qty * (1 - discount / 100);}

The CalcLinePrice method enables you to reuse the calculation code. Though the methodtakes nullable parameters, you don't have to check variables for null before they are used,because you've defined the default 0.0 value for each of these data fields in the OrderLineDAC.

2. In the SalesOrderEntry graph, invoke the CalcLinePrice() method in theFieldUpdated() event handlers for the UnitPrice, OrderQty, and DiscPct data fields asfollows.

protected virtual void OrderLine_UnitPrice_FieldUpdated( PXCache sender, PXFieldUpdatedEventArgs e){ OrderLine line = (OrderLine)e.Row; line.LinePrice = CalcLinePrice(line.UnitPrice, line.OrderQty, line.DiscPct);}

protected virtual void OrderLine_OrderQty_FieldUpdated( PXCache sender, PXFieldUpdatedEventArgs e){ OrderLine line = (OrderLine)e.Row; line.LinePrice = CalcLinePrice(line.UnitPrice, line.OrderQty, line.DiscPct);}

protected virtual void OrderLine_DiscPct_FieldUpdated( PXCache sender, PXFieldUpdatedEventArgs e){ OrderLine line = (OrderLine)e.Row; line.LinePrice = CalcLinePrice(line.UnitPrice, line.OrderQty, line.DiscPct);}

As in the case of initialization of dependent fields (Inserting Product Details into an Order Line),in the code above, you implement calculation of each field, which depends from other fields ofthe same DAC, in the FieldUpdated event.

3. Rebuild the project.

4. On the RB301000.aspx page, enable the callback by setting the CommitChanges:True propertyfor the OrderQty column of the grid (as the screenshot demonstrates):

Page 86: T100 Introduction to Acumatica Framework€¦ · Functional Requirements ... • On the website of the Acumatica Framework-based application template that you will ... BQL is written

| Part 2: Data Entry Pages | 86

Figure: Enable the callback on the grid column

5. Save the changes.

Open the Sales Orders page in a web browser. Create a new sales order and add a product to it. Specifythe order line quantity and check whether the extended price has been updated.

Because you've set CommitChanges to true for the OrderQty field, when you change its value andmove the focus to the next field in the same line, the modifications to the line are immediately sentto the server. As a result, the system raises events on the OrderLine cache object and the extendedprice of the line recalculated.

The page automatically commits changes to the server when you move to the next line or press the Ctrl+Enter key combination, which finishes the editing of the current line. For example, specify the discountand select another line or press Ctrl+Enter. You can see that the discount is immediately applied andthe Ext. Price value is updated (see the screenshot below).

Figure: Test the extended price calculation

Page 87: T100 Introduction to Acumatica Framework€¦ · Functional Requirements ... • On the website of the Acumatica Framework-based application template that you will ... BQL is written

| Part 2: Data Entry Pages | 87

Calculating the Lines Total and Tax Total of a Sales OrderIn this step, you will add calculation of the lines and tax totals of a sales order by the given formulas:

lines total = sum of the extended prices on all order details,

tax total = sum of the tax amounts on all order details.

Since you update the master data fields, SalesOrder.LinesTotal and SalesOrder.TaxTotal,that depend on the data fields of the detail data record, OrderLine.LinePrice andOrderLine.TaxAmt you implement update in three event handlers for the detail data record,OrderLine_RowInserted(), OrderLine_RowUpdated(), and OrderLine_RowDeleted(). Inthese events, you update sales order totals after an order detail has been inserted, updated, or markedas deleted in the cache object. If you update master data fields before the order detail is modified inthe cache object, you may get inconsistent data in the master record. For instance, if an order detailhasn't been added to the document due to a validation error, the lines total may have already beenincreased. Do the following:

1. In the SalesOrderEntry graph, define the OrderLine_RowInserted(),OrderLine_RowUpdated(), and OrderLine_RowDeleted() as follows.

protected virtual void OrderLine_RowInserted( PXCache sender, PXRowInsertedEventArgs e){ OrderLine line = (OrderLine)e.Row; SalesOrder order = Orders.Current; bool isUpdated = false;

if (line.LinePrice != null) { order.LinesTotal += line.LinePrice; isUpdated = true; } if (line.TaxAmt != null) { order.TaxTotal += line.TaxAmt; isUpdated = true; }

if (isUpdated) Orders.Update(order);}

protected virtual void OrderLine_RowUpdated( PXCache sender, PXRowUpdatedEventArgs e){ OrderLine newLine = (OrderLine)e.Row; OrderLine oldLine = (OrderLine)e.OldRow; SalesOrder order = Orders.Current; bool isUpdated = false;

if (!sender.ObjectsEqual<OrderLine.linePrice>(newLine, oldLine)) { if (oldLine.LinePrice != null) { order.LinesTotal -= oldLine.LinePrice; } if (newLine.LinePrice != null) { order.LinesTotal += newLine.LinePrice; } isUpdated = true; } if (!sender.ObjectsEqual<OrderLine.taxAmt>(newLine, oldLine)) { if (oldLine.TaxAmt != null) {

Page 88: T100 Introduction to Acumatica Framework€¦ · Functional Requirements ... • On the website of the Acumatica Framework-based application template that you will ... BQL is written

| Part 2: Data Entry Pages | 88

order.TaxTotal -= oldLine.TaxAmt; } if (newLine.TaxAmt != null) { order.TaxTotal += newLine.TaxAmt; } isUpdated = true; }

if (isUpdated) Orders.Update(order);}

protected virtual void OrderLine_RowDeleted( PXCache sender, PXRowDeletedEventArgs e){ OrderLine line = ( OrderLine)e.Row; SalesOrder order = Orders.Current; PXEntryStatus orderStatus = Orders.Cache.GetStatus(order); bool isDeleted = orderStatus == PXEntryStatus.InsertedDeleted || orderStatus == PXEntryStatus.Deleted; if (isDeleted) return;

bool isUpdated = false; if (line.LinePrice != null) { order.LinesTotal -= line.LinePrice; isUpdated = true; } if (line.TaxAmt != null) { order.TaxTotal -= line.TaxAmt; isUpdated = true; }

if (isUpdated) Orders.Update(order);}

In each of these events, you obtain the sales order to be updated through the Current propertyof the Orders data view that works with the SalesOrder cache object. The Current property ofthe Orders data view retrieves the data record that is currently selected in the UI. The orderdetail data record that has been inserted, updated, or marked as deleted in the cache object isobtained from the event arguments, the e.Row object. At the end if each method, you invokethe Orders.Update(order) method to update the data record in the cache object that workswith instances of the SalesOrder DAC.

2. Rebuild the project.

Open the Sales Orders page in a web browser. Create a new sales order and add several products to it.Check whether the lines total and tax total are correctly calculated when you add products, modify theirparameters, or delete products from the order (see the screenshot below).

Page 89: T100 Introduction to Acumatica Framework€¦ · Functional Requirements ... • On the website of the Acumatica Framework-based application template that you will ... BQL is written

| Part 2: Data Entry Pages | 89

Figure: Test calculation of the lines and tax totals

Page 90: T100 Introduction to Acumatica Framework€¦ · Functional Requirements ... • On the website of the Acumatica Framework-based application template that you will ... BQL is written

| Part 2: Data Entry Pages | 90

Calculating the Order TotalFinally, you will add calculation of the sales order total by the given formula:

order total = lines total + tax total.

Since the SalesOrder.OrderTotal data field depends on the fields of the same record,SalesOrder.LinesTotal and SalesOrder.TaxTotal, you will recalculate the order total onFieldUpdated events for these fields. Do the following:

1. Add the SalesOrder_LinesTotal_FieldUpdated() andSalesOrder_TaxTotal_FieldUpdated() event handlers to the SalesOrderEntry classas follows.

protected virtual void SalesOrder_LinesTotal_FieldUpdated( PXCache sender, PXFieldUpdatedEventArgs e){ SalesOrder order = (SalesOrder)e.Row; order.OrderTotal = order.LinesTotal + order.TaxTotal;}

protected virtual void SalesOrder_TaxTotal_FieldUpdated( PXCache sender, PXFieldUpdatedEventArgs e){ SalesOrder order = (SalesOrder)e.Row; order.OrderTotal = order.LinesTotal + order.TaxTotal;}

2. Rebuild the project.

Open the Sales Orders page in a web browser. Create a new sales order and add several products to it.Check whether the order total is calculated correctly as soon as either of Lines Total or Tax Total fieldis changed (see the screenshot below).

Figure: Test the order total calculation

Page 91: T100 Introduction to Acumatica Framework€¦ · Functional Requirements ... • On the website of the Acumatica Framework-based application template that you will ... BQL is written

| Part 2: Data Entry Pages | 91

Conclusion: CalculationsFor the Sales Orders page, you've added the calculation logic of sales order and detail totals. Tocalculate a field of the same data record, you implemented the FieldUpdated event handlers for thedata fields on which the calculated field depends. To find the sum of extended prices for the order totaldata field, you've implemented calculation in three RowInserted, RowUpdated, and RowDeleted eventson the detail DAC.

For calculations, instead of implementing a bunch of event handlers, you can use the PXFormulaattribute. PXFormula handles the RowInserted, RowUpdated, and RowDeleted events in a similar wayas you've handled these events to update SalesOrder.LinesTotal and SalesOrder.TaxTotalfields. You can see the examples of PXFormula use in the T200 Acumatica Framework Fundamentalscourse and in the documentation: Acumatica Framework > API Reference > Attributes >Referential integrity and Calculations.

Page 92: T100 Introduction to Acumatica Framework€¦ · Functional Requirements ... • On the website of the Acumatica Framework-based application template that you will ... BQL is written

| Part 3: Inquiry Pages | 92

Part 3: Inquiry Pages

In this part of the course, you will create the Sales Order Inquiry page. Inquiry pages usually display alist of data records selected by the specified filter.

Page 93: T100 Introduction to Acumatica Framework€¦ · Functional Requirements ... • On the website of the Acumatica Framework-based application template that you will ... BQL is written

| Part 3: Inquiry Pages | 93

Lesson 7: Creating the Sales Order Inquiry PageIn this lesson, you will create the Sales Order Inquiry page that provides the list of documents selectedby the specified customer (see the screenshot of the page below).

Figure: The Sales Orders Inquiry page on the website

Page 94: T100 Introduction to Acumatica Framework€¦ · Functional Requirements ... • On the website of the Acumatica Framework-based application template that you will ... BQL is written

| Part 3: Inquiry Pages | 94

Adding the SalesOrderInq GraphIn this step, you will add the business logic controller that works with the Sales Order Inquiry page. Dothe following:

1. In the RapidByte folder of the application project, create the new SalesOrderInq.cs file from thePXGraph template. The graph definition should look as follows.

namespace RB.RapidByte{ public class SalesOrderInq : PXGraph<SalesOrderInq> { }}

2. In the SalesOrderInq graph, define the SalesOrderFilter data access class with twounbound data fields,CustomerID and Status. Data fields of the SalesOrderFilterclass will be used as filtering parameters on the inquiry page. The definition of theSalesOrderFilter DAC looks as follows.

[Serializable]public class SalesOrderFilter : IBqlTable{ #region CustomerID public abstract class customerID : IBqlField { } [PXInt] [PXDefault] [PXUIField(DisplayName = "Customer ID")] [PXSelector( typeof(Customer.customerID), typeof(Customer.customerCD), typeof(Customer.companyName), SubstituteKey = typeof(Customer.customerCD))] public virtual int? CustomerID { get; set; } #endregion #region Status public abstract class status : PX.Data.IBqlField { } [PXString(1, IsFixed = true)] [PXUIField(DisplayName = "Status")] [PXStringList( new string[] { OrderStatus.Open, OrderStatus.Hold, OrderStatus.Approved, OrderStatus.Completed }, new string[] { OrderStatus.UI.Open, OrderStatus.UI.Hold, OrderStatus.UI.Approved, OrderStatus.UI.Completed })] public virtual string Status { get; set; } #endregion}

The filter class is defined as an ordinary DAC that consists of only unbound data fields. Datafields are unbound because we use them only for UI and we do not retrieve data records of

Page 95: T100 Introduction to Acumatica Framework€¦ · Functional Requirements ... • On the website of the Acumatica Framework-based application template that you will ... BQL is written

| Part 3: Inquiry Pages | 95

this class from the database. We will use this class to compose the BQL query that returns datarecords selected by the customer specified in the filtering parameter displayed in the UI.

3. In the SalesOrderInq graph, define the Filter data view of the specific PXFilter type asfollows. Define the Cancel action to add the Cancel button to the page that clears the filter.

public PXCancel<SalesOrderFilter> Cancel;

public PXFilter<SalesOrderFilter> Filter;

The PXFilter type of data views is used to provide data selection parameters on pages. Thedata view of this type always returns one record that consists of the filtering parametersspecified by the user in the UI. The PXFilter data view never requests data from the database.The type parameter of the PXFilter data view must be the DAC that provides filteringparameters, which is SalesOrderFilter in our case. The Filter data view must be declaredas the first data view in the graph and specified as the primary view for the datasource controlon the page.

4. In the SalesOrderInq graph, define the SalesOrders data view that retrieves all datarecords if no customer and status are specified in the filter, or the data records selected by thespecified customer and status.

public PXSelectReadonly<SalesOrder, Where2<Where<Current<SalesOrderFilter.customerID>, IsNull, Or<SalesOrder.customerID, Equal<Current<SalesOrderFilter.customerID>>>>, And<Where<Current<SalesOrderFilter.status>, IsNull, Or<SalesOrder.status, Equal<Current<SalesOrderFilter.status>>>>>>> Orders;

The PXSelectReadonly type of the data view specifies that the data is displayed in read-onlymode in the UI. Because of the data view type, the framework disables edit controls in the UI fordata fields retrieved through the data view.

The resulting definition of the SalesOrderInq graph is given below.

public class SalesOrderInq : PXGraph<SalesOrderInq>{ [Serializable] public class SalesOrderFilter : IBqlTable { #region CustomerID public abstract class customerID : IBqlField { } [PXInt] [PXDefault] [PXUIField(DisplayName = "Customer ID")] [PXSelector( typeof(Search<Customer.customerID>), typeof(Customer.customerCD), typeof(Customer.companyName), SubstituteKey = typeof(Customer.customerCD))] public virtual int? CustomerID { get; set; } #endregion #region Status public abstract class status : PX.Data.IBqlField { } [PXString(1, IsFixed = true)] [PXUIField(DisplayName = "Status")] [PXStringList( new string[] { OrderStatus.Open, OrderStatus.Hold,

Page 96: T100 Introduction to Acumatica Framework€¦ · Functional Requirements ... • On the website of the Acumatica Framework-based application template that you will ... BQL is written

| Part 3: Inquiry Pages | 96

OrderStatus.Approved, OrderStatus.Completed }, new string[] { OrderStatus.UI.Open, OrderStatus.UI.Hold, OrderStatus.UI.Approved, OrderStatus.UI.Completed })] public virtual string Status { get; set; } #endregion }

public PXCancel<SalesOrderFilter> Cancel;

public PXFilter<SalesOrderFilter> Filter; public PXSelectReadonly<SalesOrder, Where2<Where<Current<SalesOrderFilter.customerID>, IsNull, Or<SalesOrder.customerID, Equal<Current<SalesOrderFilter.customerID>>>>, And<Where<Current<SalesOrderFilter.status>, IsNull, Or<SalesOrder.status, Equal<Current<SalesOrderFilter.status>>>>>>> Orders;}

5. Rebuild the project.

Now the graph that works with the inquiry page is ready. Go to the next step to add the ASP.NET page.

Page 97: T100 Introduction to Acumatica Framework€¦ · Functional Requirements ... • On the website of the Acumatica Framework-based application template that you will ... BQL is written

| Part 3: Inquiry Pages | 97

Adding Page RB401000In this step, you will create a new ASP.NET page that provides inquiry of sales orders by the specifiedcustomer. To add the page, perform the following instructions:

1. In the Pages > RapidByte folder of Site, create the new RB401000.aspx page from theFormDetail template.

2. Open the created page in design mode and specify the following properties for the ds datasourcecontrol:

• TypeName: RB.RapidByte.SalesOrderInq

• PrimaryView: Filter

3. Select the form PXFormView control on the page and set the DataMember:Filter property for it.

Now you can generate controls for the form, which represent filtering parameters.

4. Open Layout Editor for the form control.

5. On the Fields tab, click Select All and Generate.

6. Select the Row node in the tree and set the following properties for it:

• Merge:True

• ControlSize: S

• LabelsWidth: S

7. Set the following properties for the edCustomerID node:

• CommitChanges: True

• Size: XM

8. Set the following properties for the edStatus node:

• CommitChanges: True

• LabelWidth: 50px

9. Click Ok to close Layout Editor.

10. Select the grid PXGrid control on the page and set the following properties for it:

• DataMember: Orders

• SkinID: Inquire

11. Open Layout Editor for the grid.

12. On the Fields tab, select any fields that you want to see for each sales order on the inquirypage. In our example, we select the OrderNbr, OrderDate, Status, CustomerID, ShippedDate,and OrderTotal data fields.

13. Select the only Columns check box below the field list. Click Generate.

14. Close Layout Editor and save changes on the page.

15. Add the page to the site map. To do this, open the System > Customization > Site Mappage and add the RB401000.aspx page under the Acumatica Company > RapidByte >RapidByte > Work Area > Explore node with the following parameters:

• Screen ID: RB.40.10.00

• Title: Sales Order Inquiry

• Icon: Empty

Page 98: T100 Introduction to Acumatica Framework€¦ · Functional Requirements ... • On the website of the Acumatica Framework-based application template that you will ... BQL is written

| Part 3: Inquiry Pages | 98

• URL: ~/Pages/RapidByte/RB401000.aspx

• Graph Type: Completed automatically

• Expanded: Cleared

Open the Sales Order Inquiry page in a web browser. Select a customer in the Customer ID filter andthe status in the Status filter and check whether the list has been filtered by the specified values (seethe screenshot below). Click Cancel to clear the filter.

Figure: Test the filter on the Sales Order Inquiry Page

Page 99: T100 Introduction to Acumatica Framework€¦ · Functional Requirements ... • On the website of the Acumatica Framework-based application template that you will ... BQL is written

| Part 3: Inquiry Pages | 99

Conclusion: Inquiry PagesTo provide filter for an inquiry page, you can use the specific PXFilter data view type. In the Filterdata view of this type, you specify the class that provides filtering parameters. Typically, you define aseparate DAC that consist of only unbound data fields to specify the class in the PXFilter data view.On the ASPX page, you have to enable the callbacks for controls that display the filtering parameters.In the data view that provides data for the grid on the inquiry page, you compose the BQL query thatselects data records by the specified filter.

Avoid using the PXFilter data view type with DACs which have at least one key field defined, i.e. containfields having the IsKey=true parameter in the type attribute.

Page 100: T100 Introduction to Acumatica Framework€¦ · Functional Requirements ... • On the website of the Acumatica Framework-based application template that you will ... BQL is written

| Part 4: Processing Pages | 100

Part 4: Processing Pages

In this part of the course, you will create the processing page that provides mass approval of salesorders.

Page 101: T100 Introduction to Acumatica Framework€¦ · Functional Requirements ... • On the website of the Acumatica Framework-based application template that you will ... BQL is written

| Part 4: Processing Pages | 101

Lesson 8: Creating the Approve Sales Orders PageIn this lesson, you will create a page for processing of sales orders. The processing operation changesthe status of a sales order to Approved. The screenshot below shows the Approve Sales Orders pageon the RapidByte website.

Figure: The Approve Sales Orders page on the website

Page 102: T100 Introduction to Acumatica Framework€¦ · Functional Requirements ... • On the website of the Acumatica Framework-based application template that you will ... BQL is written

| Part 4: Processing Pages | 102

Implementing the Approval OperationIn this step, you will define the ApproveOrder() method that processes a sales order and setsthe status to Approved. Also, you will add the Approve button to the Sales Orders page thatinvokes the method to process the sales order currently opened on the data entry page. The sameApproveOrder() method will be used on the processing page. Do the following:

1. In the SalesOrderEntry graph, define the ApproveOrder() method as follows.

public void ApproveOrder(SalesOrder order, bool isMassProcess = false){ Orders.Current = order; if (order.Status == OrderStatus.Hold) { throw new PXException(String.Format( "Order {0} is On Hold and cannot be approved.", order.OrderNbr)); } else if (order.Status != OrderStatus.Open) { throw new PXException(String.Format( "Order {0} is already approved.", order.OrderNbr)); } order.Status = OrderStatus.Approved; Orders.Update(order); Persist(); if (isMassProcess) { PXProcessing.SetInfo(String.Format( "Order {0} has been successfully approved.", order.OrderNbr)); }}

In the ApproveOrder() method, you set the Status field to Approved flag for the orderobtained from the input parameter of the method. To work with a SalesOrder data record,you use the SalesOrderEntry graph; after the status is set to Approved for the object inmemory, you invoke the Orders.Update() method to update the order in the cache object,and then call the Persist() method to save changes to the database.

The isMassProcess flag means that the method is invoked from the mass processing page,where a user can select multiple sales orders and run the operation for them. In the case ofmass processing, you return the successful processing message to the UI by using the staticPXProcessing.SetInfo() method.

To return a processing error to the UI, you throw the PXException with the specified errormessage.

For internationalization support and better maintainability of the application, you should uselocalizable constants instead of hard-coded strings in the application. For more information,see Acumatica Framework > Programming Tasks > Localizing Applications in thedocumentation.

2. In the SalesOrderEntry graph, define the Approve action as follows and invoke theprocessing method in the approve() handler for this action.

public PXAction<SalesOrder> Approve;[PXProcessButton][PXUIField(DisplayName = "Approve")]protected virtual IEnumerable approve(PXAdapter adapter){ foreach (SalesOrder order in adapter.Get()) { Actions.PressSave();

Page 103: T100 Introduction to Acumatica Framework€¦ · Functional Requirements ... • On the website of the Acumatica Framework-based application template that you will ... BQL is written

| Part 4: Processing Pages | 103

PXLongOperation.StartOperation(this, delegate() { SalesOrderEntry graph = PXGraph.CreateInstance<SalesOrderEntry>(); graph.ApproveOrder(order); }); yield return order; }}

This is the typical definition of a processing action that is invoked from a data entry page. Theapprove() method meets the delegate type of an action handler. Also, the action handler musthave the same name as the PXAction field but with another case of the first letter, as the codeabove shows.

To run the ApproveOrder() processing method within the approve() action handler, youinvoke the PXLongOperation.StartOperation() that takes the anonymous method in whichyou create a separate instance of the graph and invoke the ApproveOrder() method forprocessing of a sales order. The delegate you pass to StartOperation() is executed in aseparate thread. Before you run the operation, you invoke the Actions.PressSave() method tosave the last changes made on the data entry page to be sure to process the latest version ofthe sales order.

Use the PXGraph.CreateInstance<T>() method to instantiate graphs.

3. Rebuild the project.

Open the Sales Orders page in a web browser. Select a sales order and click Approve. As soon thedocument has been processed, the status of the sales order becomes Approved (see the screenshotbelow).

Figure: Test the approval operation

Page 104: T100 Introduction to Acumatica Framework€¦ · Functional Requirements ... • On the website of the Acumatica Framework-based application template that you will ... BQL is written

| Part 4: Processing Pages | 104

Adding the SalesOrderProcess GraphIn this step, you will add the business logic controller that works with the Approve Sales Order page. Dothe following:

1. In the RapidByte folder of the application project, create the new SalesOrderProcess.cs file fromthe PXGraph template.

2. Define the Cancel action for the toolbar and the Orders data view that provides data recordsto be processed on the page, as follows.

public class SalesOrderProcess : PXGraph<SalesOrderProcess>{ public PXCancel<SalesOrder> Cancel; public PXProcessing<SalesOrder> Orders;}

The Orders data view will be the primary view for the page.

3. In the SalesOrderProcess graph, define the constructor as follows.

public SalesOrderProcess(){ Orders.SetProcessCaption("Approve"); Orders.SetProcessAllCaption("Approve All"); Orders.SetProcessDelegate<SalesOrderEntry>( delegate(SalesOrderEntry graph, SalesOrder order) { graph.Clear(); graph.ApproveOrder(order, true); });}

The constructor overrides captions of two standard buttons that will be automatically addedto the toolbar due to the PXProcessing type of the primary view of the page. By default, theframework adds the Process and Process All buttons to the page toolbar. To override thebutton captions, you use the SetProcessCaption() and the SetProcessAllCaption() methods.

Also, the constructor specifies the processing delegate that is the required definition in graph.To specify the processing method, you invoke the Orders.SetProcessDelegate() methodthat takes the anonymous method with two input parameters. For such type of the delegate,the framework creates the specified graph and gets the list of orders selected on the page. Foreach order, the framework executes the specified anonymous method in which you invoke theApproveOrder() method. Every time the anonymous method gets the same instance of thegraph, so we first call the graph.Clear() method, which deletes all data from cache objectswithin the graph, before we process the next order.

4. Rebuild the project.

Now the graph is ready and you can create the ASP.NET page that displays the list of sales orders toprocess.

Page 105: T100 Introduction to Acumatica Framework€¦ · Functional Requirements ... • On the website of the Acumatica Framework-based application template that you will ... BQL is written

| Part 4: Processing Pages | 105

Adding Page RB501000In this step, you will create a new ASP.NET page for mass approval of sales orders. To add the page,perform the following instructions:

1. In the SalesOrder.cs file, add the unbound Selected data field to the SalesOrder dataaccess class.

#region Selectedpublic abstract class selected : IBqlField{}[PXBool][PXUIField(DisplayName = "Selected")]public virtual bool? Selected { get; set; }#endregion

The Selected data field is unbound, which is defined by the PXBool type attribute. Selectedwill be used only for UI to display the check box for selection of multiple sales orders on thepage. Selected is the default name of a DAC field that the framework uses for a check boxthat marks records on processing pages. You can learn more about processing pages in the T200Acumatica Framework Fundamentals course.

2. Save the changes and rebuild the project.

Now you can create a new ASP.NET page that displays the list of sales orders for processing.

3. In the Pages > RapidByte folder of Site, create the new RB501000.aspx page from theListView template.

4. Open the page in design mode and specify the following properties for the ds datasourcecontrol:

• TypeName: RB.RapidByte.SalesOrderProcess

• PrimaryView: Orders

5. Select the grid PXGrid control at the bottom of the page. In the Properties window, specify thefollowing properties for it:

• DataMember:Orders

• SkinID: Inquire

6. Open Layout Editor for the grid PXGrid control.

7. On the Fields tab, select any fields that you'd want to see for each sales order in the list forprocessing. In our example, we select the Selected, OrderNbr, OrderDate, Status, CustomerID,ShippedDate, and OrderTotal fields from the list.

8. Select the Columns check box below the field list and clear the Controls check box. ClickGenerate.

9. Move the Selected column to the topmost position in the Grid Columns list and setAllowCheckAll: True for this column. As a result, the column header will contain a check boxwhich you can use to select all data records in the grid.

10. Click Ok to save the generated controls and to close Layout Editor.

11. Save the changes.

12. Add the Daily node as a child of the Acumatica Company > RapidByte > RapidByte >Processes node.

Page 106: T100 Introduction to Acumatica Framework€¦ · Functional Requirements ... • On the website of the Acumatica Framework-based application template that you will ... BQL is written

| Part 4: Processing Pages | 106

13. Add the page to the site map. To do this, open the System > Customization > Site Mappage and add the RB501000.aspx page under the Acumatica Company > RapidByte >RapidByte > Processes > Daily node with the following parameters:

• Screen ID: RB.50.10.00

• Title: Approve Sales Order

• Icon: Empty

• URL: ~/Pages/RapidByte/RB501000.aspx

• Graph Type: Completed automatically

• Expanded: Cleared

Open the Approve Sales Order page in a web browser. On the page, you can select one or multiplesales orders to launch processing for all of them at once. Select several sales orders and click Approve.The processing result appears on the page (see the screenshot below). The Cancel button clears theselection and refreshes the list of sales orders on the page. Notice that you can select all data records inthe grid by checking the box in the header of the first column.

Figure: Test the mass sales order approval

Page 107: T100 Introduction to Acumatica Framework€¦ · Functional Requirements ... • On the website of the Acumatica Framework-based application template that you will ... BQL is written

| Part 4: Processing Pages | 107

Conclusion: Processing PagesFor the graph that works with the processing page, you have to:

• Use the specific PXProcessing (or derived) data view type to provide data records for the page.

• Define the processing delegate for the PXProcessing (or derived) data view in the graphconstructor.

The processing delegate is a method that executes for each data record selected on the page. To adda check box to the page that enables users to select multiple data records for processing, you haveto define the unbound boolean field in the DAC whose data records are processed. Also, you haveto add the column for this data field to the grid that lists the processed data records. The Processand Process All buttons are automatically added to the toolbar of the page whether you specify thePXProcessing data view as the primary view for the page or not.

Page 108: T100 Introduction to Acumatica Framework€¦ · Functional Requirements ... • On the website of the Acumatica Framework-based application template that you will ... BQL is written

| Part 4: Processing Pages | 108

Lesson 9: Setting Up the UI for Approved Sales OrdersIn this short lesson, you will set up the graph to display approved sales orders in read-only mode on theSales Orders page.

Lesson Objective

• See how to use the RowSelected event to dynamically set up the UI depending on the currentdata record.

Page 109: T100 Introduction to Acumatica Framework€¦ · Functional Requirements ... • On the website of the Acumatica Framework-based application template that you will ... BQL is written

| Part 4: Processing Pages | 109

Making Approved Sales Orders Read-only in the UITo make the page display approved sales orders in read-only mode, do the following:

1. In the SalesOrderEntry graph, define the SalesOrder_RowSelected() event handler asfollows.

protected virtual void SalesOrder_RowSelected(PXCache sender, PXRowSelectedEventArgs e){ SalesOrder order = (SalesOrder)e.Row; if (order == null) return;

bool editable = order.Status != OrderStatus.Approved && order.Status != OrderStatus.Completed;

Orders.Cache.AllowUpdate = editable; Orders.Cache.AllowDelete = editable; PXUIFieldAttribute.SetEnabled(sender, order, editable); OrderDetails.Cache.AllowDelete = editable; OrderDetails.Cache.AllowInsert = editable; OrderDetails.Cache.AllowUpdate = editable; Approve.SetEnabled(editable && order.Hold != true);}

The framework raises the RowSelected() event for every data record displayed on the page. Theevent is raised in the end in all scenarios of events. The RowSelected event is used to set up theUI for a particular data record or the details grid. In the SalesOrder_RowSelected() event, youdisable or enable editing of the currently selected data record, which depends on the Statusvalue. If a sales order has the Approved or Completed status, the page displays the datarecord in read-only mode: users cannot update or delete the read-only data record. Otherwise,the Approve button is enabled only if the Hold value isn't true.

The PXUIFieldAttribute.SetEnabled() method disables all controls on the page except forthe first declared control that displays the key value. The user can select another key valueto navigate between data records in the UI. The AllowDelete, AllowUpdate, AllowInsertproperties disable the corresponding toolbar buttons that works with data records kept in thecorresponding cache objects. Thus, the Orders.Cache.AllowDelete = false; propertydisables the Delete button for the sales order; the OrderDetails.Cache.AllowDelete =false; property disables the Delete button for the order details. To configure the Approvebutton, we use the Approve.SetEnabled(...) method.

2. Rebuild the project.

Open the Sales Orders page in a web browser and select an approved document. Make sure the UI isdisabled for the sales order and doesn't allow the user to edit the document (see the screenshot below).

Page 110: T100 Introduction to Acumatica Framework€¦ · Functional Requirements ... • On the website of the Acumatica Framework-based application template that you will ... BQL is written

| Part 4: Processing Pages | 110

Figure: View an approved sales order in read-only mode

Page 111: T100 Introduction to Acumatica Framework€¦ · Functional Requirements ... • On the website of the Acumatica Framework-based application template that you will ... BQL is written

| Part 4: Processing Pages | 111

Conclusion: UI SetupTo make certain data records display in read-only mode, implement the UI setup in the RowSelected()event handler. By the specified condition, you can dynamically enable/disable controls and buttons forthe currently selected data record on the page. Use the PXUIFieldAttribute.SetEnabled() methodto disable/enable controls, and AllowDelete, AllowUpdate, and AllowInsert properties of the cacheobject to enable/disable buttons on the page. You have to implement both UI disabling and enablinglogic, because the controls are not automatically enabled once you've disabled them from the code.

Page 112: T100 Introduction to Acumatica Framework€¦ · Functional Requirements ... • On the website of the Acumatica Framework-based application template that you will ... BQL is written

| Part 5: Reports | 112

Part 5: Reports

In this part of the course, you will see how to create a report by using Report Designer, the visual toolprovided with Acumatica Framework, on the example of the printable sales order page. The printablelayout definition of a page is created in the same way as a report.

Page 113: T100 Introduction to Acumatica Framework€¦ · Functional Requirements ... • On the website of the Acumatica Framework-based application template that you will ... BQL is written

| Part 5: Reports | 113

Lesson 10: Creating the Sales Orders Printable FormIn this lesson, you will design the report form for sales order printing. Printable pages are createdin Report Designer in the same .rpx format as report forms. On the website, the form for generatingprintable documents looks the same as the form for building reports. While making the report, you willalso add a report variable that provides row numbers in the detail section of the report. Additionally,you will add the status of a sales order to the printable page. The screenshot below shows the reportthat you will be able to generate by the end of this lesson.

Figure: The Sales Orders form on the website

Page 114: T100 Introduction to Acumatica Framework€¦ · Functional Requirements ... • On the website of the Acumatica Framework-based application template that you will ... BQL is written

| Part 5: Reports | 114

Preparing Data for the ReportThe first step of creating a report is preparing the report query, which is called the 'report schema' inReport Designer. To configure the report schema, you have to complete the following steps:

1. Add the data access classes to the report that will provide the data required for the report,SalesOrder, OrderLine, Product, and Customer.

2. Specify the relationships between the selected DACs, which are left and inner joins.

3. Add the report parameters intended for user input, OrderNbr.

4. Specify filtering conditions based on the parameters and other requirements to the report.

5. Save the report form to the file in the web site folder, /Site/ReportsDefault.

1. Adding Data Access Classes to the Report

To start configuring the report schema, you need to add the required data access classes to the report.

1. Start Report Designer located by default under All Programs > Acumatica in the WindowsStart menu.

The Report Designer visual editor opens a new blank report form.

To create a new report, you can select File -> New from the main menu of Report Designer.

2. In the File menu, select Build schema.

The Schema Builder dialog box appears.

3. In the dialog, select the Tables tab and enter the application URL, http://localhost/RapidByte/,in the Web service URL field, as it is shown in the screenshot (1).

4. Set Login=admin (2) and Password=123 (3) in the text boxes at the right side of the dialog.

You can specify any account to log in to the web site for loading of the DAC schema. In this lesson,you use the admin account with unrestricted access rights.

5. Click Load schema (4).

The list of data access classes loaded from the web site appears. The list includes all data accessclasses of your application, including the system DACs that you do not need to add to the report.

6. In the list of DACs, select the SalesOrder, OrderLine, Product, and Customer (5) data accessclasses and move them to the selected list by clicking the right-arrow button.

7. Click Apply to apply the selected data access classes to the report schema (6).

Page 115: T100 Introduction to Acumatica Framework€¦ · Functional Requirements ... • On the website of the Acumatica Framework-based application template that you will ... BQL is written

| Part 5: Reports | 115

Figure: Selecting DACs for the report

Your changes aren't saved to the file until you save the report by selecting File -> Save in themain menu.

2. Defining Relationships Between DACs

After you have added the data access classes to the report, you need to specify the relationshipsbetween these DACs that represent data joining conditions.

1. On the Relationships tab of the Schema Builder dialog box, specify of the selected DACs.

• Row 1 (see the screenshot below):

• Parent Table: SalesOrder (1)

• Join type: Left (2)

• Child Table: OrderLine (3)

After you select the child table, click at the table below to switch to the second tablefor specifying the join condition.

• Parent Field: SalesOrder.OrderNbr (4)

• Link Condition: Equal (5)

• Child Field: OrderLine.OrderNbr (6)

• Operator: And (7)

• Row 2:

• Parent Table: OrderLine

• Join type: Left

• Child Table: Product

Page 116: T100 Introduction to Acumatica Framework€¦ · Functional Requirements ... • On the website of the Acumatica Framework-based application template that you will ... BQL is written

| Part 5: Reports | 116

• Parent Field: OrderLine.ProductID

• Link Condition: Equal

• Child Field: Product.ProductID

• Operator: And

• Row 3:

• Parent Table: SalesOrder

• Join type: Inner

• Child Table: Customer

• Parent Field: SalesOrder.CustomerID

• Link Condition: Equal

• Child Field: Customer.CustomerID

Figure: Specifying join relationships for DACs

The Join type parameter of a condition is equivalent to a join operation in SQL Server. You mayuse inner, left, right, full and cross joins to retrieve data records based on the correspondinglogical relationships.

The parent-child order of DACs is important. Do not specify the same data access class as the childin more than one relationship.

To delete a relationship, select it from the first table and press Del.

2. Click Apply to apply changes to the report schema.

3. Adding Report Parameters

Report parameters are usually intended for manual input on the page before a user runs the report.

1. On the Parameters tab of the Schema Builder dialog box, add the OrderNbr report parameter.

To add a parameter, click Add below the list of parameters at the left of the dialog box (see 1 onthe screenshot). Set the following properties for the OrderNbr parameter:

Page 117: T100 Introduction to Acumatica Framework€¦ · Functional Requirements ... • On the website of the Acumatica Framework-based application template that you will ... BQL is written

| Part 5: Reports | 117

• Name: OrderNbr (2)

• Data Type: String (3)

• View name: =[SalesOrder.OrderNbr] (4)

• Prompt: Order Number (5)

• Allow Null: selected (6)

• Visible: selected (7)

• Required: selected (8)

Figure: Adding the report parameters

The Allow Null property determines whether the parameter must be provided by the userbefore running of the report. An optional parameter may have a null value during reportexecution.

The Required property specifies that the parameter must be provided by the user beforerunning the report. Otherwise, the report won't be generated.

2. Click Apply to apply the parameter to the report schema.

4. Specifying Data Filtering Conditions

Report filters define which data is selected for the report based on the parameters and other conditionsrequired for the report.

1. On the Filters tab of the Schema Builder dialog box, specify the data filtering condition (seethe screenshot).

SalesOrder.OrderNbr Equal @OrderNbr

The report parameter name is preceded by '@' in the filter expression.

Page 118: T100 Introduction to Acumatica Framework€¦ · Functional Requirements ... • On the website of the Acumatica Framework-based application template that you will ... BQL is written

| Part 5: Reports | 118

Figure: Specifying filtering conditions

In the filtering condition, you select the sales order by its number taken from the required reportparameter, @OrderNbr.

2. Click OK to apply changes and to close the Schema Builder dialog box.

Now the report schema provides the data to be displayed in the report. Save changes in the report fileas it is described below.

5. Saving the Report to a File

You can save the report to a file in the web site folder or to the database. Users who have no directaccess to the site folder can save the report to the database. In this example, you save the report tothe file. Do the following:

1. Select File > Save As from the main menu.

To save the report to the database, you select Save On Server from the main menu. To savethe created report form to the server, you need to specify an account having the Customizer userrole. The admin account has unrestricted access rights, and so you can use this account for savingthe report forms to the server. The report form (.rpx file) is saved to the UserReport table of theapplication database. In this case, you will not see the file in the /Site/ReportsDefault folder, but thereport form is available for adding to the site map. To edit the report, you can open it from serverby selecting Open From Server in the main menu.

2. In the dialog, open the /Site/ReportsDefault/ folder and save the report with the RB601000 filename.

The RB601000.rpx report is saved to the web site folder.

The website engine searches for reports and style template files in the /Site/ReportsDefault/ folder,which is specified in the PX.Reports.ReportFileManager.ReportsDir property in Site/App_Code/Auxiliary/Initialization.cs.

Now you can go to the next step to add a variable to the report.

Page 119: T100 Introduction to Acumatica Framework€¦ · Functional Requirements ... • On the website of the Acumatica Framework-based application template that you will ... BQL is written

| Part 5: Reports | 119

Adding a Variable to the ReportIn this step, you will add the RowNumber variable to the detail section of the report.

Adding a Report Variable

By using report variables, you can insert some calculated values related to the document, such as rownumbers in the detail section. To sequentially numerate order detail rows in the printed document, addthe RowNumber variable to the report.

1. On the Properties tab, select the detailSection1 DetailSection object from the drop-down list(see 1 on the screenshot).

2. In the Variables property, click the three ellipses button to open the variable collection editor(2).

3. In the ReportVariable Collection Editor dialog box, click Add (3).

4. Set the following properties for the new variable (4):

• Name: RowNumber

• ProcessOrder: Always

• ResetGroup: OrderNbr

5. Click OK to close the dialog box and to add the variable to the report. Save changes.

Now you can use the variable in a text box value expression referred by its name precededwith the dollar $ sign, as follows: $RowNumber. This variable will be used for printing detailrow numbers on the form. You can declare the same variable in several sections. In this case,the variable will be shared between them. Once modified in one section, the new value will bepassed to the next section where the variable is used. The variable is initiated at the top-mostsection where it is referred. Then the variable is sequentially modified in the following sectionsby the order as they declared in the report.

Figure: Adding the RowNumber variable to the detail section

Now the schema is ready and the report is ready for layout design. Go to the next step to add textboxes to the form that display the report data.

Page 120: T100 Introduction to Acumatica Framework€¦ · Functional Requirements ... • On the website of the Acumatica Framework-based application template that you will ... BQL is written

| Part 5: Reports | 120

Configuring the Printable Page LayoutIn this step, you will add one group for the sales order information and place text boxes on the formthat displays data on the printable page. You can also apply style templates to the text boxes that youadd to the report (see the details below).

Adding a Group to the Form

Add the OrderNbr group for displaying the sales order information. Do the following:

1. Open the RB601000.rpx report form in Report Designer.

2. On the Properties tab, select the report1 Report object from the drop-down list.

To select the report form, you can also click the top left box located under the toolbar on the reportform. The black marker will appear in the box.

Figure: Select the report form by clicking the box at the top left corner of the form

3. On the Properties tab, click the three ellipses button (...) in the Groups property to open theGroup Collection Editor.

Figure: Open the Group Collection Editor

4. In the Group Collection Editor window, click Add to add a new group (see 1 on the screenshotbelow).

5. Specify the following properties of the group (2):

• KeepTogether:WholeGroup

• PrintEmpty:False

• (Name):OrderNbr

6. Click the three ellipses button (...) in the Grouping property of the OrderNbr group (3).

7. In the GroupExp Collection Editor window, click Add (4) and setDataField:SalesOrder.OrderNbr (5), by which the nested data records will be grouped. Click OKto apply the property and to close the window.

Page 121: T100 Introduction to Acumatica Framework€¦ · Functional Requirements ... • On the website of the Acumatica Framework-based application template that you will ... BQL is written

| Part 5: Reports | 121

Figure: Add the OrderNbr group to the report

The OrderNbr group has been added to the report.

Adding Text Boxes to Sections

A report form consists of the page header and footer, group sections, and the detail section nestedwithin the most internal group. You can group data by several parameters and nest groups one inanother. The data records of each nested group are grouped by the data field specified in the higher-level group. Each group consists of the two sections on the form, header and footer. The header sectioncontains the group caption and captions for the detail data records. The footer is used to display sumsand other aggregated values calculated by the detail data.

Add the text boxes to the report sections as described below:

1. Add the Delivery Note text box to the printable page header and place a line at the border ofthe page header section. Adjust the height to 24px of this and of all other text boxes on theform.

Figure: Page Header Elements

Page 122: T100 Introduction to Acumatica Framework€¦ · Functional Requirements ... • On the website of the Acumatica Framework-based application template that you will ... BQL is written

| Part 5: Reports | 122

To add a text box to the report form:

• Click TextBox on the toolbar and then click on the place where you want to position thebox. Place the report name text box at the top right corner of the report.

• Double-click the added text box and type the displayed value. Type Delivery Note for thefirst text box. This is the value of the Value property of the text box.

• Enlarge the text box height by 8px by pulling the handle at the bottom of the box, so thatthe text box height becomes equal to 24px. Adjust the text box width so that the wholetext is visible in the box.

You can also specify the text box height on the Properties tab in the Size group. The styleparameters, including the font and text align, are applied by using the style templates,which is demonstrated further. It is also possible to adjust the style in the Style group of theproperties, but we don't recommend you to specify every style property for each text boxindividually.

Figure: Enlarge the height of a text box

2. Select the OrderNbr group header section and set the PrintOnEveryPage property to True.

Group header and footer sections has this property that enables repeating of the section contenton every page in the report.

3. Add the text boxes that display the sales order information to the OrderNbr group header sectionand set the following values for them:

• To:

• =IsNull([Customer.CompanyName],'') + IsNull('{br}'+[Customer.Address],'') + ISNull('{br} '+[Customer.City],'')+ IsNull('{br} '+[Customer.CountryCD],'') + IsNull('{br}'+[Customer.Region],'') + IsNull('{br} '+[Customer.PostalCode],'')

• Attn:

• =[Customer.ContactName]

• Order ID:

• =[SalesOrder.OrderNbr]

• Customer ID:

• =[Customer.CustomerCD]

• Order Date:

• =[SalesOrder.OrderDate]

• Shipment Date:

• =[SalesOrder.ShippedDate]

• Status:

• =[SalesOrder.Status]

Page 123: T100 Introduction to Acumatica Framework€¦ · Functional Requirements ... • On the website of the Acumatica Framework-based application template that you will ... BQL is written

| Part 5: Reports | 123

• No.

• Product Item

• Stock Unit

• Quantity

• Unit Price

• Discount

• Extended Price

Figure: Add the OrderNbr group header elements

4. Add the text boxes that display the order details to the detail section of the report and set thefollowing values for them:

• =Assign('$RowNumber',$RowNumber+1)

• =[Product.ProductName]

• =[OrderLine.StockUnit]

• =[OrderLine.OrderQty]

• =[OrderLine.UnitPrice]

• =[OrderLine.DiscPct]

• =[OrderLine.LinePrice]

Figure: Detail Section Elements

5. On the Properties tab, select the OrderNbr group footer section and specify the followingproperties for it:

• PrintAtBottom: True

• PrintOnEveryPage: True

• ProcessOrder: Always

• ResetPageNumber: True

The PrintAtBottom property makes the group footer printed always at the bottom of a page. Apage break is inserted after the section.

The ProcessOrder property is commonly used for sections and particular text boxes. Oncespecified for a section, the property is applied to every text box in this section unless theproperty is overridden for this text box. The ProcessOrder property specifies when the textbox value is processed during the report generation. A text box value can be processed when

Page 124: T100 Introduction to Acumatica Framework€¦ · Functional Requirements ... • On the website of the Acumatica Framework-based application template that you will ... BQL is written

| Part 5: Reports | 124

the data is read from the database (WhileRead), when the report is printed (WhilePrint), orin both cases (Always). In most cases, when a value is just read from the database and thendisplayed in the report, WhileRead is enough, for instance, for the employee's name. However, ifthe value is calculated depending on data that will be known only at the report rendering stage,the WhilePrint mode should be specified. In our example, the sales order total will have theconditional visibility depending on the page count. The sales order total should be printed on thelast page of the report. You should use the WhilePrint mode for the sales order total, because thelast page number will be known only at the report rendering stage. Document totals are typicaldata fields with the WhilePrint processing mode.

The ProcessOrder property is also applied to sections. This property should be set to Always forthose sections that have at least one text box with the WhilePrint processing mode.

The ResetPageNumber property specifies whether the page number is reset after the section isprinted.

6. Add the text boxes to the OrderNbr group footer section and specify the following values forthem:

• ***Continued***

• Lines Total:

• =[SalesOrder.LinesTotal]

• Tax Total:

• =[SalesOrder.TaxTotal]

• Order Total:

• =[SalesOrder.OrderTotal]

• ='Page: '+[PageOf]

Figure: OrderNbr Group Footer Elements

7. On the Properties tab, set the following properties for the ***Continued*** text box:

• ProcessOrder: WhilePrint

• VisibleExpr: =([PageIndex]<[PageCount])

The ProcessOrder property makes the text box processed at the report rendering stage. Thevisibility condition specifies that the label appears on all pages except for the last page in thereport.

8. Set the following properties for all text boxes from the group footer section, except for***Continued*** and Page:

• ProcessOrder: WhilePrint

• VisibleExpr:=([PageIndex]=[PageCount])

These properties make the values printed on only the last page of the report.

9. Save the changes.

Page 125: T100 Introduction to Acumatica Framework€¦ · Functional Requirements ... • On the website of the Acumatica Framework-based application template that you will ... BQL is written

| Part 5: Reports | 125

Now the printable page is ready for running on the web site. Before you test the page, see how toformat the report by using the style templates.

Applying Style Templates

Style templates are extremely useful for quick and uniform formatting of text displayed in areport. There are two files with default style templates located in the Site/ReportsDefault/ folder,TemplateReport.rpx and TemplateForm.rpx. The TemplateReport.rpx file contains styles that you canuse for reports, while the styles from TemplateForm.rpx file are intended for printable pages. You canuse these default styles, as well as define your own custom styles required for the application.

Specify the styles template file for the report and apply style templates to text boxes, to make thereport look neat.

1. On the Properties tab, select the report1 Report object from the drop-down list.

2. In the StyleTemplate property, click the three ellipses button (...) and select theTemplateForm.rpx file.

You have specified the file containing the style templates for the printable page. Now you canapply styles defined in this file to text boxes on the form.

3. Select the Delivery Note text box on the form.

4. On the Properties tab, set StyleName:Report Name for the text box (see the screenshotbelow).

Figure: Specify the Report Name style for the text box

The appearance of the text box value has changed according to the applied style. In the sameway, you can specify styles for other text boxes on the form.

We recommend that you follow the design guidelines on creating reports in Report Designer, seeAcumatica Framework > Report Designer > Recommendations in the documentation.

Go to the next step to test the printable page on the website.

Page 126: T100 Introduction to Acumatica Framework€¦ · Functional Requirements ... • On the website of the Acumatica Framework-based application template that you will ... BQL is written

| Part 5: Reports | 126

Adding the Report URL to the Site MapIn this step, you will add the URL to the report to the site map to make users able to run the report.Complete the following steps:

1. Open the System > Customization > Site Map page and add the Forms node underAcumatica Company > RapidByte > RapidByte > Reports.

2. Add a new node under Acumatica Company > RapidByte > RapidByte > Reports > Formswith the following parameters:

• Screen ID: RB.60.10.00

• Title: Sales Orders

• Icon: Empty

• URL: ~/Frames/ReportLauncher.aspx?ID=RB601000.rpx

• Graph Type: Completed automatically

• Expanded: Cleared

3. Save the changes to the site map.

Now you can open the Sales Orders page on the website.

Page 127: T100 Introduction to Acumatica Framework€¦ · Functional Requirements ... • On the website of the Acumatica Framework-based application template that you will ... BQL is written

| Part 5: Reports | 127

Running the Report FormOpen the Sales Orders report launcher page on the website. To get a printable version of a sales order,select the Report Parameters tab item, specify the Order Number parameter and click Run Report(see the screenshot below).

Figure: Run the report form

The framework opens the sales order page for printing. The web browser Print dialog appears byclicking Print on the toolbar (see the screenshot).

Page 128: T100 Introduction to Acumatica Framework€¦ · Functional Requirements ... • On the website of the Acumatica Framework-based application template that you will ... BQL is written

| Part 5: Reports | 128

Figure: Run the report to get the printable document

Page 129: T100 Introduction to Acumatica Framework€¦ · Functional Requirements ... • On the website of the Acumatica Framework-based application template that you will ... BQL is written

| Part 5: Reports | 129

Conclusion: ReportsA report or printable page is a separate .rpx file that is created in the visual report builder, ReportDesigner, a tool provided with Acumatica Framework. While making the report, you construct the querythat is called the schema of the report; you design the position and style of text fields in the report. Youcan save the report file to the web site folder or application database. The report has the specific URL inthe site map.

Users run reports from the specific ReportLauncher page defined in the site map with a particular reportID. To build the report, the user specifies the parameters and clicks Run. Based on the parameters andlayout defined in the .rpx file, the platform generates the report and then outputs the result in printableformat.

Page 130: T100 Introduction to Acumatica Framework€¦ · Functional Requirements ... • On the website of the Acumatica Framework-based application template that you will ... BQL is written

| Appendix: Application Design | 130

Appendix: Application Design

In this course, we have already designed the application for you. During the development of AcumaticaFramework-based applications, you have to perform the following steps of application design:

• Analyse the requirements, plan the entity model of the application.

• Prepare the ORM that consists of the database schema and the data access class design.

• Plan the webpages that provide the user interface of the application. You create application pagesfrom specific Acumatica Framework page templates.

• Plan the business logic controller (a graph) for each page, which encapsulate business processesand use-cases that should be implemented in the application.

Each of these steps is iterated for multiple times as the development is progress.

Page 131: T100 Introduction to Acumatica Framework€¦ · Functional Requirements ... • On the website of the Acumatica Framework-based application template that you will ... BQL is written

| Appendix: Application Design | 131

Database SchemaDuring the database design, you define how the main business objects will be stored in the database.

Entity-Relationship Model

Since the requirements, a sales order is the main object the application works with. Sales orders are inone-to-many relationship with order lines. Order lines are in many-to-one relationship with products.Multiple products can be associated with an order line, and the same product can be added to multipleorder lines. Each order has a reference to a customer; these objects are in one-to-many relationshipwith sales orders. The customer is a person or company who ordered the products. The resulting modelis shown in the diagram below.

Figure: The entity-relationship model of the RapidByte application

Database Schema

You have to design the database schema that stores the application data. You have to create andmaintain your own application tables in the database during the design and development of theapplication. The Acumatica Framework-based application template contains only the system tablesthat are required for the platform. You can modify your own application tables but not the AcumaticaFramework system tables, because any changes to the system tables would be lost on AcumaticaFramework upgrade.

We have already designed the database of the RapidByte application. The RapidByte application usesfive application tables: SalesOrder, OrderLine, Customer, Product, and Country (see theschema below).

Page 132: T100 Introduction to Acumatica Framework€¦ · Functional Requirements ... • On the website of the Acumatica Framework-based application template that you will ... BQL is written

| Appendix: Application Design | 132

Figure: The database schema of the RapidByte application

In each application table, we have to set the primary key and define nullable columns. Foreign keysare not necessary; it depends on the database design approach you use. We do not define foreignkeys in the database since we will use the approach according to which the database schema has onlythe primary key restrictions and all other restrictions are defined at the higher level of the applicationobject model.

The SalesOrder table uses the string OrderNbr column as the primary key. Users can manuallyinput the sales order number and then search for a sales order by this number. The correspondingOrderNbr data field is set as the key in the data access class. Non-null columns are only the absoluterequired sales order attributes, OrderNbr, OrderDate, and CustomerID.

The primary key of the OrderLine table consists of two columns, OrderNbr and ProductID. Thecorresponding data fields is set as the key fields in the data access class. The OrderNbr column linksan order detail to the master record from the SalesOrder table. This link is set up in the data accessclass. The ProductID column is included in the primary key to support multiple products on a salesorder. As for nullable columns, we consider that all columns can be null except for the primary key.

The OrderLine.ProductID value is taken from the ProductID column of the Product table.The ProductID is the identity column set as the primary key in the Product table. Unlike the table,

Page 133: T100 Introduction to Acumatica Framework€¦ · Functional Requirements ... • On the website of the Acumatica Framework-based application template that you will ... BQL is written

| Appendix: Application Design | 133

the string ProductCD value, which is the product code, set as the key in the data access class. Thedifferent database-level and model-level keys are used to provide a user-friendly key of a product inthe UI, which is the product code. Acumatica Framework keeps the ProductCD value unique for eachproduct and handle the ProductID column automatically. Users work only with ProductCD valuesthat identify products in the UI. As for nullable columns, we consider all product attributes as requiredand make all columns not-null.

The Customer table has the CustomerID as the primary key, while the key of the data access class isCustomerCD.

The Country table is a country dictionary that is referred from the Customer table. The Countrytable uses the string CountryCD column as the primary key since the list of dictionaries is rather fixedand short. In our application, the country identifier is a two-letter code from ISO 3166.

At the same time as you plan the database schema, you can design the object model of yourapplication. The object model is represented by data access classes that are mapped to the databasetables of your application.

For more information on database design, see Acumatica Framework > Design Guidelines >Database Design Conventions in the documentation.

Page 134: T100 Introduction to Acumatica Framework€¦ · Functional Requirements ... • On the website of the Acumatica Framework-based application template that you will ... BQL is written

| Appendix: Application Design | 134

Data Access ClassesPlanning and designing of database tables is performed simultaneously with designing of the applicationdata access classes (DACs). DACs encapsulate working with database tables in the application.The application class diagram (which follows this paragraph) shows the relationships between dataaccess classes of the RapidByte application. We could define these relationships as foreign keys at thedatabase level, but we use the generic database schema approach and define these restrictions only atthe object model level. In the application, you work only with classes that represent data on a higher,database-abstract level. To retrieve data you write BQL statements, which are transparently translatedinto SQL statements by the Acumatica Data Access Layer. Unique key fields for each data access classare marked on the diagram with gray. The relationships between DACs are defined declaratively inattributes on the DAC data fields.

As you can see from the diagram, the data access classes directly correspond to the database tableswe created at the previous step. A sales order may exist without any details, so the relationship isone-to-many (1 - 0..*). The relationship between the Product and OrderLine entities is also one-to-many (actually, 0 - 0..*), because an order detail cannot be saved without the specified product:OrderLine.ProductID is a required reference to a product from the Product table. In theProduct and Customer classes, the CD data field is included in the key instead of ID. The ID fieldcorresponds to the database identity column in each table; in the data access class, these identity fieldsare annotated with the PXDBIdentity attribute and not included in the key fields of the class.

Also, an additional SalesOrderFilter filter class (not shown on the diagram) is used in theapplication. Filter classes are used only for data representation and they don't used for queries to thedatabase or implementation of any business logic.

Figure: The data access class diagram of the RapidByte application

Page 135: T100 Introduction to Acumatica Framework€¦ · Functional Requirements ... • On the website of the Acumatica Framework-based application template that you will ... BQL is written

| Appendix: Application Design | 135

Application PagesIn Acumatica Framework-based applications, the user interface is provided through webpages. The userworks with webpages and doesn't need to install any specific client.

You create application pages from the specific Acumatica Framework ASP.NET templates. You can usethe visual editors provided by Acumatica Framework to add controls to ASP.NET pages and configureproperties of the controls.

The sales order printable form is not an ASP.NET page, it is an .rpx definition file. The file containsthe data definition and the page layout description for printing. The definition file is created in ReportDesigner. To create a printable form or report, you have to compose just the definition file, addthe file to the website, and then add the specific report URL to the site map. To get the printabledocument, you run the printable form from the specific report launcher page provided by AcumaticaFramework. The report launcher renders the output and generates the document for printing. Supportfor generating printable forms and reports is built-in in Acumatica Framework. You don't have to createany application pages or business logic controllers for rendering of reports and printable forms.

In Acumatica Framework, every page has a unique identifier that encodes the module, type and numberof the page. We will assign the following identifiers to the RapidByte pages, in which the first twosymbols denote the module, the second two symbols denote the page type, and the last two symbolsdenote the sequential number of the page:

• Countries—RB201000 (maintenance)

• Customers—RB202000 (20 means maintenance)

• Sales Orders—RB301000 (30 means data entry)

• Sales Order Inquiry—RB401000 (40 means inquiry)

• Approve Sales Order—RB501000 (50 means processing)

• Sales Orders Form—RB601000 (60 means reports and printable layouts)

We recommend the page identification convention for use in Acumatica Framework-based applications. Formore information about the convention, see Acumatica Framework > Design Guidelines > ApplicationDesign Guidelines in the documentation.

In Acumatica Framework-based applications, you usually create the following types of pages: dataentry, maintenance, inquiry, and processing. Data entry pages are the most often used pages in theapplication. These pages provide input of business documents, such as sales orders. Maintenance pagesare also used for data input, but more rare than the data entry pages. Maintenance pages are usedto input of helper objects mostly during configuration and less used over time. Inquiry pages provideselection of data by the specified parameters. On inquiry pages, users specify the selection criteriaand retrieve the records that match the criteria. Processing pages are dedicated to mass processingof records—for instance, provides changing of the document status for a list of selected documents atonce.

You can learn more about pages of different types in the T200 Acumatica Framework Fundamentalscourse.

The Navigation Menu and the Site Map

In the user interface, all pages are typically grouped into four tabs of the navigation pane according totheir purpose and frequency of use. The menu structure is composed in the site map that is configuredon the System > Customization > Manage > Site Map page. For the RapidByte application, wesuggest the following menu:

• Work Area tab ( ):

• Enter: Sales Orders

Page 136: T100 Introduction to Acumatica Framework€¦ · Functional Requirements ... • On the website of the Acumatica Framework-based application template that you will ... BQL is written

| Appendix: Application Design | 136

• Manage: Customers

• Explore: Sales Order Inquiry

• Processes tab ( ):

• Daily: Approve Sales Orders

• Reports tab ( ):

• Forms: Sales Orders

• Configuration tab ( ):

• Manage: Countries

For instance, the Work Area tab of the navigation pane will look as follows.

Figure: Work Area Tab

In the site map, the menu structure is configured as shown in the following screenshot.

Page 137: T100 Introduction to Acumatica Framework€¦ · Functional Requirements ... • On the website of the Acumatica Framework-based application template that you will ... BQL is written

| Appendix: Application Design | 137

Figure: The site map of the RapidByte application module menu

Page 138: T100 Introduction to Acumatica Framework€¦ · Functional Requirements ... • On the website of the Acumatica Framework-based application template that you will ... BQL is written

| Appendix: Application Design | 138

Business LogicThe business logic layer of the application is implemented in business logic controllers (graphs) ofapplication pages. For each application page, you have to create an individual graph. The graph isa class derived from PXGraph that encapsulates the logic executed on the page. In the graph, youimplement data retrieval and manipulation, validation of input values, processing operations, and UIbehaviour, such as appearance of error messages and page redirection.

In RapidByte, you will create the following graphs, each of which corresponds to the application page:

• CountryMaint—for the Countries page (RB201000)

• CustomerMaint—for the Customers page (RB202000)

• SalesOrderEntry—for the Sales Orders page (RB301000)

• SalesOrderInq—for the Sales Order Inquiry page (RB401000)

• SalesOrderProcess—for the Approve Sales Order page (RB501000)

The graph name suffix denotes the page type the graph works with. For instance, Inq denotes a graphfor an inquiry page.

For more information on graph naming conventions, see Acumatica Framework > Design Guidelines >Application Design Guidelines in the documentation. You can learn more about graphs in the T200Acumatica Framework Fundamentals course.