-
Notifications
You must be signed in to change notification settings - Fork 435
Add expense activity history foundation #10237
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
Open
Prangshuman Das (t-prda)
wants to merge
15
commits into
main
Choose a base branch
from
feature/expense-activity-log-foundation
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
15 commits
Select commit
Hold shift + click to select a range
3f61e55
Add expense activity history foundation
t-prda 5a92237
Fix expense activity review issues
t-prda 2becc02
Resolve activity page object IDs
t-prda 259268e
Resolve localized activity codeunit IDs
t-prda 29f330a
Harden activity history access
t-prda 3da9c13
Resolve activity API test object ID
t-prda 5bbe88d
Document activity API preload
t-prda ad5c4db
Use committed reads for activity API
t-prda 928440a
Index retention and parse capability JSON
t-prda 0104770
Make persistent activity scenarios rerunnable
t-prda 58ae2aa
Add activity and posted-report query keys
t-prda a36355e
Rename activity event key
t-prda 6284d35
Use default activity API read isolation
t-prda 775467b
Stabilize activity tests under restricted permissions
t-prda 311cc8b
Avoid expense policy page ID clashes
t-prda File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -134,7 +134,7 @@ | |
| }, | ||
| { | ||
| "from": 7073, | ||
| "to": 7103 | ||
| "to": 7123 | ||
| } | ||
| ], | ||
| "features": [ | ||
|
|
||
229 changes: 229 additions & 0 deletions
229
src/Apps/W1/ExpenseAgent/app/src/APIs/ActivityLog/ExpenseActivityLogAPI.Page.al
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,229 @@ | ||
| // ------------------------------------------------------------------------------------------------ | ||
| // Copyright (c) Microsoft Corporation. All rights reserved. | ||
| // Licensed under the MIT License. See License.txt in the project root for license information. | ||
| // ------------------------------------------------------------------------------------------------ | ||
| namespace Microsoft.ExpenseAgent; | ||
|
|
||
| page 7122 "Expense Activity Log API" | ||
| { | ||
| APIGroup = 'expense'; | ||
| APIPublisher = 'microsoft'; | ||
| APIVersion = 'beta'; | ||
| EntityCaption = 'Expense Activity Log Entry'; | ||
| EntitySetCaption = 'Expense Activity Log Entries'; | ||
| EntityName = 'expenseActivityLogEntry'; | ||
| EntitySetName = 'expenseActivityLogEntries'; | ||
| PageType = API; | ||
| SourceTable = "Expense Activity Log Entry"; | ||
| SourceTableView = sorting("Occurred At", "Entry No.") order(descending); | ||
| Permissions = tabledata "Expense Activity Log Entry" = r; | ||
| ODataKeyFields = SystemId; | ||
| DataAccessIntent = ReadOnly; | ||
| Editable = false; | ||
| InsertAllowed = false; | ||
| ModifyAllowed = false; | ||
| DeleteAllowed = false; | ||
| Extensible = false; | ||
| AboutText = 'Provides activity history when scoped through an expense report, posted expense report, or expense user. Direct unscoped access is not allowed. Expense user history requires the historyActorRole filter.'; | ||
|
|
||
| layout | ||
| { | ||
| area(Content) | ||
| { | ||
| repeater(General) | ||
| { | ||
| field(id; Rec.SystemId) | ||
| { | ||
| Caption = 'ID'; | ||
| } | ||
| field(entryNumber; Rec."Entry No.") | ||
| { | ||
| Caption = 'Entry Number'; | ||
| } | ||
| field(sourceTableId; Rec."Source Table ID") | ||
| { | ||
| Caption = 'Source Table ID'; | ||
| } | ||
| field(sourceId; Rec."Source Record System ID") | ||
| { | ||
| Caption = 'Source ID'; | ||
| } | ||
| field(subjectTableId; Rec."Subject Table ID") | ||
| { | ||
| Caption = 'Subject Table ID'; | ||
| } | ||
| field(subjectId; Rec."Subject System ID") | ||
| { | ||
| Caption = 'Subject ID'; | ||
| } | ||
| field(documentNumber; Rec."Document No.") | ||
| { | ||
| Caption = 'Document Number'; | ||
| } | ||
| field(documentDescription; Rec."Document Description") | ||
| { | ||
| Caption = 'Document Description'; | ||
| } | ||
| field(eventType; Rec."Event Type") | ||
| { | ||
| Caption = 'Event Type'; | ||
| } | ||
| field(occurredAt; Rec."Occurred At") | ||
| { | ||
| Caption = 'Occurred At'; | ||
| } | ||
| field(initiatedBy; Rec."Initiated By") | ||
| { | ||
| Caption = 'Initiated By'; | ||
| } | ||
| field(actorRole; Rec."Actor Role") | ||
| { | ||
| Caption = 'Actor Role'; | ||
| } | ||
| field(actorTableId; Rec."Actor Table ID") | ||
| { | ||
| Caption = 'Actor Table ID'; | ||
| } | ||
| field(actorId; Rec."Actor Record System ID") | ||
| { | ||
| Caption = 'Actor ID'; | ||
| } | ||
| field(actorDisplayName; Rec."Actor Display Name") | ||
| { | ||
| Caption = 'Actor Display Name'; | ||
| } | ||
| field(comment; Rec.Comment) | ||
| { | ||
| Caption = 'Comment'; | ||
| } | ||
| field(amountLCY; Rec."Amount (LCY)") | ||
| { | ||
| Caption = 'Amount (LCY)'; | ||
| } | ||
| field(currencyLCY; CurrencyLCY) | ||
| { | ||
| Caption = 'Currency (LCY)'; | ||
| } | ||
| field(nonRefundableAmountLCY; Rec."Non-Refundable Amount (LCY)") | ||
| { | ||
| Caption = 'Non-Refundable Amount (LCY)'; | ||
| } | ||
| field(reimbursableAmount; Rec."Reimbursable Amount") | ||
| { | ||
| Caption = 'Reimbursable Amount'; | ||
| } | ||
| field(reimbursableAmountLCY; Rec."Reimbursable Amount (LCY)") | ||
| { | ||
| Caption = 'Reimbursable Amount (LCY)'; | ||
| } | ||
| field(refundableAmount; Rec."Refundable Amount") | ||
| { | ||
| Caption = 'Refundable Amount'; | ||
| } | ||
| field(refundableAmountLCY; Rec."Refundable Amount (LCY)") | ||
| { | ||
| Caption = 'Refundable Amount (LCY)'; | ||
| } | ||
| field(reimbursementCurrencyCode; ReimbursementCurrencyCode) | ||
| { | ||
| Caption = 'Reimbursement Currency Code'; | ||
| } | ||
| field(reimbursementCurrencyFactor; Rec."Reimbursement Currency Factor") | ||
| { | ||
| Caption = 'Reimbursement Currency Factor'; | ||
| } | ||
| field(categories; Rec.Categories) | ||
| { | ||
| Caption = 'Categories'; | ||
| } | ||
| field(receiptCount; Rec."Receipt Count") | ||
| { | ||
| Caption = 'Receipt Count'; | ||
| } | ||
| field(policyStatus; Rec."Policy Status") | ||
| { | ||
| Caption = 'Policy Status'; | ||
| } | ||
| field(historyActorRole; Rec."History Actor Role Filter") | ||
| { | ||
| Caption = 'History Actor Role'; | ||
| } | ||
| } | ||
| } | ||
| } | ||
|
|
||
| var | ||
| CurrencyHelper: Codeunit "Expense API Currency Helper"; | ||
| CurrencyLCY: Code[10]; | ||
| HistoryScopeApplied: Boolean; | ||
| ReimbursementCurrencyCode: Code[10]; | ||
| HistoryActorRoleRequiredErr: Label 'The historyActorRole filter must be specified as Submitter or Approver.'; | ||
| ActivityScopeRequiredErr: Label 'Activity log entries must be requested through an expense report, posted expense report, or expense user.'; | ||
| AgentAccessRequiredErr: Label 'Only the Expense Agent can access the activity log API.'; | ||
|
|
||
| trigger OnInit() | ||
| var | ||
| ExpenseAgentAPIValidation: Codeunit "Expense Agent API Validation"; | ||
| begin | ||
| ExpenseAgentAPIValidation.VerifyAgentAccess(); | ||
|
t-prda marked this conversation as resolved.
|
||
| if not ExpenseAgentAPIValidation.IsCurrentUserExpenseAgent() then | ||
| Error(AgentAccessRequiredErr); | ||
| end; | ||
|
|
||
| trigger OnOpenPage() | ||
|
t-prda marked this conversation as resolved.
|
||
| begin | ||
| // Avoid JIT load consistency errors by including fields read in OnAfterGetRecord in the initial record buffer. | ||
| Rec.AddLoadFields("Reimbursement Currency Code"); | ||
| end; | ||
|
|
||
| trigger OnAfterGetRecord() | ||
|
t-prda marked this conversation as resolved.
|
||
| begin | ||
| Clear(CurrencyLCY); | ||
| Clear(ReimbursementCurrencyCode); | ||
| if Rec."Event Type" in [Rec."Event Type"::Submitted, Rec."Event Type"::Resubmitted, Rec."Event Type"::Posted] then begin | ||
| CurrencyLCY := CurrencyHelper.GetCurrencyCodeForAPI(''); | ||
| ReimbursementCurrencyCode := CurrencyHelper.GetCurrencyCodeForAPI(Rec."Reimbursement Currency Code"); | ||
| end; | ||
| end; | ||
|
|
||
| trigger OnFindRecord(Which: Text): Boolean | ||
| begin | ||
| ApplyHistoryScope(); | ||
| exit(Rec.Find(Which)); | ||
| end; | ||
|
|
||
| local procedure ApplyHistoryScope() | ||
| var | ||
| OriginalFilterGroup: Integer; | ||
| HasHistoryActorFilters: Boolean; | ||
| HasSourceFilters: Boolean; | ||
| HistoryActorRoleFilter: Text; | ||
| begin | ||
| if HistoryScopeApplied then | ||
| exit; | ||
|
|
||
| OriginalFilterGroup := Rec.FilterGroup(); | ||
| HistoryActorRoleFilter := Rec.GetFilter("History Actor Role Filter"); | ||
| Rec.FilterGroup(4); | ||
| HasSourceFilters := | ||
| (Rec.GetFilter("Source Table ID") <> '') and | ||
| (Rec.GetFilter("Source Record System ID") <> ''); | ||
| HasHistoryActorFilters := | ||
| (Rec.GetFilter("History Actor Table ID Filter") <> '') and | ||
| (Rec.GetFilter("History Actor System ID Filter") <> ''); | ||
| if HistoryActorRoleFilter = '' then | ||
| HistoryActorRoleFilter := Rec.GetFilter("History Actor Role Filter"); | ||
| Rec.FilterGroup(0); | ||
| if HasHistoryActorFilters then begin | ||
|
t-prda marked this conversation as resolved.
|
||
| if HistoryActorRoleFilter <> '' then | ||
| Rec.SetRange("History Subject Match", true) | ||
| else | ||
| Error(HistoryActorRoleRequiredErr); | ||
| end else | ||
| if not HasSourceFilters then | ||
| Error(ActivityScopeRequiredErr); | ||
| Rec.FilterGroup(OriginalFilterGroup); | ||
| HistoryScopeApplied := true; | ||
| end; | ||
|
|
||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.