Monday 6 November 2017

Dynamics 365 Price and Licensing details

I’m sure SMBs faced lot of challenges when comes to choose which D365 plan either business or Enterprise edition. Well, Say goodbye to the Business\Enterprise edition.

If you want to know the reason why Microsoft doing this? Check here

As we mentioned before, Microsoft scrapped the Business and Enterprise editions and replaced them with 3 newer plans,
  •      Dynamics 365
  •       Customer Engagement
  •       Unified Operations


You can find the full details about the pricing and plan here.

Happy coding!

Sunday 2 July 2017

Financial Dimension Update through Job

Financial Dimension Update through Job

Scenario:

We are going to update financial dimension (specific values)in sales quotation without affecting other dimesnion values.

Code:


static void AbsSalesQuotationDimension_Upd(Args _args)
{
    int                            j, k;
    Struct                         struct = new Struct();
    container                      ledgerDimension;
    DimensionDefault               DimensionDefault;
    SalesQuotationTable            salesquotbl;

    DimensionAttributeValueSetStorage    dimStorage;
    DimensionAttribute                   DimensionAttribute;
    Counter                                               i;
    DimensionAttribute          dimAttr;
    DimensionAttributeValue     dimAttrValue;
    Common                      common;
    DictTable                   dictTable;
    DimensionValue              activity, country, department, project, property, unit;
    str                         Name;
    str                         value;
    SalesQuotationLine  sqline;

    //department = '111';

    ttsBegin;
    while select forupdate salesquotbl where salesquotbl.QuotationStatus == SalesQuotationStatus::Created
    {
        activity   = '';
        country    = '';
        department = '';
        project    = '';
        property   = '';
        unit       = '';
        ledgerDimension = conNull();
        k = 1;
        j = 0;
        DimensionDefault = 0;
        struct = new Struct();
        

            dimStorage = DimensionAttributeValueSetStorage::find(salesquotbl.DefaultDimension);

            for (i=1 ; i<= dimStorage.elements() ; i++)
            {
                select firstonly dimAttrValue
                where dimAttrValue.RecId == dimStorage.getValueByIndex(i)
                join dimAttr
                    where dimAttr.RecId == dimAttrValue.DimensionAttribute;

                    if (dimAttr && dimAttrValue)
                    {
                        dictTable = new DictTable(dimAttr.BackingEntityType);
                        common = dictTable.makeRecord();

                        if (common.TableId)
                        {
                            select common where common.(dimAttr.KeyAttribute) == dimAttrValue.EntityInstance;
                            name = common.(dimAttr.NameAttribute);
                            value = common.(dimAttr.ValueAttribute);
                            if (dimAttr.Name == 'Activities')
                            {
                               activity =  value;
                            }
                            if (dimAttr.Name == 'Country')
                            {
                               country  =  value;
                            }
                            else if (dimAttr.Name == 'Departments')
                            {
                               department =  '111'; //value;
                            }
                            else if (dimAttr.Name == 'Project_ID')
                            {
                               project =  value;
                            }
                            else if (dimAttr.Name == 'Property_id')
                            {
                               property =  value;
                            }
                            else if (dimAttr.Name == 'Unit_ID')
                            {
                               unit =  value;
                            }
                        }
                    }
            }  //for

                if (activity)
                {
                struct.add('Activities', activity);
                }
                if (country)
                {
                struct.add('Country', country);
                }

                if (department)
                {
                struct.add('Departments', department);
                }

                if (project)
                {
                struct.add('Project_ID', project);
                }

                if (property)
                {
                struct.add('Property_id', property);
                }

                if (unit)
                {
                struct.add('Unit_ID', unit);
                }

                j = struct.fields();

                ledgerDimension += struct.fields();
                for (k =1; k <= j; k++)
                {
                    ledgerDimension += struct.fieldName(k);
                    ledgerDimension += struct.valueIndex(k);
                }

                DimensionDefault = AxdDimensionUtil::getDimensionAttributeValueSetId(ledgerDimension);

                salesquotbl.DefaultDimension = DimensionDefault;
                salesquotbl.update();

            update_recordSet sqline
            setting DefaultDimension = salesquotbl.DefaultDimension
             where salesquotbl.QuotationId == sqline.QuotationId; 
            
    }
    ttsCommit;

}

Happy coding!

