feat: Add Attendees to Edit multiple in expenses - #97108
Conversation
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: fefa84706e
ℹ️ 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".
| writeBulkEditMoneyRequestAttendees({ | ||
| transactionID, | ||
| reportID: iouReport?.reportID, | ||
| attendees: serializedAttendees, | ||
| }); |
There was a problem hiding this comment.
Give the attendee request its own rollback data
When a bulk edit changes attendees together with another field, all optimistic, success, and failure data is attached only to the generic request, while this independently failing attendee request receives none. If the generic request succeeds first, it clears the attendee pending state before this request finishes; if this request then fails, the optimistic attendees remain displayed without an error or retry indication even though the backend did not save them. Conversely, a generic failure can roll back attendees that this request subsequently saves. Split the Onyx data by command so each request owns only its fields and rollback state.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Yes, We don’t need to send reportActionID for a locally-only thread, since UpdateMoneyRequestAttendees doesn’t create threads.
There was a problem hiding this comment.
@samranahm not sure I'm following here, the comment is about splitting onyxData per command and I think we should address this, each write should have its own rollback state.
There was a problem hiding this comment.
My bad, my earlier reply was about the reportActionID line and missed the actual point.
Addressed now, pendingFields/errorFields are split per command and UpdateMoneyRequest payloads no longer carry or revert attendee fields, and UpdateMoneyRequestAttendees has its own optimistic value, success clear and failure revert (with an error so it can be retried). The attendees-only path is unchanged since it still carries the shared report/thread updates.
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.
|
There was a problem hiding this comment.
Pull request overview
Adds bulk-edit support for Attendees when using Spend > Reports > select multiple expenses > Edit multiple, including navigation/route wiring and persistence via a dedicated API command.
Changes:
- Add “Attendees” as an editable field in the Search “Edit multiple” flow, including a new RHP page for selecting attendees.
- Update bulk-edit persistence to write attendees via
UpdateMoneyRequestAttendees, including optimistic transaction updates and recent-attendee tracking. - Add/extend unit tests to cover attendees-only updates and mixed (generic + attendees) updates.
Reviewed changes
Copilot reviewed 12 out of 12 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/actions/IOUTest/BulkEditTest.ts | Adds tests validating attendees persistence command selection and optimistic updates. |
| src/SCREENS.ts | Introduces a new Search bulk-edit attendees RHP screen constant. |
| src/ROUTES.ts | Adds the route for the Search bulk-edit attendees RHP page. |
| src/pages/Search/SearchEditMultiple/SearchEditMultipleUtils.ts | Adds selection-level gating to determine when attendees bulk edit is enabled. |
| src/pages/Search/SearchEditMultiple/SearchEditMultiplePage.tsx | Surfaces the Attendees field in the bulk-edit field list and includes it in save payload. |
| src/pages/Search/SearchEditMultiple/SearchEditMultipleAttendeesPage.tsx | New RHP page for choosing attendees and writing to the bulk-edit draft transaction. |
| src/pages/iou/request/MoneyRequestAttendeeSelector.tsx | Adjusts error-message behavior to avoid showing it during loading/transition. |
| src/libs/ReportUtils.ts | Allows bulk-editing the ATTENDEES edit-request field. |
| src/libs/Navigation/linkingConfig/config.ts | Wires deep linking config for the new attendees RHP screen/route. |
| src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx | Registers the attendees RHP page in the Search modal stack navigator. |
| src/libs/actions/IOU/BulkEdit.ts | Implements attendees bulk-edit persistence (including optimistic updates and API command splitting). |
| src/CONST/index.ts | Adds ATTENDEES to EDIT_REQUEST_FIELD constants. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
joekaufmanexpensify
left a comment
There was a problem hiding this comment.
Good for product.
|
Bug: One attendee selected shown from bulk edit when both transactions have two same attendees I think the expected behavior should show no attendee selected, just like other field selectors. So bulk edit has consistent behavior for all fields - there's no default values and merged values until selecting some. @joekaufmanexpensify do you agree? Screen.Recording.2026-07-28.at.4.34.31.PM.mov |
|
Yep, I think that works. One note: an expense must always have one attendee. I assume we'll throw if the user tries to proceed without selecting at least one attendee? If so, good with me. 👍 |
yes, you're right we can't proceed if no attendee is selected. Screen.Recording.2026-07-29.at.9.38.21.PM.mov |
|
Sounds good. This is good with me then. 👍 |
|
@samranahm gentle bump on #97108 (comment) and #97108 (comment) |
|
Ahh, missed this one. Looking into it. |
Agreed. We'll show the current user as the default attendee only for expenses that haven't been updated yet. Once an expense or all selected expenses has been updated, no attendee will be selected by default unless all the selected expenses have the same one attendee, and the user won't be able to save without selecting at least one attendee. |
|
@eh2077 All yours, please take a look. |
|
Test steps updated. |
Reviewer Checklist
Screenshots/VideosAndroid: HybridAppScreen.Recording.2026-08-05.at.11.42.09.PM.movAndroid: mWeb ChromeScreen.Recording.2026-08-05.at.11.39.38.PM.moviOS: HybridAppScreen.Recording.2026-08-05.at.11.20.34.PM.moviOS: mWeb SafariScreen.Recording.2026-08-05.at.11.15.45.PM.movMacOS: Chrome / SafariScreen.Recording.2026-08-05.at.11.09.43.PM.mov |
|
Resolving merge conflicts. |
|
review & test ongoing, aim to sort it out by tmr |
|
@youssef-lr Gentle bump. |
|
Sorry guys I wasn't feeling well last week. Will review today. |
|
@youssef-lr Gentle bump to review the PR when you get a moment please. |
|
@youssef-lr gentle bump, thx! |
|
Let's address this #97108 (comment) |
|
On it. |
…API command owns only its fields and rollback state.
|
@youssef-lr all yours! PR ready for another round of review. |
|
🚧 youssef-lr has triggered a test Expensify/App build. You can view the workflow run here. |
|
🧪🧪 Use the links below to test this adhoc build on Android, iOS, and Web. Happy testing! 🧪🧪
|
|
🚀 Deployed to staging by https://github.com/youssef-lr in version: 9.4.65-0 🚀
|
|
Yes — help site changes were required. Draft PR: #99962 This PR adds Attendees to the Edit multiple expenses panel, but the help site described bulk edit without it, and the Attendee tracking rule that gates it wasn't documented anywhere. What changed on the help site
The three behaviors I documented, drawn from the diff:
UI verificationI drove the running web app to confirm the labels rather than guessing them: Result: pass — all five checks confirmed.
Evidence (2)Edit multiple expenses page with Amount, Description, Merchant, Date, Billable, Reimbursable rows
Workspace Rules page showing the Attendee tracking toggle under ExpensesI applied One thing I couldn't do: GitHub rejected both assigning you to the docs PR and requesting you as a reviewer — @samranahm, please review the linked help site PR and confirm it reflects the current behavior. Then mark the linked help site PR |
|
🚀 Deployed to production by https://github.com/francoisl in version: 9.4.65-3 🚀
Bundle Size Analysis (Sentry): |

Explanation of Change
Fixed Issues
$ #94313
PROPOSAL: #94313 (comment)
Tests
Precondition:
Offline tests
QA Steps
Same as test
// TODO: These must be filled out, or the issue title must include "[No QA]."
PR Author Checklist
### Fixed Issuessection aboveTestssectionOffline stepssectionQA stepssectionAvatar, I verified the components usingAvatarare working as expected)StyleUtils.getBackgroundAndBorderStyle(theme.componentBG))npm run compress-svg)Avataris modified, I verified thatAvataris working as expected in all cases)Designlabel and/or tagged@Expensify/designso the design team can review the changes.mainbranch was merged into this PR after a review, I tested again and verified the outcome was still expected according to theTeststeps.Screenshots/Videos
Android: Native
Android: mWeb Chrome
Android.mWeb.Chrome.mp4
iOS: Native
IOS.Native.mp4
iOS: mWeb Safari
IOS.mWeb.Safari.mp4
MacOS: Chrome / Safari
macOS.Chrome.mp4