Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 13 additions & 3 deletions src/libs/CardUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -712,6 +712,15 @@ function doesCardFeedExist(feed: CardFeed | undefined, cardFeeds: OnyxCollection
return false;
}

/**
* Check if the cardFeeds collection has any loaded data.
* An empty collection ({}) means data was never fetched (e.g. non-admin users),
* which is different from having data that shows a feed was deleted.
*/
function hasLoadedCardFeeds(cardFeeds: OnyxCollection<CardFeeds> | undefined): boolean {
return !!cardFeeds && Object.keys(cardFeeds).length > 0;
}

/**
* Retrieve the custom nickname for a feed from the card feeds collection.
*/
Expand Down Expand Up @@ -1588,7 +1597,7 @@ function getCardHintText(validFrom: string | undefined, validThru: string | unde

/**
* Resolves card-related fields on transactions for report layout display.
* The search API pre-resolves cardName and isCardFeedDeleted, but local Onyx transactions have raw values.
* The search API pre-resolves cardName, but local Onyx transactions have raw values.
* This ensures the report layout matches the search page.
*/
function resolveTransactionCardFields<T extends {cardID?: number; cardName?: string; bank?: string}>(
Expand All @@ -1611,8 +1620,8 @@ function resolveTransactionCardFields<T extends {cardID?: number; cardName?: str
}
}

// Resolve isCardFeedDeleted
if (cardFeeds !== undefined) {
// Resolve isCardFeedDeleted — only when we have actual feed data to make an informed judgment
if (hasLoadedCardFeeds(cardFeeds)) {
updates = {...updates, isCardFeedDeleted: !!transaction.bank && !doesCardFeedExist(transaction.bank as CompanyCardFeed, cardFeeds)};
}

Expand Down Expand Up @@ -1680,6 +1689,7 @@ export {
lastFourNumbersFromCardName,
isMatchingCard,
normalizeCardName,
hasLoadedCardFeeds,
hasIssuedExpensifyCard,
isExpensifyCardFullySetUp,
getCardSettings,
Expand Down
6 changes: 3 additions & 3 deletions src/libs/SearchUIUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ import type {TransactionPreviewData} from './actions/Search';
import {setOptimisticDataForTransactionThreadPreview} from './actions/Search';
import type {CardFeedForDisplay} from './CardFeedUtils';
import {getCardFeedsForDisplay} from './CardFeedUtils';
import {doesCardFeedExist, getCardDescriptionForSearchTable, getFeedNameForDisplay} from './CardUtils';
import {doesCardFeedExist, getCardDescriptionForSearchTable, getFeedNameForDisplay, hasLoadedCardFeeds} from './CardUtils';
import {getDecodedCategoryName} from './CategoryUtils';
import {convertToDisplayString} from './CurrencyUtils';
import DateUtils from './DateUtils';
Expand Down Expand Up @@ -2074,8 +2074,8 @@ function getTransactionsSections({
const from = fromAccountID ? (personalDetailsMap.get(fromAccountID.toString()) ?? emptyPersonalDetails) : emptyPersonalDetails;
const to = getToFieldValueForTransaction(transactionItem, report, data.personalDetailsList, reportAction);
const isIOUReport = report?.type === CONST.REPORT.TYPE.IOU;
// Check if the card feed has been deleted. If cardFeeds is still loading (undefined), return undefined to avoid showing incorrect state.
const isCardFeedDeleted = cardFeeds === undefined ? undefined : !!transactionItem.bank && !doesCardFeedExist(transactionItem.bank as OnyxTypes.CompanyCardFeed, cardFeeds);
// Only compute isCardFeedDeleted when we have actual feed data — an empty collection means feed data was never loaded (e.g. non-admin users)
const isCardFeedDeleted = hasLoadedCardFeeds(cardFeeds) ? !!transactionItem.bank && !doesCardFeedExist(transactionItem.bank as OnyxTypes.CompanyCardFeed, cardFeeds) : undefined;

const {formattedFrom, formattedTo, formattedTotal, formattedMerchant, date, submitted, approved, posted} = getTransactionItemCommonFormattedProperties(
transactionItem,
Expand Down
8 changes: 4 additions & 4 deletions tests/unit/Search/SearchUIUtilsTest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5401,18 +5401,18 @@ describe('SearchUIUtils', () => {
expect(item?.isCardFeedDeleted).toBeUndefined();
});

it('should set isCardFeedDeleted to true when card feed does not exist', () => {
it('should leave isCardFeedDeleted undefined when cardFeeds is an empty collection', () => {
const data = makeFilterTestData({}, {bank: 'deleted-bank-feed'});
const [sections] = callGetTransactionsSections(data, {cardFeeds: {}});
const item = sections.find((s) => s.transactionID === filterTestTxID);
expect(item?.isCardFeedDeleted).toBe(true);
expect(item?.isCardFeedDeleted).toBeUndefined();
});

it('should set isCardFeedDeleted to false when bank is empty', () => {
it('should leave isCardFeedDeleted undefined when cardFeeds is empty even with no bank', () => {
const data = makeFilterTestData({}, {bank: ''});
const [sections] = callGetTransactionsSections(data, {cardFeeds: {}});
const item = sections.find((s) => s.transactionID === filterTestTxID);
expect(item?.isCardFeedDeleted).toBe(false);
expect(item?.isCardFeedDeleted).toBeUndefined();
});

it('should set exported to empty string when transaction has no reportID', () => {
Expand Down
Loading