RSS

Monthly Archives: March 2015

Dynamics AX Ledger Dimension using DimensionServiceProvider

There are different ways to create combinations of dimension using X++ code.

in previous blog  i have written how to create ledger dimension using class AxdDimensionUtil method getledgerAccountid which takes container as input and container has account entry pattern along with dimensions.for more details look in to this Dynamics AX Ledger Dimension using AxdDimensionUtil::getLedgerAccountId

These combinations are saved as records in the DimensionAttributeValueCombination table.The RecId from the DimensionAttributeValueCombination table is what is saved in the LedgerDimension field on the LedgerJournalTrans table.

The  table DimensionAttributeValueCombination as it stores a full multi-segment account combination along with some de-normalized information about the combination such as the concatenated segments as a single string, a foreign key (FK) reference to the Account structure, and a FK to the MainAccount that was used.

The best way to create dimension combinations is to use the class and method DimensionServiceProvider\buildDimensionStorageForLedgerAccount.

The buildDimensionStorageForLedgerAccount method takes a LedgerAccountContract class. In the LedgerAccountContract class there are two parm methods, parmMainAccount and parmValues. The parmMainAccount method takes the MainAccount like ‘10060’ and the parmValues method takes a list of the other dimension values you want to set.

More specifically the parmValues method takes a list of classes. The classes are of type DimensionAttributeValueContract. On the DimensionAttributeValueContract class you set two methods, parmName and parmValue. For example, ‘Branch’ for the name and ‘Mumbai’ for the value.

Build up a list of DimensionAttributeValueContract classes for each dimension you want to specify and then pass the list to the parmValues method on the LedgerAccountContract class. Once you have the LedgerAccountContract built up send it to the DimensionServiceProvider\buildDimensionStorageForLedgerAccount.

The following code can be used to update LedgerDimension field on the LedgerJournalTrans

RecId getDimension(str _ledgerAccount, str _branch, str _serviceCentre, str _department)  
 {  
   DimensionServiceProvider      DimensionServiceProvider = new DimensionServiceProvider();  
   LedgerAccountContract        LedgerAccountContract = new LedgerAccountContract();  
   DimensionAttributeValueContract   ValueContract;  
   List                ListValueContract = new List(Types::Class);  
   dimensionAttributeValueCombination dimensionAttributeValueCombination;  
   DimensionStorage          dimStorage;  
   if (_businessUnit)  
   {  
     ValueContract = new DimensionAttributeValueContract();  
     ValueContract.parmName('Branch') ;  
     ValueContract.parmValue(_branch);  
     ListValueContract.addEnd(ValueContract);  
   }  
   if (_costCentre)  
   {  
     ValueContract = new DimensionAttributeValueContract();  
     ValueContract.parmName('Serviceentre') ;  
     ValueContract.parmValue(_serviceCentre);  
     ListValueContract.addEnd(ValueContract);  
   }  
   if (_department)  
   {  
     ValueContract = new DimensionAttributeValueContract();  
     ValueContract.parmName('Department') ;  
     ValueContract.parmValue(_department);  
   }  
   
   LedgerAccountContract.parmMainAccount(_ledgerAccount);  
   LedgerAccountContract.parmValues(ListValueContract);  
   dimStorage = DimensionServiceProvider::buildDimensionStorageForLedgerAccount(LedgerAccountContract);  
   dimensionAttributeValueCombination = DimensionAttributeValueCombination::find(dimStorage.save());  
   return dimensionAttributeValueCombination.RecId;  
 }
 

Tags: , , , , , , ,

Dynamics AX Ledger Dimension using AxdDimensionUtil::getLedgerAccountId

The way ledger dimensions work changed drastically with the release of Dynamics AX 2012. You have probably seen the dynamic account strings, in which main account numbers are merged with ledger dimensions into one string. This is handled automatically by the user interface, but as a programmer you may have to do the same from code.

The underlying a structures are rather complex, but fortunately the utility class AxdDimensionUtil can help you with this. Assuming you have a main account ‘0001’, a dimension called “Branch” with a value of “031”, and a dimension called “Service centre” with a value of “Mumbai”, we needs to create a container with main account and all other required dimensions as Account entry pattern:

[‘MainAccountId’, ‘MainAccountId’, no. of dimensions, ‘DimensionName’, ‘DimensionValue’ , …]

Example

dimensions = ['112050-AFS002', '0001', 2, 'Branch', 'AFS002', 'Service centre', 'Mumbai'];

