From RunBase to SysOperation : Business Operation Framework

RunBase framework

Whenever you write a class that typically asks a user for input and then starts a process based on that input you use the RunBase framework as most of the typical methods needed for such a Job is already implemented in the RunBase class. This means that using the RunBase framework is done by extending RunBase either by directly extending RunBase or by extending a class that extends RunBase.

Some of the features implemented in the RunBase framework are the following:

• Run: The main flow of the operation

• Dialog: Prompting the user for input and storing that input

• Batch execution: Schedule the Job for later execution

• Query: Used to select data

• Progress bar: Shows the progress of a task

• Pack/unpack with versioning: Remember variable values until the next time

the task is executed

Just go through the below Post:

http://daxmusings.codecrib.com/2011/08/from-runbase-to-sysoperation-business.html

Generate number Sequence

Suppose we want create number sequence for Test field on form in General ledger module

Consideration: EDT-Test, Table-TestTable and Form- TestTable

  1. Create new EDT with name Test

Step 2. Modify load module() method on NumberSeqModuleLedger class at end with below code:

{

  1. parmDatatypeId(extendedTypeNum(Test));

     datatype.parmReferenceHelp(literalStr(“Test”));

     datatype.parmWizardIsManual(NoYes::No);

     datatype.parmWizardIsChangeDownAllowed(NoYes::No);

     datatype.parmWizardIsChangeUpAllowed(NoYes::No);

     datatype.parmWizardHighest(999);

     datatype.parmSortField(30);

  1. addParameterType(NumberSeqParameterType::DataArea, true, false);

     this.create(datatype);

}

Step 3.Create a method on LedgerParameters Table

     client server static NumberSequenceReference numRefTest()

{

     return NumberSeqReference::findReference(extendedTypeNum(Test));

}

Step 4.Write and run following job

static void NumberSeqLoadAll(Args _args)

{

   NumberSeqApplicationModule::loadAll();

}

Step 5.Then run the wizard

Organization Administration -> CommonForms -> Numbersequences->Numbersequences-> Number Sequence->Generate   run the wizard.

Create your own Number Sequence by using the above wizard.

Step 6.Now we have to check the number sequence  is correctly working  for that write a job:

static void NumSeq(Args _args)

{

   NumberSeq numberSeq;

   Test num;

   ;

   numberSeq = NumberSeq::newGetNum(ProjParameters:: numRefTest ());

   num = numberSeq.num();

   info(num);

}

Step 7.Now we want that Number Sequence in form level(Test Table):

Write below code in class declaration  

public class FormRun extends ObjectRun

{

   NumberSeqFormHandler numberSeqFormHandler;

}

Step 8.Write the NumberSeqFormHandler() in form methods node.

NumberSeqFormHandler numberSeqFormHandler()

{

   if (!numberSeqFormHandler)

   {

       numberSeqFormHandler = NumberSeqFormHandler::newForm(LedgerParameters:: numRefTest ().NumberSequenceId,

                                                             element,

                                                             TestTable_DS,

                                                             fieldNum(TestTable, Test)

                                                            );

   }

   return numberSeqFormHandler;

}

Step 9.Write the Create(),Delete(),Write() , Validate Write(),Link Active() on the Data source methods node.

Create() Method

void create(boolean append = false,

           boolean extern = false)

{

   element.numberSeqFormHandler().formMethodDataSourceCreatePre();

   super(append);

   if (!extern)

   {

       element.numberSeqFormHandler().formMethodDataSourceCreate(true);

   }

}

Delete() Method

public void delete()

{

   element.numberSeqFormHandler().formMethodDataSourceDelete();

   super();

}

Write()Method

public void write()

{

   super();

   element.numberSeqFormHandler().formMethodDataSourceWrite();

}

Validate Write() Method

public boolean validateWrite()

{

   boolean         ret;

   ret = super();

   ret = element.numberSeqFormHandler().formMethodDataSourceValidateWrite(ret) && ret;

   if (ret)

   {

       TestTable.validateWrite();

   }

   return ret;

}

