Monday, July 4, 2016

Dimension Combination Validation by Account Structure (Ledger/Cust/Vend/FA/Bank) AX 2012

//Dimension Validation by Account Structure

//Create New Class

class GlobalDimensionValidation
{
}
//Dimension Validation check by ledger
Public  Static Boolean DimensionValidationLedger(   MainAccountNum          _AccountNum,
                                                    Name                    _BU,
                                                    Name                    _CC,
                                                    Name                    _Dept
                                                    )
{
    boolean validDimCombination    = true;
    ;
    validDimCombination = GlobalDimensionValidation::DimensionCombinationCheck(
                        GlobalDimensionValidation::LedgerDimensionCreate(_AccountNum,_BU,_CC,_Dept));
    return validDimCombination;
}
//Dimension Vlaidation check by Non Ledger Account
Public  Static Boolean DimensionValidationNonLedger(Name                    _AccountNum,
                                                    LedgerJournalACType     _accountType,
                                                    Name                    _BU,
                                                    Name                    _CC,
                                                    Name                    _Dept,
                                                    AssetTransType   _transType = AssetTransType::Acquisition
                                                    )
{
    boolean validDimCombination    = true;
    ;
    switch(_accountType)
    {
        case LedgerJournalACType::Cust :
            if(GlobalDimensionValidation::CustLedgerInforCode(_AccountNum) != "")
            {
                validDimCombination = GlobalDimensionValidation::DimensionCombinationCheck(
                        GlobalDimensionValidation::LedgerDimensionCreate(
                                GlobalDimensionValidation::CustLedgerInforCode(_AccountNum),
                                _BU,
                                _CC,
                                _Dept)
                                );
            }
            else
            {
                throw warning("Map Ledger Posting Profile for Customer Account");
            }
            break;
        case LedgerJournalACType::Vend :
            if(GlobalDimensionValidation::VendLedgerInfoCode(_AccountNum) != "")
            {
                validDimCombination = GlobalDimensionValidation::DimensionCombinationCheck(
                        GlobalDimensionValidation::LedgerDimensionCreate(
                                GlobalDimensionValidation::VendLedgerInfoCode(_AccountNum),
                                _BU,
                                _CC,
                                _Dept)
                                );
            }
            else
            {
                throw warning("Map Ledger Posting Profile for Vendor Account");
            }
            break;
        case LedgerJournalACType::FixedAssets :
            if(GlobalDimensionValidation::FALedgerInfoCode(_AccountNum,_transType) != "")
            {
                validDimCombination = GlobalDimensionValidation::DimensionCombinationCheck(
                        GlobalDimensionValidation::LedgerDimensionCreate(
                                GlobalDimensionValidation::FALedgerInfoCode(_AccountNum,_transType),
                                _BU,
                                _CC,
                                _Dept)
                                );
            }
            else
            {
                throw warning("Map Ledger Posting Profile for FA Account");
            }
            break;
        //case LedgerJournalACType::Project :
            //break;
        case LedgerJournalACType::Bank :
            if(GlobalDimensionValidation::BankLedgerInforCode(_AccountNum) != "")
            {
                validDimCombination = GlobalDimensionValidation::DimensionCombinationCheck(
                        GlobalDimensionValidation::LedgerDimensionCreate(
                                GlobalDimensionValidation::BankLedgerInforCode(_AccountNum),
                                _BU,
                                _CC,
                                _Dept)
                                );
            }
            else
            {
                throw warning("Map Ledger Posting Profile for Bank Account");
            }
            break;
        default :
            info(strFmt("Account Type %1 is not valid ",_accountType));
            break;
    }
    return validDimCombination;
}

