Latest Entries »

I came across an issue while trying to send emails using email distributor batch job in AX 2012. If 10 entries are created in email sending status form, only one of them is emailed and rest of them were failing. I have found the reason for this in LCS and the reason is mentioned below:

SysEmailDistributor can only send one email with same attachment name in batch due to WinApiServer::FileDelete not removing files when called in common intermediate language (CIL).

Microsoft has confirmed that this is an issue, but they are not fixing at this time. More details can be found at the following link:

https://fix.lcs.dynamics.com/Issue/NotFixed/313591?bugId=1651803&qc=baf7c6ff636fd40738c7cc6618d53fce

So, the only resolution is to have different file name for your email attachments. For instance, if you are sending sales order invoice to your customer, you can have the sales order invoice number as your attachment file name.

Advertisements

Hi,

In AX 2012, we cannot use the set based operation on Dynamic queries (where filters on the query can be specified at run time). Now with AX 2012 R3, Microsoft has added a functionality to perform set based operation on Dynamic queries by adding a static method insert_recordset in Query class. More details can be found in the following blog post:

http://blogs.msdn.com/b/axperf/archive/2014/05/06/improving-ssrs-report-performance-using-new-r3-features-part-6.aspx

This is really helpful in improving SSRS report performance where Dynamic queries are used. Instead of using old code while (queryrun.next()), you should use this new set based method.

Enjoy Daxing.

 

Hi,

Recently, I added some X++ code related to MS hotfix in AX 2012 R2 environment to resolve an issue with Sales order invoicing. After adding the hotfix code, when I was clicking on Invoice button for a Sales order I was getting the below error:

“Removal of suspension of recid allocation for SalesParmLine has failed”.

I tried to do full CIL, AOS restart, delete  *.auc files, but it didn’t resolve the issue. So, I went to Tools -> options -> Development tab under development workspace and then uncheck the ‘Execute business operation in CIL” checkbox. After doing this, I clicked on the Invoice button and then I got the below error in addition to the above error:

“RecordInsertList object not initialized”

Then I looked at the code I added as part of the hotfix and found that the object was infact not initialized. So, I corrected that error and then all went fine after that. The conclusion is, whenever you get this error this might not always be related to CIL generation, so turn off the option in development workspace which I mentioned and then run the scenario again to find out if there are any runtime error in your modified X++ code.

 

Recently, I was trying to process the out of the box Production order cube available in AX 2012 R2 and got the below error:

The conversion of nvarchar data type to a datetime data type resulted in an out of range value.

I was getting this error due to the DaysDelayed column in ProdTableExpanded View in AX. I found this when I run the following select statement in SQL server management studio:

select DaysDelayed from ProdTableExpanded;

After running the above query, I got the same conversion error which I mentioned above. The resolution is to install the hotfix KB2859489. Here is the lifecycle services link from where you can download and install the hotfix:

https://fix.lcs.dynamics.com/Issue/CodeView/313591?kb=2859489.

After applying the hotfix code in ProdTableExpanded view, the cube successfully processed and deployed in SSAS database.

Enjoy!.

 

 

 

Recently, I had an issue in AX 2012 feature pack version where posting from AR or AP module resulted in Trial balance update process stuck in InProcess state. The checkbox ‘Update balance during the posting process’ greyed out in Financial dimension sets form and you cannot uncheck or check it again. The resolution for all the trial balance issues is to install the hotfix KB 2864076. This hotfix has lot of other dependent objects, so extra care is required if you are installing the hotfix directly because it may affect your customized objects in current AX implementation.

 

Not sure how many of you actually used the Issue search functionality in Microsoft Dynamics AX Lifecycle services. I recently used it to search an issue related to an SSRS report and found this really helpful. The tool searches for all the hotfixes released till date and then you can click on any of the hotfix to see the list of affected objects. The most useful part is that when you click on any object except SSRS report design, it will show you the exact X++ code changes made as part of the hotfix in a browser window. So without downloading the hotfix and running the impact analysis tool, you can determine what changes are being made as part of the hotfix and this will eventually save plenty of time doing the estimation for applying a hotfix in any AX environment.

Below is a sample screen shot of a DP class for Accrued purchases report showing in a browser window. The green highlighted code showing the additions and red one showing the deletion:

Image

Enjoy!

Consider a scenario, where we need to allow only those financial dimension segments to be edited on the forms which are empty. Suppose, we are defaulting the Financial dimension for Customer from Project record and we have a scenario to only allow those segments to be edited which are not defaulted from Project and are empty. In standard AX, we have the same scenario for Advanced Ledger Entry source document. Here, I am going to explain that how we can achieve the similar functionality for Customer master record in AX. Below are the detailed steps:

Step 1: Create a new class extends from DimensionLinkProvider class

Following are the details of the methods, you need to add:

In classDeclaration, add the variables as shown below:

Image

 

Override subscribed method and return isSubscribed variable as shown below:

Image

 

Override new method and add the code shown below:

Image

As you can see in the above code, we need to check for CustTable record and call our local method to add the logic for enable/disable individual dimension segment on the form. Now we need to create a new method in order to be called from the new method shown above. The new method will be used to call the delegate DimensionLinkAllowFieldEdit . Code is shown below:

Image

Now, override the allowFieldEdit method. This method responds to a Dimension controller object whenever a field is made editable for specific dimension attribute. Below is the definition for the method:

Image

Step 2: Add a reference for CustTableDimensionLinkProvider class in DimensionLinkProviders class

Open the new method of DimensionLinkProviders class and add the code as shown below. Note the letter ‘s’ in class name, this is different from the class from which we extend our new link provider class.

Image

 

Now, if you open any customer record from Accounts Receivable -> Common -> Customers, you can see this in action as shown below:

Image

 

As you can see, the ItemGroup financial dimension segment has some value, so it is not editable and hence the drop down arrow is not showing, whereas the Department segment is editable as it is empty. Interesting, isn’t it. This will work for the segmented entry control as well.

If you need to disable the main account segment in a segmented entry control displayed on the form, then you just need to call a method of LedgerDimensionAccountController class. The code is shown below:

ledgerDimensionController.parmLockMainAccountSegment(true);

You must have the LedgerDimensionAccountController object already initialized, if you have the segmented entry control on the form.

Consider a scenario where we have two customers account with the below Financial dimension values:

 

 

BusinessUnit

CostCenter

Department

Customer1

001

007

024

Customer2

002

011

031

 Now, let say I have a requirement to replace only CostCenter financial dimension for Customer1 with Customer2 if it is not empty. The resulting Financial dimension for Customer1 would become BusinessUnit: 001, CostCenter: 011 and Department: 024.

 Below is the code to implement the above scenario:

Image

I have added the comments on the code for better understanding. 

Enjoy!!

 

Recently, I had a requirement to show multiple selected records from Item master form to a new form, when a button is clicked on the Item master form. I wrote all the necessary code using MultiSelectionHelper class in X++ and applied the range on form’s datasource, but it was showing only one selected record on the new form instead of all the selected records. After wasting lot of time on this, I was finally able to figured out the solution which I want to share. The problem was that due to the dynalink created between the InventTable and the datasource on my new form, it was preventing all the selected records to be shown and only one record was showing on my new form. So, the solution is to clear the dynalinks on the datasource before applying the ranges. Below is the code I wrote in the datasource’s init method on my new form which is called from Item master form:

public void init()
{
MultiSelectionHelper multiSelectionHelper;
InventTable inventTableLocal;

QueryBuildDataSource qbds;

str selectedProducts;

super();

if (element.args().caller() &&
element.args().record())
{
multiSelectionHelper = MultiSelectionHelper::construct();
multiSelectionHelper.parmDatasource(element.args().record().dataSource());

inventTableLocal = multiSelectionHelper.getFirst();

while (inventTableLocal.RecId != 0 &&
EcoResProduct::find(inventTableLocal.Product).productSubtype() == EcoResProductSubtype::ProductMaster)
{
selectedProducts = queryRangeConcat(selectedProducts, inventTableLocal.ItemId);

inventTableLocal = multiSelectionHelper.getNext();
}

ecoResProductMaster_ds.query().dataSourceTable(tableNum(EcoResProductMaster)).clearDynalinks();

ecoResProductMaster_ds.query().literals(true);
ecoResProductMaster_ds.query().dataSourceTable(tableNum(EcoResProductMaster)).
addRange(fieldNum(EcoResProductMaster, DisplayProductNumber)).value(selectedProducts);
}
}