Friday, November 30, 2012

Generating Sales order confirmation in XML file in AX 2012

Let's say we need to provide one of our vendors with a Sales order confirmation in the form of XML file for the further consuming in their automated system. We suppose your license configuration is OK for that.

First of all, the appropriate service has to be set up in AIF module of AX 2012. (For the previous version, take a look at Microsoft Dynamics AX AIF: Sending Outbound Documents Automatically post) Given that we are going to export this information, we need to create a new outbound port.

Setting new Outbound port

Open the form of Outbound ports (System administration/Setup/Services and Application Integration Framework) to set up one: give it a name and short description to recognize it later among others.

Adapter should be File system adapter to generate XML file.
URI is the path where you can find generated XML files. Of course, AX has to have appropriate rights for this folder.



Now, we are choosing in the drop-list the appropriate service defined in AOT. For the most documents these services are already created; however, if you need to set up some specific or even new document service, please refer to the development manual.

The one we are looking for is SalesSalesConfirmationService. As you can see, all the document services are named in a very evident style: you always know for which document it serves.



Do not worry, if you cannot find this service in the list because it exists but needs to be registered from AOT  like follows.

Open Services branch in AOT tree, find this service in it, and register by the context menu item. You need to do it every time you add a new document service. Now this service appears in the list.



Read method will be enough for our job, so we activate our new port. Now we can proceed with the next step:

Adding a batch job maintaining AIF module

For my particular case, I am adding two tasks within it:

 - AifOutboundProcessingService responsible for outbound processing; and
 - AifGatewaySendService that will save XML files in the folder of URI, defined on the preceding step.



Note that you have to strictly follow the sequence so that a document will be pushed in the Message queue first and then a file will be created.


Do not forget to start the batch job with the right recurrence rules. You find more detail on how to deal with this batch job here.

Print management for clients

Finally, we change the print management for the client to whom we want to send XML files while updating Sales order confirmation.



Choose Print archive as a Destination to avoid the real printing and to generate an XML file.


Since now, when I confirm a sales order for this client I get after within one-two minutes an appropriate XML file in the folder.



For your environment, of course, you need to use your own parameters like those for the file folder or period of time for the batch job.

Also, it is possible to set up Sales order confirmation as a batch job, too.

Let me know if you have any troubles with this!

Saturday, October 27, 2012

Alice in Wonderland

Every day my "Alice in Wonderland" adventure starts with Ctrl-D with a little help from my friends from http://axforum.info/

Thank you friends! I am still safe and sound!

Каждый день моё приключение алисы в стране чудес начинается с Ctrl-D при поддержке моих друзей с форума http://axforum.info/

Спасибо, друзья! Я всё ещё цел и невредим!

Monday, July 9, 2012

How to get the current system language

SystemParameters::getSystemLanguageId()

Monday, June 4, 2012

How to get AOS name to attach to in Visual Studio 2010

When you are going to debug your AX application in Visual Studio 2010, it is easy to choose which AOS to attach to. There is the application file path in the hint above the name of AOS service.

Tuesday, March 20, 2012

COMVariant type to work with Excel in AX

To avoid eventual issues while working with Excel objects in X++, do not forget about COMVariant type in AX!

Lets say we output some information directly to an Excel file and want to change the current row height based on the number of strings on notes.


...
COM             rng;
COMVariant      rowHeightVariant;
real            rowHeight;
...

rng = wks.Range(strFmt("A%1", curRow));   cell.Value2(_route.OprNum);
// to keep the current row height
rowHeightVariant = rng.RowHeight();
rowHeight = rowHeightVariant.double();
...
//to adjust the row height accordingly to the number of strings in notes
rng.RowHeight(rowHeight*this.countLines(notes));
...


Unfortunately, I had spent so much time trying to understand the reason of errors until I found this posting. Thank you Max!

Tuesday, March 6, 2012

RouteId Lookup

In AX2012 we cannot input a new route number manually because the type RouteId has a direct reference to RouteTable.

