Thursday 22 February 2018

Extension in D365


To add new method to VendTable to get address of Vendors.

public static class VendTable_Extension

{
    public static Notes getVendAddress(VendTable vendTable)
    {
        DirPartyTable       dirPartyTable;
        LogisticsLocation   logisticsLocation;

        select dirPartyTable where dirPartyTable.RecId == vendTable.Party
        join logisticsLocation
        where dirPartyTable.PrimaryAddressLocation == logisticsLocation.RecId;      
       
        return logisticsLocation.postalAddress();
    }

}

Once we will build our project, this method will be usable as if it is method of VendTable.

I have tested the same using job(Runable Job)

class VendTable_Demo
{        
   
    public static void main(Args _args)
    {    
        VendTable vendTable;

        vendTable = VendTable::find("1001"); 
        
        info(strFmt("Vendor Address - %1",vendTable.getVendAddress()));
      
    }


To get a form control 

formRun.design().controlName(“ControlName”)

or


formRun.design().controlName(formControlStr(FormName, ControlName));

Ex:
[FormControlEventHandler(formControlStr(EcoResProductCreate, CategoryReferenceGroup), FormControlEventType::Modified)]

    public static void CategoryReferenceGroup_OnModified(FormControl sender, FormControlEventArgs e)
{
FormStringControl                   identification_ProductNumber;   //Product number
FormStringControl                   itemIdentification_ItemId;      //Item number

identification_ProductNumber   = formRun.design().controlName("identification_ProductNumber");
       
identification_ProductNumber.text(itemid);
//To call form level method in the extension class
formrun.productData().identification().parmProductNumber(itemid);
}

SysTableLookup in D365

1.Create Extension for form
2.Create New field and copy event handler(OnLookup)




3. Paste event handler in new class and write below logic


[ExtensionOf(formStr(PurchCreateOrder))]
final class PurchTable_Extension
{
    /// <summary>
    /// Added by Rajendra on 01-03-2018
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    [FormControlEventHandler(formControlStr(PurchCreateOrder, NEC_RelatedPO), FormControlEventType::Lookup)]
    public static void NEC_RelatedPO_OnLookup(FormControl sender, FormControlEventArgs e)
    {
        SysTableLookup          sysTableLookup;
        Query                   query;
        QueryBuildDataSource    qbds;
        QueryBuildRange         qbr;
        FormRun                 formRun;
        FormStringControl       vendAccount;
       
        formRun        = sender.formRun();
        vendAccount    = formRun.design().controlName(formControlStr(PurchCreateOrder, PurchTable_OrderAccount));
        sysTableLookup = SysTableLookup::newParameters(tableNum(PurchTable), sender);
        //sysTableLookup.addLookupfield(fieldNum(PurchTable, OrderAccount), true);
        sysTableLookup.addLookupfield(fieldNum(PurchTable, PurchId), true);

        query   = new Query();
        qbds    = query.addDataSource(tableNum(PurchTable));
        qbds.addRange(fieldNum(PurchTable, OrderAccount)).value(vendAccount.valueStr());

        sysTableLookup.parmQuery(query);
        sysTableLookup.performFormLookup();

FormControlCancelableSuperEventArgs ce = e as FormControlCancelableSuperEventArgs;


        ce.CancelSuperCall();
       
    }

Please note that execution of original lookup should be cancelled by FormControlCancelableSuperEventArgs.CancelSuperCall() otherwise AX will throw an error “More than one form was opened at once for the lookup control.”


}


Thursday 8 February 2018

D365 Basics (Architeture, Models, Packages, Files)

The template project types are:

Dynamics AX Best Practice Rules – used for writing best practices checks for code and metadata
Dynamics AX Developer Tool Add-in

Dynamics AX Project – main project template type for containing customizations

Models, Packages, Files

https://varun-shah-2c8h.squarespace.com/news/2017/4/7/dynamics-365-models-mangement-and-packages

KeyPoints
  • Circular referencing is not allowed
  • The concept of models is more or less the same as previous versions of AX 2012. In Dynamics 365 they are a design time concept that groups meta data and source files. Packages have have multiple models associated with Them
  • Every model still exists within a single layer but that concept does not mean as much as in AX 2012 if the approach taken for development in D365 is  extension. If the approach is approach is to overlay, which is the only development approach in previous version of AX, then layers become more important.
  • The file structure is saved as XML , Each folder is a package with has sub folders of the models
  • If you want to override a method, create a new class extending the base class and override the method. Inheritance (parent / child relationship and overriding) isn’t related to extensions.
  • If you want to run some extra code on the beginning or the end of the method, you can also use events. You don’t need class extensions for this either.
  • You can extend any Enum that is marked extensible (IsExtensible=True).
extensibleenums

By extending an Enum, you can add new Enum values to it. It is important to keep the following in mind when dealing with extensible Enums:
  1. You cannot have X++ logic that depends on the integer value of Enum values (For example. If (Enum1.v1 > Enum1.v2) ... is not supported for extensible enums)
  2. When Enum values of extensible Enums are synchronized into the database:
    • Integer values that belong to the baseline enum are deterministic, they come from the metadata.
    • Integer values that are an extension are generated during the synchronization process and are not deterministic.

Package local directory


Packages
  • It includes all of the models, binaries and additional pieces needed to deploy code.
  • Similar concept to an AX2012 modelstore or in VS a solution.
  • You can have multiple packages per installation.
  • AX ships with several packages including:
  • Application Suite:   This is the package containing most of the application code and is the most likely to be overridden.
  • Application Suite Form Adaptor
  • Application Foundation
  • Application Foundation Form Adaptor
  • Application Platform
  • Application Platform Form Adaptor
When creating a model, the wizard prompts for which package the model should live in.


To create customization objects (overlayer objects) you have to:
Create a new model in the same package as the objects being customized.
This is because there will be a dependency between your customizations and the objects being customized.
The new model has to exist in a layer that you can access (usr, cus, or var).

AXPP Files

