Page 232 Apply Customer Entries

App
Base Application
Namespace
Microsoft.Sales.Receivables
Versions
17-28
Source table
21

Procedures, 21Events, 56Obsolete, 6

Versions171819202122232425262728

Source29

Source in 29

src/Layers/W1/BaseApp/Sales/Receivables/ApplyCustomerEntries.Page.al2061 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.Receivables;

using Microsoft.Finance.Currency;
using Microsoft.Finance.Dimension;
using Microsoft.Finance.GeneralLedger.Journal;
using Microsoft.Finance.GeneralLedger.Setup;
using Microsoft.Finance.ReceivablesPayables;
using Microsoft.Foundation.Navigate;
using Microsoft.Sales.Customer;
using Microsoft.Sales.Document;
using Microsoft.Sales.FinanceCharge;
using Microsoft.Sales.Posting;
using Microsoft.Sales.Setup;

/// <summary>
/// Displays open customer ledger entries and enables users to select and apply payments to invoices.
/// </summary>
page 232 "Apply Customer Entries"
{
    Caption = 'Apply Customer Entries';
    DataCaptionFields = "Customer No.";
    DeleteAllowed = false;
    InsertAllowed = false;
    LinksAllowed = false;
    PageType = Worksheet;
    SourceTable = "Cust. Ledger Entry";

    layout
    {
        area(content)
        {
            group(General)
            {
                Caption = 'General';
#pragma warning disable AA0100
                field("ApplyingCustLedgEntry.""Posting Date"""; TempApplyingCustLedgEntry."Posting Date")
#pragma warning restore AA0100
                {
                    ApplicationArea = Basic, Suite;
                    Caption = 'Posting Date';
                    Editable = false;
                    ToolTip = 'Specifies the posting date of the entry to be applied. This date is used to find the correct exchange rate when applying entries in different currencies.';
                }
#pragma warning disable AA0100
                field("ApplyingCustLedgEntry.""Document Type"""; TempApplyingCustLedgEntry."Document Type")
#pragma warning restore AA0100
                {
                    ApplicationArea = Basic, Suite;
                    Caption = 'Document Type';
                    Editable = false;
                    ToolTip = 'Specifies the document type of the entry to be applied.';
                }
#pragma warning disable AA0100
                field("ApplyingCustLedgEntry.""Document No."""; TempApplyingCustLedgEntry."Document No.")
#pragma warning restore AA0100
                {
                    ApplicationArea = Basic, Suite;
                    Caption = 'Document No.';
                    Editable = false;
                    ToolTip = 'Specifies the document number of the entry to be applied.';
                }
                field(ApplyingCustomerNo; TempApplyingCustLedgEntry."Customer No.")
                {
                    ApplicationArea = Basic, Suite;
                    Caption = 'Customer No.';
                    Editable = false;
                    ToolTip = 'Specifies the customer number of the entry to be applied.';
                    Visible = false;
                }
                field(ApplyingCustomerName; TempApplyingCustLedgEntry."Customer Name")
                {
                    ApplicationArea = Basic, Suite;
                    Caption = 'Customer Name';
                    Editable = false;
                    ToolTip = 'Specifies the customer name of the entry to be applied.';
                    Visible = CustNameVisible;
                }
                field(ApplyingDescription; TempApplyingCustLedgEntry.Description)
                {
                    ApplicationArea = Basic, Suite;
                    Caption = 'Description';
                    Editable = false;
                    ToolTip = 'Specifies the description of the entry to be applied.';
                    Visible = false;
                }
#pragma warning disable AA0100
                field("ApplyingCustLedgEntry.""Currency Code"""; TempApplyingCustLedgEntry."Currency Code")
#pragma warning restore AA0100
                {
                    ApplicationArea = Suite;
                    Caption = 'Currency Code';
                    Editable = false;
                    ToolTip = 'Specifies the code for the currency that amounts are shown in.';
                }
                field("ApplyingCustLedgEntry.Amount"; TempApplyingCustLedgEntry.Amount)
                {
                    ApplicationArea = Basic, Suite;
                    Caption = 'Amount';
                    Editable = false;
                    ToolTip = 'Specifies the amount on the entry to be applied.';
                }
#pragma warning disable AA0100
                field("ApplyingCustLedgEntry.""Remaining Amount"""; TempApplyingCustLedgEntry."Remaining Amount")
#pragma warning restore AA0100
                {
                    ApplicationArea = Basic, Suite;
                    Caption = 'Remaining Amount';
                    Editable = false;
                    ToolTip = 'Specifies the amount on the entry to be applied.';
                }
            }
            repeater(Control1)
            {
                ShowCaption = false;
                field(AppliesToID; Rec."Applies-to ID")
                {
                    ApplicationArea = All;
                    Visible = AppliesToIDVisible;

                    trigger OnValidate()
                    begin
                        if Rec."Applies-to ID" = xRec."Applies-to ID" then
                            exit;

                        if (CalcType = CalcType::"Gen. Jnl. Line") and (ApplnType = ApplnType::"Applies-to Doc. No.") then
                            Error(CannotSetAppliesToIDErr);

                        SetCustApplId(true);
                        Rec.Get(Rec."Entry No.");
                        if Rec."Applies-to ID" <> '' then
                            UpdateCustomAppliesToIDForGenJournal(Rec."Applies-to ID");

                        CurrPage.Update(false);
                    end;
                }
                field("Posting Date"; Rec."Posting Date")
                {
                    ApplicationArea = Basic, Suite;
                    Editable = false;
                }
                field("Document Type"; Rec."Document Type")
                {
                    ApplicationArea = Basic, Suite;
                    Editable = false;
                    StyleExpr = StyleTxt;
                }
                field("Document No."; Rec."Document No.")
                {
                    ApplicationArea = Basic, Suite;
                    Editable = false;
                    StyleExpr = StyleTxt;
                }
                field(Prepayment; Rec.Prepayment)
                {
                    ApplicationArea = Prepayments;
                    Editable = false;
                }
                field("Customer No."; Rec."Customer No.")
                {
                    ApplicationArea = Basic, Suite;
                    Editable = false;
                }
                field("Customer Name"; Rec."Customer Name")
                {
                    ApplicationArea = Basic, Suite;
                    Editable = false;
                    Visible = CustNameVisible;
                }
                field(Description; Rec.Description)
                {
                    ApplicationArea = Basic, Suite;
                    Editable = false;
                }
                field("Currency Code"; Rec."Currency Code")
                {
                    ApplicationArea = Suite;
                }
                field("Original Amount"; Rec."Original Amount")
                {
                    ApplicationArea = Basic, Suite;
                    Editable = false;
                    Visible = false;
                }
                field(Amount; Rec.Amount)
                {
                    ApplicationArea = Basic, Suite;
                    Editable = false;
                    Visible = false;
                }
                field("Debit Amount"; Rec."Debit Amount")
                {
                    ApplicationArea = Basic, Suite;
                    Visible = false;
                }
                field("Credit Amount"; Rec."Credit Amount")
                {
                    ApplicationArea = Basic, Suite;
                    Visible = false;
                }
                field("Remaining Amount"; Rec."Remaining Amount")
                {
                    ApplicationArea = Basic, Suite;
                    Editable = false;
                }
#pragma warning disable AA0100
                field("CalcApplnRemainingAmount(""Remaining Amount"")"; CalcApplnRemainingAmount(Rec."Remaining Amount"))
#pragma warning restore AA0100
                {
                    ApplicationArea = Basic, Suite;
                    AutoFormatExpression = ApplnCurrencyCode;
                    AutoFormatType = 1;
                    Caption = 'Appln. Remaining Amount';
                    ToolTip = 'Specifies the amount that remains to be applied to before the entry is totally applied to.';
                }
                field("Amount to Apply"; Rec."Amount to Apply")
                {
                    ApplicationArea = Basic, Suite;
                    trigger OnValidate()
                    begin
                        CODEUNIT.Run(CODEUNIT::"Cust. Entry-Edit", Rec);

                        if (xRec."Amount to Apply" = 0) or (Rec."Amount to Apply" = 0) and
                           ((ApplnType = ApplnType::"Applies-to ID") or (CalcType = CalcType::Direct))
                        then
                            SetCustApplId(false);
                        Rec.Get(Rec."Entry No.");
                        AmountToApplyOnAfterValidate();
                    end;
                }
                field(ApplnAmountToApply; CalcApplnAmountToApply(Rec."Amount to Apply"))
                {
                    ApplicationArea = Basic, Suite;
                    AutoFormatExpression = ApplnCurrencyCode;
                    AutoFormatType = 1;
                    Caption = 'Appln. Amount to Apply';
                    ToolTip = 'Specifies the amount to apply.';
                }
                field("Due Date"; Rec."Due Date")
                {
                    ApplicationArea = Basic, Suite;
                    StyleExpr = StyleTxt;
                }
                field("Pmt. Discount Date"; Rec."Pmt. Discount Date")
                {
                    ApplicationArea = Basic, Suite;
                    trigger OnValidate()
                    begin
                        RecalcApplnAmount();
                    end;
                }
                field("Pmt. Disc. Tolerance Date"; Rec."Pmt. Disc. Tolerance Date")
                {
                    ApplicationArea = Basic, Suite;
                }
                field("Original Pmt. Disc. Possible"; Rec."Original Pmt. Disc. Possible")
                {
                    ApplicationArea = Basic, Suite;
                    Visible = false;
                }
                field("Remaining Pmt. Disc. Possible"; Rec."Remaining Pmt. Disc. Possible")
                {
                    ApplicationArea = Basic, Suite;
                    trigger OnValidate()
                    begin
                        RecalcApplnAmount();
                    end;
                }
#pragma warning disable AA0100
                field("CalcApplnRemainingAmount(""Remaining Pmt. Disc. Possible"")"; CalcApplnRemainingAmount(Rec."Remaining Pmt. Disc. Possible"))
#pragma warning restore AA0100
                {
                    ApplicationArea = Basic, Suite;
                    AutoFormatExpression = ApplnCurrencyCode;
                    AutoFormatType = 1;
                    Caption = 'Appln. Pmt. Disc. Possible';
                    ToolTip = 'Specifies the discount that the customer can obtain if the entry is applied to before the payment discount date.';
                }
                field("Max. Payment Tolerance"; Rec."Max. Payment Tolerance")
                {
                    ApplicationArea = Basic, Suite;
                }
                field("External Document No."; Rec."External Document No.")
                {
                    ApplicationArea = Basic, Suite;
                    Editable = false;
                    Visible = false;
                }
                field("Your Reference"; Rec."Your Reference")
                {
                    ApplicationArea = Basic, Suite;
                    Editable = false;
                    Visible = false;
                }
                field(Open; Rec.Open)
                {
                    ApplicationArea = Basic, Suite;
                    Editable = false;
                }
                field(Positive; Rec.Positive)
                {
                    ApplicationArea = Basic, Suite;
                    Editable = false;
                }
                field("Global Dimension 1 Code"; Rec."Global Dimension 1 Code")
                {
                    ApplicationArea = Dimensions;
                }
                field("Global Dimension 2 Code"; Rec."Global Dimension 2 Code")
                {
                    ApplicationArea = Dimensions;
                }
            }
            group(Control41)
            {
                ShowCaption = false;
                fixed(Control1903222401)
                {
                    ShowCaption = false;
                    group("Appln. Currency")
                    {
                        Caption = 'Appln. Currency';
                        field(ApplnCurrencyCode; ApplnCurrencyCode)
                        {
                            ApplicationArea = Suite;
                            Editable = false;
                            ShowCaption = false;
                            TableRelation = Currency;
                            ToolTip = 'Specifies the currency code that the amount will be applied in, in case of different currencies.';
                        }
                    }
                    group(Control1903098801)
                    {
                        Caption = 'Amount to Apply';
                        field(AmountToApply; AppliedAmount)
                        {
                            ApplicationArea = Basic, Suite;
                            AutoFormatExpression = ApplnCurrencyCode;
                            AutoFormatType = 1;
                            Caption = 'Amount to Apply';
                            Editable = false;
                            ToolTip = 'Specifies the sum of the amounts on all the selected customer ledger entries that will be applied by the entry shown in the Available Amount field. The amount is in the currency represented by the code in the Currency Code field.';
                        }
                    }
                    group("Pmt. Disc. Amount")
                    {
                        Caption = 'Pmt. Disc. Amount';
                        field(PmtDiscountAmount; -PmtDiscAmount)
                        {
                            ApplicationArea = Basic, Suite;
                            AutoFormatExpression = ApplnCurrencyCode;
                            AutoFormatType = 1;
                            Caption = 'Pmt. Disc. Amount';
                            Editable = false;
                            ToolTip = 'Specifies the sum of the payment discount amounts granted on all the selected customer ledger entries that will be applied by the entry shown in the Available Amount field. The amount is in the currency represented by the code in the Currency Code field.';
                        }
                    }
                    group(Rounding)
                    {
                        Caption = 'Rounding';
                        field(ApplnRounding; ApplnRounding)
                        {
                            ApplicationArea = Basic, Suite;
                            AutoFormatExpression = ApplnCurrencyCode;
                            AutoFormatType = 1;
                            Caption = 'Rounding';
                            Editable = false;
                            ToolTip = 'Specifies the rounding difference when you apply entries in different currencies to one another. The amount is in the currency represented by the code in the Currency Code field.';
                        }
                    }
                    group("Applied Amount")
                    {
                        Caption = 'Applied Amount';
                        field(AppliedAmount; AppliedAmount + (-PmtDiscAmount) + ApplnRounding)
                        {
                            ApplicationArea = Basic, Suite;
                            AutoFormatExpression = ApplnCurrencyCode;
                            AutoFormatType = 1;
                            Caption = 'Applied Amount';
                            Editable = false;
                            ToolTip = 'Specifies the sum of the amounts in the Amount to Apply field, Pmt. Disc. Amount field, and the Rounding. The amount is in the currency represented by the code in the Currency Code field.';
                        }
                    }
                    group("Available Amount")
                    {
                        Caption = 'Available Amount';
                        field(ApplyingAmount; ApplyingAmount)
                        {
                            ApplicationArea = Basic, Suite;
                            AutoFormatExpression = ApplnCurrencyCode;
                            AutoFormatType = 1;
                            Caption = 'Available Amount';
                            Editable = false;
                            ToolTip = 'Specifies the amount of the journal entry, sales credit memo, or current customer ledger entry that you have selected as the applying entry.';
                        }
                    }
                    group(Balance)
                    {
                        Caption = 'Balance';
                        field(ControlBalance; AppliedAmount + (-PmtDiscAmount) + ApplyingAmount + ApplnRounding)
                        {
                            ApplicationArea = Basic, Suite;
                            AutoFormatExpression = ApplnCurrencyCode;
                            AutoFormatType = 1;
                            Caption = 'Balance';
                            Editable = false;
                            ToolTip = 'Specifies any extra amount that will remain after the application.';
                        }
                    }
                }
            }
        }
        area(factboxes)
        {
            part(Control1903096107; "Customer Ledger Entry FactBox")
            {
                ApplicationArea = Basic, Suite;
                SubPageLink = "Entry No." = field("Entry No.");
                Visible = true;
            }
        }
    }

    actions
    {
        area(navigation)
        {
            group("Ent&ry")
            {
                Caption = 'Ent&ry';
                Image = Entry;
                action("Reminder/Fin. Charge Entries")
                {
                    ApplicationArea = Suite;
                    Caption = 'Reminder/Fin. Charge Entries';
                    Image = Reminder;
                    RunObject = Page "Reminder/Fin. Charge Entries";
                    RunPageLink = "Customer Entry No." = field("Entry No.");
                    RunPageView = sorting("Customer Entry No.");
                    ToolTip = 'View the reminders and finance charge entries that you have entered for the customer.';
                }
                action("Applied E&ntries")
                {
                    ApplicationArea = Basic, Suite;
                    Caption = 'Applied E&ntries';
                    Image = Approve;
                    RunObject = Page "Applied Customer Entries";
                    RunPageOnRec = true;
                    ToolTip = 'View the ledger entries that have been applied to this record.';
                }
                action(Dimensions)
                {
                    AccessByPermission = TableData Dimension = R;
                    ApplicationArea = Dimensions;
                    Caption = 'Dimensions';
                    Image = Dimensions;
                    ShortCutKey = 'Alt+D';
                    ToolTip = 'View or edit dimensions, such as area, project, or department, that you can assign to sales and purchase documents to distribute costs and analyze transaction history.';

                    trigger OnAction()
                    begin
                        Rec.ShowDimensions();
                    end;
                }
                action("Detailed &Ledger Entries")
                {
                    ApplicationArea = Basic, Suite;
                    Caption = 'Detailed &Ledger Entries';
                    Image = View;
                    RunObject = Page "Detailed Cust. Ledg. Entries";
                    RunPageLink = "Cust. Ledger Entry No." = field("Entry No.");
                    RunPageView = sorting("Cust. Ledger Entry No.", "Posting Date");
                    ShortCutKey = 'Ctrl+F7';
                    ToolTip = 'View a summary of the all posted entries and adjustments related to a specific customer ledger entry.';
                }
                action("&Navigate")
                {
                    ApplicationArea = Basic, Suite;
                    Caption = 'Find entries...';
                    Image = Navigate;
                    ShortCutKey = 'Ctrl+Alt+Q';
                    ToolTip = 'Find entries and documents that exist for the document number and posting date on the selected document. (Formerly this action was named Navigate.)';

                    trigger OnAction()
                    begin
                        Navigate.SetDoc(Rec."Posting Date", Rec."Document No.");
                        Navigate.Run();
                    end;
                }
            }
        }
        area(processing)
        {
            group("&Application")
            {
                Caption = '&Application';
                Image = Apply;
                action("Set Applies-to ID")
                {
                    ApplicationArea = Basic, Suite;
                    Visible = AppliesToIDVisible;
                    Caption = 'Set Applies-to ID';
                    Image = SelectLineToApply;
                    ShortCutKey = 'Shift+F11';
                    ToolTip = 'Set the Applies-to ID field on the posted entry to automatically be filled in with the document number of the entry in the journal.';

                    trigger OnAction()
                    begin
                        if (CalcType = CalcType::"Gen. Jnl. Line") and (ApplnType = ApplnType::"Applies-to Doc. No.") then
                            Error(CannotSetAppliesToIDErr);

                        SetCustApplId(false);
                    end;
                }
                action("Post Application")
                {
                    ApplicationArea = Basic, Suite;
                    Visible = CalledFromEntry;
                    Caption = 'Post Application';
                    Ellipsis = true;
                    Image = PostApplication;
                    ShortCutKey = 'F9';
                    ToolTip = 'Define the document number of the ledger entry to use to perform the application. In addition, you specify the Posting Date for the application.';

                    trigger OnAction()
                    begin
                        PostDirectApplication(false);
                    end;
                }
                action(Preview)
                {
                    ApplicationArea = Basic, Suite;
                    Visible = CalledFromEntry;
                    Caption = 'Preview Posting';
                    Image = ViewPostedOrder;
                    ShortCutKey = 'Ctrl+Alt+F9';
                    ToolTip = 'Review the different types of entries that will be created when you post the document or journal.';

                    trigger OnAction()
                    begin
                        PostDirectApplication(true);
                    end;
                }
                separator("-")
                {
                    Caption = '-';
                }
                action("Show Only Selected Entries to Be Applied")
                {
                    ApplicationArea = Basic, Suite;
                    Caption = 'Show Only Selected Entries to Be Applied';
                    Image = ShowSelected;
                    ToolTip = 'View the selected ledger entries that will be applied to the specified record.';

                    trigger OnAction()
                    begin
                        ShowAppliedEntries := not ShowAppliedEntries;
                        if ShowAppliedEntries then
                            if CalcType = CalcType::"Gen. Jnl. Line" then
                                Rec.SetRange("Applies-to ID", GenJnlLine."Applies-to ID")
                            else begin
                                CustEntryApplID := UserId;
                                if CustEntryApplID = '' then
                                    CustEntryApplID := '***';
                                Rec.SetRange("Applies-to ID", CustEntryApplID);
                            end
                        else
                            Rec.SetRange("Applies-to ID");
                    end;
                }
            }
            action(ShowPostedDocument)
            {
                ApplicationArea = Basic, Suite;
                Caption = 'Show Posted Document';
                Image = Document;
                ToolTip = 'Show details for the posted payment, invoice, or credit memo.';

                trigger OnAction()
                begin
                    Rec.ShowDoc();
                end;
            }
            action(ShowDocumentAttachment)
            {
                ApplicationArea = Basic, Suite;
                Caption = 'Show Document Attachment';
                Enabled = HasDocumentAttachment;
                Image = Attach;
                ToolTip = 'View documents or images that are attached to the posted invoice or credit memo.';

                trigger OnAction()
                begin
                    Rec.ShowPostedDocAttachment();
                end;
            }
        }
        area(Promoted)
        {
            group(Category_Process)
            {
                Caption = 'Process', Comment = 'Generated from the PromotedActionCategories property index 1.';

                actionref("Set Applies-to ID_Promoted"; "Set Applies-to ID")
                {
                }
                actionref("Post Application_Promoted"; "Post Application")
                {
                }
                actionref(Preview_Promoted; Preview)
                {
                }
                actionref("Show Only Selected Entries to Be Applied_Promoted"; "Show Only Selected Entries to Be Applied")
                {
                }
                group(Category_Category4)
                {
                    Caption = 'Line', Comment = 'Generated from the PromotedActionCategories property index 3.';
                    ShowAs = SplitButton;

                    actionref(ShowPostedDocument_Promoted; ShowPostedDocument)
                    {
                    }
                    actionref(ShowDocumentAttachment_Promoted; ShowDocumentAttachment)
                    {
                    }
                }
            }
            group(Category_Report)
            {
                Caption = 'Report', Comment = 'Generated from the PromotedActionCategories property index 2.';
            }
            group(Category_Category5)
            {
                Caption = 'Entry', Comment = 'Generated from the PromotedActionCategories property index 4.';

                actionref("&Navigate_Promoted"; "&Navigate")
                {
                }
                actionref(Dimensions_Promoted; Dimensions)
                {
                }
                actionref("Reminder/Fin. Charge Entries_Promoted"; "Reminder/Fin. Charge Entries")
                {
                }
                actionref("Applied E&ntries_Promoted"; "Applied E&ntries")
                {
                }
                actionref("Detailed &Ledger Entries_Promoted"; "Detailed &Ledger Entries")
                {
                }
            }
        }
    }

    trigger OnAfterGetCurrRecord()
    begin
        if ApplnType = ApplnType::"Applies-to Doc. No." then
            CalcApplnAmount();
        HasDocumentAttachment := Rec.HasPostedDocAttachment();
    end;

    trigger OnAfterGetRecord()
    begin
        StyleTxt := Rec.SetStyle();
    end;

    trigger OnInit()
    begin
        AppliesToIDVisible := true;
    end;

    trigger OnModifyRecord(): Boolean
    begin
        CODEUNIT.Run(CODEUNIT::"Cust. Entry-Edit", Rec);
        if Rec."Applies-to ID" <> xRec."Applies-to ID" then
            CalcApplnAmount();
        exit(false);
    end;

    trigger OnOpenPage()
    begin
        if CalcType = CalcType::Direct then begin
            Cust.Get(Rec."Customer No.");
            ApplnCurrencyCode := Cust."Currency Code";
            FindApplyingEntry();
        end;

        ActivateFields();

        SalesSetup.Get();
        CustNameVisible := SalesSetup."Copy Customer Name to Entries";

        AppliesToIDVisible := ApplnType <> ApplnType::"Applies-to Doc. No.";

        GLSetup.Get();

        if ApplnType = ApplnType::"Applies-to Doc. No." then
            CalcApplnAmount();
        PostingDone := false;

        OnAfterOnOpenPage(GenJnlLine, Rec, TempApplyingCustLedgEntry);
    end;

    trigger OnQueryClosePage(CloseAction: Action): Boolean
    var
        RaiseError: Boolean;
    begin
        if CloseAction = ACTION::LookupOK then
            LookupOKOnPush();
        if ApplnType = ApplnType::"Applies-to Doc. No." then begin
            if OK then begin
                RaiseError := TempApplyingCustLedgEntry."Posting Date" < Rec."Posting Date";
                OnBeforeEarlierPostingDateError(TempApplyingCustLedgEntry, Rec, RaiseError, CalcType.AsInteger(), OK);
                if RaiseError then begin
                    OK := false;
                    Error(
                      EarlierPostingDateErr, TempApplyingCustLedgEntry."Document Type", TempApplyingCustLedgEntry."Document No.",
                      Rec."Document Type", Rec."Document No.");
                end;
                OnQueryClosePageOnAfterEarlierPostingDateTest(TempApplyingCustLedgEntry, Rec, CalcType, OK);
            end;
            if OK then begin
                if Rec."Amount to Apply" = 0 then
                    Rec."Amount to Apply" := Rec."Remaining Amount";
                CODEUNIT.Run(CODEUNIT::"Cust. Entry-Edit", Rec);
            end;
        end;
        if (CalcType = CalcType::Direct) and not OK and not PostingDone then begin
            Rec := TempApplyingCustLedgEntry;
            Rec."Applying Entry" := false;
            if AppliesToID = '' then begin
                Rec."Applies-to ID" := '';
                Rec."Amount to Apply" := 0;
            end;

            OnOnQueryClosePageOnBeforeRunCustEntryEdit(Rec);
            CODEUNIT.Run(CODEUNIT::"Cust. Entry-Edit", Rec);
        end;
    end;

    var
        Cust: Record Customer;
        GLSetup: Record "General Ledger Setup";
        SalesSetup: Record "Sales & Receivables Setup";
        TotalSalesLine: Record "Sales Line";
        TotalSalesLineLCY: Record "Sales Line";
        CustEntrySetApplID: Codeunit "Cust. Entry-SetAppl.ID";
        GenJnlApply: Codeunit "Gen. Jnl.-Apply";
        SalesPost: Codeunit "Sales-Post";
        PaymentToleranceMgt: Codeunit "Payment Tolerance Management";
        Navigate: Page Navigate;
        StyleTxt: Text;
        AppliesToID: Code[50];
        CustomAppliesToID: Code[50];
        TimesSetCustomAppliesToID: Integer;
        ValidExchRate: Boolean;
        MustSelectEntryErr: Label 'You must select an applying entry before you can post the application.';
        PostingInWrongContextErr: Label 'You must post the application from the window where you entered the applying entry.';
        CannotSetAppliesToIDErr: Label 'You cannot set Applies-to ID while selecting Applies-to Doc. No.';
        ShowAppliedEntries: Boolean;
        CalledFromEntry: Boolean;
        EarlierPostingDateErr: Label 'You cannot apply and post an entry to an entry with an earlier posting date.\\Instead, post the document of type %1 with the number %2 and then apply it to the document of type %3 with the number %4.', Comment = '%1 - document type, %2 - document number,%3 - document type,%4 - document number';
        ApplicationPostedMsg: Label 'The application was successfully posted.';
#pragma warning disable AA0470
        ApplicationDateErr: Label 'The %1 entered must not be before the %1 on the %2.';
#pragma warning restore AA0470
        HasDocumentAttachment: Boolean;
        CustNameVisible: Boolean;
        GenJnlLineApply: Boolean;

    protected var
        Currency: Record Currency;
        CurrExchRate: Record "Currency Exchange Rate";
        CustLedgEntry: Record "Cust. Ledger Entry";
        TempApplyingCustLedgEntry: Record "Cust. Ledger Entry" temporary;
        AppliedCustLedgEntry: Record "Cust. Ledger Entry";
        GenJnlLine: Record "Gen. Journal Line";
        GenJnlLine2: Record "Gen. Journal Line";
        SalesHeader: Record "Sales Header";
        ApplnDate: Date;
        ApplnRoundingPrecision: Decimal;
        ApplnRounding: Decimal;
        ApplnType: Enum "Customer Apply-to Type";
        AmountRoundingPrecision: Decimal;
        VATAmount: Decimal;
        VATAmountText: Text[30];
        AppliedAmount: Decimal;
        ApplyingAmount: Decimal;
        PmtDiscAmount: Decimal;
        ApplnCurrencyCode: Code[10];
        CustEntryApplID: Code[50];
        AppliesToIDVisible: Boolean;
        DifferentCurrenciesInAppln: Boolean;
        PostingDone: Boolean;
        ProfitLCY: Decimal;
        ProfitPct: Decimal;
        CalcType: Enum "Customer Apply Calculation Type";
        OK: Boolean;

    /// <summary>
    /// Sets up the page to apply entries from a general journal line context.
    /// </summary>
    /// <param name="NewGenJnlLine">The general journal line from which to apply entries.</param>
    /// <param name="ApplnTypeSelect">The field number indicating the application type selection.</param>
    procedure SetGenJnlLine(NewGenJnlLine: Record "Gen. Journal Line"; ApplnTypeSelect: Integer)
    begin
        GenJnlLine := NewGenJnlLine;
        GenJnlLineApply := true;

        if GenJnlLine."Account Type" = GenJnlLine."Account Type"::Customer then
            ApplyingAmount := GenJnlLine.Amount;
        if GenJnlLine."Bal. Account Type" = GenJnlLine."Bal. Account Type"::Customer then
            ApplyingAmount := -GenJnlLine.Amount;
        ApplnDate := GenJnlLine."Posting Date";
        ApplnCurrencyCode := GenJnlLine."Currency Code";
        CalcType := CalcType::"Gen. Jnl. Line";

        case ApplnTypeSelect of
            GenJnlLine.FieldNo("Applies-to Doc. No."):
                ApplnType := ApplnType::"Applies-to Doc. No.";
            GenJnlLine.FieldNo("Applies-to ID"):
                ApplnType := ApplnType::"Applies-to ID";
        end;

        SetApplyingCustLedgEntry();
    end;

    /// <summary>
    /// Sets up the page to apply entries from a sales header document context.
    /// </summary>
    /// <param name="NewSalesHeader">The sales header document from which to apply entries.</param>
    /// <param name="NewCustLedgEntry">The customer ledger entry filters to apply.</param>
    /// <param name="ApplnTypeSelect">The field number indicating the application type selection.</param>
    procedure SetSales(NewSalesHeader: Record "Sales Header"; var NewCustLedgEntry: Record "Cust. Ledger Entry"; ApplnTypeSelect: Integer)
    var
        TotalAdjCostLCY: Decimal;
    begin
        SalesHeader := NewSalesHeader;
        Rec.CopyFilters(NewCustLedgEntry);

        SalesPost.SumSalesLines(
          SalesHeader, 0, TotalSalesLine, TotalSalesLineLCY,
          VATAmount, VATAmountText, ProfitLCY, ProfitPct, TotalAdjCostLCY);

        case SalesHeader."Document Type" of
            SalesHeader."Document Type"::"Return Order",
          SalesHeader."Document Type"::"Credit Memo":
                ApplyingAmount := -TotalSalesLine."Amount Including VAT"
            else
                ApplyingAmount := TotalSalesLine."Amount Including VAT";
        end;

        ApplnDate := SalesHeader."Posting Date";
        ApplnCurrencyCode := SalesHeader."Currency Code";
        CalcType := CalcType::"Sales Header";

        case ApplnTypeSelect of
            SalesHeader.FieldNo("Applies-to Doc. No."):
                ApplnType := ApplnType::"Applies-to Doc. No.";
            SalesHeader.FieldNo("Applies-to ID"):
                ApplnType := ApplnType::"Applies-to ID";
        end;

        SetApplyingCustLedgEntry();
    end;


    /// <summary>
    /// Sets the current record to the specified customer ledger entry.
    /// </summary>
    /// <param name="NewCustLedgEntry">The customer ledger entry to set as the current record.</param>
    procedure SetCustLedgEntry(NewCustLedgEntry: Record "Cust. Ledger Entry")
    begin
        Rec := NewCustLedgEntry;
    end;

    /// <summary>
    /// Initializes the applying customer ledger entry based on the current calculation type.
    /// </summary>
    procedure SetApplyingCustLedgEntry()
    var
        IsHandled: Boolean;
    begin
        IsHandled := false;
        OnBeforeSetApplyingCustLedgerEntry(TempApplyingCustLedgEntry, GenJnlLine, SalesHeader, CalcType, IsHandled);
        if not IsHandled then begin
            case CalcType of
                CalcType::"Sales Header":
                    SetApplyingCustledgEntrySalesHeader();
                CalcType::"Gen. Jnl. Line":
                    SetApplyingCustLedgEntryGenJnlLine();
                CalcType::Direct:
                    SetApplyingCustLedgEntryDirect();
            end;

            CalcApplnAmount();
        end;

        OnAfterSetApplyingCustLedgEntry(TempApplyingCustLedgEntry, GenJnlLine, SalesHeader);
    end;

    /// <summary>
    /// Gets the custom Applies-to ID if it was set exactly once during the session.
    /// </summary>
    /// <returns>The custom Applies-to ID or an empty string if not set or set multiple times.</returns>
    internal procedure GetCustomAppliesToID(): Code[50]
    begin
        if TimesSetCustomAppliesToID <> 1 then
            exit('');
        exit(CustomAppliesToID);
    end;

    local procedure UpdateCustomAppliesToIDForGenJournal(NewAppliesToID: Code[50])
    begin
        if (not GenJnlLineApply) or (ApplnType <> ApplnType::"Applies-to ID") then
            exit;
        if JournalHasDocumentNo(NewAppliesToID) then
            exit;
        if (CustomAppliesToID = '') or ((CustomAppliesToID <> '') and (CustomAppliesToID <> NewAppliesToID)) then
            TimesSetCustomAppliesToID += 1;

        CustomAppliesToID := NewAppliesToID;
    end;

    local procedure JournalHasDocumentNo(AppliesToIDCode: Code[50]): Boolean
    var
        GenJournalLine: Record "Gen. Journal Line";
    begin
        GenJournalLine.SetRange("Journal Template Name", GenJnlLine."Journal Template Name");
        GenJournalLine.SetRange("Journal Batch Name", GenJnlLine."Journal Batch Name");
        GenJournalLine.SetRange("Document No.", CopyStr(AppliesToIDCode, 1, MaxStrLen(GenJournalLine."Document No.")));
        exit(not GenJournalLine.IsEmpty());
    end;

    local procedure SetApplyingCustledgEntrySalesHeader()
    begin
        TempApplyingCustLedgEntry."Entry No." := 1;
        TempApplyingCustLedgEntry."Posting Date" := SalesHeader."Posting Date";
        if SalesHeader."Document Type" = SalesHeader."Document Type"::"Return Order" then
            TempApplyingCustLedgEntry."Document Type" := TempApplyingCustLedgEntry."Document Type"::"Credit Memo"
        else
            TempApplyingCustLedgEntry."Document Type" := TempApplyingCustLedgEntry."Document Type"::Invoice;
        TempApplyingCustLedgEntry."Document No." := SalesHeader."No.";
        TempApplyingCustLedgEntry."Customer No." := SalesHeader."Bill-to Customer No.";
        TempApplyingCustLedgEntry.Description := SalesHeader."Posting Description";
        TempApplyingCustLedgEntry."Currency Code" := SalesHeader."Currency Code";
        if TempApplyingCustLedgEntry."Document Type" = TempApplyingCustLedgEntry."Document Type"::"Credit Memo" then begin
            TempApplyingCustLedgEntry.Amount := -TotalSalesLine."Amount Including VAT";
            TempApplyingCustLedgEntry."Remaining Amount" := -TotalSalesLine."Amount Including VAT";
        end else begin
            TempApplyingCustLedgEntry.Amount := TotalSalesLine."Amount Including VAT";
            TempApplyingCustLedgEntry."Remaining Amount" := TotalSalesLine."Amount Including VAT";
        end;

        OnAfterSetApplyingCustLedgEntrySalesHeader(TempApplyingCustLedgEntry, SalesHeader);
    end;


    local procedure SetApplyingCustLedgEntryGenJnlLine()
    var
        Customer: Record Customer;
    begin
        TempApplyingCustLedgEntry."Entry No." := 1;
        TempApplyingCustLedgEntry."Posting Date" := GenJnlLine."Posting Date";
        TempApplyingCustLedgEntry."Document Type" := GenJnlLine."Document Type";
        TempApplyingCustLedgEntry."Document No." := GenJnlLine."Document No.";
        if GenJnlLine."Bal. Account Type" = GenJnlLine."Account Type"::Customer then begin
            TempApplyingCustLedgEntry."Customer No." := GenJnlLine."Bal. Account No.";
            Customer.Get(TempApplyingCustLedgEntry."Customer No.");
            TempApplyingCustLedgEntry.Description := Customer.Name;
        end else begin
            TempApplyingCustLedgEntry."Customer No." := GenJnlLine."Account No.";
            TempApplyingCustLedgEntry.Description := GenJnlLine.Description;
        end;
        TempApplyingCustLedgEntry."Currency Code" := GenJnlLine."Currency Code";
        TempApplyingCustLedgEntry.Amount := GenJnlLine.Amount;
        TempApplyingCustLedgEntry."Remaining Amount" := GenJnlLine.Amount;

        OnAfterSetApplyingCustLedgEntryGenJnlLine(TempApplyingCustLedgEntry, GenJnlLine);
    end;

    local procedure SetApplyingCustledgEntryDirect()
    begin
        if Rec."Applying Entry" then begin
            if TempApplyingCustLedgEntry."Entry No." <> 0 then
                CustLedgEntry := TempApplyingCustLedgEntry;
            CODEUNIT.Run(CODEUNIT::"Cust. Entry-Edit", Rec);
            if Rec."Applies-to ID" = '' then
                SetCustApplId(false);
            Rec.CalcFields(Amount);
            TempApplyingCustLedgEntry := Rec;
            if CustLedgEntry."Entry No." <> 0 then begin
                Rec := CustLedgEntry;
                Rec."Applying Entry" := false;
                SetCustApplId(false);
            end;
            Rec.SetFilter("Entry No.", '<> %1', TempApplyingCustLedgEntry."Entry No.");
            ApplyingAmount := TempApplyingCustLedgEntry."Remaining Amount";
            ApplnDate := TempApplyingCustLedgEntry."Posting Date";
            ApplnCurrencyCode := TempApplyingCustLedgEntry."Currency Code";
        end;
        OnSetApplyingCustLedgEntryOnBeforeCalcTypeDirectCalcApplnAmount(Rec, ApplyingAmount, TempApplyingCustLedgEntry);
    end;

    /// <summary>
    /// Sets the Applies-to ID on selected customer ledger entries for application.
    /// </summary>
    /// <param name="CurrentRec">Indicates whether to apply only to the current record or to all selected records.</param>
    procedure SetCustApplId(CurrentRec: Boolean)
    begin
        CurrPage.SetSelectionFilter(CustLedgEntry);
        CheckCustLedgEntry(CustLedgEntry);

        OnSetCustApplIdOnAfterCheckAgainstApplnCurrency(Rec, CustLedgEntry, CalcType.AsInteger(), GenJnlLine, SalesHeader, TempApplyingCustLedgEntry);
        SetCustEntryApplID(CurrentRec);

        CalcApplnAmount();
    end;

    local procedure SetCustEntryApplID(CurrentRec: Boolean)
    var
        IsHandled: Boolean;
    begin
        IsHandled := false;
        OnBeforeSetCustEntryApplID(Rec, CurrentRec, ApplyingAmount, TempApplyingCustLedgEntry, GetAppliesToID(), IsHandled, GenJnlLine);
        if IsHandled then
            exit;

        CustLedgEntry.Copy(Rec);
        if CurrentRec then begin
            CustLedgEntry.SetRecFilter();
            CustEntrySetApplID.SetApplId(CustLedgEntry, TempApplyingCustLedgEntry, Rec."Applies-to ID")
        end else begin
            CurrPage.SetSelectionFilter(CustLedgEntry);
            CustEntrySetApplID.SetApplId(CustLedgEntry, TempApplyingCustLedgEntry, GetAppliesToID())
        end;
    end;

    /// <summary>
    /// Validates that selected customer ledger entries can be applied against the applying entry.
    /// </summary>
    /// <param name="CustLedgerEntry">The customer ledger entries to validate.</param>
    procedure CheckCustLedgEntry(var CustLedgerEntry: Record "Cust. Ledger Entry")
    var
        RaiseError: Boolean;
    begin
        if CustLedgerEntry.FindSet() then
            repeat
                if CalcType = CalcType::"Gen. Jnl. Line" then begin
                    RaiseError := TempApplyingCustLedgEntry."Posting Date" < CustLedgerEntry."Posting Date";
                    OnBeforeEarlierPostingDateError(TempApplyingCustLedgEntry, CustLedgerEntry, RaiseError, CalcType.AsInteger(), OK);
                    if RaiseError then
                        Error(
                            EarlierPostingDateErr, TempApplyingCustLedgEntry."Document Type", TempApplyingCustLedgEntry."Document No.",
                            CustLedgerEntry."Document Type", CustLedgerEntry."Document No.");

                    OnCheckCustLedgEntryOnAfterEarlierPostingDateTest(TempApplyingCustLedgEntry, Rec, CalcType, OK);
                end;

                OnCheckCustLedgEntryOnBeforeCheckAgainstApplnCurrency(CustLedgerEntry, GenJnlLine, TempApplyingCustLedgEntry, CalcType);

                if TempApplyingCustLedgEntry."Entry No." <> 0 then begin
                    OnCheckCustLedgEntryOnBeforeCheckAgainstApplnCurrencyWhenEntryNoIsNotNull(CustLedgerEntry, GenJnlLine);
                    GenJnlApply.CheckAgainstApplnCurrency(
                        ApplnCurrencyCode, CustLedgerEntry."Currency Code", GenJnlLine."Account Type"::Customer, true);
                end;
            until CustLedgerEntry.Next() = 0;
    end;

    local procedure GetAppliesToID() AppliesToID: Code[50]
    begin
        case CalcType of
            CalcType::"Gen. Jnl. Line":
                AppliesToID := GenJnlLine."Applies-to ID";
            CalcType::"Sales Header":
                AppliesToID := SalesHeader."Applies-to ID";
        end;
        OnAfterGetAppliesToID(CalcType, AppliesToID);
    end;

    /// <summary>
    /// Calculates the application amounts including applied amount, payment discount, and rounding.
    /// </summary>
    procedure CalcApplnAmount()
    var
        IsHandled: Boolean;
    begin
        IsHandled := false;
        OnBeforeCalcApplnAmount(
            Rec, GenJnlLine, SalesHeader, AppliedCustLedgEntry, CalcType.AsInteger(), ApplnType.AsInteger(), IsHandled);
        if not IsHandled then begin
            AppliedAmount := 0;
            PmtDiscAmount := 0;
            DifferentCurrenciesInAppln := false;

            case CalcType of
                CalcType::Direct:
                    begin
                        FindAmountRounding();
                        CustEntryApplID := UserId;
                        if CustEntryApplID = '' then
                            CustEntryApplID := '***';

                        CustLedgEntry := TempApplyingCustLedgEntry;

                        AppliedCustLedgEntry.SetCurrentKey("Customer No.", Open, Positive);
                        AppliedCustLedgEntry.SetRange("Customer No.", Rec."Customer No.");
                        AppliedCustLedgEntry.SetRange(Open, true);
                        if AppliesToID = '' then
                            AppliedCustLedgEntry.SetRange("Applies-to ID", CustEntryApplID)
                        else
                            AppliedCustLedgEntry.SetRange("Applies-to ID", AppliesToID);

                        if TempApplyingCustLedgEntry."Entry No." <> 0 then begin
                            CustLedgEntry.CalcFields("Remaining Amount");
                            AppliedCustLedgEntry.SetFilter("Entry No.", '<>%1', TempApplyingCustLedgEntry."Entry No.");
                        end;

                        HandleChosenEntries(
                            CalcType::Direct, CustLedgEntry."Remaining Amount", CustLedgEntry."Currency Code", CustLedgEntry."Posting Date");
                    end;
                CalcType::"Gen. Jnl. Line":
                    begin
                        FindAmountRounding();
                        if GenJnlLine."Bal. Account Type" = GenJnlLine."Bal. Account Type"::Customer then
                            CODEUNIT.Run(CODEUNIT::"Exchange Acc. G/L Journal Line", GenJnlLine);

                        case ApplnType of
                            ApplnType::"Applies-to Doc. No.":
                                begin
                                    AppliedCustLedgEntry := Rec;
                                    AppliedCustLedgEntry.CalcFields("Remaining Amount");
                                    if AppliedCustLedgEntry."Currency Code" <> ApplnCurrencyCode then
                                        AppliedCustLedgEntry.UpdateAmountsForApplication(ApplnDate, ApplnCurrencyCode, false, false);

                                    OnCalcApplnAmountOnCalcTypeGenJnlLineOnApplnTypeToDocNoOnBeforeSetAppliedAmount(Rec, ApplnDate, ApplnCurrencyCode);
                                    if AppliedCustLedgEntry."Amount to Apply" <> 0 then
                                        AppliedAmount := Round(AppliedCustLedgEntry."Amount to Apply", AmountRoundingPrecision)
                                    else
                                        AppliedAmount := Round(AppliedCustLedgEntry."Remaining Amount", AmountRoundingPrecision);
                                    OnCalcApplnAmountOnCalcTypeGenJnlLineOnApplnTypeToDocNoOnAfterSetAppliedAmount(Rec, ApplnDate, ApplnCurrencyCode, AppliedAmount);

                                    if PaymentToleranceMgt.CheckCalcPmtDiscGenJnlCust(
                                        GenJnlLine, AppliedCustLedgEntry, 0, false) and
                                       ((Abs(GenJnlLine.Amount) + ApplnRoundingPrecision >=
                                        Abs(AppliedAmount - AppliedCustLedgEntry.GetRemainingPmtDiscPossible(GenJnlLine."Posting Date"))) or
                                        (GenJnlLine.Amount = 0))
                                    then
                                        PmtDiscAmount := AppliedCustLedgEntry.GetRemainingPmtDiscPossible(GenJnlLine."Posting Date");

                                    if not DifferentCurrenciesInAppln then
                                        DifferentCurrenciesInAppln := ApplnCurrencyCode <> AppliedCustLedgEntry."Currency Code";
                                    CheckRounding();
                                end;
                            ApplnType::"Applies-to ID":
                                begin
                                    GenJnlLine2 := GenJnlLine;
                                    AppliedCustLedgEntry.SetCurrentKey("Customer No.", Open, Positive);
                                    AppliedCustLedgEntry.SetRange("Customer No.", GenJnlLine."Account No.");
                                    AppliedCustLedgEntry.SetRange(Open, true);
                                    AppliedCustLedgEntry.SetRange("Applies-to ID", GenJnlLine."Applies-to ID");

                                    HandleChosenEntries(
                                        CalcType::"Gen. Jnl. Line", GenJnlLine2.Amount, GenJnlLine2."Currency Code", GenJnlLine2."Posting Date");
                                end;
                        end;
                    end;
                CalcType::"Sales Header", CalcType::"Service Header":
                    begin
                        FindAmountRounding();

                        case ApplnType of
                            ApplnType::"Applies-to Doc. No.":
                                begin
                                    AppliedCustLedgEntry := Rec;
                                    AppliedCustLedgEntry.CalcFields("Remaining Amount");

                                    if AppliedCustLedgEntry."Currency Code" <> ApplnCurrencyCode then
                                        AppliedCustLedgEntry."Remaining Amount" :=
                                        CurrExchRate.ExchangeAmtFCYToFCY(
                                            ApplnDate, AppliedCustLedgEntry."Currency Code", ApplnCurrencyCode, AppliedCustLedgEntry."Remaining Amount");

                                    OnCalcApplnAmountOnCalcTypeSalesHeaderOnApplnTypeToDocNoOnBeforeSetAppliedAmount(Rec, ApplnDate, ApplnCurrencyCode);
                                    AppliedAmount := Round(AppliedCustLedgEntry."Remaining Amount", AmountRoundingPrecision);

                                    if not DifferentCurrenciesInAppln then
                                        DifferentCurrenciesInAppln := ApplnCurrencyCode <> AppliedCustLedgEntry."Currency Code";
                                    CheckRounding();
                                end;
                            ApplnType::"Applies-to ID":
                                begin
                                    AppliedCustLedgEntry.SetCurrentKey("Customer No.", Open, Positive);
                                    case CalcType of
                                        CalcType::"Sales Header":
                                            AppliedCustLedgEntry.SetRange("Customer No.", SalesHeader."Bill-to Customer No.");
                                    end;
                                    AppliedCustLedgEntry.SetRange(Open, true);
                                    AppliedCustLedgEntry.SetRange("Applies-to ID", GetAppliesToID());

                                    HandleChosenEntries(CalcType::"Sales Header", ApplyingAmount, ApplnCurrencyCode, ApplnDate);
                                end;
                        end;
                    end;
            end;
        end;

        OnAfterCalcApplnAmount(Rec, AppliedAmount, ApplyingAmount, CalcType, AppliedCustLedgEntry, GenJnlLine);
    end;

    protected procedure CalcApplnRemainingAmount(Amount: Decimal): Decimal
    var
        ApplnRemainingAmount: Decimal;
    begin
        ValidExchRate := true;
        if ApplnCurrencyCode = Rec."Currency Code" then
            exit(Amount);

        if ApplnDate = 0D then
            ApplnDate := Rec."Posting Date";
        ApplnRemainingAmount :=
          CurrExchRate.ApplnExchangeAmtFCYToFCY(
            ApplnDate, Rec."Currency Code", ApplnCurrencyCode, Amount, ValidExchRate);

        OnAfterCalcApplnRemainingAmount(Rec, ApplnRemainingAmount);
        exit(ApplnRemainingAmount);
    end;

    local procedure CalcApplnAmountToApply(AmountToApply: Decimal): Decimal
    var
        ApplnAmountToApply: Decimal;
    begin
        ValidExchRate := true;

        if ApplnCurrencyCode = Rec."Currency Code" then
            exit(AmountToApply);

        if ApplnDate = 0D then
            ApplnDate := Rec."Posting Date";
        ApplnAmountToApply :=
          CurrExchRate.ApplnExchangeAmtFCYToFCY(
            ApplnDate, Rec."Currency Code", ApplnCurrencyCode, AmountToApply, ValidExchRate);

        OnAfterCalcApplnAmountToApply(Rec, ApplnAmountToApply);
        exit(ApplnAmountToApply);
    end;

    protected procedure FindAmountRounding()
    begin
        if ApplnCurrencyCode = '' then begin
            Currency.Init();
            Currency.Code := '';
            Currency.InitRoundingPrecision();
        end else
            if ApplnCurrencyCode <> Currency.Code then
                Currency.Get(ApplnCurrencyCode);

        AmountRoundingPrecision := Currency."Amount Rounding Precision";
    end;

    /// <summary>
    /// Calculates any rounding amount needed when applying entries in different currencies.
    /// </summary>
    procedure CheckRounding()
    var
        IsHandled: Boolean;
    begin
        IsHandled := false;
        OnBeforeCheckRounding(CalcType, ApplnRounding, IsHandled);
        if IsHandled then
            exit;

        ApplnRounding := 0;

        case CalcType of
            CalcType::"Sales Header", CalcType::"Service Header":
                exit;
            CalcType::"Gen. Jnl. Line":
                if (GenJnlLine."Document Type" <> GenJnlLine."Document Type"::Payment) and
                   (GenJnlLine."Document Type" <> GenJnlLine."Document Type"::Refund)
                then
                    exit;
        end;

        if ApplnCurrencyCode = '' then
            ApplnRoundingPrecision := GLSetup."Appln. Rounding Precision"
        else begin
            if ApplnCurrencyCode <> Rec."Currency Code" then
                Currency.Get(ApplnCurrencyCode);
            ApplnRoundingPrecision := Currency."Appln. Rounding Precision";
        end;

        if (Abs((AppliedAmount - PmtDiscAmount) + ApplyingAmount) <= ApplnRoundingPrecision) and DifferentCurrenciesInAppln then
            ApplnRounding := -((AppliedAmount - PmtDiscAmount) + ApplyingAmount);
    end;

    /// <summary>
    /// Gets the current customer ledger entry record.
    /// </summary>
    /// <param name="CustLedgEntry">Returns the current customer ledger entry.</param>
    procedure GetCustLedgEntry(var CustLedgEntry: Record "Cust. Ledger Entry")
    begin
        CustLedgEntry := Rec;
    end;

    local procedure FindApplyingEntry()
    begin
        if CalcType = CalcType::Direct then begin
            CustEntryApplID := UserId;
            if CustEntryApplID = '' then
                CustEntryApplID := '***';

            CustLedgEntry.SetCurrentKey("Customer No.", "Applies-to ID", Open);
            CustLedgEntry.SetRange("Customer No.", Rec."Customer No.");
            if AppliesToID = '' then
                CustLedgEntry.SetRange("Applies-to ID", CustEntryApplID)
            else
                CustLedgEntry.SetRange("Applies-to ID", AppliesToID);
            CustLedgEntry.SetRange(Open, true);
            CustLedgEntry.SetRange("Applying Entry", true);
            OnFindFindApplyingEntryOnAfterCustLedgEntrySetFilters(Rec, CustLedgEntry);
            if CustLedgEntry.FindFirst() then begin
                CustLedgEntry.CalcFields(Amount, "Remaining Amount");
                TempApplyingCustLedgEntry := CustLedgEntry;
                Rec.SetFilter("Entry No.", '<>%1', CustLedgEntry."Entry No.");
                ApplyingAmount := CustLedgEntry."Remaining Amount";
                ApplnDate := CustLedgEntry."Posting Date";
                ApplnCurrencyCode := CustLedgEntry."Currency Code";
            end;
            OnFindApplyingEntryOnBeforeCalcApplnAmount(Rec);
            CalcApplnAmount();
        end;
    end;

    protected procedure HandleChosenEntries(Type: Enum "Customer Apply Calculation Type"; CurrentAmount: Decimal; CurrencyCode: Code[10]; PostingDate: Date)
    var
        TempAppliedCustLedgEntry: Record "Cust. Ledger Entry" temporary;
        PossiblePmtDisc: Decimal;
        OldPmtDisc: Decimal;
        CorrectionAmount: Decimal;
        RemainingAmountExclDiscounts: Decimal;
        CanUseDisc: Boolean;
        FromZeroGenJnl: Boolean;
        IsHandled: Boolean;
    begin
        IsHandled := false;
        OnBeforeHandledChosenEntries(Type.AsInteger(), CurrentAmount, CurrencyCode, PostingDate, AppliedCustLedgEntry, IsHandled, CustLedgEntry);
        if IsHandled then
            exit;

        if not AppliedCustLedgEntry.FindSet(false) then
            exit;

        repeat
            TempAppliedCustLedgEntry := AppliedCustLedgEntry;
            TempAppliedCustLedgEntry.Insert();
            OnHandleChosenEntriesOnAfterTempAppliedCustLedgEntryInsert(TempAppliedCustLedgEntry);
        until AppliedCustLedgEntry.Next() = 0;

        FromZeroGenJnl := (CurrentAmount = 0) and (Type = Type::"Gen. Jnl. Line");

        repeat
            if not FromZeroGenJnl then
                TempAppliedCustLedgEntry.SetRange(Positive, CurrentAmount < 0);
            if TempAppliedCustLedgEntry.FindFirst() then begin
                ExchangeLedgerEntryAmounts(Type, CurrencyCode, TempAppliedCustLedgEntry, PostingDate);

                case Type of
                    Type::Direct:
                        CanUseDisc := PaymentToleranceMgt.CheckCalcPmtDiscCust(CustLedgEntry, TempAppliedCustLedgEntry, 0, false, false);
                    Type::"Gen. Jnl. Line":
                        CanUseDisc := PaymentToleranceMgt.CheckCalcPmtDiscGenJnlCust(GenJnlLine2, TempAppliedCustLedgEntry, 0, false)
                    else
                        CanUseDisc := false;
                end;

                if CanUseDisc and
                   (Abs(TempAppliedCustLedgEntry."Amount to Apply") >=
                    Abs(TempAppliedCustLedgEntry."Remaining Amount" - TempAppliedCustLedgEntry.GetRemainingPmtDiscPossible(PostingDate)))
                then
                    if Abs(CurrentAmount) >
                       Abs(TempAppliedCustLedgEntry."Remaining Amount" - TempAppliedCustLedgEntry.GetRemainingPmtDiscPossible(PostingDate))
                    then begin
                        PmtDiscAmount += TempAppliedCustLedgEntry.GetRemainingPmtDiscPossible(PostingDate);
                        CurrentAmount += TempAppliedCustLedgEntry."Remaining Amount" - TempAppliedCustLedgEntry.GetRemainingPmtDiscPossible(PostingDate);
                    end else
                        if Abs(CurrentAmount) =
                           Abs(TempAppliedCustLedgEntry."Remaining Amount" - TempAppliedCustLedgEntry.GetRemainingPmtDiscPossible(PostingDate))
                        then begin
                            PmtDiscAmount += TempAppliedCustLedgEntry.GetRemainingPmtDiscPossible(PostingDate);
                            CurrentAmount +=
                              TempAppliedCustLedgEntry."Remaining Amount" - TempAppliedCustLedgEntry.GetRemainingPmtDiscPossible(PostingDate);
                            AppliedAmount += CorrectionAmount;
                        end else
                            if FromZeroGenJnl then begin
                                PmtDiscAmount += TempAppliedCustLedgEntry.GetRemainingPmtDiscPossible(PostingDate);
                                CurrentAmount +=
                                  TempAppliedCustLedgEntry."Remaining Amount" - TempAppliedCustLedgEntry.GetRemainingPmtDiscPossible(PostingDate);
                            end else begin
                                PossiblePmtDisc := TempAppliedCustLedgEntry.GetRemainingPmtDiscPossible(PostingDate);
                                RemainingAmountExclDiscounts :=
                                  TempAppliedCustLedgEntry."Remaining Amount" - PossiblePmtDisc - TempAppliedCustLedgEntry."Max. Payment Tolerance";
                                if Abs(CurrentAmount) + Abs(CalcOppositeEntriesAmount(TempAppliedCustLedgEntry)) >=
                                   Abs(RemainingAmountExclDiscounts)
                                then begin
                                    PmtDiscAmount += PossiblePmtDisc;
                                    AppliedAmount += CorrectionAmount;
                                end;
                                CurrentAmount +=
                                  TempAppliedCustLedgEntry."Remaining Amount" - TempAppliedCustLedgEntry.GetRemainingPmtDiscPossible(PostingDate);
                            end
                else begin
                    if ((CurrentAmount + TempAppliedCustLedgEntry."Amount to Apply") * CurrentAmount) <= 0 then
                        AppliedAmount += CorrectionAmount;
                    CurrentAmount += TempAppliedCustLedgEntry."Amount to Apply";
                end;
            end else begin
                TempAppliedCustLedgEntry.SetRange(Positive);
                TempAppliedCustLedgEntry.FindFirst();
                ExchangeLedgerEntryAmounts(Type, CurrencyCode, TempAppliedCustLedgEntry, PostingDate);
            end;

            if OldPmtDisc <> PmtDiscAmount then
                AppliedAmount += TempAppliedCustLedgEntry."Remaining Amount"
            else
                AppliedAmount += TempAppliedCustLedgEntry."Amount to Apply";
            OldPmtDisc := PmtDiscAmount;

            if PossiblePmtDisc <> 0 then
                CorrectionAmount := TempAppliedCustLedgEntry."Remaining Amount" - TempAppliedCustLedgEntry."Amount to Apply"
            else
                CorrectionAmount := 0;

            if not DifferentCurrenciesInAppln then
                DifferentCurrenciesInAppln := ApplnCurrencyCode <> TempAppliedCustLedgEntry."Currency Code";

            OnHandleChosenEntriesOnBeforeDeleteTempAppliedCustLedgEntry(Rec, TempAppliedCustLedgEntry, CurrencyCode);
            TempAppliedCustLedgEntry.Delete();
            TempAppliedCustLedgEntry.SetRange(Positive);

        until not TempAppliedCustLedgEntry.FindFirst();
        CheckRounding();
    end;

    local procedure AmountToApplyOnAfterValidate()
    begin
        if ApplnType <> ApplnType::"Applies-to Doc. No." then begin
            CalcApplnAmount();
            CurrPage.Update(false);
        end;
    end;

    local procedure RecalcApplnAmount()
    begin
        CurrPage.Update(true);
        CalcApplnAmount();
    end;

    local procedure LookupOKOnPush()
    begin
        OK := true;

        OnAfterLookupOKOnPush(OK);
    end;

    local procedure PostDirectApplication(PreviewMode: Boolean)
    var
        RecBeforeRunPostApplicationCustLedgerEntry: Record "Cust. Ledger Entry";
        ApplyUnapplyParameters: Record "Apply Unapply Parameters";
        NewApplyUnapplyParameters: Record "Apply Unapply Parameters";
        CustEntryApplyPostedEntries: Codeunit "CustEntry-Apply Posted Entries";
        PostApplication: Page "Post Application";
        Applied: Boolean;
        ApplicationDate: Date;
        IsHandled: Boolean;
    begin
        IsHandled := false;
        OnBeforePostDirectApplication(Rec, PreviewMode, IsHandled, TempApplyingCustLedgEntry);
        if IsHandled then
            exit;

        if CalcType = CalcType::Direct then begin
            if TempApplyingCustLedgEntry."Entry No." <> 0 then begin
                Rec := TempApplyingCustLedgEntry;
                IsTheApplicationValid();
                ApplicationDate := CustEntryApplyPostedEntries.GetApplicationDate(Rec);

                OnPostDirectApplicationBeforeSetValues(ApplicationDate);
                Clear(ApplyUnapplyParameters);
                ApplyUnapplyParameters.CopyFromCustLedgEntry(Rec);
                GLSetup.GetRecordOnce();
                ApplyUnapplyParameters."Posting Date" := ApplicationDate;
                if GLSetup."Journal Templ. Name Mandatory" then begin
                    GLSetup.TestField("Apply Jnl. Template Name");
                    GLSetup.TestField("Apply Jnl. Batch Name");
                    ApplyUnapplyParameters."Journal Template Name" := GLSetup."Apply Jnl. Template Name";
                    ApplyUnapplyParameters."Journal Batch Name" := GLSetup."Apply Jnl. Batch Name";
                end;
                PostApplication.SetParameters(ApplyUnapplyParameters);
                RecBeforeRunPostApplicationCustLedgerEntry := Rec;
                if ACTION::OK = PostApplication.RunModal() then begin
                    if Rec."Entry No." <> RecBeforeRunPostApplicationCustLedgerEntry."Entry No." then
                        Rec := RecBeforeRunPostApplicationCustLedgerEntry;
                    PostApplication.GetParameters(NewApplyUnapplyParameters);
                    if NewApplyUnapplyParameters."Posting Date" < ApplicationDate then
                        Error(ApplicationDateErr, Rec.FieldCaption("Posting Date"), Rec.TableCaption());
                end else
                    exit;

                OnPostDirectApplicationBeforeApply(GLSetup, NewApplyUnapplyParameters);
                if PreviewMode then
                    CustEntryApplyPostedEntries.PreviewApply(Rec, NewApplyUnapplyParameters)
                else
                    Applied := CustEntryApplyPostedEntries.Apply(Rec, NewApplyUnapplyParameters);

                OnPostDirectApplicationOnAfterApply(Rec, NewApplyUnapplyParameters, PreviewMode, Applied);

                if (not PreviewMode) and Applied then begin
                    Message(ApplicationPostedMsg);
                    PostingDone := true;
                    CurrPage.Close();
                end;
            end else
                Error(MustSelectEntryErr);
        end else
            Error(PostingInWrongContextErr);
    end;

    /// <summary>
    /// Sets the Applies-to ID to use for filtering entries.
    /// </summary>
    /// <param name="AppliesToID2">The Applies-to ID value to set.</param>
    procedure SetAppliesToID(AppliesToID2: Code[50])
    begin
        AppliesToID := AppliesToID2;
    end;

    /// <summary>
    /// Converts ledger entry amounts to the specified currency using the exchange rate at the posting date.
    /// </summary>
    /// <param name="Type">The calculation type context for the exchange.</param>
    /// <param name="CurrencyCode">The target currency code for conversion.</param>
    /// <param name="CalcCustLedgEntry">The customer ledger entry with amounts to convert.</param>
    /// <param name="PostingDate">The date to use for the exchange rate.</param>
    procedure ExchangeLedgerEntryAmounts(Type: Enum "Customer Apply Calculation Type"; CurrencyCode: Code[10]; var CalcCustLedgEntry: Record "Cust. Ledger Entry"; PostingDate: Date)
    var
        CalculateCurrency, IsHandled : Boolean;
    begin
        CalcCustLedgEntry.CalcFields("Remaining Amount");

        if Type = Type::Direct then
            CalculateCurrency := TempApplyingCustLedgEntry."Entry No." <> 0
        else
            CalculateCurrency := true;

        IsHandled := false;
        OnExchangeLedgerEntryAmountsOnBeforeCalculateAmounts(CalcCustLedgEntry, CustLedgEntry, CurrencyCode, CalculateCurrency, IsHandled);
        if IsHandled then
            exit;

        if (CurrencyCode <> CalcCustLedgEntry."Currency Code") and CalculateCurrency then begin
            CalcCustLedgEntry."Remaining Amount" :=
              CurrExchRate.ExchangeAmount(
                CalcCustLedgEntry."Remaining Amount", CalcCustLedgEntry."Currency Code", CurrencyCode, PostingDate);
            CalcCustLedgEntry."Remaining Pmt. Disc. Possible" :=
              CurrExchRate.ExchangeAmount(
                CalcCustLedgEntry."Remaining Pmt. Disc. Possible", CalcCustLedgEntry."Currency Code", CurrencyCode, PostingDate);
            CalcCustLedgEntry."Amount to Apply" :=
              CurrExchRate.ExchangeAmount(
                CalcCustLedgEntry."Amount to Apply", CalcCustLedgEntry."Currency Code", CurrencyCode, PostingDate);
        end;

        OnAfterExchangeLedgerEntryAmounts(CalcCustLedgEntry, CustLedgEntry, CurrencyCode);
    end;

    local procedure IsTheApplicationValid()
    var
        ApplyToCustLedgEntry: Record "Cust. Ledger Entry";
        IsFirst, IsPositiv, ThereAreEntriesToApply : boolean;
        Counter: Integer;
        AllEntriesHaveTheSameSignErr: Label 'All entries have the same sign this will not lead to an application. Update the application by including entries with opposite sign.';
    begin
        IsFirst := true;
        ThereAreEntriesToApply := false;
        Counter := 0;
        ApplyToCustLedgEntry.SetCurrentKey("Customer No.", "Applies-to ID");
        ApplyToCustLedgEntry.SetRange("Customer No.", CustLedgEntry."Customer No.");
        ApplyToCustLedgEntry.SetRange("Applies-to ID", CustLedgEntry."Applies-to ID");
        if ApplyToCustLedgEntry.FindSet() then
            repeat
                if not IsFirst then
                    ThereAreEntriesToApply := (IsPositiv <> ApplyToCustLedgEntry.Positive)
                else
                    IsPositiv := ApplyToCustLedgEntry.Positive;
                IsFirst := false;
                Counter += 1;
            until (ApplyToCustLedgEntry.next() = 0) or ThereAreEntriesToApply;
        if not ThereAreEntriesToApply and (Counter > 1) then
            error(AllEntriesHaveTheSameSignErr)
    end;

    local procedure ActivateFields()
    begin
        CalledFromEntry := CalcType = CalcType::Direct;
        AppliesToIDVisible := ApplnType <> ApplnType::"Applies-to Doc. No.";
    end;

    /// <summary>
    /// Calculates the total remaining amount of entries with the opposite sign.
    /// </summary>
    /// <param name="TempAppliedCustLedgerEntry">The temporary applied customer ledger entry set to analyze.</param>
    /// <returns>The total remaining amount of entries with opposite sign.</returns>
    procedure CalcOppositeEntriesAmount(var TempAppliedCustLedgerEntry: Record "Cust. Ledger Entry" temporary) Result: Decimal
    var
        SavedAppliedCustLedgerEntry: Record "Cust. Ledger Entry";
        CurrPosFilter: Text;
    begin
        CurrPosFilter := TempAppliedCustLedgerEntry.GetFilter(Positive);
        if CurrPosFilter <> '' then begin
            SavedAppliedCustLedgerEntry := TempAppliedCustLedgerEntry;
            TempAppliedCustLedgerEntry.SetRange(Positive, not TempAppliedCustLedgerEntry.Positive);
            if TempAppliedCustLedgerEntry.FindSet() then
                repeat
                    TempAppliedCustLedgerEntry.CalcFields("Remaining Amount");
                    Result += TempAppliedCustLedgerEntry."Remaining Amount";
                until TempAppliedCustLedgerEntry.Next() = 0;
            TempAppliedCustLedgerEntry.SetFilter(Positive, CurrPosFilter);
            TempAppliedCustLedgerEntry := SavedAppliedCustLedgerEntry;
        end;
    end;

    /// <summary>
    /// Gets the application currency code.
    /// </summary>
    /// <returns>The currency code used for the application.</returns>
    procedure GetApplnCurrencyCode(): Code[10]
    begin
        exit(ApplnCurrencyCode);
    end;

    /// <summary>
    /// Gets the calculation type as an integer value.
    /// </summary>
    /// <returns>The calculation type as an integer.</returns>
    procedure GetCalcType(): Integer
    begin
        exit(CalcType.AsInteger());
    end;

    /// <summary>
    /// Sets the calculation type for the application process.
    /// </summary>
    /// <param name="NewCalcType">The calculation type to set.</param>
    procedure SetCalcType(NewCalcType: Enum "Customer Apply Calculation Type")
    begin
        CalcType := NewCalcType;
    end;

    /// <summary>
    /// Raised after the application amount has been calculated.
    /// </summary>
    /// <param name="CustLedgerEntry">The customer ledger entry being applied.</param>
    /// <param name="AppliedAmount">The calculated applied amount.</param>
    /// <param name="ApplyingAmount">The applying amount from the source document.</param>
    /// <param name="CalcType">The calculation type used.</param>
    /// <param name="AppliedCustLedgEntry">The applied customer ledger entry.</param>
    /// <param name="GenJournalLine">The general journal line if applicable.</param>
    [IntegrationEvent(true, false)]
    local procedure OnAfterCalcApplnAmount(CustLedgerEntry: Record "Cust. Ledger Entry"; var AppliedAmount: Decimal; var ApplyingAmount: Decimal; var CalcType: Enum "Customer Apply Calculation Type"; var AppliedCustLedgEntry: Record "Cust. Ledger Entry"; var GenJournalLine: Record "Gen. Journal Line")
    begin
    end;

    /// <summary>
    /// Raised after the application amount to apply has been calculated.
    /// </summary>
    /// <param name="CustLedgerEntry">The customer ledger entry.</param>
    /// <param name="ApplnAmountToApply">The calculated amount to apply.</param>
    [IntegrationEvent(false, false)]
    local procedure OnAfterCalcApplnAmountToApply(CustLedgerEntry: Record "Cust. Ledger Entry"; var ApplnAmountToApply: Decimal)
    begin
    end;

    /// <summary>
    /// Raised after the remaining application amount has been calculated.
    /// </summary>
    /// <param name="CustLedgerEntry">The customer ledger entry.</param>
    /// <param name="ApplnRemainingAmount">The calculated remaining amount.</param>
    [IntegrationEvent(false, false)]
    local procedure OnAfterCalcApplnRemainingAmount(CustLedgerEntry: Record "Cust. Ledger Entry"; var ApplnRemainingAmount: Decimal)
    begin
    end;

    /// <summary>
    /// Raised after ledger entry amounts have been exchanged to the application currency.
    /// </summary>
    /// <param name="CalcCustLedgEntry">The customer ledger entry with converted amounts.</param>
    /// <param name="CustLedgerEntry">The original customer ledger entry.</param>
    /// <param name="CurrencyCode">The target currency code.</param>
    [IntegrationEvent(false, false)]
    local procedure OnAfterExchangeLedgerEntryAmounts(var CalcCustLedgEntry: Record "Cust. Ledger Entry"; CustLedgerEntry: Record "Cust. Ledger Entry"; CurrencyCode: Code[10])
    begin
    end;

    /// <summary>
    /// Raised after the Applies-to ID has been retrieved.
    /// </summary>
    /// <param name="CalcType">The calculation type.</param>
    /// <param name="AppliesToID">The Applies-to ID value.</param>
    [IntegrationEvent(true, false)]
    local procedure OnAfterGetAppliesToID(CalcType: Enum "Customer Apply Calculation Type"; var AppliesToID: Code[50])
    begin
    end;

    /// <summary>
    /// Raised after the Lookup OK action has been processed.
    /// </summary>
    /// <param name="OK">Indicates whether the lookup was successful.</param>
    [IntegrationEvent(false, false)]
    local procedure OnAfterLookupOKOnPush(var OK: Boolean)
    begin
    end;

    /// <summary>
    /// Raised after the page has been opened.
    /// </summary>
    /// <param name="GenJnlLine">The general journal line if applicable.</param>
    /// <param name="CustLedgerEntry">The customer ledger entry record.</param>
    /// <param name="ApplyingCustLedgEntry">The applying customer ledger entry.</param>
    [IntegrationEvent(true, false)]
    local procedure OnAfterOnOpenPage(var GenJnlLine: Record "Gen. Journal Line"; var CustLedgerEntry: Record "Cust. Ledger Entry"; var ApplyingCustLedgEntry: Record "Cust. Ledger Entry")
    begin
    end;

    /// <summary>
    /// Raised after the applying customer ledger entry has been set.
    /// </summary>
    /// <param name="ApplyingCustLedgEntry">The applying customer ledger entry.</param>
    /// <param name="GenJournalLine">The general journal line if applicable.</param>
    /// <param name="SalesHeader">The sales header if applicable.</param>
    [IntegrationEvent(true, false)]
    local procedure OnAfterSetApplyingCustLedgEntry(var ApplyingCustLedgEntry: Record "Cust. Ledger Entry"; GenJournalLine: Record "Gen. Journal Line"; SalesHeader: Record "Sales Header")
    begin
    end;

    /// <summary>
    /// Raised before the application amount is calculated.
    /// </summary>
    /// <param name="CustLedgerEntry">The customer ledger entry.</param>
    /// <param name="GenJournalLine">The general journal line if applicable.</param>
    /// <param name="SalesHeader">The sales header if applicable.</param>
    /// <param name="AppliedCustLedgerEntry">The applied customer ledger entry.</param>
    /// <param name="CalculationType">The calculation type option.</param>
    /// <param name="ApplicationType">The application type option.</param>
    /// <param name="IsHandled">Set to true to skip default processing.</param>
    [IntegrationEvent(false, false)]
    local procedure OnBeforeCalcApplnAmount(var CustLedgerEntry: Record "Cust. Ledger Entry"; var GenJournalLine: Record "Gen. Journal Line"; SalesHeader: Record "Sales Header"; var AppliedCustLedgerEntry: Record "Cust. Ledger Entry"; CalculationType: Option; ApplicationType: Option; var IsHandled: Boolean)
    begin
    end;

    /// <summary>
    /// Raised before rounding is checked for the application.
    /// </summary>
    /// <param name="CalcType">The calculation type.</param>
    /// <param name="ApplnRounding">The application rounding amount.</param>
    /// <param name="IsHandled">Set to true to skip default processing.</param>
    [IntegrationEvent(false, false)]
    local procedure OnBeforeCheckRounding(CalcType: Enum "Customer Apply Calculation Type"; var ApplnRounding: Decimal; var IsHandled: Boolean)
    begin
    end;

    /// <summary>
    /// Raised before chosen entries are processed for application.
    /// </summary>
    /// <param name="Type">The calculation type option.</param>
    /// <param name="CurrentAmount">The current amount being applied.</param>
    /// <param name="CurrencyCode">The currency code.</param>
    /// <param name="PostingDate">The posting date.</param>
    /// <param name="AppliedCustLedgerEntry">The applied customer ledger entries.</param>
    /// <param name="IsHandled">Set to true to skip default processing.</param>
    /// <param name="CustLedgEntry">The customer ledger entry.</param>
    [IntegrationEvent(true, false)]
    local procedure OnBeforeHandledChosenEntries(Type: Option Direct,GenJnlLine,SalesHeader; CurrentAmount: Decimal; CurrencyCode: Code[10]; PostingDate: Date; var AppliedCustLedgerEntry: Record "Cust. Ledger Entry"; var IsHandled: Boolean; var CustLedgEntry: Record "Cust. Ledger Entry")
    begin
    end;

    /// <summary>
    /// Raised before an error is raised for applying entries with earlier posting dates.
    /// </summary>
    /// <param name="ApplyingCustLedgerEntry">The applying customer ledger entry.</param>
    /// <param name="CustLedgerEntry">The customer ledger entry being applied to.</param>
    /// <param name="RaiseError">Set to false to suppress the error.</param>
    /// <param name="CalcType">The calculation type option.</param>
    /// <param name="OK">Indicates whether the operation is successful.</param>
    [IntegrationEvent(false, false)]
    local procedure OnBeforeEarlierPostingDateError(ApplyingCustLedgerEntry: Record "Cust. Ledger Entry"; CustLedgerEntry: Record "Cust. Ledger Entry"; var RaiseError: Boolean; CalcType: Option; var OK: Boolean)
    begin
    end;

    /// <summary>
    /// Raised before a direct application is posted.
    /// </summary>
    /// <param name="CustLedgerEntry">The customer ledger entry.</param>
    /// <param name="PreviewMode">Indicates whether posting is in preview mode.</param>
    /// <param name="IsHandled">Set to true to skip default processing.</param>
    /// <param name="ApplyingCustLedgEntry">The applying customer ledger entry.</param>
    [IntegrationEvent(true, false)]
    local procedure OnBeforePostDirectApplication(var CustLedgerEntry: Record "Cust. Ledger Entry"; PreviewMode: Boolean; var IsHandled: Boolean; var ApplyingCustLedgEntry: Record "Cust. Ledger Entry" temporary)
    begin
    end;


    /// <summary>
    /// Raised before the applying customer ledger entry is set.
    /// </summary>
    /// <param name="ApplyingCustLedgEntry">The applying customer ledger entry.</param>
    /// <param name="GenJournalLine">The general journal line if applicable.</param>
    /// <param name="SalesHeader">The sales header if applicable.</param>
    /// <param name="CalcType">The calculation type.</param>
    /// <param name="IsHandled">Set to true to skip default processing.</param>
    [IntegrationEvent(true, false)]
    local procedure OnBeforeSetApplyingCustLedgerEntry(var ApplyingCustLedgEntry: Record "Cust. Ledger Entry"; GenJournalLine: Record "Gen. Journal Line"; SalesHeader: Record "Sales Header"; var CalcType: Enum "Customer Apply Calculation Type"; var IsHandled: Boolean)
    begin
    end;

    /// <summary>
    /// Raised before the customer entry Applies-to ID is set.
    /// </summary>
    /// <param name="CustLedgerEntry">The customer ledger entry.</param>
    /// <param name="CurrentRec">Indicates whether applying to current record only.</param>
    /// <param name="ApplyingAmount">The applying amount.</param>
    /// <param name="ApplyingCustLedgerEntry">The applying customer ledger entry.</param>
    /// <param name="AppliesToID">The Applies-to ID.</param>
    /// <param name="IsHandled">Set to true to skip default processing.</param>
    /// <param name="GenJournalLine">The general journal line.</param>
    [IntegrationEvent(false, false)]
    local procedure OnBeforeSetCustEntryApplID(CustLedgerEntry: Record "Cust. Ledger Entry"; CurrentRec: Boolean; var ApplyingAmount: Decimal; var ApplyingCustLedgerEntry: Record "Cust. Ledger Entry"; AppliesToID: Code[50]; var IsHandled: Boolean; var GenJournalLine: Record "Gen. Journal Line")
    begin
    end;

    /// <summary>
    /// Raised before setting the applied amount during general journal line application to document number.
    /// </summary>
    /// <param name="AppliedCustLedgEntry">The applied customer ledger entry.</param>
    /// <param name="ApplnDate">The application date.</param>
    /// <param name="ApplnCurrencyCode">The application currency code.</param>
    [IntegrationEvent(false, false)]
    local procedure OnCalcApplnAmountOnCalcTypeGenJnlLineOnApplnTypeToDocNoOnBeforeSetAppliedAmount(var AppliedCustLedgEntry: Record "Cust. Ledger Entry"; ApplnDate: Date; ApplnCurrencyCode: Code[10])
    begin
    end;

    /// <summary>
    /// Raised before checking against application currency during customer ledger entry validation.
    /// </summary>
    /// <param name="CustLedgerEntry">The customer ledger entry being validated.</param>
    /// <param name="GenJournalLine">The general journal line.</param>
    /// <param name="TempApplyingCustLedgEntry">The applying customer ledger entry.</param>
    /// <param name="CalcType">The calculation type.</param>
    [IntegrationEvent(false, false)]
    local procedure OnCheckCustLedgEntryOnBeforeCheckAgainstApplnCurrency(var CustLedgerEntry: Record "Cust. Ledger Entry"; GenJournalLine: Record "Gen. Journal Line"; var TempApplyingCustLedgEntry: Record "Cust. Ledger Entry" temporary; CalcType: Enum "Customer Apply Calculation Type")
    begin
    end;

    /// <summary>
    /// Raised after setting the applied amount during general journal line application to document number.
    /// </summary>
    /// <param name="AppliedCustLedgEntry">The applied customer ledger entry.</param>
    /// <param name="ApplnDate">The application date.</param>
    /// <param name="ApplnCurrencyCode">The application currency code.</param>
    /// <param name="AppliedAmount">The applied amount.</param>
    [IntegrationEvent(false, false)]
    local procedure OnCalcApplnAmountOnCalcTypeGenJnlLineOnApplnTypeToDocNoOnAfterSetAppliedAmount(var AppliedCustLedgEntry: Record "Cust. Ledger Entry"; ApplnDate: Date; ApplnCurrencyCode: Code[10]; var AppliedAmount: Decimal)
    begin
    end;

    /// <summary>
    /// Raised before setting the applied amount during sales header application to document number.
    /// </summary>
    /// <param name="AppliedCustLedgEntry">The applied customer ledger entry.</param>
    /// <param name="ApplnDate">The application date.</param>
    /// <param name="ApplnCurrencyCode">The application currency code.</param>
    [IntegrationEvent(false, false)]
    local procedure OnCalcApplnAmountOnCalcTypeSalesHeaderOnApplnTypeToDocNoOnBeforeSetAppliedAmount(var AppliedCustLedgEntry: Record "Cust. Ledger Entry"; ApplnDate: Date; ApplnCurrencyCode: Code[10])
    begin
    end;

    /// <summary>
    /// Raised after filters have been set when finding the applying entry.
    /// </summary>
    /// <param name="ApplyingCustLedgerEntry">The applying customer ledger entry.</param>
    /// <param name="CustLedgerEntry">The customer ledger entry being filtered.</param>
    [IntegrationEvent(false, false)]
    local procedure OnFindFindApplyingEntryOnAfterCustLedgEntrySetFilters(ApplyingCustLedgerEntry: Record "Cust. Ledger Entry"; var CustLedgerEntry: Record "Cust. Ledger Entry")
    begin
    end;

    /// <summary>
    /// Raised before calculating the application amount when finding the applying entry.
    /// </summary>
    /// <param name="CustLedgerEntry">The customer ledger entry.</param>
    [IntegrationEvent(true, false)]
    local procedure OnFindApplyingEntryOnBeforeCalcApplnAmount(var CustLedgerEntry: Record "Cust. Ledger Entry")
    begin
    end;

    /// <summary>
    /// Raised after a temporary applied customer ledger entry has been inserted during entry handling.
    /// </summary>
    /// <param name="TempAppliedCustLedgerEntry">The temporary applied customer ledger entry.</param>
    [IntegrationEvent(true, false)]
    local procedure OnHandleChosenEntriesOnAfterTempAppliedCustLedgEntryInsert(var TempAppliedCustLedgerEntry: Record "Cust. Ledger Entry" temporary)
    begin
    end;

    /// <summary>
    /// Raised before deleting a temporary applied customer ledger entry during entry handling.
    /// </summary>
    /// <param name="AppliedCustLedgEntry">The applied customer ledger entry.</param>
    /// <param name="TempAppliedCustLedgEntry">The temporary applied customer ledger entry to delete.</param>
    /// <param name="CurrencyCode">The currency code.</param>
    [IntegrationEvent(false, false)]
    local procedure OnHandleChosenEntriesOnBeforeDeleteTempAppliedCustLedgEntry(var AppliedCustLedgEntry: Record "Cust. Ledger Entry"; TempAppliedCustLedgEntry: Record "Cust. Ledger Entry" temporary; CurrencyCode: Code[10])
    begin
    end;


    /// <summary>
    /// Raised after checking against application currency when setting the Applies-to ID.
    /// </summary>
    /// <param name="CustLedgerEntry">The customer ledger entry.</param>
    /// <param name="CustLedgerEntry2">The second customer ledger entry.</param>
    /// <param name="CalcType">The calculation type option.</param>
    /// <param name="GenJnlLine">The general journal line.</param>
    /// <param name="SalesHeader">The sales header.</param>
    /// <param name="ApplyingCustLedgEntry">The applying customer ledger entry.</param>
    [IntegrationEvent(false, false)]
    local procedure OnSetCustApplIdOnAfterCheckAgainstApplnCurrency(var CustLedgerEntry: Record "Cust. Ledger Entry"; var CustLedgerEntry2: Record "Cust. Ledger Entry"; CalcType: Option; var GenJnlLine: Record "Gen. Journal Line"; SalesHeader: Record "Sales Header"; ApplyingCustLedgEntry: Record "Cust. Ledger Entry")
    begin
    end;

    /// <summary>
    /// Raised before calculating the application amount for direct calculation type.
    /// </summary>
    /// <param name="CustLedgerEntry">The customer ledger entry.</param>
    /// <param name="ApplyingAmount">The applying amount.</param>
    /// <param name="TempApplyingCustLedgEntry">The applying customer ledger entry.</param>
    [IntegrationEvent(true, false)]
    local procedure OnSetApplyingCustLedgEntryOnBeforeCalcTypeDirectCalcApplnAmount(var CustLedgerEntry: Record "Cust. Ledger Entry"; var ApplyingAmount: Decimal; var TempApplyingCustLedgEntry: Record "Cust. Ledger Entry")
    begin
    end;

    /// <summary>
    /// Raised before running customer entry edit when closing the page.
    /// </summary>
    /// <param name="CustLedgerEntry">The customer ledger entry.</param>
    [IntegrationEvent(true, false)]
    local procedure OnOnQueryClosePageOnBeforeRunCustEntryEdit(var CustLedgerEntry: Record "Cust. Ledger Entry")
    begin
    end;

    /// <summary>
    /// Raised before setting values during direct application posting.
    /// </summary>
    /// <param name="ApplicationDate">The application date.</param>
    [IntegrationEvent(false, false)]
    local procedure OnPostDirectApplicationBeforeSetValues(var ApplicationDate: Date)
    begin
    end;

    /// <summary>
    /// Raised before applying during direct application posting.
    /// </summary>
    /// <param name="GLSetup">The general ledger setup.</param>
    /// <param name="NewApplyUnapplyParameters">The apply/unapply parameters.</param>
    [IntegrationEvent(false, false)]
    local procedure OnPostDirectApplicationBeforeApply(GLSetup: Record "General Ledger Setup"; var NewApplyUnapplyParameters: Record "Apply Unapply Parameters")
    begin
    end;

    /// <summary>
    /// Raised after setting the applying customer ledger entry from a sales header.
    /// </summary>
    /// <param name="TempApplyingCustLedgEntry">The applying customer ledger entry.</param>
    /// <param name="SalesHeader">The sales header.</param>
    [IntegrationEvent(false, false)]
    local procedure OnAfterSetApplyingCustLedgEntrySalesHeader(var TempApplyingCustLedgEntry: Record "Cust. Ledger Entry" temporary; var SalesHeader: Record "Sales Header")
    begin
    end;


    /// <summary>
    /// Raised after setting the applying customer ledger entry from a general journal line.
    /// </summary>
    /// <param name="TempApplyingCustLedgEntry">The applying customer ledger entry.</param>
    /// <param name="GenJnlLine">The general journal line.</param>
    [IntegrationEvent(false, false)]
    local procedure OnAfterSetApplyingCustLedgEntryGenJnlLine(var TempApplyingCustLedgEntry: Record "Cust. Ledger Entry" temporary; var GenJnlLine: Record "Gen. Journal Line")
    begin
    end;

    /// <summary>
    /// Raised before calculating amounts during ledger entry exchange.
    /// </summary>
    /// <param name="CalcCustLedgerEntry">The customer ledger entry for calculation.</param>
    /// <param name="CustLedgerEntry">The original customer ledger entry.</param>
    /// <param name="CurrencyCode">The currency code.</param>
    /// <param name="CalculateCurrency">Indicates whether to calculate currency conversion.</param>
    /// <param name="IsHandled">Set to true to skip default processing.</param>
    [IntegrationEvent(false, false)]
    local procedure OnExchangeLedgerEntryAmountsOnBeforeCalculateAmounts(var CalcCustLedgerEntry: Record "Cust. Ledger Entry"; CustLedgerEntry: Record "Cust. Ledger Entry"; CurrencyCode: Code[10]; CalculateCurrency: Boolean; var IsHandled: Boolean)
    begin
    end;

    /// <summary>
    /// Raised after testing for earlier posting date during customer ledger entry check.
    /// </summary>
    /// <param name="ApplyingCustLedgerEntry">The applying customer ledger entry.</param>
    /// <param name="CustLedgerEntry">The customer ledger entry being checked.</param>
    /// <param name="CalcType">The calculation type.</param>
    /// <param name="OK">Indicates whether the check passed.</param>
    [IntegrationEvent(false, false)]
    local procedure OnCheckCustLedgEntryOnAfterEarlierPostingDateTest(ApplyingCustLedgerEntry: Record "Cust. Ledger Entry"; CustLedgerEntry: Record "Cust. Ledger Entry"; CalcType: Enum "Customer Apply Calculation Type"; var OK: Boolean)
    begin
    end;

    /// <summary>
    /// Raised after testing for earlier posting date when closing the page.
    /// </summary>
    /// <param name="ApplyingCustLedgerEntry">The applying customer ledger entry.</param>
    /// <param name="CustLedgerEntry">The customer ledger entry.</param>
    /// <param name="CalcType">The calculation type.</param>
    /// <param name="OK">Indicates whether the check passed.</param>
    [IntegrationEvent(false, false)]
    local procedure OnQueryClosePageOnAfterEarlierPostingDateTest(ApplyingCustLedgerEntry: Record "Cust. Ledger Entry"; CustLedgerEntry: Record "Cust. Ledger Entry"; CalcType: Enum "Customer Apply Calculation Type"; var OK: Boolean)
    begin
    end;

    /// <summary>
    /// Raised before checking against application currency when entry number is not null.
    /// </summary>
    /// <param name="CustLedgerEntry">The customer ledger entry.</param>
    /// <param name="GenJournalLine">The general journal line.</param>
    [IntegrationEvent(false, false)]
    local procedure OnCheckCustLedgEntryOnBeforeCheckAgainstApplnCurrencyWhenEntryNoIsNotNull(CustLedgerEntry: Record "Cust. Ledger Entry"; GenJournalLine: Record "Gen. Journal Line")
    begin
    end;

    /// <summary>
    /// Raised after the application has been posted during direct application.
    /// </summary>
    /// <param name="CustLedgerEntry">The customer ledger entry.</param>
    /// <param name="NewApplyUnapplyParameters">The apply/unapply parameters used.</param>
    /// <param name="PreviewMode">Indicates whether posting was in preview mode.</param>
    /// <param name="Applied">Indicates whether the application was successful.</param>
    [IntegrationEvent(false, false)]
    local procedure OnPostDirectApplicationOnAfterApply(var CustLedgerEntry: Record "Cust. Ledger Entry"; var NewApplyUnapplyParameters: Record "Apply Unapply Parameters"; PreviewMode: Boolean; Applied: Boolean)
    begin
    end;
}