Wednesday, April 4, 2018

Delete AUC for all users

Hey Guys!

Today I have got a small but interesting thing in Ax. We had a situation wherein space of C drive was reaching the alarming level of the Ax-client server (from where all users access Ax). I ran the tool WizTree which displays the analysis of a drive as per the space occupancy. It showed that the maximum amount of space was taken by the AppData folder and I knew what needs to be done next.

The problem was auc files had accumulated for all the users which were summed up to almost 30Gb. So, I decided to delete them but the challenge was how to delete it for all the users at once. So I took help from my master (yes, it's Google) and created a batch which will traverse through all the users AppData folder and delete the auc/kti files.

1. Open Notepad.
2. Paste the below commands there:

for /D %D in ("C:\USERS\*") do del "%~fD\AppData\Local\*.auc"
for /D %D in ("C:\USERS\*") do del "%~fD\AppData\Local\*.kti"
pause

3. Save the notepad as .bat file.


4. Run the batch file and it will delete all the auc/kti files for all the users.

Credits: http://blog.bhsolutions.com/index.php/2014/05/dynamics-ax-2012-spring-cleaning-app-data/
https://stackoverflow.com/questions/34019989/batch-file-copy-all-users-profile-app-data

Tuesday, January 9, 2018

Filter AOT objects using X++ in Ax2012

Hey guys,

Let's discuss a very interesting code for the simple purpose of filtering objects in a project. I hope we all know about the standard of Ax to filter and import AOT objects in a project. So now we will see how to do it using x++ code:

static void alle_aks_ImportObjectsToProjects(Args _args)
{
    sysprojectfilterrunbase varProject;
    utilelements            aotElements;

    varProject = new sysprojectfilterrunbase();
    varProject.parmProjectNode(systreenode::createProject('Alle_GST_TaxObejcts'));
    varProject.grouping(sysprojectgrouping::AOT);

    while select name, utilLevel, RecordType, ParentId from aotElements
        where aotElements.utilLevel == UtilEntryLevel::var
        && aotElements.name like 'Tax*'
    {
        try
        {
            aotElements.reread();
            varProject.doUtilElements(aotElements);
        }
        catch (exception::Error)
        {
            throw error('Error');
        }
    }
    varProject.write();
    info('Done');
}

Here you can modify the while select query to suit your need i.e. to change the layer or the name filter.


Source: https://mydynamicsax.wordpress.com/2015/03/19/how-to-filter-aot-objects-to-a-project/

Wednesday, June 7, 2017

"No elements are found in AOD files in the old directory" error in Ax2012

Hi guys,

Today while applying GST patch for one of our clients I faced an error in Code Upgrade. I had installed the hotfix and run the "Detect Code Upgrade Conflicts" and I received an error which said "No elements are found in AOD files in the old directory. The layer conflict project will not be created.". So of course after googling a bit I got a solution to this:

Modify the detectConflictsRun method on SysUpgradeDetectConflicts class like below:
Comment the code that checks for a record on utilElementsOld Table and sets layerDetectorRequirementsOk variable to True.

   // check if the Old directory exists
   /*select firstonly RecId from utilElementsOld;
   if (utilElementsOld.RecId)
   {
       layerDetectorRequirementsOk = true;
   }
   else
   {
       layerDetectorRequirementsOk = false;
       // Inform user that the layer project will not be created
       info("@SYS106623");
   }*/
   layerDetectorRequirementsOk = true;

And that works like a charm and you will get a project with code conflicts. :)

Credits: https://community.dynamics.com/ax/f/33/t/123783

Friday, May 26, 2017

The state of the source document or source document line could not be updated Ax2012

Hi Guys,

Today we faced this in our production environment. A particular PO had developed this issue wherein whenever a user clicks the Invoice button system would throw the error "The state of the source document or source document line could not be updated.".

While debugging, I came to know that this had something to do with Source Document Line records. So I tried looking for a solution on the web and got the below job which works perfectly in deleting the orphan records from SourceDocumentLine:

