[Due for payment 2026-05-26] [$250] New Feature: Single Non-Reimbursable Expense Reports Show Redundant Rows Above Total #89548
Description
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:
- Create a report with: A single expense and mark it as non-reimbursable
- Navigate to Spend > Reports
- Open the report
- 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
Issue Owner
Current Issue Owner: @mallenexpensifyUpwork Automation - Do Not Edit
- Upwork Job URL: https://www.upwork.com/jobs/~022051365707056487272
- Upwork Job ID: 2051365707056487272
- Last Price Increase: 2026-05-11
Metadata
Metadata
Labels
Type
Projects
- StatusShow more project fieldsDone
Activity
melvin-bot commentedon May 4, 2026
Current assignee @shawnborton is eligible for the NewFeature assigner, not assigning anyone new.
mukhrr commentedon May 4, 2026
🚨 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-L253theReimbursable(outOfPocket) andNon-reimbursable(companySpend) rows are both gated on!!nonReimbursableSpend:So when a single non-reimbursable expense exists, you get a redundant
Reimbursable $0.00row plus aNon-reimbursable $Xrow that just restates the total.2. The transaction's reimbursable status isn't surfaced inline. In
MoneyRequestView.tsx#L453theAmountfield'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:And update
shouldShowBreakdownat L99 to use the same gate so the wrapper isn't rendered for the all-non-reimbursable case:2. In
MoneyRequestView.tsx, append· Non-reimbursableto theAmountfield description alongside the existing dot-separated suffixes (matching the designAmount · Non-reimbursablefrom 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'))}`; + }Stris already imported and theiou.nonReimbursabletranslation 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)
transactions.length === 1). Rejected because the redundancy isn't strictly about "one expense" — a 5-expense report that's entirely non-reimbursable hits the sameReimbursable $0problem, and the spend-split gate fixes both with one rule.Reimbursable $0row and keep theNon-reimbursablerow. Cleaner than today, but theNon-reimbursablerow still restates the total amount on a second line — putting the classification on the per-transactionAmountfield is closer to the design in the issue and saves the row entirely.· Non-reimbursableto the reportTotallabel instead. I tried this first, but the issue's screenshot shows theAmountfield (which is rendered byMoneyRequestView, notMoneyReportView), so the inline label belongs there.Result:
melvin-bot commentedon May 4, 2026
Triggered auto assignment to Contributor-plus team member for initial proposal review - @hoangzinh (
External)[-]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[/+]melvin-bot commentedon May 4, 2026
Job added to Upwork: https://www.upwork.com/jobs/~022051365707056487272
MelvinBot commentedon May 4, 2026
Proposal
What is the root cause of that problem?
In
MoneyReportView.tsx:252-253, both the "Reimbursable" and "Non-reimbursable" breakdown rows use the sameshowcondition:!!nonReimbursableSpend. This means whenever any non-reimbursable expense exists, both rows appear — even whenreimbursableSpendis 0 and there's nothing meaningful to break down.The
shouldShowBreakdowngate (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:
nonReimbursableSpend > 0 && reimbursableSpend === 0(or vice versa), set a flag likeshouldShowInlineLabeland skip rendering the "outOfPocket"/"companySpend" pair in the breakdown array.shouldShowInlineLabelis true, render the total as"$Amount · Non-reimbursable"(matching the design shown in the issue screenshots).What alternative solutions did you explore? (Optional)
Next Steps for Contributor+ team: Reply with
@MelvinBot implement thisto create a draft PR,@MelvinBot <your feedback>to refine this analysis, or explain why you are rejecting Melvin's proposal.David-2002065 commentedon May 4, 2026
🚫 Duplicated proposal withdrawn by 🤖 ProposalPolice.
47 remaining items
melvin-bot commentedon May 25, 2026
Triggered auto assignment to @mallenexpensify (
Awaiting Payment)melvin-bot commentedon May 26, 2026
Payment Summary
Upwork Job
BugZero Checklist (@mallenexpensify)
mallenexpensify commentedon May 28, 2026
Payment Summary
Contributor: @mukhrr due $75 via NewDot
Contributor+: @hoangzinh due $75 via NewDot
^ Test case created. Thx
laurenreidexpensify commentedon Jun 1, 2026
$75 approved for @hoangzinh
flaviadefaria commentedon Jun 2, 2026
Approved: @mukhrr due $75 via NewDot
cretadn22 commentedon Oct 28, 2026
We should append · Non-reimbursable to the Amount field to all money requests, not just single requests, to maintain consistency. Addressed this in #101587
hoangzinh commentedon Oct 28, 2026
@cretadn22 I recall the original scope of this issue is single expenses only #89548 (comment)