Report AX 2012 : example Class Data processing
General
DP extends
Example 0 : Customer without Contract
Example 1 : Customer receipt localisation
Example 1 - menu item, query ...
Example 2 : Example from internet
Code simple without controller
Code simple with controller

General
//To deploy a report on an AOS we need to run the service Remote registrery.

AX2012 Create SSRS Report using Data Provider Classes 
RDP implments the standard MVC(Model View Controller) design pattern.
What is MVC?
Model-view-controller (MVC) is a pattern used to isolate business logic from the user interface. 
Model: Responsible for retrieving data and for business logic, this can included queries, data methods,
or other classes that are designed to retrieve data. 
View: Responsible for the User Interface, this can also be thought of as the design for the report. 
Controller: Orchestrates the flow between Model and View 

CONTRACT 		: classDeclaration 	: [DataContractAttribute]
				  methods				: [DataMemberAttribute]
//This class is used to create parameters, parm methods for the reports
//the contract is processing through the builder with the following attribute of the contract class.
//builder class to the contract and adding the logic to lookup the data for the contract parmmethods.

CONTROLLER 		: MAIN method is the method that define the report name. It is the starting point of the report


DATA PROVIDER 	: processReport() fill the tmp table.

Temporation table : set CreateTransactionId = Yes ?

DP extends
If extends SRSReportDataProviderBase -> We must use a tempporary table TempDB.
If extends -> We must use a regular table and do a CreateTransactionId.

//1)
[
    SRSReportQueryAttribute(queryStr(SPLWasteSMAQuotationQuery))
]
class SPLWasteSMAQuotationJourDP extends SRSReportDataProviderBase
{
    SPLWasteSMAQuotationJourReportTmp    SMAQuotationJourReportTmp;   // -> TempDB
}

//2)
[
    SRSReportParameterAttribute(classStr(SalesQuotationContract))
]
public class SalesQuotationDP extends SrsReportDataProviderPreProcess
{
    SalesQuotationDetailsTmp        salesQuotationTmp;				// -> regular Table with CreateTransactionId : Yes
    SalesQuotationHeaderTmp         salesQuotationHeaderTmp;
}


// Method getTableTMP() ... , This method is used in VS to contruct the Query :
[SRSReportDataSetAttribute(tablestr(SPLWasteSMAQuotationJourReportTmp))]
public SPLWasteSMAQuotationJourReportTmp getSMAQuotationJourReportTmp()
{
    select * from SMAQuotationJourReportTmp;
    return SMAQuotationJourReportTmp;
}
In the VS we construct the query with the DP.
Query

Example 0 : Customer without Contract
Query
The query that is in the DP is known in the Controller.
The controller prompt the query after the method modifyContract is done.
The menu button launch the controller.

//Class Controller 
class SPLWasteSMAQuotationJourController extends SrsReportRunController
{
}
protected void prePromptModifyContract()
{
    //super();

    Query                       _query;
    QueryBuildRange             qbr;
    SPLWasteSMAQuotationJour    SPLWasteSMAQuotationJour;


   if ( this.parmArgs()             &&
        this.parmArgs().record()    &&
        this.parmArgs().dataset() == tableNum(SPLWasteSMAQuotationJour))
    {

        SPLWasteSMAQuotationJour = this.parmArgs().multiSelectionContext().getFirst();

        if(!SPLWasteSMAQuotationJour.RecId)
        {
            SPLWasteSMAQuotationJour = this.parmArgs().record();
        }


        _query = this.parmReportContract().parmQueryContracts().lookup(this.getFirstQueryContractKey());

        if (_query)
        {
            _query.dataSourceTable(tableNum(SPLWasteSMAQuotationJour)).clearRanges();
            while (SPLWasteSMAQuotationJour)
            {
				qbr = _query.dataSourceTable(tableNum(SPLWasteSMAQuotationJour)).addRange(fieldNum(SPLWasteSMAQuotationJour, RecId));
                qbr.value(queryValue(SPLWasteSMAQuotationJour.RecId));
                SPLWasteSMAQuotationJour=this.parmArgs().multiSelectionContext().getNext();
            }
       }
    }
}
public static SPLWasteSMAQuotationJourController construct()
{
    return new SPLWasteSMAQuotationJourController();
}
public static void main(Args _args)
{
    SPLWasteSMAQuotationJourController    controller = SPLWasteSMAQuotationJourController::construct();

    controller.parmArgs(_args);

    controller.parmReportName(ssrsReportStr(SPLWasteSMAQuotationJourReport,Report));


    controller.startOperation();
}

