Financial Dimensions - Deep Dive

April 2 · 2015 Dimensions are ways to tag each financial transaction so that you later can track and group them in a meaningful way. In this article we will dig deeper into what it is and how we can use them...

Dimensions are ways to tag each financial transaction so that you later can track and group them in a meaningful way. In this article we will dig deeper into what it is and how we can use them.

Business perspective

In the end every financial activity becomes a voucher transaction: every sales, production, invoice and salary. Voucher

From a legal perspective we keep track of all voucher transactions with main accounts (listed in the chart of accounts). But this is not enough, dimensions are needed to tag every transaction, so that we later can say that Department X have spent Y and earned Z.

In AX 2012, Main Account is one dimension and we can have unlimited dimensions. Common ones are Business unit and Department, but you can choose Customer or your own implemented dimension.

The dimensions used for each legal entity can be different and can be configured in Ledger setup (General ledger > Setup > Ledger) and Account Structures (General ledger > Setup > Chart of accounts > Configure account structures).

Technical terms

Ledger dimension vs. default dimension

There are many ways to store dimension attribute values. The most common ways are ledger dimensions and default dimensions. This is used for instance in General journal (General ledger > Journals > General journal). The table below will explain it more detailed. Because the label, field names and EDT are not consistant (for its reasons), it is important that you get this right from the beginning, before we continue to elaborate all related concepts.

Terms Ledger dimension Default dimension
Example
Label in forms Account or Ledger Account Financial Dimension
Field name LedgerDimension DefaultDimension
EDT DimensionDynamicAccount, LedgerDimensionAccount DimensionDefault
Referenced table DimensionAttributeValueCombination DimensionAttributeValueSet
Comments Ledger dimension is an ordered list of dimension attribute values. Default dimensions unordered set of dimension attribute values. In the scenario of general journal lines, default dimensions are inherited from customers, vendors, journals and so on, all the way to the journal lines, but only if the account type is not Ledger. If the account type is ledger then only ledger dimension is enough.

Both ledger account and financial dimensions are stored as RecIds referencing to the tables listed above (Referenced table). The string in ledger dimension is a form control that gets the value from DimensionAttributeValueCombination.DisplayValue.

It is important to understand how the dimensions are used and what the differences are. In the final posted voucher only ledger dimension is used. But in the journal lines, default dimensions might be used. If the account type is Ledger then only ledger dimension will be used. But in all other cases Customer, Vendor, Fixed assets, Project and Bank - the default dimension will be used. The default dimensions will be combined with the main account into a ledger dimension. The strength with this is that the default dimensions can be set in the customer level and journal level and inherited to the journal lines.

Important patterns used in ledger dimension:

Lesser used terms:

Data Model

There are a lot of tables that involves dimension. In this section we will focus on a few important ones and how we can use these.

Get display value from LedgerJournalTrans

In the table LedgerJournalTrans, the ledger dimension is stored as a RecId reference. To get the display value you need to get it from DimensionAttributeValueCombination. DimensionAttributeValue Data model

static DimensionDisplayValue getDisplayValue(LedgerJournalTrans _transaction)
{
    DimensionAttributeValueCombination combination;
    ;
    select DisplayValue from combination 
        where combination.recId == _transaction.LedgerDimension;
    return combination.DisplayValue;
}

Get specific attribute from a combination

This can be useful for instance in a reporting situation where you need to extract the BusinessUnit. In the example below we assume that you have used the previous code to get the DimensionAttributeValueCombination already. DimensionAttributeValue Data model

static DimensionDisplayValue getAttributeValueFromCombination(
    DimensionAttributeValueCombination _combination, 
    Name _attributeName = 'BusinessUnit')
{
    DimensionAttributeLevelValueView valueView;
    DimensionAttribute attribute = DimensionAttribute::findByName(_attributeName);
    ;
    select DisplayValue from valueView 
        where valueView.ValueCombinationRecId == _combination.recId 
        && valueView.DimensionAttribute == attribute.RecId;
    return valueView.DisplayValue;
}

Get main account from a combination

DimensionAttributeValue Data model

static AccountName getMainAccountFromCombination(
    DimensionAttributeValueCombination _combination)
{
    MainAccount mainAccount;
    ;
    select mainAccount where mainAccount.RecId == _combination.MainAccount;
    return mainAccount.MainAccountId;
}

Get specific attribute from customer

DimensionAttributeValue Data model

static DimensionDisplayValue getAttributeValueFromCustomer(
    CustTable _custTable, 
    Name _attribute = 'BusinessUnit')
{
    DimensionAttribute  attribute = DimensionAttribute::findByName(_attribute);
    DimensionAttributeValueSetItemView valueSetItemView;
    ;
    select DisplayValue from valueSetItemView 
        where valueSetItemView.DimensionAttributeValueSet == _custTable.DefaultDimension 
        && valueSetItemView.DimensionAttribute == attribute.RecId;
    return valueSetItemView.DisplayValue;
}

Service class for integration

The are many service classes that can be used to handle the dimensions. These classes can be used from both X++, C# using proxies and through AIF. Very useful in other words. The first time to use them might take some time but once you recognize the pattern it is not difficult to guess how to utilize them. The code below is one example for creating a dimension attribute value.

DimensionValueService service = new DimensionValueService();
DimensionValueContract contract = new DimensionValueContract();
;
contract.parmDimensionAttribute('Department');
contract.parmValue('HR')
contract.parmDescription('Human Resources');
service.createDimensionValue(contract);

Because the service classes can be used in both AIF and in code so easily. I recommend that you at least read through the following list at least once, so that you remember to use them when the opportunity arises. Notice that this is not a complete list of all service classes and methods, but a chosen few that believe are useful.

ChartOfAccountsService

DimensionService

DimensionValueService

FinancialDimensionValidationService

FinancialDimensionBalanceService

Useful classes

If you can't find your solution in the service classes the following classes will probably do that.

For instance we can use this to create a LedgerDimension in this way:

//Example usage
//createLedgerDimension('110110', 'Service Industries B/S', '003', '022');
public static LedgerDimensionAccount createLedgerDimension(
    MainAccountNum _mainAccountId, 
    Name _accountStructureName, 
    Name _businessUnit, 
    Name _department)
{
    MainAccount mainAccount;
    DimensionHierarchy hierarchy;
    DimensionAttributeValueSetStorage storage = new DimensionAttributeValueSetStorage();
    ;
    mainAccount = MainAccount::findByMainAccountId(_mainAccountId);
    hierarchy = DimensionHierarchy::findByTypeAndName(
        DimensionHierarchyType::AccountStructure, _accountStructureName);
    storage.addItem(DimensionAttributeValue::findByDimensionAttributeAndValue(
        DimensionAttribute::findByName('BusinessUnit'), _businessUnit));
    storage.addItem(DimensionAttributeValue::findByDimensionAttributeAndValue(
        DimensionAttribute::findByName('Department'), _department));
    return DimensionDefaultingEngine::getLedgerDimensionFromAccountAndDim(
        mainAccount.RecId, hierarchy.RecId, storage.save());  
}

Creating a new dimension attribute

Creating a new dimension attribute is very simple. First create new view called DimAttribute<name>, in this example we create DimAttributePartyTable. Add the table, and three fields: Key (PartyTable.recId), Value (PartyTable.PartyId) and Name (PartyTable.Name)

Notice that for Value only 30 chars will get stored. So in the case for PartyTable the PartyId will get truncated if we don't shorten the PartyId EDT. Also the Name field is limited to 60 chars. But truncated names are lesser sensitive than the Value.

DimAttributePartyTable

After refreshing the cache (Tools > Cache > Refresh Elements). We can add the new attribute to a structure. In the form Configure account structures click the Add segment you will see your new dimension attribute. Create financial dimension

Final words

In this article we have seen financial dimensions from many aspects: business, data model, classes, integration and coding. I hope this have helped you. If something is missing, please send me an email.