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
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();
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.
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 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:
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