Monday 3 April 2017

Multiple Customer Transaction Reverse by using X++

Multiple Customer Transaction Reverse by using X++

Scenario:

If user wants to reverse the bulk customer transaction (irrespective of Customer account) based on the customer transaction txt column (or any other column).

Code:

static void Abs_CustTrans_Reverse(Args _args)
{
   
    CustTrans                custtran, custtranOut;
    TransTxt                 txt;
    Counter                  counter;
    boolean                  reversed;
    TransactionReversal_Cust transsactionCust = new TransactionReversal_Cust();
    Args args = new Args();
    ;

    counter = 0;

    //Counts how many records which we are going to reverse   
    select count(RecId) from custtranOut
                        where custtranOut.Txt like 'sho*'
                        &&    custtranOut.OrderAccount == '';

    while select custtran
          where custtran.Txt like 'sho*'
          &&    custtran.OrderAccount == ''
    {
        //Returns the reversed status
        reversed = TransactionReversalTrans::findTransactionReversalTrans(tableNum(CustTrans),         custtran.RecId).Reversed;

      if(!reversed)
      {
         args.record(custtran);
         new MenuFunction(menuitemActionStr(TransactionReversal_Cust), MenuItemType::Action).run(args);
         counter++;
      }
    }

        info(strFmt("Actual records %1 and reversed records %2", custtranOut.recid, counter));
}


Happy coding!

Wednesday 29 March 2017

Show Documents Icon in Listpage

Show Documents Icon in Listpage

Show document icon in list page, if documents attached to the specific record

Scenario:  Display document icon if user attached any document to the specific record in Listpage.
Below are the steps to bring it in real..

1    1)      Create a below display method in table
display smmDocIconNum showDocHandIcon()
{
    #macrolib.resource

    if ((select firstonly docuRef where docuRef.RefCompanyId  == this.DataAreaId && docuRef.RefTableId ==                this.TableId && docuRef.RefRecId == this.RecId).RecId)
    {
        return #RES_NODE_DOC;
    }

    return #RES_AM_NEW;
}

2     2)      Create a window control in form listpage  and point the table method in control properties.
3     3)      Create window control mouseUp method and paste the below code

int mouseUp(int _x, int _y, int _button, boolean _ctrl, boolean _shift)
{
    int ret;

    ret = super(_x, _y, _button, _ctrl, _shift);

    smmUtility::openSmmDocHandling(salesQuotationTable, element);

    return ret;
}


(I took SalesQuotationtable as an example)

Happy coding!

Copy data from one company to other companies using X++

Copy data from one company to other companies using X++

Overview:

The requirement is to copy BudgetExceltemplate table data from ‘02’ company to other companies. Before import in other companies must delete the dump data.

Code:

The below job will copy and create records from ‘02’ to other companies,

static void CopyDataacrossCmy(Args _args)
{
    //BudgetExcelTemplate is the customized table.
    // Need to copy BudgetExcelTemplate table data from '02' company to all the company
    // Change the table which you want to copy from based on your needs.

    BudgetExcelTemplate   BudgettableFrom, BudgettableTo, tabledelete;
    DataArea            dataareatbl;  

    // ProgressCounter
    #avifiles
    SysOperationProgress                 progressbar;
    int                                  totalRecords;
    #define.TITLE("Copying data to other companies...")
    ;

    select count(RecId) from BudgettableFrom;

    totalRecords = any2int(BudgettableFrom.RecId);
    progressbar  = SysOperationProgress::newGeneral(#aviUpdate, #TITLE, totalRecords);

    // Delete the dump data in other companies except the from company data.
    while select dataareatbl where dataareatbl.id != '02'
    {
         changecompany(dataareatbl.id)
         { 
             tabledelete.clear();           
            ttsBegin;
            delete_from tabledelete where tabledelete.dataAreaId == dataareatbl.id;
            ttsCommit;           
         }
    }   
    BudgettableFrom.clear();   
    // Copy data from 02 company to rest of the companies
    while select dataareatbl where dataareatbl.id != "02"
    {      
        while select BudgettableFrom
        {
            changecompany(dataareatbl.id)
            {
                BudgettableTo.clear();

                ttsbegin;
                buf2buf(BudgettableFrom, BudgettableTo);
                BudgettableTo.insert();
                ttscommit;
            }
            progressbar.incCount();
        }
       
        BudgettableFrom.clear();
    }

    progressbar.hide();

}

Happy coding!

Tuesday 9 August 2016

Combine XPOs into Single XPO in AX 2012


Microsoft has given a new feature called Combine XPO, which will mainly be used in big project where more than one technical is developing and keeping their own XPO in separate folder.

It is very hard to import one by one if we want to move code by using XPO. Of course, Modelstore is the best option but if there is any scenario where project has to move by XPO, its better we can organize those XPO and combined into single XPO by using the below command.

For example, you have organized all the XPOs and store in the below path,

C:\Users\erp3\Desktop\SourceXPOs\

For example, you want to place the finalized single XPO in the below path,

C:\Users\erp3\Desktop\New\AXDestinationfiles.xpo

Step1:

Open Command Prompt with Administrator mode

Step 2:

Bring the below path by running the below command,

cd \Program Files\Microsoft Dynamics AX\60\ManagementUtilities

Step 3: Run the below command,

CombineXPOs.exe -XpoDir C:\Users\erp3\Desktop\SourceXPOs\ -CombinedXpoFile C:\Users\erp3\Desktop\New\ AXDestinationfiles.xpo

Great! Now you have combined all the XPOs into single XPO..

Happy coding!

Sunday 7 August 2016

Recursive function in X++


One of my project, I have to show the records based on the employee position wise in form. The requirement is 1) CEO can view all the records and root node employees (Emp6, Emp7, Emp8 & Emp4) can only see his\her records if they created.

