Integration of D365 using Azure API and logic apps: part 2



I hope you all are doing great and might have gone through my earlier blog on Azure APIm introduction: https://www.blogger.com/blog/post/edit/2520883737187850604/4308148657431504181

This documentation focuses through live examples as to how such a system could be effectively designed and made to work with D365.

Situation: problem statement

We have a 3rd party logistics system who creates Purchase orders in DAX, validates and creates GRN in AX and subsequently posts them.

Solution design

a.       A batch job that creates an Azure storage file in a shared Azure folder.

b.       Custom Ax services pick up the file and creates Purchase orders in D365

c.       The third party receives the purchase order in their own system and tries to replicate the same in Ax. For that

I.                     It needs to call an Ax defined class that validates various information for a given purchase order.

II.                   In order to do this you can define an action/method in an exposed entity in D365, which in turns Class method from Step I. You can call this action from a logic app.

III.                 If returns Ok/true, it calls Step IV. Else validation fails

IV.                It calls another action and pushes a record to a staging table in Ax

V.                  A batch picks up from this staging table and creates/posts packing slips.

For our discussion’s sake we are concentrating for now on Azure API and logic apps’ interactions. For creating and managing batches using Azure folder, could be discussed separately on another blog.

Step 1: the staging table

We can make a staging table that primarily consist of the following information/fields:

Table name

DEMImportPurchaseGRNTable

Fields

Fieldname

Field type

Extends

Mandatory

PurchId

String(20)

PurchId

Yes

LineNum

Real

Linenum

Yes

Qty

Real

Qty

Yes

ItemId

String(20)

ItemId

Yes

ImportId

String(20)

Num

No

Status

Enum

New Enum: DEMProcessStatus

Values: In-process, Processed, Error

No

 

Properties

I.                     Caching: Not_In_Transaction

II.                   Table group: Worksheet line

III.                 Label: provide suitable label

IV.                Developer documentation: provide suitable documentation

V.                  Set created date time and modified date time properties to true

Methods

Create

a.       find

b.       exists

c.       logic for obtaining new ImportId

d.       initValue:

this.Status = DEMProcessStatus::created;

this.ImportId = //call the Import Id logic defined in step ‘c’ above

Keys

ImportIdIdx:

Field: Import Id

Allow duplicate: false

Set table Clustered Index and Surrogate key = ImportIdIdx

Step 2: method for validating

Create a class: DEMValidateImportGRN.

Validation Method:

Public static Boolean validatePurchaseOrder(PurchId _purchId, ItemId _itemId, Qty _qty)

{

              If (!PurchTable::exists(_purhId))

                             checkFailed (strfmt(“PurchId %1 does not exist”, _purchId));

              PurchLine purchLine;

              Select firstonly RecId, Qty from purchLine

                             Where purchLine.purchId == _purchId

                             && purchLine.ItemId == _itemId;

              If (! purchLine.RecId)

                             checkFailed(strfmt(“Purchase order %1 does not have %2 item”, _purchId, _itemId));

              if (purchLine.Qty > _qty)

{

              checkFailed(strfmt(“Insufficient inventory for Purchase order %1 does not have %2 item”, _purchId, _itemId));  

}

}

Defining the action:

You can select/create an existing/new entity à create a new method like this:

[SysODataActionAttribute(‘validatePurchaseOrder’, true)]
public static boolean validatePurchaseOrder’ (PurchId _purchId, ItemId _itemId, Qty _qty)

{
              return DEMValidateImportGRN:: validatePurchaseOrder(_purchId, _itemId, _qty);
}

Step 3: populate the staging table for GRN post

In the same class as above, create a method to populate staging table:

Public static Boolean populateStaging(PurchId _purchId, ItemId _itemId, Qty _qty)

{

              DEMImportPurchaseGRNTable purchGRNTable;

              try

              {

                             purchGRNTable.initValue();

                             purchGRNTable.PurchId = _purchId;

                             purchGRNTable.Qty = _qty;

                             purchGRNTable.ItemId = _itemId;

purchGRNTable.LineNum = //create your own logic for populating line num; as a reference, please see the PurchLine à new line num logic.

purchGRNTable.insert();

return true;

              }

              Catch(exception::Ex)

              {

                             Return checkFailed(“insert failed for GRN import”);

}

 

}

Step 4: the Azure API

Open your https://portal.azure.com à search for available API management services. Here, you can create your own API or use an already existing one.

Add new service operation:

Validate purchase Order: validate:



Click on query and add parameters:



 

Click on save.

Click on outbound processing à and add the policies:

<inbound>

<set-variable name=”purchId” value=”@(context.Request.Url.Query.GetValueOrdefault(“purchId”))”>

<set-variable name=”itemId” value=”@(context.Request.Url.Query.GetValueOrdefault(“itemId”))”>

<set-variable name=”qty” value=”@(context.Request.Url.Query.GetValueOrdefault(“qty”))”>

</inbound>

The above logic obtains the supplied ItemId, PurchId and qty from query parameters.

Now we will call the logic append pass the above parameters:



Inside the <set_url> you can actually set the url of your logic app.

See how you are creating a JSON object on the fly and passing on as a response, like this:

{

“purchId”: “P000111”,

“itemId”:”It00001”,

“qty”: 5

}

Step 5: logic app to call your custom code:

You can create a Logic app like this (for more details, refer to the the previous blog of logic app integration)

a.       Select the following trigger: “when a http request is received”.

b.       Select the above template for JSON request body

{

“purchId”: “P000111”,

“itemId”:”It00001”,

“qty”: 5

}

 

c.       Add action: D365 for F&O as an action. Go to connections and select your desired D365 instance.



 

d.       Select ‘Compose’ – a JSON template as a next action:



 

In the inputs à create a new JSON as:

{

“Result”: ***Bring in the value output from above action***

}

 

e.       As a last step create a response action, that prints the result:



 

Why 202? It means when your request is ‘Accepted’. 200 means ‘Success, Ok”, etc.

Conclusion:

a.       When you call this logic app from Azure API as mentioned above, you can get the result outcome as a HTTP request body

For populating the GRN import, you create a similar action and get this call from a logic app, whic

Comments

Popular posts from this blog

X++ : mistakes which developers commit the most

Make your menu items visible on main menu, conditionally,, using this cool feature of D365FO

Speed up your execution performance by using SysGlobalCaches