Thursday, September 26, 2013

AX2012 : Post costs for a project using X++ code

In this post I would like to share X++ code to post costs for a project without any user intervention. Normally post cost  is a three step process, but before running this process you should have proper data setup in the system and have some transactions against the project:

Step 1: User open post cost screen from project form



Step 2: Click on select button the following selection criterion screen opens up














Step 3 - Post: User fills the selection criterion and click OK, system generates some records based on this selection and those records are shown in the post cost screen as shown below and then user posts the cost and these can be seen in posted transactions of the project.

 
















In this process technically system populates some temporary table buffers based on the user selection criterion and then posts the costs based on the temporary tables populated in step 2. It is important to know the classes and there hierarchy involved in this process.
Hierarchy of classes used to build the temporary table buffers for posting the cost based on user criterion are shown below:















Hierarchy of classes used to post the cost is shown below

 











The three steps shown above can be automated using the below X++ code job:

 


















Let me show you how the code relates to the actual steps:
The selection criterion in step 2 goes here:
You can create a setup to run the code on any setting. For illustration I have used Balance in the job.















The Query criterion in step 2 again goes here


 
The assignment of temporary table buffer to post the cost goes as shown below:














Trigger of post function goes here:




For those who quickly want to reuse the code, here it is:

  Args                                args;
  ProjPeriodPostingSelectCost_Proj    projPeriod;
  ProjId                              projId = strFmt("%1*",'JOB001159'); //Your project Number
  ProjPeriodPostingLedger             projPeriodPosting;

  args = new Args();
  args.parmEnumType(enumNum(ProjCostSales));
  args.parmEnum(ProjCostSales::Cost);
  projPeriod  = ProjPeriodPostingSelect::newProj(args,projId);
  projPeriod.setQueryRange();
  projPeriod.initQuery();
  projPeriod.parmProjLedgerStatus(ProjGroup::periodic2ledgerStatus(ProjLedgerStatusPeriodic::BalanceSheet));
  projPeriod.parmTransActionDate(systemDateGet());
  projPeriod.parmQueryCost(NoYes::Yes);
  projPeriod.parmQueryEmpl(NoYes::Yes);
  projPeriod.parmQueryItem(NoYes::Yes);
  projPeriod.parmProjTimeMaterial(NoYes::Yes);
  projPeriod.parmProjInternal(NoYes::Yes);
  projPeriod.createTrans();

  //Posting the cost
  projPeriodPosting  = ProjPeriodPostingLedger::construct(args);
  projPeriodPosting.getLast();
  projPeriodPosting.parmProjLedgerStatus(ProjLedgerStatus::BalanceSheet);
  projPeriodPosting.parmtransActionDate(systemDateGet());
  projPeriodPosting.parmAcknowledgementDate(systemDateGet());
  projPeriodPosting.parmTmpProjPeriodic(projPeriod.tmpProjPeriodic());
  projPeriodPosting.parmTmpProjPeriodicCost(projPeriod.tmpProjPeriodicCost());
  projPeriodPosting.parmTmpProjPeriodicSale(projPeriod.tmpProjPeriodicSale());
  projPeriodPosting.run();

Next section is for those interested in deep diving into the job:

U might notice that I have declared object of ProjPeriodPostingSelectCost_Proj class instead of ProjPeriodPostingSelectCost and the reason for this is I need to initialize query for the project. If you debug the standard AX class then you will notice that the function to initialize it for a project is called from the dialog() method of class "ProjPeriodPostingSelectCost_Proj "

 





















If you dive into this function you will notice that the query is getting initialized here

















As we are doing this fully behind the scenes and will not be calling the prompt() method so we cannot initialize the query from the base class as it does not has this function






















So in order to initialize our query properly we need to call this method.Another important thing to note is the sequence of calling the methods as shown in job is important.

Thanks for reading the blog. Have a great day!!!
Rachit Garg

Wednesday, September 25, 2013

AX2012 : Custom lookup on Dialog control - A standard AX 2012 example


Recently while debugging a process of approving BOM, I came across a standard AX example where registerOverrideMethod() is used to create lookup on a dialog field. Thought to share with the community.

 

There are some nice blogs which explain more about this method :




 
Apart from having the flexibility to create custom lookups on dialog, this also helps us to reuse the existing code.