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 :)!