Link Active() Method

public void linkActive()

{

   ;

   element.numberSeqFormHandler().formMethodDataSourceLinkActive();

   super();

}

To get list of all Classes & Tables in AOT

To get list of all Classes In AOT

static void AllClassesInAOT(Args _args)
{
SysDictionary dictionary = new SysDictionary();
ClassId id;
;
id = dictionary.classNext(0);
while(id)
{
info(classId2Name(id));
id = dictionary.classNext(id);
}
}

To get list of all Tables In AOT

static void lookupAOTTables(FormStringControl _ctrl)
{
UtilElements    UtilElementsLocal;

while select * from UtilElementsLocal
where UtilElementsLocal.recordType == UtilElementType::Table // Here we can get list of Enum, EDT etc..
//&& UtilElementsLocal.utilLevel == global::currentAOLayer()         //Prints Current Layer Tables
{
info(UtilElementsLocal.name) ;
}
}

Creating Info part & Cue Part (Fact Boxes) in Ax 2012

Hi today I’m going to explain you about how to create Info part & Cue Part (Fact Boxes) in Ax 2012.
In this example we are going to take
Two Tables: CustInfo & TransInfo
EDT :CustId
Queries: CustTransInfoPartQuery
Info Part: CustTransInfoPart
Menu Item: CustTransMI
Note: CustId in both tables is an EDT CustTrans have an relation as shown below:
1
To create Query
Note:
Make sure you set Dynamic Property set to yes to get all fields into data source & also

Set relation as yes in TransInfo_1 Data Source.

2-a
To Create the Info Part

  1. In the AOT, click Parts, right-click Info Parts, and then click New Info Part. A part is added to the Info Parts node.
  2. 3
  3. Click the new info part. In the property sheet, click the Name property and specify a name that uniquely identifies the info part.
  4. Click Query and then select the query to use to obtain the data fields for the part.
  5. Click Caption, and then select the label. This label will appear in the title bar of the FactBox.444444
  6. Click Layout. In the property sheet, click ShowMore and then click Yes. This property adds More as a link at the bottom of the FactBox.
  7. Click ShowMoreDataSource and select a data source. The FormRef property of the main table of the selected data source specifies the form that opens when you click the More link in the FactBox.
  8. To organize the data fields that appear in the FactBox, add one or more groups to the info part. To add a group, right-click Layout, and then click New Group.
  9. For each group in the Layout node, click the group and supply values for the following properties
  10. Each group in the info part must have one or more data fields. To add a field, right-click the group, and then click New Field. For each field you add to a group, click the field, and then supply values for the following properties.    5
  11. Right-click Actions, and then click New Action.
  12. Click the action, click the Name property, and then enter a name that uniquely identifies the action.
  13. Click the MenuItemType and select the type of menu item associated with the action you want to perform. For example, click Display to select from the menu items listed in the Menu Items > Display node of the AOT.

Creating Menu Item:
6Click MenuItemName and then click the menu item that you want to use.
7Right-click the info part and then click Save.
Create a form as shown below :
8
Rename the form & add Data source
9In designs -> design -> Grid add CustId & CustName to show in the Form
Place the CustTransMI Menu Item into parts section of form & change properties as shown
10Here you go the output screenshot
11

For Cue & Cue Group

https://erpdax.wordpress.com/2014/10/13/cue-cue-group/

Thanks,
Have a nice day..

Report Data provider [RDP] as data source type in data set – SSRS reports [Dynamics ax 2012]

I am excited to share this new source of data[RDP] for the dataset..We all know in the older version, for a dataset we had only Query and Business logic as a dataset source in SSRS reports. Now in the current version, we have actually 4 options : Query, Business Logic, Report data provider and AX Enum provider.

Today, I will be covering the Report data provider. An RDP class is an X++ class that is used to access and process data for a Reporting Services report. An RDP class is an appropriate data source type when the following conditions are met.

hmmmm.. confused..let me explain with an example. It will be all clear soon 🙂

First things first: The following elements are required to set RDP as your data source type.

step 1: Query
step 2: Temporary table – RDP class fills a temporary table with data that will be used by Reporting Services to display the report.
[msdn help]
step 3:Data contract class – To define the parameters in the report.

step 4:Report data provider class – processes business logic based on parameters and a query, and then returns the tables as a dataset for the report. [msdn help]

Let me explain all the steps mentioned above with an example
For step 1: Create a new query by name SR_CustTable and add the dataasource as CustTable as shown below

Next step 2: Let us create a new temporory table by name TmpSR_CustTable and add 4 new fields as shown below. Ensure that you set the Table type propert as TempDB or InMemory

Use an InMemory temporary table if the dataset is small, for reports that will display fewer than 1000 records.

Use a TempDB temporary table for large datasets to improve performance.

In the below Table: I have set the Table type property to TempDB to improve the performance.Also, I have dragged dropped 4 fields AccountNum, Blocked, priceGroup, Currency as shown below.

Step 3: Now we need to Data Contract class – which will help to define parameters in the report.

Create a new class by name “SRSRDPCustTableContractClass” and add a AccountNum global variable as shown below

class SRSRDPCustTableContractClass
{
AccountNum accountNum;
}
______________________________________________
Add one more parm method to it as shown below

[DataMemberAttribute(“AccountNum”),

SysOperationLabelAttribute(literalstr(“@SYS316394”))

]
public AccountNum parmAccountNum(AccountNum _accountNum = accountNum)
{
accountNum = _accountNum;
return accountNum;
}
________________________________________________
Done…Lets move to Step 4

Step 4:
Now we need to create Report Data provider class
Create a new class by name “SR_CustTableRDP” that should extend SRSReportDataProviderBase class.

Attach the SRSReportQueryAttribute attribute to specify the query to use to get the data for the report.

For this example, set the attribute to the SR_CustTable query.

Attach the SRSReportParameterAttribute attribute to specify the data contract class that defines the report parameters for the report.

For this example, set the attribute to the SRSRDPCustTableContractClass.

[ SRSReportQueryAttribute (querystr(SR_CustTable)),
SRSReportParameterAttribute(classstr(SrsRDPCustTableContractClass))
]

class SR_CustTableRDP extends SRSReportDataProviderBase
{
TmpSR_CustTable tmpSR_CustTable;
}
_________________________________________________________
Now we need 3 more methods to be added

///

/// Processes the report business logic.
///

///
/// 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(false)]
public void processReport()
{
QueryRun queryRun;
Query query;
CustTable custTable;
SRSRDPCustTableContractClass srsRDPCustTableContractClass;
AccountNum accountNum;
QueryBuildDataSource queryBuildDataSource;
QueryBuildRange queryBuildRange;

query = this.parmQuery();

srsRDPCustTableContractClass = this.parmDataContract() as SRSRDPCustTableContractClass;
accountNum = srsRDPCustTableContractClass.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));
this.insertTmpTable(CustTable);

}
}
________________________________________________

///

/// This method inserts data into the temporary table.
///

///
/// Table buffer of CustTable table.
///

private void insertTmpTable(CustTable _custTable)
{
tmpSR_CustTable.AccountNum = _custTable.AccountNum;
tmpSR_CustTable.Blocked = _custTable.Blocked;
tmpSR_CustTable.PriceGroup = _custTable.PriceGroup;
tmpSR_CustTable.Currency = _custTable.Currency;
tmpSR_CustTable.insert();

}
____________________________________________
[SRSReportDataSetAttribute(“Tmp_SRCustTable”)]
public tmpSR_CustTable getTmpSR_CustTable()
{
select * from tmpSR_CustTable;
return tmpSR_CustTable;
}
________________________________________________
wow…we are done with all the steps mentioned above and I am excited to help you guys understand how to use the RDP class as a datasource for the dataset. For this we need to create a new report in the visual studio .

Follow me friends…[I am assuming that all the visual tools have been installed and you have report model template available to created the reports]

Open visual studio. Click on File >> New project and follow the below process.

