Skip to content

[W1][Table][348][Dimension][Function][CheckIfDimUsed][Ishandled]CheckItemAnalysisViewDim extensibility OnBefore OnAfter #29630

@pandea04

Description

@pandea04

Why do you need this change?

Why do you need this change?

Further extensibility for CheckItemAnalysisViewDim as per enum request
#29601

Currently, the Item Analysis View framework in Business Central supports only three Item Analysis dimensions (ItemAnalysis1ΓÇô3). However, several Operating Companies rely on extended analytical classification for:
ΓÇó Financial analysis
ΓÇó Operational consumption reporting
ΓÇó Purchase and inventory performance extraction
To meet these reporting obligations, Client requires two additional Item Analysis dimensions ΓÇö ItemAnalysis4 and ItemAnalysis5. These dimensions are already part of the business model and are actively used across Operating Companies for material grouping and management-level analytics.

Alternatives Evaluation
We have evaluated the following existing events:

OnBeforeCheckIfDimUsed: This event is at CheckIfDimUsed procedure but does give flexibility to add additional Dimensions to check CheckItemAnalysisViewDim which is limited to 3 dimensions which is needed to further extend to 5 Dimensions.
Code is starting from Line 290 to 301.

another block of code starting from 397 to 417 Line.
These blocks of Code needs to be extracted to further procedure and aligned with OnBefore and OnAfter Events

IsHandled Justification:
While we're using a GetVendor Boolean parameter rather than IsHandled, the pattern serves a similar purpose and requires justification. The GetVendor parameter is necessary because:

Error Prevention: IsHandled false will keep process as normal execution, only will give flexibility to enhance financial reporting

Performance Optimization:Better handling over code execution and additional dimensions intergration.

Business Logic Requirements:The requested enhancement is required to support critical financial reporting, Item Analysis View enrichment, and data extraction processes used by multiple Heineken Operating Companies.

A standard integration event (without the ability to control execution) would not work because:

We cannot fully skip execution and add dimension to in already check part even after it is extended to enum.

Error handling after the fact is insufficient for user experience requirements

We need to update variable with additional dimensions to work with.

Microsoft Idea Proposal Document-348 Sent to Avnish (1).docx

Performance Considerations

Performance Impact: The addition of the event call adds minimal overhead (< 1ms) as it's a simple Boolean evaluation and event invocation. as we are simply adding a boolean check and then assigning value to code for runtime evaluation which will help with financial reporting to be correct
Timing-Critical Scenarios: This procedure is not in a posting or batch processing critical path. It's primarily used by user to run and is operated out of business hours

Expected Impact: Positive to get financial reporting correct and structured execution handle events for change

Data Sensitivity Review
The data exposed through this event includes:

Shortcut Dimension is being evaluated: which are required for financial reporting. which is Customer Content data

Safeguards: This event follows the safe structured model for event extensibility by keeping flow structured. No additional sensitive data exposure occurs beyond what's already available through standard table access.

Multi-Extension Interaction
The risk of conflicts is relatively low:

IsHandled false will allow standard behaviour to execute

IsHandled true will help to modify execution expected for reporting.

OnBefore will allow flexibility to correct financial reporting
OnAfter will help with adding additional check

Describe the request

Current Code Microsoft

Image Image

Suugested update:

Extract it to new Procedure

From :

        CheckAllDim := DimTypeChecked in [DimTypeChecked::" "];
        CheckGlobalDim := DimTypeChecked in [DimTypeChecked::Global1, DimTypeChecked::Global2];
        CheckShortcutDim := DimTypeChecked in [DimTypeChecked::Shortcut3, DimTypeChecked::Shortcut4, DimTypeChecked::Shortcut5,
                                               DimTypeChecked::Shortcut6, DimTypeChecked::Shortcut7, DimTypeChecked::Shortcut8];
        CheckBudgetDim := DimTypeChecked in [DimTypeChecked::Budget1, DimTypeChecked::Budget2, DimTypeChecked::Budget3,
                                             DimTypeChecked::Budget4];
        CheckAnalysisViewDim := DimTypeChecked in [DimTypeChecked::Analysis1, DimTypeChecked::Analysis2, DimTypeChecked::Analysis3,
                                                   DimTypeChecked::Analysis4];
        CheckItemBudgetDim :=
          DimTypeChecked in [DimTypeChecked::ItemBudget1, DimTypeChecked::ItemBudget2, DimTypeChecked::ItemBudget3];
        CheckItemAnalysisViewDim :=
          DimTypeChecked in [DimTypeChecked::ItemAnalysis1, DimTypeChecked::ItemAnalysis2, DimTypeChecked::ItemAnalysis3];

