Wednesday, December 26, 2018

ADFS configuration error Invalid scope names

I am about to finish On-Prem deployment, where i was facing error at step number 18  as below:
"ADFS configuration for premises deployment Invalid scope names"

Grant-AdfsApplicationPermission : MSIS7628: Scope names should be a valid Scope Description name in AD FS configuration.
At C:\smcondc\adfschkns\fi\D365FO-OP\D365FO-OP-ADFSApplicationGroup.psm1:204 char:5

Link below helped me to solve this issue.

https://community.dynamics.com/ax/f/33/t/262091

Tuesday, December 25, 2018

Add Financial default dimension on form AX 2012

Followings are some useful links to understand Financial default dimension on Form AX 2012.

1) https://www.intergen.co.nz/blog/Tim-Schofield/dates/2011/12/how-to-add-a-financial-dimension-in-ax-2012/
2) https://community.dynamics.com/ax/b/mukeshhirwani_dynamicsax/archive/2012/09/07/how-add-financial-dimension-on-forms-inside-ax2012
3) https://dynamicscognizance.wordpress.com/2017/02/02/adding-financial-dimensions-of-form-ax-2012/
4) http://www.axdeveloperconnection.it/webapp/blog/financial-dimension-control-no-data-source

Tuesday, November 27, 2018

Enable single user multiple sessions windows server.

Follow steps below to enable single user multiple sessions in Windows server 2012 & 2016
1.Open registry editor using regedit from Run.
2. Navigate to path below.
HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\TerminalServer.
3. Select Terminal Server registry.
4. Update value of fSingleSessionPerUser from 1 to 0, which will allow to login multiple session for single user.

1. Log into the server using Remote Desktop.
2. Open the start screen (press the Windows key) and type gpedit.msc and open it
3. Go to Computer Configuration > Administrative Templates > Windows Components > Remote Desktop Services > Remote Desktop Session Host > Connections.
4. Set Restrict Remote Desktop Services user to a single Remote Desktop Services session to Disabled.
5. Double click Limit number of connections and set the RD Maximum Connections allowed to 999999.


Tuesday, October 16, 2018

Transaction log backup

In this post, i want to populate good to know information about log backup in SQL Server.

Query to know the history of transaction log backup.

SELECT      bs.backup_start_date, bs.backup_finish_date, *
FROM        msdb..backupfile bf
JOIN        msdb..backupset bs ON bf.backup_set_id = bs.backup_set_id
WHERE       bf.File_Type = 'L'

OR using

select database_name, max(backup_finish_date)
from msdb..backupset
where type = 'L'
group by database_name

Detailed reference for above query : Link

How often we should take transaction log backup: Link

 Recover data from transaction log backup: Link

Import Export model Dynamics 365 for operations

Following model management commands i have tried on Demo VM downloaded from LCS, which i found working as per the expectations.

Export model in Dynamics 365 operations.
C:\AOSService\PackagesLocalDirectory\Bin>ModelUtil.exe -export -metadatastorepath=C:\AOSService\PackagesLocalDirectory -modelname="FleetManagement" -outputpath=c:\temp

Import model in Dynamics 365 operations.
C:\AOSService\PackagesLocalDirectory\Bin>ModelUtil.exe -import -metadatastorepath=C:\AOSService\PackagesLocalDirectory -file=C:\Test\XYZDevelopments.axmodel

Delete model in dynamics 365 operations.
C:\AOSService\PackagesLocalDirectory\Bin>ModelUtil.exe -delete -metadatastorepath=C:\AOSService\PackagesLocalDirectory -modelname="FleetManagement"

Wednesday, October 10, 2018

Object Server XX: Fatal SQL condition during login.


Message in event viewer on AOS server:

Object Server XX:  Fatal SQL condition during login. Error message: "The internal time zone version number stored in the database is higher than the version supported by the kernel (11/10). Use a newer Microsoft Dynamics AX kernel."


select * from SQLSystemVariables
WHERE PARM = 'SYSTIMEZONESVERSION'

Execute query above and check value in field "VALUE", it should look like image below. Please note that message in event viewer is helpful to update this value.



Event viewer message shows kernel (11/10) means current value is 11 and supported is 10, so here we need to update value to 10 using query below. - in your environment it can be 8/7 instead of 11/10 or it can be anything. I don't come across any MS documentation for the same. Please share your experience for the same error, does it works for you or have you solved by any other way.

update SQLSystemVariables set VALUE = 10
WHERE PARM = 'SYSTIMEZONESVERSION'

Friday, September 28, 2018

How to give authorization in fiddler

Fiddler: Set username and password for basic authentication

