Thursday, February 28, 2019

D365FO change EDT type or length precautions (Alert)

A common change request in organization is to change field length due to impetuous development in first place. Though it my look quite easy task for developer, wrongly done can cause hours of painful resolution. So better to be prescient and follow these steps:



  1. Make sure it is not out of the box EDT which is used on that table column. If it is out of the box try to find another EDT with you desired length or create new EDT. *But don't assign the EDT to that column in this stage*
  2. Take backup of the table (the xml file in folder) in which this EDT is being used. In case it is used in many tables on that form take theirs backup too.
  3. Delete the particular field from all the targeted tables.
  4. Build and sync (preferably build the model). In case the field is used inside any class or form code it will give error. Comment them all to successfully build and sync.
  5. Make sure you can run your form without that column. i.e. there is not any popup error or warnings. If there's still any error try to reset iis (open command prompt as adminstrator and write iisreset and enter) and clear usage data (from AX client go to option> Usage data>Reset).
  6. You may crosscheck by opening the SQL server and see if that column has successfully been removed.
  7. Now create the deleted column back using the new EDT (or with same EDT with length changed already). If it is possible create with different name (it is far more safe).
  8. Build and Sync.
  9. If sync is successful uncomment lines you commented for successful build in step 4.
  10. You can now see the column with updated length/type.

Tuesday, February 26, 2019

D365FO get datasource and FormRun from FormDataObject

When creating extension of any field of form datasource, the event handler passes FormDataObject as default parameter. We then have only this to get our any reference to datasource to which it belongs and the form it belongs. Here is an example to get any form related values:


    //Here my target field is Category which is inside <c>TrvRequisitionLine</c> 
    //datasouce of form <c>TrvRequisition</c>

    [FormDataFieldEventHandler(formDataFieldStr(TrvRequisition, TrvRequisitionLine, Category),
    FormDataFieldEventType::Modified)]
    public static void Category_OnModified(FormDataObject sender, FormDataFieldEventArgs e)
    {
       
        FormDataSource              trvRequisitionLine_DS;
        TrvRequisitionTable         requisitionTable;
        TrvRequisitionLine          requisitionLine;
        ormReferenceGroupControl    formControlLocationDetail;
        //Get datasouce
        trvRequisitionLine_DS = sender.datasource();

        //Get the formRun
        formRun = TrvRequisitionLine_DS.formRun();

        //Get currently selected record
        requisitionLine = trvRequisitionLine_DS.cursor();

        //Get any other datasouce you want form form with help of relation
        requisitionTable = TrvRequisitionTable::find(requisitionLine.TrvRequisitionTable);
       
        //Set any value of record field value based on your calculation
        requisitionLine.AccountingCurrencyAmount = 0;//TODO::Some calculations you need to do and set value of amount

        //Change state of any control on form
        formControlLocationDetail = 
        formRun.design().controlName(formControlStr(TrvRequisition,PerdiemTrvLocations_Details));

        formControlLocationDetail.mandatory(false);
        formControlLocationDetail.enabled(false);

    }

Tuesday, February 19, 2019

D365FO RecordInsertList

While traversing on while loop it's always not necessary to insert each record separately. There is another good way to do this; it is using RecordInsertList. It will minimize the number of hits to database. Here is code snippet to use it:


    RecordInsertList    recordInsertList = new RecordInsertList(tableNum(YourTargetTable));     
    YourTargetTable     yourTargetTable;

    while select  tabel1
    join table2
     where table1.RecId == table2.table1
    {
          yourTargetTable.clear();
          yourTargetTable.FirstField   = table1.AnyField;
          yourTargetTable.SecondField  = table2.AnyField;
          yourTargetTable.ThirdField   = table1.AnyField1 + table2.AnyField1;
          recordInsertList.add(yourTargetTable);
    }
   
    recordInsertList.insertDatabase();