Skip to content

Fix E-Document purchase draft header Sub Total overwrite; notify on mismatch#9711

Open
ventselartur wants to merge 12 commits into
mainfrom
bugs/642364-edoc-purchase-draft-header-totals
Open

Fix E-Document purchase draft header Sub Total overwrite; notify on mismatch#9711
ventselartur wants to merge 12 commits into
mainfrom
bugs/642364-edoc-purchase-draft-header-totals

Conversation

@ventselartur

@ventselartur ventselartur commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

Why

On the E-Document purchase draft page, editing a line recalculated the header "Sub Total" from the sum of the lines and silently overwrote the value that came in on the incoming document. This masked genuine discrepancies between the supplier-provided document total and the captured lines, so users could finalize a draft whose header total did not actually reflect the source document (bug 642364). The header total should be preserved, and the user should instead be warned when it diverges from the lines beyond a rounding tolerance.

Summary

  • Stopped overwriting the purchase draft header "Sub Total" from the lines — the incoming document total is now preserved.
  • Added a tolerance-based mismatch check (rounding-precision × line count) that compares the header Sub Total against the sum of the lines.
  • Added a "Sub Total Mismatch" notification type with Dismiss / Don't-show-again actions on the purchase draft subform.
  • Added a "Sub Total Mismatch Dismissed" flag on the E-Document Purchase Header so a dismissal persists and re-arms only when the user edits an amount.
  • Added telemetry logging for detected mismatches (with and without tolerance) including header/lines totals, tolerance, and difference.
  • Added comprehensive tests covering mismatch notification, dismissal persistence, re-arming on amount edits, and total invariants.

Fixes AB#642364

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: c1715353-5157-420a-8c46-89c1d255b62f
…smatch (642364)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: c1715353-5157-420a-8c46-89c1d255b62f
…notification (642364)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: c1715353-5157-420a-8c46-89c1d255b62f
…ce setup, cleanup)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: c1715353-5157-420a-8c46-89c1d255b62f
…lify recalc

Add AL test AddingLineTriggersSubTotalMismatchNotification verifying the Sub Total Mismatch notification is shown when a new draft line makes the sum of the lines diverge from the header Sub Total. Tag existing tests with [AI test] and add Initialize/filter helpers.

Simplify UpdateCalculatedAmounts to always re-check totals (drop UpdateParentRecord flag) and remove the redundant beyond-tolerance telemetry message.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 00495e7a-6f16-4a80-b771-1977bec17731
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: ec60766f-5fac-4cc4-b894-2dd0de933ca4
@ventselartur
ventselartur requested review from a team July 24, 2026 11:22
@github-actions github-actions Bot added AL: Apps (W1) Add-on apps for W1 Integration GitHub request for Integration area labels Jul 24, 2026
@github-actions github-actions Bot added this to the Version 29.0 milestone Jul 24, 2026
@github-actions

Copy link
Copy Markdown
Contributor

$\textbf{🟠\ High\ Severity\ —\ Performance}$

UpdateCalculatedAmounts(false) is invoked unconditionally from the subform's OnAfterGetRecord, which fires once per visible line every time the user scrolls, sorts, or refreshes. It now always calls CheckSubTotalMatchesLines, which re-reads and re-sums every line of the document (an O(n) FindSet loop) and can Insert/Delete rows in the 'E-Document Notification' table and re-send all pending notifications for the document. For a draft with n lines this makes opening/scrolling the page O(n^2) and turns simple row navigation into repeated database writes, matching the 'Do not Modify inside OnAfterGetRecord' anti-pattern (DB writes belong behind an explicit user action, not per-row display). Previously this branch (UpdateParentRecord = false) exited immediately without touching the header or other lines.

Recommendation:

  • only recompute/notify from OnValidate triggers on Quantity/Unit Price/Total Discount (already wired via UpdateCalculatedAmounts(true)), and drop the per-row call from OnAfterGetRecord, or cache the last-checked totals so the mismatch check runs once per document load rather than once per row.

Knowledge:

Line mapping was unavailable, so this was posted as an issue comment.

👍 useful · ❤️ especially valuable · 👎 wrong - reply with why · AL review agent v1.15.4

var
EDocumentNotification: Record "E-Document Notification";
MyNotifications: Record "My Notifications";
SubTotalMismatchMsg: Label 'The document total does not match the sum of the lines. Review the amounts before finalizing the draft.';

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

$\textbf{🟡\ Medium\ Severity\ —\ Style}$

The new SubTotalMismatchMsg Label in AddSubTotalMismatchNotification is declared inside the procedure's local var block instead of the codeunit's top-level var block, which hides it from object-level translation review and is fragile in XLIFF extraction across BC versions.

