Add expense activity history foundation - #10255
Add expense activity history foundation#10255Prangshuman Das (t-prda) wants to merge 42 commits into
Conversation
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: d9178a5c-c5ff-43a4-b9cb-877ec18618fa
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: d9178a5c-c5ff-43a4-b9cb-877ec18618fa
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: d9178a5c-c5ff-43a4-b9cb-877ec18618fa
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: d9178a5c-c5ff-43a4-b9cb-877ec18618fa
Apply partial-record reads and mediate activity table access through the API and factbox pages. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: d9178a5c-c5ff-43a4-b9cb-877ec18618fa
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: d9178a5c-c5ff-43a4-b9cb-877ec18618fa
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: d9178a5c-c5ff-43a4-b9cb-877ec18618fa
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: d9178a5c-c5ff-43a4-b9cb-877ec18618fa
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: d9178a5c-c5ff-43a4-b9cb-877ec18618fa
Clean prior marked fixtures and use a cleanup-safe posted source while retaining real API lifecycle actions. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: d9178a5c-c5ff-43a4-b9cb-877ec18618fa
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: d9178a5c-c5ff-43a4-b9cb-877ec18618fa
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: d9178a5c-c5ff-43a4-b9cb-877ec18618fa
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: d9178a5c-c5ff-43a4-b9cb-877ec18618fa
Give the test cleanup explicit activity permissions and use a deterministic approver overload for reopen coverage. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: d9178a5c-c5ff-43a4-b9cb-877ec18618fa
Reserve globally free activity page IDs alongside BCApps PR 10031. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: d9178a5c-c5ff-43a4-b9cb-877ec18618fa
Keep public configured/default approver checks separate from explicit internal actor validation. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: d9178a5c-c5ff-43a4-b9cb-877ec18618fa
Use standard agent API permissions, defer unused policy status, simplify factbox fields, and retain only query-backed indexes. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: d9178a5c-c5ff-43a4-b9cb-877ec18618fa
Move cleanup-safe lifecycle coverage into the API test codeunit and remove the persistent scenario test file. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: d9178a5c-c5ff-43a4-b9cb-877ec18618fa
Allow retention-policy refresh to execute independently of Expense Management role assignment. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: d9178a5c-c5ff-43a4-b9cb-877ec18618fa
Grant execute through the agent object permission set instead of inherent permissions. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: d9178a5c-c5ff-43a4-b9cb-877ec18618fa
Remove the test-only overload and isolate the current-user approver mapping in the unit test. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: d9178a5c-c5ff-43a4-b9cb-877ec18618fa
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: d9178a5c-c5ff-43a4-b9cb-877ec18618fa
Keep transactional cleanup under full test permissions instead of elevating the shared library. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: d9178a5c-c5ff-43a4-b9cb-877ec18618fa
Register activity retention on install and extend Retention Pol. View so refresh cannot fail on missing execute permission. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: d9178a5c-c5ff-43a4-b9cb-877ec18618fa
Remove retention registration from the foundation and track install, upgrade, refresh, permission, and audit semantics separately. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: d9178a5c-c5ff-43a4-b9cb-877ec18618fa
Select query-backed keys, lock wire-token errors, avoid UI handlers, and restore setup backups before disabled-isolation tests. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: d9178a5c-c5ff-43a4-b9cb-877ec18618fa
Grant direct read through Expense Mgmt. Read like the other factbox source tables. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: d9178a5c-c5ff-43a4-b9cb-877ec18618fa
Remove the API page from human Expense Management object permissions; the FactBox remains available there. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: d9178a5c-c5ff-43a4-b9cb-877ec18618fa
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: d9178a5c-c5ff-43a4-b9cb-877ec18618fa
Successful submission, resubmission, and posting already guarantee that Business Central rule validation passed, so the connector can derive compliance without persisting another field. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: d9178a5c-c5ff-43a4-b9cb-877ec18618fa
|
The code filters the Expense record by SystemId and then calls FindFirst(). This is a direct single-record lookup, so GetBySystemId() is the cheaper and clearer access pattern than a filtered FindFirst(). Suggested fix (apply manually — could not be anchored as a one-click suggestion): if Expense.GetBySystemId(ExpenseId) then beginKnowledge: Line mapping was unavailable, so this was posted as an issue comment. 👍 useful · ❤️ especially valuable · 👎 wrong - reply with why · AL review agent v1.33.4 |
|
The code filters Posted Expense Report Header on its full primary key field "No." and then calls FindFirst(). Get() expresses the direct primary-key seek without a filtered-search shape. Suggested fix (apply manually — could not be anchored as a one-click suggestion): if PostedExpenseReportHeader.Get(Rec."Last Posting No.") thenKnowledge: Line mapping was unavailable, so this was posted as an issue comment. 👍 useful · ❤️ especially valuable · 👎 wrong - reply with why · AL review agent v1.33.4 |
1 similar comment
|
The code filters Posted Expense Report Header on its full primary key field "No." and then calls FindFirst(). Get() expresses the direct primary-key seek without a filtered-search shape. Suggested fix (apply manually — could not be anchored as a one-click suggestion): if PostedExpenseReportHeader.Get(Rec."Last Posting No.") thenKnowledge: Line mapping was unavailable, so this was posted as an issue comment. 👍 useful · ❤️ especially valuable · 👎 wrong - reply with why · AL review agent v1.33.4 |
|
The changed file is named Knowledge: Line mapping was unavailable, so this was posted as an issue comment. 👍 useful · ❤️ especially valuable · 👎 wrong - reply with why · AL review agent v1.33.4 |
|
ProcessExpenseReportLines iterates every expense-report line, and that per-line path calls CreateSalesDocument, which then does SalesHeader.FindFirst() and SalesLine.FindLast() to locate or extend an open invoice. Posting a report with many billable lines therefore re-scans sales tables once per line, creating the N+1 lookup shape this rule warns about. Cache the target invoice and next line number by (customer, currency, posting date) or batch/group the billable lines before entering the posting loop. Knowledge: Line mapping was unavailable, so this was posted as an issue comment. 👍 useful · ❤️ especially valuable · 👎 wrong - reply with why · AL review agent v1.33.4 |
Persist the report line count used by report summaries while retaining an explicitly named attached receipt count for audit and future scenarios. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: d9178a5c-c5ff-43a4-b9cb-877ec18618fa
Stop lowercasing the response before case-sensitive JSON lookup and safely ignore rows that do not expose the expected capability fields. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: d9178a5c-c5ff-43a4-b9cb-877ec18618fa
|
This permission-set file is still named ExpenseManagementObjects.permissionset.al, but the style rule requires the canonical object-type suffix PermissionSet in ..al. Keeping the lowercase suffix breaks the filesystem-to-object-type mapping that grep, explorers, and other tooling rely on; rename the file to ExpenseManagementObjects.PermissionSet.al while touching this object. Knowledge: Line mapping was unavailable, so this was posted as an issue comment. 👍 useful · ❤️ especially valuable · 👎 wrong - reply with why · AL review agent v1.33.4 |
|
Review follow-up for the unanchored findings:
The actionable activity-history findings are being handled separately and remain open until the local fixes are reviewed and pushed. |
Follow API page conventions, keep user-facing validation translatable, narrow cleanup reads, and make read-only transport assertions less brittle. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: d9178a5c-c5ff-43a4-b9cb-877ec18618fa
|
"Expense Capabilities Provider" selects capability-specific behaviour with a Knowledge: Line mapping was unavailable, so this was posted as an issue comment. 👍 useful · ❤️ especially valuable · 👎 wrong - reply with why · AL review agent v1.33.4 |
|
The changed file path Knowledge: Line mapping was unavailable, so this was posted as an issue comment. 👍 useful · ❤️ especially valuable · 👎 wrong - reply with why · AL review agent v1.33.4 |
Agentic PR Review - Round 1Recommendation: Request ChangesWhat this PR doesThis adds an append-oriented expense activity timeline, lifecycle snapshots, active-to-posted source reassignment, scoped APIs, FactBoxes, capabilities, permissions, and tests. The storage model, event ordering, deletion flow, and transaction placement are coherent, but the current implementation does not preserve agent provenance, enforce committed history reads, or keep table access behind the scoped surfaces. SuggestionsS1 - Preserve agent creation provenance S2 - Expose only committed activity history S3 - Record agent lifecycle provenance correctly S4 - Keep activity reads code-mediated Risk assessment and necessityRisk: This is audit and approval history. The current code can persist false initiator data, expose rolled-back or partly reassigned timelines to concurrent API reads, and let assigned roles bypass report and actor-role scopes through direct table access. The schema is additive and the lifecycle tests are broad, but these gaps affect the trust boundary of the new history. Necessity: The feature is coherent and needed for expense traceability and approver history. The one-table model and source reassignment are appropriate, but the provenance, committed-read, and mediated-permission blockers must be fixed before the history can be trusted.
|
Allow the activity management codeunit to resolve protected User records while keeping the read permission code-mediated. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: d9178a5c-c5ff-43a4-b9cb-877ec18618fa
|
Response to Agentic PR Review - Round 1:
The codeunit now has code-mediated |
Include the field used by ModifyAll so localized builds do not introduce AA0242 JIT-load warnings. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: d9178a5c-c5ff-43a4-b9cb-877ec18618fa
Register the new table for evaluation data and mark actor identifiers and names as Personal. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: d9178a5c-c5ff-43a4-b9cb-877ec18618fa
Summary
Validation
historyActorRolewere verified to fail closedFixes AB#644172
Related: AB#639704
Replaces #10237 to reset stale review and CI history after the design was finalized.