Tuesday, May 31, 2022

Data Management Framework in Dynamics 365 FO

Data entities – a conceptual abstraction of one or more underlying tables. It represents a common data concept or functionality, for example, Customers or Vendors


Data project – contains configured data entities, which include mapping and default processing options


Data job – a job that contains an execution instance of the data project, uploaded files, schedule (recurrence), and processing options


Job history – histories of the source to staging and staging to target jobs


Data package – A single compressed file that contains a data project manifest and data files. This is generated from a data job and used for the import or export of multiple files within the manifest.


Data management workspace



Execution page



Mapping



Excel



Editing in excel



Friday, May 27, 2022

How to install a Deployable package from LIVE to DEV server in Dynamcis 365 F&O

Go to https://lcs.dynamics.com/

Click on the Shared asset library button

Select Software deployable package

Download Dynamics 365 Unified Operations Platform Update 11 and copy the downloaded archive to a specific folder manually created on VM. For instance, C:\Update11

Right-click on the downloaded zip file, select Properties and click on the Unblock

Extract archive file to C:\Update11\AXPlatformUpdate folder

Open Command prompt application as Administrator, change the current folder to C:\Update11\AXPlatformUpdate by the following command:

cd C:\Update11\AXPlatformUpdate


Run the following command:

AXUpdateInstaller.exe generate -runbookid=”DevBox” -topologyfile=”DefaultTopologyData.xml” -servicemodelfile=”DefaultServiceModelData.xml” -runbookfile=”DevBox-runbook.xml”


Run the following command:

AXUpdateInstaller.exe import -runbookfile=”DevBox-runbook.xml”


Run the following command:

AXUpdateInstaller.exe execute -runbookid=”DevBox”


Now, wait until it’s completed. For me, it took approx. 3 hours.


After completion, you can check the About form and you will notice that the platform version has been changed.

Sunday, May 22, 2022

Lookup method in D365 FO

1. For Normal field

a. Inside DS-Path – Form < DataSource < table < Field < method - Lookup

public void lookup(FormControl _formControl, str _filterStr)

{


 Query query = new Query();

 QueryBuildDataSource qbdsVendInvoiceInfoTable;


 // Instantiate sysTableLookup object using table which will provide the visible fields

 SysTableLookup sysTableLookup =

sysTableLookup::newParameters(tableNum(VendTable), _formControl);

 // Create the query.

 qbdsVendTable =

query.addDataSource(TableNum(VendTable));


 // Set the query to be used by the lookup form

 sysTableLookup.parmQuery(query);

 // Specify the fields to show in the form.

 sysTableLookup.addLookupfield(fieldNum(VendTable, AccountNum));

 sysTableLookup.addLookupfield(fieldNum(VendTable, Party));


 // Perform the lookup

 sysTableLookup.performFormLookup();

}







b. Inside Design

Path- Form<Design < Field< method – Lookup()

public void lookup()

{

 SysTableLookup relationsLookup;

 QueryBuildDataSource qbd;

 QueryBuildRange qbr;

 Query query = new Query();

 relationsLookup = SysTableLookup::newParameters(tableNum(DirRelationshipTypeTable), this, true);

 relationsLookup.addLookupfield(fieldNum(DirRelationshipTypeTable , RelationshipTypeId));

 relationsLookup.addLookupfield(fieldNum(DirRelationshipTypeTable , Description));

 relationsLookup.addLookupfield(fieldNum(DirRelationshipTypeTable , ChildPartyType));

 relationsLookup.addLookupfield(fieldNum(DirRelationshipTypeTable , ParentPartyType));

 relationsLookup.addLookupfield(fieldNum(DirRelationshipTypeTable , ChildParentName));

 relationsLookup.addLookupfield(fieldNum(DirRelationshipTypeTable , ParentChildName));

 qbd = query.addDataSource(tableNum(DirRelationshipTypeTable));

 qbr = qbd.addRange(fieldNum(DirRelationshipTypeTable, ChildPartyType));

 qbr.value(queryValue(DirPartyType::Person));

 qbr = qbd.addRange(fieldNum(DirRelationshipTypeTable, ParentPartyType));

 qbr.value(queryValue(DirPartyType::Person));

 relationsLookup.parmQuery(query);

 relationsLookup.performFormLookup();

}








2. For reference field

Path- Form < DS < table < field < lookupReference()

public Common lookupReference(FormReferenceControl _formReferenceControl)