1. Open fiddler, click Tools->TextWizard.
2. Select checkbox of "To Base64"
3. Input your user name and password in top textbox such as
myUsername:myPassword
4. Go back to fiddler composer screen, below Host: line add line for Authorization as shown in image below.

Authorization: Basic bXlVc2VybmFSDlaAOaptOIeVBhc3N3b3J

https://XXX.YYY.ZZZ.AAA:4444/user/auth

User-Agent: Fiddler
Host: XXX.YYY.ZZZ.AAA:4444
Authorization: Basic bXlVc2VybmFSDlaAOaptOIeVBhc3N3b3J

Composer window should look like image below.




5. Hit execute.
6.Observe Result column on left side as well as Inspectors tab.


Wednesday, September 26, 2018

SQL Administration

I want to maintain this post to make my day to day SQL administration activities easy.

1. SQL always on demonstration. - Link
2. Tracking page split in detail - Link

Tuesday, September 25, 2018

Dynamics 365 for operations administration.

I want to maintain this blog post for purpose of dynamics 365 for operations administration tips and tricks.
This will consist of useful links from around the world to make administrator's life easy.

1. Dynamics 365 for operations, downloaded demo or development VHD default passwords - Link
Server remote login:
Username: local\Administrator
Password: pass@word1

SQL login (SSMS)
Username: axdbadmin 

Password: AOSWebSite@123

2. Database synchronizations using powershell
C:\AOSService\webroot\bin\Microsoft.Dynamics.AX.Deployment.Setup.exe -bindir "C:\AosService\PackagesLocalDirectory" metadatadir "C:\AosService\PackagesLocalDirectory" -sqluser "AOSUSER" -sqlserver "." -sqldatabase "AxDB" -setupmode "sync" -syncmode "fullall" -isazuresql "false" -sqlpwd "AOSWebSite@123"


3. Batch service exception/ Maintenance mode in Dynamics 365 operations - Link
Command: (Standard way)
C:\AOSService\PackagesLocalDirectory\Bin\Microsoft.Dynamics.AX.Deployment.Setup.exe –metadatadir C:\AOSService\PackagesLocalDirectory –bindir C:\AOSService\PackagesLocalDirectory –sqlserver . –sqldatabase axdb –sqluser AOSUser –sqlpwd AOSWebSite@123 –setupmode maintenancemode –isinmaintenancemode false

Using SQL query (Not verified!)
Update SQLSystemvariables set Value=0 where parm='CONFIGURATIONMODE'

4. Import license file  - Link

5. Deploy Dynamics 365 for operations environment into Azure - Link
This is good series of blog posts, to take you through deployment of various LCS environments. i.e. Development, Build and Test and Production environments.

6. Configure port forwarding. - Link

6. Install latest CU on local developer VM. - Link


Saturday, August 11, 2018

Reindexing Dynamis AX database

Below script will create job to re-index and update statistics of dynamics ax database.

In script below fill factor is used as 30%, review and adjust it as per your requirements.

This will be useful as part of Dynamics AX database maintenance.

Replace <Domain UserName> with domain user name.
Replace DatabaseName with database name.

 
USE [msdb]
GO

/****** Object:  Job [<DatabaseName> - Index and Statistics maintenance]    Script Date: 9/26/2017 12:28:53 PM ******/
BEGIN TRANSACTION
DECLARE @ReturnCode INT
SELECT @ReturnCode = 0
/****** Object:  JobCategory [[Uncategorized (Local)]]    Script Date: 9/26/2017 12:28:53 PM ******/
IF NOT EXISTS (SELECT name FROM msdb.dbo.syscategories WHERE name=N'[Uncategorized (Local)]' AND category_class=1)
BEGIN
EXEC @ReturnCode = msdb.dbo.sp_add_category @class=N'JOB', @type=N'LOCAL', @name=N'[Uncategorized (Local)]'
IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback

END

DECLARE @jobId BINARY(16)
EXEC @ReturnCode =  msdb.dbo.sp_add_job @job_name=N'DatabaseName - Index and Statistics maintenance',
  @enabled=1,
  @notify_level_eventlog=0,
  @notify_level_email=0,
  @notify_level_netsend=0,
  @notify_level_page=0,
  @delete_level=0,
  @description=N'No description available.',
  @category_name=N'[Uncategorized (Local)]',
  @owner_login_name=N'<Domain UserName>', @job_id = @jobId OUTPUT
IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
/****** Object:  Step [Update column statistics only]    Script Date: 9/26/2017 12:28:54 PM ******/
EXEC @ReturnCode = msdb.dbo.sp_add_jobstep @job_id=@jobId, @step_name=N'Update column statistics only',
  @step_id=1,
  @cmdexec_success_code=0,
  @on_success_action=3,
  @on_success_step_id=0,
  @on_fail_action=3,
  @on_fail_step_id=0,
  @retry_attempts=0,
  @retry_interval=0,
  @os_run_priority=0, @subsystem=N'TSQL',
  @command=N'SET NOCOUNT ON
DECLARE @init INT = 1, @cnt INT, @tsql nvarchar(max) = N''''
DECLARE @objectid int;
DECLARE @schemaname nvarchar(130);
DECLARE @objectname nvarchar(130);
DECLARE @statsname nvarchar(130);
DECLARE @tableStat table (id int identity(1,1), obj_id int, name varchar(1000))
INSERT INTO @tableStat
SELECT [object_id], name
FROM sys.stats
WHERE OBJECTPROPERTY([object_id], ''IsUserTable'') = 1
                AND (auto_created = 1 or user_created = 1)

SELECT @cnt = COUNT(1) FROM @tableStat

WHILE @init <= @cnt
BEGIN
select @objectid = obj_id, @statsname = name from @tableStat where id = @init

SELECT @objectname = QUOTENAME(o.name), @schemaname = QUOTENAME(s.name)
FROM sys.objects AS o
JOIN sys.schemas as s ON s.schema_id = o.schema_id
WHERE o.object_id = @objectid;

SET @tsql = N''UPDATE STATISTICS '' + @schemaname + N''.'' + @objectname + N'' '' + @statsname + N'' WITH FULLSCAN'';
--PRINT @tsql
EXEC sp_executesql @tsql
SET @init += 1
END',
  @database_name=N'DatabaseName',
  @flags=0
IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
/****** Object:  Step [Reorganize, Rebuild indexes and Update statistics.]    Script Date: 9/26/2017 12:28:54 PM ******/
EXEC @ReturnCode = msdb.dbo.sp_add_jobstep @job_id=@jobId, @step_name=N'Reorganize, Rebuild indexes and Update statistics.',
  @step_id=2,
  @cmdexec_success_code=0,
  @on_success_action=1,
  @on_success_step_id=0,
  @on_fail_action=2,
  @on_fail_step_id=0,
  @retry_attempts=0,
  @retry_interval=0,
  @os_run_priority=0, @subsystem=N'TSQL',
  @command=N'--Index rebuild and reorg
SET NOCOUNT ON
SET QUOTED_IDENTIFIER ON -- 22/08/2015 added to avoid error due to xml and name identifier.
DECLARE @tsql NVARCHAR(MAX),@fillfactor INT=70,@init int = 1, @cnt int =0,@AvgFragmentationInPercent DECIMAL(6,2), @heap bit = 0
DECLARE @FragmentedIndexs TABLE (ID INT IDENTITY(1,1),IndexName VARCHAR(500),ObjectName VARCHAR(500),AvgFragmentationInPercent DECIMAL(6,2),FragmentCount INT,AvgFragmentSizeInPage DECIMAL(6,2),IndexDepth INT, index_id INT)

INSERT INTO @FragmentedIndexs
SELECT QUOTENAME(I.name) Name, QUOTENAME(DB_NAME())+''.''+QUOTENAME(OBJECT_SCHEMA_NAME(I.[object_id]))+''.''+QUOTENAME(OBJECT_NAME(I.[object_id])) ObjectName,PS.avg_fragmentation_in_percent,
PS.fragment_count,PS.avg_fragment_size_in_pages,PS.index_depth, i.index_id FROM sys.dm_db_index_physical_stats (DB_ID(), NULL ,NULL, NULL, ''LIMITED'') AS PS
INNER JOIN sys.indexes AS I ON PS.[object_id]= I.[object_id] AND PS.index_id = I.index_id WHERE PS.avg_fragmentation_in_percent > 10 --AND PS.index_type_desc = ''NONCLUSTERED INDEX''  
AND page_count > 0 AND page_count > 500 --AND i.index_id = 0 -- 22/08/2015 to exclude small tables having less than 500 pages for live database.
ORDER BY PS.avg_fragmentation_in_percent DESC

SELECT @cnt = COUNT(ID) FROM @FragmentedIndexs

WHILE @cnt >= @init
BEGIN
SELECT @AvgFragmentationInPercent=AvgFragmentationInPercent, @heap = CASE WHEN (IndexName IS NULL OR index_id = 0) THEN 1 ELSE 0 END FROM @FragmentedIndexs WHERE ID=@init

--Index rebuild
IF @AvgFragmentationInPercent<=30.00
BEGIN
 SELECT @tsql = STUFF((SELECT DISTINCT '';''+''ALTER INDEX ''+FI.IndexName+'' ON ''+FI.ObjectName+'' REORGANIZE ''
 FROM @FragmentedIndexs FI WHERE FI.AvgFragmentationInPercent <= 30 AND FI.ID = @init
 AND NOT EXISTS (SELECT * FROM @FragmentedIndexs X WHERE X.index_id = 0 AND FI.ObjectName = X.ObjectName)
 FOR XML PATH('''')), 1,1,'''')
END

ELSE IF @AvgFragmentationInPercent>30.00
BEGIN
 SELECT @tsql = STUFF((SELECT DISTINCT '';''+''ALTER INDEX ''+FI.IndexName+'' ON ''+FI.ObjectName+'' REBUILD WITH (FILLFACTOR = ''+CONVERT(VARCHAR(3),@fillfactor)+'') ''
 FROM @FragmentedIndexs FI WHERE FI.AvgFragmentationInPercent > 30 AND FI.ID = @init
 AND NOT EXISTS (SELECT * FROM @FragmentedIndexs X WHERE X.index_id = 0 AND FI.ObjectName = X.ObjectName)
 FOR XML PATH('''')), 1,1,'''')
END

--print @tsql
EXEC sp_executesql @tsql

--Update stats
IF @AvgFragmentationInPercent <= 30.00
BEGIN
SELECT @tsql = STUFF(( SELECT DISTINCT '';''+''UPDATE STATISTICS '' + FI.ObjectName + '' '' + FI.IndexName FROM @FragmentedIndexs FI
WHERE FI.AvgFragmentationInPercent <= 30 AND FI.ID = @init FOR XML PATH('''')), 1,1,'''')
--print @tsql
EXEC sp_executesql @tsql
END

--Table rebuild
IF @heap = 1
BEGIN
SELECT @tsql = STUFF(( SELECT DISTINCT '';''+''ALTER TABLE '' + FI.ObjectName + '' REBUILD'' FROM @FragmentedIndexs FI
WHERE FI.ID = @init AND index_id = 0 FOR XML PATH('''')), 1,1,'''')
--print @tsql
EXEC sp_executesql @tsql
END

SELECT @tsql = '''', @heap = 0
SET @init += 1
END
',
  @database_name=N'DatabaseName',
  @flags=0
IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
EXEC @ReturnCode = msdb.dbo.sp_update_job @job_id = @jobId, @start_step_id = 1
IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
EXEC @ReturnCode = msdb.dbo.sp_add_jobschedule @job_id=@jobId, @name=N'Daily',
  @enabled=1,
  @freq_type=4,
  @freq_interval=1,
  @freq_subday_type=1,
  @freq_subday_interval=0,
  @freq_relative_interval=0,
  @freq_recurrence_factor=0,
  @active_start_date=20140603,
  @active_end_date=99991231,
  @active_start_time=30000,
  @active_end_time=235959,
  @schedule_uid=N'b728c1ec-de6f-44bb-abee-dacc0049de00'
IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
EXEC @ReturnCode = msdb.dbo.sp_add_jobserver @job_id = @jobId, @server_name = N'(local)'
IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
COMMIT TRANSACTION
GOTO EndSave
QuitWithRollback:
    IF (@@TRANCOUNT > 0) ROLLBACK TRANSACTION
EndSave:
GO

Wednesday, July 25, 2018

Create and release product variant Dynamics 365

Code below can be used to create and release product variant in Dynamics AX 2012 & Dynamics 365 Operations.

It will work straight forwardly for AX 2012.

For Dynamics 365 operations,you need to create runable class to execute the same.

I have checked and tested that below code is working fine in dynamics 365 operations for different application but not to import data.

As all the classes and tables used below are available in Dynamics 365 operations, it should work to import as well.

Awaiting for feedback, if any!
 static void dtReleaseProductAllVariant(Args _args)  
 {  
   ecoResDistinctProductVariant    ecoResDistinctProductVariant;  
   EcoResProductVariantDimensionValue EcoResProductVariantDimensionValue;  
   RefRecId              ecoResDistinctProductVariantRecId;  
   EcoResProductReleaseManagerBase   releaseManager;  
   container              productDimensions;  
   EcoResProduct            ecoResProduct;  
   EcoResProductDimensionAttribute   prodDimensionAttribute; //fix for perticular dim, using tableid  
   //Configuration  
   EcoResProductMasterConfiguration  productMasterConfiguration;  
   EcoResConfiguration         ecoResConfiguration;  
   //Color  
   EcoResProductMasterColor      productMasterColor;  
   EcoResColor             ecoResColor;  
   //Size  
   EcoResProductMasterSize       productMasterSize;  
   EcoResSize             ecoResSize;  
   //Style  
   EcoResProductMasterStyle      productMasterStyle;  
   EcoResStyle             ecoResStyle;  
   CommaTextIo         file;  
   container          rec;  
   Dialog       d;  
   DialogField     df1, df2;  
   int64        counter = 0;  
   ;  
   d = new Dialog("Release Product Variant");  
   df1 = d.addField(ExtendedTypeStr("FilenameOpen"));  
   if (d.run())  
   {  
     file = new CommaTextIo(df1.value(), 'r');  
     file.inFieldDelimiter(';');  
     try  
     {  
       while (file.status() == IO_Status::Ok)  
       {  
         rec = file.read();  
         if(!rec)  
           break;  
           ttsBegin;  
           ecoResProduct = EcoResProduct::findByProductNumber(conPeek(rec, 1));  
           //Configuration - Start  
           ecoResConfiguration = EcoResConfiguration::findByName(conPeek(rec, 2));  
           if (!ecoResConfiguration.RecId)  
           {  
             ecoResConfiguration.Name = conPeek(rec, 2);  
             ecoResConfiguration.insert();  
           }  
           select * from productMasterConfiguration where productMasterConfiguration.Configuration == ecoResConfiguration.RecId &&  
                             productMasterConfiguration.ConfigProductMaster == ecoResProduct.RecId;  
           if(!productMasterConfiguration.RecId)  
           {  
             select * from prodDimensionAttribute where prodDimensionAttribute.DimensionTableId == tableNum(EcoResConfiguration);  
             productMasterConfiguration.Configuration              = ecoResConfiguration.RecId;  
             productMasterConfiguration.ConfigProductDimensionAttribute     = prodDimensionAttribute.RecId;  
             productMasterConfiguration.ConfigProductMaster           = ecoResProduct.RecId;  
             productMasterConfiguration.insert();  
           }  
           //Configuration - End  
           //Size - Start  
           ecoResSize = EcoResSize::findByName(conPeek(rec, 3));  
           if (!ecoResSize.RecId)  
           {  
             ecoResSize.Name = conPeek(rec, 3);  
             ecoResSize.insert();  
           }  
           select * from productMasterSize where productMasterSize.Size == ecoResSize.RecId &&  
                             productMasterSize.SizeProductMaster == ecoResProduct.RecId;  
           if(!productMasterSize.RecId)  
           {  
             select * from prodDimensionAttribute where prodDimensionAttribute.DimensionTableId == tableNum(EcoResSize);  
             productMasterSize.Size              = ecoResSize.RecId;  
             productMasterSize.SizeProductDimensionAttribute  = prodDimensionAttribute.RecId;  
             productMasterSize.SizeProductMaster        = ecoResProduct.RecId;  
             productMasterSize.insert();  
           }  
           //Size - End  
           //Color - Start  
           ecoResColor = EcoResColor::findByName(conPeek(rec, 4));  
           if (!ecoResColor.RecId)  
           {  
             ecoResColor.Name = conPeek(rec, 4);  
             ecoResColor.insert();  
           }  
           select * from productMasterColor where productMasterColor.color == ecoResColor.RecId &&  
                             productMasterColor.ColorProductMaster == ecoResProduct.RecId;  
           if(!productMasterColor.RecId)  
           {  
             select * from prodDimensionAttribute where prodDimensionAttribute.DimensionTableId == tableNum(EcoResColor);  
             productMasterColor.Color              = ecoResColor.RecId;  
             productMasterColor.ColorProductDimensionAttribute  = prodDimensionAttribute.RecId;  
             productMasterColor.ColorProductMaster        = ecoResProduct.RecId;  
             productMasterColor.insert();  
           }  
           //Color - End  
           //Style - Start  
           ecoResStyle = EcoResStyle::findByName(conPeek(rec, 5));  
           if (!ecoResStyle.RecId)  
           {  
             ecoResStyle.Name = conPeek(rec, 5);  
             ecoResStyle.insert();  
           }  
           select * from productMasterStyle where productMasterStyle.Style == ecoResStyle.RecId &&  
                             productMasterStyle.StyleProductMaster == ecoResProduct.RecId;  
           if(!productMasterStyle.RecId)  
           {  
             select * from prodDimensionAttribute where prodDimensionAttribute.DimensionTableId == tableNum(EcoResStyle);  
             productMasterStyle.Style              = ecoResStyle.RecId;  
             productMasterStyle.StyleProductDimensionAttribute  = prodDimensionAttribute.RecId;  
             productMasterStyle.StyleProductMaster        = ecoResProduct.RecId;  
             productMasterStyle.insert();  
           }  
           //Style - End  
           //Create a container to hold dimension values  
           productDimensions = EcoResProductVariantDimValue::getDimensionValuesContainer(conPeek(rec, 2),  
                                                   conPeek(rec, 3),  
                                                   conPeek(rec, 4),  
                                                   conPeek(rec, 5));  
           //Create Product search name  
           ecoResDistinctProductVariant.DisplayProductNumber = EcoResProductNumberBuilderVariant::buildFromProductNumberAndDimensions(  
                                             conPeek(rec, 1),  
                                             productDimensions);  
           //Create Product variant with Product and dimensions provided  
           ecoResDistinctProductVariantRecId = EcoResProductVariantManager::createProductVariant(ecoResProduct.RecId,  
                                             ecoResDistinctProductVariant.DisplayProductNumber,  
                                             productDimensions);  
           //Find newly created Product Variant  
           ecoResDistinctProductVariant = ecoResDistinctProductVariant::find(ecoResDistinctProductVariantRecId);  
           //Now release the Product variant  
           releaseManager = EcoResProductReleaseManagerBase::newFromProduct(ecoResDistinctProductVariant);  
           releaseManager.release();  
           counter++;  
           ttsCommit;  
         info(strFmt("%1 Product variant released successfully",conPeek(rec, 1)));  
         info(strFmt("Total %1 Product variants released successfully",counter));  
       }  
     }  
     catch  
     {  
       info(strFmt("Total %1 Product variants released successfully",counter));  
       info(strFmt("Job terminated for product %1 and config %2 Size %3 Color %4 Style %5",conPeek(rec, 1),conPeek(rec, 2),conPeek(rec, 3),conPeek(rec, 4),conPeek(rec, 5)));  
     }  
   }  
 }  

Saturday, July 7, 2018

Dynamics ax administration guide

1) Deploy all Reports using Dynamics AX Power shell.

Publish-AXReport –ReportName * -id <AX Report server config name>

2) Delete label files from AOT - Dynamics AX 2012.
Solution provided in below two blogs are useful.

https://community.dynamics.com/ax/b/axilitynet/archive/2015/12/08/label-file-creation-and-language-removal

http://www.agermark.com/2014/01/how-to-delete-label-files-from-ax-2012.html

3) Scale out dynamics 365 operation On Premise installation.

4) SQL/Dynamics AX Administration.
     a. Read this post to get currently running queries, this will help to identify if any blocking.
     b. Read this post to get script for re-indexing and statics update for Dynamics AX database.
     c. Read this post to get script for SQL wait stats - Link

5) Management Reporter
    a. This link is useful to Rebuild Management Reporter Database.
    b. This link is useful to find MRDM synchronization issues due to bad records.

6) Visio diagrams
     1) Stencils Dell - Link
     2) Stencils Cisco - Link

7) Object Id conflicts, while synchronization - Link





Wednesday, July 4, 2018

Create simple dialog dynamics 365 Operations

Below code can be used as base to create dialog in Dynamics 365 Operations.

To Start with, create new project in either existing model or create new model and add a new Runnable class with name ppPurchDeliveryScheduleCreateDialog.

Copy code below and past into your class code area, this contains all the basic methods, which are required to override while extending RunBase class.

Modify logic of this dialog as per your requirement.

/// <summary>
/// The <c>ppPurchDeliveryScheduleCreate</c> class takes inputs from user and creates delivery schedule lines.
/// </summary>
/// <remarks>
/// Create delivery schedule lines.
/// </remarks>
public class ppPurchDeliveryScheduleCreateDialog extends RunBase
{
    // User Input fields
    DialogField     fieldNoOfLines;
    
    // Variables to store user input
    ppNumberOfLines numberOfLines;

    // pack() and unpack() methods are used to load the last value from user
    // for our simple example we are not going to use them.
    public container pack()
    {
        return conNull();
    }

    public boolean unpack(container packedClass)
    {
        return true;
    }

    // Dialog method to capture runtime user inputs for customer details
    public Object dialog()
    {
        Dialog dialog = super();

        // Set a title for dialog
        dialog.caption( 'Enter number of lines:');

        // Add a new field to Dialog
        fieldNoOfLines = dialog.addField(extendedTypeStr(ppNumberOfLines), 'No of lines:');

        return dialog;
    }

    // Retrieve values from Dialog
    public boolean getFromDialog()
    {
        numberOfLines = fieldNoOfLines.value();
        return super();
    }

