Conversation
The in-place "To" picker on the confirmation page rewrites the transaction participants but leaves the route on the report the flow started from - the self-DM, whose policyID is the '_FAKE_' placeholder. Every step page reached from the confirmation then resolves its policy from that frozen route report, so the distance Rate list renders empty and never recovers when the workspace is switched again. Resolve the picked workspace inside usePolicyForTransaction instead, so the transaction participants - the only thing in the flow that tracks what the user selected - win over a route report that can no longer change. The five call sites that already pass this expression are unaffected; the six that pass a raw report policyID are fixed. Fixes Expensify#98323
|
@eVoloshchak 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] |
|
Looking good! |
…rate-selected-workspace
|
@eVoloshchak Merged the latest main. The failing NavigateTests.tsx cases were coming from main - the same three tests were failing on unrelated PRs too (e.g. #101017) - and all checks are green now. Ready for another look. |
Reviewer Checklist
Screenshots/VideosAndroid: HybridAppAndroid: mWeb ChromeiOS: HybridAppiOS: mWeb SafariMacOS: Chrome / Safari |
eVoloshchak
left a comment
There was a problem hiding this comment.
Bug 1
- Go to Account -> Troubleshoot -> Clear cache and restart (or perform a fresh login)
- FAB → Track distance → Manual, enter a distance → Next.
- Verify that self DM (you) is selected in
Tosection - Verify the default rate is selected
- Tap "To" and select a workspace with only one (default) rate
- Notice the "Rate not valid for this workspace" error
Screen.Recording.2026-09-17.at.22.51.39.mov
Bug 2
- Go through steps 1-7
- Tap "To" and select the self DM (you)
- Notice the Rate section is forever
Pending
Screen.Recording.2026-09-17.at.22.56.44.mov
…rate-selected-workspace
…ves to Review of Expensify#101023 surfaced two rate problems in the in-place "To" picker. Selecting a workspace flashed "Rate not valid for this workspace" for a couple of seconds before clearing itself. Picking a participant resolves the new policy before Onyx has its custom units, so the validation effect ran with no rates to compare against and reported the selected rate as invalid; it cleared once the rates arrived. Treat an empty rate list as "not loaded yet" and leave the state alone until the effect runs again. Moving the expense back to the self DM left the Rate field reading "Pending..." and the amount blank for good, with the workspace rate error still on screen. The self-DM branch never re-resolved the rate, so the expense kept one that does not exist outside the workspace it had left, and the validation effect returned early off a workspace chat without clearing its own error. Re-resolve the rate the self DM uses, and clear the error when there is no workspace left to validate against.
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.
|
|
@eVoloshchak Fixed both, thanks for the clear steps and videos. Bug 1 was a race, not a wrong rate: picking the workspace resolves its policy before Onyx has the custom units, so validation ran with no rates to compare against and flagged the selected rate — then cleared itself once the rates arrived. An empty rate list is now treated as "not loaded yet" rather than "invalid". Bug 2 had two halves. The self-DM branch of the participant switch never re-resolved the rate, so the expense kept one that doesn't exist outside the workspace it had left — hence Three unit tests in rate.mp4pending.mp4 |
|
@oqildev, TS check is failing, could you take a look please? |
The Rate type carries no unit of its own - the distance unit comes from the custom unit attributes, which already set kilometres for this mock - so tsc rejected the property and the typecheck job failed.
Explanation of Change
The in-place "To" picker on the confirmation page rewrites the transaction participants but leaves the route on the report the flow started from — the self-DM, whose
policyIDis the_FAKE_placeholder. Every step page reached from that confirmation then resolves its policy from a route report that no longer matches the expense, sogetMileageRates()runs against an undefined policy and the distance Rate list renders empty. Switching back to a workspace whose rates displayed a moment earlier does not recover it, because each selection re-reads the same frozen route report.I verified this by reading the Rate route at three points while changing the selected workspace — the
reportIDis identical every time:This resolves the picked workspace inside
usePolicyForTransactioninstead, so the transaction participants — the only thing in the flow that tracks what the user actually selected — win over a route report that can no longer change. It is the same expression five call sites already pass in, so for them it is a no-op; the call sites that pass a rawreport?.policyIDare fixed. The helper'saction === EDITguard keeps an existing expense's own report authoritative while editing, which is a live path since the Rate page is also reachable withaction=edit.Note on scope: the first row above (
iouType=track) deliberately still resolves through the moving-expenses policy. At that point the expense is still a self-DM track expense, so that behaviour is intended and unchanged.Fixed Issues
$ #98323
PROPOSAL: #98323 (comment)
Tests
Precondition: two workspaces with distance rates enabled and clearly different rates (e.g. workspace A = $5.00/mi, workspace B = UZS 0.76/mi). Workflows → Submissions is off on both.
A unit test covering this was added in
tests/unit/hooks/usePolicyForTransactionTest.tsx: the two bug cases fail onmainand pass with this change, and three guard cases (editing an existing expense, a P2P participant, and a self-DM track expense) hold in both.Offline tests
Same as tests.
QA Steps
Same as tests.
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
native.android.mp4
Android: mWeb Chrome
android.mWeb.mp4
iOS: Native
native.ios.mp4
iOS: mWeb Safari
ios.mWeb.mp4
MacOS: Chrome / Safari
web.chrome.mp4
web.safari.mp4