Recommendation:

  • move SubTotalMismatchMsg (and similarly-scoped new labels) to the codeunit-level var section, alongside the existing VendorMatchedByNameNotAddressMsg pattern this file already partly follows for other labels.

Knowledge:

👍 useful · ❤️ especially valuable · 👎 wrong - reply with why · AL review agent v1.15.4

CustomDimensions.Add('Difference', Format(Difference, 0, 9));

if Difference <> 0 then
Telemetry.LogMessage('', SubTotalMismatchNoToleranceTxt, Verbosity::Normal, DataClassification::SystemMetadata, TelemetryScope::All, CustomDimensions);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

$\textbf{🟠\ High\ Severity\ —\ Telemetry}$

Telemetry.LogMessage is called with an empty string as the event ID ('', SubTotalMismatchNoToleranceTxt, ...). The event ID is the field telemetry consumers (Application Insights queries, KQL dashboards, alert rules) pivot on; an empty string is a placeholder that is unsearchable and indistinguishable from any other event that omits an ID.

Recommendation:

  • assign a real, registered, stable event ID (e.g. an 'EDOC-nnnn' style prefix already used elsewhere in this app) instead of ''.

Knowledge:

👍 useful · ❤️ especially valuable · 👎 wrong - reply with why · AL review agent v1.15.4

Telemetry.LogMessage('', SubTotalMismatchNoToleranceTxt, Verbosity::Normal, DataClassification::SystemMetadata, TelemetryScope::All, CustomDimensions);

if Difference > Tolerance then begin
Telemetry.LogMessage('', SubTotalMismatchNotificationShownTxt, Verbosity::Normal, DataClassification::SystemMetadata, TelemetryScope::All, CustomDimensions);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

$\textbf{🟠\ High\ Severity\ —\ Telemetry}$

Same issue as the neighboring call: Telemetry.LogMessage('', SubTotalMismatchNotificationShownTxt, ...) also uses an empty-string event ID, making this second new telemetry signal equally unsearchable and impossible to distinguish from other placeholder-ID events.

Knowledge:

👍 useful · ❤️ especially valuable · 👎 wrong - reply with why · AL review agent v1.15.4

EDocument.DeleteAll();
end;

local procedure CreatePurchaseDraft(var EDocument: Record "E-Document"; var EDocumentPurchaseHeader: Record "E-Document Purchase Header"; HeaderSubTotal: Decimal)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

$\textbf{🟡\ Medium\ Severity\ —\ Testing}$

The new test's local CreatePurchaseDraft/CreatePurchaseLine helpers hand-roll Record.Insert() on 'E-Document Purchase Header' and 'E-Document Purchase Line' instead of reusing the existing test-library fixtures in LibraryEDocument.Codeunit.al (InsertForEDocument via MockPurchaseDraftPrepared, and InsertPurchaseDraftLine), which already encode how these records should be created. Duplicating fixture-construction logic in the test file risks drifting from the library helpers as the schema evolves.

Recommendation:

  • extend LibraryEDocument with a parameterized header/line creation overload (accepting the custom Sub Total / amounts these tests need) rather than reimplementing insertion locally.

Knowledge:

👍 useful · ❤️ especially valuable · 👎 wrong - reply with why · AL review agent v1.15.4

Evaluate(EDocumentEntryNo, Notification.GetData(EDocumentNotification.FieldName("E-Document Entry No.")));
Evaluate(Id, Notification.GetData(EDocumentNotification.FieldName(ID)));
if EDocumentPurchaseHeader.Get(EDocumentEntryNo) then begin
EDocumentPurchaseHeader."Sub Total Mismatch Dismissed" := true;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe we can move this Sub Total Mismatch Dismissed to the EDocNotification table? then if it has it, it's just not launched? It feels a bit out of place in EDocPurchsaeHeader

EDocumentPurchaseHeader."Sub Total Mismatch Dismissed" := false;
EDocumentPurchaseHeader.Modify();
end;
CheckSubTotalMatchesLines(EDocumentPurchaseHeader);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could maybe avoid going down this path if we already know the notification is disabled?

Tolerance: Decimal;
LineCount: Integer;
begin
RoundingPrecision := EDocumentImportHelper.GetCurrencyRoundingPrecision(EDocPurchaseHeader."Currency Code");

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

very unlikely, but just paranoid, this could be negative, so maybe an abs inside this proc wouldn't hurt

@mynjj mynjj left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

AL: Apps (W1) Add-on apps for W1 Integration GitHub request for Integration area

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants