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..8f44f5d008 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,75 @@ 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/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