//Class DP
[
    SRSReportQueryAttribute(queryStr(SPLWasteSMAQuotationJourQuery))
]
class SPLWasteSMAQuotationJourDP extends SRSReportDataProviderBase
{
    SPLWasteSMAQuotationJourReportTmp    SMAQuotationJourReportTmp;
}
[SRSReportDataSetAttribute(tablestr(SPLWasteSMAQuotationJourReportTmp))]
public SPLWasteSMAQuotationJourReportTmp getSMAQuotationJourReportTmp()
{
    select * from SMAQuotationJourReportTmp;
    return SMAQuotationJourReportTmp;
}
[SysEntryPointAttribute(false)]
public void processReport()
{
    Query                       query;
    QueryRun                    qr;
    SPLWasteSMAQuotationJour    SPLWasteSMAQuotationJour;
    SPLWasteSMAQuotationTrans   SPLWasteSMAQuotationTrans;
    SMAServiceOrderTable        SMAServiceOrderTable;
    ;
    query   = this.parmQuery();
    qr      = new QueryRun(query);
    ttsbegin;
    while (qr.next())
    {
        SMAQuotationJourReportTmp.clear();
        SMAQuotationJourReportTmp.initValue();

        SPLWasteSMAQuotationJour    = qr.get(tablenum(SPLWasteSMAQuotationJour));
        SMAServiceOrderTable        = SPLWasteSMAQuotationJour.SMAServiceOrderTable();
        //SPLWasteSMAQuotationJour           = SPLWasteSMAQuotationJour::findRecId(SPLWasteSMAQuotationJourRecId);
        while select SPLWasteSMAQuotationTrans
        where SPLWasteSMAQuotationTrans.ServiceOrderId == SPLWasteSMAQuotationJour.ServiceOrderId
        {
            SMAQuotationJourReportTmp.clear();
            if (ProjLineProperty::find(SPLWasteSMAQuotationTrans.ProjLinePropertyId).ToBeInvoiced == NoYes::Yes || true)
            {
            SMAQuotationJourReportTmp.QuotationId               = SPLWasteSMAQuotationJour.ServiceOrderId;
            SMAQuotationJourReportTmp.Description               = SPLWasteSMAQuotationJour.Description;
            SMAQuotationJourReportTmp.InterventionPostalAddress = SPLWasteSMAQuotationJour.InterventionPostalAddress;
            if(SPLWasteSMAQuotationJour.InterventionPostalAddress)
            {
                SMAQuotationJourReportTmp.InterventionAddress = LogisticsPostalAddress::addressFromRecId(SPLWasteSMAQuotationJour.InterventionPostalAddress);
            }
            SMAQuotationJourReportTmp.PostalAddress             = SMAQuotationJourReportTmp.InterventionAddress;
            SMAQuotationJourReportTmp.CurrencyCode              = SPLWasteSMAQuotationJour.CurrencyCode;
            SMAQuotationJourReportTmp.ProjTransType             = SPLWasteSMAQuotationTrans.TransactionType;
            SMAQuotationJourReportTmp.SalesQty                  = SPLWasteSMAQuotationTrans.Qty;
            SMAQuotationJourReportTmp.ProjCategoryId            = SPLWasteSMAQuotationTrans.ProjCategoryId;
            SMAQuotationJourReportTmp.CustomerName              = SPLWasteSMAQuotationJour.customerName();
            SMAQuotationJourReportTmp.ProjDescription           = SPLWasteSMAQuotationTrans.Description;
            }
            SMAQuotationJourReportTmp.insert();
        }
    }
    ttscommit;
}

Example 1 : Customer receipt localisation
//***************************************************************************************
//=== CONTRACT [DataContractAttribute,SysOperationContractProcessingAttribute(classStr(QCustReceiptJourReportUIBuilder))]

[
	DataContractAttribute,
	SysOperationContractProcessingAttribute(classStr(QCustReceiptJourReportUIBuilder))
]
public class QCustReceiptJourDC_IL implements SysOperationValidatable
{
	LedgerJournalId             journalNum;
	DimensionDynamicAccount     ledgerDimension;
	NoYesId                     printReport;
}

[
	DataMemberAttribute('JournalNum')
]
public LedgerJournalId parmJournalNum(LedgerJournalId _journalNum = journalNum)
{
	journalNum = _journalNum;
	return journalNum;
}

//***************************************************************************************
//=== CONTROLLER extends SrsReportRunController

class QCustReceiptJourCR_IL extends SrsReportRunController
{
	LedgerJournalId         journalNum;
	DimensionDynamicAccount ledgerDimension;
	NoYesId                 printReport;
}

public static void main(Args _args)
{
	QCustReceiptJourCR_IL   controller = new QCustReceiptJourCR_IL();
	QCustReceiptJour_IL     QCustReceiptJour_IL;
	;
	if(_args && _args.record())
		QCustReceiptJour_IL = _args.record();

	controller.parmReportName('QCustReceipt_IL.CustReceipt');
	controller.parmDialogCaption("@GIL504");
	controller.parmShowDialog(false);

	if(_args && _args.parmEnum() == NoYes::Yes)
		controller.parmShowDialog(true);

	if(QCustReceiptJour_IL)
	{
		controller.parmJournalNum(QCustReceiptJour_IL.JournalNum);
		controller.parmledgerDimension(QCustReceiptJour_IL.LedgerDimension);
		controller.parmPrintReport(!controller.parmShowDialog());
	}
	controller.startOperation();
}

