Skip to content
Merged
2 changes: 1 addition & 1 deletion src/libs/actions/IOU.js
Original file line number Diff line number Diff line change
Expand Up @@ -2274,7 +2274,7 @@ function deleteMoneyRequest(transactionID, reportAction, isSingleTransactionView
// STEP 2: Decide if we need to:
// 1. Delete the transactionThread - delete if there are no visible comments in the thread
// 2. Update the moneyRequestPreview to show [Deleted request] - update if the transactionThread exists AND it isn't being deleted
const shouldDeleteTransactionThread = transactionThreadID ? ReportActionsUtils.getLastVisibleMessage(transactionThreadID).lastMessageText.length === 0 : false;
const shouldDeleteTransactionThread = transactionThreadID ? lodashGet(reportAction, 'childVisibleActionCount', 0) === 0 : false;
const shouldShowDeletedRequestMessage = transactionThreadID && !shouldDeleteTransactionThread;

// STEP 3: Update the IOU reportAction and decide if the iouReport should be deleted. We delete the iouReport if there are no visible comments left in the report.
Expand Down
20 changes: 20 additions & 0 deletions src/libs/actions/Task.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import * as UserUtils from '@libs/UserUtils';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import ROUTES from '@src/ROUTES';
import {isNotEmptyObject} from '@src/types/utils/EmptyObject';
import * as Report from './Report';

let currentUserEmail;
Expand Down Expand Up @@ -179,6 +180,12 @@ function createTaskAndNavigate(parentReportID, title, description, assigneeEmail
},
);

// If needed, update optimistic data for parent report action of the parent report.
const optimisticParentReportData = ReportUtils.getOptimisticDataForParentReportAction(parentReportID, currentTime, CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD);
if (isNotEmptyObject(optimisticParentReportData)) {
optimisticData.push(optimisticParentReportData);
}

// FOR PARENT REPORT (SHARE DESTINATION)
successData.push({
onyxMethod: Onyx.METHOD.MERGE,
Expand Down Expand Up @@ -772,6 +779,19 @@ function cancelTask(taskReportID, taskTitle, originalStateNum, originalStatusNum
},
];

// Update optimistic data for parent report action if the report is a child report and the task report has no visible child
const childVisibleActionCount = lodashGet(parentReportAction, 'childVisibleActionCount', 0);
if (childVisibleActionCount === 0) {
const optimisticParentReportData = ReportUtils.getOptimisticDataForParentReportAction(
parentReport.reportID,
parentReport.lastVisibleActionCreated || '',
CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE,
);
if (isNotEmptyObject(optimisticParentReportData)) {
optimisticData.push(optimisticParentReportData);
}
}

const successData = [
{
onyxMethod: Onyx.METHOD.MERGE,
Expand Down
94 changes: 94 additions & 0 deletions tests/actions/IOUTest.js
Original file line number Diff line number Diff line change
Expand Up @@ -2236,6 +2236,86 @@ describe('actions/IOU', () => {
expect(report).toBeFalsy();
});

it('delete the transaction thread if there are only changelogs (i.e. MODIFIEDEXPENSE actions) in the thread', async () => {
// Given all promises are resolved
await waitForBatchedUpdates();
jest.advanceTimersByTime(10);

// Given a transaction thread
thread = ReportUtils.buildTransactionThread(createIOUAction, IOU_REPORT_ID);

Onyx.connect({
key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${thread.reportID}`,
callback: (val) => (reportActions = val),
});

await waitForBatchedUpdates();

jest.advanceTimersByTime(10);

// Given User logins from the participant accounts
const userLogins = PersonalDetailsUtils.getLoginsByAccountIDs(thread.participantAccountIDs);

// When Opening a thread report with the given details
Report.openReport(thread.reportID, userLogins, thread, createIOUAction.reportActionID);
await waitForBatchedUpdates();

// Then The iou action has the transaction report id as a child report ID
const allReportActions = await new Promise((resolve) => {
const connectionID = Onyx.connect({
key: ONYXKEYS.COLLECTION.REPORT_ACTIONS,
waitForCollectionCallback: true,
callback: (actions) => {
Onyx.disconnect(connectionID);
resolve(actions);
},
});
});
const reportActionsForIOUReport = allReportActions[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${chatReport.iouReportID}`];
createIOUAction = _.find(reportActionsForIOUReport, (ra) => ra.actionName === CONST.REPORT.ACTIONS.TYPE.IOU);
expect(createIOUAction.childReportID).toBe(thread.reportID);

await waitForBatchedUpdates();

jest.advanceTimersByTime(10);
IOU.editMoneyRequest(transaction, thread.reportID, {amount: 20000, comment: 'Double the amount!'});
await waitForBatchedUpdates();

// Verify there are two actions (created + changelog)
expect(_.size(reportActions)).toBe(2);

// Fetch the updated IOU Action from Onyx
await new Promise((resolve) => {
const connectionID = Onyx.connect({
key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${iouReport.reportID}`,
waitForCollectionCallback: true,
callback: (reportActionsForReport) => {
Onyx.disconnect(connectionID);
createIOUAction = _.find(reportActionsForReport, (reportAction) => reportAction.actionName === CONST.REPORT.ACTIONS.TYPE.IOU);
resolve();
},
});
});

// When Deleting a money request
IOU.deleteMoneyRequest(transaction.transactionID, createIOUAction, false);
await waitForBatchedUpdates();

// Then, the report for the given thread ID does not exist
const report = await new Promise((resolve) => {
const connectionID = Onyx.connect({
key: `${ONYXKEYS.COLLECTION.REPORT}${thread.reportID}`,
waitForCollectionCallback: true,
callback: (reportData) => {
Onyx.disconnect(connectionID);
resolve(reportData);
},
});
});

expect(report).toBeFalsy();
});

it('does not delete the transaction thread if there are visible comments in the thread', async () => {
// Given initial environment is set up
await waitForBatchedUpdates();
Expand Down Expand Up @@ -2367,6 +2447,20 @@ describe('actions/IOU', () => {
Report.addComment(thread.reportID, 'Testing a comment');
await waitForBatchedUpdates();

// Fetch the updated IOU Action from Onyx due to addition of comment to transaction thread.
// This needs to be fetched as `deleteMoneyRequest` depends on `childVisibleActionCount` in `createIOUAction`.
await new Promise((resolve) => {
const connectionID = Onyx.connect({
key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${iouReport.reportID}`,
waitForCollectionCallback: true,
callback: (reportActionsForReport) => {
Onyx.disconnect(connectionID);
createIOUAction = _.find(reportActionsForReport, (reportAction) => reportAction.actionName === CONST.REPORT.ACTIONS.TYPE.IOU);
resolve();
},
});
});

let resultAction = _.find(reportActions, (ra) => ra.actionName === CONST.REPORT.ACTIONS.TYPE.ADDCOMMENT);
reportActionID = resultAction.reportActionID;

Expand Down