Wednesday, October 29, 2014

Fetching Financial Dimension Value X++

This post shows the code for extracting Financial Dimension value by providing dimension name for each dimension combination which is created and persisted. 

The DimensionAttributeValueCombination table contains information about accounts and various dimensions combinations that are used. However, they are stored as a combination ex: (100010-AX-00001- – – -). These values are retrieved through DimensionAttributeValueSetStorage storage class. This class can be used to manipulate these combinations.

The job below helps you in finding out the required values. 


static void AI_GetProjectCostCenterValue(Args _args)
{
    ProjTable                           projTable;
    DimensionAttributeValueSetStorage   dimStorage;
    str                                 dimValue;
       
    projTable = projTable::find('000409');
    dimStorage = DimensionAttributeValueSetStorage::find
                 projTable.DefaultDimension);
    
    info(strFmt('Project 000409, Cost Center value : %1',                        dimStorage.getDisplayValueByDimensionAttribute(                      DimensionAttribute::findByName('CostCenter').RecId)));
    
}

Output

Project 
In order to fetch Value and Description use the following query

      DimensionAttributeValueSet      dimensionAttributeValueSet;
    DimensionAttributeValueSetItem  dimensionAttributeValueSetItem;
    DimensionAttributeValue         dimensionAttributeValue;
    DimensionAttribute              dimensionAttribute;
    DimensionFinancialTag           dimensionFinancialTag;
    ProjTable                       projTable;

    while select RecId from projTable
        join RecId from dimensionAttributeValueSet
            where dimensionAttributeValueSet.RecId == projTable.DefaultDimension
               && projTable.ProjId == this.ProjId
        join RecId from dimensionAttributeValueSetItem
            where dimensionAttributeValueSetItem.DimensionAttributeValueSet == dimensionAttributeValueSet.RecId
        join RecId from dimensionAttributeValue
            where dimensionAttributeValue.RecId == dimensionAttributeValueSetItem.DimensionAttributeValue
        join RecId from dimensionAttribute
            where dimensionAttributeValue.DimensionAttribute == dimensionAttribute.RecId
//&& dimensionAttribute.Name == 'A_Managing_Group' //Un Comment to get specific value of Financial Dimension
        join Description from dimensionFinancialTag
            where dimensionFinancialTag.RecId == dimensionAttributeValue.EntityInstance
{
    info(strfmt('%1', dimensionFinancialTag.Description));
}

Monday, October 27, 2014

Expanding favorites node on startup

My Favorites node is collapsed while AX environment workspace is created, which is the out of box functionality. However, with small code hookup you can make the My Favorites node as expanded when workspace window is created.

In order to apply the tweak follow the following steps.

Step 1

Add the following code line in Info -> workspaceWindowCreated function after super call.

if (infolog.navPane())
{
    infolog.navPane().expandFavoriteNode('My favorites');
}


Step 2

Compile the class and Generate Incremental IL

Step 3


Now open a new workspace.

After

Before

Executing a Job through X++

There is a possibility of calling a job from X++, but using a job instead of a class has only disadvantages (e.g. jobs aren't able to run on server side). Don't use jobs in any production code.

In general, you have two possibilities - to create a menu item and call it:

Option 1

//you can change the type of called object without changing the invocation code
MenuFunction::runClient(menuItemActionStr(YourMenuItem), MenuItemType::Action);

Option 2

Run an application object via TreeNode:

#AOT

TreeNode::findNode(strFmt(#JobPath, identifierStr(YourJob))).AOTrun();

Scheduling a simple logic in Batch

This post shows the steps for executing a simple class in Batch processor.

Step 1 

Create a simple class which extends from "RunBaseBatch" class with following methods.

class Batch4DemoClass extends RunBaseBatch
{
}

public container pack()
{
    return conNull();
}

public void run()
{
    // The purpose of your job.
        info(strFmt("Hello from Batch4DemoClass .executed at %1"
            ,DateTimeUtil ::toStr(
                DateTimeUtil ::utcNow())
            ));
}

public boolean unpack(container packedClass)
{
    return true;
}

Step 2 

Now create a simple job to add the class execution in Batch processor.

BatchHeader     batchHeader;
BatchInfo       batchInfo;
RunBaseBatch    runbasebatchTask;
str             sParmCaption = "My Demonstration (b351)";
    
//Creating Batch4DemoClass object
runbasebatchTask = new Batch4DemoClass();
    
//Assigning BatchInfo from RunBaseBatch task
batchInfo = runbasebatchTask.batchInfo();
batchInfo.parmCaption(sParmCaption);
batchInfo.parmGroupId(""); // The "Empty batch group".
    
//Creating BatchHeader and adding it to BatchQueue
batchHeader = BatchHeader::construct();
batchHeader.addTask(runbasebatchTask);
batchHeader.save();


info(strFmt("'%1' batch has been scheduled.", sParmCaption));





Read-only DocuRef form for Auditors

The most common problem encounters while auditing period in companies is not to allow auditors to attach or delete attachments from DocuRef form. However, there is no out of the box role in AX, but it can be achieved with small customizations and by applying the modified duplicated copy of system role and privilege.

Step 1


Make duplicate copy of “SystemUser” role and “DocumentHandlingEssentials” privilege. In my case, I have duplicated with the name “MySystemUser” and MyDocumentHandlingEssentials”.

Step 2

In “MyDocumentHandlingEssentials” remove all entry points accept “DocuView”.

Step 3

Now assign “MyDocumentHandlingEssentials” privilege to “MySystemUser” role and make sure “DocumentHandlingEssentials” is not overriding it.

Step 4

Now go to “DocuView” form and change the “NeedPermission” property for both “New” and “Delete” command buttons to “Delete”.



You are done with the changes, now assign this customized “MySystemUser” to Auditor user and remove the default “SystemUser” role.



Note: In some AX builds you may find a privilege with name “ClientEssentials”, it too contains all “DocuRef” entry points, so if you find one in your build, apply the same process of duplicating and removal of all “DocuRef” related entry points from it.

Friday, October 24, 2014

Fetching file name from the file path using X++

AX has a standard method in the Global Class to split the file name from the entire file path.The method is fileNameSplit().The method takes filepath as the parameter.It splits the filepath into three different strings filepath, filename and fileextension respectively.The usage of the function can be seen below.


    str    filepath; 
    str    filename; 
    str    fileType; 
    str    fileNameString;

    filepath = @'C:\Users\imran\AppData\Local\Text Document.txt';
    
    info(strFmt('File path  : %1', filepath));
    [filepath, filename, fileType] = fileNameSplit(filepath); 
    
    fileNameString= filename + fileType; 
    
    info(strFmt('File name : %1', filename));
    info(strFmt('File name with extension : %1', fileNameString));

Results: