From c1d0a4241109b03d6242056144e08936f6861c0f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Magnus=20Hartvig=20Gr=C3=B8nbech?= Date: Tue, 20 Jan 2026 10:18:47 +0100 Subject: [PATCH 1/4] introduce line from history --- .../Extensions/EDocPurchInvLine.TableExt.al | 28 ++++ .../PreparePurchaseEDocDraft.Codeunit.al | 78 +++++----- .../Purchase/EDocPurchaseDraftSubform.Page.al | 50 +++++++ .../History/EDocPurchSearchHistory.Page.al | 137 ++++++++++++++++++ 4 files changed, 254 insertions(+), 39 deletions(-) create mode 100644 src/Apps/W1/EDocument/App/src/Extensions/EDocPurchInvLine.TableExt.al create mode 100644 src/Apps/W1/EDocument/App/src/Processing/Import/Purchase/History/EDocPurchSearchHistory.Page.al diff --git a/src/Apps/W1/EDocument/App/src/Extensions/EDocPurchInvLine.TableExt.al b/src/Apps/W1/EDocument/App/src/Extensions/EDocPurchInvLine.TableExt.al new file mode 100644 index 0000000000..6322ce10bf --- /dev/null +++ b/src/Apps/W1/EDocument/App/src/Extensions/EDocPurchInvLine.TableExt.al @@ -0,0 +1,28 @@ +// ------------------------------------------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for license information. +// ------------------------------------------------------------------------------------------------ +namespace Microsoft.Purchases.History; + +tableextension 6130 "E-Doc. Purch. Inv. Line" extends "Purch. Inv. Line" +{ + fields + { + field(6101; "Search Similarity Score"; Decimal) + { + Caption = 'Search Similarity Score'; + Editable = false; + DataClassification = SystemMetadata; + } + + } + + internal procedure GetStyle() Result: Text + begin + if Rec."Search Similarity Score" < 0.5 then + exit('Unfavorable'); + + exit('None'); + end; + +} diff --git a/src/Apps/W1/EDocument/App/src/Processing/Import/PrepareDraft/PreparePurchaseEDocDraft.Codeunit.al b/src/Apps/W1/EDocument/App/src/Processing/Import/PrepareDraft/PreparePurchaseEDocDraft.Codeunit.al index 7997ca6d44..96defac7d4 100644 --- a/src/Apps/W1/EDocument/App/src/Processing/Import/PrepareDraft/PreparePurchaseEDocDraft.Codeunit.al +++ b/src/Apps/W1/EDocument/App/src/Processing/Import/PrepareDraft/PreparePurchaseEDocDraft.Codeunit.al @@ -5,7 +5,7 @@ namespace Microsoft.eServices.EDocument.Processing.Import; using Microsoft.eServices.EDocument; -using Microsoft.eServices.EDocument.Processing.AI; +// using Microsoft.eServices.EDocument.Processing.AI; using Microsoft.eServices.EDocument.Processing.Import.Purchase; using Microsoft.eServices.EDocument.Processing.Interfaces; using Microsoft.Foundation.UOM; @@ -74,7 +74,7 @@ codeunit 6125 "Prepare Purchase E-Doc. Draft" implements IProcessStructuredData until EDocumentPurchaseLine.Next() = 0; // Apply all Copilot-powered matching techniques to the lines - CopilotLineMatching(EDocument."Entry No"); + // CopilotLineMatching(EDocument."Entry No"); end; // Log telemetry and activity sessions @@ -112,43 +112,43 @@ codeunit 6125 "Prepare Purchase E-Doc. Draft" implements IProcessStructuredData ActivityLog.Log(); end; - local procedure CopilotLineMatching(EDocumentEntryNo: Integer) - var - EDocumentPurchaseLine: Record "E-Document Purchase Line"; - begin - EDocumentPurchaseLine.SetLoadFields("E-Document Entry No.", "[BC] Purchase Type No.", "[BC] Deferral Code"); - EDocumentPurchaseLine.ReadIsolation(IsolationLevel::ReadCommitted); - - // Step 1: Apply historical pattern matching - EDocumentPurchaseLine.SetRange("E-Document Entry No.", EDocumentEntryNo); - EDocumentPurchaseLine.SetRange("[BC] Purchase Type No.", ''); - EDocumentPurchaseLine.SetRange("[BC] Item Reference No.", ''); - - if not EDocumentPurchaseLine.IsEmpty() then begin - Commit(); - Codeunit.Run(Codeunit::"E-Doc. Historical Matching", EDocumentPurchaseLine); - end; - - // Step 2: Apply line-to-account matching for remaining lines with no purchase type - Clear(EDocumentPurchaseLine); - EDocumentPurchaseLine.SetRange("E-Document Entry No.", EDocumentEntryNo); - EDocumentPurchaseLine.SetRange("[BC] Purchase Type No.", ''); - EDocumentPurchaseLine.SetRange("[BC] Item Reference No.", ''); - if not EDocumentPurchaseLine.IsEmpty() then begin - Commit(); - Codeunit.Run(Codeunit::"E-Doc. GL Account Matching", EDocumentPurchaseLine); - end; - - // Step 3: Apply deferral matching for lines with a purchase type but no deferral code - Clear(EDocumentPurchaseLine); - EDocumentPurchaseLine.SetRange("E-Document Entry No.", EDocumentEntryNo); - EDocumentPurchaseLine.SetRange("[BC] Deferral Code", ''); - EDocumentPurchaseLine.SetRange("[BC] Item Reference No.", ''); - if not EDocumentPurchaseLine.IsEmpty() then begin - Commit(); - if Codeunit.Run(Codeunit::"E-Doc. Deferral Matching", EDocumentPurchaseLine) then; - end; - end; + // local procedure CopilotLineMatching(EDocumentEntryNo: Integer) + // var + // EDocumentPurchaseLine: Record "E-Document Purchase Line"; + // begin + // EDocumentPurchaseLine.SetLoadFields("E-Document Entry No.", "[BC] Purchase Type No.", "[BC] Deferral Code"); + // EDocumentPurchaseLine.ReadIsolation(IsolationLevel::ReadCommitted); + + // // Step 1: Apply historical pattern matching + // EDocumentPurchaseLine.SetRange("E-Document Entry No.", EDocumentEntryNo); + // EDocumentPurchaseLine.SetRange("[BC] Purchase Type No.", ''); + // EDocumentPurchaseLine.SetRange("[BC] Item Reference No.", ''); + + // if not EDocumentPurchaseLine.IsEmpty() then begin + // Commit(); + // Codeunit.Run(Codeunit::"E-Doc. Historical Matching", EDocumentPurchaseLine); + // end; + + // // Step 2: Apply line-to-account matching for remaining lines with no purchase type + // Clear(EDocumentPurchaseLine); + // EDocumentPurchaseLine.SetRange("E-Document Entry No.", EDocumentEntryNo); + // EDocumentPurchaseLine.SetRange("[BC] Purchase Type No.", ''); + // EDocumentPurchaseLine.SetRange("[BC] Item Reference No.", ''); + // if not EDocumentPurchaseLine.IsEmpty() then begin + // Commit(); + // Codeunit.Run(Codeunit::"E-Doc. GL Account Matching", EDocumentPurchaseLine); + // end; + + // // Step 3: Apply deferral matching for lines with a purchase type but no deferral code + // Clear(EDocumentPurchaseLine); + // EDocumentPurchaseLine.SetRange("E-Document Entry No.", EDocumentEntryNo); + // EDocumentPurchaseLine.SetRange("[BC] Deferral Code", ''); + // EDocumentPurchaseLine.SetRange("[BC] Item Reference No.", ''); + // if not EDocumentPurchaseLine.IsEmpty() then begin + // Commit(); + // if Codeunit.Run(Codeunit::"E-Doc. Deferral Matching", EDocumentPurchaseLine) then; + // end; + // end; procedure OpenDraftPage(var EDocument: Record "E-Document") var diff --git a/src/Apps/W1/EDocument/App/src/Processing/Import/Purchase/EDocPurchaseDraftSubform.Page.al b/src/Apps/W1/EDocument/App/src/Processing/Import/Purchase/EDocPurchaseDraftSubform.Page.al index 3b770f226a..41f18bc607 100644 --- a/src/Apps/W1/EDocument/App/src/Processing/Import/Purchase/EDocPurchaseDraftSubform.Page.al +++ b/src/Apps/W1/EDocument/App/src/Processing/Import/Purchase/EDocPurchaseDraftSubform.Page.al @@ -5,6 +5,7 @@ namespace Microsoft.eServices.EDocument.Processing.Import.Purchase; using Microsoft.eServices.EDocument; +using Microsoft.eServices.EDocument.Processing.AI; using Microsoft.eServices.EDocument.Processing.Import; using Microsoft.Finance.Dimension; using Microsoft.Purchases.Document; @@ -168,6 +169,55 @@ page 6183 "E-Doc. Purchase Draft Subform" { Caption = '&Line'; Image = Line; + group("Classify") + { + Caption = 'Classify'; + action(ChooseFromHistory) + { + ApplicationArea = All; + Caption = 'Classify line from history'; + ToolTip = 'Choose values from similar lines on previously posted invoices.'; + Image = History; + + trigger OnAction() + var + TempPurchInvLine: Record "Purch. Inv. Line" temporary; + EDocPurchSearchHistory: Page "E-Doc Purch. Search History"; + begin + EDocPurchSearchHistory.SetDescription(Rec.Description); + EDocPurchSearchHistory.LookupMode := true; + if EDocPurchSearchHistory.RunModal() <> Action::LookupOK then + exit; + EDocPurchSearchHistory.GetRecord(TempPurchInvLine); + + if TempPurchInvLine."No." = '' then + exit; + + Rec."[BC] Purchase Type No." := TempPurchInvLine."No."; + Rec."[BC] Purchase Line Type" := TempPurchInvLine.Type; + Rec.Modify(); + CurrPage.Update(); + end; + } + action(SuggestGLAccount) + { + ApplicationArea = All; + Caption = 'Suggest G/L accounts'; + ToolTip = 'Suggests a G/L account based on the line description.'; + Image = SuggestLines; + + trigger OnAction() + begin + EDocumentPurchaseLine.SetRange("E-Document Entry No.", Rec."E-Document Entry No."); + EDocumentPurchaseLine.SetRange("[BC] Purchase Type No.", ''); + EDocumentPurchaseLine.SetRange("[BC] Item Reference No.", ''); + if not EDocumentPurchaseLine.IsEmpty() then + Codeunit.Run(Codeunit::"E-Doc. GL Account Matching", EDocumentPurchaseLine); + + CurrPage.Update(); + end; + } + } group("Order Matching") { Caption = 'Order matching'; diff --git a/src/Apps/W1/EDocument/App/src/Processing/Import/Purchase/History/EDocPurchSearchHistory.Page.al b/src/Apps/W1/EDocument/App/src/Processing/Import/Purchase/History/EDocPurchSearchHistory.Page.al new file mode 100644 index 0000000000..fa7e3988d3 --- /dev/null +++ b/src/Apps/W1/EDocument/App/src/Processing/Import/Purchase/History/EDocPurchSearchHistory.Page.al @@ -0,0 +1,137 @@ +page 6157 "E-Doc Purch. Search History" +{ + PageType = List; + ApplicationArea = All; + SourceTableTemporary = true; + SourceTable = "Purch. Inv. Line"; + SourceTableView = sorting("Search Similarity Score") order(descending); + Editable = false; + Extensible = false; + InsertAllowed = false; + DeleteAllowed = false; + + layout + { + area(Content) + { + group(SearchFields) + { + ShowCaption = false; + field(DescriptionText; DescriptionText) + { + ApplicationArea = All; + Caption = 'Description'; + ToolTip = 'Specifies the description of the e-document purchase line history record.'; + Editable = true; + + trigger OnValidate() + begin + SearchAndFillPart(DescriptionText); + end; + + } + } + repeater(Lines) + { + Editable = false; + field("Document No."; Rec."Document No.") + { + ToolTip = 'Specifies the document number of the purchase invoice line.'; + } + field(Type; Rec.Type) + { + ToolTip = 'Specifies the type of the purchase invoice line.'; + } + field("No."; Rec."No.") + { + ToolTip = 'Specifies the number of the purchase invoice line.'; + } + field(Description; Rec.Description) + { + ToolTip = 'Specifies the description of the purchase invoice line.'; + } + field(Quantity; Rec.Quantity) + { + ToolTip = 'Specifies the quantity of the purchase invoice line.'; + } + field("Unit of Measure"; Rec."Unit of Measure") + { + ToolTip = 'Specifies the unit of measure of the purchase invoice line.'; + } + field("Direct Unit Cost"; Rec."Direct Unit Cost") + { + ToolTip = 'Specifies the direct unit cost of the purchase invoice line.'; + } + field(Amount; Rec.Amount) + { + ToolTip = 'Specifies the amount of the purchase invoice line.'; + } + field("Search Similarity Score"; Rec."Search Similarity Score") + { + ToolTip = 'Specifies the similarity score of the e-document purchase line search result.'; + StyleExpr = StyleTxt; + } + } + } + } + + var + DescriptionText: Text; + StyleTxt: Text; + + trigger OnAfterGetRecord() + begin + StyleTxt := Rec.GetStyle(); + end; + + trigger OnOpenPage() + begin + if DescriptionText <> '' then + SearchAndFillPart(DescriptionText); + end; + + internal procedure SetDescription(Text: Text) + begin + DescriptionText := Text; + end; + + local procedure SearchAndFillPart(DescriptionText: Text) + var + TempPurchInvLine: Record "Purch. Inv. Line" temporary; + PurchInvLine: Record "Purch. Inv. Line"; + TempResultTable: Record "Data Similarity Result" temporary; + SemanticDataSearch: Codeunit "Semantic Data Search"; + RecordRef: RecordRef; + begin + RecordRef.GetTable(PurchInvLine); + SemanticDataSearch.SetSearchTarget(RecordRef); + if not SemanticDataSearch.FindSimilar(DescriptionText, TempResultTable) then + exit; + + TempPurchInvLine.DeleteAll(); + if TempResultTable.FindSet() then + repeat + PurchInvLine.GetBySystemId(TempResultTable."System ID"); + TempPurchInvLine := PurchInvLine; + TempPurchInvLine."Search Similarity Score" := TempResultTable.Similarity; + Rec := TempPurchInvLine; + if Rec.Insert() then; + until TempResultTable.Next() = 0; + + // SetLines(TempPurchInvLine); + end; + + // local procedure SetLines(var PurchInvLine: Record "Purch. Inv. Line") + // begin + // Rec.DeleteAll(); + // if PurchInvLine.FindSet() then + // repeat + // Rec := PurchInvLine; + // if Rec.Insert() then; + // until PurchInvLine.Next() = 0; + // if Rec.FindSet() then; + // end; + + + +} \ No newline at end of file From 077a45fcb70b60129cc7cc8862c78cf4751d91ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Magnus=20Hartvig=20Gr=C3=B8nbech?= Date: Wed, 21 Jan 2026 09:27:16 +0100 Subject: [PATCH 2/4] Build fix --- .../App/src/Extensions/EDocPurchInvLine.TableExt.al | 7 +++++++ .../Import/Purchase/History/EDocPurchSearchHistory.Page.al | 6 +++--- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/Apps/W1/EDocument/App/src/Extensions/EDocPurchInvLine.TableExt.al b/src/Apps/W1/EDocument/App/src/Extensions/EDocPurchInvLine.TableExt.al index 6322ce10bf..1db1b2a35d 100644 --- a/src/Apps/W1/EDocument/App/src/Extensions/EDocPurchInvLine.TableExt.al +++ b/src/Apps/W1/EDocument/App/src/Extensions/EDocPurchInvLine.TableExt.al @@ -17,6 +17,13 @@ tableextension 6130 "E-Doc. Purch. Inv. Line" extends "Purch. Inv. Line" } + keys + { + key(KeySearch; "Search Similarity Score") + { + } + } + internal procedure GetStyle() Result: Text begin if Rec."Search Similarity Score" < 0.5 then diff --git a/src/Apps/W1/EDocument/App/src/Processing/Import/Purchase/History/EDocPurchSearchHistory.Page.al b/src/Apps/W1/EDocument/App/src/Processing/Import/Purchase/History/EDocPurchSearchHistory.Page.al index fa7e3988d3..376af90128 100644 --- a/src/Apps/W1/EDocument/App/src/Processing/Import/Purchase/History/EDocPurchSearchHistory.Page.al +++ b/src/Apps/W1/EDocument/App/src/Processing/Import/Purchase/History/EDocPurchSearchHistory.Page.al @@ -26,7 +26,7 @@ page 6157 "E-Doc Purch. Search History" trigger OnValidate() begin - SearchAndFillPart(DescriptionText); + SearchAndFillPart(); end; } @@ -87,7 +87,7 @@ page 6157 "E-Doc Purch. Search History" trigger OnOpenPage() begin if DescriptionText <> '' then - SearchAndFillPart(DescriptionText); + SearchAndFillPart(); end; internal procedure SetDescription(Text: Text) @@ -95,7 +95,7 @@ page 6157 "E-Doc Purch. Search History" DescriptionText := Text; end; - local procedure SearchAndFillPart(DescriptionText: Text) + local procedure SearchAndFillPart() var TempPurchInvLine: Record "Purch. Inv. Line" temporary; PurchInvLine: Record "Purch. Inv. Line"; From 970a4e639105c201446b3efbc818ebf838c89f36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Magnus=20Hartvig=20Gr=C3=B8nbech?= Date: Wed, 21 Jan 2026 16:54:47 +0100 Subject: [PATCH 3/4] Small mistakes. --- .../Extensions/EDocPurchInvLine.TableExt.al | 2 ++ .../History/EDocPurchSearchHistory.Page.al | 23 ++++++++----------- 2 files changed, 11 insertions(+), 14 deletions(-) diff --git a/src/Apps/W1/EDocument/App/src/Extensions/EDocPurchInvLine.TableExt.al b/src/Apps/W1/EDocument/App/src/Extensions/EDocPurchInvLine.TableExt.al index 1db1b2a35d..e035b87668 100644 --- a/src/Apps/W1/EDocument/App/src/Extensions/EDocPurchInvLine.TableExt.al +++ b/src/Apps/W1/EDocument/App/src/Extensions/EDocPurchInvLine.TableExt.al @@ -10,6 +10,8 @@ tableextension 6130 "E-Doc. Purch. Inv. Line" extends "Purch. Inv. Line" { field(6101; "Search Similarity Score"; Decimal) { + AutoFormatExpression = ''; + AutoFormatType = 1; Caption = 'Search Similarity Score'; Editable = false; DataClassification = SystemMetadata; diff --git a/src/Apps/W1/EDocument/App/src/Processing/Import/Purchase/History/EDocPurchSearchHistory.Page.al b/src/Apps/W1/EDocument/App/src/Processing/Import/Purchase/History/EDocPurchSearchHistory.Page.al index 376af90128..c9bfd436a4 100644 --- a/src/Apps/W1/EDocument/App/src/Processing/Import/Purchase/History/EDocPurchSearchHistory.Page.al +++ b/src/Apps/W1/EDocument/App/src/Processing/Import/Purchase/History/EDocPurchSearchHistory.Page.al @@ -1,3 +1,12 @@ +// ------------------------------------------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for license information. +// ------------------------------------------------------------------------------------------------ +namespace Microsoft.EServices.EDocument.Processing.Import.Purchase; + +using Microsoft.Purchases.History; +using System.Search; + page 6157 "E-Doc Purch. Search History" { PageType = List; @@ -118,20 +127,6 @@ page 6157 "E-Doc Purch. Search History" if Rec.Insert() then; until TempResultTable.Next() = 0; - // SetLines(TempPurchInvLine); end; - // local procedure SetLines(var PurchInvLine: Record "Purch. Inv. Line") - // begin - // Rec.DeleteAll(); - // if PurchInvLine.FindSet() then - // repeat - // Rec := PurchInvLine; - // if Rec.Insert() then; - // until PurchInvLine.Next() = 0; - // if Rec.FindSet() then; - // end; - - - } \ No newline at end of file From 5567d30c52dfe083e51b1f24b6a93db6983e9d45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Magnus=20Hartvig=20Gr=C3=B8nbech?= Date: Thu, 22 Jan 2026 16:47:33 +0100 Subject: [PATCH 4/4] Fix minor --- .../Import/Purchase/History/EDocPurchSearchHistory.Page.al | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/Apps/W1/EDocument/App/src/Processing/Import/Purchase/History/EDocPurchSearchHistory.Page.al b/src/Apps/W1/EDocument/App/src/Processing/Import/Purchase/History/EDocPurchSearchHistory.Page.al index c9bfd436a4..1b35d4d6ec 100644 --- a/src/Apps/W1/EDocument/App/src/Processing/Import/Purchase/History/EDocPurchSearchHistory.Page.al +++ b/src/Apps/W1/EDocument/App/src/Processing/Import/Purchase/History/EDocPurchSearchHistory.Page.al @@ -59,10 +59,6 @@ page 6157 "E-Doc Purch. Search History" { ToolTip = 'Specifies the description of the purchase invoice line.'; } - field(Quantity; Rec.Quantity) - { - ToolTip = 'Specifies the quantity of the purchase invoice line.'; - } field("Unit of Measure"; Rec."Unit of Measure") { ToolTip = 'Specifies the unit of measure of the purchase invoice line.';