Skip to content

Scope Top Spenders suggested search to eligible workspace policyIDs - #95593

Merged
MonilBhavsar merged 14 commits into
mainfrom
claude-topSpendersPolicyScope
Jul 20, 2026
Merged

MonilBhavsar merged 14 commits into
mainfrom
claude-topSpendersPolicyScope

Conversation

@MelvinBot

@MelvinBot MelvinBot commented Jul 8, 2026 •

Copy link
Copy Markdown
Contributor

Explanation of Change

The "Top Spenders" suggested search (under Spend → insights) built its query with type:expense grouped by submitter for the last month, but with no policyID filter. The backend therefore returned every expense the user is party to — including personal / individual-chat expenses that don't belong to any workspace — which is how an IOU submitted to an individual chat leaked into "Top Spenders".

This PR scopes the Top Spenders query to the workspaces that are actually eligible for the section, so only expenses belonging to those workspaces are returned.

What changed in src/libs/SearchUIUtils.ts:

  • getSuggestedSearchesVisibility now also collects the IDs of every policy that passes the Top Spenders eligibility check (isEligibleForTopSpendersSuggestion) and returns them as topSpendersPolicyIDs. The per-policy loop was converted from Array.some(...) (which short-circuited once all suggestion flags were true) to a full for…of iteration so that later eligible policies are always visited and the ID list is complete.
  • getSuggestedSearches accepts a new topSpendersPolicyIDs: string[] argument and, when it is non-empty, adds policyID: topSpendersPolicyIDs to the Top Spenders query via buildQueryStringFromFilterFormValues (which serializes it to policyID:id1,id2). When the list is empty the filter is omitted, so we never emit a query that silently matches nothing.
  • createTypeMenuSections threads the collected topSpendersPolicyIDs from the visibility helper into getSuggestedSearches.

Note: adding policyID to the query changes the resulting hash/recentSearchHash, which is expected — the suggested-search identity now includes the scoped workspaces.

Added unit tests covering: eligible policy IDs are collected and scoped into the query, ineligible (personal) workspaces are excluded, and no policyID filter is emitted when there are no eligible workspaces.

Fixed Issues

$ #90294
PROPOSAL: #90294 (comment)

Tests

  1. Create a manual expense with a date from last month and submit it to any individual chat.
  2. Navigate to "Spend" > "Top Spenders".
  3. Verify that the just-created expense is not listed for the user.
  • Verify that no errors appear in the JS console

Offline tests

N/A

QA Steps

  1. Create a manual expense with a date from last month and submit it to any individual chat.
  2. Navigate to "Spend" > "Top Spenders".
  3. Verify that the just-created expense is not listed for the user.
  • Verify that no errors appear in the JS console