//Diemnsion Check by combiantion (Method after creation of lines)
Public  Static Boolean DimensionCombinationCheck(RecId    _dimensionCombinationId)
{
    boolean validCombination    = true;
    ;
    if(DimensionValidation::validateByTree(_dimensionCombinationId,today(),true)
                                                    != DimensionValidationStatus::Valid)
    {
        validCombination = false;
        //DimensionValidation::validateByTree(jourTrans.LedgerDimension,today(),true);
    }
    return validCombination;
}
//Default Dimension Create
Protected Static DimensionDefault DefaultDimensionCreate(Description _BU,Description _CC,Description _Department)
{
    DimensionAttributeValueSetStorage valueSetStorage = new DimensionAttributeValueSetStorage();
    DimensionDefault result;
    int i;
    DimensionAttribute dimensionAttribute;
    DimensionAttributeValue dimensionAttributeValue; //DimensionAttributeValueCombination
    container conAttr = ["BusinessUnit","CostCenter","Department"]; //101,106,1
    container conValue;
    str dimValue;
    conValue = [_BU,_CC,_Department];
    dimValue = "";
    i = 0;
    for (i = 1; i <= conLen(conAttr); i++)
    {
        dimensionAttribute = dimensionAttribute::findByName(conPeek(conAttr,i));
        if (dimensionAttribute.RecId == 0)
        {
            continue;
            //control will not go down
        }
        dimValue = conPeek(conValue,i);
        if (dimValue != "")
        {
            dimensionAttributeValue =
            dimensionAttributeValue::findByDimensionAttributeAndValue(dimensionAttribute,dimValue,false,true);
            valueSetStorage.addItem(dimensionAttributeValue);
        }
    }
    result = valueSetStorage.save();

    return result;
}
//Ledger Dimension Create
Protected static LedgerDimensionAccount LedgerDimensionCreate(MainAccountNum   _AccountId,Description _BU,Description _CC,Description _Department)
{
     DimensionAttributeValueSetStorage dimensionAttributeValueSetStorage;
     DimensionAttribute dimensionAttribute;
     DimensionAttributeValue dimensionAttributeValue;
     DimensionDefault dimensionDefault;
     LedgerDimensionAccount ledgerDimensionAccount;
     dimensionAttributeValueSetStorage = new DimensionAttributeValueSetStorage();
     // BusinessUnit
     dimensionAttribute = DimensionAttribute::findByName('BusinessUnit');
     if(dimensionAttribute)
     {
         dimensionAttributeValue = DimensionAttributeValue::findByDimensionAttributeAndValue(dimensionAttribute,_BU, false, true);
         dimensionAttributeValueSetStorage.addItem(dimensionAttributeValue);
     }
     // CostCenter
     dimensionAttribute = DimensionAttribute::findByName('CostCenter');
     if(dimensionAttribute)
     {
         dimensionAttributeValue = DimensionAttributeValue::findByDimensionAttributeAndValue(dimensionAttribute,_CC, false, true);
         dimensionAttributeValueSetStorage.addItem(dimensionAttributeValue);
     }
     // Department
     dimensionAttribute = DimensionAttribute::findByName('Department');
     if(dimensionAttribute)
     {
         dimensionAttributeValue = DimensionAttributeValue::findByDimensionAttributeAndValue(dimensionAttribute,_Department, false, true);
         dimensionAttributeValueSetStorage.addItem(dimensionAttributeValue);
     }
     dimensionDefault = dimensionAttributeValueSetStorage.save();
     // Merging Main Account and default dimension Combination values and  return RecId which can be used as ledgerDimension
     ledgerDimensionAccount = DimensionDefaultingService::serviceCreateLedgerDimension(
                    DimensionStorage::getDefaultAccountForMainAccountNum(_AccountId),dimensionDefault);

    return ledgerDimensionAccount;
}
//Offset Ledger Dimension create
Protected static DimensionDynamicAccount OffsetLedgerDimensionCreate(MainAccountNum   _AccountId,Description _BU,Description _CC,Description _Department)
{
     DimensionAttributeValueSetStorage dimensionAttributeValueSetStorage;
     DimensionAttribute dimensionAttribute;
     DimensionAttributeValue dimensionAttributeValue;
     DimensionDefault dimensionDefault;
     LedgerDimensionAccount ledgerDimensionAccount;
     dimensionAttributeValueSetStorage = new DimensionAttributeValueSetStorage();
     // BusinessUnit
     dimensionAttribute = DimensionAttribute::findByName('BusinessUnit');
     if(dimensionAttribute)
     {
         dimensionAttributeValue = DimensionAttributeValue::findByDimensionAttributeAndValue(dimensionAttribute,_BU, false, true);
         dimensionAttributeValueSetStorage.addItem(dimensionAttributeValue);
     }
     // CostCenter
     dimensionAttribute = DimensionAttribute::findByName('CostCenter');
     if(dimensionAttribute)
     {
         dimensionAttributeValue = DimensionAttributeValue::findByDimensionAttributeAndValue(dimensionAttribute,_CC, false, true);
         dimensionAttributeValueSetStorage.addItem(dimensionAttributeValue);
     }
     // Department
     dimensionAttribute = DimensionAttribute::findByName('Department');
     if(dimensionAttribute)
     {
         dimensionAttributeValue = DimensionAttributeValue::findByDimensionAttributeAndValue(dimensionAttribute,_Department, false, true);
         dimensionAttributeValueSetStorage.addItem(dimensionAttributeValue);
     }
     dimensionDefault = dimensionAttributeValueSetStorage.save();
     //Merging Main Account and default dimension Combination values and  return RecId which can be used as ledgerDimension
     ledgerDimensionAccount = DimensionDefaultingService::serviceCreateLedgerDimension(
                    DimensionStorage::getDefaultAccountForMainAccountNum(_AccountId),dimensionDefault);

    return ledgerDimensionAccount;
}

//Finding Posting Profile Account cust /Bank/Vend
//CUstomer
Protected Static Description255   CustLedgerInforCode(Name _AccountNum,RecId   _TransRecId = 0)
{
    Description255  CustLedInfo;
    CustParameters parms;
    LedgerJournalTrans  trans;
    CustLedgerAccounts          ledgerscustAccounts,ledgerscustAccounts1,ledgerscustAccounts2;
    ;
    parms = CustParameters::findByCompany(curext());
    trans = LedgerJournalTrans::findRecId(_TransRecId,false);
    if(_TransRecId ==0)
    {
        select firstonly SummaryLedgerDimension from ledgerscustAccounts
                                where ledgerscustAccounts.PostingProfile == parms.PostingProfile
                                    && ledgerscustAccounts.AccountCode    == TableGroupAll::All;
        select firstonly SummaryLedgerDimension from ledgerscustAccounts1
                                where ledgerscustAccounts1.PostingProfile == parms.PostingProfile
                                    && ledgerscustAccounts1.AccountCode    == TableGroupAll::GroupId
                                    && ledgerscustAccounts1.Num          == CustTable::find(_AccountNum).CustGroup;
        select firstonly SummaryLedgerDimension from ledgerscustAccounts2
                                where ledgerscustAccounts2.PostingProfile == parms.PostingProfile
                                    && ledgerscustAccounts2.AccountCode    == TableGroupAll::Table
                                    && ledgerscustAccounts2.Num          == _AccountNum;

        if(ledgerscustAccounts)
        {
            CustLedInfo = DimensionAttributeValueCombination::getDisplayValue(ledgerscustAccounts.SummaryLedgerDimension);
        }
        if(ledgerscustAccounts1)
        {
            CustLedInfo = DimensionAttributeValueCombination::getDisplayValue(ledgerscustAccounts1.SummaryLedgerDimension);
        }
        if(ledgerscustAccounts2)
        {
            CustLedInfo = DimensionAttributeValueCombination::getDisplayValue(ledgerscustAccounts2.SummaryLedgerDimension);
        }
    }
    else
    {
        select firstonly SummaryLedgerDimension from ledgerscustAccounts
                                where ledgerscustAccounts.PostingProfile == trans.PostingProfile
                                    && ledgerscustAccounts.AccountCode    == TableGroupAll::All;
        select firstonly SummaryLedgerDimension from ledgerscustAccounts1
                                where ledgerscustAccounts1.PostingProfile == trans.PostingProfile
                                    && ledgerscustAccounts1.AccountCode    == TableGroupAll::GroupId
                                    && ledgerscustAccounts1.Num          == CustTable::find(_AccountNum).CustGroup;
        select firstonly SummaryLedgerDimension from ledgerscustAccounts2
                                where ledgerscustAccounts2.PostingProfile == trans.PostingProfile
                                    && ledgerscustAccounts2.AccountCode    == TableGroupAll::Table
                                    && ledgerscustAccounts2.Num          == _AccountNum;

        if(ledgerscustAccounts)
        {
            CustLedInfo = DimensionAttributeValueCombination::getDisplayValue(ledgerscustAccounts.SummaryLedgerDimension);
        }
        if(ledgerscustAccounts1)
        {
            CustLedInfo = DimensionAttributeValueCombination::getDisplayValue(ledgerscustAccounts1.SummaryLedgerDimension);
        }
        if(ledgerscustAccounts2)
        {
            CustLedInfo = DimensionAttributeValueCombination::getDisplayValue(ledgerscustAccounts2.SummaryLedgerDimension);
        }
    }
    return CustLedInfo;
}

