Friday, 14 December 2018

Update Variant Sizes based on Configuration

Recently in a project, there was a scenario where the sizes had an incorrect display order imported when the configuration was imported. On the size groups, the data seemed correct. To tackle that, the following job was created. It looks at the correct display order from the configuration and populates it to the variant configuration.

static void UpdateProductSizeDisplayOrder(Args _args)
{
    InventTable inventTable;
    EcoResProductMasterDimensionValue dimValue;
    EcoResProductMasterSize prodMasterSize;
    EcoResDistinctProduct disProduct;
    RetailSizeGroupTrans retailSizeGroupTrans;
    CommaIo file;
    int iCount=0;

    ;
    file = new CommaIo(@"\\XXX\ProdSizes_PROD_NEW"+".csv","W");

    file.write("ItemId","Size","sizeRecId","DisplayOrder","SizeGroup","CorrectDisplayOrder","ChangeMade");
    while select inventTable // where inventTable.ItemId == 'B4E2200'
    {
        while select forupdate prodMasterSize where prodMasterSize.SizeProductMaster == inventTable.Product
        {
            select retailSizeGroupTrans where retailSizeGroupTrans.size == EcoResSize::find(prodMasterSize.Size).Name
            && retailSizeGroupTrans.sizeGroup == EcoResProductMaster::find(prodMasterSize.SizeProductMaster).RetailSizeGroupId;



            if(prodMasterSize.RetailDisplayOrder != retailSizeGroupTrans.DisplayOrder)
            {
                file.write(
                            inventTable.ItemId,
                            EcoResSize::find(prodMasterSize.Size).Name,
                            prodMasterSize.RecId,
                            prodMasterSize.RetailDisplayOrder,
                            EcoResProductMaster::find(prodMasterSize.SizeProductMaster).RetailSizeGroupId,
                            retailSizeGroupTrans.DisplayOrder,"YES"
                            );

                ttsBegin;
                prodMasterSize.RetailDisplayOrder = retailSizeGroupTrans.DisplayOrder;
                prodMasterSize.update();
                ttsCommit;

                iCount++;
            }
            else
            {
                file.write( inventTable.ItemId,
            EcoResSize::find(prodMasterSize.Size).Name,
            prodMasterSize.RecId,
            prodMasterSize.RetailDisplayOrder,
            EcoResProductMaster::find(prodMasterSize.SizeProductMaster).RetailSizeGroupId,
            retailSizeGroupTrans.DisplayOrder,"NO");
            }

        }
    }
        info("Finished");
}

Tuesday, 9 October 2018

Update Product numbers for Released and Product Master

In one of my projects, there was a requirement for bulk renaming the released products and the product master. Luckily, the numbers for both released and master were kept the same for me to filter on the PKs conveniently. Used the code below to achieve that.

static void RenameInvenTableProdsPK(Args _args)
{
    InventTable inventTable;
    str oldDisplayNumber,newDisplayNumber;
    int iCount;
    CommaIo file;
    ;
    file = new CommaIo(@"\\XXXXX\file.csv","W");
    While select ItemId from InventTable where inventTable.ItemId like 'B4*'
    {
        try
        {
            oldDisplayNumber = inventTable.ItemId;
            newdisplayNumber = "O_"+inventTable.ItemId;
            inventTable.ItemId = newdisplayNumber;
            inventTable.renamePrimaryKey(); //old method of product renaming
           
            //using the service to rename product master
            EcoResProductNumberRenameService::newFromProduct(
            EcoResProduct::findByProductNumber(oldDisplayNumber).RecId,
            oldDisplayNumber,
            newdisplayNumber,NoYes::Yes).rename(); //one of the attributes allows us to include product variants in the renaming process
            iCount++;
    }
    
    catch{
        file.write(oldDisplayNumber);
        continue;
    }
    }
   info(strFmt("Done - %1",iCount));  
}


Tuesday, 2 October 2018

Dynamics AX R3 | List of all tables with details

In one of the recent projects, I had to pull the details of all the tables with their current record counts and if they are the part of any country specific localisation. I used the following code to pull those details. Nice simple code got the job done well.
static void GetTablesDetails(Args _args)

