How to Validate GSTIN Number in ax 2012

What is GSTIN - Goods & Services Tax Identification Number?

All the business entities registering under GST will be provided a unique identification number known as GSTIN or GST Identification Number.

Currently any dealer registered under state VAT law has a unique TIN number assigned to him by state tax authorities. Similarly, service tax registration number is assigned to a service provider by Central Board of Excise and Customs (CBEC).

Under GST regime, all these parties will come under one single authority and the different identification numbers will be replaced by a single type of registration number for everyone (GSTIN). This will ensure better administration by the authority and greater compliance by taxpayers and hopefully improve tax collection.

Let’s understand the structure of GST Identification Number:

Every taxpayer will be assigned a state-wise PAN-based Goods and Services Taxpayer Identification Number (GSTIN) which will be 15 digit long.
The first two digits of GSTIN will represent the state code according to Indian Census 2011. Each state has a unique two digit code like “27” for Maharashtra and “10” for Bihar.
The next ten digits of GSTIN will be the PAN number of the taxpayer.
13th digit indicates the number of registrations an entity has within a state for the same PAN.

It will be an alpha-numeric number (first 1-9 and then A-Z) and will be assigned on the basis of number of registrations a legal entity (having the same PAN) has within one state.

For example, if a legal entity has single or one registration only within a state then it will be assigned the number “1” as 13th digit of the GSTIN. If the same legal entity gets another or second registration for a second business vertical within the same state, then the 13th digit of GSTIN assigned to this entity will become “2”. Similarly, if an entity has 11 registrations in the same state then it will be assigned letter “B” in the 13th place. This way up to 35 business verticals of any legal entity can be registered within a state using this system.
The fourteenth digit currently has no use and therefore will be “Z” by default.
The last digit will be a check code which will be used for detection of errors.


Will existing taxpayers under Central Excise or Service Tax or State VAT have to apply for fresh registration under GST?

The answer is no. All the taxpayers with PAN validated from CBDT’s database are not required to apply for fresh registration under GST. They can get provisional GSTIN from GST portal with a validity of 6 months so that they can provide relevant data as per GST registration form.

Once they complete data filing process, their provisional registration will get converted into regular registration. After this, further notification by relevant tax authorities will be issued for giving timelines.

However, the service tax assesses having centralized registration will have to apply for a fresh registration in the respective states wherever they operate their businesses.