PR Author Checklist

  • I linked the correct issue in the ### Fixed Issues section above
  • I wrote clear testing steps that cover the changes made in this PR
    • I added steps for local testing in the Tests section
    • I added steps for the expected offline behavior in the Offline steps section
    • I added steps for Staging and/or Production testing in the QA steps section
    • I added steps to cover failure scenarios (i.e. verify an input displays the correct error message if the entered data is not correct)
    • I turned off my network connection and tested it while offline to ensure it matches the expected behavior (i.e. verify the default avatar icon is displayed if app is offline)
    • I tested this PR with a High Traffic account against the staging or production API to ensure there are no regressions (e.g. long loading states that impact usability).
  • I included screenshots or videos for tests on all platforms
  • I ran the tests on all platforms & verified they passed on:
    • Android: Native
    • Android: mWeb Chrome
    • iOS: Native
    • iOS: mWeb Safari
    • MacOS: Chrome / Safari
  • I verified there are no console errors (if there's a console error not related to the PR, report it or open an issue for it to be fixed)
  • I followed proper code patterns (see Reviewing the code)
    • I verified that any callback methods that were added or modified are named for what the method does and never what callback they handle (i.e. toggleReport and not onIconClick)
    • I verified that comments were added to code that is not self explanatory
    • I verified that any new or modified comments were clear, correct English, and explained "why" the code was doing something instead of only explaining "what" the code was doing.
    • I verified any copy / text that was added to the app is grammatically correct in English. It adheres to proper capitalization guidelines (note: only the first word of header/labels should be capitalized), and is either coming verbatim from figma or has been approved by marketing (in order to get marketing approval, ask the Bug Zero team member to add the Waiting for copy label to the issue)
  • If a new code pattern is added I verified it was agreed to be used by multiple Expensify engineers
  • I followed the guidelines as stated in the Review Guidelines
  • I tested other components that can be impacted by my changes (i.e. if the PR modifies a shared library or component like Avatar, I verified the components using Avatar are working as expected)
  • If any new file was added I verified that:
    • The file has a description of what it does and/or why is needed at the top of the file if the code is not self explanatory
  • If a new CSS style is added I verified that:
    • A similar style doesn't already exist
    • The style can't be created with an existing StyleUtils function (i.e. StyleUtils.getBackgroundAndBorderStyle(theme.componentBG))
  • If new assets were added or existing ones were modified, I verified that:
    • The assets are optimized and compressed (for SVG files, run npm run compress-svg)
    • The assets load correctly across all supported platforms.
  • If the PR modifies code that runs when editing or sending messages, I tested and verified there is no unexpected behavior for all supported markdown - URLs, single line code, code blocks, quotes, headings, bold, strikethrough, and italic.
  • If the PR modifies a generic component, I tested and verified that those changes do not break usages of that component in the rest of the App (i.e. if a shared library or component like Avatar is modified, I verified that Avatar is working as expected in all cases)
  • If the PR modifies a component related to any of the existing Storybook stories, I tested and verified all stories for that component are still working as expected.
  • If the PR modifies a component or page that can be accessed by a direct deeplink, I verified that the code functions as expected when the deeplink is used - from a logged in and logged out account.
  • If the PR modifies the UI (e.g. new buttons, new UI components, changing the padding/spacing/sizing, moving components, etc) or modifies the form input styles:
    • I verified that all the inputs inside a form are aligned with each other.
    • I added Design label and/or tagged @Expensify/design so the design team can review the changes.
  • I added unit tests for any new feature or bug fix in this PR to help automatically prevent regressions in this user flow.
  • If the main branch was merged into this PR after a review, I tested again and verified the outcome was still expected according to the Test steps.

Screenshots/Videos

Android: Native
Android: mWeb Chrome
iOS: Native
iOS: mWeb Safari
MacOS: Chrome / Safari

MelvinBot and others added 5 commits July 8, 2026 13:25
Co-authored-by: abdulrahuman5196 <abdulrahuman5196@users.noreply.github.com>
Co-authored-by: abdulrahuman5196 <abdulrahuman5196@users.noreply.github.com>
Co-authored-by: abdulrahuman5196 <abdulrahuman5196@users.noreply.github.com>
Co-authored-by: abdulrahuman5196 <abdulrahuman5196@users.noreply.github.com>
Co-authored-by: abdulrahuman5196 <abdulrahuman5196@users.noreply.github.com>
@MelvinBot
MelvinBot requested a review from a team July 8, 2026 13:34
@MelvinBot

Copy link
Copy Markdown
Contributor Author

🤖 I created this PR from a branch on the upstream repo (Expensify/App) because I couldn't find a fork of App under your account to push to.

If you'd like to take ownership of this branch and push updates from your own fork, run:

git remote add upstream https://github.com/Expensify/App.git
git fetch upstream claude-topSpendersPolicyScope
git checkout -b claude-topSpendersPolicyScope upstream/claude-topSpendersPolicyScope
git push -u origin claude-topSpendersPolicyScope

Then you can close this PR and open a new one from your fork. Otherwise, feel free to push to this upstream branch directly if you have access.

@MelvinBot

Copy link
Copy Markdown
Contributor Author

⚠️ MelvinBot CI Fix Loop Detected

MelvinBot has made 5 consecutive commits trying to fix CI failures. Automatic CI fix dispatches are now paused for this PR.

Next steps: A human should review the recent commits and resolve the conflicting CI errors manually.

@codecov

codecov Bot commented Jul 8, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Looks like you've decreased code coverage for some files. Please write tests to increase, or at least maintain, the existing level of code coverage. See our documentation here for how to interpret this table.

Files with missing lines Coverage Δ
src/components/Search/SearchQueryProvider.tsx 100.00% <100.00%> (ø)
src/libs/SearchUIUtils.ts 63.15% <88.88%> (-0.06%) ⬇️
... and 9 files with indirect coverage changes

@abdulrahuman5196

Copy link
Copy Markdown
Contributor

@MelvinBot Can you merge from main and publish this PR?

MelvinBot and others added 2 commits July 15, 2026 08:05
…icyScope

Co-authored-by: abdulrahuman5196 <abdulrahuman5196@users.noreply.github.com>
…_POLICY/PERSONAL_POLICY)

Co-authored-by: abdulrahuman5196 <abdulrahuman5196@users.noreply.github.com>
@MelvinBot
MelvinBot marked this pull request as ready for review July 15, 2026 08:07
@MelvinBot
MelvinBot requested a review from a team as a code owner July 15, 2026 08:07
@melvin-bot
melvin-bot Bot requested review from abdulrahuman5196 and heyjennahay and removed request for a team July 15, 2026 08:07
@melvin-bot

melvin-bot Bot commented Jul 15, 2026

Copy link
Copy Markdown

@abdulrahuman5196 Please copy/paste the Reviewer Checklist from here into a new comment on this PR and complete it. If you have the K2 extension, you can simply click: [this button]

@melvin-bot
melvin-bot Bot removed the request for review from a team July 15, 2026 08:07
@MelvinBot

Copy link
Copy Markdown
Contributor Author

🤖 Done — merged main and published this PR (marked ready for review).

What I did:

  • Merged the latest main into claude-topSpendersPolicyScope (merge commit 5d99ad1). No conflicts.
  • Fixed a real failing check while I was here: spellcheck was failing on two test identifiers (GROUPWS01, PERSONALWS02). Renamed them to GROUP_POLICY_01 / PERSONAL_POLICY_02 so cspell splits them into dictionary words. Assertions reference the same variables, so test behavior is unchanged.
  • Pushed both to the branch and marked the PR ready for review.

A couple of notes:

  • The remaining PR Author Checklist / checklist failure is expected — the Tests, Offline tests, and QA Steps sections still have // TODO placeholders that a human co-author needs to fill in.
  • I couldn't run the local test/lint suite in this environment (npx/gh pr ready are blocked here) and couldn't verify anything in a browser. The spellcheck fix is a rename of test-only string constants, and CI will re-run all checks on the new commit, so watch the checks to confirm they're green.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: b7a330a13a

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread src/libs/SearchUIUtils.ts Resolved
@abdulrahuman5196

Copy link
Copy Markdown
Contributor

@MelvinBot For Tests,

Create a manual expense with date from last month and submit it to any individual chat.
Navigate to "Spend" > "Top Spenders"
Note that the just created expense is not listed for the user.

Mark QA tests as same as Tests and Offline tests as not applicable.

Also check all the author's checklist.

@MelvinBot

Copy link
Copy Markdown
Contributor Author