Now add a new report to the report model by right clicking and selecting new report as shown below

Rename the report to “SR_CustTableRDPReport” as shown below by going to the properties of the report

Now the next thing what we have to do [the most awaited…] is to create a dataset for this report.

Right click on the DataSet and add new dataset as shown below. Rename it to CustomerDataSet as shown below

Go to its properties and rename it to “CustomerDataSet”

Now the real trick, we have a datasource type property on the dataset properties. Select report data provider as the datasource type as show below.

Select the query property and Click on the ellipsis (…) button to selct the RDP class which you have created in the step 4 as shown below

This will come up with all the RDP classes available in AX. Select SR_CustTableRDP Class and click on next button to select the fields from the tmpTable to shown it on the report.

Follow the below screen shot to select the fields and click on Ok button

wonderful..we are done with dataset..Only few steps now..Now we need to create design. Drag and drop this CustomerDataSet to Designs node. It will automatically create the Autodesign1 as shown below

Few more properties for good look and feel of reports : Right click on the Autodesign1 and set the
LayOutTemplate as ReportLayoutStyleTemplate as shown below

Then set the style template as TableStyleTemplate as shown below

Also, since I dont have data in default DAT Company, I would like to use company parameter as well. so I am unhiding the company parameter to select the company parameter along with the Account number [step 3 parameter]

To do this, follow me and change the hidden property to visible as shown below for company parameter

Thats it..Now let us run this report.

Right click on the Autodesign1 and select option Preview and select the parameters as shown below

Select the report Tab to view the report. It will take some time to render data.

Here comes the final data on the report – from the RDP class by inserting in to temporary table and showing the same on to report.

hmmmm.. I am done..Hope you understood how RDP classes will help to render the data on to report by using the temporary table concept and Data contract classes. In my last post I have explained how to add this report to the AX menu item.. Follow the same process and check the report by opening from within AX.

Dialog fields and runtime lookups / Simple UI Builder Class on SSRS Report parameters [Dynamics AX 2012] && Filtering drop down list based on another drop down

In this post, we will learn how to add dialog fields and get run time lookups on the dialog field in AX 2012 SSRS reports. In Dynamics AX 5.0, we used to get this by overriding dialog, dialogpostrun, controlMethodOverload, Field_runTimeFieldId_lookup/modified methods  etc.

In AX 2012 there is a class by name “SrsReportDataContractUIBuilder” to serve the same purpose.

Example : In the below screen shot, I have added dialog field “Filter by Cust” and in the lookup it will only display the customers who belongs to

customer group “20”.

Interesting right, now lets see how to accomplish this:

Create a new Query by name “SRCustTable” and add data source as “CustTable” as shown below

Then create a new temporary Table by name TmpSRSalesTable and add 2 fields CustAccount and SalesId fields as shown below.

image

Now, we need to create contract classes, DP class and Builder class as shown below.

Follow the below classes and methods.

SRCustomLookupUIBuilder Class:

Create a new class by name SRCustomLookupsUIBuilder that should extend SrsReportDataContractUIBuilder as shown below

class SRCustomLookupsUIBuilder extends SrsReportDataContractUIBuilder

{

DialogField   dialogAccountNum;

DialogGroup   dialogGroup;

boolean       enable;

}

The below accountNumLookUp method will help to get the runtime lookup based on the query defined in the code [customer group – 20]

private void accountNumLookup(FormStringControl accountNumLookup)

{

Query                   query = new Query();

QueryBuildDataSource    qbds_CustTable;

SysTableLookup          sysTableLookup;

QueryBuildRange         qbr;

if (accountNumLookup != null)

{

// Create an instance of SysTableLookup with

// the current calling form control.

sysTableLookup = SysTableLookup::newParameters(tablenum(CustTable), accountNumLookup);

//sysTableLookup.addLookupMethod(

// Add fields to be shown in the lookup form.

qbds_CustTable = query.addDataSource(tableNum(CustTable));

sysTableLookup.addLookupfield(fieldnum(CustTable, AccountNum), true);

sysTableLookup.addLookupfield(fieldnum(CustTable, CustGroup),false);

qbr = qbds_CustTable.addRange(fieldNum(CustTable,CustGroup));

qbr.value(’20′);

sysTableLookup.parmUseLookupValue(false);

sysTableLookup.parmQuery(query);

// Perform the lookup.

sysTableLookup.performFormLookup();

}

}

