How to set a single dimension value in AX 2012?

﹥>﹥吖頭↗ 提交于 2019-11-30 12:59:21
dlannoye

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();

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();
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!