Codeunit 1511 Notification Lifecycle Mgt., source in 29
Source29
src/Layers/W1/BaseApp/Modules/System/Notifications/NotificationLifecycleMgt.Codeunit.al236 lines, Copyright (c) Microsoft Corporation. MIT
namespace System.Environment.Configuration;
codeunit 1511 "Notification Lifecycle Mgt."
{
SingleInstance = true;
trigger OnRun()
begin
end;
var
TempNotificationContext: Record "Notification Context" temporary;
NotificationSentCategoryTxt: Label 'AL Notification Sent', Locked = true;
NotificationSentTelemetryMsg: Label 'A notification with ID %1 was sent for a record of table %2.', Locked = true;
SubscribersDisabled: Boolean;
procedure SendNotification(NotificationToSend: Notification; RecId: RecordID)
begin
if IsNullGuid(NotificationToSend.Id) then
NotificationToSend.Id := CreateGuid();
NotificationToSend.Send();
OnAfterNotificationSent(NotificationToSend, RecId.TableNo);
CreateNotificationContext(NotificationToSend.Id, RecId);
end;
procedure SendNotificationWithAdditionalContext(NotificationToSend: Notification; RecId: RecordID; AdditionalContextId: Guid)
begin
if IsNullGuid(NotificationToSend.Id) then
NotificationToSend.Id := CreateGuid();
OnBeforeSendNotification(NotificationToSend, RecId, AdditionalContextId);
NotificationToSend.Send();
OnAfterNotificationSent(NotificationToSend, RecId.TableNo);
CreateNotificationContextWithAdditionalContext(NotificationToSend.Id, RecId, AdditionalContextId);
end;
procedure RecallNotificationsForRecord(RecId: RecordID; HandleDelayedInsert: Boolean)
var
TempNotificationContextToRecall: Record "Notification Context" temporary;
begin
if GetNotificationsForRecord(RecId, TempNotificationContextToRecall, HandleDelayedInsert) then
RecallNotifications(TempNotificationContextToRecall);
end;
procedure RecallNotificationsForRecordWithAdditionalContext(RecId: RecordID; AdditionalContextId: Guid; HandleDelayedInsert: Boolean)
var
TempNotificationContextToRecall: Record "Notification Context" temporary;
begin
if GetNotificationsForRecordWithAdditionalContext(RecId, AdditionalContextId, TempNotificationContextToRecall, HandleDelayedInsert) then
RecallNotifications(TempNotificationContextToRecall);
end;
procedure RecallAllNotifications()
begin
TempNotificationContext.Reset();
if TempNotificationContext.FindSet() then
RecallNotifications(TempNotificationContext);
end;
procedure GetTmpNotificationContext(var TempNotificationContextOut: Record "Notification Context" temporary)
begin
TempNotificationContext.Reset();
TempNotificationContextOut.Copy(TempNotificationContext, true);
end;
procedure SetRecordID(RecId: RecordID)
var
RecRef: RecordRef;
begin
RecRef.Open(RecId.TableNo);
UpdateRecordIDHandleDelayedInsert(RecRef.RecordId, RecId, false);
end;
[TryFunction]
local procedure TryFctThrowsErrorIfRecordExists(RecId: RecordID; var Exists: Boolean)
var
RecRef: RecordRef;
begin
// If record exists, in some cases RecRef.GET(RecId) throws an error
Exists := RecRef.Get(RecId);
end;
local procedure UpdateRecordIDHandleDelayedInsert(CurrentRecId: RecordID; NewRecId: RecordID; HandleDelayedInsert: Boolean)
var
TempNotificationContextToUpdate: Record "Notification Context" temporary;
Exists: Boolean;
begin
if HandleDelayedInsert then begin
if not TryFctThrowsErrorIfRecordExists(NewRecId, Exists) then
Exists := true;
if not Exists then
exit;
end;
if GetNotificationsForRecord(CurrentRecId, TempNotificationContextToUpdate, HandleDelayedInsert) then
repeat
TempNotificationContextToUpdate."Record ID" := NewRecId;
TempNotificationContextToUpdate.Modify(true);
until TempNotificationContextToUpdate.Next() = 0
end;
procedure UpdateRecordID(CurrentRecId: RecordID; NewRecId: RecordID)
begin
UpdateRecordIDHandleDelayedInsert(CurrentRecId, NewRecId, true);
end;
procedure GetNotificationsForRecord(RecId: RecordID; var TempNotificationContextOut: Record "Notification Context" temporary; HandleDelayedInsert: Boolean): Boolean
begin
TempNotificationContext.Reset();
GetUsableRecordId(RecId, HandleDelayedInsert);
TempNotificationContext.SetRange("Record ID", RecId);
TempNotificationContextOut.Copy(TempNotificationContext, true);
exit(TempNotificationContextOut.FindSet());
end;
procedure GetNotificationsForRecordWithAdditionalContext(RecId: RecordID; AdditionalContextId: Guid; var TempNotificationContextOut: Record "Notification Context" temporary; HandleDelayedInsert: Boolean): Boolean
begin
TempNotificationContext.Reset();
GetUsableRecordId(RecId, HandleDelayedInsert);
TempNotificationContext.SetRange("Record ID", RecId);
TempNotificationContext.SetRange("Additional Context ID", AdditionalContextId);
TempNotificationContextOut.Copy(TempNotificationContext, true);
exit(TempNotificationContextOut.FindSet());
end;
local procedure CreateNotificationContext(NotificationId: Guid; RecId: RecordID)
begin
DeleteAlreadyRegisteredNotificationBeforeInsert(NotificationId);
TempNotificationContext.Init();
TempNotificationContext."Notification ID" := NotificationId;
if GetUsableRecordId(RecId, true) then
TempNotificationContext."Record ID" := RecId;
TempNotificationContext.Insert(true);
OnAfterInsertNotificationContext(TempNotificationContext);
end;
local procedure CreateNotificationContextWithAdditionalContext(NotificationId: Guid; RecId: RecordID; AdditionalContextId: Guid)
begin
DeleteAlreadyRegisteredNotificationBeforeInsert(NotificationId);
TempNotificationContext.Init();
TempNotificationContext."Notification ID" := NotificationId;
if GetUsableRecordId(RecId, true) then
TempNotificationContext."Record ID" := RecId;
TempNotificationContext."Additional Context ID" := AdditionalContextId;
TempNotificationContext.Insert(true);
OnAfterInsertNotificationContext(TempNotificationContext);
end;
local procedure DeleteAlreadyRegisteredNotificationBeforeInsert(NotificationId: Guid)
begin
TempNotificationContext.Reset();
TempNotificationContext.SetRange("Notification ID", NotificationId);
if TempNotificationContext.FindFirst() then begin
TempNotificationContext.Delete(true);
OnAfterDeleteNotificationContext(TempNotificationContext);
end;
end;
local procedure RecallNotifications(var TempNotificationContextToRecall: Record "Notification Context" temporary)
var
NotificationToRecall: Notification;
begin
repeat
NotificationToRecall.Id := TempNotificationContextToRecall."Notification ID";
// Notification.Recall does not fail if the notification was never sent, is no longer there, is dismissed or already recalled
NotificationToRecall.Recall();
TempNotificationContextToRecall.Delete(true);
OnAfterDeleteNotificationContext(TempNotificationContextToRecall);
until TempNotificationContextToRecall.Next() = 0
end;
local procedure GetUsableRecordId(var RecId: RecordID; HandleDelayedInsert: Boolean): Boolean
var
RecRef: RecordRef;
begin
if RecId.TableNo = 0 then
exit(false);
if not HandleDelayedInsert then
exit(true);
RecRef.Open(RecId.TableNo);
RecRef.ReadIsolation := IsolationLevel::ReadUncommitted;
RecRef.SetLoadFields(RecRef.SystemIdNo);
// Handle delayed insert
if not RecRef.Get(RecId) then
RecId := RecRef.RecordId;
exit(true);
end;
[IntegrationEvent(false, false)]
local procedure OnAfterNotificationSent(CurrentNotification: Notification; TableNo: Integer)
begin
end;
[EventSubscriber(ObjectType::Codeunit, Codeunit::"Notification Lifecycle Mgt.", 'OnAfterNotificationSent', '', true, true)]
local procedure LogNotificationSentSubscriber(CurrentNotification: Notification; TableNo: Integer)
begin
Session.LogMessage('00001KO', StrSubstNo(NotificationSentTelemetryMsg, CurrentNotification.Id, TableNo), Verbosity::Normal, DataClassification::SystemMetadata, TelemetryScope::ExtensionPublisher, 'Category', NotificationSentCategoryTxt);
end;
[IntegrationEvent(false, false)]
local procedure OnAfterInsertNotificationContext(NotificationContext: Record "Notification Context")
begin
end;
[IntegrationEvent(false, false)]
local procedure OnAfterDeleteNotificationContext(NotificationContext: Record "Notification Context")
begin
end;
procedure EnableSubscribers()
begin
SubscribersDisabled := false;
end;
procedure DisableSubscribers()
begin
SubscribersDisabled := true;
end;
procedure AreSubscribersDisabled(): Boolean
begin
exit(SubscribersDisabled);
end;
[IntegrationEvent(false, false)]
local procedure OnBeforeSendNotification(var NotificationToSend: Notification; RecId: RecordID; AdditionalContextId: Guid)
begin
end;
}