Wednesday 23 July 2014

we can auto create purchase order when item in stock decrease...

we need to go to master planning>>planned orders>>create a new planned orders

for info :http://technet.microsoft.com/en-us/library/aa498581.aspx

Monday 21 July 2014

How to call job to another job in axapta using x++ code

How to call job to another job in axapta using x++ code

How to call job to another job in axapta using x++ code1. Create simple job job_test  and add it to action menu item in AOT.
2. Call job_test in other job using following code.Args                    args;
;
args = new Args();
args.name(identifierStr(Jobs_Test));
new menuFunction(menuItemActionStr(Jobs_Test), MenuItemType::Action).run(args);
If you want to add job in action menuitem then just right click on aot menuitem on action type then create new menuitem. After that you can set that job in object selection property of menuitem.  You can not direction drag job to action menuitem

Sunday 20 July 2014

look up in form

1) create a simple form  with a simple data source
2) we can add a simple table in data source and drag both in design and
3)under design we can go to particular field  and  over ride method  called look up


4) before  the super declare all the query, systablelook up, querybuild data source



 then save the form and open the  form under the field  where we have over ridden the look up there a look up will be appeared and   rtequired  fields and look up will be created '


Navigating methods in X++ code editor

To move to the next\previous method in X++ code editor use Ctrl+Tab and Ctrl+Shift+Tab correspondingly.
X++ developers seem to be having a lot of trouble with these 4 datasource methods, no matter how senior they are in AX.
So I decided to make a small hands-on tutorial, demonstrating the common usage scenario for each of the methods. I have ordered the methods based on the impact on the rows being displayed in the grid.
You can download the xpo with the tutorial on my SkyDrive.

1. Common mistakes

Often, developers call 2 of the mentioned methods in the following order:
formDataSource.refresh()
formDataSource.research()

or
formDataSource.reread()
formDataSource.research()

or
formDataSource.research()
formDataSource.executeQuery()

or
formDataSource.research()
formDataSource.refresh() / formDataSource.reread()

All of these are wrong, or at least partially redundant.
Hopefully, after reading the full post, there will be no questions as to why they are wrong. Leave a comment to this post if one of them is still unclear, and I will try to explain in more detail.

2. Refresh

This method basically refreshes the data displayed in the form controls with whatever is stored in the form cache for that particular datasource record. Calling refresh() method will NOT reread the record from the database. So if changes happened to the record in another process, these will not be shown after executing refresh().

refreshEx
Does a redraw of the grid rows, depending on the optional argment for specifying the number of the record to refresh (and this means the actual row number in the grid, which is less useful for AX devs). Special argument values include -1, which means that all records will be redrawn, and -2, which redraws all marked records and records with displayOptions. Default argument value is -2.
This method should be used sparingly, in cases where multiple rows from the grid are updated, resulting in changes in their displayOptions, as an example. So you should avoid using it as a replacement for refresh(), since they actually have completely different implementations in the kernel.
Also, note, that refreshEx() only redraws the grid, so the controls not in the grid might still contain outdated values. Refresh() updates everything, since this is its intention. 

3. Reread

Calling reread() will query the database and re-read the current record contents into the datasource form cache. This will not display the changes on the form until a redraw of the grid contents happens (for example, when you navigate away from the row or re-open the form).
You should not use it to refresh the form data if you have through code added or removed records. For this, you would use a different method described below.

How are these 2 methods commonly used?
Usually, when you change some values in the current record through some code (for example, when the user clicks on a button), and update the database by calling update method on the table buffer, you would want to show the user the changes that happened.
In this case, you would call reread() method to update the datasource form cache with the values from the database (this will not update the screen), and then call refresh() to actually redraw the grid and show the changes to the user.

Clicking buttons with SaveRecord == Yes
Each button has a property SaveRecord, which is by default set to Yes. Whenever you click a button, the changes you have done in the current record are saved to the database. So callingreread will not restore the original record values, as some expect. If that is the user expectation, you as a developer should set the property to No

4. Research

Calling research() will rerun the existing form query against the database, therefore updating the list with new/removed records as well as updating all existing rows. This will honor any existing filters and sorting on the form, that were set by the user.

Research(true)
The research method starting with AX 2009 accepts an optional boolean argument _retainPosition. If you call research(true), the cursor position in the grid will be preserved after the data has been refreshed. This is an extremely useful addition, which solves most of the problems with cursor positioning (findRecord method is the alternative, but this method is very slow).

5. ExecuteQuery

Calling executeQuery() will also rerun the query and update/add/delete the rows in the grid. The difference in behavior from research is described below.
ExecuteQuery should be used if you have modified the query in your code and need to refresh the form to display the data based on the updated query.

