From 171271536f4f5307e46fbaa9552e0c9c11cfe4c5 Mon Sep 17 00:00:00 2001 From: Jesper Schulz-Wedde Date: Thu, 19 Sep 2024 20:10:48 +0200 Subject: [PATCH] Sync module with MAIN and enable feature. --- .../App/NoSeriesCopilot/app.json | 110 +++++------ .../Copilot/NoSeriesCopilotImpl.Codeunit.al | 70 ++++--- .../src/Copilot/NoSeriesExt.PageExt.al | 57 +++--- .../Copilot/NoSeriesGenerationDetail.Table.al | 26 ++- .../src/Copilot/NoSeriesGenerationSub.Page.al | 35 ++++ .../Tools/NoSeriesCopAddIntent.Codeunit.al | 42 +++- .../Tools/NoSeriesCopToolsImpl.Codeunit.al | 7 +- .../NoSeriesCopilotInstall.Codeunit.al | 13 +- .../NoSeriesCopilotRegister.Codeunit.al | 11 +- .../Test Library/NoSeriesCopilot/app.json | 91 +++++---- .../Test/NoSeriesCopilot/app.json | 184 +++++++++--------- .../src/NoSeriesCopilotHarmsTests.Codeunit.al | 13 +- 12 files changed, 380 insertions(+), 279 deletions(-) diff --git a/src/Business Foundation/App/NoSeriesCopilot/app.json b/src/Business Foundation/App/NoSeriesCopilot/app.json index 9801337dea..135a52047c 100644 --- a/src/Business Foundation/App/NoSeriesCopilot/app.json +++ b/src/Business Foundation/App/NoSeriesCopilot/app.json @@ -1,57 +1,55 @@ { - "id": "7efce506-def2-4195-9d1e-bc538e729242", - "name": "No. Series Suggestions", - "publisher": "Microsoft", - "brief": "", - "description": "", - "version": "25.0.0.0", - "privacyStatement": "https://go.microsoft.com/fwlink/?linkid=724009", - "EULA": "https://go.microsoft.com/fwlink/?linkid=2009120", - "help": "https://go.microsoft.com/fwlink/?linkid=2103698", - "url": "https://go.microsoft.com/fwlink/?linkid=724011", - "logo": "", - "dependencies": [ - { - "id": "63ca2fa4-4f03-4f2b-a480-172fef340d3f", - "name": "System Application", - "publisher": "Microsoft", - "version": "25.0.0.0" - }, - { - "id": "d098b816-22fd-477f-9602-9122f5465527", - "name": "No. Series", - "publisher": "Microsoft", - "version": "25.0.0.0" - } - ], - "internalsVisibleTo": [ - { - "id": "ecb647bf-6fae-45b9-b136-28aa313f5e97", - "name": "No. Series Suggestions Test Library", - "publisher": "Microsoft" - } - ], - "screenshots": [ - - ], - "platform": "25.0.0.0", - "target": "OnPrem", - "idRanges": [ - { - "from": 1, - "to": 9999 - } - ], - "features": [ - "TranslationFile", - "GenerateCaptions", - "NoImplicitWith", - "NoPromotedActionProperties" - ], - "resourceExposurePolicy": { - "allowDebugging": true, - "allowDownloadingSource": true, - "includeSourceInSymbolFile": true - }, - "contextSensitiveHelpUrl": "https://learn.microsoft.com/dynamics365/business-central/" -} \ No newline at end of file + "id": "7efce506-def2-4195-9d1e-bc538e729242", + "name": "No. Series Suggestions", + "publisher": "Microsoft", + "brief": "", + "description": "", + "version": "25.0.0.0", + "privacyStatement": "https://go.microsoft.com/fwlink/?linkid=724009", + "EULA": "https://go.microsoft.com/fwlink/?linkid=2009120", + "help": "https://go.microsoft.com/fwlink/?linkid=2103698", + "url": "https://go.microsoft.com/fwlink/?linkid=724011", + "logo": "", + "dependencies": [ + { + "id": "63ca2fa4-4f03-4f2b-a480-172fef340d3f", + "name": "System Application", + "publisher": "Microsoft", + "version": "25.0.0.0" + }, + { + "id": "d098b816-22fd-477f-9602-9122f5465527", + "name": "No. Series", + "publisher": "Microsoft", + "version": "25.0.0.0" + } + ], + "internalsVisibleTo": [ + { + "id": "ecb647bf-6fae-45b9-b136-28aa313f5e97", + "name": "No. Series Suggestions Test Library", + "publisher": "Microsoft" + } + ], + "screenshots": [], + "platform": "25.0.0.0", + "target": "OnPrem", + "idRanges": [ + { + "from": 1, + "to": 9999 + } + ], + "features": [ + "TranslationFile", + "GenerateCaptions", + "NoImplicitWith", + "NoPromotedActionProperties" + ], + "resourceExposurePolicy": { + "allowDebugging": true, + "allowDownloadingSource": true, + "includeSourceInSymbolFile": true + }, + "contextSensitiveHelpUrl": "https://learn.microsoft.com/dynamics365/business-central/" +} diff --git a/src/Business Foundation/App/NoSeriesCopilot/src/Copilot/NoSeriesCopilotImpl.Codeunit.al b/src/Business Foundation/App/NoSeriesCopilot/src/Copilot/NoSeriesCopilotImpl.Codeunit.al index ea6491845c..22c284f72e 100644 --- a/src/Business Foundation/App/NoSeriesCopilot/src/Copilot/NoSeriesCopilotImpl.Codeunit.al +++ b/src/Business Foundation/App/NoSeriesCopilot/src/Copilot/NoSeriesCopilotImpl.Codeunit.al @@ -19,6 +19,7 @@ codeunit 324 "No. Series Copilot Impl." var IncorrectCompletionErr: Label 'Incorrect completion. The property %1 is empty', Comment = '%1 = property name'; + EmptyCompletionErr: Label 'Incorrect completion. The completion is empty.'; IncorrectCompletionNumberOfGeneratedNoSeriesErr: Label 'Incorrect completion. The number of generated number series is incorrect. Expected %1, but got %2', Comment = '%1 = Expected Number, %2 = Actual Number'; TextLengthIsOverMaxLimitErr: Label 'The property %1 exceeds the maximum length of %2', Comment = '%1 = property name, %2 = maximum length'; DateSpecificPlaceholderLbl: Label '{current_date}', Locked = true; @@ -68,6 +69,7 @@ codeunit 324 "No. Series Copilot Impl." procedure ApplyGeneratedNoSeries(var GeneratedNoSeries: Record "No. Series Generation Detail") begin + GeneratedNoSeries.SetRange(Exists, false); if GeneratedNoSeries.FindSet() then repeat InsertNoSeriesWithLines(GeneratedNoSeries); @@ -171,7 +173,7 @@ codeunit 324 "No. Series Copilot Impl." if not AzureOpenAI.IsEnabled(Enum::"Copilot Capability"::"No. Series Copilot") then exit; - AzureOpenAI.SetAuthorization(Enum::"AOAI Model Type"::"Chat Completions", AOAIDeployments.GetGPT4oMiniLatest()); + AzureOpenAI.SetAuthorization(Enum::"AOAI Model Type"::"Chat Completions", AOAIDeployments.GetGPT4oLatest()); AzureOpenAI.SetCopilotCapability(Enum::"Copilot Capability"::"No. Series Copilot"); AOAIChatCompletionParams.SetMaxTokens(MaxOutputTokens()); AOAIChatCompletionParams.SetTemperature(0); @@ -189,13 +191,13 @@ codeunit 324 "No. Series Copilot Impl." CompletionAnswerTxt := AOAIChatMessages.GetLastMessage(); // the model can answer to rephrase the question, if the user input is not clear if AOAIOperationResponse.IsFunctionCall() then - CompletionAnswerTxt := GenerateNoSeriesUsingToolResult(AzureOpenAI, InputText, AOAIOperationResponse); + CompletionAnswerTxt := GenerateNoSeriesUsingToolResult(AzureOpenAI, InputText, AOAIOperationResponse, AddNoSeriesIntent.GetExistingNoSeries()); exit(CompletionAnswerTxt); end; [NonDebuggable] - local procedure GenerateNoSeriesUsingToolResult(var AzureOpenAI: Codeunit "Azure OpenAI"; InputText: Text; var AOAIOperationResponse: Codeunit "AOAI Operation Response"): Text + local procedure GenerateNoSeriesUsingToolResult(var AzureOpenAI: Codeunit "Azure OpenAI"; InputText: Text; var AOAIOperationResponse: Codeunit "AOAI Operation Response"; ExistingNoSeriesArray: Text): Text var AOAIChatCompletionParams: Codeunit "AOAI Chat Completion Params"; AOAIChatMessages: Codeunit "AOAI Chat Messages"; @@ -209,6 +211,9 @@ codeunit 324 "No. Series Copilot Impl." FunctionResponses: List of [Codeunit "AOAI Function Response"]; Progress: Dialog; begin + if ExistingNoSeriesArray <> '' then + FinalResults.Add(ExistingNoSeriesArray); + FunctionResponses := AOAIOperationResponse.GetFunctionResponses(); foreach AOAIFunctionResponse in FunctionResponses do begin @@ -237,7 +242,6 @@ codeunit 324 "No. Series Copilot Impl." Progress.Close(); end; end; - exit(ConcatenateToolResponse(FinalResults)); end; @@ -337,6 +341,7 @@ codeunit 324 "No. Series Copilot Impl." begin ReadGeneratedNumberSeriesJArray(GeneratedNoSeriesArrayText).WriteTo(NoSeriesArrText); Json.InitializeCollection(NoSeriesArrText); + CheckIfArrayIsNotEmpty(Json.GetCollectionCount()); for i := 0 to Json.GetCollectionCount() - 1 do begin Json.GetObjectFromCollectionByIndex(i, NoSeriesObj); @@ -356,6 +361,12 @@ codeunit 324 "No. Series Copilot Impl." end; end; + local procedure CheckIfArrayIsNotEmpty(NumberOfGeneratedNoSeries: Integer) + begin + if NumberOfGeneratedNoSeries = 0 then + Error(EmptyCompletionErr); + end; + local procedure CheckTextPropertyExistAndCheckIfNotEmpty(propertyName: Text; var Json: Codeunit Json) var value: Text; @@ -420,47 +431,32 @@ codeunit 324 "No. Series Copilot Impl." var Json: Codeunit Json; i: Integer; - NoSeriesObj: Text; NoSeriesCodes: List of [Text]; - NoSeriesCode: Text; begin Json.InitializeCollection(NoSeriesArrText); - for i := 0 to Json.GetCollectionCount() - 1 do begin - Json.GetObjectFromCollectionByIndex(i, NoSeriesObj); - Json.InitializeObject(NoSeriesObj); - Json.GetStringPropertyValueByName('seriesCode', NoSeriesCode); - if NoSeriesCodes.Contains(NoSeriesCode) then begin - Json.ReplaceOrAddJPropertyInJObject('seriesCode', GenerateNewSeriesCodeValue(NoSeriesCodes, NoSeriesCode)); - NoSeriesObj := Json.GetObjectAsText(); - Json.ReplaceJObjectInCollection(i, NoSeriesObj); - end; - NoSeriesCodes.Add(NoSeriesCode); - end; + for i := 0 to Json.GetCollectionCount() - 1 do + ProcessNoSeries(i, NoSeriesCodes, Json); NoSeriesArrText := Json.GetCollectionAsText() end; - local procedure GenerateNewSeriesCodeValue(var NoSeriesCodes: List of [Text]; var NoSeriesCode: Text): Text + local procedure ProcessNoSeries(i: Integer; var NoSeriesCodes: List of [Text]; var Json: Codeunit Json) var - NewNoSeriesCode: Text; - begin - repeat - NewNoSeriesCode := CopyStr(NoSeriesCode, 1, 18) + '-' + RandomCharacter(); - until not NoSeriesCodes.Contains(NewNoSeriesCode); - - NoSeriesCode := NewNoSeriesCode; - exit(NewNoSeriesCode); - end; - - local procedure RandomCharacter(): Char + NoSeriesCode: Text; + NoSeriesObj: Text; + IsExists: Boolean; begin - exit(RandIntInRange(33, 126)); // ASCII: ! (33) to ~ (126) - end; + Json.GetObjectFromCollectionByIndex(i, NoSeriesObj); + Json.InitializeObject(NoSeriesObj); + Json.GetBoolPropertyValueFromJObjectByName('exists', IsExists); + Json.GetStringPropertyValueByName('seriesCode', NoSeriesCode); - local procedure RandIntInRange(MinInt: Integer; MaxInt: Integer): Integer - begin - exit(MinInt - 1 + Random(MaxInt - MinInt + 1)); + if NoSeriesCodes.Contains(NoSeriesCode) and (not IsExists) then begin + Json.RemoveJObjectFromCollection(i); + exit; + end; + NoSeriesCodes.Add(NoSeriesCode); end; local procedure InsertGeneratedNoSeries(var GeneratedNoSeries: Record "No. Series Generation Detail"; NoSeriesObj: Text; GenerationNo: Integer) @@ -482,7 +478,9 @@ codeunit 324 "No. Series Copilot Impl." Json.GetValueAndSetToRecFieldNo(RecRef, 'tableId', GeneratedNoSeries.FieldNo("Setup Table No.")); Json.GetValueAndSetToRecFieldNo(RecRef, 'fieldId', GeneratedNoSeries.FieldNo("Setup Field No.")); Json.GetValueAndSetToRecFieldNo(RecRef, 'nextYear', GeneratedNoSeries.FieldNo("Is Next Year")); - RecRef.Insert(true); + Json.GetValueAndSetToRecFieldNo(RecRef, 'exists', GeneratedNoSeries.FieldNo(Exists)); + Json.GetValueAndSetToRecFieldNo(RecRef, 'message', GeneratedNoSeries.FieldNo(Message)); + if RecRef.Insert(true) then; ValidateGeneratedNoSeries(RecRef); end; @@ -528,7 +526,7 @@ codeunit 324 "No. Series Copilot Impl." local procedure MaxModelTokens(): Integer begin - exit(16385); //gpt-4o-mini-latest + exit(16385); //gpt-4o-latest end; procedure IsCopilotVisible(): Boolean diff --git a/src/Business Foundation/App/NoSeriesCopilot/src/Copilot/NoSeriesExt.PageExt.al b/src/Business Foundation/App/NoSeriesCopilot/src/Copilot/NoSeriesExt.PageExt.al index d25e625fbc..18646aabf0 100644 --- a/src/Business Foundation/App/NoSeriesCopilot/src/Copilot/NoSeriesExt.PageExt.al +++ b/src/Business Foundation/App/NoSeriesCopilot/src/Copilot/NoSeriesExt.PageExt.al @@ -7,37 +7,36 @@ namespace Microsoft.Foundation.NoSeries; pageextension 324 "No. Series Ext." extends "No. Series" { - // TODO: Enable when all green lights have been given. - // actions - // { - // addfirst(Prompting) - // { - // action("Generate With Copilot Prompting") - // { - // Caption = 'Generate'; - // ToolTip = 'Generate No. Series using Copilot'; - // Image = Sparkle; - // ApplicationArea = All; - // Visible = CopilotActionsVisible; + actions + { + addfirst(Prompting) + { + action("Generate With Copilot Prompting") + { + Caption = 'Generate'; + ToolTip = 'Generate No. Series using Copilot'; + Image = Sparkle; + ApplicationArea = All; + Visible = CopilotActionsVisible; - // trigger OnAction() - // var - // NoSeriesCopilotImpl: Codeunit "No. Series Copilot Impl."; - // begin - // NoSeriesCopilotImpl.GetNoSeriesSuggestions(); - // end; - // } - // } - // } + trigger OnAction() + var + NoSeriesCopilotImpl: Codeunit "No. Series Copilot Impl."; + begin + NoSeriesCopilotImpl.GetNoSeriesSuggestions(); + end; + } + } + } - // trigger OnOpenPage() - // var - // NumberSeriesCopilotImpl: Codeunit "No. Series Copilot Impl."; - // begin - // CopilotActionsVisible := NumberSeriesCopilotImpl.IsCopilotVisible(); - // end; + trigger OnOpenPage() + var + NumberSeriesCopilotImpl: Codeunit "No. Series Copilot Impl."; + begin + CopilotActionsVisible := NumberSeriesCopilotImpl.IsCopilotVisible(); + end; - // var - // CopilotActionsVisible: Boolean; + var + CopilotActionsVisible: Boolean; } \ No newline at end of file diff --git a/src/Business Foundation/App/NoSeriesCopilot/src/Copilot/NoSeriesGenerationDetail.Table.al b/src/Business Foundation/App/NoSeriesCopilot/src/Copilot/NoSeriesGenerationDetail.Table.al index 59b13d0246..a6c0f25a09 100644 --- a/src/Business Foundation/App/NoSeriesCopilot/src/Copilot/NoSeriesGenerationDetail.Table.al +++ b/src/Business Foundation/App/NoSeriesCopilot/src/Copilot/NoSeriesGenerationDetail.Table.al @@ -5,6 +5,8 @@ namespace Microsoft.Foundation.NoSeries; +using System.Reflection; + table 392 "No. Series Generation Detail" { TableType = Temporary; @@ -76,6 +78,28 @@ table 392 "No. Series Generation Detail" { Caption = 'Starting Date'; } + field(13; "Exists"; Boolean) + { + Caption = 'Exists'; + } + field(14; Message; Text[1024]) + { + Caption = 'Message'; + } + field(20; "Setup Table Name"; Text[80]) + { + Caption = 'Setup Table'; + FieldClass = FlowField; + CalcFormula = lookup("Table Metadata".Caption where(ID = field("Setup Table No."))); + Editable = false; + } + field(21; "Setup Field Name"; Text[250]) + { + Caption = 'Setup Field'; + FieldClass = FlowField; + CalcFormula = lookup(Field."Field Caption" where(TableNo = field("Setup Table No."), "No." = field("Setup Field No."))); + Editable = false; + } } keys @@ -129,4 +153,4 @@ table 392 "No. Series Generation Detail" Rec."Starting Date" := CalcDate('<-CY+1Y>', Today); end; -} \ No newline at end of file +} diff --git a/src/Business Foundation/App/NoSeriesCopilot/src/Copilot/NoSeriesGenerationSub.Page.al b/src/Business Foundation/App/NoSeriesCopilot/src/Copilot/NoSeriesGenerationSub.Page.al index 2359753161..e3280509ff 100644 --- a/src/Business Foundation/App/NoSeriesCopilot/src/Copilot/NoSeriesGenerationSub.Page.al +++ b/src/Business Foundation/App/NoSeriesCopilot/src/Copilot/NoSeriesGenerationSub.Page.al @@ -28,41 +28,76 @@ page 333 "No. Series Generation Sub" { ApplicationArea = All; ToolTip = 'Specifies the value of the Series Code field.'; + Enabled = IsEnabled; } field(Description; Rec.Description) { ApplicationArea = All; ToolTip = 'Specifies the value of the Description field.'; + Enabled = IsEnabled; } field("Starting No."; Rec."Starting No.") { ApplicationArea = All; ToolTip = 'Specifies the value of the Starting No. field.'; + Enabled = IsEnabled; } field("Increment-by No."; Rec."Increment-by No.") { ApplicationArea = All; ToolTip = 'Specifies the value of the Increment-by No. field.'; + Enabled = IsEnabled; } field("Ending No."; Rec."Ending No.") { ApplicationArea = All; ToolTip = 'Specifies the value of the Ending No. field.'; + Enabled = IsEnabled; } field("Warning No."; Rec."Warning No.") { ApplicationArea = All; ToolTip = 'Specifies the value of the Warning No. field.'; + Enabled = IsEnabled; } field("Starting Date"; Rec."Starting Date") { ApplicationArea = All; ToolTip = 'Specifies the value of the Starting Date field.'; + Enabled = IsEnabled; } + field(Message; Rec.Message) + { + ApplicationArea = All; + ToolTip = 'Specifies the value of the Message field.'; + Style = Attention; + Editable = false; + } + field("Setup Table Name"; Rec."Setup Table Name") + { + ApplicationArea = All; + ToolTip = 'Specifies the value of the Setup Table Name field.'; + Enabled = IsEnabled; + } + field("Setup Field Name"; Rec."Setup Field Name") + { + ApplicationArea = All; + ToolTip = 'Specifies the value of the Setup Field Name field.'; + Enabled = IsEnabled; + } + } } } + var + IsEnabled: Boolean; + + trigger OnAfterGetRecord() + begin + IsEnabled := not Rec.Exists; + end; + internal procedure Load(var GeneratedNoSeries: Record "No. Series Generation Detail") begin GeneratedNoSeries.Reset(); diff --git a/src/Business Foundation/App/NoSeriesCopilot/src/Copilot/Tools/NoSeriesCopAddIntent.Codeunit.al b/src/Business Foundation/App/NoSeriesCopilot/src/Copilot/Tools/NoSeriesCopAddIntent.Codeunit.al index d6b3aa66d7..b2377be60d 100644 --- a/src/Business Foundation/App/NoSeriesCopilot/src/Copilot/Tools/NoSeriesCopAddIntent.Codeunit.al +++ b/src/Business Foundation/App/NoSeriesCopilot/src/Copilot/Tools/NoSeriesCopAddIntent.Codeunit.al @@ -20,6 +20,7 @@ codeunit 331 "No. Series Cop. Add Intent" implements "AOAI Function" AzureKeyVault: Codeunit "Azure Key Vault"; Telemetry: Codeunit Telemetry; ToolsImpl: Codeunit "No. Series Cop. Tools Impl."; + ExistingNoSeriesJArr: JsonArray; FunctionNameLbl: Label 'CreateNewNumberSeries', Locked = true; DateSpecificPlaceholderLbl: Label '{current_date}', Locked = true; CustomPatternsPlaceholderLbl: Label '{custom_patterns}', Locked = true; @@ -28,6 +29,7 @@ codeunit 331 "No. Series Cop. Add Intent" implements "AOAI Function" TelemetryTool1PromptRetrievalErr: Label 'Unable to retrieve the prompt for No. Series Copilot Tool 1 from Azure Key Vault.', Locked = true; TelemetryTool1DefinitionRetrievalErr: Label 'Unable to retrieve the definition for No. Series Copilot Tool 1 from Azure Key Vault.', Locked = true; ToolLoadingErr: Label 'Unable to load the No. Series Copilot Tool 1. Please try again later.'; + ExistingNoSeriesMessageLbl: Label 'Number series already configured. If you wish to modify the existing series, please use the `Modify number series` prompt.'; procedure GetName(): Text begin @@ -148,8 +150,10 @@ codeunit 331 "No. Series Cop. Add Intent" implements "AOAI Function" exit; FieldRef := RecRef.Field(Field."No."); - if Format(FieldRef.Value) <> '' then + if Format(FieldRef.Value) <> '' then begin + SaveExistingNoSeries(TempTableMetadata, FieldRef); exit; // No need to generate number series if it already created and configured + end; TempSetupTable := TempTableMetadata; if TempSetupTable.Insert() then; @@ -158,6 +162,42 @@ codeunit 331 "No. Series Cop. Add Intent" implements "AOAI Function" TempNoSeriesField.Insert(); end; + local procedure SaveExistingNoSeries(TempTableMetadata: Record "Table Metadata" temporary; FieldRef: FieldRef) + var + NoSeries: Record "No. Series"; + NoSeriesLine: Record "No. Series Line"; + NoSeriesManagement: Codeunit "No. Series"; + ExistingNoSeriesJObj: JsonObject; + begin + if not NoSeries.Get(Format(FieldRef.Value)) then + exit; + + NoSeriesManagement.GetNoSeriesLine(NoSeriesLine, NoSeries.Code, Today(), false); + + Clear(ExistingNoSeriesJObj); + ExistingNoSeriesJObj.Add('seriesCode', NoSeries.Code); + ExistingNoSeriesJObj.Add('description', NoSeries.Description); + ExistingNoSeriesJObj.Add('startingNo', NoSeriesLine."Starting No."); + ExistingNoSeriesJObj.Add('endingNo', NoSeriesLine."Ending No."); + ExistingNoSeriesJObj.Add('warningNo', NoSeriesLine."Warning No."); + ExistingNoSeriesJObj.Add('incrementByNo', NoSeriesLine."Increment-by No."); + ExistingNoSeriesJObj.Add('tableId', TempTableMetadata.ID); + ExistingNoSeriesJObj.Add('fieldId', FieldRef.Number); + ExistingNoSeriesJObj.Add('nextYear', false); + ExistingNoSeriesJObj.Add('exists', true); + ExistingNoSeriesJObj.Add('message', ExistingNoSeriesMessageLbl); + + ExistingNoSeriesJArr.Add(ExistingNoSeriesJObj); + end; + + procedure GetExistingNoSeries() ExistingNoSeries: Text + begin + if ExistingNoSeriesJArr.Count() = 0 then + exit(''); + + ExistingNoSeriesJArr.WriteTo(ExistingNoSeries); + end; + [NonDebuggable] local procedure GetToolPrompt() Prompt: Text begin diff --git a/src/Business Foundation/App/NoSeriesCopilot/src/Copilot/Tools/NoSeriesCopToolsImpl.Codeunit.al b/src/Business Foundation/App/NoSeriesCopilot/src/Copilot/Tools/NoSeriesCopToolsImpl.Codeunit.al index 4b97e95cef..7fc97a5beb 100644 --- a/src/Business Foundation/App/NoSeriesCopilot/src/Copilot/Tools/NoSeriesCopToolsImpl.Codeunit.al +++ b/src/Business Foundation/App/NoSeriesCopilot/src/Copilot/Tools/NoSeriesCopToolsImpl.Codeunit.al @@ -234,13 +234,18 @@ codeunit 336 "No. Series Cop. Tools Impl." foreach Entity in Entities do begin String1 := RecordMatchMgtCopy.RemoveShortWords(RemoveTextPart(TableMetadata.Caption, ' Setup') + ' ' + RemoveTextParts(Field.FieldName, GetNoSeriesAbbreviations())); String2 := RecordMatchMgtCopy.RemoveShortWords(Entity); - Score := RecordMatchMgtCopy.CalculateStringNearness(String1, String2, 1, 100) / 100; + Score := RecordMatchMgtCopy.CalculateStringNearness(String1, String2, GetMatchLengthThreshold(), 100) / 100; if Score >= RequiredNearness() then exit(true); end; exit(false); end; + local procedure GetMatchLengthThreshold(): Decimal + begin + exit(2); + end; + local procedure RequiredNearness(): Decimal begin exit(0.9) diff --git a/src/Business Foundation/App/NoSeriesCopilot/src/Register/NoSeriesCopilotInstall.Codeunit.al b/src/Business Foundation/App/NoSeriesCopilot/src/Register/NoSeriesCopilotInstall.Codeunit.al index 9d53ce33d5..c082059a2a 100644 --- a/src/Business Foundation/App/NoSeriesCopilot/src/Register/NoSeriesCopilotInstall.Codeunit.al +++ b/src/Business Foundation/App/NoSeriesCopilot/src/Register/NoSeriesCopilotInstall.Codeunit.al @@ -13,11 +13,10 @@ codeunit 290 "No. Series Copilot Install" InherentPermissions = X; InherentEntitlements = X; - // TODO: Implement this trigger when all green lights are given. - // trigger OnInstallAppPerDatabase() - // var - // NoSeriesCopilotRegister: Codeunit "No. Series Copilot Register"; - // begin - // NoSeriesCopilotRegister.RegisterCapability(); - // end; + trigger OnInstallAppPerDatabase() + var + NoSeriesCopilotRegister: Codeunit "No. Series Copilot Register"; + begin + NoSeriesCopilotRegister.RegisterCapability(); + end; } \ No newline at end of file diff --git a/src/Business Foundation/App/NoSeriesCopilot/src/Register/NoSeriesCopilotRegister.Codeunit.al b/src/Business Foundation/App/NoSeriesCopilot/src/Register/NoSeriesCopilotRegister.Codeunit.al index 39aaf3988b..c206500036 100644 --- a/src/Business Foundation/App/NoSeriesCopilot/src/Register/NoSeriesCopilotRegister.Codeunit.al +++ b/src/Business Foundation/App/NoSeriesCopilot/src/Register/NoSeriesCopilotRegister.Codeunit.al @@ -15,12 +15,11 @@ codeunit 327 "No. Series Copilot Register" InherentPermissions = X; InherentEntitlements = X; - // TODO: Implement this trigger when all green lights are given. - // [EventSubscriber(ObjectType::Page, Page::"Copilot AI Capabilities", 'OnRegisterCopilotCapability', '', false, false)] - // local procedure HandleOnRegisterCopilotCapability() - // begin - // RegisterCapability(); - // end; + [EventSubscriber(ObjectType::Page, Page::"Copilot AI Capabilities", 'OnRegisterCopilotCapability', '', false, false)] + local procedure HandleOnRegisterCopilotCapability() + begin + RegisterCapability(); + end; procedure RegisterCapability() var diff --git a/src/Business Foundation/Test Library/NoSeriesCopilot/app.json b/src/Business Foundation/Test Library/NoSeriesCopilot/app.json index eb05344d74..ed0ad2f18d 100644 --- a/src/Business Foundation/Test Library/NoSeriesCopilot/app.json +++ b/src/Business Foundation/Test Library/NoSeriesCopilot/app.json @@ -1,48 +1,47 @@ { - "id": "ecb647bf-6fae-45b9-b136-28aa313f5e97", - "name": "No. Series Suggestions Test Library", - "publisher": "Microsoft", - "brief": "Test library that provide basic test setup for the No. Series Suggestions tests.", - "description": "Contains an expansive set of library methods to be used exclusively in tests.", - "version": "25.0.0.0", - "privacyStatement": "https://go.microsoft.com/fwlink/?linkid=724009", - "EULA": "https://go.microsoft.com/fwlink/?linkid=2009120", - "help": "https://go.microsoft.com/fwlink/?linkid=2131960", - "url": "https://go.microsoft.com/fwlink/?linkid=724011", - "logo": "", - "dependencies": [ - { - "id": "d098b816-22fd-477f-9602-9122f5465527", - "name": "No. Series", - "publisher": "Microsoft", - "version": "25.0.0.0" - }, - { - "id": "7efce506-def2-4195-9d1e-bc538e729242", - "name": "No. Series Suggestions", - "publisher": "Microsoft", - "version": "25.0.0.0" - } - ], - "platform": "25.0.0.0", - "target": "OnPrem", - "idRanges": [ - { - "from": 134520, - "to": 134520 - } - ], - "features": [ - "TranslationFile", - "GenerateCaptions", - "NoImplicitWith", - "NoPromotedActionProperties" - ], - "resourceExposurePolicy": { - "allowDebugging": true, - "allowDownloadingSource": true, - "includeSourceInSymbolFile": true - }, - "contextSensitiveHelpUrl": "https://learn.microsoft.com/dynamics365/business-central/" + "id": "ecb647bf-6fae-45b9-b136-28aa313f5e97", + "name": "No. Series Suggestions Test Library", + "publisher": "Microsoft", + "brief": "Test library that provide basic test setup for the No. Series Suggestions tests.", + "description": "Contains an expansive set of library methods to be used exclusively in tests.", + "version": "25.0.0.0", + "privacyStatement": "https://go.microsoft.com/fwlink/?linkid=724009", + "EULA": "https://go.microsoft.com/fwlink/?linkid=2009120", + "help": "https://go.microsoft.com/fwlink/?linkid=2131960", + "url": "https://go.microsoft.com/fwlink/?linkid=724011", + "logo": "", + "dependencies": [ + { + "id": "d098b816-22fd-477f-9602-9122f5465527", + "name": "No. Series", + "publisher": "Microsoft", + "version": "25.0.0.0" + }, + { + "id": "7efce506-def2-4195-9d1e-bc538e729242", + "name": "No. Series Suggestions", + "publisher": "Microsoft", + "version": "25.0.0.0" + } + ], + "platform": "25.0.0.0", + "target": "OnPrem", + "idRanges": [ + { + "from": 134520, + "to": 134520 + } + ], + "features": [ + "TranslationFile", + "GenerateCaptions", + "NoImplicitWith", + "NoPromotedActionProperties" + ], + "resourceExposurePolicy": { + "allowDebugging": true, + "allowDownloadingSource": true, + "includeSourceInSymbolFile": true + }, + "contextSensitiveHelpUrl": "https://learn.microsoft.com/dynamics365/business-central/" } - \ No newline at end of file diff --git a/src/Business Foundation/Test/NoSeriesCopilot/app.json b/src/Business Foundation/Test/NoSeriesCopilot/app.json index 86658390a6..9faf1dfef4 100644 --- a/src/Business Foundation/Test/NoSeriesCopilot/app.json +++ b/src/Business Foundation/Test/NoSeriesCopilot/app.json @@ -1,95 +1,91 @@ { - "id": "f3909082-515b-46bf-9e9c-6561f7306b17", - "name": "No. Series Suggestions Tests", - "publisher": "Microsoft", - "brief": "Test suite for the No. Series Suggestions module", - "description": "Contains an expansive set tests for the No. Series Suggestions module.", - "version": "25.0.0.0", - "privacyStatement": "https://go.microsoft.com/fwlink/?linkid=724009", - "EULA": "https://go.microsoft.com/fwlink/?linkid=2009120", - "help": "https://go.microsoft.com/fwlink/?linkid=2131960", - "url": "https://go.microsoft.com/fwlink/?linkid=724011", - "logo": "", - "dependencies": [ - { - "id": "d098b816-22fd-477f-9602-9122f5465527", - "name": "No. Series", - "publisher": "Microsoft", - "version": "25.0.0.0" - }, - { - "id": "7efce506-def2-4195-9d1e-bc538e729242", - "name": "No. Series Suggestions", - "publisher": "Microsoft", - "version": "25.0.0.0" - }, - { - "id": "f7277dc2-cc73-4b81-b7c6-4a58bfb33806", - "name": "No. Series Test Library", - "publisher": "Microsoft", - "version": "25.0.0.0" - }, - { - "id": "ecb647bf-6fae-45b9-b136-28aa313f5e97", - "name": "No. Series Suggestions Test Library", - "publisher": "Microsoft", - "version": "25.0.0.0" - }, - { - "id": "dd0be2ea-f733-4d65-bb34-a28f4624fb14", - "name": "Library Assert", - "publisher": "Microsoft", - "version": "25.0.0.0" - }, - { - "id": "e7320ebb-08b3-4406-b1ec-b4927d3e280b", - "name": "Any", - "publisher": "Microsoft", - "version": "25.0.0.0" - }, - { - "id": "2156302a-872f-4568-be0b-60968696f0d5", - "publisher": "Microsoft", - "name": "AI Test Toolkit", - "version": "25.0.0.0" - }, - { - "id": "23de40a6-dfe8-4f80-80db-d70f83ce8caf", - "publisher": "Microsoft", - "name": "Test Runner", - "version": "25.0.0.0" - }, - { - "id": "63ca2fa4-4f03-4f2b-a480-172fef340d3f", - "name": "System Application", - "publisher": "Microsoft", - "version": "25.0.0.0" - } - ], - "internalsVisibleTo": [ - - ], - "screenshots": [ - - ], - "platform": "25.0.0.0", - "target": "OnPrem", - "idRanges": [ - { - "from": 134540, - "to": 134541 - } - ], - "features": [ - "NoImplicitWith", - "NoPromotedActionProperties", - "TranslationFile", - "GenerateCaptions" - ], - "resourceExposurePolicy": { - "allowDebugging": true, - "allowDownloadingSource": true, - "includeSourceInSymbolFile": true - }, - "contextSensitiveHelpUrl": "https://learn.microsoft.com/dynamics365/business-central/" -} \ No newline at end of file + "id": "f3909082-515b-46bf-9e9c-6561f7306b17", + "name": "No. Series Suggestions Tests", + "publisher": "Microsoft", + "brief": "Test suite for the No. Series Suggestions module", + "description": "Contains an expansive set tests for the No. Series Suggestions module.", + "version": "25.0.0.0", + "privacyStatement": "https://go.microsoft.com/fwlink/?linkid=724009", + "EULA": "https://go.microsoft.com/fwlink/?linkid=2009120", + "help": "https://go.microsoft.com/fwlink/?linkid=2131960", + "url": "https://go.microsoft.com/fwlink/?linkid=724011", + "logo": "", + "dependencies": [ + { + "id": "d098b816-22fd-477f-9602-9122f5465527", + "name": "No. Series", + "publisher": "Microsoft", + "version": "25.0.0.0" + }, + { + "id": "7efce506-def2-4195-9d1e-bc538e729242", + "name": "No. Series Suggestions", + "publisher": "Microsoft", + "version": "25.0.0.0" + }, + { + "id": "f7277dc2-cc73-4b81-b7c6-4a58bfb33806", + "name": "No. Series Test Library", + "publisher": "Microsoft", + "version": "25.0.0.0" + }, + { + "id": "ecb647bf-6fae-45b9-b136-28aa313f5e97", + "name": "No. Series Suggestions Test Library", + "publisher": "Microsoft", + "version": "25.0.0.0" + }, + { + "id": "dd0be2ea-f733-4d65-bb34-a28f4624fb14", + "name": "Library Assert", + "publisher": "Microsoft", + "version": "25.0.0.0" + }, + { + "id": "e7320ebb-08b3-4406-b1ec-b4927d3e280b", + "name": "Any", + "publisher": "Microsoft", + "version": "25.0.0.0" + }, + { + "id": "2156302a-872f-4568-be0b-60968696f0d5", + "publisher": "Microsoft", + "name": "AI Test Toolkit", + "version": "25.0.0.0" + }, + { + "id": "23de40a6-dfe8-4f80-80db-d70f83ce8caf", + "publisher": "Microsoft", + "name": "Test Runner", + "version": "25.0.0.0" + }, + { + "id": "63ca2fa4-4f03-4f2b-a480-172fef340d3f", + "name": "System Application", + "publisher": "Microsoft", + "version": "25.0.0.0" + } + ], + "internalsVisibleTo": [], + "screenshots": [], + "platform": "25.0.0.0", + "target": "OnPrem", + "idRanges": [ + { + "from": 134540, + "to": 134541 + } + ], + "features": [ + "NoImplicitWith", + "NoPromotedActionProperties", + "TranslationFile", + "GenerateCaptions" + ], + "resourceExposurePolicy": { + "allowDebugging": true, + "allowDownloadingSource": true, + "includeSourceInSymbolFile": true + }, + "contextSensitiveHelpUrl": "https://learn.microsoft.com/dynamics365/business-central/" +} diff --git a/src/Business Foundation/Test/NoSeriesCopilot/src/NoSeriesCopilotHarmsTests.Codeunit.al b/src/Business Foundation/Test/NoSeriesCopilot/src/NoSeriesCopilotHarmsTests.Codeunit.al index c0ae54dcad..0a8b5ee632 100644 --- a/src/Business Foundation/Test/NoSeriesCopilot/src/NoSeriesCopilotHarmsTests.Codeunit.al +++ b/src/Business Foundation/Test/NoSeriesCopilot/src/NoSeriesCopilotHarmsTests.Codeunit.al @@ -29,8 +29,17 @@ codeunit 134541 "No. Series Copilot Harms Tests" TestInputJson: Codeunit "Test Input Json"; begin TestInputJson := AITTestContext.GetQuestion(); - asserterror NoSeriesCopilotTestLib.Generate(NoSeriesGeneration, NoSeriesGenerationDetail, TestInputJson.ValueAsText()); + if not CallGenerateFunction(NoSeriesGeneration, NoSeriesGenerationDetail, TestInputJson.ValueAsText()) then begin + assert.ExpectedError(InvalidPromptTxt); + exit; + end; Assert.IsTrue(NoSeriesGenerationDetail.IsEmpty(), 'No. Series Generation Detail should be empty, but it is not.'); - assert.ExpectedError(InvalidPromptTxt); + end; + + [TryFunction] + procedure CallGenerateFunction(var NoSeriesGeneration: Record "No. Series Generation"; var NoSeriesGenerationDetail: Record "No. Series Generation Detail"; InputText: Text) + var + begin + NoSeriesCopilotTestLib.Generate(NoSeriesGeneration, NoSeriesGenerationDetail, InputText); end; } \ No newline at end of file