diff --git a/src/components/MoneyRequestConfirmationList.tsx b/src/components/MoneyRequestConfirmationList.tsx index 5c5bb0fab548..1e82c75fb5eb 100644 --- a/src/components/MoneyRequestConfirmationList.tsx +++ b/src/components/MoneyRequestConfirmationList.tsx @@ -615,6 +615,7 @@ function MoneyRequestConfirmationList({ isDistanceRequestWithPendingRoute={isDistanceRequestWithPendingRoute} shouldCalculateDistanceAmount={shouldCalculateDistanceAmount} distanceRequestAmount={distanceRequestAmount} + currentUserAccountID={currentUserPersonalDetails.accountID} setFormError={setFormError} clearFormErrors={clearFormErrors} /> diff --git a/src/components/MoneyRequestConfirmationList/DistanceRequestController.tsx b/src/components/MoneyRequestConfirmationList/DistanceRequestController.tsx index 01d6be663648..98dc5dab26ce 100644 --- a/src/components/MoneyRequestConfirmationList/DistanceRequestController.tsx +++ b/src/components/MoneyRequestConfirmationList/DistanceRequestController.tsx @@ -33,6 +33,7 @@ type DistanceRequestControllerProps = { distance: number; distanceRequestAmount: number; shouldCalculateDistanceAmount: boolean; + currentUserAccountID: number; isDistanceRequestWithPendingRoute: boolean; hasRoute: boolean; defaultMileageRateCustomUnitRateID: string | undefined; @@ -65,6 +66,7 @@ function DistanceRequestController({ distance, distanceRequestAmount, shouldCalculateDistanceAmount, + currentUserAccountID, isDistanceRequestWithPendingRoute, hasRoute, defaultMileageRateCustomUnitRateID, @@ -147,9 +149,20 @@ function DistanceRequestController({ // If it's a split request among individuals, set the split shares const participantAccountIDs: number[] = selectedParticipantsProp.map((participant) => participant.accountID ?? CONST.DEFAULT_NUMBER_ID); if (isTypeSplit && !isPolicyExpenseChat && amount && transaction?.currency) { - setSplitShares(transaction, amount, currency, participantAccountIDs); + setSplitShares(transaction, amount, currency, participantAccountIDs, currentUserAccountID); } - }, [shouldCalculateDistanceAmount, isReadOnly, distanceRequestAmount, transactionID, currency, isTypeSplit, isPolicyExpenseChat, selectedParticipantsProp, transaction]); + }, [ + shouldCalculateDistanceAmount, + isReadOnly, + distanceRequestAmount, + transactionID, + currency, + isTypeSplit, + isPolicyExpenseChat, + selectedParticipantsProp, + transaction, + currentUserAccountID, + ]); useEffect(() => { if ( diff --git a/src/components/MoneyRequestConfirmationList/sections/AmountField.tsx b/src/components/MoneyRequestConfirmationList/sections/AmountField.tsx index bfed3d20459f..b708d796914b 100644 --- a/src/components/MoneyRequestConfirmationList/sections/AmountField.tsx +++ b/src/components/MoneyRequestConfirmationList/sections/AmountField.tsx @@ -81,7 +81,6 @@ function AmountField({ const {getCurrencyDecimals} = useCurrencyListActions(); const [report] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${reportID}`); const [splitDraftTransaction] = useOnyx(`${ONYXKEYS.COLLECTION.SPLIT_TRANSACTION_DRAFT}${transactionID}`); - const [currentUserAccountID] = useOnyx(ONYXKEYS.SESSION, {selector: (session) => session?.accountID}); const currentUserPersonalDetails = useCurrentUserPersonalDetails(); const amountInputRef = useRef(null); const {didScreenTransitionEnd} = useScreenWrapperTransitionStatus(); @@ -159,7 +158,7 @@ function AmountField({ return; } const splitShares = splitDraftTransaction?.splitShares ?? transaction?.splitShares; - const accountID = currentUserAccountID ?? CONST.DEFAULT_NUMBER_ID; + const accountID = currentUserPersonalDetails.accountID ?? CONST.DEFAULT_NUMBER_ID; const newAccountIDs = Object.keys(splitShares ?? {}).map((key) => Number(key)); const oldAccountIDs = Object.keys(transaction?.splitShares ?? {}).map((key) => Number(key)); const accountIDs = [...new Set([accountID, ...newAccountIDs, ...oldAccountIDs])]; @@ -193,7 +192,7 @@ function AmountField({ const participantAccountIDs = shareAccountIDs.length > 0 ? shareAccountIDs : (transaction.participants ?? []).map((p) => p.accountID).filter((id): id is number => id !== undefined); if (participantAccountIDs.length > 0) { - setSplitShares(transaction, updatedAmount, updatedCurrency, participantAccountIDs); + setSplitShares(transaction, updatedAmount, updatedCurrency, participantAccountIDs, currentUserPersonalDetails.accountID); } return; } diff --git a/src/hooks/useParticipantSubmission.ts b/src/hooks/useParticipantSubmission.ts index 430cf8b0e17c..556be4c23ecf 100644 --- a/src/hooks/useParticipantSubmission.ts +++ b/src/hooks/useParticipantSubmission.ts @@ -286,7 +286,7 @@ function useParticipantSubmission({ const isPolicyExpenseChat = effectiveParticipants?.some((participant) => participant.isPolicyExpenseChat); if (iouType === CONST.IOU.TYPE.SPLIT && !isPolicyExpenseChat && splitTransaction?.amount && splitTransaction?.currency) { const participantAccountIDs = effectiveParticipants?.map((participant) => participant.accountID) as number[]; - setSplitShares(splitTransaction, splitTransaction.amount, splitTransaction.currency, participantAccountIDs); + setSplitShares(splitTransaction, splitTransaction.amount, splitTransaction.currency, participantAccountIDs, userDetails.accountID); } const newReportID = selectedReportID.current; diff --git a/src/libs/actions/IOU/Split.ts b/src/libs/actions/IOU/Split.ts index 1e0490cb03b0..6ff732cca4cc 100644 --- a/src/libs/actions/IOU/Split.ts +++ b/src/libs/actions/IOU/Split.ts @@ -1077,7 +1077,7 @@ function completeSplitBill( /** * Sets the `splitShares` map that holds individual shares of a split bill */ -function setSplitShares(transaction: OnyxEntry, amount: number, currency: string, newAccountIDs: number[], isDraft = true) { +function setSplitShares(transaction: OnyxEntry, amount: number, currency: string, newAccountIDs: number[], currentUserAccountID: number, isDraft = true) { if (!transaction) { return; } @@ -1096,20 +1096,20 @@ function setSplitShares(transaction: OnyxEntry, amount: n // Create an array containing unique IDs of the current transaction participants and the new ones // The current userAccountID might not be included in newAccountIDs if this is called from the participants step using Global Create // If this is called from an existing group chat, it'll be included. So we manually add them to account for both cases. - const accountIDs = [...new Set([getUserAccountID(), ...newAccountIDs, ...oldAccountIDs])]; + const accountIDs = [...new Set([currentUserAccountID, ...newAccountIDs, ...oldAccountIDs])]; const splitShares: SplitShares = accountIDs.reduce((acc: SplitShares, accountID): SplitShares => { // We want to replace the contents of splitShares to contain only `newAccountIDs` entries // In the case of going back to the participants page and removing a participant // a simple merge will have the previous participant still present in the splitShares object // So we manually set their entry to null - if (!newAccountIDs.includes(accountID) && accountID !== getUserAccountID()) { + if (!newAccountIDs.includes(accountID) && accountID !== currentUserAccountID) { acc[accountID] = null; return acc; } - const isPayer = accountID === getUserAccountID(); - const participantsLength = newAccountIDs.includes(getUserAccountID()) ? newAccountIDs.length - 1 : newAccountIDs.length; + const isPayer = accountID === currentUserAccountID; + const participantsLength = newAccountIDs.includes(currentUserAccountID) ? newAccountIDs.length - 1 : newAccountIDs.length; const splitAmount = calculateIOUAmount(participantsLength, amount, currency, isPayer); acc[accountID] = { amount: splitAmount, @@ -1129,7 +1129,7 @@ function resetSplitShares(transaction: OnyxEntry, newAmou if (!accountIDs) { return; } - setSplitShares(transaction, newAmount ?? transaction.amount, currency ?? transaction.currency, accountIDs, isDraft); + setSplitShares(transaction, newAmount ?? transaction.amount, currency ?? transaction.currency, accountIDs, getUserAccountID(), isDraft); } function setDraftSplitTransaction( diff --git a/src/pages/iou/request/step/IOURequestStepAmount.tsx b/src/pages/iou/request/step/IOURequestStepAmount.tsx index 613aff460b35..234a51317d1e 100644 --- a/src/pages/iou/request/step/IOURequestStepAmount.tsx +++ b/src/pages/iou/request/step/IOURequestStepAmount.tsx @@ -340,7 +340,7 @@ function IOURequestStepAmount({ } if (isSplitBill && !report.isOwnPolicyExpenseChat && report.participants) { const participantAccountIDs = Object.keys(report.participants).map((accountID) => Number(accountID)); - setSplitShares(transaction, amountInSmallestCurrencyUnits, selectedCurrency || CONST.CURRENCY.USD, participantAccountIDs); + setSplitShares(transaction, amountInSmallestCurrencyUnits, selectedCurrency || CONST.CURRENCY.USD, participantAccountIDs, currentUserAccountIDParam); } setMoneyRequestParticipantsFromReport(transactionID, report, currentUserPersonalDetails.accountID).then(() => { navigateToConfirmationPage(iouType, transactionID, reportID, backToReport); diff --git a/src/pages/iou/request/step/IOURequestStepDistance.tsx b/src/pages/iou/request/step/IOURequestStepDistance.tsx index ba241f7474e9..0028af3084ce 100644 --- a/src/pages/iou/request/step/IOURequestStepDistance.tsx +++ b/src/pages/iou/request/step/IOURequestStepDistance.tsx @@ -225,7 +225,15 @@ function IOURequestStepDistance({ lastSyncedRouteDistance.current = routeDistance; }, [routeDistance, distanceUnit, customUnitQuantity]); - const setDistanceRequestData = useDistanceRequestData({policy, personalPolicy, transaction, customUnitRateID, transactionID, isSplitRequest}); + const setDistanceRequestData = useDistanceRequestData({ + policy, + personalPolicy, + transaction, + customUnitRateID, + transactionID, + isSplitRequest, + currentUserAccountID: currentUserAccountIDParam, + }); // For quick button actions, we'll skip the confirmation page unless the report is archived or this is a workspace // request and the workspace requires a category or a tag diff --git a/src/pages/iou/request/step/IOURequestStepDistance/hooks/useDistanceRequestData.ts b/src/pages/iou/request/step/IOURequestStepDistance/hooks/useDistanceRequestData.ts index f724ab438090..7415571f53b1 100644 --- a/src/pages/iou/request/step/IOURequestStepDistance/hooks/useDistanceRequestData.ts +++ b/src/pages/iou/request/step/IOURequestStepDistance/hooks/useDistanceRequestData.ts @@ -26,10 +26,21 @@ type UseDistanceRequestDataParams = { /** True for split flows — triggers per-participant share calculation against non-policy chats. */ isSplitRequest: boolean; + + /** Account ID of the current user, used as the payer when calculating split shares. */ + currentUserAccountID: number; }; // Sets `amount` and `split` share data before moving to the next step to avoid briefly showing `0.00` as the split share for participants -function useDistanceRequestData({policy, personalPolicy, transaction, customUnitRateID, transactionID, isSplitRequest}: UseDistanceRequestDataParams): (participants: Participant[]) => void { +function useDistanceRequestData({ + policy, + personalPolicy, + transaction, + customUnitRateID, + transactionID, + isSplitRequest, + currentUserAccountID, +}: UseDistanceRequestDataParams): (participants: Participant[]) => void { return (participants: Participant[]) => { // Get policy report based on transaction participants const isPolicyExpenseChat = participants?.some((participant) => participant.isPolicyExpenseChat); @@ -49,7 +60,7 @@ function useDistanceRequestData({policy, personalPolicy, transaction, customUnit const participantAccountIDs: number[] | undefined = participants?.map((participant) => Number(participant.accountID ?? CONST.DEFAULT_NUMBER_ID)); if (isSplitRequest && amount && currency && !isPolicyExpenseChat) { - setSplitShares(transaction, amount, currency ?? '', participantAccountIDs ?? []); + setSplitShares(transaction, amount, currency ?? '', participantAccountIDs ?? [], currentUserAccountID); } }; } diff --git a/src/pages/iou/request/step/IOURequestStepDistanceMap.tsx b/src/pages/iou/request/step/IOURequestStepDistanceMap.tsx index 48130e27506d..462e22c7a4e0 100644 --- a/src/pages/iou/request/step/IOURequestStepDistanceMap.tsx +++ b/src/pages/iou/request/step/IOURequestStepDistanceMap.tsx @@ -143,7 +143,15 @@ function IOURequestStepDistanceMap({ const currentUserAccountIDParam = currentUserPersonalDetails.accountID; const currentUserEmailParam = currentUserPersonalDetails.login ?? ''; - const setDistanceRequestData = useDistanceRequestData({policy, personalPolicy, transaction, customUnitRateID, transactionID, isSplitRequest}); + const setDistanceRequestData = useDistanceRequestData({ + policy, + personalPolicy, + transaction, + customUnitRateID, + transactionID, + isSplitRequest, + currentUserAccountID: currentUserAccountIDParam, + }); // For quick button actions, we'll skip the confirmation page unless the report is archived or this is a workspace // request and the workspace requires a category or a tag diff --git a/tests/actions/IOU/IOUSettersTest.ts b/tests/actions/IOU/IOUSettersTest.ts index ddebb5cca488..62d5705c3608 100644 --- a/tests/actions/IOU/IOUSettersTest.ts +++ b/tests/actions/IOU/IOUSettersTest.ts @@ -266,7 +266,7 @@ describe('IOU setter functions', () => { await Onyx.set(`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${TRANSACTION_ID}`, transaction); await waitForBatchedUpdates(); - setSplitShares(transaction, 10000, 'USD', [USER_ACCOUNT_ID, PARTICIPANT_ACCOUNT_ID]); + setSplitShares(transaction, 10000, 'USD', [USER_ACCOUNT_ID, PARTICIPANT_ACCOUNT_ID], USER_ACCOUNT_ID); await waitForBatchedUpdates(); const draft = await getOnyxValue(`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${TRANSACTION_ID}`); @@ -280,7 +280,7 @@ describe('IOU setter functions', () => { await Onyx.set(`${ONYXKEYS.COLLECTION.TRANSACTION}${TRANSACTION_ID}`, transaction); await waitForBatchedUpdates(); - setSplitShares(transaction, 10000, 'USD', [USER_ACCOUNT_ID, PARTICIPANT_ACCOUNT_ID], false); + setSplitShares(transaction, 10000, 'USD', [USER_ACCOUNT_ID, PARTICIPANT_ACCOUNT_ID], USER_ACCOUNT_ID, false); await waitForBatchedUpdates(); const updated = await getOnyxValue(`${ONYXKEYS.COLLECTION.TRANSACTION}${TRANSACTION_ID}`); @@ -294,7 +294,7 @@ describe('IOU setter functions', () => { await Onyx.set(`${ONYXKEYS.COLLECTION.TRANSACTION}${TRANSACTION_ID}`, transaction); await waitForBatchedUpdates(); - setSplitShares(transaction, 8000, 'USD', [USER_ACCOUNT_ID, PARTICIPANT_ACCOUNT_ID], false); + setSplitShares(transaction, 8000, 'USD', [USER_ACCOUNT_ID, PARTICIPANT_ACCOUNT_ID], USER_ACCOUNT_ID, false); await waitForBatchedUpdates(); const draft = await getOnyxValue(`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${TRANSACTION_ID}`); @@ -302,7 +302,7 @@ describe('IOU setter functions', () => { }); it('should do nothing when transaction is null', async () => { - setSplitShares(undefined, 10000, 'USD', [USER_ACCOUNT_ID, PARTICIPANT_ACCOUNT_ID]); + setSplitShares(undefined, 10000, 'USD', [USER_ACCOUNT_ID, PARTICIPANT_ACCOUNT_ID], USER_ACCOUNT_ID); await waitForBatchedUpdates(); const draft = await getOnyxValue(`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${TRANSACTION_ID}`); diff --git a/tests/unit/hooks/useDistanceRequestData.test.ts b/tests/unit/hooks/useDistanceRequestData.test.ts index 10fc7638715b..6a36000ff08f 100644 --- a/tests/unit/hooks/useDistanceRequestData.test.ts +++ b/tests/unit/hooks/useDistanceRequestData.test.ts @@ -42,6 +42,7 @@ const baseParams: Params = { customUnitRateID: 'rate1', transactionID: 'txn1', isSplitRequest: false, + currentUserAccountID: 1, }; const personalParticipant: Participant = {accountID: 1, isPolicyExpenseChat: false}; @@ -74,7 +75,7 @@ describe('useDistanceRequestData', () => { result.current([personalParticipant, otherParticipant]); expect(mockSetSplitShares).toHaveBeenCalledTimes(1); - expect(mockSetSplitShares).toHaveBeenCalledWith(baseParams.transaction, 300, 'USD', [1, 2]); + expect(mockSetSplitShares).toHaveBeenCalledWith(baseParams.transaction, 300, 'USD', [1, 2], 1); }); it('skips setSplitShares for split requests against a policy expense chat', () => {