Tuesday, November 15, 2016

Batch jobs in AX 2012

Today, I will demo about batch jobs in AX 2012. At first, I will let you explore the Batch Server Overview on msdn. You have to follow all the steps as given bellow:
1. Configure an AOS instance as the batch server. (Click System administration > Setup > System > Server configuration).

2. Create a new Batch Group, name it ProcessD (Click System administration > Setup > Batch group).
 3. Add available batch server for batch group that has been created.
Now we have to create and schedule a batch job. Let's say we are going to schedule a batch which will fetch the number of purchase orders that are invoiced and add the count in a table named PurchaseOrders. So let's add a custom table Purchase Orders adding two fields DateTill and TotalPurchaseOrder.
Now create a class "ProcessingDataBatch", set it run at server. Also make sure you extend it with RunBaseBatch to make it behave like a batch job.



class ProcessingDataBatch extends RunBaseBatch
{
}
private void processdata()
{
    PurchTable          purchTable;
    PurchaseOrders      purchaseOrder;
    ttsBegin;

    select count(PurchId) from purchTable
        where purchTable.PurchStatus == PurchStatus::Invoiced;

    if (purchTable.PurchId)
    {
        purchaseOrder.TotalPurchOrders = purchTable.PurchId;
        purchaseOrder.DateTill         = today();
        purchaseOrder.insert();
    }


    ttsCommit;
}
public void run()
{
   this.processdata();
}
public static ClassDescription description()
{
    return "Process Data";
}
public static void main(Args _args)
{
    ProcessingDataBatch scheduler = new ProcessingDataBatch();

    if (scheduler.prompt())
    {
        scheduler.run();
    }
}

Now next thing is to compile the code and Generate Increment CIL which is required to setup every time you update the code.

In order to deploy the above class as batch Process job, we can do it in two way. Either to create a ax job or a action menu item.

static void ProcessingData(Args _args)
{
    BatchHeader header;
    SysRecurrenceData sysRecurrenceData;
    Batch batch;
    BatchJob batchJob;
    ProcessingDataBatch _ProcessIncrement;
    BatchInfo processBatchInfo;
    BatchRetries noOfRetriesOnFailure = 4;
;

    select batch where batch.ClassNumber == classnum(ProcessingDataBatch);
    if(!batch)
    {
        header = BatchHeader::construct();
        _ProcessIncrement = new ProcessingDataBatch();
        processBatchInfo = _ProcessIncrement.batchInfo();
        processBatchInfo.parmRetriesOnFailure(noOfRetriesOnFailure);
        processBatchInfo.parmCaption("Process Data");
        header.addTask(_ProcessIncrement);
        // Set the recurrence data
        sysRecurrenceData = SysRecurrence::defaultRecurrence();
        SysRecurrence::setRecurrenceStartDateTime(sysRecurrenceData, DateTimeUtil::addSeconds(DateTimeUtil::utcNow(), 20));
        SysRecurrence::setRecurrenceNoEnd(sysRecurrenceData);
        SysRecurrence::setRecurrenceUnit(sysRecurrenceData, SysRecurrenceUnit::Minute);
        header.parmRecurrenceData(sysRecurrenceData);
        // Set the batch alert configurations
        header.parmAlerts(NoYes::No, NoYes::Yes, NoYes::No, NoYes::Yes, NoYes::Yes);
        header.save();
        // Update the frequency to run the job to every two minutes
        ttsbegin;
        select forupdate batchJob
            join batch
        where batchJob.RecId == batch.BatchJobId
        && batch.ClassNumber == classnum(ProcessingDataBatch);

        sysRecurrenceData = batchJob.RecurrenceData;
        sysRecurrenceData = conpoke(sysRecurrenceData, 8, [3]);
        batchJob.RecurrenceData = sysRecurrenceData;
        batchJob.update();
        ttscommit;
    }

}
When you execute this AX job, you would be able to see a new batch job created in waiting state at System Administration > Inquiries > Batch jobs > Batch jobs with caption Process Data.

 Another way is to add an action menu item ProcessingDataBatchSchedule
Open action menu item select the available batch group as created above and set the recurrence as needed.

See the batch job state here, you can specify alerts check logs and modify recurrence, remove or delete batch jobs etc. Hope this blog post is going to help you in start your work on batch jobs. You can explore the batch jobs in this post as well.

Tuesday, November 1, 2016