  • Files ending in axpp are the replacement for xpo files.
  • To export and import projects similar to what you would do with xpos on 2012:

  • 1. In the Solution Explorer, right-click on a project and choose Export project <ProjectName>
    2. The project gets saved as a file with an extension of .axpp
    a. The model the project is created in is saved in the axpp fileii

    ii. The model contains the layer infoii. The model contains the layer info

    ii. The model contains the layer info

    b. The axpp file cannot be read with Notepad
    3.   To import the axpp containing the project in VS go to the Dynamics AX menu and choose Import project.

      a. The project is created in the model (and layer) and saved in the axpp file.

      b. If the model doesn’t exist in the imported environment, it will be generated.

    4.  Similar to 2012 and importing an xpo, in Dynamics 365 for Operations (AX7) you can do a compare between the contents of the axpp file and the current environment.

       a. To compare objects during the import: When you select Import project a dialog opens asking you to select the location       of the axpp file.

    1)When you select Import project a dialog opens asking you to select the location of the axpp file.
    2)Once you have selected the axpp file at the bottom of the dialog there is a Details section.
    3)In the details section, you can see all of the objects to be imported.
    4)When viewing the objects, right-click on one of them and choose Compare to bring up compare window.
    Event Handlers


    https://dynenterprisestrategies.com/news/2017/4/9/event-and-event-handlers-d365o

    Naming Guidelines 

    https://docs.microsoft.com/en-us/dynamics365/unified-operations/dev-itpro/extensibility/naming-guidelines-extensions

    Table Methods

    [ExtensionOf(tableStr(InventTable))] final class MyInventTable_Extension { [DataEventHandler(tableStr(InventTable), DataEventType::Inserting)] public static void InventTable_onInserting(Common sender, DataEventArgs e) { InventTable inventTable = sender as InventTable; // Call the method as if it was defined directly on InventTable. inventTable.defaultMyInventLocationId(); } public void defaultMyInventLocationId() { // This would have partner specific logic to initialize the new field. this.MyInventLocationId = this.inventLocationId(); } }

    You can now add new methods to the augmentation class. These methods will then appear in IntelliSense for variables of the InventTable type, just as if they were defined directly on the table. This behavior applies to both static methods and instance methods.
    There are a few rules for augmentation classes:
    • They must be final.
    • They must be suffixed by _Extension.
    • They must be decorated with the [ExtensionOf()] attribute.
    Note
    In this example, the data event handling method is also defined on the augmentation class. In a real implementation, you might want to move the data event handling method into a separate class that contains the event handlers for the InventTable table.