Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions src/libs/API/parameters/ApproveMoneyRequestParams.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,14 @@ type ApproveMoneyRequestParams = {
* }>
*/
optimisticHoldReportExpenseActionIDs?: string;
/**
* Stringified JSON object with type of following structure:
* Array<{
* optimisticReportActionID: string;
* oldReportActionID: string;
* }>
*/
optimisticDuplicatedReportActionIDs?: string;
};

export default ApproveMoneyRequestParams;
8 changes: 8 additions & 0 deletions src/libs/API/parameters/PayMoneyRequestParams.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,14 @@ type PayMoneyRequestParams = {
* }>
*/
optimisticHoldReportExpenseActionIDs?: string;
/**
* Stringified JSON object with type of following structure:
* Array<{
* optimisticReportActionID: string;
* oldReportActionID: string;
* }>
*/
optimisticDuplicatedReportActionIDs?: string;
};

export default PayMoneyRequestParams;
104 changes: 104 additions & 0 deletions src/libs/actions/IOU.ts
Original file line number Diff line number Diff line change
Expand Up @@ -759,7 +759,7 @@
};

let allPersonalDetails: OnyxTypes.PersonalDetailsList = {};
Onyx.connect({

Check warning on line 762 in src/libs/actions/IOU.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.PERSONAL_DETAILS_LIST,
callback: (value) => {
allPersonalDetails = value ?? {};
Expand Down Expand Up @@ -855,7 +855,7 @@
};

let allTransactions: NonNullable<OnyxCollection<OnyxTypes.Transaction>> = {};
Onyx.connect({

Check warning on line 858 in src/libs/actions/IOU.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.COLLECTION.TRANSACTION,
waitForCollectionCallback: true,
callback: (value) => {
Expand All @@ -869,7 +869,7 @@
});

let allTransactionDrafts: NonNullable<OnyxCollection<OnyxTypes.Transaction>> = {};
Onyx.connect({

Check warning on line 872 in src/libs/actions/IOU.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.COLLECTION.TRANSACTION_DRAFT,
waitForCollectionCallback: true,
callback: (value) => {
Expand All @@ -878,7 +878,7 @@
});

let allTransactionViolations: NonNullable<OnyxCollection<OnyxTypes.TransactionViolations>> = {};
Onyx.connect({

Check warning on line 881 in src/libs/actions/IOU.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS,
waitForCollectionCallback: true,
callback: (value) => {
Expand All @@ -892,7 +892,7 @@
});

let allNextSteps: NonNullable<OnyxCollection<OnyxTypes.ReportNextStepDeprecated>> = {};
Onyx.connect({

Check warning on line 895 in src/libs/actions/IOU.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.COLLECTION.NEXT_STEP,
waitForCollectionCallback: true,
callback: (value) => {
Expand All @@ -904,14 +904,14 @@
// `allRecentlyUsedTags` was moved here temporarily from `src/libs/actions/Policy/Tag.ts` during the `Deprecate Onyx.connect` refactor.
// All uses of this variable should be replaced with `useOnyx`.
let allRecentlyUsedTags: OnyxCollection<RecentlyUsedTags> = {};
Onyx.connect({

Check warning on line 907 in src/libs/actions/IOU.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.COLLECTION.POLICY_RECENTLY_USED_TAGS,
waitForCollectionCallback: true,
callback: (val) => (allRecentlyUsedTags = val),
});

let allReports: OnyxCollection<OnyxTypes.Report>;
Onyx.connect({

Check warning on line 914 in src/libs/actions/IOU.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.COLLECTION.REPORT,
waitForCollectionCallback: true,
callback: (value) => {
Expand All @@ -920,7 +920,7 @@
});

let allReportNameValuePairs: OnyxCollection<OnyxTypes.ReportNameValuePairs>;
Onyx.connect({

Check warning on line 923 in src/libs/actions/IOU.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS,
waitForCollectionCallback: true,
callback: (value) => {
Expand All @@ -930,7 +930,7 @@

let userAccountID = -1;
let currentUserEmail = '';
Onyx.connect({

Check warning on line 933 in src/libs/actions/IOU.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.SESSION,
callback: (value) => {
currentUserEmail = value?.email ?? '';
Expand All @@ -939,7 +939,7 @@
});

let deprecatedCurrentUserPersonalDetails: OnyxEntry<OnyxTypes.PersonalDetails>;
Onyx.connect({

Check warning on line 942 in src/libs/actions/IOU.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.PERSONAL_DETAILS_LIST,
callback: (value) => {
deprecatedCurrentUserPersonalDetails = value?.[userAccountID] ?? undefined;
Expand Down Expand Up @@ -10164,6 +10164,93 @@
return {holdReportActions, holdTransactions};
}

/**
* Gets duplicate workflow actions for a partial expense report.
* Used when splitting held expenses into a new partial report to maintain action history.
*
* @param sourceReportID - The ID of the original report to copy actions from
* @param targetReportID - The ID of the new partial expense report to copy actions to
* @returns A tuple of [optimisticData, successData, failureData, duplicatedReportActionIDs]
*/
function getDuplicateActionsForPartialReport(
sourceReportID: string | undefined,
targetReportID: string | undefined,
): [
Array<OnyxUpdate<typeof ONYXKEYS.COLLECTION.REPORT_ACTIONS>>,
Array<OnyxUpdate<typeof ONYXKEYS.COLLECTION.REPORT_ACTIONS>>,
Array<OnyxUpdate<typeof ONYXKEYS.COLLECTION.REPORT_ACTIONS>>,
OptimisticHoldReportExpenseActionID[],
] {
const optimisticData: Array<OnyxUpdate<typeof ONYXKEYS.COLLECTION.REPORT_ACTIONS>> = [];
const successData: Array<OnyxUpdate<typeof ONYXKEYS.COLLECTION.REPORT_ACTIONS>> = [];
const failureData: Array<OnyxUpdate<typeof ONYXKEYS.COLLECTION.REPORT_ACTIONS>> = [];
const optimisticDuplicatedReportActionIDs: OptimisticHoldReportExpenseActionID[] = [];

if (!sourceReportID || !targetReportID) {
return [optimisticData, successData, failureData, optimisticDuplicatedReportActionIDs];
}

const sourceReportActions = getAllReportActions(sourceReportID);

// Match the backend's WORKFLOW_ACTIONS list
const workflowActionTypes = [
CONST.REPORT.ACTIONS.TYPE.SUBMITTED,
CONST.REPORT.ACTIONS.TYPE.SUBMITTED_AND_CLOSED,
CONST.REPORT.ACTIONS.TYPE.APPROVED,
CONST.REPORT.ACTIONS.TYPE.UNAPPROVED,
CONST.REPORT.ACTIONS.TYPE.REJECTED,
CONST.REPORT.ACTIONS.TYPE.RETRACTED,
CONST.REPORT.ACTIONS.TYPE.CLOSED,
CONST.REPORT.ACTIONS.TYPE.REOPENED,
CONST.REPORT.ACTIONS.TYPE.FORWARDED,
CONST.REPORT.ACTIONS.TYPE.TAKE_CONTROL,
CONST.REPORT.ACTIONS.TYPE.REROUTE,
] as const;

const copiedActions: Record<string, OnyxTypes.ReportAction> = {};
const copiedActionsSuccess: OnyxCollection<NullishDeep<ReportAction>> = {};
const copiedActionsFailure: Record<string, null> = {};

for (const action of Object.values(sourceReportActions)) {
if (action && (workflowActionTypes as readonly string[]).includes(action.actionName)) {
const newActionID = NumberUtils.rand64();
copiedActions[newActionID] = {
...action,
reportActionID: newActionID,
reportID: targetReportID,
pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD,
};
copiedActionsSuccess[newActionID] = {
pendingAction: null,
};
copiedActionsFailure[newActionID] = null;
optimisticDuplicatedReportActionIDs.push({optimisticReportActionID: newActionID, oldReportActionID: action.reportActionID});
}
}

if (Object.keys(copiedActions).length > 0) {
optimisticData.push({
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${targetReportID}`,
value: copiedActions,
});

successData.push({
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${targetReportID}`,
value: copiedActionsSuccess,
});

failureData.push({
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${targetReportID}`,
value: copiedActionsFailure,
});
}

return [optimisticData, successData, failureData, optimisticDuplicatedReportActionIDs];
}

function getReportFromHoldRequestsOnyxData(
chatReport: OnyxTypes.Report,
iouReport: OnyxEntry<OnyxTypes.Report>,
Expand All @@ -10172,6 +10259,7 @@
optimisticHoldReportID: string;
optimisticHoldActionID: string;
optimisticHoldReportExpenseActionIDs: OptimisticHoldReportExpenseActionID[];
optimisticDuplicatedReportActionIDs: OptimisticHoldReportExpenseActionID[];
optimisticData: OnyxUpdate[];
successData: OnyxUpdate[];
failureData: OnyxUpdate[];
Expand Down Expand Up @@ -10389,13 +10477,23 @@
},
];

// Copy submission/approval actions to the new report
const [copiedActionsOptimistic, copiedActionsSuccess, copiedActionsFailure, optimisticDuplicatedReportActionIDs] = getDuplicateActionsForPartialReport(
iouReport?.reportID,
optimisticExpenseReport.reportID,
);
optimisticData.push(...copiedActionsOptimistic);
successData.push(...copiedActionsSuccess);
failureData.push(...copiedActionsFailure);

return {
optimisticData,
optimisticHoldActionID: optimisticExpenseReportPreview.reportActionID,
failureData,
successData,
optimisticHoldReportID: optimisticExpenseReport.reportID,
optimisticHoldReportExpenseActionIDs,
optimisticDuplicatedReportActionIDs,
};
}

Expand Down Expand Up @@ -10715,6 +10813,7 @@
let optimisticHoldReportID;
let optimisticHoldActionID;
let optimisticHoldReportExpenseActionIDs;
let optimisticDuplicatedReportActionIDs;
if (!full) {
const holdReportOnyxData = getReportFromHoldRequestsOnyxData(chatReport, iouReport, recipient);

Expand All @@ -10724,6 +10823,7 @@
optimisticHoldReportID = holdReportOnyxData.optimisticHoldReportID;
optimisticHoldActionID = holdReportOnyxData.optimisticHoldActionID;
optimisticHoldReportExpenseActionIDs = JSON.stringify(holdReportOnyxData.optimisticHoldReportExpenseActionIDs);
optimisticDuplicatedReportActionIDs = JSON.stringify(holdReportOnyxData.optimisticDuplicatedReportActionIDs);
}

return {
Expand All @@ -10737,6 +10837,7 @@
optimisticHoldReportID,
optimisticHoldActionID,
optimisticHoldReportExpenseActionIDs,
optimisticDuplicatedReportActionIDs,
...policyParams,
},
optimisticData,
Expand Down Expand Up @@ -11163,6 +11264,7 @@
let optimisticHoldReportID;
let optimisticHoldActionID;
let optimisticHoldReportExpenseActionIDs;
let optimisticDuplicatedReportActionIDs;
if (!full && !!chatReport && !!expenseReport) {
const holdReportOnyxData = getReportFromHoldRequestsOnyxData(chatReport, expenseReport, {accountID: expenseReport.ownerAccountID});

Expand All @@ -11172,6 +11274,7 @@
optimisticHoldReportID = holdReportOnyxData.optimisticHoldReportID;
optimisticHoldActionID = holdReportOnyxData.optimisticHoldActionID;
optimisticHoldReportExpenseActionIDs = JSON.stringify(holdReportOnyxData.optimisticHoldReportExpenseActionIDs);
optimisticDuplicatedReportActionIDs = JSON.stringify(holdReportOnyxData.optimisticDuplicatedReportActionIDs);
}

// Remove duplicates violations if we approve the report
Expand Down Expand Up @@ -11214,6 +11317,7 @@
optimisticHoldReportID,
optimisticHoldActionID,
optimisticHoldReportExpenseActionIDs,
optimisticDuplicatedReportActionIDs,
};

playSound(SOUNDS.SUCCESS);
Expand Down
Loading