Fix E-Document purchase draft header Sub Total overwrite; notify on mismatch#9711
Fix E-Document purchase draft header Sub Total overwrite; notify on mismatch#9711ventselartur wants to merge 12 commits into
Conversation
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
…arm on amount edits
|
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:
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.'; |
There was a problem hiding this comment.
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); |
There was a problem hiding this comment.
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); |
There was a problem hiding this comment.
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) |
There was a problem hiding this comment.
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; |
There was a problem hiding this comment.
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); |
There was a problem hiding this comment.
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"); |
There was a problem hiding this comment.
very unlikely, but just paranoid, this could be negative, so maybe an abs inside this proc wouldn't hurt
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
Fixes AB#642364