diff --git a/src/components/MoneyRequestReportView/MoneyRequestReportActionsList.tsx b/src/components/MoneyRequestReportView/MoneyRequestReportActionsList.tsx index c21deb495d39d..bf0f1bb257fbe 100644 --- a/src/components/MoneyRequestReportView/MoneyRequestReportActionsList.tsx +++ b/src/components/MoneyRequestReportView/MoneyRequestReportActionsList.tsx @@ -557,7 +557,7 @@ function MoneyRequestReportActionsList({ hasNextActionMadeBySameActor(visibleReportActions, index); const actionEmojiReactions = emojiReactions?.[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS_REACTIONS}${reportAction.reportActionID}`]; - const originalReportID = getOriginalReportID(report.reportID, reportAction); + const originalReportID = getOriginalReportID(report.reportID, reportAction, undefined); const reportDraftMessages = draftMessage?.[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS_DRAFTS}${originalReportID}`]; const matchingDraftMessage = reportDraftMessages?.[reportAction.reportActionID]; const matchingDraftMessageString = matchingDraftMessage?.message; diff --git a/src/components/ShowContextMenuContext.ts b/src/components/ShowContextMenuContext.ts index 90c873002c090..f56e6e62e8eca 100644 --- a/src/components/ShowContextMenuContext.ts +++ b/src/components/ShowContextMenuContext.ts @@ -62,7 +62,7 @@ function showContextMenuForReport( contextMenuAnchor: anchor, report: { reportID, - originalReportID: reportID ? getOriginalReportID(reportID, action) : undefined, + originalReportID: reportID ? getOriginalReportID(reportID, action, undefined) : undefined, isArchivedRoom, }, reportAction: { diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index d0b324a788515..1918a4692d958 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -9960,11 +9960,11 @@ function canUserPerformWriteAction(report: OnyxEntry, isReportArchived: /** * Returns ID of the original report from which the given reportAction is first created. */ -function getOriginalReportID(reportID: string | undefined, reportAction: OnyxInputOrEntry): string | undefined { +function getOriginalReportID(reportID: string | undefined, reportAction: OnyxInputOrEntry, reportActionsParam: OnyxEntry | undefined): string | undefined { if (!reportID) { return undefined; } - const reportActions = allReportActions?.[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${reportID}`]; + const reportActions = reportActionsParam ?? allReportActions?.[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${reportID}`]; const currentReportAction = reportAction?.reportActionID ? reportActions?.[reportAction.reportActionID] : undefined; const report = allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${reportID}`]; const chatReport = allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${report?.chatReportID}`]; @@ -10807,16 +10807,6 @@ function getIndicatedMissingPaymentMethod( return !hasCreditBankAccount(bankAccountList) ? 'bankAccount' : undefined; } -/** - * Checks if report chat contains missing payment method - */ -function hasMissingPaymentMethod(userWalletTierName: string | undefined, iouReportID: string | undefined, bankAccountList: OnyxEntry): boolean { - const reportActions = allReportActions?.[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${iouReportID}`] ?? {}; - return Object.values(reportActions) - .filter(Boolean) - .some((action) => getIndicatedMissingPaymentMethod(userWalletTierName, iouReportID, action, bankAccountList) !== undefined); -} - /** * Used from expense actions to decide if we need to build an optimistic expense report. * Create a new report if: @@ -12919,7 +12909,6 @@ export { hasExpensifyGuidesEmails, hasHeldExpenses, hasIOUWaitingOnCurrentUserBankAccount, - hasMissingPaymentMethod, hasNonReimbursableTransactions, hasOnlyHeldExpenses, hasOnlyTransactionsWithPendingRoutes, diff --git a/src/libs/actions/Report/index.ts b/src/libs/actions/Report/index.ts index d73e9948f1485..c119e06dca19d 100644 --- a/src/libs/actions/Report/index.ts +++ b/src/libs/actions/Report/index.ts @@ -2092,7 +2092,7 @@ function deleteReportComment( currentEmail: string, ) { const reportID = report?.reportID; - const originalReportID = getOriginalReportID(reportID, reportAction); + const originalReportID = getOriginalReportID(reportID, reportAction, undefined); const reportActionID = reportAction.reportActionID; if (!reportActionID || !originalReportID || !reportID) { @@ -2420,13 +2420,13 @@ function editReportComment( /** Deletes the draft for a comment report action. */ function deleteReportActionDraft(reportID: string | undefined, reportAction: ReportAction) { - const originalReportID = getOriginalReportID(reportID, reportAction); + const originalReportID = getOriginalReportID(reportID, reportAction, undefined); Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS_DRAFTS}${originalReportID}`, {[reportAction.reportActionID]: null}); } /** Saves the draft for a comment report action. This will put the comment into "edit mode" */ function saveReportActionDraft(reportID: string | undefined, reportAction: ReportAction, draftMessage: string) { - const originalReportID = getOriginalReportID(reportID, reportAction); + const originalReportID = getOriginalReportID(reportID, reportAction, undefined); Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS_DRAFTS}${originalReportID}`, {[reportAction.reportActionID]: {message: draftMessage}}); } @@ -3761,7 +3761,7 @@ function toggleEmojiReaction( currentUserAccountID: number, ignoreSkinToneOnCompare = false, ) { - const originalReportID = getOriginalReportID(reportID, reportAction); + const originalReportID = getOriginalReportID(reportID, reportAction, undefined); if (!originalReportID) { return; diff --git a/src/libs/actions/ReportActions.ts b/src/libs/actions/ReportActions.ts index fe23be8b09d87..739e87d7625c2 100644 --- a/src/libs/actions/ReportActions.ts +++ b/src/libs/actions/ReportActions.ts @@ -27,7 +27,7 @@ Onyx.connect({ }); function clearReportActionErrors(reportID: string, reportAction: ReportAction, keys?: string[]) { - const originalReportID = getOriginalReportID(reportID, reportAction); + const originalReportID = getOriginalReportID(reportID, reportAction, undefined); if (!reportAction?.reportActionID) { return; diff --git a/src/pages/FlagCommentPage.tsx b/src/pages/FlagCommentPage.tsx index e5cedc052bd06..83b39775a2473 100644 --- a/src/pages/FlagCommentPage.tsx +++ b/src/pages/FlagCommentPage.tsx @@ -60,7 +60,8 @@ function FlagCommentPage({parentReportAction, route, report, parentReport, repor if (isChatThread(report) && reportAction?.reportActionID === parentReportAction?.reportActionID) { reportID = parentReport?.reportID; } - const originalReportID = getOriginalReportID(reportID, reportAction); + const [reportActions] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${reportID}`, {canBeMissing: true}); + const originalReportID = getOriginalReportID(reportID, reportAction, reportActions); const [originalReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${originalReportID}`, {canBeMissing: true}); const isOriginalReportArchived = useReportIsArchived(originalReportID); diff --git a/src/pages/ReportDetailsPage.tsx b/src/pages/ReportDetailsPage.tsx index 1228d714b6aaf..4281eb991ee63 100644 --- a/src/pages/ReportDetailsPage.tsx +++ b/src/pages/ReportDetailsPage.tsx @@ -176,6 +176,7 @@ function ReportDetailsPage({policy, report, route, reportMetadata}: ReportDetail const [conciergeReportID] = useOnyx(ONYXKEYS.CONCIERGE_REPORT_ID, {canBeMissing: true}); const {reportActions} = usePaginatedReportActions(report.reportID); + const [reportActionsForOriginalReportID] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${report.reportID}`, {canBeMissing: true}); const {removeTransaction} = useSearchContext(); @@ -439,7 +440,7 @@ function ReportDetailsPage({policy, report, route, reportMetadata}: ReportDetail } if (isTrackExpenseReport && !isDeletedParentAction) { - const actionReportID = getOriginalReportID(report.reportID, parentReportAction); + const actionReportID = getOriginalReportID(report.reportID, parentReportAction, reportActionsForOriginalReportID); const whisperAction = getTrackExpenseActionableWhisper(iouTransactionID, moneyRequestReport?.reportID); const actionableWhisperReportActionID = whisperAction?.reportActionID; items.push({ @@ -621,6 +622,7 @@ function ReportDetailsPage({policy, report, route, reportMetadata}: ReportDetail allTransactionDrafts, activePolicy, parentReport, + reportActionsForOriginalReportID, ]); const displayNamesWithTooltips = useMemo(() => { diff --git a/src/pages/TransactionDuplicate/DuplicateTransactionItem.tsx b/src/pages/TransactionDuplicate/DuplicateTransactionItem.tsx index 43d8ed26b7016..89571c7070489 100644 --- a/src/pages/TransactionDuplicate/DuplicateTransactionItem.tsx +++ b/src/pages/TransactionDuplicate/DuplicateTransactionItem.tsx @@ -43,7 +43,7 @@ function DuplicateTransactionItem({transaction, index, allReports, policies, onP return IOUTransactionID === transaction?.transactionID; }); - const originalReportID = getOriginalReportID(report?.reportID, action); + const originalReportID = getOriginalReportID(report?.reportID, action, reportActions); const [draftMessage] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS_DRAFTS}${originalReportID}`, { canBeMissing: true, diff --git a/src/pages/inbox/report/ContextMenu/BaseReportActionContextMenu.tsx b/src/pages/inbox/report/ContextMenu/BaseReportActionContextMenu.tsx index 13c300f003b91..b8a5d33ee3455 100755 --- a/src/pages/inbox/report/ContextMenu/BaseReportActionContextMenu.tsx +++ b/src/pages/inbox/report/ContextMenu/BaseReportActionContextMenu.tsx @@ -365,6 +365,7 @@ function BaseReportActionContextMenu({ // eslint-disable-next-line @typescript-eslint/non-nullable-type-assertion-style reportAction: (reportAction ?? null) as ReportAction, reportID, + originalReportID, report, draftMessage, selection, diff --git a/src/pages/inbox/report/ContextMenu/ContextMenuActions.tsx b/src/pages/inbox/report/ContextMenu/ContextMenuActions.tsx index e507a4be8d03c..19dcdf6f1cc9d 100644 --- a/src/pages/inbox/report/ContextMenu/ContextMenuActions.tsx +++ b/src/pages/inbox/report/ContextMenu/ContextMenuActions.tsx @@ -152,7 +152,6 @@ import { getIOUReportActionDisplayMessage, getMovedActionMessage, getMovedTransactionMessage, - getOriginalReportID, getPolicyChangeMessage, getReimbursementDeQueuedOrCanceledActionMessage, getReimbursementQueuedActionMessage, @@ -239,6 +238,7 @@ type ContextMenuActionPayload = { reportAction: ReportAction; transaction?: OnyxEntry; reportID: string | undefined; + originalReportID: string | undefined; currentUserAccountID: number; report: OnyxEntry; policy?: OnyxEntry; @@ -460,12 +460,11 @@ const ContextMenuActions: ContextMenuAction[] = [ return hasReasoning(reportAction); }, - onPress: (closePopover, {reportAction, reportID, translate, currentUserPersonalDetails}) => { + onPress: (closePopover, {reportAction, reportID, originalReportID, translate, currentUserPersonalDetails}) => { if (!reportID) { return; } - const originalReportID = getOriginalReportID(reportID, reportAction); if (closePopover) { hideContextMenu(false, () => { KeyboardUtils.dismiss().then(() => { @@ -1084,8 +1083,7 @@ const ContextMenuActions: ContextMenuAction[] = [ const isDynamicWorkflowRoutedAction = isActionOfType(reportAction, CONST.REPORT.ACTIONS.TYPE.DYNAMIC_EXTERNAL_WORKFLOW_ROUTED); return type === CONST.CONTEXT_MENU_TYPES.REPORT_ACTION && !isAttachmentTarget && !isMessageDeleted(reportAction) && !isDynamicWorkflowRoutedAction; }, - onPress: (closePopover, {reportAction, reportID}) => { - const originalReportID = getOriginalReportID(reportID, reportAction); + onPress: (closePopover, {reportAction, originalReportID}) => { getEnvironmentURL().then((environmentURL) => { const reportActionID = reportAction?.reportActionID; Clipboard.setString(`${environmentURL}/r/${originalReportID}/${reportActionID}`); diff --git a/src/pages/inbox/report/ContextMenu/PopoverReportActionContextMenu.tsx b/src/pages/inbox/report/ContextMenu/PopoverReportActionContextMenu.tsx index 44543b1aa41ed..d9d890f9565b3 100644 --- a/src/pages/inbox/report/ContextMenu/PopoverReportActionContextMenu.tsx +++ b/src/pages/inbox/report/ContextMenu/PopoverReportActionContextMenu.tsx @@ -56,7 +56,8 @@ function PopoverReportActionContextMenu({ref}: PopoverReportActionContextMenuPro const selectionRef = useRef(''); const reportActionDraftMessageRef = useRef(undefined); const isReportArchived = useReportIsArchived(reportIDRef.current); - const isOriginalReportArchived = useReportIsArchived(getOriginalReportID(reportIDRef.current, reportActionRef.current)); + const [reportActions] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${reportIDRef.current}`, {canBeMissing: true}); + const isOriginalReportArchived = useReportIsArchived(getOriginalReportID(reportIDRef.current, reportActionRef.current, reportActions)); const {iouReport, chatReport, isChatIOUReportArchived} = useGetIOUReportFromReportAction(reportActionRef.current); const {transitionActionSheetState} = useActionSheetAwareScrollViewActions(); @@ -332,7 +333,7 @@ function PopoverReportActionContextMenu({ref}: PopoverReportActionContextMenuPro policy, }); - const [originalReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${getOriginalReportID(reportIDRef.current, reportActionRef.current)}`, { + const [originalReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${getOriginalReportID(reportIDRef.current, reportActionRef.current, reportActions)}`, { canBeMissing: true, }); const ancestorsRef = useRef([]); diff --git a/src/pages/inbox/report/ReportActionItemMessageEdit.tsx b/src/pages/inbox/report/ReportActionItemMessageEdit.tsx index 5c624142612fd..ac421a99ea121 100644 --- a/src/pages/inbox/report/ReportActionItemMessageEdit.tsx +++ b/src/pages/inbox/report/ReportActionItemMessageEdit.tsx @@ -151,8 +151,9 @@ function ReportActionItemMessageEdit({ // The ref to check whether the comment saving is in progress const isCommentPendingSaved = useRef(false); const [originalReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${originalReportID}`, {canBeMissing: true}); + const [reportActions] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${originalReportID}`, {canBeMissing: true}); const isOriginalReportArchived = useReportIsArchived(originalReportID); - const originalParentReportID = getOriginalReportID(originalReportID, action); + const originalParentReportID = getOriginalReportID(originalReportID, action, reportActions); const isOriginalParentReportArchived = useReportIsArchived(originalParentReportID); const ancestors = useAncestors(originalReport); const icons = useMemoizedLazyExpensifyIcons(['Checkmark', 'Close']); diff --git a/src/pages/inbox/report/ReportActionItemMessageWithExplain.tsx b/src/pages/inbox/report/ReportActionItemMessageWithExplain.tsx index df389bda9da6d..01c7b5504d37e 100644 --- a/src/pages/inbox/report/ReportActionItemMessageWithExplain.tsx +++ b/src/pages/inbox/report/ReportActionItemMessageWithExplain.tsx @@ -4,10 +4,12 @@ import type {OnyxEntry} from 'react-native-onyx'; import RenderHTML from '@components/RenderHTML'; import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails'; import useLocalize from '@hooks/useLocalize'; +import useOnyx from '@hooks/useOnyx'; import {explain} from '@libs/actions/Report'; import {hasReasoning} from '@libs/ReportActionsUtils'; import {getOriginalReportID} from '@libs/ReportUtils'; import CONST from '@src/CONST'; +import ONYXKEYS from '@src/ONYXKEYS'; import type {ReportAction} from '@src/types/onyx'; import ReportActionItemBasicMessage from './ReportActionItemBasicMessage'; @@ -29,6 +31,7 @@ type ReportActionItemMessageWithExplainProps = { function ReportActionItemMessageWithExplain({message, action, reportID}: ReportActionItemMessageWithExplainProps) { const {translate} = useLocalize(); const personalDetail = useCurrentUserPersonalDetails(); + const [reportActions] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${reportID}`, {canBeMissing: true}); const actionHasReasoning = hasReasoning(action); const computedMessage = actionHasReasoning ? `${message}${translate('iou.AskToExplain')}` : message; @@ -39,10 +42,10 @@ function ReportActionItemMessageWithExplain({message, action, reportID}: ReportA return; } - const actionOriginalReportID = getOriginalReportID(reportID, action); + const actionOriginalReportID = getOriginalReportID(reportID, action, reportActions); explain(action, actionOriginalReportID, translate, personalDetail?.timezone); }, - [action, reportID, translate, personalDetail?.timezone], + [action, reportID, reportActions, translate, personalDetail?.timezone], ); return ( diff --git a/src/pages/inbox/report/ReportActionItemParentAction.tsx b/src/pages/inbox/report/ReportActionItemParentAction.tsx index 5ea1a0a704ad3..21873a5063312 100644 --- a/src/pages/inbox/report/ReportActionItemParentAction.tsx +++ b/src/pages/inbox/report/ReportActionItemParentAction.tsx @@ -161,7 +161,7 @@ function ReportActionItemParentAction({ const shouldDisplayThreadDivider = !isTripPreview(ancestorReportAction); const isAncestorReportArchived = isArchivedReport(ancestorsReportNameValuePairs?.[`${ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS}${ancestorReport.reportID}`]); - const originalReportID = getOriginalReportID(ancestorReport.reportID, ancestorReportAction); + const originalReportID = getOriginalReportID(ancestorReport.reportID, ancestorReportAction, undefined); const reportDraftMessages = originalReportID ? allDraftMessages?.[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS_DRAFTS}${originalReportID}`] : undefined; const matchingDraftMessage = reportDraftMessages?.[ancestorReportAction.reportActionID]; const matchingDraftMessageString = matchingDraftMessage?.message; diff --git a/src/pages/inbox/report/ReportActionsList.tsx b/src/pages/inbox/report/ReportActionsList.tsx index f1dcbdd642294..bfb903bca0f8f 100644 --- a/src/pages/inbox/report/ReportActionsList.tsx +++ b/src/pages/inbox/report/ReportActionsList.tsx @@ -185,6 +185,7 @@ function ReportActionsList({ const [isUserValidated] = useOnyx(ONYXKEYS.ACCOUNT, {selector: isUserValidatedSelector, canBeMissing: true}); const [draftMessage] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS_DRAFTS}`, {canBeMissing: true}); const [emojiReactions] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS_REACTIONS}`, {canBeMissing: true}); + const [reportActionsFromOnyx] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${report.reportID}`, {canBeMissing: true}); const [userBillingFundID] = useOnyx(ONYXKEYS.NVP_BILLING_FUND_ID, {canBeMissing: true}); const [tryNewDot] = useOnyx(ONYXKEYS.NVP_TRY_NEW_DOT, {canBeMissing: false}); const isTryNewDotNVPDismissed = !!tryNewDot?.classicRedirect?.dismissed; @@ -692,7 +693,7 @@ function ReportActionsList({ const renderItem = useCallback( ({item: reportAction, index}: ListRenderItemInfo) => { - const originalReportID = getOriginalReportID(report.reportID, reportAction); + const originalReportID = getOriginalReportID(report.reportID, reportAction, reportActionsFromOnyx); const reportDraftMessages = draftMessage?.[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS_DRAFTS}${originalReportID}`]; const matchingDraftMessage = reportDraftMessages?.[reportAction.reportActionID]; const matchingDraftMessageString = matchingDraftMessage?.message; @@ -767,6 +768,7 @@ function ReportActionsList({ isReportArchived, reportNameValuePairs?.origin, reportNameValuePairs?.originalID, + reportActionsFromOnyx, ], ); diff --git a/tests/unit/ReportUtilsTest.ts b/tests/unit/ReportUtilsTest.ts index 4e7ec819bd8d1..d626dab8df158 100644 --- a/tests/unit/ReportUtilsTest.ts +++ b/tests/unit/ReportUtilsTest.ts @@ -73,6 +73,7 @@ import { getIOUReportActionDisplayMessage, getMoneyReportPreviewName, getMostRecentlyVisitedReport, + getOriginalReportID, getOutstandingChildRequest, getParentNavigationSubtitle, getParticipantsList, @@ -12022,6 +12023,44 @@ describe('ReportUtils', () => { }); }); + describe('getOriginalReportID', () => { + it('should return undefined when reportID is undefined', () => { + const reportAction = createRandomReportAction(1); + const result = getOriginalReportID(undefined, reportAction, undefined); + expect(result).toBeUndefined(); + }); + + it('should return reportID when currentReportAction exists in reportActions', () => { + const reportID = '123'; + const reportAction = createRandomReportAction(1); + const reportActions = { + [reportAction.reportActionID]: reportAction, + }; + + const result = getOriginalReportID(reportID, reportAction, reportActions); + expect(result).toBe(reportID); + }); + + it('should return reportID when reportActions is undefined but reportAction has no reportActionID', () => { + const reportID = '123'; + const reportAction = { + ...createRandomReportAction(1), + reportActionID: undefined, + } as unknown as ReportAction; + + const result = getOriginalReportID(reportID, reportAction, undefined); + expect(result).toBe(reportID); + }); + + it('should return reportID when reportActions is empty and no thread conditions apply', () => { + const reportID = '123'; + const reportAction = createRandomReportAction(1); + + const result = getOriginalReportID(reportID, reportAction, {}); + expect(result).toBe(reportID); + }); + }); + describe('getBillableAndTaxTotal', () => { const expenseReport: Report = { ...createExpenseReport(1),