Skip to content

[Due for payment 2026-05-26] [$250] New Feature: Single Non-Reimbursable Expense Reports Show Redundant Rows Above Total #89548

Closed

Description

@m-natarajan

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.66-1
Reproducible in staging?: Y
Reproducible in production?: Y
If this was caught during regression testing, add the test name, ID and link from BrowserStack:
Email or phone of affected tester (no customers):
Logs: https://stackoverflow.com/c/expensify/questions/4856
Expensify/Expensify Issue URL:
Issue reported by: @shawnborton
Slack conversation (hyperlinked to channel name): #Expensify Product

Action Performed:

  1. Create a report with: A single expense and mark it as non-reimbursable
  2. Navigate to Spend > Reports
  3. Open the report
  4. Observe the section above the total

Expected Result:

The UI should be simplified by:
Removing redundant rows
Displaying the information inline as:
“Amount · Non-reimbursable”

Actual Result:

Two extra rows are displayed above the total (Reimbursable and Non-reimbursable)
Results in unnecessary vertical space

Workaround:

Unknown

Platforms:

Select the officially supported platforms where the issue was reproduced:

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

Screenshots/Videos

Image Image Image

View all open jobs on GitHub

Issue OwnerCurrent Issue Owner: @mallenexpensify
Upwork Automation - Do Not Edit
  • Upwork Job URL: https://www.upwork.com/jobs/~022051365707056487272
  • Upwork Job ID: 2051365707056487272
  • Last Price Increase: 2026-05-11

Activity

  1. added
    NewFeatureSomething to build that is a new item.
    BugSomething is broken. Auto assigns a BugZero manager.
    on May 4, 2026
  2. melvin-bot commented on May 4, 2026

    @melvin-bot

    Current assignee @shawnborton is eligible for the NewFeature assigner, not assigning anyone new.

  3. added
    ExternalAdded to denote the issue can be worked on by a contributor
    on May 4, 2026
  4. added
    Help WantedApply this label when an issue is open to proposals by contributors
    on May 4, 2026
  5. mukhrr commented on May 4, 2026

    @mukhrr
    Contributor

    🚨 Edited by proposal-police: This proposal was edited at 2026-05-04 18:26:51 UTC.

    Proposal

    What is the root cause of that problem?

    There are two contributing factors that produce the redundant rows shown in the issue:

    1. Both breakdown rows share one visibility flag. In MoneyReportView.tsx#L249-L253 the Reimbursable (outOfPocket) and Non-reimbursable (companySpend) rows are both gated on !!nonReimbursableSpend:

    {label: 'cardTransactions.outOfPocket',  value: formattedOutOfPocketAmount,  show: !!nonReimbursableSpend},
    {label: 'cardTransactions.companySpend', value: formattedCompanySpendAmount, show: !!nonReimbursableSpend},

    So when a single non-reimbursable expense exists, you get a redundant Reimbursable $0.00 row plus a Non-reimbursable $X row that just restates the total.

    2. The transaction's reimbursable status isn't surfaced inline. In MoneyRequestView.tsx#L453 the Amount field's description is built up from a chain of dot-separated suffixes (· Original, · Canceled, · Approved, · Converted, etc.) at L545-L561, but there's no branch that adds · Non-reimbursable, so the only way to see a transaction's classification is via the breakdown rows that we're removing.

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

    1. In MoneyReportView.tsx, decouple the row visibility conditions so each row only renders when there's a genuine reimbursable / non-reimbursable split:

    -                                    {label: 'cardTransactions.outOfPocket', value: formattedOutOfPocketAmount, show: !!nonReimbursableSpend},
    -                                    {label: 'cardTransactions.companySpend', value: formattedCompanySpendAmount, show: !!nonReimbursableSpend},
    +                                    {label: 'cardTransactions.outOfPocket',  value: formattedOutOfPocketAmount,  show: !!reimbursableSpend && !!nonReimbursableSpend},
    +                                    {label: 'cardTransactions.companySpend', value: formattedCompanySpendAmount, show: !!reimbursableSpend && !!nonReimbursableSpend},

    And update shouldShowBreakdown at L99 to use the same gate so the wrapper isn't rendered for the all-non-reimbursable case:

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

    2. In MoneyRequestView.tsx, append · Non-reimbursable to the Amount field description alongside the existing dot-separated suffixes (matching the design Amount · Non-reimbursable from the issue):

         if (shouldShowConvertedAmount) {
             amountDescription += ` ${CONST.DOT_SEPARATOR} ${translate('common.converted')} ${convertToDisplayString(transactionConvertedAmount, moneyRequestReport?.currency)}`;
         }
    +    const isCurrentTransactionReimbursable = updatedTransaction?.reimbursable ?? !!transactionReimbursable;
    +    if (!isCurrentTransactionReimbursable) {
    +        amountDescription += ` ${CONST.DOT_SEPARATOR} ${Str.UCFirst(translate('iou.nonReimbursable'))}`;
    +    }

    Str is already imported and the iou.nonReimbursable translation key already exists (en.ts#L1603), so no new translations are required.

    Together, this collapses the three rows into one inline label for a single non-reimbursable expense, while mixed reports keep their existing breakdown.

    What alternative solutions did you explore? (Optional)

    • Gate purely on transaction count (e.g., transactions.length === 1). Rejected because the redundancy isn't strictly about "one expense" — a 5-expense report that's entirely non-reimbursable hits the same Reimbursable $0 problem, and the spend-split gate fixes both with one rule.
    • Hide only the Reimbursable $0 row and keep the Non-reimbursable row. Cleaner than today, but the Non-reimbursable row still restates the total amount on a second line — putting the classification on the per-transaction Amount field is closer to the design in the issue and saves the row entirely.
    • Append · Non-reimbursable to the report Total label instead. I tried this first, but the issue's screenshot shows the Amount field (which is rendered by MoneyRequestView, not MoneyReportView), so the inline label belongs there.

    Result:

    Image
  6. melvin-bot commented on May 4, 2026

    @melvin-bot

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

  7. changed the title [-]New Feature: Single Non-Reimbursable Expense Reports Show Redundant Rows Above Total[/-] [+][$250] New Feature: Single Non-Reimbursable Expense Reports Show Redundant Rows Above Total[/+] on May 4, 2026
  8. melvin-bot commented on May 4, 2026

    @melvin-bot
  9. MelvinBot commented on May 4, 2026

    @MelvinBot
    Contributor

    Proposal

    What is the root cause of that problem?

    In MoneyReportView.tsx:252-253, both the "Reimbursable" and "Non-reimbursable" breakdown rows use the same show condition: !!nonReimbursableSpend. This means whenever any non-reimbursable expense exists, both rows appear — even when reimbursableSpend is 0 and there's nothing meaningful to break down.

    The shouldShowBreakdown gate (nonReimbursableSpend || !!billableTotal || (!!taxTotal && isTaxEnabled)) triggers the breakdown section, but there's no further logic to suppress individual rows when only one expense type exists.

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

    In MoneyReportView.tsx, when the report contains only one type of expense (all reimbursable or all non-reimbursable), skip the breakdown rows entirely and instead append the type label (e.g., "Non-reimbursable") inline next to the total amount on the existing total row.

    Specifically:

    1. Add a condition: if nonReimbursableSpend > 0 && reimbursableSpend === 0 (or vice versa), set a flag like shouldShowInlineLabel and skip rendering the "outOfPocket"/"companySpend" pair in the breakdown array.
    2. On the total row (around line 212-247), when shouldShowInlineLabel is true, render the total as "$Amount · Non-reimbursable" (matching the design shown in the issue screenshots).
    3. Keep the existing two-row breakdown for reports that have both reimbursable and non-reimbursable expenses, since the breakdown is useful there.

    What alternative solutions did you explore? (Optional)

    • Simply hiding the $0.00 row (e.g., only showing "Non-reimbursable" and hiding "Reimbursable: $0.00") — this reduces clutter but still uses a separate row rather than the inline display requested.
    • Moving the label into the total row's subtitle instead of appending it inline — viable, but the issue screenshots explicitly show the inline "Amount · Non-reimbursable" format.

    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.

  10. David-2002065 commented on May 4, 2026

    @David-2002065
    Contributor

    🚫 Duplicated proposal withdrawn by 🤖 ProposalPolice.

  11. 45 remaining items

  12. melvin-bot commented on May 25, 2026

    @melvin-bot

    Triggered auto assignment to @mallenexpensify (Awaiting Payment)

  13. melvin-bot commented on May 26, 2026

    @melvin-bot

    Payment Summary

    Upwork Job

    • Reviewer: @hoangzinh owed $250 via NewDot
    • ROLE: @mukhrr paid $(AMOUNT) via Upwork (LINK)

    BugZero Checklist (@mallenexpensify)

    • I have verified the correct assignees and roles are listed above and updated the necessary manual offers
    • I have verified that there are no duplicate or incorrect contracts on Upwork for this job (https://www.upwork.com/ab/applicants/2051365707056487272/hired)
    • I have verified the PR was not reverted
    • I have applied any discounts due to bugs/regressions introduced by this PR
    • I have paid out the Upwork contracts or cancelled the ones that are incorrect
    • I have verified the payment summary above is correct
  14. mallenexpensify commented on May 28, 2026

    @mallenexpensify
    Contributor

    Payment Summary

    Contributor: @mukhrr due $75 via NewDot
    Contributor+: @hoangzinh due $75 via NewDot

    ^ Test case created. Thx

  15. laurenreidexpensify commented on Jun 1, 2026

    @laurenreidexpensify
    Contributor

    $75 approved for @hoangzinh

  16. flaviadefaria commented on Jun 2, 2026

    @flaviadefaria
    Contributor

    Approved: @mukhrr due $75 via NewDot

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

Metadata

Metadata

Labels

Awaiting PaymentAuto-added when associated PR is deployed to productionBugSomething is broken. Auto assigns a BugZero manager.ExternalAdded to denote the issue can be worked on by a contributorNewFeatureSomething to build that is a new item.ReviewingHas a PR in reviewWeeklyKSv2

Type

No type

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions