Compile AX 2012




Using below command you can compile the AX-2012

  1. copy and paste the highlighted cd C:\Program Files\Microsoft Dynamics AX\60\Server\MicrosoftDynamicsAX\bin , press enter.
  2. copy and paste the highlighted ,AXBuild.exe xppcompileall /s=06,press enter.

Compnay Currency X++



Company Currency X++



You can find the company Currency using below Code.

CompanyInfo::standardCurrency() 
Ledger::accountingCurrency(CompanyInfo::current()

info(strFmt("%1",CompanyInfo::standardCurrency() ));

info(strFmt("%1",Ledger::accountingCurrency(CompanyInfo::current())));

Ledger Dimension D365FO



Ledger Dimension AX2012 & D365FO



In AX -2012 We use DimensionStorage class and method getDynamicAccount to get the Ledger dimension of the following accounts.

For Instance 
DimensionStorage::getDynamicAccount("ABC",LedgerJournalACType::Ledger);
  1. Ledger
  2. Cust
  3. Vend
  4. Project
  5. FixedAssets
  6. Bank
In D365FO  DimensionStorage is removed and the new class introduces LedgerDynamicAccountHelper to get the Ledger dimension of the following accounts.

For Instance 


LedgerDynamicAccountHelper::getDynamicAccountFromAccountNumber("Project-001",LedgerJournalACType::Project);


WBS key for a project activity X++ code



WBS key for a project activity X++ code 



Using following SQL Query you can retrieve all activities of one project.

select PURPOSE,ACTIVITYNUMBER from smmActivities
where ACTIVITYNUMBER in (
select ActivityNumber from SmmActivityParentLinkTable
join projTable
            on  projTable.Recid=SmmActivityParentLinkTable.refRecId
   and  SmmActivityParentLinkTable.parentType=7


   where projTable.ProjId='PROJ-0000003')



Using following AX Query you can retrieve all activities of one project.

    SmmActivityParentLinkTable  activityParentLinkTable;
        ProjTable                   projTable;
        ProjectActivityNumber           projectActivityNumber;
        smmActivities               smmActivities;
         
            
            
            
         while   select PURPOSE,ACTIVITYNUMBER from smmActivities
           exists join activityParentLinkTable
            where activityParentLinkTable.ActivityNumber==smmActivities.ActivityNumber
           exists join projTable
            where projTable.Recid==activityParentLinkTable.refRecId
            && activityParentLinkTable.parentType==smmActivityParentType::Project
            && projTable.ProjId=="PROJ-0000003"
        {
         //   projectActivityNumber=new ProjectActivityNumber();

           // projectActivityNumber.ActivityNumber=activityParentLinkTable.ActivityNumber;
           info(strFmt("%1 %2",smmActivities.Purpose, smmActivities.ActivityNumber));
     //       _objContract.addProjectActivity(projectActivityNumber);
        }

Compare Records D365FO & AX 2012





How to compare two records buffer field to field. 



public static container compareRecords(Common _record1, Common _record2)
{
    SysDictTable    dictTable = new SysDictTable(_record1.TableId);
    SysDictField    dictField;
    FieldId         fieldId, extFieldId;
    container       ret;
    int             i, j;
    ;

    if (_record1.TableId != _record2.TableId)
        return conNull();

    for (i=1; i<=dictTable.fieldCnt(); ++i)
    {
        fieldId = dictTable.fieldCnt2Id(i);
        dictField = new SysDictField(_record1.tableId, fieldId);

        if (!dictField.isSystem())
        {
            for (j=1; j<= dictField.arraySize(); ++j)
            {
                extFieldId = fieldId2Ext(fieldId, j);

                if (_record1.(extFieldId) != _record2.(extFieldId))
                {
                    ret += [extFieldId, _record1.(extFieldId), _record2.(extFieldId)];
                }
            }
        }
    }

    return ret;
}




For Demo purpose you can use below code in job/runnable class.


static void demoCompareRecords(Args _args)
{
    VendTable vendTable_1 = VendTable::find('ABC'); 
    VendTable vendTable_2 = VendTable::find('XYZ'); 
 
    container   con;
    int         i;
    ;
 
    con = MyClass::compareRecords(vendTable_1 , vendTable_2 );
 
    for (i=1; i<=conLen(con); i+=3)
    {
        info(strFmt("%1, %2 ,%3"
                   ,fieldId2Name(tableNum(VendTable), conPeek(con, i))
                   ,conPeek(con, i+1)
                   ,conPeek(con, i+2)
                   )
             );
    }
}







Pass field value from SalesTable to CustTrans in AX 2012 & D365FO



Pass field value from SalesTable to CustTrans in AX 2012 & D365FO


AX 2012 

Following are the steps to pass the value from Sales Table to custtrans.

1) Create a new field (If not already existing)

2) Create the parm method for that field on CustVoucher class

3) Assign value to this parm method in SalesInvoiceJournalPost.postCustVend() method by using the salesTable buffer

