Technical Concepts in New Dynamics AX – AX7

Today I will discuss two methods of customizing new Dynamics AX source code of model elements which are: over layering and extensions.

Extensions:

A new way of customization has been introduced by Microsoft by using extensions. An Extension is a brand new AX object that references an existing object. This style of development allows existing objects to be customized without directly touching the original object. It is a useful concept for future application updates as upgrades will become much simpler by reducing the number of dependencies.

Example:

Taking example from my recent scenario, where I have to add my Recruitment and leavers reports menu items into HRM module in order to be accessible for end users. Now see how things are working differently here that Instead of directly touching the existing menu, a new object is created that references the existing HRM menu. The AX compiler magically merger both HRM and HRM extended with newly added menu items.

Extensions

What is great about this approach is that there is distinct ownership of each object. Microsoft owns the HRM Menu, while an ISV, Partner, or Customer owns the HRM extended menu. Each party can make changes to their object without impacting the other.

Menus are one area for extensions, but there are quite a few objects types eligible for extension.

  • Tables
  • Data entities
  • Forms
  • Menus
  • Security
  • Some Enums
  • X++ Code (Events)

We are hoping to see more in future from Microsoft as they continues to evolve the extension story and support more scenarios.

Over Layering

Another way of doing customization in source code and metadata model elements that are shipped by Microsoft or third-party partners in Microsoft Dynamics AX, the developer must create a new model that overlays the model they want to customize. For example, solution developers can provide code in the SLN layer, independent software vendors can use the ISV layer, and value-added resellers can use the VAR layer. Functionality defined in higher layers (VAR layer in this example) can override the functionality of lower layers.

The overlaying model must belong to the same Package as the source model and must belong to a layer that is higher than the source model. Over layering is a powerful tool to perform advanced customizations of metadata and source code, but may increase the cost of upgrading a Dynamics AX solution to a new version.

You can create a new model by going in visual studio -> Microsoft Dynamics – > Model management – > create new model

Model

 

The below picture will help in understand both:

Extensions-vs-overlaying

 

That’s it for now, I will cover more in depth including Packages. Extensions. Layers. Models in future blogs.

 

Happy Daxing :)

 

Write/Create Files into folder during Batch jobs

A sample code to write data into specified directory. I have used TEXTIO  here because my requirment is to run that from batch and i have used sys Operational framework  .

 

 

TextIo textIOWrite;
str fileLine, headerFileLine, fileName, filePath;
//Creating the header of my file

headerFileLine = strFmt(“%1|%2|%3|%4|%5|%6|%7|%8|%9|%10|%11|%12|%13|%14|%15|%16|%17|%18|%19|%20|%21|%22|%23|%24”,
‘client’, ‘company’, ‘keycode’, ‘order_number’, ‘order_date’, ‘po_number’, ‘po_date’, ‘international’, ‘ship_method’, ‘first_name’, ‘last_name’ ,’addr1′,
‘addr2′ ,’addr3′ ,’city’ ,’state’ ,’zip’ ,’country’ ,’ship_date’ ,’comments’ ,’item’, ‘description’ ,’size’ , ‘qty’);

//Insert logic here for data manupilation

// Inserting data into my FileLine
fileLine = strFmt(“%1|%2|%3|%4|%5|%6|%7|%8|%9|%10|%11|%12|%13|%14|%15|%16|%17|%18|%19|%20|%21|%22|%23|%24″,
’56’, countryName , ‘DEFAULT’, salesTable.SalesId, salesLine.ShippingDateRequested, SalesTable.CustomerRef, SalesLine.ReceiptDateRequested,
Country, SalesLine.DlvMode,’ ‘, SalesLine.DeliveryName, addr1, addr2, addr3, city , state , zip, logisticsPostalAddress.CountryRegionId,
SalesLine.ShippingDateRequested, notes, salesLine.ItemId, SalesLine.itemName(), Size::findbyRecId(InventTable::find(salesLine.ItemId).Size).Name,SalesLine.SalesQty);

//After creating the header and data line i am creating my file now
fileName = ‘MyFile’ + ‘.csv’; // I am creating CSV files here

filePath = SysFileStoreParameters::find().OutgoingDirectory; // I have created a parameter to save my folder location in system parameters and reading data from that custom parameter

if (filePath == ”)
{
throw error(‘File path no setup.’);
}

if (subStr(filePath, strLen(filePath)-1, 1) != @”\”)
{
filePath = filePath +@”\”;
}

filePath = filePath+fileName;

languageId = SystemParameters::find().SystemLanguageId;

FileIOPermission = new FileIOPermission(filePath, “RW”);
FileIOPermission.assert();

textIOWrite = new TextIo(filePath , “W”, 20127);

textIOWrite.write(headerFileLine);
textIOWrite.write(fileLine);

AX7 Technical Changes Summary

With the AX 7, Microsoft Dynamics AX have been changed in such a manner that it can truly be classed as a brand new platform. On the function side, the changes are minimal (only the required changes to run the features on this  new platform).