To

CheckAllDimesions(DimTypeChecked, CheckAllDim, CheckGlobalDim, CheckShortcutDim, CheckBudgetDim, CheckAnalysisViewDim, CheckItemBudgetDim, CheckItemAnalysisViewDim, UsedAsCustomDim, CustomDimErr);
    [IntegrationEvent(false, false)]
    local procedure OnBeforeCheckAllDimesions(var DimTypeChecked: Enum DimTypeChecked; var CheckAllDim: Boolean; var CheckGlobalDim: Boolean; var CheckShortcutDim: Boolean; var CheckBudgetDim: Boolean; var CheckAnalysisViewDim: Boolean; var CheckItemBudgetDim: Boolean; var CheckItemAnalysisViewDim: Boolean; var UsedAsCustomDim: Boolean; var CustomDimErr: Text;var IsHandled: Boolean)
    begin
    end;

    [IntegrationEvent(false, false)]
    local procedure OnAfterCheckAllDimesions(var DimTypeChecked: Enum DimTypeChecked; var CheckAllDim: Boolean; var CheckGlobalDim: Boolean; var CheckShortcutDim: Boolean; var CheckBudgetDim: Boolean; var CheckAnalysisViewDim: Boolean; var CheckItemBudgetDim: Boolean; var CheckItemAnalysisViewDim: Boolean; var UsedAsCustomDim: Boolean; var CustomDimErr: Text)
    begin
    end;
 local procedure CheckAllDimesions(var DimTypeChecked: Enum DimTypeChecked; var CheckAllDim: Boolean; var CheckGlobalDim: Boolean; var CheckShortcutDim: Boolean; var CheckBudgetDim: Boolean; var CheckAnalysisViewDim: Boolean; var CheckItemBudgetDim: Boolean; var CheckItemAnalysisViewDim: Boolean;var UsedAsCustomDim: Boolean; var CustomDimErr: Text)
    var
        IsHandled: Boolean;
    begin
        OnBeforeCheckAllDimesions(DimTypeChecked, CheckAllDim, CheckGlobalDim, CheckShortcutDim, CheckBudgetDim, CheckAnalysisViewDim, CheckItemBudgetDim, CheckItemAnalysisViewDim, UsedAsCustomDim,CustomDimErr,IsHandled);
        if IsHandled then
            exit;
        
        CheckAllDim := DimTypeChecked in [DimTypeChecked::" "];
        CheckGlobalDim := DimTypeChecked in [DimTypeChecked::Global1, DimTypeChecked::Global2];
        CheckShortcutDim := DimTypeChecked in [DimTypeChecked::Shortcut3, DimTypeChecked::Shortcut4, DimTypeChecked::Shortcut5,
                                               DimTypeChecked::Shortcut6, DimTypeChecked::Shortcut7, DimTypeChecked::Shortcut8];
        CheckBudgetDim := DimTypeChecked in [DimTypeChecked::Budget1, DimTypeChecked::Budget2, DimTypeChecked::Budget3,
                                             DimTypeChecked::Budget4];
        CheckAnalysisViewDim := DimTypeChecked in [DimTypeChecked::Analysis1, DimTypeChecked::Analysis2, DimTypeChecked::Analysis3,
                                                   DimTypeChecked::Analysis4];
        CheckItemBudgetDim :=
          DimTypeChecked in [DimTypeChecked::ItemBudget1, DimTypeChecked::ItemBudget2, DimTypeChecked::ItemBudget3];
        CheckItemAnalysisViewDim :=
          DimTypeChecked in [DimTypeChecked::ItemAnalysis1, DimTypeChecked::ItemAnalysis2, DimTypeChecked::ItemAnalysis3];
        
        OnAfterCheckAllDimesions(DimTypeChecked, CheckAllDim, CheckGlobalDim, CheckShortcutDim, CheckBudgetDim, CheckAnalysisViewDim, CheckItemBudgetDim, CheckItemAnalysisViewDim, UsedAsCustomDim, CustomDimErr);
    end;

Part 2: Microsoft implementation:

Image

Extract it to new Procedure
Line 397 to 417