//Vend
Protected Static Description255   VendLedgerInfoCode(Name _AccountNum,RecId   _TransRecId = 0)
{
    Description255              VendLedInfo;
    VendParameters parms;
    LedgerJournalTrans  trans;
    VendLedgerAccounts          ledgersAccounts,ledgersAccounts1,ledgersAccounts2;
    ;
    parms = VendParameters::find();
    trans = LedgerJournalTrans::findRecId(_TransRecId,false);
    if(_TransRecId == 0)
    {
        select firstonly SummaryLedgerDimension from ledgersAccounts
                                where ledgersAccounts.PostingProfile == parms.PostingProfile
                                    && ledgersAccounts.AccountCode    == TableGroupAll::All;
        select firstonly SummaryLedgerDimension from ledgersAccounts1
                                where ledgersAccounts1.PostingProfile == parms.PostingProfile
                                    && ledgersAccounts1.AccountCode    == TableGroupAll::GroupId
                                    && ledgersAccounts1.Num          == VendTable::find(_AccountNum).VendGroup;
        select firstonly SummaryLedgerDimension from ledgersAccounts2
                                where ledgersAccounts2.PostingProfile == parms.PostingProfile
                                    && ledgersAccounts2.AccountCode    == TableGroupAll::Table
                                    && ledgersAccounts2.Num          == _AccountNum;

        if(ledgersAccounts)
        {
            VendLedInfo = DimensionAttributeValueCombination::getDisplayValue(ledgersAccounts.SummaryLedgerDimension);
        }
        if(ledgersAccounts1)
        {
            VendLedInfo = DimensionAttributeValueCombination::getDisplayValue(ledgersAccounts1.SummaryLedgerDimension);
        }
        if(ledgersAccounts2)
        {
            VendLedInfo = DimensionAttributeValueCombination::getDisplayValue(ledgersAccounts2.SummaryLedgerDimension);
        }
    }
    else
    {
        select firstonly SummaryLedgerDimension from ledgersAccounts
                                where ledgersAccounts.PostingProfile == trans.PostingProfile
                                    && ledgersAccounts.AccountCode    == TableGroupAll::All;
        select firstonly SummaryLedgerDimension from ledgersAccounts1
                                where ledgersAccounts1.PostingProfile == trans.PostingProfile
                                    && ledgersAccounts1.AccountCode    == TableGroupAll::GroupId
                                    && ledgersAccounts1.Num          == VendTable::find(_AccountNum).VendGroup;
        select firstonly SummaryLedgerDimension from ledgersAccounts2
                                where ledgersAccounts2.PostingProfile == trans.PostingProfile
                                    && ledgersAccounts2.AccountCode    == TableGroupAll::Table
                                    && ledgersAccounts2.Num          == _AccountNum;

        if(ledgersAccounts)
        {
            VendLedInfo = DimensionAttributeValueCombination::getDisplayValue(ledgersAccounts.SummaryLedgerDimension);
        }
        if(ledgersAccounts1)
        {
            VendLedInfo = DimensionAttributeValueCombination::getDisplayValue(ledgersAccounts1.SummaryLedgerDimension);
        }
        if(ledgersAccounts2)
        {
            VendLedInfo = DimensionAttributeValueCombination::getDisplayValue(ledgersAccounts2.SummaryLedgerDimension);
        }
    }

    return VendLedInfo;
}
//Bank
Protected Static Description255   BankLedgerInforCode(Name _AccountNum)
{
    Description255  BankLedInfo;
    ;
    BankLedInfo = DimensionAttributeValueCombination::getDisplayValue(BankAccountTable::find(_AccountNum).LedgerDimension);
    return BankLedInfo;
}
//FA -- (Note : For FA Required Posting Profile Account Manadatory)
Protected Static Description255   FALedgerInfoCode(Name _AccountNum,AssetTransType   _transType)
{
    Description255  FALedInfo;
    AssetTable      assetTable;
    AssetLedgerAccounts         ledgersAssetAccounts,ledgersAssetAccounts1,ledgersAssetAccounts2;
    AssetTransType              AssetTransType;
    ;
    assetTable.clear();
    assetTable = AssetTable::find(_AccountNum);
   
    select firstonly LedgerDimension from ledgersAssetAccounts
                            where ledgersAssetAccounts.PostingProfile == assetTable.book().PostingProfile
                                && ledgersAssetAccounts.BookId == assetTable.book().BookId
                                && ledgersAssetAccounts.AccountCode    == TableGroupAll::All
                                && ledgersAssetAccounts.TransType == str2enum(AssetTransType,enum2str(_transType));
    select firstonly LedgerDimension from ledgersAssetAccounts1
                        where ledgersAssetAccounts1.PostingProfile == assetTable.book().PostingProfile
                            && ledgersAssetAccounts1.BookId == assetTable.book().BookId
                            && ledgersAssetAccounts1.AccountCode    == TableGroupAll::GroupId
                            && ledgersAssetAccounts1.TransType == str2enum(AssetTransType,enum2str(_transType))
                            && ledgersAssetAccounts1.AccountRelation    == AssetTable::find(_AccountNum).AssetGroup;
    select firstonly LedgerDimension from ledgersAssetAccounts2
                        where ledgersAssetAccounts2.PostingProfile == assetTable.book().PostingProfile
                            && ledgersAssetAccounts2.BookId == assetTable.book().BookId
                            && ledgersAssetAccounts2.AccountCode    == TableGroupAll::Table
                            && ledgersAssetAccounts2.TransType == str2enum(AssetTransType,enum2str(_transType))
                            && ledgersAssetAccounts2.AccountRelation    == _AccountNum;
    if(ledgersAssetAccounts)
    {
        FALedInfo = DimensionAttributeValueCombination::getDisplayValue(ledgersAssetAccounts.LedgerDimension);
    }
    if(ledgersAssetAccounts1)
    {
        FALedInfo = DimensionAttributeValueCombination::getDisplayValue(ledgersAssetAccounts1.LedgerDimension);
    }
    if(ledgersAssetAccounts2)
    {
        FALedInfo = DimensionAttributeValueCombination::getDisplayValue(ledgersAssetAccounts2.LedgerDimension);
    }
    return FALedInfo;
}

