Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,12 @@ import TransactionPreviewContent from './TransactionPreviewContent';
import type {TransactionPreviewProps} from './types';

const getOriginalTransactionIfBillIsSplit = (transaction: OnyxEntry<Transaction>) => {
const {originalTransactionID, source} = transaction?.comment ?? {};
const {originalTransactionID, source, splits} = transaction?.comment ?? {};

// If splits property is defined in the transaction, it is actually an original transaction
if (splits && splits.length > 0) {
return {isSplit: true, originalTransaction: transaction};
}

if (!originalTransactionID || source !== CONST.IOU.TYPE.SPLIT) {
return {isSplit: false, originalTransaction: transaction};
Expand All @@ -40,7 +45,7 @@ function TransactionPreview(props: TransactionPreviewProps) {
const [report] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${route.params?.threadReportID}`, {canBeMissing: true});
const isMoneyRequestAction = isMoneyRequestActionReportActionsUtils(action);
const transactionID = transactionIDFromProps ?? (isMoneyRequestAction ? getOriginalMessage(action)?.IOUTransactionID : null);
const [transaction] = useOnyx(`${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`, {canBeMissing: true});
const [transaction] = useOnyx(`${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`, {canBeMissing: false});
const violations = useTransactionViolations(transaction?.transactionID);
const [walletTerms] = useOnyx(ONYXKEYS.WALLET_TERMS, {canBeMissing: true});
const [session] = useOnyx(ONYXKEYS.SESSION, {canBeMissing: true});
Expand Down
26 changes: 12 additions & 14 deletions src/libs/ReportActionsUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -515,18 +515,18 @@ function getCombinedReportActions(
return getSortedReportActions(filteredReportActions, true);
}

const iouRequestTypes: Array<ValueOf<typeof CONST.IOU.REPORT_ACTION_TYPE>> = [CONST.IOU.REPORT_ACTION_TYPE.CREATE, CONST.IOU.REPORT_ACTION_TYPE.SPLIT, CONST.IOU.REPORT_ACTION_TYPE.TRACK];

// Get all IOU report actions for the report.
const iouRequestTypesSet = new Set<ValueOf<typeof CONST.IOU.REPORT_ACTION_TYPE>>([...iouRequestTypes, CONST.IOU.REPORT_ACTION_TYPE.PAY]);

/**
* Finds most recent IOU request action ID.
*/
function getMostRecentIOURequestActionID(reportActions: ReportAction[] | null): string | null {
if (!Array.isArray(reportActions)) {
return null;
}
const iouRequestTypes: Array<ValueOf<typeof CONST.IOU.REPORT_ACTION_TYPE>> = [
CONST.IOU.REPORT_ACTION_TYPE.CREATE,
CONST.IOU.REPORT_ACTION_TYPE.SPLIT,
CONST.IOU.REPORT_ACTION_TYPE.TRACK,
];
const iouRequestActions =
reportActions?.filter((action) => {
if (!isActionOfType(action, CONST.REPORT.ACTIONS.TYPE.IOU)) {
Expand Down Expand Up @@ -1160,6 +1160,11 @@ function isSplitBillAction(reportAction: OnyxInputOrEntry<ReportAction>): report
return isActionOfType(reportAction, CONST.REPORT.ACTIONS.TYPE.IOU) && getOriginalMessage(reportAction)?.type === CONST.IOU.REPORT_ACTION_TYPE.SPLIT;
}

function isIOURequestReportAction(reportAction: OnyxInputOrEntry<ReportAction>): boolean {
const type = isMoneyRequestAction(reportAction) && getOriginalMessage(reportAction)?.type;
return !!type && iouRequestTypes.includes(type);
}

function isTrackExpenseAction(reportAction: OnyxEntry<ReportAction | OptimisticIOUReportAction>): reportAction is ReportAction<typeof CONST.REPORT.ACTIONS.TYPE.IOU> {
return isActionOfType(reportAction, CONST.REPORT.ACTIONS.TYPE.IOU) && getOriginalMessage(reportAction)?.type === CONST.IOU.REPORT_ACTION_TYPE.TRACK;
}
Expand Down Expand Up @@ -1193,14 +1198,6 @@ function isTagModificationAction(actionName: string): boolean {
);
}

// Get all IOU report actions for the report.
const iouRequestTypes = new Set<ValueOf<typeof CONST.IOU.REPORT_ACTION_TYPE>>([
CONST.IOU.REPORT_ACTION_TYPE.CREATE,
CONST.IOU.REPORT_ACTION_TYPE.SPLIT,
CONST.IOU.REPORT_ACTION_TYPE.PAY,
CONST.IOU.REPORT_ACTION_TYPE.TRACK,
]);

/**
* Gets the reportID for the transaction thread associated with a report by iterating over the reportActions and identifying the IOU report actions.
* Returns a reportID if there is exactly one transaction thread for the report, and null otherwise.
Expand Down Expand Up @@ -1232,7 +1229,7 @@ function getOneTransactionThreadReportID(
const actionType = originalMessage?.type;
if (
actionType &&
iouRequestTypes.has(actionType) &&
iouRequestTypesSet.has(actionType) &&
action.childReportID &&
// Include deleted IOU reportActions if:
// - they have an assocaited IOU transaction ID or
Expand Down Expand Up @@ -2418,6 +2415,7 @@ export {
isResolvedConciergeCategoryOptions,
isAddCommentAction,
isApprovedOrSubmittedReportAction,
isIOURequestReportAction,
isChronosOOOListAction,
isClosedAction,
isConsecutiveActionMadeByPreviousActor,
Expand Down
38 changes: 24 additions & 14 deletions src/pages/home/report/PureReportActionItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ import {
isCreatedTaskReportAction,
isDeletedAction,
isDeletedParentAction as isDeletedParentActionUtils,
isIOURequestReportAction,
isMessageDeleted,
isMoneyRequestAction,
isPendingRemove,
Expand All @@ -111,6 +112,7 @@ import {
isWhisperActionTargetedToOthers,
useNewTableReportViewActionRenderConditionals,
} from '@libs/ReportActionsUtils';
import type {MissingPaymentMethod} from '@libs/ReportUtils';
import {
canWriteInReport,
chatIncludesConcierge,
Expand Down Expand Up @@ -138,7 +140,6 @@ import {
isTaskReport,
shouldDisplayThreadReplies as shouldDisplayThreadRepliesUtils,
} from '@libs/ReportUtils';
import type {MissingPaymentMethod} from '@libs/ReportUtils';
import SelectionScraper from '@libs/SelectionScraper';
import shouldRenderAddPaymentCard from '@libs/shouldRenderAppPaymentCard';
import {ReactionListContext} from '@pages/home/ReportScreenContext';
Expand All @@ -150,8 +151,8 @@ import {addComment, expandURLPreview} from '@userActions/Report';
import type {IgnoreDirection} from '@userActions/ReportActions';
import {isAnonymousUser, signOutAndRedirectToSignIn} from '@userActions/Session';
import {isBlockedFromConcierge} from '@userActions/User';
import CONST from '@src/CONST';
import type {IOUAction} from '@src/CONST';
import CONST from '@src/CONST';
import ROUTES from '@src/ROUTES';
import type * as OnyxTypes from '@src/types/onyx';
import type {Errors} from '@src/types/onyx/OnyxCommon';
Expand Down Expand Up @@ -771,22 +772,19 @@ function PureReportActionItem({
*/
const renderItemContent = (hovered = false, isWhisper = false, hasErrors = false): React.JSX.Element => {
let children;
const moneyRequestOriginalMessage = isMoneyRequestAction(action) ? getOriginalMessage(action) : undefined;
const moneyRequestActionType = moneyRequestOriginalMessage?.type;

// Show the MoneyRequestPreview for when expense is present
if (
isMoneyRequestAction(action) &&
getOriginalMessage(action) &&
// For the pay flow, we only want to show MoneyRequestAction when sending money. When paying, we display a regular system message
(getOriginalMessage(action)?.type === CONST.IOU.REPORT_ACTION_TYPE.CREATE ||
getOriginalMessage(action)?.type === CONST.IOU.REPORT_ACTION_TYPE.SPLIT ||
getOriginalMessage(action)?.type === CONST.IOU.REPORT_ACTION_TYPE.TRACK)
) {
if (isIOURequestReportAction(action)) {
const isSplitInGroupChat = moneyRequestActionType === CONST.IOU.REPORT_ACTION_TYPE.SPLIT && report?.chatType === CONST.REPORT.CHAT_TYPE.GROUP;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can split in rooms too and that check should be included to show the split in the chat. More details here. #64725

const chatReportID = moneyRequestOriginalMessage?.IOUReportID ? report?.chatReportID : reportID;
// There is no single iouReport for bill splits, so only 1:1 requests require an iouReportID
const iouReportID = getOriginalMessage(action)?.IOUReportID?.toString();
const iouReportID = moneyRequestOriginalMessage?.IOUReportID?.toString();
children = (
<MoneyRequestAction
// If originalMessage.iouReportID is set, this is a 1:1 IOU expense in a DM chat whose reportID is report.chatReportID
chatReportID={getOriginalMessage(action)?.IOUReportID ? report?.chatReportID : reportID}
chatReportID={chatReportID}
requestReportID={iouReportID}
reportID={reportID}
action={action}
Expand All @@ -802,7 +800,7 @@ function PureReportActionItem({

// Table Report View does not display these components as separate messages, except for self-DM
if (canUseTableReportView && report?.type === CONST.REPORT.TYPE.CHAT) {
if (report.chatType === CONST.REPORT.CHAT_TYPE.SELF_DM && !isDeletedAction(action)) {
if ((report.chatType === CONST.REPORT.CHAT_TYPE.SELF_DM && !isDeletedAction(action)) || isSplitInGroupChat) {
children = (
<View style={[styles.mt1, styles.w100]}>
<TransactionPreview
Expand All @@ -811,8 +809,20 @@ function PureReportActionItem({
reportID={reportID}
action={action}
isBillSplit={isSplitBillActionReportActionsUtils(action)}
transactionID={isSplitInGroupChat ? moneyRequestOriginalMessage?.IOUTransactionID : undefined}
wrapperStyle={shouldUseNarrowLayout ? {...styles.w100, ...styles.mw100} : reportPreviewStyles.transactionPreviewStyle}
onPreviewPressed={() => {}}
onPreviewPressed={() => {
if (isSplitInGroupChat) {
Navigation.navigate(ROUTES.SPLIT_BILL_DETAILS.getRoute(chatReportID, action.reportActionID, Navigation.getReportRHPActiveRoute()));
return;
}

if (!action.childReportID) {
return;
}

Navigation.navigate(ROUTES.REPORT_WITH_ID.getRoute(action.childReportID));
Comment thread
mountiny marked this conversation as resolved.
}}
isTrackExpense={isTrackExpenseActionReportActionsUtils(action)}
/>
</View>
Expand Down