public LedgerJournalId parmJournalNum(LedgerJournalId _journalNum = journalNum)
{
	journalNum = _journalNum;
	return journalNum;
}

protected void preRunModifyContract()
{
    QCustReceiptJourDC_IL contract = this.parmReportContract().parmRdpContract() as QCustReceiptJourDC_IL;
    //07/04/13-SBE-BEGIN
    SrsReportRdlDataContract    rdlContract;
    CustLanguageId              languageId;
    CustTable                   custTable;
    //07/04/13-SBE-END
    ;
    contract.parmPrintReport(true);
    contract.parmJournalNum(this.parmJournalNum());
    contract.parmledgerDimension(this.parmledgerDimension());
    //07/04/13-SBE-BEGIN
    languageId = "HE";
    custTable = CustTable::find(DimensionStorage::ledgerDimension2AccountNum(this.parmledgerDimension()));
    if (custTable.languageId() == "EN-US")
        languageId ="EN-US";
    rdlContract = this.parmReportContract().parmRdlContract();
    rdlContract.parmLanguageId(languageId);
    //07/04/13-SBE-END
}

//this method I don't know if we need it.
public void runReport()
{
    QCustReceiptJourDC_IL contract = this.parmReportContract().parmRdpContract() as QCustReceiptJourDC_IL;
    ;
    if(printReport || contract.parmPrintReport())
        super();
}

//***************************************************************************************
//=== DATA PROVIDER extends SrsReportDataProviderPreProcess 
[
    SRSReportQueryAttribute(querystr(QCustReceipt_IL)),
    SRSReportParameterAttribute(classstr(QCustReceiptJourDC_IL))
]
class QCustReceiptJourDP_IL extends SRSReportDataProviderBase
{
    QReceiptJourTmp_IL          QReceiptJourTmp_IL;
    LedgerJournalId             journalNum;
    DimensionDynamicAccount     ledgerDimension;
    LedgerJournalTrans          ledgerJournalTrans;
    QCustReceiptJour_IL         custReceiptJour_IL;
}

[AifDocumentCreateAttribute, SysEntryPointAttribute(true)]
public void processReport()
{
    Query                               query;
    QueryRun                            qRun;
    QueryBuildDataSource                qbs;
    QueryBuildRange                     qbrjournalNum, qbrLedgerDimension;
    QCustReceiptJourDC_IL               contract = this.parmDataContract() as QCustReceiptJourDC_IL;
										//contract<== (from SRSReportParameterAttribute(classstr(QCustReceiptJourDC_IL))
    ;
    journalNum            = contract.parmJournalNum();
    ledgerDimension       = contract.parmledgerDimension();
    query = this.parmQuery();			//Query   <== (from SRSReportQueryAttribute(querystr(QCustReceipt_IL))
    // Get queryRun from report
    qRun = new QueryRun(query);

    qbs =  qRun.query().dataSourceTable(tablenum(QCustReceiptJour_IL));
    qbrjournalNum = qbs.addRange(fieldnum(QCustReceiptJour_IL,JournalNum));
    qbrjournalNum.value(journalNum);
    qbrLedgerDimension = qbs.addRange(fieldnum(QCustReceiptJour_IL,LedgerDimension));
    qbrLedgerDimension.value(queryValue(ledgerDimension));

    while (qRun.next())
    {
        custReceiptJour_IL      = qRun.get(custReceiptJour_IL.TableId);
        ledgerJournalTrans      = qRun.get(ledgerJournalTrans.TableId);
        this.calculateCustReceipt();
        QCustReceiptJour_IL::updatePrinted(custReceiptJour_IL);
    }
}

[
    SRSReportDataSetAttribute(tablestr(QReceiptJourTmp_IL))
]
public QReceiptJourTmp_IL getQReceiptJourTmp_IL()
{
    select QReceiptJourTmp_IL;
    return QReceiptJourTmp_IL;
}

public void calculateCustReceipt()
{
    ;
    QReceiptJourTmp_IL.initValue();
    QReceiptJourTmp_IL.initFromQCustReceiptJour_IL(custReceiptJour_IL);
    QReceiptJourTmp_IL.initFromLedgerJournalTrans(ledgerJournalTrans);
    QReceiptJourTmp_IL.InitFromCustTable(custReceiptJour_IL.LedgerDimension);
    QReceiptJourTmp_IL.initFromCompanyInfo();
    QReceiptJourTmp_IL.QxShowLocalCurAmount(ledgerJournalTrans,CustVendACType::Cust);

    QReceiptJourTmp_IL.insert();
}

//***************************************************************************************
//=== BUILDER extends SrsReportDataContractUIBuilder
public class QCustReceiptJourReportUIBuilder extends SrsReportDataContractUIBuilder
{
    QCustReceiptJourDC_IL       QCustReceiptJourDC_IL;
    QCustReceiptJourCR_IL       QCustReceiptJourCR_IL;
}