formDataSource.queryRun().query() vs formDataSource.query()
An important thing to mention here is that the form has 2 instances of the query object - one is the original datasource query (stored in formDataSource.query()), and the other is the currently used query with any user filters applied (stored in formDataSource.queryRun().query()).
When the research method is called, a new instance of the queryRun is created, using theformDataSource.queryRun().query() as the basis. Therefore, if the user has set up some filters on the displayed data, those will be preserved.
This is useful, for example, when multiple users work with a certain form, each user has his own filters set up for displaying only relevant data, and rows get inserted into the underlying table externally (for example, through AIF).
Calling executeQuery, on the other hand, will use the original query as the basis, therefore removing any user filters.
This is a distinction that everyone should understand when using research/executeQuery methods in order to prevent possible collisions with the user filters when updating the query.


http://kashperuk.blogspot.in/2010/03/tutorial-reread-refresh-research.html

length of array

static void TestArray(Args _args)
{
    Array   strArray = new Array(Types::String);
    ;

    strArray.value(1, 'abc');
    strArray.value(2, 'def');

    info(strfmt("%1", strArray.lastIndex()));
}


for more info please have a look............

http://msdn.microsoft.com/en-us/library/array.aspx

AX tips

If the form opens from other form menuitem not directly from form then we have to write this code in form init method after super()


if (!element.args().caller())
    {
        throw error("@SYS22539");
    }

Un Select all coding: In click method of button:
void clicked()
{
    DNGRSSalesPaymentSettelmentLines _DNGRSSalesPaymentSettelmentLines;
    super();

   _DNGRSSalesPaymentSettelmentLines =DNGRSSalesPaymentSettelmentLines_ds.getFirst();
    while (_DNGRSSalesPaymentSettelmentLines)
    {

        if(_DNGRSSalesPaymentSettelmentLines.SelectPayment == NoYes::Yes)
        {
            _DNGRSSalesPaymentSettelmentLines.SelectPayment = NoYes::no;
        }
        _DNGRSSalesPaymentSettelmentLines.update();

        _DNGRSSalesPaymentSettelmentLines = DNGRSSalesPaymentSettelmentLines_ds.getNext();
    }
}
 Select all coding:   In click method of button:
void clicked()
{
    DNGRSSalesPaymentSettelmentLines _DNGRSSalesPaymentSettelmentLines;
    super();

   _DNGRSSalesPaymentSettelmentLines =DNGRSSalesPaymentSettelmentLines_ds.getFirst();
    while (_DNGRSSalesPaymentSettelmentLines)
    {

        if(_DNGRSSalesPaymentSettelmentLines.SelectPayment == NoYes::no)
        {
            _DNGRSSalesPaymentSettelmentLines.SelectPayment = NoYes::yes;
        }
        _DNGRSSalesPaymentSettelmentLines.update();

        _DNGRSSalesPaymentSettelmentLines = DNGRSSalesPaymentSettelmentLines_ds.getNext();
    }
}



Note : For invoice settlements we can use the  CustVendSettle class:
                CustVendSettle  - updateOtherSettlementFieldsOnTrans






Existing and new customer creation:

class DNGRSCustomertEntitiesFromReservatio
{
}



static public void main(Args args, boolean _showForm = true)
{
    smmEntityToCreate   entityCreate;
    NoYes               conversionSuccessful;
    MenuFunction        menuFunction;
    Args                argsToPass = new Args();
    smmBusRelTable      smmBusRelTable;
    DNGRSReservationTable  dngRSReservationTable;
    smmOpportunityTable    smmOpportunityTableLoc;
    CustTable              Custtable;
    ;

    if (!args || !args.dataset())
    {
        throw error("@SYS22996");
    }

    dngRSReservationTable = args.record();

    smmOpportunityTableLoc = smmOpportunityTable::findbyReservationId(dngRSReservationTable.ReservationId);

    if(!smmOpportunityTableLoc.RecId)
    {
        throw error("@DNG21273");
    }

    if (smmOpportunityTableLoc.RecId)
    {
        entityCreate = args.parmEnum();

        // from Create Customer function button
        if (entityCreate == smmEntityToCreate::Customer)
        {
            // Convert to customer
            smmBusRelTable = smmBusRelTable::findByParty(smmOpportunityTableLoc.Party);
            if (smmBusRelTable.canConvertToCustomer())
            {
                conversionSuccessful = smmBusRelTable::convert2Customer(smmBusRelTable, ''false);
            }
            if (conversionSuccessful)
            {
                Custtable = CustTable::findByPartyRecId(smmBusRelTable.Party);
                info(strfmt("New Customer %1 is created",CustTable::findByPartyRecId(smmBusRelTable.Party).AccountNum),'',SysInfoAction_TableField::newBuffer(CustTable));


                info(strfmt("%1 %2 ",dngRSReservationTable.ReservationId,dngRSReservationTable.ExistingCustomer));
                dngRSReservationTable.ExistingCustomer = CustTable::findByPartyRecId(smmBusRelTable.Party).AccountNum;
                // Open the Customer table form if configured to do so
                //if (smmParameters::getBusRelOpenCustForm())
                //{
                    //menuFunction = new MenuFunction(menuitemDisplayStr(CustTable), MenuItemType::Display);
//
                    //// Check access rights
                    //if (!menuFunction || !menuFunction.checkAccessRights())
                    //{
                        //// Access rights are not sufficient to use this function.
                        //throw error("@SYS81158");
                    //}
//
                    //argsToPass.record(smmBusRelTable);
                    //if(_showForm)
                    //{
                        //menuFunction.run(args);
                    //}
                //}
            }
        }

    }

}

