Potential hole in handling default dimension

Since NAV 2013 we have been using Dimension Set instead of the Dimension Entry tables.  One of the function that was changed was GetDefaultDimID in Codeunit 408.

In NAV 2009 and older this would return a set of dimension for any of the dimension entry tables.  In NAV 2013 and newer this will return the Dimension Set Id and updated Global Dimension Codes.

Here; “updated” is the key word.  One could think that when a function is returning these codes you should be able to trust that it does.  If we look at the CreateDim function in the Sales Line table the code is

[code]
SourceCodeSetup.GET;
TableID[1] := Type1;
No[1] := No1;
TableID[2] := Type2;
No[2] := No2;
TableID[3] := Type3;
No[3] := No3;
"Shortcut Dimension 1 Code" := ”;
"Shortcut Dimension 2 Code" := ”;
GetSalesHeader;
"Dimension Set ID" :=
DimMgt.GetDefaultDimID(
TableID,No,SourceCodeSetup.Sales,
"Shortcut Dimension 1 Code","Shortcut Dimension 2 Code",
SalesHeader."Dimension Set ID",DATABASE::Customer);
DimMgt.UpdateGlobalDimFromDimSetID("Dimension Set ID","Shortcut Dimension 1 Code","Shortcut Dimension 2 Code");[/code]

But a better version might be

[code]
SourceCodeSetup.GET;
TableID[1] := Type1;
No[1] := No1;
TableID[2] := Type2;
No[2] := No2;
TableID[3] := Type3;
No[3] := No3;
GetSalesHeader;
"Shortcut Dimension 1 Code" := SalesHeader."Shortcut Dimension 1 Code";
"Shortcut Dimension 2 Code" := SalesHeader."Shortcut Dimension 2 Code";
"Dimension Set ID" :=
DimMgt.GetDefaultDimID(
TableID,No,SourceCodeSetup.Sales,
"Shortcut Dimension 1 Code","Shortcut Dimension 2 Code",
SalesHeader."Dimension Set ID",DATABASE::Customer);[/code]

The reason is that the function DimMgt.GetDefaultDimID will update the “Shortcut Dimension 1 Code” and “Shortcut Dimension 2 Code” only if they are changed. If the Dimension Set used in the Sales Header contains dimension values for “Shortcut Dimension 1 Code” or “Shortcut Dimension 2 Code” we need to add the DimMgt.UpdateGlobalDimFromDimSetID function to make sure that all the correct data is in place.

The lesson is; if using InheritFromDimSetID in the function DimMgt.GetDefaultDimID then make sure it is followed by calling DimMgt.UpdateGlobalDimFromDimSetID.

I have however suggested to Microsoft that they make a change to the DimMgt.GetDefaultDimID function to close this hole. The original version is

[code]
GetGLSetup;
IF InheritFromDimSetID > 0 THEN
GetDimensionSet(TempDimSetEntry0,InheritFromDimSetID);
TempDimBuf2.RESET;
TempDimBuf2.DELETEALL;
IF TempDimSetEntry0.FINDSET THEN
REPEAT
TempDimBuf2.INIT;
TempDimBuf2."Table ID" := InheritFromTableNo;
TempDimBuf2."Entry No." := 0;
TempDimBuf2."Dimension Code" := TempDimSetEntry0."Dimension Code";
TempDimBuf2."Dimension Value Code" := TempDimSetEntry0."Dimension Value Code";
TempDimBuf2.INSERT;
UNTIL TempDimSetEntry0.NEXT = 0;

NoFilter[2] := ”;
FOR i := 1 TO ARRAYLEN(TableID) DO BEGIN
IF (TableID[i] <> 0) AND (No[i] <> ”) THEN BEGIN
DefaultDim.SETRANGE("Table ID",TableID[i]);
NoFilter[1] := No[i];
FOR j := 1 TO 2 DO BEGIN
DefaultDim.SETRANGE("No.",NoFilter[j]);
IF DefaultDim.FINDSET THEN
REPEAT
IF DefaultDim."Dimension Value Code" <> ” THEN BEGIN
TempDimBuf2.SETRANGE("Dimension Code",DefaultDim."Dimension Code");
IF NOT TempDimBuf2.FINDFIRST THEN BEGIN
TempDimBuf2.INIT;
TempDimBuf2."Table ID" := DefaultDim."Table ID";
TempDimBuf2."Entry No." := 0;
TempDimBuf2."Dimension Code" := DefaultDim."Dimension Code";
TempDimBuf2."Dimension Value Code" := DefaultDim."Dimension Value Code";
TempDimBuf2.INSERT;
END ELSE BEGIN
IF DefaultDimPriority1.GET(SourceCode,DefaultDim."Table ID") THEN BEGIN
IF DefaultDimPriority2.GET(SourceCode,TempDimBuf2."Table ID") THEN BEGIN
IF DefaultDimPriority1.Priority < DefaultDimPriority2.Priority THEN BEGIN
TempDimBuf2.DELETE;
TempDimBuf2."Table ID" := DefaultDim."Table ID";
TempDimBuf2."Entry No." := 0;
TempDimBuf2."Dimension Value Code" := DefaultDim."Dimension Value Code";
TempDimBuf2.INSERT;
END;
END ELSE BEGIN
TempDimBuf2.DELETE;
TempDimBuf2."Table ID" := DefaultDim."Table ID";
TempDimBuf2."Entry No." := 0;
TempDimBuf2."Dimension Value Code" := DefaultDim."Dimension Value Code";
TempDimBuf2.INSERT;
END;
END;
END;
IF GLSetupShortcutDimCode[1] = TempDimBuf2."Dimension Code" THEN
GlobalDim1Code := TempDimBuf2."Dimension Value Code";
IF GLSetupShortcutDimCode[2] = TempDimBuf2."Dimension Code" THEN
GlobalDim2Code := TempDimBuf2."Dimension Value Code";
END;
UNTIL DefaultDim.NEXT = 0;
END;
END;
END;
TempDimBuf2.RESET;
IF TempDimBuf2.FINDSET THEN BEGIN
REPEAT
DimVal.GET(TempDimBuf2."Dimension Code",TempDimBuf2."Dimension Value Code");
TempDimSetEntry."Dimension Code" := TempDimBuf2."Dimension Code";
TempDimSetEntry."Dimension Value Code" := TempDimBuf2."Dimension Value Code";
TempDimSetEntry."Dimension Value ID" := DimVal."Dimension Value ID";
TempDimSetEntry.INSERT;
UNTIL TempDimBuf2.NEXT = 0;
NewDimSetID := GetDimensionSetID(TempDimSetEntry);
END;
EXIT(NewDimSetID);[/code]

