Thursday, 20 February 2014

X++ code to reset ListEnumerator

Hi Friends,
Sometimes we need to iterate a list enumerator multiple times. We can use reset() function to easily do this as shown below:


AX2012 R2 CU7: X++ code to post Product Receipt for a Purchase Order

Hi Friends,
The below can be used to post the product receipt for a purchase order. It is same as we used to do in previous version but it is good to keep it handy.

The main thing is to pass the parameters in update method. The below job will post the product receipt for the inventory quantities which have been Registered. Please note the purchase order should be confirmed before posting the product receipt.

To reuse it quickly, here it is:

static void Job12(Args _args)
    PurchTable  purchTable = PurchTable::find("000032");
    PurchFormLetter     purchFormLetter;
    purchFormLetter = purchFormLetter::construct(DocumentStatus::PackingSlip);
    purchFormLetter.update( purchTable,


Tuesday, 18 February 2014

AX2012 R2 CU7 : Creating pay periods lookup in Payroll module

Hi Friends,
Recently I was working on some customizations in Payroll module and was required to create controls to select pay cycle and pay periods. I want to share this information on how we can create lookups for pay periods based on a pay cycle.
In standard AX, Pay cycles and pay periods are defined in payroll > setup > pay cycles and pay periods as shown below:

A standard AX example is the dialog of generate pay statements,where user first selects a pay cycle and based on that pay cycle, the pay periods are shown in the control as shown below, the pay periods are specific to the pay cycle:

So I looked into the class to understand how the lookup is coming and found the following, system was storing all the values in a container and then adding them to the combo box control. So I have tried to highlight the code used in the process:

When user selects a payCycle then the method to create the period list is called

In this method the container to hold the payPeriodList is populated with all the valid values, system is selecting all the pay period and then converting it into a string format and then adding it to container and the combo box selection list

In order to read the user selection the value is fetched from the container based on the selection in the combo Box control

So I followed the same pattern, and create a form as shown below :

1. Created a new reference group control for the pay cycle control, these controls are really helpful in AX2012.

Now if I open my form, I see all the pay cycles of the system

2. Then add a new combo box control to show the pay period lookup

Change the auto declaration to true

Declare the variables in class, a container to store the data and the variables to hold the user selection

Then copied the createPayPeriod method and removed the unwanted code. The same pattern is used in benefit register report UI builder class, the below code is copied from there:

On the modified of the pay cycle control I called this method:

And we are all set to go. On my form I have now lookups of pay cycle and pay period as per standard AX design.

Another great example of reusing standard AX code rather then reinventing the wheel. Thanks for reading the blog.

Saturday, 8 February 2014

AX2012 R2 CU7: X++ code to create and post route card journal for production order

Hi Friends,
The below code can be used to create and post route card journal in AX2012 R2 CU7 for a production order when we know the Production order number and the operation number.
I have assigned the costing resource defined on the route as the work center ID in this case.

static void createRouteCardJournalSample(Args _args)
    ProdJournalTable                      prodJournalTable;
    ProdJournalRoute                     prodJournalRoute;
    ProdRoute                               prodRoute;
    ProdId                                     prodId = 'PO000065';
    OprNum                                  oprNum = 10;
    RouteOprId                              routeOprId;
    ProdJournalCheckPostRoute     prodJournalCheckPostRoute;

    select prodRoute where prodRoute.ProdId == prodId
                        && prodRoute.OprNum == oprNum;

    prodJournalTable.JournalType        = prodjournaltype::RouteCard;
    prodJournalTable.ProdId             = prodId;
    prodJournalTable.JournalNameId      = ProdParametersDim::findDefault().RouteJournalNameId;
    prodJournalTable.Description        =                                                  ProdJournalName::find(prodJournalTable.JournalNameId).Description;
    prodJournalTable.VoucherSeqRecId    = ProdJournalName::find(prodJournalTable.JournalNameId).VoucherSeqRecId;
    prodJournalTable.VoucherDraw        = journalVoucherDraw::Post;
    prodJournalTable.NumOfLines         = 1;

    //Route card entry
    prodJournalRoute.JournalId               = prodJournalTable.journalId;
    prodJournalRoute.ProdId                   = prodId;
    prodJournalRoute.OprNum                = oprNum;
    prodJournalRoute.OprId                    = prodRoute.OprId;
    prodJournalRoute.JobType                = RouteJobType::Process;
    prodJournalRoute.CategoryHoursId   = prodRoute.SetUpCategoryId;
    prodJournalRoute.CategoryQtyId      = prodRoute.ProcessCategoryId;
    prodJournalRoute.DefaultDimension  = prodRoute.DefaultDimension;
    prodJournalRoute.WrkCtrId              = prodRoute.WrkCtrIdCost;
    prodJournalRoute.QtyGood              = 2;
    prodJournalRoute.Hours                   = 1;
    ProdJournalCheckPostRoute = ProdJournalCheckPostRoute::newPostJournal(prodJournalRoute.journalId,true);;