    //write business logic.
    public void run()
    {
        //TODO: User numberOfLines variable to create delivery schedule.
    }

    public static void main(Args _args)
    {
        ppPurchDeliveryScheduleCreateDialog deliverySchedule = new ppPurchDeliveryScheduleCreateDialog();

        // Prompt the dialog, if user clicks in OK it returns true
        if (deliverySchedule.prompt())
        {
            deliverySchedule.run();
        }
    }

}

Saturday, June 23, 2018

Retrieve last approver name for any workflow

Below code can be used to retrieve last approver name for any workflow activated in Dynamics AX/ 365 Finance and operations.

 static void dtGetLastApproverName(Args _args)  
 {  
    WorkflowTrackingStatusTable workflowTrackingStatus;  
    WorkflowTrackingTable workflowTrackingTable;  
    WorkflowTrackingCommentTable workflowTrackingCommentTable;  
    UserInfo userInfo;  

    select firstFast RecId, User from workflowTrackingTable  
     order by RecId desc   
     join workflowTrackingCommentTable   
    where workflowTrackingCommentTable.WorkflowTrackingTable ==   
          workflowTrackingTable.RecId  
    join UserInfo where UserInfo.id == WorkflowTrackingTable.User  
    exists join workflowTrackingStatus  
    where workflowTrackingTable.WorkflowTrackingStatusTable ==   
    workflowTrackingStatus.RecId  
    && workflowTrackingStatus.ContextRecId == _salesRecId //PurchRecID  
    && workflowTrackingStatus.ContextTableId == tableNum(SalesTable) //SalesTable  
    && workflowTrackingTable.TrackingType == WorkflowTrackingType::Approval;  

    if (workflowTrackingTable.RecId > 0)  
    {  
      info(strFmt(“%1 – %2 “,userInfo.name, workflowTrackingCommentTable.RecId));  
    }  
 }  

Move SQL Server database files

Create tempdb partitions and move to new location location.

Know existing location:
SELECT name, physical_name FROM sys.master_files WHERE database_id = DB_ID('tempdb');

Move to new location:

ALTER DATABASE tempdb MODIFY FILE ( NAME = tempdev, FILENAME = "C:\SQLDB\tempdb.mdf")
ALTER DATABASE tempdb MODIFY FILE ( NAME = templog, FILENAME = "C:\SQLDB\templog.ldf")
ALTER DATABASE tempdb MODIFY FILE ( NAME = tempdev1, FILENAME = "C:\SQLDB\tempdb1.mdf")
ALTER DATABASE tempdb MODIFY FILE ( NAME = templog1, FILENAME = "C:\SQLDB\templog1.ldf")

Note:
Also verify that SQL service account has full access to new location.

To move msdb, need to follow steps below after executing above queries.

1. Go to SQL Server configuration manager.
2. Update path on parameters.


Friday, June 22, 2018

Verify active/enabled product dimension

Below code can be used to verify active or enabled specific or all product dimensions.

 
   public static void main(Args _args)
   {
     InventTable   inventTable;  
     InventDimParm  inventDimParm;  
     ;  

     inventTable  = InventTable::find('ABC');  

     inventDimParm = InventDimParm::activeDimFlag(InventDimGroupSetup::newInventTable(inventTable));  

     if(inventDimParm.InventColorIdFlag)  
     {  
       info("Color Enabled."); 
     }  
   }

Production picking list reservation through X++

Reserve without changing dimension.
 dtProdBOMReserve(Args _args)   
 {   
   prodJournalBOM prodJournalBOM;
   InventUpd_Reservation reservation;   
   ;   

   select * from prodJournalBOM    
    where prodJournalBOM.RecId == 5637695365;   

   movement = InventMovement::construct(prodJournalBOM);   
   reserveQuantity = prodJournalBOM.BOMConsump - abs(movement.transIdSum().reserved());  
   if(reserveQuantity)
   {
     reservation = InventUpd_Reservation::newMovement(movement,-reserveQuantity,true);   
     reservation.updateNow();  
   } 
   info('Reserved.');   
  }   

Reserve for specific dimension.


static void dtProdBOMReserveWithDim(Args _args)  
 {  
   prodJournalBOM prodJournalBOM;;  
   InventDim InventDim;  
   InventUpd_Reservation reservation;  
   ;  
   select * from prodJournalBOM  
     where prodJournalBOM.RecId == 5637695365;  

   //Update dimension
   inventDim = prodJournalBOM.inventDim();  
   inventDim.wMSLocationId = '12420301';  

   movement = InventMovement::construct(prodJournalBOM);  

   reserveQuantity = prodJournalBOM.BOMConsump - abs(movement.transIdSum().reserved()); 
 
   if(reserveQuantity)
   {
     reservation = InventUpd_Reservation::newInventDim(movement,inventDim, -reserveQuantity,false);  
     reservation.updateNow();  
   }

   info('Reserved.');  
 }  

