Friday, September 14, 2018

D365/AX7 – How to use Change Group and Optional Record Mode properties

When a record needs to be created, updated or deleted in a form data source based on the joined form data source, we can achieve this using ChangeGroupMode and OptionalRecordMode properties on form and form data source respectively.

Problem

Consider two tables TaskTable and CriticalTask, such that the CriticalTask table contains the foreign key relation with TaskTable. We need to create record in CriticalTask table if the checkbox is marked check.

Solution

Follow the steps below to create/delete a record based on joined table.

Step#1 Create tables MY_TaskTable and MY_CriticalTask with a Normal relation between two tables.


Step#2 Add the tables MY_TaskTable and MY_CriticalTask to the form.

Step#3 Set the property Data Source Change Group Mode to ImplicitInnerOuter to use a change group for the tables in the form data source.



A change group is a set of joined tables in a form data source. The change group uses UnitOfWork framework to implement database transaction, such that if create, update or delete fails for any of the tables in change group, the change is rolled back for all the tables in the group. For further information regarding Change Group Mode property, see Change Group and Optional Record Modes.


Step#4 On form data source for MY_CriticalTask, the Link Type must be set to OuterJoin to use optional record mode. Set the property Optional Record Mode to ExlicitCreate.

               

Setting the Optional Record Mode to ExpliciteCreate, we use a check box control to explicitly specify whether to create or delete the joined record. If the check box is selected, the record is always created. If the check box is cleared, the record is always deleted. For further information regarding Optional Record Mode property, see Change Group and Optional Record Modes.

Step#5 Add a checkbox on form and set the Data Source to MY_CriticalTask and Optional Record Control to Yes. This check box will work as a command to create a record in table MY_CriticalTask for the respective MY_TaskTable record.




Execution

It can be now observed on form that when the check box for Critical task is marked checked, a record is added to the MY_CriticalTask table for the selected MY_TaskTable record. Whereas, on unchecking the checkbox, the record is deleted from the MY_CriticalTask table for the selected MY_TaskTable record.

Wednesday, September 12, 2018

D365/AX7 – Adding conditional check box on SSRS report design


Problem

There are several requirements to add checkbox to the SSRS report design and mark it checked or unchecked based on some condition. Let’s look at the steps to add checkbox.

Solution

In order to show the checkbox marked check and unchecked based on some condition, follow the steps below.

Step#1 Insert a textbox or create a placeholder on report

Step#2 Set the font style of the textbox/placeholder as Wingdings

Step#3 Add below expression to the text box or the placeholder.
=IIF(Fields!IsEmployed.Value = "No", chr(254), chr(168))

Here,
Chr(254): Displays checked checkbox  รพ
Chr(168): Displays unchecked checkbox c

Thursday, August 9, 2018

D365/AX7 - Code Extensions Using Plugins - SysPluginFactory


Overview

In AX7, the code extensions provide a cleaner way to add your code without modifying the existing one. Most used ways of code extensions include Class Extensions, Delegates and Plugins. Here we are going to look into the code extensions using plugins i.e. SysPluginFactory.Apart from code segregation, plugins play a key role in breaking dependencies between models. Consider the following scenario from existing classes in AX7 for clear understanding.



Here the LedgerDimensionValidationRequest is a member of Ledger model whereas DimensionValidationRequest is a member of Dimensions model. Since LedgerDimensionValidationRequest is a derived class of DimensionValidationRequest, the Ledger model has the reference to the Dimensions model. Therefore, any class in Dimensions model cannot directly use LedgerDimensionValidationRequest to avoid cyclic dependency.
In order to break such dependency, we can use plugins. Plugins use attributes to create subclasses which can be alternatively used by the existing classes and methods in the same plugin base model.
Let’s have a look at how SysPluginFactory is used.

Implementation


Step#1: Create an interface or abstract base class decorated with the attribute ExportInterfaceAttribute.


using Microsoft.Dynamics.AX.Platform.Extensibility;

[ExportInterfaceAttribute()]
public abstract class DimensionValidationRequest implements SysPackable
{

}

Step#2: Create a class to implement the interface or to extend the class created in step1. Apply the attributes below


using System.ComponentModel.Composition;

[ExportMetadataAttribute(enumstr(LedgerDimensionType), LedgerDimensionType::Account)]
[ExportAttribute(identifierstr(Dynamics.AX.Application.DimensionValidationRequest))]
public class LedgerDimensionValidationRequest extends DimensionValidationRequest
{
}

- ExportMetadataAttribute – Parameters are key and value. The key is kept same for all the implementations or subclasses
- ExportAttribute – Parameter is the interface/parent class name

