diff --git a/src/components/Search/index.tsx b/src/components/Search/index.tsx index 7778e4f2c61d..72b12b5143c6 100644 --- a/src/components/Search/index.tsx +++ b/src/components/Search/index.tsx @@ -70,7 +70,6 @@ import {columnsSelector} from '@src/selectors/AdvancedSearchFiltersForm'; import {isActionLoadingSetSelector} from '@src/selectors/ReportMetaData'; import type {OutstandingReportsByPolicyIDDerivedValue, Transaction} from '@src/types/onyx'; import type SearchResults from '@src/types/onyx/SearchResults'; -import type {SearchTransaction} from '@src/types/onyx/SearchResults'; import type {TransactionViolation} from '@src/types/onyx/TransactionViolation'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; import arraysEqual from '@src/utils/arraysEqual'; @@ -176,6 +175,7 @@ function prepareTransactionsList( action: item.action, reportID: item.reportID, policyID: item.policyID, + // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing amount: Math.abs(item.modifiedAmount || item.amount), groupAmount: item.groupAmount, groupCurrency: item.groupCurrency, @@ -260,8 +260,7 @@ function Search({ const transactionKeys = Object.keys(searchResults.data).filter((key) => key.startsWith(ONYXKEYS.COLLECTION.TRANSACTION)); for (const key of transactionKeys) { - // eslint-disable-next-line @typescript-eslint/no-deprecated - const transaction = searchResults.data[key as keyof typeof searchResults.data] as SearchTransaction; + const transaction = searchResults.data[key as keyof typeof searchResults.data] as Transaction; if (!transaction || typeof transaction !== 'object' || !('transactionID' in transaction) || !('reportID' in transaction)) { continue; } diff --git a/src/components/Search/types.ts b/src/components/Search/types.ts index df353388fd2d..289d2a889634 100644 --- a/src/components/Search/types.ts +++ b/src/components/Search/types.ts @@ -37,7 +37,7 @@ type SelectedTransactionInfo = { action: ValueOf; /** The reportID of the transaction */ - reportID: string; + reportID?: string; /** The policyID tied to the report the transaction is reported on */ policyID: string | undefined; @@ -71,7 +71,7 @@ type SelectedTransactions = Record; /** Model of selected reports */ type SelectedReports = { - reportID: string; + reportID: string | undefined; policyID: string | undefined; action: ValueOf; allActions: Array>; diff --git a/src/components/SelectionListWithSections/Search/TaskListItemRow.tsx b/src/components/SelectionListWithSections/Search/TaskListItemRow.tsx index 08ede3bb037c..231d2972c821 100644 --- a/src/components/SelectionListWithSections/Search/TaskListItemRow.tsx +++ b/src/components/SelectionListWithSections/Search/TaskListItemRow.tsx @@ -22,6 +22,7 @@ import {callFunctionIfActionIsAllowed} from '@libs/actions/Session'; import {canActionTask, completeTask} from '@libs/actions/Task'; import variables from '@styles/variables'; import CONST from '@src/CONST'; +import type {Report} from '@src/types/onyx'; import AvatarWithTextCell from './AvatarWithTextCell'; import DateCell from './DateCell'; import UserInfoCell from './UserInfoCell'; @@ -110,7 +111,7 @@ function ActionCell({taskItem, isLargeScreenWidth}: TaskCellProps) { style={[styles.w100]} isDisabled={!isTaskActionable} onPress={callFunctionIfActionIsAllowed(() => { - completeTask(taskItem, parentReport?.hasOutstandingChildTask ?? false, hasOutstandingChildTask, parentReportAction, taskItem.reportID); + completeTask(taskItem as Report, parentReport?.hasOutstandingChildTask ?? false, hasOutstandingChildTask, parentReportAction, taskItem.reportID); })} /> ); diff --git a/src/components/SelectionListWithSections/types.ts b/src/components/SelectionListWithSections/types.ts index e9bb1e3d0407..86e75db64843 100644 --- a/src/components/SelectionListWithSections/types.ts +++ b/src/components/SelectionListWithSections/types.ts @@ -29,7 +29,7 @@ import type CONST from '@src/CONST'; import type {PersonalDetails, PersonalDetailsList, Policy, Report, ReportAction, SearchResults, TransactionViolation, TransactionViolations} from '@src/types/onyx'; import type {Attendee, SplitExpense} from '@src/types/onyx/IOU'; import type {Errors, Icon, PendingAction} from '@src/types/onyx/OnyxCommon'; -import type {SearchCardGroup, SearchDataTypes, SearchMemberGroup, SearchTask, SearchTransaction, SearchTransactionAction, SearchWithdrawalIDGroup} from '@src/types/onyx/SearchResults'; +import type {SearchCardGroup, SearchDataTypes, SearchMemberGroup, SearchTask, SearchTransactionAction, SearchWithdrawalIDGroup} from '@src/types/onyx/SearchResults'; import type {ReceiptErrors} from '@src/types/onyx/Transaction'; import type Transaction from '@src/types/onyx/Transaction'; import type ChildrenProps from '@src/types/utils/ChildrenProps'; @@ -167,7 +167,7 @@ type ListItem = { icons?: Icon[]; /** Errors that this user may contain */ - errors?: Errors; + errors?: Errors | ReceiptErrors; /** The type of action that's pending */ pendingAction?: PendingAction; @@ -239,8 +239,7 @@ type ListItem = { }; type TransactionListItemType = ListItem & - // eslint-disable-next-line @typescript-eslint/no-deprecated - SearchTransaction & { + Transaction & { /** Report to which the transaction belongs */ report: Report | undefined; diff --git a/src/components/WideRHPContextProvider/index.tsx b/src/components/WideRHPContextProvider/index.tsx index 4920c89c7976..47d71499f2fd 100644 --- a/src/components/WideRHPContextProvider/index.tsx +++ b/src/components/WideRHPContextProvider/index.tsx @@ -210,7 +210,10 @@ function WideRHPContextProvider({children}: React.PropsWithChildren) { * It helps us open expense as wide, before it fully loads. */ const markReportIDAsExpense = useCallback( - (reportID: string) => { + (reportID?: string) => { + if (!reportID) { + return; + } const report = allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${reportID}`]; const isInvoice = report?.type === CONST.REPORT.TYPE.INVOICE; const isTask = report?.type === CONST.REPORT.TYPE.TASK; diff --git a/src/components/WideRHPContextProvider/types.ts b/src/components/WideRHPContextProvider/types.ts index 76f6d2df7adc..db6c01379cb0 100644 --- a/src/components/WideRHPContextProvider/types.ts +++ b/src/components/WideRHPContextProvider/types.ts @@ -32,7 +32,7 @@ type WideRHPContextType = { removeSuperWideRHPRouteKey: (route: NavigationRoute) => void; // Mark reportID as expense before condition check - markReportIDAsExpense: (reportID: string) => void; + markReportIDAsExpense: (reportID?: string) => void; // Mark reportID as multi-transaction expense before condition check markReportIDAsMultiTransactionExpense: (reportID: string) => void; diff --git a/src/libs/MergeTransactionUtils.ts b/src/libs/MergeTransactionUtils.ts index 561f922c72fd..547ef4283f5e 100644 --- a/src/libs/MergeTransactionUtils.ts +++ b/src/libs/MergeTransactionUtils.ts @@ -176,15 +176,15 @@ function getTransactionsAndReportsFromSearch( } { const transaction1 = searchResults.data[`${ONYXKEYS.COLLECTION.TRANSACTION}${transactionIDs.at(0)}`]; const transaction2 = searchResults.data[`${ONYXKEYS.COLLECTION.TRANSACTION}${transactionIDs.at(1)}`]; + const policyID1 = searchResults.data[`${ONYXKEYS.COLLECTION.REPORT}${transaction1?.reportID}`]?.policyID; + const policyID2 = searchResults.data[`${ONYXKEYS.COLLECTION.REPORT}${transaction2?.reportID}`]?.policyID; return { transactions: [transaction1, transaction2].filter((transaction) => !!transaction), reports: [searchResults.data[`${ONYXKEYS.COLLECTION.REPORT}${transaction1?.reportID}`], searchResults.data[`${ONYXKEYS.COLLECTION.REPORT}${transaction2?.reportID}`]].filter( (report) => !!report, ), - policies: [searchResults.data[`${ONYXKEYS.COLLECTION.POLICY}${transaction1?.policyID}`], searchResults.data[`${ONYXKEYS.COLLECTION.POLICY}${transaction2?.policyID}`]].filter( - (policy) => !!policy, - ), + policies: [searchResults.data[`${ONYXKEYS.COLLECTION.POLICY}${policyID1}`], searchResults.data[`${ONYXKEYS.COLLECTION.POLICY}${policyID2}`]].filter((policy) => !!policy), }; } diff --git a/src/libs/SearchUIUtils.ts b/src/libs/SearchUIUtils.ts index 76e3624c0230..79f778e19f74 100644 --- a/src/libs/SearchUIUtils.ts +++ b/src/libs/SearchUIUtils.ts @@ -54,7 +54,6 @@ import type { SearchDataTypes, SearchMemberGroup, SearchTask, - SearchTransaction, SearchTransactionAction, SearchWithdrawalIDGroup, } from '@src/types/onyx/SearchResults'; @@ -696,8 +695,7 @@ function getSuggestedSearchesVisibility( * Returns a list of properties that are common to every Search ListItem */ function getTransactionItemCommonFormattedProperties( - // eslint-disable-next-line @typescript-eslint/no-deprecated - transactionItem: SearchTransaction, + transactionItem: OnyxTypes.Transaction, from: OnyxTypes.PersonalDetails, to: OnyxTypes.PersonalDetails, policy: OnyxTypes.Policy, @@ -854,15 +852,13 @@ function isAmountTooLong(amount: number, maxLength = 8): boolean { return Math.abs(amount).toString().length >= maxLength; } -// eslint-disable-next-line @typescript-eslint/no-deprecated -function isTransactionAmountTooLong(transactionItem: TransactionListItemType | SearchTransaction | OnyxTypes.Transaction) { +function isTransactionAmountTooLong(transactionItem: TransactionListItemType | OnyxTypes.Transaction) { // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing const amount = Math.abs(transactionItem.modifiedAmount || transactionItem.amount); return isAmountTooLong(amount); } -// eslint-disable-next-line @typescript-eslint/no-deprecated -function isTransactionTaxAmountTooLong(transactionItem: TransactionListItemType | SearchTransaction | OnyxTypes.Transaction) { +function isTransactionTaxAmountTooLong(transactionItem: TransactionListItemType | OnyxTypes.Transaction) { // it won't matter if pass true or false as second argument to getTaxAmount here because isAmountTooLong function uses Math.abs on the returned value of getTaxAmount const taxAmount = getTaxAmount(transactionItem, false); return isAmountTooLong(taxAmount); @@ -875,8 +871,7 @@ function getWideAmountIndicators(data: TransactionListItemType[] | TransactionGr let isAmountWide = false; let isTaxAmountWide = false; - // eslint-disable-next-line @typescript-eslint/no-deprecated - const processTransaction = (transaction: TransactionListItemType | SearchTransaction) => { + const processTransaction = (transaction: TransactionListItemType | OnyxTypes.Transaction) => { isAmountWide ||= isTransactionAmountTooLong(transaction); isTaxAmountWide ||= isTransactionTaxAmountTooLong(transaction); }; @@ -1043,7 +1038,7 @@ function shouldShowYear( result.shouldShowYearPosted = postedYear !== currentYear; } - const exportedAction = lastExportedActionByReportID.get(item.reportID); + const exportedAction = item.reportID ? lastExportedActionByReportID.get(item.reportID) : undefined; if (exportedAction?.created && DateUtils.doesDateBelongToAPastYear(exportedAction.created)) { result.shouldShowYearExported = true; } @@ -1109,8 +1104,7 @@ function getIOUReportName(translate: LocalizedTranslate, data: OnyxTypes.SearchR function getTransactionViolations( allViolations: OnyxCollection, - // eslint-disable-next-line @typescript-eslint/no-deprecated - transaction: SearchTransaction, + transaction: OnyxTypes.Transaction, currentUserEmail: string, currentUserAccountID: number, report: OnyxEntry, @@ -1304,7 +1298,7 @@ function getTransactionsSections( submitted, approved, posted, - exported: lastExportedActionByReportID.get(transactionItem.reportID)?.created ?? '', + exported: transactionItem.reportID ? (lastExportedActionByReportID.get(transactionItem.reportID)?.created ?? '') : '', shouldShowMerchant, shouldShowYear: shouldShowYearCreated, shouldShowYearSubmitted, @@ -1327,15 +1321,10 @@ function getTransactionsSections( * Retrieves all transactions associated with a specific report ID from the search data. */ -// eslint-disable-next-line @typescript-eslint/no-deprecated -function getTransactionsForReport(data: OnyxTypes.SearchResults['data'], reportID: string): SearchTransaction[] { - return ( - Object.entries(data) - // eslint-disable-next-line @typescript-eslint/no-deprecated - .filter(([key, value]) => isTransactionEntry(key) && (value as SearchTransaction)?.reportID === reportID) - // eslint-disable-next-line @typescript-eslint/no-deprecated - .map(([, value]) => value as SearchTransaction) - ); +function getTransactionsForReport(data: OnyxTypes.SearchResults['data'], reportID: string): OnyxTypes.Transaction[] { + return Object.entries(data) + .filter(([key, value]) => isTransactionEntry(key) && (value as OnyxTypes.Transaction)?.reportID === reportID) + .map(([, value]) => value as OnyxTypes.Transaction); } /** @@ -1426,8 +1415,7 @@ function getActions( } const allActions: SearchTransactionAction[] = []; - // eslint-disable-next-line @typescript-eslint/no-deprecated - let allReportTransactions: SearchTransaction[]; + let allReportTransactions: OnyxTypes.Transaction[]; if (isReportEntry(key)) { allReportTransactions = getTransactionsForReport(data, report.reportID); } else { @@ -1846,7 +1834,7 @@ function getReportSections( formattedTotal, formattedMerchant, date, - exported: lastExportedActionByReportID.get(transactionItem.reportID)?.created ?? '', + exported: transactionItem.reportID ? (lastExportedActionByReportID.get(transactionItem.reportID)?.created ?? '') : '', shouldShowMerchant, shouldShowYear: shouldShowYearCreatedTransaction, shouldShowYearSubmitted: shouldShowYearSubmittedTransaction, @@ -2495,8 +2483,7 @@ function isSearchResultsEmpty(searchResults: SearchResults, groupBy?: SearchGrou return !Object.keys(searchResults?.data).some( (key) => key.startsWith(ONYXKEYS.COLLECTION.TRANSACTION) && - // eslint-disable-next-line @typescript-eslint/no-deprecated - (searchResults?.data[key as keyof typeof searchResults.data] as SearchTransaction)?.pendingAction !== CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE, + (searchResults?.data[key as keyof typeof searchResults.data] as OnyxTypes.Transaction)?.pendingAction !== CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE, ); } @@ -3208,9 +3195,7 @@ function getColumnsToShow( } const {moneyRequestReportActionsByTransactionID} = Array.isArray(data) ? {} : createReportActionsLookupMaps(data); - - // eslint-disable-next-line @typescript-eslint/no-deprecated - const updateColumns = (transaction: OnyxTypes.Transaction | SearchTransaction) => { + const updateColumns = (transaction: OnyxTypes.Transaction) => { const merchant = transaction.modifiedMerchant ? transaction.modifiedMerchant : (transaction.merchant ?? ''); if ((merchant !== '' && merchant !== CONST.TRANSACTION.PARTIAL_TRANSACTION_MERCHANT) || isScanning(transaction)) { columns[CONST.SEARCH.TABLE_COLUMNS.MERCHANT] = true; @@ -3247,7 +3232,7 @@ function getColumnsToShow( } // eslint-disable-next-line @typescript-eslint/no-deprecated - const toFieldValue = getToFieldValueForTransaction(transaction as SearchTransaction, report, data.personalDetailsList, reportAction); + const toFieldValue = getToFieldValueForTransaction(transaction, report, data.personalDetailsList, reportAction); if (toFieldValue.accountID && toFieldValue.accountID !== currentAccountID && !columns[CONST.SEARCH.TABLE_COLUMNS.TO]) { columns[CONST.SEARCH.TABLE_COLUMNS.TO] = !!report && !isOpenReport(report); } diff --git a/src/libs/TransactionUtils/index.ts b/src/libs/TransactionUtils/index.ts index 59a9b7d19204..f5bfd3cb1bcd 100644 --- a/src/libs/TransactionUtils/index.ts +++ b/src/libs/TransactionUtils/index.ts @@ -71,8 +71,6 @@ import type {Attendee, Participant, SplitExpense} from '@src/types/onyx/IOU'; import type {Errors, PendingAction} from '@src/types/onyx/OnyxCommon'; import type {CurrentUserPersonalDetails} from '@src/types/onyx/PersonalDetails'; import type {OnyxData} from '@src/types/onyx/Request'; -// eslint-disable-next-line @typescript-eslint/no-deprecated -import type {SearchTransaction} from '@src/types/onyx/SearchResults'; import type { Comment, Receipt, @@ -1268,8 +1266,7 @@ function hasMissingSmartscanFields(transaction: OnyxInputOrEntry, r * Get all transaction violations of the transaction with given transactionID. */ function getTransactionViolations( - // eslint-disable-next-line @typescript-eslint/no-deprecated - transaction: OnyxEntry, + transaction: OnyxEntry, transactionViolations: OnyxCollection, currentUserEmail: string, currentUserAccountID: number, @@ -1314,8 +1311,7 @@ function hasPendingRTERViolation(transactionViolations?: TransactionViolations | * Check if there is broken connection violation. */ function hasBrokenConnectionViolation( - // eslint-disable-next-line @typescript-eslint/no-deprecated - transaction: Transaction | SearchTransaction, + transaction: Transaction, transactionViolations: OnyxCollection | undefined, currentUserEmail: string, currentUserAccountID: number, @@ -1457,8 +1453,7 @@ function shouldShowViolation( * Check if there is pending rter violation in all transactionViolations with given transactionIDs. */ function allHavePendingRTERViolation( - // eslint-disable-next-line @typescript-eslint/no-deprecated - transactions: OnyxEntry, + transactions: OnyxEntry, transactionViolations: OnyxCollection | undefined, currentUserEmail: string, currentUserAccountID: number, @@ -1492,8 +1487,7 @@ function checkIfShouldShowMarkAsCashButton(hasRTERPendingViolation: boolean, sho * Check if there is any transaction without RTER violation within the given transactionIDs. */ function hasAnyTransactionWithoutRTERViolation( - // eslint-disable-next-line @typescript-eslint/no-deprecated - transactions: Transaction[] | SearchTransaction[], + transactions: Transaction[], transactionViolations: OnyxCollection | undefined, currentUserEmail: string, currentUserAccountID: number, diff --git a/src/libs/actions/IOU/index.ts b/src/libs/actions/IOU/index.ts index d7fb79600463..20f82f0ed110 100644 --- a/src/libs/actions/IOU/index.ts +++ b/src/libs/actions/IOU/index.ts @@ -261,7 +261,6 @@ import type RecentlyUsedTags from '@src/types/onyx/RecentlyUsedTags'; import type {InvoiceReceiver, InvoiceReceiverType, ReportNextStep} from '@src/types/onyx/Report'; import type ReportAction from '@src/types/onyx/ReportAction'; import type {OnyxData} from '@src/types/onyx/Request'; -import type {SearchTransaction} from '@src/types/onyx/SearchResults'; import type {Comment, Receipt, ReceiptSource, Routes, SplitShares, TransactionChanges, TransactionCustomUnit, WaypointCollection} from '@src/types/onyx/Transaction'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; @@ -9654,8 +9653,8 @@ function deleteMoneyRequest({ value: { data: { [`${ONYXKEYS.COLLECTION.REPORT}${iouReport?.reportID}`]: { - // @ts-expect-error - will be solved in https://github.com/Expensify/App/issues/73830 pendingFields: { + // @ts-expect-error - will be solved in https://github.com/Expensify/App/issues/73830 preview: CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE, }, }, @@ -10400,8 +10399,7 @@ function canIOUBePaid( iouReport: OnyxTypes.OnyxInputOrEntry, chatReport: OnyxTypes.OnyxInputOrEntry, policy: OnyxTypes.OnyxInputOrEntry, - // eslint-disable-next-line @typescript-eslint/no-deprecated - transactions?: OnyxTypes.Transaction[] | SearchTransaction[], + transactions?: OnyxTypes.Transaction[], onlyShowPayElsewhere = false, chatReportRNVP?: OnyxTypes.ReportNameValuePairs, invoiceReceiverPolicy?: OnyxTypes.Policy, @@ -10472,8 +10470,7 @@ function canCancelPayment(iouReport: OnyxEntry, session: OnyxE function canSubmitReport( report: OnyxEntry, policy: OnyxEntry, - // eslint-disable-next-line @typescript-eslint/no-deprecated - transactions: OnyxTypes.Transaction[] | SearchTransaction[], + transactions: OnyxTypes.Transaction[], allViolations: OnyxCollection | undefined, isReportArchived: boolean, currentUserEmailParam: string, diff --git a/src/libs/actions/Search.ts b/src/libs/actions/Search.ts index 9303ef3964f0..1ff6868c0b16 100644 --- a/src/libs/actions/Search.ts +++ b/src/libs/actions/Search.ts @@ -48,7 +48,6 @@ import type {SearchAdvancedFiltersForm} from '@src/types/form/SearchAdvancedFilt import type {ExportTemplate, LastPaymentMethod, LastPaymentMethodType, Policy, Report, ReportAction, ReportActions, Transaction} from '@src/types/onyx'; import type {PaymentInformation} from '@src/types/onyx/LastPaymentMethod'; import type {ConnectionName} from '@src/types/onyx/Policy'; -import type {SearchTransaction} from '@src/types/onyx/SearchResults'; import type Nullable from '@src/types/utils/Nullable'; import SafeString from '@src/utils/SafeString'; import {setPersonalBankAccountContinueKYCOnSuccess} from './BankAccounts'; @@ -86,8 +85,7 @@ function handleActionButtonPress( ) { // The transactionIDList is needed to handle actions taken on `status:""` where transactions on single expense reports can be approved/paid. // We need the transactionID to display the loading indicator for that list item's action. - // eslint-disable-next-line @typescript-eslint/no-deprecated - const allReportTransactions = (isTransactionGroupListItemType(item) ? item.transactions : [item]) as SearchTransaction[]; + const allReportTransactions = (isTransactionGroupListItemType(item) ? item.transactions : [item]) as Transaction[]; const hasHeldExpense = hasHeldExpenses('', allReportTransactions); if (hasHeldExpense && item.action !== CONST.SEARCH.ACTION_TYPES.SUBMIT) { @@ -112,14 +110,14 @@ function handleActionButtonPress( onDEWModalOpen?.(); return; } - approveMoneyRequestOnSearch(hash, [item.reportID], currentSearchKey); + approveMoneyRequestOnSearch(hash, item.reportID ? [item.reportID] : [], currentSearchKey); return; case CONST.SEARCH.ACTION_TYPES.SUBMIT: { if (hasDynamicExternalWorkflow(snapshotPolicy)) { onDEWModalOpen?.(); return; } - submitMoneyRequestOnSearch(hash, [item], [snapshotPolicy], currentSearchKey); + submitMoneyRequestOnSearch(hash, [item as Report], [snapshotPolicy], currentSearchKey); return; } case CONST.SEARCH.ACTION_TYPES.EXPORT_TO_ACCOUNTING: { @@ -134,7 +132,7 @@ function handleActionButtonPress( return; } - exportToIntegrationOnSearch(hash, item.reportID, connectedIntegration, currentSearchKey); + exportToIntegrationOnSearch(hash, item?.reportID, connectedIntegration, currentSearchKey); return; } default: @@ -164,6 +162,7 @@ function getLastPolicyPaymentMethod( return undefined; } + // eslint-disable-next-line @typescript-eslint/no-deprecated const personalPolicy = getPersonalPolicy(); const lastPolicyPaymentMethod = lastPaymentMethods?.[policyID] ?? (isIOUReport && personalPolicy ? lastPaymentMethods?.[personalPolicy.id] : undefined); @@ -199,6 +198,10 @@ function getPayActionCallback( ) { const lastPolicyPaymentMethod = getLastPolicyPaymentMethod(item.policyID, lastPaymentMethod, getReportType(item.reportID)); + if (!item.reportID) { + return; + } + if (!lastPolicyPaymentMethod || !Object.values(CONST.IOU.PAYMENT_TYPE).includes(lastPolicyPaymentMethod)) { goToItem(); return; @@ -558,7 +561,10 @@ function approveMoneyRequestOnSearch(hash: number, reportIDList: string[], curre API.write(WRITE_COMMANDS.APPROVE_MONEY_REQUEST_ON_SEARCH, {hash, reportIDList}, {optimisticData, failureData, successData}); } -function exportToIntegrationOnSearch(hash: number, reportID: string, connectionName: ConnectionName, currentSearchKey?: SearchKey) { +function exportToIntegrationOnSearch(hash: number, reportID: string | undefined, connectionName: ConnectionName, currentSearchKey?: SearchKey) { + if (!reportID) { + return; + } const optimisticAction = buildOptimisticExportIntegrationAction(connectionName); const successAction: OptimisticExportIntegrationAction = {...optimisticAction, pendingAction: null}; const optimisticReportActionID = optimisticAction.reportActionID; @@ -771,7 +777,7 @@ function rejectMoneyRequestInBulk(reportID: string, comment: string, policy: Ony /** Minimal transaction info needed for reject - only reportID is used */ type TransactionReportInfo = { - reportID: string; + reportID?: string; }; function rejectMoneyRequestsOnSearch( @@ -786,6 +792,10 @@ function rejectMoneyRequestsOnSearch( const transactionsByReport = transactionIDs.reduce>((acc, transactionID) => { const reportID = selectedTransactions[transactionID].reportID; + if (!reportID) { + return acc; + } + if (!acc[reportID]) { acc[reportID] = []; } @@ -1007,7 +1017,9 @@ function shouldShowBulkOptionForRemainingTransactions(selectedTransactions: Sele if (!selectedTransactions || isEmpty(selectedTransactions)) { return true; } - const neededFilterTransactions = transactionKeys?.filter((transactionIDKey) => !selectedReportIDs?.includes(selectedTransactions[transactionIDKey].reportID)); + const neededFilterTransactions = transactionKeys?.filter( + (transactionIDKey) => selectedTransactions[transactionIDKey]?.reportID && !selectedReportIDs?.includes(selectedTransactions[transactionIDKey]?.reportID), + ); if (!neededFilterTransactions?.length) { return true; } diff --git a/src/pages/Search/SearchPage.tsx b/src/pages/Search/SearchPage.tsx index bdcaaa3c7dd6..8293969d49ce 100644 --- a/src/pages/Search/SearchPage.tsx +++ b/src/pages/Search/SearchPage.tsx @@ -163,8 +163,19 @@ function SearchPage({route}: SearchPageProps) { // eslint-disable-next-line rulesdir/no-default-id-values const [currentSearchResults] = useOnyx(`${ONYXKEYS.COLLECTION.SNAPSHOT}${queryJSON?.hash ?? CONST.DEFAULT_NUMBER_ID}`, {canBeMissing: true}); const lastNonEmptySearchResults = useRef(undefined); - const selectedTransactionReportIDs = useMemo(() => [...new Set(Object.values(selectedTransactions).map((transaction) => transaction.reportID))], [selectedTransactions]); - const selectedReportIDs = Object.values(selectedReports).map((report) => report.reportID); + const selectedTransactionReportIDs = useMemo( + () => [ + ...new Set( + Object.values(selectedTransactions) + .map((transaction) => transaction.reportID) + .filter((reportID) => reportID !== undefined), + ), + ], + [selectedTransactions], + ); + const selectedReportIDs = Object.values(selectedReports) + .map((report) => report.reportID) + .filter((reportID) => reportID !== undefined); const isCurrencySupportedBulkWallet = isCurrencySupportWalletBulkPay(selectedReports, selectedTransactions); const hasOnlyPersonalPolicies = useMemo(() => hasOnlyPersonalPoliciesUtil(policies), [policies]); @@ -282,6 +293,9 @@ function SearchPage({route}: SearchPageProps) { for (const item of selectedOptions) { const itemPolicyID = item.policyID; const itemReportID = item.reportID; + if (!itemReportID) { + return; + } const isExpenseReport = isExpenseReportUtil(itemReportID); const isIOUReport = isIOUReportUtil(itemReportID); const reportType = getReportType(itemReportID); @@ -443,7 +457,7 @@ function SearchPage({route}: SearchPageProps) { { query: status, jsonQuery: JSON.stringify(queryJSON), - reportIDList: selectedReports?.filter((report) => !!report).map((report) => report.reportID) ?? [], + reportIDList: selectedReports?.map((report) => report?.reportID).filter((reportID) => reportID !== undefined) ?? [], transactionIDList: selectedTransactionsKeys, }, () => { @@ -504,7 +518,9 @@ function SearchPage({route}: SearchPageProps) { } // Otherwise, we provide the full set of options depending on the state of the selected transactions and reports - const areSelectedTransactionsIncludedInReports = selectedTransactionsKeys.every((id) => selectedReportIDs.includes(selectedTransactions[id].reportID)); + const areSelectedTransactionsIncludedInReports = selectedTransactionsKeys.every((id) => + selectedTransactions[id].reportID ? selectedReportIDs.includes(selectedTransactions[id].reportID) : true, + ); const shouldShowApproveOption = !isOffline && !isAnyTransactionOnHold && @@ -547,7 +563,10 @@ function SearchPage({route}: SearchPageProps) { const reportIDList = !selectedReports.length ? Object.values(selectedTransactions).map((transaction) => transaction.reportID) : (selectedReports?.filter((report) => !!report).map((report) => report.reportID) ?? []); - approveMoneyRequestOnSearch(hash, reportIDList); + approveMoneyRequestOnSearch( + hash, + reportIDList.filter((reportID) => reportID !== undefined), + ); // eslint-disable-next-line @typescript-eslint/no-deprecated InteractionManager.runAfterInteractions(() => { clearSelectedTransactions(); @@ -616,7 +635,7 @@ function SearchPage({route}: SearchPageProps) { for (const item of itemList) { const policy = policies?.[`${ONYXKEYS.COLLECTION.POLICY}${item.policyID}`]; if (policy) { - submitMoneyRequestOnSearch(hash, [item], [policy]); + submitMoneyRequestOnSearch(hash, [item as Report], [policy]); } } clearSelectedTransactions(); @@ -968,7 +987,7 @@ function SearchPage({route}: SearchPageProps) { } setIsDownloadExportModalVisible(false); - const reportIDList = selectedReports?.filter((report) => !!report).map((report) => report.reportID) ?? []; + const reportIDList = selectedReports?.map((report) => report?.reportID).filter((reportID) => reportID !== undefined) ?? []; queueExportSearchItemsToCSV({ query: status, jsonQuery: JSON.stringify(queryJSON), diff --git a/src/types/onyx/SearchResults.ts b/src/types/onyx/SearchResults.ts index c94475279202..53b4fd9ef0d6 100644 --- a/src/types/onyx/SearchResults.ts +++ b/src/types/onyx/SearchResults.ts @@ -4,7 +4,6 @@ import type ChatListItem from '@components/SelectionListWithSections/ChatListIte import type TransactionGroupListItem from '@components/SelectionListWithSections/Search/TransactionGroupListItem'; import type TransactionListItem from '@components/SelectionListWithSections/Search/TransactionListItem'; import type {ReportActionListItemType, TaskListItemType, TransactionGroupListItemType, TransactionListItemType} from '@components/SelectionListWithSections/types'; -import type {IOURequestType} from '@libs/actions/IOU'; import type CONST from '@src/CONST'; import type ONYXKEYS from '@src/ONYXKEYS'; import type {BankName} from './Bank'; @@ -14,6 +13,7 @@ import type Policy from './Policy'; import type Report from './Report'; import type ReportAction from './ReportAction'; import type ReportNameValuePairs from './ReportNameValuePairs'; +import type Transaction from './Transaction'; import type {TransactionViolation} from './TransactionViolation'; /** Types of search data */ @@ -69,120 +69,6 @@ type SearchResultsInfo = { /** The action that can be performed for the transaction */ type SearchTransactionAction = ValueOf; -/** Model of transaction search result - * - * @deprecated - Use Transaction instead - */ -type SearchTransaction = { - /** The ID of the transaction */ - transactionID: string; - - /** The transaction created date */ - created: string; - - /** The edited transaction created date */ - modifiedCreated: string; - - /** The transaction amount */ - amount: number; - - /** The edited transaction amount */ - modifiedAmount: number; - - /** The transaction currency */ - currency: string; - - /** The edited transaction currency */ - modifiedCurrency: string; - - /** The transaction merchant */ - merchant: string; - - /** The edited transaction merchant */ - modifiedMerchant: string; - - /** The receipt object */ - receipt?: { - /** Source of the receipt */ - source?: string; - - /** State of the receipt */ - state?: ValueOf; - - /** The name of the file of the receipt */ - filename?: string; - }; - - /** The transaction tag */ - tag: string; - - /** The transaction description */ - comment?: { - /** Content of the transaction description */ - comment?: string; - - /** The HOLD report action ID if the transaction is on hold */ - hold?: string; - }; - - /** The transaction category */ - category: string; - - /** The ID of the parent of the transaction */ - parentTransactionID?: string; - - /** If the transaction has an Ereceipt */ - hasEReceipt?: boolean; - - /** Used during the creation flow before the transaction is saved to the server */ - iouRequestType?: IOURequestType; - - /** The transaction tax amount */ - taxAmount?: number; - - /** The ID of the report the transaction is associated with */ - reportID: string; - - /** The policyID of the report */ - policyID?: string; - - /** The MCC Group associated with the transaction */ - mccGroup?: ValueOf; - - /** The modified MCC Group associated with the transaction */ - modifiedMCCGroup?: ValueOf; - - /** Whether the transaction has violations or errors */ - errors?: OnyxCommon.Errors; - - /** The type of action that's pending */ - pendingAction?: OnyxCommon.PendingAction; - - /** The CC for this transaction */ - cardID?: number; - - /** The display name of the purchaser card, if any */ - cardName?: string; - - /** The transaction converted amount in `groupCurrency` currency */ - groupAmount?: number; - - /** The group currency if the transaction is grouped. Defaults to the active policy currency if group has no target currency */ - groupCurrency?: string; - - /** The exchange rate of the transaction if the transaction is grouped. Defaults to the exchange rate against the active policy currency if group has no target currency */ - groupExchangeRate?: number; - - /** Reimbursable status of the transaction */ - reimbursable?: boolean; - - /** Billable status of the transaction */ - billable?: boolean; - - /** The card transaction's posted date */ - posted?: string; -}; - /** Model of tasks search result */ type SearchTask = { /** The type of the response */ @@ -296,8 +182,7 @@ type SearchResults = { search: SearchResultsInfo; /** Search results data */ - // eslint-disable-next-line @typescript-eslint/no-deprecated - data: PrefixedRecord & + data: PrefixedRecord & Record> & PrefixedRecord> & PrefixedRecord & @@ -315,16 +200,4 @@ type SearchResults = { export default SearchResults; -export type { - ListItemType, - ListItemDataType, - SearchTask, - // eslint-disable-next-line @typescript-eslint/no-deprecated - SearchTransaction, - SearchTransactionAction, - SearchDataTypes, - SearchResultsInfo, - SearchMemberGroup, - SearchCardGroup, - SearchWithdrawalIDGroup, -}; +export type {ListItemType, ListItemDataType, SearchTask, SearchTransactionAction, SearchDataTypes, SearchResultsInfo, SearchMemberGroup, SearchCardGroup, SearchWithdrawalIDGroup};