Codeunit 122 Calc. Running GL. Acc. Balance
- App
- Base Application
- Namespace
- Microsoft.Finance.GeneralLedger.Ledger
- Versions
- 23-28
Versions171819202122232425262728
Source29
Source in 29
src/Layers/W1/BaseApp/Finance/GeneralLedger/Ledger/CalcRunningGLAccBalance.codeunit.al104 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.Finance.GeneralLedger.Ledger;
/// <summary>
/// Calculates running balance for G/L accounts with performance optimization through caching.
/// Provides running balance calculations in both local currency (LCY) and additional currency (ACY).
/// </summary>
/// <remarks>
/// Uses dictionary caching to optimize performance when calculating running balances for multiple entries.
/// Automatically resets cache when switching between different G/L accounts.
/// Excludes calculations for OData clients to prevent performance issues.
/// </remarks>
codeunit 122 "Calc. Running GL. Acc. Balance"
{
InherentPermissions = X;
var
GLEntry2: Record "G/L Entry";
ClientTypeManagement: Codeunit System.Environment."Client Type Management";
DayTotals: Dictionary of [Date, Decimal];
DayTotalsACY: Dictionary of [Date, Decimal];
EntryValues: Dictionary of [Integer, Decimal];
EntryValuesACY: Dictionary of [Integer, Decimal];
PrevAccNo: Code[20];
/// <summary>
/// Calculates running balance in local currency for the specified G/L entry.
/// </summary>
/// <param name="GLEntry">G/L entry for which to calculate running balance</param>
/// <returns>Running balance amount in local currency up to and including the specified entry</returns>
procedure GetGLAccBalance(var GLEntry: Record "G/L Entry"): Decimal
var
RunningBalance: Decimal;
RunningBalanceACY: Decimal;
begin
CalcGLAccBalance(GLEntry, RunningBalance, RunningBalanceACY);
exit(RunningBalance);
end;
/// <summary>
/// Calculates running balance in additional currency for the specified G/L entry.
/// </summary>
/// <param name="GLEntry">G/L entry for which to calculate running balance</param>
/// <returns>Running balance amount in additional currency up to and including the specified entry</returns>
procedure GetGLAccBalanceACY(var GLEntry: Record "G/L Entry"): Decimal
var
RunningBalance: Decimal;
RunningBalanceACY: Decimal;
begin
CalcGLAccBalance(GLEntry, RunningBalance, RunningBalanceACY);
exit(RunningBalanceACY);
end;
local procedure CalcGLAccBalance(var GLEntry: Record "G/L Entry"; var RunningBalance: Decimal; var RunningBalanceACY: Decimal)
var
DateTotal: Decimal;
DateTotalACY: Decimal;
begin
if ClientTypeManagement.GetCurrentClientType() in [ClientType::OData, ClientType::ODataV4] then
exit;
if (PrevAccNo <> '') and (PrevAccNo <> GLEntry."G/L Account No.") then begin
Clear(DayTotals);
Clear(DayTotalsACY);
end;
PrevAccNo := GLEntry."G/L Account No.";
if EntryValues.Get(GLEntry."Entry No.", RunningBalance) and EntryValuesACY.Get(GLEntry."Entry No.", RunningBalanceACY) then
exit;
GLEntry2.Reset();
GLEntry2.SetLoadFields("Entry No.", "G/L Account No.", "Posting Date", Amount, "Additional-Currency Amount");
GLEntry2.SetRange("G/L Account No.", GLEntry."G/L Account No.");
if not (DayTotals.Get(GLEntry."Posting Date", DateTotal) and DayTotalsACY.Get(GLEntry."Posting Date", DateTotalACY)) then begin
GLEntry2.SetFilter("Posting Date", '<=%1', GLEntry."Posting Date");
GLEntry2.CalcSums(Amount, "Additional-Currency Amount");
DateTotal := GLEntry2.Amount;
DateTotalACY := GLEntry2."Additional-Currency Amount";
DayTotals.Add(GLEntry."Posting Date", DateTotal);
DayTotalsACY.Add(GLEntry."Posting Date", DateTotalACY);
end;
RunningBalance := DateTotal;
RunningBalanceACY := DateTotalACY;
GLEntry2.SetRange("Posting Date", GLEntry."Posting Date");
GLEntry2.SetCurrentKey("Entry No.");
GLEntry2.Ascending(false);
if GLEntry2.FindSet() then
repeat
if GLEntry2."Entry No." = GLEntry."Entry No." then begin
RunningBalance := DateTotal;
RunningBalanceACY := DateTotalACY;
end;
if not EntryValues.ContainsKey(GLEntry2."Entry No.") then
EntryValues.Add(GLEntry2."Entry No.", DateTotal);
if not EntryValuesACY.ContainsKey(GLEntry2."Entry No.") then
EntryValuesACY.Add(GLEntry2."Entry No.", DateTotalACY);
DateTotal -= GLEntry2.Amount;
DateTotalACY -= GLEntry2."Additional-Currency Amount";
until GLEntry2.Next() = 0;
end;
}