For Ex1: Emp5 can view only his record and Emp7 and Emp8 records.

Ex2: Emp4 can view only his\her record.

Ex3: Emp 1 can view his records and Emp3, Emp4 & Emp6

So in any transaction if you want to show the records based on the position hierarchy need to write a recursive method to get the reporting position employee id.

Step 1:

Table must have userid field who is creating the record

Step 2: Create a below form method and pass the current empl id

static void Ave_ReporttoPosition(EmplId ownerid)

{

    HRPPartyPositionTableRelationship     _partyEmplId1,_partyEmplId2,_partyEmplId3;

  

    EmplId                                ownerid;

    str 255                               reporttoposition ;

    int                                   i, j, k, m, n;

    container                             con,con1,con2,conbackup,conRPId,conRPIdTmp;

    PositionId                            _PositionId;

    boolean                               test;

 

       void  GITL_AbsRPosition(PositionId  _posid)

        {

            while select _partyEmplId2 where _partyEmplId2.ReportsToPosition == _posid

            {

               if(_partyEmplId2.ReportsToPosition)

               {

                  con = conins(con,j,_partyEmplId2.PositionId);

                  j++;

                  conRPId = conins(conRPId,k,_partyEmplId2.Reference);

                  k++;

               }

            }

         }

    ;

    ownerid     = '10009';  //_emplid ;

    i = 1;

    j = 1;

    k = 2;

    con        = connull();

    conRPId    = connull();

    conRPIdTmp = connull();

    select _partyEmplId1 where _partyEmplId1.Reference == ownerid;

 

     conRPId  = conins(conRPId,1,ownerid);

     if(_partyEmplId1.ReportsToPosition)

     {

        while select _partyEmplId3 where _partyEmplId3.ReportsToPosition == _partyEmplId1.PositionId

        {

            if(_partyEmplId3.ReportsToPosition)

               {

                  con = conins(con,j,_partyEmplId2.PositionId);

                  j++;

 

                  conRPId = conins(conRPId,k,_partyEmplId2.Reference);

                  k++;

               }

        }

         for(i = 1; i >= conlen(con); i++)

         {

             _PositionId  = conpeek(con,i);

             this.GITL_AbsRPosition(_PositionId);

         }

             conRPIdTmp = conRPId;

     }

     Else

     {

        conRPIdTmp  = conRPId;

     }

  return conRPIdTmp;

} 

(This is Ax 2009 – code but you can get the recursive logic from this sample code)

Step 4) The above method will get the report to position emplid of the current employee id . But the values are in container. So get those values into string variable and then pass all the emplid into executequery  method (As you know that write a query filer and pass this value)

Guess what, every user can able to see their own record as well as their reporting records.

May be I may not explianied here properly. If you have any queries or doubt, please comment or send me an email. I will try to help you!