To solve this issue I created a new extended type WmpRouteIdBase and a related lookup form WmpRouteIdLookup similarly to BOMIdBase type.

The final step is to rewrite promptCreateRoute method on RouteTable:


if (! inventTable.inventItemType().canHaveRoutes())
        throw error(strfmt("@SYS22874",inventTable.ItemId));

    dialog = new Dialog("@SYS25123");
    if (manual)
        // to allow to input the route id manually
        //-->
        fieldNumber = dialog.addField(extendedtypestr(WmpRouteIdBase),"@SYS21709");
        //<--
    fieldName       = dialog.addField(extendedtypestr(Name),"@SYS6303","@SYS50977");

The whole project you download from here.

Thursday, March 1, 2012

How to make a temporary instance of a database table to be shown on the form

This short code shows how to work with a temporary table without creating it in AOT.

// how to use temporary table
// method Init of the form
public void init()
{
    WmpInventNutrition        nut; // regular table in AOT
    WmpInventNutrition        tmp; // instead of creating in AOT a temporary table
                                   // we can create a temporary instance of the preivous regular table
    ;
     super();

    // here we make it temporary;
    // it will disappear from memory when loses the scope
    // in other words, when we close the form
    tmp.setTmp();

    // simply selecting some of records from the regular table
    while select nut
        where nut.ItemId like '_wmp*'
    {
        // and putting them in the temporary one
        tmp.data(nut);
        tmp.doInsert();
    }
    // finally to show them on the form
    // we set the form data source to the temporary table
    wmpInventNutrition.setTmp();
    wmpInventNutrition.setTmpData(tmp);
}



Alternatively, if you know exactly how the field match, it will be faster to use insert_recordset:


 // simply selecting some of records from the regular table
    tmp.skipDataMethods();
    insert_recordSet tmp (itemid) select ItemId from nut where nut.ItemId like '_wmp*';
    

Wednesday, February 8, 2012

How to go to the object from Infolog

Usually, it is more useful if the user can go directly to the object from an Infolog line.

For example, we need to see all the BOM without any active version. By the way, this is a good example, too, for what we cannot do by means of Advanced Filtre but quickly by coding a short job.


static void SIBOMwithNoActiveVersion(Args _args)
{
    BOMTable    bomTable;
    BOMVersion  bomVersion;
    int         nmbr, i;
    boolean     printOnly = false;
    ;

    SetPrefix('BOMs without any active version');
    Nmbr = 0;

    while select bomTable
    notexists join bomVersion
    where bomVersion.Active == NoYes::Yes
    && bomVersion.BOMId == bomTable.BOMId
    {
        nmbr++;
        info(strfmt("%1 %2, %3, %4, %5, %6, %7",
                                          nmbr,
                                          bomTable.BOMId,
                                          bomTable.Name,
                                          bomVersion.ItemId,
                                          bomVersion.Name,
                                          bomVersion.Active
                                          ),"",
        SysInfoAction_TableField::newBufferField(bomTable, fieldnum(bomTable, BOMId)));

    }

}

Now the user can opt for Show from the context menu or just double-click on the interesting line to open the related form.





Tuesday, January 17, 2012

Universal Field Changer new version for Microsoft Dynamics AX2012

So, I took my old project from the case just to add a new feature: this time I would like to get all the table fields with their labels in the user's language.



Frankly seaking I was going to get it in a grid in order to export to Excel; but unfortunately I did not find a fast way to show my temporary table. Finally, I just use InfoLog in the comma separated format that can be used lately to open in Excel.



Enjoy, anyway!

Description:

Universal Field Changer class for Microsoft Dynamics AX2012:

- collects all the fields from all the tables in AOT in temporary tables;
- makes possible to change any values using filtres by table and field names and existing values;
- provides access to SQL query string;
- prints the field lists with labels in user's language;
- creates dynamically all the form controls and uses method overloading and can be used as a tutorial;