static void ValidateGSTIN(Args _args)
{
    str RegistrationNumber;

    RegistrationNumber ="24AACHA6869P1Z1";

    #define.alphabets('ABCDEFGHIJKLMNOPQRSTUVWXYZ')
    #define.numbers('0123456789')
    #define.15(15)
    #define.20(20)

    if(
    (strkeep(substr(RegistrationNumber, 1, 2), #numbers) != substr(RegistrationNumber, 1, 2)) ||
    (strkeep(substr(RegistrationNumber, 3, 5), #alphabets)   != substr(RegistrationNumber, 3, 5)) ||
    (strkeep(substr(RegistrationNumber, 8, 4), #numbers) != substr(RegistrationNumber, 8, 4)) ||
    (strkeep(substr(RegistrationNumber, 12, 1), #alphabets)   != substr(RegistrationNumber, 12, 1)) ||
    (strlen(RegistrationNumber)   != #15 ) ||
    (strkeep(substr(RegistrationNumber, 13, 1), #numbers)   != substr(RegistrationNumber, 13, 1)) ||
    (strkeep(substr(RegistrationNumber, 14, 1), #alphabets)   != substr(RegistrationNumber, 14, 1))
    //Number or Charactor
    //(strkeep(substr(RegistrationNumber, 15, 1), #numbers)   != substr(RegistrationNumber, 15, 1))
    //(strkeep(substr(RegistrationNumber, 15, 1), #alphabets)   != substr(RegistrationNumber, 15, 1))
    )
    {
        info("Registration Number must be 2 Number, 5 Charactors, 4 Numbers, 1 Charactor, 1 Number, 1 Charactor, Last Char Number or Alpha");
    }
    else
    {
        info(strFmt("Valid GSTTIN Numbet - %1",RegistrationNumber));
    }

}

How to bind table Columns Name in Custom Lookup in Ax 2012


In this article we will see how to bind table all columns name in custom lookup. For that we have to create table for storing getting table fields and tableid. And in form create custom lookup for display value in dropdown. Create custom lookup in form controls and create method for storing values in table. 

publicvoid lookup()
{
//super();
//A_PurchaseOrder::lookupFields(this);
// A_PurchaseOrder PurchaseOrder1;
    Query                   query = new Query();
    QueryBuildDataSource    queryBuildDataSource,qbds1;
    QueryBuildRange         queryBuildRange,qbr1;
    SysTableLookup          sysTableLookup;
tableNametableName = 'A_PurchaseOrder';
    DictField           dictField;
SysModelElement     tables;
SysModelElement     fields;
A_FieldLookUpTableA_FieldLookUpTable;
    DictTable dictTable;
inttmpTableid =    tablename2id(tableName);
inti;
dictTable = new DictTable(tableName2id(tableName));
select A_PurchaseOrder whereA_PurchaseOrder.TableId == tmpTableid;
if(A_PurchaseOrder.TableId == tmpTableid)
    {
whileselect tables
wheretables.ElementType            == UtilElementType::Table       &&
tables.Name                   == tableName
join fields
wherefields.ElementType        == UtilElementType::TableField&&
fields.ParentModelElement == tables.RecId
        {
dictField = new DictField(tables.AxId, fields.AxId);
selectA_FieldLookUpTablewhereA_FieldLookUpTable.A_TableID == int2str(tmpTableid) &&
A_FieldLookUpTable.Label == dictField.label() &&A_FieldLookUpTable.Field==dictField.name();
if(!(A_FieldLookUpTable.A_TableID) && !(A_FieldLookUpTable.Field==dictField.name() && !(A_FieldLookUpTable.Label == dictField.label())))
            {
//Create table and Add fields Label(String),Field(String),A_TableID(int)
//insert into A_FieldLookUpTable table
A_FieldLookUpTable.Label = dictField.label();
A_FieldLookUpTable.Field  = dictField.name();
A_FieldLookUpTable.A_TableID = int2str(tmpTableid);
A_FieldLookUpTable.insert();
            }
        }
    }
//Create an instance of SysTableLookup with the form control passed in
    sysTableLookup = SysTableLookup::newParameters(tablenum(A_FieldLookUpTable), this);

//Add the fields to be shown in the lookup form
//sysTableLookup.addLookupfield(fieldnum(A_FieldLookUpTable, Label));
    sysTableLookup.addLookupfield(fieldnum(A_FieldLookUpTable,Field));

//create the query datasource
queryBuildDataSource = query.addDataSource(tablenum(A_FieldLookUpTable));
queryBuildDataSource.addSortField(fieldNum(A_FieldLookUpTable, Field), SortOrder::Ascending);
queryBuildRange = queryBuildDataSource.addRange(fieldnum(A_FieldLookUpTable, A_TableID));
queryBuildRange.value(A_FieldLookUpTable.A_TableID);

//add the query to the lookup form
sysTableLookup.parmQuery(query);

// Perform lookup
sysTableLookup.performFormLookup();
}

Making string field a custom lookup on user selection in Ax 2012

Making string field a custom lookup on user selection in Ax 2012

Sometimes we just compile our posts to keep the things at one place so we or someone can get it easily when we in need. This post belongs to the same concept :)

Requirement was to filter the records in grid according to the selection of base enum values from a lookup. Easy task :) but then I had to make a string field a custom lookup on selection of first value from base enum and to make it a read only on selection of second value of the base enum.

This is what I did;

Filter: modified
public boolean modified()
{
    boolean ret;
    ret = super();
    if(str2enum(enum_variable,this.valueStr()) == enum::firstvalue)
    {
        stringField.allowEdit(true);
        stringField .text(' ');
    }
    else
    {
         stringField .allowEdit(False);
         stringField .text(curuserid());
    }
    return ret;
} 

StringEdit: StringField
// This lookup is populating users 
Public void lookup()
{
    Query                   query = new Query();
    QueryBuildDataSource    queryBuildDataSource;
    QueryBuildRange         queryBuildRange;
    SysTableLookup          sysTableLookup;
    ;
    //Create an instance of SysTableLookup with the form control passed in
    sysTableLookup = SysTableLookup::newParameters(tablenum(UserInfo), this);

    //Add the fields to be shown in the lookup form
    sysTableLookup.addLookupfield(fieldnum(UserInfo, id), true);
    sysTableLookup.addLookupfield(fieldnum(UserInfo, name), false); 

    //create the query datasource
    queryBuildDataSource = query.addDataSource(tablenum(UserInfo));
    queryBuildRange = queryBuildDataSource.addRange(fieldnum(UserInfo, Id));
    queryBuildRange.value(element.getusers()); 

    //add the query to the lookup form
    sysTableLookup.parmQuery(query); 

    // Perform lookup
    sysTableLookup.performFormLookup();
} 

// Method to get users
str 100 getusers()
{    
    str 100                     Users;
    ;
    While Select UsersTable where  UsersTable .UserId == Curuserid()
    {
        Select Firstonly SysCompanyUserInfo where SysCompanyUserInfo.EmplId ==  UsersTable.Emplid ;
        Users+= SysCompanyUserInfo.UserId +',';
    }
    if(!Users)
        Return '\"\"' ;
    Return Users ;
}

Hiding parameter or Dynamics filters on SSRS report dialog at runtime

Description:-

Recently I had a requirement to hide report parameters from report dialog based on the caller menu item. So here is how to do it. I will show you the example of Item transaction summary report. Item transaction summary report in AX 2012 feature pack version has the following report parameters:



There are parameter on the report dialog above which are as follows:
·         From Date
·         To Date
·         Item Id
·         Item Group
·         Dimension

And below is the classDeclaration of the contract class, as shown below:

[DataContractAttribute,
    SysOperationContractProcessingAttribute(classstr(ItemTransactionSummaryUIB))]
class ItemTransactionSummaryContract implements SysOperationValidatable
{
    List  ItemGroupIdList,ListItemId;
    BaseDate FromDate,ToDate;
    NoYesId   IsDiamension;
}

The View group fields comes from ItemTransactionSummaryContract class.

Suppose, we want to hide all the parameter from report dialog and just want to display the dynamics filters on the report. You need to modify the UIBuilder class of your report. For Item transaction summary report, the UI Builder class is ItemTransactionSummaryUIB. The build method needs to be modified and the code in Bold below can be used to hide the whole parameter group from SSRS report dialog:

public void build()
{
    FormBuildGroupControl grp;
    grp = this.dialog().curFormGroup();
    grp.frameType();
    grp.columns(2);
    if (this.controller().parmArgs().menuitemName() == "ItemTransactionSummaryController")
    {
        grp.visible(false);
    }
    super ();
 }

Below is the output, after hiding the whole parameter group:



To hide the dynamic filters from SSRS report dialog based on caller menu item, you need to override the following method in your controller class and return false from this method based on your condition:

ShowQueryValues

Override this method in your controller class and write the following code:

public boolean showQueryValues(str parameterName)
{
    //return false;
    If (this.parmArgs().menuItemName() == menuItemOutputStr("ItemTransactionSummaryController"))
    {
        return false;
    }
    else
    {
        return true;
    }
}

You will see the following output when the report is run:



Only the Printer and Print destination options will be shown which is displayed by default on the reports.
SSRS Report Data Provider class in Ax 2012

SSRS Report Data Provider class in Ax 2012

Description:-

There are multiple methods to develop SSRS reports in Microsoft Dynamics AX 2012. This tutorial will guide you in developing Report Data Provider (RDP) based SSRS reports.

RDP based SSRS Reports are used when complex business logic cannot be achieved using AOT query.

Pre-requisites
·         Microsoft Dynamics AX 2012
·         Visual studio 2012
·         SQL Server Reporting Services (SSRS) must be configured
·         Reporting services extensions must be installed in Dynamics AX

Report Data Provider (RDP) Class

Report Data Provider Class is an X++ class that is used to access and process data for a SSRS report. The RDP class processes the business logic based on a specified parameter and/or query and returns a dataset to the reporting services. In order to create a RDP class in AX, you have to extend that class with SRSReportDataProviderBase. This tells AX that this class will be used by reporting services to process the data.

Two important attributes are used in RDP classes:

1) SRSReportQueryAttribute: specifies which AOT query will be used in this report. If the RDP class uses an AOT query to process data, define this attribute at the beginning of the class.
2) SRSReportParameterAttribute: defines the data contract class that will be used by this report to prompt for parameter values. If the RDP class contains any parameters this define this attribute at the beginning of the class.

Both the attributes are optional. If the report does not use any query or does not want any parameter to filter report data, these attributes do not need to be used.

Data Contract Class

A data contract class is an X++ class which contains parm methods with the DataMemberAttribute defined at the beginning of the method. This class is used to define one or more parameters that will be used in a SSRS report.

Table

An AX table is used as the dataset to store data for the report. The RDP class processes the data and stores it in the table which is then used by a SSRS report to render data.

A table can be a temporary table (InMemory or TempDB) or a regular table, but it is Microsoft best practice to use a temporary table.

The type of temporary table is based upon the performance considerations. InMemory temporary table is used when the data set is small, while TempDB is normally used for larger datasets to improve performance.

Report Data Provider (RDP) Class declaration

If you are passing parameter through contract class.

[SRSReportParameterAttribute(classStr(ItemTransactionSummaryContract))]
class ItemTransactionSummaryDp extends SRSReportDataProviderBase
{
    ItemTransactionSummaryContract  contract;
    ItemTransactionSummary          ItemTransactionSummary;
    BaseDate                        _FromDate,_ToDate;
    NoYesId                         _IsDeamensionEnable;
}

Add a new method and name it getItemTransactionSummary. This method is mandatory because reporting services uses this method to get the table buffer containing the processed data.

The SRSReportDataSetAttribute attribute is used to indicate the temporary table name and also tells the reporting services to use this method to retrieve the processed data.

Write the following code in the method:

[SRSReportDataSetAttribute(tableStr("ItemTransactionSummary"))]
public ItemTransactionSummary getItemTransactionSummary()
{
    select * from ItemTransactionSummary;
    return ItemTransactionSummary;
}

Add a new method and name it processReport. This method contains the business logic and is called by reporting services to generate data.

This method will query item transaction details and fill the temporary table buffer. Write the following code in the method:

/// Processes the SQL Server Reporting Services report business logic
/// This method provides the ability to write the report business logic. This method will be called by
/// SSRS at runtime. The method should compute data and populate the data tables that will be returned
/// to SSRS.
[SysEntryPointAttribute]
public void processReport()
{
    InventTrans                         InventTrans;
    InventTransOrigin                   InventTransOrigin;
    
    //Itemid List Object Start
    List                    list1 = new List(Types::String);
    Query                   queryItemId;
    QueryRun                queryRunItemId;
    InventItemGroupItem     InventItemGroupItem;
    QueryBuildDataSource    qbdsItemId;
    ListIterator            ItemIdListIterator;
    //Itemid List Object end    

    contract            = this.parmDataContract() as ItemTransactionSummaryContract;
    _FromDate           = contract.ParmFromDate();
    _ToDate             = contract.ParmToDate();
    _IsDeamensionEnable = contract.parmDiamension();
    //list              = contract.parmItemGroup();
    list1               = contract.parmItemId();   
    
    //Itemid List start
    if(list1 != null)
    {
        ItemIdListIterator  = new ListIterator(list1);
        queryItemId         = new Query(queryStr(dev_ItemTransSumItemIdQry));
        qbdsItemId          = queryItemId.dataSourceTable(tableNum(InventItemGroupItem));

        while(ItemIdListIterator.more())
        {
            qbdsItemId.addRange(fieldNum(InventItemGroupItem, ItemId)).value(ItemIdListIterator.value());
            qbdsItemId.addRange(fieldNum(InventItemGroupItem, ItemDataAreaId)).value(curExt());
            qbdsItemId.addRange(fieldNum(InventItemGroupItem, ItemGroupDataAreaId)).value(curExt());
            ItemIdListIterator.next();
        }
        queryRunItemId = new QueryRun(queryItemId);
        while(queryRunItemId.next())
        {
            InventItemGroupItem = queryRunItemId.get(tableNum(InventItemGroupItem));

            //Get start
            InventTrans.clear();
            InventTransOrigin.clear();

            while select sum(Qty) from InventTrans
            order by InventTrans.DatePhysical
            group by InventTrans.DatePhysical,InventTrans.StatusReceipt,
                InventTrans.ItemId,InventTransOrigin.RecId,InventTransOrigin.ReferenceCategory,
                InventTransOrigin.ReferenceId,InventTransOrigin.ItemId,
                InventTransOrigin.InventTransId,InventTrans.inventDimId
     join InventTransOrigin
            where InventTrans.InventTransOrigin == InventTransOrigin.RecId
                && (InventTrans.StatusReceipt == StatusReceipt::Purchased ||
                    InventTrans.StatusReceipt == StatusReceipt::Received ||
                    InventTrans.StatusReceipt == StatusReceipt::Arrived ||
                    InventTrans.StatusReceipt == StatusReceipt::QuotationReceipt)
                && (InventTrans.StatusIssue != StatusIssue::Sold ||
                    InventTrans.StatusIssue != StatusIssue::Deducted ||
                    InventTrans.StatusIssue != StatusIssue::Picked ||
                    InventTrans.StatusIssue != StatusIssue::QuotationIssue)
                && InventTrans.DatePhysical != dateNull()
                && InventTransOrigin.ReferenceCategory != InventTransType::InventTransaction
            && InventTrans.DatePhysical >= _FromDate
            && InventTrans.DatePhysical <= _ToDate
            && InventTransOrigin.ItemId == InventItemGroupItem.ItemId
            {
   ItemTransactionSummary.clear();
   ItemTransactionSummary.ItemId         = InventTrans.ItemId;
   ItemTransactionSummary.Name           = EcoResProductTranslation::findByProductLanguage(EcoResProduct::findByDisplayProductNumber(InventTrans.ItemId).RecId,'en-in').Name;
   ItemTransactionSummary.ItemGroup      = inventItemGroupItem::findByItemIdLegalEntity(InventTrans.ItemId).ItemGroupId;
   ItemTransactionSummary.Configuration  = InventDim::find(InventTrans.InventDimId).configId;
   ItemTransactionSummary.InventColorId  = InventDim::find(InventTrans.InventDimId).InventColorId;
   ItemTransactionSummary.InventSizeId   = InventDim::find(InventTrans.InventDimId).InventSizeId;
   ItemTransactionSummary.InventStyleId  = InventDim::find(InventTrans.InventDimId).InventStyleId;
   ItemTransactionSummary.FromDate       = Fromdate;
   ItemTransactionSummary.ToDate         = Todate;
   ItemTransactionSummary.UnitId         = InventTableModule::find(InventTransOrigin.ItemId,ModuleInventPurchSales::Invent).UnitId;
   ItemTransactionSummary.IsDimensionEnable = _IsDeaEnable;
   if(ItemTransactionSummary.validateWrite())
   {
               ItemTransactionSummary.insert();
   }
     }
            //Get End
        }
    }
    //Itemid List end
}

If you are using query based data provider class

Processes business logic based on parameters and a query, and then returns the tables as a dataset for the report. Let me explain all the steps mentioned above with an example.

Step 1: Create a new query and add the datasource as Table.

[SRSReportQueryAttribute (querystr(AOTQueryName)), 
SRSReportParameterAttribute(classstr(ItemTransactionSummaryContract))]
class ItemTransactionSummaryDp extends SRSReportDataProviderBase 
{

}

Add a new method and name it processReport. This method contains the business logic and is called by reporting services to generate data.

[SysEntryPointAttribute(false)] 
public void processReport() 
{ 
    QueryRun       queryRun; 
    Query        query; 
    CustTable       custTable; 
    ItemTransactionSummaryContract  Contract; 
    AccountNum       accountNum; 
    QueryBuildDataSource    queryBuildDataSource; 
    QueryBuildRange     queryBuildRange;

    query = this.parmQuery();

    Contract = this.parmDataContract() as ItemTransactionSummaryContract; 
    accountNum = Contract.parmAccountNum();

    // Add parameters to the query. 
    queryBuildDataSource = query.dataSourceTable(tablenum(CustTable));

    if(accountNum) 
    { 
        queryBuildRange = queryBuildDataSource.findRange(fieldnum(CustTable, AccountNum)); 
 if (!queryBuildRange) 
 { 
     queryBuildRange = queryBuildDataSource.addRange(fieldnum(CustTable, AccountNum)); 
 } 
 // If an account number has not been set, then use the parameter value to set it. 
 if(!queryBuildRange.value()) 
 queryBuildRange.value(accountNum); 
    }
    queryRun = new QueryRun(query);
    while(queryRun.next()) 
    { 
        custTable = queryRun.get(tableNum(CustTable)); 
  
 ItemTransactionSummary.AccountNum  = custTable.AccountNum; 
 ItemTransactionSummary.Blocked   = custTable.Blocked; 
 ItemTransactionSummary.PriceGroup  = custTable.PriceGroup; 
 ItemTransactionSummary.Currency  = custTable.Currency; 
 ItemTransactionSummary.insert();
    } 
}

Example for Query and contract class parameter based Data Provider class in Ax 2012
Use a Report Data Provider Class in a Report

SSRS Report UI Builder class in Ax 2012

Description:-

User Interface (UI) Builder Class is used to define the layout of the parameter dialog box that opens before a report is run in Microsoft Dynamics AX. It is used to add the customizations as well as additional fields in the dialog.

Following are the scenarios where UI Builder Class can be used:

1.       Grouping dialog fields
2.       Overriding dialog field events
3.       Adding a customized lookup to a dialog field
4.       Binding dialog fields with Report contract parameters
5.       Changing the layout of the dialog
6.       Adding custom controls to the dialog

To create a UI builder class, extend it with SrsReportDataContractUIBuilder.

Sample UI Builder Class

·         Create a new class. Open AOT à Classes.
·         Right Click on Classes and select New Class. Name it as ItemTransactionSummaryUIB.
·         Open the Class declaration by right clicking on it and selecting View code.
·         Write the following code.

Class ItemTransactionSummaryUIB extends SysOperationAutomaticUIBuilder
{

}

Now open the contract class and add the following line to the header of the class. It will tell the contract class to build the parameter dialog. In other words, it will link the UI Builder Class with the contract class.

[DataContractAttribute,
    SysOperationContractProcessingAttribute(classstr(ItemTransactionSummaryUIB))]
class ItemTransactionSummaryContract implements SysOperationValidatable
{

}

Examples of UI Builder Class Usage

Based on different scenarios, different methods are overridden as shown in the following examples:

Grouping the dialog fields/Changing the layout of the dialog/Adding custom controls to the dialog

To customize the layout and add custom fields, override the build as shown below:

public void build()
{
    DialogGroup dlgGrp;    

    //get the current dialog
    Dialog      dlg = this.dialog();       

    //make required modifications to the dialog
    dlgGrp = dlg.addGroup('Dates');  
    dlgGrp.columns(2);   
    dlg.addField(identifierStr(FromDate));
    dlg.addField(identifierStr(ToDate));    
        
    dlgGrp = dlg.addGroup('Customer');  
    dlg.addField(identifierStr(CustAccount));    
}

This build method is called by the report framework to generate the layout of the dialog.

Binding dialog fields with Report contract parameters. 
Write the following code in the build method:

Public void build()
{
    ItemTransactionSummaryContract   contract;

    contract = this.dataContractObject() as ItemTransactionSummaryContract;

    dialogFromDate    = this.addDialogField(methodStr(ItemTransactionSummaryContract, ParmFromDate),contract);
    dialogToDate      = this.addDialogField(methodStr(ItemTransactionSummaryContract, ParmToDate),contract);
    dialogItemId      = this.addDialogField(methodStr(ItemTransactionSummaryContract, parmItemId),contract);
    dialogItemGroupId = this.addDialogField(methodStr(ItemTransactionSummaryContract, parmItemGroup),contract);
    dialogDiamension  = this.addDialogField(methodStr(ItemTransactionSummaryContract, parmDiamension),contract);
}

Overriding dialog field events/Adding a customized lookup to a dialog field

To add a customized lookup or to override a control method, create a new method containing the business logic. The new method must have the same signature as the method you want to override.
Then, override the postBuild method and register the method to override with the new method created.

In the following example, the lookup method of a field is to be overridden. To do this, create a new method lookupCustGroup and add the following code:

public void lookupCustGroup(FormStringControl _formStringControl)
{    
    Query query = new Query();
    QueryBuildDataSource DS;    
    SysTableLookup sysTablelookup;

    //create a table lookup    
    sysTablelookup = SysTableLookup::newParameters(tableNum(CustGroup),_formStringControl);
    sysTablelookup.addLookupfield(fieldNum(CustGroup,CustGroup));
    sysTablelookup.addLookupfield(fieldNum(CustGroup,Name));

    //create a query
    DS = query.addDataSource(tableNum(CustGroup));
    DS.addRange(fieldNum(CustGroup,PaymTermId)).value('N030');

    //assign the query and call lookup
    sysTablelookup.parmQuery(query);
    sysTablelookup.performFormLookup();
}

Now, override the postBuild method and write the following code:

public void postBuild()
{
    DialogField dlgCustGroup;
    
    super();
    
    //get the field to override by providing the data contract object and the associated attribute/method
    dlgCustGroup = this.bindInfo().getDialogField(this.dataContractObject(),
                methodStr(ItemTransactionSummaryContract,parmCustGroupId));

    //register the method we want to override
    dlgCustGroup.registerOverrideMethod(
          methodStr(FormStringControl, lookup),
          methodStr(ItemTransactionSummaryUIB,lookupCustGroup),
          this);    
}

bindInfo returns an object of type SysOperationUIBindInfo. It contains information about the dialog controls bounded to a report contract. postBuild method is called when dialog is created.

Also you can create lookup using the AOT query and use in UI Builder class like below.

I have used below AOT query to get ItemGroupId for creating lookup in SSRS report.

 

UI Builder class declaration

class ItemTransactionSummaryUIB extends SysOperationAutomaticUIBuilder
{
    DialogField                    dialogItemGroupId;
    ItemTransactionSummaryContract ItemTransactionSummaryContract;
}

Build method

public void build()
{
    ItemTransactionSummaryContract   contract;
    contract = this.dataContractObject() as ItemTransactionSummaryContract;
 dialogItemGroupId = this.addDialogField(methodStr(ItemTransactionSummaryContract, parmItemGroup),contract);
}

PostBuild method

public void postBuild()
{
    ItemTransactionSummaryContract   contract;
    super();
    contract = this.dataContractObject() as ItemTransactionSummaryContract;
    dialogItemGroupId = this.bindInfo().getDialogField(contract,methodStr(ItemTransactionSummaryContract, parmItemGroup));
    dialogItemGroupId.registerOverrideMethod(methodStr(FormStringControl, lookup),
        methodStr(ItemTransactionSummaryUIB, ItemGroupLookup),this);
    if (dialogItemGroupId)
    {
        dialogItemGroupId.lookupButton(2);
    }
}

Lookup method

private void ItemGroupLookup(FormStringControl _control1)
{
    Query       query;
    container   conItemGroup;

    query = new Query(queryStr(dev_ItemTransSumItemGroupQry));
    SysLookupMultiSelectGrid::lookup(query,_control1,_control1,conItemGroup);
}

If you have check box and you want to enable/disable other control based on the checkbox tick you also can do using the UI Builder class.

class ItemTransactionSummaryUIB extends SysOperationAutomaticUIBuilder
{
    DialogField                    dialogDiamension;
    ItemTransactionSummaryContract ItemTransactionSummaryContract;
}

public void build()
{
    ItemTransactionSummaryContract   contract;
    contract = this.dataContractObject() as ItemTransactionSummaryContract;
    
    dialogDiamension = this.addDialogField(methodStr(ItemTransactionSummaryContract, parmDiamension),contract);
}

public void postBuild()
{
    ItemTransactionSummaryContract   contract;
    super();
    contract = this.dataContractObject() as ItemTransactionSummaryContract;
 
    dialogDiamension  = this.bindInfo().getDialogField(contract, methodstr(ItemTransactionSummaryContract, parmDiamension));
    dialogDiamension.registerOverrideMethod(methodstr(FormCheckBoxControl, modified),
        methodstr(ItemTransactionSummaryUIB, dialoggetDiamension), this);
    //dialogToDate.enabled(any2enum(dialogDiamension.value()));
    if (dialogDiamension)
    {
        dialogDiamension.value();
    }
}

public boolean dialoggetDiamension(FormCheckBoxControl _checkBoxControl)
{
    ;
    if(any2enum(dialogDiamension.value()) == true)
    {
      //return true;
      //dialogToDate.enabled(any2enum(dialogDiamension.value()));
    }
    else
    {
      //return false;
    }
    //set enabled or disabled based on checkbox
    dialogFieldTransDate.enabled(any2enum(dialogFieldAllowModifyDate.value()));

    //or alternatively
    dialogFieldTransDate.enabled(_checkBoxControl.checked());

    return true;
}