Saturday 28 July 2012

AX 2012 Data Migration Framework




Microsoft has released Microsoft Dynamics AX 2012 Data Migration Framework Beta.

You can download the beta release of MicrosoftDynamics AX 2012 Data Migration Framework (Beta)  from information source with Partner/Customer login.

The Data Migration Framework for Microsoft Dynamics AX 2012 is an extension that helps you migrate data into Microsoft Dynamics AX. For Example: master data, open stock, and balances.



The following diagram shows the architecture of the Data Migration Framework. Staging is a table that the Data Migration Framework creates in the Microsoft Dynamics AX database where the target entities reside. 








The following diagram shows the configuration steps that are required before you can migrate entities into Microsoft Dynamics AX. 



  1. The following entities available in the Microsoft Dynamics AX 2012 Data Migration Framework:
ü  Bill of materials (BOM)
ü  Contacts
ü  Contact addresses
ü  Customer
ü  Customer addresses
ü  Dimension
ü  Employees
ü  Employee addresses
ü  Inventory journal
ü  Ledger balances
ü  Main account
ü  Open invoices (accounts payable)
ü  Open invoices (accounts receivable)
ü  Open sales orders
ü  Open purchase orders
ü  Price disc
ü  Product
ü  Project
ü  Unit of measure
ü  Vendor
ü  Vendor address

When you define a processing group, you must identify sample data for each entity. The sample data is used to validate the source to staging mapping.


If you do not have sample data, you can use the Data Migration Framework to help define a template for the data, and then enter sample data in the template.






The approach is de-normalize the datasets that make up the Data model in AX 2012 with targeted staging tables. Then you have X++ code that work against the staging tables, to fill the normalized, and sometimes super normalized, datasets of AX 2012.
The following diagram shows the processes that run when data is copied from source to staging, and from staging to target.



  1. Source to staging processing
When an entity is copied from source to staging, a processing group that is associated with one or more entities runs as a job.
After processing has been completed, you should validate that the entity appears accurate in the staging table, and that the reference data is mapped correctly.
  1. Staging to target processing
When data is copied from staging to target, a job that is already defined, and that is associated with a processing group, runs.
After processing has been completed, you should validate that the entity appears accurate in the target table.
  1. After the migration has been completed successfully, we recommend that you delete the staging data.
Microsoft strongly recommend to delete the staging data after migration is complete. It may contain high business impact information. 


After Downloading the files from Partner/Customer source. Click on the Setup file.




Setup should run on AOS Instance and on AX Client.


    




After Installation, increase the "Maximum buffer size" setting for your environment while you migrate data. Use the Server configuration utility to set the value.

When you open the Destination folder of installed objects, you can see the following files will be created.

   
Now we have to import the model file that came as part of the installation. Install the model file using the PowerShell command console.

Command: (If you have multiple instances on a single machine)
Install-AXModel -File c:\Program Files\Microsoft Dynamics AX 2012 Data Migration Framework (Beta)\ DataMigrationFramework.axmodel –config $AOSInstanceName


After Model file installation, if you open the instance the following screen will be displayed. Because of the model store has been modified.

Click on the compile and synchronization, after completion of compilation and synchronization from the application, need to generate the FULL CIL compilation.


After compilation of FULL CIL, AX 2012 instance has the Data Migration Framework Beta version is deployed.


In My Next Article I will Post How to Use "Microsoft Dynamics AX 2012 Data Migration Framework" 




Monday 23 July 2012

Data Import in AX 2012 - Employee


HCMWorker (employee or worker) import

In Cumulative Update 2 for Microsoft Dynamics AX 2012, a new HCMWorkerImport service was added. This service can be used to import employees or workers into the system. When you use this service, your code will create new HCMWorker, HCMEmployment, and HCMEmploymentDetail objects, and will use dirPartyAddressView and dirPartyContactView, similar to the customer import sample code.

Expose an inbound port for the HCMWorker service
To call the service, you need to expose the service on a new inbound port in Microsoft Dynamics AX.
1. Click System administration > Setup > Services and Application Integration Framework > Inbound ports, and then click New.
2. Give the new port a name, such as HCMWorkerImport Services.
3. Enter a description.
4. Under Service Contract Customizations, click Service Operations. The Select service operations form opens.

5. Select the HCMWorkerImportService operations, move them to the Selected operations pane, and then click Close.
6. In the Inbound ports form, click Activate.
You can now access the service externally by using the WSDL URI.





HCMWorkerImport service to create an employee in Microsoft Dynamics AX 2012.

CSV:


Employee
EMP-0001-786
WorkerType
Employee
firstname
RACHNA
Middle name

LastName
Pandey
Title
ASSISTANT MANAGER
Birthday
6/4/1985
Street name
Opp: Maroli Bus Depot,  Marol Maroshi,
ZIP/postal Code
220027
City
Mumbai
State
MH
Country/region
IND
Telephone
9966699914
Mobile phone
9966699914
Fax
022-456256236
E-mail
Personal Email Id

Salutation

Suffix

Date Of Joining
10/22/2007

Set up the HCMWorker service reference in Visual Studio

1. Open Visual Studio, and create a new project.
2. Add a new service reference by using the WSDL URI for the HCMWorker service from the Inbound ports form.
3. Add a Using statement for the service reference.





using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Worker.HcmDataImportService;
using System.IO;
using System.Text.RegularExpressions; 

namespace Worker
{
    public partial class HcmWorkers : Form
    {

        internal static int Personalnumber = 0;
        internal static int Employeetype = 1;
        internal static int firstname = 2;
        internal static int Middlename = 3;
        internal static int LastName = 4;
        internal static int Title = 5;
        internal static int Birthday = 6;
        internal static int Streetname = 7;
        internal static int ZIPCode = 8;
        internal static int City = 9;
        internal static int State = 10;
        internal static int Country = 11;
        internal static int phone = 12;
        internal static int mobile = 13;
        internal static int Fax = 14;
        internal static int Bemail = 15;
        internal static int Pemail = 16;
        internal static int sal = 17;
        internal static int Suffix = 18;
        internal static int Joindate = 19;
        internal static int Gender = 20;
        internal static int Maritialstatus = 21;

        public static List<string[]> ParseCSVFile(string path, Boolean hasHeaders)

        {

            List<string[]> CSVRows = new List<string[]>();

            int rowNumber = 0;

            using (StreamReader inputFile = new StreamReader(path))

            {

                string line;
                string[] line1;

                while ((line = inputFile.ReadLine()) != null)
                {

                    String pattern = ",(?=(?:[^\"]*\"[^\"]*\")*(?![^\"]*\"))";

                    Regex r = new Regex(pattern);

                    line1 = r.Split(line);

                    if (hasHeaders != true || rowNumber != 0)

                    {

                        CSVRows.Add(line1);

                    }

                    rowNumber++;

                }

            }

            return CSVRows;

        }


        public HcmWorkers()
        {

           InitializeComponent();
        }



        public void createHcmWorker(String[] _WorkerData)

