Properly apply commuter exclusions when merging expenses - #98427
Conversation
|
@marufsharifi 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] |
Reviewer Checklist
Screenshots/VideosAndroid: HybridAppScreen.Recording.2026-08-12.at.8.57.11.PM.movAndroid: mWeb ChromeRecording_20260812_185222.mp4iOS: HybridAppScreen.Recording.2026-08-12.at.9.51.57.PM.moviOS: mWeb SafariScreen.Recording.2026-08-12.at.9.56.09.PM.movMacOS: Chrome / SafariScreencast.From.2026-08-12.18-42-34.webm |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 16da227b36
ℹ️ 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".
| return amount; | ||
| } | ||
|
|
||
| return Math.round((amount / billedDistance) * newBilledDistance); |
There was a problem hiding this comment.
Proportional re-scaling can drift ±1¢ from a rate-based recompute.
amount / billedDistance reconstructs an implied per-unit rate from an already-rounded cents amount, then re-rounds. For rates with sub-cent precision that don't divide evenly, this can land 1¢ off from DistanceRequestUtils.getDistanceRequestAmount(reimbursableMeters, unit, rate) (the rate-based path used everywhere else for distance). Most rates match exactly (verified 0.67/mi, 0.70/mi), so this is minor — but it's only safe if the backend recomputes the merged amount from the rate. If the FE amount is authoritative on merge, please confirm the drift is acceptable; otherwise compute from the rate for an exact result.
The newBilledDistance === undefined guard (rather than !newBilledDistance) is a nice touch — it correctly lets a 0 reimbursable distance drive the amount to 0 on a full exclusion. 👍
There was a problem hiding this comment.
I think this is fine? Maybe I'm misunderstanding
|
@MelvinBot Review |
|
🤖 Reviewed the commuter-exclusion merge logic. The core fix (thread the destination workspace through 1. Auto-merge (no-conflict) path strips the exclusion and can wipe
|
Let's try to avoid heavily agent-based reviews for the last human-based reviews. Feel free to use agents, but let's make sure the review is actually written by the reviewer. This leaves the owner to analyze and determine whether the review makes sense, which defeats the purpose of a reviewer |
|
Ready for another round |
|
Thanks, i am checking again. |
|
Bug: merging two distance expenses loses the trip distance and rate What happens: When two identical map-distance expenses on the same report are merged (and the merge completes automatically with no conflicts to resolve), the merged expense loses its distance and rate. RF-1.mp4 |
|
Bug: manual distance expense gets a commuter deduction it shouldn't when merged What happens: When a manually-entered (or odometer) distance expense is merged onto a workspace that has a commuter exclusion, the merged expense gets a commuter deduction applied. A manual distance expense created fresh on that same workspace would NOT get this deduction — the deduction is only meant for map-based distance. So merging produces a different result than creating the expense normally. RF-2.mov |
|
@Gonals, could you please check the above comments, thanks. |
|
@Gonals, Gentle bump. thanks. |
Been ooo for a long week. Cleaning this up and getting it ready for review |
|
@marufsharifi, ready for another look |
Explanation of Change
Fixed Issues
$ #98343
PROPOSAL:
Tests
In an account with the beta and in 2 workspaces:
Enable distance rates in both workspaces
Enable commuter deductions and set the deduction to 1 mile in one of the (workspace A)
Create a map distance expense in each of those workspaces. Make sure they have different mileage.
Open Expense A and click merge. Select Expense B for the merge.
Confirm that:
If Expense A Merchant and Expense A report are selected, the exclusion is applied.
If Expense A Merchant and Expense B report are selected, the exclusion is NOT applied.
If Expense B Merchant and Expense A report are selected, the exclusion is applied.
If Expense B Merchant and Expense B report are selected, the exclusion is NOT applied.
Verify that no errors appear in the JS console
Offline tests
Same
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
Android: mWeb Chrome
iOS: Native
iOS: mWeb Safari
MacOS: Chrome / Safari