🤖 Updated the PR description:

  • Tests — added your steps (create a last-month manual expense → submit to an individual chat → Spend > Top Spenders → confirm it's not listed).
  • QA Steps — set to the same steps.
  • Offline tests — marked N/A.

On the author checklist: I checked the items that are truthfully satisfied by this PR — issue linked, testing/QA steps written, code-pattern/guideline items, and unit tests added. I intentionally left the following unchecked because they assert manual work that hasn't been done and that I can't verify (there are also no screenshots in the PR yet), so please complete and tick these yourself:

  • I included screenshots or videos for tests on all platforms
  • I ran the tests on all platforms (Android Native/mWeb, iOS Native/mWeb, MacOS Chrome/Safari)
  • I verified there are no console errors
  • I added steps to cover failure scenarios / offline network test / High Traffic account test
  • The offline-steps sub-item (left unchecked since offline behavior is N/A here)

Ticking those on your behalf would be claiming verification that didn't happen, which would defeat the checklist's purpose — I'd rather flag them than assert them falsely. Once you've done the manual platform testing and added the screenshots, check the remaining boxes so the PR Author Checklist CI turns green.

@abdulrahuman5196

Copy link
Copy Markdown
Contributor

@MelvinBot Can you analyse and address this concern - #95593 (comment) ? Seems valid, make the required changes if valid?

@MelvinBot
MelvinBot requested a review from a team as a code owner July 15, 2026 11:46
@melvin-bot
melvin-bot Bot requested a review from MonilBhavsar July 15, 2026 11:46
@MonilBhavsar

Copy link
Copy Markdown
Contributor

@heyjennahay this is ready for your look

Comment thread src/libs/SearchUIUtils.ts Resolved
Comment thread src/libs/SearchUIUtils.ts Resolved
heyjennahay
heyjennahay previously approved these changes Jul 16, 2026

@heyjennahay heyjennahay left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Product change LGTM

@abdulrahuman5196

Copy link
Copy Markdown
Contributor

@MelvinBot Can you fix the merge conflicts and make the exact change alone as suggested here #95593 (comment) and here #95593 (comment)

MelvinBot and others added 2 commits July 20, 2026 07:52
Co-authored-by: abdulrahuman5196 <abdulrahuman5196@users.noreply.github.com>
…icyScope

Co-authored-by: abdulrahuman5196 <abdulrahuman5196@users.noreply.github.com>

# Conflicts:
#	src/libs/SearchUIUtils.ts
@MelvinBot

Copy link
Copy Markdown
Contributor Author

🤖 Done — pushed to claude-topSpendersPolicyScope in 3cde337.

Merge conflicts: Resolved by merging origin/main. Both conflicts were in src/libs/SearchUIUtils.ts where main added the hasReportAwaitingApproval parameter/argument to getSuggestedSearchesVisibility — I kept that alongside this PR's topSpendersPolicyIDs additions. mergeable is now MERGEABLE.

Review suggestions applied (exactly as suggested, nothing else):

  • r3596054111 — removed the two extra rationale comment lines, keeping the single scoping comment.
  • r3596061057 — reordered the guard to if (policy.id && isEligibleForTopSpendersSuggestion).

Verification: typecheck-tsgo ✅, lint-changed ✅, fmt (no changes) ✅, and tests/unit/Search/SearchUIUtilsTest.ts ✅ (393 passed).

@MonilBhavsar
MonilBhavsar merged commit 241cc85 into main Jul 20, 2026
45 checks passed
@MonilBhavsar
MonilBhavsar deleted the claude-topSpendersPolicyScope branch July 20, 2026 08:28
@github-actions

Copy link
Copy Markdown
Contributor

🚧 MonilBhavsar has triggered a test Expensify/App build. You can view the workflow run here.

@OSBotify

Copy link
Copy Markdown
Contributor

✋ This PR was not deployed to staging yet because QA is ongoing. It will be automatically deployed to staging after the next production release.

@OSBotify

Copy link
Copy Markdown
Contributor

🚀 Deployed to staging by https://github.com/MonilBhavsar in version: 9.4.41-0 🚀

platform result
🕸 web 🕸 success ✅
🤖 android 🤖 success ✅
🍎 iOS 🍎 success ✅

@MelvinBot

Copy link
Copy Markdown
Contributor Author

Help site review — no changes required

I reviewed this PR against the help site files under App/docs/articles and no changes are required.

Why: This is a backend query-scoping bug fix. It stops personal / individual-chat expenses from leaking into the Top spenders suggested search by scoping the query to the eligible workspace policyIDs. It does not change any user-facing feature, label, navigation path, or documented behavior.

The one relevant article — View-the-Top-Spenders-report.md — already describes the intended (post-fix) behavior, not the buggy behavior:

  • It frames the report as workspace/employee spending, viewable only by Workspace Admins, Approvers, and Auditors.
  • The FAQ "How is the Top Spenders report calculated?" states it "uses expenses from the previous calendar month and groups them by submitter (employee)" and "shows the top 10 people by total amount spent" — still accurate.

Nowhere does the article claim personal / individual-chat expenses are included, so the fix brings actual behavior in line with what's already documented. No draft PR was created.


@abdulrahuman5196, since no help site changes are needed there is no linked docs PR to review. If you believe the article should be updated (e.g. to explicitly note the workspace-scoping), let me know and I'll create a draft PR.

@IuliiaHerets

Copy link
Copy Markdown

QA team failed this PR on iOS with an original issue

1784608140919.4d4d43f2-160b-4ce6-b63f-5c7b2469fb56.mp4

@yuwenmemon

yuwenmemon commented Jul 22, 2026 •

Copy link
Copy Markdown
Contributor

The original issue is under review, so I'm going to let this keep going forward.

@OSBotify

Copy link
Copy Markdown
Contributor

🚀 Deployed to production by https://github.com/yuwenmemon in version: 9.4.41-4 🚀

platform result
🕸 web 🕸 success ✅
🤖 android 🤖 success ✅
🍎 iOS 🍎 success ✅

Bundle Size Analysis (Sentry):

@bernhardoj bernhardoj mentioned this pull request Aug 24, 2026
40 tasks done
TaduJR pushed a commit to TaduJR/App that referenced this pull request Sep 8, 2026
…pendersPolicyScope"

This reverts commit 241cc85, reversing
changes made to be5e677.

Top Spenders is one of several workspace insights that can leak
individual-chat expenses, and the client-side workspace filter made the
UX unpredictable. The leakage will be fixed on the backend instead, by
excluding expenses on IOU reports from the suggested-search insights.
@OSBotify OSBotify mentioned this pull request Sep 9, 2026
83 tasks done
@OSBotify

OSBotify commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

🚀 Deployed to staging by https://github.com/MonilBhavsar in version: 9.4.75-0 🚀

platform result
🕸 web 🕸 success ✅
🤖 android 🤖 success ✅
🍎 iOS 🍎 success ✅

@MelvinBot

Copy link
Copy Markdown
Contributor Author

🤖 Yes — help site changes are required. Draft PR: #100741

This PR scoped Top spenders to eligible workspaces, so expenses submitted in an individual chat no longer appear. The help site never stated which expenses the report covers, so a reader could reasonably still expect personal expenses to be counted. Two articles now document the workspace scope.

What changed in the docs PR

  • docs/articles/new-expensify/insights/View-the-Top-Spenders-report.md — added a scope sentence under "What information the Top Spenders report displays", updated the "How is the Top Spenders report calculated?" FAQ, added a "Why is an expense missing from the Top Spenders report?" FAQ covering the individual-chat case from [Due for payment 2026-09-17] [$250] Spend - IOU is displayed on "Top Spenders" section. #90294, and extended internalScope.
  • docs/articles/new-expensify/insights/How-to-Use-Insights-in-Expensify.md — added the same scope to the Top Spenders summary only.
Why only Top spenders, and how labels were verified

Only the Top Spenders query gained a policyID filter. topCategories and topMerchants are still built without one, so I did not extend the scope claim to those sections of the Insights overview — that would document behavior the code doesn't have.

Scope wording matches the eligibility rule at src/libs/SearchUIUtils.ts:1214: a paid group workspace with at least two members where you're an admin, auditor, or approver — written for readers as "the workspaces where you're a Workspace Admin, Approver, or Auditor".

UI labels were verified against src/languages/en.ts: spend: 'Spend', insights: 'Insights', topSpenders: 'Top spenders'. I could not verify against a live session — the web tester was handed a browser session with no app loaded (blank page, zero snapshot nodes, no network requests) even though the dev server returned 200, so the language file was the source of truth for capitalization.

Applied docs/HELPSITE_NAMING_CONVENTIONS.md, docs/HELP_AUTHORING_GUIDELINES.md, and docs/TEMPLATE.md. Two pre-existing issues in the article were left alone as out of scope: the prose uses title case ("Top Spenders") where the UI label is "Top spenders", and the mobile navigation step says the hamburger menu is in the top-right corner while the naming conventions specify top-left.


@abdulrahuman5196, please review the linked help site PR and confirm it reflects the current behavior. Then mark the linked help site PR Ready for review


view run

@OSBotify

Copy link
Copy Markdown
Contributor

🚀 Deployed to production by https://github.com/mountiny in version: 9.4.75-3 🚀

platform result
🕸 web 🕸 success ✅
🤖 android 🤖 failure ❌
🍎 iOS 🍎 success ✅

Bundle Size Analysis (Sentry):

@OSBotify

Copy link
Copy Markdown
Contributor

🚀 Deployed to production by https://github.com/mountiny in version: 9.4.75-3 🚀

platform result
🕸 web 🕸 success ✅
🤖 android 🤖 failure ❌
🍎 iOS 🍎 success ✅

Bundle Size Analysis (Sentry):

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants