Data migration: Importing the InventItemGroupForm Table

November 8, 2011 at 12:23
filed under Dynamics AX
Tagged , , , ,

Hi everyone :-).

I am tasked with doing data migration for a project that is about to go live. One of the things that have to be converted are item groups (InventItemGroup) and their linked dimensions (InventItemGroupForm).

Importing the InventItemGroup table is easy, but InventItemGroupForm is a little bit trickier.
There is a job below that shows how to fill in the LedgerDimension field on the InventItemGroupForm table. I’m not saying I completely understand the new dimension framework, but this method worked for me, and I hope it helps you when you have to do the same thing.

You will notice that you won’t be able to import the InventItemGroupForm table with the excel add-on. You’ll have to use a custom job (or make you own import framework like I did).

This white paper can help too: Implementing the Account and Financial Dimensions Framework (White paper)

Note december 2012: The code is wrong, it works but you shouldn’t do it this way.
When I figure everything out, there will be a blogpost :).

static void klforDimensionTest(Args _args)
    /* input */

    // the InventItemGroup record we want to set accounts for
    InventItemGroup                     inventItemGroup = InventItemGroup::find("Car Audio");
    // the main account we want to link to our InventItemGroup
    MainAccountNum                      mainAccountNum = "0107";
    // The account type we are setting
    InventAccountType                   inventAccountType = InventAccountType::InventIssue;
    // the dimension group of the account type
    ItemGroupLedgerDimensionGroup       itemGroupLedgerDimensionGroup = ItemGroupLedgerDimensionGroup::Inventory;

    /* declarations */
    Ledger                              ledger;
    MainAccount                         mainAccount;
    DimensionAttributeValueCombination  dimensionAttributeValueCombination;
    DimensionAttributeValue             dimAttributeValue;
    DimensionAttribute                  dimAttribute;
    DimensionStorage                    dimStorage;
    RecId                               hierarchyRecId;

    DimensionStorageSegment             dimensionStorageSegment;
    InventItemGroupForm                 inventItemGroupForm;

    if(inventItemGroup.RecId == 0)
        throw error("InventItemGroup not found");

    // check if inventItemGroupForm record exists
    select firstOnly forUpdate inventItemGroupForm
    where  inventItemGroupForm.ItemGroupId          == inventItemGroup.ItemGroupId
        && inventItemGroupForm.InventAccountType    == inventAccountType
        && inventItemGroupForm.LedgerDimensionGroup == itemGroupLedgerDimensionGroup;

        // record does not exists, initialize it
        inventItemGroupForm.ItemGroupId             = inventItemGroup.ItemGroupId;
        inventItemGroupForm.InventAccountType       = inventAccountType;
        inventItemGroupForm.LedgerDimensionGroup    = itemGroupLedgerDimensionGroup;

    // get the ledger record for the current company
    ledger = Ledger::findByLegalEntity(CompanyInfo::current());

    // lookup main account record
    mainAccount = MainAccount::findByMainAccountId(mainAccountNum, false, ledger.ChartOfAccounts);

    if (mainAccount.RecId == 0)
        throw error("MainAccount not found");

    // check if DAVC exists
    select firstOnly dimensionAttributeValueCombination
    where dimensionAttributeValueCombination.MainAccount == mainAccount.RecId
      && dimensionAttributeValueCombination.AccountStructure == 0
      && dimensionAttributeValueCombination.LedgerDimensionType == LedgerDimensionType::DefaultAccount;

    // when the DAVC does not exist, create it
    if(dimensionAttributeValueCombination.RecId == 0)
       // Cache the dimension attribute that represents the Main account
        select firstonly * from dimAttribute where
            dimAttribute.RecId == DimensionAttribute::getMainAccountDimensionAttribute();

        // Lookup the DAV backing the main account instance
        dimAttributeValue = DimensionAttributeValue::findByDimensionAttributeAndEntityInst(dimAttribute.RecId, mainAccount.RecId, false, true);

        // lookup the hierarchy for the default acount
        hierarchyRecId = DimensionHierarchy::getHierarchyIdByHierarchyType(DimensionHierarchyType::DefaultAccount);

        // create new storage
        dimStorage = DimensionStorage::construct();
        // add the default account structure hierarchy

        // create storage segment for the value
        dimensionStorageSegment = DimensionStorageSegment::construct(mainAccountNum, dimAttributeValue.RecId, dimAttributeValue.HashKey);
        // add the segment to the storage
        dimStorage.setSegment(1, dimensionStorageSegment);

        // save storage as default account and get the record
        dimensionAttributeValueCombination = DimensionAttributeValueCombination::find(dimStorage.saveAsDefaultAccount());

    // set the ledgerdimension reference field
    inventItemGroupForm.LedgerDimension = dimensionAttributeValueCombination.RecId;
    // call modifiedfield voor ledgerdimension field to sync inventPosting
    inventItemGroupForm.modifiedField(fieldNum(InventItemGroupForm, LedgerDimension));


    if(inventItemGroupForm.recid == 0)
        // insert if this is a new record
        // update existing record



Comments with ideas / insights / improvements are welcome as always.


RSS / trackback

  1. Shiva


    Many thanks for your post.

    I am trying to execute the same job. It shows the following error.

    An internal error occurred in the remove operation in the InventPostingSetupCache_AILD object cache.

  2. Dynamics AX blog

    Hello, how its going? Is there any news about new code? Thank you :)

  3. Klaas Deforche

    Hi! I’m glad you ask :). I believe the correct way to get the ledger dimension value for a main account is (e.g, for main account 100000):


    In my tests this returns the same result as the (way to complicated) code above.