Monday, June 18, 2018

Cache weight item

Below method is to check, if cache weight is enabled or not for a particular Item.

AX 2012

Dynamics 365 Operations


Saturday, June 16, 2018

All the users in domain are not available to import.

When we are running Active Directory Import Wizard in Microsoft Dynamics AX. All the users in domain might not be available to import.

Link below is the solution for the same.

https://blogs.msdn.microsoft.com/axsupport/2016/11/01/cannot-see-all-users-on-the-domain-in-active-directory-import-wizard/

Below steps are described on above mentioned link.
  1. In Active Directory Users and Computers, make sure that Advanced Features is selected under the View menu option.
  2. Right-click the user that you cannot see when you run the import wizard. Then, select Properties.
  3. Click the Security tab.
  4. Click Authenticated Users group.
  5. Click the Advanced button.
  6. Select Authenticated Users name, and then click Edit.
  7. Make sure that the Type is set to Allow and that the Applies to: box is set to This object and all descendant objects.
  8. Make sure Read all.
Properties check box in Properties section is checked.








Thursday, June 14, 2018

Unit conversion AX 2012/ D365FO

Code below can be used for unit conversion with rounding.
 public SalesQty dtConvert(Qty _salesQty,ItemId _itemId,SalesUnit _inventUnit,SalesUnit _salesUnit )  
 {  
      SalesQty salesQty;  
      salesQty = UnitOfMeasureConverter::convert(_salesQty,  
               UnitOfMeasure::unitOfMeasureIdBySymbol(_inventUnit),  
               UnitOfMeasure::unitOfMeasureIdBySymbol(_salesUnit),  
               NoYes::Yes,  
               InventTable::itemProduct(_itemId),  
               NoYes::Yes);  
     return salesQty;  
 }  

Saturday, June 9, 2018

SQL Currently running queries

Execute below query to find currently running queries in SQL.

This can be helpful to identify blocking.

SELECT
      cast(axsess.context_info AS VARCHAR(128)) AS [Connection info],
      req.session_id
   ,blocking_session_id
      ,req.status
      ,req.total_elapsed_time / 1000.0 AS total_elapsed_time
      ,req.wait_type
   ,ses.host_name     
   ,DB_NAME(req.database_id) AS DB_NAME     
      ,sqltext.text     
   ,ses.login_name 
   ,req.command
   ,req.start_time
   ,req.cpu_time 
   ,req.command   
 FROM  sys.dm_exec_requests req
 CROSS APPLY sys.dm_exec_sql_text(sql_handle) AS sqltext
 JOIN  sys.dm_exec_sessions ses
     ON ses.session_id = req.session_id
      join 
  ---cast(axsess.context_info AS VARCHAR(128)) AS [Connection info] , *
  sys.dm_exec_sessions axsess
 on axsess.session_id = req.session_id
 where DB_NAME(req.database_id) = db_name()
 --WHERE         
 --axsess.program_name LIKE '%Dynamics%'
 --and axsess.status = 'running' 
 --and req.wait_type IS NOT NULL
 --and req.wait_type = 'OLEDB'     

OData Date time filter D365 Finance and operations

Date Time filter
OldFormat
https://usnconeboxax1aos.cloud.onebox.dynamics.com/data/Vendors?cross-company=true&$filter=ModifiedDateTime ge DateTime'2018-06-07T09:13:28'
New Format
https://usnconeboxax1aos.cloud.onebox.dynamics.com/data/Vendors?cross-company=true&$filter=ModifiedDateTime gt 2018-06-07T23:59:59.99Z


String Filter
https://usnconeboxax1aos.cloud.onebox.dynamics.com/data/Vendors?cross-company=true&$filter=VendorAccountNumber eq '1001'

Wednesday, June 6, 2018

Job in dynamics 365 Finance and Operations


Below option is to create Runnable Class, which is job in AX 2012 R3.



This will create class with static method as below.

As this class have only static method, this will execute without creating object of class, which is same as job.

To debug this job, set current project as start up project as well as current job class as start up object.


From Debug menu, select option Start Debugging.

This will hit break point.


Happening

Upgrade from AX 2012 to Latest Dynamics 365 Finance and Operation

Below are the steps defined by sequence. 1. Create new Upgrade project in Dynamics LCS. 2. Create VSTS Project and connect it with L...

Trending now