RSS

Replace a Financial Dimension in Default Dimensions [AX 2012]

18 Jan

In my earlier post, I had explained how we can set financial dimensions. In this post, I will provide a job by which we can replace one attribute value in a combination of financial dimensions.

The class that we can use is the DimensionDefaultingService and method to use is “serviceReplaceAttributeValue”.

For this purpose, we will use the following combination taken from a customer record.

Fin1

In this financial dimensions, we will replace value if worker from “114” to “51011”.

The job below will be helpful for you to see how this can be achieved.

static void replaceDefaultDimensions(Args _args)

{

    CustTable                       custTable = CustTable::find(‘CUS-00004′); //Customer Record containing Financial Dimension

    DimensionSHA1Hash               hash; //To store the calculated hash for DimensionAttributeValueSet

    DimensionAttribute              dimAttr; // Contains the financial dimensions records

    DimAttributeHcmWorker           dimAttrWorker; //Backing entity view for Employee type dimension

    DimensionDefault                defaultDimension;

    DimensionEnumeration            dimensionSetId; //Record id for table that contains active dimensions for current ledger

    DimensionAttributeValue         dimAttrValue; // Contains used financial dimension values

    DimensionAttributeValueSet      dimAttrValueSet; //Contains default dimension records

    DimensionAttributeValueSetItem  dimAttrValueSetItem; //Contains individual records for default dimensions

    DimensionAttributeSetItem       dimAttrSetItem; // Contains the number of dimensions active for a account structure ledger

 

    HashKey valueKeyHashArray[]; //To store the has key of dimension in question

    Map     dimAttrIdx, dimAttrRecId; //to store the dimension index and backing entity type

    int     dimAttrCount, i;

    int     emplBackEntityType; //Stores the backing entity type for Employee type dimension

 

    //The employee backing entity will be the view DimAttributeHcmWorker

    emplBackEntityType = tableNum(DimAttributeHcmWorker);

 

    //Initialize the map to store the backing entity types

    dimAttrIdx = new Map(Types::Integer, Types::Integer);

    dimAttrRecId = new Map(Types::Integer, Types::Int64);

    //Get the record Id (dimension set id) for current ledger to find active dimensions

    dimensionSetId = DimensionCache::getDimensionAttributeSetForLedger();

 

    //Find all the active dimensions for current ledger except main account and store there

    //backing entity type in the map

    while select * from dimAttr

            order by Name

            where dimAttr.Type != DimensionAttributeType::MainAccount

        join RecId from dimAttrSetItem

            where dimAttrSetItem.DimensionAttribute == dimAttr.RecId &&

                dimAttrSetItem.DimensionAttributeSet == dimensionSetId

    {

        dimAttrCount++;

        dimAttrIdx.insert(dimAttr.BackingEntityType, dimAttrCount);

        dimAttrRecId.insert(dimAttr.BackingEntityType, dimAttr.RecId);

    }

 

    //Get the backing entity type for the dimension value to process

    select firstOnly dimAttrWorker

        where dimAttrWorker.Value == "51011";

 

    //initialize hash key array to null

    for (i = 1; i<= dimAttrCount; i++)

        valueKeyHashArray[i] = emptyGuid();

 

    //Find the Dimension attribute record for the dimension to work on, in our case it is HcmWorker

    dimAttr.clear();

    dimAttr = DimensionAttribute::find(dimAttrRecId.lookup(emplBackEntityType));

 

    //Get the backing entity type for the dimension value to process

    select firstOnly dimAttrWorker

        where dimAttrWorker.Value == "51011";

 

    //Find the required Dimension Attribute Value record

    //Create if necessary

    dimAttrValue = DimensionAttributeValue::findByDimensionAttributeAndEntityInst(dimAttr.RecId, dimAttrWorker.RecId, false, true);

 

    //Replace the required combination hash keys and other value arrays

    i = dimAttrIdx.lookup(emplBackEntityType);

    valueKeyHashArray[i]    = dimAttrValue.HashKey;

 

    //Calculate the hash for the current values

    hash = DimensionAttributeValueSetStorage::getHashFromArray(valueKeyHashArray, dimAttrCount);

 

    //Null hash indicates no values exist, which may occur if the user entered an invalid value for one dimension attribute

    if (hash == conNull())

    {

        throw error("Wrong value for Employee Dimension");

    }

 

    // Search for existing value set

    dimAttrValueSet = DimensionAttributeValueSet::findByHash(hash);

 

    // This value set does not exist, so it must be persisted

    if (!dimAttrValueSet)

    {

        ttsbegin;

 

        // Insert the value set with appropriate hash

        dimAttrValueSet.Hash = hash;

        dimAttrValueSet.insert();

 

        // Insert only specified set items use this

        dimAttrValueSetItem.clear();

        dimAttrValueSetItem.DimensionAttributeValueSet = dimAttrValueSet.RecId;

        dimAttrValueSetItem.DimensionAttributeValue = dimAttrValue.RecId;

        dimAttrValueSetItem.DisplayValue = dimAttrWorker.Value;

        dimAttrValueSetItem.insert();

 

        ttscommit;

    }

 

    defaultDimension = DimensionDefaultingService::serviceReplaceAttributeValue(custTable.DefaultDimension, dimAttrValueSet.RecId, dimAttr.RecId);

 

    ttsBegin;

    custTable.selectForUpdate(true);

    custTable.DefaultDimension = defaultDimension;

    custTable.doUpdate();

    ttsCommit;

}

 

This is the output after running this job.

Fin2

 
6 Comments

Posted by on January 18, 2012 in AX 2012

 

Tags: , , , ,

6 Responses to Replace a Financial Dimension in Default Dimensions [AX 2012]

  1. Giancarlo

    February 17, 2012 at 2:42 pm

    Hi Sumit.

    May be I have found a “simpler” way to set/change the value.
    In the followinf code I set a new dimension value (Subchannel) that I have mapped on Subsegment table (i.e. I use Subchannel in spite of worker);

    The code seems to me simpler because I use the AxdDimensionUtil class

    static void Giancarlo_SettaDimSuClienti(Args _args)
    {

    void ReplaceSubchannelOnCustomer(AccountNum numCliente) {

    CustTable custTable;
    Struct struct = new Struct();
    container ledgerDimension;

    DimensionAttribute dimSubchannelName; // fine the name of the dimension to set
    DimAttributeSubchannel subChannelValue; // used only

    DimensionDefault newDimDefault;
    DimensionAttributeValueSet valSet;
    DimensionAttributeValueSetItem valSetItem;
    DimensionAttributeValue value;
    DimensionAttribute nomeDim;
    int i;

    ;

    custTable = custTable::find(numCliente, true);

    select firstOnly * from dimSubchannelName where dimSubchannelName.BackingEntityType == tableNum(DimAttributeSubchannel);
    select firstOnly * from subChannelValue where subChannelValue.Value == custTable.SubsegmentId;

    if (custTable.SubsegmentId == “” ) {
    throw error(strFmt(“Error: Subsegment/Subchannel not setted on Customer %1″,custTable.AccountNum));
    } else if (subChannelValue.RecId == 0) {
    throw error(strFmt(“Error: Subsegment/Subchannel %1 on Customer %2 does not exists”,custTable.SubsegmentId,custTable.AccountNum));
    return;
    }

    select firstOnly * from valSet where valSet.RecId == custTable.DefaultDimension; // Get Customer dimension
    // deposit on struct the dimensions values
    while select * from valSetItem where valSetItem.DimensionAttributeValueSet == valSet.RecId
    join value where value.RecId == valSetItem.DimensionAttributeValue
    join nomeDim where nomeDim.RecId == value.DimensionAttribute
    struct.add(nomeDim.Name,valSetItem.DisplayValue); // Accumulate Values
    //
    // Replace or add the dimension value
    //
    if(struct.exists(dimSubchannelName.Name))
    struct.remove(dimSubchannelName.Name); // if exist, replace (remove + add
    struct.add(dimSubchannelName.Name, custTable.SubsegmentId);

    //
    // Fill the container structure
    //
    i = struct.fields();
    ledgerDimension += struct.fields();
    while (i >0) {
    ledgerDimension += struct.fieldName(i);
    ledgerDimension += struct.valueIndex(i);
    i–;
    }

    ttsBegin;
    //replace the values
    newDimDefault = AxdDimensionUtil::getDimensionAttributeValueSetId(ledgerDimension);
    if (custTable.DefaultDimension != newDimDefault) {
    custTable.DefaultDimension = newDimDefault;
    custTable.update();
    ttsCommit;
    } else
    ttsAbort;

    }
    //ReplaceSubchannelOnCustomer(‘CE000115-ESTE’);
    //ReplaceSubchannelOnCustomer(‘CI003708′);
    ReplaceSubchannelOnCustomer(‘CI016269-ITAL’);

    }

     
  2. Tom

    February 21, 2012 at 7:48 pm

    I have read your post, but I am rather surprised that Microsoft has chosen such an inferior replacement for dimensions in AX2009. From what I can tell, the following AX 2009 lines

    ProjJournalTrans.clear();
    ProjJournalTrans.dimension[2] = “Dept01″;

    need to be replaced by nearly 100 lines of code in AX 2012, including 5 database reads/writes and two transactions. Or am I missing something?

     
    • Sumit Loya

      February 24, 2012 at 5:51 pm

      Well I have checked some the service classes related to dimensions and other framework classes. I could find these methods only. So yes to replace or default one value, I see we need to write some good amount of code.

       

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Connecting to %s

 
Follow

Get every new post delivered to your Inbox.

Join 46 other followers