Altering BLC Virtual Methods

In a BLC extension, you can override virtual methods defined within a business logic controller (BLC, also referred to as graph). As with the event handlers, you have two options:

  • You can define the override method with exactly the same signature—that is, the return value, the name of the method, and all method parameters—as the overridden base virtual method. As a result, the method is added to the queue of all override methods. When the system invokes the base method, all methods in the queue are executed sequentially, from the first to the last one. The lower the level the BLC extension has, the earlier the system invokes the override method.
  • You can define the override method with an additional parameter, which represents the delegate for one of the following:
    • The override method with an additional parameter from the extension of the previous level, if such a method exists.
    • The base virtual method, if no override methods with additional parameters declared within lower-level extensions exist.

In both cases, you should attach the PXOverrideAttribute to the override method declared within the BLC extension. See the topics below for details.

Override Method That is Added to the Override Method Queue

By declaring an override method with exactly the same signature as the overridden base virtual method, you extend the base method execution. The base BLC method is replaced at run time with the queue of methods that starts with the base BLC method. When the system invokes the base method, all methods in the queue are executed sequentially, from the first to the last one. The lower the level the BLC extension has, the earlier the system invokes the override method. If the system has invoked the base method, you have no option to prevent the override method queue from execution. To prevent the base method executions, see Override Method That Replaces the Original Method below.

Suppose that you need to modify the behavior of the Journal Transactions (GL301000) form.

Open the form and explore its original behavior. Start by adding a new journal entry, selecting an account, and setting the Debit Amount to 2000.00. Then add one more journal entry and select a different account. Notice that the Credit Amount is set by default to 2000.00 to balance the batch, as the following screenshot illustrates.

Figure 1. The Credit Amount set to balance the batch


Suppose that you need this form to work differently, so that if the user first enters a debit entry, by default, the Credit Amount value is 0.00, and the user must add the required value manually. If the user first enters a credit entry, the Debit Amount value should also be 0.00 by default, so that the user must enter the needed value. You can implement this behavior in the PopulateSubDescr method that you have to override in a BLC extension for the JournalEntry class.

To select the business logic controller for customization, on the Customization menu, select Inspect Element and click any element on the form, for example, the form area. The system should retrieve the following information that appears in the Element Properties dialog box:

  • Business Logic: JournalEntry. The business logic controller that provides the logic for the Journal Transactions form.

Select Actions > Customize Business Logic in the Element Inspector. In the Select Customization Project dialog box, specify the project to which you want to add the customization item for the business logic controller of the form and click OK.

The Code Editor opens for customization of the business logic code of the form (see the screenshot below). The system generates the BLC extension class in which you can develop the customization code. (See Graph Extensions for details.)

Figure 2. The BLC extension class generated for customization of the business logic code executed for the Journal Transactions form


To the BLC extension class for JournalEntry, add the code that is listed below.

[PXOverride]
public void PopulateSubDescr(PXCache sender, GLTran row, bool externalCall)
{
    decimal difference = (Base.BatchModule.Current.CuryCreditTotal ?? decimal.Zero)  
        (Base.BatchModule.Current.CuryDebitTotal ?? decimal.Zero);
    if (difference != 0)
    {
        if (row.CuryCreditAmt == Math.Abs(difference))
        {
            row.CuryCreditAmt = 0;
        }
        else if (row.CuryDebitAmt == Math.Abs(difference))
        {
            row.CuryDebitAmt = 0;
        }
    }
}

In the code, you override the PopulateSubDescr method of the original BLC by adding the new method to the queue of override methods to be executed. The system invokes the base method first, and then executes the override method. The override method resets the value of the Credit Amount or the Debit Amount to 0.00.

Click Save in Code Editor to save the changes.

Figure 3. The override method implemented in the BLC extension class


To view the result of the customization, publish the customization project and open the Journal Transactions (GL301000) form.

Test the modified behavior of Journal Transactions. Add a new journal transaction, select an account, and set the Debit Amount to 2000.00. Then add one more journal transaction and select a different account, and notice that the Credit Amount is set by default to 0.00. You must manually specify the amount for every journal entry to make the batch balanced. Otherwise, you will not be able to save the batch with the Balanced status, and you will see the appropriate error message on the Debit Total box.

Note: You should also test the case when the user first adds a transaction with a Credit Amount: Then the Debit Amount must equal 0.00 by default.
Figure 4. Viewing the result of the customization


Override Method That Replaces the Original Method

The override method with an additional parameter replaces the base BLC virtual method. When the virtual method is invoked, the system invokes the override method with an additional parameter of the highest-level BLC extension. The system passes a link to the override method with an additional parameter from the extension of the previous level, if such a method exists, or to the base virtual method.

You use a delegate as an additional parameter to encapsulate the method with exactly the same signature as the base virtual method. If the base virtual method contains a params parameter, then you should not use the params keyword when you declare the override method with an addition parameter. For example, to declare an ExecuteInsert override method with an additional parameter within a BLC extension, you can use the following code.
public class BaseBLCExt : PXGraphExtension<BaseBLC>
{
    [PXOverride]
    public int ExecuteInsert(string viewName, IDictionary values, object[] parameters,
                             Func<int, string, IDictionary, object[]> del)
    {
        if (del != null)
        {
            del(viewName, values, parameters)
        }
    }
}

You can decide whether to call the method pointed to by the delegate. By invoking the base method, you also start the override method queue execution.

Suppose that you need to modify the logic of generating batches on release of Accounts Receivable documents.

For example, open the Invoices and Memos (AR301000) form and explore its original behavior. Create and save an invoice. On the More menu (under Processing), click Remove Hold and then Release. Notice that a new GL batch has been generated by the system while the system releases the invoice. You can see the batch number on the Financial Details tab of the Invoices and Memos form, as the following screenshot shows.

Figure 5. The batch has been generated during release of the Accounts Receivable invoice


Suppose that you need to prevent generation of batches during release of Accounts Receivable documents. You can implement the new behavior in the Persist method that you have to override in a BLC extension for the JournalEntry class. In the override method, you need to handle execution of the Persist method of the original BLC. Therefore, you have to implement the override method with an additional parameter, as described below.

To the BLC extension class for JournalEntry, add the code that is listed below. For example, you can add the override method to the JournalEntry_Extension BLC extension class generated by the system, as described above in Override Method That is Added to the Override Method Queue.

[PXOverride]
public void Persist(Action del)
{
    if (Base.BatchModule.Current != null &&
        Base.BatchModule.Cache.GetStatus(Base.BatchModule.Current) == PXEntryStatus.Inserted &&
        Base.BatchModule.Current.Module == "AR")
        return;
    if (del != null) 
        del();
}

The code modifies the logic so that the system will not invoke the base virtual method if the batch is being generated from accounts receivable; otherwise, the system executes the base business logic.

To view the result of the customization, publish the customization project and open the Invoices and Memos form.

To test the modified behavior of the Invoices and Memos form, add and save a new invoice, and on the More menu (under Processing), click Remove Hold and then Release. Notice that no new GL batch is generated by the system while it releases the invoice. Open the Financial Details tab. No batch number is displayed, as the following screenshot illustrates.

Figure 6. No batch has been generated by the system for the accounts receivable invoice