-
Notifications
You must be signed in to change notification settings - Fork 412
feat(Sustainability): Add Reverse Transaction for Sustainability Ledger Entries #9478
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 3 commits
5fe173b
521e5b0
d64cda4
6de072b
d935eb5
4ba7e4d
0300160
00e64c9
4a42419
39cb7b3
1b4b8c0
364a843
12a21c7
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,132 @@ | ||
| namespace Microsoft.Sustainability.Ledger; | ||
|
|
||
| using Microsoft.Sustainability.Setup; | ||
|
|
||
| codeunit 6230 "Sust. Entry Reverse Mgt." | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. "Sustainability Read" is an assignable read-only role for
|
||
| { | ||
| Permissions = tabledata "Sustainability Ledger Entry" = rimd; | ||
|
|
||
| var | ||
| AlreadyReversedErr: Label 'Entry No. %1 has already been reversed.', Comment = '%1 = Entry No.'; | ||
| DocumentEntryErr: Label 'Entry No. %1 was posted from a document and cannot be reversed from here. Use a corrective document instead.', Comment = '%1 = Entry No.'; | ||
| ConfirmReverseQst: Label 'Do you want to reverse the selected sustainability ledger entry?'; | ||
| ConfirmReverseMultipleQst: Label 'Do you want to reverse %1 sustainability ledger entries?', Comment = '%1 = Count'; | ||
|
|
||
| procedure ReverseEntry(var SustLedgEntry: Record "Sustainability Ledger Entry") | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The new reversal workflow in codeunit "Sust.Entry Reverse Mgt." is a core ledger operation but it exposes no OnBefore/OnAfter integration events around validation, reversal-entry creation, or original-entry update. That makes the reversal process a hard wall for extensions: partners must copy or replace the codeunit to customize reversal behavior. Add thin, empty publishers at the natural reversal boundaries and let the calling procedures own the logic. Knowledge: 👍 useful · ❤️ especially valuable · 👎 wrong - reply with why
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The new reversal management codeunit exposes ReverseEntry, ReverseEntryFromGL, and ReverseEntries as public API by omitting access modifiers, even though the callers in this diff are only this app and its friend test app.Mark these routines internal (or local where possible) so they do not become a supported external contract you must preserve indefinitely. Suggested fix (apply manually — could not be anchored as a one-click suggestion): internal procedure ReverseEntry(var SustLedgEntry: Record "Sustainability Ledger Entry")
var
NewSustLedgEntry: Record "Sustainability Ledger Entry";
NextEntryNo: Integer;
begin
ValidateEntryForReversal(SustLedgEntry);
NextEntryNo := GetNextEntryNo();
CreateReversalEntry(SustLedgEntry, NewSustLedgEntry, NextEntryNo);
UpdateOriginalEntry(SustLedgEntry, NextEntryNo);
end;
internal procedure ReverseEntryFromGL(var SustLedgEntry: Record "Sustainability Ledger Entry")
var
NewSustLedgEntry: Record "Sustainability Ledger Entry";
NextEntryNo: Integer;
begin
if SustLedgEntry.Reversed then
exit;
NextEntryNo := GetNextEntryNo();
CreateReversalEntry(SustLedgEntry, NewSustLedgEntry, NextEntryNo);
UpdateOriginalEntry(SustLedgEntry, NextEntryNo);
end;
internal procedure ReverseEntries(var SustLedgEntry: Record "Sustainability Ledger Entry"): Integer
var
TempSustLedgEntry: Record "Sustainability Ledger Entry";
EntryCount: Integer;
begin
EntryCount := SustLedgEntry.Count();
if EntryCount = 0 then
exit(0);
if EntryCount = 1 then begin
if not Confirm(ConfirmReverseQst) then
exit(0);
end else
if not Confirm(ConfirmReverseMultipleQst, false, EntryCount) then
exit(0);
// Validate all entries first (all-or-nothing)
TempSustLedgEntry.Copy(SustLedgEntry);
TempSustLedgEntry.SetLoadFields("Entry No.", Reversed, "Journal Template Name");
if TempSustLedgEntry.FindSet() then
repeat
ValidateEntryForReversal(TempSustLedgEntry);
until TempSustLedgEntry.Next() = 0;
// Reverse all entries
if SustLedgEntry.FindSet(true) then
repeat
ReverseEntry(SustLedgEntry);
until SustLedgEntry.Next() = 0;
exit(EntryCount);
end;Knowledge: 👍 useful · ❤️ especially valuable · 👎 wrong - reply with why
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The new sustainability reversal flow commits a new ledger entry and marks the original entry as reversed in both
|
||
| var | ||
| NewSustLedgEntry: Record "Sustainability Ledger Entry"; | ||
| NextEntryNo: Integer; | ||
| begin | ||
| ValidateEntryForReversal(SustLedgEntry); | ||
|
|
||
| NextEntryNo := GetNextEntryNo(); | ||
|
|
||
| CreateReversalEntry(SustLedgEntry, NewSustLedgEntry, NextEntryNo); | ||
| UpdateOriginalEntry(SustLedgEntry, NextEntryNo); | ||
| end; | ||
|
|
||
| procedure ReverseEntryFromGL(var SustLedgEntry: Record "Sustainability Ledger Entry") | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ReverseEntry and ReverseEntries both route through ValidateEntryForReversal, which blocks reversing an entry whose "Journal Template Name" is blank (document-posted, per DocumentEntryErr: 'was posted from a document and cannot be reversed from here').ReverseEntryFromGL is a third public entry point into the same reversal logic (CreateReversalEntry/UpdateOriginalEntry) but only checks SustLedgEntry.Reversed - it never checks "Journal Template Name". Today the only caller (Sust. GL Reverse Subscriber) happens to pre-filter with SetFilter("Journal Template Name", '<>%1', ''), but that guard lives in the caller, not in the shared procedure. Any other code that calls the public ReverseEntryFromGL directly with a document-posted entry would silently create an incorrect reversal that the two sibling entry points explicitly forbid. Consider moving the document-template check into ReverseEntryFromGL (or a shared validation step) so the business rule is enforced once, in the procedure that owns it, rather than relying on every caller to re-derive the same filter. If this were treated as high-impact, this would warrant a knowledge-backed rule rather than an agent-severity flag; it is kept at minor per the agent-finding severity cap. 👍 useful · ❤️ especially valuable · 👎 wrong - reply with why |
||
| var | ||
| NewSustLedgEntry: Record "Sustainability Ledger Entry"; | ||
| NextEntryNo: Integer; | ||
| begin | ||
| if SustLedgEntry.Reversed then | ||
| exit; | ||
|
|
||
| NextEntryNo := GetNextEntryNo(); | ||
|
|
||
| CreateReversalEntry(SustLedgEntry, NewSustLedgEntry, NextEntryNo); | ||
| UpdateOriginalEntry(SustLedgEntry, NextEntryNo); | ||
| end; | ||
|
|
||
| procedure ReverseEntries(var SustLedgEntry: Record "Sustainability Ledger Entry"): Integer | ||
| var | ||
| TempSustLedgEntry: Record "Sustainability Ledger Entry"; | ||
| EntryCount: Integer; | ||
| begin | ||
| EntryCount := SustLedgEntry.Count(); | ||
|
|
||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ReverseEntries validates the selected ledger entries by calling ValidateEntryForReversal inside a batch loop, but each validation failure still raises a plain Error.That means the first invalid entry aborts the validation pass and the user must fix issues one at a time instead of seeing every bad entry in the selection. For this batch validation path, use ErrorBehavior::Collect, then retrieve and clear the collected errors and fail once with the aggregated result. Knowledge: 👍 useful · ❤️ especially valuable · 👎 wrong - reply with why |
||
| if EntryCount = 0 then | ||
| exit(0); | ||
|
|
||
| if EntryCount = 1 then begin | ||
| if not Confirm(ConfirmReverseQst) then | ||
| exit(0); | ||
| end else | ||
| if not Confirm(ConfirmReverseMultipleQst, false, EntryCount) then | ||
| exit(0); | ||
|
|
||
| // Validate all entries first (all-or-nothing) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
| TempSustLedgEntry.Copy(SustLedgEntry); | ||
| TempSustLedgEntry.SetLoadFields("Entry No.", Reversed, "Journal Template Name"); | ||
| if TempSustLedgEntry.FindSet() then | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ReverseEntries validates every selected entry in a loop but calls ValidateEntryForReversal, which raises a plain Error on the first invalid entry.When multiple selected entries fail validation (for example several are already reversed or document-posted), the user only ever learns about the first failure, has to deselect that one entry, and re-run the action to discover the next failure. Marking the orchestrating validation loop with [ErrorBehavior(ErrorBehavior::Collect)] and reporting all collected failures at once would let the user fix every problem in one pass instead of one-at-a-time. Knowledge: 👍 useful · ❤️ especially valuable · 👎 wrong - reply with why |
||
| repeat | ||
| ValidateEntryForReversal(TempSustLedgEntry); | ||
| until TempSustLedgEntry.Next() = 0; | ||
|
|
||
| // Reverse all entries | ||
| if SustLedgEntry.FindSet(true) then | ||
| repeat | ||
| ReverseEntry(SustLedgEntry); | ||
| until SustLedgEntry.Next() = 0; | ||
|
|
||
| exit(EntryCount); | ||
| end; | ||
|
|
||
| local procedure ValidateEntryForReversal(SustLedgEntry: Record "Sustainability Ledger Entry") | ||
| begin | ||
| if SustLedgEntry.Reversed then | ||
| Error(AlreadyReversedErr, SustLedgEntry."Entry No."); | ||
|
|
||
| if SustLedgEntry."Journal Template Name" = '' then | ||
| Error(DocumentEntryErr, SustLedgEntry."Entry No."); | ||
| end; | ||
|
|
||
| local procedure CreateReversalEntry(OriginalEntry: Record "Sustainability Ledger Entry"; var NewEntry: Record "Sustainability Ledger Entry"; NewEntryNo: Integer) | ||
| begin | ||
| NewEntry.Init(); | ||
| NewEntry.TransferFields(OriginalEntry, false); | ||
| NewEntry."Entry No." := NewEntryNo; | ||
| // Post the reversal on the original entry's posting date so emissions net to zero within the same period (matches G/L Reverse). | ||
| NewEntry."Posting Date" := OriginalEntry."Posting Date"; | ||
| NewEntry."Document No." := OriginalEntry."Document No."; | ||
|
|
||
| // Negate emission values | ||
| NewEntry."Emission CO2" := -OriginalEntry."Emission CO2"; | ||
| NewEntry."Emission CH4" := -OriginalEntry."Emission CH4"; | ||
| NewEntry."Emission N2O" := -OriginalEntry."Emission N2O"; | ||
| NewEntry."CO2e Emission" := -OriginalEntry."CO2e Emission"; | ||
| NewEntry."Carbon Fee" := -OriginalEntry."Carbon Fee"; | ||
|
|
||
| // Negate water & waste values | ||
| NewEntry."Water Intensity" := -OriginalEntry."Water Intensity"; | ||
| NewEntry."Discharged Into Water" := -OriginalEntry."Discharged Into Water"; | ||
| NewEntry."Waste Intensity" := -OriginalEntry."Waste Intensity"; | ||
| NewEntry."Energy Consumption" := -OriginalEntry."Energy Consumption"; | ||
|
|
||
| // Set reversal tracking fields | ||
| NewEntry.Reversed := true; | ||
| NewEntry."Reversed Entry No." := OriginalEntry."Entry No."; | ||
| NewEntry."Reversed by Entry No." := 0; | ||
|
|
||
| NewEntry.Insert(true); | ||
| end; | ||
|
|
||
| local procedure UpdateOriginalEntry(var OriginalEntry: Record "Sustainability Ledger Entry"; ReversalEntryNo: Integer) | ||
| begin | ||
| OriginalEntry.Reversed := true; | ||
| OriginalEntry."Reversed by Entry No." := ReversalEntryNo; | ||
| OriginalEntry.Modify(true); | ||
| end; | ||
|
|
||
| local procedure GetNextEntryNo(): Integer | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. GetNextEntryNo() reads the last "Sustainability Ledger Entry" number with FindLast() and CreateReversalEntry then inserts that explicit "Entry No." without locking the table or letting the AutoIncrement key assign the value.Two concurrent reversals or postings can therefore compute the same next number and fail (or silently collide) on duplicate primary-key insertion; this also adds an avoidable extra SQL lookup per row when reversing several entries in one batch. Either keep the AutoIncrement pattern already used for this table (leave "Entry No." at 0, insert, then read the assigned key back) or call LockTable() before computing and consuming a manual next entry number. 👍 useful · ❤️ especially valuable · 👎 wrong - reply with why |
||
| var | ||
| SustLedgEntry: Record "Sustainability Ledger Entry"; | ||
| begin | ||
| SustLedgEntry.SetCurrentKey("Entry No."); | ||
| if SustLedgEntry.FindLast() then | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. GetNextEntryNo's if/then/else both branches terminate with exit, so the else is structural noise the reader has to mentally flatten.Per BCQuality style guidance, drop the else and let the second exit fall through naturally. Suggested fix (apply manually — could not be anchored as a one-click suggestion): if SustLedgEntry.FindLast() then
exit(SustLedgEntry."Entry No." + 1);
exit(1);Knowledge: 👍 useful · ❤️ especially valuable · 👎 wrong - reply with why |
||
| exit(SustLedgEntry."Entry No." + 1) | ||
| else | ||
| exit(1); | ||
| end; | ||
| } | ||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -161,6 +161,18 @@ page 6220 "Sustainability Ledger Entries" | |||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||
| ToolTip = 'Specifies the Energy Consumption.'; | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
| field(Reversed; Rec.Reversed) | ||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||
| ToolTip = 'Specifies whether this entry has been reversed.'; | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
| field("Reversed by Entry No."; Rec."Reversed by Entry No.") | ||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||
| ToolTip = 'Specifies the entry number that reversed this entry.'; | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
| field("Reversed Entry No."; Rec."Reversed Entry No.") | ||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||
| ToolTip = 'Specifies the original entry number that this entry reverses.'; | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
| field("Country/Region Code"; Rec."Country/Region Code") | ||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||
| ToolTip = 'Specifies the country/region code of the entry.'; | ||||||||||||||||||||||||||
|
|
@@ -260,6 +272,33 @@ page 6220 "Sustainability Ledger Entries" | |||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
| area(processing) | ||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||
| action(ReverseTransaction) | ||||||||||||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The new
|
||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||
| ApplicationArea = Basic, Suite; | ||||||||||||||||||||||||||
| Caption = 'Reverse Transaction'; | ||||||||||||||||||||||||||
| ToolTip = 'Reverse the selected sustainability ledger entry by creating a new entry with negated emission values.'; | ||||||||||||||||||||||||||
| Image = ReverseRegister; | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| trigger OnAction() | ||||||||||||||||||||||||||
| var | ||||||||||||||||||||||||||
| SustLedgEntry: Record "Sustainability Ledger Entry"; | ||||||||||||||||||||||||||
| SustEntryReverseMgt: Codeunit "Sust. Entry Reverse Mgt."; | ||||||||||||||||||||||||||
| ReversedCount: Integer; | ||||||||||||||||||||||||||
| begin | ||||||||||||||||||||||||||
| CurrPage.SetSelectionFilter(SustLedgEntry); | ||||||||||||||||||||||||||
| ReversedCount := SustEntryReverseMgt.ReverseEntries(SustLedgEntry); | ||||||||||||||||||||||||||
|
Comment on lines
+290
to
+291
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This batch action passes the result of
|
||||||||||||||||||||||||||
| CurrPage.SetSelectionFilter(SustLedgEntry); | |
| ReversedCount := SustEntryReverseMgt.ReverseEntries(SustLedgEntry); | |
| CurrPage.SetSelectionFilter(SustLedgEntry); | |
| if not SustLedgEntry.MarkedOnly then | |
| SustLedgEntry.Copy(Rec); | |
| ReversedCount := SustEntryReverseMgt.ReverseEntries(SustLedgEntry); |
Knowledge:
👍 useful · ❤️ especially valuable · 👎 wrong - reply with why
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The 'Reverse Transaction' action calls CurrPage.SetSelectionFilter(SustLedgEntry) and passes the resulting record straight into SustEntryReverseMgt.ReverseEntries without checking MarkedOnly.
Per the cited guidance, SetSelectionFilter only marks the full explicit selection and sets MarkedOnly := true when the user has actively multi-selected rows; in other cases (cursor on a single row, or a Ctrl+A select-all that the platform does not report as an explicit mark) it silently narrows the filter to one row. Because ReverseEntries is a genuine multi-record batch action (it has dedicated 'reverse N entries' confirmation and success messages), a user who selects all rows with Ctrl+A instead of manually marking each one can have the action silently reverse only a single entry with no error, appearing to have succeeded.
| CurrPage.SetSelectionFilter(SustLedgEntry); | |
| ReversedCount := SustEntryReverseMgt.ReverseEntries(SustLedgEntry); | |
| CurrPage.SetSelectionFilter(SustLedgEntry); | |
| if not SustLedgEntry.MarkedOnly() then | |
| SustLedgEntry.Copy(Rec); | |
| ReversedCount := SustEntryReverseMgt.ReverseEntries(SustLedgEntry); |
Knowledge:
👍 useful · ❤️ especially valuable · 👎 wrong - reply with why
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
duplicate ! already reported !!!!!!!
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -340,6 +340,26 @@ table 6216 "Sustainability Ledger Entry" | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Caption = 'Correction'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| field(5818; Reversed; Boolean) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Caption = 'Reversed'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| DataClassification = SystemMetadata; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Editable = false; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| field(5819; "Reversed by Entry No."; Integer) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Caption = 'Reversed by Entry No.'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| DataClassification = SystemMetadata; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Editable = false; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| TableRelation = "Sustainability Ledger Entry"."Entry No."; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| field(5820; "Reversed Entry No."; Integer) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Caption = 'Reversed Entry No.'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| DataClassification = SystemMetadata; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Editable = false; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| TableRelation = "Sustainability Ledger Entry"."Entry No."; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+349
to
+362
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The new Integer fields "Reversed by Entry No." and "Reversed Entry No." (fields 5819/5820 in Sustainability Ledger Entry) omit BlankZero = true.The equivalent fields on G/L Entry ("Reversed by Entry No."/"Reversed Entry No.", fields 74/75), which this feature explicitly mirrors per its own comments, both set BlankZero = true. Without it, every unreversed Sustainability Ledger Entry will display a literal '0' in these Editable = false columns instead of a blank cell, which is a visible, user-facing inconsistency with the pattern this PR is deliberately copying. Add BlankZero = true to both fields.
Suggested change
Agent judgement — not directly backed by a BCQuality knowledge article. 👍 useful · ❤️ especially valuable · 👎 wrong - reply with why |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| keys | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -370,4 +390,4 @@ table 6216 "Sustainability Ledger Entry" | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| begin | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| DimMgt.ShowDimensionSet("Dimension Set ID", StrSubstNo(EntryRecIDLbl, TableCaption(), "Entry No.")); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| end; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The new codeunit "Sust.
Entry Reverse Mgt." is public by default, and its
ReverseEntry,ReverseEntryFromGL, andReverseEntriesprocedures are also externally reachable. In this app the codeunit is only consumed by the internal page action and tests, so this exposes implementation-detail reversal logic as a supported API other extensions could bind to. Make the codeunitAccess = Internal;and keep these proceduresinternalunless you intentionally want to support them as a stable external contract.Suggested fix (apply manually — could not be anchored as a one-click suggestion):
Knowledge:
👍 useful · ❤️ especially valuable · 👎 wrong - reply with why