diff --git a/src/components/ReportActionItem/MoneyRequestPreview/MoneyRequestPreviewContent.tsx b/src/components/ReportActionItem/MoneyRequestPreview/MoneyRequestPreviewContent.tsx index 0a740e65747f..6aa047052e14 100644 --- a/src/components/ReportActionItem/MoneyRequestPreview/MoneyRequestPreviewContent.tsx +++ b/src/components/ReportActionItem/MoneyRequestPreview/MoneyRequestPreviewContent.tsx @@ -51,19 +51,25 @@ import {isEmptyObject} from '@src/types/utils/EmptyObject'; import type {MoneyRequestPreviewProps, PendingMessageProps} from './types'; function MoneyRequestPreviewContent({ + iouReport, isBillSplit, + session, action, + personalDetails, + chatReport, + transaction, contextMenuAnchor, chatReportID, reportID, onPreviewPressed, containerStyles, + walletTerms, checkIfContextMenuActive = () => {}, shouldShowPendingConversionMessage = false, isHovered = false, isWhisper = false, + transactionViolations, shouldDisplayContextMenu = true, - iouReportID, }: MoneyRequestPreviewProps) { const theme = useTheme(); const styles = useThemeStyles(); @@ -72,16 +78,6 @@ function MoneyRequestPreviewContent({ const {windowWidth} = useWindowDimensions(); const route = useRoute>(); const {shouldUseNarrowLayout} = useResponsiveLayout(); - const [personalDetails] = useOnyx(ONYXKEYS.PERSONAL_DETAILS_LIST); - const [chatReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${chatReportID || '-1'}`); - const [session] = useOnyx(ONYXKEYS.SESSION); - const [iouReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${iouReportID || '-1'}`); - - const isMoneyRequestAction = ReportActionsUtils.isMoneyRequestAction(action); - const transactionID = isMoneyRequestAction ? ReportActionsUtils.getOriginalMessage(action)?.IOUTransactionID : '-1'; - const [transaction] = useOnyx(`${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`); - const [walletTerms] = useOnyx(ONYXKEYS.WALLET_TERMS); - const [transactionViolations] = useOnyx(ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS); const sessionAccountID = session?.accountID; const managerID = iouReport?.managerID ?? -1; diff --git a/src/components/ReportActionItem/MoneyRequestPreview/index.tsx b/src/components/ReportActionItem/MoneyRequestPreview/index.tsx index f902948b2cb5..c01206f83f55 100644 --- a/src/components/ReportActionItem/MoneyRequestPreview/index.tsx +++ b/src/components/ReportActionItem/MoneyRequestPreview/index.tsx @@ -1,18 +1,44 @@ import lodashIsEmpty from 'lodash/isEmpty'; import React from 'react'; -import {useOnyx} from 'react-native-onyx'; +import {withOnyx} from 'react-native-onyx'; +import * as ReportActionsUtils from '@libs/ReportActionsUtils'; import ONYXKEYS from '@src/ONYXKEYS'; import MoneyRequestPreviewContent from './MoneyRequestPreviewContent'; -import type {MoneyRequestPreviewProps} from './types'; +import type {MoneyRequestPreviewOnyxProps, MoneyRequestPreviewProps} from './types'; function MoneyRequestPreview(props: MoneyRequestPreviewProps) { - const [iouReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${props.iouReportID || '-1'}`); // We should not render the component if there is no iouReport and it's not a split or track expense. // Moved outside of the component scope to allow for easier use of hooks in the main component. // eslint-disable-next-line react/jsx-props-no-spreading - return lodashIsEmpty(iouReport) && !(props.isBillSplit || props.isTrackExpense) ? null : ; + return lodashIsEmpty(props.iouReport) && !(props.isBillSplit || props.isTrackExpense) ? null : ; } MoneyRequestPreview.displayName = 'MoneyRequestPreview'; -export default MoneyRequestPreview; +export default withOnyx({ + personalDetails: { + key: ONYXKEYS.PERSONAL_DETAILS_LIST, + }, + chatReport: { + key: ({chatReportID}) => `${ONYXKEYS.COLLECTION.REPORT}${chatReportID}`, + }, + iouReport: { + key: ({iouReportID}) => `${ONYXKEYS.COLLECTION.REPORT}${iouReportID}`, + }, + session: { + key: ONYXKEYS.SESSION, + }, + transaction: { + key: ({action}) => { + const isMoneyRequestAction = ReportActionsUtils.isMoneyRequestAction(action); + const transactionID = isMoneyRequestAction ? ReportActionsUtils.getOriginalMessage(action)?.IOUTransactionID : 0; + return `${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`; + }, + }, + walletTerms: { + key: ONYXKEYS.WALLET_TERMS, + }, + transactionViolations: { + key: ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS, + }, +})(MoneyRequestPreview); diff --git a/src/components/ReportActionItem/MoneyRequestPreview/types.ts b/src/components/ReportActionItem/MoneyRequestPreview/types.ts index c40b45c6d2bd..021ae5d188d9 100644 --- a/src/components/ReportActionItem/MoneyRequestPreview/types.ts +++ b/src/components/ReportActionItem/MoneyRequestPreview/types.ts @@ -1,9 +1,33 @@ import type {GestureResponderEvent, StyleProp, ViewStyle} from 'react-native'; +import type {OnyxCollection, OnyxEntry} from 'react-native-onyx'; import type {ContextMenuAnchor} from '@pages/home/report/ContextMenu/ReportActionContextMenu'; import type * as OnyxTypes from '@src/types/onyx'; import type IconAsset from '@src/types/utils/IconAsset'; -type MoneyRequestPreviewProps = { +type MoneyRequestPreviewOnyxProps = { + /** All of the personal details for everyone */ + personalDetails: OnyxEntry; + + /** Chat report associated with iouReport */ + chatReport: OnyxEntry; + + /** IOU report data object */ + iouReport: OnyxEntry; + + /** Session info for the currently logged in user. */ + session: OnyxEntry; + + /** The transaction attached to the action.message.iouTransactionID */ + transaction: OnyxEntry; + + /** The transaction violations attached to the action.message.iouTransactionID */ + transactionViolations: OnyxCollection; + + /** Information about the user accepting the terms for payments */ + walletTerms: OnyxEntry; +}; + +type MoneyRequestPreviewProps = MoneyRequestPreviewOnyxProps & { /** The active IOUReport, used for Onyx subscription */ // The iouReportID is used inside withOnyx HOC // eslint-disable-next-line react/no-unused-prop-types @@ -66,4 +90,4 @@ type PendingProps = { type PendingMessageProps = PendingProps | NoPendingProps; -export type {MoneyRequestPreviewProps, PendingMessageProps}; +export type {MoneyRequestPreviewProps, MoneyRequestPreviewOnyxProps, PendingMessageProps}; diff --git a/src/libs/API/parameters/ResolveDuplicatesParams.ts b/src/libs/API/parameters/ResolveDuplicatesParams.ts deleted file mode 100644 index d225f227c0d7..000000000000 --- a/src/libs/API/parameters/ResolveDuplicatesParams.ts +++ /dev/null @@ -1,24 +0,0 @@ -type ResolveDuplicatesParams = { - /** The ID of the transaction that we want to keep */ - transactionID: string; - - /** The list of other duplicated transactions */ - transactionIDList: string[]; - created: string; - merchant: string; - amount: number; - currency: string; - category: string; - comment: string; - billable: boolean; - reimbursable: boolean; - tag: string; - - /** The reportActionID of the dismissed violation action in the kept transaction thread report */ - dismissedViolationReportActionID: string; - - /** The ID list of the hold report actions corresponding to the transactionIDList */ - reportActionIDList: string[]; -}; - -export default ResolveDuplicatesParams; diff --git a/src/libs/API/parameters/index.ts b/src/libs/API/parameters/index.ts index 9f51cab3f360..e5cde1b77be7 100644 --- a/src/libs/API/parameters/index.ts +++ b/src/libs/API/parameters/index.ts @@ -238,7 +238,6 @@ export type {default as SendInvoiceParams} from './SendInvoiceParams'; export type {default as PayInvoiceParams} from './PayInvoiceParams'; export type {default as MarkAsCashParams} from './MarkAsCashParams'; export type {default as TransactionMergeParams} from './TransactionMergeParams'; -export type {default as ResolveDuplicatesParams} from './ResolveDuplicatesParams'; export type {default as UpdateSubscriptionTypeParams} from './UpdateSubscriptionTypeParams'; export type {default as SignUpUserParams} from './SignUpUserParams'; export type {default as UpdateSubscriptionAutoRenewParams} from './UpdateSubscriptionAutoRenewParams'; diff --git a/src/libs/API/types.ts b/src/libs/API/types.ts index b72b77ae4739..8e35a0cb1984 100644 --- a/src/libs/API/types.ts +++ b/src/libs/API/types.ts @@ -285,7 +285,6 @@ const WRITE_COMMANDS = { PAY_INVOICE: 'PayInvoice', MARK_AS_CASH: 'MarkAsCash', TRANSACTION_MERGE: 'Transaction_Merge', - RESOLVE_DUPLICATES: 'ResolveDuplicates', UPDATE_SUBSCRIPTION_TYPE: 'UpdateSubscriptionType', SIGN_UP_USER: 'SignUpUser', UPDATE_SUBSCRIPTION_AUTO_RENEW: 'UpdateSubscriptionAutoRenew', @@ -704,7 +703,6 @@ type WriteCommandParameters = { [WRITE_COMMANDS.PAY_INVOICE]: Parameters.PayInvoiceParams; [WRITE_COMMANDS.MARK_AS_CASH]: Parameters.MarkAsCashParams; [WRITE_COMMANDS.TRANSACTION_MERGE]: Parameters.TransactionMergeParams; - [WRITE_COMMANDS.RESOLVE_DUPLICATES]: Parameters.ResolveDuplicatesParams; [WRITE_COMMANDS.UPDATE_SUBSCRIPTION_TYPE]: Parameters.UpdateSubscriptionTypeParams; [WRITE_COMMANDS.SIGN_UP_USER]: Parameters.SignUpUserParams; [WRITE_COMMANDS.UPDATE_SUBSCRIPTION_AUTO_RENEW]: Parameters.UpdateSubscriptionAutoRenewParams; diff --git a/src/libs/actions/IOU.ts b/src/libs/actions/IOU.ts index 5262cc4dc4ff..874056cac4a0 100644 --- a/src/libs/actions/IOU.ts +++ b/src/libs/actions/IOU.ts @@ -17,7 +17,6 @@ import type { PayMoneyRequestParams, ReplaceReceiptParams, RequestMoneyParams, - ResolveDuplicatesParams, SendInvoiceParams, SendMoneyParams, SetNameValuePairParams, @@ -8069,21 +8068,6 @@ function getIOURequestPolicyID(transaction: OnyxEntry, re return workspaceSender?.policyID ?? report?.policyID ?? '-1'; } -function getIOUActionForTransactions(transactionIDList: string[], iouReportID: string): Array> { - return Object.values(allReportActions?.[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${iouReportID}`] ?? {})?.filter( - (reportAction): reportAction is ReportAction => { - if (!ReportActionsUtils.isMoneyRequestAction(reportAction)) { - return false; - } - const message = ReportActionsUtils.getOriginalMessage(reportAction); - if (!message?.IOUTransactionID) { - return false; - } - return transactionIDList.includes(message.IOUTransactionID); - }, - ); -} - /** Merge several transactions into one by updating the fields of the one we want to keep and deleting the rest */ function mergeDuplicates(params: TransactionMergeParams) { const originalSelectedTransaction = allTransactions[`${ONYXKEYS.COLLECTION.TRANSACTION}${params.transactionID}`]; @@ -8168,7 +8152,18 @@ function mergeDuplicates(params: TransactionMergeParams) { }, }; - const iouActionsToDelete = getIOUActionForTransactions(params.transactionIDList, params.reportID); + const iouActionsToDelete = Object.values(allReportActions?.[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${params.reportID}`] ?? {})?.filter( + (reportAction): reportAction is ReportAction => { + if (!ReportActionsUtils.isMoneyRequestAction(reportAction)) { + return false; + } + const message = ReportActionsUtils.getOriginalMessage(reportAction); + if (!message?.IOUTransactionID) { + return false; + } + return params.transactionIDList.includes(message.IOUTransactionID); + }, + ); const deletedTime = DateUtils.getDBTime(); const expenseReportActionsOptimisticData: OnyxUpdate = { @@ -8229,125 +8224,6 @@ function mergeDuplicates(params: TransactionMergeParams) { API.write(WRITE_COMMANDS.TRANSACTION_MERGE, params, {optimisticData, failureData}); } -/** Instead of merging the duplicates, it updates the transaction we want to keep and puts the others on hold without deleting them */ -function resolveDuplicates(params: TransactionMergeParams) { - const originalSelectedTransaction = allTransactions[`${ONYXKEYS.COLLECTION.TRANSACTION}${params.transactionID}`]; - - const optimisticTransactionData: OnyxUpdate = { - onyxMethod: Onyx.METHOD.MERGE, - key: `${ONYXKEYS.COLLECTION.TRANSACTION}${params.transactionID}`, - value: { - ...originalSelectedTransaction, - billable: params.billable, - comment: { - comment: params.comment, - }, - category: params.category, - created: params.created, - currency: params.currency, - modifiedMerchant: params.merchant, - reimbursable: params.reimbursable, - tag: params.tag, - }, - }; - - const failureTransactionData: OnyxUpdate = { - onyxMethod: Onyx.METHOD.MERGE, - key: `${ONYXKEYS.COLLECTION.TRANSACTION}${params.transactionID}`, - // eslint-disable-next-line @typescript-eslint/non-nullable-type-assertion-style - value: originalSelectedTransaction as OnyxTypes.Transaction, - }; - - const optimisticTransactionViolations: OnyxUpdate[] = [...params.transactionIDList, params.transactionID].map((id) => { - const violations = allTransactionViolations[`${ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS}${id}`] ?? []; - const newViolation = {name: CONST.VIOLATIONS.HOLD, type: CONST.VIOLATION_TYPES.VIOLATION}; - const updatedViolations = id === params.transactionID ? violations : [...violations, newViolation]; - return { - onyxMethod: Onyx.METHOD.MERGE, - key: `${ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS}${id}`, - value: updatedViolations.filter((violation) => violation.name !== CONST.VIOLATIONS.DUPLICATED_TRANSACTION), - }; - }); - - const failureTransactionViolations: OnyxUpdate[] = [...params.transactionIDList, params.transactionID].map((id) => { - const violations = allTransactionViolations[`${ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS}${id}`] ?? []; - return { - onyxMethod: Onyx.METHOD.MERGE, - key: `${ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS}${id}`, - value: violations, - }; - }); - - const iouActionList = getIOUActionForTransactions(params.transactionIDList, params.reportID); - const transactionThreadReportIDList = iouActionList.map((action) => action?.childReportID); - const orderedTransactionIDList = iouActionList.map((action) => { - const message = ReportActionsUtils.getOriginalMessage(action); - return message?.IOUTransactionID ?? ''; - }); - - const optimisticHoldActions: OnyxUpdate[] = []; - const failureHoldActions: OnyxUpdate[] = []; - const reportActionIDList: string[] = []; - transactionThreadReportIDList.forEach((transactionThreadReportID) => { - const createdReportAction = ReportUtils.buildOptimisticHoldReportAction(); - reportActionIDList.push(createdReportAction.reportActionID); - optimisticHoldActions.push({ - onyxMethod: Onyx.METHOD.MERGE, - key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${transactionThreadReportID}`, - value: { - [createdReportAction.reportActionID]: createdReportAction, - }, - }); - failureHoldActions.push({ - onyxMethod: Onyx.METHOD.MERGE, - key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${transactionThreadReportID}`, - value: { - [createdReportAction.reportActionID]: { - errors: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('iou.error.genericHoldExpenseFailureMessage'), - }, - }, - }); - }); - - const transactionThreadReportID = getIOUActionForTransactions([params.transactionID], params.reportID)?.[0]?.childReportID; - const optimisticReportAction = ReportUtils.buildOptimisticDismissedViolationReportAction({ - reason: 'manual', - violationName: CONST.VIOLATIONS.DUPLICATED_TRANSACTION, - }); - - const optimisticReportActionData: OnyxUpdate = { - onyxMethod: Onyx.METHOD.MERGE, - key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${transactionThreadReportID}`, - value: { - [optimisticReportAction.reportActionID]: optimisticReportAction, - }, - }; - - const failureReportActionData: OnyxUpdate = { - onyxMethod: Onyx.METHOD.MERGE, - key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${transactionThreadReportID}`, - value: { - [optimisticReportAction.reportActionID]: null, - }, - }; - - const optimisticData: OnyxUpdate[] = []; - const failureData: OnyxUpdate[] = []; - - optimisticData.push(optimisticTransactionData, ...optimisticTransactionViolations, ...optimisticHoldActions, optimisticReportActionData); - failureData.push(failureTransactionData, ...failureTransactionViolations, ...failureHoldActions, failureReportActionData); - const {reportID, transactionIDList, receiptID, ...otherParams} = params; - - const parameters: ResolveDuplicatesParams = { - ...otherParams, - reportActionIDList, - transactionIDList: orderedTransactionIDList, - dismissedViolationReportActionID: optimisticReportAction.reportActionID, - }; - - API.write(WRITE_COMMANDS.RESOLVE_DUPLICATES, parameters, {optimisticData, failureData}); -} - export { adjustRemainingSplitShares, getNextApproverAccountID, @@ -8419,7 +8295,5 @@ export { updateMoneyRequestTaxAmount, updateMoneyRequestTaxRate, mergeDuplicates, - resolveDuplicates, - prepareToCleanUpMoneyRequest, }; export type {GPSPoint as GpsPoint, IOURequestType}; diff --git a/src/pages/TransactionDuplicate/Confirmation.tsx b/src/pages/TransactionDuplicate/Confirmation.tsx index b9a4adb729e2..15217e215ad4 100644 --- a/src/pages/TransactionDuplicate/Confirmation.tsx +++ b/src/pages/TransactionDuplicate/Confirmation.tsx @@ -14,7 +14,6 @@ import ScreenWrapper from '@components/ScreenWrapper'; import ScrollView from '@components/ScrollView'; import {ShowContextMenuContext} from '@components/ShowContextMenuContext'; import Text from '@components/Text'; -import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails'; import useLocalize from '@hooks/useLocalize'; import useReviewDuplicatesNavigation from '@hooks/useReviewDuplicatesNavigation'; import useThemeStyles from '@hooks/useThemeStyles'; @@ -35,7 +34,6 @@ import isLoadingOnyxValue from '@src/types/utils/isLoadingOnyxValue'; function Confirmation() { const styles = useThemeStyles(); const {translate} = useLocalize(); - const currentUserPersonalDetails = useCurrentUserPersonalDetails(); const route = useRoute>(); const [reviewDuplicates, reviewDuplicatesResult] = useOnyx(ONYXKEYS.REVIEW_DUPLICATES); const transaction = useMemo(() => TransactionUtils.buildNewTransactionAfterReviewingDuplicates(reviewDuplicates), [reviewDuplicates]); @@ -43,26 +41,17 @@ function Confirmation() { const compareResult = TransactionUtils.compareDuplicateTransactionFields(transactionID); const {goBack} = useReviewDuplicatesNavigation(Object.keys(compareResult.change ?? {}), 'confirmation', route.params.threadReportID, route.params.backTo); const [report, reportResult] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${route.params.threadReportID}`); - const [iouReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${transaction?.reportID}`); const [reportActions] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${transaction?.reportID}`); const reportAction = Object.values(reportActions ?? {}).find( (action) => ReportActionsUtils.isMoneyRequestAction(action) && ReportActionsUtils.getOriginalMessage(action)?.IOUTransactionID === reviewDuplicates?.transactionID, ); - const isReportOwner = iouReport?.ownerAccountID === currentUserPersonalDetails?.accountID; - const transactionsMergeParams = useMemo(() => TransactionUtils.buildTransactionsMergeParams(reviewDuplicates, transaction), [reviewDuplicates, transaction]); - const mergeDuplicates = useCallback(() => { IOU.mergeDuplicates(transactionsMergeParams); Navigation.navigate(ROUTES.REPORT_WITH_ID.getRoute(reportAction?.childReportID ?? '-1')); }, [reportAction?.childReportID, transactionsMergeParams]); - const resolveDuplicates = useCallback(() => { - IOU.resolveDuplicates(transactionsMergeParams); - Navigation.navigate(ROUTES.REPORT_WITH_ID.getRoute(reportAction?.childReportID ?? '-1')); - }, [transactionsMergeParams, reportAction?.childReportID]); - const contextValue = useMemo( () => ({ transactionThreadReport: report, @@ -127,13 +116,7 @@ function Confirmation() {