Skip to main content
Lesson 4

Creating an Acumatica ERP Entity

Back to T190: QuickStartInCustomization

Lesson 4: Creating an Acumatica ERP Entity

Corresponding to a Custom Entity

For a repair work order to be billed and then paid, a user needs to create an invoice for the order. In this lesson, for the Repair Work Orders (RS301000) form, you will implement the CreateInvoice action, which initiates the creation of an invoice. You will also create the associated Create Invoice button on the form toolbar and the equivalent command on the More menu (under Other). Creating an invoice might be a time-consuming operation, so it needs to be performed asynchronously. To perform asynchronous operations, Acumatica Framework provides the PXLongOperation class, which you will learn how to use in this lesson.

Lesson Objectives

In this lesson, you will learn how to implement an asynchronous operation by using the PXLongOperation class.

Step 4.1: Performing Preliminary Steps

In the Smart Fix company, there are no shipments or sales orders associated with repair work orders. Therefore, you need to configure Acumatica ERP so that during the creation of an SO invoice on the Invoices (SO303000) form, stock items can be added directly to the SO invoice without sales orders and shipments being processed. Aer you perform the customization tasks, you will be testing your changes, including the Create Invoice button or command (which corresponds to the CreateInvoice action that you will create) of the Repair Work Orders (RS301000) form. If you click the button multiple times during testing, you may run into an issue with insufficient stock items in a warehouse. When an SO invoice is released, the quantity of stock items included in the invoice is checked, and if there are not enough stock items in a warehouse, an invoice cannot be created. You need to prevent this issue from occurring.

Step 1: Turning on the Feature To turn on the feature, on the Enable/Disable Features (CS100000) form, do the following:

  1. On the form toolbar, click Modify.
  2. Select the Advanced SO Invoices check box.
  3. Click Enable on the form toolbar.

Step 2: Allowing Negative Quantities for Stock Items To allow negative quantities for stock items, do the following:

  1. On the Item Classes (IN201000) form, in the Item Class Tree, select STOCKITEM. All the stock items used in the activities of this training course belong to this class.
  2. On the General tab (General Settings section), select the Allow Negative Quantity check box, as shown in the following screenshot. Lesson 4: Creating an Acumatica ERP Entity Corresponding to a Custom Entity | 42
       Figure: Item Classes form
    
  3. On the form toolbar, click Save.

Step 4.2: Defining the Logic of Creating an SO Invoice and the Graph Action

You should define the method in which an invoice is created, and then you can call this method in the PXLongOperation.StartOperation method. You will use multiple graphs in the method that creates an invoice. To save all changes from multiple graphs to the database, you will use a single PXTransactionScope object. It gives you the ability to avoid incomplete data being saved to the database if an error occurs in the middle of the method.

         In Acumatica ERP, there are two types of invoices that can be created for a customer: SO and AR. An
         SO invoice, which can include stock items, is an extension of an AR invoice, which cannot include
         stock items. Repair work orders usually have stock items; therefore, you will implement the creation
         of an SO invoice. However, regardless of your implementation, if an order does not include stock
         items, the system will create an AR invoice, and if an order includes stock items, the system will create
         an SO invoice.