Dynamics AX Date Calculator : How to get The difference between two date in ax 2012 in detail years months days

You often try to calculate the differences between two dates using the available functions in dynamics ax for dates. However, for example I have two dates such as start date = 07/07/2007 and end date = 01/11/2016 where date caculator would show difference like 9 Years 3 Months 25 Day. What if the same detail calculation I have to perform in X++. This post will save your time since we might sometimes require this code during ax programming.
 static void AXDateCaculator(Args _args)  
 {  
     int monthsDiff, daysDiff, yearsDiff;  
     date emergingDateMth, emergingDateYear;  
     str dateCalculated;  
     //Dates can be changed here  
     date startdate = mkDate(7, 7, 2007);  
     date endDate  = mkDate(1, 11, 2016);  
     ///  
     yearsDiff                  = intvNo(endDate,startDate,IntvScale::Year);       
     emergingDateYear              = DateMthFwd(startDate, yearsDiff*12);                          
     monthsDiff                 = intvNo(endDate,emergingDateYear,IntvScale::YearMonth);  
     if (monthsDiff < 0)  
     {    
       yearsDiff                = yearsDiff - 1;  
       emergingDateYear            = DateMthFwd(startDate, yearsDiff*12);                          
       monthsDiff               = intvNo(endDate,emergingDateYear,IntvScale::YearMonth);  
     }  
     emergingDateMth               = DateMthFwd(emergingDateYear, monthsDiff);  
     daysDiff                  = intvNo(endDate,emergingDateMth,IntvScale::MonthDay);  
     if (daysDiff < 0)  
     {  
       monthsDiff               = monthsDiff - 1;  
       emergingDateMth            = DateMthFwd(emergingDateYear, monthsDiff);  
       daysDiff                = intvNo(endDate,emergingDateMth,IntvScale::MonthDay);  
     }   
     
     if(daysDiff < 0)
     {
        daysDiff = 365 + daysDiff;
     }

     if (yearsDiff)  
     {  
       dateCalculated             += strfmt(" Years: %1", yearsDiff);              
     }   
     if (monthsDiff)  
     {  
       dateCalculated             += strfmt(" Months: %1", monthsDiff);             
     }  
     if (daysDiff)  
     {  
      dateCalculated             += strfmt(" Days: %1", daysDiff);              
     }  
     info(dateCalculated);   
 }  
After you execute this code you will see this result:
Happy Daxing :)!

Tuesday, March 15, 2016

CIL Code in AX 2012

Often you must be looking into the the message, ".....Generate incremental CIL before running CIL code" when any AOT class, table or project you are going to compile


I recommend you to understand the concept of CIL because some times your changes doesn't show any effect even after compiling the code. The main reason behind this could be because the CIL code is not generated. I am giving you an example for this. I added few fields recently in performa invoice every time I clicked performa invoice the fields that were added were not showing any modified value. In order to address this thing, I tried many things but it didn't work eventually I generated incremental CIL and then it started working!!. It is quite evident from this there has been CIL code behind performa invoice which has to be generated. Also I am writing few things related to CIL and concept of CIL bellow.



Concept of CIL, Why CIL?

At first let's understand  the concept of  "CIL" in Dynamics AX. There are multiple blogs are written already to elaborate the concept of CIL. Here I am writing few lines in my own words.

CIL is common intermediate language which is low level language used by .NET framework.  And as most of you guys must be aware of the concept of CLR which is actually the run-time environment provided by the .NET framework. CLR understands "CIL", it doesn't work directly with high level languages such as C#, Visual Basic or X++.

Dynamics AX 2012 is able to generate Common Intermediate Language from X++.  As this diagram shows, that AX 2012 has the ability to compile P-Code to CIL, and therefore AX 2012 is able to run X++ code directly into the CIL, which is much faster the P-Code compiler we had before.



This above snapshot is taken from the source:- http://axwonders.blogspot.in/2013/04/ax-2012-cil-how-does-it-work.html, which explains the same process in detail.

The major benefit of using CIL is due to the fact that converting the X++ code to CIL will have very positive impact on performance such as switching between X++ run-time and CLR can greatly be reduced.

Further I would recommend you to read these two blogs

http://dev.goshoom.net/en/2013/03/x-to-cil/
http://axwonders.blogspot.com/2013/04/ax-2012-cil-how-does-it-work.html