Saturday, 10 June 2017

Extension of Class in D365 for Operations


We can create extension for class but can use/call only Public Members/Methods. Private and Protected can not be accessed from Extension Class.

Added new field TstField in MainAccount Table using extension.
Would like to show newly added field on Trail balance Form/Report.
Added new field TstField in LedgerTrialBalanceTmp Table using extension.

/// <summary>

/// Extension Class for LedgerTrialBalanceDP
/// </summary>
[ExtensionOf(classStr(LedgerTrialBalanceDP))]
final class HNWLedgerTrialBalanceDP_Extension
{
    protected void new()
    {

    }

    /// <summary>
    /// Updating new field in <c>LedgerTrialBalanceTmp</c> Table
    /// </summary>
    public void UpdateTstField()
    {
        MainAccount                         mainAccount;
        DimensionAttributeValueCombination  ledgerDimension;
        LedgerTrialBalanceTmp               ledgerTrialBalanceTmp;
       
        ledgerTrialBalanceTmp = this.getLedgerTrialBalanceTmp();     

        update_recordset ledgerTrialBalanceTmp
            setting
            TstField     =   mainAccount.TstField
            join mainAccount
        exists join ledgerDimension where
            ledgerDimension.MainAccount == mainAccount.RecId &&
            ledgerDimension.RecId == ledgerTrialBalanceTmp.LedgerDimension;

        this.setTrialBalanceTmpTable(ledgerTrialBalanceTmp);
    }

}

Create postEventHandler for processReport method in LedgerTrialBalanceDP Class
and call our newly created method in Extension Class of LedgerTrialBalanceDP


public class HNWLedgerTrailBalanceHandlersExt

{
    [PostHandlerFor(classStr(LedgerTrialBalanceDP), methodStr(LedgerTrialBalanceDP, processReport))]

    public static void LedgerTrialBalanceDP_Post_processReport(XppPrePostArgs args)        {
       LedgerTrialBalanceDP ledgerTrialBalanceDP = args.getThis();
        ledgerTrialBalanceDP.UpdateTstField();
     }
}


 

Friday, 29 July 2016

Using/Extending SysOperationFramework instead of RunBaseFramework in AX 2012

Below are the Classes created to Demonstrate
 

1.  ESS_DemoSysOperationController Class which extends SysOperationServiceController – (For Batch Dialog)
2.  ESS_DemoSysOperationService Class which extends SysOperationServiceBase – (For multitask Batch Initiation)
3.  ESS_DemoOperationDataContract Class – (For parameter values)
4.  ESS_DemoSysOperationTaskService Class – (For actual logic to execute in Batch)

1.   Create a class extends SysOperationServiceController
    class ESS_DemoSysOperationController extends SysOperationServiceController
    {

}

    a.   Override new method
       protected void new()
       {
            super(classStr(ESS_DemoSysOperationService), methodStr(ESS_DemoSysOperationService, update),   SysOperationExecutionMode::Synchronous);
       }

b.   Create  Construct method
        server static ESS_DemoSysOperationController construct()
        {

    ESS_DemoSysOperationController      controller; 

    controller = new ESS_DemoSysOperationController ();

    controller.parmShowDialog(true); // Actually the default value

    controller.parmShowProgressForm(false);

    return controller;
        }

c.   Create main method

static void main(Args args)
        {

    ESS_DemoSysOperationController operation;
            operation = new ESS_DemoSysOperationController ();
            operation.startOperation();
        }

2.   Create a class extends SysOperationServiceBase

class ESS_DemoSysOperationService extends SysOperationServiceBase
    {

    BatchHeader                         batchHeader;
        SysOperationServiceController       controller;
        ESS_DemoSysOperationDataContract    contract;
    }

 

a.   Create update method

[SysEntryPointAttribute]
    public void update()
    {

    RefRecId minRecId, maxRecId, fromRecId, toRecId;
        minRecId =  5637775244;
        maxRecId =  5648390004;
        fromRecId = minRecId;

    if(this.isExecutingInBatch())
        {
            if(!batchHeader)
            {
                 batchHeader = BatchHeader::getCurrentBatchHeader();
            }

        while (toRecId < maxRecId)
            {
                 toRecId = fromRecId + 100000;

            // Create a service controller to run the task
            controller = new SysOperationServiceController(classStr(ESS_DemoSysOperationTaskService), methodStr(ESS_DemoSysOperationTaskService, insertRecords),SysOperationExecutionMode::Synchronous);

        contract = controller.getDataContractObject();
            contract.parmValues(["value01", "value02",fromRecId,toRecId]);
            batchHeader.addRuntimeTask(controller, this.getCurrentBatchTask().RecId); // Create a runTimeTask within the current batch job
           fromRecId = toRecId;
        }
    }
    else
    {
        // Create a service controller to run the task
        controller = new SysOperationServiceController(classStr(ESS_DemoSysOperationTaskService), methodStr(ESS_DemoSysOperationTaskService, insertRecords),SysOperationExecutionMode::Synchronous);

        contract = controller.getDataContractObject();
        contract.parmValues(["value01", "value02",minRecId,maxRecId]);
        controller.run();
  
    }
    // If we're processing in batch, then save the batch header
    if(batchHeader)
    {
        batchHeader.save();
    }
}

3.   Create a Class ESS_DemoSysOperationDataContract

[DataContractAttribute]
    public class ESS_DemoSysOperationDataContract
    {
         container   conValues;
    }

a.   Create parmValues method

[DataMemberAttribute]
        public container parmValues(container _values = conValues)
        {
             conValues = _values;
         
             return conValues;
        }

 
4.   Create a Class ESS_DemoSysOperationTaskService
 
     public class ESS_DemoSysOperationTaskService
     {
         ESS_SysOperationDemoTable       ess_SysOperationDemoTable;
     }

a.   Create insertRecords method

[SysEntryPointAttribute]
        public insertRecords(ESS_DemoSysOperationDataContract _contract)
        {
            str                         value01, value02;
            RefRecId            fromRecId, toRecId;    
            RecordInsertList     recordInsertList = new RecordInsertList(tableNum(ESS_SysOperationDemoTable));

    [value01, value02, fromRecId, toRecId] = _contract.parmValues();

    While (condition)
            {
                 ess_SysOperationDemoTable.clear();
                 ess_SysOperationDemoTable.Field01 = 1
                 ess_SysOperationDemoTable.Field02 = 2;
                 recordInsertList.add(ess_SysOperationDemoTable);
            }
       
            recordInsertList.insertDatabase();
        }

Older SQL Backup files deletion through batch


To keep backup files up to 30 days and delete rest of the files in Windows Batch:

Create a batch file using the below command:

forfiles /M *.bak /P "Backup Folder" /S /D -NoOfDays /C "cmd /c del /F /Q @path"

forfiles /M *.bak /P "E:\SQL Backup" /S /D -30 /C "cmd /c del /F /Q @path"

Copy paste the below command in notepad and change your folder path and Days then Save as .bak file.

Refer below link for further:


Use the Windows Task Scheduler to call the batch script:
https://technet.microsoft.com/en-us/library/cc748993(v=ws.11).aspx

Monday, 27 June 2016

AX7 - How to get recent modifications/changes in application



1.       To count particular of objects in a model:

