Codeunit 1890 Reminder Communication

App
Base Application
Namespace
Microsoft.Sales.Reminder
Versions
24-28

Procedures, 20Events, 4

Versions171819202122232425262728

Source29

Source in 29

src/Layers/W1/BaseApp/Sales/Reminder/TermsAndLevels/ReminderCommunication.Codeunit.al1005 lines, Copyright (c) Microsoft Corporation. MIT

// ------------------------------------------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.
// ------------------------------------------------------------------------------------------------
namespace Microsoft.Sales.Reminder;

using Microsoft.Finance.GeneralLedger.Account;
using Microsoft.Foundation.Company;
using Microsoft.Foundation.Reporting;
using Microsoft.Sales.Customer;
using Microsoft.Sales.FinanceCharge;
using Microsoft.Sales.Receivables;
using System.EMail;
using System.Globalization;
using System.Reflection;
using System.Text;
using System.Utilities;

/// <summary>
/// Handles reminder email and attachment text generation with multi-language support and placeholder substitution.
/// </summary>
codeunit 1890 "Reminder Communication"
{
    /// <summary>
    /// Finds the description text for a line fee based on reminder level and customer language settings.
    /// </summary>
    /// <param name="ReminderLevel">The reminder level to get the description from.</param>
    /// <param name="CustLedgerEntry">The customer ledger entry for language lookup.</param>
    /// <param name="ReminderLine">The reminder line for placeholder substitution.</param>
    /// <param name="GLAccount">The G/L account for fallback description.</param>
    /// <returns>The line fee description text.</returns>
    procedure FindDescriptionForLineFee(var ReminderLevel: Record "Reminder Level"; var CustLedgerEntry: Record "Cust. Ledger Entry"; var ReminderLine: Record "Reminder Line"; var GLAccount: Record "G/L Account"): Text[100]
    var
        ReminderTerms: Record "Reminder Terms";
        ReminderAttachmentText: Record "Reminder Attachment Text";
        LanguageCode: Code[10];
        Result: Text[100];
    begin
        LanguageCode := GetCustomerLanguageOrDefaultUserLanguage(CustLedgerEntry."Customer No.");

        // Check if there is a reminder attachment text for the Reminder Level
        if TryGetReminderAttachmentText(ReminderLevel."Reminder Attachment Text", LanguageCode, ReminderAttachmentText) then
            Result := SubstituteInlineFeeDescription(ReminderAttachmentText."Inline Fee Description", ReminderLevel, ReminderLine)
        else begin
            // If there are no reminder attachment text for the language, check the Reminder Terms attachment text
            ReminderTerms.Get(ReminderLevel."Reminder Terms Code");
            if TryGetReminderAttachmentText(ReminderTerms."Reminder Attachment Text", LanguageCode, ReminderAttachmentText) then
                Result := SubstituteInlineFeeDescription(ReminderAttachmentText."Inline Fee Description", ReminderLevel, ReminderLine)
        end;

        if Result = '' then
            if GLAccount.Get(ReminderLine."No.") then
                Result := GLAccount.Name;
        exit(Result);
    end;

    /// <summary>
    /// Inserts the beginning text lines into a reminder based on the reminder level and language.
    /// </summary>
    /// <param name="ReminderHeader">The reminder header to insert text into.</param>
    /// <param name="ReminderLevel">The reminder level containing the text template.</param>
    /// <param name="ReminderLine">The reminder line record for positioning.</param>
    procedure InsertBeginningText(var ReminderHeader: Record "Reminder Header"; var ReminderLevel: Record "Reminder Level"; var ReminderLine: Record "Reminder Line")
    var
        ReminderTerms: Record "Reminder Terms";
        ReminderAttachmentText: Record "Reminder Attachment Text";
        LineSpacing, NextLineNo : Integer;
        LanguageCode: Code[10];
    begin
        LanguageCode := GetCustomerLanguageOrDefaultUserLanguage(ReminderHeader."Customer No.");
        ReminderLine.Reset();
        ReminderLine.SetRange("Reminder No.", ReminderHeader."No.");
        ReminderLine."Reminder No." := ReminderHeader."No.";

        if TryGetReminderAttachmentText(ReminderLevel."Reminder Attachment Text", LanguageCode, ReminderAttachmentText) then begin
            LineSpacing := CalculateLineSpacingForBeginningText(ReminderLine, ReminderAttachmentText);
            ReminderHeader.InsertTextLines(ReminderHeader, ReminderAttachmentText, Enum::"Reminder Line Type"::"Beginning Text", NextLineNo, LineSpacing);
        end
        else begin
            ReminderTerms.Get(ReminderLevel."Reminder Terms Code");
            if TryGetReminderAttachmentText(ReminderTerms."Reminder Attachment Text", LanguageCode, ReminderAttachmentText) then begin
                LineSpacing := CalculateLineSpacingForBeginningText(ReminderLine, ReminderAttachmentText);
                ReminderHeader.InsertTextLines(ReminderHeader, ReminderAttachmentText, Enum::"Reminder Line Type"::"Beginning Text", NextLineNo, LineSpacing)
            end;
        end;
    end;

    /// <summary>
    /// Inserts the ending text lines into a reminder based on the reminder level and language.
    /// </summary>
    /// <param name="ReminderHeader">The reminder header to insert text into.</param>
    /// <param name="ReminderLevel">The reminder level containing the text template.</param>
    /// <param name="ReminderLine">The reminder line record for positioning.</param>
    procedure InsertEndingText(var ReminderHeader: Record "Reminder Header"; var ReminderLevel: Record "Reminder Level"; var ReminderLine: Record "Reminder Line")
    var
        ReminderLine2: Record "Reminder Line";
        ReminderTerms: Record "Reminder Terms";
        ReminderAttachmentText: Record "Reminder Attachment Text";
        LanguageCode: Code[10];
        LineSpacing, NextLineNo : Integer;
    begin
        LanguageCode := GetCustomerLanguageOrDefaultUserLanguage(ReminderHeader."Customer No.");
        ReminderLine.Reset();
        ReminderLine.SetRange("Reminder No.", ReminderHeader."No.");
        ReminderLine.SetFilter(
          "Line Type", '%1|%2|%3',
          ReminderLine."Line Type"::"Reminder Line",
          ReminderLine."Line Type"::"Additional Fee",
          ReminderLine."Line Type"::Rounding);

        if ReminderLine.FindLast() then
            NextLineNo := ReminderLine."Line No."
        else begin
            ReminderLine.SetRange("Line Type", ReminderLine."Line Type"::"Beginning Text");
            if ReminderLine.FindLast() then
                NextLineNo := ReminderLine."Line No."
            else
                NextLineNo := 0;
        end;

        ReminderLine.SetRange("Line Type");
        ReminderLine2 := ReminderLine;
        ReminderLine2.CopyFilters(ReminderLine);
        ReminderLine2.SetFilter("Line Type", '<>%1', ReminderLine2."Line Type"::"Line Fee");
        if TryGetReminderAttachmentText(ReminderLevel."Reminder Attachment Text", LanguageCode, ReminderAttachmentText) then begin
            LineSpacing := CalculateLineSpacingForEndingText(ReminderLine, ReminderLine2, ReminderAttachmentText);
            ReminderHeader.InsertTextLines(ReminderHeader, ReminderAttachmentText, Enum::"Reminder Line Type"::"Ending Text", NextLineNo, LineSpacing);
        end
        else begin
            ReminderTerms.Get(ReminderLevel."Reminder Terms Code");
            if TryGetReminderAttachmentText(ReminderTerms."Reminder Attachment Text", LanguageCode, ReminderAttachmentText) then begin
                LineSpacing := CalculateLineSpacingForEndingText(ReminderLine, ReminderLine2, ReminderAttachmentText);
                ReminderHeader.InsertTextLines(ReminderHeader, ReminderAttachmentText, Enum::"Reminder Line Type"::"Ending Text", NextLineNo, LineSpacing);
            end;
        end;
    end;

    local procedure GetCustomerLanguageOrDefaultUserLanguage(CustomerNo: Code[20]): Code[10]
    var
        Customer: Record Customer;
        Language: Codeunit Language;
        LanguageCode: Code[10];
    begin
        if Customer.Get(CustomerNo) then
            LanguageCode := Customer."Language Code";

        if LanguageCode = '' then
            LanguageCode := Language.GetUserLanguageCode();

        if LanguageCode = '' then
            LanguageCode := Language.GetLanguageCode(Language.GetDefaultApplicationLanguageId());

        exit(LanguageCode);
    end;

    /// <summary>
    /// Substitutes placeholders in the inline fee description with actual values from the reminder.
    /// </summary>
    /// <param name="FeeLineDescriptionText">The description text containing placeholders.</param>
    /// <param name="ReminderLevel">The reminder level for substitution values.</param>
    /// <param name="ReminderLine">The reminder line for substitution values.</param>
    /// <returns>The description text with placeholders replaced.</returns>
    procedure SubstituteInlineFeeDescription(FeeLineDescriptionText: Text[100]; var ReminderLevel: Record "Reminder Level"; var ReminderLine: Record "Reminder Line"): Text[100]
    begin
        // Here we should work on improving the user experience instead of inputting %1, %2, %3.
        exit(StrSubstNo(FeeLineDescriptionText,
                ReminderLine."Reminder No.",
                ReminderLine."No. of Reminders",
                ReminderLine."Document Date",
                ReminderLine."Posting Date",
                ReminderLine."No.",
                ReminderLine.Amount,
                ReminderLine."Applies-to Document Type",
                ReminderLine."Applies-to Document No.",
                ReminderLevel."No."))
    end;

    /// <summary>
    /// Substitutes placeholders in beginning or ending description text with actual reminder values.
    /// </summary>
    /// <param name="SourceDescriptionText">The source text containing placeholders.</param>
    /// <param name="ReminderTotal">The total reminder amount for substitution.</param>
    /// <param name="MaxLength">The maximum length of the resulting text.</param>
    /// <param name="ReminderHeader">The reminder header for substitution values.</param>
    /// <param name="FinanceChargeTerms">The finance charge terms for interest rate.</param>
    /// <returns>The description text with placeholders replaced.</returns>
    procedure SubstituteBeginningOrEndingDescription(SourceDescriptionText: Text[100]; ReminderTotal: Decimal; MaxLength: Integer; var ReminderHeader: Record "Reminder Header"; var FinanceChargeTerms: Record "Finance Charge Terms"): Text[100]
    var
        CompanyInfo: Record "Company Information";
        AutoFormat: Codeunit "Auto Format";
        AutoFormatType: Enum "Auto Format";
    begin
        CompanyInfo.Get();
        if MaxLength > 100 then
            MaxLength := 100;
        // Here we should work on improving the user experience instead of inputting %1, %2, %3.
        exit(CopyStr(CopyStr(
            StrSubstNo(
                SourceDescriptionText,
                ReminderHeader."Document Date",
                ReminderHeader."Due Date",
                FinanceChargeTerms."Interest Rate",
                Format(
                    ReminderHeader."Remaining Amount",
                    0,
                    AutoFormat.ResolveAutoFormat(
                        AutoFormatType::AmountFormat,
                        ReminderHeader."Currency Code")),
                ReminderHeader."Interest Amount",
                ReminderHeader."Additional Fee",
                Format(
                    ReminderTotal,
                    0,
                    AutoFormat.ResolveAutoFormat(
                        AutoFormatType::AmountFormat,
                        ReminderHeader."Currency Code")),
                ReminderHeader."Reminder Level",
                ReminderHeader."Currency Code",
                ReminderHeader."Posting Date",
                CompanyInfo.Name,
                ReminderHeader."Add. Fee per Line"),
            1, MaxLength),
            1, 100));
    end;

    /// <summary>
    /// Gets a formatted text list of attachment language codes separated by the specified separator.
    /// </summary>
    /// <param name="SelectedGuid">The ID of the attachment text group.</param>
    /// <param name="SeparatorText">The separator format text for combining languages.</param>
    /// <returns>A formatted text with all language codes.</returns>
    procedure GetListOfAttachmentLanguagesFromIdWithSeparator(SelectedGuid: Guid; SeparatorText: Text): Text
    var
        LanguageCodes: List of [Code[10]];
    begin
        LanguageCodes := GetListOfAttachmentLanguagesFromId(SelectedGuid);
        exit(GenerateTextofLanguagesFromListOfCode(LanguageCodes, SeparatorText));
    end;

    /// <summary>
    /// Gets a formatted text list of email language codes separated by the specified separator.
    /// </summary>
    /// <param name="SelectedGuid">The ID of the email text group.</param>
    /// <param name="SeparatorText">The separator format text for combining languages.</param>
    /// <returns>A formatted text with all language codes.</returns>
    procedure GetListOfEmailLanguagesFromIdWithSeparator(SelectedGuid: Guid; SeparatorText: Text): Text
    var
        LanguageCodes: List of [Code[10]];
    begin
        LanguageCodes := GetListOfEmailLanguagesFromId(SelectedGuid);
        exit(GenerateTextofLanguagesFromListOfCode(LanguageCodes, SeparatorText));
    end;

    local procedure GenerateTextofLanguagesFromListOfCode(var LanguageCodes: List of [Code[10]]; SeparatorText: Text): Text
    var
        LanguageCode: Text;
        ResultingText: Text;
        FirstLanguage: Boolean;
    begin
        FirstLanguage := true;
        foreach LanguageCode in LanguageCodes do
            if FirstLanguage then begin
                ResultingText := LanguageCode;
                FirstLanguage := false;
            end
            else
                ResultingText := StrSubstNo(SeparatorText, ResultingText, LanguageCode);
        exit(ResultingText);
    end;

    /// <summary>
    /// Gets a list of all language codes that have attachment text defined for the specified ID.
    /// </summary>
    /// <param name="SelectedGuid">The ID of the attachment text group.</param>
    /// <returns>A list of language codes.</returns>
    procedure GetListOfAttachmentLanguagesFromId(SelectedGuid: Guid): List of [Code[10]]
    var
        ReminderAttachmentText: Record "Reminder Attachment Text";
        LanguageCodes: List of [Code[10]];
    begin
        if IsNullGuid(SelectedGuid) then
            exit(LanguageCodes);

        ReminderAttachmentText.SetRange(Id, SelectedGuid);
        if ReminderAttachmentText.IsEmpty() then
            exit(LanguageCodes);

        if ReminderAttachmentText.FindSet() then
            repeat
                LanguageCodes.Add(ReminderAttachmentText."Language Code");
            until ReminderAttachmentText.Next() = 0;
        exit(LanguageCodes);
    end;

    /// <summary>
    /// Gets a list of all language codes that have email text defined for the specified ID.
    /// </summary>
    /// <param name="SelectedGuid">The ID of the email text group.</param>
    /// <returns>A list of language codes.</returns>
    procedure GetListOfEmailLanguagesFromId(SelectedGuid: Guid): List of [Code[10]]
    var
        ReminderEmailText: Record "Reminder Email Text";
        LanguageCodes: List of [Code[10]];
    begin
        if IsNullGuid(SelectedGuid) then
            exit(LanguageCodes);

        ReminderEmailText.SetRange(Id, SelectedGuid);
        if ReminderEmailText.IsEmpty() then
            exit(LanguageCodes);

        if ReminderEmailText.FindSet() then
            repeat
                LanguageCodes.Add(ReminderEmailText."Language Code");
            until ReminderEmailText.Next() = 0;
        exit(LanguageCodes);
    end;

    /// <summary>
    /// Creates default attachment and email text records for a new language.
    /// </summary>
    /// <param name="SelectedId">The ID of the text group.</param>
    /// <param name="LanguageCode">The language code for the new records.</param>
    /// <param name="SourceType">The source type (Reminder Term or Reminder Level).</param>
    /// <param name="SelectedSystemId">The system ID of the source record to link to.</param>
    procedure SetDefaultContentForNewLanguage(SelectedId: Guid; LanguageCode: Code[10]; SourceType: Enum "Reminder Text Source Type"; SelectedSystemId: Guid)
    var
        ReminderAttachmentText: Record "Reminder Attachment Text";
        ReminderEmailText: Record "Reminder Email Text";
    begin
        ReminderAttachmentText.SetDefaultContentForNewLanguage(SelectedId, LanguageCode, SourceType, SelectedSystemId);
        ReminderEmailText.SetDefaultContentForNewLanguage(SelectedId, LanguageCode, SourceType, SelectedSystemId);
    end;

    /// <summary>
    /// Extracts and formats the available attachment and email languages for the reminder terms.
    /// </summary>
    /// <param name="ReminderTerms">The reminder terms to extract languages from.</param>
    /// <returns>A formatted text showing attachment and email languages.</returns>
    procedure ExtractAttachmentAndEmailLanguages(var ReminderTerms: Record "Reminder Terms"): Text
    begin
        exit(ExtractAttachmentAndEmailLanguages(ReminderTerms."Reminder Attachment Text"));
    end;

    /// <summary>
    /// Extracts and formats the available attachment and email languages for the reminder level.
    /// </summary>
    /// <param name="ReminderLevel">The reminder level to extract languages from.</param>
    /// <returns>A formatted text showing attachment and email languages.</returns>
    procedure ExtractAttachmentAndEmailLanguages(var ReminderLevel: Record "Reminder Level"): Text
    begin
        exit(ExtractAttachmentAndEmailLanguages(ReminderLevel."Reminder Attachment Text"));
    end;

    /// <summary>
    /// Extracts and formats the available attachment and email languages for the specified ID.
    /// </summary>
    /// <param name="SelectedId">The ID of the text group to extract languages from.</param>
    /// <returns>A formatted text showing attachment and email languages.</returns>
    procedure ExtractAttachmentAndEmailLanguages(SelectedId: Guid): Text
    var
        AttachmentLanguages: Text;
        EmailLanguages: Text;
    begin
        AttachmentLanguages := GetListOfAttachmentLanguagesFromIdWithSeparator(SelectedId, CommaSeparatedTok);
        EmailLanguages := GetListOfEmailLanguagesFromIdWithSeparator(SelectedId, CommaSeparatedTok);
        exit(StrSubstNo(LanguagesCustomerCommunicationsLbl, AttachmentLanguages, EmailLanguages));
    end;

    /// <summary>
    /// Populates the email text components for an issued reminder based on language and template settings.
    /// </summary>
    /// <param name="IssuedReminderHeader">The issued reminder header to get text for.</param>
    /// <param name="CompanyInfo">The company information for substitution.</param>
    /// <param name="GreetingTxt">Returns the greeting text.</param>
    /// <param name="AmtDueTxt">Returns the amount due text.</param>
    /// <param name="BodyTxt">Returns the body text.</param>
    /// <param name="ClosingTxt">Returns the closing text.</param>
    /// <param name="DescriptionTxt">Returns the description text.</param>
    /// <param name="NNC_TotalInclVAT">The total including VAT for substitution.</param>
    procedure PopulateEmailText(var IssuedReminderHeader: Record "Issued Reminder Header"; var CompanyInfo: Record "Company Information"; var GreetingTxt: Text; var AmtDueTxt: Text; var BodyTxt: Text; var ClosingTxt: Text; var DescriptionTxt: Text; NNC_TotalInclVAT: Decimal)
    var
        ReminderEmailText: Record "Reminder Email Text";
        MailManagement: Codeunit "Mail Management";
    begin
        AmtDueTxt := '';
        GreetingTxt := '';
        ClosingTxt := '';
        BodyTxt := ReplaceTextTok;
        DescriptionTxt := ReminderEmailText.GetDescriptionLbl();
        IssuedReminderHeader.CalcFields("Email Text");

        if IssuedReminderHeader."Email Text".HasValue() then begin
            GreetingTxt := ReminderEmailText.GetDefaultGreetingLbl();
            ClosingTxt := ReminderEmailText.GetDefaultClosingLbl();
            if Format(IssuedReminderHeader."Due Date") <> '' then
                if not MailManagement.IsHandlingGetEmailBody() then begin
                    SelectEmailBodyText(IssuedReminderHeader, AmtDueTxt);
                    AmtDueTxt := StripHtmlTags(AmtDueTxt);
                    SubstituteRelatedValues(AmtDueTxt, IssuedReminderHeader, NNC_TotalInclVAT, CopyStr(CompanyName, 1, 100));
                end;
        end else begin
            ReminderEmailText.SetAutoCalcFields("Body Text");
            if GetReminderEmailText(IssuedReminderHeader, ReminderEmailText) then begin
                GreetingTxt := ReminderEmailText.Greeting;
                ClosingTxt := ReminderEmailText.Closing;
                if Format(IssuedReminderHeader."Due Date") <> '' then
                    if not MailManagement.IsHandlingGetEmailBody() then begin
                        SelectEmailBodyText(ReminderEmailText, IssuedReminderHeader, AmtDueTxt);
                        AmtDueTxt := StripHtmlTags(AmtDueTxt);
                        SubstituteRelatedValues(AmtDueTxt, IssuedReminderHeader, NNC_TotalInclVAT, CopyStr(CompanyName, 1, 100));
                    end;
            end else begin
                GreetingTxt := ReminderEmailText.GetDefaultGreetingLbl();
                if Format(IssuedReminderHeader."Due Date") <> '' then
                    AmtDueTxt := StrSubstNo(ReminderEmailText.GetAmtDueLbl(), IssuedReminderHeader."Due Date");
                ClosingTxt := ReminderEmailText.GetDefaultClosingLbl();
            end;
        end;
        SubstituteRelatedValues(GreetingTxt, IssuedReminderHeader, NNC_TotalInclVAT, CopyStr(CompanyName, 1, 100));
        SubstituteRelatedValues(ClosingTxt, IssuedReminderHeader, NNC_TotalInclVAT, CopyStr(CompanyName, 1, 100));
    end;

    local procedure SelectEmailBodyText(var ReminderEmailText: Record "Reminder Email Text"; var IssuedReminderHeader: Record "Issued Reminder Header"; var BodyTxt: Text)
    var
        TypeHelper: Codeunit "Type Helper";
        EmailBodyTextInStream: InStream;
    begin
        // if there is an email text on the reminder itself, read that it  
        if IssuedReminderHeader."Email Text".HasValue() then begin
            IssuedReminderHeader."Email Text".CreateInStream(EmailBodyTextInStream, TextEncoding::UTF8);
            BodyTxt := TypeHelper.TryReadAsTextWithSepAndFieldErrMsg(EmailBodyTextInStream, TypeHelper.LFSeparator(), IssuedReminderHeader.FieldName("Email Text"));
        end
        else
            BodyTxt += ReminderEmailText.GetBodyText();
    end;

    local procedure SelectEmailBodyText(var IssuedReminderHeader: Record "Issued Reminder Header"; var BodyTxt: Text)
    var
        ReminderEmailText: Record "Reminder Email Text";
        TypeHelper: Codeunit "Type Helper";
        EmailBodyTextInStream: InStream;
    begin
        // if there is an email text on the reminder itself, read that it  
        if IssuedReminderHeader."Email Text".HasValue() then begin
            IssuedReminderHeader."Email Text".CreateInStream(EmailBodyTextInStream, TextEncoding::UTF8);
            BodyTxt := TypeHelper.TryReadAsTextWithSepAndFieldErrMsg(EmailBodyTextInStream, TypeHelper.LFSeparator(), IssuedReminderHeader.FieldName("Email Text"));
        end
        else
            BodyTxt := ReminderEmailText.GetBodyLbl();
    end;

    local procedure SubstituteRelatedValues(var BodyTxt: Text; var IssuedReminderHeader: Record "Issued Reminder Header"; NNC_TotalInclVAT: Decimal; CompanyName: Text[100])
    var
        FinanceChargeTerms: Record "Finance Charge Terms";
        AutoFormat: Codeunit "Auto Format";
        AutoFormatType: Enum "Auto Format";
    begin
        if IssuedReminderHeader."Fin. Charge Terms Code" <> '' then
            FinanceChargeTerms.Get(IssuedReminderHeader."Fin. Charge Terms Code");

        BodyTxt := StrSubstNo(
            BodyTxt,
            IssuedReminderHeader."Document Date",
            IssuedReminderHeader."Due Date",
            FinanceChargeTerms."Interest Rate",
            Format(IssuedReminderHeader."Remaining Amount", 0,
                AutoFormat.ResolveAutoFormat(AutoFormatType::AmountFormat, IssuedReminderHeader."Currency Code")),
            IssuedReminderHeader."Interest Amount",
            IssuedReminderHeader."Additional Fee",
            Format(NNC_TotalInclVAT, 0, AutoFormat.ResolveAutoFormat(AutoFormatType::AmountFormat, IssuedReminderHeader."Currency Code")),
            IssuedReminderHeader."Reminder Level",
            IssuedReminderHeader."Currency Code",
            IssuedReminderHeader."Posting Date",
            CompanyName,
            IssuedReminderHeader."Add. Fee per Line");

        OnAfterSubstituteRelatedValues(BodyTxt, IssuedReminderHeader);
    end;

    internal procedure CheckMissMatchBetweenLanguages(var ReminderTerms: Record "Reminder Terms"): Boolean
    var
        ReminderLevel: Record "Reminder Level";
        ReminderCommunication: Codeunit "Reminder Communication";
        ReminderTermsAttachmentLanguages: Text;
        ReminderTermsEmailLanguages: Text;
        ReminderLevelAttachmentLanguages: Text;
        ReminderLevelEmailLanguages: Text;
        PreviousReminderLevelAttachmentLanguages: Text;
        PreviousReminderLevelEmailLanguages: Text;
        AffectedReminderLevels: Text;
        FirstLevel: Boolean;
        MissalignedLevels: Boolean;
        ConfirmMessage: Text;
    begin
        ReminderTermsAttachmentLanguages := ReminderCommunication.GetListOfAttachmentLanguagesFromIdWithSeparator(ReminderTerms."Reminder Attachment Text", CommaSeparatedTok);
        ReminderTermsEmailLanguages := ReminderCommunication.GetListOfEmailLanguagesFromIdWithSeparator(ReminderTerms."Reminder Email Text", CommaSeparatedTok);
        ReminderLevel.SetRange("Reminder Terms Code", ReminderTerms.Code);
        if not ReminderLevel.IsEmpty() then begin
            FirstLevel := true;
            ReminderLevel.FindSet();
            repeat
                ReminderLevelAttachmentLanguages := ReminderCommunication.GetListOfAttachmentLanguagesFromIdWithSeparator(ReminderLevel."Reminder Attachment Text", CommaSeparatedTok);
                ReminderLevelEmailLanguages := ReminderCommunication.GetListOfEmailLanguagesFromIdWithSeparator(ReminderLevel."Reminder Email Text", CommaSeparatedTok);
                if (ReminderTermsAttachmentLanguages <> ReminderLevelAttachmentLanguages) or (ReminderTermsEmailLanguages <> ReminderLevelEmailLanguages) then
                    if AffectedReminderLevels = '' then
                        AffectedReminderLevels := Format(ReminderLevel."No.")
                    else
                        AffectedReminderLevels := StrSubstNo(CommaSeparatedTok, AffectedReminderLevels, ReminderLevel."No.");

                if FirstLevel then
                    FirstLevel := false
                else
                    if (PreviousReminderLevelAttachmentLanguages <> ReminderLevelAttachmentLanguages) or (PreviousReminderLevelEmailLanguages <> ReminderLevelEmailLanguages) then
                        MissalignedLevels := true;

                PreviousReminderLevelAttachmentLanguages := ReminderLevelAttachmentLanguages;
                PreviousReminderLevelEmailLanguages := ReminderLevelEmailLanguages;
            until ReminderLevel.Next() = 0;
        end;

        if AffectedReminderLevels <> '' then begin
            ConfirmMessage := StrSubstNo(MismatchLanguagesBetweenTermsAndLevelsMsg, AffectedReminderLevels);
            if MissalignedLevels then
                ConfirmMessage := StrSubstNo(AppendixTextTok, ConfirmMessage, ExtensionMismatchLanguagesBetweenTermsAndLevelsMsg);
        end
        else
            if MissalignedLevels then
                ConfirmMessage := MismatchLanguagesBetweenLevelsMsg;

        if ConfirmMessage <> '' then
            exit(Confirm(ConfirmMessage));

        exit(false);
    end;

    internal procedure TransferReminderText()
    var
        ReminderLevels: Record "Reminder Level";
        ReminderText: Record "Reminder Text";
        ReminderAttachmentText: Record "Reminder Attachment Text";
        ReminderAttachmentTextLine: Record "Reminder Attachment Text Line";
        ReminderEmailText: Record "Reminder Email Text";
        Language: Codeunit Language;
        TypeHelper: Codeunit "Type Helper";
        ReadStream: InStream;
        DefaultLanguageCode: Code[10];
        LocalGuid: Guid;
    begin
        if ReminderText.IsEmpty() then
            exit;
        DefaultLanguageCode := Language.GetUserLanguageCode();
        ReminderText.FindSet();
        repeat
            Clear(ReminderAttachmentText);
            Clear(ReminderEmailText);
            Clear(LocalGuid);
            Clear(ReadStream);
            // Check if there are existing texts for the reminder level
            if ReminderLevels.Get(ReminderText."Reminder Terms Code", ReminderText."Reminder Level") then begin

                if not IsNullGuid(ReminderLevels."Reminder Attachment Text") then
                    LocalGuid := ReminderLevels."Reminder Attachment Text";
                if not IsNullGuid(ReminderLevels."Reminder Email Text") then
                    LocalGuid := ReminderLevels."Reminder Email Text";
                if IsNullGuid(LocalGuid) then
                    LocalGuid := CreateGuid();
                // If not then create the default ones
                if not ReminderAttachmentText.Get(LocalGuid, DefaultLanguageCode) then
                    ReminderAttachmentText.SetDefaultContentForNewLanguage(LocalGuid, DefaultLanguageCode, Enum::"Reminder Text Source Type"::"Reminder Level", ReminderLevels.SystemId);

                if not ReminderEmailText.Get(LocalGuid, DefaultLanguageCode) then
                    ReminderEmailText.SetDefaultContentForNewLanguage(LocalGuid, DefaultLanguageCode, Enum::"Reminder Text Source Type"::"Reminder Level", ReminderLevels.SystemId);
                if ReminderAttachmentText.Get(LocalGuid, DefaultLanguageCode) and ReminderEmailText.Get(LocalGuid, DefaultLanguageCode) then
                    // And then personalized them with the customer data
                    case ReminderText.Position of
                        Enum::"Reminder Text Position"::Beginning:
                            begin
                                ReminderAttachmentTextLine.Init();
                                ReminderAttachmentTextLine.Id := ReminderAttachmentText.Id;
                                ReminderAttachmentTextLine."Language Code" := ReminderAttachmentText."Language Code";
                                ReminderAttachmentTextLine.Position := ReminderAttachmentTextLine.Position::"Beginning Line";
                                ReminderAttachmentTextLine."Line No." := ReminderText."Line No.";
                                ReminderAttachmentTextLine.Text := ReminderText.Text;
                                OnTransferReminderTextOnBeforeInsertBeginningReminderAttachmentTextLine(ReminderText, ReminderAttachmentTextLine);
                                ReminderAttachmentTextLine.Insert(true);
                            end;
                        Enum::"Reminder Text Position"::Ending:
                            begin
                                ReminderAttachmentTextLine.Init();
                                ReminderAttachmentTextLine.Id := ReminderAttachmentText.Id;
                                ReminderAttachmentTextLine."Language Code" := ReminderAttachmentText."Language Code";
                                ReminderAttachmentTextLine.Position := ReminderAttachmentTextLine.Position::"Ending Line";
                                ReminderAttachmentTextLine."Line No." := ReminderText."Line No.";
                                ReminderAttachmentTextLine.Text := ReminderText.Text;
                                OnTransferReminderTextOnBeforeInsertEndingReminderAttachmentTextLine(ReminderText, ReminderAttachmentTextLine);
                                ReminderAttachmentTextLine.Insert(true);
                            end;
                        Enum::"Reminder Text Position"::"Email Body":
                            if ReminderText."Email Text".HasValue() then begin
                                ReminderText.CalcFields("Email Text");
                                ReminderText."Email Text".CreateInStream(ReadStream);
                                ReminderEmailText.SetBodyText(TypeHelper.TryReadAsTextWithSepAndFieldErrMsg(ReadStream, TypeHelper.LFSeparator(), ReminderText.FieldName("Email Text")));
                            end;
                    end;
            end;
        until ReminderText.Next() = 0;
    end;

    internal procedure TransferReminderTermsTranslations()
    var
        ReminderTerms: Record "Reminder Terms";
        ReminderTermsTranslations: Record "Reminder Terms Translation";
        ReminderAttachmentText: Record "Reminder Attachment Text";
        ReminderEmailText: Record "Reminder Email Text";
        LocalGuid: Guid;
    begin
        if ReminderTermsTranslations.IsEmpty() then
            exit;
        ReminderTermsTranslations.FindSet();
        repeat
            Clear(ReminderAttachmentText);
            Clear(ReminderEmailText);
            Clear(LocalGuid);
            if ReminderTerms.Get(ReminderTermsTranslations."Reminder Terms Code") then begin
                if not IsNullGuid(ReminderTerms."Reminder Attachment Text") then
                    LocalGuid := ReminderTerms."Reminder Attachment Text";
                if not IsNullGuid(ReminderTerms."Reminder Email Text") then
                    LocalGuid := ReminderTerms."Reminder Email Text";
                if IsNullGuid(LocalGuid) then
                    LocalGuid := CreateGuid();
                if not ReminderAttachmentText.Get(LocalGuid, ReminderTermsTranslations."Language Code") then
                    ReminderAttachmentText.SetDefaultContentForNewLanguage(LocalGuid, ReminderTermsTranslations."Language Code", Enum::"Reminder Text Source Type"::"Reminder Term", ReminderTerms.SystemId);
                if not ReminderEmailText.Get(LocalGuid, ReminderTermsTranslations."Language Code") then
                    ReminderEmailText.SetDefaultContentForNewLanguage(LocalGuid, ReminderTermsTranslations."Language Code", Enum::"Reminder Text Source Type"::"Reminder Term", ReminderTerms.SystemId);
                if ReminderAttachmentText.Get(LocalGuid, ReminderTermsTranslations."Language Code") then begin
                    ReminderAttachmentText."Inline Fee Description" := CopyStr(ReminderTermsTranslations."Note About Line Fee on Report", 1, 100);
                    ReminderAttachmentText.Modify(true);
                end;
            end;
        until ReminderTermsTranslations.Next() = 0;
    end;

    internal procedure TransferReminderTermsLineFeeDescription()
    var
        ReminderTerms: Record "Reminder Terms";
        ReminderAttachmentText: Record "Reminder Attachment Text";
        ReminderEmailText: Record "Reminder Email Text";
        Language: Codeunit Language;
        LocalGuid: Guid;
        DefaultLanguageCode: Code[10];
    begin
        if ReminderTerms.IsEmpty() then
            exit;
        DefaultLanguageCode := Language.GetUserLanguageCode();
        ReminderTerms.FindSet();
        repeat
            Clear(ReminderAttachmentText);
            Clear(ReminderEmailText);
            Clear(LocalGuid);
            if not IsNullGuid(ReminderTerms."Reminder Attachment Text") then
                LocalGuid := ReminderTerms."Reminder Attachment Text";
            if not IsNullGuid(ReminderTerms."Reminder Email Text") then
                LocalGuid := ReminderTerms."Reminder Email Text";
            if IsNullGuid(LocalGuid) then
                LocalGuid := CreateGuid();
            if not ReminderAttachmentText.Get(LocalGuid, DefaultLanguageCode) then
                ReminderAttachmentText.SetDefaultContentForNewLanguage(LocalGuid, DefaultLanguageCode, Enum::"Reminder Text Source Type"::"Reminder Term", ReminderTerms.SystemId);
            if not ReminderEmailText.Get(LocalGuid, DefaultLanguageCode) then
                ReminderEmailText.SetDefaultContentForNewLanguage(LocalGuid, DefaultLanguageCode, Enum::"Reminder Text Source Type"::"Reminder Term", ReminderTerms.SystemId);
            if ReminderAttachmentText.Get(LocalGuid, DefaultLanguageCode) then begin
                ReminderAttachmentText."Inline Fee Description" := CopyStr(ReminderTerms."Note About Line Fee on Report", 1, 100);
                ReminderAttachmentText.Modify(true);
            end;
        until ReminderTerms.Next() = 0;
    end;

    internal procedure TransferReminderLevelLineFeeDescription()
    var
        ReminderLevel: Record "Reminder Level";
        ReminderAttachmentText: Record "Reminder Attachment Text";
        ReminderEmailText: Record "Reminder Email Text";
        Language: Codeunit Language;
        LocalGuid: Guid;
        DefaultLanguageCode: Code[10];
    begin
        if ReminderLevel.IsEmpty() then
            exit;
        DefaultLanguageCode := Language.GetUserLanguageCode();
        ReminderLevel.FindSet();
        repeat
            Clear(ReminderAttachmentText);
            Clear(ReminderEmailText);
            Clear(LocalGuid);
            if not IsNullGuid(ReminderLevel."Reminder Attachment Text") then
                LocalGuid := ReminderLevel."Reminder Attachment Text";
            if not IsNullGuid(ReminderLevel."Reminder Email Text") then
                LocalGuid := ReminderLevel."Reminder Email Text";
            if IsNullGuid(LocalGuid) then
                LocalGuid := CreateGuid();
            if not ReminderAttachmentText.Get(LocalGuid, DefaultLanguageCode) then
                ReminderAttachmentText.SetDefaultContentForNewLanguage(LocalGuid, DefaultLanguageCode, Enum::"Reminder Text Source Type"::"Reminder Level", ReminderLevel.SystemId);
            if not ReminderEmailText.Get(LocalGuid, DefaultLanguageCode) then
                ReminderEmailText.SetDefaultContentForNewLanguage(LocalGuid, DefaultLanguageCode, Enum::"Reminder Text Source Type"::"Reminder Level", ReminderLevel.SystemId);
            if ReminderAttachmentText.Get(LocalGuid, DefaultLanguageCode) then begin
                ReminderAttachmentText."Inline Fee Description" := CopyStr(ReminderLevel."Add. Fee per Line Description", 1, 100);
                ReminderAttachmentText.Modify(true);
            end;
        until ReminderLevel.Next() = 0;
    end;

    local procedure FindEmailSubject(var IssuedReminderHeader: Record "Issued Reminder Header"; var EmailSubject: Text[250]): Boolean
    var
        ReminderEmailText: Record "Reminder Email Text";
    begin
        if not GetReminderEmailText(IssuedReminderHeader, ReminderEmailText) then
            exit(false);

        EmailSubject := ReminderEmailText.Subject;
        SubstituteRelatedValues(EmailSubject, IssuedReminderHeader, IssuedReminderHeader.CalculateTotalIncludingVAT(), CopyStr(CompanyName, 1, 100));
        exit(true);
    end;

    local procedure ReplaceHTMLText(var IssuedReminderHeader: Record "Issued Reminder Header"; var HtmlContent: Text)
    var
        ReminderEmailText: Record "Reminder Email Text";
        BodyText: Text;
    begin
        ReminderEmailText.SetAutoCalcFields("Body Text");
        if GetReminderEmailText(IssuedReminderHeader, ReminderEmailText) then
            SelectEmailBodyText(ReminderEmailText, IssuedReminderHeader, BodyText)
        else
            SelectEmailBodyText(IssuedReminderHeader, BodyText);

        SubstituteRelatedValues(BodyText, IssuedReminderHeader, IssuedReminderHeader.CalculateTotalIncludingVAT(), CopyStr(CompanyName, 1, 100));
        HtmlContent := HtmlContent.Replace(ReplaceTextTok, BodyText);
    end;

    local procedure FindFileName(var IssuedReminderHeader: Record "Issued Reminder Header"; var Filename: Text; FileExtension: Text[30]): Boolean
    var
        ReminderAttachmentText: Record "Reminder Attachment Text";
    begin
        if not GetReminderAttachmentText(IssuedReminderHeader, ReminderAttachmentText) then
            exit(false);

        if ReminderAttachmentText."File Name" = '' then
            exit(false);

        Filename := ReminderAttachmentText."File Name" + FileExtension;
        SubstituteRelatedValues(Filename, IssuedReminderHeader, IssuedReminderHeader.CalculateTotalIncludingVAT(), CopyStr(CompanyName, 1, 100));
        Filename := Filename.Replace('/', '-');
        exit(true);
    end;

    local procedure GetReminderEmailText(var IssuedReminderHeader: Record "Issued Reminder Header"; var ReminderEmailText: Record "Reminder Email Text"): Boolean
    var
        ReminderLevel: Record "Reminder Level";
        ReminderTerms: Record "Reminder Terms";
        LanguageCode: Code[10];
    begin
        if (IssuedReminderHeader."Reminder Level" = 0) or (IssuedReminderHeader."Reminder Terms Code" = '') then
            exit(false);

        if not ReminderLevel.Get(IssuedReminderHeader."Reminder Terms Code", IssuedReminderHeader."Reminder Level") then
            Error(ReminderLevelNotFoundErr, IssuedReminderHeader."Reminder Level", IssuedReminderHeader."Reminder Terms Code");

        LanguageCode := GetCustomerLanguageOrDefaultUserLanguage(IssuedReminderHeader."Customer No.");
        if TryGetReminderEmailText(ReminderLevel."Reminder Email Text", LanguageCode, ReminderEmailText) then
            exit(true);

        if not ReminderTerms.Get(IssuedReminderHeader."Reminder Terms Code") then
            Error(ReminderTermNotFoundErr, IssuedReminderHeader."Reminder Terms Code");

        if TryGetReminderEmailText(ReminderTerms."Reminder Email Text", LanguageCode, ReminderEmailText) then
            exit(true);

        exit(false);
    end;

    local procedure CalculateLineSpacingForBeginningText(var ReminderLine: Record "Reminder Line"; var ReminderAttachmentText: Record "Reminder Attachment Text"): Integer
    var
        ReminderAttachmentTextLine: Record "Reminder Attachment Text Line";
        LineSpacing: Integer;
    begin
        if ReminderLine.FindFirst() then begin
            ReminderAttachmentTextLine.SetRange(Id, ReminderAttachmentText.Id);
            ReminderAttachmentTextLine.SetRange("Language Code", ReminderAttachmentText."Language Code");
            ReminderAttachmentTextLine.SetRange(Position, ReminderAttachmentTextLine.Position::"Beginning Line");
            LineSpacing := ReminderLine."Line No." div (ReminderAttachmentTextLine.Count() + 2);
            if LineSpacing = 0 then
                Error(NoEnoughSpaceForTextErr);
        end else
            LineSpacing := 10000;

        exit(LineSpacing);
    end;

    local procedure CalculateLineSpacingForEndingText(var ReminderLine: Record "Reminder Line"; var ReminderLine2: Record "Reminder Line"; var ReminderAttachmentText: Record "Reminder Attachment Text"): Integer
    var
        ReminderAttachmentTextLine: Record "Reminder Attachment Text Line";
        LineSpacing: Integer;
    begin

        if ReminderLine2.Next() <> 0 then begin
            ReminderAttachmentTextLine.SetRange(Id, ReminderAttachmentText.Id);
            ReminderAttachmentTextLine.SetRange("Language Code", ReminderAttachmentText."Language Code");
            ReminderAttachmentTextLine.SetRange(Position, ReminderAttachmentTextLine.Position::"Ending Line");
            LineSpacing := (ReminderLine2."Line No." - ReminderLine."Line No.") div (ReminderAttachmentTextLine.Count() + 2);
            if LineSpacing = 0 then
                Error(NoEnoughSpaceForTextErr);
        end else
            LineSpacing := 10000;

        exit(LineSpacing);
    end;

    local procedure GetReminderAttachmentText(var IssuedReminderHeader: Record "Issued Reminder Header"; var ReminderAttachmentText: Record "Reminder Attachment Text"): Boolean
    var
        ReminderLevel: Record "Reminder Level";
        ReminderTerms: Record "Reminder Terms";
        LanguageCode: Code[10];
    begin
        if (IssuedReminderHeader."Reminder Level" = 0) or (IssuedReminderHeader."Reminder Terms Code" = '') then
            exit(false);

        if not ReminderLevel.Get(IssuedReminderHeader."Reminder Terms Code", IssuedReminderHeader."Reminder Level") then
            Error(ReminderLevelNotFoundErr, IssuedReminderHeader."Reminder Level", IssuedReminderHeader."Reminder Terms Code");

        LanguageCode := GetCustomerLanguageOrDefaultUserLanguage(IssuedReminderHeader."Customer No.");
        if TryGetReminderAttachmentText(ReminderLevel."Reminder Attachment Text", LanguageCode, ReminderAttachmentText) then
            exit(true);

        if not ReminderTerms.Get(IssuedReminderHeader."Reminder Terms Code") then
            Error(ReminderTermNotFoundErr, IssuedReminderHeader."Reminder Terms Code");

        if TryGetReminderAttachmentText(ReminderTerms."Reminder Attachment Text", LanguageCode, ReminderAttachmentText) then
            exit(true);

        exit(false);
    end;

    local procedure TryGetReminderAttachmentText(AttachmentTextId: Guid; LanguageCode: Code[10]; var ReminderAttachmentText: Record "Reminder Attachment Text"): Boolean
    begin
        if IsNullGuid(AttachmentTextId) then
            exit(false);

        exit(ReminderAttachmentText.Get(AttachmentTextId, LanguageCode));
    end;

    local procedure TryGetReminderEmailText(EmailTextId: Guid; LanguageCode: Code[10]; var ReminderEmailText: Record "Reminder Email Text"): Boolean
    begin
        if IsNullGuid(EmailTextId) then
            exit(false);

        exit(ReminderEmailText.Get(EmailTextId, LanguageCode));
    end;

    local procedure StripHtmlTags(HtmlText: Text): Text
    var
        Regex: Codeunit Regex;
        TypeHelper: Codeunit "Type Helper";
    begin
        // Remove HTML tags using regex (more accurate than string manipulation)
        HtmlText := Regex.Replace(HtmlText, '<.*?>', '');

        // Decode HTML entities using framework utility
        HtmlText := TypeHelper.HtmlDecode(HtmlText);

        // Clean up whitespace
        HtmlText := HtmlText.Trim();
        while HtmlText.Contains('  ') do
            HtmlText := HtmlText.Replace('  ', ' ');

        exit(HtmlText);
    end;

    var
        ReplaceTextTok: Label '==ReplaceText==', Locked = true;
        PDFFileExtensionTok: Label '.pdf', Locked = true;
        CommaSeparatedTok: Label '%1, %2', Locked = true;
        AppendixTextTok: Label '%1\\%2', Locked = true;
        ReminderLbl: Label 'Reminder';
        NoEnoughSpaceForTextErr: Label 'There is not enough space to insert the text.';
        LanguagesCustomerCommunicationsLbl: Label 'Attachments: %1\Emails: %2', Comment = '%1 = List of languages with attachment texts, %2 = List of languages with email texts';
        ReminderLevelNotFoundErr: Label 'Reminder Level %1 on Reminder Term %2 was not found.', Comment = '%1 = Reminder Level No., %2 = Reminder Term Code';
        ReminderTermNotFoundErr: Label 'Reminder Term %1 was not found.', Comment = '%1 = Reminder Term Code';
        MismatchLanguagesBetweenTermsAndLevelsMsg: Label 'The languages for the communications for the reminder terms and levels don''t match, which means that reminders won''t be personalized for some languages. Do you want to review the languages in level %1?', Comment = '%1 = List of affected reminder levels.';
        ExtensionMismatchLanguagesBetweenTermsAndLevelsMsg: Label 'There are differences among selected languages on levels also, so you might want to review those as well.';
        MismatchLanguagesBetweenLevelsMsg: Label 'The languages for the communications for the reminder levels don''t match, which means that reminders won''t be personalized for some languages. Do you want to review the languages before leaving this page?';

    [EventSubscriber(ObjectType::Table, Database::"Report Selections", 'OnAfterDoSaveReportAsHTMLInTempBlob', '', true, true)]
    local procedure OnReplaceHTMLText(ReportID: Integer; var TempBlob: Codeunit "Temp Blob"; var RecordVariant: Variant)
    var
        IssuedReminderHeader: Record "Issued Reminder Header";
        TypeHelper: Codeunit "Type Helper";
        RecordReference: RecordRef;
        ReadStream: InStream;
        WriteStream: OutStream;
        HtmlContent: Text;
        ReportIDExit: Boolean;
    begin
        if ReportID <> Report::Reminder then begin
            ReportIDExit := true;
            OnBeforeExitReportIDOnReplaceHTMLText(ReportID, RecordVariant, ReportIDExit);
            if ReportIDExit then
                exit;
        end;
        if not RecordVariant.IsRecordRef() then
            exit;

        RecordReference.GetTable(RecordVariant);
        if RecordReference.Number <> IssuedReminderHeader.RecordId.TableNo then
            exit;
        IssuedReminderHeader.Copy(RecordVariant);

        TempBlob.CreateInStream(ReadStream, TextEncoding::UTF8);
        TypeHelper.TryReadAsTextWithSeparator(ReadStream, TypeHelper.LFSeparator(), HtmlContent);
        Clear(ReadStream);
        Clear(TempBlob);

        ReplaceHTMLText(IssuedReminderHeader, HtmlContent);

        TempBlob.CreateOutStream(WriteStream, TextEncoding::UTF8);
        WriteStream.WriteText(HtmlContent);
    end;

    [EventSubscriber(ObjectType::Codeunit, Codeunit::"Document-Mailing", 'OnBeforeGetEmailSubject', '', true, true)]
    local procedure OnBeforeGetEmailSubject(PostedDocNo: Code[20]; EmailDocumentName: Text[250]; ReportUsage: Integer; var EmailSubject: Text[250]; var IsHandled: Boolean)
    var
        IssuedReminderHeader: Record "Issued Reminder Header";
        ReportDistributionManagement: Codeunit "Report Distribution Management";
    begin
        if IsHandled or (EmailSubject <> '') then
            exit;

        if ReportUsage <> Enum::"Report Selection Usage"::Reminder.AsInteger() then
            exit;

        if EmailDocumentName <> ReportDistributionManagement.GetIssuedReminderDocTypeTxt() then
            exit;

        if not IssuedReminderHeader.Get(PostedDocNo) then
            exit;

        if FindEmailSubject(IssuedReminderHeader, EmailSubject) then
            IsHandled := true;
    end;

    [EventSubscriber(ObjectType::Codeunit, Codeunit::ReportManagement, 'OnGetFilename', '', false, false)]
    local procedure GetFilename(ReportID: Integer; Caption: Text[250]; ObjectPayload: JsonObject; FileExtension: Text[30]; ReportRecordRef: RecordRef; var Filename: Text; var Success: Boolean)
    var
        IssuedReminderHeader: Record "Issued Reminder Header";
    begin
        if Success then
            exit;

        if ReportID <> Report::Reminder then
            exit;

        if (FileExtension <> PDFFileExtensionTok) or (not Filename.Contains(ReminderLbl)) then
            exit;

        if ReportRecordRef.Number <> IssuedReminderHeader.RecordId.TableNo then
            exit;
        ReportRecordRef.SetTable(IssuedReminderHeader);

        if FindFileName(IssuedReminderHeader, Filename, FileExtension) then
            Success := true;
    end;

    [EventSubscriber(ObjectType::Codeunit, Codeunit::"Document-Mailing", 'OnBeforeGetAttachmentFileName', '', false, false)]
    local procedure OnBeforeGetAttachmentFileName(PostedDocNo: Code[20]; ReportUsage: Integer; var AttachmentFileName: Text[250])
    var
        IssuedReminderHeader: Record "Issued Reminder Header";
    begin
        if ReportUsage <> "Report Selection Usage"::Reminder.AsInteger() then
            exit;

        if not IssuedReminderHeader.Get(PostedDocNo) then
            exit;

        if not FindFileName(IssuedReminderHeader, AttachmentFileName, PDFFileExtensionTok) then
            exit;
    end;

    [IntegrationEvent(false, false)]
    local procedure OnBeforeExitReportIDOnReplaceHTMLText(ReportID: Integer; var RecordVariant: Variant; var ReportIDExit: Boolean)
    begin
    end;

    [IntegrationEvent(false, false)]
    local procedure OnAfterSubstituteRelatedValues(var BodyTxt: Text; var IssuedReminderHeader: Record "Issued Reminder Header")
    begin
    end;

    [IntegrationEvent(false, false)]
    local procedure OnTransferReminderTextOnBeforeInsertBeginningReminderAttachmentTextLine(var ReminderText: Record "Reminder Text"; var ReminderAttachmentTextLine: Record "Reminder Attachment Text Line")
    begin
    end;

    [IntegrationEvent(false, false)]
    local procedure OnTransferReminderTextOnBeforeInsertEndingReminderAttachmentTextLine(var ReminderText: Record "Reminder Text"; var ReminderAttachmentTextLine: Record "Reminder Attachment Text Line")
    begin
    end;
}