static void aks_fixOrphanedSourceDocumentsHeader(Args _args)
{
    SourceDocumentLine sline;
    SysDictTable table;
    PurchTable header;
    PurchLine purchline;
    PurchId purchId = "WPFO1617-0001218";
    boolean fix;
    Common rec;
    int fieldId, found, notfound;

    if (purchId)
    {
        while select purchLine where purchLine.PurchId == purchId
        {
            while select forUpdate sline where sline.ParentSourceDocumentLine == purchLine.SourceDocumentLine
            {
                table = new SysDictTable(sline.SourceRelationType);
                rec = table.makeRecord();
                fieldId = fieldName2id(sline.SourceRelationType, "SourceDocumentLine");
                select rec where rec.(fieldId) == sline.RecId;

                if (rec.RecId)
                {
                    info(strFmt("Record Match Found %1 %2", table.name(),rec.caption()));
                    found++;
                }
                else
                {
                    ttsBegin;
                    sline.doDelete();
                    ttsCommit;

                    info(strFmt("Orphan Found %1", table.name()));
                    notfound++;
                }
            }
            info(strFmt("Found %1", found));
            info(strFmt("Orphans found and deleted %1",notfound));

            found = 0;
            notfound = 0;
        }
    }
}


Credit: https://community.dynamics.com/ax/f/33/t/144316

Friday, March 24, 2017

Copy data from a table to another Ax2012

Hi guys,

Another short code for copying data from one table to another (backupTable). This is useful when you have to take backup of the data while you want to perform some operations of the production data (original table) or maybe to resolve some DB sync issues.

static void AKS_CopyTableData(Args _args)
{
    EcomInboundInventoryUpdate          origTable;
    Backup_EcomInboundInventoryUpdate   copyTable;

    ttsBegin;
    delete_from copyTable;

    while select origTable
    {
        buf2Buf(origTable, copyTable);
        copyTable.insert();
    }

    ttsCommit;
}

Delete duplicate records of a table AX2012

Hi Guys,

A code snippet to delete duplicate records of a table and keeping just one of the duplicate set.

static void AKS_DeleteDuplicates(Args _args)
{
    EcomInboundInventoryUpdate      table, tableSelect, tableDelete;

    while select table group by wmsreferencenum
        where table.EcomProcessStatus == EcomProcessStatus::Waiting
    {

        select firstOnly RecId from tableSelect
            where tableselect.WMSReferenceNum == table.WMSReferenceNum;


        delete_from tableDelete
            where tableDelete.WMSReferenceNum == table.WMSReferenceNum &&
                  tableDelete.RecId != tableSelect.RecId;
    }
}

Monday, March 13, 2017

Get dimension name and value in Ax2012

Hi Guys,

Here is another code snippet to get Dimension value and name by dimension:

static DimensionValue Ale_getDefaultDimensionValue(DimensionDefault   _dimensionDefault , Name  _defaultDimensionName)
{
    DimensionAttributeValueSet      dimAttrValueSet;
    DimensionAttributeValueSetItem  dimAttrValueSetItem;
    DimensionAttributeValue         dimAttrValue;
    DimensionAttribute              dimAttr;
    Common                          dimensionValueEntity;
    DimensionValue                  dimValue;
    Name                                   dimName;
    container                           dimNameValue;
    ;
    dimAttrValueSet = DimensionAttributeValueSet::find(_dimensionDefault);

    while select DimensionAttributeValue from dimAttrValueSetItem
        where   dimAttrValueSetItem.DimensionAttributeValueSet   == dimAttrValueSet.RecId
    {
        dimAttrValue        = DimensionAttributeValue::find(dimAttrValueSetItem.DimensionAttributeValue);

        dimAttr             = DimensionAttribute::find(dimAttrValue.DimensionAttribute);

        dimensionValueEntity = DimensionDefaultingControllerBase::findBackingEntityInstance(curext(),dimAttr,dimAttrValue.EntityInstance);

        if (dimAttr.Name == _defaultDimensionName)
        {
            dimNameValue = [dimAttrValue.getValue(), dimAttrValue.getName()];
        }
    }
    return dimNameValue;
}