Codeunit 432 Consolidate, source in 29
Source29
src/Layers/W1/BaseApp/Finance/Consolidation/Consolidate.Codeunit.al2101 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.Consolidation;
using Microsoft.Finance.Analysis;
using Microsoft.Finance.Currency;
using Microsoft.Finance.Dimension;
using Microsoft.Finance.GeneralLedger.Account;
using Microsoft.Finance.GeneralLedger.Journal;
using Microsoft.Finance.GeneralLedger.Ledger;
using Microsoft.Finance.GeneralLedger.Posting;
using Microsoft.Foundation.AuditCodes;
using System.Security.User;
/// <summary>
/// Core consolidation engine for processing subsidiary company data and creating consolidated G/L entries.
/// Handles currency translation, dimension mapping, and residual amount calculations during consolidation.
/// </summary>
/// <remarks>
/// Primary consolidation processing engine supporting file-based, database, and API data import methods.
/// Integrates with General Ledger posting, dimension management, and currency exchange rate systems.
/// Extensibility: Multiple integration events for custom validation, processing, and posting logic.
/// </remarks>
codeunit 432 Consolidate
{
Permissions = TableData "G/L Entry" = rimd,
tabledata "Analysis View" = r;
TableNo = "Business Unit";
trigger OnRun()
var
PreviousDate: Date;
i: Integer;
ShouldClearPreviousConsolidation: Boolean;
IsHandled: Boolean;
begin
OnBeforeOnRun(Rec);
BusUnit := Rec;
if not ValidateMaxNumberOfDaysInConsolidation(StartingDate, EndingDate) then
ReportError(StrSubstNo(Text008, ArrayLen(RoundingResiduals)));
if (Rec."Starting Date" <> 0D) or (Rec."Ending Date" <> 0D) then begin
if Rec."Starting Date" = 0D then
ReportError(StrSubstNo(
Text033, Rec.FieldCaption("Starting Date"),
Rec.FieldCaption("Ending Date"), Rec."Company Name"));
if Rec."Ending Date" = 0D then
ReportError(StrSubstNo(
Text033, Rec.FieldCaption("Ending Date"),
Rec.FieldCaption("Starting Date"), Rec."Company Name"));
if Rec."Starting Date" > Rec."Ending Date" then
ReportError(StrSubstNo(
Text032, Rec.FieldCaption("Starting Date"),
Rec.FieldCaption("Ending Date"), Rec."Company Name"));
end;
ConsolidatingClosingDate :=
(StartingDate = EndingDate) and
(StartingDate <> NormalDate(StartingDate));
if (StartingDate <> NormalDate(StartingDate)) and
(StartingDate <> EndingDate)
then
ReportError(Text030);
ReadSourceCodeSetup();
ClearInternals();
IsHandled := false;
OnRunOnBeforeWindowOpen(Window, IsHandled);
if not IsHandled then
Window.Open(Text001 + Text002 + Text003 + Text004);
Window.Update(1, BusUnit.Code);
ShouldClearPreviousConsolidation := not TestMode;
OnRunOnAfterCalcShouldClearPreviousConsolidation(ShouldClearPreviousConsolidation);
if ShouldClearPreviousConsolidation then begin
UpdatePhase(Text018);
ClearPreviousConsolidation();
end;
if (Rec."Last Balance Currency Factor" <> 0) and
(Rec."Balance Currency Factor" <> Rec."Last Balance Currency Factor")
then begin
UpdatePhase(Text019);
UpdatePriorPeriodBalances();
end;
// Consolidate Current Entries
UpdatePhase(Text020);
Clear(GenJnlLine);
GenJnlLine."Business Unit Code" := BusUnit.Code;
GenJnlLine."Document No." := GLDocNo;
GenJnlLine."Source Code" := ConsolidSourceCode;
GenJnlLine."Journal Template Name" := GenJnlBatch."Journal Template Name";
GenJnlLine."Journal Batch Name" := GenJnlBatch.Name;
TempSubsidGLEntry.Reset();
TempSubsidGLEntry.SetCurrentKey("G/L Account No.", "Posting Date");
TempSubsidGLEntry.SetRange("Posting Date", StartingDate, EndingDate);
OnBeforeUpdateTempGLEntry(TempSubsidGLEntry, GenJnlLine, CurErrorIdx, ErrorText, TestMode, Window);
TempSubsidGLAcc.Reset();
if TempSubsidGLAcc.FindSet() then
repeat
Window.Update(3, TempSubsidGLAcc."No.");
DimBufMgt.DeleteAllDimensions();
InitializeGLAccount();
PreviousDate := 0D;
OnRunOnBeforeLoopTempSubsidGLEntry(BusUnit, TempSubsidGLAcc);
if TempSubsidGLEntry.FindSet() then
repeat
OnRunOnTempSubsidGLEntryLoopStart(GenJnlLine, BusUnit, TempSubsidGLEntry);
if (TempSubsidGLEntry."Posting Date" <> NormalDate(TempSubsidGLEntry."Posting Date")) and
not ConsolidatingClosingDate
then
ReportError(
StrSubstNo(Text031,
TempSubsidGLEntry.TableCaption(),
TempSubsidGLEntry.FieldCaption("Posting Date"),
TempSubsidGLEntry."Posting Date"));
if (TempSubsidGLAcc."Consol. Translation Method" = TempSubsidGLAcc."Consol. Translation Method"::"Historical Rate") and
(TempSubsidGLEntry."Posting Date" <> PreviousDate)
then begin
if PreviousDate <> 0D then begin
TempDimBufOut.Reset();
TempDimBufOut.DeleteAll();
if TempGLEntry.FindSet() then
repeat
if not SkipAllDimensions then begin
DimBufMgt.GetDimensions(TempGLEntry."Entry No.", TempDimBufOut);
TempDimBufOut.SetRange("Entry No.", TempGLEntry."Entry No.");
end;
CreateAndPostGenJnlLine(GenJnlLine, TempGLEntry, TempDimBufOut);
until TempGLEntry.Next() = 0;
end;
TempGLEntry.Reset();
TempGLEntry.DeleteAll();
DimBufMgt.DeleteAllDimensions();
PreviousDate := TempSubsidGLEntry."Posting Date";
end;
TempDimBufIn.Reset();
TempDimBufIn.DeleteAll();
if not SkipAllDimensions then begin
TempSubsidDimBuf.SetRange("Entry No.", TempSubsidGLEntry."Entry No.");
if TempSubsidDimBuf.FindSet() then
repeat
if TempSelectedDim.Get('', 0, 0, '', TempSubsidDimBuf."Dimension Code") then begin
TempDimBufIn.Init();
TempDimBufIn."Table ID" := DATABASE::"G/L Entry";
TempDimBufIn."Entry No." := TempSubsidGLEntry."Entry No.";
TempDimBufIn."Dimension Code" := TempSubsidDimBuf."Dimension Code";
TempDimBufIn."Dimension Value Code" := TempSubsidDimBuf."Dimension Value Code";
OnRunOnBeforeInsertTempDimBuf(TempDimBufIn, TempSubsidDimBuf);
TempDimBufIn.Insert();
end;
until TempSubsidDimBuf.Next() = 0;
end;
UpdateTempGLEntry(TempSubsidGLEntry);
OnAfterUpdateTempGLEntry(BusUnit, TempSubsidGLEntry);
until TempSubsidGLEntry.Next() = 0;
TempDimBufOut.Reset();
TempDimBufOut.DeleteAll();
OnRunOnBeforeTempGLEntryLoop(TempGLEntry, TempSubsidGLAcc);
if TempGLEntry.FindSet() then
repeat
if not SkipAllDimensions then begin
DimBufMgt.GetDimensions(TempGLEntry."Entry No.", TempDimBufOut);
TempDimBufOut.SetRange("Entry No.", TempGLEntry."Entry No.");
end;
CreateAndPostGenJnlLine(GenJnlLine, TempGLEntry, TempDimBufOut);
until TempGLEntry.Next() = 0;
until TempSubsidGLAcc.Next() = 0;
// Post balancing entries and adjustments
UpdatePhase(Text025);
OnBeforePostBalancingEntries(GenJnlLine);
for i := 1 to NormalDate(EndingDate) - NormalDate(StartingDate) + 1 do begin
if ExchRateAdjAmounts[i] <> 0 then begin
GenJnlLine.Amount := ExchRateAdjAmounts[i];
if (BusUnit."Consolidation %" < 100) and
(BusUnit."Consolidation %" > 0)
then begin
GenJnlLine.Amount := GenJnlLine.Amount * 100 / BusUnit."Consolidation %";
MinorExchRateAdjAmts[i] :=
MinorExchRateAdjAmts[i] - GenJnlLine.Amount + ExchRateAdjAmounts[i];
end;
if GenJnlLine.Amount < 0 then begin
BusUnit.TestField("Exch. Rate Gains Acc.");
GenJnlLine."Account No." := BusUnit."Exch. Rate Gains Acc.";
end else begin
BusUnit.TestField("Exch. Rate Losses Acc.");
GenJnlLine."Account No." := BusUnit."Exch. Rate Losses Acc.";
end;
Window.Update(3, GenJnlLine."Account No.");
if not ConsolidatingClosingDate then
GenJnlLine."Posting Date" := StartingDate + i - 1
else
GenJnlLine."Posting Date" := StartingDate;
GenJnlLine.Description := StrSubstNo(Text015, WorkDate());
GenJnlPostLineTmp(GenJnlLine);
RoundingResiduals[i] := RoundingResiduals[i] + GenJnlLine.Amount;
end;
if CompExchRateAdjAmts[i] <> 0 then begin
GenJnlLine.Amount := CompExchRateAdjAmts[i];
if (BusUnit."Consolidation %" < 100) and
(BusUnit."Consolidation %" > 0)
then begin
GenJnlLine.Amount := GenJnlLine.Amount * 100 / BusUnit."Consolidation %";
MinorExchRateAdjAmts[i] :=
MinorExchRateAdjAmts[i] - GenJnlLine.Amount + CompExchRateAdjAmts[i];
end;
if GenJnlLine.Amount < 0 then begin
BusUnit.TestField("Comp. Exch. Rate Gains Acc.");
GenJnlLine."Account No." := BusUnit."Comp. Exch. Rate Gains Acc.";
end else begin
BusUnit.TestField("Comp. Exch. Rate Losses Acc.");
GenJnlLine."Account No." := BusUnit."Comp. Exch. Rate Losses Acc.";
end;
OnBeforeWindowUpdate(GenJnlLine);
Window.Update(3, GenJnlLine."Account No.");
if not ConsolidatingClosingDate then
GenJnlLine."Posting Date" := StartingDate + i - 1
else
GenJnlLine."Posting Date" := StartingDate;
GenJnlLine.Description := StrSubstNo(Text027 + Text015, WorkDate());
GenJnlPostLineTmp(GenJnlLine);
RoundingResiduals[i] := RoundingResiduals[i] + GenJnlLine.Amount;
end;
if EqExchRateAdjAmts[i] <> 0 then begin
GenJnlLine.Amount := EqExchRateAdjAmts[i];
if (BusUnit."Consolidation %" < 100) and
(BusUnit."Consolidation %" > 0)
then begin
GenJnlLine.Amount := GenJnlLine.Amount * 100 / BusUnit."Consolidation %";
MinorExchRateAdjAmts[i] :=
MinorExchRateAdjAmts[i] - GenJnlLine.Amount + EqExchRateAdjAmts[i];
end;
if GenJnlLine.Amount < 0 then begin
BusUnit.TestField("Equity Exch. Rate Gains Acc.");
GenJnlLine."Account No." := BusUnit."Equity Exch. Rate Gains Acc.";
end else begin
BusUnit.TestField("Equity Exch. Rate Losses Acc.");
GenJnlLine."Account No." := BusUnit."Equity Exch. Rate Losses Acc.";
end;
OnBeforeWindowUpdate(GenJnlLine);
Window.Update(3, GenJnlLine."Account No.");
if not ConsolidatingClosingDate then
GenJnlLine."Posting Date" := StartingDate + i - 1
else
GenJnlLine."Posting Date" := StartingDate;
GenJnlLine.Description := StrSubstNo(Text028 + Text015, WorkDate());
GenJnlPostLineTmp(GenJnlLine);
RoundingResiduals[i] := RoundingResiduals[i] + GenJnlLine.Amount;
end;
if MinorExchRateAdjAmts[i] <> 0 then begin
GenJnlLine.Amount := MinorExchRateAdjAmts[i];
if GenJnlLine.Amount < 0 then begin
BusUnit.TestField("Minority Exch. Rate Gains Acc.");
GenJnlLine."Account No." := BusUnit."Minority Exch. Rate Gains Acc.";
end else begin
BusUnit.TestField("Minority Exch. Rate Losses Acc");
GenJnlLine."Account No." := BusUnit."Minority Exch. Rate Losses Acc";
end;
OnBeforeWindowUpdate(GenJnlLine);
Window.Update(3, GenJnlLine."Account No.");
GenJnlLine."Posting Date" := StartingDate + i - 1;
GenJnlLine.Description := StrSubstNo(Text029 + Text015, WorkDate());
GenJnlPostLineTmp(GenJnlLine);
RoundingResiduals[i] := RoundingResiduals[i] + GenJnlLine.Amount;
end;
if RoundingResiduals[i] <> 0 then begin
GenJnlLine.Amount := -RoundingResiduals[i];
IsHandled := false;
OnRunOnBeforeSetResidualAccount(BusUnit, GenJnlLine, IsHandled);
if not IsHandled then begin
BusUnit.TestField("Residual Account");
GenJnlLine."Account No." := BusUnit."Residual Account";
end;
OnBeforeWindowUpdate(GenJnlLine);
Window.Update(3, GenJnlLine."Account No.");
if not ConsolidatingClosingDate then
GenJnlLine."Posting Date" := StartingDate + i - 1
else
GenJnlLine."Posting Date" := StartingDate;
GenJnlLine.Description :=
CopyStr(
StrSubstNo(Text016, WorkDate(), GenJnlLine.Amount),
1, MaxStrLen(GenJnlLine.Description));
GenJnlPostLineTmp(GenJnlLine);
end;
end;
if not TestMode then begin
UpdatePhase(Text026);
GenJnlPostLineFinally();
end;
Window.Close();
if not TestMode then begin
BusUnit."Last Balance Currency Factor" := BusUnit."Balance Currency Factor";
BusUnit."Last Run" := Today();
BusUnit.Modify();
OnAfterBusUnitModify(Rec, BusUnit);
end;
ShowAnalysisViewEntryMessage();
end;
internal procedure ValidateMaxNumberOfDaysInConsolidation(StartDate: Date; EndDate: Date): Boolean
begin
exit(NormalDate(EndDate) - NormalDate(StartDate) + 1 <= MaxNumberOfDaysInConsolidation());
end;
internal procedure MaxNumberOfDaysInConsolidation(): Integer
begin
exit(ArrayLen(RoundingResiduals));
end;
var
BusUnit: Record "Business Unit";
ConsolidGLAcc: Record "G/L Account";
ConsolidGLEntry: Record "G/L Entry";
ConsolidDimSetEntry: Record "Dimension Set Entry";
ConsolidCurrExchRate: Record "Currency Exchange Rate";
TempSubsidGLAcc: Record "G/L Account" temporary;
TempSubsidGLEntry: Record "G/L Entry" temporary;
TempSubsidDimBuf: Record "Dimension Buffer" temporary;
TempSubsidCurrExchRate: Record "Currency Exchange Rate" temporary;
TempSelectedDim: Record "Selected Dimension" temporary;
GenJnlLine: Record "Gen. Journal Line";
GenJnlBatch: Record "Gen. Journal Batch";
TempGenJnlLine: Record "Gen. Journal Line" temporary;
TempDimBufIn: Record "Dimension Buffer" temporary;
TempDimBufOut: Record "Dimension Buffer" temporary;
TempGLEntry: Record "G/L Entry" temporary;
DimBufMgt: Codeunit "Dimension Buffer Management";
DimMgt: Codeunit DimensionManagement;
Window: Dialog;
GLDocNo: Code[20];
ProductVersion: Code[10];
FormatVersion: Code[10];
SubCompanyName: Text[30];
CurrencyLCY: Code[10];
CurrencyACY: Code[10];
CurrencyPCY: Code[10];
StoredCheckSum: Decimal;
StartingDate: Date;
EndingDate: Date;
ConsolidSourceCode: Code[10];
RoundingResiduals: array[500] of Decimal;
ExchRateAdjAmounts: array[500] of Decimal;
CompExchRateAdjAmts: array[500] of Decimal;
EqExchRateAdjAmts: array[500] of Decimal;
MinorExchRateAdjAmts: array[500] of Decimal;
DeletedAmounts: array[500] of Decimal;
DeletedDates: array[500] of Date;
DeletedIndex: Integer;
MaxDeletedIndex: Integer;
AnalysisViewEntriesDeleted: Boolean;
#pragma warning disable AA0074
Text000: Label 'Enter a document number.';
Text001: Label 'Consolidating companies...\\';
#pragma warning disable AA0470
Text002: Label 'Business Unit Code #1###################\';
Text003: Label 'Phase #2############################\';
Text004: Label 'G/L Account No. #3##################';
#pragma warning restore AA0470
Text005: Label 'Analysis View Entries were deleted during the consolidation. An update is necessary.';
#pragma warning disable AA0470
Text006: Label 'There are more than %1 errors.';
Text008: Label 'The consolidation can include a maximum of %1 days.';
Text010: Label 'Previously consolidated entries cannot be erased because this would cause the general ledger to be out of balance by an amount of %1. ';
Text011: Label ' Check for manually posted G/L entries on %2 for posting across business units.';
Text013: Label '%1 adjusted from %2 to %3 on %4';
Text014: Label 'Adjustment of opening entries on %1';
Text015: Label 'Exchange rate adjustment on %1';
Text016: Label 'Posted %2 to residual account as of %1';
Text017: Label '%1 at exchange rate %2 on %3';
#pragma warning restore AA0470
Text018: Label 'Clear Previous Consolidation';
#pragma warning restore AA0074
SkipAllDimensions: Boolean;
#pragma warning disable AA0074
Text019: Label 'Update Prior Period Balances';
#pragma warning restore AA0074
ConsolidatingClosingDate: Boolean;
ExchRateAdjAmount: Decimal;
HistoricalCurrencyFactor: Decimal;
NextLineNo: Integer;
#pragma warning disable AA0074
Text020: Label 'Consolidate Current Data';
#pragma warning disable AA0470
Text021: Label 'Within the Subsidiary (%5), there are two G/L Accounts: %1 and %4; which refer to the same %2, but with a different %3.';
Text022: Label '%1 %2, referenced by %5 %3 %4, does not exist in the consolidated %3 table.';
Text023: Label '%7 %1 %2 must have the same %3 as consolidated %1 %4. (%5 and %6, respectively)';
Text024: Label '%1 at %2 %3';
#pragma warning restore AA0470
Text025: Label 'Calculate Residual Entries';
Text026: Label 'Post to General Ledger';
Text027: Label 'Composite ';
Text028: Label 'Equity ';
Text029: Label 'Minority ';
#pragma warning restore AA0074
TestMode: Boolean;
CurErrorIdx: Integer;
ErrorText: array[500] of Text;
#pragma warning disable AA0074
Text030: Label 'When using closing dates, the starting and ending dates must be the same.';
#pragma warning disable AA0470
Text031: Label 'A %1 with %2 on a closing date (%3) was found while consolidating non-closing entries.';
Text032: Label 'The %1 is later than the %2 in company %3.';
Text033: Label '%1 must not be empty when %2 is not empty, in company %3.';
Text034: Label 'It is not possible to consolidate ledger entry dimensions for G/L Entry No. %1, because there are conflicting dimension values %2 and %3 for consolidation dimension %4.';
#pragma warning restore AA0470
#pragma warning restore AA0074
ConsolidationAccMissingErr: Label 'The G/L account %1 can''t be found in the consolidation company, but it is specified in the business unit %2. Verify that the G/L account exists in the consolidation company or that it''s correctly mapped by setting the Consolidation fields in the subsidiary G/L account.', Comment = '%1 - A G/L account code, %2 - A Business Unit code';
/// <summary>
/// Sets the document number for consolidation entries that will be posted to the General Ledger.
/// </summary>
/// <param name="NewDocNo">Document number to use for posting consolidation entries</param>
procedure SetDocNo(NewDocNo: Code[20])
begin
GLDocNo := NewDocNo;
if GLDocNo = '' then
Error(Text000);
end;
/// <summary>
/// Configures the General Journal batch for posting consolidation entries.
/// </summary>
/// <param name="NewGenJnlBatch">General Journal batch configuration for consolidation posting</param>
procedure SetGenJnlBatch(NewGenJnlBatch: Record "Gen. Journal Batch")
begin
GenJnlBatch := NewGenJnlBatch;
end;
/// <summary>
/// Configures dimension selection filter for consolidation processing and posting.
/// </summary>
/// <param name="SelectedDim">Selected dimensions configuration for consolidation</param>
procedure SetSelectedDim(var SelectedDim: Record "Selected Dimension")
var
IsHandled: Boolean;
begin
OnBeforeSetSelectedDim(TempSelectedDim, SelectedDim, SkipAllDimensions, IsHandled);
if IsHandled then
exit;
TempSelectedDim.Reset();
TempSelectedDim.DeleteAll();
SkipAllDimensions := SelectedDim.IsEmpty();
if SkipAllDimensions then
exit;
if SelectedDim.FindSet() then
repeat
TempSelectedDim := SelectedDim;
TempSelectedDim."User ID" := '';
TempSelectedDim."Object Type" := 0;
TempSelectedDim."Object ID" := 0;
TempSelectedDim.Insert();
until SelectedDim.Next() = 0;
end;
/// <summary>
/// Initializes global variables for consolidation processing from subsidiary business unit data.
/// </summary>
/// <param name="NewProductVersion">Product version identifier from subsidiary system</param>
/// <param name="NewFormatVersion">Data format version for consolidation compatibility</param>
/// <param name="NewCompanyName">Name of subsidiary company being consolidated</param>
/// <param name="NewCurrencyLCY">Local currency code of subsidiary company</param>
/// <param name="NewCurrencyACY">Additional reporting currency code of subsidiary</param>
/// <param name="NewCurrencyPCY">Parallel currency code of subsidiary</param>
/// <param name="NewCheckSum">Validation checksum for data integrity verification</param>
/// <param name="NewStartingDate">Starting date for consolidation period</param>
/// <param name="NewEndingDate">Ending date for consolidation period</param>
procedure SetGlobals(NewProductVersion: Code[10]; NewFormatVersion: Code[10]; NewCompanyName: Text[30]; NewCurrencyLCY: Code[10]; NewCurrencyACY: Code[10]; NewCurrencyPCY: Code[10]; NewCheckSum: Decimal; NewStartingDate: Date; NewEndingDate: Date)
begin
ProductVersion := NewProductVersion;
FormatVersion := NewFormatVersion;
SubCompanyName := NewCompanyName;
CurrencyLCY := NewCurrencyLCY;
CurrencyACY := NewCurrencyACY;
CurrencyPCY := NewCurrencyPCY;
StoredCheckSum := NewCheckSum;
StartingDate := NewStartingDate;
EndingDate := NewEndingDate;
OnAfterSetGlobals(ProductVersion, FormatVersion, SubCompanyName, CurrencyLCY, CurrencyACY, CurrencyPCY, StoredCheckSum, StartingDate, EndingDate);
end;
local procedure ShowAnalysisViewEntryMessage()
var
IsHandled: Boolean;
begin
IsHandled := false;
OnBeforeShowAnalysisViewEntryMessage(AnalysisViewEntriesDeleted, IsHandled);
if IsHandled then
exit;
if AnalysisViewEntriesDeleted then
Message(Text005);
end;
/// <summary>
/// Adds a subsidiary G/L Account to the temporary consolidation account buffer for processing.
/// </summary>
/// <param name="NewGLAccount">G/L Account from subsidiary company with consolidation mapping configuration</param>
procedure InsertGLAccount(NewGLAccount: Record "G/L Account")
begin
TempSubsidGLAcc.Init();
TempSubsidGLAcc."No." := NewGLAccount."No.";
TempSubsidGLAcc."Consol. Translation Method" := NewGLAccount."Consol. Translation Method";
TempSubsidGLAcc."Consol. Debit Acc." := NewGLAccount."Consol. Debit Acc.";
TempSubsidGLAcc."Consol. Credit Acc." := NewGLAccount."Consol. Credit Acc.";
TempSubsidGLAcc.Insert();
end;
/// <summary>
/// Adds a subsidiary G/L Entry to the temporary consolidation entry buffer for processing.
/// </summary>
/// <param name="NewGLEntry">G/L Entry from subsidiary company to include in consolidation</param>
/// <returns>Entry number assigned to the temporary consolidation entry</returns>
procedure InsertGLEntry(NewGLEntry: Record "G/L Entry"): Integer
var
NextEntryNo: Integer;
begin
NextEntryNo := TempSubsidGLEntry.GetLastEntryNo() + 1;
TempSubsidGLEntry.Init();
TempSubsidGLEntry."Entry No." := NextEntryNo;
TempSubsidGLEntry."G/L Account No." := NewGLEntry."G/L Account No.";
TempSubsidGLEntry."Posting Date" := NewGLEntry."Posting Date";
TempSubsidGLEntry."Debit Amount" := NewGLEntry."Debit Amount";
TempSubsidGLEntry."Credit Amount" := NewGLEntry."Credit Amount";
TempSubsidGLEntry."Add.-Currency Debit Amount" := NewGLEntry."Add.-Currency Debit Amount";
TempSubsidGLEntry."Add.-Currency Credit Amount" := NewGLEntry."Add.-Currency Credit Amount";
OnBeforeInsertGLEntry(TempSubsidGLEntry, NewGLEntry);
TempSubsidGLEntry.Insert();
exit(NextEntryNo);
end;
/// <summary>
/// Adds dimension information for a subsidiary G/L Entry in the consolidation buffer.
/// </summary>
/// <param name="NewDimBuf">Dimension buffer containing dimension values for the G/L Entry</param>
/// <param name="GLEntryNo">Entry number of the G/L Entry to associate dimensions with</param>
procedure InsertEntryDim(NewDimBuf: Record "Dimension Buffer"; GLEntryNo: Integer)
begin
if TempSubsidDimBuf.Get(NewDimBuf."Table ID", GLEntryNo, NewDimBuf."Dimension Code") then begin
if NewDimBuf."Dimension Value Code" <> TempSubsidDimBuf."Dimension Value Code" then
Error(
Text034, GLEntryNo, NewDimBuf."Dimension Value Code", TempSubsidDimBuf."Dimension Value Code",
NewDimBuf."Dimension Code");
end else begin
TempSubsidDimBuf.Init();
TempSubsidDimBuf := NewDimBuf;
TempSubsidDimBuf."Entry No." := GLEntryNo;
TempSubsidDimBuf.Insert();
end;
end;
/// <summary>
/// Adds currency exchange rate information from subsidiary company to consolidation buffer.
/// </summary>
/// <param name="NewCurrExchRate">Currency exchange rate from subsidiary system</param>
procedure InsertExchRate(NewCurrExchRate: Record "Currency Exchange Rate")
begin
TempSubsidCurrExchRate.Init();
TempSubsidCurrExchRate."Currency Code" := NewCurrExchRate."Currency Code";
TempSubsidCurrExchRate."Starting Date" := NewCurrExchRate."Starting Date";
TempSubsidCurrExchRate."Relational Currency Code" := NewCurrExchRate."Relational Currency Code";
TempSubsidCurrExchRate."Exchange Rate Amount" := NewCurrExchRate."Exchange Rate Amount";
TempSubsidCurrExchRate."Relational Exch. Rate Amount" := NewCurrExchRate."Relational Exch. Rate Amount";
TempSubsidCurrExchRate.Insert();
end;
/// <summary>
/// Updates dimension set IDs for all G/L entries in the consolidation buffer based on dimension data.
/// </summary>
procedure UpdateGLEntryDimSetID()
begin
if SkipAllDimensions then
exit;
TempSubsidGLEntry.Reset();
TempSubsidDimBuf.Reset();
TempSubsidDimBuf.SetRange("Table ID", DATABASE::"G/L Entry");
TempSubsidGLEntry.Reset();
if TempSubsidGLEntry.FindSet(true) then
repeat
TempSubsidDimBuf.SetRange("Entry No.", TempSubsidGLEntry."Entry No.");
if TempSubsidDimBuf.FindFirst() then begin
TempSubsidGLEntry."Dimension Set ID" := DimMgt.CreateDimSetIDFromDimBuf(TempSubsidDimBuf);
OnUpdateGLEntryDimSetIDOnAfterAssignDimensionSetID(TempSubsidDimBuf);
TempSubsidGLEntry.Modify();
end;
until TempSubsidGLEntry.Next() = 0;
end;
/// <summary>
/// Calculates validation checksum for consolidation data integrity verification.
/// </summary>
/// <returns>Calculated checksum value for data validation</returns>
procedure CalcCheckSum() CheckSum: Decimal
begin
CheckSum :=
DateToDecimal(StartingDate) + DateToDecimal(EndingDate) +
TextToDecimal(FormatVersion) + TextToDecimal(ProductVersion);
TempSubsidGLAcc.Reset();
if TempSubsidGLAcc.FindSet() then
repeat
CheckSum :=
CheckSum +
TextToDecimal(CopyStr(TempSubsidGLAcc."No.", 1, 10)) + TextToDecimal(CopyStr(TempSubsidGLAcc."No.", 11, 10)) +
TextToDecimal(CopyStr(TempSubsidGLAcc."Consol. Debit Acc.", 1, 10)) +
TextToDecimal(CopyStr(TempSubsidGLAcc."Consol. Debit Acc.", 11, 10)) +
TextToDecimal(CopyStr(TempSubsidGLAcc."Consol. Credit Acc.", 1, 10)) +
TextToDecimal(CopyStr(TempSubsidGLAcc."Consol. Credit Acc.", 11, 10));
until TempSubsidGLAcc.Next() = 0;
TempSubsidGLEntry.Reset();
if TempSubsidGLEntry.FindSet() then
repeat
CheckSum := CheckSum +
TempSubsidGLEntry."Debit Amount" + TempSubsidGLEntry."Credit Amount" +
TempSubsidGLEntry."Add.-Currency Debit Amount" + TempSubsidGLEntry."Add.-Currency Credit Amount" +
DateToDecimal(TempSubsidGLEntry."Posting Date");
until TempSubsidGLEntry.Next() = 0;
end;
[Scope('OnPrem')]
procedure ImportFromXML(FileName: Text)
var
Consolidation: XMLport "Consolidation Import/Export";
InputFile: File;
InputStream: InStream;
IsHandled: Boolean;
begin
IsHandled := false;
OnBeforeImportFromXML(FileName, TempSubsidGLAcc, TempSubsidGLEntry, TempSubsidDimBuf, TempSubsidCurrExchRate, IsHandled);
if not IsHandled then begin
InputFile.TextMode(true);
InputFile.WriteMode(false);
InputFile.Open(FileName);
InputFile.CreateInStream(InputStream);
Consolidation.SetSource(InputStream);
Consolidation.Import();
InputFile.Close();
Consolidation.GetGLAccount(TempSubsidGLAcc);
OnAfterGetGLAccount(TempSubsidGLAcc);
Consolidation.GetGLEntry(TempSubsidGLEntry);
Consolidation.GetEntryDim(TempSubsidDimBuf);
Consolidation.GetExchRate(TempSubsidCurrExchRate);
Consolidation.GetGlobals(
ProductVersion, FormatVersion, SubCompanyName, CurrencyLCY, CurrencyACY, CurrencyPCY,
StoredCheckSum, StartingDate, EndingDate);
OnImportFromXMLOnBeforeSelectAllImportedDimensions(ProductVersion, FormatVersion, SubCompanyName, CurrencyLCY, CurrencyACY, CurrencyPCY, StoredCheckSum, StartingDate, EndingDate);
SelectAllImportedDimensions();
end;
end;
[Scope('OnPrem')]
procedure ExportToXML(FileName: Text)
var
Consolidation: XMLport "Consolidation Import/Export";
OutputFile: File;
OutputStream: OutStream;
IsHandled: Boolean;
begin
IsHandled := false;
OnBeforeExportToXML(FileName, TempSubsidGLAcc, TempSubsidGLEntry, TempSubsidDimBuf, TempSubsidCurrExchRate, IsHandled);
if IsHandled then
exit;
OutputFile.TextMode(true);
OutputFile.WriteMode(true);
OutputFile.Create(FileName);
OutputFile.CreateOutStream(OutputStream);
Consolidation.SetGlobals(SubCompanyName, CurrencyLCY, CurrencyACY, CurrencyPCY, StoredCheckSum, StartingDate, EndingDate);
Consolidation.SetGLAccount(TempSubsidGLAcc);
Consolidation.SetGLEntry(TempSubsidGLEntry);
Consolidation.SetEntryDim(TempSubsidDimBuf);
Consolidation.SetExchRate(TempSubsidCurrExchRate);
Consolidation.SetDestination(OutputStream);
Consolidation.Export();
OutputFile.Close();
end;
/// <summary>
/// Retrieves global consolidation variables for external processes and validation.
/// </summary>
/// <param name="ImpProductVersion">Returns product version from subsidiary data</param>
/// <param name="ImpFormatVersion">Returns data format version for compatibility checking</param>
/// <param name="ImpCompanyName">Returns subsidiary company name</param>
/// <param name="ImpCurrencyLCY">Returns local currency code of subsidiary</param>
/// <param name="ImpCurrencyACY">Returns additional reporting currency code</param>
/// <param name="ImpCurrencyPCY">Returns parallel currency code</param>
/// <param name="ImpCheckSum">Returns validation checksum for data integrity</param>
/// <param name="ImpStartingDate">Returns consolidation period starting date</param>
/// <param name="ImpEndingDate">Returns consolidation period ending date</param>
procedure GetGlobals(var ImpProductVersion: Code[10]; var ImpFormatVersion: Code[10]; var ImpCompanyName: Text[30]; var ImpCurrencyLCY: Code[10]; var ImpCurrencyACY: Code[10]; var ImpCurrencyPCY: Code[10]; var ImpCheckSum: Decimal; var ImpStartingDate: Date; var ImpEndingDate: Date)
begin
ImpProductVersion := ProductVersion;
ImpFormatVersion := FormatVersion;
ImpCompanyName := SubCompanyName;
ImpCurrencyLCY := CurrencyLCY;
ImpCurrencyACY := CurrencyACY;
ImpCurrencyPCY := CurrencyPCY;
ImpCheckSum := StoredCheckSum;
ImpStartingDate := StartingDate;
ImpEndingDate := EndingDate;
end;
/// <summary>
/// Enables test mode for consolidation processing to accumulate errors without stopping execution.
/// </summary>
/// <param name="NewTestMode">True to enable test mode, false for normal processing</param>
procedure SetTestMode(NewTestMode: Boolean)
begin
TestMode := NewTestMode;
CurErrorIdx := 0;
end;
/// <summary>
/// Retrieves accumulated error messages when running in test mode.
/// </summary>
/// <param name="NumErrors">Returns number of errors encountered</param>
/// <param name="Errors">Array of error messages collected during test mode processing</param>
procedure GetAccumulatedErrors(var NumErrors: Integer; var Errors: array[100] of Text)
var
Idx: Integer;
begin
NumErrors := 0;
Clear(Errors);
for Idx := 1 to CurErrorIdx do begin
NumErrors := NumErrors + 1;
Errors[NumErrors] := ErrorText[Idx];
if (Idx = ArrayLen(Errors)) and (CurErrorIdx > Idx) then begin
CopyArray(ErrorText, ErrorText, ArrayLen(Errors) + 1);
CurErrorIdx := CurErrorIdx - ArrayLen(Errors);
exit;
end;
end;
CurErrorIdx := 0;
Clear(ErrorText);
end;
/// <summary>
/// Automatically selects all dimensions that were imported from subsidiary data for consolidation processing.
/// </summary>
procedure SelectAllImportedDimensions()
begin
// assume all dimensions that were imported were also selected.
TempSelectedDim.Reset();
TempSelectedDim.DeleteAll();
if TempSubsidDimBuf.FindSet() then
repeat
TempSelectedDim.Init();
TempSelectedDim."User ID" := '';
TempSelectedDim."Object Type" := 0;
TempSelectedDim."Object ID" := 0;
TempSelectedDim."Dimension Code" := TempSubsidDimBuf."Dimension Code";
if TempSelectedDim.Insert() then;
until TempSubsidDimBuf.Next() = 0;
SkipAllDimensions := TempSelectedDim.IsEmpty();
end;
local procedure ReadSourceCodeSetup()
var
SourceCodeSetup: Record "Source Code Setup";
begin
SourceCodeSetup.Get();
ConsolidSourceCode := SourceCodeSetup.Consolidation;
end;
local procedure ClearInternals()
begin
NextLineNo := 0;
AnalysisViewEntriesDeleted := false;
TempGenJnlLine.Reset();
TempGenJnlLine.DeleteAll();
TempDimBufOut.Reset();
TempDimBufOut.DeleteAll();
TempDimBufIn.Reset();
TempDimBufIn.DeleteAll();
Clear(RoundingResiduals);
Clear(ExchRateAdjAmounts);
Clear(CompExchRateAdjAmts);
Clear(EqExchRateAdjAmts);
Clear(MinorExchRateAdjAmts);
end;
local procedure UpdatePhase(PhaseText: Text[50])
begin
Window.Update(2, PhaseText);
Window.Update(3, '');
end;
local procedure ClearPreviousConsolidation()
var
TempGLAccount: Record "G/L Account" temporary;
AnalysisView: Record "Analysis View";
TempAnalysisView: Record "Analysis View" temporary;
AnalysisViewEntry: Record "Analysis View Entry";
UserSetupManagement: Codeunit "User Setup Management";
AnalysisViewFound: Boolean;
IsHandled: Boolean;
begin
OnBeforeClearPreviousConsolidation(ConsolidGLEntry);
ClearAmountArray();
if not ConsolidGLEntry.SetCurrentKey("G/L Account No.", "Business Unit Code", "Global Dimension 1 Code", "Global Dimension 2 Code", "Posting Date") then
ConsolidGLEntry.SetCurrentKey("G/L Account No.", "Business Unit Code", "Posting Date");
ConsolidGLEntry.SetRange("Business Unit Code", BusUnit.Code);
ConsolidGLEntry.SetRange("Posting Date", StartingDate, EndingDate);
OnClearPreviousConsolidationOnAfterConsolidGLEntrySetFilters(ConsolidGLEntry);
if ConsolidGLEntry.FindSet(true) then
repeat
IsHandled := false;
OnClearPreviousConsolidationOnBeforeUpdateAmountArray(ConsolidGLEntry, DeletedAmounts, DeletedDates, DeletedIndex, IsHandled);
if not IsHandled then begin
UserSetupManagement.CheckAllowedPostingDate(ConsolidGLEntry."Posting Date");
UpdateAmountArray(ConsolidGLEntry."Posting Date", ConsolidGLEntry.Amount);
ConsolidGLEntry.Description := '';
ConsolidGLEntry.Amount := 0;
ConsolidGLEntry."Debit Amount" := 0;
ConsolidGLEntry."Credit Amount" := 0;
ConsolidGLEntry."Additional-Currency Amount" := 0;
ConsolidGLEntry."Add.-Currency Debit Amount" := 0;
ConsolidGLEntry."Add.-Currency Credit Amount" := 0;
OnClearPreviousConsolidationOnBeforeModifyConsolidGLEntry(ConsolidGLEntry);
ConsolidGLEntry.Modify();
if ConsolidGLEntry."G/L Account No." <> TempGLAccount."No." then begin
Window.Update(3, ConsolidGLEntry."G/L Account No.");
TempGLAccount."No." := ConsolidGLEntry."G/L Account No.";
TempGLAccount.Insert();
end;
end;
until ConsolidGLEntry.Next() = 0;
OnClearPreviousConsolidationOnBeforeCheckAmountArray(DeletedAmounts, DeletedDates);
CheckAmountArray();
if AnalysisView.FindSet() then
repeat
AnalysisViewFound := false;
if TempGLAccount.FindSet() then
repeat
AnalysisViewEntry.SetRange("Analysis View Code", AnalysisView.Code);
AnalysisViewEntry.SetRange("Account No.", TempGLAccount."No.");
AnalysisViewEntry.SetRange("Account Source", AnalysisViewEntry."Account Source"::"G/L Account");
if AnalysisViewEntry.FindFirst() then begin
TempAnalysisView.Code := AnalysisViewEntry."Analysis View Code";
TempAnalysisView."Account Source" := AnalysisViewEntry."Account Source";
TempAnalysisView.Insert();
AnalysisViewFound := true;
end;
until (TempGLAccount.Next() = 0) or AnalysisViewFound;
until AnalysisView.Next() = 0;
AnalysisViewEntry.Reset();
if TempAnalysisView.FindSet() then
repeat
AnalysisView.Get(TempAnalysisView.Code);
if AnalysisView.Blocked then begin
AnalysisView."Refresh When Unblocked" := true;
AnalysisView.Modify();
end else begin
AnalysisViewEntry.SetRange("Analysis View Code", TempAnalysisView.Code);
AnalysisViewEntry.DeleteAll();
AnalysisView."Last Entry No." := 0;
AnalysisView."Last Date Updated" := 0D;
AnalysisView.Modify();
AnalysisViewEntriesDeleted := true;
end;
until TempAnalysisView.Next() = 0;
end;
local procedure ClearAmountArray()
begin
Clear(DeletedAmounts);
Clear(DeletedDates);
DeletedIndex := 0;
MaxDeletedIndex := 0;
end;
local procedure UpdateAmountArray(PostingDate: Date; Amount: Decimal)
var
Top: Integer;
Bottom: Integer;
Middle: Integer;
Found: Boolean;
NotFound: Boolean;
idx: Integer;
begin
if DeletedIndex = 0 then begin
DeletedIndex := 1;
MaxDeletedIndex := 1;
DeletedDates[DeletedIndex] := PostingDate;
DeletedAmounts[DeletedIndex] := Amount;
end else
if PostingDate = DeletedDates[DeletedIndex] then
DeletedAmounts[DeletedIndex] := DeletedAmounts[DeletedIndex] + Amount
else begin
Top := 0;
Bottom := MaxDeletedIndex + 1;
Found := false;
NotFound := false;
repeat
Middle := (Top + Bottom) div 2;
if Bottom - Top <= 1 then
NotFound := true
else
if DeletedDates[Middle] > PostingDate then
Bottom := Middle
else
if DeletedDates[Middle] < PostingDate then
Top := Middle
else
Found := true;
until Found or NotFound;
if Found then begin
DeletedIndex := Middle;
DeletedAmounts[DeletedIndex] := DeletedAmounts[DeletedIndex] + Amount;
end else begin
if MaxDeletedIndex >= ArrayLen(DeletedDates) then
ReportError(StrSubstNo(Text008, ArrayLen(DeletedDates)))
else
MaxDeletedIndex := MaxDeletedIndex + 1;
for idx := MaxDeletedIndex downto Bottom + 1 do begin
DeletedAmounts[idx] := DeletedAmounts[idx - 1];
DeletedDates[idx] := DeletedDates[idx - 1];
end;
DeletedIndex := Bottom;
DeletedDates[DeletedIndex] := PostingDate;
DeletedAmounts[DeletedIndex] := Amount;
end;
end;
end;
local procedure CheckAmountArray()
var
idx: Integer;
IsHandled: Boolean;
begin
for idx := 1 to MaxDeletedIndex do
if DeletedAmounts[idx] <> 0 then begin
IsHandled := false;
OnCheckAmountArrayOnBeforeReportError(DeletedAmounts, DeletedDates, idx, IsHandled);
if not IsHandled then
ReportError(StrSubstNo(Text010 + Text011, DeletedAmounts[idx], DeletedDates[idx]));
end;
end;
local procedure TestGLAccounts()
var
AccountToTest: Record "G/L Account";
begin
// First test within the Subsidiary Chart of Accounts
AccountToTest := TempSubsidGLAcc;
if AccountToTest.TranslationMethodConflict(TempSubsidGLAcc) then begin
if TempSubsidGLAcc.GetFilter("Consol. Debit Acc.") <> '' then
ReportError(
StrSubstNo(
Text021,
TempSubsidGLAcc."No.",
TempSubsidGLAcc.FieldCaption("Consol. Debit Acc."),
TempSubsidGLAcc.FieldCaption("Consol. Translation Method"),
AccountToTest."No.", BusUnit.TableCaption()))
else
ReportError(
StrSubstNo(Text021,
TempSubsidGLAcc."No.",
TempSubsidGLAcc.FieldCaption("Consol. Credit Acc."),
TempSubsidGLAcc.FieldCaption("Consol. Translation Method"),
AccountToTest."No.", BusUnit.TableCaption()));
end else begin
TempSubsidGLAcc.Reset();
TempSubsidGLAcc := AccountToTest;
TempSubsidGLAcc.Find('=');
end;
OnTestGLAccountsOnBeforeTestForConflicts(TempSubsidGLAcc);
// Then, test for conflicts between subsidiary and parent (consolidated)
if TempSubsidGLAcc."Consol. Debit Acc." <> '' then begin
if not ConsolidGLAcc.Get(TempSubsidGLAcc."Consol. Debit Acc.") then
ReportError(
StrSubstNo(Text022,
TempSubsidGLAcc.FieldCaption("Consol. Debit Acc."), TempSubsidGLAcc."Consol. Debit Acc.",
TempSubsidGLAcc.TableCaption(), TempSubsidGLAcc."No.", BusUnit.TableCaption()));
if (TempSubsidGLAcc."Consol. Translation Method" <> ConsolidGLAcc."Consol. Translation Method") and
(BusUnit."File Format" <> BusUnit."File Format"::"Version 3.70 or Earlier (.txt)")
then
ReportError(
StrSubstNo(Text023,
TempSubsidGLAcc.TableCaption(), TempSubsidGLAcc."No.",
TempSubsidGLAcc.FieldCaption("Consol. Translation Method"), ConsolidGLAcc."No.",
TempSubsidGLAcc."Consol. Translation Method", ConsolidGLAcc."Consol. Translation Method",
BusUnit.TableCaption()));
end;
if TempSubsidGLAcc."Consol. Debit Acc." = TempSubsidGLAcc."Consol. Credit Acc." then
exit;
if TempSubsidGLAcc."Consol. Credit Acc." <> '' then begin
if not ConsolidGLAcc.Get(TempSubsidGLAcc."Consol. Credit Acc.") then
ReportError(
StrSubstNo(Text022,
TempSubsidGLAcc.FieldCaption("Consol. Credit Acc."), TempSubsidGLAcc."Consol. Credit Acc.",
TempSubsidGLAcc.TableCaption(), TempSubsidGLAcc."No.", BusUnit.TableCaption()));
if (TempSubsidGLAcc."Consol. Translation Method" <> ConsolidGLAcc."Consol. Translation Method") and
(BusUnit."File Format" <> BusUnit."File Format"::"Version 3.70 or Earlier (.txt)")
then
ReportError(
StrSubstNo(Text023,
TempSubsidGLAcc.TableCaption(), TempSubsidGLAcc."No.",
TempSubsidGLAcc.FieldCaption("Consol. Translation Method"), ConsolidGLAcc."No.",
TempSubsidGLAcc."Consol. Translation Method", ConsolidGLAcc."Consol. Translation Method",
BusUnit.TableCaption()));
end;
end;
local procedure UpdatePriorPeriodBalances()
var
idx: Integer;
AdjustmentAmount: Decimal;
begin
Clear(GenJnlLine);
OnBeforeUpdatePriorPeriodBalances(GenJnlLine);
GenJnlLine."Business Unit Code" := BusUnit.Code;
GenJnlLine."Document No." := GLDocNo;
GenJnlLine."Journal Template Name" := GenJnlBatch."Journal Template Name";
GenJnlLine."Journal Batch Name" := GenJnlBatch.Name;
GenJnlLine."Source Code" := ConsolidSourceCode;
BusUnit.TestField("Balance Currency Factor");
BusUnit.TestField("Last Balance Currency Factor");
ExchRateAdjAmount := 0;
idx := NormalDate(EndingDate) - NormalDate(StartingDate) + 1;
ConsolidGLAcc.Reset();
ConsolidGLAcc.SetRange("Account Type", ConsolidGLAcc."Account Type"::Posting);
ConsolidGLAcc.SetRange("Business Unit Filter", BusUnit.Code);
ConsolidGLAcc.SetRange("Date Filter", 0D, EndingDate);
ConsolidGLAcc.SetRange("Income/Balance", ConsolidGLAcc."Income/Balance"::"Balance Sheet");
ConsolidGLAcc.SetFilter(
ConsolidGLAcc."No.", '<>%1&<>%2&<>%3&<>%4&<>%5&<>%6&<>%7&<>%8&<>%9',
BusUnit."Exch. Rate Losses Acc.", BusUnit."Exch. Rate Gains Acc.",
BusUnit."Comp. Exch. Rate Gains Acc.", BusUnit."Comp. Exch. Rate Losses Acc.",
BusUnit."Equity Exch. Rate Gains Acc.", BusUnit."Equity Exch. Rate Losses Acc.",
BusUnit."Minority Exch. Rate Gains Acc.", BusUnit."Minority Exch. Rate Losses Acc",
BusUnit."Residual Account");
OnBeforeConsolidGlAccFindSet(ConsolidGLAcc);
if ConsolidGLAcc.FindSet() then
repeat
Window.Update(3, ConsolidGLAcc."No.");
case ConsolidGLAcc."Consol. Translation Method" of
ConsolidGLAcc."Consol. Translation Method"::"Average Rate (Manual)",
ConsolidGLAcc."Consol. Translation Method"::"Closing Rate":
// Post adjustment to existing balance to convert that balance to new Closing Rate
if SkipAllDimensions then begin
ConsolidGLAcc.CalcFields(ConsolidGLAcc."Debit Amount", ConsolidGLAcc."Credit Amount");
OnUpdatePriorPeriodBalancesOnBeforePostBalanceAdjustment(ConsolidGLAcc);
if ConsolidGLAcc."Debit Amount" <> 0 then
PostBalanceAdjustment(ConsolidGLAcc."No.", ConsolidGLAcc."Debit Amount");
if ConsolidGLAcc."Credit Amount" <> 0 then
PostBalanceAdjustment(ConsolidGLAcc."No.", -ConsolidGLAcc."Credit Amount");
end else begin
TempGLEntry.Reset();
TempGLEntry.DeleteAll();
DimBufMgt.DeleteAllDimensions();
ConsolidGLEntry.Reset();
ConsolidGLEntry.SetCurrentKey("G/L Account No.", "Posting Date");
ConsolidGLEntry.SetRange("G/L Account No.", ConsolidGLAcc."No.");
ConsolidGLEntry.SetRange("Posting Date", 0D, EndingDate);
ConsolidGLEntry.SetRange("Business Unit Code", BusUnit.Code);
OnBeforeConsolidGLEntryFindSet(ConsolidGLEntry);
if ConsolidGLEntry.FindSet() then
repeat
TempDimBufIn.Reset();
TempDimBufIn.DeleteAll();
ConsolidDimSetEntry.SetRange("Dimension Set ID", ConsolidGLEntry."Dimension Set ID");
if ConsolidDimSetEntry.FindSet() then
repeat
if TempSelectedDim.Get('', 0, 0, '', ConsolidDimSetEntry."Dimension Code") then begin
TempDimBufIn.Init();
TempDimBufIn."Table ID" := DATABASE::"G/L Entry";
TempDimBufIn."Entry No." := ConsolidGLEntry."Entry No.";
TempDimBufIn."Dimension Code" := ConsolidDimSetEntry."Dimension Code";
TempDimBufIn."Dimension Value Code" := ConsolidDimSetEntry."Dimension Value Code";
TempDimBufIn.Insert();
end;
until ConsolidDimSetEntry.Next() = 0;
UpdateTempGLEntry(ConsolidGLEntry);
until ConsolidGLEntry.Next() = 0;
TempDimBufOut.Reset();
TempDimBufOut.DeleteAll();
if TempGLEntry.FindSet() then
repeat
DimBufMgt.GetDimensions(TempGLEntry."Entry No.", TempDimBufOut);
TempDimBufOut.SetRange("Entry No.", TempGLEntry."Entry No.");
if TempGLEntry."Debit Amount" <> 0 then
PostBalanceAdjustment(ConsolidGLAcc."No.", TempGLEntry."Debit Amount");
if TempGLEntry."Credit Amount" <> 0 then
PostBalanceAdjustment(ConsolidGLAcc."No.", -TempGLEntry."Credit Amount");
until TempGLEntry.Next() = 0;
end;
ConsolidGLAcc."Consol. Translation Method"::"Historical Rate":
// accumulate adjustment for historical accounts
begin
ConsolidGLAcc.CalcFields(ConsolidGLAcc."Balance at Date");
AdjustmentAmount := 0;
ExchRateAdjAmounts[idx] := ExchRateAdjAmounts[idx] + AdjustmentAmount;
end;
ConsolidGLAcc."Consol. Translation Method"::"Composite Rate":
// accumulate adjustment for composite accounts
begin
ConsolidGLAcc.CalcFields(ConsolidGLAcc."Balance at Date");
AdjustmentAmount := 0;
CompExchRateAdjAmts[idx] := CompExchRateAdjAmts[idx] + AdjustmentAmount;
end;
ConsolidGLAcc."Consol. Translation Method"::"Equity Rate":
// accumulate adjustment for equity accounts
begin
ConsolidGLAcc.CalcFields(ConsolidGLAcc."Balance at Date");
AdjustmentAmount := 0;
EqExchRateAdjAmts[idx] := EqExchRateAdjAmts[idx] + AdjustmentAmount;
end;
end;
until ConsolidGLAcc.Next() = 0;
TempDimBufOut.Reset();
TempDimBufOut.DeleteAll();
if ExchRateAdjAmount <> 0 then begin
Clear(GenJnlLine);
GenJnlLine."Business Unit Code" := BusUnit.Code;
GenJnlLine."Document No." := GLDocNo;
GenJnlLine."Journal Template Name" := GenJnlBatch."Journal Template Name";
GenJnlLine."Journal Batch Name" := GenJnlBatch.Name;
GenJnlLine."Source Code" := ConsolidSourceCode;
GenJnlLine.Amount := -ExchRateAdjAmount;
if GenJnlLine.Amount < 0 then begin
BusUnit.TestField("Exch. Rate Gains Acc.");
GenJnlLine."Account No." := BusUnit."Exch. Rate Gains Acc.";
end else begin
BusUnit.TestField("Exch. Rate Losses Acc.");
GenJnlLine."Account No." := BusUnit."Exch. Rate Losses Acc.";
end;
OnBeforeGenJnlPostLineTmp(GenJnlLine);
Window.Update(3, GenJnlLine."Account No.");
GenJnlLine."Posting Date" := EndingDate;
GenJnlLine.Description := StrSubstNo(Text014, WorkDate());
GenJnlPostLineTmp(GenJnlLine);
end;
end;
local procedure PostBalanceAdjustment(GLAccNo: Code[20]; AmountToPost: Decimal)
var
TempDimSetEntry2: Record "Dimension Set Entry" temporary;
DimValue: Record "Dimension Value";
begin
GenJnlLine.Amount :=
Round(
(AmountToPost * BusUnit."Last Balance Currency Factor" / BusUnit."Balance Currency Factor") - AmountToPost);
if GenJnlLine.Amount <> 0 then begin
GenJnlLine."Account No." := GLAccNo;
GenJnlLine."Posting Date" := EndingDate;
GenJnlLine.Description :=
CopyStr(
StrSubstNo(
Text013,
AmountToPost,
Round(BusUnit."Last Balance Currency Factor", 0.00001),
Round(BusUnit."Balance Currency Factor", 0.00001),
WorkDate()),
1, MaxStrLen(GenJnlLine.Description));
if TempDimBufOut.FindSet() then begin
repeat
TempDimSetEntry2.Init();
TempDimSetEntry2."Dimension Code" := TempDimBufOut."Dimension Code";
TempDimSetEntry2."Dimension Value Code" := TempDimBufOut."Dimension Value Code";
DimValue.Get(TempDimSetEntry2."Dimension Code", TempDimSetEntry2."Dimension Value Code");
TempDimSetEntry2."Dimension Value ID" := DimValue."Dimension Value ID";
TempDimSetEntry2.Insert();
until TempDimBufOut.Next() = 0;
GenJnlLine."Dimension Set ID" := DimMgt.GetDimensionSetID(TempDimSetEntry2);
end else begin
GenJnlLine."Shortcut Dimension 1 Code" := '';
GenJnlLine."Shortcut Dimension 2 Code" := '';
GenJnlLine."Dimension Set ID" := 0;
end;
GenJnlPostLineTmp(GenJnlLine);
ExchRateAdjAmount := ExchRateAdjAmount + GenJnlLine.Amount;
end;
end;
local procedure UpdateTempGLEntry(var GLEntry: Record "G/L Entry")
var
DimEntryNo: Integer;
Found: Boolean;
IsHandled: Boolean;
begin
IsHandled := false;
OnBeforeUpdateTempGLEntryProcedure(TempGLEntry, GLEntry, IsHandled, TempDimBufIn);
if IsHandled then
exit;
DimEntryNo := DimBufMgt.FindDimensions(TempDimBufIn);
Found := TempDimBufIn.FindFirst();
if Found and (DimEntryNo = 0) then begin
TempGLEntry := GLEntry;
TempGLEntry."Entry No." := DimBufMgt.InsertDimensions(TempDimBufIn);
TempGLEntry.Insert();
end else
if TempGLEntry.Get(DimEntryNo) then begin
TempGLEntry.Amount := TempGLEntry.Amount + GLEntry.Amount;
TempGLEntry."Debit Amount" := TempGLEntry."Debit Amount" + GLEntry."Debit Amount";
TempGLEntry."Credit Amount" := TempGLEntry."Credit Amount" + GLEntry."Credit Amount";
TempGLEntry."Additional-Currency Amount" := TempGLEntry."Additional-Currency Amount" + GLEntry."Additional-Currency Amount";
TempGLEntry."Add.-Currency Debit Amount" := TempGLEntry."Add.-Currency Debit Amount" + GLEntry."Add.-Currency Debit Amount";
TempGLEntry."Add.-Currency Credit Amount" :=
TempGLEntry."Add.-Currency Credit Amount" + GLEntry."Add.-Currency Credit Amount";
TempGLEntry.Modify();
end else begin
TempGLEntry := GLEntry;
TempGLEntry."Entry No." := DimEntryNo;
TempGLEntry.Insert();
end;
end;
/// <summary>
/// Creates and posts a General Journal line for consolidation with currency translation and dimension processing.
/// </summary>
/// <param name="GenJnlLine">General Journal line template for consolidation posting</param>
/// <param name="GLEntry">G/L Entry from subsidiary containing amounts and account information</param>
/// <param name="DimBuf">Dimension buffer containing dimension values for the entry</param>
procedure CreateAndPostGenJnlLine(GenJnlLine: Record "Gen. Journal Line"; var GLEntry: Record "G/L Entry"; var DimBuf: Record "Dimension Buffer")
var
TempDimSetEntry2: Record "Dimension Set Entry" temporary;
DimValue: Record "Dimension Value";
ConsolidAmount: Decimal;
AmountToPost: Decimal;
AdjustAmount: Decimal;
ClosingAmount: Decimal;
TranslationNeeded: Boolean;
idx: Integer;
OriginalTranslationMethod: Integer;
begin
if BusUnit."Data Source" = BusUnit."Data Source"::"Local Curr. (LCY)" then
AmountToPost := GLEntry."Debit Amount" - GLEntry."Credit Amount"
else
AmountToPost := GLEntry."Add.-Currency Debit Amount" - GLEntry."Add.-Currency Credit Amount";
if AmountToPost > 0 then
GenJnlLine."Account No." := TempSubsidGLAcc."Consol. Debit Acc."
else
GenJnlLine."Account No." := TempSubsidGLAcc."Consol. Credit Acc.";
if GenJnlLine."Account No." = '' then
GenJnlLine."Account No." := TempSubsidGLAcc."No.";
if AmountToPost = 0 then
exit;
OnCreateAndPostGenJnlLineOnBeforeConsolidGLAccGet(GenJnlLine, GLEntry, BusUnit, TempSubsidGLAcc);
if not ConsolidGLAcc.Get(GenJnlLine."Account No.") then
Error(ConsolidationAccMissingErr, GenJnlLine."Account No.", BusUnit.Code);
OriginalTranslationMethod := TempSubsidGLAcc."Consol. Translation Method";
if TempSubsidGLAcc."Consol. Translation Method" = TempSubsidGLAcc."Consol. Translation Method"::"Average Rate (Manual)" then
if ConsolidGLAcc."Income/Balance" = ConsolidGLAcc."Income/Balance"::"Balance Sheet" then
TempSubsidGLAcc."Consol. Translation Method" := TempSubsidGLAcc."Consol. Translation Method"::"Closing Rate";
ConsolidAmount := AmountToPost * BusUnit."Consolidation %" / 100;
TranslationNeeded := (BusUnit."Currency Code" <> '');
if TranslationNeeded then
if BusUnit."Data Source" = BusUnit."Data Source"::"Add. Rep. Curr. (ACY)" then
TranslationNeeded := (BusUnit."Currency Code" <> CurrencyACY);
if TranslationNeeded then begin
ClosingAmount :=
Round(
ConsolidCurrExchRate.ExchangeAmtFCYToLCY(
EndingDate, BusUnit."Currency Code",
ConsolidAmount, BusUnit."Balance Currency Factor"));
case TempSubsidGLAcc."Consol. Translation Method" of
TempSubsidGLAcc."Consol. Translation Method"::"Closing Rate":
begin
GenJnlLine.Amount := ClosingAmount;
GenJnlLine.Description :=
CopyStr(
StrSubstNo(
Text017,
ConsolidAmount, Round(BusUnit."Balance Currency Factor", 0.00001), EndingDate),
1, MaxStrLen(GenJnlLine.Description));
end;
TempSubsidGLAcc."Consol. Translation Method"::"Composite Rate",
TempSubsidGLAcc."Consol. Translation Method"::"Equity Rate",
TempSubsidGLAcc."Consol. Translation Method"::"Average Rate (Manual)":
begin
GenJnlLine.Amount :=
Round(
ConsolidCurrExchRate.ExchangeAmtFCYToLCY(
EndingDate, BusUnit."Currency Code",
ConsolidAmount, BusUnit."Income Currency Factor"));
GenJnlLine.Description :=
CopyStr(
StrSubstNo(
Text017,
ConsolidAmount, Round(BusUnit."Income Currency Factor", 0.00001), EndingDate),
1, MaxStrLen(GenJnlLine.Description));
end;
TempSubsidGLAcc."Consol. Translation Method"::"Historical Rate":
begin
GenJnlLine.Amount := TranslateUsingHistoricalRate(ConsolidAmount, GLEntry."Posting Date");
GenJnlLine.Description :=
CopyStr(
StrSubstNo(
Text017,
ConsolidAmount, Round(HistoricalCurrencyFactor, 0.00001), GLEntry."Posting Date"),
1, MaxStrLen(GenJnlLine.Description));
end;
end;
end else begin
GenJnlLine.Amount := Round(ConsolidAmount);
ClosingAmount := GenJnlLine.Amount;
GenJnlLine.Description :=
StrSubstNo(Text024, AmountToPost, BusUnit."Consolidation %", BusUnit.FieldCaption("Consolidation %"));
end;
if TempSubsidGLAcc."Consol. Translation Method" = TempSubsidGLAcc."Consol. Translation Method"::"Historical Rate" then
GenJnlLine."Posting Date" := GLEntry."Posting Date"
else
GenJnlLine."Posting Date" := EndingDate;
idx := NormalDate(GenJnlLine."Posting Date") - NormalDate(StartingDate) + 1;
if DimBuf.FindSet() then begin
repeat
TempDimSetEntry2.Init();
TempDimSetEntry2."Dimension Code" := DimBuf."Dimension Code";
TempDimSetEntry2."Dimension Value Code" := DimBuf."Dimension Value Code";
DimValue.Get(TempDimSetEntry2."Dimension Code", TempDimSetEntry2."Dimension Value Code");
TempDimSetEntry2."Dimension Value ID" := DimValue."Dimension Value ID";
TempDimSetEntry2.Insert();
until DimBuf.Next() = 0;
GenJnlLine."Dimension Set ID" := DimMgt.GetDimensionSetID(TempDimSetEntry2);
DimMgt.UpdateGlobalDimFromDimSetID(GenJnlLine."Dimension Set ID",
GenJnlLine."Shortcut Dimension 1 Code", GenJnlLine."Shortcut Dimension 2 Code");
end;
OnBeforeTempDimSetEntryDelete(GenJnlLine, GLEntry);
if GenJnlLine.Amount <> 0 then
GenJnlPostLineTmp(GenJnlLine);
TempDimSetEntry2.Reset();
TempDimSetEntry2.DeleteAll();
RoundingResiduals[idx] := RoundingResiduals[idx] + GenJnlLine.Amount;
AdjustAmount := ClosingAmount - GenJnlLine.Amount;
case TempSubsidGLAcc."Consol. Translation Method" of
TempSubsidGLAcc."Consol. Translation Method"::"Composite Rate":
CompExchRateAdjAmts[idx] := CompExchRateAdjAmts[idx] + AdjustAmount;
TempSubsidGLAcc."Consol. Translation Method"::"Equity Rate":
EqExchRateAdjAmts[idx] := EqExchRateAdjAmts[idx] + AdjustAmount;
else
ExchRateAdjAmounts[idx] := ExchRateAdjAmounts[idx] + AdjustAmount;
end;
TempSubsidGLAcc."Consol. Translation Method" := OriginalTranslationMethod;
OnAfterCreateAndPostGenJnlLine(GenJnlLine, ConsolidAmount, CurrencyACY);
end;
local procedure TranslateUsingHistoricalRate(AmountToTranslate: Decimal; DateToTranslate: Date) TranslatedAmount: Decimal
begin
if BusUnit."Currency Exchange Rate Table" = BusUnit."Currency Exchange Rate Table"::"Local"
then begin
ConsolidCurrExchRate.Reset();
ConsolidCurrExchRate.SetRange("Currency Code", BusUnit."Currency Code");
ConsolidCurrExchRate.SetRange("Starting Date", 0D, DateToTranslate);
ConsolidCurrExchRate.FindLast();
ConsolidCurrExchRate.TestField("Exchange Rate Amount");
ConsolidCurrExchRate.TestField("Relational Exch. Rate Amount");
ConsolidCurrExchRate.TestField("Relational Currency Code", '');
HistoricalCurrencyFactor :=
ConsolidCurrExchRate."Exchange Rate Amount" / ConsolidCurrExchRate."Relational Exch. Rate Amount";
end else begin
TempSubsidCurrExchRate.Reset();
TempSubsidCurrExchRate.SetRange("Starting Date", 0D, DateToTranslate);
TempSubsidCurrExchRate.SetRange("Currency Code", CurrencyPCY);
TempSubsidCurrExchRate.FindLast();
TempSubsidCurrExchRate.TestField("Exchange Rate Amount");
TempSubsidCurrExchRate.TestField("Relational Exch. Rate Amount");
TempSubsidCurrExchRate.TestField("Relational Currency Code", '');
HistoricalCurrencyFactor := TempSubsidCurrExchRate."Relational Exch. Rate Amount" /
TempSubsidCurrExchRate."Exchange Rate Amount";
if BusUnit."Data Source" = BusUnit."Data Source"::"Add. Rep. Curr. (ACY)" then begin
TempSubsidCurrExchRate.SetRange("Currency Code", CurrencyACY);
TempSubsidCurrExchRate.FindLast();
TempSubsidCurrExchRate.TestField("Exchange Rate Amount");
TempSubsidCurrExchRate.TestField("Relational Exch. Rate Amount");
TempSubsidCurrExchRate.TestField("Relational Currency Code", '');
HistoricalCurrencyFactor := HistoricalCurrencyFactor *
TempSubsidCurrExchRate."Exchange Rate Amount" / TempSubsidCurrExchRate."Relational Exch. Rate Amount";
end;
end;
TranslatedAmount := Round(AmountToTranslate / HistoricalCurrencyFactor);
end;
local procedure GenJnlPostLineTmp(var GenJnlLine: Record "Gen. Journal Line")
begin
NextLineNo := NextLineNo + 1;
TempGenJnlLine := GenJnlLine;
TempGenJnlLine.Amount := Round(TempGenJnlLine.Amount);
TempGenJnlLine."Line No." := NextLineNo;
TempGenJnlLine."System-Created Entry" := true;
OnBeforeTempGenJnlLineInsert(TempGenJnlLine);
DimMgt.UpdateGlobalDimFromDimSetID(TempGenJnlLine."Dimension Set ID",
TempGenJnlLine."Shortcut Dimension 1 Code", TempGenJnlLine."Shortcut Dimension 2 Code");
TempGenJnlLine.Insert();
end;
local procedure GenJnlPostLineFinally()
var
GenJnlPostLine: Codeunit "Gen. Jnl.-Post Line";
begin
TempGenJnlLine.SetCurrentKey("Journal Template Name", "Journal Batch Name", "Posting Date");
if TempGenJnlLine.FindSet() then
repeat
Window.Update(3, TempGenJnlLine."Account No.");
OnBeforeGenJnlPostLine(TempGenJnlLine);
GenJnlPostLine.RunWithCheck(TempGenJnlLine);
until TempGenJnlLine.Next() = 0;
end;
local procedure TextToDecimal(Txt: Text[50]) Result: Decimal
var
DecOnlyTxt: Text[50];
Idx: Integer;
begin
for Idx := 1 to StrLen(Txt) do
if Txt[Idx] in ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'] then
DecOnlyTxt := DecOnlyTxt + CopyStr(Txt, Idx, 1);
if DecOnlyTxt = '' then
Result := 0
else
Evaluate(Result, DecOnlyTxt);
end;
local procedure DateToDecimal(Dt: Date) Result: Decimal
var
Mon: Decimal;
Day: Decimal;
Yr: Decimal;
begin
Day := Date2DMY(Dt, 1);
Mon := Date2DMY(Dt, 2);
Yr := Date2DMY(Dt, 3);
Result := Yr * 100 + Mon + Day / 100;
end;
local procedure ReportError(ErrorMsg: Text)
begin
if TestMode then begin
if CurErrorIdx = ArrayLen(ErrorText) then
ErrorText[CurErrorIdx] := StrSubstNo(Text006, ArrayLen(ErrorText))
else begin
CurErrorIdx := CurErrorIdx + 1;
ErrorText[CurErrorIdx] := ErrorMsg;
end;
end else
Error(ErrorMsg);
end;
/// <summary>
/// Returns the count of subsidiary G/L accounts available for consolidation processing.
/// </summary>
/// <returns>Number of G/L accounts in the temporary subsidiary G/L account table</returns>
procedure GetNumSubsidGLAcc(): Integer
begin
TempSubsidGLAcc.Reset();
exit(TempSubsidGLAcc.Count);
end;
/// <summary>
/// Retrieves the first subsidiary G/L account for consolidation processing.
/// Initializes account traversal and performs validation if running in test mode.
/// </summary>
/// <param name="GlAccount">G/L Account record to populate with first subsidiary account data</param>
/// <returns>True if first subsidiary account exists, false otherwise</returns>
procedure Get1stSubsidGLAcc(var GlAccount: Record "G/L Account"): Boolean
begin
TempSubsidGLAcc.Reset();
if TempSubsidGLAcc.FindFirst() then begin
GlAccount := TempSubsidGLAcc;
if TestMode then
TestGLAccounts();
exit(true);
end;
exit(false);
end;
/// <summary>
/// Retrieves the next subsidiary G/L account in consolidation processing sequence.
/// Advances account traversal and performs validation if running in test mode.
/// </summary>
/// <param name="GLAccount">G/L Account record to populate with next subsidiary account data</param>
/// <returns>True if next subsidiary account exists, false if end of accounts reached</returns>
procedure GetNxtSubsidGLAcc(var GLAccount: Record "G/L Account"): Boolean
begin
if TempSubsidGLAcc.Next() <> 0 then begin
GLAccount := TempSubsidGLAcc;
if TestMode then
TestGLAccounts();
exit(true);
end;
exit(false);
end;
/// <summary>
/// Returns the count of subsidiary G/L entries for the current G/L account during consolidation.
/// Filters entries by current G/L account number and posting date.
/// </summary>
/// <returns>Number of G/L entries for current account in consolidation processing</returns>
procedure GetNumSubsidGLEntry(): Integer
begin
TempSubsidGLEntry.Reset();
TempSubsidGLEntry.SetCurrentKey("G/L Account No.", "Posting Date");
TempSubsidGLEntry.SetRange("G/L Account No.", TempSubsidGLAcc."No.");
exit(TempSubsidGLEntry.Count());
end;
/// <summary>
/// Retrieves the first subsidiary G/L entry for the current account in consolidation processing.
/// Performs posting date validation and closes-date handling if in test mode.
/// </summary>
/// <param name="GLEntry">G/L Entry record to populate with first subsidiary entry data</param>
/// <returns>True if first entry exists for current account, false otherwise</returns>
procedure Get1stSubsidGLEntry(var GLEntry: Record "G/L Entry"): Boolean
var
IsError: Boolean;
ErrorMsg: Text;
begin
ConsolidatingClosingDate :=
(StartingDate = EndingDate) and
(StartingDate <> NormalDate(StartingDate));
if (StartingDate <> NormalDate(StartingDate)) and
(StartingDate <> EndingDate)
then
ReportError(Text030);
TempSubsidGLEntry.Reset();
TempSubsidGLEntry.SetCurrentKey("G/L Account No.", "Posting Date");
TempSubsidGLEntry.SetRange("G/L Account No.", TempSubsidGLAcc."No.");
if TempSubsidGLEntry.FindFirst() then begin
GLEntry := TempSubsidGLEntry;
if TestMode then begin
if (TempSubsidGLEntry."Posting Date" <> NormalDate(TempSubsidGLEntry."Posting Date")) and
not ConsolidatingClosingDate
then
ReportError(StrSubstNo(
Text031,
TempSubsidGLEntry.TableCaption,
TempSubsidGLEntry.FieldCaption("Posting Date"),
TempSubsidGLEntry."Posting Date"));
IsError := false;
OnAfterCheckPostingDate(TempSubsidGLEntry, IsError, ErrorMsg);
if IsError then
ReportError(ErrorMsg);
end;
exit(true);
end;
exit(false);
end;
/// <summary>
/// Retrieves the next subsidiary G/L entry for the current account in consolidation processing.
/// Advances entry traversal and performs posting date validation if in test mode.
/// </summary>
/// <param name="GLEntry">G/L Entry record to populate with next subsidiary entry data</param>
/// <returns>True if next entry exists for current account, false if end of entries reached</returns>
procedure GetNxtSubsidGLEntry(var GLEntry: Record "G/L Entry"): Boolean
var
IsError: Boolean;
ErrorMsg: Text;
begin
if TempSubsidGLEntry.Next() <> 0 then begin
GLEntry := TempSubsidGLEntry;
if TestMode then begin
if (TempSubsidGLEntry."Posting Date" <> NormalDate(TempSubsidGLEntry."Posting Date")) and
not ConsolidatingClosingDate
then
ReportError(StrSubstNo(
Text031,
TempSubsidGLEntry.TableCaption,
TempSubsidGLEntry.FieldCaption("Posting Date"),
TempSubsidGLEntry."Posting Date"));
IsError := false;
OnAfterCheckPostingDate(TempSubsidGLEntry, IsError, ErrorMsg);
if IsError then
ReportError(ErrorMsg);
end;
exit(true);
end else
exit(false);
end;
local procedure InitializeGLAccount()
begin
TestGLAccounts();
TempGLEntry.Reset();
TempGLEntry.DeleteAll();
TempSubsidGLEntry.SetRange("G/L Account No.", TempSubsidGLAcc."No.");
end;
internal procedure GetGLAccounts(var TempGLAccount: Record "G/L Account" temporary)
begin
if not TempSubsidGLAcc.FindSet() then
exit;
repeat
TempGLAccount.TransferFields(TempSubsidGLAcc);
TempGLAccount.Insert();
until TempSubsidGLAcc.Next() = 0;
end;
/// <summary>
/// Integration event raised before posting a General Journal line during consolidation.
/// </summary>
/// <param name="GenJnlLine">General Journal line being posted with consolidation data</param>
[IntegrationEvent(false, false)]
local procedure OnBeforeGenJnlPostLine(var GenJnlLine: Record "Gen. Journal Line")
begin
end;
/// <summary>
/// Integration event raised before inserting a subsidiary G/L Entry into consolidation buffer.
/// </summary>
/// <param name="SubsidGLEntry">Subsidiary G/L Entry being processed for consolidation</param>
/// <param name="GLEntry">Original G/L Entry from subsidiary data source</param>
[IntegrationEvent(false, false)]
local procedure OnBeforeInsertGLEntry(var SubsidGLEntry: Record "G/L Entry"; GLEntry: Record "G/L Entry")
begin
end;
/// <summary>
/// Integration event raised before displaying analysis view entry deletion message during consolidation.
/// </summary>
/// <param name="AnalysisViewEntriesDeleted">Indicates whether analysis view entries were deleted</param>
/// <param name="IsHandled">Set to true to skip showing the message</param>
[IntegrationEvent(true, false)]
local procedure OnBeforeShowAnalysisViewEntryMessage(var AnalysisViewEntriesDeleted: Boolean; var IsHandled: Boolean)
begin
end;
/// <summary>
/// Integration event raised during previous consolidation clearing before checking amount arrays.
/// </summary>
/// <param name="DeletedAmountsArray">Array containing deleted consolidation amounts</param>
/// <param name="DeletedDatesArray">Array containing dates of deleted consolidation entries</param>
[IntegrationEvent(false, false)]
local procedure OnClearPreviousConsolidationOnBeforeCheckAmountArray(var DeletedAmountsArray: array[500] of Decimal; var DeletedDatesArray: array[500] of Date)
begin
end;
/// <summary>
/// Integration event raised during previous consolidation clearing before updating amount arrays.
/// </summary>
/// <param name="ConsolidatedGLEntry">Consolidated G/L Entry being processed for removal</param>
/// <param name="DeletedAmountsArray">Array tracking deleted consolidation amounts</param>
/// <param name="DeletedDatesArray">Array tracking dates of deleted entries</param>
/// <param name="DeletedIdx">Index for tracking deleted entries in arrays</param>
/// <param name="IsHandled">Set to true to skip standard array update processing</param>
[IntegrationEvent(false, false)]
local procedure OnClearPreviousConsolidationOnBeforeUpdateAmountArray(var ConsolidatedGLEntry: Record "G/L Entry"; var DeletedAmountsArray: array[500] of Decimal; var DeletedDatesArray: array[500] of Date; var DeletedIdx: Integer; var IsHandled: Boolean)
begin
end;
/// <summary>
/// Integration event raised after assigning dimension set ID during G/L Entry dimension processing.
/// </summary>
/// <param name="TempSubsidDimBuf">Temporary dimension buffer with assigned dimension set ID</param>
[IntegrationEvent(false, false)]
local procedure OnUpdateGLEntryDimSetIDOnAfterAssignDimensionSetID(var TempSubsidDimBuf: Record "Dimension Buffer" temporary)
begin
end;
/// <summary>
/// Integration event raised before updating temporary G/L entry during consolidation processing.
/// Enables custom validation and modification of subsidiary G/L entry data before consolidation.
/// </summary>
/// <param name="TempSubsidGLEntry">Temporary subsidiary G/L Entry being processed</param>
/// <param name="GenJnlLine">General Journal Line for consolidation posting</param>
/// <param name="CurErrorIdx">Current error index for error tracking</param>
/// <param name="ErrorText">Array of error messages for consolidation validation</param>
/// <param name="TestMode">Indicates if consolidation is running in test mode</param>
/// <param name="WindowDialog">Progress dialog for consolidation status updates</param>
[IntegrationEvent(false, false)]
local procedure OnBeforeUpdateTempGLEntry(var TempSubsidGLEntry: Record "G/L Entry"; var GenJnlLine: Record "Gen. Journal Line"; var CurErrorIdx: Integer; var ErrorText: array[500] of Text; TestMode: Boolean; var WindowDialog: Dialog)
begin
end;
/// <summary>
/// Integration event raised after updating temporary G/L entry during consolidation processing.
/// Enables custom post-processing of consolidated subsidiary G/L entry data.
/// </summary>
/// <param name="BusUnit">Business Unit being consolidated</param>
/// <param name="TempSubsidGLEntry">Temporary subsidiary G/L Entry after processing</param>
[IntegrationEvent(false, false)]
local procedure OnAfterUpdateTempGLEntry(var BusUnit: Record "Business Unit"; var TempSubsidGLEntry: Record "G/L Entry")
begin
end;
/// <summary>
/// Integration event raised after creating and posting general journal line during consolidation.
/// Enables custom post-processing of consolidated journal entries and currency handling.
/// </summary>
/// <param name="GenJournalLine">General Journal Line that was created and posted</param>
/// <param name="ConsolidAmount">Consolidated amount after currency translation</param>
/// <param name="CurrencyACY">Additional Currency Code used for consolidation</param>
[IntegrationEvent(false, false)]
local procedure OnAfterCreateAndPostGenJnlLine(var GenJournalLine: Record "Gen. Journal Line"; ConsolidAmount: Decimal; CurrencyACY: Code[10])
begin
end;
/// <summary>
/// Integration event raised before consolidation processing begins for a business unit.
/// Enables custom initialization and validation before consolidation execution.
/// </summary>
/// <param name="BusinessUnit">Business Unit record about to be processed for consolidation</param>
[IntegrationEvent(true, false)]
local procedure OnBeforeOnRun(var BusinessUnit: Record "Business Unit")
begin
end;
/// <summary>
/// Integration event raised before posting balancing entries during consolidation.
/// Enables custom modification of balancing journal entries before posting.
/// </summary>
/// <param name="GenJnlLine">General Journal Line for balancing entries</param>
[IntegrationEvent(false, false)]
local procedure OnBeforePostBalancingEntries(var GenJnlLine: Record "Gen. Journal Line")
begin
end;
/// <summary>
/// Integration event raised before updating consolidation progress window during processing.
/// Enables custom progress tracking and status display modifications.
/// </summary>
/// <param name="GenJnlLine">General Journal Line being processed in current consolidation step</param>
[IntegrationEvent(false, false)]
local procedure OnBeforeWindowUpdate(var GenJnlLine: Record "Gen. Journal Line")
begin
end;
/// <summary>
/// Integration event raised after modifying Business Unit record during consolidation processing.
/// Enables custom post-processing of business unit configuration changes.
/// </summary>
/// <param name="Rec">Current Business Unit record after modification</param>
/// <param name="BusUnit">Original Business Unit record before modification</param>
[IntegrationEvent(false, false)]
local procedure OnAfterBusUnitModify(var Rec: Record "Business Unit"; var BusUnit: Record "Business Unit")
begin
end;
/// <summary>
/// Integration event raised before setting selected dimensions during consolidation processing.
/// Enables custom dimension selection logic and dimension filtering modifications.
/// </summary>
/// <param name="TempSelectedDim">Temporary Selected Dimension record for processing</param>
/// <param name="SelectedDim">Selected Dimension record from configuration</param>
/// <param name="SkipAllDimensions">Flag indicating whether to skip all dimension processing</param>
/// <param name="IsHandled">Set to true to bypass standard dimension selection logic</param>
[IntegrationEvent(false, false)]
local procedure OnBeforeSetSelectedDim(var TempSelectedDim: Record "Selected Dimension"; var SelectedDim: Record "Selected Dimension"; var SkipAllDimensions: Boolean; var IsHandled: Boolean)
begin
end;
/// <summary>
/// Integration event raised after retrieving G/L account during consolidation processing.
/// Enables custom post-processing of subsidiary G/L account data.
/// </summary>
/// <param name="TempSubsidGLAcc">Temporary subsidiary G/L Account record after retrieval</param>
[IntegrationEvent(false, false)]
local procedure OnAfterGetGLAccount(var TempSubsidGLAcc: Record "G/L Account")
begin
end;
/// <summary>
/// Integration event raised before clearing previous consolidation entries.
/// Enables custom logic for handling existing consolidated G/L entries before new consolidation.
/// </summary>
/// <param name="ConsolidGLEntry">Consolidated G/L Entry record to be cleared</param>
[IntegrationEvent(false, false)]
local procedure OnBeforeClearPreviousConsolidation(var ConsolidGLEntry: Record "G/L Entry")
begin
end;
/// <summary>
/// Integration event raised before updating prior period balances during consolidation.
/// Enables custom handling of prior period balance adjustments and journal line modifications.
/// </summary>
/// <param name="GenJnlLine">General Journal Line for prior period balance updates</param>
[IntegrationEvent(false, false)]
local procedure OnBeforeUpdatePriorPeriodBalances(var GenJnlLine: Record "Gen. Journal Line")
begin
end;
/// <summary>
/// Integration event raised before finding consolidated G/L entries during consolidation processing.
/// Enables custom filtering and selection criteria for consolidated entry processing.
/// </summary>
/// <param name="ConsolidGLEntry">Consolidated G/L Entry record for processing</param>
[IntegrationEvent(false, false)]
local procedure OnBeforeConsolidGLEntryFindSet(var ConsolidGLEntry: Record "G/L Entry")
begin
end;
/// <summary>
/// Integration event raised before finding consolidated G/L accounts during consolidation processing.
/// Enables custom filtering and selection criteria for consolidated account processing.
/// </summary>
/// <param name="ConsolidGLAcc">Consolidated G/L Account record for processing</param>
[IntegrationEvent(false, false)]
local procedure OnBeforeConsolidGLAccFindSet(var ConsolidGLAcc: Record "G/L Account")
begin
end;
/// <summary>
/// Integration event raised before posting general journal line in temporary mode during consolidation.
/// Enables custom modification of journal line before temporary posting processing.
/// </summary>
/// <param name="GenJnlLine">General Journal Line being prepared for temporary posting</param>
[IntegrationEvent(false, false)]
local procedure OnBeforeGenJnlPostLineTmp(var GenJnlLine: Record "Gen. Journal Line")
begin
end;
/// <summary>
/// Integration event raised before deleting temporary dimension set entries during consolidation.
/// Enables custom handling of dimension cleanup and journal line dimension processing.
/// </summary>
/// <param name="GenJnlLine">General Journal Line being processed for dimension cleanup</param>
/// <param name="GLEntry">G/L Entry associated with dimension set entry deletion</param>
[IntegrationEvent(false, false)]
local procedure OnBeforeTempDimSetEntryDelete(var GenJnlLine: Record "Gen. Journal Line"; var GLEntry: Record "G/L Entry")
begin
end;
/// <summary>
/// Integration event raised before inserting temporary general journal line during consolidation.
/// Enables custom modification of journal line before insertion into temporary processing table.
/// </summary>
/// <param name="TempGenJnlLine">Temporary General Journal Line record before insertion</param>
[IntegrationEvent(false, false)]
local procedure OnBeforeTempGenJnlLineInsert(var TempGenJnlLine: Record "Gen. Journal Line")
begin
end;
/// <summary>
/// Integration event raised after checking posting date validation during consolidation.
/// Enables custom posting date validation logic and error handling.
/// </summary>
/// <param name="GlEntry">G/L Entry with posting date being validated</param>
/// <param name="IsError">Set to true to indicate posting date validation error</param>
/// <param name="ErrorMsg">Custom error message for posting date validation failure</param>
[IntegrationEvent(false, false)]
local procedure OnAfterCheckPostingDate(var GlEntry: Record "G/L Entry"; var IsError: Boolean; var ErrorMsg: Text)
begin
end;
/// <summary>
/// Integration event raised before updating temporary G/L entry during consolidation procedure.
/// Enables custom modification of G/L entry data and dimension buffer handling.
/// </summary>
/// <param name="TempGLEntry">Temporary G/L Entry record being updated</param>
/// <param name="GLEntry">Source G/L Entry record for data copying</param>
/// <param name="IsHandled">Set to true to bypass standard G/L entry update processing</param>
/// <param name="TempDimensionBufferIn">Dimension Buffer record for dimension processing</param>
[IntegrationEvent(false, false)]
local procedure OnBeforeUpdateTempGLEntryProcedure(var TempGLEntry: Record "G/L Entry"; GLEntry: Record "G/L Entry"; var IsHandled: Boolean; TempDimensionBufferIn: Record "Dimension Buffer")
begin
end;
/// <summary>
/// Integration event raised after calculating whether to clear previous consolidation.
/// Enables custom logic for determining consolidation clearing behavior.
/// </summary>
/// <param name="ShouldClearPreviousConsolidation">Set to true to clear previous consolidation entries</param>
[IntegrationEvent(true, false)]
local procedure OnRunOnAfterCalcShouldClearPreviousConsolidation(var ShouldClearPreviousConsolidation: Boolean)
begin
end;
/// <summary>
/// Integration event raised before starting temporary G/L entry processing loop during consolidation.
/// Enables custom initialization logic before G/L entry iteration begins.
/// </summary>
/// <param name="TempGLEntry">Temporary G/L Entry record for loop processing</param>
/// <param name="TempSubsidGLAcc">Temporary subsidiary G/L Account record context</param>
[IntegrationEvent(false, false)]
local procedure OnRunOnBeforeTempGLEntryLoop(var TempGLEntry: Record "G/L Entry"; TempSubsidGLAcc: Record "G/L Account")
begin
end;
/// <summary>
/// Integration event raised before opening progress window during consolidation processing.
/// Enables custom window handling and progress tracking modifications.
/// </summary>
/// <param name="WindowDialog">Progress window dialog for consolidation status display</param>
/// <param name="IsHandled">Set to true to bypass standard window opening</param>
[IntegrationEvent(false, false)]
local procedure OnRunOnBeforeWindowOpen(var WindowDialog: Dialog; var IsHandled: Boolean)
begin
end;
/// <summary>
/// Integration event raised before inserting temporary dimension buffer during consolidation.
/// Enables custom dimension processing and modification before insertion.
/// </summary>
/// <param name="TempDimensionBuffer">Temporary Dimension Buffer record for consolidation</param>
/// <param name="TempSubsidDimensionBuffer">Temporary subsidiary Dimension Buffer record</param>
[IntegrationEvent(false, false)]
local procedure OnRunOnBeforeInsertTempDimBuf(var TempDimensionBuffer: Record "Dimension Buffer"; var TempSubsidDimensionBuffer: Record "Dimension Buffer")
begin
end;
/// <summary>
/// Integration event raised before retrieving consolidated G/L account during journal line creation.
/// Enables custom account mapping and G/L account selection logic.
/// </summary>
/// <param name="GenJournalLine">General Journal Line being created for consolidation</param>
/// <param name="GLEntry">Source G/L Entry for journal line creation</param>
/// <param name="BusinessUnit">Business Unit being consolidated</param>
/// <param name="TempSubsidGLAccount">Temporary subsidiary G/L Account record</param>
[IntegrationEvent(false, false)]
local procedure OnCreateAndPostGenJnlLineOnBeforeConsolidGLAccGet(var GenJournalLine: Record "Gen. Journal Line"; var GLEntry: Record "G/L Entry"; var BusinessUnit: Record "Business Unit"; var TempSubsidGLAccount: Record "G/L Account")
begin
end;
/// <summary>
/// Integration event raised before starting subsidiary G/L entry processing loop.
/// Enables custom initialization for business unit and G/L account processing.
/// </summary>
/// <param name="BusinessUnit">Business Unit being processed for consolidation</param>
/// <param name="TempSubsidGLAccount">Temporary subsidiary G/L Account for processing context</param>
[IntegrationEvent(false, false)]
local procedure OnRunOnBeforeLoopTempSubsidGLEntry(var BusinessUnit: Record "Business Unit"; var TempSubsidGLAccount: Record "G/L Account")
begin
end;
/// <summary>
/// Integration event raised at the start of subsidiary G/L entry processing loop iteration.
/// Enables custom processing for each G/L entry during consolidation.
/// </summary>
/// <param name="GenJournalLine">General Journal Line being processed for current entry</param>
/// <param name="BusinessUnit">Business Unit context for entry processing</param>
/// <param name="TempSubsidGLEntry">Temporary subsidiary G/L Entry being processed</param>
[IntegrationEvent(false, false)]
local procedure OnRunOnTempSubsidGLEntryLoopStart(var GenJournalLine: Record "Gen. Journal Line"; var BusinessUnit: Record "Business Unit"; var TempSubsidGLEntry: Record "G/L Entry")
begin
end;
/// <summary>
/// Integration event raised before setting residual account during consolidation.
/// Enables custom residual account logic and balancing entry handling.
/// </summary>
/// <param name="BusinessUnit">Business Unit being consolidated</param>
/// <param name="GenJournalLine">General Journal Line for residual account processing</param>
/// <param name="IsHandled">Set to true to bypass standard residual account setting</param>
[IntegrationEvent(false, false)]
local procedure OnRunOnBeforeSetResidualAccount(var BusinessUnit: Record "Business Unit"; var GenJournalLine: Record "Gen. Journal Line"; var IsHandled: Boolean)
begin
end;
/// <summary>
/// Integration event raised before exporting consolidation data to XML format.
/// Enables custom export processing and data transformation before XML generation.
/// </summary>
/// <param name="FileName">Name of XML file for consolidation data export</param>
/// <param name="TempSubsidGLAccount">Temporary subsidiary G/L Account records for export</param>
/// <param name="TempSubsidGLEntry">Temporary subsidiary G/L Entry records for export</param>
/// <param name="TempSubsidDimensionBuffer">Temporary subsidiary Dimension Buffer records</param>
/// <param name="TempSubsidCurrencyExchangeRate">Temporary subsidiary Currency Exchange Rate records</param>
/// <param name="IsHandled">Set to true to bypass standard XML export processing</param>
[IntegrationEvent(false, false)]
local procedure OnBeforeExportToXML(FileName: Text; var TempSubsidGLAccount: Record "G/L Account"; var TempSubsidGLEntry: Record "G/L Entry"; var TempSubsidDimensionBuffer: Record "Dimension Buffer"; var TempSubsidCurrencyExchangeRate: Record "Currency Exchange Rate"; var IsHandled: Boolean)
begin
end;
/// <summary>
/// Integration event raised before reporting error during amount array validation.
/// Enables custom error handling and validation logic for deleted consolidation amounts.
/// </summary>
/// <param name="DeletedAmountsArray">Array of deleted consolidation amounts being validated</param>
/// <param name="DeletedDatesArray">Array of dates for deleted consolidation entries</param>
/// <param name="DeletedIndex">Current index in deleted amounts array</param>
/// <param name="IsHandled">Set to true to bypass standard error reporting</param>
[IntegrationEvent(false, false)]
local procedure OnCheckAmountArrayOnBeforeReportError(var DeletedAmountsArray: array[500] of Decimal; var DeletedDatesArray: array[500] of Date; DeletedIndex: Integer; var IsHandled: Boolean)
begin
end;
/// <summary>
/// Integration event raised before importing consolidation data from XML format.
/// Enables custom import processing and data transformation from XML files.
/// </summary>
/// <param name="FileName">Name of XML file containing consolidation data to import</param>
/// <param name="TempSubsidGLAccount">Temporary subsidiary G/L Account records for import</param>
/// <param name="TempSubsidGLEntry">Temporary subsidiary G/L Entry records for import</param>
/// <param name="TempSubsidDimensionBuffer">Temporary subsidiary Dimension Buffer records</param>
/// <param name="TempSubsidCurrencyExchangeRate">Temporary subsidiary Currency Exchange Rate records</param>
/// <param name="IsHandled">Set to true to bypass standard XML import processing</param>
[IntegrationEvent(true, false)]
local procedure OnBeforeImportFromXML(FileName: Text; var TempSubsidGLAccount: Record "G/L Account"; var TempSubsidGLEntry: Record "G/L Entry"; var TempSubsidDimensionBuffer: Record "Dimension Buffer"; var TempSubsidCurrencyExchangeRate: Record "Currency Exchange Rate"; var IsHandled: Boolean)
begin
end;
/// <summary>
/// Integration event raised after setting filters on consolidated G/L entries during previous consolidation clearing.
/// Enables custom filtering logic for consolidated entry identification and processing.
/// </summary>
/// <param name="ConsolidGLEntry">Consolidated G/L Entry record with applied filters</param>
[IntegrationEvent(false, false)]
local procedure OnClearPreviousConsolidationOnAfterConsolidGLEntrySetFilters(var ConsolidGLEntry: Record "G/L Entry")
begin
end;
/// <summary>
/// Integration event raised after setting global variables during consolidation processing.
/// Enables custom modification of consolidation parameters and global settings.
/// </summary>
/// <param name="ProductVersion">Product version for consolidation compatibility</param>
/// <param name="FormatVersion">File format version for data compatibility</param>
/// <param name="CompanyName">Company name for consolidation context</param>
/// <param name="CurrencyLCY">Local Currency Code for consolidation</param>
/// <param name="CurrencyACY">Additional Currency Code for reporting</param>
/// <param name="CurrencyPCY">Previous Currency Code for comparison</param>
/// <param name="CheckSum">Checksum for data validation</param>
/// <param name="StartingDate">Starting date for consolidation period</param>
/// <param name="EndingDate">Ending date for consolidation period</param>
[IntegrationEvent(false, false)]
local procedure OnAfterSetGlobals(var ProductVersion: Code[10]; var FormatVersion: Code[10]; var CompanyName: Text[30]; var CurrencyLCY: Code[10]; var CurrencyACY: Code[10]; var CurrencyPCY: Code[10]; var CheckSum: Decimal; var StartingDate: Date; var EndingDate: Date)
begin
end;
/// <summary>
/// Integration event raised before selecting all imported dimensions during XML import processing.
/// Enables custom dimension selection logic and processing during consolidation data import.
/// </summary>
/// <param name="ProductVersion">Product version from imported consolidation data</param>
/// <param name="FormatVersion">Format version from imported consolidation data</param>
/// <param name="CompanyName">Company name from imported consolidation data</param>
/// <param name="CurrencyLCY">Local Currency Code from imported data</param>
/// <param name="CurrencyACY">Additional Currency Code from imported data</param>
/// <param name="CurrencyPCY">Previous Currency Code from imported data</param>
/// <param name="CheckSum">Checksum from imported data for validation</param>
/// <param name="StartingDate">Starting date from imported consolidation period</param>
/// <param name="EndingDate">Ending date from imported consolidation period</param>
[IntegrationEvent(false, false)]
local procedure OnImportFromXMLOnBeforeSelectAllImportedDimensions(var ProductVersion: Code[10]; var FormatVersion: Code[10]; var CompanyName: Text[30]; var CurrencyLCY: Code[10]; var CurrencyACY: Code[10]; var CurrencyPCY: Code[10]; var CheckSum: Decimal; var StartingDate: Date; var EndingDate: Date)
begin
end;
/// <summary>
/// Integration event raised before posting balance adjustment entries during prior period balance updates.
/// Enables custom G/L account processing and balance adjustment logic during consolidation.
/// </summary>
/// <param name="GLAccount">G/L Account record being processed for balance adjustments</param>
[IntegrationEvent(false, false)]
local procedure OnUpdatePriorPeriodBalancesOnBeforePostBalanceAdjustment(var GLAccount: Record "G/L Account")
begin
end;
/// <summary>
/// Integration event raised before testing for G/L account conflicts during consolidation validation.
/// Enables custom validation logic for subsidiary G/L account compatibility and conflict resolution.
/// </summary>
/// <param name="TempSubsidGLAcc">Temporary subsidiary G/L Account records being tested for conflicts</param>
[IntegrationEvent(true, false)]
local procedure OnTestGLAccountsOnBeforeTestForConflicts(var TempSubsidGLAcc: Record "G/L Account" temporary)
begin
end;
/// <summary>
/// Integration event raised before modifying consolidated G/L entry during previous consolidation clearing.
/// Enables custom modification of consolidated G/L entry data before clearing amounts.
/// </summary>
/// <param name="ConsolidGLEntry">Consolidated G/L Entry record being modified</param>
[IntegrationEvent(false, false)]
local procedure OnClearPreviousConsolidationOnBeforeModifyConsolidGLEntry(var ConsolidGLEntry: Record "G/L Entry")
begin
end;
}