Codeunit 413 AnalysisViewEntryToGLEntries
- App
- Base Application
- Namespace
- Microsoft.Finance.Analysis
- Versions
- 17-28
Versions171819202122232425262728
Source29
Source in 29
src/Layers/W1/BaseApp/Finance/Analysis/AnalysisViewEntryToGLEntries.Codeunit.al311 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.Analysis;
using Microsoft.CashFlow.Forecast;
using Microsoft.Finance.Dimension;
using Microsoft.Finance.GeneralLedger.Ledger;
using Microsoft.Finance.GeneralLedger.Setup;
using Microsoft.Foundation.Period;
/// <summary>
/// Provides functionality to retrieve and process G/L entries and cash flow entries from analysis view entries.
/// Handles drill-down navigation from analysis view entries to underlying ledger entries with dimension filtering.
/// </summary>
/// <remarks>
/// Key functionality includes G/L entry retrieval, cash flow entry processing, and dimension validation.
/// Supports both date-compressed and detailed analysis view entry drill-down scenarios.
/// </remarks>
codeunit 413 AnalysisViewEntryToGLEntries
{
trigger OnRun()
begin
end;
var
AnalysisView: Record "Analysis View";
GLSetup: Record "General Ledger Setup";
DimSetEntry: Record "Dimension Set Entry";
/// <summary>
/// Retrieves G/L entries that correspond to an analysis view entry for drill-down functionality.
/// Applies appropriate filters based on analysis view configuration and dimension settings.
/// </summary>
/// <param name="AnalysisViewEntry">Analysis view entry to drill down from</param>
/// <param name="TempGLEntry">Temporary G/L Entry record to populate with matching entries</param>
procedure GetGLEntries(var AnalysisViewEntry: Record "Analysis View Entry"; var TempGLEntry: Record "G/L Entry")
var
GLEntry: Record "G/L Entry";
AnalysisViewFilter: Record "Analysis View Filter";
UpdateAnalysisView: Codeunit "Update Analysis View";
StartDate: Date;
EndDate: Date;
GlobalDimValue: Code[20];
IsHandled: Boolean;
begin
AnalysisView.Get(AnalysisViewEntry."Analysis View Code");
if AnalysisView."Date Compression" = AnalysisView."Date Compression"::None then begin
if GLEntry.Get(AnalysisViewEntry."Entry No.") then begin
TempGLEntry := GLEntry;
TempGLEntry.Insert();
end;
OnAfterGetGLEntryIfDateCompressionNone(AnalysisViewEntry, TempGLEntry);
exit;
end;
GLSetup.Get();
StartDate := AnalysisViewEntry."Posting Date";
EndDate := StartDate;
if StartDate < AnalysisView."Starting Date" then
StartDate := 0D
else
if (AnalysisViewEntry."Posting Date" = NormalDate(AnalysisViewEntry."Posting Date")) and
not (AnalysisView."Date Compression" in [AnalysisView."Date Compression"::None, AnalysisView."Date Compression"::Day])
then
EndDate := CalculateEndDate(AnalysisView."Date Compression", AnalysisViewEntry);
IsHandled := false;
OnGetGLEntriesOnBeforeCopyGLEntries(AnalysisViewEntry, IsHandled);
if not IsHandled then begin
GLEntry.SetCurrentKey("G/L Account No.", GLEntry."Posting Date");
GLEntry.SetRange("G/L Account No.", AnalysisViewEntry."Account No.");
GLEntry.SetRange("Posting Date", StartDate, EndDate);
GLEntry.SetRange("Entry No.", 0, AnalysisView."Last Entry No.");
if GetGlobalDimValue(GLSetup."Global Dimension 1 Code", AnalysisViewEntry, GlobalDimValue) then
GLEntry.SetRange("Global Dimension 1 Code", GlobalDimValue)
else
if AnalysisViewFilter.Get(AnalysisViewEntry."Analysis View Code", GLSetup."Global Dimension 1 Code")
then
GLEntry.SetFilter("Global Dimension 1 Code", AnalysisViewFilter."Dimension Value Filter");
if GetGlobalDimValue(GLSetup."Global Dimension 2 Code", AnalysisViewEntry, GlobalDimValue) then
GLEntry.SetRange("Global Dimension 2 Code", GlobalDimValue)
else
if AnalysisViewFilter.Get(AnalysisViewEntry."Analysis View Code", GLSetup."Global Dimension 2 Code")
then
GLEntry.SetFilter("Global Dimension 2 Code", AnalysisViewFilter."Dimension Value Filter");
OnGetGLEntriesOnAfterGLEntrySetFilters(GLEntry, AnalysisView, AnalysisViewEntry);
if GLEntry.Find('-') then
repeat
if DimEntryOK(GLEntry."Dimension Set ID", AnalysisView."Dimension 1 Code", AnalysisViewEntry."Dimension 1 Value Code") and
DimEntryOK(GLEntry."Dimension Set ID", AnalysisView."Dimension 2 Code", AnalysisViewEntry."Dimension 2 Value Code") and
DimEntryOK(GLEntry."Dimension Set ID", AnalysisView."Dimension 3 Code", AnalysisViewEntry."Dimension 3 Value Code") and
DimEntryOK(GLEntry."Dimension Set ID", AnalysisView."Dimension 4 Code", AnalysisViewEntry."Dimension 4 Value Code") and
UpdateAnalysisView.DimSetIDInFilter(GLEntry."Dimension Set ID", AnalysisView)
then begin
TempGLEntry := GLEntry;
if TempGLEntry.Insert() then;
end;
until GLEntry.Next() = 0;
end;
OnAfterGetGLEntries(AnalysisViewEntry, TempGLEntry);
end;
/// <summary>
/// Retrieves cash flow forecast entries that correspond to an analysis view entry for drill-down functionality.
/// Applies appropriate filters based on analysis view configuration and cash flow dimension settings.
/// </summary>
/// <param name="AnalysisViewEntry">Analysis view entry to drill down from</param>
/// <param name="CFForecastEntry">Cash Flow Forecast Entry record to populate with matching entries</param>
procedure GetCFLedgEntries(var AnalysisViewEntry: Record "Analysis View Entry"; var CFForecastEntry: Record "Cash Flow Forecast Entry")
var
CFForecastEntry2: Record "Cash Flow Forecast Entry";
AnalysisViewFilter: Record "Analysis View Filter";
UpdateAnalysisView: Codeunit "Update Analysis View";
StartDate: Date;
EndDate: Date;
GlobalDimValue: Code[20];
begin
AnalysisView.Get(AnalysisViewEntry."Analysis View Code");
if AnalysisView."Date Compression" = AnalysisView."Date Compression"::None then begin
if CFForecastEntry2.Get(AnalysisViewEntry."Entry No.") then begin
CFForecastEntry := CFForecastEntry2;
CFForecastEntry.Insert();
end;
exit;
end;
GLSetup.Get();
StartDate := AnalysisViewEntry."Posting Date";
EndDate := StartDate;
if StartDate < AnalysisView."Starting Date" then
StartDate := 0D
else
if (AnalysisViewEntry."Posting Date" = NormalDate(AnalysisViewEntry."Posting Date")) and
not (AnalysisView."Date Compression" in [AnalysisView."Date Compression"::None, AnalysisView."Date Compression"::Day])
then
EndDate := CalculateEndDate(AnalysisView."Date Compression", AnalysisViewEntry);
CFForecastEntry2.SetCurrentKey("Cash Flow Forecast No.", CFForecastEntry2."Cash Flow Account No.", CFForecastEntry2."Source Type", CFForecastEntry2."Cash Flow Date");
CFForecastEntry2.SetRange("Cash Flow Forecast No.", AnalysisViewEntry."Cash Flow Forecast No.");
CFForecastEntry2.SetRange("Cash Flow Account No.", AnalysisViewEntry."Account No.");
CFForecastEntry2.SetRange("Cash Flow Date", StartDate, EndDate);
if GetGlobalDimValue(GLSetup."Global Dimension 1 Code", AnalysisViewEntry, GlobalDimValue) then
CFForecastEntry2.SetRange("Global Dimension 1 Code", GlobalDimValue)
else
if AnalysisViewFilter.Get(AnalysisViewEntry."Analysis View Code", GLSetup."Global Dimension 1 Code")
then
CFForecastEntry2.SetFilter("Global Dimension 1 Code", AnalysisViewFilter."Dimension Value Filter");
if GetGlobalDimValue(GLSetup."Global Dimension 2 Code", AnalysisViewEntry, GlobalDimValue) then
CFForecastEntry2.SetRange("Global Dimension 2 Code", GlobalDimValue)
else
if AnalysisViewFilter.Get(AnalysisViewEntry."Analysis View Code", GLSetup."Global Dimension 2 Code")
then
CFForecastEntry2.SetFilter("Global Dimension 2 Code", AnalysisViewFilter."Dimension Value Filter");
if CFForecastEntry2.Find('-') then
repeat
if DimEntryOK(CFForecastEntry2."Dimension Set ID", AnalysisView."Dimension 1 Code", AnalysisViewEntry."Dimension 1 Value Code") and
DimEntryOK(CFForecastEntry2."Dimension Set ID", AnalysisView."Dimension 2 Code", AnalysisViewEntry."Dimension 2 Value Code") and
DimEntryOK(CFForecastEntry2."Dimension Set ID", AnalysisView."Dimension 3 Code", AnalysisViewEntry."Dimension 3 Value Code") and
DimEntryOK(CFForecastEntry2."Dimension Set ID", AnalysisView."Dimension 4 Code", AnalysisViewEntry."Dimension 4 Value Code") and
UpdateAnalysisView.DimSetIDInFilter(CFForecastEntry2."Dimension Set ID", AnalysisView)
then begin
CFForecastEntry := CFForecastEntry2;
CFForecastEntry.Insert();
end;
until CFForecastEntry2.Next() = 0;
end;
/// <summary>
/// Validates whether a dimension set entry matches expected dimension value for analysis view filtering.
/// Checks if the dimension value in a dimension set matches the required value for analysis view drill-down.
/// </summary>
/// <param name="DimSetID">Dimension set ID to check</param>
/// <param name="Dim">Dimension code to validate</param>
/// <param name="DimValue">Expected dimension value</param>
/// <returns>True if dimension entry matches expected value or dimension is not used, false otherwise</returns>
procedure DimEntryOK(DimSetID: Integer; Dim: Code[20]; DimValue: Code[20]): Boolean
begin
if Dim = '' then
exit(true);
if DimSetEntry.Get(DimSetID, Dim) then
exit(DimSetEntry."Dimension Value Code" = DimValue);
exit(DimValue = '');
end;
local procedure CalculateEndDate(DateCompression: Integer; AnalysisViewEntry: Record "Analysis View Entry"): Date
var
AnalysisView2: Record "Analysis View";
AccountingPeriod: Record "Accounting Period";
begin
case DateCompression of
AnalysisView2."Date Compression"::Week:
exit(CalcDate('<+6D>', AnalysisViewEntry."Posting Date"));
AnalysisView2."Date Compression"::Month:
exit(CalcDate('<+1M-1D>', AnalysisViewEntry."Posting Date"));
AnalysisView2."Date Compression"::Quarter:
exit(CalcDate('<+3M-1D>', AnalysisViewEntry."Posting Date"));
AnalysisView2."Date Compression"::Year:
exit(CalcDate('<+1Y-1D>', AnalysisViewEntry."Posting Date"));
AnalysisView2."Date Compression"::Period:
begin
AccountingPeriod."Starting Date" := AnalysisViewEntry."Posting Date";
if AccountingPeriod.Next() <> 0 then
exit(CalcDate('<-1D>', AccountingPeriod."Starting Date"));
exit(DMY2Date(31, 12, 9999));
end;
end;
end;
/// <summary>
/// Retrieves global dimension value from analysis view entry for specified dimension code.
/// Maps analysis view dimension codes to corresponding dimension values for filtering purposes.
/// </summary>
/// <param name="GlobalDim">Global dimension code to retrieve value for</param>
/// <param name="AnalysisViewEntry">Analysis view entry containing dimension values</param>
/// <param name="GlobalDimValue">Retrieved dimension value for the specified global dimension</param>
/// <returns>True if the dimension code is a global dimension in the analysis view, false otherwise</returns>
procedure GetGlobalDimValue(GlobalDim: Code[20]; var AnalysisViewEntry: Record "Analysis View Entry"; var GlobalDimValue: Code[20]): Boolean
var
IsGlobalDim: Boolean;
begin
case GlobalDim of
AnalysisView."Dimension 1 Code":
begin
IsGlobalDim := true;
GlobalDimValue := AnalysisViewEntry."Dimension 1 Value Code";
end;
AnalysisView."Dimension 2 Code":
begin
IsGlobalDim := true;
GlobalDimValue := AnalysisViewEntry."Dimension 2 Value Code";
end;
AnalysisView."Dimension 3 Code":
begin
IsGlobalDim := true;
GlobalDimValue := AnalysisViewEntry."Dimension 3 Value Code";
end;
AnalysisView."Dimension 4 Code":
begin
IsGlobalDim := true;
GlobalDimValue := AnalysisViewEntry."Dimension 4 Value Code";
end;
end;
exit(IsGlobalDim);
end;
/// <summary>
/// Integration event raised after setting filters on G/L Entry record during drill-down process.
/// Enables custom filtering logic for G/L entries retrieved from analysis view entries.
/// </summary>
/// <param name="GLEntry">G/L Entry record with applied filters</param>
/// <param name="AnalysisView">Analysis view configuration being processed</param>
/// <param name="AnalysisViewEntry">Source analysis view entry for drill-down</param>
[IntegrationEvent(false, false)]
local procedure OnGetGLEntriesOnAfterGLEntrySetFilters(var GLEntry: Record "G/L Entry"; var AnalysisView: Record "Analysis View"; var AnalysisViewEntry: Record "Analysis View Entry")
begin
end;
/// <summary>
/// Integration event raised after retrieving G/L entry when date compression is disabled.
/// Allows custom processing of G/L entries in non-compressed analysis view scenarios.
/// </summary>
/// <param name="AnalysisViewEntry">Source analysis view entry for drill-down</param>
/// <param name="TempGLEntry">Temporary G/L Entry record containing retrieved data</param>
[IntegrationEvent(false, false)]
local procedure OnAfterGetGLEntryIfDateCompressionNone(var AnalysisViewEntry: Record "Analysis View Entry"; var TempGLEntry: Record "G/L Entry" temporary)
begin
end;
/// <summary>
/// Integration event raised after completing G/L entry retrieval process.
/// Enables final processing or validation of retrieved G/L entries from analysis view drill-down.
/// </summary>
/// <param name="AnalysisViewEntry">Source analysis view entry for drill-down</param>
/// <param name="TempGLEntry">Temporary G/L Entry record containing all retrieved entries</param>
[IntegrationEvent(false, false)]
local procedure OnAfterGetGLEntries(var AnalysisViewEntry: Record "Analysis View Entry"; var TempGLEntry: Record "G/L Entry" temporary)
begin
end;
/// <summary>
/// Integration event raised before copying G/L entries during analysis view drill-down process.
/// Allows custom handling or skipping of standard G/L entry retrieval logic.
/// </summary>
/// <param name="AnalysisViewEntry">Source analysis view entry for drill-down</param>
/// <param name="IsHandled">Set to true to skip standard G/L entry copying logic</param>
[IntegrationEvent(false, false)]
local procedure OnGetGLEntriesOnBeforeCopyGLEntries(var AnalysisViewEntry: Record "Analysis View Entry"; var IsHandled: Boolean)
begin
end;
}