{

 Query query = new Query();

 QueryBuildDataSource qbrdDirPartytable, qbdsDirPartyOrganization;

 SysReferenceTableLookup sysTableLookup =

SysReferenceTableLookup::newParameters(tableNum(DirPartyTable), _formReferenceControl, true);

 ;

 qbrdDirPartytable = query.addDataSource(tableNum(DirPartyTable));

 qbdsDirpartyorganization =

qbrdDirPartytable.addDataSource(tableNum(DirOrganization));

 qbdsDirpartyorganization.joinMode(JoinMode::ExistsJoin);

 qbdsDirpartyorganization.relations(true);

 sysTableLookup.parmQuery(query);

 sysTableLookup.addLookupField(fieldNum(DirPartyTable, name));

 sysTableLookup.addLookupField(fieldNum(DirPartyTable, PartyNumber));

 sysTableLookup.addLookupField(fieldNum(DirPartyTable, NameAlias));

 sysTableLookup.addLookupField(fieldNum(DirPartyTable, DEL_Type));

 return sysTableLookup.performFormLookup();

}

Friday, May 20, 2022

Enable batch retryable in D365 FO

In the batch class implement following :

class GITS_ImportFromAttendanceList extends RunBaseBatch implements BatchRetryable    




and following method

[Wrappable(true), Replaceable(true)]

    public boolean isRetryable()

    {

        return true;

    }

Wednesday, May 18, 2022

Exceptional handling - Try Catch Throw in Dynamics 365 FO

try

{

***********

***********

***********

***********

}

catch(Exception::Error)

{

    System.Exception ex = CLRInterop::getLastException();

    error(ex.Message);

}

 






try, catch, finally, and retry statements

try

{

    // Code here.

}

catch (Exception::Numeric)

{

    info("Caught a Numeric exception.");

}

catch

{

    info("Caught an exception.");

}

finally

{

    // Executed no matter how the try block exits.

}

 






Exception for throwing/saving error message

#1

System.ArgumentException ex;

try

{

    throw new System.ArgumentException("Invalid argument specified");

}

catch(ex)

{

    error(ex.Message);

}

#2

try

{

    // call to .NET code which throws exception

}

catch(Exception::CLRError)

{

    System.Exception ex = CLRInterop::getLastException();

    error(ex.Message);

}

 






Handling a CLRError

// This example shows that a CLRError exception is not displayed

// in the Infolog unless you catch the exception and manually

static void TryCatchCauseCLRError3Job(Args _args)

