@@ -9447,6 +9447,95 @@ function getHoldReportActionsAndTransactions(reportID: string | undefined) {
94479447 return {holdReportActions, holdTransactions};
94489448}
94499449
9450+ type OptimisticReportActionCopyIDs = Record<string, string>;
9451+
9452+ /**
9453+ * Gets duplicate workflow actions for a partial expense report.
9454+ * Used when splitting held expenses into a new partial report to maintain action history.
9455+ *
9456+ * @param sourceReportID - The ID of the original report to copy actions from
9457+ * @param targetReportID - The ID of the new partial expense report to copy actions to
9458+ * @returns A tuple of [optimisticData, successData, failureData, duplicatedReportActionIDs]
9459+ */
9460+ function getDuplicateActionsForPartialReport(
9461+ sourceReportID: string | undefined,
9462+ targetReportID: string | undefined,
9463+ ): [
9464+ Array<OnyxUpdate<typeof ONYXKEYS.COLLECTION.REPORT_ACTIONS>>,
9465+ Array<OnyxUpdate<typeof ONYXKEYS.COLLECTION.REPORT_ACTIONS>>,
9466+ Array<OnyxUpdate<typeof ONYXKEYS.COLLECTION.REPORT_ACTIONS>>,
9467+ OptimisticReportActionCopyIDs,
9468+ ] {
9469+ const optimisticData: Array<OnyxUpdate<typeof ONYXKEYS.COLLECTION.REPORT_ACTIONS>> = [];
9470+ const successData: Array<OnyxUpdate<typeof ONYXKEYS.COLLECTION.REPORT_ACTIONS>> = [];
9471+ const failureData: Array<OnyxUpdate<typeof ONYXKEYS.COLLECTION.REPORT_ACTIONS>> = [];
9472+ const optimisticReportActionCopyIDs: OptimisticReportActionCopyIDs = {};
9473+
9474+ if (!sourceReportID || !targetReportID) {
9475+ return [optimisticData, successData, failureData, optimisticReportActionCopyIDs];
9476+ }
9477+
9478+ const sourceReportActions = getAllReportActions(sourceReportID);
9479+
9480+ // Match the backend's WORKFLOW_ACTIONS list
9481+ const workflowActionTypes = [
9482+ CONST.REPORT.ACTIONS.TYPE.SUBMITTED,
9483+ CONST.REPORT.ACTIONS.TYPE.SUBMITTED_AND_CLOSED,
9484+ CONST.REPORT.ACTIONS.TYPE.APPROVED,
9485+ CONST.REPORT.ACTIONS.TYPE.UNAPPROVED,
9486+ CONST.REPORT.ACTIONS.TYPE.REJECTED,
9487+ CONST.REPORT.ACTIONS.TYPE.RETRACTED,
9488+ CONST.REPORT.ACTIONS.TYPE.CLOSED,
9489+ CONST.REPORT.ACTIONS.TYPE.REOPENED,
9490+ CONST.REPORT.ACTIONS.TYPE.FORWARDED,
9491+ CONST.REPORT.ACTIONS.TYPE.TAKE_CONTROL,
9492+ CONST.REPORT.ACTIONS.TYPE.REROUTE,
9493+ ] as const;
9494+
9495+ const copiedActions: Record<string, OnyxTypes.ReportAction> = {};
9496+ const copiedActionsSuccess: OnyxCollection<NullishDeep<ReportAction>> = {};
9497+ const copiedActionsFailure: Record<string, null> = {};
9498+
9499+ for (const action of Object.values(sourceReportActions)) {
9500+ if (action && (workflowActionTypes as readonly string[]).includes(action.actionName)) {
9501+ const newActionID = NumberUtils.rand64();
9502+ copiedActions[newActionID] = {
9503+ ...action,
9504+ reportActionID: newActionID,
9505+ reportID: targetReportID,
9506+ pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD,
9507+ };
9508+ copiedActionsSuccess[newActionID] = {
9509+ pendingAction: null,
9510+ };
9511+ copiedActionsFailure[newActionID] = null;
9512+ optimisticReportActionCopyIDs[action.reportActionID] = newActionID;
9513+ }
9514+ }
9515+
9516+ if (Object.keys(copiedActions).length > 0) {
9517+ optimisticData.push({
9518+ onyxMethod: Onyx.METHOD.MERGE,
9519+ key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${targetReportID}`,
9520+ value: copiedActions,
9521+ });
9522+
9523+ successData.push({
9524+ onyxMethod: Onyx.METHOD.MERGE,
9525+ key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${targetReportID}`,
9526+ value: copiedActionsSuccess,
9527+ });
9528+
9529+ failureData.push({
9530+ onyxMethod: Onyx.METHOD.MERGE,
9531+ key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${targetReportID}`,
9532+ value: copiedActionsFailure,
9533+ });
9534+ }
9535+
9536+ return [optimisticData, successData, failureData, optimisticReportActionCopyIDs];
9537+ }
9538+
94509539function getReportFromHoldRequestsOnyxData({
94519540 chatReport,
94529541 iouReport,
@@ -9466,6 +9555,7 @@ function getReportFromHoldRequestsOnyxData({
94669555 optimisticHoldActionID: string;
94679556 optimisticCreatedReportForUnapprovedTransactionsActionID: string | undefined;
94689557 optimisticHoldReportExpenseActionIDs: OptimisticHoldReportExpenseActionID[];
9558+ optimisticReportActionCopyIDs: OptimisticReportActionCopyIDs;
94699559 optimisticData: OnyxUpdate[];
94709560 successData: OnyxUpdate[];
94719561 failureData: OnyxUpdate[];
@@ -9710,6 +9800,17 @@ function getReportFromHoldRequestsOnyxData({
97109800 },
97119801 ];
97129802
9803+ // Copy submission/approval actions to the new report
9804+ const [copiedActionsOptimistic, copiedActionsSuccess, copiedActionsFailure, optimisticReportActionCopyIDs] = getDuplicateActionsForPartialReport(
9805+ iouReport?.reportID,
9806+ optimisticExpenseReport.reportID,
9807+ );
9808+ // Only copy the report action for approval flow
9809+ if (isApprovalFlow && !isEmptyObject(optimisticReportActionCopyIDs)) {
9810+ optimisticData.push(...copiedActionsOptimistic);
9811+ successData.push(...copiedActionsSuccess);
9812+ failureData.push(...copiedActionsFailure);
9813+ }
97139814 // add optimistic system message explaining the created report for unapproved transactions
97149815 if (isApprovalFlow && optimisticCreatedReportForUnapprovedAction) {
97159816 optimisticData.push({
@@ -9748,6 +9849,7 @@ function getReportFromHoldRequestsOnyxData({
97489849 successData,
97499850 optimisticHoldReportID: optimisticExpenseReport.reportID,
97509851 optimisticHoldReportExpenseActionIDs,
9852+ optimisticReportActionCopyIDs,
97519853 };
97529854}
97539855
@@ -10454,6 +10556,7 @@ function approveMoneyRequest(
1045410556 let optimisticHoldReportID;
1045510557 let optimisticHoldActionID;
1045610558 let optimisticHoldReportExpenseActionIDs;
10559+ let optimisticReportActionCopyIDs;
1045710560 let optimisticCreatedReportForUnapprovedTransactionsActionID;
1045810561 if (!full && !!chatReport && !!expenseReport) {
1045910562 const originalCreated = getReportOriginalCreationTimestamp(expenseReport);
@@ -10473,6 +10576,7 @@ function approveMoneyRequest(
1047310576 optimisticHoldActionID = holdReportOnyxData.optimisticHoldActionID;
1047410577 optimisticCreatedReportForUnapprovedTransactionsActionID = holdReportOnyxData.optimisticCreatedReportForUnapprovedTransactionsActionID;
1047510578 optimisticHoldReportExpenseActionIDs = JSON.stringify(holdReportOnyxData.optimisticHoldReportExpenseActionIDs);
10579+ optimisticReportActionCopyIDs = JSON.stringify(holdReportOnyxData.optimisticReportActionCopyIDs);
1047610580 }
1047710581
1047810582 // Remove duplicates violations if we approve the report
@@ -10515,6 +10619,7 @@ function approveMoneyRequest(
1051510619 optimisticHoldReportID,
1051610620 optimisticHoldActionID,
1051710621 optimisticHoldReportExpenseActionIDs,
10622+ optimisticReportActionCopyIDs,
1051810623 optimisticCreatedReportForUnapprovedTransactionsActionID,
1051910624 };
1052010625
0 commit comments