public void Build()
{
    DialogField     dlgPrintReport;
    CustAccount     CustAccount;
    ;
    super();
    // initializing data contract object

    QCustReceiptJourDC_IL = this.dataContractObject();
    QCustReceiptJourCR_IL = this.controller();
    CustAccount = CustTable::findByLedgerDimension(QCustReceiptJourCR_IL.parmledgerDimension()).AccountNum;
    // Get the parameter controls from dialog
    dlgPrintReport = this.bindInfo().getDialogField(QCustReceiptJourDC_IL, methodStr(QCustReceiptJourDC_IL, parmPrintReport));
    dlgPrintReport.label(strFmt("@GIL497",CustAccount));

    QCustReceiptJourCR_IL.parmDialogCaption("@GIL504");
}

Example 1 - menu item, query ...
Example 1 - CustReceipt : Pictures
Menu Item call the controller class
menu item call the controller class
In the dataset Query = "SELECT * FROM QCustReceiptJourDP_IL.QReceiptJourTmp_IL"
The link is done with the Data Provider class QCustReceiptJourDP_IL
Dataset

Example of query
Example of query

Example from internet
//***************************************************************************************
//=== CONTRACT ===[DataContractAttribute,SysOperationContractProcessingAttribute]***********************

[DataContractAttribute,
SysOperationContractProcessingAttribute(classstr(ProdPackListUIBuilder)) ]
public class ProdPacklistContract
{
	SalesId salesId;
	LineNum lineNum
}

[DataMemberAttribute('SalesId')]
public SalesId parmSalesId(SalesId _salesId=salesId)
{
	salesId=_salesId;
	return salesId;
}

[DataMemberAttribute('LineNum')]
public LineNum parmLineNum(LineNum _lineNum=LineNum)
{
	lineNum =_lineNum;
	return lineNum;
}

//***************************************************************************************
//=== CONTROLLER extends SrsReportRunController
public class ProdPackListController extends SrsReportRunController
{
}
public static void main(Args _args)
{
    SrsReportRunController    controller = new  ProdPackListController  ();
    controller.parmReportName("ProdPackList.Report");
    controller.parmArgs(_args);
    controller.startOperation();
}
protected void preRunModifyContract()
{
    GNProdPacklistContract    contract;
    contract = this.parmReportContract().parmRdpContract() as GNProdPacklistContract;
}

if you want to pass the values for the report before promting to user for input you can override this method
prePromptModifyContract 

In my case I am overriding to pass the value and ranges for my query before showing the dialog to user.

protected void prePromptModifyContract()
{
    QueryBuildRange         queryBuildRangeSerial;
    QueryBuildRange         queryBuildRangeProd,qbrTransStatus;

    QueryBuildDataSource    queryBuildDataSource,queryBuildDataSource1,queryBuildDataSource2;
    ProdTable               localProdTable;
    Query                   query;
    // get the report query
    query                   = this.parmReportContract().parmQueryContracts().lookup(this.getFirstQueryContractKey());

    queryBuildDataSource    = SysQuery::findOrCreateDataSource(query, tableNum(ProdTable));
    queryBuildDataSource1   = SysQuery::findOrCreateDataSource(query, tableNum(InventDim));
    queryBuildDataSource2   = SysQuery::findOrCreateDataSource(query, tableNum(InventTrans));

    queryBuildRangeProd     = SysQuery::findOrCreateRange(queryBuildDataSource, fieldNum(ProdTable,ProdId));
    queryBuildRangeSerial   = SysQuery::findOrCreateRange(queryBuildDataSource1, fieldNum(InventDim,inventSerialId));
    qbrTransStatus          = SysQuery::findOrCreateRange(queryBuildDataSource2, fieldNum(InventTrans,StatusReceipt));
    qbrTransStatus.value(queryValue(StatusReceipt::Received));

    if (this.parmArgs().dataset() ==  tableNum(ProdTable))
    {
        localProdTable = this.parmArgs().record();
        queryBuildRangeProd.value(queryValue(localProdTable.ProdId));
        this.parmShowDialog(true);
    }
    else if ((this.parmArgs().menuItemName() == menuitemOutputStr(ProdPacklist)) && (this.parmArgs().dataset() ==0))
    {
        this.parmShowDialog(true);
    }
    else
    {
        throw error(strFmt("Packing list can only printed from Production",funcName()));
    }

}

//***************************************************************************************
//=== DATA PROVIDER extends SrsReportDataProviderPreProcess
//processReport() fill the tmp table.
[
    SRSReportQueryAttribute(queryStr(ProdPackList)),
    SRSReportParameterAttribute(classStr(ProdPacklistContract))
]
class ProdPacklistDP extends SrsReportDataProviderPreProcess
{

    boolean                     showQuery;
    boolean                     firstPage;
    ProdTable                   prodTable;
    ProdId                      prodId;

    CompanyInfo                 companyInfo;

    ProdBOM                     prodBOM;
    InventDim                   inventDim;

    ProdPackingSlipDetailsTmp 	prodPackingSlipDetailsTmp;
    BarcodeSetup                barCodeSetup;
    BarcodeSetupId  		barcodeSetupId;
    Barcode         		barcode;
}