{

    System.String netString = "Net string.";

    System.Exception netExcepn;

    try

    {

        info("In the 'try' block. (j3)");

        netString.Substring(-2); // Causes CLR Exception.

    }

    catch (Exception::Error)

    {

        info("Caught 'Exception::Error'.");

    }

    catch (Exception::CLRError)

    {

        info("Caught 'Exception::CLRError'.");

        netExcepn = CLRInterop::getLastException();

        info(netExcepn.ToString());

    }

 






List of exceptions :

The following table shows the exception literals that are the values of the Exception enumeration.

Break -------- The user pressed Break or Ctrl+C.

CLRError -------- An error occurred while the CLR functionality was being used.

CodeAccessSecurity -------- An error occurred while the CodeAccessPermission.demand method was being used.

DDEerror -------- An error occurred while the DDE system class was being used.

Deadlock -------- A database deadlock occurred, because several transactions are waiting for each other.

DuplicateKeyException -------- An error occurred in a transaction that is using Optimistic Concurrency Control. The transaction can be retried (use a retry statement in the catch block).

DuplicateKeyExceptionNotRecovered -------- An error occurred in a transaction that is using Optimistic Concurrency Control. The code won't be retried. This exception can't be caught inside a transaction.

Error -------- A fatal error occurred. The transaction has been stopped.

Info -------- This exception literal holds a message for the user. Don't throw an info exception.

Internal -------- An internal error occurred in the development system.

Numeric -------- An error occurred while the str2int, str2int64, or str2num function was being used.

UpdateConflict -------- An error occurred in a transaction that is using Optimistic Concurrency Control. The transaction can be retried (use a retry statement in the catch block).

UpdateConflictNotRecovered -------- An error occurred in a transaction that is using Optimistic Concurrency Control. The code won't be retried. This exception can't be caught within a transaction.

Warning -------- An exceptional event has occurred. Although the user might have to take action, the event isn't fatal. Don't throw a warning exception.

SQL connection error X++ exception -------- An error occurred when during the query execution. The transaction will be canceled. This exception can't be caught within a transaction.

Link

Tuesday, May 17, 2022

Valid time state table in D365 FO

hcmPositionWorkerAssignment HcmPositionWorkerAssignmentLocal;

utcdatetime                 _validFrom = DateTimeUtil::utcNow();

select firstonly ValidTimeState(_validFrom) hcmPositionWorkerAssignmentLocal

    where hcmPositionWorkerAssignmentLocal.Worker == worker

Thursday, May 12, 2022

Power BI connection to Microsoft D365 FO

Download the Power BI desktop application. Link

Install the application and run it.

Sign in with your Microsoft account.




Step 3. Connection to the database
URL Based connection
SQL server connection

URL Based connection
You can connect to D365 server URL directly.



Copy the URL and add data at the end. Enter the client credentials and you will get the connection. 

SQL server connection
Login to LCS and get the AX DB details like. 



Server name: spartan-***-****-d365***prod-**********.database.windows.net
Database name: db_d365***prod_********_********_****
Username: axdbadmin
Password: ***************

utcDatetime functions in Dynamics 365 FO

transDateTime = DateTimeUtil::minvalue();

transDateTime = DateTimeUtil::maxvalue();

DateTimeUtil::utcNow()


To extract the date components (day, month, year) and time components (hour, minute, second) from a utcDateTime value as follows :
info(strFmt("%1", DateTimeUtil::date(transDateTime)));
info(int2str(DateTimeUtil::time(transDateTime)));
info(int2str(DateTimeUtil::day(transDateTime)));
info(int2str(DateTimeUtil::month(transDateTime)));
info(int2str(DateTimeUtil::year(transDateTime)));
info(int2str(DateTimeUtil::hour(transDateTime)));
info(int2str(DateTimeUtil::minute(transDateTime)));
info(int2str(DateTimeUtil::second(transDateTime)));


To add or subtract seconds, minutes, hours, days, months and years as follows :
transDateTime = DateTimeUtil::addSeconds(transDateTime, 60);
transDateTime = DateTimeUtil::addMinutes(transDateTime, 719);
transDateTime = DateTimeUtil::addHours(transDateTime, 36);
transDateTime = DateTimeUtil::addDays(transDateTime, 28);
transDateTime = DateTimeUtil::addMonths(transDateTime, 11);
transDateTime = DateTimeUtil::addYears(transDateTime, -1);
info(int642str(DateTimeUtil::getDifference(transDateTime, DateTimeUtil::minValue())));


utcDateTime to str conversion can be done as follows :
dateTimeStr = DateTimeUtil::toStr(transDateTime);
dateTimeStr = DateTimeUtil::toFormattedStr(transDateTime, 231, DateDay::Digits2, DateSeparator::Hyphen, DateMonth::Short, DateSeparator::Hyphen, DateYear::Digits4, TimeSeparator::Colon, TimeSeparator::Colon, DateFlags::None);

Thursday, May 5, 2022

Create a custom web service in D365FO Integration (Data Receiving)

Create a Table where you want to insert the fields in my case I am creating a table GITS_Worker, which has 2 fields "Name" and "Number"


Now create a contract class, in my case, I am naming my contract class "GITSCreateWorker" and write the following code:

-------------------------------------------------------START------------------------------------------------------------

[DataContractAttribute]

class GITSCreateWorker

{

    Name Number;

    Name Name;

    [DataMemberAttribute]

    public str Number(str _Number= Number)

    {

        Number = Number;

        return Number;

    }

    [DataMemberAttribute]

    public str Name(str _Name= Name)

    {

        Name = Name;

        return Name;

    }

}

------------------------------------------------------------END----------------------------------------------------------

Now create a class for inserting data in a table, in my case, I am naming my class "GITSWorkerIntegrationService" and write the following code:

-------------------------------------------------------START------------------------------------------------------------

class GITSWorkerIntegrationService

{

 [AifCollectionTypeAttribute('_CreateWorker',Types::Class,classStr(GITSCreateWorker)),SysEntryPointAttribute(true)]

    public Str CreateWorker(List    _CreateWorker)

    {

        GITSCreateWorker        CreateWorker;

        Enumerator              EnumeratorHeader;

        GITS_Worker             Worker;

        EnumeratorHeader    = _CreateWorker.getEnumerator();

        while(EnumeratorHeader.moveNext())

        {

            CreateWorker    = EnumeratorHeader.current();

            Worker.Name     = CreateWorker.Name();

            Worker.Number   = CreateWorker.Number();

            Worker.insert();

        }

        return "Success";

    }

}

------------------------------------------------------------END----------------------------------------------------------


Now create an AxService, in my case I am creating "GITSWorkerIntegrationService"

In the properties of this service put in the name of the class that we created "GITSWorkerIntegrationService"

Now put in the description property

Now right click on "Service operation" and create a new service operation, in the properties of this service operation put in the name of the method that we created

Now create an AxServiceGroup, in my case I am creating "GITSWorkerIntegrationServiceGroup"

In the properties set auto-deploy yes and put in the description

Now create a new "Service" in the group and put in the AxService that we created

Sync and build 

Tada !!!

Now your web service is ready to use. use below urls for respective services

<D365FO URL>/api/services/<Service group name>/<Service Name>/<Service operation name>

<D365FO URL>/soap/services/<Service group name>?wsdl

Wednesday, May 4, 2022

Access modifiers in X++ Language Dynamics 365 FO

Abstract: The method is declared but not implemented in a parent class. The method must be overridden in subclasses. If you try to create an object from a subclass where one or more of the abstract methods belonging to the parent class have not been overridden, you will get a compiler error. Note: Classes can also be abstract. Sometimes a class represents an abstract concept, but it should not be instantiated: Only sub-classes should be instantiated. Such base classes can be declared abstract. Consider the case where the programmer wants to model the concept of an account. Accounts are abstract—only derived classes (ledger accounts and so on) exist in the real world. This would be a clear case for declaring the Account class abstract.


Final: Indicates that the method cannot be overridden in any class that derives from its class.


Public: Methods that are declared as public are accessible anywhere the class is accessible and can be overridden by subclasses. Methods that have no access modifier are implicitly public.


Protected: Methods that are declared as protected can only be called from methods in the class and in subclasses that extend the class where the method is declared.


Private: Methods that are declared as private can be called only from methods in the class where the private method is declared.


Client: Establishes the location where the method is to be executed (on the client). Can only be used on static methods. If the method is not static, specify the location by using the class property RunOn.


Server: Establishes the location where the method is to be executed (on the server). Can only be used on static methods. If the method is not static, you need to specify the location using the class property RunOn.


Display: Indicates that the method's return value is to be displayed on a form or a report. The value cannot be altered in the form or report. The return value is typically a calculated value, for example, a sum.


Edit: Indicates that the method's return type is to be used to provide information for a field that is used in a form. The value in the field can be edited.


Static: Specifies that the method is a class method and does not operate on an object. Static methods cannot refer to instance variables and are invoked by using the class name rather than on an instance of the class (MyClass::aStaticMethod()).

Reference

Monday, May 2, 2022

How to call menu item through code in D365 FO

Below code will call Action menu item. Args is used to send parameter to class

MenuFunction menuFunction;

args.record(dmfExecution); // to send whole table as parameter

args.caller(this);

menuFunction = new MenuFunction(menuitemActionStr(DMFStagingWriterBatch), MenuItemType::Action);

menuFunction.run(args);



Below code will call Action menu item. Args is used to send parameter to class

Args args = new Args();

args.record(VendTable::find("XYZ")); // to send specific record in a table

MenuFunction menuFunction;

menuFunction = new MenuFunction(menuItemDisplayStr(MyDisplayMenuItem), MenuItemType::Display);

menuFunction.run();


Use formRun to call the form.

FormRun formRun;

Args args = new Args();

;

args.name(formstr(VendTable));

args.record(CustTable::find("XYZ"));

formRun = ClassFactory.formRunClass(args);

formRun.init();

formRun.run();

formRun.wait();


Below code will call the Output menu item.

MenuFunction menuFunction; 

menuFunction = new MenuFunction(menuItemOutputStr(MyOutputMenuItem), MenuItemType::Output);

menuFunction.run();

Download the attachment of record on focus of a field D365 FO

class DapApplicantEventViewer

{    

[FormControlEventHandler(formControlStr(HRMApplication, AttachmentLink), FormControlEventType::GotFocus)]

    public static void AttachmentLink_OnGotFocus(FormControl sender, FormControlEventArgs e)

    {

        FormDataSource FormDatasource;

        DocuRef          docuRef;

        HRMApplication   hRMApplication;

        MenuFunction     menuFunction;

        HcmApplicant HcmApplicantLocal;

        Args             argsMenu= new Args();

        


        FormRun form = sender.formRun();

        FormDatasource  =       form.dataSource(formDataSourceStr(HRMApplication,HRMApplication)) as FormDataSource;

        hRMApplication                   = FormDatasource.cursor();


        select RecId,TableId from HcmApplicantLocal

            where HcmApplicantLocal.Recid == hRMApplication.Applicant;

        select docuref

                where docuref.RefRecId == HcmApplicantLocal.recid

            &&    docuref.RefTableId  == HcmApplicantLocal.Tableid;


        argsMenu.record(docuRef);

        argsMenu.parmEnumType(enumNum(DocuCode));

        argsMenu.parmEnum(DocuCode::Open);

        URL displayUrl = DocumentManagement::getAttachmentPublicUrl(docuref);

        //Info(strFmt("%1", displayUrl));

        menuFunction = new MenuFunction(menuItemActionStr(DocuActionOpen),MenuItemType::Action);

        menuFunction.run(argsMenu);  

    }

}