diff --git a/src/libs/API/parameters/DetachReceiptParams.ts b/src/libs/API/parameters/DetachReceiptParams.ts index a19b525a0ef0..b0aeed075d51 100644 --- a/src/libs/API/parameters/DetachReceiptParams.ts +++ b/src/libs/API/parameters/DetachReceiptParams.ts @@ -1,5 +1,6 @@ type DetachReceiptParams = { transactionID: string; + reportActionID: string; }; export default DetachReceiptParams; diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index 5e50f69e28fa..2502cfd64608 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -5595,6 +5595,43 @@ function buildOptimisticModifiedExpenseReportAction( }; } +/** + * Builds an optimistic DETACH_RECEIPT report action with a randomly generated reportActionID. + */ +function buildOptimisticDetachReceipt(reportID: string | undefined, transactionID: string, merchant: string = CONST.TRANSACTION.PARTIAL_TRANSACTION_MERCHANT) { + return { + actionName: CONST.REPORT.ACTIONS.TYPE.MANAGER_DETACH_RECEIPT, + actorAccountID: currentUserAccountID, + automatic: false, + avatar: getCurrentUserAvatar(), + created: DateUtils.getDBTime(), + isAttachmentOnly: false, + originalMessage: { + transactionID, + merchant: `${merchant}`, + }, + message: [ + { + type: 'COMMENT', + html: `detached a receipt from expense '${merchant}'`, + text: `detached a receipt from expense '${merchant}'`, + whisperedTo: [], + }, + ], + person: [ + { + style: 'strong', + text: currentUserPersonalDetails?.displayName ?? String(currentUserAccountID), + type: 'TEXT', + }, + ], + pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD, + reportActionID: rand64(), + reportID, + shouldShow: true, + }; +} + /** * Builds an optimistic modified expense action for a tracked expense move with a randomly generated reportActionID. * @param transactionThreadID - The reportID of the transaction thread @@ -8915,6 +8952,7 @@ export { buildOptimisticAnnounceChat, buildOptimisticWorkspaceChats, buildOptimisticCardAssignedReportAction, + buildOptimisticDetachReceipt, buildParticipantsFromAccountIDs, buildReportNameFromParticipantNames, buildTransactionThread, diff --git a/src/libs/actions/IOU.ts b/src/libs/actions/IOU.ts index 3c86ce947742..ef698e19272c 100644 --- a/src/libs/actions/IOU.ts +++ b/src/libs/actions/IOU.ts @@ -81,6 +81,7 @@ import { buildOptimisticCancelPaymentReportAction, buildOptimisticChatReport, buildOptimisticCreatedReportAction, + buildOptimisticDetachReceipt, buildOptimisticDismissedViolationReportAction, buildOptimisticExpenseReport, buildOptimisticHoldReportAction, @@ -8706,8 +8707,51 @@ function detachReceipt(transactionID: string | undefined) { }, }, ]; + const expenseReport = allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${transaction?.reportID}`] ?? null; + const updatedReportAction = buildOptimisticDetachReceipt(expenseReport?.reportID, transactionID, transaction?.merchant); - const parameters: DetachReceiptParams = {transactionID}; + optimisticData.push({ + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${updatedReportAction?.reportID}`, + value: { + [updatedReportAction.reportActionID]: updatedReportAction as OnyxTypes.ReportAction, + }, + }); + optimisticData.push({ + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.REPORT}${updatedReportAction?.reportID}`, + value: { + lastVisibleActionCreated: updatedReportAction.created, + lastReadTime: updatedReportAction.created, + }, + }); + failureData.push({ + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.REPORT}${updatedReportAction?.reportID}`, + value: { + lastVisibleActionCreated: expenseReport?.lastVisibleActionCreated, + lastReadTime: expenseReport?.lastReadTime, + }, + }); + successData.push({ + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${expenseReport?.reportID}`, + value: { + [updatedReportAction.reportActionID]: {pendingAction: null}, + }, + }); + failureData.push({ + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${expenseReport?.reportID}`, + value: { + [updatedReportAction.reportActionID]: { + ...(updatedReportAction as OnyxTypes.ReportAction), + errors: getMicroSecondOnyxErrorWithTranslationKey('iou.error.genericEditFailureMessage'), + }, + }, + }); + + const parameters: DetachReceiptParams = {transactionID, reportActionID: updatedReportAction.reportActionID}; API.write(WRITE_COMMANDS.DETACH_RECEIPT, parameters, {optimisticData, successData, failureData}); }