To define the method in which the SO invoice is created and the respective action, do the following:

  1. Add the following using directives to the RSSVWorkOrderEntry.cs file (if they have not been added yet).
        using System.Collections.Generic;
        using PX.Objects.SO;
        using PX.Objects.AR;
    
    
                  Instead of adding the using directives manually, you can add them with the help of the
                  Quick Actions and Refactorings feature of Visual Studio aer you define the method in the next
                  instruction.
    
  2. Add the following static method, CreateInvoice, to the RSSVWorkOrderEntry graph. The CreateInvoice method creates the SO invoice for the current work order. Lesson 4: Creating an Acumatica ERP Entity Corresponding to a Custom Entity | 43
       private static void CreateInvoice(RSSVWorkOrder workOrder)
       {
           using (var ts = new PXTransactionScope())
           {
               // Create an instance of the SOInvoiceEntry graph.
               var invoiceEntry = PXGraph.CreateInstance<SOInvoiceEntry>();
               // Initialize the summary of the invoice.
               var doc = new ARInvoice()
               {
                   DocType = ARDocType.Invoice
               };
               doc = invoiceEntry.Document.Insert(doc);
               doc.CustomerID = workOrder.CustomerID;
               invoiceEntry.Document.Update(doc);
    
                 // Create an instance of the RSSVWorkOrderEntry graph.
                 var workOrderEntry =
                     PXGraph.CreateInstance<RSSVWorkOrderEntry>();
                 workOrderEntry.WorkOrders.Current = workOrder;
    
                 // Add the lines associated with the repair items
                 // (from the Repair Items tab).
                 foreach (RSSVWorkOrderItem line in
                     workOrderEntry.RepairItems.Select())
                 {
                     var repairTran = invoiceEntry.Transactions.Insert();
                     repairTran.InventoryID = line.InventoryID;
                     repairTran.Qty = 1;
                     repairTran.CuryUnitPrice = line.BasePrice;
                     invoiceEntry.Transactions.Update(repairTran);
                 }
                 // Add the lines associated with labor (from the Labor tab).
                 foreach (RSSVWorkOrderLabor line in
                     workOrderEntry.Labor.Select())
                 {
                     var laborTran = invoiceEntry.Transactions.Insert();
                     laborTran.InventoryID = line.InventoryID;
                     laborTran.Qty = line.Quantity;
                     laborTran.CuryUnitPrice = line.DefaultPrice;
                     laborTran.CuryExtPrice = line.ExtPrice;
                     invoiceEntry.Transactions.Update(laborTran);
                 }
    
                 // Save the invoice to the database.
                 invoiceEntry.Actions.PressSave();
    
                 // Assign the generated invoice number and save the changes.
                 workOrder.InvoiceNbr = invoiceEntry.Document.Current.RefNbr;
                 workOrderEntry.WorkOrders.Update(workOrder);
                 workOrderEntry.Actions.PressSave();
    
                 ts.Complete();
            }
       }
    

In the method above, you have done the following: Lesson 4: Creating an Acumatica ERP Entity Corresponding to a Custom Entity | 44

a. You have created an instance of the SOInvoiceEntry graph. This graph works with SO invoices.

             To instantiate graphs from code, use the PXGraph.CreateInstance<T>() method.
             Do not use the graph constructor new T(), because in this case, no extensions or
             overrides of the graph are initialized.

 You have initialized the summary of the invoice by using the ARInvoice class. You have assigned a
 value to the CustomerID field, which is required to create an invoice. Aer that you have updated the
 ARInvoice instance in cache.

b. You have created an instance of the RSSVWorkOrderEntry graph, which you need to get access to the current work order and to save the generated invoice number to the current work order. c. You have selected the repair and labor items specified on the Repair Work Orders form by using the instance of the RSSVWorkOrderEntry graph. Then you have added lines to the invoice by adding instances of the ARTran class: the lines associated with repair items, followed by the lines associated with labor items. d. To save the created invoice in the database, you have called the PressSave() method of the SOInvoiceEntry graph. e. You have saved the number of the generated invoice to the work order and updated its value in the cache. Then you have saved the changes to the database by invoking the Actions.PressSave() method. f. At the end of the method, you have completed the transaction. 3. In the RSSVWorkOrderEntry graph, define the CreateInvoiceAction action, which adds the Create Invoice command to the More menu (under Other), adds the button with the same name on the form toolbar, and invokes the PXLongOperation.StartOperation method, as shown in the following code.

        To perform a background operation, an action method needs to have a parameter of the
        PXAdapter type and return IEnumerable.


         public PXAction<RSSVWorkOrder> CreateInvoiceAction = null!;
         [PXButton]
         [PXUIField(DisplayName = "Create Invoice", Enabled = true)]
         protected virtual IEnumerable createInvoiceAction(PXAdapter adapter)
         {
             // Populate a local list variable.
             List<RSSVWorkOrder> list = new List<RSSVWorkOrder>();
             foreach (RSSVWorkOrder order in adapter.Get<RSSVWorkOrder>())
             {
                 list.Add(order);
             }

              // Trigger the Save action to save changes in the database.
              Actions.PressSave();

              var workOrder = WorkOrders.Current;
              PXLongOperation.StartOperation(this, delegate () {
                  CreateInvoice(workOrder);
              });

              // Return the local list variable.
              return list;
         }