//Create the method which return the tmp table object

[
    SRSReportDataSetAttribute(tableStr('ProdPackingSlipDetailsTmp'))
]
public ProdPackingSlipDetailsTmp getProdPacklistDetailsTmp()
{
    select prodPackingSlipDetailsTmp;
    return prodPackingSlipDetailsTmp;
}

[SysEntryPointAttribute(false)]
public void processReport()
{
    QueryRun                queryRun;
    ProdPacklistContract contract       = this.parmDataContract() as  ProdPacklistContract ;
    // Set the userconnection to use on table.
    // This is required to ensure that createdTransactionId of inserted record is different than default 
           transaction.
    prodPackingSlipDetailsTmp.setConnection(this.parmUserConnection());
    this.init();
    this.setupBarcode();
    queryRun                        = new QueryRun(this.parmQuery());
    while (queryRun.next())
    {
        prodTable       = queryRun.get(tableNum(ProdTable));
        inventDim       = queryRun.get(tableNum(InventDim));
        prodId          = prodTable.ProdId;
        if(prodTable.InventRefType==InventRefType::Sales)
        {
           this.insertHeader();
           this.insertDetails(prodId,inventDim.inventSerialId);
        }
    }
}


private void init()
{
    companyInfo = CompanyInfo::find();
    firstPage   = true;
}


//BP Deviation documented
protected BarCodeString barcode(str _SerialNumber)
{
    str jobId = strupr(_SerialNumber);

    if (barcodeSetup.validateBarcode(jobId))
    {
        barcode.string(true, jobId);
        barcode.encode();
    }
    else
    {
        throw(error(strfmt("@SYS41409", barcode.barcodeType(), jobId)));
    }
    return barcode.barcodeStr();
}

protected void setupBarcode()
{
    barcodeSetupId = JmgParameters::find().getBarcodeSetupId();
    barcodeSetup = BarcodeSetup::find(barcodeSetupId);
    barcode = barcodeSetup.barcode();
}

// assigns the data into header information first

private void insertHeader()
{
    prodPackingSlipDetailsTmp.clear();
    prodPackingSlipDetailsTmp.initValue();
    prodPackingSlipDetailsTmp.SalesId=prodTable.InventRefId;
    prodPackingSlipDetailsTmp.SerialNumber=inventDim.inventSerialId;


    prodPackingSlipDetailsTmp.ProdItemId                = prodTable.ItemId;
    prodPackingSlipDetailsTmp.Description               = prodTable.Name;
    prodPackingSlipDetailsTmp.Customer                  = SalesTable::find(prodPackingSlipDetailsTmp.SalesId).CustAccount;


    prodPackingSlipDetailsTmp.initValue();
    prodPackingSlipDetailsTmp.barcodeSetupId=barCodeSetup.barcodeSetupId;
    prodPackingSlipDetailsTmp.barcodeType=barCodeSetup.barcodeType;
    prodPackingSlipDetailsTmp.fontName=barCodeSetup.fontName;
    prodPackingSlipDetailsTmp.fontSize=barCodeSetup.fontSize;
    prodPackingSlipDetailsTmp.maximumLength=barCodeSetup.maximumLength;
    prodPackingSlipDetailsTmp.minimumLength=barCodeSetup.minimumLength;
    prodPackingSlipDetailsTmp.SerialNumberBarCode=this.barcode(inventDim.inventSerialId);
}


private void insertDetails(ProdId _prodId,InventSerialId _inventSerialId)
{
    SMAServiceObjectTable smaServiceObjectTable;
    SMAServiceBOMTable    smaServiceBOMTable;
    ProdBOM               prodBOMTable;

    while select prodBOMTable order by InventTransId asc
        where prodBOMTable.ProdId==_prodId
    {
        if(InventTable::Find(prodBOMTable.ItemId).PrintItemProduction)
        {
            prodPackingSlipDetailsTmp.ItemId=prodBOMTable.ItemId;
            prodPackingSlipDetailsTmp.Qty=prodBOMTable.BOMQty;
            prodPackingSlipDetailsTmp.Name=prodBOMTable.itemName();
            if(prodBOMTable.SerialnoControlled())
            {
                select TemplateBOMId,ServiceObjectId from smaServiceObjectTable
                    where smaServiceObjectTable.InventSerialId==_inventSerialId
                    && smaServiceObjectTable.ReferenceId==_prodId
                    && smaServiceObjectTable.ReferenceCategory==InventTransType::Production
                join InventSerialId from smaServiceBOMTable where
                    smaServiceBOMTable.ItemId==prodBOMTable.ItemId
                    && smaServiceBOMTable.ObjectId==smaServiceObjectTable.ServiceObjectId
                    && smaServiceBOMTable.ServiceBOMId==smaServiceObjectTable.TemplateBOMId;

                prodPackingSlipDetailsTmp.SerialNo=smaServiceBOMTable.InventSerialId;
            }
            prodPackingSlipDetailsTmp.SalesFormNotes=FormLetterRemarks::find(companyInfo.LanguageId,FormTextType::ProductionPackingList).Txt;
            prodPackingSlipDetailsTmp.insert();
            prodPackingSlipDetailsTmp.SerialNo="";
        }
    }
}

