Skip to content
Open
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
4 changes: 2 additions & 2 deletions src/libs/actions/IOU/MoneyRequestBuilder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -555,8 +555,8 @@ function buildOnyxDataForMoneyRequest(moneyRequestParams: BuildOnyxDataForMoneyR
...chat.report,
lastReadTime: DateUtils.getDBTime(),
...(shouldCreateNewMoneyRequestReport ? {lastVisibleActionCreated: chat.reportPreviewAction.created} : {}),
// do not update iouReportID if auto submit beta is enabled and it is a scan request
...(isASAPSubmitBetaEnabled && isScanRequest ? {} : {iouReportID: iou.report.reportID}),
// do not update iouReportID if auto submit beta is enabled and it is a scan request, or when adding to an existing report
...((isASAPSubmitBetaEnabled && isScanRequest) || !shouldCreateNewMoneyRequestReport ? {} : {iouReportID: iou.report.reportID}),

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve the new report ID for batched expenses

When the confirmation flow creates multiple expenses, useExpenseSubmission reuses the original report object for every item while passing the first optimistic iouReport as existingIOUReport on later iterations. If that original workspace chat still has a stale iouReportID for a submitted/non-addable report, the first item creates a fresh report and sets the chat to it, but the second item has shouldCreateNewMoneyRequestReport === false; this branch then skips overriding iouReportID and the spread chat.report writes the stale ID back. In that batched scenario, future expenses from the workspace chat can again resolve to the submitted report instead of the new open report.

Useful? React with 👍 / 👎.

...outstandingChildRequest,
...(isNewChatReport ? {pendingFields: {createChat: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD}} : {}),
},
Expand Down
82 changes: 82 additions & 0 deletions tests/actions/IOU/BuildOnyxDataForMoneyRequestTest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -380,4 +380,86 @@ describe('buildOnyxDataForMoneyRequest', () => {
});
});
});

describe('chatReport.iouReportID update behavior', () => {
const OTHER_OPEN_REPORT_ID = '999';

function buildParamsWithCreateFlag(shouldCreateNewMoneyRequestReport: boolean, iouReportIDOverride?: string | null): BuildOnyxDataParams {
const optimisticParams = buildBaseOptimisticParams(IOU_REPORT_ID);

return {
isNewChatReport: false,
shouldCreateNewMoneyRequestReport,
shouldGenerateTransactionThreadReport: false,
isASAPSubmitBetaEnabled: false,
currentUserAccountIDParam: CURRENT_USER_ACCOUNT_ID,
currentUserEmailParam: CURRENT_USER_EMAIL,
hasViolations: false,
quickAction: undefined,
isSelfDMSplit: false,
optimisticParams: {
...optimisticParams,
chat: {
...optimisticParams.chat,
report: {
...optimisticParams.chat.report,
...(iouReportIDOverride !== undefined ? {iouReportID: iouReportIDOverride} : {}),
} as Report,
},
},
};
}

function getChatReportOptimisticEntry(optimisticData: ReturnType<typeof buildOnyxDataForMoneyRequest>['optimisticData']) {
return optimisticData?.find((entry) => entry.key === `${ONYXKEYS.COLLECTION.REPORT}${CHAT_REPORT_ID}`);
}

it('sets iouReportID on chat report when shouldCreateNewMoneyRequestReport is true', () => {
const {optimisticData} = buildOnyxDataForMoneyRequest(buildParamsWithCreateFlag(true));
const chatReportEntry = getChatReportOptimisticEntry(optimisticData);

expect(chatReportEntry).toBeDefined();
expect((chatReportEntry?.value as Partial<Report>)?.iouReportID).toBe(IOU_REPORT_ID);
});

it('does not update iouReportID when shouldCreateNewMoneyRequestReport is false', () => {
const {optimisticData} = buildOnyxDataForMoneyRequest(buildParamsWithCreateFlag(false, null));
const chatReportEntry = getChatReportOptimisticEntry(optimisticData);

expect(chatReportEntry).toBeDefined();
expect((chatReportEntry?.value as Partial<Report>)?.iouReportID).toBeNull();
});

it('preserves existing iouReportID when adding expense to a different existing report', () => {
const {optimisticData} = buildOnyxDataForMoneyRequest(buildParamsWithCreateFlag(false, OTHER_OPEN_REPORT_ID));
const chatReportEntry = getChatReportOptimisticEntry(optimisticData);

expect(chatReportEntry).toBeDefined();
expect((chatReportEntry?.value as Partial<Report>)?.iouReportID).toBe(OTHER_OPEN_REPORT_ID);
});

it('does not update iouReportID when isASAPSubmitBetaEnabled and transaction is a scan request', () => {
const optimisticParams = buildBaseOptimisticParams(IOU_REPORT_ID);
const params: BuildOnyxDataParams = {
...buildParamsWithCreateFlag(true),
isASAPSubmitBetaEnabled: true,
optimisticParams: {
...optimisticParams,
transactionParams: {
...optimisticParams.transactionParams,
transaction: {
...optimisticParams.transactionParams.transaction,
iouRequestType: CONST.IOU.REQUEST_TYPE.SCAN,
},
},
},
};

const {optimisticData} = buildOnyxDataForMoneyRequest(params);
const chatReportEntry = getChatReportOptimisticEntry(optimisticData);

expect(chatReportEntry).toBeDefined();
expect((chatReportEntry?.value as Partial<Report>)?.iouReportID).toBeUndefined();
});
});
});
Loading