Lesson 4: Creating an Acumatica ERP Entity Corresponding to a Custom Entity | 45

      You have used the PXButton attribute to set up a button on the form. You have specified the button name
      in the PXUIField attribute.
      In the createInvoiceAction method, you have composes a list of work orders by using the
      adapter.Get method, and invoked the Actions.PressSave action. Because the return of the
      adapter.Get method does not include data that has not been saved on the form, by calling the
      PressSave method, you have updated the workOrders in the composed list.
      Then you have used the PXLongOperation.StartOperation() method to create an invoice. Within
      the method that you pass to StartOperation(), you have invoked the CreateInvoice method,
      which creates the invoice for the current work order.

                 Inside the delegate method of the StartOperation method, you cannot use members of
                 the current graph.

      Finally, you have returned the list of work orders.

Step 4.3: Testing the Creation of an Invoice

To test the Create Invoice button and the corresponding action, do the following:

  1. In Acumatica ERP, open the Repair Work Orders (RS301000) form.
  2. Open the 000001 repair work order. To change the status of the order to Completed, do the following: a. On the form toolbar, click Remove Hold. The status of the work order is changed to Ready for Assignment. b. On the form toolbar, click Assign. The status of the work order is changed to Assigned. c. On the form toolbar, click Complete.
  3. On the form toolbar, click Create Invoice. A notification appears indicating processing, as shown in the following screenshot. Lesson 4: Creating an Acumatica ERP Entity Corresponding to a Custom Entity | 46
     Figure: Creation of an SO invoice
    
     When the process is complete, the number of the created invoice is displayed in the Invoice Nbr. box, as
     shown in the following screenshot.
    
    
     Figure: Update of the Invoice Nbr box
    

Lesson Summary

In this lesson, you have learned how to initiate an asynchronous operation inside an action method by using the PXLongOperation class. Also, you have implemented the creation of an SO invoice based on a repair work order by doing the following in the RSSVWorkOrderEntry graph:

  • Defining the static CreateInvoice method, which creates an instance of the SOInvoiceEntry graph Lesson 4: Creating an Acumatica ERP Entity Corresponding to a Custom Entity | 47
  • Defining the Create Invoice button on the form toolbar and the command with the same name on the More menu; the underlying action initiates the asynchronous execution of the CreateInvoice method by using the PXLongOperation class The following diagram shows the changes that you have made in this lesson.

Additional Information: Actions

In this lesson, you have learned how to implement an action that creates an Acumatica ERP entity (an SO invoice) that corresponds to a custom entity (a repair work order). The implementation of other kinds of actions is outside of the scope of this course but may be useful to some readers. You can find information about how to implement other kinds of actions, along with examples, in the following training courses:

  • T230 Actions
  • Activity 1.1: To Define an Action for a Form
  • Activity 2.1: To Define an Action for a Table
  • Activity 3.1: To Implement an Asynchronous Operation
  • T240 Processing Forms
  • Activity 1.1.1: To Create a Simple Processing Form
  • Activity 2.2.3: To Modify the Processing Form to Use the Field Updated by PXAccumulator
  • Activity 3.1.1: To Add Redirection to a Report at the End of Processing Lesson 5: Deriving the Value of a Custom Field from Another Entity | 48