CheckIfDimUsedAsItemAnalysisViewDim(ItemAnalysisView,DimChecked, DimTypeChecked, AnalysisViewChecked, AnalysisAreaChecked, CheckAllDim, CheckItemAnalysisViewDim, UsedAsCustomDim, CustomDimErr);//NewProcedure

 

  local procedure CheckIfDimUsedAsItemAnalysisViewDim(ItemAnalysisView: Record "Item Analysis View";
     DimChecked: Code[20];
     DimTypeChecked: Enum "DimTypeChecked";
     AnalysisViewChecked: Code[10];
     AnalysisAreaChecked: Integer;
     CheckAllDim: Boolean;
     CheckItemAnalysisViewDim: Boolean; var UsedAsCustomDim: Boolean; var CustomDimErr: Text)
    var

        IsHandled: Boolean;
      begin
    
        // OnBefore: subscriber can modify before main logic
        OnBeforeCheckIfDimUsedAsItemAnalysisViewDim(ItemAnalysisView,
            DimChecked,
            DimTypeChecked,
            AnalysisViewChecked,
            AnalysisAreaChecked,
            CheckAllDim,
            CheckItemAnalysisViewDim,
            UsedAsItemAnalysisViewDim, UsedAsCustomDim, CustomDimErr,
            IsHandled);

        if IsHandled then 
            exit;
       

        // Main logic
        if CheckAllDim or CheckItemAnalysisViewDim then begin
            if AnalysisViewChecked <> '' then begin
                ItemAnalysisView.SetRange("Analysis Area", AnalysisAreaChecked);
                ItemAnalysisView.SetRange(Code, AnalysisViewChecked);
            end;

            if ItemAnalysisView.FindSet() then
                repeat
                    if (DimTypeChecked <> DimTypeChecked::ItemAnalysis1) and
                       (DimChecked = ItemAnalysisView."Dimension 1 Code")
                    then
                        UsedAsItemAnalysisViewDim := true;

                    if (DimTypeChecked <> DimTypeChecked::ItemAnalysis2) and
                       (DimChecked = ItemAnalysisView."Dimension 2 Code")
                    then
                        UsedAsItemAnalysisViewDim := true;

                    if (DimTypeChecked <> DimTypeChecked::ItemAnalysis3) and
                       (DimChecked = ItemAnalysisView."Dimension 3 Code")
                    then
                        UsedAsItemAnalysisViewDim := true;
                until ItemAnalysisView.Next() = 0;
        end;

        // OnAfter: pass LOCAL variable by reference
        OnAfterCheckIfDimUsedAsItemAnalysisViewDim(ItemAnalysisView,
            DimChecked,
            DimTypeChecked,
            AnalysisViewChecked,
            AnalysisAreaChecked,
            CheckAllDim,
            CheckItemAnalysisViewDim,
            UsedAsItemAnalysisViewDim, UsedAsCustomDim, CustomDimErr);


    end;

Integrationevent

    local procedure OnBeforeCheckIfDimUsedAsItemAnalysisViewDim(ItemAnalysisView: Record "Item Analysis View";var DimChecked: Code[20]; var DimTypeChecked: Enum DimTypeChecked; var AnalysisViewChecked: Code[10]; var AnalysisAreaChecked: Integer; var CheckAllDim: Boolean; var CheckItemAnalysisViewDim: Boolean; var UsedAsItemAnalysisViewDim: Boolean; var UsedAsCustomDim: Boolean; var CustomDimErr: Text; var IsHandled: Boolean)
    begin
    end;

    [IntegrationEvent(false, false)]
    local procedure OnAfterCheckIfDimUsedAsItemAnalysisViewDim(var ItemAnalysisView: Record "Item Analysis View";var DimChecked: Code[20]; var DimTypeChecked: Enum DimTypeChecked; var AnalysisViewChecked: Code[10]; var AnalysisAreaChecked: Integer; var CheckAllDim: Boolean; var CheckItemAnalysisViewDim: Boolean; var UsedAsItemAnalysisViewDim: Boolean; var UsedAsCustomDim: Boolean; var CustomDimErr: Text)
    begin
    end;

New CheckIfDimUsed() will be like

    procedure CheckIfDimUsed(DimChecked: Code[20]; DimTypeChecked: Enum DimTypeChecked; BudgetNameChecked: Code[10]; AnalysisViewChecked: Code[10]; AnalysisAreaChecked: Integer): Boolean
    var
        GLSetup: Record "General Ledger Setup";
        GLBudgetName: Record "G/L Budget Name";
        AnalysisView: Record "Analysis View";
        ItemBudgetName: Record "Item Budget Name";
        ItemAnalysisView: Record "Item Analysis View";
        CustomDimErr: Text;
        CheckAllDim: Boolean;
        CheckGlobalDim: Boolean;
        CheckShortcutDim: Boolean;
        CheckBudgetDim: Boolean;
        CheckAnalysisViewDim: Boolean;
        CheckItemBudgetDim: Boolean;
        CheckItemAnalysisViewDim: Boolean;
        UsedAsCustomDim: Boolean;
    begin
        if DimChecked = '' then
            exit;

        OnBeforeCheckIfDimUsed(DimChecked, DimTypeChecked, UsedAsCustomDim, CustomDimErr, AnalysisViewChecked, AnalysisAreaChecked);

        CheckAllDimesions(DimTypeChecked, CheckAllDim, CheckGlobalDim, CheckShortcutDim, CheckBudgetDim, CheckAnalysisViewDim, CheckItemBudgetDim, CheckItemAnalysisViewDim, UsedAsCustomDim, CustomDimErr);//New Procedure





        UsedAsGlobalDim := false;
        UsedAsShortcutDim := false;
        UsedAsBudgetDim := false;
        UsedAsAnalysisViewDim := false;
        UsedAsItemBudgetDim := false;
        UsedAsItemAnalysisViewDim := false;

        if CheckAllDim or CheckGlobalDim or CheckShortcutDim or CheckBudgetDim or CheckItemBudgetDim then begin
            GLSetup.Get();
            if (DimTypeChecked <> DimTypeChecked::Global1) and
               (DimChecked = GLSetup."Global Dimension 1 Code")
            then
                UsedAsGlobalDim := true;
            if (DimTypeChecked <> DimTypeChecked::Global2) and
               (DimChecked = GLSetup."Global Dimension 2 Code")
            then
                UsedAsGlobalDim := true;
        end;

        if CheckGlobalDim or CheckShortcutDim then begin
            if (DimTypeChecked <> DimTypeChecked::Shortcut3) and
               (DimChecked = GLSetup."Shortcut Dimension 3 Code")
            then
                UsedAsShortcutDim := true;
            if (DimTypeChecked <> DimTypeChecked::Shortcut4) and
               (DimChecked = GLSetup."Shortcut Dimension 4 Code")
            then
                UsedAsShortcutDim := true;
            if (DimTypeChecked <> DimTypeChecked::Shortcut5) and
               (DimChecked = GLSetup."Shortcut Dimension 5 Code")
            then
                UsedAsShortcutDim := true;
            if (DimTypeChecked <> DimTypeChecked::Shortcut6) and
               (DimChecked = GLSetup."Shortcut Dimension 6 Code")
            then
                UsedAsShortcutDim := true;
            if (DimTypeChecked <> DimTypeChecked::Shortcut7) and
               (DimChecked = GLSetup."Shortcut Dimension 7 Code")
            then
                UsedAsShortcutDim := true;
            if (DimTypeChecked <> DimTypeChecked::Shortcut8) and
               (DimChecked = GLSetup."Shortcut Dimension 8 Code")
            then
                UsedAsShortcutDim := true;
        end;

        if CheckAllDim or CheckGlobalDim or CheckBudgetDim then begin
            if BudgetNameChecked <> '' then
                GLBudgetName.SetRange(Name, BudgetNameChecked);
            if GLBudgetName.FindSet() then
                repeat
                    if (DimTypeChecked <> DimTypeChecked::Budget1) and
                       (DimChecked = GLBudgetName."Budget Dimension 1 Code")
                    then
                        UsedAsBudgetDim := true;
                    if (DimTypeChecked <> DimTypeChecked::Budget2) and
                       (DimChecked = GLBudgetName."Budget Dimension 2 Code")
                    then
                        UsedAsBudgetDim := true;
                    if (DimTypeChecked <> DimTypeChecked::Budget3) and
                       (DimChecked = GLBudgetName."Budget Dimension 3 Code")
                    then
                        UsedAsBudgetDim := true;
                    if (DimTypeChecked <> DimTypeChecked::Budget4) and
                       (DimChecked = GLBudgetName."Budget Dimension 4 Code")
                    then
                        UsedAsBudgetDim := true;
                until GLBudgetName.Next() = 0;
        end;

        if CheckAllDim or CheckGlobalDim or CheckItemBudgetDim then begin
            if BudgetNameChecked <> '' then begin
                ItemBudgetName.SetRange("Analysis Area", AnalysisAreaChecked);
                ItemBudgetName.SetRange(Name, BudgetNameChecked);
            end;
            if ItemBudgetName.FindSet() then
                repeat
                    if (DimTypeChecked <> DimTypeChecked::ItemBudget1) and
                       (DimChecked = ItemBudgetName."Budget Dimension 1 Code")
                    then
                        UsedAsItemBudgetDim := true;
                    if (DimTypeChecked <> DimTypeChecked::ItemBudget2) and
                       (DimChecked = ItemBudgetName."Budget Dimension 2 Code")
                    then
                        UsedAsItemBudgetDim := true;
                    if (DimTypeChecked <> DimTypeChecked::ItemBudget3) and
                       (DimChecked = ItemBudgetName."Budget Dimension 3 Code")
                    then
                        UsedAsItemBudgetDim := true;
                until ItemBudgetName.Next() = 0;
        end;

        CheckIfDimUsedAsAnalysisViewDim(AnalysisView, DimChecked, DimTypeChecked, CheckAllDim, CheckAnalysisViewDim, AnalysisViewChecked);

        CheckIfDimUsedAsItemAnalysisViewDim(ItemAnalysisView,DimChecked, DimTypeChecked, AnalysisViewChecked, AnalysisAreaChecked, CheckAllDim, CheckItemAnalysisViewDim, UsedAsCustomDim, CustomDimErr);//NewProcedure

        if UsedAsGlobalDim or
           UsedAsShortcutDim or
           UsedAsBudgetDim or
           UsedAsAnalysisViewDim or
           UsedAsItemBudgetDim or
           UsedAsItemAnalysisViewDim or
           UsedAsCustomDim
        then begin
            MakeCheckDimErr(CustomDimErr);
            exit(true);
        end;
        exit(false);
    end;

Client Code:


CheckItemAnalysisViewDim :=
  //DimTypeChecked IN [DimTypeChecked::ItemAnalysis1,DimTypeChecked::ItemAnalysis2,DimTypeChecked::ItemAnalysis3]; //HEI.02 commented
  DimTypeChecked IN [DimTypeChecked::ItemAnalysis1,DimTypeChecked::ItemAnalysis2,DimTypeChecked::ItemAnalysis3,DimTypeChecked::ItemAnalysis4,DimTypeChecked::ItemAnalysis5]; //HEI.02

IF CheckAllDim OR CheckItemAnalysisViewDim THEN BEGIN
  IF AnalysisViewChecked <> '' THEN BEGIN
    ItemAnalysisView.SETRANGE("Analysis Area",AnalysisAreaChecked);
    ItemAnalysisView.SETRANGE(Code,AnalysisViewChecked);
  END;
  IF ItemAnalysisView.FINDSET THEN
    REPEAT
      IF (DimTypeChecked <> DimTypeChecked::ItemAnalysis1) AND
         (DimChecked = ItemAnalysisView."Dimension 1 Code")
      THEN
        UsedAsItemAnalysisViewDim := TRUE;
      IF (DimTypeChecked <> DimTypeChecked::ItemAnalysis2) AND
         (DimChecked = ItemAnalysisView."Dimension 2 Code")
      THEN
        UsedAsItemAnalysisViewDim := TRUE;
      IF (DimTypeChecked <> DimTypeChecked::ItemAnalysis3) AND
         (DimChecked = ItemAnalysisView."Dimension 3 Code")
      THEN
        UsedAsItemAnalysisViewDim := TRUE;
     //HEI.02<<
      IF (DimTypeChecked <> DimTypeChecked::ItemAnalysis4) AND
         (DimChecked = ItemAnalysisView."Shortcut 1 Code")
      THEN
        UsedAsItemAnalysisViewDim := TRUE;
      IF (DimTypeChecked <> DimTypeChecked::ItemAnalysis5) AND
         (DimChecked = ItemAnalysisView."Shortcut 2 Code")
      THEN
        UsedAsItemAnalysisViewDim := TRUE;
     //HEI.02>>
    UNTIL ItemAnalysisView.NEXT = 0;
END;

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions