Codeunit 423 Change Log Management, source in 29
Source29
src/Layers/W1/BaseApp/System/ChangeLog/ChangeLogManagement.Codeunit.al696 lines, Copyright (c) Microsoft Corporation. MIT
namespace System.Diagnostics;
using System.IO;
using System.Security.AccessControl;
using System.Telemetry;
#pragma warning disable AS0018
codeunit 423 "Change Log Management"
{
InherentEntitlements = X;
InherentPermissions = X;
Permissions = TableData "Change Log Setup" = r,
TableData "Change Log Setup (Table)" = r,
TableData "Change Log Setup (Field)" = r,
TableData "Change Log Entry" = ri,
TableData "Field Monitoring Setup" = r;
SingleInstance = true;
trigger OnRun()
begin
end;
var
ChangeLogSetup: Record "Change Log Setup";
FieldMonitoringSetup: Record "Field Monitoring Setup";
ChangeLogSetupTable: Record "Change Log Setup (Table)";
TempChangeLogSetupTable: Record "Change Log Setup (Table)" temporary;
ChangeLogSetupField: Record "Change Log Setup (Field)";
TempChangeLogSetupField: Record "Change Log Setup (Field)" temporary;
MonitorSensitiveFieldData: Codeunit "Monitor Sensitive Field Data";
ChangeLogSetupRead: Boolean;
MonitorSensitiveFieldSetupRead: Boolean;
CannotSelectTableErr: Label 'Change log cannot be enabled for the table %1.', Comment = '%1: Table caption.';
ChangeLogFieldAddedTxt: Label 'Field added to changelog configuration', Locked = true;
ChangeLogFieldUpdatedTxt: Label 'Field logging changed in changelog configuration', Locked = true;
ChangeLogFieldDeletedTxt: Label 'Field removed from changelog configuration', Locked = true;
ChangeLogCategoryLbl: Label 'Change Log', Locked = true;
procedure GetDatabaseTableTriggerSetup(TableID: Integer; var LogInsert: Boolean; var LogModify: Boolean; var LogDelete: Boolean; var LogRename: Boolean)
begin
// Do not add events that allow control of LogInsert, LogModify, LogDelete, LogRename or IsHandled.
if LogDelete and LogInsert and LogModify and LogRename then
exit;
if CompanyName = '' then
exit;
if TableID = Database::"Change Log Entry" then
exit;
if IsAlwaysLoggedTable(TableID) then begin
LogInsert := true;
LogModify := true;
LogDelete := true;
LogRename := true;
exit;
end;
if not ChangeLogSetupRead then begin
if ChangeLogSetup.Get() then;
ChangeLogSetupRead := true;
end;
if not MonitorSensitiveFieldSetupRead then begin
if FieldMonitoringSetup.Get() then;
MonitorSensitiveFieldSetupRead := true;
end;
if not (ChangeLogSetup."Change Log Activated" or FieldMonitoringSetup."Monitor Status") then
exit;
if not TempChangeLogSetupTable.Get(TableID) then begin
if not ChangeLogSetupTable.Get(TableID) then begin
TempChangeLogSetupTable.Init();
TempChangeLogSetupTable."Table No." := TableID;
end else
TempChangeLogSetupTable := ChangeLogSetupTable;
TempChangeLogSetupTable.Insert();
end;
if not MonitorSensitiveFieldData.CheckIfTableIsMonitored(TempChangeLogSetupTable, FieldMonitoringSetup, ChangeLogSetup) then
exit;
LogInsert := LogInsert or (TempChangeLogSetupTable."Log Insertion" <> TempChangeLogSetupTable."Log Insertion"::" ");
LogModify := LogModify or (TempChangeLogSetupTable."Log Modification" <> TempChangeLogSetupTable."Log Modification"::" ");
LogRename := LogRename or (TempChangeLogSetupTable."Log Modification" <> TempChangeLogSetupTable."Log Modification"::" ");
LogDelete := LogDelete or (TempChangeLogSetupTable."Log Deletion" <> TempChangeLogSetupTable."Log Deletion"::" ");
end;
procedure IsLogActive(TableNumber: Integer; FieldNumber: Integer; TypeOfChange: Option Insertion,Modification,Deletion): Boolean
begin
// Do not add events that allow control of return value
if IsAlwaysLoggedTable(TableNumber) then
exit(true);
if TableNumber = Database::"Change Log Entry" then
exit(false);
if not ChangeLogSetupRead then begin
if ChangeLogSetup.Get() then;
ChangeLogSetupRead := true;
end;
if not MonitorSensitiveFieldSetupRead then begin
if FieldMonitoringSetup.Get() then;
MonitorSensitiveFieldSetupRead := true;
end;
if not (ChangeLogSetup."Change Log Activated" or FieldMonitoringSetup."Monitor Status") then
exit(false);
if not TempChangeLogSetupTable.Get(TableNumber) then begin
if not ChangeLogSetupTable.Get(TableNumber) then begin
TempChangeLogSetupTable.Init();
TempChangeLogSetupTable."Table No." := TableNumber;
end else
TempChangeLogSetupTable := ChangeLogSetupTable;
TempChangeLogSetupTable.Insert();
end;
if not MonitorSensitiveFieldData.CheckIfTableIsMonitored(TempChangeLogSetupTable, FieldMonitoringSetup, ChangeLogSetup) then
exit(false);
case TypeOfChange of
TypeOfChange::Insertion:
if TempChangeLogSetupTable."Log Insertion" = TempChangeLogSetupTable."Log Insertion"::"Some Fields" then
exit(IsFieldLogActive(TableNumber, FieldNumber, TypeOfChange))
else
exit(TempChangeLogSetupTable."Log Insertion" = TempChangeLogSetupTable."Log Insertion"::"All Fields");
TypeOfChange::Modification:
if TempChangeLogSetupTable."Log Modification" = TempChangeLogSetupTable."Log Modification"::"Some Fields" then
exit(IsFieldLogActive(TableNumber, FieldNumber, TypeOfChange))
else
exit(TempChangeLogSetupTable."Log Modification" = TempChangeLogSetupTable."Log Modification"::"All Fields");
TypeOfChange::Deletion:
if TempChangeLogSetupTable."Log Deletion" = TempChangeLogSetupTable."Log Deletion"::"Some Fields" then
exit(IsFieldLogActive(TableNumber, FieldNumber, TypeOfChange))
else
exit(TempChangeLogSetupTable."Log Deletion" = TempChangeLogSetupTable."Log Deletion"::"All Fields");
end;
end;
local procedure IsFieldLogActive(TableNumber: Integer; FieldNumber: Integer; TypeOfChange: Option Insertion,Modification,Deletion): Boolean
begin
if FieldNumber = 0 then
exit(true);
if not TempChangeLogSetupField.Get(TableNumber, FieldNumber) then begin
if not ChangeLogSetupField.Get(TableNumber, FieldNumber) then begin
TempChangeLogSetupField.Init();
TempChangeLogSetupField."Table No." := TableNumber;
TempChangeLogSetupField."Field No." := FieldNumber;
end else
TempChangeLogSetupField := ChangeLogSetupField;
TempChangeLogSetupField.Insert();
end;
if TempChangeLogSetupField."Monitor Sensitive Field" then
if not FieldMonitoringSetup."Monitor Status" then
exit(false);
case TypeOfChange of
TypeOfChange::Insertion:
exit(TempChangeLogSetupField."Log Insertion");
TypeOfChange::Modification:
exit(TempChangeLogSetupField."Log Modification");
TypeOfChange::Deletion:
exit(TempChangeLogSetupField."Log Deletion");
end;
end;
procedure IsAlwaysLoggedTable(TableID: Integer) AlwaysLogTable: Boolean
begin
AlwaysLogTable :=
TableID in
[Database::User,
Database::"User Property",
Database::"Access Control",
Database::"Permission Set",
Database::Permission,
Database::"Change Log Setup",
Database::"Change Log Setup (Table)",
Database::"Change Log Setup (Field)",
9004, // Plan
9005, // UserPlan
Database::"Tenant Permission Set Rel.",
Database::"Tenant Permission Set",
Database::"Tenant Permission",
Database::"Field Monitoring Setup"];
if not AlwaysLogTable then
OnAfterIsAlwaysLoggedTable(TableID, AlwaysLogTable);
end;
procedure InsertLogEntry(var FldRef: FieldRef; var xFldRef: FieldRef; var RecRef: RecordRef; TypeOfChange: Enum "Change Log Entry Type"; IsReadable: Boolean)
var
ChangeLogEntry: Record "Change Log Entry";
xRecRef: RecordRef;
KeyFldRef: FieldRef;
KeyRef1: KeyRef;
ChangedRecordSystemId: Guid;
i: Integer;
begin
if RecRef.CurrentCompany <> ChangeLogEntry.CurrentCompany then
ChangeLogEntry.ChangeCompany(RecRef.CurrentCompany);
if MonitorSensitiveFieldData.IsIgnoredMonitorField(RecRef, FldRef) then
exit;
OnInsertLogEntryOnBeforeInitChangeLogEntry(ChangeLogEntry);
ChangeLogEntry.Init();
ChangeLogEntry."Date and Time" := CurrentDateTime;
ChangeLogEntry.Time := DT2Time(ChangeLogEntry."Date and Time");
ChangeLogEntry."User ID" := CopyStr(UserId(), 1, MaxStrLen(ChangeLogEntry."User ID"));
ChangeLogEntry."Table No." := RecRef.Number;
ChangeLogEntry."Field No." := FldRef.Number;
ChangeLogEntry."Type of Change" := TypeOfChange;
if (RecRef.Number = Database::"User Property") and (FldRef.Number in [2 .. 5]) then begin // Password like
ChangeLogEntry."Old Value" := '*';
ChangeLogEntry."New Value" := '*';
end else begin
if TypeOfChange <> TypeOfChange::Insertion then
if IsReadable then
ChangeLogEntry."Old Value" := Format(xFldRef.Value, 0, 9)
else
ChangeLogEntry."Old Value" := '';
if TypeOfChange <> TypeOfChange::Deletion then
ChangeLogEntry."New Value" := Format(FldRef.Value, 0, 9);
end;
ChangeLogEntry."Record ID" := RecRef.RecordId;
ChangeLogEntry."Primary Key" := CopyStr(RecRef.GetPosition(false), 1, MaxStrLen(ChangeLogEntry."Primary Key"));
KeyRef1 := RecRef.KeyIndex(1);
for i := 1 to KeyRef1.FieldCount do begin
KeyFldRef := KeyRef1.FieldIndex(i);
case i of
1:
begin
ChangeLogEntry."Primary Key Field 1 No." := KeyFldRef.Number;
ChangeLogEntry."Primary Key Field 1 Value" :=
CopyStr(Format(KeyFldRef.Value, 0, 9), 1, MaxStrLen(ChangeLogEntry."Primary Key Field 1 Value"));
end;
2:
begin
ChangeLogEntry."Primary Key Field 2 No." := KeyFldRef.Number;
ChangeLogEntry."Primary Key Field 2 Value" :=
CopyStr(Format(KeyFldRef.Value, 0, 9), 1, MaxStrLen(ChangeLogEntry."Primary Key Field 2 Value"));
end;
3:
begin
ChangeLogEntry."Primary Key Field 3 No." := KeyFldRef.Number;
ChangeLogEntry."Primary Key Field 3 Value" :=
CopyStr(Format(KeyFldRef.Value, 0, 9), 1, MaxStrLen(ChangeLogEntry."Primary Key Field 3 Value"));
end;
end;
end;
ChangedRecordSystemId := RecRef.Field(RecRef.SystemIdNo).Value;
if IsNullGuid(ChangedRecordSystemId) and IsReadable and (TypeOfChange = TypeOfChange::Modification) then begin
xRecRef := xFldRef.Record();
ChangedRecordSystemId := xRecRef.Field(xRecRef.SystemIdNo).Value;
end;
OnInsertLogEntryOnBeforeChangeLogEntryValidateChangedRecordSystemId(ChangeLogEntry, RecRef, FldRef);
ChangeLogEntry.Validate("Changed Record SystemId", ChangedRecordSystemId);
MonitorSensitiveFieldData.HandleMonitorSensitiveFields(ChangeLogEntry, TempChangeLogSetupField, RecRef, FldRef, IsAlwaysLoggedTable(RecRef.Number), FieldMonitoringSetup."Monitor Status");
ChangeLogEntry.Insert(true);
end;
procedure LogInsertion(var RecRef: RecordRef)
var
FldRef: FieldRef;
i: Integer;
begin
OnBeforeLogInsertion(RecRef);
if RecRef.IsTemporary then
exit;
if not IsLogActive(RecRef.Number, 0, 0) then
exit;
for i := 1 to RecRef.FieldCount do begin
FldRef := RecRef.FieldIndex(i);
if HasValue(FldRef) then
if IsNormalField(FldRef) then
if IsLogActive(RecRef.Number, FldRef.Number, 0) then
InsertLogEntry(FldRef, FldRef, RecRef, "Change Log Entry Type"::Insertion, true);
end;
OnAfterLogInsertion(RecRef);
end;
procedure LogModification(var RecRef: RecordRef)
var
xRecRef: RecordRef;
FldRef: FieldRef;
xFldRef: FieldRef;
i: Integer;
IsReadable: Boolean;
begin
OnBeforeLogModification(RecRef);
if RecRef.IsTemporary then
exit;
if not IsLogActive(RecRef.Number, 0, 1) then
exit;
xRecRef.Open(RecRef.Number, false, RecRef.CurrentCompany());
xRecRef.ReadIsolation := xRecRef.ReadIsolation::ReadCommitted;
OnLogModificationOnBeforeCheckSecurityFiltering(xRecRef);
xRecRef."SecurityFiltering" := SECURITYFILTER::Filtered;
OnLogModificationOnAfterCheckSecurityFiltering(xRecRef);
if xRecRef.ReadPermission() then begin
IsReadable := true;
if not xRecRef.Get(RecRef.RecordId) then
exit;
end;
OnLogModificationOnBeforeRecRefLoopStart(RecRef, xRecRef);
for i := 1 to RecRef.FieldCount do begin
FldRef := RecRef.FieldIndex(i);
xFldRef := xRecRef.FieldIndex(i);
if IsNormalField(FldRef) then
if FldRef.Value <> xFldRef.Value then
if IsLogActive(RecRef.Number, FldRef.Number, 1) then
InsertLogEntry(FldRef, xFldRef, RecRef, "Change Log Entry Type"::Modification, IsReadable);
end;
OnAfterLogModification(RecRef);
end;
procedure LogRename(var RecRef: RecordRef; var xRecRefParam: RecordRef)
var
xRecRef: RecordRef;
FldRef: FieldRef;
xFldRef: FieldRef;
i: Integer;
begin
OnBeforeLogRename(RecRef, xRecRefParam);
if RecRef.IsTemporary then
exit;
if not IsLogActive(RecRef.Number, 0, 1) then
exit;
xRecRef.Open(xRecRefParam.Number, false, RecRef.CurrentCompany);
xRecRef.ReadIsolation := xRecRef.ReadIsolation::ReadCommitted;
xRecRef.Get(xRecRefParam.RecordId);
for i := 1 to RecRef.FieldCount do begin
FldRef := RecRef.FieldIndex(i);
xFldRef := xRecRef.FieldIndex(i);
if IsNormalField(FldRef) then
if FldRef.Value <> xFldRef.Value then
if IsLogActive(RecRef.Number, FldRef.Number, 1) then
InsertLogEntry(FldRef, xFldRef, RecRef, "Change Log Entry Type"::Modification, true);
end;
end;
procedure LogDeletion(var RecRef: RecordRef)
var
FldRef: FieldRef;
i: Integer;
begin
OnBeforeLogDeletion(RecRef);
if RecRef.IsTemporary then
exit;
if not IsLogActive(RecRef.Number, 0, 2) then
exit;
for i := 1 to RecRef.FieldCount do begin
FldRef := RecRef.FieldIndex(i);
if HasValue(FldRef) then
if IsNormalField(FldRef) then
if IsLogActive(RecRef.Number, FldRef.Number, 2) then
InsertLogEntry(FldRef, FldRef, RecRef, "Change Log Entry Type"::Deletion, true);
end;
OnAfterLogDeletion(RecRef);
end;
procedure IsNormalField(FieldRef: FieldRef): Boolean
begin
exit(FieldRef.Class = FieldClass::Normal)
end;
procedure HasValue(FldRef: FieldRef): Boolean
var
HasValue: Boolean;
Int: Integer;
Dec: Decimal;
D: Date;
T: Time;
begin
case FldRef.Type of
FieldType::Boolean:
HasValue := FldRef.Value();
FieldType::Option:
HasValue := true;
FieldType::Integer:
begin
Int := FldRef.Value();
HasValue := Int <> 0;
end;
FieldType::Decimal:
begin
Dec := FldRef.Value();
HasValue := Dec <> 0;
end;
FieldType::Date:
begin
D := FldRef.Value();
HasValue := D <> 0D;
end;
FieldType::Time:
begin
T := FldRef.Value();
HasValue := T <> 0T;
end;
FieldType::BLOB:
HasValue := false;
else
HasValue := Format(FldRef.Value) <> '';
end;
exit(HasValue);
end;
procedure InitChangeLog()
begin
ChangeLogSetupRead := false;
MonitorSensitiveFieldSetupRead := false;
TempChangeLogSetupField.DeleteAll();
TempChangeLogSetupTable.DeleteAll();
end;
procedure EvaluateTextToFieldRef(InputText: Text; var FieldRef: FieldRef): Boolean
var
DateFormulaVar: DateFormula;
IntVar: Integer;
DecimalVar: Decimal;
DateVar: Date;
TimeVar: Time;
DateTimeVar: DateTime;
BoolVar: Boolean;
DurationVar: Duration;
BigIntVar: BigInteger;
GUIDVar: Guid;
begin
if FieldRef.Class in [FieldClass::FlowField, FieldClass::FlowFilter] then
exit(true);
case FieldRef.Type of
FieldType::Integer, FieldType::Option:
if Evaluate(IntVar, InputText) then begin
FieldRef.Value := IntVar;
exit(true);
end;
FieldType::Decimal:
if Evaluate(DecimalVar, InputText, 9) then begin
FieldRef.Value := DecimalVar;
exit(true);
end;
FieldType::Date:
if Evaluate(DateVar, InputText, 9) then begin
FieldRef.Value := DateVar;
exit(true);
end;
FieldType::Time:
if Evaluate(TimeVar, InputText, 9) then begin
FieldRef.Value := TimeVar;
exit(true);
end;
FieldType::DateTime:
if Evaluate(DateTimeVar, InputText, 9) then begin
FieldRef.Value := DateTimeVar;
exit(true);
end;
FieldType::Boolean:
if Evaluate(BoolVar, InputText, 9) then begin
FieldRef.Value := BoolVar;
exit(true);
end;
FieldType::Duration:
if Evaluate(DurationVar, InputText, 9) then begin
FieldRef.Value := DurationVar;
exit(true);
end;
FieldType::BigInteger:
if Evaluate(BigIntVar, InputText) then begin
FieldRef.Value := BigIntVar;
exit(true);
end;
FieldType::GUID:
if Evaluate(GUIDVar, InputText, 9) then begin
FieldRef.Value := GUIDVar;
exit(true);
end;
FieldType::Code, FieldType::Text:
begin
if StrLen(InputText) > FieldRef.Length then begin
FieldRef.Value := PadStr(InputText, FieldRef.Length);
exit(false);
end;
FieldRef.Value := InputText;
exit(true);
end;
FieldType::DateFormula:
if Evaluate(DateFormulaVar, InputText, 9) then begin
FieldRef.Value := DateFormulaVar;
exit(true);
end;
end;
exit(false);
end;
local procedure AddChangeLogSetupFieldToDimensions(var ChangeLogSetupFieldRec: Record "Change Log Setup (Field)"; var Dimensions: Dictionary of [Text, Text])
begin
Dimensions.Add('Category', ChangelogCategoryLbl);
Dimensions.Add('TableNumber', Format(ChangeLogSetupFieldRec."Table No."));
Dimensions.Add('TableCaption', ChangeLogSetupFieldRec."Table Caption");
Dimensions.Add('FieldNumber', Format(ChangeLogSetupFieldRec."Field No."));
Dimensions.Add('FieldCaption', ChangeLogSetupFieldRec."Field Caption");
Dimensions.Add('LogInsertion', Format(ChangeLogSetupFieldRec."Log Insertion"));
Dimensions.Add('LogModification', Format(ChangeLogSetupFieldRec."Log Modification"));
Dimensions.Add('LogDeletion', Format(ChangeLogSetupFieldRec."Log Deletion"));
end;
[EventSubscriber(ObjectType::Table, Database::"Change Log Setup (Table)", 'OnBeforeInsertEvent', '', false, false)]
local procedure OnBeforeInsertChangeLogSetup(var Rec: Record "Change Log Setup (Table)"; RunTrigger: Boolean)
begin
if Rec."Table No." = Database::"Change Log Entry" then begin
Rec.CalcFields("Table Caption");
Error(CannotSelectTableErr, ChangeLogSetupTable."Table Caption");
end;
end;
[EventSubscriber(ObjectType::Table, Database::"Change Log Setup (Table)", 'OnBeforeRenameEvent', '', false, false)]
local procedure OnBeforeRenameChangeLogSetup(var Rec: Record "Change Log Setup (Table)"; var xRec: Record "Change Log Setup (Table)"; RunTrigger: Boolean)
begin
if Rec."Table No." = Database::"Change Log Entry" then begin
Rec.CalcFields("Table Caption");
Error(CannotSelectTableErr, ChangeLogSetupTable."Table Caption");
end;
end;
[EventSubscriber(ObjectType::Table, Database::"Change Log Setup (Field)", 'OnAfterRenameEvent', '', false, false)]
local procedure OnAfterRenameChangeLogSetupField(var Rec: Record "Change Log Setup (Field)"; var xRec: Record "Change Log Setup (Field)"; RunTrigger: Boolean)
var
Telemetry: Codeunit "Telemetry";
TranslationHelper: Codeunit "Translation Helper";
Dimensions: Dictionary of [Text, Text];
begin
if Rec.IsTemporary then
exit;
TranslationHelper.SetGlobalLanguageToDefault();
AddChangeLogSetupFieldToDimensions(Rec, Dimensions);
Dimensions.Add('LogInsertionOld', Format(xRec."Log Insertion"));
Dimensions.Add('LogModificationOld', Format(xRec."Log Modification"));
Dimensions.Add('LogDeletionOld', Format(xRec."Log Deletion"));
Telemetry.LogMessage('0000LA0', ChangeLogFieldUpdatedTxt, Verbosity::Normal, DataClassification::SystemMetadata, TelemetryScope::All, Dimensions);
TranslationHelper.RestoreGlobalLanguage();
end;
[EventSubscriber(ObjectType::Table, Database::"Change Log Setup (Field)", 'OnAfterModifyEvent', '', false, false)]
local procedure OnAfterModifyChangeLogSetupField(var Rec: Record "Change Log Setup (Field)"; var xRec: Record "Change Log Setup (Field)"; RunTrigger: Boolean)
var
Telemetry: Codeunit "Telemetry";
TranslationHelper: Codeunit "Translation Helper";
Dimensions: Dictionary of [Text, Text];
begin
if Rec.IsTemporary then
exit;
TranslationHelper.SetGlobalLanguageToDefault();
AddChangeLogSetupFieldToDimensions(Rec, Dimensions);
Dimensions.Add('LogInsertionOld', Format(xRec."Log Insertion"));
Dimensions.Add('LogModificationOld', Format(xRec."Log Modification"));
Dimensions.Add('LogDeletionOld', Format(xRec."Log Deletion"));
Telemetry.LogMessage('0000LA1', ChangeLogFieldUpdatedTxt, Verbosity::Normal, DataClassification::SystemMetadata, TelemetryScope::All, Dimensions);
TranslationHelper.RestoreGlobalLanguage();
end;
[EventSubscriber(ObjectType::Table, Database::"Change Log Setup (Field)", 'OnAfterInsertEvent', '', false, false)]
local procedure OnAfterInsertChangeLogSetupField(var Rec: Record "Change Log Setup (Field)")
var
Telemetry: Codeunit "Telemetry";
TranslationHelper: Codeunit "Translation Helper";
Dimensions: Dictionary of [Text, Text];
begin
if Rec.IsTemporary then
exit;
TranslationHelper.SetGlobalLanguageToDefault();
AddChangeLogSetupFieldToDimensions(Rec, Dimensions);
Telemetry.LogMessage('0000LA2', ChangeLogFieldAddedTxt, Verbosity::Normal, DataClassification::SystemMetadata, TelemetryScope::All, Dimensions);
TranslationHelper.RestoreGlobalLanguage();
end;
[EventSubscriber(ObjectType::Table, Database::"Change Log Setup (Field)", 'OnAfterDeleteEvent', '', false, false)]
local procedure OnAfterDeleteChangeLogSetupField(var Rec: Record "Change Log Setup (Field)")
var
Telemetry: Codeunit "Telemetry";
TranslationHelper: Codeunit "Translation Helper";
Dimensions: Dictionary of [Text, Text];
begin
if Rec.IsTemporary then
exit;
TranslationHelper.SetGlobalLanguageToDefault();
AddChangeLogSetupFieldToDimensions(Rec, Dimensions);
Telemetry.LogMessage('0000LA3', ChangeLogFieldDeletedTxt, Verbosity::Normal, DataClassification::SystemMetadata, TelemetryScope::All, Dimensions);
TranslationHelper.RestoreGlobalLanguage();
end;
[IntegrationEvent(false, false)]
local procedure OnAfterLogInsertion(var RecRef: RecordRef)
begin
end;
[IntegrationEvent(false, false)]
local procedure OnAfterLogModification(var RecRef: RecordRef)
begin
end;
[IntegrationEvent(false, false)]
local procedure OnAfterLogDeletion(var RecRef: RecordRef)
begin
end;
[IntegrationEvent(false, false)]
local procedure OnInsertLogEntryOnBeforeChangeLogEntryValidateChangedRecordSystemId(var ChangeLogEntry: Record "Change Log Entry"; RecRef: RecordRef; FldRef: FieldRef)
begin
end;
[IntegrationEvent(false, false)]
local procedure OnBeforeLogDeletion(var RecRef: RecordRef)
begin
end;
[IntegrationEvent(false, false)]
local procedure OnBeforeLogInsertion(var RecRef: RecordRef)
begin
end;
[IntegrationEvent(false, false)]
local procedure OnBeforeLogModification(var RecRef: RecordRef)
begin
end;
[IntegrationEvent(false, false)]
local procedure OnBeforeLogRename(var RecRef: RecordRef; var xRecRefParam: RecordRef)
begin
end;
[IntegrationEvent(false, false)]
local procedure OnAfterIsAlwaysLoggedTable(TableID: Integer; var AlwaysLogTable: Boolean)
begin
end;
[IntegrationEvent(false, false)]
local procedure OnLogModificationOnAfterCheckSecurityFiltering(var xRecRef: RecordRef)
begin
end;
[IntegrationEvent(false, false)]
local procedure OnLogModificationOnBeforeCheckSecurityFiltering(var xRecRef: RecordRef)
begin
end;
[IntegrationEvent(false, false)]
local procedure OnLogModificationOnBeforeRecRefLoopStart(var RecRef: RecordRef; var xRecRef: RecordRef)
begin
end;
[IntegrationEvent(false, false)]
local procedure OnInsertLogEntryOnBeforeInitChangeLogEntry(var ChangeLogEntry: Record "Change Log Entry")
begin
end;
}
#pragma warning restore AS0018