From b180d1a29ae1a0df05929a5f0be68b948e7421a9 Mon Sep 17 00:00:00 2001
From: Stefan Sosic <59221826+StefanSosic@users.noreply.github.com>
Date: Tue, 28 Oct 2025 16:24:34 +0100
Subject: [PATCH] Extensibility Interface for File Scenario
---
.../DefaultFileScenarioImpl.Codeunit.al | 46 +++++++++++++++++++
.../src/Scenario/FileScenario.Codeunit.al | 13 +++++-
.../src/Scenario/FileScenario.Enum.al | 4 +-
.../src/Scenario/FileScenario.Interface.al | 33 +++++++++++++
.../src/Scenario/FileScenarioImpl.Codeunit.al | 26 ++++++++++-
.../src/Scenario/FileScenarioSetup.Page.al | 20 ++++++++
.../src/Scenario/FileScenariosFactBox.Page.al | 24 ++++++++++
7 files changed, 163 insertions(+), 3 deletions(-)
create mode 100644 src/System Application/App/External File Storage/src/Scenario/DefaultFileScenarioImpl.Codeunit.al
create mode 100644 src/System Application/App/External File Storage/src/Scenario/FileScenario.Interface.al
diff --git a/src/System Application/App/External File Storage/src/Scenario/DefaultFileScenarioImpl.Codeunit.al b/src/System Application/App/External File Storage/src/Scenario/DefaultFileScenarioImpl.Codeunit.al
new file mode 100644
index 0000000000..fb6033ae74
--- /dev/null
+++ b/src/System Application/App/External File Storage/src/Scenario/DefaultFileScenarioImpl.Codeunit.al
@@ -0,0 +1,46 @@
+// ------------------------------------------------------------------------------------------------
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License. See License.txt in the project root for license information.
+// ------------------------------------------------------------------------------------------------
+
+namespace System.ExternalFileStorage;
+
+codeunit 9459 "Default File Scenario Impl." implements "File Scenario"
+{
+ Access = Internal;
+ InherentPermissions = X;
+ InherentEntitlements = X;
+
+ ///
+ /// Called before adding or modifying a file scenario.
+ ///
+ /// The ID of the file scenario.
+ /// The file storage connector.
+ /// True if the operation is allowed, otherwise false.
+ procedure BeforeAddOrModifyFileScenarioCheck(Scenario: Enum "File Scenario"; Connector: Enum System.ExternalFileStorage."Ext. File Storage Connector") SkipInsertOrModify: Boolean
+ begin
+ SkipInsertOrModify := false;
+ end;
+
+ ///
+ /// Called to get additional setup for a file scenario.
+ ///
+ /// The ID of the file scenario.
+ /// The file storage connector.
+ /// True if additional setup is available, otherwise false.
+ procedure GetAdditionalScenarioSetup(Scenario: Enum "File Scenario"; Connector: Enum System.ExternalFileStorage."Ext. File Storage Connector") SetupExist: Boolean
+ begin
+ SetupExist := false;
+ end;
+
+ ///
+ /// Called before deleting a file scenario.
+ ///
+ /// The ID of the file scenario.
+ /// The file storage connector.
+ /// True if the delete operation is handled and should not proceed, otherwise false.
+ procedure BeforeDeleteFileScenarioCheck(Scenario: Enum "File Scenario"; Connector: Enum System.ExternalFileStorage."Ext. File Storage Connector") SkipDelete: Boolean
+ begin
+ SkipDelete := false;
+ end;
+}
\ No newline at end of file
diff --git a/src/System Application/App/External File Storage/src/Scenario/FileScenario.Codeunit.al b/src/System Application/App/External File Storage/src/Scenario/FileScenario.Codeunit.al
index 82200e7283..6a0f3313f1 100644
--- a/src/System Application/App/External File Storage/src/Scenario/FileScenario.Codeunit.al
+++ b/src/System Application/App/External File Storage/src/Scenario/FileScenario.Codeunit.al
@@ -17,7 +17,7 @@ codeunit 9452 "File Scenario"
/// True if an account for the default scenario was found; otherwise - false.
procedure GetDefaultFileAccount(var TempFileAccount: Record "File Account" temporary): Boolean
begin
- exit(FileScenarioImpl.GetFileAccount(Enum::"File Scenario"::Default, TempFileAccount));
+ exit(FileScenarioImpl.GetFileAccountOrDefault(Enum::"File Scenario"::Default, TempFileAccount));
end;
///
@@ -32,6 +32,17 @@ codeunit 9452 "File Scenario"
exit(FileScenarioImpl.GetFileAccount(Scenario, TempFileAccount));
end;
+ ///
+ /// Gets the file account used by the given file scenario or the default file account if no specific account is assigned to the scenario.
+ ///
+ /// The scenario to look for.
+ /// Out parameter holding information about the file account.
+ /// True if an account for the specified scenario was found; otherwise - false.
+ procedure GetFileAccountOrDefault(Scenario: Enum "File Scenario"; var TempFileAccount: Record "File Account" temporary): Boolean
+ begin
+ exit(FileScenarioImpl.GetFileAccountOrDefault(Scenario, TempFileAccount));
+ end;
+
///
/// Sets a default file account.
///
diff --git a/src/System Application/App/External File Storage/src/Scenario/FileScenario.Enum.al b/src/System Application/App/External File Storage/src/Scenario/FileScenario.Enum.al
index 381e03b4ad..80266851dd 100644
--- a/src/System Application/App/External File Storage/src/Scenario/FileScenario.Enum.al
+++ b/src/System Application/App/External File Storage/src/Scenario/FileScenario.Enum.al
@@ -9,9 +9,10 @@ namespace System.ExternalFileStorage;
/// File scenarios.
/// Used to decouple file accounts from sending files.
///
-enum 9451 "File Scenario"
+enum 9451 "File Scenario" implements "File Scenario"
{
Extensible = true;
+ DefaultImplementation = "File Scenario" = "Default File Scenario Impl.";
///
/// The default file scenario.
@@ -20,5 +21,6 @@ enum 9451 "File Scenario"
value(0; Default)
{
Caption = 'Default';
+ Implementation = "File Scenario" = "Default File Scenario Impl.";
}
}
\ No newline at end of file
diff --git a/src/System Application/App/External File Storage/src/Scenario/FileScenario.Interface.al b/src/System Application/App/External File Storage/src/Scenario/FileScenario.Interface.al
new file mode 100644
index 0000000000..a953279b62
--- /dev/null
+++ b/src/System Application/App/External File Storage/src/Scenario/FileScenario.Interface.al
@@ -0,0 +1,33 @@
+// ------------------------------------------------------------------------------------------------
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License. See License.txt in the project root for license information.
+// ------------------------------------------------------------------------------------------------
+
+namespace System.ExternalFileStorage;
+
+interface "File Scenario"
+{
+ ///
+ /// Called before adding or modifying a file scenario.
+ ///
+ /// The ID of the file scenario.
+ /// The file storage connector.
+ /// True if the operation is allowed; otherwise false.
+ procedure BeforeAddOrModifyFileScenarioCheck(Scenario: Enum "File Scenario"; Connector: Enum System.ExternalFileStorage."Ext. File Storage Connector") SkipInsertOrModify: Boolean;
+
+ ///
+ /// Called to get additional setup for a file scenario.
+ ///
+ /// The ID of the file scenario.
+ /// The file storage connector.
+ /// True if additional setup is available, otherwise false.
+ procedure GetAdditionalScenarioSetup(Scenario: Enum "File Scenario"; Connector: Enum System.ExternalFileStorage."Ext. File Storage Connector") SetupExist: Boolean;
+
+ ///
+ /// Called before deleting a file scenario.
+ ///
+ /// The ID of the file scenario.
+ /// The file storage connector.
+ /// True if the delete operation is handled and should not proceed; otherwise false.
+ procedure BeforeDeleteFileScenarioCheck(Scenario: Enum "File Scenario"; Connector: Enum System.ExternalFileStorage."Ext. File Storage Connector") SkipDelete: Boolean;
+}
\ No newline at end of file
diff --git a/src/System Application/App/External File Storage/src/Scenario/FileScenarioImpl.Codeunit.al b/src/System Application/App/External File Storage/src/Scenario/FileScenarioImpl.Codeunit.al
index a4903091fb..2a03512b32 100644
--- a/src/System Application/App/External File Storage/src/Scenario/FileScenarioImpl.Codeunit.al
+++ b/src/System Application/App/External File Storage/src/Scenario/FileScenarioImpl.Codeunit.al
@@ -28,8 +28,20 @@ codeunit 9453 "File Scenario Impl."
TempFileAccount := TempAllFileAccounts;
exit(true);
end;
+ end;
+
+ procedure GetFileAccountOrDefault(Scenario: Enum "File Scenario"; var TempFileAccount: Record "File Account" temporary): Boolean
+ var
+ TempAllFileAccounts: Record "File Account" temporary;
+ FileScenario: Record "File Scenario";
+ FileAccounts: Codeunit "File Account";
+ begin
+ // Find the account for the provided scenario
+ if GetFileAccount(Scenario, TempFileAccount) then
+ exit(true);
// Fallback to the default account if the scenario isn't mapped or the mapped account doesn't exist
+ FileAccounts.GetAllAccounts(TempAllFileAccounts);
if FileScenario.Get(Enum::"File Scenario"::Default) then
if TempAllFileAccounts.Get(FileScenario."Account Id", FileScenario.Connector) then begin
TempFileAccount := TempAllFileAccounts;
@@ -174,6 +186,8 @@ codeunit 9453 "File Scenario Impl."
TempSelectedFileAccScenarios: Record "File Account Scenario" temporary;
FileScenario: Record "File Scenario";
FileScenariosForAccount: Page "File Scenarios for Account";
+ FileScenarioInterface: Interface "File Scenario";
+ FileScenarioEnum: Enum "File Scenario";
begin
FileAccountImpl.CheckPermissions();
@@ -193,6 +207,11 @@ codeunit 9453 "File Scenario Impl."
exit;
repeat
+ FileScenarioEnum := Enum::"File Scenario".FromInteger(TempSelectedFileAccScenarios.Scenario);
+ FileScenarioInterface := FileScenarioEnum;
+ if FileScenarioInterface.BeforeAddOrModifyFileScenarioCheck(FileScenarioEnum, TempSelectedFileAccScenarios.Connector) then
+ exit;
+
if not FileScenario.Get(TempSelectedFileAccScenarios.Scenario) then begin
FileScenario."Account Id" := TempFileAccountScenario."Account Id";
FileScenario.Connector := TempFileAccountScenario.Connector;
@@ -289,6 +308,8 @@ codeunit 9453 "File Scenario Impl."
procedure DeleteScenario(var TempFileAccountScenario: Record "File Account Scenario" temporary): Boolean
var
FileScenario: Record "File Scenario";
+ FileScenarioInterface: Interface "File Scenario";
+ FileScenarioEnum: Enum "File Scenario";
begin
FileAccountImpl.CheckPermissions();
@@ -301,7 +322,10 @@ codeunit 9453 "File Scenario Impl."
FileScenario.SetRange("Account Id", TempFileAccountScenario."Account Id");
FileScenario.SetRange(Connector, TempFileAccountScenario.Connector);
- FileScenario.DeleteAll();
+ FileScenarioEnum := Enum::"File Scenario".FromInteger(TempFileAccountScenario.Scenario);
+ FileScenarioInterface := FileScenarioEnum;
+ if not FileScenarioInterface.BeforeDeleteFileScenarioCheck(FileScenarioEnum, TempFileAccountScenario.Connector) then
+ FileScenario.DeleteAll();
end;
until TempFileAccountScenario.Next() = 0;
diff --git a/src/System Application/App/External File Storage/src/Scenario/FileScenarioSetup.Page.al b/src/System Application/App/External File Storage/src/Scenario/FileScenarioSetup.Page.al
index 6470b1f0d0..8a3fc7b11c 100644
--- a/src/System Application/App/External File Storage/src/Scenario/FileScenarioSetup.Page.al
+++ b/src/System Application/App/External File Storage/src/Scenario/FileScenarioSetup.Page.al
@@ -80,6 +80,25 @@ page 9452 "File Scenario Setup"
group(Scenario)
{
+ action(ScenarioSetup)
+ {
+ Visible = (TypeOfEntry = TypeOfEntry::Scenario) and CanUserManageFileSetup;
+ Caption = 'Additional Scenario Setup';
+ ToolTip = 'Additional scenario setup for the selected scenario.';
+ Image = Setup;
+ Scope = Repeater;
+ trigger OnAction()
+ var
+ FileScenarioInterface: Interface "File Scenario";
+ FileScenarioEnum: Enum "File Scenario";
+ NoSetupAvailableMsg: Label 'No additional setup is available for this scenario.';
+ begin
+ FileScenarioEnum := Enum::"File Scenario".FromInteger(Rec.Scenario);
+ FileScenarioInterface := FileScenarioEnum;
+ if not FileScenarioInterface.GetAdditionalScenarioSetup(FileScenarioEnum, Rec.Connector) then
+ Message(NoSetupAvailableMsg);
+ end;
+ }
action(ChangeAccount)
{
Visible = (TypeOfEntry = TypeOfEntry::Scenario) and CanUserManageFileSetup;
@@ -123,6 +142,7 @@ page 9452 "File Scenario Setup"
group(Category_Process)
{
actionref(AddScenario_Promoted; AddScenario) { }
+ actionref(ScenarioSetup_Promoted; ScenarioSetup) { }
actionref(ChangeAccount_Promoted; ChangeAccount) { }
actionref(Unassign_Promoted; Unassign) { }
}
diff --git a/src/System Application/App/External File Storage/src/Scenario/FileScenariosFactBox.Page.al b/src/System Application/App/External File Storage/src/Scenario/FileScenariosFactBox.Page.al
index 533492a3a7..c73e46617b 100644
--- a/src/System Application/App/External File Storage/src/Scenario/FileScenariosFactBox.Page.al
+++ b/src/System Application/App/External File Storage/src/Scenario/FileScenariosFactBox.Page.al
@@ -39,4 +39,28 @@ page 9453 "File Scenarios FactBox"
}
}
}
+ actions
+ {
+ area(Processing)
+ {
+ action(ScenarioSetup)
+ {
+ Caption = 'Additional Scenario Setup';
+ ToolTip = 'Additional scenario setup for the selected scenario.';
+ Image = Setup;
+ Scope = Repeater;
+ trigger OnAction()
+ var
+ FileScenarioInterface: Interface "File Scenario";
+ FileScenarioEnum: Enum "File Scenario";
+ NoSetupAvailableMsg: Label 'No additional setup is available for this scenario.';
+ begin
+ FileScenarioEnum := Rec.Scenario;
+ FileScenarioInterface := FileScenarioEnum;
+ if not FileScenarioInterface.GetAdditionalScenarioSetup(Rec.Scenario, Rec.Connector) then
+ Message(NoSetupAvailableMsg);
+ end;
+ }
+ }
+ }
}
\ No newline at end of file