Skip to content

Commit 04ad1eb

Browse files
committed
fixed tax rate in expenses created before tax rate is enabled in WS
1 parent 39d1d17 commit 04ad1eb

4 files changed

Lines changed: 92 additions & 2 deletions

File tree

src/components/MoneyRequestReportView/MoneyRequestReportTransactionList.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -334,8 +334,9 @@ function MoneyRequestReportTransactionList({
334334
shouldShowCommentsColumn,
335335
shouldShowReimbursableColumn: hasNonReimbursableTransactions(transactions),
336336
reportCurrency: report?.currency,
337+
policy,
337338
});
338-
}, [transactions, currentUserDetails?.accountID, isExpenseReportViewFromIOUReport, shouldShowBillableColumn, shouldShowCommentsColumn, reportDetailsColumns, report?.currency]);
339+
}, [transactions, currentUserDetails?.accountID, isExpenseReportViewFromIOUReport, shouldShowBillableColumn, shouldShowCommentsColumn, reportDetailsColumns, report?.currency, policy]);
339340

340341
const {windowWidth, windowHeight} = useWindowDimensions();
341342
const minTableWidth = getTableMinWidth(columnsToShow);

src/libs/SearchUIUtils.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ import {
118118
isPolicyAdmin,
119119
isPolicyApprover,
120120
isPolicyPayer,
121+
isPolicyTaxEnabled,
121122
} from './PolicyUtils';
122123
import {
123124
getIOUActionForReportID,
@@ -5131,6 +5132,7 @@ function getColumnsToShow({
51315132
shouldShowCommentsColumn = false,
51325133
reportCurrency,
51335134
shouldUseStrictDefaultExpenseColumns = false,
5135+
policy,
51345136
}: {
51355137
currentAccountID: number | undefined;
51365138
data: OnyxTypes.SearchResults['data'] | OnyxTypes.Transaction[];
@@ -5388,7 +5390,10 @@ function getColumnsToShow({
53885390
// Use truthy checks so default/no-tax values (0, null, '', undefined) don't trigger
53895391
// false positives — buildOptimisticTransaction seeds taxAmount: 0 on every new draft,
53905392
// which would otherwise flash tax columns on for offline-pending transactions.
5391-
const hasTaxInfo = !!transaction.taxCode || !!transaction.taxAmount || !!transaction.taxValue;
5393+
// When the user explicitly selected the tax columns (customResult) and the workspace
5394+
// has taxes enabled, keep them regardless of per-transaction values — older expenses
5395+
// created before taxes were turned on still have null taxCode/taxAmount/taxValue.
5396+
const hasTaxInfo = (!!customResult && isPolicyTaxEnabled(policy)) || !!transaction.taxCode || !!transaction.taxAmount || !!transaction.taxValue;
53925397
if (hasTaxInfo) {
53935398
columns[CONST.SEARCH.TABLE_COLUMNS.TAX_RATE] = true;
53945399
columns[CONST.SEARCH.TABLE_COLUMNS.TAX_AMOUNT] = true;

src/pages/settings/Report/ReportDetailsColumnsPage.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ function ReportDetailsColumnsPage() {
8080
shouldShowBillableColumn: isBillableEnabledOnPolicy(policy),
8181
shouldShowReimbursableColumn: hasNonReimbursableTransactions(reportTransactions),
8282
reportCurrency: report?.currency,
83+
policy,
8384
});
8485

8586
// Filter to only columns available in the custom columns list (drops RECEIPT/TYPE/COMMENTS etc.)

tests/unit/Search/SearchUIUtilsTest.ts

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ import ONYXKEYS from '@src/ONYXKEYS';
4141
import ROUTES from '@src/ROUTES';
4242
import type * as OnyxTypes from '@src/types/onyx';
4343
import type {CustomCardFeedData} from '@src/types/onyx/CardFeeds';
44+
import type Policy from '@src/types/onyx/Policy';
4445
import type {Connections} from '@src/types/onyx/Policy';
4546
import type {SearchDataTypes} from '@src/types/onyx/SearchResults';
4647
import getOnyxValue from '../../utils/getOnyxValue';
@@ -8265,6 +8266,88 @@ describe('SearchUIUtils', () => {
82658266
expect(columns).toContain(CONST.SEARCH.TABLE_COLUMNS.TAX_AMOUNT);
82668267
});
82678268

8269+
test('Should show TAX columns when user selected them and the workspace has taxes enabled, even for transactions with null tax fields', () => {
8270+
// Repro for the issue raised on GH #82252: expenses created before taxes were
8271+
// enabled have null taxCode/taxAmount/taxValue and never get backfilled, so the
8272+
// per-transaction check alone would hide the columns even though the user has
8273+
// both selected the columns and enabled taxes on the workspace.
8274+
const baseTransaction = searchResults.data[`transactions_${transactionID}`];
8275+
const legacyTransaction = {
8276+
...baseTransaction,
8277+
transactionID: 'legacy',
8278+
merchant: 'Legacy Expense',
8279+
taxCode: undefined,
8280+
taxAmount: undefined,
8281+
};
8282+
const taxEnabledPolicy = {...policy, tax: {trackingEnabled: true}} as unknown as Policy;
8283+
8284+
const visibleColumns = [CONST.SEARCH.TABLE_COLUMNS.DATE, CONST.SEARCH.TABLE_COLUMNS.TAX_RATE, CONST.SEARCH.TABLE_COLUMNS.TAX_AMOUNT, CONST.SEARCH.TABLE_COLUMNS.TOTAL_AMOUNT];
8285+
const columns = SearchUIUtils.getColumnsToShow({
8286+
currentAccountID: submitterAccountID,
8287+
data: [legacyTransaction],
8288+
visibleColumns,
8289+
isExpenseReportView: true,
8290+
policy: taxEnabledPolicy,
8291+
});
8292+
8293+
expect(columns).toContain(CONST.SEARCH.TABLE_COLUMNS.TAX_RATE);
8294+
expect(columns).toContain(CONST.SEARCH.TABLE_COLUMNS.TAX_AMOUNT);
8295+
});
8296+
8297+
test('Should NOT inject TAX columns when the workspace has taxes enabled but the user did not select them', () => {
8298+
// Guard: enabling taxes on the workspace must not force the columns into the
8299+
// result if the user deselected them in the column selector. The customResult
8300+
// path filters to the user's selection, so unselected columns stay hidden even
8301+
// when columns[TAX_RATE]/[TAX_AMOUNT] get flipped on internally.
8302+
const baseTransaction = searchResults.data[`transactions_${transactionID}`];
8303+
const legacyTransaction = {
8304+
...baseTransaction,
8305+
transactionID: 'legacy',
8306+
merchant: 'Legacy Expense',
8307+
taxCode: undefined,
8308+
taxAmount: undefined,
8309+
};
8310+
const taxEnabledPolicy = {...policy, tax: {trackingEnabled: true}} as unknown as Policy;
8311+
8312+
const visibleColumns = [CONST.SEARCH.TABLE_COLUMNS.DATE, CONST.SEARCH.TABLE_COLUMNS.MERCHANT, CONST.SEARCH.TABLE_COLUMNS.TOTAL_AMOUNT];
8313+
const columns = SearchUIUtils.getColumnsToShow({
8314+
currentAccountID: submitterAccountID,
8315+
data: [legacyTransaction],
8316+
visibleColumns,
8317+
isExpenseReportView: true,
8318+
policy: taxEnabledPolicy,
8319+
});
8320+
8321+
expect(columns).not.toContain(CONST.SEARCH.TABLE_COLUMNS.TAX_RATE);
8322+
expect(columns).not.toContain(CONST.SEARCH.TABLE_COLUMNS.TAX_AMOUNT);
8323+
});
8324+
8325+
test('Should hide TAX columns when the workspace does not have taxes enabled and transactions have no tax data', () => {
8326+
// Regression guard: without a tax-enabled policy and without per-transaction tax
8327+
// data, the columns must stay hidden even if the user selected them.
8328+
const baseTransaction = searchResults.data[`transactions_${transactionID}`];
8329+
const legacyTransaction = {
8330+
...baseTransaction,
8331+
transactionID: 'legacy',
8332+
merchant: 'Legacy Expense',
8333+
taxCode: undefined,
8334+
taxAmount: undefined,
8335+
};
8336+
const taxDisabledPolicy = {...policy, tax: {trackingEnabled: false}} as unknown as Policy;
8337+
8338+
const visibleColumns = [CONST.SEARCH.TABLE_COLUMNS.DATE, CONST.SEARCH.TABLE_COLUMNS.TAX_RATE, CONST.SEARCH.TABLE_COLUMNS.TAX_AMOUNT, CONST.SEARCH.TABLE_COLUMNS.TOTAL_AMOUNT];
8339+
const columns = SearchUIUtils.getColumnsToShow({
8340+
currentAccountID: submitterAccountID,
8341+
data: [legacyTransaction],
8342+
visibleColumns,
8343+
isExpenseReportView: true,
8344+
policy: taxDisabledPolicy,
8345+
});
8346+
8347+
expect(columns).not.toContain(CONST.SEARCH.TABLE_COLUMNS.TAX_RATE);
8348+
expect(columns).not.toContain(CONST.SEARCH.TABLE_COLUMNS.TAX_AMOUNT);
8349+
});
8350+
82688351
test('Should hide empty AMOUNT column in expense report view when no conversion', () => {
82698352
const baseTransaction = searchResults.data[`transactions_${transactionID}`];
82708353
const testTransaction = {

0 commit comments

Comments
 (0)