/// <summary>

///    Builds the dialog.

/// </summary>

/// <remarks>

///    The dialog appears with the parameters.

/// </remarks>

public void build()

{

SRCustomLookUpContract rdpContract =  this.dataContractObject();

dialogAccountNum = this.addDialogField(methodstr(SRCustomLookUpContract,parmAccountNum),rdpContract);

dialogAccountNum.lookupButton(2);

}

public void postRun()

{

Dialog dialogLocal = this.dialog();

DialogField dialogField;

super();

// This method should be called in order to handle events on dialogs.

dialogLocal.dialogForm().formRun().controlMethodOverload(false);

// Override the methods of department  field.

dialogField = this.bindInfo().getDialogField(this.dataContractObject(), methodstr(SRCustomLookUpContract, parmAccountNum));

dialogField.registerOverrideMethod(methodstr(FormStringControl, lookup), methodstr(SRCustomLookupsUIBuilder, accountNumLookup), this);

}

Note : we can even use intializeFields and getfromdialog overridden methods to initialize values and get the values from dialog.

Contract class

[DataContractAttribute,

SysOperationContractProcessingAttribute(classstr(SRCustomLookupsUIBuilder))

]

class SRCustomLookUpContract

{

AccountNum  accountNum;

}

Add parmAccountNum method as shown below

[DataMemberAttribute(‘AccountNum’)

]

public AccountNum parmAccountNum(AccountNum _accountNum = accountNum)

{

accountNum = _accountNum;

return accountNum;

}

DataProvider class

[

SRSReportQueryAttribute(queryStr(SRCustTable)),

SRSReportParameterAttribute(classStr(SRCustomLookUpContract))

]

class SRCustomLookupDP extends SRSReportDataProviderBase

{

SRCustomLookUpContract contract;

TmpSRSalesTable        tmpSRSalesTable;

}

/// <summary>

/// executes the logic based on the parameter entries

/// </summary>

/// <remarks>

/// fills up the temp table

/// </remarks>

[SysEntryPointAttribute]

public void processReport()

{

Query query;

QueryRun qRun;

QueryBuildRange qbr;

CustTable       custTable;

contract = this.parmDataContract() as SRCustomLookUpContract;

query =  this.parmQuery();

qbr = query.dataSourceNo(1).addRange(fieldNum(CustTable, AccountNum));

qbr.value(contract.parmAccountNum());

qRun = new QueryRun(query);

while(qRun.next())

{

custTable = qRun.get(tableNum(custTable));

this.insertInToTempTable(custTable.AccountNum);

}

}

public  void insertInToTempTable(AccountNum _accountNum)

{

SalesTable salesTable;

;

while select salesTable where salesTable.CustAccount == _accountNum

{

tmpSRSalesTable.CustAccount = _accountNum;

tmpSRSalesTable.SalesId     = salesTable.SalesId;

tmpSRSalesTable.insert();

}

}

[

SRSReportDataSetAttribute(‘TmpSRSalesTable’)

]

public TmpSRSalesTable getTmpSRSalesTableDetails()

{

select * from tmpSRSalesTable;

return tmpSRSalesTable;

}

We are done with all the classes and I have already posted in my earlier blogs how to add this data provider classes as a dataset data source. Follow the same process and create a new SSRS report in visual studio 2010 and save the report to AOT and deploy as well.

Once you invoke the report from within AX, you will get the parameters from as shown below and runtime lookup clearly shows all the customers who belong to customer group 20. Click on Ok button.

image

You should see the result as shown below: you can use layout and table style templates for beautification.

image

 

Filtering drop down list based on another drop down

