Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ codeunit 6385 "Outlook Processing"
FolderConfigured := OutlookSetup."Email Folder Id" <> '';

TempFilters."Load Attachments" := true;
TempFilters."Load Headers" := true;
TempFilters."Max No. of Emails" := GetMaxNoOfEmails();
// In folder mode, dedup is enforced server-side by the category-exclude filter only.
// Applying "Earliest Email" would drop emails moved into the folder after that floor.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,12 @@ table 3308 "PA Known Sender"
Caption = 'Email';
ToolTip = 'Specifies the email address of a sender whose e-documents have been processed by the Payables Agent.';
}
field(3; "Sender Policy"; Enum "PA Sender Policy")
{
DataClassification = CustomerContent;
Caption = 'Review policy';
ToolTip = 'Specifies how an incoming email from this sender is handled. ''Ask'' requests human review. ''Approve'' processes without review (effective when overall email review is ''Only if untrusted''). ''Reject'' ignores the email.';
}
}
keys
{
Expand All @@ -39,9 +45,23 @@ table 3308 "PA Known Sender"
}
}

trigger OnInsert()
begin
LogSenderAdded();
if Rec."Sender Policy" = Rec."Sender Policy"::Approve then
LogSenderApproved();
end;

trigger OnModify()
begin
if (Rec."Sender Policy" = Rec."Sender Policy"::Approve) and (xRec."Sender Policy" <> Rec."Sender Policy"::Approve) then
LogSenderApproved();
end;

internal procedure InsertIfNew(EDocument: Record "E-Document")
var
Existing: Record "PA Known Sender";
Setup: Record "Payables Agent Setup";
SenderEmail: Text[250];
begin
SenderEmail := CopyStr(EDocument."Source Details", 1, MaxStrLen(SenderEmail));
Expand All @@ -52,7 +72,42 @@ table 3308 "PA Known Sender"
exit;
Rec.Init();
Rec.Email := SenderEmail;
Rec.Insert();
Session.LogSecurityAudit(Rec.TableName(), SecurityOperationResult::Success, 'Added new known sender.', AuditCategory::PolicyManagement);
Setup.GetSetup();
if Setup."Email Review Policy" = "PA Email Review Policy"::OnlyIfUntrusted then
Rec."Sender Policy" := "PA Sender Policy"::Approve
else
Rec."Sender Policy" := "PA Sender Policy"::Ask;
Rec.Insert(true);
end;

/// <summary>
/// Finds the known-sender record matching the e-document's sender, if any.
/// Returns false when the sender is empty or not in the list.
/// </summary>
internal procedure GetForEDocument(EDocument: Record "E-Document"; var KnownSender: Record "PA Known Sender"): Boolean
var
SenderEmail: Text[250];
begin
SenderEmail := CopyStr(EDocument."Source Details", 1, MaxStrLen(KnownSender.Email));
if SenderEmail = '' then
exit(false);
KnownSender.SetRange(Email, SenderEmail);
exit(KnownSender.FindFirst());
end;

// Logs every path that adds a known sender, and separately every path that results in a sender
// marked Approve (which lets its emails be processed without human review).
local procedure LogSenderAdded()
begin
Session.LogSecurityAudit(Rec.TableName(), SecurityOperationResult::Success, StrSubstNo(SenderAddedAuditLbl, Rec.Email), AuditCategory::PolicyManagement);
end;

local procedure LogSenderApproved()
begin
Session.LogSecurityAudit(Rec.TableName(), SecurityOperationResult::Success, StrSubstNo(SenderApprovedAuditLbl, Rec.Email), AuditCategory::PolicyManagement);
end;

var
SenderAddedAuditLbl: Label 'Added Payables Agent known sender %1.', Locked = true;
SenderApprovedAuditLbl: Label 'Payables Agent known sender %1 was set to Approve, allowing its emails to be processed without review.', Locked = true;
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@

namespace Microsoft.Agent.PayablesAgent;

using Microsoft.EServices.EDocumentConnector.Microsoft365;

page 3313 "PA Known Senders"
{
Caption = 'Payables Agent Known Senders', Comment = 'Payables Agent is a term, and should not be translated.';
Expand All @@ -24,7 +26,42 @@ page 3313 "PA Known Senders"
ApplicationArea = All;
ToolTip = 'Specifies the email address of a sender whose e-documents have been processed by the Payables Agent.';
}
field("Sender Policy"; Rec."Sender Policy")
{
ApplicationArea = All;
ToolTip = 'Specifies how an incoming email from this sender is handled. ''Ask'' requests human review. ''Approve'' processes without review (effective when overall email review is ''Only if untrusted''). ''Reject'' ignores the email.';
}
}
}
}

