You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[Due for payment 2026-05-26] [$250] New Feature: Single Non-Reimbursable Expense Reports Show Redundant Rows Above Total #89548
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:
🚨 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:
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:
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):
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.
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
In MoneyReportView.tsx:252-253, both the "Reimbursable" and "Non-reimbursable" breakdown rows use the sameshow 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:
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.
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).
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.
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.
45 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