Hello All,
I’ve come across a scenario where I have to select a value from a drop down and based on that value I have to fill another drop down. After I did it, I though it will be usefull for others as well. So, I am posting it here.
So, Here is what we need to do.
First create a contract class as (I am hoping) we already know. Here I am using an example of Customer which will be filtered by Customer group. The code of class declaration will be:

[

DataContractAttribute

]

public class custReportContract

{

CustGroupId custGroup;

AccountNum cust;

}

Now creating 2 new methods for getting and setting these parameters. 1 for cust group

[

DataMemberAttribute(‘CustGroup’),

SysOperationLabelAttribute(literalstr(“@SYS11904”))

]

public CustGroupId parmCustGroup(CustGroupId _custGroup= custGroup)

{

custGroup = _custGroup;

return custGroup;

}

And the other one for customer

[

DataMemberAttribute(‘Cust’),

SysOperationLabelAttribute(literalstr(“@SYS313797”))

]

public AccountNum parmCust(AccountNum _cust= cust)

{

cust = _cust;

return cust;

}

Your screen will look like this:

Nothing new in it. We all know it (I guess). Moving forward and now we are creating another class for UI builder.

Create this new class and on the class declaration method, type the following code

public class custReportUIBuilder extends SysOperationAutomaticUIBuilder

{

}

your screen will look like this

Now we have to create 2 dialog boxes. 1 for customer group and customer each. To do this type the following code.

DialogField dialogCustGroup;

DialogField dialogCust;

We also have to define our contract class here, so declare the contract class

custReportContract contract;

so, the class declaration method will look like this:

public class custReportUIBuilder extends SysOperationAutomaticUIBuilder

{

DialogField dialogCustGroup;

DialogField dialogCust;

custReportContract contract;

}

Now, we have to draw the dialog boxes. For this reason, we will create another method of build and type the following code In it.

public void build()

{

Dialog      dialogLocal = this.dialog();

custReportContract contract = this.dataContractObject();

dialogLocal.addGroup(“Customer”);

this.addDialogField(methodStr(custReportContract,parmCustGroup), contract);

this.addDialogField(methodStr(custReportContract,parmCust), contract);

}

Now that we created the build method, let’s move into filling the cust group drop down with the table CustGroup. We’ll create another method for lookup and type the following code in it.

public void lookupCustGroup(FormStringControl _control)

{

Query query = new Query();

SysTableLookup sysTablelookup;

sysTablelookup =SysTableLookup::newParameters(tableNum(CustGroup),_control);

sysTablelookup.addLookupfield(fieldNum(CustGroup,CustGroup));

sysTablelookup.addLookupfield(fieldnum(CustGroup,Name));

query.addDataSource(tableNum(CustGroup));

sysTablelookup.parmQuery(query);

sysTablelookup.performFormLookup();

}

We need to create another method so that when user selects any record from cust group drop down, the customer drop down will be filtered with that value, for this reason we will select the modified event of cust group and then type the code:

public boolean custGroupModified(FormStringControl _control)

{

dialogCustGroup.value(_control.valueStr());

dialogCust.value(”);

return true

}

Ok now we will create the lookup method for customer. Here is the code

public void lookupCust(FormStringControl _control)

{

Query query = new Query();

SysTableLookup sysTablelookup;

sysTablelookup =SysTableLookup::newParameters(tableNum(CustTable),_control);

sysTablelookup.addLookupfield(fieldNum(CustTable,AccountNum));

sysTablelookup.addLookupfield(fieldnum(CustTable,Party));

query.addDataSource(tableNum(CustTable));

query.dataSourceTable(tableNum(CustTable)).addRange(fieldNum(CustTable, CustGroup)).value(dialogCustGroup.value());

sysTablelookup.parmQuery(query);

sysTablelookup.performFormLookup();

}

Note that I filtered the cust query with the value selected in cust group drop down

query.dataSourceTable(tableNum(CustTable)).addRange(fieldNum(CustTable, CustGroup)).value(dialogCustGroup.value());