Manually creation of numbersequence:
num     = NumberSeq::newGetNum(DNGRSSalesParameter::numRefRESUnitPaymentSchedule());





Adding range in execute query:
()
public void executeQuery()
{

 if(DNGRSUnitPaymentschedule.DNGRSChangeorderid == "")
   this.query().dataSourceTable(tableNum(DNGRSUnitPaymentschedule)).addRange(fieldNum(DNGRSUnitPaymentschedule,DNGRSChangeorderid)).value(queryValue(DNGRSUnitPaymentschedule.DNGRSChangeorderid));
    else
      this.query().dataSourceTable(tableNum(DNGRSUnitPaymentschedule)).addRange(fieldNum(DNGRSUnitPaymentschedule,DNGRSChangeorderid)).value(SysQuery::valueEmptyString());
       super();

}

Monday 14 July 2014

Using Excel to Import Products & Services in Dynamics AX

 Dynamics AX tables that are available, and select the following:
  • EcoResProduct (Base product)
  • EcoResProductTranslation (Product description)
  • InventTable (Released product)
please follow this for more info :
http://atinkerersnotebook.com/2013/06/17/using-excel-to-import-products-services-in-dynamics-ax/

Friday 11 July 2014

What is the difference between new() and construct() methods

Method new() actually constructs a class and finalize() destructs.
Method construct() is a best practice to use when creating an instance. In this method you code how to construct a specific class.

Thursday 10 July 2014

Top 10 issues discovered from Dynamics AX Code Review

The following list is not exhaustive and is only based on our experience from the field.
1. Wrong caching leads to unnecessary database calls
This is one of the most fundamental feature of the product today. The three tiers architecture of Dynamics AX allows you to define caching on AOS and client. Not using caching properly is the first root cause for performance. Make sure the following rules are defined:
  • All your customized tables have relevant table group defined in AOT. For example, master data should have “Main” category and transactional data should be set to “Transaction” (header or line).
  • Don’t leave the default setting “None” for Cache Lookup and set the correct value to your table such as “EntireTable” for Parameter table and “Found” for Main group.
  • Review the cache limit for every table group in the server performance settings
2. Expensive database calls from the form
Since Dynamics AX 2012, you can use the Form Style checker tool to detect any SQL operations directly written within the form objects. Typically, this code persists in the click() method of the button. SQL operations such as update, create or delete a record should be written on the class level or directly on the table. Having one single version of the code on the class will also help you to avoid duplicate method and obsolete method. 
3. Large and expensive queries due to select * query
This got to be the most common issue with huge penalty on performance, but also the easiest to detect and to fix. Make sure you can use the Field list and Exist join when possible. For every X++ Select statement, make sure you only retrieve the necessary fields. Same idea with Exists Join statement where you can reduce the amount of communication between the AOS and the database. This is especially true when customization adds lot of new fields on existing tables. For example, replace the following code:

           While select TableA
              {  Select TableB where TableB.FieldA == TableA.FieldA;
                 Print TableB.FieldB;
              }With
              While select FieldA from TableA Join FieldA, FieldB from TableB
              
Where TableB.FieldA == TableA.FieldA;              {  Print TableB.FieldB;
              
}
4. Massive and unnecessary X++ loop
This one is more rare but always nice to catch and easy to fix. Basically the developer is not using theaggregate function and executes a loop to calculate a sum or a count. You can easily find those patterns by searching in the AOT with the keyword “++” or “=+”. So the advice is to replace the following code:
            While Select TableA where FieldA = “ConditionA”
            {  CounterA ++;
            }
