Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
ca778d8
[E-Document] Agent-driven line matching infrastructure
dayland-ms Mar 31, 2026
fc8f9dc
[E-Document] Agent-driven line matching infrastructure
dayland-ms Mar 31, 2026
ec8c181
Merge remote-tracking branch 'origin/main' into features/607916-payab…
dayland-ms May 18, 2026
8981d5f
Merge remote-tracking branch 'origin/main' into features/607916-payab…
dayland-ms May 18, 2026
a9f2b74
Merge branch 'features/607916-payables-agent-line-matching' of https:…
dayland-ms May 19, 2026
feedf3c
Merge remote-tracking branch 'origin/main' into features/607916-payab…
dayland-ms Jun 1, 2026
a4c5087
feat: add OpenItems action to E-Doc. Purchase Draft Subform
dayland-ms Jun 4, 2026
7ec1340
Remove IPrepareDraftGuard interface pattern; check ECS inline in Prep…
dayland-ms Jun 16, 2026
3db57e6
Merge commit '106174f68f5ca73567e5f39dacc433b921658d48' into features…
dayland-ms Jun 17, 2026
11ef6de
Add missing interface import in PreparePurchaseEDocDraft codeunit
dayland-ms Jun 29, 2026
82041cb
Merge BCApps main (748fdaa4): pick up migrated PayablesAgent app
dayland-ms Jun 30, 2026
97089c9
feat(PA): apply line matching feature changes post-migration
dayland-ms Jun 30, 2026
b540a26
[Payables Agent] Add line matching source page customizations to profile
dayland-ms Jun 30, 2026
92bb0a7
Merge remote-tracking branch 'origin/main' into features/607916-payab…
dayland-ms Jul 1, 2026
c08fd60
Merge remote-tracking branch 'origin/main' into features/607916-payab…
dayland-ms Jul 2, 2026
0ae0ec4
Merge remote-tracking branch 'origin/main' into features/607916-payab…
dayland-ms Jul 9, 2026
56c10f2
feat(PA): gate agent instructions prompt behind PAAgentDrivenLineMatc…
dayland-ms Jul 23, 2026
dab8b09
feat(EDoc): gate agent-driven line matching lookup buttons behind PAA…
dayland-ms Jul 23, 2026
43e7063
Merge remote-tracking branch 'origin/main' into features/607916-payab…
dayland-ms Jul 23, 2026
e012f73
[Payables Agent] Reconcile agent instructions with ECS config on task…
dayland-ms Jul 28, 2026
9509a8b
[Payables Agent] Remove unneeded AS0007 pragma suppression
dayland-ms Aug 10, 2026
01857e9
[Payables Agent] Show Posting Date in agent historical lines view
dayland-ms Aug 10, 2026
7f8b235
[Payables Agent] Address automated AL review findings
dayland-ms Aug 10, 2026
a9ca176
[Payables Agent] Grant permissions and guard historical-line read access
dayland-ms Aug 10, 2026
18e009e
[Payables Agent] Resolve similar descriptions once per historical load
dayland-ms Aug 10, 2026
8ddfb38
[Payables Agent] Historical lines: newest-first sort and committed reads
dayland-ms Aug 10, 2026
ad67c35
Merge remote-tracking branch 'origin/main' into features/607916-payab…
dayland-ms Aug 10, 2026
d5d28e3
[Payables Agent] Address review: header error, telemetry, naming
dayland-ms Aug 10, 2026
3666dc8
[Payables Agent] Scope historical line search to the draft vendor only
dayland-ms Aug 10, 2026
b8114d9
[Payables Agent] Use ExtensionPublisher scope for drift telemetry
dayland-ms Aug 10, 2026
6df0f67
[Payables Agent] Address review batch: filter escaping, guards, promp…
dayland-ms Aug 10, 2026
6185411
[Payables Agent] Add usage/error telemetry to historical-line loader
dayland-ms Aug 11, 2026
f2eb794
[Payables Agent] Avoid redundant re-read in draft subform OnAfterGetR…
dayland-ms Aug 11, 2026
a23a5e9
[Payables Agent] Redact historical-loader telemetry and normalize dim…
dayland-ms Aug 11, 2026
9d42f08
[Payables Agent] Log last-error detail on best-effort instruction rec…
dayland-ms Aug 11, 2026
32d1a92
[Payables Agent] Merge origin/main into line-matching feature
dayland-ms Aug 11, 2026
d996534
Merge remote-tracking branch 'origin/main' into features/607916-payab…
dayland-ms Aug 12, 2026
ff58c59
Merge remote-tracking branch 'origin/main' into features/607916-payab…
dayland-ms Aug 13, 2026
6a5418e
Merge remote-tracking branch 'origin/main' into features/607916-payab…
dayland-ms Aug 13, 2026
ac6ed4e
[Payables Agent] Fix evaluation task startup
dayland-ms Aug 14, 2026
be58e44
Merge latest main into Payables Agent line matching
dayland-ms Aug 14, 2026
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 @@ -103,6 +103,7 @@ permissionset 6100 "E-Doc. Core - Objects"
codeunit "E-Doc. PO Copilot Matching" = X,
#endif
codeunit "E-Doc. Attachment Processor" = X,
codeunit "E-Doc. Hist. Line Data Loader" = X,
codeunit "E-Doc. Message Mgt." = X,
codeunit "Service Participant" = X,
page "E-Doc. Changes Part" = X,
Expand Down Expand Up @@ -134,6 +135,7 @@ permissionset 6100 "E-Doc. Core - Objects"
page "Service Participants" = X,
page "E-Doc. Create Purch Order Line" = X,
page "E-Doc. Purchase Draft Subform" = X,
page "E-Doc. Historical Lines List" = X,
page "E-Doc. Read. Purch. Lines" = X,
page "E-Doc. Readable Purchase Doc." = X,
page "E-Document Purchase Draft" = X,
Expand Down
4 changes: 4 additions & 0 deletions src/Apps/W1/EDocument/App/app.json
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,10 @@
"from": 6234,
"to": 6234
},
{
"from": 6244,
"to": 6249
},
{
"from": 6401,
"to": 6411
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ namespace Microsoft.eServices.EDocument.Processing.Import;
using Microsoft.eServices.EDocument;
using Microsoft.eServices.EDocument.Processing.Interfaces;
using Microsoft.Purchases.Vendor;
using System.Config;

codeunit 6125 "Prepare Purchase E-Doc. Draft" implements IProcessStructuredData
{
Expand All @@ -16,7 +17,12 @@ codeunit 6125 "Prepare Purchase E-Doc. Draft" implements IProcessStructuredData
PrepareDraftHelper: Codeunit "EDoc Prepare Purch. Draft";

procedure PrepareDraft(EDocument: Record "E-Document"; EDocImportParameters: Record "E-Doc. Import Parameters"): Enum "E-Document Type"
var
Comment thread
dayland marked this conversation as resolved.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

$\textbf{🟡\ Medium\ Severity\ —\ Agent}$

The tenant-level experiment key 'PAAgentDrivenLineMatching' and its treatment value 'agent_driven' are declared as separate, independently-maintained Label literals in two different apps: src/Apps/W1/EDocument/App/src/Processing/Import/PrepareDraft/PreparePurchaseEDocDraft.Codeunit.al (AgentDrivenLineMatchingTok/AgentDrivenTreatmentTok) and src/Apps/W1/PayablesAgent/app/Setup/PayablesAgentSetup.Codeunit.al (same token names/values, used both to select the prompt variant and to build the config-hash fingerprint). Both call sites must agree on the exact key and treatment string for the feature to behave consistently (EDocument decides whether to skip its own draft-prep logic based on the same flag PayablesAgent uses to pick the prompt and to detect instruction drift). Because the string is duplicated rather than shared from one owning location, a future rename or value change in one app silently desynchronizes from the other with no compile-time signal, causing PrepareDraft's branch and the agent's active prompt/config-hash to diverge. Recommend hoisting the experiment key (and its treatment value) into a single shared/public constant or procedure that both apps reference, or having EDocument call a published PayablesAgent API for the check instead of re-declaring the literal.

👍 useful · ❤️ especially valuable · 👎 wrong - reply with why · AL review agent v1.33.4

FeatureConfiguration: Codeunit "Feature Configuration";
begin
if FeatureConfiguration.GetConfiguration(AgentDrivenLineMatchingTok) = AgentDrivenTreatmentTok then
Comment thread
dayland marked this conversation as resolved.
exit("E-Document Type"::"Purchase Invoice");

PrepareDraftHelper.PrepareDraft(EDocument, EDocImportParameters);
exit("E-Document Type"::"Purchase Invoice");
end;
Expand All @@ -35,4 +41,8 @@ codeunit 6125 "Prepare Purchase E-Doc. Draft" implements IProcessStructuredData
begin
Vendor := PrepareDraftHelper.GetVendor(EDocument, Customizations);
end;

var
AgentDrivenLineMatchingTok: Label 'PAAgentDrivenLineMatching', Locked = true;
Comment thread
dayland marked this conversation as resolved.
AgentDrivenTreatmentTok: Label 'agent_driven', Locked = true;
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,18 @@
// ------------------------------------------------------------------------------------------------
namespace Microsoft.eServices.EDocument.Processing.Import.Purchase;

using Microsoft.Bank.Reconciliation;
using Microsoft.eServices.EDocument;
using Microsoft.eServices.EDocument.Processing.Import;
using Microsoft.Finance.Deferral;
using Microsoft.Finance.Dimension;
using Microsoft.Finance.GeneralLedger.Account;
using Microsoft.Inventory.Item;
using Microsoft.Inventory.Item.Catalog;
using Microsoft.Purchases.Document;
using Microsoft.Purchases.History;
using Microsoft.Purchases.Setup;
using System.Config;

page 6183 "E-Doc. Purchase Draft Subform"
{
Expand Down Expand Up @@ -322,19 +327,107 @@ page 6183 "E-Doc. Purchase Draft Subform"
Caption = 'Item References';
ToolTip = 'View item references for the vendor associated with this e-document.';
Image = Change;
Scope = Repeater;
Comment thread
dayland marked this conversation as resolved.

trigger OnAction()
var
ItemReference: Record "Item Reference";
ItemReferencePage: Page "Item Reference Entries";
begin
EnsureEDocumentPurchaseHeader();
EDocumentPurchaseHeader.TestField("[BC] Vendor No.");
ItemReference.SetRange("Reference Type", ItemReference."Reference Type"::Vendor);
ItemReference.SetRange("Reference Type No.", EDocumentPurchaseHeader."[BC] Vendor No.");
ItemReferencePage.SetTableView(ItemReference);
ItemReferencePage.Run();
end;
}
action(OpenTextToAccountMappings)
{
ApplicationArea = All;
Caption = 'Text-to-Account Mappings';
ToolTip = 'Opens the Text-to-Account Mapping filtered for the current vendor.';
Image = MapAccounts;
Scope = Repeater;
Visible = AgentDrivenLineMatchingEnabled;

trigger OnAction()
var
TextToAccountMapping: Record "Text-to-Account Mapping";
begin
EnsureEDocumentPurchaseHeader();
EDocumentPurchaseHeader.TestField("[BC] Vendor No.");
TextToAccountMapping.SetFilter("Vendor No.", '%1|%2', '', EDocumentPurchaseHeader."[BC] Vendor No.");
Page.Run(Page::"Text-to-Account Mapping", TextToAccountMapping);
end;
}
action(OpenHistoricalPurchaseLines)
Comment thread
dayland marked this conversation as resolved.
{
ApplicationArea = All;
Caption = 'Historical Purchase Lines';
ToolTip = 'Opens historical purchase invoice lines to help match this draft line based on past invoices.';
Image = History;
Scope = Repeater;
Visible = AgentDrivenLineMatchingEnabled;

trigger OnAction()
var
TempPurchInvLine: Record "Purch. Inv. Line" temporary;
EDocHistLineDataLoader: Codeunit "E-Doc. Hist. Line Data Loader";
EDocHistoricalLinesList: Page "E-Doc. Historical Lines List";
begin
EnsureEDocumentPurchaseHeader();
EDocumentPurchaseHeader.TestField("[BC] Vendor No.");
EDocHistLineDataLoader.LoadHistoricalLines(TempPurchInvLine, EDocumentPurchaseHeader."[BC] Vendor No.", Rec."Product Code", Rec.Description);
EDocHistoricalLinesList.SetRecords(TempPurchInvLine);
EDocHistoricalLinesList.Run();
Comment thread
dayland marked this conversation as resolved.
end;
}
action(OpenChartOfAccounts)
{
ApplicationArea = All;
Caption = 'Chart of Accounts';
ToolTip = 'Opens the Chart of Accounts to look up G/L accounts for this line.';
Image = ChartOfAccounts;
Scope = Repeater;
Visible = AgentDrivenLineMatchingEnabled;

trigger OnAction()
begin
Page.Run(Page::"Chart of Accounts");
end;
}
action(OpenItems)
{
ApplicationArea = All;
Caption = 'Items';
ToolTip = 'Opens the item list to look up items for this line.';
Image = Item;
Scope = Repeater;
Visible = AgentDrivenLineMatchingEnabled;

trigger OnAction()
var
Item: Record Item;
begin
Item.SetRange(Blocked, false);
Page.Run(Page::"Item List", Item);
end;
}
action(OpenDeferralTemplates)
{
ApplicationArea = All;
Caption = 'Deferral Templates';
ToolTip = 'Opens the list of deferral templates for assigning deferrals to this line.';
Image = CalculateCalendar;
Scope = Repeater;
Visible = AgentDrivenLineMatchingEnabled;

trigger OnAction()
begin
Page.Run(Page::"Deferral Template List");
end;
}
}
}
}
Expand All @@ -350,12 +443,17 @@ page 6183 "E-Doc. Purchase Draft Subform"
AdditionalColumns, OrderMatchedCaption, MatchWarningsCaption, MatchWarningsStyleExpr, MatchedEntityName : Text;
LineAmount: Decimal;
DimVisible1, DimVisible2, HasAdditionalColumns, IsEDocumentMatchedToAnyPOLine, IsLineMatchedToOrderLine, IsLineMatchedToReceiptLine, HasEDocumentOrderMatchWarnings, VATProdPostGroupIsVisible : Boolean;
AgentDrivenLineMatchingEnabled: Boolean;
HistoryCantBeRetrievedErr: Label 'The purchase invoice that matched historically with this line can''t be opened.';
EDocumentPurchaseHeaderNotFoundErr: Label 'The purchase header for this e-document could not be found.';
AgentDrivenLineMatchingTok: Label 'PAAgentDrivenLineMatching', Locked = true;
Comment thread
dayland marked this conversation as resolved.
AgentDrivenTreatmentTok: Label 'agent_driven', Locked = true;

