### Create Module Setup Page Source: https://github.com/microsoft/alappextensions/blob/main/Apps/W1/ContosoCoffeeDemoDataset/app/Getting-Started.md Creates a 'Module Setup' card page linked to the 'Module Setup' table. This page allows users to configure module settings, such as the StartDate. ```AL page 5281 "Module Setup" { PageType = Card; Caption = 'Module Setup'; SourceTable = "Module Setup"; Extensible = false; DeleteAllowed = false; InsertAllowed = false; layout { area(Content) { group("Setup Data") { field(StartDate; Rec.StartDate) { } } } } trigger OnOpenPage() begin Rec.InitRecord(); end; } ``` -------------------------------- ### Conditional Validation in Configuration Setup Source: https://github.com/microsoft/alappextensions/blob/main/Apps/W1/ContosoCoffeeDemoDataset/app/Coding-Patterns.md Provides an example of how to perform a validation on a configuration field only if it is currently empty. This prevents overwriting user customizations while ensuring default values are set when no specific value is provided. ```AL if ManufacturingDemoDataSetup."Manufacturing Location" = '' then ManufacturingDemoDataSetup.Validate("Manufacturing Location", CommonLocation.MainLocation()); ``` -------------------------------- ### Creating Initial Setup Data Source: https://github.com/microsoft/alappextensions/blob/main/Apps/W1/ContosoCoffeeDemoDataset/app/Coding-Patterns.md Demonstrates the initialization of a module's setup record. This procedure is called to create default or initial data for the module's configuration when it's first set up. ```AL procedure CreateSetupData() var ManufacturingDemoDataSetup: Record "Manufacturing Module Setup"; begin ManufacturingDemoDataSetup.InitRecord(); ... ``` -------------------------------- ### Define Module Setup Table Source: https://github.com/microsoft/alappextensions/blob/main/Apps/W1/ContosoCoffeeDemoDataset/app/Getting-Started.md Defines a 'Module Setup' table to store configuration data for the module, including a StartDate field. This table is intended for customer content and is company-specific. ```AL table 5282 "Module Setup" { DataClassification = CustomerContent; InherentEntitlements = RMX; InherentPermissions = RMX; Extensible = false; DataPerCompany = true; ReplicateData = false; fields { field(1; "Primary Key"; Integer) { DataClassification = SystemMetadata; Caption = 'Primary Key'; } field(2; StartDate; Date) { Caption = 'Start Date'; ToolTip = 'Specifies the start date for the scenario.'; } } keys { key(Key1; "Primary Key") { Clustered = true; } } [InherentPermissions(PermissionObjectType::TableData, Database::"Module Setup", 'I')] internal procedure InitRecord() begin if Rec.Get() then exit; Rec.Insert(); end; } ``` -------------------------------- ### Handle 'OnInitialize' Event Moved to 'Assisted Setup' Codeunit Source: https://github.com/microsoft/alappextensions/blob/main/BREAKINGCHANGES.md If the 'OnInitialize' event is not found, it has been moved to codeunit 3725 "Assisted Setup", function `OnRegister`. ```al codeunit 3725 "Assisted Setup", function `OnRegister` ``` -------------------------------- ### Resolve 'Assisted Setup' Protection Level Error Source: https://github.com/microsoft/alappextensions/blob/main/BREAKINGCHANGES.md If 'Assisted Setup' or 'Assisted Setup Icon' is inaccessible due to protection level, use the appropriate API methods in codeunit 3725 "Assisted Setup". For status changes, use the `Complete` function instead of the discontinued `SetStatus` function. ```al codeunit 3725 "Assisted Setup" ``` -------------------------------- ### Running Module Configuration Page Source: https://github.com/microsoft/alappextensions/blob/main/Apps/W1/ContosoCoffeeDemoDataset/app/Coding-Patterns.md Shows how to programmatically run a module's setup configuration page. This is typically used within a module's codeunit to allow users to access and modify module-specific settings. ```AL procedure RunConfigurationPage() begin Page.Run(Page::"Manufacturing Module Setup"); end; ``` -------------------------------- ### Subscribe to OnAfterGeneratingDemoData Event Source: https://github.com/microsoft/alappextensions/blob/main/Apps/W1/ContosoCoffeeDemoDataset/app/Coding-Patterns.md This event subscriber allows for populating additional demo data specific to localizations. It uses a case statement to conditionally run module-specific setup logic based on the provided module and level. ```AL [EventSubscriber(ObjectType::Codeunit, Codeunit::"Contoso Demo Tool", 'OnAfterGeneratingDemoData', '', false, false)] local procedure LocalizationContosoDemoData(Module: Enum "Contoso Demo Data Module"; ContosoDemoDataLevel: Enum "Contoso Demo Data Level") begin case Module of Enum::"Contoso Demo Data Module"::Foundation: FoundationModule(ContosoDemoDataLevel); ... end; end; local procedure FoundationModule(ContosoDemoDataLevel: Enum "Contoso Demo Data Level") begin case ContosoDemoDataLevel of Enum::"Contoso Demo Data Level"::"Setup Data": begin Codeunit.Run(Codeunit::"Create Job Queue Category US"); ... end; end; ``` -------------------------------- ### Implement Demo Data Module Interface Source: https://github.com/microsoft/alappextensions/blob/main/Apps/W1/ContosoCoffeeDemoDataset/app/Getting-Started.md Implement the 'Contoso Demo Data Module' interface in a codeunit to define data creation procedures. This includes setting dependencies and defining methods for creating setup, master, and transactional data. ```AL codeunit 50100 "Contoso Shoes Module" implements "Contoso Demo Data Module" { procedure RunConfigurationPage(); begin end; procedure GetDependencies() Dependencies: List of [Enum "Contoso Demo Data Module"] begin Dependencies.Add(Enum::"Contoso Demo Data Module"::"Common Module"); end; procedure CreateSetupData() begin Codeunit.Run(Codeunit::"Create Contoso Shoes Item Category"); Codeunit.Run(Codeunit::"Create Contoso Shoes Unit of Measure"); end; procedure CreateMasterData() begin Codeunit.Run(Codeunit::"Cearte Contoso Shoes Item"); Codeunit.Run(Codeunit::"Create Contoso Shoes Size"); end; procedure CreateTransactionalData(); begin end; procedure CreateHistoricalData(); begin end; } ``` -------------------------------- ### Localization Configuration for Demo Data Setup Source: https://github.com/microsoft/alappextensions/blob/main/Apps/W1/ContosoCoffeeDemoDataset/app/Coding-Patterns.md An event subscriber that modifies the 'Contoso Coffee Demo Data Setup' record before insertion to set localization-specific values, such as Country/Region Code and Company Type. This is used to tailor demo data for different regions. ```AL [EventSubscriber(ObjectType::Table, Database::"Contoso Coffee Demo Data Setup", 'OnBeforeInsertEvent', '', false, false)] local procedure LocalDemoDataSetup(var Rec: Record "Contoso Coffee Demo Data Setup") begin Rec."Country/Region Code" := 'US'; Rec."Company Type" := Rec."Company Type"::"Sales Tax"; end; ``` -------------------------------- ### Replacing TempBlob.WriteAsText with OutStream.WriteText Source: https://github.com/microsoft/alappextensions/blob/main/BREAKINGCHANGES.md When encountering errors related to 'TempBlob.WriteAsText', use the CreateOutStream method to get an OutStream and then use WriteText. ```al TempBlob.CreateOutStream(OutStream[, TextEncoding]); OutStream.WriteText(Text); ``` -------------------------------- ### TryGetCultureName Function Replacement Source: https://github.com/microsoft/alappextensions/blob/main/BREAKINGCHANGES.md This snippet shows the replacement for the removed 'TryGetCultureName' function. It uses DotNet_CultureInfo to get the culture name. ```AL [TryFunction] procedure TryGetCultureName(Culture : Integer; VAR CultureName : Text) var DotNet_CultureInfo: Codeunit DotNet_CultureInfo; begin DotNet_CultureInfo.GetCultureInfoByName(Culture); CultureName := DotNet_CultureInfo.Name(); end; ``` -------------------------------- ### Using the and Tags Source: https://github.com/microsoft/alappextensions/wiki/AL-Code-Documentation Shows how to document raised events using the tag and return values using the tag. The tag is specific to AL. ```AL /// /// My awesome name getter /// /// OnAfterGeMyName /// My name procedure GetMyName() Name: Text begin Name:= MyName; OnAfterGeMytName(Name); end; /// /// Integration event, raised from . /// Subscribe to this event to modify the returned name. /// [IntegrationEvent(false, false)] local procedure OnAfterGetMyName(var Name: Text) begin end; ``` -------------------------------- ### Downloading from URL using HttpClient Source: https://github.com/microsoft/alappextensions/blob/main/BREAKINGCHANGES.md The 'TempBlob.TryDownloadFromUrl' function has been removed. Use HttpClient to fetch the content as an InStream and then copy it to an OutStream. ```al HttClient.Get(url, HttpResponseMessage); HttpResponseMessage.Content.ReadAs(InStream); TempBlob.CreateOutStream(OutStream); CopyStream(OutStream, InStream); ``` -------------------------------- ### Defining Labels with MaxLength and Comments Source: https://github.com/microsoft/alappextensions/blob/main/Apps/W1/ContosoCoffeeDemoDataset/app/Coding-Patterns.md Illustrates how to define labels with a specified maximum length and optional comments to improve translation accuracy and context. This is crucial for ensuring labels fit within UI constraints and are translated correctly. ```AL ShoeSuppliesLbl: Label 'Shoe Supplies', MaxLength = 100; ``` -------------------------------- ### Basic Codeunit Documentation Source: https://github.com/microsoft/alappextensions/wiki/AL-Code-Documentation Demonstrates the use of the tag for documenting a codeunit and its procedures. ```AL /// /// My awesome codeunit /// Codeunit 42 "My awesome codeunit" { /// /// Hello AL Documentation! /// procedure HelloALDocumentation() begin ... end; } ``` -------------------------------- ### Implement TrySetGlobalLanguage Function Source: https://github.com/microsoft/alappextensions/blob/main/BREAKINGCHANGES.md This snippet shows how to implement a local procedure to set the global language, as the original function 'TrySetGlobalLanguage' has been removed. This is useful when you need to manage language settings programmatically. ```al // // TryFunction for setting the global language. // // The id of the language to be set as global [TryFunction] local procedure TrySetGlobalLanguage(LanguageId: Integer) begin GlobalLanguage(LanguageId); end; ``` -------------------------------- ### Replacement for Removed DownloadZip Function Source: https://github.com/microsoft/alappextensions/blob/main/BREAKINGCHANGES.md When the 'DownloadZip' function is removed, use these replacement APIs to achieve similar functionality. ```al DataCompression.SaveZipArchive(TempBlob); TempBlob.CreateInStream(InStream); DownloadFromStream(InStream, '', '', '', OutputFileName); ``` -------------------------------- ### Scope of 'OnResolveAutoFormat' Publisher Source: https://github.com/microsoft/alappextensions/blob/main/BREAKINGCHANGES.md The publisher `OnResolveAutoFormat` has the scope OnPrem, but it can be subscribed to by anyone to implement new logic for formatting decimal numbers in text messages. ```al publisher OnResolveAutoFormat(): Codeunit "Auto Format" ``` -------------------------------- ### Overwrite Data with Helper Codeunit Source: https://github.com/microsoft/alappextensions/blob/main/Apps/W1/ContosoCoffeeDemoDataset/app/Coding-Patterns.md Use this pattern when helper procedures are simple and you need to show that the Primary Key is the same but specific fields are localized. Ensure to set OverwriteData to true before inserting and false afterwards. ```AL ContosoPostingGroup.SetOverwriteData(true); ContosoPostingGroup.InsertVATProductPostingGroup(CreateVATPostingGroups.Standard(), StandardVATDescriptionLbl); ContosoPostingGroup.InsertVATProductPostingGroup(CreateVATPostingGroups.Reduced(), ReducedVATDescriptionLbl); ContosoPostingGroup.SetOverwriteData(false); ``` -------------------------------- ### Update Codeunit Reference for Auto Format Source: https://github.com/microsoft/alappextensions/blob/main/BREAKINGCHANGES.md The 'AutoFormatManagement' codeunit has been renamed to `codeunit 45 "Auto Format"`. Ensure all references are updated. ```al codeunit 45 "Auto Format" ``` -------------------------------- ### Using the Tag Source: https://github.com/microsoft/alappextensions/wiki/AL-Code-Documentation Illustrates how to use the tag to document potential errors a procedure might throw. This tag is specific to AL. ```AL /// /// My awesome name setter /// /// The name to set as my name /// When the provided name is empty procedure SetMyName(NewName: Text) begin if NewName = '' then Error('Oops! Cannot set an empty name.'); MyName := NewName; end; ``` -------------------------------- ### Replacing TempBlob.ReadAsText with InStream.ReadText Source: https://github.com/microsoft/alappextensions/blob/main/BREAKINGCHANGES.md For 'TempBlob.ReadAsText' errors, use CreateInStream to obtain an InStream and then use ReadText. ```al TempBlob.CreateInStream(InStream); Result := InStream.ReadText; ``` -------------------------------- ### Replacing TempBlob.WriteTextLine with OutStream.WriteText Source: https://github.com/microsoft/alappextensions/blob/main/BREAKINGCHANGES.md To replace the removed 'TempBlob.WriteTextLine' function, obtain an OutStream using CreateOutStream and then use WriteText. ```al TempBlob.CreateOutStream(OutStream); OutStream.WriteText(Text); ``` -------------------------------- ### AI Development Toolkit - Design Dependencies Source: https://github.com/microsoft/alappextensions/blob/main/Apps/W1/AIDevelopmentToolkit/DependencyGraph.md Visual representation of the dependency structure for the 'AI Development Toolkit - Design' application. Shows direct and indirect dependencies. ```text AI Development Toolkit - Design ├── Agent Design Experience └── Agent Samples └── Agent Design Experience ``` -------------------------------- ### AI Development Toolkit - Evaluation Dependencies Source: https://github.com/microsoft/alappextensions/blob/main/Apps/W1/AIDevelopmentToolkit/DependencyGraph.md Visual representation of the dependency structure for the 'AI Development Toolkit - Evaluation' application. Lists all direct and indirect dependencies. ```text AI Development Toolkit - Evaluation (MARKETPLACE) ├── Agent Test Library │ ├── AI Test Toolkit (MARKETPLACE) │ │ ├── System Application │ │ └── Test Runner │ └── Library Assert ├── AI Test Toolkit (MARKETPLACE) │ ├── System Application │ └── Test Runner ├── Test Runner ├── Any ├── Library Variable Storage │ └── Library Assert ├── Library Assert ├── Business Foundation Test Libraries │ ├── System Application │ └── Business Foundation │ └── System Application └── Application Test Library ├── Any ├── Library Assert ├── Library Variable Storage │ └── Library Assert └── Business Foundation Test Libraries ├── System Application └── Business Foundation └── System Application ``` -------------------------------- ### Localize GL Accounts using ContosoGLAccount Codeunit Source: https://github.com/microsoft/alappextensions/blob/main/Apps/W1/ContosoCoffeeDemoDataset/app/Coding-Patterns.md This pattern is specific to GL account localization. It involves adding accounts for W1 localization first, then using the ContosoGLAccount codeunit to manage localized account numbers via a temporary table and integration events. ```AL trigger OnRun() begin AddGLAccountsForLocalization(); ContosoGLAccount.InsertGLAccount(EmployeesPayable(), EmployeesPayableName(), ...); end; local procedure AddGLAccountsForLocalization() begin ContosoGLAccount.AddAccountForLocalization(EmployeesPayableName(), '5850'); OnAfterAddGLAccountsForLocalization(); end; var ContosoGLAccount: Codeunit "Contoso GL Account"; EmployeesPayableLbl: Label 'Employees Payable', MaxLength = 100; procedure EmployeesPayable(): Code[20] begin exit(ContosoGLAccount.GetAccountNo(EmployeesPayableName())); end; procedure EmployeesPayableName(): Text[100] begin exit(EmployeesPayableLbl); end; [IntegrationEvent(false, false)] local procedure OnAfterAddGLAccountsForLocalization() begin end; ``` -------------------------------- ### Descriptive Methods for Reusable Labels Source: https://github.com/microsoft/alappextensions/blob/main/Apps/W1/ContosoCoffeeDemoDataset/app/Coding-Patterns.md Defines reusable label constants and procedures to ensure data consistency and accurate translations across different tables and documents. This pattern avoids typos and translation errors by centralizing label definitions. ```AL procedure Sneakers(): Code[20] begin exit(SneakersTok); end; procedure Boots(): Code[20] begin exit(BootsTok); end; procedure Sandals(): Code[20] begin exit(SandalsTok); end; procedure Formal(): Code[20] begin exit(FormalTok); end; procedure Misc(): Code[20] begin exit(MiscTok); end; procedure Supplier(): Code[20] begin exit(SuppliersTok); end; var SneakersTok: Label 'SNEAKERS', MaxLength = 20; BootsTok: Label 'BOOTS', MaxLength = 20; SandalsTok: Label 'SANDALS', MaxLength = 20; FormalTok: Label 'FORMAL', MaxLength = 20; MiscTok: Label 'MISC', MaxLength = 20; SuppliersTok: Label 'SUPPLIERS', MaxLength = 20; SneakersLbl: Label 'Sneakers', MaxLength = 100; BootsLbl: Label 'Boots', MaxLength = 100; SandalsLbl: Label 'Sandals', MaxLength = 100; FormalLbl: Label 'Formal Shoes', MaxLength = 100; MiscellaneousLbl: Label 'Miscellaneous', MaxLength = 100; ShoeSuppliesLbl: Label 'Shoe Supplies', MaxLength = 100; ``` -------------------------------- ### Implement Demo Data Codeunit for Item Categories Source: https://github.com/microsoft/alappextensions/blob/main/Apps/W1/ContosoCoffeeDemoDataset/app/Getting-Started.md Create a codeunit to insert item categories using a helper 'Contoso Item' codeunit. This snippet defines procedures for different shoe types and their corresponding labels. ```AL codeunit 5380 "Create Shoe Category" { InherentEntitlements = X; InherentPermissions = X; trigger OnRun() var ContosoItem: Codeunit "Contoso Item"; begin ContosoItem.InsertItemCategory(Sneakers(), SneakersLbl, ''); ContosoItem.InsertItemCategory(Boots(), BootsLbl, ''); ContosoItem.InsertItemCategory(Sandals(), SandalsLbl, ''); ContosoItem.InsertItemCategory(Formal(), FormalLbl, ''); ContosoItem.InsertItemCategory(Misc(), MiscellaneousLbl, ''); ContosoItem.InsertItemCategory(Supplier(), ShoeSuppliesLbl, Misc()); end; procedure Sneakers(): Code[20] begin exit(SneakersTok); end; procedure Boots(): Code[20] begin exit(BootsTok); end; procedure Sandals(): Code[20] begin exit(SandalsTok); end; procedure Formal(): Code[20] begin exit(FormalTok); end; procedure Misc(): Code[20] begin exit(MiscTok); end; procedure Supplier(): Code[20] begin exit(SuppliersTok); end; var SneakersTok: Label 'SNEAKERS', MaxLength = 20; BootsTok: Label 'BOOTS', MaxLength = 20; SandalsTok: Label 'SANDALS', MaxLength = 20; FormalTok: Label 'FORMAL', MaxLength = 20; MiscTok: Label 'MISC', MaxLength = 20; SuppliersTok: Label 'SUPPLIERS', MaxLength = 20; SneakersLbl: Label 'Sneakers', MaxLength = 100; BootsLbl: Label 'Boots', MaxLength = 100; SandalsLbl: Label 'Sandals', MaxLength = 100; FormalLbl: Label 'Formal Shoes', MaxLength = 100; MiscellaneousLbl: Label 'Miscellaneous', MaxLength = 100; ShoeSuppliesLbl: Label 'Shoe Supplies', MaxLength = 100; } ``` -------------------------------- ### Replacement for Removed UploadZip Function Source: https://github.com/microsoft/alappextensions/blob/main/BREAKINGCHANGES.md When the 'UploadZip' function is removed, use these replacement APIs to achieve similar functionality. ```al UploadIntoStream('', '', '*.*', '', InStream); DataCompression.OpenZipArchive(InStream, OpenForUpdate); ``` -------------------------------- ### Display User Information with DrillDown Source: https://github.com/microsoft/alappextensions/blob/main/BREAKINGCHANGES.md This snippet shows how to enable DrillDown for non-editable pages by calling the 'DisplayUserInformation' function from the 'User Management' codeunit. ```al field("User ID"; "User ID") { ApplicationArea = Jobs; ToolTip = 'Specifies the ID of the user who posted the entry, to be used, for example, in the change log.'; trigger OnDrillDown() var UserMgt: Codeunit "User Management"; begin UserMgt.DisplayUserInformation("User ID"); end; } ``` -------------------------------- ### Insert GenProductPostingGroup Helper Source: https://github.com/microsoft/alappextensions/blob/main/Apps/W1/ContosoCoffeeDemoDataset/app/Coding-Patterns.md This helper codeunit inserts or overwrites Gen. Product Posting Group data. It handles company type variations and provides options to skip insertion if data exists and OverwriteData is false. ```AL ... procedure InsertGenProductPostingGroup(ProductGroupCode: Code[20]; Description: Text[100]; DefaultVATProdPostingGroup: Code[20]) var ContosoCoffeeDemoDataSetup: Record "Contoso Coffee Demo Data Setup"; GenProductPostingGroup: Record "Gen. Product Posting Group"; Exists: Boolean; begin ContosoCoffeeDemoDataSetup.Get(); if GenProductPostingGroup.Get(ProductGroupCode) then begin Exists := true; if not OverwriteData then exit; end; GenProductPostingGroup.Validate(Code, ProductGroupCode); GenProductPostingGroup.Validate(Description, Description); if ContosoCoffeeDemoDataSetup."Company Type" = ContosoCoffeeDemoDataSetup."Company Type"::VAT then GenProductPostingGroup.Validate("Def. VAT Prod. Posting Group", DefaultVATProdPostingGroup); if Exists then GenProductPostingGroup.Modify(true) else GenProductPostingGroup.Insert(true); end; ... ``` -------------------------------- ### Modify Data via OnBeforeInsertEvent Trigger Source: https://github.com/microsoft/alappextensions/blob/main/Apps/W1/ContosoCoffeeDemoDataset/app/Coding-Patterns.md Employ this pattern when more fields require modification. Set EventSubscriberInstance to Manual to ensure the event only affects the Contoso context. Remember to bind and unbind the event. ```AL [EventSubscriber(ObjectType::Table, Database::Vendor, 'OnBeforeInsertEvent', '', false, false)] local procedure OnBeforeInsertVendor(var Rec: Record Vendor) begin case Rec."No." of CreateVendor.ExportFabrikam(): ValidateVendorRecordFields(Rec, ExportFabrikamVatRegLbl, PostCodeGA31772Lbl, 'GA'); ... ``` -------------------------------- ### Extend Demo Data Module Enum Source: https://github.com/microsoft/alappextensions/blob/main/Apps/W1/ContosoCoffeeDemoDataset/app/Getting-Started.md Add a new enum value to the 'Contoso Demo Data Module' and specify its implementation codeunit. ```AL enumextension 50100 "Contoso Shoes" extends "Contoso Demo Data Module" { value(50100; "Contoso Shoes") { Implementation = "Contoso Demo Data Module" = "Contoso Shoes Module"; } } ``` -------------------------------- ### Add Recipients to Email Source: https://github.com/microsoft/alappextensions/blob/main/BREAKINGCHANGES.md Use a List of Text to add recipients for email functionality. ```AL procedure Adding() var Recipients: List of [Text]; begin Recipients.Add('Email'); SMTPMail.AddRecipients(Recipients); end; ``` -------------------------------- ### Replacing TempBlob.GetXMLAsText with XmlDocument.WriteTo Source: https://github.com/microsoft/alappextensions/blob/main/BREAKINGCHANGES.md To replace the removed 'TempBlob.GetXMLAsText' function, create an InStream, parse it into an XmlDocument, and then write the XML to a text variable. ```al TempBlob.CreateInStream(InStream); Xml := XmlDocument.Create(Instream); Xml.WriteTo(Text); ``` -------------------------------- ### Rename 'AutoFormatTranslate' Procedure to 'ResolveAutoFormat' Source: https://github.com/microsoft/alappextensions/blob/main/BREAKINGCHANGES.md The procedure `AutoFormatTranslate` in 'Codeunit "Auto Format"' has been renamed to `ResolveAutoFormat`. The parameter `AutoFormatType: Integer` is replaced by `AutoFormatType: Enum Auto Format`. Logic for certain cases has been moved to Base Application. ```al procedure ResolveAutoFormat(AutoFormatType: Enum "Auto Format") ``` -------------------------------- ### Handle Renamed SMTP Mail Functions Source: https://github.com/microsoft/alappextensions/blob/main/BREAKINGCHANGES.md The `TrySend` function in `Codeunit "SMTP Mail"` has been renamed to `Send`. If you previously used `Send`, it is now `SendShowError`. ```AL SMTPMail.AddRecipients parameter cannot convert from 'Text' to 'List of [Text]' ``` ```AL SMTPMail.AddCC parameter cannot convert from 'Text' to 'List of [Text]' ``` ```AL SMTPMail.AddBCC parameter cannot convert from 'Text' to 'List of [Text]' ``` -------------------------------- ### Replace RegexReplaceIgnoreCase Function Source: https://github.com/microsoft/alappextensions/blob/main/BREAKINGCHANGES.md Use `codeunit 3001 DotNet_Regex`'s `Replace` function with `RegexIgnoreCase` set to true for case-insensitive regex replacement. ```AL procedure RegexReplaceIgnoreCase(Input : Text; Pattern : Text; Replacement : Text) var DotNet_Regex: Codeunit DotNet_Regex; begin DotNet_Regex.RegexIgnoreCase(Pattern); DotNet_Regex.Replace(Input, Replacement); end; ``` -------------------------------- ### Replace IsAlphanumeric with IsMatch Source: https://github.com/microsoft/alappextensions/blob/main/BREAKINGCHANGES.md The `IsAlphanumeric` function has been removed. Use `DotNet_Regex.IsMatch` with a regex pattern to check for alphanumeric strings. ```AL DotNet_Regex.IsMatch(InputString,'^[a-zA-Z0-9]*$') ``` -------------------------------- ### Convert Decimal to Enum Source: https://github.com/microsoft/alappextensions/blob/main/BREAKINGCHANGES.md When encountering an error converting Decimal to an Enum type, use the Enum's FromInteger functionality for conversion. ```al procedure EnumFromDecimal() var d: Decimal; e: Enum MyEnum; begin e := MyEnum.FromInteger(d); end; ``` -------------------------------- ### Increment String Procedure Source: https://github.com/microsoft/alappextensions/blob/main/BREAKINGCHANGES.md This procedure increments a string containing a number. It throws an error if the string does not contain a number. ```AL procedure EvaluateIncStr(StringToIncrement: Code[50]; ErrorHint: Text) begin if IncStr(StringToIncrement) = '' then Error('%1 contains no number and cannot be incremented.', ErrorHint); end; ``` -------------------------------- ### Calculate Date with Custom Calendar Changes Source: https://github.com/microsoft/alappextensions/blob/main/BREAKINGCHANGES.md Use a CustomCalendarChange array to provide specific calendar adjustments when calculating dates. This overload is used when the standard CalcDateBOC function requires more detailed input. ```AL CustomCalendarChange[1].SetSource(CalChange."Source Type"::"Shipping Agent", "Shipping Agent Code", "Shipping Agent Service Code", ''); CustomCalendarChange[2].SetSource(CalChange."Source Type"::Location, "Location Code", '', ''); CalendarMgmt.CalcDateBOC2(Format("Shipping Time"), "Planned Delivery Date", CustomCalendarChange, true); ``` -------------------------------- ### Replace TextEndsWith with IsMatch Source: https://github.com/microsoft/alappextensions/blob/main/BREAKINGCHANGES.md The `TextEndsWith` function is removed. Use `DotNet_Regex.IsMatch` with a regex pattern that includes the end-of-string anchor '$' to check if a string ends with a specific substring. ```AL DotNet_Regex.IsMatch(InputString, EndingString + '$') ``` -------------------------------- ### Validate User ID in User Selection Source: https://github.com/microsoft/alappextensions/blob/main/BREAKINGCHANGES.md This snippet demonstrates how to validate a User ID using the 'User Selection' codeunit. It's used when the ValidateTableRelation property is set to false. ```al field(1; "User ID"; Code[50]) { Caption = 'User ID'; DataClassification = EndUserIdentifiableInformation; NotBlank = true; TableRelation = User."User Name"; ValidateTableRelation = false; trigger OnValidate() var UserSelection: Codeunit "User Selection"; begin UserSelection.ValidateUserName("User ID"); end; } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.