From d2faade5300bedc766ec0774874fd7c4100afb05 Mon Sep 17 00:00:00 2001 From: Bernhard Owen Josephus Date: Mon, 6 Jul 2026 13:39:02 +0800 Subject: [PATCH 1/4] refactor getSubmitToEmail and getSubmitToAccountID --- src/hooks/useReportSubmitToPopover.tsx | 4 ++- src/libs/PolicyUtils.ts | 36 ++++++++++---------------- src/pages/ReportSubmitToContent.tsx | 4 +-- 3 files changed, 18 insertions(+), 26 deletions(-) diff --git a/src/hooks/useReportSubmitToPopover.tsx b/src/hooks/useReportSubmitToPopover.tsx index 3e970cad0d97..af166d1dd665 100644 --- a/src/hooks/useReportSubmitToPopover.tsx +++ b/src/hooks/useReportSubmitToPopover.tsx @@ -7,6 +7,7 @@ import ReportSubmitToContent from '@pages/ReportSubmitToContent'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; +import {personalDetailsLoginSelector} from '@src/selectors/PersonalDetails'; import type AnchorAlignment from '@src/types/utils/AnchorAlignment'; import type {RefObject} from 'react'; @@ -91,8 +92,9 @@ function useReportSubmitToPopover({reportID, onSubmitSuccess, anchorAlignment = const [policy] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY}${getNonEmptyStringOnyxID(report?.policyID)}`); const [isLoadingReportData] = useOnyx(ONYXKEYS.IS_LOADING_REPORT_DATA); const [willAlertModalBecomeVisible] = useOnyx(ONYXKEYS.MODAL, {selector: willAlertModalBecomeVisibleSelector}); + const [ownerLogin] = useOnyx(ONYXKEYS.PERSONAL_DETAILS_LIST, {selector: personalDetailsLoginSelector(report?.ownerAccountID)}); - const submitToContentKey = useMemo(() => `${reportID}:${getSubmitToEmail(policy, report)}`, [reportID, policy, report]); + const submitToContentKey = `${reportID}:${getSubmitToEmail(policy, report, ownerLogin)}`; const clearDismissGuard = useCallback(() => { setIsDismissGuardActive(false); diff --git a/src/libs/PolicyUtils.ts b/src/libs/PolicyUtils.ts index 2b475d1c0603..fc286ad7db0b 100644 --- a/src/libs/PolicyUtils.ts +++ b/src/libs/PolicyUtils.ts @@ -1746,19 +1746,28 @@ function getManagerAccountID(policy: OnyxEntry, ownerLogin: string | und } /** - * Returns the accountID to whom the given expenseReport submits reports to in the given Policy. + * Returns the email the expense report should submit to per workspace approval config + * (approval rules, employee submitsTo, or default approver for basic/optional workflows). */ -function getSubmitToAccountID(policy: OnyxEntry, expenseReport: OnyxEntry, ownerLogin: string | undefined): number { +function getSubmitToEmail(policy: OnyxEntry, expenseReport: OnyxEntry, ownerLogin: string | undefined): string { const approvalRules = policy?.rules?.approvalRules; if (!isSubmitAndClose(policy) && approvalRules?.length) { const ruleApprover = getFirstRuleApprover(approvalRules, expenseReport, ownerLogin); if (ruleApprover) { - return getAccountIDsByLogins([ruleApprover]).at(0) ?? -1; + return ruleApprover; } } - return getManagerAccountID(policy, ownerLogin); + return getManagerAccountEmail(policy, ownerLogin); +} + +/** + * Returns the accountID to whom the given expenseReport submits reports to in the given Policy. + */ +function getSubmitToAccountID(policy: OnyxEntry, expenseReport: OnyxEntry, ownerLogin: string | undefined): number { + const submitToEmail = getSubmitToEmail(policy, expenseReport, ownerLogin); + return submitToEmail ? (getAccountIDsByLogins([submitToEmail]).at(0) ?? -1) : -1; } function getSubmitReportManagerAccountID(policy: OnyxEntry, expenseReport: OnyxEntry, submitterLogin: string | undefined): number | undefined { @@ -1785,25 +1794,6 @@ function getSubmitReportManagerAccountID(policy: OnyxEntry, expenseRepor return isValidSubmitToAccountID ? submitToAccountID : existingManagerID; } -/** - * Returns the email the expense report should submit to per workspace approval config - * (approval rules, employee submitsTo, or default approver for basic/optional workflows). - */ -function getSubmitToEmail(policy: OnyxEntry, expenseReport: OnyxEntry): string { - const defaultApprover = getDefaultApprover(policy).trim(); - if (!expenseReport) { - return defaultApprover; - } - - const ownerLogin = getLoginsByAccountIDs([expenseReport.ownerAccountID ?? CONST.DEFAULT_NUMBER_ID]).at(0); - const submitToAccountID = getSubmitToAccountID(policy, expenseReport, ownerLogin); - if (!isValidAccountRoute(submitToAccountID)) { - return defaultApprover; - } - - return getLoginsByAccountIDs([submitToAccountID]).at(0)?.trim() ?? defaultApprover; -} - /** * Returns the email of the account to forward the report to depending on the approver's approval limit. * Used for advanced approval mode only. diff --git a/src/pages/ReportSubmitToContent.tsx b/src/pages/ReportSubmitToContent.tsx index 00e362de2752..c3e163f831eb 100644 --- a/src/pages/ReportSubmitToContent.tsx +++ b/src/pages/ReportSubmitToContent.tsx @@ -103,7 +103,7 @@ function ReportSubmitToContent({ const isASAPSubmitBetaEnabled = isBetaEnabled(CONST.BETAS.ASAP_SUBMIT); const hasViolations = hasViolationsReportUtils(report?.reportID, transactionViolations, currentUserDetails.accountID, currentUserDetails.login ?? ''); - const prepopulatedEmail = useMemo(() => getSubmitToEmail(policy, report), [policy, report]); + const prepopulatedEmail = getSubmitToEmail(policy, report, submitterLogin); const [userSelectedManagerEmail, setUserSelectedManagerEmail] = useState(); const [extraSubmitToRecipients, setExtraSubmitToRecipients] = useState([]); @@ -160,7 +160,7 @@ function ReportSubmitToContent({ } const accountID = getKnownAccountIDByLogin(email); - const details = accountID ? getPersonalDetailsByID(accountID, personalDetails) : undefined; + const details = getPersonalDetailsByID(accountID, personalDetails); return { accountID, From a66d67c17a258d8d8ffd331086442330022bc0b6 Mon Sep 17 00:00:00 2001 From: Bernhard Owen Josephus Date: Tue, 7 Jul 2026 11:50:05 +0800 Subject: [PATCH 2/4] fix test --- tests/unit/PolicyUtilsTest.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/unit/PolicyUtilsTest.ts b/tests/unit/PolicyUtilsTest.ts index 5b096422c037..12b2fa6066a9 100644 --- a/tests/unit/PolicyUtilsTest.ts +++ b/tests/unit/PolicyUtilsTest.ts @@ -1101,7 +1101,7 @@ describe('PolicyUtils', () => { ownerAccountID: employeeAccountID, }; - expect(getSubmitToEmail(policy, report)).toBe(adminEmail); + expect(getSubmitToEmail(policy, report, employeeEmail)).toBe(adminEmail); }); it('should return the default approver', () => { From 92649a30dbd72b37641356e13a3487fea7a64bbd Mon Sep 17 00:00:00 2001 From: Bernhard Owen Josephus Date: Tue, 7 Jul 2026 15:16:28 +0800 Subject: [PATCH 3/4] remove unused import --- src/libs/PolicyUtils.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/PolicyUtils.ts b/src/libs/PolicyUtils.ts index bb617cc3db5e..22337c3028fb 100644 --- a/src/libs/PolicyUtils.ts +++ b/src/libs/PolicyUtils.ts @@ -57,7 +57,7 @@ import {isAnyHRConnected, isMergeHRCompleteSetupNeeded, shouldShowHRConnectionEr import Navigation from './Navigation/Navigation'; import {getIsOffline} from './NetworkState'; import {formatMemberForList} from './OptionsListUtils'; -import {getAccountIDsByLogins, getKnownAccountIDByLogin, getLoginsByAccountIDs, getPersonalDetailByEmail} from './PersonalDetailsUtils'; +import {getAccountIDsByLogins, getKnownAccountIDByLogin, getPersonalDetailByEmail} from './PersonalDetailsUtils'; import {getAllSortedTransactions, getCategory, getTag, getTagArrayFromName} from './TransactionUtils'; import {generateAccountID} from './UserUtils'; import {isPublicDomain, isValidAccountRoute} from './ValidationUtils'; From a14177b06de41253800634e5d93a1a19afcf4917 Mon Sep 17 00:00:00 2001 From: Bernhard Owen Josephus Date: Wed, 8 Jul 2026 13:16:45 +0800 Subject: [PATCH 4/4] use default number id fallback --- src/libs/PolicyUtils.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/PolicyUtils.ts b/src/libs/PolicyUtils.ts index 22337c3028fb..f5b31e29f278 100644 --- a/src/libs/PolicyUtils.ts +++ b/src/libs/PolicyUtils.ts @@ -1772,7 +1772,7 @@ function getSubmitToEmail(policy: OnyxEntry, expenseReport: OnyxEntry, expenseReport: OnyxEntry, ownerLogin: string | undefined): number { const submitToEmail = getSubmitToEmail(policy, expenseReport, ownerLogin); - return submitToEmail ? (getAccountIDsByLogins([submitToEmail]).at(0) ?? -1) : -1; + return submitToEmail ? (getAccountIDsByLogins([submitToEmail]).at(0) ?? CONST.DEFAULT_NUMBER_ID) : CONST.DEFAULT_NUMBER_ID; } function getSubmitReportManagerAccountID(policy: OnyxEntry, expenseReport: OnyxEntry, submitterLogin: string | undefined): number | undefined {