we have almost completed our code for lookups and their filters. Now we will bind our dialog boxes with the contract class params and also override the modified method of cust group with the method we just wrote. To do this we will create another method for postBuild. Here we go

public void postBuild()

{

super();

// From binding info, get the dialog field for racecode attribute and add button

dialogCustGroup = this.bindInfo().getDialogField(

this.dataContractObject(),

methodStr(custReportContract,parmCustGroup));

if (dialogCustGroup)

{

dialogCustGroup.lookupButton(2);

}

// register override method for lookup cust Group

dialogCustGroup.registerOverrideMethod(methodStr(FormStringControl, lookup),methodStr(custReportUIBuilder, lookupCustGroup), this);

// register override method for modified

dialogCustGroup.registerOverrideMethod(methodStr(FormStringControl, modified),methodStr(custReportUIBuilder, custGroupModified), this);

//binding info for customer drop down

dialogCust = this.bindInfo().getDialogField(

this.dataContractObject(),

methodStr(custReportContract,parmCust));

// register override method for lookup customer

dialogCust.registerOverrideMethod(methodStr(FormStringControl, lookup),methodStr(custReportUIBuilder, lookupCust), this);

if (dialogCust)

{

dialogCust.lookupButton(2);

}

}

We may have to create some other methods as well in order to functioning your code properly. They are getFromDialog, initializeFields and postRun. Create three new methods each for getFromDialog, initializeFields and postRun and copy the following code to them

public void getFromDialog()

{

contract = this.dataContractObject();

super();

}

public void initializeFields()

{

contract = this.dataContractObject();

}

public void postRun()

{

super();

}

We are done. But wait one last thing, open your contract class and in the class declaration method, reference your UI builder class just below the DataContractAttribute. Your code will become:

[

DataContractAttribute,

SysOperationContractProcessingAttribute(classStr(custReportUIBuilder))

]

public class custReportContract

{

CustGroupId custGroup;

AccountNum cust;

}

We are now done. In this post we have tried to filter our single value drop down based on another drop down. In the next post we will try to repeat the same process for multi value drop down list.

Reference:http://ssrsax.blogspot.in/2012/05/filtering-drop-down-list-based-on.html

Delete Actions

Types of DeleteActions

None

A None deletion action will delete selected row in the table but nothing occurs to the table that relate to this table.

Cascade

A cascading deletion action will delete all records in the related table, where the foreign key is equivalent to the primary key of the current table. That is, deleting the parent record will also delete the child record(s) in the related table.
This cascading will take place whether the deletion is performed in code or directly by a user through the user interface.

Restricted

A restricting delete action will raise an error message if the user tries to delete a record, where records exist in the related table where the foreign key is equivalent to the primary key of the current table.
This error will only appear if the deletion is performed through the user interface. A deletion from X++ code will be allowed to proceed and will not be cascaded to the related table. In this case the programmer should call .validateDelete() themselves prior to the call to .delete()

Cascade+Restricted

Cascade+Restricted comes into exist only when we are dealing with more than two tables.

The delete action performs an restricted, if the record of the table will be deleted directly and performs an cascade, if the record of the table will be deleted through a cascade delete action of a other table.

E.g.: tableA (Customer) (a cascade deleteaction to tableB) tableB (SalesOrder) (a cascade+restricted deleteaction to tableC) tableC (SalesLine)
When a record of tableB will be deleted, the restricted part of the deleteaction will be performed. The record of tableB can only be deleted, if no record in tableC exist for the record in tableB. (The SalesOrder can only be deleted, if no SalesLine exist for the SalesOrder).
A record in tableA will be deleted, so the cascade deleteaction to tableB will be performed. In this case, the cascade part of the deleteaction to tableC will be performed. (When a Customer will be deleted, the SalesOrders and SalesLines will also be deleted)

So, the performing action of a cascade+restriced deleteaction depends on the kind of deletion of the record. (direct:restricted, cascading:cascade)

If a cascade+restriced deleteaction is performed on a table for the related table it acts as a restriced deleteaction.