App icon indicating copy to clipboard operation
App copied to clipboard

[$250] Confirm details - Unit doesn't change from Km to Mile when switching workspaces after selecting non-default rate

Open lanitochka17 opened this issue 2 weeks ago • 7 comments

If you haven’t already, check out our contributing guidelines for onboarding and email [email protected] to request to join our Slack channel!


Version Number: v9.2.85-0 Reproducible in staging?: Yes Reproducible in production?: Yes If this was caught during regression testing, add the test name, ID and link from BrowserStack: Exploratory around https://test-management.browserstack.com/projects/2219752/test-runs/TR-2467/folder/13176744/41237142/1086558789 and https://test-management.browserstack.com/projects/2219752/test-runs/TR-2467/folder/13176744/41237140/1086558788 Email or phone of affected tester (no customers): [email protected] Issue reported by: Applause Internal Team Bug source: Exploratory - Significant User Experience Deterioration Device used: Windows 11/Chrome, iPhone 16/iOS 18.3.1, Pixel 8a/Android 16 App Component: Money Requests

Action Performed:

Preconditions: On User A's side

  1. Workspace created with Distance rates enabled
  2. Few additional distance rates added
  3. Changed the unit to kilometer in settings
  4. Invited User B as member to workspace

On User's B side

  1. User B has created his default workspace with distance rates enabled

Steps:

  1. [User B] - Navigate to staging.new.expensify.com
  2. [User B] - Click FAB >> Track Distance >> Map option >> Enter waypoints >> Next
  3. Observe To field has User's B default workspace with default distance rate/mile ($0.7/mile) & take note of distance & amount
  4. Switch to User's A workspace in To field
  5. Observe rate field has default rate with kilometer unit ($0.7/kilometer)
  6. Change rate to non-default one
  7. Switch to User's B default workspace in To field 8.Observe incorrect unit displayed in Rate field which changes the distance & amount values

Expected Result:

When User B switches from User's A workspace to User's B default workspace, the Rate field unit should change from kilometer to mile & reflect correct distance & amount

Actual Result:

When User B switches from User's A workspace to User's B default workspace , the Rate field unit still display kilometer & does not change to mile unit which is User's B workspace default unit.

Workaround:

Unknown

Platforms:

  • [x] Android: App
  • [ ] Android: mWeb Chrome
  • [x] iOS: App
  • [ ] iOS: mWeb Safari
  • [ ] iOS: mWeb Chrome
  • [x] Windows: Chrome
  • [ ] MacOS: Chrome / Safari

Screenshots/Videos

View all open jobs on GitHub

Upwork Automation - Do Not Edit
  • Upwork Job URL: https://www.upwork.com/jobs/~022003058270992773869
  • Upwork Job ID: 2003058270992773869
  • Last Price Increase: 2025-12-22
Issue OwnerCurrent Issue Owner: @mananjadhav

lanitochka17 avatar Dec 20 '25 16:12 lanitochka17

Triggered auto assignment to @laurenreidexpensify (Bug), see https://stackoverflow.com/c/expensify/questions/14418 for more details. Please add this bug to a GH project, as outlined in the SO.

melvin-bot[bot] avatar Dec 20 '25 16:12 melvin-bot[bot]

Job added to Upwork: https://www.upwork.com/jobs/~022003058270992773869

melvin-bot[bot] avatar Dec 22 '25 11:12 melvin-bot[bot]

Triggered auto assignment to Contributor-plus team member for initial proposal review - @mananjadhav (External)

melvin-bot[bot] avatar Dec 22 '25 11:12 melvin-bot[bot]

Proposal

Please re-state the problem that we are trying to solve in this issue.

Confirm details - Unit doesn't change from Km to Mile when switching workspaces after selecting non-default rate

What is the root cause of that problem?

This is because when we use a custom rate, we perform this function: https://github.com/Expensify/App/blob/6072cfb8aa701c282c0078bd512949b0465a9964/src/pages/iou/request/step/IOURequestStepDistanceRate.tsx#L116 Which adds distanceUnit: https://github.com/Expensify/App/blob/6072cfb8aa701c282c0078bd512949b0465a9964/src/libs/actions/IOU.ts#L1469-L1490 https://github.com/Expensify/App/blob/6072cfb8aa701c282c0078bd512949b0465a9964/src/libs/actions/IOU.ts#L1485

This means that the transaction now has this value, and when the unit is received here: https://github.com/Expensify/App/blob/6072cfb8aa701c282c0078bd512949b0465a9964/src/components/MoneyRequestConfirmationList.tsx#L326-L329

In the getRate function: https://github.com/Expensify/App/blob/6072cfb8aa701c282c0078bd512949b0465a9964/src/libs/DistanceRequestUtils.ts#L378

We always try to get the unit from transaction?.comment?.customUnit?.distanceUnit first, and since we inserted it when selecting a non-default unit, we get it: https://github.com/Expensify/App/blob/6072cfb8aa701c282c0078bd512949b0465a9964/src/libs/DistanceRequestUtils.ts#L347-L349

And we don't have any logic that would clear this field when the participant changes, we only have the logic for changing the rate: https://github.com/Expensify/App/blob/6072cfb8aa701c282c0078bd512949b0465a9964/src/pages/iou/request/step/IOURequestStepParticipants.tsx#L258-L271

What changes do you think we should make in order to solve the problem?

When changing a participant, we can determine and set the same logic that we use here: https://github.com/Expensify/App/blob/6072cfb8aa701c282c0078bd512949b0465a9964/src/libs/actions/IOU.ts#L1469-L1490

Or reset this field, which I think is more correct, since it will correspond to the logic we have now (transaction?.comment?.customUnit does not have the distanceUnit field in the normal flow). To do this, we can create a separate function:

function clearCustomDistanceUnit(transactionID: string) {
    Onyx.merge(`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${transactionID}`, {
        comment: {
            customUnit: {
                distanceUnit: null,
            },
        },
    });
}

And use it here: https://github.com/Expensify/App/blob/6072cfb8aa701c282c0078bd512949b0465a9964/src/pages/iou/request/step/IOURequestStepParticipants.tsx#L265

And we can use it here, if necessary: https://github.com/Expensify/App/blob/6072cfb8aa701c282c0078bd512949b0465a9964/src/pages/iou/request/step/IOURequestStepParticipants.tsx#L269

What alternative solutions did you explore? (Optional)

Reminder: Please use plain English, be brief and avoid jargon. Feel free to use images, charts or pseudo-code if necessary. Do not post large multi-line diffs or write walls of text. Do not create PRs unless you have been hired for this job.

Eskalifer1 avatar Dec 22 '25 22:12 Eskalifer1

Proposal

Please re-state the problem that we are trying to solve in this issue.

Confirm details - Unit doesn't change from Km to Mile when switching workspaces after selecting non-default rate

What is the root cause of that problem?

The issue originates from how the distance unit is persisted and later resolved during the distance request flow:

  1. When a user selects a non-default distance rate in a workspace,

    setMoneyRequestDistanceRate updates the draft transaction by storing: transaction.comment.customUnit.distanceUnit here:

https://github.com/Expensify/App/blob/c00b37a1589ed02d6d8ac974e02c6d296ffdf1ef/src/libs/actions/IOU.ts#L1482-L1491

This is expected behavior and ensures correct recalculation within the same workspace .

  1. The transaction is still in draft state when the user switches the To workspace. At this point, the draft transaction continues to carry the previously stored distanceUnit.

  2. In the confirmation step, MoneyRequestConfirmationList resolves the mileage rate via getRate, which internally calls getDistanceUnit: https://github.com/Expensify/App/blob/54c7eb47b7e774379769129367bc930dbdfb976f/src/libs/DistanceRequestUtils.ts#L378

  3. getDistanceUnit currently prioritizes the transaction’s stored unit:

    https://github.com/Expensify/App/blob/54c7eb47b7e774379769129367bc930dbdfb976f/src/libs/DistanceRequestUtils.ts#L347-L349

    This means the draft transaction’s unit always overrides the mileage rate’s unit, even when the mileage rate now belongs to a different workspace with a different default unit.

  4. As a result, a kilometer unit from Workspace A incorrectly overrides a mile-based rate from Workspace B.

In short, the draft transaction’s stored unit leaks across workspace boundaries and incorrectly takes precedence over the newly selected workspace’s mileage rate unit.

What changes do you think we should make in order to solve the problem?

The distance unit used for display and calculation should always be consistent with the currently selected mileage rate . While the transaction’s stored distance unit is valid within the same workspace, it should not override the unit of a mileage rate that belongs to a different workspace.

To achieve this, we should refine the distance unit resolution logic so that:

  • The transaction’s stored distance unit is treated as contextual , not authoritative
  • It is only used when it matches the unit of the active mileage rate
  • When a mismatch occurs (e.g. after switching workspaces), the mileage rate’s unit becomes the source of truth

This ensures that:

  • Units persist correctly when editing or reselecting rates within the same workspace
  • Units automatically realign when switching to a workspace with a different default unit
  • Draft transactions do not leak unit state across workspace boundaries
  • No draft mutation or reset logic is required

We update getDistanceUnit to explicitly validate whether the transaction’s stored unit is compatible with the mileage rate’s unit before using it.

function getDistanceUnit(
    transaction: OnyxEntry<Transaction>,
    mileageRate: OnyxEntry<MileageRate>
): Unit {
    const transactionUnit = transaction?.comment?.customUnit?.distanceUnit;
    const rateUnit = mileageRate?.unit;

    // Use the transaction unit only when it matches the active mileage rate
    if (transactionUnit && rateUnit && transactionUnit === rateUnit) {
        return transactionUnit;
    }

    // Otherwise, fall back to the mileage rate unit
    return rateUnit ?? CONST.CUSTOM_UNITS.DISTANCE_UNIT_MILES;
}

What alternative solutions did you explore? (Optional)

Reminder: Please use plain English, be brief and avoid jargon. Feel free to use images, charts or pseudo-code if necessary. Do not post large multi-line diffs or write walls of text. Do not create PRs unless you have been hired for this job.

marufsharifi avatar Dec 25 '25 12:12 marufsharifi

Proposal

Please re-state the problem that we are trying to solve in this issue.

Confirm details - Unit doesn't change from Km to Mile when switching workspaces after selecting non-default rate

What is the root cause of that problem?

When we change distance rate we call setMoneyRequestDistanceRate, and we set the draftTransaction's comment?.customUnit?.distanceUnit to km https://github.com/Expensify/App/blob/54c7eb47b7e774379769129367bc930dbdfb976f/src/libs/actions/IOU.ts#L1471-L1488

And when try to get the rate on MoneyRequestConfirmationList, we call getRate, and inside getRate useTransactionDistanceUnit transaction is true by default in getRate function call. https://github.com/Expensify/App/blob/54c7eb47b7e774379769129367bc930dbdfb976f/src/libs/DistanceRequestUtils.ts#L357-L361 And we always calculate unit from transaction (transaction?.comment?.customUnit?.distanceUnit). And we fallback to using mileageRate when transaction?.comment?.customUnit?.distanceUnit is undefined. https://github.com/Expensify/App/blob/54c7eb47b7e774379769129367bc930dbdfb976f/src/libs/DistanceRequestUtils.ts#L378 The logic to get the distance rate unit from transaction was introduced in this PR. The logic was introduced to avoid changing distance rate unit on MoneyRequestView when user changes unit in workspace settings by using the transaction as source of truth rather than using workspace distance rates (policy?.customUnits).

What changes do you think we should make in order to solve the problem?

We should pass false to useTransactionDistanceUnit when we call getRate in MoneyRequestConfirmationList.tsx

    const mileageRate = DistanceRequestUtils.getRate({transaction, policy, policyDraft, useTransactionDistanceUnit: false});

https://github.com/Expensify/App/blob/54c7eb47b7e774379769129367bc930dbdfb976f/src/components/MoneyRequestConfirmationList.tsx#L326

That should work fine since we get distance rate unit from the policy when creating distance request to a policy and from personal policy when we create distance request in DM.

What alternative solutions did you explore? (Optional)

Reminder: Please use plain English, be brief and avoid jargon. Feel free to use images, charts or pseudo-code if necessary. Do not post large multi-line diffs or write walls of text. Do not create PRs unless you have been hired for this job.

etCoderDysto avatar Dec 25 '25 12:12 etCoderDysto

Proposal

Please re-state the problem that we are trying to solve in this issue.

Unit doesn't change from Km to Mile when switching workspaces after selecting non-default rate

What is the root cause of that problem?

  1. Because the distanceUnit of the transaction is not set when the workspace changes, the old unit is still displayed.

  2. When we change the distance rate, the function setMoneyRequestDistanceRate is used.
    https://github.com/Expensify/App/blob/589574c1ca5caaed0c0c947de22e8e2c97981432/src/libs/actions/IOU.ts#L1471-L1492

  3. However, when changing the workspace, the function setCustomUnitRateID is used.
    https://github.com/Expensify/App/blob/589574c1ca5caaed0c0c947de22e8e2c97981432/src/libs/actions/IOU.ts#L1322-L1332 We can see that the setCustomUnitRateID function does not update the distanceUnit according to the customUnitRateID.

What changes do you think we should make in order to solve the problem?

In setCustomUnitRateID, we should also use DistanceRequestUtils.getRateByCustomUnitRateID to retrieve the distanceUnit and update it, just like in setMoneyRequestDistanceRate. https://github.com/Expensify/App/blob/589574c1ca5caaed0c0c947de22e8e2c97981432/src/libs/actions/IOU.ts#L1476

What alternative solutions did you explore? (Optional)

N/A

dmkt9 avatar Dec 25 '25 14:12 dmkt9

@mananjadhav Uh oh! This issue is overdue by 2 days. Don't forget to update your issues!

melvin-bot[bot] avatar Dec 26 '25 00:12 melvin-bot[bot]

📣 It's been a week! Do we have any satisfactory proposals yet? Do we need to adjust the bounty for this issue? 💸

melvin-bot[bot] avatar Dec 29 '25 16:12 melvin-bot[bot]

Reviewing proposals.

mananjadhav avatar Dec 31 '25 21:12 mananjadhav

@mananjadhav @laurenreidexpensify this issue was created 2 weeks ago. Are we close to approving a proposal? If not, what's blocking us from getting this issue assigned? Don't hesitate to create a thread in #expensify-open-source to align faster in real time. Thanks!

melvin-bot[bot] avatar Jan 03 '26 21:01 melvin-bot[bot]