From fbbcdae27919e54642ca4e1fe80eba3966251e64 Mon Sep 17 00:00:00 2001 From: Lizzi Lindboe Date: Tue, 6 Feb 2024 11:13:00 -0800 Subject: [PATCH] Revert "editMoneyRequest is no longer used, delete" This reverts commit 34930401a0b74bc3144a000b05fb3da620d2a865. --- .../API/parameters/EditMoneyRequestParams.ts | 14 + src/libs/API/parameters/index.ts | 1 + src/libs/API/types.ts | 2 + src/libs/actions/IOU.ts | 288 ++++++++++++++++++ tests/actions/IOUTest.js | 276 +++++++++++++++++ 5 files changed, 581 insertions(+) create mode 100644 src/libs/API/parameters/EditMoneyRequestParams.ts diff --git a/src/libs/API/parameters/EditMoneyRequestParams.ts b/src/libs/API/parameters/EditMoneyRequestParams.ts new file mode 100644 index 000000000000..6d320510e267 --- /dev/null +++ b/src/libs/API/parameters/EditMoneyRequestParams.ts @@ -0,0 +1,14 @@ +type EditMoneyRequestParams = { + transactionID: string; + reportActionID: string; + created?: string; + amount?: number; + currency?: string; + comment?: string; + merchant?: string; + category?: string; + billable?: boolean; + tag?: string; +}; + +export default EditMoneyRequestParams; diff --git a/src/libs/API/parameters/index.ts b/src/libs/API/parameters/index.ts index d3a730dd64a2..4d784463c2f8 100644 --- a/src/libs/API/parameters/index.ts +++ b/src/libs/API/parameters/index.ts @@ -134,6 +134,7 @@ export type {default as CreateDistanceRequestParams} from './CreateDistanceReque export type {default as StartSplitBillParams} from './StartSplitBillParams'; export type {default as SendMoneyParams} from './SendMoneyParams'; export type {default as ApproveMoneyRequestParams} from './ApproveMoneyRequestParams'; +export type {default as EditMoneyRequestParams} from './EditMoneyRequestParams'; export type {default as ReplaceReceiptParams} from './ReplaceReceiptParams'; export type {default as SubmitReportParams} from './SubmitReportParams'; export type {default as DetachReceiptParams} from './DetachReceiptParams'; diff --git a/src/libs/API/types.ts b/src/libs/API/types.ts index 679d7af63cd5..a4ab3db9a7cd 100644 --- a/src/libs/API/types.ts +++ b/src/libs/API/types.ts @@ -135,6 +135,7 @@ const WRITE_COMMANDS = { SEND_MONEY_ELSEWHERE: 'SendMoneyElsewhere', SEND_MONEY_WITH_WALLET: 'SendMoneyWithWallet', APPROVE_MONEY_REQUEST: 'ApproveMoneyRequest', + EDIT_MONEY_REQUEST: 'EditMoneyRequest', REPLACE_RECEIPT: 'ReplaceReceipt', SUBMIT_REPORT: 'SubmitReport', DETACH_RECEIPT: 'DetachReceipt', @@ -272,6 +273,7 @@ type WriteCommandParameters = { [WRITE_COMMANDS.SEND_MONEY_ELSEWHERE]: Parameters.SendMoneyParams; [WRITE_COMMANDS.SEND_MONEY_WITH_WALLET]: Parameters.SendMoneyParams; [WRITE_COMMANDS.APPROVE_MONEY_REQUEST]: Parameters.ApproveMoneyRequestParams; + [WRITE_COMMANDS.EDIT_MONEY_REQUEST]: Parameters.EditMoneyRequestParams; [WRITE_COMMANDS.REPLACE_RECEIPT]: Parameters.ReplaceReceiptParams; [WRITE_COMMANDS.SUBMIT_REPORT]: Parameters.SubmitReportParams; [WRITE_COMMANDS.DETACH_RECEIPT]: Parameters.DetachReceiptParams; diff --git a/src/libs/actions/IOU.ts b/src/libs/actions/IOU.ts index 766f35e4e58b..e1d4b2dbf51f 100644 --- a/src/libs/actions/IOU.ts +++ b/src/libs/actions/IOU.ts @@ -13,6 +13,7 @@ import type { CreateDistanceRequestParams, DeleteMoneyRequestParams, DetachReceiptParams, + EditMoneyRequestParams, PayMoneyRequestParams, ReplaceReceiptParams, RequestMoneyParams, @@ -1318,6 +1319,19 @@ function updateMoneyRequestDescription( API.write(WRITE_COMMANDS.UPDATE_MONEY_REQUEST_DESCRIPTION, params, onyxData); } +/** Edits an existing distance request */ +function updateDistanceRequest( + transactionID: string, + transactionThreadReportID: string, + transactionChanges: TransactionChanges, + policy: OnyxTypes.Policy, + policyTags: OnyxTypes.PolicyTagList, + policyCategories: OnyxTypes.PolicyCategories, +) { + const {params, onyxData} = getUpdateMoneyRequestParams(transactionID, transactionThreadReportID, transactionChanges, policy, policyTags, policyCategories, false); + API.write(WRITE_COMMANDS.UPDATE_DISTANCE_REQUEST, params, onyxData); +} + /** * Request money from another user */ @@ -2379,6 +2393,279 @@ function setDraftSplitTransaction(transactionID: string, transactionChanges: Tra Onyx.merge(`${ONYXKEYS.COLLECTION.SPLIT_TRANSACTION_DRAFT}${transactionID}`, updatedTransaction); } +function editRegularMoneyRequest( + transactionID: string, + transactionThreadReportID: string, + transactionChanges: TransactionChanges, + policy: OnyxTypes.Policy, + policyTags: OnyxTypes.PolicyTagList, + policyCategories: OnyxTypes.PolicyCategories, +) { + // STEP 1: Get all collections we're updating + const transactionThread = allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${transactionThreadReportID}`] ?? null; + const transaction = allTransactions[`${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`]; + const iouReport = allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${transactionThread?.parentReportID}`] ?? null; + const chatReport = allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${iouReport?.chatReportID}`] ?? null; + const isFromExpenseReport = ReportUtils.isExpenseReport(iouReport); + + // STEP 2: Build new modified expense report action. + const updatedReportAction = ReportUtils.buildOptimisticModifiedExpenseReportAction(transactionThread, transaction, transactionChanges, isFromExpenseReport); + const updatedTransaction = transaction ? TransactionUtils.getUpdatedTransaction(transaction, transactionChanges, isFromExpenseReport) : null; + + // STEP 3: Compute the IOU total and update the report preview message so LHN amount owed is correct + // Should only update if the transaction matches the currency of the report, else we wait for the update + // from the server with the currency conversion + let updatedMoneyRequestReport = {...iouReport}; + const updatedChatReport = {...chatReport}; + const diff = TransactionUtils.getAmount(transaction, true) - TransactionUtils.getAmount(updatedTransaction, true); + if (updatedTransaction?.currency === iouReport?.currency && updatedTransaction?.modifiedAmount && diff !== 0) { + if (ReportUtils.isExpenseReport(iouReport) && typeof updatedMoneyRequestReport.total === 'number') { + updatedMoneyRequestReport.total += diff; + } else { + updatedMoneyRequestReport = iouReport + ? IOUUtils.updateIOUOwnerAndTotal(iouReport, updatedReportAction.actorAccountID ?? -1, diff, TransactionUtils.getCurrency(transaction), false) + : {}; + } + + updatedMoneyRequestReport.cachedTotal = CurrencyUtils.convertToDisplayString(updatedMoneyRequestReport.total, updatedTransaction.currency); + + // Update the last message of the IOU report + const lastMessage = ReportUtils.getIOUReportActionMessage( + iouReport?.reportID ?? '', + CONST.IOU.REPORT_ACTION_TYPE.CREATE, + updatedMoneyRequestReport.total ?? 0, + '', + updatedTransaction.currency, + '', + false, + ); + updatedMoneyRequestReport.lastMessageText = lastMessage[0].text; + updatedMoneyRequestReport.lastMessageHtml = lastMessage[0].html; + + // Update the last message of the chat report + const hasNonReimbursableTransactions = ReportUtils.hasNonReimbursableTransactions(iouReport?.reportID); + const messageText = Localize.translateLocal(hasNonReimbursableTransactions ? 'iou.payerSpentAmount' : 'iou.payerOwesAmount', { + payer: ReportUtils.getPersonalDetailsForAccountID(updatedMoneyRequestReport.managerID ?? -1).login ?? '', + amount: CurrencyUtils.convertToDisplayString(updatedMoneyRequestReport.total, updatedMoneyRequestReport.currency), + }); + updatedChatReport.lastMessageText = messageText; + updatedChatReport.lastMessageHtml = messageText; + } + + const isScanning = TransactionUtils.hasReceipt(updatedTransaction) && TransactionUtils.isReceiptBeingScanned(updatedTransaction); + + // STEP 4: Compose the optimistic data + const currentTime = DateUtils.getDBTime(); + const optimisticData: OnyxUpdate[] = [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${transactionThread?.reportID}`, + value: { + [updatedReportAction.reportActionID]: updatedReportAction as OnyxTypes.ReportAction, + }, + }, + { + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`, + value: updatedTransaction, + }, + { + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.REPORT}${iouReport?.reportID}`, + value: updatedMoneyRequestReport, + }, + { + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.REPORT}${iouReport?.chatReportID}`, + value: updatedChatReport, + }, + { + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.REPORT}${transactionThreadReportID}`, + value: { + lastReadTime: currentTime, + lastVisibleActionCreated: currentTime, + }, + }, + ]; + + if (!isScanning) { + optimisticData.push( + { + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${iouReport?.reportID}`, + value: { + [transactionThread?.parentReportActionID ?? '']: { + whisperedToAccountIDs: [], + }, + }, + }, + { + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${iouReport?.parentReportID}`, + value: { + [iouReport?.parentReportActionID ?? '']: { + whisperedToAccountIDs: [], + }, + }, + }, + ); + } + + // Update recently used categories if the category is changed + if ('category' in transactionChanges) { + const optimisticPolicyRecentlyUsedCategories = Policy.buildOptimisticPolicyRecentlyUsedCategories(iouReport?.policyID, transactionChanges.category); + if (optimisticPolicyRecentlyUsedCategories.length) { + optimisticData.push({ + onyxMethod: Onyx.METHOD.SET, + key: `${ONYXKEYS.COLLECTION.POLICY_RECENTLY_USED_CATEGORIES}${iouReport?.policyID}`, + value: optimisticPolicyRecentlyUsedCategories, + }); + } + } + + // Update recently used categories if the tag is changed + if ('tag' in transactionChanges) { + const optimisticPolicyRecentlyUsedTags = Policy.buildOptimisticPolicyRecentlyUsedTags(iouReport?.policyID, transactionChanges.tag); + if (!isEmptyObject(optimisticPolicyRecentlyUsedTags)) { + optimisticData.push({ + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.POLICY_RECENTLY_USED_TAGS}${iouReport?.policyID}`, + value: optimisticPolicyRecentlyUsedTags, + }); + } + } + + const successData: OnyxUpdate[] = [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${transactionThread?.reportID}`, + value: { + [updatedReportAction.reportActionID]: {pendingAction: null}, + }, + }, + { + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`, + value: { + pendingFields: { + comment: null, + amount: null, + created: null, + currency: null, + merchant: null, + billable: null, + category: null, + tag: null, + }, + }, + }, + { + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.REPORT}${iouReport?.reportID}`, + value: {pendingAction: null}, + }, + ]; + + const failureData: OnyxUpdate[] = [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${transactionThread?.reportID}`, + value: { + [updatedReportAction.reportActionID]: { + errors: ErrorUtils.getMicroSecondOnyxError('iou.error.genericEditFailureMessage'), + }, + }, + }, + { + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`, + value: { + ...transaction, + modifiedCreated: transaction?.modifiedCreated ? transaction.modifiedCreated : null, + modifiedAmount: transaction?.modifiedAmount ? transaction.modifiedAmount : null, + modifiedCurrency: transaction?.modifiedCurrency ? transaction.modifiedCurrency : null, + modifiedMerchant: transaction?.modifiedMerchant ? transaction.modifiedMerchant : null, + modifiedWaypoints: transaction?.modifiedWaypoints ? transaction.modifiedWaypoints : null, + pendingFields: null, + }, + }, + { + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.REPORT}${iouReport?.reportID}`, + value: { + ...iouReport, + cachedTotal: iouReport?.cachedTotal ? iouReport?.cachedTotal : null, + }, + }, + { + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.REPORT}${iouReport?.chatReportID}`, + value: chatReport, + }, + { + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.REPORT}${transactionThreadReportID}`, + value: { + lastReadTime: transactionThread?.lastReadTime, + lastVisibleActionCreated: transactionThread?.lastVisibleActionCreated, + }, + }, + ]; + + // Add transaction violations if there is a policy and updated transaaction + if (policy?.id && updatedTransaction) { + const currentTransactionViolations = allTransactionViolations[`${ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS}${transactionID}`] ?? []; + const updatedViolationsOnyxData = ViolationsUtils.getViolationsOnyxData( + updatedTransaction, + currentTransactionViolations, + !!policy.requiresTag, + policyTags, + !!policy.requiresCategory, + policyCategories, + ); + optimisticData.push(updatedViolationsOnyxData); + failureData.push({ + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS}${transactionID}`, + value: currentTransactionViolations, + }); + } + + // STEP 6: Call the API endpoint + const {created, amount, currency, comment, merchant, category, billable, tag} = ReportUtils.getTransactionDetails(updatedTransaction) ?? {}; + + const parameters: EditMoneyRequestParams = { + transactionID, + reportActionID: updatedReportAction.reportActionID, + created, + amount, + currency, + comment, + merchant, + category, + billable, + tag, + }; + + API.write(WRITE_COMMANDS.EDIT_MONEY_REQUEST, parameters, {optimisticData, successData, failureData}); +} + +function editMoneyRequest( + transaction: OnyxTypes.Transaction, + transactionThreadReportID: string, + transactionChanges: TransactionChanges, + policy: OnyxTypes.Policy, + policyTags: OnyxTypes.PolicyTagList, + policyCategories: OnyxTypes.PolicyCategories, +) { + if (TransactionUtils.isDistanceRequest(transaction)) { + updateDistanceRequest(transaction.transactionID, transactionThreadReportID, transactionChanges, policy, policyTags, policyCategories); + } else { + editRegularMoneyRequest(transaction.transactionID, transactionThreadReportID, transactionChanges, policy, policyTags, policyCategories); + } +} + /** Updates the amount and currency fields of a money request */ function updateMoneyRequestAmountAndCurrency( transactionID: string, @@ -3565,6 +3852,7 @@ export { replaceReceipt, detachReceipt, getIOUReportID, + editMoneyRequest, navigateToStartStepIfScanFileCannotBeRead, savePreferredPaymentMethod, }; diff --git a/tests/actions/IOUTest.js b/tests/actions/IOUTest.js index d45e60d1999e..92b39fc3ac50 100644 --- a/tests/actions/IOUTest.js +++ b/tests/actions/IOUTest.js @@ -1390,6 +1390,282 @@ describe('actions/IOU', () => { }); }); + describe('edit money request', () => { + const amount = 10000; + const comment = '💸💸💸💸'; + const merchant = 'NASDAQ'; + + afterEach(() => { + fetch.resume(); + }); + + it('updates the IOU request and IOU report when offline', () => { + let thread = {}; + let iouReport = {}; + let iouAction = {}; + let transaction = {}; + + fetch.pause(); + IOU.requestMoney({}, amount, CONST.CURRENCY.USD, '', merchant, RORY_EMAIL, RORY_ACCOUNT_ID, {login: CARLOS_EMAIL, accountID: CARLOS_ACCOUNT_ID}, comment); + return waitForBatchedUpdates() + .then(() => { + Onyx.set(ONYXKEYS.SESSION, {email: RORY_EMAIL, accountID: RORY_ACCOUNT_ID}); + return waitForBatchedUpdates(); + }) + .then( + () => + new Promise((resolve) => { + const connectionID = Onyx.connect({ + key: ONYXKEYS.COLLECTION.REPORT, + waitForCollectionCallback: true, + callback: (allReports) => { + Onyx.disconnect(connectionID); + iouReport = _.find(allReports, (report) => report.type === CONST.REPORT.TYPE.IOU); + + resolve(); + }, + }); + }), + ) + .then( + () => + new Promise((resolve) => { + const connectionID = Onyx.connect({ + key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${iouReport.reportID}`, + waitForCollectionCallback: true, + callback: (reportActionsForIOUReport) => { + Onyx.disconnect(connectionID); + + [iouAction] = _.filter(reportActionsForIOUReport, (reportAction) => reportAction.actionName === CONST.REPORT.ACTIONS.TYPE.IOU); + resolve(); + }, + }); + }), + ) + .then( + () => + new Promise((resolve) => { + const connectionID = Onyx.connect({ + key: ONYXKEYS.COLLECTION.TRANSACTION, + waitForCollectionCallback: true, + callback: (allTransactions) => { + Onyx.disconnect(connectionID); + + transaction = _.find(allTransactions, (t) => !_.isEmpty(t)); + resolve(); + }, + }); + }), + ) + .then(() => { + thread = ReportUtils.buildTransactionThread(iouAction, iouReport.reportID); + Onyx.set(`report_${thread.reportID}`, thread); + return waitForBatchedUpdates(); + }) + .then(() => { + IOU.editMoneyRequest(transaction, thread.reportID, {amount: 20000, comment: 'Double the amount!'}); + return waitForBatchedUpdates(); + }) + .then( + () => + new Promise((resolve) => { + const connectionID = Onyx.connect({ + key: ONYXKEYS.COLLECTION.TRANSACTION, + waitForCollectionCallback: true, + callback: (allTransactions) => { + Onyx.disconnect(connectionID); + + const updatedTransaction = _.find(allTransactions, (t) => !_.isEmpty(t)); + expect(updatedTransaction.modifiedAmount).toBe(20000); + expect(updatedTransaction.comment).toMatchObject({comment: 'Double the amount!'}); + resolve(); + }, + }); + }), + ) + .then( + () => + new Promise((resolve) => { + const connectionID = Onyx.connect({ + key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${thread.reportID}`, + waitForCollectionCallback: true, + callback: (allActions) => { + Onyx.disconnect(connectionID); + const updatedAction = _.find(allActions, (reportAction) => !_.isEmpty(reportAction)); + expect(updatedAction.actionName).toEqual('MODIFIEDEXPENSE'); + expect(updatedAction.originalMessage).toEqual( + expect.objectContaining({amount: 20000, newComment: 'Double the amount!', oldAmount: amount, oldComment: comment}), + ); + resolve(); + }, + }); + }), + ) + .then( + () => + new Promise((resolve) => { + const connectionID = Onyx.connect({ + key: ONYXKEYS.COLLECTION.REPORT, + waitForCollectionCallback: true, + callback: (allReports) => { + Onyx.disconnect(connectionID); + const updatedIOUReport = _.find(allReports, (report) => report.type === CONST.REPORT.TYPE.IOU); + const updatedChatReport = _.find(allReports, (report) => report.reportID === iouReport.chatReportID); + expect(updatedIOUReport).toEqual( + expect.objectContaining({ + total: 20000, + cachedTotal: '$200.00', + lastMessageHtml: 'requested $200.00', + lastMessageText: 'requested $200.00', + }), + ); + expect(updatedChatReport).toEqual( + expect.objectContaining({ + lastMessageHtml: `${CARLOS_EMAIL} owes $200.00`, + lastMessageText: `${CARLOS_EMAIL} owes $200.00`, + }), + ); + resolve(); + }, + }); + }), + ) + .then(() => { + fetch.resume(); + }); + }); + + it('resets the IOU request and IOU report when api returns an error', () => { + let thread = {}; + let iouReport = {}; + let iouAction = {}; + let transaction = {}; + + IOU.requestMoney({}, amount, CONST.CURRENCY.USD, '', merchant, RORY_EMAIL, RORY_ACCOUNT_ID, {login: CARLOS_EMAIL, accountID: CARLOS_ACCOUNT_ID}, comment); + return waitForBatchedUpdates() + .then(() => { + Onyx.set(ONYXKEYS.SESSION, {email: RORY_EMAIL, accountID: RORY_ACCOUNT_ID}); + return waitForBatchedUpdates(); + }) + .then( + () => + new Promise((resolve) => { + const connectionID = Onyx.connect({ + key: ONYXKEYS.COLLECTION.REPORT, + waitForCollectionCallback: true, + callback: (allReports) => { + Onyx.disconnect(connectionID); + [iouReport] = _.filter(allReports, (report) => report.type === CONST.REPORT.TYPE.IOU); + resolve(); + }, + }); + }), + ) + .then( + () => + new Promise((resolve) => { + const connectionID = Onyx.connect({ + key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${iouReport.reportID}`, + waitForCollectionCallback: true, + callback: (reportActionsForIOUReport) => { + Onyx.disconnect(connectionID); + + [iouAction] = _.filter(reportActionsForIOUReport, (reportAction) => reportAction.actionName === CONST.REPORT.ACTIONS.TYPE.IOU); + resolve(); + }, + }); + }), + ) + .then( + () => + new Promise((resolve) => { + const connectionID = Onyx.connect({ + key: ONYXKEYS.COLLECTION.TRANSACTION, + waitForCollectionCallback: true, + callback: (allTransactions) => { + Onyx.disconnect(connectionID); + + transaction = _.find(allTransactions, (t) => !_.isEmpty(t)); + resolve(); + }, + }); + }), + ) + .then(() => { + thread = ReportUtils.buildTransactionThread(iouAction, iouReport.reportID); + Onyx.set(`report_${thread.reportID}`, thread); + return waitForBatchedUpdates(); + }) + .then(() => { + fetch.fail(); + IOU.editMoneyRequest(transaction, thread.reportID, {amount: 20000, comment: 'Double the amount!'}); + return waitForBatchedUpdates(); + }) + .then( + () => + new Promise((resolve) => { + const connectionID = Onyx.connect({ + key: ONYXKEYS.COLLECTION.TRANSACTION, + waitForCollectionCallback: true, + callback: (allTransactions) => { + Onyx.disconnect(connectionID); + + const updatedTransaction = _.find(allTransactions, (t) => !_.isEmpty(t)); + expect(updatedTransaction.modifiedAmount).toBe(undefined); + expect(updatedTransaction.amount).toBe(10000); + expect(updatedTransaction.comment).toMatchObject({comment}); + resolve(); + }, + }); + }), + ) + .then( + () => + new Promise((resolve) => { + const connectionID = Onyx.connect({ + key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${thread.reportID}`, + waitForCollectionCallback: true, + callback: (allActions) => { + Onyx.disconnect(connectionID); + const updatedAction = _.find(allActions, (reportAction) => !_.isEmpty(reportAction)); + expect(updatedAction.actionName).toEqual('MODIFIEDEXPENSE'); + expect(_.values(updatedAction.errors)).toEqual(expect.arrayContaining(['iou.error.genericEditFailureMessage'])); + resolve(); + }, + }); + }), + ) + .then( + () => + new Promise((resolve) => { + const connectionID = Onyx.connect({ + key: ONYXKEYS.COLLECTION.REPORT, + waitForCollectionCallback: true, + callback: (allReports) => { + Onyx.disconnect(connectionID); + const updatedIOUReport = _.find(allReports, (report) => report.type === CONST.REPORT.TYPE.IOU); + const updatedChatReport = _.find(allReports, (report) => report.reportID === iouReport.chatReportID); + expect(updatedIOUReport).toEqual( + expect.objectContaining({ + total: 10000, + cachedTotal: '$100.00', + lastMessageHtml: `requested $${amount / 100}.00 for ${comment}`, + lastMessageText: `requested $${amount / 100}.00 for ${comment}`, + }), + ); + expect(updatedChatReport).toEqual( + expect.objectContaining({ + lastMessageHtml: '', + }), + ); + resolve(); + }, + }); + }), + ); + }); + }); + describe('pay expense report via ACH', () => { const amount = 10000; const comment = '💸💸💸💸';