4) Add the code for assigning the variable value(or the parm method value) in CustVoucher.initCustVendTrans() method

And now post an invoice and go to custTrans table to check the field value.

Source AX-2012

D365FO

Add the field in SalesTable 
Add the field in CustTrans
Create Extension class of SalesInvoiceJournalPost
Override postCustVend method using coc 

[ExtensionOf(classStr(SalesInvoiceJournalPost))]
final class SLD_SalesInvoiceJournalPost_Extension
{
    /// <summary>
    ///   Performs the customer related postings.
    /// </summary>
    protected void postCustVend()
    {
        CustTrans                   custTrans;
        Name                        ecomMethodOfPayment = this.salesTable.SLDTenderTypeName;        // getting E-Com method of payment from Sales order

        next postCustVend();

        // getting the customer transaction
        custTrans                   = CustTrans::findByVoucher(this.custInvoiceJour.LedgerVoucher);
        custTrans.selectForUpdate(true);

        // updating the customer transaction
        ttsbegin;
        custTrans.SLDTenderTypeName = ecomMethodOfPayment;
        custTrans.update();
        ttscommit;
    }
}

Please feel free to contact me if you are facing any issue during implementation of this blog.


Settle Clearing Entries (Postdated Check) Status



Settle Clearing Entries (Postdated Check) Status



Recently I face the issue that after posting of payment journal status of a post-dated check was not changed from Open to Post. I have lots of R&D in this but no luck,

So I write a batch job where will change the status of custVendPosted check for me.






    LedgerJournalTable _ledgerJournalTable;
    LedgerJournalTrans _ledgerJournalTrans;
    CustVendPDCRegister custPDC;
    Counter             _counter=0;

    while select forUpdate custPDC
            where custPDC.PDCStatus==PostDatedCheckStatus::Open
            && custPDC.MaturityDate > systemDateGet()
          exists join _ledgerJournalTrans
            where custPDC.LedgerJournalTrans==_ledgerJournalTrans.RecId
          exists join _ledgerJournalTable
            where _ledgerJournalTrans.JournalNum==_ledgerJournalTable.JournalNum
            && _ledgerJournalTable.Posted==NoYes::Yes
    {
               _counter++;
               custPDC.PDCStatus=PostDatedCheckStatus::Posted;
               ttsBegin;
               custPDC.update();
               ttsCommit;

    }
        info(strFmt("Total Number %1 of records updated on %2.",_counter,today()));


Form Data Source Field Method Override D365FO


Form Data Source Field Method Override D365FO



In this demo, I will show to create an extension class of form data source Field class and override method through COC.

Here is the annotation code to create COC



[ExtensionOf(formDataFieldStr(FormName, DataSourceName,DataFieldName))]


In this demo, we are using the HcmWorker form and creating Extension of DirPerson Data source field Personal Title..

[ExtensionOf(formDataFieldStr(HcmWorker, DirPerson,PersonalTitle))]

In actual code, you can find the method in the Hcmworker form 


 [DataField]
        class PersonalTitle
        {
            public Common lookupReference(FormReferenceControl _formReferenceControl)
            {
                return DirUtility::buildAffixReferenceControlLookup(_formReferenceControl, DirNameAffixType::PersonalPrefix);
            }

        }


Here is the code through which we create extensions.

[ExtensionOf(formDataFieldStr(HcmWorker, DirPerson,PersonalTitle))]
final class Demo_Extension
{
}


Here is the code through this we override the method.


[ExtensionOf(formDataFieldStr(HcmWorker, DirPerson,PersonalTitle))]
final class Demo_Extension
{
    public Common lookupReference(FormReferenceControl _formReferenceControl)
    {
        next lookupReference(_formReferenceControl);
        return DirUtility::buildAffixReferenceControlLookup(_formReferenceControl, DirNameAffixType::PersonalPrefix);
    }

}

Now perform build in sync on your module. enjoy


Form Data Source Method override COC D365FO


Form Data Source Method override COC D365FO


Here is the sample how can you override the form data-source event.

In this demo we have created the extension of HcmWorker form data-source (HcmWorker).


Here is the original method  of HcmWorker data-source 

    public boolean validateWrite()
        {
            boolean ret;

            ret = super();

            if (ret)
            {
                partyForm.validateWrite();
            }

            return ret;
        }

Here is the  code to create form data-source extension class 

[ExtensionOf(formdatasourcestr(HcmWorker, HcmWorker))]
final class Demo_Extension
{

}


Here is the code to override the data-source method through COC.

[ExtensionOf(formdatasourcestr(HcmWorker, HcmWorker))]
final class Demo_Extension
{
    public boolean validateWrite()
    {
        boolean ret;

        ret  =  next validateWrite();

        if (ret)
        {
                    
           /// do your code here
        }

        return ret;
    }

}


In last perform Build & Sync.

Important 
Feature available from Build 8.1 PU-20


Virtual Fields Vs Computed Fields

  Virtual Field: A virtual field in D365FO is a field that doesn't have a direct representation in the database. It's a field that y...