Tuesday 24 June 2014

Select the batch tab in dialog by default using SysOperation controller class

Hi,
Many times we have use sysOperation framework without using any data contract. In that case, if you run the class to open the dialog you would see a blank tab. To select the batch tab by default just place this code in your controller class.

protected void dialogPostRun()
{
    sysOperationDialog sysOperationDialog;
    DialogTabPage batchTab;
    FormRun formRun;

    super();

    sysOperationDialog = this.dialog() as SysOperationDialog;

    formRun = sysOperationDialog.formRun();

    batchTab = sysOperationDialog.batchDialogTabPage();

    formRun.selectControl(batchTab.control());
}

Wednesday 18 June 2014

Generate Excel Template of AX 2012 tables-all columns

Hi, This job can be used in data migration when your client asks for a template of a particular table.

static void Wipfli_TemplateGenerator(Args _args)
{
    SysExcelWorksheetHelper worksheetHelper;
    SysExcelHelper          sysExcelHelper;
    SysExcelWorksheet       worksheet;
    int                     column = 1;
    int                     row = 1;
    str                     worksheetName;
    SysDictField            dictField;
    SysExcelCell            excelCell;
    int                     redColor = WinAPI::RGB2int(255, 0, 0);
    SysExcelRange           range;
    COMVariant              cellValue = new COMVariant(COMVariantInOut::Out);
    DictTable DictTable;

    int fieldCount, _x, fieldId,enumValues, enumValue;

    sysExcelHelper = SysExcelHelper::construct();

    sysExcelHelper.initialize();

    worksheet = sysExcelHelper.addWorksheet("Template");
    worksheetHelper = SysExcelWorksheetHelper::construct(worksheet);

    DictTable = new DictTable(tableNum(InventTable));// Use your table name here.

    fieldCount = DictTable.fieldCnt();
    fieldId = DictTable.fieldNext(0);

    while (fieldId)
    {
      DictField = DictTable.fieldObject(fieldId);
      worksheetHelper.addColumn(column, dictField.name(),Types::AnyType);

      fieldId = DictTable.fieldNext(fieldId);
      column++;
    }

    sysExcelHelper.launchExcel();

}

Thursday 29 May 2014

Purchase order- line number increments

  1. Click System administration > Setup > System parameters.
  2. Click General, and then select options for the general system parameters:
    • Increment – Enter the increment to use when new line numbers are assigned to purchase order lines. This increment is used for all purchase order lines. Line increments are applied for purchase orders only.

Monday 26 May 2014

Make update changes on Packing slip post?

Many times we are required to make certain changes right after the packing slip has been posted. To do that, use the EndPost() method in the SalesPackingSlipJournalPost class. This method is called after the packing slip is successfully posted.

Friday 16 May 2014

Job to fetch entry points for a Role in AX 2012 security

static void JobSecurityRoleEntryPoints(Args _args)
{
  SecurityTaskEntryPoint  taskEntryPoint;
    SecurityRole            role;
    SecurityRoleTaskGrant   taskGrant;
    SecuritySubTask         subTask;
    SecurityTask            privilege;
    SecurityTask            securityTask;
    SecurableObject         securableObject;
    RecId                   roleRecId;

    #AOT
    str userlicense, maintainlicense, privName;
    TreeNode treeMenuItem;
    TreeNode treeMenu;

    while select RecId, Name from role where role.AotName == 'TradeCustomer'
    {
        roleRecId = role.RecId;

        while select securityTask, SecurityRole from taskGrant
            join RecId, Type, AOTName from securitytask where securityTask.RecId == taskGrant.SecurityTask
                && taskGrant.SecurityRole == roleRecId && securitytask.Type == SecurityTaskType::Duty
            join securityTask, SecuritySubTask from subTask where subTask.SecurityTask == securityTask.RecId
            join securityTask, EntryPoint from taskEntryPoint where taskEntryPoint.SecurityTask == subtask.SecuritySubTask

            {
               select RecId, Type, Name from securableObject
                    where securableObject.RecId == taskEntryPoint.EntryPoint && (securableObject.Type == SecurableType::MenuItemDisplay
                        || securableObject.Type == SecurableType::MenuItemAction || securableObject.Type == SecurableType::MenuItemOutput);

                if( securableObject)
                {
                    select RecId, Type, AOTName from privilege where privilege.RecId == subTask.SecuritySubTask && SecurityTaskType::Privilege == privilege.Type;

                    privName = privilege.AotName;

                    info(strFmt("Role: %1   Duty: %2   Priv:  %3   Menu item : %4", role.Name,securitytask.AotName,privName,securableObject.Name));

                }
        }
       
        //sometimes a role has a privielge direclty assigned instead of a duty. So this code is for those privileges. In this case duty will not exist.
        while select SecurityTask, SecurityRole from taskGrant
            join RecId, Type, AOTName from securitytask where securityTask.RecId == taskGrant.SecurityTask
                 && taskGrant.SecurityRole == roleRecId && securitytask.Type == SecurityTaskType::Privilege
            join securityTask, EntryPoint from taskEntryPoint where taskEntryPoint.SecurityTask == securitytask.RecId

            {
                select RecId, Type, Name from securableObject
                    where securableObject.RecId == taskEntryPoint.EntryPoint && (securableObject.Type == SecurableType::MenuItemDisplay
                        || securableObject.Type == SecurableType::MenuItemAction || securableObject.Type == SecurableType::MenuItemOutput);

                if( securableObject)
                {
                   info(strFmt("Role: %1   Duty:   Priv:  %2   Menu item : %3", role.Name,securitytask.AotName,securableObject.Name));
                }
        }
    }
}