Sunday, July 3, 2016

QueryRun.changed in ax 2012

//queryRun.changed in ax 2012
Example :
1) CustTable
2) SalesTable
    Query                   query;
    QueryBuildDataSource    datasource;
    QueryRun                queryRun;
    int                     i= 0,
    ;
    query = new Query();
    datasource = query.addDataSource(tableNum(CustTable));
    datasource = datasource.addDataSource(tableNum(SalesTable));
    datasource.joinMode(JoinMode::OuterJoin);
    datasource.relations(true);
    datasource.addLink(fieldNum(CustTable, AccountNum),fieldNum(SalesTable, CustAccount));
    queryRun = new QueryRun(query);
    while (queryRun.next())
    {
        if (queryRun.changed(tableNum(CustTable)))
            i++;
    }
queryRun.changed(tableNum(CustTable));
//Above line return only when Customer table selecting next record

Ax help development Guide

//Ax help development Guide

https://ax.help.dynamics.com/en/wiki/technical-concepts-guide/

Query Range for Existing Range field in ax 2012 AOT Query

//Query Range for Existing Range field in ax 2012 AOT Query

Query --> init-->

this.query().dataSourceTable(tableNum(InventValueReportTmpLine)).rangeField(fieldNum(InventValueReportTmpLine,InventLocationId)).value("");
this.query().dataSourceTable(tableNum(InventValueReportTmpLine)).rangeField(fieldNum(InventValueReportTmpLine,InventLocationId)).status(1); // 1 Lock , 0 Open

Customize X++ Workflow single approval ax 2012 R3

//Customize X++ Workflow single approval ax 2012 R3
1) Table - (Approver Name)
 Add new field approver name in Journal Master
 Display Name getJournalApprvName()
 {
     InventJournalName inventJournalName;
     select firstOnly inventJournalName where inventJournalName.JournalNameId == this.JournalNameId;
     return inventJournalName.ApproverUser;
 }
2) Table - Workflow enabling Table - Add Workflow status field
3) Form -> Method
Public void setInvtApprovalCtrlVisibility(container _con)
{
    // Group - InventApproval
    // StaticText - InventStatic
    // Button - InventSubmit
    // Menubutton - InventAction
    InventApproval.visible(conPeek(_con,1));
    InventStatic.text(conPeek(_con,2));
    InventSubmit.visible(conPeek(_con,3));
    InventAction.visible(conPeek(_con,4));
}
4) Form --> Datasource Method
 active-->
 element.setInvtApprovalCtrlVisibility(EPGE_InventJournalApproval::setVisibility(InventJournalTable_ds.cursor()));
5)
// Group visibility
// Static text
// Submit button visibility
// Action button visibility
Public static container setVisibility(Common _common)
{
    InventJournalTable      inventJournalTable;
    container               con;
    ;
    if (_common.TableId == tableNum(InventJournalTable))
    {
        inventJournalTable = _common;
    }

    if (!_common)
    {
        con = conIns(con,1,false);
        con = conIns(con,2,"");
        con = conIns(con,3,false);
        con = conIns(con,4,false);
    }
    if (inventJournalTable.InventWorkflowStatus == InventWorkflowStatus::None)
    {
        con = conIns(con,1,true);
        con = conIns(con,2,"Workflow Not yet Submitted");
        con = conIns(con,3,True);
        con = conIns(con,4,false);
    }
    else if (inventJournalTable.InventWorkflowStatus == InventWorkflowStatus::Submitted)
    {
        if(inventJournalTable.getJournalApprvName() == curUserId()
                || inventJournalTable.getJournalApprvName2() == curUserId())
        {
            con = conIns(con,1,True);
            con = conIns(con,2,"Approval is InProgress ");
            con = conIns(con,3,False);
            con = conIns(con,4,True);
        }
        else
        {
            con = conIns(con,1,True);
            con = conIns(con,2,"Workflow is Submitted to Journal Reviewer Approval User");
            con = conIns(con,3,False);
            con = conIns(con,4,False);
        }
    }
    else if (inventJournalTable.InventWorkflowStatus == InventWorkflowStatus::Approved)
    {
        con = conIns(con,1,True);
        con = conIns(con,2,strFmt("Workflow is %1.... Journal %2 for posting",inventJournalTable.InventWorkflowStatus,inventJournalTable.InventWorkflowStatus));
        con = conIns(con,3,false);
        con = conIns(con,4,false);
    }
    else if (inventJournalTable.InventWorkflowStatus == InventWorkflowStatus::Rejected)
    {
        con = conIns(con,1,True);
        con = conIns(con,2,strFmt("Workflow is %1.... Journal %2 for posting, Workflow can Submit Again",inventJournalTable.InventWorkflowStatus,inventJournalTable.InventWorkflowStatus));
        con = conIns(con,3,True);
        con = conIns(con,4,False);
    }
    return con;
}

Customize x++ workflow with Mulitple level of Approval in Ax 2012