trigger OnOpenPage()
var
SavedSetup: Record "Payables Agent Setup";
OutlookSetup: Record "Outlook Setup";
PayablesAgentSetup: Codeunit "Payables Agent Setup";
Impact: Enum "PA Setup Change Impact";
UnusedNotification: Notification;
SavedFolder: Text;
begin
SavedSetup.GetSetup();
if OutlookSetup.FindFirst() then
SavedFolder := OutlookSetup."Email Folder";

Impact := PayablesAgentSetup.ClassifyKnownSendersUnusedReason(SavedSetup."Email Review Policy", SavedFolder);
case Impact of
Impact::KnownSendersIgnoredByFolder:
UnusedNotification.Message := StrSubstNo(UnusedByFolderLbl, SavedFolder);
Impact::KnownSendersIgnoredByPolicy:
UnusedNotification.Message := StrSubstNo(UnusedByPolicyLbl, PayablesAgentSetup.PolicyLabel(SavedSetup."Email Review Policy"));
else
exit;
end;
UnusedNotification.Scope := NotificationScope::LocalScope;
UnusedNotification.Send();
end;

var
UnusedByFolderLbl: Label 'This list is currently unused. Emails arrive through subfolder ''%1'' and are processed without consulting it.', Comment = '%1 = folder name';
Comment thread
mynjj marked this conversation as resolved.
UnusedByPolicyLbl: Label 'This list doesn''t affect processing while review policy is set to ''%1''.', Comment = '%1 = review policy';
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// ------------------------------------------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.
// ------------------------------------------------------------------------------------------------

namespace Microsoft.Agent.PayablesAgent;

enum 3307 "PA Sender Policy"
{
Access = Internal;
Extensible = false;

value(0; Ask)
{
Caption = 'Ask';
}
value(1; Approve)
{
Caption = 'Approve';
}
value(2; Reject)
{
Caption = 'Reject';
}
}
15 changes: 12 additions & 3 deletions src/Apps/W1/PayablesAgent/app/PayablesAgent.Codeunit.al
Original file line number Diff line number Diff line change
Expand Up @@ -176,11 +176,19 @@ codeunit 3303 "Payables Agent" implements IAgentMetadata, IAgentFactory
if Agent.State = Agent.State::Disabled then
exit;

BuildAgentTask(EDocument, Agent);

PayablesAgentSetupRec.GetSetup();
CustomDimensions.Set('Category', PayablesAgentSetup.FeatureName());
CustomDimensions.Set('SystemId', EDocImpSessionTelemetry.CreateSystemIdText(EDocument.SystemId));
CustomDimensions.Set('EmailReviewPolicy', Format(PayablesAgentSetupRec."Email Review Policy", 0, 9));

// A sender explicitly set to Reject is a blocklist: no agent task is created.
if PayablesAgentSetup.IsSenderRejected(EDocument) then begin
Telemetry.LogMessage('0000QJ2', 'Payables Agent Task Skipped: sender rejected', Verbosity::Normal, DataClassification::SystemMetadata, TelemetryScope::All, CustomDimensions);
exit;
end;

BuildAgentTask(EDocument, Agent);

CustomDimensions.Set('ReviewIncomingInvoice', Format(PayablesAgentSetupRec."Review Incoming Invoice", 0, 9));
Telemetry.LogMessage('0000PJA', 'Payables Agent Task Received', Verbosity::Normal, DataClassification::SystemMetadata, TelemetryScope::All, CustomDimensions);
PayablesAgentKPI.InsertKPIEntry("PA KPI Scenario"::"Agent Tasks Received");
Expand All @@ -190,6 +198,7 @@ codeunit 3303 "Payables Agent" implements IAgentMetadata, IAgentFactory
var
PayablesAgentSetup: Record "Payables Agent Setup";
PayablesAgent: Codeunit "Payables Agent";
PASetup: Codeunit "Payables Agent Setup";
AgentTaskBuilder: Codeunit "Agent Task Builder";
AgentTaskMessageBuilder: Codeunit "Agent Task Message Builder";
PATrial: Codeunit "PA Trial";
Expand All @@ -203,7 +212,7 @@ codeunit 3303 "Payables Agent" implements IAgentMetadata, IAgentFactory
TrialModeTok: Label 'Agent Task created in trial mode. Skipping billing for invoice.', Locked = true;
begin
PayablesAgentSetup.GetSetup();
MustRequestReviewOfMessage := PayablesAgentSetup."Review Incoming Invoice";
MustRequestReviewOfMessage := PASetup.ShouldRequestReview(EDocument);
Message := StrSubstNo(MessageLbl, EDocument."Entry No");
AgentTaskTitle := CopyStr(StrSubstNo(TaskTitleLbl, LowerCase(EDocument."Source Details")), 1, MaxStrLen(AgentTaskTitle));