[System.IO.Directory]::GetFiles("C:\Packages\ESS_WBS\ESS_WBS\AxClass\","*.xml").count

 
 
 

2.       To get list of objects modified in past 120 days:

Get-ChildItem -Path "C:\Packages\*" -Recurse -Include *.xml |select LastWriteTime, FullName,Name| Where{$_.LastWriteTime –ge (Get-Date).addDays(-120)} |Sort-Object lastWriteTime -descending| out-gridview

 
 

Sunday, 15 May 2016

Get Department Financial Dimension Value


  • To get Department financial dimension value from Journal Transactions (LedgerJournalTrans)
// BP Deviation Documented
public display OMOperatingUnitNumber sha_displayDepartment()
{

    DimensionAttribute                  dimAttribute = DimensionAttribute::findByName('Department'); // Change 'Department' to which dimension you are looking for
    DimensionAttributeValueSetItemView  dimAttributeValueSetItemView;

    select firstOnly dimAttributeValueSetItemView
        where dimAttributeValueSetItemView.DimensionAttributeValueSet == this.DefaultDimension &&
              dimAttributeValueSetItemView.DimensionAttribute == dimAttribute.RecId;
   
    return dimAttributeValueSetItemView.DisplayValue;
}



  • To get Department financial dimension value from Voucher Transactions (GeneralJournalAccountEntry)

 
// BP Deviation Documented
public display OMOperatingUnitNumber sha_displayDepartment()
{
    DimensionAttribute                  dimAttribute = DimensionAttribute::findByName('Department'); // Change 'Department' to which dimension you are looking for
    DimensionAttributeLevelValueAllView dimAttributeLevelValueAllView;
   
   
    select firstOnly dimAttributeLevelValueAllView
        where dimAttributeLevelValueAllView.ValueCombinationRecId == this.LedgerDimension &&
              dimAttributeLevelValueAllView.DimensionAttribute == dimAttribute.RecId;
   
    return dimAttributeLevelValueAllView.DisplayValue;
}

Saturday, 9 April 2016

AX 7 Form Event Handlers


We must use Event handlers, if you are using Extension Model Development in AX 7.

1. How we can handle the Datasource fields based on active/selected record, in Event handler method.

[FormDataSourceEventHandler(formDataSourceStr(FormName, DataSource), FormDataSourceEventType::Activated)]
public static void DataSource_OnActivated(FormDataSource sender, FormDataSourceEventArgs e)
{
    Common    common = sender.cursor();
    sender.object(fieldNum(DataSource, ProjActivityNumber)).enable(common.ProjId);
}

2. How we can handle the Controls like, Tab/TabPage/Button etc
 
[PostHandlerFor(formStr(
LedgerJournalTable), formMethodStr(LedgerJournalTable, init))]
    public static void LedgerJournalTable_Post_init(XppPrePostArgs args)
    {
        FormRun             sender = args.getThis();
        LedgerJournalType   journalType = sender.args().parmEnum();

        if (journalType == LedgerJournalType::Assets)
        {
            sender.control(sender.controlId(formControlStr(LedgerJournalTable, YourControl))).visible (true);
        }
 
3. To get new number sequence reference for an existing module.
 
 
    [PostHandlerFor(formStr(AssetParameters), formMethodStr(AssetParameters, numberSeqPreInit))]
    public static void AssetParameters_Post_numberSeqPreInit(XppPrePostArgs args)
    {
        TmpIdRef                                tmpIdRef;
        NumberSeqScope                          scope;
        NumberSeqApplicationModule              numberSeqApplicationModule;
        container                               numberSequenceModules;
 
        numberSequenceModules = [NumberSeqModule::Asset];
        numberSeqApplicationModule = new NumberSeqModuleAsset_XXX();
        scope = NumberSeqScopeFactory::createDataAreaScope();
        NumberSeqApplicationModule::createReferencesMulti(numberSequenceModules, scope);
        tmpIdRef.setTmpData(NumberSequenceReference::configurationKeyTableMulti(numberSequenceModules));
 
        args.setArg('tmpIdRef',tmpIdRef);
    }
 
 
 

 
 

Label editor in AX 7

We have Lookup Label/Text option in earlier versions of AX in X++ Code Editor.
We don’t have exact option in AX 7. Use label search short cut (Ctrl-R, Ctrl-L).