        {

            HcmWorkerImportServiceClient hcmSvcClient = new HcmWorkerImportServiceClient();

            AxdHcmWorkerImport workerDocument = new AxdHcmWorkerImport();

            AxdEntity_HcmWorker worker = new AxdEntity_HcmWorker();

            AxdEntity_HcmWorker[] workerList = new AxdEntity_HcmWorker[1];

            AxdEntity_HcmWorkerTitle workerTitle = new AxdEntity_HcmWorkerTitle();

            AxdEntity_DirPerson_DirPerson person = new AxdEntity_DirPerson_DirPerson();

            AxdEntity_DirPersonName personName = new AxdEntity_DirPersonName();

            AxdEntity_HcmPersonDetails personDetails = new AxdEntity_HcmPersonDetails();

            AxdEntity_HcmPersonPrivateDetails personPrivateDetails = new

            AxdEntity_HcmPersonPrivateDetails();

            AxdEntity_HcmEmployment employment = new AxdEntity_HcmEmployment();

            AxdEntity_HcmEmploymentDetail employmentDetail = new

            AxdEntity_HcmEmploymentDetail();

            AxdEntityKey_DirNameAffix[] affix = new AxdEntityKey_DirNameAffix[2];

            AxdEntity_DirPartyPostalAddressView[] postalAddView = new

            AxdEntity_DirPartyPostalAddressView[1];

            postalAddView[0] = new AxdEntity_DirPartyPostalAddressView()

            {

                LocationName = "EmployeeAddr",

                BuildingCompliment = "EmplBuildCompliment",

                City = _WorkerData[City],

                State = _WorkerData[State],

                ZipCode = _WorkerData[ZIPCode],

                Street = _WorkerData[Streetname],

                CountryRegionId = _WorkerData[Country],

                Roles = "Home",

                IsPrimary = AxdExtType_LogisticsIsPrimaryAddress.Yes

            };



            //Add the party Address to the person
            person.DirPartyPostalAddressView = postalAddView;
          

            //Create a contact for the person. You can add a loop and add as many address and

            //types you want to here

            AxdEntity_DirPartyContactInfoView[] contactList = new

            AxdEntity_DirPartyContactInfoView[5];
           

            contactList[0] = new AxdEntity_DirPartyContactInfoView()

            {

                LocationName = "Employee Telephone",

                //Value of locator will vary by type.

                Locator = _WorkerData[phone],

                IsPrimarySpecified = true,

                IsPrimary = AxdEnum_NoYes.Yes,

                TypeSpecified = true,

                Type = AxdEnum_LogisticsElectronicAddressMethodType.Phone,

                Roles = "Business"

            };

            contactList[1] = new AxdEntity_DirPartyContactInfoView()

            {

                LocationName = "Employee Mobile",

                Locator = _WorkerData[mobile],

                IsPrimarySpecified = true,

                IsPrimary = AxdEnum_NoYes.Yes,

                TypeSpecified = true,

                Type = AxdEnum_LogisticsElectronicAddressMethodType.Phone,

                Roles = "Business"

            };

            contactList[2] = new AxdEntity_DirPartyContactInfoView()

            {

                LocationName = "Employee Fax",

                Locator = _WorkerData[Fax],

                IsPrimarySpecified = true,

                IsPrimary = AxdEnum_NoYes.Yes,

                TypeSpecified = true,

                Type = AxdEnum_LogisticsElectronicAddressMethodType.Fax,

                Roles = "Home"

            };

            contactList[3] = new AxdEntity_DirPartyContactInfoView()

            {

                LocationName = "Employee email",

                Locator = _WorkerData[Bemail],

                IsPrimarySpecified = true,

                IsPrimary = AxdEnum_NoYes.Yes,

                TypeSpecified = true,

                Type = AxdEnum_LogisticsElectronicAddressMethodType.Email,

                Roles = "Home"

            };

            contactList[4] = new AxdEntity_DirPartyContactInfoView()

            {

                LocationName = "Personal email",

                Locator = _WorkerData[Pemail],

                IsPrimarySpecified = true,

                IsPrimary = AxdEnum_NoYes.No,

                TypeSpecified = true,

                Type = AxdEnum_LogisticsElectronicAddressMethodType.Email,

                Roles = "Home"

            };

           

            //Add the contacts to the person

            person.DirPartyContactInfoView = contactList;

            personName.LastName = _WorkerData[LastName];

            personName.FirstName = _WorkerData[firstname];

            personName.MiddleName = _WorkerData[Middlename];

            

            //Assign PersonName to DirPersonName

            person.DirPersonName = personName;

            person.HcmPersonDetails = personDetails;

            DateTime convertedDate2 = DateTime.Parse(_WorkerData[Birthday]);

            System.DateTime univDateTime2 = convertedDate2.ToUniversalTime();

            personPrivateDetails.BirthDate = univDateTime2;

            personPrivateDetails.BirthDateSpecified = true;

           

            //Assign person private Details to the person

            person.HcmPersonPrivateDetails = personPrivateDetails;

            person.ProfessionalTitle = _WorkerData[Title];

            //Assign the person to the worker

            worker.DirPerson = person;

            //Create the employment array for the worker

            AxdEntity_HcmEmployment[] employmentList = new AxdEntity_HcmEmployment[1];

            //Set the employment ValidTo and ValidFrom Fields

            AxdExtType_HcmEmploymentValidFrom employmentValidFrom = new

            AxdExtType_HcmEmploymentValidFrom();

            //employmentValidFrom.Value = Convert.ToDateTime(_WorkerData[Joindate]);//UtcNow.AddYears(-5);

            DateTime convertedDate = DateTime.Parse(_WorkerData[Joindate]);

            System.DateTime univDateTime = convertedDate.ToUniversalTime();

            employmentValidFrom.Value = univDateTime;

            AxdExtType_HcmEmploymentValidTo employmentValidTo = new

            AxdExtType_HcmEmploymentValidTo();

            //Set the properties to the employment object

            employment.ValidFrom = employmentValidFrom;

            // employment.ValidTo = employmentValidTo;

            employment.LegalEntity = "HYD";

            employment.EmploymentType = AxdEnum_HcmEmploymentType.Employee;

            //Create an employment Detail object and set the start date

            AxdExtType_HcmEmploymentStartDateTime employmentStartDate = new

            AxdExtType_HcmEmploymentStartDateTime();

            // AxdExtType_Hcm transitiondate = new AxdExtType_EndDateTime();

            //transitiondate.Value = DateTime.Parse(_WorkerData[]);

           

            DateTime convertedDate1 = DateTime.Parse(_WorkerData[Joindate]);

            System.DateTime univDateTime1 = convertedDate.ToUniversalTime();

            employmentStartDate.Value = univDateTime;

            employmentDetail.WorkerStartDate = employmentStartDate;

            //Assign the Detail to the employment object

            employment.HcmEmploymentDetail = employmentDetail;

            //Assign the employment object to the employment list

            employmentList[0] = employment;

            worker.HcmEmployment = employmentList;

            //Assign values to the worker title object

            AxdExtType_HcmEmploymentSeniorityDateTime seniorityDateEDT = new

            AxdExtType_HcmEmploymentSeniorityDateTime();

            // seniorityDateEDT.Value = DateTime.UtcNow.AddYears(1);

            // workerTitle.SeniorityDate = seniorityDateEDT;

            workerTitle.OfficeLocation = "Room101";

            //Assign worker Title to Worker

            worker.HcmWorkerTitle = workerTitle;

            //Set the Personnel number. This must be unique for each worker record.



            worker.PersonnelNumber = _WorkerData[Personalnumber];//"ImportSVCNum1";

            //worker.d = _WorkerData[ProdNumber];

           

            affix[0] = new AxdEntityKey_DirNameAffix()
            {

                AffixType = AxdEnum_DirNameAffixType.PersonalPrefix,
                Affix = _WorkerData[sal]

            };

            affix[1] = new AxdEntityKey_DirNameAffix()
            {

                AffixType = AxdEnum_DirNameAffixType.PersonalSuffix,
                Affix = _WorkerData[Suffix] 

            };

            //Create the worker element in the document

            workerDocument.HcmWorker = new AxdEntity_HcmWorker[1];

            //assign the worker to the document

            workerDocument.HcmWorker[0] = worker;


            workerDocument.DocPurpose = AxdEnum_XMLDocPurpose.Original;

            workerDocument.DocPurposeSpecified = true;

            //Call the create on the service with the worker document

            EntityKey[] ek = hcmSvcClient.create(null, workerDocument);

        }
       

        private void button1_Click(object sender, EventArgs e)
        {

            //Read in your .csv file however you want to
            //This is just provided as a reference

            List<string[]> HcmData = ParseCSVFile("D:\\Employee_Singu.csv", true); 

            foreach (string[] HcmMasterData in HcmData)

            { 

                createHcmWorker(HcmMasterData); 

            }

        } 

    }

}