//***************************************************************************************
//=== BUILDER 

public class ProdPackListUIBuilder extends SysOperationAutomaticUIBuilder
        {
            DialogField dialogSalesId;
            DialogField dialogSalesLine;
            SalesId  salesId;
            LineNum  lineNum;
            ProdPacklistContract prodPacklistContract;
            ProdPackListController packListcontroller;
            QueryRun queryRun;
            Query baseQuery;
            ProdTable prodTable;
        }
       public void build()
        {
            FormBuildGroupControl grp;
        
            Dialog      dialogLocal = this.dialog();
            ;
            prodPacklistContract = this.dataContractObject();
            if(this.validateCaller())
            {
                dialogLocal.addGroup("Sales");
                this.addDialogField(methodStr(ProdPacklistContract,parmSalesId), prodPacklistContract);
                this.addDialogField(methodStr(ProdPacklistContract,parmSalesLine), prodPacklistContract);
            }
       }


        public SysOperationController controller()
        {
            SysOperationController ret;
            ret = super();
            packListcontroller=ret;
            return ret;
        }


        private str getFirstQuery()
        {
              // this will just return the first contract key in the Map
            Map queryContracts =packListcontroller.parmReportContract().parmQueryContracts();
            MapEnumerator mapEnum;
            str firstQueryKey;
            if(queryContracts)
            {
                mapEnum = queryContracts.getEnumerator();
                if(mapEnum.moveNext())
                {
                    firstQueryKey = mapEnum.currentKey();
                }
            }
            return firstQueryKey;
        }
        public void getFromDialog()
        {
            prodPacklistContract = this.dataContractObject();
            if(this.validateCaller())
            {
                salesId=dialogSalesId.value();
                LineNum=dialogSalesLine.value();
                this.validateData(salesId,LineNum);
            }
            super();
        }


        public void initializeFields()
        {
            prodPacklistContract = this.dataContractObject();
        }


        private void initquery()
        {
baseQuery=packListcontroller.parmReportContract().parmQueryContracts().lookup(this.getFirstQuery());
            QueryRun=new QueryRun(baseQuery);
            while (queryRun.next())
            {
                prodTable=queryRun.get(tableNum(ProdTable));
                if(prodTable)
                    break;
            }
        }
        public void lookupSalesId(FormStringControl _control)
        {
            Query query = new Query();
            SysTableLookup sysTablelookup;
            sysTablelookup =SysTableLookup::newParameters(tableNum(SalesTable),_control);
            sysTablelookup.addLookupfield(fieldNum(SalesTable,SalesId));
            sysTablelookup.addLookupfield(fieldnum(SalesTable,CustAccount));
            sysTablelookup.addLookupMethod(tableMethodStr(SalesTable,customerName));
        
            query.addDataSource(tableNum(SalesTable));
            if(ProdTable.InventRefType==InventRefType::Sales)
            {
                query.dataSourceTable(tableNum(SalesTable)).addRange(fieldNum(SalesTable, SalesId)).value(queryValue(ProdTable.InventRefId));
            }
            sysTablelookup.parmQuery(query);
            sysTablelookup.performFormLookup();
        }
        public void lookupSalesLine(FormStringControl _control)
        {
            Query query = new Query();
            SysTableLookup sysTablelookup;
            sysTablelookup =SysTableLookup::newParameters(tableNum(SalesLine),_control);
            sysTablelookup.addLookupfield(fieldnum(SalesLine,LineNum));
            sysTablelookup.addLookupfield(fieldnum(SalesLine,Itemid));
            sysTablelookup.addLookupfield(fieldNum(SalesLine,SalesId));
            query.addDataSource(tableNum(SalesLine));
            query.dataSourceTable(tableNum(SalesLine)).addRange(fieldNum(SalesLine, SalesId)).value(dialogSalesId.value());
            query.dataSourceTable(tableNum(SalesLine)).addRange(fieldNum(SalesLine, ItemId)).value(queryValue(prodTable.ItemId));
            if(prodTable.InventRefType==InventRefType::Sales)
            {
                query.dataSourceTable(tableNum(SalesLine)).addRange(fieldNum(SalesLine, InventtransId)).value(queryValue(prodTable.InventRefTransId));
            }
        
            sysTablelookup.parmQuery(query);
            sysTablelookup.performFormLookup();
        }