Thursday 17 April 2014

How do I refresh AIF service schema after the Query is refreshed?

Go to AOT/Forms. Locate the AifService form. Select your particular service and simply click refresh.
Also make sure that in your outbound port, go to Data policies and make sure your newly added fields are marked Enabled otherwise they would not show up on the form.

Jobs that must be running for EDI documents in AX 2012

Four tasks that must be running periodically as a batch job in order for the EDI processing to occur are as below. Note that the order of their execution matters. If these jobs are not in Waiting state, then the Queue manager will show your document in Ready state and will never process it.

The four services that move documents through the gateway queue are:
  1. AIFGatewayReceiveService – This service communicates with the adapters, receives messages from their external source locations, and puts them into the gateway queue to wait for processing.
  2. AIFInboundProcessingService – This service takes incoming messages from the gateway queue and then processes the documents according to the rules that are specified by the inbound port.
  3. AIFOutboundProcessingService – This service processes an outbound document according to the rules that are specified by the integration port and then adds the envelope XML code to create a fully-formed AIF message. The service then places the message into the gateway queue to send.
  4. AIFGatewaySendService – This service sends the messages to the correct external destinations.
These services must run in a specific order because they depend on each other. For example, the gateway receive service must run before the inbound processing service. Otherwise, the inbound processing service will have no data to process. The order in which these services must run is the order in the previous list.

Tuesday 15 April 2014

Configure an AOS instance to print [AX 2012]

A great technet article explaining how can you set up printers for printing business documents in AX 2012.

http://technet.microsoft.com/en-us/library/aa569633.aspx

Tuesday 8 April 2014

Job to import customer contact information- Logistics electronic address

static void CustomerContactInformationJob(Args _args)
{
#File
    CommaTextIo        commaTextIo;
    FileIOPermission   permission;
    container          containFromRead;
    int                x;
    int                cols;
    int rowNum;

    str Customer,Description,Type,Locator;
    int Done,UnDone;

    CustTable custTAble;
    DirPartyContactInfoView DirPartyContactInfoView;
    DirParty dirParty;
    List locatorList;
    ListEnumerator locatorListEnumerator;
    SysDictEnum dictEnum;
    int         enumValue;

    ;
    permission = new FileIOPermission(@'C:\Users\Administrator\Desktop\Data\CustomerContacts.csv',#io_read);
    permission.assert();

    commaTextIo = new CommaTextIO(@'C:\Users\Administrator\Desktop\Data\CustomerContacts.csv','R');

    rowNum = 0;
    Done= 0;
    UnDone= 0;

    containFromRead = commaTextIo.read();

    dictEnum = new SysDictEnum(enumNum(LogisticsElectronicAddressMethodType));

    While(containFromRead)
    {
        if(rowNum>0)
        {
            Customer= any2str(conpeek(containFromRead,1));
            Description= any2str(conpeek(containFromRead,2));
            Type= any2str(conpeek(containFromRead,3));
            Locator= any2str(conpeek(containFromRead,4));

            custTable =CustTable::find(Customer);

    if(custTable)
        {
            dirParty = dirParty::constructFromPartyRecId(custTAble.Party);

            locatorList = strSplit(Locator, ";");
            locatorListEnumerator = locatorList.getEnumerator();

            while ( locatorListEnumerator.moveNext())
            {

                DirPartyContactInfoView.Locator = locatorListEnumerator.current();
                DirPartyContactInfoView.Type =   dictEnum.name2Value(Type);

                DirPartyContactInfoView.Party =   custTable.Party;
                DirPartyContactInfoView.LocationName = Description;
                dirParty.createOrUpdateContactInfo(DirPartyContactInfoView);

                DirPartyContactInfoView.clear();
                Done++;

            }



        }
        else
        {
            info("Customer not found " + Customer);
            UnDone++;
        }


        }
        containFromRead = commaTextIo.read();
        rowNum++;
    }
    commaTextIo = null;

    info(strFmt("Inserted : %1 Not inserted: %2", Done, UnDone));
}

tags: Ax 2012 Customer contact information ; Logistics Electronic address; importing contacts from csv using x++;

Tuesday 25 March 2014

Shipping carrier interface

In AX 2012 you can allow external shipping softwares to calculate shipping charges using the Shipping carrier interface. A number of tables are used:

Two important tables are :

ShipCarrierShippingRequest:

This acts as the source table for the external software and contains SO or packing slip data.

ShipCarrierStaging:

This table is written by external software with all the calculated charges. 

Saturday 22 March 2014

Starting my career in Microsoft Dynamics

A career in ERP has always been a lucrative one. Not because ERP is something complex, but its because the resources are less. If you take the decision of stepping into this career, you surely need to consider all the pros and cons. Although this career offers better salaries, however, narrowing down your scope to a particular technology reduces the amount of opportunities you can acquire.

A .net developer can get 100s of jobs, whereas an ERP consultant might have a handful of job opportunities compared to that.

In this series of blogs I would like to point out what it takes for a developer to migrate to Microsoft Dynamics as a career. What steps he must take and the route he should follow. Also, later in this blog I would highlight few benefits of stepping into this career and what is the future scope of it.

Moving from .net to Dynamics AX:

Let me give you a brief intro to AX in layman terms particularly target for .net intending immigrants :)

1. Interface:

In Dynamics AX 2012, there are two workspaces.

One is the user workspace which is exposed to the end user.(figure 1)

The other one is the development workspace which the developer uses to make changes in the objects.(figure 2)


As you can see in the developer workspace, there is a tree node. This is called the Application object tree or AOT. All the application objects lie in this tree node. All of the development from classes to forms to services take place in this workspace. You can also integrate it with Visual studio but that is beyond the scope of this blog post.

2. Tables in AX

In AX 2012, the tables are present in the data dictionary node within the AOT. The table present in AX is actually an image of an equivalent table present at the SQL level.
Or more precisely AX automatically creates an entity for your table.

You can use the table just like a class. You can declare its variable(called buffer in AX).
Cool thing is that you can even write table level methods. You can define both static and non static methods.
Common methods are like the find() method that takes the RecID(an auto unique generated index by AX) and returns the record.



Querying the table is similar to SQL queries but not as powerful. There are certain limitations which are encountered in rare cases only.
You can easily learn the queries if you know SQL.

3. The mysterious language - X++

If you already know java or c#, there nothing special about X++ then. It's just like any other language. The only difference is the name. And yes, if you want to access static methods you use " :: " instead of a dot " . " .
You can declare a variable having the same name as that of the class. For example, a class SalesInvoiceDP can have an object with the same name.

4. Forms in AX 

In AX, everything you develop for the desktop client is either a form or a report. Creating a form in AX is very easy. And its really very easy. All you need to do is drag and drop the datasources(tables) and drag and drop the table fields the controls would automatically be created. No need to bother about designing the controls and all. Binding the grid is also pathetically easy. If you are coming from .net, you 'll feel extremely comfortable working with AX forms. You can create a basic databound form with grid and details pane in less than 15 minutes if you know how to. Designing of the form is done by AX itself.



5. SSRS 

