Skip to content

[Due for payment 2026-05-28] [Due for payment 2026-05-26] Expense - Missing Billable row when expense is non-reimbursable #91057

Closed

Description

@mitarachim

If you haven’t already, check out our contributing guidelines for onboarding and email contributors@expensify.com to request to join our Slack channel!


Version Number: 9.3.76-0
Reproducible in staging?: Yes
Reproducible in production?: N/A - new feature, doesn't exist in prod
If this was caught during regression testing, add the test name, ID and link from BrowserStack: #90411
Email or phone of affected tester (no customers): sdsdjoijdoisnjodis@gmail.com
Issue reported by: Applause Internal Team
Bug source: Exploratory - Significant User Experience Deterioration
Device used: Mac 26.2 / Chrome
App Component: Money Requests

Action Performed:

Precondition:

  • Enable Rules in workspace settings.
  • Set Billable default to Billable in Rules settings.
  1. Go to staging.new.expensify.com
  2. Go to workspace chat.
  3. Create a non-reimbursable, billable expense.
  4. Open the report.

Expected Result:

Billable row will be present in the expense report.

Actual Result:

Billable row is not present in the expense report when expense is not reimbursable. It is present only when the expense is reimbursable.

Workaround:

Unknown

Platforms:

  • Android: App
  • Android: mWeb Chrome
  • iOS: App
  • iOS: mWeb Safari
  • iOS: mWeb Chrome
  • Windows: Chrome
  • MacOS: Chrome / Safari

Screenshots/Videos

Bug7157864_1779185147390.2.mp4

View all open jobs on GitHub

Issue OwnerCurrent Issue Owner: @hoangzinh

Activity

  1. added
    DeployBlockerCashThis issue or pull request should block deployment
    BugSomething is broken. Auto assigns a BugZero manager.
    on May 19, 2026
  2. melvin-bot commented on May 19, 2026

    @melvin-bot

    You have been assigned to this deploy blocker because you recently merged this PR: #90411

  3. melvin-bot commented on May 19, 2026

    @melvin-bot

    💬 A slack conversation has been started in #expensify-open-source

  4. github-actions commented on May 19, 2026

    @github-actions
    Contributor

    👋 Friendly reminder that deploy blockers are time-sensitive ⏱ issues! Check out the open `StagingDeployCash` deploy checklist to see the list of PRs included in this release, then work quickly to do one of the following:

    1. Identify the pull request that introduced this issue and revert it.
    2. Find someone who can quickly fix the issue.
    3. Fix the issue yourself.
  5. OSBotify commented on May 19, 2026

    @OSBotify
    Contributor

    Investigation Summary

    Classification: Frontend bug
    Causing PR: #90411 - "Hide redundant Reimbursable rows; show '· Non-reimbursable' on Amount" by @mukhrr (High confidence)
    Related Issues: #89548 (the issue that PR #90411 was fixing)

    Recommendation: REVERT

    PR #90411 introduced a logic regression that hides the Billable breakdown row when an expense is simultaneously non-reimbursable and billable. Reverting this PR will restore the correct behavior immediately.

    Assigned: @mukhrr (PR author), @hoangzinh (approving reviewer), @rlinoz (approving reviewer)
    Labels: DeployBlockerCash kept (App PR is the cause). No label changes made.

    Detailed Analysis

    Evidence

    Verification

    The affected file is src/components/ReportActionItem/MoneyReportView.tsx.

    PR #90411 modified this file (confirmed via gh pr view 90411 --json files).

    The change introduced in MoneyReportView.tsx:

    const isSingleNonReimbursableExpense =
      isSingleTransactionReport(report, transactions) &&
      transactions.at(0)?.reimbursable === false;
    const shouldShowBreakdown =
      !isSingleNonReimbursableExpense &&
      (!!nonReimbursableSpend || !!billableTotal || (!!taxTotal && isTaxEnabled));

    Before the PR, shouldShowBreakdown was:

    const shouldShowBreakdown =
      nonReimbursableSpend || !!billableTotal || (!!taxTotal && isTaxEnabled);

    Root Cause

    The !isSingleNonReimbursableExpense guard short-circuits the entire shouldShowBreakdown expression to false when the report has exactly one non-reimbursable transaction — even when billableTotal is non-zero (i.e., the expense is also marked as billable).

    The original intent of the PR was to avoid showing redundant "Out of Pocket" and "Company Spend" breakdown rows when a report contains only a single non-reimbursable expense (since the total row already conveys that information). However, the guard was applied too broadly: it also suppresses the Billable row, which provides distinct and non-redundant information.

    The fix should scope the isSingleNonReimbursableExpense guard to only suppress the non-reimbursable/reimbursable split rows, not the Billable row. However, since reverting is simpler and safer, that is the recommended action.

  6. MelvinBot commented on May 19, 2026

    @MelvinBot
    Contributor

    Proposal

    What is the root cause of that problem?

    PR #90411 introduced isSingleNonReimbursableExpense at MoneyReportView.tsx:109-110 and used it to gate the entire shouldShowBreakdown:

    const shouldShowBreakdown = !isSingleNonReimbursableExpense && (!!nonReimbursableSpend || !!billableTotal || (!!taxTotal && isTaxEnabled));

    When the expense is a single non-reimbursable transaction, shouldShowBreakdown is forced to false regardless of whether a billable amount exists. This hides the entire breakdown block (lines 261-294) — including the Billable and Tax rows, which should still be visible.

    The intent was to suppress only the redundant "Out of pocket" / "Company spend" rows, but the condition is too broad.

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

    Move the isSingleNonReimbursableExpense guard so it only suppresses the out-of-pocket/company-spend rows, not billable or tax.

    1. At MoneyReportView.tsx:110, change shouldShowBreakdown to:

      const shouldShowBreakdown = (!isSingleNonReimbursableExpense && !!nonReimbursableSpend) || !!billableTotal || (!!taxTotal && isTaxEnabled);
      
    2. At the breakdown items array (lines 264-265), add the guard to the individual show conditions for the two reimbursable-related rows:

      {label: 'cardTransactions.outOfPocket', ..., show: !isSingleNonReimbursableExpense && !!nonReimbursableSpend},
      {label: 'cardTransactions.companySpend', ..., show: !isSingleNonReimbursableExpense && !!nonReimbursableSpend},
      

    This preserves the PR #90411 intent (hide redundant reimbursable breakdown for single non-reimbursable expenses) while keeping billable and tax rows visible.

    Related issues

    Next Steps for Contributor+ team: Reply with @MelvinBot implement this to create a draft PR, @MelvinBot <your feedback> to refine this analysis, or explain why you are rejecting Melvin's proposal.

  7. hoangzinh commented on May 19, 2026

    @hoangzinh
    Contributor

    @mukhrr, are you available to pick up this DB?

  8. 5 remaining items

  9. m-natarajan commented on May 19, 2026

    @m-natarajan

    Not repro, Xiaomi Redmi Note 10 / Android 12, Chrome / v9.3.77-3 (Waiting for validation in iOS)

    bandicam.2026-05-19.23-38-20-165.mp4
    Screenrecorder-2026-05-19-23-35-00-731.mp4
  10. added and removed
    DeployBlockerCashThis issue or pull request should block deployment
    on May 19, 2026
  11. changed the title [-]Expense - Missing Billable row when expense is non-reimbursable[/-] [+][Due for payment 2026-05-26] Expense - Missing Billable row when expense is non-reimbursable[/+] on May 19, 2026
  12. melvin-bot commented on May 19, 2026

    @melvin-bot

    Reviewing label has been removed, please complete the "BugZero Checklist".

  13. melvin-bot commented on May 19, 2026

    @melvin-bot

    The solution for this issue has been 🚀 deployed to production 🚀 in version 9.3.77-3 and is now subject to a 7-day regression period 📆. Here is the list of pull requests that resolve this issue:

    If no regressions arise, payment will be issued on 2026-05-26. 🎊

    For reference, here are some details about the assignees on this issue:

    • @hoangzinh requires payment through NewDot Manual Requests
  14. melvin-bot commented on May 19, 2026

    @melvin-bot

    @hoangzinh The PR fixing this issue has been merged! The following checklist (instructions) will need to be completed before the issue can be closed. Please copy/paste the BugZero Checklist from here into a new comment on this GH and complete it. If you have the K2 extension, you can simply click: [this button]

  15. hoangzinh commented on May 20, 2026

    @hoangzinh
    Contributor

    We can close this issue. No payment required

  16. melvin-bot commented on May 21, 2026

    @melvin-bot

    The solution for this issue has been 🚀 deployed to production 🚀 in version 9.3.78-1 and is now subject to a 7-day regression period 📆. Here is the list of pull requests that resolve this issue:

    If no regressions arise, payment will be issued on 2026-05-28. 🎊

    For reference, here are some details about the assignees on this issue:

    • @hoangzinh requires payment through NewDot Manual Requests
  17. changed the title [-][Due for payment 2026-05-26] Expense - Missing Billable row when expense is non-reimbursable[/-] [+][Due for payment 2026-05-28] [Due for payment 2026-05-26] Expense - Missing Billable row when expense is non-reimbursable[/+] on May 21, 2026
  18. melvin-bot commented on May 21, 2026

    @melvin-bot

    @hoangzinh The PR fixing this issue has been merged! The following checklist (instructions) will need to be completed before the issue can be closed. Please copy/paste the BugZero Checklist from here into a new comment on this GH and complete it. If you have the K2 extension, you can simply click: [this button]

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

Metadata

Metadata

Labels

BugSomething is broken. Auto assigns a BugZero manager.DailyKSv2Engineering

Type

No type

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions