-
Notifications
You must be signed in to change notification settings - Fork 3.9k
Exclude all-held reports from the Inbox to-do, keep them for whoever placed the hold #96178
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
base: main
Are you sure you want to change the base?
Changes from all commits
435e130
8fdf6ab
8c399fa
5bbd22f
a1ef2f1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -4481,11 +4481,21 @@ function getReasonAndReportActionThatRequiresAttention( | |
| const transactions = getReportTransactions(iouReportID); | ||
| const hasOnlyPendingTransactions = transactions.length > 0 && transactions.every((t) => isPending(t)); | ||
|
|
||
| const iouReportActions = getAllReportActions(iouReportID); | ||
| const currentUserPlacedHold = didCurrentUserPlaceHoldOnReportExpense(iouReportActions, transactions, currentUserAccountID); | ||
| // An all-held report can't move to its next state, so it isn't a to-do. Keep it only for an Approve or Pay report | ||
| // where the current user placed a hold, since only they can unhold it. Submit stays excluded even then, because on | ||
| // an open report only the owner can hold, so the exception would apply to every all-held report and defeat it. | ||
| const isExcludedForHeldExpenses = hasOnlyHeldExpenses(transactions) && (actionBadge === CONST.REPORT.ACTION_BADGE.SUBMIT ? true : !currentUserPlacedHold); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
When the chat reaches the fallback path above ( Useful? React with 👍 / 👎. |
||
|
|
||
| // Has a child report that is awaiting action (e.g. approve, pay, add bank account) from current user. | ||
| // A report whose only expenses are pending Expensify Card transactions can't be actioned until they post, so it | ||
| // shouldn't demand attention even when the chat still carries an outstanding-child flag. | ||
| const hasStaleChildRequest = isTripRoom(optionOrReport) && (optionOrReport.transactionCount ?? 0) === 0; | ||
| const hasValidIOUAction = ((optionOrReport.hasOutstandingChildRequest === true && !hasStaleChildRequest) || iouReportActionToApproveOrPay?.reportActionID) && !hasOnlyPendingTransactions; | ||
| const hasValidIOUAction = | ||
| ((optionOrReport.hasOutstandingChildRequest === true && !hasStaleChildRequest) || iouReportActionToApproveOrPay?.reportActionID) && | ||
| !hasOnlyPendingTransactions && | ||
| !isExcludedForHeldExpenses; | ||
|
|
||
| if (actionTypeForAssigneeToComplete) { | ||
| const isAssigneeExpenseAction = actionTypeForAssigneeToComplete === CONST.REPORT.ACTION_TYPES_FOR_ASSIGNEE_TO_COMPLETE.EXPENSE; | ||
|
|
@@ -4710,9 +4720,24 @@ function isReportFieldOfTypeTitle(reportField: OnyxEntry<PolicyReportField>): bo | |
| /** | ||
| * Check if Report has any held expenses | ||
| */ | ||
| function isHoldCreator(transaction: OnyxEntry<Transaction>, reportID: string | undefined): boolean { | ||
| function isHoldCreator(transaction: OnyxEntry<Transaction>, reportID: string | undefined, currentUserAccountID?: number): boolean { | ||
| const holdReportAction = getReportAction(reportID, `${transaction?.comment?.hold ?? ''}`); | ||
| return isActionCreator(holdReportAction); | ||
| return isActionCreator(holdReportAction, currentUserAccountID); | ||
| } | ||
|
|
||
| /** | ||
| * Whether the current user placed the hold on at least one of the report's held expenses. Used to keep an | ||
| * all-held report in that user's to-do queue, since only the person who placed a hold can remove it. | ||
| */ | ||
| function didCurrentUserPlaceHoldOnReportExpense(reportActions: OnyxEntry<ReportActions>, reportTransactions: Transaction[], currentUserAccountID?: number): boolean { | ||
| return Object.values(reportActions ?? {}).some((action) => { | ||
| if (!isMoneyRequestAction(action)) { | ||
| return false; | ||
| } | ||
| const transactionID = getOriginalMessage(action)?.IOUTransactionID; | ||
| const transaction = reportTransactions.find((reportTransaction) => reportTransaction.transactionID === transactionID); | ||
| return !!transaction && isOnHoldTransactionUtils(transaction) && isHoldCreator(transaction, action.childReportID, currentUserAccountID); | ||
| }); | ||
| } | ||
|
|
||
| /** | ||
|
|
@@ -13717,6 +13742,7 @@ export { | |
| isGroupChatAdmin, | ||
| isHarvestCreatedExpenseReport, | ||
| isHoldCreator, | ||
| didCurrentUserPlaceHoldOnReportExpense, | ||
| isIOUOwnedByCurrentUser, | ||
| isIOUReport, | ||
| isIOUReportUsingReport, | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
❌ PERF-2 (docs)
didCurrentUserPlaceHoldOnReportExpenseis the expensive part of this block — it iterates every report action and, for each money-request action, scansreportTransactions.find(...)plus agetReportActionlookup (roughly O(actions × transactions)). It runs unconditionally here, but its result (currentUserPlacedHold) is only ever consumed whenhasOnlyHeldExpenses(transactions)is true (the short-circuit&&on the next line). SincegetReasonAndReportActionThatRequiresAttentionis called across the LHN/report-attributes derivation for many reports, this overhead is paid on every report even when no expense is held.Gate the expensive call behind the cheap
hasOnlyHeldExpenses(transactions)check so it only runs when it can actually change the outcome:Reviewed at: a1ef2f1 | Please rate this suggestion with 👍 or 👎 to help us improve! Reactions are used to monitor reviewer efficiency.