// Customize x++ workflow with Mulitple level of Approval in Ax 2012
Table -
Create table
1) Approval Tracking
Code Method --> Sample to Get No Of approval for Current Project
Public static Counter getNoOfApproval(ProjId _projId, RefRecid _recid, Tableid _tableid, name _level)
{
    Counter i;
    Fcc_ProjApprovalTracking    approvalTracking;
    select count(RecId) from approvalTracking
        where approvalTracking.ProjId == _projId &&
              approvalTracking.RefRecId == _recid &&
              approvalTracking.RefTableId == _tableid &&
              approvalTracking.Level == _level;

    return any2int(approvalTracking.RecId);
}
Public static boolean approvalExist(ProjId _projid,
                                    Tableid _tableid,
                                    Refrecid _recid,
                                    Name _level,
                                    UserId _userid = curUserId())
{
     Boolean approvalExist;
    Fcc_ProjApprovalTracking    approvalTracking;

    select count(RecId) from approvalTracking
        where approvalTracking.ProjId == _projId &&
              approvalTracking.RefRecId == _recid &&
              approvalTracking.RefTableId == _tableid &&
              approvalTracking.Level == _level &&
              approvalTracking.UserName == _userid;
    if(approvalTracking.RecId >= 1)
        approvalExist = true;
    else
        approvalExist =false;
    return approvalExist;
}
2) Approval group with levels
Public static int GetLevels(Projid  _project)
{
    Fcc_ProjApprovalGroup   approvalGroup;
    int i;
    ;
    select  count(RecId)
        from approvalGroup where approvalGroup.ProjectId == _project
                && approvalGroup.Level like "L-*";
    i = any2int(approvalGroup.RecId);
    return i;
}
3) Approval user list with Levels
New Class to Get Mulitple level Approval and Passing to Next Level
Class --> (Refer Point Code - 1)
Class --> FOr Workflow Notification (Refer Point code - 8)
Form - Control
 1) Form --> Design --> Create New Group and Name
  Property - Auto decalration - yes
     Column Width and Column Height
             Color Scheme - RGB
            Back Style - Opaque
            Background Color - Yellow
 2) Form --> Design --> static Text
         property -  Auto decalration - yes
 3) Form-->Design--> Button (For Submit)
  Property - Auto decalration - yes
   Left - Right Edge
  Method - > Code (Refer Point Code - 2)
 4) Form-->Design--> Menu Button --> Two Button Conntrol (For Approve and Reject)
  Property - Auto decalration - yes
   Left - Right Edge
  Method -> Code (Refer Point Code - 3)
Form Method
 1) Init --> Code for Hiding Group Based on Requirement
 2) New Method --> ModifyCurrentLevelApproval (Refer Point Code - 4) (note : Only if required multiple level)
 3) New Method --> setApprovalCtrlVisibility (Refer Point Code - 5)
 4) Form -> parent Datasource -> Method-> Init-> Code (Refer Point Code - 6)
 5) Form -> parent Datasource -> Method-> Active -> Code (Refer Point Code - 7)