If you are planning to join AX team as a developer, reporting is one thing you need to be perfect at. Cause 95% of the times the customizations are related to reporting. AX 2012 allows you to design reports in visual studio conveniently. AX 2012 supports two types of reports, one is the Query based and the other one is the code based. The code based reports are used when there is some business logic that needs to run. In most cases you develop a code based report unless the report is very simple in that case you would use the Query based approach.

There are lots and lots of reports in the ERP system. Sales invoice, packing slip, picking list, bill of lading, credit note, debit note, etc. This is because ERP is the software that handles all the business documents for the organization. Reports are the core and most important feature of any ERP system.

So above you find the basic introduction of AX environment. The purpose was to enlighten you guys that AX 2012 is not a very complicated thing. I myself used to be in .net. Trust me life is much easier in AX and specially when you get paid more. The reason is that you are doing something meaningful rather than playing with pixels in your c++ code that nobody cares about.

How to start?

Well, there are some labs that you can get from the Microsoft partner source. Just go through those labs. In one week time only you will have sufficient knowledge of AX and can actually start development.

I would not recommend you to read a book on it first. The book deals a lot with architecture and model stores that a beginner does not need to know. Even after much experience its difficult for me to read a book as it contains very complex details that a developer doesn't need for customization. Atleast a beginner does not need to know all those things. Knowing about the 14 layered architecture is only going to distract you.

Stick to the labs and then jump in. That's how you would learn. Read blogs on it and access the online materials.

For a developer who is good in .net, he should take around 2 months to get absorbed into AX. You cannot have expertise in all the areas as AX is too vast.

Knowledge of data models, classes and frameworks:

In AX, you need to have good grip on the various frameworks that are built in. For example the global address book framework, number sequence framework etc. Also you need to know the data models and existing classes.

For example, I get a requirement to add a new field in my sales order form, you need to know which table is used for the sales order. Also which form is used and what classes are associated.

For this, you need to have a lot of experience. The more jobs you do, the more you 'll learn. There is no other why for mastering this. And believe me, if you have good grip over the data model, you are considered a very very strong developer. Cause most of the time is utilized in searching for tables and associated classes. If you have good domain knowledge, you'll rock.

That's all for now. In my next blog I would share more like the pros and cons of this career choice and much more.
If you have any queries, please feel free to post comments, I ll be happy to help you out.



Thursday 6 March 2014

How to add multiline data using data import export framework?

For example, you want to import addresses. And you would like to have multiple lines as shown in the figure below:


When entering data in your MS Excel cell for this address, simply add a new line within the cell by pressing ALT+Enter. This would insert a new line within the cell. Then save the file as a tab or comma delimited. Then import into AX using DIX. This would appear as shown in the figure above.

Thursday 27 February 2014

AX 2012 layer magic

Hi,
Many times it so happens that the developer is engrossed in his work and he happens to write his code in the wrong layer. This can cause big troubles when you are dealing with clients.
A very common scenario is:

You are working in the cus or isv layer. Suddenly during the development the client gets stuck and asks you to restart the client(very common in AX 2012). And then you click YES.

There is a bug in here. When the AX restarts, it will open the AX in the usr layer instead of the layer you were working in. So be careful here.

Wednesday 26 February 2014

Error: Cannot create a record. Record already exists.

Hi,
Sometimes you would encounter this error no matter what you do.
If there is no technical flaw, just try these two steps:

1. Restart SQL Server service
2. Restart AOS

Monday 17 February 2014

How do I deploy reports to for different AOS configurations using powershell?

Enter this command in the powershell:

Publish-AXReport –Id SSRSConfigID -ReportName SalesInvoice

SSRSConfigID refers to a configuration ID that was defined in Microsoft Dynamics AX. 

To view these configuration IDs, open Microsoft Dynamics AX and then open the Report servers form. (Click System administration > Setup > Business intelligence > Reporting Services > Report servers.) To deploy reports to the new Reporting Services instance, enter the configuration ID that is associated with that instance.

How do I set a default tab in a form?

Many times, you want a particular tab to be selected by default against a certain condition. This can be accomplished by simply calling the tabName.activePage() method. 

Saturday 15 February 2014

Update conflict while posting credit note against fully invoiced Sales order



Hi,
At times you would receive this strange error all of a sudden that would not let you post a credit note. In particular, when you do not want the sales order lines to be deleted and wish to retain the original order.
In order to fix this bug, just add a line a code in the "SalesCopying" class.


In the copy method, just add this line highlighted in green. In my environment, this is line no 530.