In today’s post, we’ll look briefly at what is changed from technical perspective.

Client
The win 32 rich client is replaced with a browser (IE, Edge, Chrome, Safari).

AOS
Replaced with the ASP.Net web application running on an IIS.

Batch
If the AOS is gone, how my batches will run? Well a new windows service will perform this task.

MorphX
This is replaced with Visual Studio. Extensions have been added to VS to deal with model management, code compile and build. The compilation can either be done from VS or using a standalone tool xppc.

XPP
XPP stays as it is  (on the surface). Under the hood there is no p-code, no interpreter. The compile now results in CIL. The unit of compile is the object itself. What does this means? Before AX7 if a method of a class fails to compile, other methods were still usable. IN AX7 the whole class’s compilation will fail. There are a lot of other enhancements to XPP. MFP’s blog is the best place to find out what these are.

AOT
AOT is visible from VS in a read-only mode and is called “Application Explorer”. It is available in “Classic view” and “Model View”. The object location have changed for some of the objects  (EDT, classes etc.) and these are now grouped with similar objects.

Model Store
Model store is no more in the database. The AX application code is stored in the files on disk in XML format.

Model
The concept of model is same as previous versions i.e. a group of objects that typically can be distributed.

Package
New concept in AX7. A package can consist of one or more models and is a used for deployment/compilation of these models. Each package have its own folder. Inside the package folder model folders exist.

VS Solution
A VS solution is a collection of projects. The solution information is not saved in the packages/models.

VS Project
A VS project is a group of objects that are related. A VS solution can have more than one VS project. Similar to VS solution, the project information is not saved in the packages/models. A VS project can only belong to one Model. Projects can be exported as .axpp file and imported on other AX7 installations.

Debugging
There is no standalone debugging application. VS is used for debugging. To start debugging a start-up project and start-up object must be specified.

Build
A single project, model or a set of models can be build. The option to synchronize database is available as part of the build process.

Original post can be found here

Further in depth details for AX 7.0 can be found here

Change No of Decimal Places in Dynamics AX

My scenario is to change the number of decimal places through out AX to 4 .It is possible and we can change all the amount fields in AX to 4 decimal places or any no of decimal places.

But the challenge is what will happen to the documents which are in open state or are in progress, for example, open work lines, an open wave, open purchase order lines, open sales order lines, production order at any stage other than ended.

Do this AT YOUR OWN RISK and test everything fully.

Assumption

All open document especially the production orders, work and waves should be closed prior to do this customization.

To change the number of decimal places in Microsoft AX 2012, follow these steps:
1. Change the NoOfDecimals property of the AmountCur, Amount, Qty and RealBase ExtendDataTypes to 4.to do this, follow these steps:
a. Open the Application Object Table (AOT) by pressing CTRL-D on the keyboard.
b. Click Data Dictionary, and then click Extended Data Types.
c. Locate the AmountCur and Qty fields, and then change the NoOfDecimals property to 4.
d. Save the changes that you made in the AOT.

EDTS-Blog
2. Change the round-off value for the exchange rates. To do this, follow these steps:
General Ledger -> Setup -> Currency -> Currency Exchange Rates.
a. Select the Currency -> Click the Round-off tab.
b. Set the round-off value to .0001 on all four modules. These are the following:
∴ General
∴ Sales Order
∴ Purchase Order
∴ Prices

Currency-Blog

The AmountCur ExtendDataType is used for pricing, and the Qty ExtendDataType is used for quantity amounts. When you change the NoOfDecimals property to 4, all fields and controls that are using these ExtendDataTypes are changed globally. The user can then type values with up to four decimal places.

When you change the round-off value, the value that the user types is saved correctly to the database. Make sure that you add enough zeros for the NoOfDecimals property that you specified. You must make sure to correctly set the NoOfDecimals property so that all four decimal places are used. For example, if you leave the round-off value at .0100, the Net Amount on a purchase order will be rounded to two decimals instead of four.

To make the changes to the decimal place visible for Production sessions and for Master Planning sessions, follow these steps:
1.FOR ax 2009: In the Main Menu window, click Basic, click Setup, click Units, and then click Units.

For ax 2012  Organization Administration -> Setup -> Units -> Units
2. Locate the unit of measure that you want to affect.
In the Decimals field, type 4.

As my scenario was to change all values to 4 decimal places so i have updated all the units listed here to 4 decimal precision

Units-Blog

Reference Blog

Steps to perform after DB restoration

Whenever we Restore DB from other machine (Like PROD to SandBox ) we always need to change some parameter configuration settings so that our machine will not point to the source machine (Like PROD). Its a general practice to copy PROD on Prod replica machines so its easy to list down some areas so that we can hammer on the right spot.

Here are some steps to remember so that every thing will point to the desired machine

 

System administration -> Setup -> Business Intelligence – > Analysis Server