Code -->
Code 7 :
element.setApprovalCtrlVisibility(Fcc_ProjSOApproval::setVisibility(LedgerJournalTable_ds.cursor()));
Code 6 :
element.setApprovalCtrlVisibility(Fcc_ProjSOApproval::setVisibility(LedgerJournalTable));
Code 5 :
Public void setApprovalCtrlVisibility(container _con)
{
    // Group -
    // StaticText - StaticText
    // Button - Submit
    // Menubutton - Action ( approve and Reject)
    ProjApproval.visible(conPeek(_con,1));
    StaticText.text(conPeek(_con,2));
    Submit.visible(conPeek(_con,3));
    Action.visible(conPeek(_con,4));
}
Code 4:
public void ModifyCurrentLevelApproval(LedgerJournalTable _jourTable)
{
    Name LevelName;
    #define.Level1("L-0001") 
    #define.Level2("L-0002")
    #define.Level3("L-0003")
    #define.Level4("L-0004")
    #define.Level5("L-0005")
 // All ABove levels denoting Multiple level names
    switch(_jourTable.Fcc_currentLevel)
    {
        case 1 :
            LevelName = #Level1;
            break;
        case 2 :
            LevelName = #Level2;
            break;
        case 3 :
            LevelName = #Level3;
            break;
        case 4 :
            LevelName = #Level4;
            break;
        case 5 :
            LevelName = #Level5;
            break;
        default :
            break;
    }
    if (_jourTable.currentLevel && _jourTable.currentLevel != 0)
    {
        if( (Fcc_projApprovalTracking::getNoOfApproval(_jourTable.getProjid(),_jourTable.RecId,_jourTable.TableId,LevelName)) >=
                (Fcc_ProjApprovalGroup::GetMinApprover(_jourTable.getProjid(),LevelName)) )
        {
            if(Fcc_ProjApprovalGroup::GetLevels(_jourTable.getProjid()) == _jourTable.Fcc_currentLevel)
            {
                LedgerJournalTable.Fcc_currentLevel = 0;
            }
            else
            {
                LedgerJournalTable.Fcc_currentLevel = LedgerJournalTable.Fcc_currentLevel + 1;
            }
        }
    }
  /*  else if (_jourTable.Fcc_currentLevel == 0)
    {
         LedgerJournalTable.Fcc_currentLevel = 0;
    }*/
}
Code 3:
//Reject
void clicked()
{
    super();
    LedgerJournalTable.Fcc_ApprovalStatus = Fcc_ApprovalStatus::Rejected;
    Fcc_ProjApproval::changeStatus(LedgerJournalTable,Fcc_ApprovalStatus::Rejected);
    LedgerJournalTable_ds.research(true);
    LedgerJournalTable_ds.refresh();
}
//Approve
void clicked()
{
    Fcc_ProjApprovalGroup   approvalGroup;
    Fcc_ProjApprovalList    approvalList;
    Fcc_ProjApprovalTracking    approvalTracking;
    Fcc_ProjSOExeApprovalList   soExeList;
    Name     level;
    super();
    level = Fcc_ProjSOApproval::GetCurrentLevel(LedgerJournalTable);
    while select soExeList
        where soExeList.ProjectId == ProjTable::find(LedgerJournalTable.getProjid()).ParentId
    {
        Fcc_ProjSOWrkNotification::NotificationAlert(LedgerJournalTable
                                                    ,soExeList.ProjectId
                                                    ,level
                                                    ,soExeList.userId);
    }
    Fcc_ProjApproval::changeStatus(LedgerJournalTable,Fcc_ApprovalStatus::Approved);
    LedgerJournalTable_ds.research(true);
    LedgerJournalTable_ds.refresh();
}
Code 2:
void clicked()
{
    Name     level;
    Fcc_ProjSOExeApprovalList   soExeList;
    super();
    LedgerJournalTable.Fcc_ApprovalStatus = Fcc_ApprovalStatus::Submitted;
    level = Fcc_ProjSOApproval::GetCurrentLevel(LedgerJournalTable);
    while select soExeList
        where soExeList.ProjectId == ProjTable::find(LedgerJournalTable.getProjid()).ParentId
    {
        Fcc_ProjSOWrkNotification::NotificationAlert(LedgerJournalTable
                                                    ,soExeList.ProjectId
                                                    ,level
                                                    ,soExeList.userId);
    }
    Fcc_ProjApproval::changeStatus(LedgerJournalTable,Fcc_ApprovalStatus::Submitted);

    LedgerJournalTable_ds.research(true);
    LedgerJournalTable_ds.refresh();
}
Code 1:
class Fcc_ProjApproval
{
}
//Changet status and Updating current level
Public static void changeStatus(Common _common, Fcc_ApprovalStatus _status)
{
    Fcc_ProjApprovalTracking    apprTracking;
    Fcc_ProjSOApprovalGroup      apprgroupCmp;
    LedgerJournalTable  ledgerjournalTable,journalTableUpd;
    InventJournalTable  inventJournalTable,inventJourTableUpd;
    ProjId  projid;
    str level;

    switch(_common.TableId)
    {
        case tableNum(LedgerJournalTable):
            ledgerjournaltable = _common;
            projid = ProjTable::find(ledgerjournaltable.getProjid()).ParentId;
            apprTracking.RefTableId = _common.TableId;
            apprTracking.RefRecId = _common.RecId;
            apprTracking.Fcc_ApprovalStatus = _status;
            if (_status == Fcc_ApprovalStatus::Submitted)
            {
                apprTracking.Level = "";
            }
            else if (_status == Fcc_ApprovalStatus::Approved)
            {
                apprTracking.Level = Fcc_ProjSOApproval::GetCurrentLevel(_common);
            }
            apprgroupCmp.clear();
            select apprgroupCmp order by RecId desc
                        where apprgroupCmp.ProjectId == projid;
            if(apprgroupCmp.Level == apprTracking.Level)
            {
                ttsBegin;
                select forUpdate journalTableUpd
                    where journalTableUpd.JournalNum == ledgerjournaltable.JournalNum;
                if(journalTableUpd)
                {
                    journalTableUpd.Fcc_ApprovalStatus = Fcc_ApprovalStatus::Approved;
                    journalTableUpd.update();
                }
                ttsCommit;
            }
            apprTracking.ProjId = projid;
            apprTracking.UserName = curUserId();
            apprTracking.ApprovedRejectDate = systemDateGet();
            apprTracking.insert();
            break;
        case tableNum(InventJournalTable) :
            inventJournalTable = InventJournalTable::findByRecId(_common.recid,false);
            projid = inventJournalTable.getProjid();
            apprTracking.RefTableId = _common.TableId;
            apprTracking.RefRecId = _common.RecId;
            apprTracking.Fcc_ApprovalStatus = _status;
            if (_status == Fcc_ApprovalStatus::Submitted)
            {
                apprTracking.Level = "";
            }
            else if (_status == Fcc_ApprovalStatus::Approved)
            {
                apprTracking.Level = Fcc_ProjSOApproval::GetCurrentLevel(_common);
            }
            apprgroupCmp.clear();
            select apprgroupCmp order by RecId desc
                        where apprgroupCmp.ProjectId == projid;
            if(apprgroupCmp.Level == apprTracking.Level)
            {
                ttsBegin;
                select forUpdate inventJourTableUpd
                    where inventJourTableUpd.JournalId == inventJournalTable.JournalId;
                if(inventJourTableUpd)
                {
                    inventJourTableUpd.Fcc_ApprovalStatus = Fcc_ApprovalStatus::Approved;
                    inventJourTableUpd.update();
                }
                ttsCommit;
            }
            apprTracking.ProjId = projid;
            apprTracking.UserName = curUserId();
            apprTracking.ApprovedRejectDate = systemDateGet();
            apprTracking.insert();
            break;
        default :
            throw error("Must be called with Journal Table");
    }
}
//get levels
Public container getLevel(JournalId  _journalId)
{
    container                   conLevel;
    Fcc_ProjApprovalGroup       approvalGroup;
    Fcc_ProjApprovalList        approvalList;
    LedgerJournalTable          ledgerjournalTable;
    LedgerJournalTrans          ledgerjournalTrans, journalTransLevel;
    LedgerJournalTrans_Project  ledgerjournalTrans_Project, journalTrans_ProjectLevel;
    Name                        level;
    Counter                     i, totLevel, nextLevel;
    Fcc_ProjApprovalGroup       projApprovalGroup;
    Fcc_ProjApprovalList        projApprovalList;
    boolean                     executionApprovalExists;
        ;
    executionApprovalExists =false;
    ledgerjournalTable = LedgerJournalTable::find(_journalId);
    if(ledgerjournalTable.Fcc_currentLevel == 0 && ledgerjournalTable.Fcc_NextLevel == 0) // execution will happen if the journal is submitted for the first time
    {
        select journalTransLevel where journalTransLevel.JournalNum == ledgerjournalTable.JournalNum
            join journalTrans_ProjectLevel where journalTrans_ProjectLevel.RefRecId == journalTransLevel.RecId;
        // Check if Execution level exist
        select projApprovalGroup where projApprovalGroup.ProjectId == journalTrans_ProjectLevel.ProjId
                                    && projApprovalGroup.Level like "EX*";
        if(projApprovalGroup)
            executionApprovalExists = true;
        projApprovalGroup.clear();
        select count(RecId) from projApprovalGroup
            where projApprovalGroup.ProjectId == journalTrans_ProjectLevel.ProjId;
        totLevel = projApprovalGroup.RecId -1; // minus the Execution level
        select ledgerjournalTrans where ledgerjournalTrans.JournalNum == ledgerjournalTable.JournalNum
                join count(RecId) from ledgerjournalTrans_Project where ledgerjournalTrans_Project.RefRecId == ledgerjournalTrans.RecId
            && ledgerjournalTrans_Project.Fcc_ExecutionApproval == Fcc_ExecutionApproval::NeedsApproval;
        if(executionApprovalExists)
        {
            i++;
            if (ledgerjournalTrans_Project.recid >= 1 )
            {
                // Assume 10 as execution approval level
                conLevel = conIns(conLevel,i,10);
                i++;
                conLevel = conIns(conLevel,i,1);
            }
        }
        else
        {
            i++;
            if (totLevel > 1)
            {
                conLevel = conIns(conLevel,i,1);
                i++;
                conLevel = conIns(conLevel,i,2);
            }
        }
    }
    else
    {
        select journalTransLevel where journalTransLevel.JournalNum == ledgerjournalTable.JournalNum
            join journalTrans_ProjectLevel where journalTrans_ProjectLevel.RefRecId == journalTransLevel.RecId;
        // Check if Execution level exist
        select projApprovalGroup where projApprovalGroup.ProjectId == journalTrans_ProjectLevel.ProjId
                                    && projApprovalGroup.Level like "EX*";
        if(projApprovalGroup)
            executionApprovalExists = true;
        projApprovalGroup.clear();
        select count(RecId) from projApprovalGroup
            where projApprovalGroup.ProjectId == journalTrans_ProjectLevel.ProjId;
        totLevel = projApprovalGroup.RecId -1; // minus the Execution level
        if (ledgerjournalTable.Fcc_NextLevel <= totLevel)
        {
             i++;
            if (totLevel > 1)
            {
                conLevel = conIns(conLevel,i,ledgerjournalTable.Fcc_NextLevel);
                i++;
                conLevel = conIns(conLevel,i, totLevel - ledgerjournalTable.Fcc_NextLevel);
            }
        }
    }
    return conLevel;
}
//Check and validate action
Public boolean isActionEnabled(JournalId _journalId)
{
    Fcc_ProjApprovalGroup   approvalGroup;
    Fcc_ProjApprovalList    approvalList;
    LedgerJournalTable      ledgerjournalTable;
    LedgerJournalTrans      ledgerjournalTrans;
    LedgerJournalTrans_Project  ledgerjournalTrans_Project;
    Name        level;
    ledgerjournalTable = LedgerJournalTable::find(_journalId);
    select ledgerjournalTrans where ledgerjournalTrans.JournalNum == ledgerjournalTable.JournalNum
        join count(RecId) from ledgerjournalTrans_Project where ledgerjournalTrans_Project.RefRecId == ledgerjournalTrans.RecId
    && ledgerjournalTrans_Project.Fcc_ExecutionApproval == Fcc_ExecutionApproval::NeedsApproval;

    if (ledgerjournalTrans_Project.recid >= 1)
    {
    }
    select approvalGroup;
    return true;
   // select approvalGroup where approvalGroup.ProjectId
}
//Check appproval to submit workflow
Public static boolean chkApproval(JournalId _journalId)
{
    LedgerJournalTable  ledgerJournalTable;
    LedgerJournalTrans  ledgerJournalTrans;
    LedgerJournalTrans_Project  ledgerjournalTrans_Project;
    boolean canSubmit = false;
    select ledgerJournalTable
        where ledgerJournalTable.Fcc_ApprovalStatus == Fcc_ApprovalStatus::NotSubmitted
        && ledgerJournalTable.JournalNum == _journalId
    join ledgerJournalTrans
        where ledgerJournalTrans.JournalNum ==  ledgerJournalTable.JournalNum
    join count(RecId) from ledgerjournalTrans_Project
        where ledgerjournalTrans_Project.RefRecId == ledgerJournalTrans.RecId;
    if (ledgerjournalTrans_Project.RecId >= 1)
        canSubmit = true;
    else
        canSubmit = false;
    return canSubmit;
}
//Check Execution Approval - positng and final approval for Validating amount
Public static boolean chkExeApproval(JournalId _journalId)
{
    LedgerJournalTable  ledgerJournalTable;
    LedgerJournalTrans  ledgerJournalTrans;
    LedgerJournalTrans_Project  ledgerjournalTrans_Project;
    boolean canSubmit = false;
    select ledgerJournalTable
        where ledgerJournalTable.Fcc_ApprovalStatus == Fcc_ApprovalStatus::NotSubmitted
        && ledgerJournalTable.JournalNum == _journalId
    join ledgerJournalTrans
        where ledgerJournalTrans.JournalNum ==  ledgerJournalTable.JournalNum
    join count(RecId) from ledgerjournalTrans_Project
        where ledgerjournalTrans_Project.RefRecId == ledgerJournalTrans.RecId &&
            ledgerjournalTrans_Project.Fcc_ExecutionApproval == Fcc_ExecutionApproval::NeedsApproval;
    if (ledgerjournalTrans_Project.RecId >= 1)
        canSubmit = true;
    else
        canSubmit = false;
    return canSubmit;
}

Code 8:
class Fcc_ProjSOWrkNotification
{
}
//Alert sending
Public static Void AlertSend(Common _common,Name    _journalId,ProjId  _projId,Name    _level,UserId  _UserName)
{
    EventInbox inbox;
    LedgerJournalTable  ledgerjournalTable;
    InventJournalTable  inventJournalTable;
    ;
    inbox.initValue();
    inbox.ShowPopup = NoYes::Yes;
    switch(_common.TableId)
    {
        case tableNum(LedgerJournalTable):
            ledgerjournaltable = _common;
            inbox.AlertedFor = strfmt("Journal Number  %1 for %2 - %3 is waiting for next level of approval",_journalId,_projId,ledgerjournaltable.JournalName);
            inbox.AlertFieldId = fieldnum(ledgerjournaltable, JournalNum);
            inbox.Subject = "Project Expenses Journal Workflow Approval";
        case tableNum(InventJournalTable) :
            inventJournalTable = InventJournalTable::findByRecId(_common.recid,false);
            inbox.AlertedFor = strfmt("Journal Number is %1 for %2 - %3 is waiting for next level of approval",_journalId,_projId,inventJournalTable.JournalNameId);
            inbox.AlertFieldId = fieldnum(inventJournalTable, JournalId);
            inbox.Subject = "Project Item Journal Workflow Approval";
    }
    inbox.Message = strfmt("Journal Number  %1 - User %2",_journalId,_UserName);
    inbox.SendEmail = false;
    inbox.UserId = curuserid();
    inbox.TypeId = classnum(EventType);
    inbox.ParentTableId = _common.TableId;
    inbox.AlertTableId = _common.TableId;
    //inbox.TypeTrigger = EventTypeTrigger::FieldChanged;
    inbox.CompanyId = curext();
    inbox.InboxId = EventInbox::nextEventId();
    inbox.AlertCreatedDateTime = DateTimeUtil::getSystemDateTime();
    inbox.insert();
}
//Notification
Public static void NotificationAlert(Common _common,ProjId  _projId,Name    _level,UserId     _UserName)
{
    LedgerJournalTable  ledgerjournalTable;
    InventJournalTable  inventJournalTable;
    ;
    switch(_common.TableId)
    {
        case tableNum(LedgerJournalTable):
            ledgerjournaltable = _common;
            Fcc_ProjSOWrkNotification::AlertSend(_common,ledgerjournaltable.JournalNum,_projId,_level,_UserName);
            break;
        case tableNum(InventJournalTable) :
            inventJournalTable = InventJournalTable::findByRecId(_common.recid,false);
            Fcc_ProjSOWrkNotification::AlertSend(_common,inventJournalTable.JournalId,_projId,_level,_UserName);
            break;
        default :
            throw error("Must be called with Journal Table");
    }
}