Step#3: To create instance of the class, use the code below


//Instance of the SysPluginMetadataCollection which holds the key-value pair to identify the class
SysPluginMetadataCollection metadataCollection = new SysPluginMetadataCollection();
metadataCollection.SetManagedValue(
enumstr(LedgerDimensionType),
       _ledgerDimensionType);

//Instance of the child class is created using reflection
        DimensionValidationRequest dimensionValidationRequest = SysPluginFactory::Instance(
            identifierstr(Dynamics.AX.Application),
            classstr(DimensionValidationRequest),
            metadataCollection);


Instead of using enumstr or classstr, simple string values can also be used. However, using these methods are more useful than the simple string text. Enums can be used conveniently for identifying the multiple implementations of a base class.
In this way the SysPluginFactory helps to create instance of the classes without the need for the child class reference in the base model and similarly, multiple implementations of the interface or class can be added without making changes to the base class.

Friday, July 20, 2018

D365/AX7 - Manage data access using AOS Authorization


Overview

Some of the database tables might contain some sensitive data which needs to be secured at the additional level to the security roles/privilege. The data such as employee’s personal details and salary details, financial data of the organization etc. should only be allowed to designated personnel of the organization to manage or view. In Microsoft Dynamics AX, this level of security can be imposed on the data by AOS Authorization.
AOS Authorization is a property associated with the TPF i.e. Tables Permission Framework in Dynamics AX, that adds additional level of security to the tables consisting sensitive data, and allows the administrator to manage access to such data.
When an attempt is made to access or to perform any operation on TPF-protected table, the AOS verifies if the user is authorized to perform respective action on the table. If the user does not have the appropriate permissions, the AOS does not complete the operation. These operations could be read, create, update or delete.


AOS Authorization Property

When concerned about how to enable AOS authorization on a table, following are the possible values for the AOS property on the table.
·         None
·         CreateDelete
·         UpdateDelete
·         CreateUpdateDelete
·         CreateReadUpdateDelete

The default value for AOS Authorization property on any table is None. Let’s say if the AOS authorization is set to CreateDelete on a table, then the AOS will authorize and confirm if the user has appropriate permissions for Create and Delete operations on the table. If the required permissions are lacked by the user, the application throws an exception. However, the rest of the operations, i.e. Read and Update are not checked by the AOS.

The AOS performs the authorization of TPF-protected tables by the following table methods.

·         aosValidateDelete
·         aosValidateInsert
·         aosValidateRead
·         aosValidateUpdate


Creating Security Roles for TPF-Protected Tables

Suppose if a report in Dynamics AX contains sensitive data related to an employee along with other basic information. If that sensitive data is maintained by a table which has the property AOS Authorization set to CreateReadUpdateDelete, then the report might not execute successfully by the user if at least Read permission is not granted to the user.
When creating the security privilege for the report getting data from the TPF-protected tables, we need to add the given table to security privilege and specify permissions explicitly for that table.

Thursday, July 19, 2018

D365/AX7 - Creating security privilege for AOS Authorization enabled table field



Problem

There are few table fields which are set with the property AOS Authorization. Such fields cannot be accessed even if their respective tables are granted access in the privilege permissions.






Solution

In order to allow access to the table fields which are AOS authorization enabled, these fields have to be explicitly added to the tables in the privilege permissions.






This sometimes might require database synchronization to reflect changes in the privilege. You can verify your changes from the form below
System Administration > Security > Security Configuration > Privilege > View Permissions






The records with Resource Type: Table Field are the fields which are explicitly added to the tables in the permissions of the privilege.

Thursday, May 31, 2018

D365/AX7 – Add validation before workflow approval action

This blog will provide you a solution to add validation before the user performs any approval action on the assigned workflow task


Problem

To add validation before the user performs any approval action on the workflow item.


Solution

Add custom workflow work item action manager class.

Step#1 Add a new class extending the class WorkflowWorkItemActionManager

class MY_TaskWorkflowActionManager extends WorkflowWorkItemActionManager
{

}


Step#2 Add the code below to the class

public static void main(Args _args)
{
MY_TaskWorkflowActionManager taskWorkflowActionManager = new MY_TaskWorkflowActionManager();
       
taskWorkflowActionManager.parmCaller(_args.caller());

if(_args.record() && _args.record().TableId == tableNum(MY_TaskTable))
{
if(taskWorkflowActionManager.validate())
{
       taskWorkflowActionManager.parmArgs(_args);
taskWorkflowActionManager.run();
}
       else
       {
              throw error("Task must be valid to perform the action");
       }
}
else
       {
              throw error("Invalid action requested");
}
}

