From 84dcd896feb3bce07026a348898a3d6ea6a9eabe Mon Sep 17 00:00:00 2001 From: thelullabyy <182625428+thelullabyy@users.noreply.github.com> Date: Fri, 2 Oct 2026 02:36:51 +0800 Subject: [PATCH] fix: Split details page does not show the new UI when scan expense is split offline --- src/libs/actions/IOU/Split.ts | 1 + tests/actions/IOUTest/SplitTest.ts | 79 ++++++++++++++++++++++++++++++ 2 files changed, 80 insertions(+) diff --git a/src/libs/actions/IOU/Split.ts b/src/libs/actions/IOU/Split.ts index d61e381a7a83..e401378fc048 100644 --- a/src/libs/actions/IOU/Split.ts +++ b/src/libs/actions/IOU/Split.ts @@ -948,6 +948,7 @@ function completeSplitBill({ receipt: { state: CONST.IOU.RECEIPT_STATE.OPEN, }, + iouRequestType: CONST.IOU.REQUEST_TYPE.MANUAL, }, }, { diff --git a/tests/actions/IOUTest/SplitTest.ts b/tests/actions/IOUTest/SplitTest.ts index f160dd5b2f1c..760e1ddfa8cb 100644 --- a/tests/actions/IOUTest/SplitTest.ts +++ b/tests/actions/IOUTest/SplitTest.ts @@ -1256,6 +1256,85 @@ describe('split expense', () => { expect(splitTransaction?.comment?.comment).toBe('

test

'); }); + it('should stop treating the split as a scan request once it is completed while offline', async () => { + // Given a scan split bill started offline, so it is marked as a scan request + const reportID = '1'; + await Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT}${reportID}`, { + reportID, + type: CONST.REPORT.TYPE.CHAT, + chatType: CONST.REPORT.CHAT_TYPE.GROUP, + participants: { + [RORY_ACCOUNT_ID]: {notificationPreference: CONST.REPORT.NOTIFICATION_PREFERENCE.ALWAYS}, + [CARLOS_ACCOUNT_ID]: {notificationPreference: CONST.REPORT.NOTIFICATION_PREFERENCE.ALWAYS}, + }, + }); + + const participants: IOUParticipant[] = [{accountID: CARLOS_ACCOUNT_ID, login: CARLOS_EMAIL}]; + const participantsPolicyTags = await getParticipantsPolicyTags(participants); + + mockFetch?.pause?.(); + + startSplitBill({ + isFirstSplitInBatch: true, + getCurrencyDecimals: getCurrencyDecimalsLocal, + participants, + currentUserLogin: RORY_EMAIL, + currentUserAccountID: RORY_ACCOUNT_ID, + comment: '', + currency: CONST.CURRENCY.USD, + existingSplitChatReportID: reportID, + receipt: {source: 'file://receipt.jpg', filename: 'receipt.jpg', state: CONST.IOU.RECEIPT_STATE.SCAN_READY}, + category: undefined, + tag: undefined, + taxCode: '', + taxAmount: 0, + quickAction: undefined, + policyRecentlyUsedCurrencies: [], + policyRecentlyUsedTags: undefined, + participantsPolicyTags, + delegateAccountID: undefined, + formatPhoneNumber, + }); + + await waitForBatchedUpdates(); + + let splitTransaction = await getScanSplitTransaction(); + const splitTransactionID = splitTransaction?.transactionID; + expect(splitTransaction?.iouRequestType).toBe(CONST.IOU.REQUEST_TYPE.SCAN); + + const reportActions = await getOnyxValue(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${reportID}`); + const iouAction = Object.values(reportActions ?? {}).find((action) => isActionOfType(action, CONST.REPORT.ACTIONS.TYPE.IOU)); + + // When the user fills the fields in by hand and completes the split while still offline + completeSplitBill({ + isVendorMatchingBetaEnabled: false, + getCurrencyDecimals: getCurrencyDecimalsLocal, + chatReportID: reportID, + reportAction: iouAction, + updatedTransaction: splitTransaction ? {...splitTransaction, amount: 100, modifiedAmount: 100, modifiedCurrency: CONST.CURRENCY.USD} : undefined, + sessionAccountID: RORY_ACCOUNT_ID, + isASAPSubmitBetaEnabled: false, + quickAction: undefined, + transactionViolations: {}, + personalDetails: mockPersonalDetails, + delegateAccountID: undefined, + isTrackIntentUser: false, + sessionEmail: RORY_EMAIL, + formatPhoneNumber, + rules: undefined, + }); + + await waitForBatchedUpdates(); + + // Then the optimistic transaction is no longer a scan request, so the split details page renders the + // manual layout right away instead of waiting for the server response to arrive + splitTransaction = await getOnyxValue(`${ONYXKEYS.COLLECTION.TRANSACTION}${splitTransactionID}`); + expect(splitTransaction?.iouRequestType).toBe(CONST.IOU.REQUEST_TYPE.MANUAL); + + mockFetch?.resume?.(); + await waitForBatchedUpdates(); + }); + it('should calculate proportional convertedAmount for split transactions with foreign currency', async () => { jest.setTimeout(10 * 1000);