trigger OnOpenPage()
begin
SetDimensionsVisibility();
UpdatePOMatching();
SetAgentDrivenLineMatchingVisibility();
end;

trigger OnNewRecord(BelowxRec: Boolean)
Expand All @@ -371,7 +469,8 @@ page 6183 "E-Doc. Purchase Draft Subform"

trigger OnAfterGetRecord()
begin
if EDocumentPurchaseLine.Get(Rec."E-Document Entry No.", Rec."Line No.") then;
// Reuse the row already loaded into Rec instead of re-reading it from the database on every displayed line.
EDocumentPurchaseLine := Rec;
AdditionalColumns := Rec.AdditionalColumnsDisplayText();
MatchedEntityName := Rec.GetMatchedEntityName();
SetHasAdditionalColumns();
Expand All @@ -394,6 +493,19 @@ page 6183 "E-Doc. Purchase Draft Subform"
EDocumentPurchaseHeader := EDocPurchHeader;
end;

local procedure EnsureEDocumentPurchaseHeader()
Comment thread
dayland marked this conversation as resolved.
begin
if not EDocumentPurchaseHeader.Get(Rec."E-Document Entry No.") then
Error(EDocumentPurchaseHeaderNotFoundErr);
end;

local procedure SetAgentDrivenLineMatchingVisibility()
Comment thread
dayland marked this conversation as resolved.
var
FeatureConfiguration: Codeunit "Feature Configuration";
begin
AgentDrivenLineMatchingEnabled := FeatureConfiguration.GetConfiguration(AgentDrivenLineMatchingTok) = AgentDrivenTreatmentTok;
end;

local procedure SetDimensionsVisibility()
var
DimMgt: Codeunit DimensionManagement;
Expand Down
Loading
Loading