10

My problem is setting some dimension values read from an external source.

Given the AX 2009 statement:

ledgerJournalTrans.Dimension    = ledgerTable.Dimension;
ledgerJournalTrans.Dimension[1] = "abc";

What is the equivalent way to that in AX 2012?

This will of cause assume the existence of a "Department" dimension as the first dimension.

Jan B. Kjeldsen
  • 17,339
  • 5
  • 30
  • 49
  • I was recently told that the financial dimensions are stored in a separate table in 2012 and they're also unlimited. I haven't had a chance to look yet, but my guess would be that it's similar to InventDim where you do ::FindOrCreate() and you have an inventDimId. Not sure if this can help point you in the correct direction. – Alex Kwitny Jan 24 '12 at 17:46
  • You are correct, but there is no simple findOrCreate(), all references are RecId, remember :) – Jan B. Kjeldsen Jan 24 '12 at 18:44
  • I haven't had time to see AX 2012 yet fully up unfortunately. I have a premier Microsoft support rep behind me doing work, but we're on 2009 and I'm sure he'd be confused if I asked him a 2012 programming question. Wish I could be more help. – Alex Kwitny Jan 24 '12 at 22:16

3 Answers3

17

First things first, the legacy dimensions in AX 2009 have been completely redone and replaced in AX 2012. The new LedgerDimension are a combination of the account and the old dimension values that are needed based on the account structure and advanced rule structures. To find out more about the new Dimension Framework in AX 2012 try reading the whitepaper about the new dimension framework.

Assuming that Department is the first dimension and that both dimensions are using the LedgerDimensionAccount EDT simplifies this scenario quite a bit, but the new dimension framework is very flexible so this assumption may not be correct. Even if it is, simply specifying a new value for Department may require that the structure of the combination needs to change drastically because of advanced rule structures that can be setup.

Honestly, I would only consider the code below as just a demonstration how some of the basics work, not something that should be used in production. With that said, this code should accomplish what you want, if that Dimension field on LedgerTable has be replaced with a LedgerDimension field using the LedgerDimensionAccount EDT which stores a full combination.

DimensionStorage dimensionStorage;
DimensionAttribute deparmentDimensionAttribute;
DimensionAttributeValue newDepartmentValue;

// Find the deparment dimension attribute
deparmentDimensionAttribute = DimensionAttribute::findByName("Department");  

// Find the new department value we want to put in the new combination.
newDepartmentValue = DimensionAttributeValue::findByDimensionAttributeAndValue(deparmentDimensionAttribute, "abc");

// Load a DimensionStorage instance with the old combination and update the first segment with new value
dimensionStorage = DimensionStorage::findById(ledgerTable.LedgerDimension);
dimensionStorage.setSegment(1,DimensionStorageSegment::constructFromValue("abc", newDepartmentValue));
ledgerJournalTrans.LedgerDimension = dimensionStorage.save();
Jan B. Kjeldsen
  • 17,339
  • 5
  • 30
  • 49
dlannoye
  • 1,621
  • 18
  • 19
2

My case was the "default dimensions" scenario, so I had to adapt a little. This is the method I eventually used:

On the DimensionAttribute table add a new field name Number then add this method:

public static DimensionAttribute findByNumber(DimensionOrdinal _number)
{
    DimensionAttribute dimensionAttribute;
    select firstonly dimensionAttribute where dimensionAttribute.Number == _number;
    return dimensionAttribute;
}

This explicitly identifies the dimension with a corresponding number.

On the DimensionAttributeValueSetStorage class add the method:

public void addItemNumber(DimensionOrdinal _idx, SysDim _value)
{
    DimensionAttributeValue attrValue;
    DimensionAttribute attr = DimensionAttribute::findByNumber(_idx);
    if (!attr)
        throw error(strFmt("@SYS342559", _idx));
    attrValue = DimensionAttributeValue::findByDimensionAttributeAndValue(attr, _value, false, true);
    this.addItemValues(attr.RecId, attrValue.RecId, attrValue.HashKey);
}

The DimensionAttributeValueSetStorage handles "default dimensions" as described in the white paper @dlannoye mentioned.

Then the corresponding code read like this:

dimensionStorage = DimensionAttributeValueSetStorage::find(salesTable.DefaultDimension);
dimensionStorage.addItemNumber(1, "abc");
salesTable.DefaultDimension = dimensionStorage.save();
Jan B. Kjeldsen
  • 17,339
  • 5
  • 30
  • 49
  • I assume for this you also had job or something similar that set the values of the Number field on the DimensionAttribute table, is that correct? – dlannoye Jan 30 '12 at 19:40
  • No, I just added the field to the Description field group, then edited the values manually in Finance\Setup\Financial dimensions. – Jan B. Kjeldsen Jan 30 '12 at 19:44
0

You can get 2 methods for doing this here:

http://daxldsoft.blogspot.it/2012/11/ax-2012-financial-dimension-update.html