With
             Select count(RecId) from TableA where FieldA = “ConditionA”;
             Counter A = TableId.RecId;
 5. Too many Display methods in your grid
This got to be the first root cause of slow opening or refreshing of form object. It is quite easy to find such root cause by removing the display method and run Trace Parser tool to compare the two traces. In a scenario where a display method is used to display a column on a grid, the display method is executed for each row that is populated in the grid. That makes the overhead of the method quite expensive.
The performance of display methods can be improved by caching them if they are calculated on AOS.Caching display methods can also improve performance when records are transferred from the server to the client. The value of all cached methods is set when data is fetched from the back-end database. In addition, the value is refreshed when the reread method is called on the form data source. To avoid any RPC call to the database, you can use the new feature from AX 2012 called Computed Column. Here the expression is directly stored in the SQL Server database as a view. You can see the walkthrough on this MSDN article.http://msdn.microsoft.com/en-us/library/gg845841.aspx
6. Direct SQL code misaligned with AOT indexes 
Every time I check a new Dynamics AX instance, I directly check the store procedure in the SQL Server Management Studio. This is where you may find Direct SQL code written against the Dynamics AX database. You can also find direct SQL statement in the X++ code by searching the AOT with the keyword "connection.createStatement()". Direct SQL can be perfectly fine if well written. If not, it will clearly impact the performance because existing indexes are not used in the query plan.
This blog article from Michael DeVoe shows a good example of such SQL Statement not aligned with AOT indexes like PartitionID and DataAreaId from AX 2012 R2. The other problem is the maintenance cost of such code. Any schema change in the AOT will not be automatically updated in those Direct SQL like in X++ methods. It is like hard coded label, it contradicts principals of object oriented X++ language. 
7. No "Error on Invalid field access" in development environment.
In order to verify that we do not access fields in an invalid way, you can use the system parameter called “Error on Invalid Field access”. This setting will throw an exception if a field that was not retrieved is being accessed. The parameter can be found under System administration \ Setup \ System\Server Configuration and it requires a restart of the AOS service. It is strongly recommended to enable this setting when testing your modifications in the application to avoid unpleasant and hard-to-find bugs later on in the production environment. Please note this is only relevant from AX 2012.
8.   Error compilation in production!
Why should we even talk about it? Well in reality, we often discover error and warning Best Practicesmessages when compiling production code. If you follow the recommended code promotion to release new development into the production instance, you should have run the full compilation a few times in previous environments. For auditing purpose, I also recommend the operational team to save the result of each compilation as HTML file during code promotion.
You can also customize the Best Practice tool to include your own rules. The classes used to check for rules are named SysBPCheck<ElementKind>. You call the init, check, and dispose methods once for each node in the AOT for the element being compiled.
Last but not least, you should define the compiler tool to reject any check-in if there is warning. Most of the errors and warnings can be easily fixed so there is no excuse to postpone the resolution during the development lifecycle. There will always be a struggle to find time for such quality assessment tasks, but it will definitively pay off in the long term. 
9. Bulk operations regressed into row by row ones 
The three bulk operations, Update_RecordSet, Insert_RecordSet and Delete_From operations are great way to improve the performance of X++ queries with only one RPC call to the database for multiple rows impacted. The problem is that overwriting the SYS method update(), insert() and delete() methods may break these features. Wrong customization can lead into a row by row operation. So it is recommended to verify the RPC calls with Trace Parser to verify the performance of the intended X++ code.
 10.  Too many fields in legacy tables
With the Dynamics AX 2012 release, the number of tables is higher than in previous releases because of database normalization. It was mainly done to reduce redundancy of data across various tables, and also to improve performance. For example, for the Parameter type table, where only one record exists per Company. On the opposite, de-normalization can also be recommended in some case to improve performance because it will reduce the number of join in the X++ queries.
You need to find the right balance when doing customization but the basic rule is to limit the number of new fields in SYS tables to 50. From our customer visit, we can discover many legacy tables with hundreds of new fields. What’s more surprising is that most of them remain empty in production because the data modelling was never analyzed in depth. Don’t forget to run the Customization Analysis Tool from Lifecycle Services to automatically get a detailed report of your model.

how to print a PO before it is invoiced....(Auto report".)

ans:Focus on Purchase order>Lines and do a Ctrl+P to print a report with the PO lines.

Auto-reports are preconfigured reports that you can generate by clicking File > Print > Print in a Microsoft Dynamics AX form. You can quickly generate an auto-report for use once, or you can create and save a custom auto-report that can be reused later. 

intercompany PO multiple product receipt by x++

public void processStampICPO(PackingSlipId _deliveryNote,                             Transdate _deliverydate,                             ...