Skip to content
Merged
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
1 change: 1 addition & 0 deletions src/components/MoneyRequestConfirmationList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -615,6 +615,7 @@ function MoneyRequestConfirmationList({
isDistanceRequestWithPendingRoute={isDistanceRequestWithPendingRoute}
shouldCalculateDistanceAmount={shouldCalculateDistanceAmount}
distanceRequestAmount={distanceRequestAmount}
currentUserAccountID={currentUserPersonalDetails.accountID}
setFormError={setFormError}
clearFormErrors={clearFormErrors}
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ type DistanceRequestControllerProps = {
distance: number;
distanceRequestAmount: number;
shouldCalculateDistanceAmount: boolean;
currentUserAccountID: number;
isDistanceRequestWithPendingRoute: boolean;
hasRoute: boolean;
defaultMileageRateCustomUnitRateID: string | undefined;
Expand Down Expand Up @@ -65,6 +66,7 @@ function DistanceRequestController({
distance,
distanceRequestAmount,
shouldCalculateDistanceAmount,
currentUserAccountID,
isDistanceRequestWithPendingRoute,
hasRoute,
defaultMileageRateCustomUnitRateID,
Expand Down Expand Up @@ -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 (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<BaseTextInputRef | null>(null);
const {didScreenTransitionEnd} = useScreenWrapperTransitionStatus();
Expand Down Expand Up @@ -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<number>([accountID, ...newAccountIDs, ...oldAccountIDs])];
Expand Down Expand Up @@ -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;
}
Expand Down
2 changes: 1 addition & 1 deletion src/hooks/useParticipantSubmission.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
12 changes: 6 additions & 6 deletions src/libs/actions/IOU/Split.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1077,7 +1077,7 @@ function completeSplitBill(
/**
* Sets the `splitShares` map that holds individual shares of a split bill
*/
function setSplitShares(transaction: OnyxEntry<OnyxTypes.Transaction>, amount: number, currency: string, newAccountIDs: number[], isDraft = true) {
function setSplitShares(transaction: OnyxEntry<OnyxTypes.Transaction>, amount: number, currency: string, newAccountIDs: number[], currentUserAccountID: number, isDraft = true) {
if (!transaction) {
return;
}
Expand All @@ -1096,20 +1096,20 @@ function setSplitShares(transaction: OnyxEntry<OnyxTypes.Transaction>, 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<number>([getUserAccountID(), ...newAccountIDs, ...oldAccountIDs])];
const accountIDs = [...new Set<number>([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,
Expand All @@ -1129,7 +1129,7 @@ function resetSplitShares(transaction: OnyxEntry<OnyxTypes.Transaction>, 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(
Expand Down
2 changes: 1 addition & 1 deletion src/pages/iou/request/step/IOURequestStepAmount.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
10 changes: 9 additions & 1 deletion src/pages/iou/request/step/IOURequestStepDistance.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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);
}
};
}
Expand Down
10 changes: 9 additions & 1 deletion src/pages/iou/request/step/IOURequestStepDistanceMap.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
8 changes: 4 additions & 4 deletions tests/actions/IOU/IOUSettersTest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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}`);
Expand All @@ -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}`);
Expand All @@ -294,15 +294,15 @@ 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}`);
expect(draft).toBeUndefined();
});

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}`);
Expand Down
3 changes: 2 additions & 1 deletion tests/unit/hooks/useDistanceRequestData.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ const baseParams: Params = {
customUnitRateID: 'rate1',
transactionID: 'txn1',
isSplitRequest: false,
currentUserAccountID: 1,
};

const personalParticipant: Participant = {accountID: 1, isPolicyExpenseChat: false};
Expand Down Expand Up @@ -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', () => {
Expand Down
Loading