Private Preview: Business Events the newest integration with Business Central
Note:
This feature is still in private preview and has his limitation.
You can see all details here (also how you can be part of the private preview):
d365bcdv/samples/Business Events/Private Preview at main · microsoft/d365bcdv · GitHub
Next the already integrations with Dataverse (Data Sync, Virtual Entities and Data Events) there is a fourth integration: Business Events.
With Business Events you can respond to an action inside Business Central. So for example if a Purchase Invoice is posted or when a Sales Quote is transferred to a Sales Order. You van add your own Business Events through AL code. In the example below I react on a event in the standard code. Bot you can also implement it in your own code!
So first you can extend the enum “EventCategory”:
enumextension 50110 MyEventCategory extends EventCategory
{
value(50110; "My Inventory Events")
{
Caption = 'Inventory Events';
}
}
After this you can add your Business Event in AL like below example when a Transfer Order is shipped or Recieved:
Codeunit 50110 MyBusinessEvents
{
var
EventCategory: Enum EventCategory;
[EventSubscriber(ObjectType::Codeunit, Codeunit::"TransferOrder-Post (Yes/No)", 'OnAfterPost', '', false, false)]
local procedure OnAfterPostTransferOrder(var TransHeader: Record "Transfer Header"; Selection: Option " ",Shipment,Receipt)
var
Url: Text[250];
TransferReceiptApiUrlTok: Label 'v2.0/companies(%1)/transferReceiptHeader(%2)', Locked = true;
TransferShipmentApiUrlTok: Label 'v2.0/companies(%1)/transferShipmentHeader(%2)', Locked = true;
Company: Record Company;
TransferReceiptHeader: Record "Transfer Receipt Header";
TransferShipmentHeader: Record "Transfer Shipment Header";
begin
Company.Get(CompanyName); //Because Company Id is not available yet
if Selection = Selection::Shipment then begin
TransferShipmentHeader.SetRange("Transfer Order No.", TransHeader."No.");
TransferShipmentHeader.FindLast();
Url := GetBaseUrl() + StrSubstNo(TransferShipmentApiUrlTok, GetCompanyId(), TrimId(TransferShipmentHeader.SystemId));
MyBusinessEventTransferOrderPostedShipment(TransferShipmentHeader.SystemId, Url, Company.SystemId, TransferShipmentHeader."Direct Transfer");
end;
if Selection = Selection::Receipt then begin
TransferReceiptHeader.SetRange("Transfer Order No.", TransHeader."No.");
TransferReceiptHeader.FindLast();
Url := GetBaseUrl() + StrSubstNo(TransferReceiptApiUrlTok, GetCompanyId(), TrimId(TransferReceiptHeader.SystemId));
MyBusinessEventTransferOrderPostedReceipt(TransferReceiptHeader.SystemId, Url, Company.SystemId, TransHeader."Direct Transfer");
end;
end;
[ExternalBusinessEvent('TransferOrderPostedShipment', 'Transfer Order Posted for Shipment', 'This business event is triggered when a Transfer Order is posted', EventCategory::"My Inventory Events")]
local procedure MyBusinessEventTransferOrderPostedShipment(TrasferOrderId: Guid; Url: text[250]; CompanyId: Guid; DirectTransfer: Boolean)
begin
end;
[ExternalBusinessEvent('TransferOrderPostedShipmentReceipt', 'Transfer Order Posted for Receipt', 'This business event is triggered when a Transfer Order is posted', EventCategory::"My Inventory Events")]
local procedure MyBusinessEventTransferOrderPostedReceipt(TrasferOrderId: Guid; Url: text[250]; CompanyId: Guid; DirectTransfer: Boolean)
begin
end;
local procedure GetBaseUrl(): text
begin
exit(GetUrl(CLIENTTYPE::Api));
end;
local procedure GetCompanyId(): text
var
Company: Record Company;
begin
Company.Get(CompanyName);
exit(TrimId(Company.SystemId));
end;
local procedure TrimId(Id: Guid): Text
begin
exit(DelChr(Format(Id), '<>', '{}'));
end;
}
The beauty of this is that you can define your own parameters that will send into the body. In this case we are sending the following parameters:
– TransferOrderId
– DirectTransfer
– CompanyID (this is beacuse the company isn’t there by default. That is a know issue but you can get it by adding this to your Business Event).
– URL
– CompanyCode
When you do a get on api/microsoft/runtime/v1.0/externalbusinesseventdefinitions you can also see it:
"value": [
{
"appId": "cd388a4b-3b9e-4756-aea6-d17f72d6e970",
"name": "TransferOrderPostedShipment",
"payload": "[{\"Index\":0,\"Name\":\"TrasferOrderId\",\"Type\":\"Guid\"},{\"Index\":1,\"Name\":\"Url\",\"Type\":\"Text[250]\"},{\"Index\":2,\"Name\":\"CompanyId\",\"Type\":\"Guid\"},{\"Index\":3,\"Name\":\"DirectTransfer\",\"Type\":\"Boolean\"}]",
"displayName": "Transfer Order Posted for Shipment",
"description": "This business event is triggered when a Transfer Order is posted",
"category": "My Inventory Events",
"appName": "BusinessEventDataverse",
"appPublisher": "Default publisher",
"appVersion": "1.0.0.0"
},
{
"appId": "cd388a4b-3b9e-4756-aea6-d17f72d6e970",
"name": "TransferOrderPostedShipmentReceipt",
"payload": "[{\"Index\":0,\"Name\":\"TrasferOrderId\",\"Type\":\"Guid\"},{\"Index\":1,\"Name\":\"Url\",\"Type\":\"Text[250]\"},{\"Index\":2,\"Name\":\"CompanyId\",\"Type\":\"Guid\"},{\"Index\":3,\"Name\":\"DirectTransfer\",\"Type\":\"Boolean\"}]",
"displayName": "Transfer Order Posted for Receipt",
"description": "This business event is triggered when a Transfer Order is posted",
"category": "My Inventory Events",
"appName": "BusinessEventDataverse",
"appPublisher": "Default publisher",
"appVersion": "1.0.0.0"
}
]
Now you can subscribe to your Business Event in two ways:
External app
When you want to subscribe to your external app you first have to subscribe your app to the Business Event. That is possible to do a Post with the following body:
POST https://api.businesscentral.dynamics.com/v2.0/<tenant-ID>/<environment>/api/microsoft/runtime/v1.0/externaleventsubscriptions
{
"companyName": "CRONUS NL",
"eventName": "TransferOrderPostedShipment",
"appId": "cd388a4b-3b9e-4756-aea6-d17f72d6e970",
"notificationUrl": "https://prod-94.westeurope.logic.azure.com:443/workflows/0d6f47c012ec492ab809de453d23cdc3/triggers/manual/paths/invoke?api-version=2016-06-01&sp=%2Ftriggers%2Fmanual%2Frun&sv=1.0&sig=Ry_7MyF9C2AJswEDqZk8pHmK-QspBFGTzdDZJaYAahU"
}
You can also view all your subscriptions:
GET https://api.businesscentral.dynamics.com/v2.0/<tenantId>/<environment>/api/microsoft/runtime/v1.0/externaleventsubscriptions
Result:
{
"@odata.context": "https://api.businesscentral.dynamics.com/v2.0/<tenantId>/<environment>/api/microsoft/runtime/v1.0/$metadata#externaleventsubscriptions",
"value": [
{
"@odata.etag": "W/\"JzE5OzE5MDUyNjM0MjcyNjg0MzU1MjUxOzAwOyc=\"",
"id": "2473052d-db1c-4144-bb1c-2f4fbdaed067",
"timestamp": 105709,
"appId": "cd388a4b-3b9e-4756-aea6-d17f72d6e970",
"eventName": "CustomerBlocked",
"companyName": "",
"userId": "89f9aa77-a97b-4ec6-9ea1-54a2065b8c74",
"notificationUrl": "https://org13abfcc3.crm4.dynamics.com/api/data/V9.0/PostRuntimeIntegrationExternalEvent",
"lastModifiedDateTime": "2023-04-17T11:52:59Z",
"clientState": "",
"subscriptionType": "Dataverse",
"systemCreatedAt": "2023-04-17T11:52:59.38Z",
"systemCreatedBy": "89f9aa77-a97b-4ec6-9ea1-54a2065b8c74",
"systemModifiedAt": "2023-04-17T11:52:59.38Z",
"systemModifiedBy": "89f9aa77-a97b-4ec6-9ea1-54a2065b8c74"
},
{
"@odata.etag": "W/\"JzE5OzE1NDYxMjMzMTk2NTk2MzExMjkxOzAwOyc=\"",
"id": "e95073fb-8f6a-450b-89bf-7dd4e480a368",
"timestamp": 106667,
"appId": "cd388a4b-3b9e-4756-aea6-d17f72d6e970",
"eventName": "TransferOrderPostedShipment",
"companyName": "",
"userId": "89f9aa77-a97b-4ec6-9ea1-54a2065b8c74",
"notificationUrl": "https://org13abfcc3.crm4.dynamics.com/api/data/V9.0/PostRuntimeIntegrationExternalEvent",
"lastModifiedDateTime": "2023-04-17T19:23:44Z",
"clientState": "",
"subscriptionType": "Dataverse",
"systemCreatedAt": "2023-04-17T19:23:44.537Z",
"systemCreatedBy": "89f9aa77-a97b-4ec6-9ea1-54a2065b8c74",
"systemModifiedAt": "2023-04-17T19:23:44.537Z",
"systemModifiedBy": "89f9aa77-a97b-4ec6-9ea1-54a2065b8c74"
},
{
"@odata.etag": "W/\"JzE5Ozk1MjUxOTM2OTA4NDcyNzE4OTMxOzAwOyc=\"",
"id": "09113fe9-3865-4dbd-a7f3-f779ee5daea9",
"timestamp": 107543,
"appId": "cd388a4b-3b9e-4756-aea6-d17f72d6e970",
"eventName": "TransferOrderPostedShipment",
"companyName": "CRONUS NL",
"userId": "d09dc8df-efb3-4fd4-b6fb-6dc42319950c",
"notificationUrl": "https://prod-94.westeurope.logic.azure.com:443/workflows/0d6f47c012ec492ab809de453d23cdc3/triggers/manual/paths/invoke?api-version=2016-06-01&sp=%2Ftriggers%2Fmanual%2Frun&sv=1.0&sig=Ry_7MyF9C2AJswEDqZk8pHmK-QspBFGTzdDZJaYAahU",
"lastModifiedDateTime": "2023-04-18T08:56:42Z",
"clientState": "",
"subscriptionType": "Webhook",
"systemCreatedAt": "2023-04-18T08:56:42.6Z",
"systemCreatedBy": "d09dc8df-efb3-4fd4-b6fb-6dc42319950c",
"systemModifiedAt": "2023-04-18T08:56:42.6Z",
"systemModifiedBy": "d09dc8df-efb3-4fd4-b6fb-6dc42319950c"
}
]
}
You can see that the Dataverse subscription is “automatically” created and it has a different subscriptionType.
When you receive the webhook the body is as follow:
{
"value": [
{
"appId": "cd388a4b-3b9e-4756-aea6-d17f72d6e970",
"eventName": "TransferOrderPostedShipment",
"timestamp": "2023-04-18T08:59:18.5700000Z",
"initiatingUserAADObjectId": "2773155c-d08c-4739-b7f0-1ceef2d7e49f",
"companyName": "CRONUS NL",
"payload": {
"TrasferOrderId": "55ee654a-c7dd-ed11-a7c7-000d3a64eef5",
"Url": "https://api.businesscentral.dynamics.com/v2.0/f347666b-e7a9-4dbb-a45f-7836c70d3024/Test/api/v2.0/companies(A1B2E55E-F9C9-ED11-94CA-6045BD8E515F)/transferShipmentHeader(2301EA86-F9C9-ED11-94CA-6045BD8E515F)",
"CompanyId": "a1b2e55e-f9c9-ed11-94ca-6045bd8e515f",
"DirectTransfer": false
},
"clientState": ""
}
]
}
Dataverse
As shown above you can also interact with Dataverse on your Business Events.
Before that you have to install the Virtual Table for Business Central App in your Dataverse and refresh the Business Event from the “Business Central Virtual Data Source Configuration” table:
When you have done that you can use the trigger “When an action is performed”:
And with the values you can get the record from Business Central and do many more things.
Note:
The users that can fire the Business Event must have the “EXT. EVENTS – SUBSCR” Permission Set assigned!
2 COMMENTS