public boolean validate()
{
boolean ret;

       //Add your validation here...

       return ret;

}


Step#3 Go to the action menu item of the above modified outcome and set the property Object with your custom workflow action manager class name




And that’s it. You can similarly use this action manager class for other outcomes of your workflow approval too.

D365/AX7 – How to apply workflow hierarchy type at runtime

The default workflow hierarchy providers as provided by Microsoft Dynamics AX, allow us to use managerial or configurable hierarchy as setup for the workflow. However, when comes a requirement where the hierarchy type of the workflow should be decided at run time, we need to do some customizations with workflow hierarchy providers.


Problem


To select workflow hierarchy type for each record at run time. 







Here, we need the workflow to be approved by the Task hierarchy of the workflow originator (say Aaliyah). The Task hierarchy of the worker Aaliyah is as follows.




Solution


To achieve above requirement, follow the steps below to create custom workflow hierarchy provider for any specified hierarchy type.

Step#1 In order to add a custom workflow hierarchy provider, refer the blog How to add custom workflow hierarchy assignment provider

Step#2 Add a method to get the position hierarchy type from the record the workflow is executing for.

public HcmPositionHierarchyTypeRecId getPositionHierarchyType(
WorkflowContext _workflowContext)
{
MY_TaskTable                 taskTable;

if(_workflowContext.parmTableId() == tableNum(MY_TaskTable))
{
taskTable = MY_TaskTable::find(_workflowContext.parmRecId());
}

return taskTable.PositionHierarchyType;

}

Step#3 Modify the method getNextNode as below

public WorkflowHierarchyProviderNode getNextNode(anytype _nodeId,
WorkflowHierarchyLevel _level,
WorkflowContext _workflowContext)
{
HcmPositionHierarchyTypeRecId positionHierarchyTypeRecId = this.getPositionHierarchyType(_workflowContext);
       
if (positionHierarchyTypeRecId == 0)
{
throw error("Position hierarchy not defined for the workflow");
}

return helper.getNextNode(_nodeId, _level, _workflowContext, dataSource, positionHierarchyTypeRecId);
}

Step#4 Build the relevant model.

Execution


Setup the workflow using task workflow hierarchy provider.


According to the task hierarchy of the worker Aaliya (workflow originator), and the workflow design as above, the task will be first assigned to Adam and then to Julia for approval. 


D365/AX7 – How to add hierarchy token using custom workflow hierarchy provider

Workflow hierarchy assignment usually provides limited options to select the start of the given hierarchy. Most common options to select for the start of hierarchy are Workflow owner, Workflow originator, Personnel number, User etc. E.g. the workflow is assigned to the managerial hierarchy of the workflow originator.


Problem

To add hierarchy token using custom workflow hierarchy provider, so that we have option to select the start of hierarchy other than those already provided by the default provider.


Solution

To achieve above requirement, follow the steps below to create custom workflow hierarchy provider and add the token using it.

Step#1 In order to add a custom workflow hierarchy provider, refer the blog How to add custom workflow hierarchy assignment provider

Step#2 Add new EDT which extends HcmWorkerRecId


Step#3 Assign the EDT to the table field, which you want to be the starting point for workflow managerial hierarchy.



Step#4 Implement the method getSupportedType of custom workflow hierarchy provider class to add your data type i.e. MY_SupervisorWorkerRecId

public Set getSupportedDataType()
{
Set supportedDataTypes = helper.getSupportedDataType();

if(!supportedDataTypes)
{
supportedDataTypes = new Set(Types::String);
}

//Add the required data types
supportedDataTypes.add(extendedTypeStr(MY_SupervisorWorkerRecId));
return supportedDataTypes;

}

Step#5 Implement the method convertToNodeDataType of custom workflow hierarchy provider class to fetch the worker’s personnel number using the field value from the record (workflow document).

public anytype convertToNodeDataType(extendedDataTypeName _dataType,
anytype _value,
       WorkflowContext _workflowContext)
{
HcmPersonnelNumberId personnelNumberId;

if(_dataType == extendedTypeStr(MY_SupervisorWorkerRecId))
{
personnelNumberId = HcmWorker::find(_value).PersonnelNumber;
}
else
{
personnelNumberId = helper.convertToNodeDataType(_dataType, _value, _workflowContext);
}
return personnelNumberId;

}

Step#6 Build the relevant model.

Execution

Setup workflow using custom hierarchy token for supervisor


A task to submit workflow by Admin. We need the workflow approval from line manager of the supervisor here i.e. Aaliyah.




Workflow is assigned to the line manager of Aaliya i.e. Adam Carter, as specified in the workflow designer