mirror of
https://github.com/microsoft/BCQuality.git
synced 2026-10-07 07:36:54 +01:00
UI knowledge: notification recall needs a known Id; open mixed-type documents through Page Management (#214)
Some checks are pending
Validate knowledge index / validate-index (push) Waiting to run
Validate AL review fixtures / validate-review-fixtures (push) Waiting to run
Validate skill index and report schemas / validate-contract (push) Waiting to run
Validate frontmatter and structure / validate (push) Waiting to run
Some checks are pending
Validate knowledge index / validate-index (push) Waiting to run
Validate AL review fixtures / validate-review-fixtures (push) Waiting to run
Validate skill index and report schemas / validate-contract (push) Waiting to run
Validate frontmatter and structure / validate (push) Waiting to run
* Add UI knowledge: notification recall Id and Page Management document routing Two ui articles with compiled good/bad samples: - notification-recall-needs-known-id: a notification that the code also recalls needs a fixed Id (single instance; recall before re-send) or per-record tracking through codeunit "Notification Lifecycle Mgt." (SendNotification[WithAdditionalContext] / RecallNotificationsForRecord, HandleDelayedInsert semantics). Never-recalled notifications are exempt. - list-page-document-routing-uses-page-management: open documents from a mixed-type list with PageManagement.PageRun(Rec) instead of a hand-written case "Document Type" / Page.Run; register new tables through OnConditionalCardPageIDNotFound. Single-type opens and tables Page Management does not route are exempt. Wired into al-ui-review (entry gate now covers notification send/recall outside pages, tokens, high-signal mappings) and registered both pairs in the ui review-fixtures override. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Address review: scope shared notification Ids, routed-table definition, pinned links - notification-recall-needs-known-id: a fixed Id shared across records is valid for one-at-a-time warnings (Sales Line blocked-item, Over-Receipt Mgt. pass a fixed Id to SendNotification after Recall); the per-record anti-pattern now requires several records' notifications to be visible at once. Recall wording follows Learn (including its false-return reasons) and cites Base App's recall-before-send practice. - list-page-document-routing-uses-page-management: definition covers opening a routed table directly or after Get; cite archive line lists, Copy Document Mgt. ShowSalesDoc/ShowPurchDoc and Office handler; no "document types added later" overclaim (GetSalesHeaderPageID has no else for the extensible enum); full GetPageID resolution order; drop the IRS single-page subscriber. - al-ui-review: non-page files admitted by the notification clause are checked only against notification knowledge; description updated; drop the "Document Type" token; case-insensitive token matching; cues aligned with both articles. - Pin BCApps links to 837ef802485ee457e52310d2ecaa08b93d0122fd. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Address review: notification recall defect is a lost identity, not an unassigned or generated Id - notification-recall-needs-known-id: the defect is a Recall() whose Id cannot be the sent one (fresh local Notification, new CreateGuid at recall time) while neither the sent instance nor its Id is kept. A retained global instance (CreateGuid once in OnOpenPage, or Id left for Send to assign), a generated Id saved after Send and reassigned before Recall, and correctly tracked per-record Ids are explicitly not findings. Findings require evidence that the recalled identity differs from or cannot recover the sent identity. Notification Lifecycle Mgt. is recommended for per-record tracking, not mandatory. Cites VAT Bus. Post. Grp. Part, Certificate, and Data Search Lines, and the lifecycle helper's Send-then-read-Id sequence. - good sample: adds a page with a retained global Notification (CreateGuid in OnOpenPage, Send in an action, Recall in a later action and OnClosePage) and a pageextension that saves the Send-assigned Id and recalls it from a later action. Bad sample comments name the lost identity. - al-ui-review: notification cue requires that evidence and lists the retained-instance, saved-Id, and direct per-record tracking controls as exclusions. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
018e62767d
commit
86d809b525
8 changed files with 365 additions and 7 deletions
|
|
@ -0,0 +1,39 @@
|
|||
---
|
||||
bc-version: [all]
|
||||
domain: ui
|
||||
keywords: [page-management, pagerun, show-document, document-type, cardpageid, list-page, page-run, getconditionalcardpageid, onconditionalcardpageidnotfound]
|
||||
technologies: [al]
|
||||
countries: [w1]
|
||||
application-area: [all]
|
||||
---
|
||||
|
||||
# Open documents from a mixed-type list through Page Management
|
||||
|
||||
## Description
|
||||
|
||||
Some tables back several document pages, chosen by a type field. `Sales Header` rows open as Sales Quote, Sales Order, Sales Invoice, Sales Credit Memo, Blanket Sales Order, or Sales Return Order, depending on `Document Type`. A list over such a table cannot use one `CardPageID`. Codeunit 700 `"Page Management"` already holds that mapping. `PageRun(Rec)` resolves the page through `GetPageID`, in this order: `GetConditionalCardPageID`, then the default card page (only for an existing record), then `GetConditionalListPageID`, then the table's lookup page. `GetConditionalCardPageID` handles `Sales Header`, `Purchase Header`, their archives, general and item journal batches and lines, requisition worksheets, and several other tables. Base App's own lists call it: the `Show Document` actions on `Sales List` and `Purchase List`, `Sales Lines` (after getting the header), and `Navigate` for posted documents.
|
||||
|
||||
A hand-written `case Rec."Document Type" of ... Page.Run(Page::"Sales Order", Rec)` copies that mapping into a single action. It misses mappings that Microsoft later adds to Page Management, and routing that extensions add through its events (`OnBeforeGetConditionalCardPageID`, `OnAfterGetPageID`, `OnPageRunAtFieldOnBeforeRunPage`). Page Management does not route new values of an extended `Sales Document Type` enum by itself either, so those still need a subscriber.
|
||||
|
||||
## Best Practice
|
||||
|
||||
In the list's open-document action, call `PageManagement.PageRun(Rec)`, or `PageRunModal` or `PageRunList` as needed. `PageRun` returns `false` without opening anything when `GuiAllowed` is false or no page resolves. See sample: [`list-page-document-routing-uses-page-management.good.al`](list-page-document-routing-uses-page-management.good.al).
|
||||
|
||||
For a new table whose rows map to different pages, register the mapping once and then use `PageRun` everywhere. Subscribe to `OnConditionalCardPageIDNotFound`, which is raised only for tables the codeunit does not route itself. Microsoft's Sustainability app routes its journal batch and line tables this way. `OnBeforeGetConditionalCardPageID` is the `IsHandled` alternative, used by the Quality Management app.
|
||||
|
||||
## Anti Pattern
|
||||
|
||||
A page action that opens a record of a table Page Management routes, directly or after a `Get`, by switching on its `Document Type` (or a similar type field) and calling `Page.Run(Page::...)` in each branch. Base App still does this in several places, for example the `Show Document` actions of `Sales Line Archive List` and `Purchase Line Archive List`, and `Copy Document Mgt.` `ShowSalesDoc`/`ShowPurchDoc`. The result is a duplicated mapping, not a runtime error, so report it as minor. The same switch in a codeunit helper is outside this review's page scope. See sample: [`list-page-document-routing-uses-page-management.bad.al`](list-page-document-routing-uses-page-management.bad.al).
|
||||
|
||||
Not this pattern:
|
||||
|
||||
- Opening one known document type directly. `Opportunity` creates a quote and runs `Sales Quote`, and a single-type list such as `Sales Order List` sets `CardPageID = "Sales Order"`.
|
||||
- A table that Page Management does not route. `Assembly List` switches on `Assembly Header."Document Type"` itself. Registering the table through `OnConditionalCardPageIDNotFound` is an improvement there, not a defect fix.
|
||||
|
||||
## References
|
||||
|
||||
- [PageManagement.Codeunit.al](https://github.com/microsoft/BCApps/blob/837ef802485ee457e52310d2ecaa08b93d0122fd/src/Layers/W1/BaseApp/Utilities/PageManagement.Codeunit.al): `PageRun` (lines 44-47), `PageRunAtField` with the `GuiAllowed` exit (75-100), `GetPageID` resolution order (112-138, order at 121-133), `GetConditionalCardPageID` (194-263; unrouted tables raise `OnConditionalCardPageIDNotFound` at 258), `GetSalesHeaderPageID` with no `else` branch (289-315), integration events (671-719). [SalesDocumentType.Enum.al](https://github.com/microsoft/BCApps/blob/837ef802485ee457e52310d2ecaa08b93d0122fd/src/Layers/W1/BaseApp/Sales/Document/SalesDocumentType.Enum.al) is `Extensible` (line 12).
|
||||
- Callers: [SalesList.Page.al](https://github.com/microsoft/BCApps/blob/837ef802485ee457e52310d2ecaa08b93d0122fd/src/Layers/W1/BaseApp/Sales/Document/SalesList.Page.al) (`ShowDocument`, lines 188-202; no `CardPageID`), [PurchaseList.Page.al](https://github.com/microsoft/BCApps/blob/837ef802485ee457e52310d2ecaa08b93d0122fd/src/Layers/W1/BaseApp/Purchases/Document/PurchaseList.Page.al) (line 200), [SalesLines.Page.al](https://github.com/microsoft/BCApps/blob/837ef802485ee457e52310d2ecaa08b93d0122fd/src/Layers/W1/BaseApp/Sales/Document/SalesLines.Page.al) (lines 224-230), [Navigate.Page.al](https://github.com/microsoft/BCApps/blob/837ef802485ee457e52310d2ecaa08b93d0122fd/src/Layers/W1/BaseApp/Foundation/Navigate/Navigate.Page.al) (from line 1564).
|
||||
- Subscribers: [SustWorkflowEventHandling.Codeunit.al](https://github.com/microsoft/BCApps/blob/837ef802485ee457e52310d2ecaa08b93d0122fd/src/Apps/W1/Sustainability/app/src/Workflow/SustWorkflowEventHandling.Codeunit.al) (lines 184-193), [QltyUtilitiesIntegration.Codeunit.al](https://github.com/microsoft/BCApps/blob/837ef802485ee457e52310d2ecaa08b93d0122fd/src/Apps/W1/Quality%20Management/app/src/Integration/Utilities/QltyUtilitiesIntegration.Codeunit.al) (lines 20-28).
|
||||
- Remaining hand-rolled routing of routed tables: [SalesLineArchiveList.Page.al](https://github.com/microsoft/BCApps/blob/837ef802485ee457e52310d2ecaa08b93d0122fd/src/Layers/W1/BaseApp/Sales/Archive/SalesLineArchiveList.Page.al) (lines 106-121), [PurchaseLineArchiveList.Page.al](https://github.com/microsoft/BCApps/blob/837ef802485ee457e52310d2ecaa08b93d0122fd/src/Layers/W1/BaseApp/Purchases/Archive/PurchaseLineArchiveList.Page.al) (from line 109), [CopyDocumentMgt.Codeunit.al](https://github.com/microsoft/BCApps/blob/837ef802485ee457e52310d2ecaa08b93d0122fd/src/Layers/W1/BaseApp/Utilities/CopyDocumentMgt.Codeunit.al) (lines 1369-1409), [OfficeDocumentHandler.Codeunit.al](https://github.com/microsoft/BCApps/blob/837ef802485ee457e52310d2ecaa08b93d0122fd/src/Layers/W1/BaseApp/CRM/Outlook/OfficeDocumentHandler.Codeunit.al) (lines 342-348).
|
||||
- Not this pattern: [AssemblyList.Page.al](https://github.com/microsoft/BCApps/blob/837ef802485ee457e52310d2ecaa08b93d0122fd/src/Layers/W1/BaseApp/Assembly/Document/AssemblyList.Page.al) (lines 111-121), [Opportunity.Table.al](https://github.com/microsoft/BCApps/blob/837ef802485ee457e52310d2ecaa08b93d0122fd/src/Layers/W1/BaseApp/CRM/Opportunity/Opportunity.Table.al) (lines 1221-1223), [SalesOrderList.Page.al](https://github.com/microsoft/BCApps/blob/837ef802485ee457e52310d2ecaa08b93d0122fd/src/Layers/W1/BaseApp/Sales/Document/SalesOrderList.Page.al) (line 44).
|
||||
Loading…
Add table
Add a link
Reference in a new issue