and the modified would be

[code]
GetGLSetup;
IF InheritFromDimSetID > 0 THEN
GetDimensionSet(TempDimSetEntry0,InheritFromDimSetID);
TempDimBuf2.RESET;
TempDimBuf2.DELETEALL;
IF TempDimSetEntry0.FINDSET THEN
REPEAT
TempDimBuf2.INIT;
TempDimBuf2."Table ID" := InheritFromTableNo;
TempDimBuf2."Entry No." := 0;
TempDimBuf2."Dimension Code" := TempDimSetEntry0."Dimension Code";
TempDimBuf2."Dimension Value Code" := TempDimSetEntry0."Dimension Value Code";
TempDimBuf2.INSERT;
UNTIL TempDimSetEntry0.NEXT = 0;

NoFilter[2] := ”;
FOR i := 1 TO ARRAYLEN(TableID) DO BEGIN
IF (TableID[i] <> 0) AND (No[i] <> ”) THEN BEGIN
DefaultDim.SETRANGE("Table ID",TableID[i]);
NoFilter[1] := No[i];
FOR j := 1 TO 2 DO BEGIN
DefaultDim.SETRANGE("No.",NoFilter[j]);
IF DefaultDim.FINDSET THEN
REPEAT
IF DefaultDim."Dimension Value Code" <> ” THEN BEGIN
TempDimBuf2.SETRANGE("Dimension Code",DefaultDim."Dimension Code");
IF NOT TempDimBuf2.FINDFIRST THEN BEGIN
TempDimBuf2.INIT;
TempDimBuf2."Table ID" := DefaultDim."Table ID";
TempDimBuf2."Entry No." := 0;
TempDimBuf2."Dimension Code" := DefaultDim."Dimension Code";
TempDimBuf2."Dimension Value Code" := DefaultDim."Dimension Value Code";
TempDimBuf2.INSERT;
END ELSE BEGIN
IF DefaultDimPriority1.GET(SourceCode,DefaultDim."Table ID") THEN BEGIN
IF DefaultDimPriority2.GET(SourceCode,TempDimBuf2."Table ID") THEN BEGIN
IF DefaultDimPriority1.Priority < DefaultDimPriority2.Priority THEN BEGIN
TempDimBuf2.DELETE;
TempDimBuf2."Table ID" := DefaultDim."Table ID";
TempDimBuf2."Entry No." := 0;
TempDimBuf2."Dimension Value Code" := DefaultDim."Dimension Value Code";
TempDimBuf2.INSERT;
END;
END ELSE BEGIN
TempDimBuf2.DELETE;
TempDimBuf2."Table ID" := DefaultDim."Table ID";
TempDimBuf2."Entry No." := 0;
TempDimBuf2."Dimension Value Code" := DefaultDim."Dimension Value Code";
TempDimBuf2.INSERT;
END;
END;
END;
END;
UNTIL DefaultDim.NEXT = 0;
END;
END;
END;
TempDimBuf2.RESET;
IF TempDimBuf2.FINDSET THEN BEGIN
REPEAT
IF GLSetupShortcutDimCode[1] = TempDimBuf2."Dimension Code" THEN
GlobalDim1Code := TempDimBuf2."Dimension Value Code";
IF GLSetupShortcutDimCode[2] = TempDimBuf2."Dimension Code" THEN
GlobalDim2Code := TempDimBuf2."Dimension Value Code";
DimVal.GET(TempDimBuf2."Dimension Code",TempDimBuf2."Dimension Value Code");
TempDimSetEntry."Dimension Code" := TempDimBuf2."Dimension Code";
TempDimSetEntry."Dimension Value Code" := TempDimBuf2."Dimension Value Code";
TempDimSetEntry."Dimension Value ID" := DimVal."Dimension Value ID";
TempDimSetEntry.INSERT;
UNTIL TempDimBuf2.NEXT = 0;
NewDimSetID := GetDimensionSetID(TempDimSetEntry);
END;
EXIT(NewDimSetID);[/code]

Where I have moved the lines that update GlobalDim1Code and GlobalDim2Code to the loop in the end of the function. By doing this the call to DimMgt.UpdateGlobalDimFromDimSetID is no longer needed and that extra loop through the Dimension Set Entries will save some time.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.