{
    #AOT
    #File
    #Properties

    CommaIo csvIO;
    str description;
    TreeNode tables;
    int total, counter;
  ;

    csvIO = new CommaIo(@"c:\AX_tables_details.csv", #IO_WRITE);
    csvIO.write("No","TableName""ID","LegacyId","SaveDataPerCompany","TableGroup","FormRef","CountryRegionCodes","RecordsCount");
    tables = TreeNode::findNode(@"\Data Dictionary\Tables");
    total = tables.AOTchildNodeCount();
    tables = tables.AOTfirstChild();

    for(counter = 1; counter <= total; counter++)
    {
       
        csvIO.write(counter,tables.AOTgetProperty("Name"),tables.AOTgetProperty("ID"),tables.AOTgetProperty("LegacyId"),tables.AOTgetProperty("SaveDataPerCompany"),tables.AOTgetProperty("TableGroup"),tables.AOTgetProperty("FormRef"),tables.AOTgetProperty("CountryRegionCodes"),SysDictTable::casRecordCount(tables.AOTname()));
        tables = tables.AOTnextSibling();
     }

    info("Done");
}

Wednesday, 28 October 2015

Many times I have been asked by customers to copy the personalization settings of one user to another. It could just be relating to one form or to replicate the whole user settings from one to another. The code below would just do that job. If it is selective copy then either elementName or designName fields can be filtered. I have been using this code on regular basis and has been quite helpful and updating personalization.
static void copyUserPersonalisations(Args _args)
{
    str userFrom = "";//userId to copy from
    str userTo = ""; //userId to copy to
    SysLastValue sysLastValueTo, sysLastValueFrom;
    int iCount=0;
    ;

    //refreshes all the records for the destination user.
    delete_from sysLastValueTo where sysLastValueTo.userId == "XXX";

    while select sysLastValueFrom where sysLastValueFrom.userId == "XXX"
    {
        select forUpdate sysLastValueTo;
        ttsBegin;
        sysLastValueTo.company = sysLastValueFrom.company;
        sysLastValueTo.designName = sysLastValueFrom.designName;
        sysLastValueTo.elementName = sysLastValueFrom.elementName;
        sysLastValueTo.isKernel = sysLastValueFrom.isKernel;
        sysLastValueTo.recordType = sysLastValueFrom.recordType;
        sysLastValueTo.userId = userTo;
        sysLastValueTo.value = sysLastValueFrom.value;
        sysLastValueTo.insert();
        iCount++;
       
        ttsCommit;
    }
    info(strFmt("Records from %1 is copied to %2. \n\rTotal Records copied: %3",userFrom,userTo,iCount));

}

Thursday, 4 December 2014

Get list of all Projects in AOT

There's many times when we tend to get the list of all the projects existing in the AOT. This is helpful to keep the development documentation up-to-date. The code below provides an easy list of all the projects and saves them in a csv file.

static void GetProjectNames(Args _args)

{
    #AOT
    #File
    #Properties
   
    TextIo csvIO;
    str description;
    TreeNode projects;
    int total, counter;
  ; 
    csvIO = new TextIo(@"C:\HBProjectsList.xls", #IO_WRITE);
    csvIO.write("Project Name\n");
    projects = TreeNode::findNode(@"\Projects\Shared");
   
    total = projects.AOTchildNodeCount();
    projects = projects.AOTfirstChild();
   
    info(int2str(Total));
   
    for(counter = 1; counter <= total; counter++)
    {
        description += projects.AOTname();
        description += "\n";
        projects = projects.AOTnextSibling();
    }
   
    csvIO.write(description);
}

Sunday, 19 October 2014

DIXF / DMF Issue with Entities

Using DIXF requires a set of versatile skills from Excel to X++. I came across this issue where I kept getting the error below every time I uploaded various entities particularly Customer.

Results. Record ('XXX') . A record with RecId 0 does not exist.
Results. Record ('XXX') . Account  does not exist.
Results. Record ('XXX') . Update has been cancelled.
This issue was caused by incorrect lincence configuration when a field was passed on and the key was not enabled. Below code can be used to clean the data in the staging on the fly.
static void CLearCustomerEntityState(Args _args)
{
    DMFCustomerEntity cust;
    int counter;
    ;
        counter = 0;
    while select forUpdate cust where cust.TransferStatus == 2
    {
        ttsBegin;
             cust.State = "";
             cust.County = "";
        cust.AccountBalance = 0;
        cust.update();
        ttsCommit;

        counter++;
    }
    info(strFmt("Cleared : %1",counter));

}