Upload GL Journal from Excel ax 2012 R3

// Upload GL Journal from Excel ax 2012 R3
http://www.daxfinanceblog.com/dynamics-ax/2015/1/11/upload-a-general-journal-from-excel-in-dynamics-ax2012-r3

Get Dimension Hrchy

//get Dimension Hrchy by dimension Hrchy

static void GetDimensionHRCHy(Args _args)
{
    DimensionHierarchy              dimHierarchy;
    DimensionHierarchyLevel         dimHierarchyLevel;
    DimensionAttribute              dimAttribute;
    DimensionConstraintTree         conTree;
    DimensionConstraintNode         conNode;
    DimensionConstraintNodeCriteria conNodeCriteria;
    ;

    dimHierarchy    = DimensionHierarchy::find(5637148326);
    conTree         = DimensionConstraintTree::findByDimensionHierarchy(dimHierarchy.RecId);

    setPrefix('"' + dimHierarchy.Name + '"');

    while select dimHierarchyLevel
        order by Level
        where dimHierarchyLevel.DimensionHierarchy  == dimHierarchy.RecId
    {

        dimAttribute = DimensionAttribute::find(dimHierarchyLevel.DimensionAttribute);
        info(strFmt("Attribute at level %1 is %2",dimHierarchyLevel.Level,dimAttribute.Name));

        while select conNode
            order by Ordinal
            where   conNode.DimensionConstraintTree  == conTree.RecId
            &&      conNode.DimensionHierarchyLevel  == dimHierarchyLevel.RecId
        {

            while select conNodeCriteria
                where   conNodeCriteria.DimensionConstraintNode == conNode.RecId
            {
                if(conNodeCriteria.RangeFrom || conNodeCriteria.RangeTo)
                {
                    info(strFmt(" - Limited from %1 to %2",
                        conNodeCriteria.RangeFrom,
                        conNodeCriteria.RangeTo));
                }
                else
                    info(" - [No restriction]");
            }
        }
    }
}

Ledger Dimension Value by account structure name using AxDimensionUtil

//Ledger Dimension Value by account structure name and AxDimensionUtil
static void GetLedgerDimensionandAccstructure(Args _args)
{
    RecId fromLedgerdimension = 5637145334;
    RecId toLedgerdimension;
    toLedgerdimension = DimensionDefaultingService::serviceCreateLedgerDimension(fromLedgerdimension);
    info(strFmt("From RecId %1 to %2", fromLedgerdimension, toLedgerdimension));   
    info(strFmt("From Display value %1 to %2",
                conPeek(AxdDimensionUtil::getLedgerAccountValue(fromLedgerdimension), 1),
                conPeek(AxdDimensionUtil::getLedgerAccountValue(toLedgerdimension), 1)));
    info(strFmt("From Account structure %1 to %2",
        DimensionStorage::getAccountStructureFromLedgerDimension(fromLedgerdimension).Name,
        DimensionStorage::getAccountStructureFromLedgerDimension(toLedgerdimension).Name));    
}

Vaidation Account structure by Ledger account and combination value ax 2012

//Vaidation Account structure by Ledger account and combination value

static void ValidateLedgerDimensionByAccStructure(Args _args)
{
   str mainAcctNum = "23010101";
   LedgerAccountValidationContract validationContract;
   LedgerAccountContract           accountContract;
   DimensionAttributeValueContract valueContract;
   FinancialDimensionValidationService service;
   
   List listValueContract = new List(Types::Class);
   // Business Unit
   valueContract = new DimensionAttributeValueContract();
   valueContract.parmName("BusinessUnit");
   valueContract.parmValue("207");
   listValueContract.addEnd(valueContract);  
    // Department
   valueContract = new DimensionAttributeValueContract();
   valueContract.parmName("Department");
   valueContract.parmValue("2");
    listValueContract.addEnd(valueContract);
   // Cost Center
   valueContract = new DimensionAttributeValueContract();
   valueContract.parmName("CostCenter");
   valueContract.parmValue("611");
   listValueContract.addEnd(valueContract);
   
   accountContract = new LedgerAccountContract();
   accountContract.parmMainAccount(mainAcctNum);
   accountContract.parmValues(listValueContract);
   validationContract = new LedgerAccountValidationContract();
   validationContract.parmLedgerAccount(accountContract);
   validationContract.parmValidDate(systemDateGet());
   service = new FinancialDimensionValidationService();
   
   if (service.validateLedgerAccount(validationContract))
   {
       info("Valid");
   }
   else
   {
       info("Invalid");
   }
}

Convert Call stack to readable format in D365FO X++

//Input --container _xppCallStack = xSession::xppCallStack();  Public static str POL_formatXppCallStack(container _xppCallStack, int _skipFr...