Expand Down
26 changes: 26 additions & 0 deletions src/Apps/W1/PayablesAgent/app/PayablesAgentUpgrade.Codeunit.al
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ codeunit 3305 "Payables Agent Upgrade"
begin
AlwaysUpdateAgentInformationOnUpgrade();
UpdatePayablesAgentSetupToUseUserSecurityId();
ReviewIncomingInvoiceToEmailReviewPolicy();
end;

trigger OnUpgradePerDatabase()
Expand Down Expand Up @@ -107,6 +108,25 @@ codeunit 3305 "Payables Agent Upgrade"
end;
end;

local procedure ReviewIncomingInvoiceToEmailReviewPolicy()
var
PayablesAgentSetup: Record "Payables Agent Setup";
begin
if UpgradeTag.HasUpgradeTag(GetMapEmailReviewPolicyTag()) then
exit;

if PayablesAgentSetup.FindFirst() then
if PayablesAgentSetup."Email Review Policy" = "PA Email Review Policy"::Unset then begin
if PayablesAgentSetup."Review Incoming Invoice" then
PayablesAgentSetup."Email Review Policy" := "PA Email Review Policy"::Always
else
PayablesAgentSetup."Email Review Policy" := "PA Email Review Policy"::OnlyIfUntrusted;
PayablesAgentSetup.Modify();
end;

UpgradeTag.SetUpgradeTag(GetMapEmailReviewPolicyTag());
end;

local procedure GetRegisterPayablesAgentCapabilityTag(): Code[250]
begin
exit('MS-575373-PayablesAgentCapability-20251021');
Expand All @@ -127,6 +147,11 @@ codeunit 3305 "Payables Agent Upgrade"
exit('MS-631300-MarkTrialEndedIfPayablesAgentExists-20260417');
end;

local procedure GetMapEmailReviewPolicyTag(): Code[250]
begin
exit('MS-625413-MapPayablesAgentEmailReviewPolicy-20260703');
end;

[EventSubscriber(ObjectType::Codeunit, Codeunit::"Upgrade Tag", OnGetPerDatabaseUpgradeTags, '', false, false)]
local procedure RegisterPerDatabaseUpgradeTags(var PerDatabaseUpgradeTags: List of [Code[250]])
begin
Expand All @@ -138,6 +163,7 @@ codeunit 3305 "Payables Agent Upgrade"
local procedure RegisterPerCompanyUpgradeTags(var PerCompanyUpgradeTags: List of [Code[250]])
begin
PerCompanyUpgradeTags.Add(GetUpdatePayablesAgentSetupToUseUserSecurityIdTag());
PerCompanyUpgradeTags.Add(GetMapEmailReviewPolicyTag());
end;

}
29 changes: 29 additions & 0 deletions src/Apps/W1/PayablesAgent/app/Setup/PAEmailReviewPolicy.Enum.al
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// ------------------------------------------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.
// ------------------------------------------------------------------------------------------------

namespace Microsoft.Agent.PayablesAgent;

enum 3305 "PA Email Review Policy"
{
Access = Internal;
Extensible = false;

value(0; Unset)
{
Caption = ' ';
}
value(1; OnlyIfUntrusted)
{
Caption = 'Only untrusted senders (recommended)';
}
value(2; Never)
{
Caption = 'Never';
}
value(3; Always)
{
Caption = 'Always';
}
}
16 changes: 16 additions & 0 deletions src/Apps/W1/PayablesAgent/app/Setup/PASetupChangeImpact.Enum.al
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// ------------------------------------------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.
// ------------------------------------------------------------------------------------------------

namespace Microsoft.Agent.PayablesAgent;

enum 3306 "PA Setup Change Impact"
{
Access = Internal;
Extensible = false;

value(0; None) { }
value(1; KnownSendersIgnoredByFolder) { }
value(2; KnownSendersIgnoredByPolicy) { }
}
Loading
Loading