When implementing DynaRent, To-Increase’s equipment rental solution suite, we’ve seen that customizations are required in most cases to meet customer requirements. This means besides creating a set of new functions and minor adjustments, it might also be that the dimensions a customer is already using are different from those that come out of the box with DynaRent.
Also, we’ve had some customers come to us with a requirement to implement dimensions on another table where it is not yet implemented. Since DynaRent made an extension on the standard AX dimensions, it will be a challenge to make full use of this extended dimensions framework.
This blog will guide your developers through the steps that will enable them to utilize the DynaRent Dimensions Framework completely for your customization.
The steps
Step 1. Object adjustments
You will need to make some adjustments, such as changes in tables, forms, and classes, and the next sections will guide you through each of them.
Table adjustments
As a first step, you need to identify the table that requires the dimensions, and then do the following:
- Make sure that the field DefaultDimension is available on the table (either with or without a prefix).
If it is not, then create a new field of type Int64 and:- Set the ExtendedDataType property to DimensionDefault.
- Create a relation to the DimensionAttributeValueSet and set the relation between the new dimension field and
the RecId field of the DimensionAttributeValueSet table. - Next, the main form for the table needs to be adjusted, and if the form does not have a financial dimensions
tab, then you need to create it as follows:- Add a new tab to the form and name it FinancialDimensions (prefix it if required) and set the Caption
to @SYS101181. - Apply the “Dimension Entry Control” pattern.
- Now a new element of type “Dimension entry” needs to be added with the following properties:
- Auto Declaration: Yes
- Controller class: LedgerDefaultDimensionEntryController
- Caption Test: @SYS138487
- Data Source: <table on which you have added the DefaultDimension field>
- Value Data Field: <the actual dimension field on the data source>
- Add a new tab to the form and name it FinancialDimensions (prefix it if required) and set the Caption
- The final adjustment on the form (when it exists in the current model) or on the extension class
(when the form’s origin is in another model) is to add the following piece of code to the init method after the
super() call: FINDimValueController::setEditableDimensionSet (tableNum(<Table name>), <Dimension entry control
name>).
Step 2. Class adjustments
Now that the table and form are adjusted, you’ll also need to create some code adjustments. First of all, it is good to mention there are a couple of classes that act as the core of the DynaRent Dimensions Framework, and these are DNREventGeneric, FINDimValueController, and FINDimValueResult.
- DNREventGeneric is a DynaRent class, meaning that if it needs to be customized, it must be done through extension. So, firstly, you need to create a new EventHandler class and events to this class.
- FINDimValueController is also a DynaRent class and needs to be extended specifically for the table for which you want to enable the dimensions framework.
- FINDimValueResult: Since a dimension value can be either a simple alphanumeric value or a reference to another value, this class is introduced. Instances of this class are passed around rather than the actual values or record and table references. This is also a DynaRent class, and it does not need to be extended.
- DNRCrossCompanySynchronizer is a DynaRent class that manages the synchronization between companies and is consumed by the DNREventGeneric class.
DNREventGeneric
Let’s start with the first one, DNREventGeneric. Since this is a DynaRent class, it cannot be adjusted, and therefore an EventHandler class needs to be created. If you would make a class that acts as an extension of (using the ExtensionOf attribute), then it would violate a best-practice check. Once this EventHandler class is created (using the customer’s suggested naming convention), you should create a couple of data event handler methods, and here are a few essential ones:
- Inserted/Inserting
- Updated/Updating
- Deleted/Deleting
Which event handler to use is decided based on whether the dimensions should be determined during or after the record modification. When it needs to happen while the record is modified, then you should use the event handler ending with “ing,” and if it is after the record modification, then the event handler ending with “ed” should be used.
Depending on the action, one of the following static methods on the FINDIMValueController class need to be called:
- eventInsert
- eventUpdate
- eventDelete
These methods require only one parameter of type Common which is the current record of the table for which the dimensions are implemented. Below a screenshot of the methods mentioned for the PurchReqLine table.
When it needs to be synchronized across companies, then the doSync method (also static) on the DNRCrossCompanySynchronizer needs to be called.
The doSync method requires the following 2 parameters:
(a) The current record and a DataEventType to specify whether the record is inserted, updated, or deleted. When, for example, the Inserted data event handler is being used, then the method calling the doSync should look like the screenshot below.
(b) Then there is also the static ValidatedWrite event handler to validate the values. This is not required, but it is good practice to have this event handler for your table as well. This method also requires only the table buffer as a parameter.
FINDimValueController
The next class is FINDimValueController. When implementing the dimensions for a new table, this class needs to be extended like so: <customer specific prefix>_FINDimValueController_<table name>.
It needs to have at least the following 3 methods:
- getDescription: to return a descriptive value of the record
- getDimensionFieldId: to return the field number of the dimension field on the consumed table
- new: this method has one parameter which is the record that is currently being processed and stores it in a global variable
Below is a screenshot of the implementation on a table called EBCTransactionType:
There are two more types of methods that can be implemented to retrieve the correct values used in the dimension field:
- ref* methods: With this type of method, a dimension reference is copied from one record to the current method. For example, the location from the InventTable to the SalesLine
- find* methods: This type of method is used to copy the value and place it in one of the dimension attributes. For example, the ItemId of the InventTable on the SalesLine’s ItemId dimension (if available).
Besides this table-specific class, two new classes also need to be created, so the new table that supports dimensions is processed correctly. They are:
- An extension class of the FINDimValueController class which has the [ExtensionOf(classStr(FINDimValueController))] attribute. This new extension class requires the getDimensionableTableIds method to be implemented. By using CoC, a set of tables can be retrieved by the next call, and the newly supported table(s) can then be added to this set, like the screenshot below:
- An event handler class for the FINDimValueController class. In this class, a new event handler method needs to be created for the contructDelegate method. An example can be found in the screenshot below
DNRCrossCompanySynchronizer
Finally, the DNRCrossCompanySynchronizer class needs to be extended because intercompany synchronization needs to be applied, followed by adding at least the following two methods to the extension class:
- getFieldIds2Sync: In this method, all fields that need to be synchronized across companies are added to a set.
Here’s an example of the InventSite table:
- getFieldIds2Identify: In this method, the fields to identify the record are added to a set, Here’s an example of the InventSite table
Furthermore, it is also possible to add an eventDeleted and eventInserted method to create logic specifically created for the currently consumed record.
The setup
Once all code and objects are created and adjusted, it is time to complete the setup. Assuming the correct dimensions are already available, it is just a matter of pointing the correct methods to the dimension field on the correct table. Below are two examples of dimensions that can be setup on the SalesLine table.
The first example has a Reference method filled with a ref method (refEBCLot), meaning that it will create a reference to the dimension found in the refEBCLot method. The second example used a find method to retrieve a certain value to store as dimension value.
If you’ve added the dimension field to a new table and made all of the adjustments in code and objects, then it is possible to add this new table to the setup as well. This is how this is done:
- Create a new record in the Dimension attribute setup
- In the Reference table name field, select the new table
- In Financial dimension, field select the dimension that needs to be filled
- Use the Reference field or Reference method field to select how the value for the dimension needs to be retrieved
- Then there are 3 fields which are also good to mention:
- Autocreate: when this is set to Yes and there is not a value found in the Custom list financial dimension (DimensionFinancialTag) then a record will be created in that table
- Allow edit: if set to Yes then the user is allowed to adjust the dimension value
- Force value: if set to Yes then a value will be stored for the dimension instead of reference