AxdDimensionUtil::getLedgerAccountId takes container as parameter and creates and return ledger dimension.

the first element is actually the display value and second element is Main Account.The third element in the container is the number of dimensions, two in this case. Then the dimensions with ID followed by value.

Finally, you can pass the container to the AxdDimensionUtil::getLedgerAccountId method, which will return a ledger dimension record ID you can use as reference on the records where you need it, for example on ledger journal transactions:

JournalTrans.LedgerDimension(AxdDimensionUtil::getLedgerAccountId(dimensions));

The actual display of the merged account string is still handled by the user interface, but this method can help you create the underlying data without getting too gritty with the details.

 

Tags: , , , , , ,

Exception "Function DimensionDefaultingEngine::constructForMainAccountId has been incorrectly called

While creating a General Journal and than post journal entries using X++, I received the following error message:
Function DimensionDefaultingEngine::constructForMainAccountId has been incorrectly called.

This issue occurs at below line of code while creating ledger dimension of specific ledger account

journalTrans.parmLedgerDimension(AxdDimensionUtil::getLedgerAccountId(accEntryPattern));

As per argument,we are passing a container of dimension values which convert a combination of a main account and financial dimension values into a ledger account RECID.So system trying to locate the record of the hierarchy of the current chart of accounts and with in account structure

When you check The account structure then you will find that Main account is not there.the error message is weird and  one can not understand through error that Main Account is missing from account structure.So system will be able to insert value only in case  if argument container “Main account and financial dimension values” are configured in ledger account structure.

Whenever a new ledger account is created, one should double check the account structure.

 

Tags: , , , ,

Financial Dimensions – Deep Dive Part-1

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.

1. Business perspective

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

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, 

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).

2. Technical terms

  • Dimension Attribute is the type of information that is traced. In the image above the attributes are MainAccount, BusinessUnit, Department and ServiceLine.
  • Dimension Attribute Value is the value of the attribute. In the image above the values are 140200, 004, 023 and Application Development
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 consistent (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

    

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:

  • Default Account – Ledger Dimension, but with only one dimension attribute value, main account.
  • Dynamic Account – Similar to Ledger Dimension but it handles the dynamic usage as in journals. When a journal type is Ledger then it stores Ledger Dimension. But when the ledger type is for instance customer, then the dynamic account will have a lookup for customer accounts instead.

Lesser used terms:

  • Dimension Attribute Set – An unordered set for Dimension Attributes.
  • Dimension Set – Similar to Ledger Dimension but without requirement of Main Account. Mainly used for reports.

3. 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 getDisplayValue(bankAccountTrans _bankAccountTrans) { GeneralJournalAccountEntry generalJournalAccountEntry; GeneralJournalEntry generalJournalEntry; DimensionAttributeValueCombination dimensionAttributeValueCombination; DimensionAttributeLevelValueView dimensionAttributeLevelValueView; MainAccount mainAccount; SubledgerVoucherGeneralJournalEntry subledgerVoucherGeneralJournalEntry; FiscalCalendarPeriod fiscalCalendarPeriod; ; select firstfast * from generalJournalEntry order by generalJournalEntry.AccountingDate ASC, generalJournalEntry.JournalNumber ASC, generalJournalEntry.SubledgerVoucher ASC join LedgerDimension from generalJournalAccountEntry where generalJournalAccountEntry.GeneralJournalEntry == generalJournalEntry.RecId join RecId,MainAccount from dimensionAttributeValueCombination where dimensionAttributeValueCombination.RecId == generalJournalAccountEntry.LedgerDimension join RecId, MainAccountId from mainAccount where mainAccount.RecId == dimensionAttributeValueCombination.MainAccount outer join RecId FROM fiscalCalendarPeriod where generalJournalEntry.FiscalCalendarPeriod == fiscalCalendarPeriod.RecId exists join * FROM SubledgerVoucherGeneralJournalEntry where GeneralJournalEntry.RecId == subledgerVoucherGeneralJournalEntry.GeneralJournalEntry && _bankAccountTrans.Voucher==subledgerVoucherGeneralJournalEntry.Voucher && _bankAccountTrans.TransDate==subledgerVoucherGeneralJournalEntry.AccountingDate; select DisplayValue from dimensionAttributeLevelValueView where generalJournalAccountEntry.LedgerDimension == dimensionAttributeLevelValueView.ValueCombinationRecId && dimensionAttributeLevelValueView.DimensionAttribute == DimensionAttribute::findByName("BusinessUnits").RecId; return dimensionAttributeLevelValueView.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; }

 
Comments Off on Financial Dimensions – Deep Dive Part-1

Posted by on March 23, 2015 in Financial Dimensions, Microsoft Dynamics AX, X++

 

Tags: , , , , ,

Brief Introduction about Models and Model Store [AX2012]

I found the no. of posting related to this from different materials but below is clearly understood explanations.
Basic Info:
Models were introduced in Microsoft Dynamics AX to help partners and customers more easily install and maintain multiple solutions side by side in the same layer. This topic introduces the concept of models, and describes how models relate to layers and label files. This topic also describes the model store, which is the part of the Microsoft Dynamics AX database in which models are stored.
Models:
A model is a set of elements in a given layer. Each layer consists of one or more models. Each layer contains one system-generated model that is specific to that layer. Every element in a layer belongs to only one model. In other words, no element can belong to two models in the same layer, and every element must belong to a model.

A model is permanently associated with the layer that is created in. If you need to move one of your models from one layer to another, you must create a project from the model in the AOT, export the project as an xpo file, create a target model in the desired layer, delete the original model to avoid having to resolve layer conflicts, and import the xpo file to the target model. If you are moving elements between models in the same layer, you can use the Move to model command in the AOT.

ModelStore:

Models are stored in the model store. The model store is the part of the Microsoft Dynamics AX database in which all application elements for Microsoft Dynamics AX are stored. Customizations are also stored in the model store. The model store replaces the Application Object Data (AOD) files that were used in earlier versions of Microsoft Dynamics AX. Models that have been installed in the model store are used at run time.

Note: Models can be exported to files that have the .axmodel extension. These files are called model files.

 
Leave a comment

Posted by on March 21, 2015 in Uncategorized

 

Generate Next RecId for Dynamics AX Table from SSIS

If you want to insert records directly into the SQL database using SSIS, you cannot on-the-fly get RecId’s easily from SQL manipulation alone, so another option is reserving the Recid’s using x++ in an x++ job or service, for example:
To get the next Recid for SalesTable,use the below code and before printing the recid , suspendrecids() has to be call then after printing recid removeRecIdSuspension() method should be call….

static void getNextRecId(Args _args)
{
//Table that stores record ids details for tables
SystemSequences systemSequences;
Counter noOfResereveRecId;

///Suppose you wants to reserve 40 records

noOfResereveRecId = 40;

//Class that handles Record id generation
SystemSequence systemSequence = new SystemSequence();
;

select firstonly systemSequences
where systemSequences.tabId == Tablenum(SalesTable);

systemSequence.suspendRecIds(systemSequences.tabId);
info(strFmt(‘Next record id: %1’,systemSequence.reserveValues(noOfResereveRecId, systemSequences.tabId)));
systemSequence.removeRecIdSuspension(systemSequences.tabId);
}

This job will take a table, and reserve one recId to be used that the system will simply ignore/skip. A word of caution, if you accidently reserve a huge number it’s not easy to get those reservations back, and int64’s do have a limit (albeit a huge number).

You could probably create a service in x++ that you could hit from your SSIS job where you tell a table name and an amount to reserve, and get an int64 back, that way you could automate the SSIS job.

 

Tags: , ,

SSRS Report Server Settings Validation Error- AX 2012 R3 CU8

 

I’m trying to validate  report server setup of a client and got the error below
Make sure that SQL Server Reporting Services is configured correctly. Verify the Web Service URL and Report Manager URL configuration in the SQL Reporting Services Configuration Manager.

image

 

In reporting services report manager site, i have already granted the AX-Admins AD group as System Administrator under site settings, Home folder settings and DynamicsAX folder with “Browser, Content Manager, DynamicsAXBrowser, My Reports, Publisher, Report Builder” roles.

AX-Admins AD group is also member of administrators in windows. UAC had already been disabled. What did i miss?

Solution:

After some troubleshooting, it turns out UAC was not turned off. I am running on MS Windows 8.1.

UAC has to be turned off via registry by changing the DWORD “EnableLUA” from 1 to 0 in “HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\policies\system”.

 

image

You will get a notification that a reboot is required. After the reboot, UAC is disabled.

After UAC is disabled, the issue is resolved.

 

Happy Daxing Smile

 

Tags: , , , ,