//Override the postbuild function to bind the lookups for the fields.
        public void postBuild()
        {
            super();
            if(this.validateCaller())
            {
                prodPacklistContract=this.dataContractObject();
                this.initquery();
                // From binding info, get the dialog field for racecode attribute and add button
                dialogSalesId = this.bindInfo().getDialogField(
                                     this.dataContractObject(),
                                     methodStr(ProdPacklistContract,parmSalesId));
                if (dialogSalesId)
                {
                    dialogSalesId.lookupButton(2);
                }
                dialogSalesId.value(" ");
        
                // register override method for lookup cust Group
                dialogSalesId.registerOverrideMethod(methodStr(FormStringControl, lookup), methodStr(ProdPackListUIBuilder, lookupSalesId), this);
                // register override method for modified
                dialogSalesId.registerOverrideMethod(methodStr(FormStringControl, modified), methodStr(ProdPackListUIBuilder, SalesIdModified), this);
        
                //binding info for customer drop down
                dialogSalesLine = this.bindInfo().getDialogField(this.dataContractObject(),
                                     methodStr(ProdPacklistContract,parmSalesLine));
                dialogSalesLine.value(" ");
                // register override method for lookup customer
                dialogSalesLine.registerOverrideMethod(methodStr(FormStringControl, lookup), methodStr(ProdPackListUIBuilder, lookupSalesLine), this);
        
                if (dialogSalesLine)
                {
                    dialogSalesLine.lookupButton(2);
                }
                if(ProdTable.InventRefType==InventRefType::Sales)
                {
                    dialogSalesId.value(prodTable.InventRefId);
                    dialogSalesLine.value(SalesLine::findInventTransId(prodTable.InventRefTransId).LineNum);
                    prodPacklistContract.parmSalesId(prodTable.InventRefId);
                    prodPacklistContract.parmSalesLine(SalesLine::findInventTransId(prodTable.InventRefTransId).LineNum);
                    dialogSalesId.enabled(false);
                    dialogSalesLine.enabled(false);
                }
                if(prodTable.RecId==0)
                {
                    throw error(strFmt("please select valid production order"));
                }
            }
            else
            {
                    prodPacklistContract.parmSalesId("");
           }
        }
// if the salesId is modified we have to load the sales lines 
        public boolean SalesIdModified(FormStringControl _control)
        {
            dialogSalesId.value(_control.valueStr());
            dialogSalesLine.value('');
            return true;
        }
        private boolean validateCaller()
        {
            if((packListcontroller.parmArgs().menuItemName() == menuitemOutputStr(ProdPacklist)) && (packListcontroller.parmArgs().dataset() ==0))
                return false;
            else
                return true;
        }


        private void validateData(SalesId _salesId,LineNum _lineNum)
        {
            boolean ret=true;
            SalesLine salesLine;
            if(this.validateCaller())
            {
                    if(_salesId=="")
                        throw error(strFmt("this production is not linked to sales %1",prodTable.ProdId));
        
                    if(_lineNum==0)
                        throw error(strFmt("this production is not linked to sales %1 ",_salesId,prodTable.ProdId));
                    if(ret)
                    {
                        salesLine= SalesLine::find(_salesId,_lineNum);
                        if(salesLine && salesline.ItemId != prodTable.ItemId)
                        {
                            throw error(strFmt("this production is not linked to sales %1 ,%2",salesLine.ItemId,prodTable.ItemId));
                        }
                    }
            }
        }
      
 This was the new functionality for the adding the lookups for the fields using builder class.

Code simple without controller
If we don't need to pass parameters from the form to the report, we don't need a controller.
Simple report

//=========================================================================//
//Report without controller: No need of controller because
//there is not initialization
//=========================================================================//

//Contract
[DataContractAttribute]
public class SPLExemptionContract
{
    FromDate            fromDate;
    ToDate              toDate;
    SPLRegulationId     regulationId;
    boolean             showQuantity;
}

[
    DataMemberAttribute('FromDate'),
    SysOperationLabelAttribute(literalstr("@SYS5209")),
    SysOperationDisplayOrderAttribute('01')
]
public FromDate parmFromDate(FromDate _fromDate = fromDate)
{
    fromDate = _fromDate;
    return fromDate;
}


//DP
[
    SRSReportQueryAttribute(queryStr(SPLExemption)),
    SRSReportParameterAttribute(classstr(SPLExemptionContract))
]
public class SPLExemptionDP extends SRSReportDataProviderBase
{
    PurchTable              purchTable;
    SPLExemptionTmp         SPLExemptionTmp;

    FromDate                fromDate;
    ToDate                  toDate;
    SPLRegulationId         regulationId;
    boolean                 showQuantity;

    CompanyInfo             companyInfo;
    LogisticsAddressing     address;
    Phone                   phone;
    TeleFax                 teleFax;
    Name                    name;

    boolean                 addressCached;
    boolean                 phoneCached;
    boolean                 telefaxCached;
    boolean                 companyNameCached;

    boolean                 insertCompanyLogo;
}