System administration -> Setup -> Business Intelligence – > SSRS Server

System administration -> Setup -> System -> Help Server

AOT-> Tables -> Ledger Parameter – > Fieldname (ManagmentReporterURL) change MR server path (if installed)

System administration -> Setup -> Setup -> System -> Email parameters

System administration -> Setup -> EP-> Websites ->Sites

AOT-> Classes -> WHSMobileClases -> change in main method-> Mobile portal path (if installed)

System administration -> Setup -> Setup ->   Batch Group (change assigned server)

System administration -> Setup -> Setup -> System -> Server configuration (delete extra servers)

System administration -> Setup -> Setup -> System -> Service account

System administration -> Setup -> Setup -> System -> Load balancing

Send email from AX using exchange servers

There are number of posts to sent emails from AX using Hotmail(Live) or gmail exchange server. This is really helpful when we don’t have exchange is in place due to high cost or you just want to send emails for testing or demo purpose, so in this case we can use this method .

To achieve this requirement go to System Administration | Setup | System | E-mail parameters

P.S. I am using a dedicated email account at outlook (Hotmail) domain for this example.

Email parameters

 

Here is the job I wrote to send email for selected user. I name it SendTextMail as in my following post I will be writing to send invitation from AX using Hotmail or Gmail exchange server.

//SmtpSSL

staticvoid SendTextMail(Args _args)

{

System.Net.Mail.MailMessage             mailMessage;

System.Net.Mail.SmtpClient              myMail;

System.Net.Mail.MailAddressCollection   mailcoll;

System.Net.Mail.MailAddress             mailFrom;

System.Net.Mail.MailAddress             mailTo;

System.Net.Mail.MailAddress             mailCC;

str                                     receiverMailAddress;

str                                     mailBody;

str                                     smtpServer;

str                                     mailSubject;

str                                     CcMailAddress;

int                                     SMTPPort;

#File

str                                     mail;

str                                     pwd;

Dialog dialog = new Dialog(‘Email’);

Dialogfield     person, emailSubject, emailBody;

HcmWorker       hcmWorker;

UserInfo        userInfo;

DirPersonUser   dirPersonUser;

SysUserInfo     sysUserInfo;

SysEmailParameters parameters;

// dialog field to select user to whom email will be send

person          = dialog.addField(extendedTypeStr(HcmWorkerRecId ), ‘Person :’ );

emailSubject    = dialog.addField(extendedTypeStr(Description), ‘Subject :’ );      // Email Subject

emailBody       = dialog.addField(extendedTypeStr(Notes), ‘Body :’ );               // Email Body

if(dialog.run())

{

parameters = SysEmailParameters::find();   // Find values from Email Parameters

new InteropPermission(InteropKind::ClrInterop).assert();

        // gets HcmWorker record based on person selected from user dialog

hcmWorker = hcmWorker::find(person.value());

if(!hcmWorker.RecId)   // Verify either user exist or not

{

throw error(‘User not found’);

}

selectfirstOnly dirPersonUser

join userInfo

where dirPersonUser.PersonParty == DirPartyTable::findByName(hcmWorker.name()).RecId &&

userInfo.id == dirPersonUser.User;

selectfirstOnly sysUserInfo

where sysUserInfo.Id == userInfo.id;      // Retrieve user info record for selected user

mailSubject         = emailSubject.value();

mailFrom            = new  System.Net.Mail.MailAddress(parameters.SMTPUserName ,”Name”);

mailTo              = new  System.Net.Mail.MailAddress(sysUserInfo.Email);

//mailTo            = new  System.Net.Mail.MailAddress(“test1@gmail.com”);

//mailCC            = new  System.Net.Mail.MailAddress(“test2@gmail.com”;

mailcoll            = new  System.Net.Mail.MailAddressCollection();

mailBody            = emailBody.value();

try

{

            // using the SMTP server ip //setup in email Parameters

smtpServer          = SysEmaiLParameters::find(false).SMTPRelayServerName;

mailMessage         = new System.Net.Mail.MailMessage(mailFrom,mailTo);

mailmessage.set_Subject(mailSubject);

mailmessage.set_Body(mailBody);

SMTPPort            = SysEmaiLParameters::find(false).SMTPPortNumber;

myMail              = new System.Net.Mail.SmtpClient(smtpServer, SMTPPort);

           // For SSL enabled mail servers. Ex: gmail, smtp.gmail.com, port 465 or 587

myMail.set_EnableSsl(true);

pwd = SysEmaiLParameters::password();

mymail.set_Credentials(New System.Net.NetworkCredential(parameters.SMTPUserName, pwd));

mymail.Send(mailmessage);

}

catch(Exception::CLRError)

{

throw Exception::CLRError;

}

mailMessage.Dispose();

CodeAccessPermission::revertAssert();

}

}

After running this job You will get this UI from where you will select person , Subject of email . and Body of email to sent click OK.

Email-dialog