diff --git a/src/libs/API/parameters/ChangeReportPolicyAndInviteSubmitterParams.ts b/src/libs/API/parameters/ChangeReportPolicyAndInviteSubmitterParams.ts deleted file mode 100644 index 55a546124116..000000000000 --- a/src/libs/API/parameters/ChangeReportPolicyAndInviteSubmitterParams.ts +++ /dev/null @@ -1,9 +0,0 @@ -type ChangeReportPolicyParams = { - reportID: string; - policyID: string; - reportPreviewReportActionID: string; - changePolicyReportActionID: string; - policyExpenseChatReportID: string; - policyExpenseCreatedReportActionID: string; -}; -export default ChangeReportPolicyParams; diff --git a/src/libs/API/parameters/index.ts b/src/libs/API/parameters/index.ts index 97be7b690980..c06d5f969550 100644 --- a/src/libs/API/parameters/index.ts +++ b/src/libs/API/parameters/index.ts @@ -392,7 +392,6 @@ export type {default as SaveCorpayOnboardingDirectorInformationParams} from './S export type {default as MoveIOUReportToPolicyAndInviteSubmitterParams} from './MoveIOUReportToPolicyAndInviteSubmitterParams'; export type {default as MoveIOUReportToExistingPolicyParams} from './MoveIOUReportToExistingPolicyParams'; export type {default as ChangeReportPolicyParams} from './ChangeReportPolicyParams'; -export type {default as ChangeReportPolicyAndInviteSubmitterParams} from './ChangeReportPolicyAndInviteSubmitterParams'; export type {ChangeTransactionsReportParams, TransactionThreadInfo} from './ChangeTransactionsReportParams'; export type {default as ResetBankAccountSetupParams} from './ResetBankAccountSetupParams'; export type {default as SetPolicyProhibitedExpensesParams} from './SetPolicyProhibitedExpensesParams'; diff --git a/src/libs/API/types.ts b/src/libs/API/types.ts index 607c4add5c67..aab6464fd315 100644 --- a/src/libs/API/types.ts +++ b/src/libs/API/types.ts @@ -478,7 +478,6 @@ const WRITE_COMMANDS = { ADD_WORK_EMAIL: 'AddWorkEmail', SAVE_CORPAY_ONBOARDING_DIRECTOR_INFORMATION: 'SaveCorpayOnboardingDirectorInformation', CHANGE_REPORT_POLICY: 'ChangeReportPolicy', - CHANGE_REPORT_POLICY_AND_INVITE_SUBMITTER: 'ChangeReportPolicyAndInviteSubmitter', CHANGE_TRANSACTIONS_REPORT: 'ChangeTransactionsReport', RETRACT_REPORT: 'RetractReport', PAY_AND_DOWNGRADE: 'PayAndDowngrade', @@ -984,7 +983,6 @@ type WriteCommandParameters = { [WRITE_COMMANDS.MERGE_WITH_VALIDATE_CODE]: Parameters.MergeWithValidateCodeParams; // Change report policy [WRITE_COMMANDS.CHANGE_REPORT_POLICY]: Parameters.ChangeReportPolicyParams; - [WRITE_COMMANDS.CHANGE_REPORT_POLICY_AND_INVITE_SUBMITTER]: Parameters.ChangeReportPolicyAndInviteSubmitterParams; [WRITE_COMMANDS.PAY_AND_DOWNGRADE]: null; diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index f96fe217f8f2..3ff1df9c0ee5 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -9573,215 +9573,6 @@ function createDraftTransactionAndNavigateToParticipantSelector( return createDraftWorkspaceAndNavigateToConfirmationScreen(transactionID, actionName); } -/** - * @private - * Builds a map of parentReportID to child report IDs for efficient traversal. - */ -function buildReportIDToThreadsReportIDsMap(): Record { - const reportIDToThreadsReportIDsMap: Record = {}; - Object.values(allReports ?? {}).forEach((report) => { - if (!report?.parentReportID) { - return; - } - if (!reportIDToThreadsReportIDsMap[report.parentReportID]) { - reportIDToThreadsReportIDsMap[report.parentReportID] = []; - } - reportIDToThreadsReportIDsMap[report.parentReportID].push(report.reportID); - }); - return reportIDToThreadsReportIDsMap; -} - -/** - * @private - * Recursively updates the policyID for a report and all its child reports. - */ -function updatePolicyIdForReportAndThreads( - currentReportID: string, - policyID: string, - reportIDToThreadsReportIDsMap: Record, - optimisticData: OnyxUpdate[], - failureData: OnyxUpdate[], -) { - const currentReport = allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${currentReportID}`]; - const originalPolicyID = currentReport?.policyID; - - if (originalPolicyID) { - optimisticData.push({ - onyxMethod: Onyx.METHOD.MERGE, - key: `${ONYXKEYS.COLLECTION.REPORT}${currentReportID}`, - value: {policyID}, - }); - failureData.push({ - onyxMethod: Onyx.METHOD.MERGE, - key: `${ONYXKEYS.COLLECTION.REPORT}${currentReportID}`, - value: {policyID: originalPolicyID}, - }); - } - - // Recursively process child reports for the current report - const childReportIDs = reportIDToThreadsReportIDsMap[currentReportID] || []; - childReportIDs.forEach((childReportID) => { - updatePolicyIdForReportAndThreads(childReportID, policyID, reportIDToThreadsReportIDsMap, optimisticData, failureData); - }); -} - -function buildOptimisticChangePolicyData(report: Report, policyID: string, optimisticPolicyExpenseChatReport?: Report | undefined) { - const optimisticData: OnyxUpdate[] = []; - const successData: OnyxUpdate[] = []; - const failureData: OnyxUpdate[] = []; - - // 1. Optimistically set the policyID on the report (and all its threads) by: - // 1.1 Preprocess reports to create a map of parentReportID to child reports list of reportIDs - // 1.2 Recursively update the policyID of the report and all its child reports - const reportID = report.reportID; - const reportIDToThreadsReportIDsMap = buildReportIDToThreadsReportIDsMap(); - updatePolicyIdForReportAndThreads(reportID, policyID, reportIDToThreadsReportIDsMap, optimisticData, failureData); - - // 2. If the old workspace had a expense chat, mark the report preview action as deleted - if (report.parentReportID && report.parentReportActionID) { - const oldWorkspaceChatReportID = report.parentReportID; - const oldReportPreviewActionID = report.parentReportActionID; - const oldReportPreviewAction = allReportActions?.[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${oldWorkspaceChatReportID}`]?.[oldReportPreviewActionID]; - const deletedTime = DateUtils.getDBTime(); - const firstMessage = Array.isArray(oldReportPreviewAction?.message) ? oldReportPreviewAction.message.at(0) : null; - const updatedReportPreviewAction = { - ...oldReportPreviewAction, - originalMessage: { - deleted: deletedTime, - }, - ...(firstMessage && { - message: [ - { - ...firstMessage, - deleted: deletedTime, - }, - ...(Array.isArray(oldReportPreviewAction?.message) ? oldReportPreviewAction.message.slice(1) : []), - ], - }), - ...(!Array.isArray(oldReportPreviewAction?.message) && { - message: { - deleted: deletedTime, - }, - }), - }; - - optimisticData.push({ - onyxMethod: Onyx.METHOD.MERGE, - key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${oldWorkspaceChatReportID}`, - value: {[oldReportPreviewActionID]: updatedReportPreviewAction}, - }); - failureData.push({ - onyxMethod: Onyx.METHOD.MERGE, - key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${oldWorkspaceChatReportID}`, - value: {[oldReportPreviewActionID]: oldReportPreviewAction}, - }); - - // Update the expense chat report - const chatReport = allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${oldWorkspaceChatReportID}`]; - const lastMessageText = getLastVisibleMessage(oldWorkspaceChatReportID, {[oldReportPreviewActionID]: updatedReportPreviewAction as ReportAction})?.lastMessageText; - const lastVisibleActionCreated = getReportLastMessage(oldWorkspaceChatReportID, {[oldReportPreviewActionID]: updatedReportPreviewAction as ReportAction})?.lastVisibleActionCreated; - - optimisticData.push({ - onyxMethod: Onyx.METHOD.MERGE, - key: `${ONYXKEYS.COLLECTION.REPORT}${oldWorkspaceChatReportID}`, - value: { - hasOutstandingChildRequest: false, - iouReportID: null, - lastMessageText, - lastVisibleActionCreated, - }, - }); - failureData.push({ - onyxMethod: Onyx.METHOD.MERGE, - key: `${ONYXKEYS.COLLECTION.REPORT}${oldWorkspaceChatReportID}`, - value: chatReport, - }); - } - - // 3. Optimistically create a new REPORT_PREVIEW reportAction with the newReportPreviewActionID - // and set it as a parent of the moved report - const newPolicyExpenseChatReport = optimisticPolicyExpenseChatReport ?? getPolicyExpenseChat(currentUserAccountID, policyID); - const optimisticReportPreviewAction = buildOptimisticReportPreview(newPolicyExpenseChatReport, report); - - if (newPolicyExpenseChatReport) { - const newPolicyExpenseChatReportID = newPolicyExpenseChatReport.reportID; - - optimisticData.push({ - onyxMethod: Onyx.METHOD.MERGE, - key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${newPolicyExpenseChatReportID}`, - value: {[optimisticReportPreviewAction.reportActionID]: optimisticReportPreviewAction}, - }); - successData.push({ - onyxMethod: Onyx.METHOD.MERGE, - key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${newPolicyExpenseChatReportID}`, - value: { - [optimisticReportPreviewAction.reportActionID]: { - pendingAction: null, - }, - }, - }); - failureData.push({ - onyxMethod: Onyx.METHOD.MERGE, - key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${newPolicyExpenseChatReportID}`, - value: {[optimisticReportPreviewAction.reportActionID]: null}, - }); - - // Set the new report preview action as a parent of the moved report, - // and set the parentReportID on the moved report as the expense chat reportID - optimisticData.push({ - onyxMethod: Onyx.METHOD.MERGE, - key: `${ONYXKEYS.COLLECTION.REPORT}${reportID}`, - value: {parentReportActionID: optimisticReportPreviewAction.reportActionID, parentReportID: newPolicyExpenseChatReportID}, - }); - failureData.push({ - onyxMethod: Onyx.METHOD.MERGE, - key: `${ONYXKEYS.COLLECTION.REPORT}${reportID}`, - value: {parentReportActionID: report.parentReportActionID, parentReportID: report.parentReportID}, - }); - - // Set lastVisibleActionCreated - optimisticData.push({ - onyxMethod: Onyx.METHOD.MERGE, - key: `${ONYXKEYS.COLLECTION.REPORT}${newPolicyExpenseChatReportID}`, - value: {lastVisibleActionCreated: optimisticReportPreviewAction?.created}, - }); - failureData.push({ - onyxMethod: Onyx.METHOD.MERGE, - key: `${ONYXKEYS.COLLECTION.REPORT}${newPolicyExpenseChatReportID}`, - value: {lastVisibleActionCreated: newPolicyExpenseChatReport.lastVisibleActionCreated}, - }); - } - - // 4. Optimistically create a CHANGE_POLICY reportAction on the report using the reportActionID - const optimisticMovedReportAction = buildOptimisticChangePolicyReportAction(report.policyID, policyID); - optimisticData.push({ - onyxMethod: Onyx.METHOD.MERGE, - key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${reportID}`, - value: {[optimisticMovedReportAction.reportActionID]: optimisticMovedReportAction}, - }); - successData.push({ - onyxMethod: Onyx.METHOD.MERGE, - key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${reportID}`, - value: { - [optimisticMovedReportAction.reportActionID]: { - pendingAction: null, - errors: null, - }, - }, - }); - failureData.push({ - onyxMethod: Onyx.METHOD.MERGE, - key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${reportID}`, - value: { - [optimisticMovedReportAction.reportActionID]: { - errors: getMicroSecondOnyxErrorWithTranslationKey('common.genericErrorMessage'), - }, - }, - }); - - return {optimisticData, successData, failureData, optimisticReportPreviewAction, optimisticMovedReportAction}; -} - /** * Check if a report has any forwarded actions */ @@ -10900,7 +10691,6 @@ export { buildOptimisticUnapprovedReportAction, buildOptimisticCancelPaymentReportAction, buildOptimisticChangedTaskAssigneeReportAction, - buildOptimisticChangePolicyData, buildOptimisticChatReport, buildOptimisticClosedReportAction, buildOptimisticCreatedReportAction, diff --git a/src/libs/actions/Policy/Policy.ts b/src/libs/actions/Policy/Policy.ts index 57c2cf379970..67b4e8b86c89 100644 --- a/src/libs/actions/Policy/Policy.ts +++ b/src/libs/actions/Policy/Policy.ts @@ -77,7 +77,6 @@ import * as PhoneNumber from '@libs/PhoneNumber'; import * as PolicyUtils from '@libs/PolicyUtils'; import {goBackWhenEnableFeature, navigateToExpensifyCardPage} from '@libs/PolicyUtils'; import * as ReportUtils from '@libs/ReportUtils'; -import type {OptimisticChatReport} from '@libs/ReportUtils'; import type {PolicySelector} from '@pages/home/sidebar/FloatingActionButtonAndPopover'; import * as PaymentMethods from '@userActions/PaymentMethods'; import * as PersistedRequests from '@userActions/PersistedRequests'; @@ -112,7 +111,6 @@ type ReportCreationData = Record< { reportID: string; reportActionID?: string; - report: OptimisticChatReport; } >; @@ -1072,7 +1070,6 @@ function createPolicyExpenseChats(policyID: string, invitedEmailsToAccountIDs: I // If the chat already exists, we don't want to create a new one - just make sure it's not archived if (oldChat) { workspaceMembersChats.reportCreationData[login] = { - report: oldChat, reportID: oldChat.reportID, }; workspaceMembersChats.onyxOptimisticData.push({ @@ -1122,7 +1119,6 @@ function createPolicyExpenseChats(policyID: string, invitedEmailsToAccountIDs: I const optimisticCreatedAction = ReportUtils.buildOptimisticCreatedReportAction(login); workspaceMembersChats.reportCreationData[login] = { - report: optimisticReport, reportID: optimisticReport.reportID, reportActionID: optimisticCreatedAction.reportActionID, }; diff --git a/src/libs/actions/Report.ts b/src/libs/actions/Report.ts index c195da1b9bd3..039ff861a776 100644 --- a/src/libs/actions/Report.ts +++ b/src/libs/actions/Report.ts @@ -89,7 +89,7 @@ import {shouldOnboardingRedirectToOldDot} from '@libs/OnboardingUtils'; import Parser from '@libs/Parser'; import * as PersonalDetailsUtils from '@libs/PersonalDetailsUtils'; import * as PhoneNumber from '@libs/PhoneNumber'; -import {getDefaultApprover, getMemberAccountIDsForWorkspace, getPolicy, isPolicyAdmin as isPolicyAdminPolicyUtils, isPolicyMember} from '@libs/PolicyUtils'; +import {getDefaultApprover, getPolicy, isPolicyAdmin as isPolicyAdminPolicyUtils, isPolicyMember} from '@libs/PolicyUtils'; import processReportIDDeeplink from '@libs/processReportIDDeeplink'; import Pusher from '@libs/Pusher'; import type {UserIsLeavingRoomEvent, UserIsTypingEvent} from '@libs/Pusher/types'; @@ -98,7 +98,6 @@ import type {OptimisticAddCommentReportAction, OptimisticChatReport, SelfDMParam import { buildOptimisticAddCommentReportAction, buildOptimisticChangeFieldAction, - buildOptimisticChangePolicyData, buildOptimisticChangePolicyReportAction, buildOptimisticChatReport, buildOptimisticCreatedReportAction, @@ -107,6 +106,7 @@ import { buildOptimisticGroupChatReport, buildOptimisticIOUReportAction, buildOptimisticRenamedRoomReportAction, + buildOptimisticReportPreview, buildOptimisticRoomDescriptionUpdatedReportAction, buildOptimisticSelfDMReport, buildOptimisticUnreportedTransactionAction, @@ -172,7 +172,6 @@ import type { PersonalDetailsList, Policy, PolicyEmployee, - PolicyEmployeeList, PolicyReportField, QuickAction, RecentlyUsedReportFields, @@ -192,7 +191,7 @@ import {clearByKey} from './CachedPDFPaths'; import {setDownload} from './Download'; import {close} from './Modal'; import navigateFromNotification from './navigateFromNotification'; -import {buildAddMembersToWorkspaceOnyxData, buildRoomMembersOnyxData} from './Policy/Member'; +import {buildRoomMembersOnyxData} from './Policy/Member'; import {createPolicyExpenseChats} from './Policy/Policy'; import { createUpdateCommentMatcher, @@ -5356,81 +5355,234 @@ function dismissChangePolicyModal() { } /** - * Changes the policy of a report and all its child reports, and moves the report to the new policy's expense chat. + * @private + * Builds a map of parentReportID to child report IDs for efficient traversal. */ -function changeReportPolicy(report: Report, policyID: string) { - if (!report || !policyID || report.policyID === policyID || !isExpenseReport(report)) { - return; - } - - const {optimisticData, successData, failureData, optimisticReportPreviewAction, optimisticMovedReportAction} = buildOptimisticChangePolicyData(report, policyID); +function buildReportIDToThreadsReportIDsMap(): Record { + const reportIDToThreadsReportIDsMap: Record = {}; + Object.values(allReports ?? {}).forEach((report) => { + if (!report?.parentReportID) { + return; + } + if (!reportIDToThreadsReportIDsMap[report.parentReportID]) { + reportIDToThreadsReportIDsMap[report.parentReportID] = []; + } + reportIDToThreadsReportIDsMap[report.parentReportID].push(report.reportID); + }); + return reportIDToThreadsReportIDsMap; +} - const params = { - reportID: report.reportID, - policyID, - reportPreviewReportActionID: optimisticReportPreviewAction.reportActionID, - changePolicyReportActionID: optimisticMovedReportAction.reportActionID, - }; - API.write(WRITE_COMMANDS.CHANGE_REPORT_POLICY, params, {optimisticData, successData, failureData}); +/** + * @private + * Recursively updates the policyID for a report and all its child reports. + */ +function updatePolicyIdForReportAndThreads( + currentReportID: string, + policyID: string, + reportIDToThreadsReportIDsMap: Record, + optimisticData: OnyxUpdate[], + failureData: OnyxUpdate[], +) { + const currentReport = allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${currentReportID}`]; + const originalPolicyID = currentReport?.policyID; - // 5. If the dismissedProductTraining.changeReportModal is not set, - // navigate to CHANGE_POLICY_EDUCATIONAL and a backTo param for the report page. - if (!nvpDismissedProductTraining?.[CONST.CHANGE_POLICY_TRAINING_MODAL]) { - Navigation.navigate(ROUTES.CHANGE_POLICY_EDUCATIONAL.getRoute(ROUTES.REPORT_WITH_ID.getRoute(report.reportID))); + if (originalPolicyID) { + optimisticData.push({ + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.REPORT}${currentReportID}`, + value: {policyID}, + }); + failureData.push({ + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.REPORT}${currentReportID}`, + value: {policyID: originalPolicyID}, + }); } + + // Recursively process child reports for the current report + const childReportIDs = reportIDToThreadsReportIDsMap[currentReportID] || []; + childReportIDs.forEach((childReportID) => { + updatePolicyIdForReportAndThreads(childReportID, policyID, reportIDToThreadsReportIDsMap, optimisticData, failureData); + }); } /** * Changes the policy of a report and all its child reports, and moves the report to the new policy's expense chat. */ -function changeReportPolicyAndInviteSubmitter(report: Report, policyID: string, employeeList: PolicyEmployeeList | undefined) { - if (!report.reportID || !policyID || report.policyID === policyID || !isExpenseReport(report) || !report.ownerAccountID) { +function changeReportPolicy(reportID: string, policyID: string) { + if (!reportID || !policyID) { + return; + } + const reportToMove = allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${reportID}`]; + if (!reportToMove || reportToMove?.policyID === policyID || !isExpenseReport(reportToMove)) { return; } - const submitterEmail = PersonalDetailsUtils.getLoginByAccountID(report.ownerAccountID); + const optimisticData: OnyxUpdate[] = []; + const successData: OnyxUpdate[] = []; + const failureData: OnyxUpdate[] = []; - if (!submitterEmail) { - return; + // 1. Optimistically set the policyID on the report (and all its threads) + + // Preprocess reports to create a map of parentReportID to child reports list of reportIDs + const reportIDToThreadsReportIDsMap = buildReportIDToThreadsReportIDsMap(); + + // Recursively update the policyID of the report and all its child reports + updatePolicyIdForReportAndThreads(reportID, policyID, reportIDToThreadsReportIDsMap, optimisticData, failureData); + + // 2. If the old workspace had a expense chat, mark the report preview action as deleted + if (reportToMove?.parentReportID && reportToMove?.parentReportActionID) { + const workspaceChatReportID = reportToMove.parentReportID; + const reportPreviewActionID = reportToMove.parentReportActionID; + const oldReportPreviewAction = allReportActions?.[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${workspaceChatReportID}`]?.[reportPreviewActionID]; + const deletedTime = DateUtils.getDBTime(); + const firstMessage = Array.isArray(oldReportPreviewAction?.message) ? oldReportPreviewAction.message.at(0) : null; + const updatedReportPreviewAction = { + ...oldReportPreviewAction, + originalMessage: { + deleted: deletedTime, + }, + ...(firstMessage && { + message: [ + { + ...firstMessage, + deleted: deletedTime, + }, + ...(Array.isArray(oldReportPreviewAction?.message) ? oldReportPreviewAction.message.slice(1) : []), + ], + }), + ...(!Array.isArray(oldReportPreviewAction?.message) && { + message: { + deleted: deletedTime, + }, + }), + }; + + optimisticData.push({ + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${workspaceChatReportID}`, + value: {[reportPreviewActionID]: updatedReportPreviewAction}, + }); + failureData.push({ + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${workspaceChatReportID}`, + value: {[reportPreviewActionID]: oldReportPreviewAction}, + }); + + // Update the expense chat report + const chatReport = allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${workspaceChatReportID}`]; + const lastMessageText = getLastVisibleMessage(workspaceChatReportID, {[reportPreviewActionID]: updatedReportPreviewAction as ReportAction})?.lastMessageText; + const lastVisibleActionCreated = getReportLastMessage(workspaceChatReportID, {[reportPreviewActionID]: updatedReportPreviewAction as ReportAction})?.lastVisibleActionCreated; + + optimisticData.push({ + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.REPORT}${workspaceChatReportID}`, + value: { + hasOutstandingChildRequest: false, + iouReportID: null, + lastMessageText, + lastVisibleActionCreated, + }, + }); + failureData.push({ + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.REPORT}${workspaceChatReportID}`, + value: chatReport, + }); } - const policyMemberAccountIDs = Object.values(getMemberAccountIDsForWorkspace(employeeList, false, false)); - const {optimisticData, successData, failureData, membersChats} = buildAddMembersToWorkspaceOnyxData( - {[submitterEmail]: report.ownerAccountID}, - policyID, - policyMemberAccountIDs, - CONST.POLICY.ROLE.USER, - ); - const optimisticPolicyExpenseChatReport = membersChats.reportCreationData[submitterEmail].report; - const optimisticPolicyExpenseChatCreatedReportActionID = membersChats.reportCreationData[submitterEmail].reportActionID; - if (!optimisticPolicyExpenseChatReport || !optimisticPolicyExpenseChatCreatedReportActionID) { - return; + // 3. Optimistically create a new REPORT_PREVIEW reportAction with the newReportPreviewActionID + // and set it as a parent of the moved report + const policyExpenseChat = getPolicyExpenseChat(currentUserAccountID, policyID); + const optimisticReportPreviewAction = buildOptimisticReportPreview(policyExpenseChat, reportToMove); + + if (policyExpenseChat) { + optimisticData.push({ + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${policyExpenseChat.reportID}`, + value: {[optimisticReportPreviewAction.reportActionID]: optimisticReportPreviewAction}, + }); + successData.push({ + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${policyExpenseChat.reportID}`, + value: { + [optimisticReportPreviewAction.reportActionID]: { + pendingAction: null, + }, + }, + }); + failureData.push({ + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${policyExpenseChat.reportID}`, + value: {[optimisticReportPreviewAction.reportActionID]: null}, + }); + + // Set the new report preview action as a parent of the moved report, + // and set the parentReportID on the moved report as the expense chat reportID + optimisticData.push({ + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.REPORT}${reportID}`, + value: {parentReportActionID: optimisticReportPreviewAction.reportActionID, parentReportID: policyExpenseChat.reportID}, + }); + failureData.push({ + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.REPORT}${reportID}`, + value: {parentReportActionID: reportToMove.parentReportActionID, parentReportID: reportToMove.parentReportID}, + }); + + // Set lastVisibleActionCreated + optimisticData.push({ + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.REPORT}${policyExpenseChat.reportID}`, + value: {lastVisibleActionCreated: optimisticReportPreviewAction?.created}, + }); + failureData.push({ + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.REPORT}${policyExpenseChat.reportID}`, + value: {lastVisibleActionCreated: policyExpenseChat.lastVisibleActionCreated}, + }); } - const { - optimisticData: optimisticChangePolicyData, - successData: successChangePolicyData, - failureData: failureChangePolicyData, - optimisticReportPreviewAction, - optimisticMovedReportAction, - } = buildOptimisticChangePolicyData(report, policyID, optimisticPolicyExpenseChatReport); - optimisticData.push(...optimisticChangePolicyData); - successData.push(...successChangePolicyData); - failureData.push(...failureChangePolicyData); + // 4. Optimistically create a CHANGE_POLICY reportAction on the report using the reportActionID + const optimisticMovedReportAction = buildOptimisticChangePolicyReportAction(reportToMove.policyID, policyID); + optimisticData.push({ + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${reportToMove.reportID}`, + value: {[optimisticMovedReportAction.reportActionID]: optimisticMovedReportAction}, + }); + successData.push({ + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${reportToMove.reportID}`, + value: { + [optimisticMovedReportAction.reportActionID]: { + pendingAction: null, + errors: null, + }, + }, + }); + failureData.push({ + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${reportToMove.reportID}`, + value: { + [optimisticMovedReportAction.reportActionID]: { + errors: getMicroSecondOnyxErrorWithTranslationKey('common.genericErrorMessage'), + }, + }, + }); + // Call the ChangeReportPolicy API endpoint const params = { - reportID: report.reportID, + reportID: reportToMove.reportID, policyID, reportPreviewReportActionID: optimisticReportPreviewAction.reportActionID, changePolicyReportActionID: optimisticMovedReportAction.reportActionID, - policyExpenseChatReportID: optimisticPolicyExpenseChatReport.reportID, - policyExpenseCreatedReportActionID: optimisticPolicyExpenseChatCreatedReportActionID, }; - API.write(WRITE_COMMANDS.CHANGE_REPORT_POLICY_AND_INVITE_SUBMITTER, params, {optimisticData, successData, failureData}); + API.write(WRITE_COMMANDS.CHANGE_REPORT_POLICY, params, {optimisticData, successData, failureData}); - // If the dismissedProductTraining.changeReportModal is not set, navigate to CHANGE_POLICY_EDUCATIONAL and a backTo param for the report page. + // 5. If the dismissedProductTraining.changeReportModal is not set, + // navigate to CHANGE_POLICY_EDUCATIONAL and a backTo param for the report page. if (!nvpDismissedProductTraining?.[CONST.CHANGE_POLICY_TRAINING_MODAL]) { - Navigation.navigate(ROUTES.CHANGE_POLICY_EDUCATIONAL.getRoute(ROUTES.REPORT_WITH_ID.getRoute(report.reportID))); + Navigation.navigate(ROUTES.CHANGE_POLICY_EDUCATIONAL.getRoute(ROUTES.REPORT_WITH_ID.getRoute(reportToMove.reportID))); } } @@ -5540,7 +5692,6 @@ export { moveIOUReportToPolicyAndInviteSubmitter, dismissChangePolicyModal, changeReportPolicy, - changeReportPolicyAndInviteSubmitter, removeFailedReport, openUnreportedExpense, }; diff --git a/src/pages/ReportChangeWorkspacePage.tsx b/src/pages/ReportChangeWorkspacePage.tsx index ee297807bcc5..1e7dac0d7d44 100644 --- a/src/pages/ReportChangeWorkspacePage.tsx +++ b/src/pages/ReportChangeWorkspacePage.tsx @@ -11,13 +11,13 @@ import useNetwork from '@hooks/useNetwork'; import useThemeStyles from '@hooks/useThemeStyles'; import type {WorkspaceListItem} from '@hooks/useWorkspaceList'; import useWorkspaceList from '@hooks/useWorkspaceList'; -import {changeReportPolicy, changeReportPolicyAndInviteSubmitter, moveIOUReportToPolicy, moveIOUReportToPolicyAndInviteSubmitter} from '@libs/actions/Report'; +import {changeReportPolicy, moveIOUReportToPolicy, moveIOUReportToPolicyAndInviteSubmitter} from '@libs/actions/Report'; import Navigation from '@libs/Navigation/Navigation'; import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types'; import type {ReportChangeWorkspaceNavigatorParamList} from '@libs/Navigation/types'; import {getLoginByAccountID} from '@libs/PersonalDetailsUtils'; import {getPolicy, isPolicyAdmin, isPolicyMember} from '@libs/PolicyUtils'; -import {isExpenseReport, isIOUReport, isMoneyRequestReport, isMoneyRequestReportPendingDeletion, isWorkspaceEligibleForReportChange} from '@libs/ReportUtils'; +import {isIOUReport, isMoneyRequestReport, isMoneyRequestReportPendingDeletion, isWorkspaceEligibleForReportChange} from '@libs/ReportUtils'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; import type SCREENS from '@src/SCREENS'; @@ -49,14 +49,11 @@ function ReportChangeWorkspacePage({report}: ReportChangeWorkspacePageProps) { moveIOUReportToPolicyAndInviteSubmitter(reportID, policyID); } else if (isIOUReport(reportID) && isPolicyMember(session?.email, policyID)) { moveIOUReportToPolicy(reportID, policyID); - } else if (isExpenseReport(report) && isPolicyAdmin(getPolicy(policyID)) && report.ownerAccountID && !isPolicyMember(getLoginByAccountID(report.ownerAccountID), policyID)) { - const employeeList = policies?.[`${ONYXKEYS.COLLECTION.POLICY}${policyID}`]?.employeeList; - changeReportPolicyAndInviteSubmitter(report, policyID, employeeList); } else { - changeReportPolicy(report, policyID); + changeReportPolicy(reportID, policyID); } }, - [session?.email, report, reportID, policies], + [session?.email, report, reportID], ); const {sections, shouldShowNoResultsFoundMessage, shouldShowSearchInput} = useWorkspaceList({