[
    SRSReportDataSetAttribute('SPLExemptionTmp')
]
public SPLExemptionTmp getSPLExemptionTmp()
{
    select * from SPLExemptionTmp;
    return SPLExemptionTmp;
}
/// 
///    Processes the report business logic.
/// 
/// 
///    This is the main method that processes the whole report logic and inserts the data into the
///    temporary table.
/// 
[SysEntryPointAttribute(false)]
public void processReport()
{
    QueryRun                qr;
    SysDictEnum             sysDictEnum;
    SPLExemptionContract    contract = this.parmDataContract() as SPLExemptionContract;

    //
    PurchLine                       purchLine;
    SPLExemptionTmp                 SPLExemptionTmpLocal;
    TransDate                       WFApprovalDate;
    int                             i;
    //
    companyInfo         = CompanyInfo::find();
    insertCompanyLogo   = true;

    fromDate        = contract.parmFromDate();
    toDate          = contract.parmToDate();
    regulationId    = contract.parmRegulationId();
    showQuantity    = contract.parmShowQuantity();

    qr              = new QueryRun(this.parmQuery());

    while (qr.next())
    {
        purchTable = qr.get(tableNum(PurchTable));
        purchLine  = qr.get(tableNum(PurchLine));

        //this.insertIntoTempTable();
        if (purchTable.PurchStatus != PurchStatus::Backorder)
            continue;
        if ((purchTable.DocumentState != VersioningDocumentState::Approved) &&
            (purchTable.DocumentState != VersioningDocumentState::Confirmed))
            continue;
        if (purchTable.mlm_BidCommittee != "")
            continue;
        if (purchLine.itemId == "23840")
            continue;

        if (purchTable.dataAreaId != curext())
        {
            changecompany(purchTable.DataAreaId)
            {
                WFApprovalDate = purchTable.SPLWorkflowApprovalDate();
            }
        }
        else
        {
            WFApprovalDate = purchTable.SPLWorkflowApprovalDate();
        }
        if ( ((purchTable.SPLRegulationId  == regulationId)  || !regulationId) &&
            WFApprovalDate &&
            ((WFApprovalDate More= fromDate) || !fromDate) &&
            ((WFApprovalDate Less= toDate  ) || !toDate) )
        {
            i++;

            SPLExemptionTmpLocal.clear();
            SPLExemptionTmpLocal.PurchId                        = purchTable.PurchId;
            SPLExemptionTmpLocal.PurchName                      = purchTable.PurchName;
            SPLExemptionTmpLocal.SPLPubApprovalDate             = purchTable.SPLPubApprovalDate;

            SPLExemptionTmpLocal.LineAmount                 = purchLine.LineAmount;
            SPLExemptionTmpLocal.ProcurementCategory        = purchLine.ProcurementCategory;
            SPLExemptionTmpLocal.CompanyId                  = purchLine.dataAreaId;
            SPLExemptionTmpLocal.SPLRegulationId            = purchTable.SPLRegulationId;
            SPLExemptionTmpLocal.CurrencyCode               = purchTable.CurrencyCode;
            SPLExemptionTmpLocal.insert();
        }
    }
    while select PurchId, PurchName, SPLPubApprovalDate, ProcurementCategory, CompanyId,
                 SPLRegulationId, CurrencyCode, sum(LineAmount) from SPLExemptionTmpLocal
    group by PurchId, PurchName, SPLPubApprovalDate, ProcurementCategory, CompanyId,
             SPLRegulationId, CurrencyCode
    {
        SPLExemptionTmp.clear();
        SPLExemptionTmp.PurchId              = SPLExemptionTmpLocal.PurchId;
        SPLExemptionTmp.PurchName            = SPLExemptionTmpLocal.PurchName;
        SPLExemptionTmp.SPLPubApprovalDate   = SPLExemptionTmpLocal.SPLPubApprovalDate;
        SPLExemptionTmp.LineAmount           = SPLExemptionTmpLocal.LineAmount;
        SPLExemptionTmp.ProcurementCategory  = SPLExemptionTmpLocal.ProcurementCategory;
        SPLExemptionTmp.CompanyId            = SPLExemptionTmpLocal.CompanyId;
        SPLExemptionTmp.CategoryName         = EcoResCategory::find(SPLExemptionTmpLocal.ProcurementCategory).Name;
        SPLExemptionTmp.SPLRegulationId      = SPLExemptionTmpLocal.SPLRegulationId;
        SPLExemptionTmp.CurrencyCode         = SPLExemptionTmpLocal.CurrencyCode;

        SPLExemptionTmp.CompanyAddress      = this.companyAddress();
        SPLExemptionTmp.CompanyName         = this.companyName();
        SPLExemptionTmp.CompanyPhone        = this.companyPhone();
        SPLExemptionTmp.CompanyTeleFax      = this.companyTelefax();

        if (insertCompanyLogo)
        {
            SPLExemptionTmp.CompanyLogo = FormLetter::companyLogo();
            insertCompanyLogo = false;
        }
        else
        {
            SPLExemptionTmp.CompanyLogo = conNull();
        }

        if (showQuantity)
            SPLExemptionTmp.PrintNumberLines = NoYes::Yes;
        else
            SPLExemptionTmp.PrintNumberLines = NoYes::No;

        SPLExemptionTmp.insert();
    }
}

Code simple with controller
//If we need to pass parameters from the form to the report, we need a controller.
Simple report