@@ -3620,6 +3620,157 @@ describe('actions/IOU', () => {
36203620 // Then the description should be the same since it was not changed
36213621 expect(splitTransaction?.comment?.comment).toBe('<h1>test</h1>');
36223622 });
3623+
3624+ it('should calculate proportional convertedAmount for split transactions with foreign currency', async () => {
3625+ jest.setTimeout(10 * 1000);
3626+
3627+ // Given: An expense report with AED currency and a USD transaction with convertedAmount
3628+ const originalAmount = -1000;
3629+ const originalConvertedAmount = -3673;
3630+ const reportID = rand64();
3631+ const originalTransactionID = rand64();
3632+
3633+ const expenseReport: Report = {
3634+ reportID,
3635+ type: CONST.REPORT.TYPE.EXPENSE,
3636+ currency: 'AED',
3637+ ownerAccountID: RORY_ACCOUNT_ID,
3638+ total: originalAmount,
3639+ };
3640+
3641+ const originalTransaction = {
3642+ transactionID: originalTransactionID,
3643+ amount: originalAmount,
3644+ modifiedAmount: '', // Empty string - the edge case that was causing the bug
3645+ currency: 'USD',
3646+ modifiedCurrency: '',
3647+ convertedAmount: originalConvertedAmount,
3648+ created: DateUtils.getDBTime(),
3649+ merchant: 'Test Merchant',
3650+ reportID,
3651+ comment: {},
3652+ } as unknown as Transaction;
3653+
3654+ const transactionThread: Report = {
3655+ reportID: rand64(),
3656+ type: CONST.REPORT.TYPE.CHAT,
3657+ parentReportID: reportID,
3658+ parentReportActionID: rand64(),
3659+ };
3660+
3661+ const iouAction: ReportAction = {
3662+ ...buildOptimisticIOUReportAction({
3663+ type: CONST.IOU.REPORT_ACTION_TYPE.CREATE,
3664+ amount: Math.abs(originalAmount),
3665+ currency: 'USD',
3666+ comment: '',
3667+ participants: [],
3668+ transactionID: originalTransactionID,
3669+ iouReportID: reportID,
3670+ }),
3671+ childReportID: transactionThread.reportID,
3672+ };
3673+
3674+ await Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT}${expenseReport.reportID}`, expenseReport);
3675+ await Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT}${transactionThread.reportID}`, transactionThread);
3676+ await Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${expenseReport.reportID}`, {
3677+ [iouAction.reportActionID]: iouAction,
3678+ });
3679+ await Onyx.merge(`${ONYXKEYS.COLLECTION.TRANSACTION}${originalTransactionID}`, originalTransaction);
3680+
3681+ const splitExpenses: SplitExpense[] = [
3682+ {
3683+ transactionID: rand64(),
3684+ amount: -500,
3685+ created: DateUtils.getDBTime(),
3686+ merchant: 'Test Merchant',
3687+ },
3688+ {
3689+ transactionID: rand64(),
3690+ amount: -500,
3691+ created: DateUtils.getDBTime(),
3692+ merchant: 'Test Merchant',
3693+ },
3694+ ];
3695+
3696+ let allTransactions: OnyxCollection<Transaction>;
3697+ let allReports: OnyxCollection<Report>;
3698+ let allReportNameValuePairs: OnyxCollection<ReportNameValuePairs>;
3699+ await getOnyxData({
3700+ key: ONYXKEYS.COLLECTION.TRANSACTION,
3701+ waitForCollectionCallback: true,
3702+ callback: (value) => {
3703+ allTransactions = value;
3704+ },
3705+ });
3706+ await getOnyxData({
3707+ key: ONYXKEYS.COLLECTION.REPORT,
3708+ waitForCollectionCallback: true,
3709+ callback: (value) => {
3710+ allReports = value;
3711+ },
3712+ });
3713+ await getOnyxData({
3714+ key: ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS,
3715+ waitForCollectionCallback: true,
3716+ callback: (value) => {
3717+ allReportNameValuePairs = value;
3718+ },
3719+ });
3720+
3721+ // When splitting the expense
3722+ updateSplitTransactionsFromSplitExpensesFlow({
3723+ allTransactionsList: allTransactions,
3724+ allReportsList: allReports,
3725+ allReportNameValuePairsList: allReportNameValuePairs,
3726+ transactionData: {
3727+ reportID,
3728+ originalTransactionID,
3729+ splitExpenses,
3730+ splitExpensesTotal: -1000,
3731+ },
3732+ searchContext: {
3733+ currentSearchHash: -1,
3734+ },
3735+ policyCategories: undefined,
3736+ policy: undefined,
3737+ policyRecentlyUsedCategories: [],
3738+ iouReport: expenseReport,
3739+ firstIOU: iouAction,
3740+ isASAPSubmitBetaEnabled: false,
3741+ currentUserPersonalDetails,
3742+ transactionViolations: {},
3743+ policyRecentlyUsedCurrencies: [],
3744+ quickAction: undefined,
3745+ iouReportNextStep: undefined,
3746+ });
3747+
3748+ await waitForBatchedUpdates();
3749+
3750+ // Then each split transaction should have proportional convertedAmount
3751+ // Formula: Math.round((originalConvertedAmount * splitAmount) / originalAmount)
3752+ const expectedProportionalConvertedAmount = -1836;
3753+
3754+ const splitTransactions = await new Promise<Transaction[]>((resolve) => {
3755+ const connection = Onyx.connect({
3756+ key: ONYXKEYS.COLLECTION.TRANSACTION,
3757+ waitForCollectionCallback: true,
3758+ callback: (transactions) => {
3759+ Onyx.disconnect(connection);
3760+ const splits = Object.values(transactions ?? {}).filter(
3761+ (t) => t?.transactionID !== originalTransactionID && t?.comment?.originalTransactionID === originalTransactionID,
3762+ );
3763+ resolve(splits as Transaction[]);
3764+ },
3765+ });
3766+ });
3767+
3768+ expect(splitTransactions.length).toBe(2);
3769+
3770+ for (const splitTransaction of splitTransactions) {
3771+ expect(splitTransaction.convertedAmount).toBe(expectedProportionalConvertedAmount);
3772+ }
3773+ });
36233774 });
36243775
36253776 describe('startSplitBill', () => {
0 commit comments