From 75274d65feebe5baa9200c62ff468a87f4e8e3c3 Mon Sep 17 00:00:00 2001 From: Carlos Martins Date: Tue, 23 Sep 2025 16:19:20 -0600 Subject: [PATCH 01/20] fix change workspace condition --- src/libs/ReportUtils.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index b8de6b257371..7b3098631af5 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -11243,7 +11243,7 @@ function isWorkspaceEligibleForReportChange(newPolicy: OnyxEntry, report // We can only move the iou report to the workspace if the manager is the payer of the new policy if (isIOUReport(report)) { - return isPaidGroupPolicyPolicyUtils(newPolicy) && isWorkspacePayer(managerLogin ?? '', newPolicy); + return isPaidGroupPolicyPolicyUtils(newPolicy) && (isWorkspacePayer(managerLogin ?? '', newPolicy) || isPolicyMember(newPolicy, managerLogin)); } return isPaidGroupPolicyPolicyUtils(newPolicy) && (isPolicyMember(newPolicy, submitterEmail) || isPolicyAdmin(newPolicy?.id, policies)); } From 12b5beaaa8c0c33037d55beb3c82b68ecca954d7 Mon Sep 17 00:00:00 2001 From: Carlos Martins Date: Tue, 23 Sep 2025 16:51:51 -0600 Subject: [PATCH 02/20] fix workspace change --- src/libs/ReportUtils.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index 7b3098631af5..70b4996a6695 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -11243,7 +11243,8 @@ function isWorkspaceEligibleForReportChange(newPolicy: OnyxEntry, report // We can only move the iou report to the workspace if the manager is the payer of the new policy if (isIOUReport(report)) { - return isPaidGroupPolicyPolicyUtils(newPolicy) && (isWorkspacePayer(managerLogin ?? '', newPolicy) || isPolicyMember(newPolicy, managerLogin)); + console.log('isWorkspaceEligibleForReportChange', {isPaidGroupPolicyPolicyUtils:isPaidGroupPolicyPolicyUtils(newPolicy), isWorkspacePayer:isWorkspacePayer(managerLogin ?? '', newPolicy), isPolicyMember:isPolicyMember(newPolicy, managerLogin)}); + return isPaidGroupPolicyPolicyUtils(newPolicy) && (isPolicyMember(newPolicy, submitterEmail) || isWorkspacePayer(managerLogin ?? '', newPolicy)); } return isPaidGroupPolicyPolicyUtils(newPolicy) && (isPolicyMember(newPolicy, submitterEmail) || isPolicyAdmin(newPolicy?.id, policies)); } From a0f149524e215ccf7ee117305426d3a768f7e0af Mon Sep 17 00:00:00 2001 From: Carlos Martins Date: Wed, 24 Sep 2025 13:45:31 -0600 Subject: [PATCH 03/20] rm iou condition --- src/libs/ReportUtils.ts | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index 8efcd6b72b16..5414a4867484 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -11238,7 +11238,7 @@ function doesReportContainRequestsFromMultipleUsers(iouReport: OnyxEntry */ function isWorkspaceEligibleForReportChange(newPolicy: OnyxEntry, report: OnyxEntry, policies: OnyxCollection): boolean { const submitterEmail = getLoginByAccountID(report?.ownerAccountID ?? CONST.DEFAULT_NUMBER_ID); - const managerLogin = getLoginByAccountID(report?.managerID ?? CONST.DEFAULT_NUMBER_ID); + // We can't move the iou report to the workspace if both users from the iou report create the expense if (doesReportContainRequestsFromMultipleUsers(report)) { return false; @@ -11248,11 +11248,6 @@ function isWorkspaceEligibleForReportChange(newPolicy: OnyxEntry, report return false; } - // We can only move the iou report to the workspace if the manager is the payer of the new policy - if (isIOUReport(report)) { - console.log('isWorkspaceEligibleForReportChange', {isPaidGroupPolicyPolicyUtils:isPaidGroupPolicyPolicyUtils(newPolicy), isWorkspacePayer:isWorkspacePayer(managerLogin ?? '', newPolicy), isPolicyMember:isPolicyMember(newPolicy, managerLogin)}); - return isPaidGroupPolicyPolicyUtils(newPolicy) && (isPolicyMember(newPolicy, submitterEmail) || isWorkspacePayer(managerLogin ?? '', newPolicy)); - } return isPaidGroupPolicyPolicyUtils(newPolicy) && (isPolicyMember(newPolicy, submitterEmail) || isPolicyAdmin(newPolicy?.id, policies)); } From dbdd9c0cea6453df77de7119689d071116fe18fd Mon Sep 17 00:00:00 2001 From: Carlos Martins Date: Wed, 24 Sep 2025 13:53:56 -0600 Subject: [PATCH 04/20] refactor method --- src/libs/ReportSecondaryActionUtils.ts | 11 ++++++++++- src/libs/ReportUtils.ts | 15 ++++----------- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/src/libs/ReportSecondaryActionUtils.ts b/src/libs/ReportSecondaryActionUtils.ts index 63b7e281d861..2838b78055eb 100644 --- a/src/libs/ReportSecondaryActionUtils.ts +++ b/src/libs/ReportSecondaryActionUtils.ts @@ -48,6 +48,7 @@ import { isSelfDM as isSelfDMReportUtils, isSettled, isWorkspaceEligibleForReportChange, + doesReportContainRequestsFromMultipleUsers, } from './ReportUtils'; import {getSession} from './SessionUtils'; import { @@ -62,6 +63,7 @@ import { isReceiptBeingScanned, shouldShowBrokenConnectionViolationForMultipleTransactions, } from './TransactionUtils'; +import {getLoginByAccountID} from './PersonalDetailsUtils'; function isAddExpenseAction(report: Report, reportTransactions: Transaction[], isReportArchived = false) { const isReportSubmitter = isCurrentUserSubmitter(report); @@ -434,7 +436,14 @@ function isHoldActionForTransaction(report: Report, reportTransaction: Transacti } function isChangeWorkspaceAction(report: Report, policies: OnyxCollection, reportActions?: ReportAction[]): boolean { - const availablePolicies = Object.values(policies ?? {}).filter((newPolicy) => isWorkspaceEligibleForReportChange(newPolicy, report, policies)); + // We can't move the iou report to the workspace if both users from the iou report create the expense + if (isIOUReportUtils(report) && doesReportContainRequestsFromMultipleUsers(report)) { + return false; + } + + const submitterEmail = getLoginByAccountID(report?.ownerAccountID ?? CONST.DEFAULT_NUMBER_ID); + const availablePolicies = Object.values(policies ?? {}).filter((newPolicy) => isWorkspaceEligibleForReportChange(submitterEmail, newPolicy)); + let hasAvailablePolicies = availablePolicies.length > 1; if (!hasAvailablePolicies && availablePolicies.length === 1) { hasAvailablePolicies = !report.policyID || report.policyID !== availablePolicies?.at(0)?.id; diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index 5414a4867484..11d949a42a3d 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -113,7 +113,6 @@ import { getAccountIDsByLogins, getDisplayNameOrDefault, getEffectiveDisplayName, - getLoginByAccountID, getLoginsByAccountIDs, getPersonalDetailByEmail, getPersonalDetailsByIDs, @@ -11236,19 +11235,12 @@ function doesReportContainRequestsFromMultipleUsers(iouReport: OnyxEntry /** * Determines whether the report can be moved to the workspace. */ -function isWorkspaceEligibleForReportChange(newPolicy: OnyxEntry, report: OnyxEntry, policies: OnyxCollection): boolean { - const submitterEmail = getLoginByAccountID(report?.ownerAccountID ?? CONST.DEFAULT_NUMBER_ID); - - // We can't move the iou report to the workspace if both users from the iou report create the expense - if (doesReportContainRequestsFromMultipleUsers(report)) { - return false; - } - - if (!newPolicy?.isPolicyExpenseChatEnabled) { +function isWorkspaceEligibleForReportChange(submitterEmail: string | undefined, newPolicy: OnyxEntry): boolean { + if (!submitterEmail || !newPolicy?.isPolicyExpenseChatEnabled) { return false; } - return isPaidGroupPolicyPolicyUtils(newPolicy) && (isPolicyMember(newPolicy, submitterEmail) || isPolicyAdmin(newPolicy?.id, policies)); + return isPaidGroupPolicyPolicyUtils(newPolicy) && (isPolicyMember(newPolicy, submitterEmail) || newPolicy.role === CONST.POLICY.ROLE.ADMIN); } function getApprovalChain(policy: OnyxEntry, expenseReport: OnyxEntry): string[] { @@ -12129,6 +12121,7 @@ export { getMovedActionMessage, excludeParticipantsForDisplay, getReportName, + doesReportContainRequestsFromMultipleUsers, }; export type { Ancestor, From dba3412bd719aba3b14e4d43ab4f74c29d6f8204 Mon Sep 17 00:00:00 2001 From: Carlos Martins Date: Wed, 24 Sep 2025 13:57:55 -0600 Subject: [PATCH 05/20] update tests --- src/pages/ReportChangeWorkspacePage.tsx | 4 +++- tests/unit/PolicyUtilsTest.ts | 24 +++--------------------- 2 files changed, 6 insertions(+), 22 deletions(-) diff --git a/src/pages/ReportChangeWorkspacePage.tsx b/src/pages/ReportChangeWorkspacePage.tsx index c955be409781..fbdb8d5f2043 100644 --- a/src/pages/ReportChangeWorkspacePage.tsx +++ b/src/pages/ReportChangeWorkspacePage.tsx @@ -19,6 +19,7 @@ import type {ReportChangeWorkspaceNavigatorParamList} from '@libs/Navigation/typ import {getLoginByAccountID} from '@libs/PersonalDetailsUtils'; import {isPolicyAdmin, isPolicyMember} from '@libs/PolicyUtils'; import {isExpenseReport, isIOUReport, isMoneyRequestReport, isMoneyRequestReportPendingDeletion, isWorkspaceEligibleForReportChange} from '@libs/ReportUtils'; +import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import type SCREENS from '@src/SCREENS'; import NotFoundPage from './ErrorPage/NotFoundPage'; @@ -67,6 +68,7 @@ function ReportChangeWorkspacePage({report, route}: ReportChangeWorkspacePagePro [session?.email, route.params, report, reportID, reportNextStep, policies, formatPhoneNumber, isReportArchived], ); + const submitterEmail = getLoginByAccountID(report?.ownerAccountID ?? CONST.DEFAULT_NUMBER_ID); const {sections, shouldShowNoResultsFoundMessage, shouldShowSearchInput} = useWorkspaceList({ policies, currentUserLogin: session?.email, @@ -74,7 +76,7 @@ function ReportChangeWorkspacePage({report, route}: ReportChangeWorkspacePagePro selectedPolicyIDs: report.policyID ? [report.policyID] : undefined, searchTerm: debouncedSearchTerm, localeCompare, - additionalFilter: (newPolicy) => isWorkspaceEligibleForReportChange(newPolicy, report, policies), + additionalFilter: (newPolicy) => isWorkspaceEligibleForReportChange(submitterEmail, newPolicy), }); if (!isMoneyRequestReport(report) || isMoneyRequestReportPendingDeletion(report)) { diff --git a/tests/unit/PolicyUtilsTest.ts b/tests/unit/PolicyUtilsTest.ts index 21a1f484b300..30e8b2565dee 100644 --- a/tests/unit/PolicyUtilsTest.ts +++ b/tests/unit/PolicyUtilsTest.ts @@ -665,7 +665,6 @@ describe('PolicyUtils', () => { it('returns false if policy is not paid group policy', async () => { const currentUserLogin = employeeEmail; - const currentUserAccountID = employeeAccountID; const newPolicy = { ...createRandomPolicy(1, CONST.POLICY.TYPE.PERSONAL), @@ -674,23 +673,14 @@ describe('PolicyUtils', () => { [currentUserLogin]: {email: currentUserLogin, role: CONST.POLICY.ROLE.USER}, }, }; - const policies = {[`${ONYXKEYS.COLLECTION.POLICY}${newPolicy.id}`]: newPolicy}; await Onyx.set(`${ONYXKEYS.COLLECTION.POLICY}${newPolicy.id}`, newPolicy); - const report = { - ...createRandomReport(0), - type: CONST.REPORT.TYPE.IOU, - stateNum: CONST.REPORT.STATE_NUM.SUBMITTED, - ownerAccountID: currentUserAccountID, - managerID: approverAccountID, - }; - const result = isWorkspaceEligibleForReportChange(newPolicy, report, policies); + const result = isWorkspaceEligibleForReportChange(currentUserLogin, newPolicy); expect(result).toBe(false); }); - it('returns true if policy is paid group policy and the manger is the payer', async () => { + it('returns true if policy is paid group policy and the manager is the payer', async () => { const currentUserLogin = employeeEmail; - const currentUserAccountID = employeeAccountID; const newPolicy = { ...createRandomPolicy(1, CONST.POLICY.TYPE.TEAM), @@ -700,17 +690,9 @@ describe('PolicyUtils', () => { [currentUserLogin]: {email: currentUserLogin, role: CONST.POLICY.ROLE.ADMIN}, }, }; - const policies = {[`${ONYXKEYS.COLLECTION.POLICY}${newPolicy.id}`]: newPolicy}; await Onyx.set(`${ONYXKEYS.COLLECTION.POLICY}${newPolicy.id}`, newPolicy); - const report = { - ...createRandomReport(0), - type: CONST.REPORT.TYPE.IOU, - stateNum: CONST.REPORT.STATE_NUM.SUBMITTED, - ownerAccountID: approverAccountID, - managerID: currentUserAccountID, - }; - const result = isWorkspaceEligibleForReportChange(newPolicy, report, policies); + const result = isWorkspaceEligibleForReportChange(currentUserLogin, newPolicy); expect(result).toBe(true); }); From 51e4e8d2efe09920a3f3dbfc1e7ff7e7fcae4fad Mon Sep 17 00:00:00 2001 From: Carlos Martins Date: Wed, 24 Sep 2025 13:59:56 -0600 Subject: [PATCH 06/20] rm call to getPolicy --- src/components/KYCWall/BaseKYCWall.tsx | 2 +- src/libs/actions/Report.ts | 7 ++----- src/pages/ReportChangeWorkspacePage.tsx | 2 +- tests/actions/ReportTest.ts | 2 +- 4 files changed, 5 insertions(+), 8 deletions(-) diff --git a/src/components/KYCWall/BaseKYCWall.tsx b/src/components/KYCWall/BaseKYCWall.tsx index 00d59d2aa11c..4d6bbd51d6db 100644 --- a/src/components/KYCWall/BaseKYCWall.tsx +++ b/src/components/KYCWall/BaseKYCWall.tsx @@ -128,7 +128,7 @@ function KYCWall({ savePreferredPaymentMethod(iouReport.policyID, policy.id, CONST.LAST_PAYMENT_METHOD.IOU, lastPaymentMethod?.[policy.id]); Navigation.navigate(ROUTES.REPORT_WITH_ID.getRoute(newPolicyExpenseChatReportID)); } else { - moveIOUReportToPolicy(iouReport.reportID, policy.id, true); + moveIOUReportToPolicy(iouReport.reportID, policy, true); savePreferredPaymentMethod(iouReport.policyID, policy.id, CONST.LAST_PAYMENT_METHOD.IOU, lastPaymentMethod?.[policy.id]); Navigation.navigate(ROUTES.REPORT_WITH_ID.getRoute(policyExpenseChatReportID)); } diff --git a/src/libs/actions/Report.ts b/src/libs/actions/Report.ts index b1ecd8532a5b..82ffaf03bfe8 100644 --- a/src/libs/actions/Report.ts +++ b/src/libs/actions/Report.ts @@ -5194,14 +5194,11 @@ function deleteAppReport(reportID: string | undefined) { /** * Moves an IOU report to a policy by converting it to an expense report * @param reportID - The ID of the IOU report to move - * @param policyID - The ID of the policy to move the report to + * @param policy - The policy to move the report to * @param isFromSettlementButton - Whether the action is from report preview */ -function moveIOUReportToPolicy(reportID: string, policyID: string, isFromSettlementButton?: boolean) { +function moveIOUReportToPolicy(reportID: string, policy: Policy, isFromSettlementButton?: boolean) { const iouReport = allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${reportID}`]; - // This will be fixed as part of https://github.com/Expensify/Expensify/issues/507850 - // eslint-disable-next-line deprecation/deprecation - const policy = getPolicy(policyID); // This flow only works for IOU reports if (!policy || !iouReport || !isIOUReportUsingReport(iouReport)) { diff --git a/src/pages/ReportChangeWorkspacePage.tsx b/src/pages/ReportChangeWorkspacePage.tsx index fbdb8d5f2043..ac472f3f0ab2 100644 --- a/src/pages/ReportChangeWorkspacePage.tsx +++ b/src/pages/ReportChangeWorkspacePage.tsx @@ -55,7 +55,7 @@ function ReportChangeWorkspacePage({report, route}: ReportChangeWorkspacePagePro if (isIOUReport(reportID) && isPolicyAdmin(policy) && report.ownerAccountID && !isPolicyMember(policy, getLoginByAccountID(report.ownerAccountID))) { moveIOUReportToPolicyAndInviteSubmitter(reportID, policyID, formatPhoneNumber); } else if (isIOUReport(reportID) && isPolicyMember(policy, session?.email)) { - moveIOUReportToPolicy(reportID, policyID); + moveIOUReportToPolicy(reportID, policy); // This will be fixed as part of https://github.com/Expensify/Expensify/issues/507850 // eslint-disable-next-line deprecation/deprecation } else if (isExpenseReport(report) && isPolicyAdmin(policy) && report.ownerAccountID && !isPolicyMember(policy, getLoginByAccountID(report.ownerAccountID))) { diff --git a/tests/actions/ReportTest.ts b/tests/actions/ReportTest.ts index fef9be0aceb7..97e29c0148c1 100644 --- a/tests/actions/ReportTest.ts +++ b/tests/actions/ReportTest.ts @@ -2132,7 +2132,7 @@ describe('actions/Report', () => { await Onyx.merge(`${ONYXKEYS.COLLECTION.POLICY}${policy.id}`, policy); // When moving iou to a workspace - Report.moveIOUReportToPolicy(iouReport.reportID, policy.id); + Report.moveIOUReportToPolicy(iouReport.reportID, policy); await waitForBatchedUpdates(); // Then MOVED report action should be added to the expense report From ec812bd38987dfe34682cd5666a993fcd8ddaf7c Mon Sep 17 00:00:00 2001 From: Carlos Martins Date: Wed, 24 Sep 2025 14:04:07 -0600 Subject: [PATCH 07/20] update optimistic data --- src/libs/actions/Report.ts | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/libs/actions/Report.ts b/src/libs/actions/Report.ts index 82ffaf03bfe8..612ddda82230 100644 --- a/src/libs/actions/Report.ts +++ b/src/libs/actions/Report.ts @@ -5213,6 +5213,7 @@ function moveIOUReportToPolicy(reportID: string, policy: Policy, isFromSettlemen // Generate new variables for the policy const policyName = policy.name ?? ''; + const policyID = policy.id; const iouReportID = iouReport.reportID; const employeeAccountID = iouReport.ownerAccountID; const expenseChatReportId = getPolicyExpenseChat(employeeAccountID, policyID)?.reportID; @@ -5233,6 +5234,7 @@ function moveIOUReportToPolicy(reportID: string, policy: Policy, isFromSettlemen // - change the sign of the report total // - update its policyID and policyName // - update the chatReportID to point to the expense chat if the policy has policy expense chat enabled + // - if the manager and new policy approver are not the same, we also need to update state and status to OPEN and set the new managerID const expenseReport = { ...iouReport, chatReportID: policy.isPolicyExpenseChatEnabled ? expenseChatReportId : undefined, @@ -5243,6 +5245,13 @@ function moveIOUReportToPolicy(reportID: string, policy: Policy, isFromSettlemen total: -(iouReport?.total ?? 0), }; + const nextApproverAccountID = getNextApproverAccountID(iouReport, true); + if (iouReport.managerID !== nextApproverAccountID) { + expenseReport.stateNum = CONST.REPORT.STATE_NUM.OPEN; + expenseReport.statusNum = CONST.REPORT.STATUS_NUM.OPEN; + expenseReport.managerID = nextApproverAccountID; + } + const titleReportField = getTitleReportField(getReportFieldsByPolicyID(policyID) ?? {}); if (!!titleReportField && isPaidGroupPolicy(policy)) { expenseReport.reportName = populateOptimisticReportFormula(titleReportField.defaultValue, expenseReport, policy); From 8506364f0c2771d915d63c1bb5e143fbde29422c Mon Sep 17 00:00:00 2001 From: Carlos Martins Date: Wed, 24 Sep 2025 14:23:07 -0600 Subject: [PATCH 08/20] rm unused code --- src/libs/ReportUtils.ts | 21 --------------------- 1 file changed, 21 deletions(-) diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index 11d949a42a3d..1b59c5671411 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -4091,27 +4091,6 @@ function getTransactionCommentObject(transaction: OnyxEntry): Comme }; } -function isWorkspacePayer(memberLogin: string, policy: OnyxEntry): boolean { - const isAdmin = policy?.employeeList?.[memberLogin]?.role === CONST.POLICY.ROLE.ADMIN; - if (isPaidGroupPolicyPolicyUtils(policy)) { - if (policy?.reimbursementChoice === CONST.POLICY.REIMBURSEMENT_CHOICES.REIMBURSEMENT_YES) { - // If we get here without a reimburser only admin is the payer. - if (!policy?.achAccount?.reimburser) { - return isAdmin; - } - - // If we are the reimburser then we are the payer. - const isReimburser = memberLogin === policy?.achAccount?.reimburser; - return isReimburser; - } - if (policy?.reimbursementChoice === CONST.POLICY.REIMBURSEMENT_CHOICES.REIMBURSEMENT_MANUAL) { - return isAdmin; - } - return false; - } - return false; -} - /** * Can only edit if: * From deef747fe66f42653818b7d94f7f8f38883a3fcc Mon Sep 17 00:00:00 2001 From: Carlos Martins Date: Wed, 24 Sep 2025 14:24:05 -0600 Subject: [PATCH 09/20] rm comment --- src/libs/actions/Report.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/libs/actions/Report.ts b/src/libs/actions/Report.ts index 612ddda82230..cff20d47ac72 100644 --- a/src/libs/actions/Report.ts +++ b/src/libs/actions/Report.ts @@ -5234,7 +5234,6 @@ function moveIOUReportToPolicy(reportID: string, policy: Policy, isFromSettlemen // - change the sign of the report total // - update its policyID and policyName // - update the chatReportID to point to the expense chat if the policy has policy expense chat enabled - // - if the manager and new policy approver are not the same, we also need to update state and status to OPEN and set the new managerID const expenseReport = { ...iouReport, chatReportID: policy.isPolicyExpenseChatEnabled ? expenseChatReportId : undefined, From 478ee8ff91bd92ba25f0ae656ff15e918df07011 Mon Sep 17 00:00:00 2001 From: Carlos Martins Date: Wed, 24 Sep 2025 14:25:16 -0600 Subject: [PATCH 10/20] update moveIOUReportToPolicyAndInviteSubmitter --- src/libs/actions/Report.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/libs/actions/Report.ts b/src/libs/actions/Report.ts index cff20d47ac72..ea3df1d4ae3b 100644 --- a/src/libs/actions/Report.ts +++ b/src/libs/actions/Report.ts @@ -5515,6 +5515,14 @@ function moveIOUReportToPolicyAndInviteSubmitter( type: CONST.REPORT.TYPE.EXPENSE, total: -(iouReport?.total ?? 0), }; + + const nextApproverAccountID = getNextApproverAccountID(iouReport, true); + if (iouReport.managerID !== nextApproverAccountID) { + expenseReport.stateNum = CONST.REPORT.STATE_NUM.OPEN; + expenseReport.statusNum = CONST.REPORT.STATUS_NUM.OPEN; + expenseReport.managerID = nextApproverAccountID; + } + optimisticData.push({ onyxMethod: Onyx.METHOD.MERGE, key: `${ONYXKEYS.COLLECTION.REPORT}${reportID}`, From 6b3475c7320f3e6f0340707b6e0e6bf22bd13d68 Mon Sep 17 00:00:00 2001 From: Carlos Martins Date: Wed, 24 Sep 2025 14:27:59 -0600 Subject: [PATCH 11/20] fix prettier --- src/libs/ReportSecondaryActionUtils.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libs/ReportSecondaryActionUtils.ts b/src/libs/ReportSecondaryActionUtils.ts index 2838b78055eb..1a4fcbde4665 100644 --- a/src/libs/ReportSecondaryActionUtils.ts +++ b/src/libs/ReportSecondaryActionUtils.ts @@ -5,6 +5,7 @@ import ONYXKEYS from '@src/ONYXKEYS'; import type {ExportTemplate, Policy, Report, ReportAction, ReportNameValuePairs, Transaction, TransactionViolation} from '@src/types/onyx'; import {isApprover as isApproverUtils} from './actions/Policy/Member'; import {getCurrentUserAccountID, getCurrentUserEmail} from './actions/Report'; +import {getLoginByAccountID} from './PersonalDetailsUtils'; import { arePaymentsEnabled as arePaymentsEnabledUtils, getConnectedIntegration, @@ -25,6 +26,7 @@ import { canEditReportPolicy, canHoldUnholdReportAction, canRejectReportAction, + doesReportContainRequestsFromMultipleUsers, getTransactionDetails, hasOnlyHeldExpenses, hasOnlyNonReimbursableTransactions, @@ -48,7 +50,6 @@ import { isSelfDM as isSelfDMReportUtils, isSettled, isWorkspaceEligibleForReportChange, - doesReportContainRequestsFromMultipleUsers, } from './ReportUtils'; import {getSession} from './SessionUtils'; import { @@ -63,7 +64,6 @@ import { isReceiptBeingScanned, shouldShowBrokenConnectionViolationForMultipleTransactions, } from './TransactionUtils'; -import {getLoginByAccountID} from './PersonalDetailsUtils'; function isAddExpenseAction(report: Report, reportTransactions: Transaction[], isReportArchived = false) { const isReportSubmitter = isCurrentUserSubmitter(report); From 61db495b2391ab0247e3433ba7823f14575de733 Mon Sep 17 00:00:00 2001 From: Carlos Martins Date: Wed, 24 Sep 2025 14:40:28 -0600 Subject: [PATCH 12/20] fix tests --- tests/unit/PolicyUtilsTest.ts | 27 ++++++--------------------- 1 file changed, 6 insertions(+), 21 deletions(-) diff --git a/tests/unit/PolicyUtilsTest.ts b/tests/unit/PolicyUtilsTest.ts index 30e8b2565dee..edc900a1a058 100644 --- a/tests/unit/PolicyUtilsTest.ts +++ b/tests/unit/PolicyUtilsTest.ts @@ -696,7 +696,9 @@ describe('PolicyUtils', () => { expect(result).toBe(true); }); - it('returns false if the manager is not the payer of the new policy', async () => { + it('returns true if the manager is not the payer of the new policy', async () => { + const currentUserLogin = employeeEmail; + const newPolicy = { ...createRandomPolicy(1, CONST.POLICY.TYPE.TEAM), isPolicyExpenseChatEnabled: true, @@ -705,23 +707,14 @@ describe('PolicyUtils', () => { [approverEmail]: {email: approverEmail, role: CONST.POLICY.ROLE.USER}, }, }; - const policies = {[`${ONYXKEYS.COLLECTION.POLICY}${newPolicy.id}`]: newPolicy}; await Onyx.set(`${ONYXKEYS.COLLECTION.POLICY}${newPolicy.id}`, newPolicy); - const report = { - ...createRandomReport(0), - type: CONST.REPORT.TYPE.IOU, - stateNum: CONST.REPORT.STATE_NUM.SUBMITTED, - ownerAccountID: employeeAccountID, - managerID: approverAccountID, - }; - const result = isWorkspaceEligibleForReportChange(newPolicy, report, policies); - expect(result).toBe(false); + const result = isWorkspaceEligibleForReportChange(currentUserLogin, newPolicy); + expect(result).toBe(true); }); it('returns false if policies are not policyExpenseChatEnabled', async () => { const currentUserLogin = employeeEmail; - const currentUserAccountID = employeeAccountID; const newPolicy = { ...createRandomPolicy(1, CONST.POLICY.TYPE.TEAM), @@ -731,17 +724,9 @@ describe('PolicyUtils', () => { [currentUserLogin]: {email: currentUserLogin, role: CONST.POLICY.ROLE.ADMIN}, }, }; - const policies = {[`${ONYXKEYS.COLLECTION.POLICY}${newPolicy.id}`]: newPolicy}; await Onyx.set(`${ONYXKEYS.COLLECTION.POLICY}${newPolicy.id}`, newPolicy); - const report = { - ...createRandomReport(0), - type: CONST.REPORT.TYPE.IOU, - stateNum: CONST.REPORT.STATE_NUM.SUBMITTED, - ownerAccountID: approverAccountID, - managerID: currentUserAccountID, - }; - const result = isWorkspaceEligibleForReportChange(newPolicy, report, policies); + const result = isWorkspaceEligibleForReportChange(currentUserLogin, newPolicy); expect(result).toBe(false); }); }); From 68b44cc21edce51f8428563003e67e556e033579 Mon Sep 17 00:00:00 2001 From: Carlos Martins Date: Mon, 29 Sep 2025 16:08:29 -0600 Subject: [PATCH 13/20] update param; --- src/components/KYCWall/BaseKYCWall.tsx | 2 +- src/libs/actions/Report.ts | 6 +----- src/pages/ReportChangeWorkspacePage.tsx | 2 +- tests/actions/ReportTest.ts | 4 ++-- 4 files changed, 5 insertions(+), 9 deletions(-) diff --git a/src/components/KYCWall/BaseKYCWall.tsx b/src/components/KYCWall/BaseKYCWall.tsx index 428d775e0585..ec130c6cfa8c 100644 --- a/src/components/KYCWall/BaseKYCWall.tsx +++ b/src/components/KYCWall/BaseKYCWall.tsx @@ -131,7 +131,7 @@ function KYCWall({ if (iouReport && isIOUReport(iouReport)) { const adminPolicy = policies?.[`${ONYXKEYS.COLLECTION.POLICY}${policy?.id}`]; if (adminPolicy) { - const inviteResult = moveIOUReportToPolicyAndInviteSubmitter(iouReport?.reportID, adminPolicy.id, formatPhoneNumber); + const inviteResult = moveIOUReportToPolicyAndInviteSubmitter(iouReport?.reportID, adminPolicy, formatPhoneNumber); if (inviteResult?.policyExpenseChatReportID) { Navigation.navigate(ROUTES.REPORT_WITH_ID.getRoute(inviteResult.policyExpenseChatReportID)); } else { diff --git a/src/libs/actions/Report.ts b/src/libs/actions/Report.ts index 62af3c9911c6..ee449342eb73 100644 --- a/src/libs/actions/Report.ts +++ b/src/libs/actions/Report.ts @@ -5406,17 +5406,13 @@ function moveIOUReportToPolicy( /** * Moves an IOU report to a policy by converting it to an expense report * @param reportID - The ID of the IOU report to move - * @param policyID - The ID of the policy to move the report to */ function moveIOUReportToPolicyAndInviteSubmitter( reportID: string, - policyID: string, + policy: Policy, formatPhoneNumber: LocaleContextProps['formatPhoneNumber'], ): {policyExpenseChatReportID?: string} | undefined { const iouReport = allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${reportID}`]; - // This will be fixed as part of https://github.com/Expensify/Expensify/issues/507850 - // eslint-disable-next-line deprecation/deprecation - const policy = getPolicy(policyID); if (!policy || !iouReport) { return; diff --git a/src/pages/ReportChangeWorkspacePage.tsx b/src/pages/ReportChangeWorkspacePage.tsx index a6a0d19b916f..47b2b1f3421e 100644 --- a/src/pages/ReportChangeWorkspacePage.tsx +++ b/src/pages/ReportChangeWorkspacePage.tsx @@ -51,7 +51,7 @@ function ReportChangeWorkspacePage({report, route}: ReportChangeWorkspacePagePro const {backTo} = route.params; Navigation.goBack(backTo); if (isIOUReport(reportID)) { - const invite = moveIOUReportToPolicyAndInviteSubmitter(reportID, policy?.id, formatPhoneNumber); + const invite = moveIOUReportToPolicyAndInviteSubmitter(reportID, policy, formatPhoneNumber); if (!invite?.policyExpenseChatReportID) { moveIOUReportToPolicy(reportID, policy); } diff --git a/tests/actions/ReportTest.ts b/tests/actions/ReportTest.ts index b8e29f7ebc7f..763866a02fa4 100644 --- a/tests/actions/ReportTest.ts +++ b/tests/actions/ReportTest.ts @@ -2181,7 +2181,7 @@ describe('actions/Report', () => { await Onyx.merge(`${ONYXKEYS.COLLECTION.POLICY}${policy.id}`, policy); // When moving iou to a workspace and invite the submitter - Report.moveIOUReportToPolicyAndInviteSubmitter(iouReport.reportID, policy.id, (phone: string) => phone); + Report.moveIOUReportToPolicyAndInviteSubmitter(iouReport.reportID, policy, (phone: string) => phone); await waitForBatchedUpdates(); // Then MOVED report action should be added to the expense report @@ -2248,7 +2248,7 @@ describe('actions/Report', () => { // Call moveIOUReportToPolicyAndInviteSubmitter const formatPhoneNumber = (phoneNumber: string) => phoneNumber; - Report.moveIOUReportToPolicyAndInviteSubmitter(iouReport.reportID, policy.id, formatPhoneNumber); + Report.moveIOUReportToPolicyAndInviteSubmitter(iouReport.reportID, policy, formatPhoneNumber); await waitForBatchedUpdates(); // Simulate network failure From 03153e65f2ace9c99fc468269ce697796d83cf3c Mon Sep 17 00:00:00 2001 From: Carlos Martins Date: Mon, 29 Sep 2025 16:10:28 -0600 Subject: [PATCH 14/20] fix error --- src/libs/actions/Report.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libs/actions/Report.ts b/src/libs/actions/Report.ts index ee449342eb73..7d8e8506631a 100644 --- a/src/libs/actions/Report.ts +++ b/src/libs/actions/Report.ts @@ -5423,6 +5423,7 @@ function moveIOUReportToPolicyAndInviteSubmitter( const submitterEmail = PersonalDetailsUtils.getLoginByAccountID(submitterAccountID ?? CONST.DEFAULT_NUMBER_ID); const submitterLogin = PhoneNumber.addSMSDomainIfPhoneNumber(submitterEmail); const iouReportID = iouReport.reportID; + const policyID = policy.id; // This flow only works for admins moving an IOU report to a policy where the submitter is NOT yet a member of the policy if (!isPolicyAdmin || !isIOUReportUsingReport(iouReport) || !submitterAccountID || !submitterEmail || isPolicyMember(policy, submitterLogin)) { From d8c06a98e6b5f6bf954d38f173d88a99d41c6918 Mon Sep 17 00:00:00 2001 From: Carlos Martins Date: Mon, 29 Sep 2025 16:28:33 -0600 Subject: [PATCH 15/20] dry code --- src/libs/actions/Report.ts | 220 +++++++------------------------------ 1 file changed, 41 insertions(+), 179 deletions(-) diff --git a/src/libs/actions/Report.ts b/src/libs/actions/Report.ts index 7d8e8506631a..7432a20c0eef 100644 --- a/src/libs/actions/Report.ts +++ b/src/libs/actions/Report.ts @@ -5225,8 +5225,6 @@ function moveIOUReportToPolicy( return; } - // Generate new variables for the policy - const policyName = policy.name ?? ''; const policyID = policy.id; const iouReportID = iouReport.reportID; const employeeAccountID = iouReport.ownerAccountID; @@ -5234,162 +5232,7 @@ function moveIOUReportToPolicy( const useTemporaryOptimisticExpenseChatReportID = !expenseChatReportId; const optimisticExpenseChatReportID = expenseChatReportId ?? generateReportID(); - const optimisticData: OnyxUpdate[] = []; - - const successData: OnyxUpdate[] = []; - - const failureData: OnyxUpdate[] = []; - - // Next we need to convert the IOU report to Expense report. - // We need to change: - // - report type - // - change the sign of the report total - // - update its policyID and policyName - // - update the chatReportID to point to the expense chat if the policy has policy expense chat enabled - const expenseReport = { - ...iouReport, - chatReportID: policy.isPolicyExpenseChatEnabled ? expenseChatReportId : undefined, - policyID, - policyName, - parentReportID: iouReport.parentReportID, - type: CONST.REPORT.TYPE.EXPENSE, - total: -(iouReport?.total ?? 0), - }; - - const nextApproverAccountID = getNextApproverAccountID(iouReport, true); - if (iouReport.managerID !== nextApproverAccountID) { - expenseReport.stateNum = CONST.REPORT.STATE_NUM.OPEN; - expenseReport.statusNum = CONST.REPORT.STATUS_NUM.OPEN; - expenseReport.managerID = nextApproverAccountID; - } - - const titleReportField = getTitleReportField(getReportFieldsByPolicyID(policyID) ?? {}); - if (!!titleReportField && isPaidGroupPolicy(policy)) { - expenseReport.reportName = populateOptimisticReportFormula(titleReportField.defaultValue, expenseReport, policy); - } - - optimisticData.push({ - onyxMethod: Onyx.METHOD.MERGE, - key: `${ONYXKEYS.COLLECTION.REPORT}${iouReportID}`, - value: expenseReport, - }); - failureData.push({ - onyxMethod: Onyx.METHOD.MERGE, - key: `${ONYXKEYS.COLLECTION.REPORT}${iouReportID}`, - value: iouReport, - }); - - // The expense report transactions need to have the amount reversed to negative values - const reportTransactions = getReportTransactions(iouReportID); - - // For performance reasons, we are going to compose a merge collection data for transactions - const transactionsOptimisticData: Record = {}; - const transactionFailureData: Record = {}; - reportTransactions.forEach((transaction) => { - transactionsOptimisticData[`${ONYXKEYS.COLLECTION.TRANSACTION}${transaction.transactionID}`] = { - ...transaction, - amount: -transaction.amount, - modifiedAmount: transaction.modifiedAmount ? -transaction.modifiedAmount : 0, - }; - - transactionFailureData[`${ONYXKEYS.COLLECTION.TRANSACTION}${transaction.transactionID}`] = transaction; - }); - - optimisticData.push({ - onyxMethod: Onyx.METHOD.MERGE_COLLECTION, - key: `${ONYXKEYS.COLLECTION.TRANSACTION}`, - value: transactionsOptimisticData, - }); - failureData.push({ - onyxMethod: Onyx.METHOD.MERGE_COLLECTION, - key: `${ONYXKEYS.COLLECTION.TRANSACTION}`, - value: transactionFailureData, - }); - - // We need to move the report preview action from the DM to the expense chat. - const parentReportActions = iouReport?.parentReportID ? allReportActions?.[iouReport.parentReportID] : undefined; - const parentReportActionID = iouReport.parentReportActionID; - const reportPreview = iouReport?.parentReportID && parentReportActionID ? parentReportActions?.[parentReportActionID] : undefined; - const oldChatReportID = iouReport.chatReportID; - - if (reportPreview?.reportActionID) { - optimisticData.push({ - onyxMethod: Onyx.METHOD.MERGE, - key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${oldChatReportID}`, - value: {[reportPreview.reportActionID]: null}, - }); - failureData.push({ - onyxMethod: Onyx.METHOD.MERGE, - key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${oldChatReportID}`, - value: {[reportPreview.reportActionID]: reportPreview}, - }); - - // Add the reportPreview action to expense chat - optimisticData.push({ - onyxMethod: Onyx.METHOD.MERGE, - key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${optimisticExpenseChatReportID}`, - value: {[reportPreview.reportActionID]: {...reportPreview, childReportName: expenseReport.reportName, created: DateUtils.getDBTime()}}, - }); - failureData.push({ - onyxMethod: Onyx.METHOD.MERGE, - key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${optimisticExpenseChatReportID}`, - value: {[reportPreview.reportActionID]: null}, - }); - } - - // Create MOVED report action and add it to the expense report which indicates to the user where the report has been moved - const movedExpenseReportAction = buildOptimisticMovedReportAction(iouReport.policyID, policyID, expenseChatReportId ?? '', iouReportID, policyName, true); - optimisticData.push({ - onyxMethod: Onyx.METHOD.MERGE, - key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${reportID}`, - value: {[movedExpenseReportAction.reportActionID]: movedExpenseReportAction}, - }); - successData.push({ - onyxMethod: Onyx.METHOD.MERGE, - key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${reportID}`, - value: { - [movedExpenseReportAction.reportActionID]: { - ...movedExpenseReportAction, - pendingAction: null, - }, - }, - }); - failureData.push({ - onyxMethod: Onyx.METHOD.MERGE, - key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${reportID}`, - value: {[movedExpenseReportAction.reportActionID]: null}, - }); - - // To optimistically remove the GBR from the DM we need to update the hasOutstandingChildRequest param to false - optimisticData.push({ - onyxMethod: Onyx.METHOD.MERGE, - key: `${ONYXKEYS.COLLECTION.REPORT}${oldChatReportID}`, - value: { - hasOutstandingChildRequest: false, - iouReportID: null, - }, - }); - failureData.push({ - onyxMethod: Onyx.METHOD.MERGE, - key: `${ONYXKEYS.COLLECTION.REPORT}${oldChatReportID}`, - value: { - hasOutstandingChildRequest: true, - iouReportID, - }, - }); - - // Create the MOVED report action and add it to the DM chat which indicates to the user where the report has been moved - const movedReportAction = buildOptimisticMovedReportAction(iouReport.policyID, policyID, optimisticExpenseChatReportID, iouReportID, policyName); - optimisticData.push({ - onyxMethod: Onyx.METHOD.MERGE, - key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${oldChatReportID}`, - value: {[movedReportAction.reportActionID]: movedReportAction}, - }); - failureData.push({ - onyxMethod: Onyx.METHOD.MERGE, - key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${oldChatReportID}`, - value: {[movedReportAction.reportActionID]: null}, - }); + const {optimisticData, successData, failureData, movedExpenseReportAction, movedReportAction} = convertIOUReportToExpenseReport(iouReport, policy, policyID, optimisticExpenseChatReportID); const parameters: MoveIOUReportToExistingPolicyParams = { iouReportID, @@ -5422,7 +5265,6 @@ function moveIOUReportToPolicyAndInviteSubmitter( const submitterAccountID = iouReport.ownerAccountID; const submitterEmail = PersonalDetailsUtils.getLoginByAccountID(submitterAccountID ?? CONST.DEFAULT_NUMBER_ID); const submitterLogin = PhoneNumber.addSMSDomainIfPhoneNumber(submitterEmail); - const iouReportID = iouReport.reportID; const policyID = policy.id; // This flow only works for admins moving an IOU report to a policy where the submitter is NOT yet a member of the policy @@ -5510,12 +5352,35 @@ function moveIOUReportToPolicyAndInviteSubmitter( successData.push(...newPersonalDetailsOnyxData.finallyData, ...policyExpenseChats.onyxSuccessData, ...announceRoomMembers.successData); failureData.push(...policyExpenseChats.onyxFailureData, ...announceRoomMembers.failureData); - // Next we need to convert the IOU report to Expense report. - // We need to change: - // - report type - // - change the sign of the report total - // - update its policyID and policyName - // - update the chatReportID to point to the expense chat if the policy has policy expense chat enabled + const {optimisticData: convertedOptimisticData, successData: convertedSuccessData, failureData: convertedFailureData, movedExpenseReportAction, movedReportAction} = convertIOUReportToExpenseReport(iouReport, policy, policyID, optimisticPolicyExpenseChatReportID); + + optimisticData.push(...convertedOptimisticData, ...newPersonalDetailsOnyxData.optimisticData, ...policyExpenseChats.onyxOptimisticData, ...announceRoomMembers.optimisticData); + successData.push(...convertedSuccessData, ...newPersonalDetailsOnyxData.finallyData, ...policyExpenseChats.onyxSuccessData, ...announceRoomMembers.successData); + failureData.push(...convertedFailureData, ...policyExpenseChats.onyxFailureData, ...announceRoomMembers.failureData); + + const parameters: MoveIOUReportToPolicyAndInviteSubmitterParams = { + iouReportID: reportID, + policyID, + policyExpenseChatReportID: optimisticPolicyExpenseChatReportID ?? String(CONST.DEFAULT_NUMBER_ID), + policyExpenseCreatedReportActionID: optimisticPolicyExpenseChatCreatedReportActionID ?? String(CONST.DEFAULT_NUMBER_ID), + changePolicyReportActionID: movedExpenseReportAction.reportActionID, + dmMovedReportActionID: movedReportAction.reportActionID, + }; + + API.write(WRITE_COMMANDS.MOVE_IOU_REPORT_TO_POLICY_AND_INVITE_SUBMITTER, parameters, {optimisticData, successData, failureData}); + return {policyExpenseChatReportID: optimisticPolicyExpenseChatReportID}; +} + +function convertIOUReportToExpenseReport( + iouReport: Report, + policy: Policy, + policyID: string, + optimisticPolicyExpenseChatReportID: string, +) { + const optimisticData: OnyxUpdate[] = []; + const successData: OnyxUpdate[] = []; + const failureData: OnyxUpdate[] = []; + const expenseReport = { ...iouReport, chatReportID: optimisticPolicyExpenseChatReportID, @@ -5533,6 +5398,13 @@ function moveIOUReportToPolicyAndInviteSubmitter( expenseReport.managerID = nextApproverAccountID; } + const titleReportField = getTitleReportField(getReportFieldsByPolicyID(policyID) ?? {}); + if (!!titleReportField && isPaidGroupPolicy(policy)) { + expenseReport.reportName = populateOptimisticReportFormula(titleReportField.defaultValue, expenseReport, policy); + } + + const reportID = iouReport.reportID; + optimisticData.push({ onyxMethod: Onyx.METHOD.MERGE, key: `${ONYXKEYS.COLLECTION.REPORT}${reportID}`, @@ -5592,7 +5464,7 @@ function moveIOUReportToPolicyAndInviteSubmitter( optimisticData.push({ onyxMethod: Onyx.METHOD.MERGE, key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${optimisticPolicyExpenseChatReportID}`, - value: {[reportPreview.reportActionID]: {...reportPreview, created: DateUtils.getDBTime()}}, + value: {[reportPreview.reportActionID]: {...reportPreview, childReportName: expenseReport.reportName, created: DateUtils.getDBTime()}}, }); failureData.push({ onyxMethod: Onyx.METHOD.MERGE, @@ -5602,7 +5474,7 @@ function moveIOUReportToPolicyAndInviteSubmitter( } // Create MOVED report action and add it to the expense report which indicates to the user where the report has been moved - const movedExpenseReportAction = buildOptimisticMovedReportAction(iouReport.policyID, policyID, optimisticPolicyExpenseChatReportID, iouReportID, policy.name, true); + const movedExpenseReportAction = buildOptimisticMovedReportAction(iouReport.policyID, policyID, optimisticPolicyExpenseChatReportID ?? '', reportID, policy.name, true); optimisticData.push({ onyxMethod: Onyx.METHOD.MERGE, key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${reportID}`, @@ -5643,7 +5515,7 @@ function moveIOUReportToPolicyAndInviteSubmitter( }); // Create the MOVED report action and add it to the DM chat which indicates to the user where the report has been moved - const movedReportAction = buildOptimisticMovedReportAction(iouReport.policyID, policyID, optimisticPolicyExpenseChatReportID, iouReportID, policy.name); + const movedReportAction = buildOptimisticMovedReportAction(iouReport.policyID, policyID, optimisticPolicyExpenseChatReportID, reportID, policy.name); optimisticData.push({ onyxMethod: Onyx.METHOD.MERGE, key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${oldChatReportID}`, @@ -5655,17 +5527,7 @@ function moveIOUReportToPolicyAndInviteSubmitter( value: {[movedReportAction.reportActionID]: null}, }); - const parameters: MoveIOUReportToPolicyAndInviteSubmitterParams = { - iouReportID: reportID, - policyID, - policyExpenseChatReportID: optimisticPolicyExpenseChatReportID ?? String(CONST.DEFAULT_NUMBER_ID), - policyExpenseCreatedReportActionID: optimisticPolicyExpenseChatCreatedReportActionID ?? String(CONST.DEFAULT_NUMBER_ID), - changePolicyReportActionID: movedExpenseReportAction.reportActionID, - dmMovedReportActionID: movedReportAction.reportActionID, - }; - - API.write(WRITE_COMMANDS.MOVE_IOU_REPORT_TO_POLICY_AND_INVITE_SUBMITTER, parameters, {optimisticData, successData, failureData}); - return {policyExpenseChatReportID: optimisticPolicyExpenseChatReportID}; + return {optimisticData, successData, failureData, movedExpenseReportAction, movedReportAction}; } /** From 3d6b529f488d35a931539f614054491f09fb221f Mon Sep 17 00:00:00 2001 From: Carlos Martins Date: Mon, 29 Sep 2025 16:30:11 -0600 Subject: [PATCH 16/20] fix lint --- src/libs/actions/Report.ts | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/src/libs/actions/Report.ts b/src/libs/actions/Report.ts index 7432a20c0eef..3271df1c8526 100644 --- a/src/libs/actions/Report.ts +++ b/src/libs/actions/Report.ts @@ -5232,7 +5232,12 @@ function moveIOUReportToPolicy( const useTemporaryOptimisticExpenseChatReportID = !expenseChatReportId; const optimisticExpenseChatReportID = expenseChatReportId ?? generateReportID(); - const {optimisticData, successData, failureData, movedExpenseReportAction, movedReportAction} = convertIOUReportToExpenseReport(iouReport, policy, policyID, optimisticExpenseChatReportID); + const {optimisticData, successData, failureData, movedExpenseReportAction, movedReportAction} = convertIOUReportToExpenseReport( + iouReport, + policy, + policyID, + optimisticExpenseChatReportID, + ); const parameters: MoveIOUReportToExistingPolicyParams = { iouReportID, @@ -5352,7 +5357,13 @@ function moveIOUReportToPolicyAndInviteSubmitter( successData.push(...newPersonalDetailsOnyxData.finallyData, ...policyExpenseChats.onyxSuccessData, ...announceRoomMembers.successData); failureData.push(...policyExpenseChats.onyxFailureData, ...announceRoomMembers.failureData); - const {optimisticData: convertedOptimisticData, successData: convertedSuccessData, failureData: convertedFailureData, movedExpenseReportAction, movedReportAction} = convertIOUReportToExpenseReport(iouReport, policy, policyID, optimisticPolicyExpenseChatReportID); + const { + optimisticData: convertedOptimisticData, + successData: convertedSuccessData, + failureData: convertedFailureData, + movedExpenseReportAction, + movedReportAction, + } = convertIOUReportToExpenseReport(iouReport, policy, policyID, optimisticPolicyExpenseChatReportID); optimisticData.push(...convertedOptimisticData, ...newPersonalDetailsOnyxData.optimisticData, ...policyExpenseChats.onyxOptimisticData, ...announceRoomMembers.optimisticData); successData.push(...convertedSuccessData, ...newPersonalDetailsOnyxData.finallyData, ...policyExpenseChats.onyxSuccessData, ...announceRoomMembers.successData); @@ -5371,12 +5382,7 @@ function moveIOUReportToPolicyAndInviteSubmitter( return {policyExpenseChatReportID: optimisticPolicyExpenseChatReportID}; } -function convertIOUReportToExpenseReport( - iouReport: Report, - policy: Policy, - policyID: string, - optimisticPolicyExpenseChatReportID: string, -) { +function convertIOUReportToExpenseReport(iouReport: Report, policy: Policy, policyID: string, optimisticPolicyExpenseChatReportID: string) { const optimisticData: OnyxUpdate[] = []; const successData: OnyxUpdate[] = []; const failureData: OnyxUpdate[] = []; From 3aa34ad5ce47e9c48e6b30932ca0791c7eb3671f Mon Sep 17 00:00:00 2001 From: Carlos Martins Date: Mon, 29 Sep 2025 16:36:26 -0600 Subject: [PATCH 17/20] fix onyx updates --- src/libs/actions/Report.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libs/actions/Report.ts b/src/libs/actions/Report.ts index 3271df1c8526..965901681be9 100644 --- a/src/libs/actions/Report.ts +++ b/src/libs/actions/Report.ts @@ -5365,9 +5365,9 @@ function moveIOUReportToPolicyAndInviteSubmitter( movedReportAction, } = convertIOUReportToExpenseReport(iouReport, policy, policyID, optimisticPolicyExpenseChatReportID); - optimisticData.push(...convertedOptimisticData, ...newPersonalDetailsOnyxData.optimisticData, ...policyExpenseChats.onyxOptimisticData, ...announceRoomMembers.optimisticData); - successData.push(...convertedSuccessData, ...newPersonalDetailsOnyxData.finallyData, ...policyExpenseChats.onyxSuccessData, ...announceRoomMembers.successData); - failureData.push(...convertedFailureData, ...policyExpenseChats.onyxFailureData, ...announceRoomMembers.failureData); + optimisticData.push(...convertedOptimisticData); + successData.push(...convertedSuccessData); + failureData.push(...convertedFailureData); const parameters: MoveIOUReportToPolicyAndInviteSubmitterParams = { iouReportID: reportID, From 86bebc0abe0922a9c5a35625a0532d6a17724c2e Mon Sep 17 00:00:00 2001 From: Carlos Martins Date: Mon, 29 Sep 2025 16:48:42 -0600 Subject: [PATCH 18/20] fix eslint --- src/libs/actions/Report.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/actions/Report.ts b/src/libs/actions/Report.ts index 965901681be9..01fed8065e87 100644 --- a/src/libs/actions/Report.ts +++ b/src/libs/actions/Report.ts @@ -5480,7 +5480,7 @@ function convertIOUReportToExpenseReport(iouReport: Report, policy: Policy, poli } // Create MOVED report action and add it to the expense report which indicates to the user where the report has been moved - const movedExpenseReportAction = buildOptimisticMovedReportAction(iouReport.policyID, policyID, optimisticPolicyExpenseChatReportID ?? '', reportID, policy.name, true); + const movedExpenseReportAction = buildOptimisticMovedReportAction(iouReport.policyID, policyID, optimisticPolicyExpenseChatReportID, reportID, policy.name, true); optimisticData.push({ onyxMethod: Onyx.METHOD.MERGE, key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${reportID}`, From 2e8d637c102b0aba9c05dfadf81830d07ec1089a Mon Sep 17 00:00:00 2001 From: Carlos Martins Date: Tue, 30 Sep 2025 11:57:10 -0600 Subject: [PATCH 19/20] rm getLoginByAccountID --- src/pages/ReportChangeWorkspacePage.tsx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/pages/ReportChangeWorkspacePage.tsx b/src/pages/ReportChangeWorkspacePage.tsx index 47b2b1f3421e..ce122c080240 100644 --- a/src/pages/ReportChangeWorkspacePage.tsx +++ b/src/pages/ReportChangeWorkspacePage.tsx @@ -40,6 +40,11 @@ function ReportChangeWorkspacePage({report, route}: ReportChangeWorkspacePagePro const [session] = useOnyx(ONYXKEYS.SESSION, {canBeMissing: false}); const [isLoadingApp] = useOnyx(ONYXKEYS.IS_LOADING_APP, {canBeMissing: false}); const isReportLastVisibleArchived = useReportIsArchived(report?.parentReportID); + const [submitterEmail] = useOnyx( + ONYXKEYS.PERSONAL_DETAILS_LIST, + {canBeMissing: false, selector: (personalDetailsList) => personalDetailsList?.[report?.ownerAccountID ?? CONST.DEFAULT_NUMBER_ID]?.login}, + [report?.ownerAccountID], + ); const shouldShowLoadingIndicator = isLoadingApp && !isOffline; const selectPolicy = useCallback( @@ -67,7 +72,6 @@ function ReportChangeWorkspacePage({report, route}: ReportChangeWorkspacePagePro [route.params, report, reportID, reportNextStep, policies, formatPhoneNumber, isReportLastVisibleArchived], ); - const submitterEmail = getLoginByAccountID(report?.ownerAccountID ?? CONST.DEFAULT_NUMBER_ID); const {sections, shouldShowNoResultsFoundMessage, shouldShowSearchInput} = useWorkspaceList({ policies, currentUserLogin: session?.email, From 34d7692c0853cf3bf698c25128cb72f3485018e3 Mon Sep 17 00:00:00 2001 From: Carlos Martins Date: Wed, 1 Oct 2025 10:49:39 -0600 Subject: [PATCH 20/20] fix error --- src/pages/ReportChangeWorkspacePage.tsx | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/pages/ReportChangeWorkspacePage.tsx b/src/pages/ReportChangeWorkspacePage.tsx index 11a415cedd92..ce122c080240 100644 --- a/src/pages/ReportChangeWorkspacePage.tsx +++ b/src/pages/ReportChangeWorkspacePage.tsx @@ -72,8 +72,6 @@ function ReportChangeWorkspacePage({report, route}: ReportChangeWorkspacePagePro [route.params, report, reportID, reportNextStep, policies, formatPhoneNumber, isReportLastVisibleArchived], ); - const submitterEmail = getLoginByAccountID(report?.ownerAccountID ?? CONST.DEFAULT_NUMBER_ID); - const {sections, shouldShowNoResultsFoundMessage, shouldShowSearchInput} = useWorkspaceList({ policies, currentUserLogin: session?.email,