Tuesday, August 14, 2018

Microsoft Dynamics 365 - How to Create default dimension with a set of dimension values through x++

According to the client requirements, sometime we need to create ledger dimension account (financial dimension value) through code in D365. In Microsoft Dynamics 365, create financial dimension value is totally different form AX 2012.





Here we have to understand some terminology before implementing the solution in your project.

1. Before creating a default dimension with a set of dimension values in D365, you need to know the your accounting structure. For this go to
https://usnconeboxax1aos.cloud.onebox.dynamics.com/?cmp=igil&mi=DimensionConfigureAccountStructure



Before creating financial dimension you should know your dimension value combination sequence from accounting structure you have define for the journal.





2. create a container, which is used as a parameter for function contains dimension values in sequence of accounting structure.


First index of container contains main account number and subsequent index contains financial dimension values.

3.     AccountId        = conPeek(_conData,1);
        mainAccount
   = MainAccount::findByMainAccountId(AccountId);

The above lines are responsible for getting the main account buffer from accountid set on the first index of _conData which holds account id and dimension values.

4.     recordvalue   = DimensionHierarchy::getAccountStructure(mainAccount.RecId,Ledger::current());

The recordvalue holds the accounting structure buffer which has been define on main account you mention in _conData, which is helpful while creating default dimensions in ledger journal.

5. hierarchyCount   = DimensionHierarchy::getLevelCount(recordvalue);
    DimensionSet      = DimensionHierarchyLevel::getDimensionHierarchyLevelNames(recordvalue);


DimensionHierarchy::getLevelCount return the total count of financial dimension used in accounting structure which has been define on main account including main account value.

DimensionHierarchyLevel::getDimensionHierarchyLevelNames returns the sequence names of financial dimension used in accounting structure  which has been define on main account including main account value.

Example: HierarchyCount = 3
                HierarchyName  = ['Main Account', 'Business Unit', 'Department']
                DimensionSet    = ["1135205","Centre","ATK"]

6. DimensionAttribute::findByLocalizedName(DimensionSet[hierarchyIdx],
                                                                            false,
                                                                            "en-us");

 The dimension value set in container used to get dimension attribute buffer, which is helpful in finding dimension attribute value buffer.

Note: In some case we are responsible to also create financial dimension values through code in D365, for which dimension attribute value is not initializes/recorded. If dimension attribute value is not set for some dimension we have to set create if necessary parameter as true to create record in dimensionAttributeValue table.

Like this:
dimensionAttributeValue = DimensionAttributeValue::findByDimensionAttributeAndValue(dimensionAttribute,
                                                                                                        conPeek(_conData,hierarchyIdx),
                                                                                                        false,
                                                                                                        true);


Run the below code for creating financial dimension values:  
dimensionAttribute      = DimensionAttribute::findByName(DimensionName);
 
if(dimensionAttribute.RecId)
{
       financialTag.initValue();

       financialTag.Description                       = "Description";
       financialTag.Value                                 = "42051";
       financialTag.FinancialTagCategory       = dimensionAttribute.financialTagCategory();


       if(financialTag.validateWrite())

       {
              financialTag.insert();
       }
 }

Now see below code for reference.

Run the below job with your specific set of dimension values and get the default dimension(Recid) for that combination:

/// <summary>
/// The method used to create a dimension dynamic account according to the financial dimesnion accounting structure
/// </summary>
/// <param name = "_conData">container constains all group record financial dimension in accouting structure sequences</param>
/// <returns></returns>

private DimensionDynamicAccount   generateLedgerDimension(container _conData)
{
    //Finanical Dimension Attribute.
    DimensionAttribute                                   dimensionAttribute;
    DimensionAttributeValue                          dimensionAttributeValue;
    DimensionSetSegmentName                     DimensionSet;
    DimensionStorage                                     dimStorage;
    DimensionAttributeValueContract            ValueContract;
    dimensionAttributeValueCombination      dimensionAttributeValueCombination;
    //Main Account details
    MainAccount                                             mainAccount;
    //table ref recid
    LedgerRecId                                              ledgerRecId;
    RefRecId                                                    recordvalue;
    //index count
    int                                                               hierarchyCount;
    int                                                               hierarchyIdx;
    //Main Account
    Str                                                              AccountId;

    //Account Contract.
    LedgerAccountContract LedgerAccountContract = new LedgerAccountContract();
    List                                 valueContracts                = new List(Types::Class);
       
    AccountId                = conPeek(_conData,1);
    mainAccount           = MainAccount::findByMainAccountId(AccountId);
    recordvalue              = DimensionHierarchy::getAccountStructure(mainAccount.RecId,Ledger::current());
    hierarchyCount        = DimensionHierarchy::getLevelCount(recordvalue);
    DimensionSet          = DimensionHierarchyLevel::getDimensionHierarchyLevelNames(recordvalue);

    for(hierarchyIdx = 1;hierarchyIdx<=hierarchyCount;hierarchyIdx++)
    {
        dimensionAttribute = DimensionAttribute::findByLocalizedName(DimensionSet[hierarchyIdx],
                                                                            false,
                                                                            "en-us");

        if(dimensionAttribute)
        {
            if(hierarchyIdx <= conLen(_conData))
            {
                dimensionAttributeValue = DimensionAttributeValue::findByDimensionAttributeAndValue(dimensionAttribute,
                                                                                                        conPeek(_conData,hierarchyIdx),
                                                                                                        false,
                                                                                                        true);
            }
            else
            {
                dimensionAttributeValue = DimensionAttributeValue::findByDimensionAttributeAndValue(dimensionAttribute,
                                                                                                        conPeek(_conData,hierarchyIdx));
            }
            if(dimensionAttributeValue)
            {
                ValueContract = new DimensionAttributeValueContract();
                ValueContract.parmName(dimensionAttribute.Name) ;
                ValueContract.parmValue(dimensionAttributeValue.CachedDisplayValue);
                valueContracts.addEnd(ValueContract);
            }
        }
    }

    LedgerAccountContract.parmMainAccount(AccountId);
    LedgerAccountContract.parmValues(valueContracts);
    dimStorage                          = DimensionServiceProvider::buildDimensionStorageForLedgerAccount(LedgerAccountContract);
    dimensionAttributeValueCombination  = DimensionAttributeValueCombination::find(dimStorage.save());
    ledgerRecId                         = dimensionAttributeValueCombination.RecId;

    return ledgerRecId;
}
 

No comments:

Post a Comment

Workflow - Bulk Action processing on workflow in Microsoft Dynamics 365

Problem Description: Some organization required to have ( approve/reject/request change ) documents/Vouchers through workflow in a bul...