From ebb0330ca92a456593c77b1eaaa70530e0fe3dc3 Mon Sep 17 00:00:00 2001
From: parasharrajat <parasharrajat@users.noreply.github.com>
Date: Fri, 21 Nov 2025 22:44:41 +0530
Subject: [PATCH 1/4] Revert "Revert "Trigger whisper when user invites a
 member to the chat ""

---
 src/libs/ReportActionsUtils.ts                |  7 ++++++
 src/libs/actions/Report.ts                    |  8 +++++++
 src/pages/RoomInvitePage.tsx                  | 22 ++++++++++++++-----
 .../home/report/PureReportActionItem.tsx      |  8 +++++--
 4 files changed, 37 insertions(+), 8 deletions(-)

diff --git a/src/libs/ReportActionsUtils.ts b/src/libs/ReportActionsUtils.ts
index 4a4578c212c9..0c0d4ecb12ed 100644
--- a/src/libs/ReportActionsUtils.ts
+++ b/src/libs/ReportActionsUtils.ts
@@ -3338,6 +3338,12 @@ function getSubmittedTo(action: OnyxEntry<ReportAction>): string | undefined {
     return getOriginalMessage(action)?.to;
 }
 
+function isSystemUserMentioned(action: OnyxInputOrEntry<ReportAction<typeof CONST.REPORT.ACTIONS.TYPE.ACTIONABLE_MENTION_WHISPER>>): boolean {
+    const mentionedUsers = getOriginalMessage(action)?.inviteeAccountIDs;
+    const systemAccountIDs = new Set(Object.values(CONST.ACCOUNT_ID));
+    return mentionedUsers?.some((accountID) => systemAccountIDs.has(accountID)) ?? false;
+}
+
 export {
     doesReportHaveVisibleActions,
     extractLinksFromMessageHtml,
@@ -3519,6 +3525,7 @@ export {
     isPendingHide,
     filterOutDeprecatedReportActions,
     getActionableCardFraudAlertMessage,
+    isSystemUserMentioned,
 };
 
 export type {LastVisibleMessage};
diff --git a/src/libs/actions/Report.ts b/src/libs/actions/Report.ts
index 12484f9a5d6e..d8a495edc178 100644
--- a/src/libs/actions/Report.ts
+++ b/src/libs/actions/Report.ts
@@ -3853,6 +3853,13 @@ function inviteToRoom(reportID: string, inviteeEmailsToAccountIDs: InvitedEmails
     API.write(WRITE_COMMANDS.INVITE_TO_ROOM, parameters, {optimisticData, successData, failureData});
 }
 
+/** Invites people to a room via concierge whisper */
+function inviteToRoomAction(reportID: string, ancestors: Ancestor[], inviteeEmailsToAccountIDs: InvitedEmailsToAccountIDs, timezoneParam: Timezone) {
+    const inviteeEmails = Object.keys(inviteeEmailsToAccountIDs);
+
+    addComment(reportID, reportID, ancestors, inviteeEmails.map((login) => `@${login}`).join(' '), timezoneParam, false);
+}
+
 function clearAddRoomMemberError(reportID: string, invitedAccountID: string) {
     const reportMetadata = getReportMetadata(reportID);
     Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT}${reportID}`, {
@@ -6082,6 +6089,7 @@ export {
     inviteToGroupChat,
     buildInviteToRoomOnyxData,
     inviteToRoom,
+    inviteToRoomAction,
     joinRoom,
     leaveGroupChat,
     leaveRoom,
diff --git a/src/pages/RoomInvitePage.tsx b/src/pages/RoomInvitePage.tsx
index 3740053d382e..01eca5ddfae7 100644
--- a/src/pages/RoomInvitePage.tsx
+++ b/src/pages/RoomInvitePage.tsx
@@ -12,12 +12,14 @@ import InviteMemberListItem from '@components/SelectionListWithSections/InviteMe
 import type {Section} from '@components/SelectionListWithSections/types';
 import withNavigationTransitionEnd from '@components/withNavigationTransitionEnd';
 import type {WithNavigationTransitionEndProps} from '@components/withNavigationTransitionEnd';
+import useAncestors from '@hooks/useAncestors';
+import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails';
 import useDebouncedState from '@hooks/useDebouncedState';
 import useLocalize from '@hooks/useLocalize';
 import useOnyx from '@hooks/useOnyx';
 import useReportIsArchived from '@hooks/useReportIsArchived';
 import useThemeStyles from '@hooks/useThemeStyles';
-import {inviteToRoom, searchInServer} from '@libs/actions/Report';
+import {inviteToRoomAction, searchInServer} from '@libs/actions/Report';
 import {clearUserSearchPhrase, updateUserSearchPhrase} from '@libs/actions/RoomMembersUserSearchPhrase';
 import {READ_COMMANDS} from '@libs/API/types';
 import {canUseTouchScreen} from '@libs/DeviceCapabilities';
@@ -55,13 +57,14 @@ function RoomInvitePage({
     },
 }: RoomInvitePageProps) {
     const styles = useThemeStyles();
-    const {translate, formatPhoneNumber} = useLocalize();
+    const {translate} = useLocalize();
     const [userSearchPhrase] = useOnyx(ONYXKEYS.ROOM_MEMBERS_USER_SEARCH_PHRASE, {canBeMissing: true});
     const [countryCode = CONST.DEFAULT_COUNTRY_CODE] = useOnyx(ONYXKEYS.COUNTRY_CODE, {canBeMissing: false});
     const [searchTerm, debouncedSearchTerm, setSearchTerm] = useDebouncedState(userSearchPhrase ?? '');
     const [selectedOptions, setSelectedOptions] = useState<OptionData[]>([]);
     const [isSearchingForReports] = useOnyx(ONYXKEYS.IS_SEARCHING_FOR_REPORTS, {initWithStoredValues: false, canBeMissing: true});
     const isReportArchived = useReportIsArchived(report.reportID);
+    const currentUserPersonalDetails = useCurrentUserPersonalDetails();
     const [nvpDismissedProductTraining] = useOnyx(ONYXKEYS.NVP_DISMISSED_PRODUCT_TRAINING, {canBeMissing: true});
 
     const {options, areOptionsInitialized} = useOptionsList();
@@ -192,6 +195,9 @@ function RoomInvitePage({
         return reportID && (!isPolicyEmployee || isReportArchived ? ROUTES.REPORT_WITH_ID_DETAILS.getRoute(reportID, backTo) : ROUTES.ROOM_MEMBERS.getRoute(reportID, backTo));
     }, [isPolicyEmployee, reportID, backTo, isReportArchived]);
     const reportName = useMemo(() => getReportName(report), [report]);
+
+    const ancestors = useAncestors(report);
+
     const inviteUsers = useCallback(() => {
         HttpUtils.cancelPendingRequests(READ_COMMANDS.SEARCH_FOR_REPORTS);
 
@@ -208,11 +214,15 @@ function RoomInvitePage({
             invitedEmailsToAccountIDs[login] = Number(accountID);
         }
         if (reportID) {
-            inviteToRoom(reportID, invitedEmailsToAccountIDs, formatPhoneNumber);
+            inviteToRoomAction(reportID, ancestors, invitedEmailsToAccountIDs, currentUserPersonalDetails.timezone ?? CONST.DEFAULT_TIME_ZONE);
+            clearUserSearchPhrase();
+            if (backTo) {
+                Navigation.goBack(backTo);
+            } else {
+                Navigation.goBack(ROUTES.REPORT_WITH_ID.getRoute(reportID));
+            }
         }
-        clearUserSearchPhrase();
-        Navigation.goBack(backRoute);
-    }, [selectedOptions, backRoute, reportID, validate, formatPhoneNumber]);
+    }, [validate, selectedOptions, ancestors, reportID, currentUserPersonalDetails.timezone, backTo]);
 
     const goBack = useCallback(() => {
         Navigation.goBack(backRoute);
diff --git a/src/pages/home/report/PureReportActionItem.tsx b/src/pages/home/report/PureReportActionItem.tsx
index 6b68c52ef9a0..703075cd9da3 100644
--- a/src/pages/home/report/PureReportActionItem.tsx
+++ b/src/pages/home/report/PureReportActionItem.tsx
@@ -58,7 +58,7 @@ import {isReportMessageAttachment} from '@libs/isReportMessageAttachment';
 import Navigation from '@libs/Navigation/Navigation';
 import Permissions from '@libs/Permissions';
 import {getDisplayNameOrDefault} from '@libs/PersonalDetailsUtils';
-import {getCleanedTagName, getPersonalPolicy, isPolicyAdmin, isPolicyOwner} from '@libs/PolicyUtils';
+import {getCleanedTagName, getPersonalPolicy, isPolicyAdmin, isPolicyOwner, isPolicyUser} from '@libs/PolicyUtils';
 import {
     extractLinksFromMessageHtml,
     getActionableCardFraudAlertMessage,
@@ -132,6 +132,7 @@ import {
     isRenamedAction,
     isResolvedConciergeCategoryOptions,
     isSplitBillAction as isSplitBillActionReportActionsUtils,
+    isSystemUserMentioned,
     isTagModificationAction,
     isTaskAction,
     isTrackExpenseAction as isTrackExpenseActionReportActionsUtils,
@@ -906,7 +907,10 @@ function PureReportActionItem({
         const actionableMentionWhisperOptions = [];
         const isReportInPolicy = !!report?.policyID && report.policyID !== CONST.POLICY.ID_FAKE && getPersonalPolicy()?.id !== report.policyID;
 
-        if (isReportInPolicy && (isPolicyAdmin(policy) || isPolicyOwner(policy, currentUserAccountID))) {
+        // Show the invite to submit expense button even if one of the mentioned users is a not a policy member
+        const hasMentionedPolicyMembers = getOriginalMessage(action)?.inviteeEmails?.every((login) => isPolicyUser(policy, login)) ?? false;
+
+        if ((isPolicyAdmin(policy) || isPolicyOwner(policy, currentUserAccountID)) && isReportInPolicy && !isSystemUserMentioned(action) && !hasMentionedPolicyMembers) {
             actionableMentionWhisperOptions.push({
                 text: 'actionableMentionWhisperOptions.inviteToSubmitExpense',
                 key: `${action.reportActionID}-actionableMentionWhisper-${CONST.REPORT.ACTIONABLE_MENTION_WHISPER_RESOLUTION.INVITE_TO_SUBMIT_EXPENSE}`,

From 284036d5b7d962730f0d1336673e0880d26b3808 Mon Sep 17 00:00:00 2001
From: Rajat Parashar <parasharrajat@users.noreply.github.com>
Date: Mon, 1 Dec 2025 11:41:31 +0530
Subject: [PATCH 2/4] Use Correct member method

---
 .../home/report/PureReportActionItem.tsx      | 27 +++----------------
 1 file changed, 3 insertions(+), 24 deletions(-)

diff --git a/src/pages/home/report/PureReportActionItem.tsx b/src/pages/home/report/PureReportActionItem.tsx
index 8cfe8f7685b0..eb2110869d1e 100644
--- a/src/pages/home/report/PureReportActionItem.tsx
+++ b/src/pages/home/report/PureReportActionItem.tsx
@@ -58,7 +58,7 @@ import {isReportMessageAttachment} from '@libs/isReportMessageAttachment';
 import Navigation from '@libs/Navigation/Navigation';
 import Permissions from '@libs/Permissions';
 import {getDisplayNameOrDefault} from '@libs/PersonalDetailsUtils';
-import {getCleanedTagName, getPersonalPolicy, isPolicyAdmin, isPolicyOwner, isPolicyUser} from '@libs/PolicyUtils';
+import {getCleanedTagName, getPersonalPolicy, isPolicyAdmin, isPolicyMember, isPolicyOwner} from '@libs/PolicyUtils';
 import {
     extractLinksFromMessageHtml,
     getActionableCardFraudAlertMessage,
@@ -941,7 +941,7 @@ function PureReportActionItem({
         const isReportInPolicy = !!report?.policyID && report.policyID !== CONST.POLICY.ID_FAKE && getPersonalPolicy()?.id !== report.policyID;
 
         // Show the invite to submit expense button even if one of the mentioned users is a not a policy member
-        const hasMentionedPolicyMembers = getOriginalMessage(action)?.inviteeEmails?.every((login) => isPolicyUser(policy, login)) ?? false;
+        const hasMentionedPolicyMembers = getOriginalMessage(action)?.inviteeEmails?.every((login) => isPolicyMember(policy, login)) ?? false;
 
         if ((isPolicyAdmin(policy) || isPolicyOwner(policy, currentUserAccountID)) && isReportInPolicy && !isSystemUserMentioned(action) && !hasMentionedPolicyMembers) {
             actionableMentionWhisperOptions.push({
@@ -968,28 +968,7 @@ function PureReportActionItem({
             },
         );
         return actionableMentionWhisperOptions;
-    }, [
-        action,
-        userBillingFundID,
-        originalReportID,
-        reportID,
-        isActionableWhisper,
-        report?.policyID,
-        policy,
-        currentUserAccountID,
-        personalDetail.timezone,
-        createDraftTransactionAndNavigateToParticipantSelector,
-        isRestrictedToPreferredPolicy,
-        preferredPolicyID,
-        dismissTrackExpenseActionableWhisper,
-        translate,
-        resolveActionableReportMentionWhisper,
-        isReportArchived,
-        formatPhoneNumber,
-        isOriginalReportArchived,
-        resolveActionableMentionWhisper,
-        introSelected,
-    ]);
+    }, [action, userBillingFundID, originalReportID, reportID, isActionableWhisper, report?.policyID, policy, currentUserAccountID, personalDetail.timezone, createDraftTransactionAndNavigateToParticipantSelector, isRestrictedToPreferredPolicy, preferredPolicyID, dismissTrackExpenseActionableWhisper, translate, resolveActionableReportMentionWhisper, isReportArchived, isOriginalReportArchived, resolveActionableMentionWhisper, introSelected]);
 
     /**
      * Get the content of ReportActionItem

From 0aa2338f4cfc75fb3264b029a0cb063045e587a6 Mon Sep 17 00:00:00 2001
From: Rajat Parashar <parasharrajat@users.noreply.github.com>
Date: Mon, 1 Dec 2025 14:09:59 +0530
Subject: [PATCH 3/4] prettier fix

---
 .../home/report/PureReportActionItem.tsx      | 22 ++++++++++++++++++-
 1 file changed, 21 insertions(+), 1 deletion(-)

diff --git a/src/pages/home/report/PureReportActionItem.tsx b/src/pages/home/report/PureReportActionItem.tsx
index eb2110869d1e..806c4f9531fe 100644
--- a/src/pages/home/report/PureReportActionItem.tsx
+++ b/src/pages/home/report/PureReportActionItem.tsx
@@ -968,7 +968,27 @@ function PureReportActionItem({
             },
         );
         return actionableMentionWhisperOptions;
-    }, [action, userBillingFundID, originalReportID, reportID, isActionableWhisper, report?.policyID, policy, currentUserAccountID, personalDetail.timezone, createDraftTransactionAndNavigateToParticipantSelector, isRestrictedToPreferredPolicy, preferredPolicyID, dismissTrackExpenseActionableWhisper, translate, resolveActionableReportMentionWhisper, isReportArchived, isOriginalReportArchived, resolveActionableMentionWhisper, introSelected]);
+    }, [
+        action,
+        userBillingFundID,
+        originalReportID,
+        reportID,
+        isActionableWhisper,
+        report?.policyID,
+        policy,
+        currentUserAccountID,
+        personalDetail.timezone,
+        createDraftTransactionAndNavigateToParticipantSelector,
+        isRestrictedToPreferredPolicy,
+        preferredPolicyID,
+        dismissTrackExpenseActionableWhisper,
+        translate,
+        resolveActionableReportMentionWhisper,
+        isReportArchived,
+        isOriginalReportArchived,
+        resolveActionableMentionWhisper,
+        introSelected,
+    ]);
 
     /**
      * Get the content of ReportActionItem

From 4cb566d850a8f45345efcb26026c19a3b3a2b926 Mon Sep 17 00:00:00 2001
From: Rajat Parashar <parasharrajat@users.noreply.github.com>
Date: Wed, 10 Dec 2025 23:02:52 +0530
Subject: [PATCH 4/4] Fix lint

---
 src/pages/RoomInvitePage.tsx | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/src/pages/RoomInvitePage.tsx b/src/pages/RoomInvitePage.tsx
index 51e9558e2276..3f005c9b174a 100644
--- a/src/pages/RoomInvitePage.tsx
+++ b/src/pages/RoomInvitePage.tsx
@@ -194,6 +194,8 @@ function RoomInvitePage({
     const backRoute = useMemo(() => {
         return reportID && (!isPolicyEmployee || isReportArchived ? ROUTES.REPORT_WITH_ID_DETAILS.getRoute(reportID, backTo) : ROUTES.ROOM_MEMBERS.getRoute(reportID, backTo));
     }, [isPolicyEmployee, reportID, backTo, isReportArchived]);
+
+    // eslint-disable-next-line @typescript-eslint/no-deprecated
     const reportName = useMemo(() => getReportName(report), [report]);
 
     const ancestors = useAncestors(report);
