From 8437251951f75ce60a1a869015bf1f795b25efd6 Mon Sep 17 00:00:00 2001 From: Hans Date: Fri, 17 Apr 2026 14:58:58 +0700 Subject: [PATCH 01/22] The final part --- src/libs/ReportUtils.ts | 10 ++++--- src/libs/SubscriptionUtils.ts | 1 + src/libs/actions/IOU/MoneyRequest.ts | 4 +-- src/libs/actions/IOU/PayMoneyRequest.ts | 2 +- src/libs/shouldUseDefaultExpensePolicy.ts | 3 +- src/pages/AddUnreportedExpense.tsx | 2 +- .../iou/request/step/IOURequestStepAmount.tsx | 2 +- .../iou/request/step/IOURequestStepHours.tsx | 2 +- tests/unit/SubscriptionUtilsTest.ts | 30 +++++++++---------- 9 files changed, 30 insertions(+), 26 deletions(-) diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index b4edd78ddb4f..fe9ffd75e9ee 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -2993,6 +2993,7 @@ type GetAddExpenseDropdownOptionsParams = { iouRequestBackToReport?: string; unreportedExpenseBackToReport?: string; lastDistanceExpenseType?: IOURequestType; + currentUserAccountID?: number; }; function getAddExpenseDropdownOptions({ @@ -3007,6 +3008,7 @@ function getAddExpenseDropdownOptions({ iouRequestBackToReport, unreportedExpenseBackToReport, lastDistanceExpenseType, + currentUserAccountID, }: GetAddExpenseDropdownOptionsParams): Array>> { return [ { @@ -3021,7 +3023,7 @@ function getAddExpenseDropdownOptions({ if ( policy && policy.type !== CONST.POLICY.TYPE.PERSONAL && - shouldRestrictUserBillableActions(policy.id, ownerBillingGracePeriodEnd, userBillingGracePeriodEnds, amountOwed, policy) + shouldRestrictUserBillableActions(policy.id, ownerBillingGracePeriodEnd, userBillingGracePeriodEnds, amountOwed, policy, currentUserAccountID) ) { Navigation.navigate(ROUTES.RESTRICTED_ACTION.getRoute(policy.id)); return; @@ -3038,7 +3040,7 @@ function getAddExpenseDropdownOptions({ if (!iouReportID) { return; } - if (policy && shouldRestrictUserBillableActions(policy.id, ownerBillingGracePeriodEnd, userBillingGracePeriodEnds, amountOwed, policy)) { + if (policy && shouldRestrictUserBillableActions(policy.id, ownerBillingGracePeriodEnd, userBillingGracePeriodEnds, amountOwed, policy, currentUserAccountID)) { Navigation.navigate(ROUTES.RESTRICTED_ACTION.getRoute(policy.id)); return; } @@ -3051,7 +3053,7 @@ function getAddExpenseDropdownOptions({ icon: icons.ReceiptPlus, sentryLabel: CONST.SENTRY_LABEL.MORE_MENU.ADD_EXPENSE_UNREPORTED, onSelected: () => { - if (policy && shouldRestrictUserBillableActions(policy.id, ownerBillingGracePeriodEnd, userBillingGracePeriodEnds, amountOwed, policy)) { + if (policy && shouldRestrictUserBillableActions(policy.id, ownerBillingGracePeriodEnd, userBillingGracePeriodEnds, amountOwed, policy, currentUserAccountID)) { Navigation.navigate(ROUTES.RESTRICTED_ACTION.getRoute(policy.id)); return; } @@ -11487,7 +11489,7 @@ function createDraftTransactionAndNavigateToParticipantSelector({ } if (actionName === CONST.IOU.ACTION.CATEGORIZE) { - if (activePolicy && shouldRestrictUserBillableActions(activePolicy.id, ownerBillingGracePeriodEnd, userBillingGracePeriodEnds, amountOwed, activePolicy)) { + if (activePolicy && shouldRestrictUserBillableActions(activePolicy.id, ownerBillingGracePeriodEnd, userBillingGracePeriodEnds, amountOwed, activePolicy, currentUserAccountID)) { Navigation.navigate(ROUTES.RESTRICTED_ACTION.getRoute(activePolicy.id)); return; } diff --git a/src/libs/SubscriptionUtils.ts b/src/libs/SubscriptionUtils.ts index cfa5c762b7fa..b24e083dbe78 100644 --- a/src/libs/SubscriptionUtils.ts +++ b/src/libs/SubscriptionUtils.ts @@ -52,6 +52,7 @@ type SubscriptionPlanIllustrations = { ShieldYellow: IconAsset; }; +// TODO: Remove this one eventually let deprecatedCurrentUserAccountID = -1; Onyx.connect({ key: ONYXKEYS.SESSION, diff --git a/src/libs/actions/IOU/MoneyRequest.ts b/src/libs/actions/IOU/MoneyRequest.ts index d46ce210acb2..9625bc588fcd 100644 --- a/src/libs/actions/IOU/MoneyRequest.ts +++ b/src/libs/actions/IOU/MoneyRequest.ts @@ -528,7 +528,7 @@ function handleMoneyRequestStepScanParticipants({ // If there was no reportID, then that means the user started this flow from the global + menu // and an optimistic reportID was generated. In that case, the next step is to select the participants for this expense. - if (shouldUseDefaultExpensePolicy(iouType, defaultExpensePolicy, amountOwed, userBillingGracePeriodEnds, ownerBillingGracePeriodEnd)) { + if (shouldUseDefaultExpensePolicy(iouType, defaultExpensePolicy, amountOwed, userBillingGracePeriodEnds, ownerBillingGracePeriodEnd, currentUserAccountID)) { const shouldAutoReport = !!defaultExpensePolicy?.autoReporting || isAutoReporting; const targetReport = shouldAutoReport ? getPolicyExpenseChat(currentUserAccountID, defaultExpensePolicy?.id) : selfDMReport; const transactionReportID = isSelfDM(targetReport) ? CONST.REPORT.UNREPORTED_REPORT_ID : targetReport?.reportID; @@ -771,7 +771,7 @@ function handleMoneyRequestStepDistanceNavigation({ // If there was no reportID, then that means the user started this flow from the global menu // and an optimistic reportID was generated. In that case, the next step is to select the participants for this expense. - if (defaultExpensePolicy && shouldUseDefaultExpensePolicy(iouType, defaultExpensePolicy, amountOwed, userBillingGracePeriodEnds, ownerBillingGracePeriodEnd)) { + if (defaultExpensePolicy && shouldUseDefaultExpensePolicy(iouType, defaultExpensePolicy, amountOwed, userBillingGracePeriodEnds, ownerBillingGracePeriodEnd, currentUserAccountID)) { const shouldAutoReport = !!defaultExpensePolicy?.autoReporting || isAutoReporting; const targetReport = shouldAutoReport ? getPolicyExpenseChat(currentUserAccountID, defaultExpensePolicy?.id) : selfDMReport; const isSelfDMReport = isSelfDM(targetReport); diff --git a/src/libs/actions/IOU/PayMoneyRequest.ts b/src/libs/actions/IOU/PayMoneyRequest.ts index 392c0dd29143..e363ec34162e 100644 --- a/src/libs/actions/IOU/PayMoneyRequest.ts +++ b/src/libs/actions/IOU/PayMoneyRequest.ts @@ -742,7 +742,7 @@ function payMoneyRequest(params: PayMoneyRequestFunctionParams) { methodID, onPaid, } = params; - if (chatReport.policyID && shouldRestrictUserBillableActions(chatReport.policyID, ownerBillingGracePeriodEnd, userBillingGracePeriodEnds, amountOwed)) { + if (chatReport.policyID && shouldRestrictUserBillableActions(chatReport.policyID, ownerBillingGracePeriodEnd, userBillingGracePeriodEnds, amountOwed, undefined, currentUserAccountID)) { Navigation.navigate(ROUTES.RESTRICTED_ACTION.getRoute(chatReport.policyID)); return; } diff --git a/src/libs/shouldUseDefaultExpensePolicy.ts b/src/libs/shouldUseDefaultExpensePolicy.ts index 109f3ec97dea..74e0e5ae4368 100644 --- a/src/libs/shouldUseDefaultExpensePolicy.ts +++ b/src/libs/shouldUseDefaultExpensePolicy.ts @@ -11,12 +11,13 @@ function shouldUseDefaultExpensePolicy( amountOwed: OnyxEntry, userBillingGracePeriodEnds: OnyxCollection, ownerBillingGracePeriodEnd: OnyxEntry, + currentUserAccountID?: number, ) { return ( iouType === CONST.IOU.TYPE.CREATE && isPaidGroupPolicy(defaultExpensePolicy) && defaultExpensePolicy?.isPolicyExpenseChatEnabled && - !shouldRestrictUserBillableActions(defaultExpensePolicy.id, ownerBillingGracePeriodEnd, userBillingGracePeriodEnds, amountOwed, defaultExpensePolicy) + !shouldRestrictUserBillableActions(defaultExpensePolicy.id, ownerBillingGracePeriodEnd, userBillingGracePeriodEnds, amountOwed, defaultExpensePolicy, currentUserAccountID) ); } diff --git a/src/pages/AddUnreportedExpense.tsx b/src/pages/AddUnreportedExpense.tsx index 2e79c3e55a4b..669e5c846f4a 100644 --- a/src/pages/AddUnreportedExpense.tsx +++ b/src/pages/AddUnreportedExpense.tsx @@ -303,7 +303,7 @@ function AddUnreportedExpense({route}: AddUnreportedExpensePageType) { if ( report && report.policyID && - shouldRestrictUserBillableActions(report.policyID, ownerBillingGracePeriodEnd, userBillingGracePeriodEnds, undefined, policy) + shouldRestrictUserBillableActions(report.policyID, ownerBillingGracePeriodEnd, userBillingGracePeriodEnds, undefined, policy, currentUserAccountID) ) { Navigation.navigate(ROUTES.RESTRICTED_ACTION.getRoute(report.policyID)); return; diff --git a/src/pages/iou/request/step/IOURequestStepAmount.tsx b/src/pages/iou/request/step/IOURequestStepAmount.tsx index a31f6ceb5113..0b6f7cd4ae2d 100644 --- a/src/pages/iou/request/step/IOURequestStepAmount.tsx +++ b/src/pages/iou/request/step/IOURequestStepAmount.tsx @@ -348,7 +348,7 @@ function IOURequestStepAmount({ // Starting from global + menu means no participant context exists yet, // so we need to handle participant selection based on available workspace settings - if (shouldUseDefaultExpensePolicy(iouType, defaultExpensePolicy, amountOwed, userBillingGracePeriodEnds, ownerBillingGracePeriodEnd)) { + if (shouldUseDefaultExpensePolicy(iouType, defaultExpensePolicy, amountOwed, userBillingGracePeriodEnds, ownerBillingGracePeriodEnd, currentUserAccountIDParam)) { const shouldAutoReport = !!defaultExpensePolicy?.autoReporting || !!personalPolicy?.autoReporting; const targetReport = shouldAutoReport ? getPolicyExpenseChat(currentUserAccountIDParam, defaultExpensePolicy?.id) : selfDMReport; const transactionReportID = isSelfDM(targetReport) ? CONST.REPORT.UNREPORTED_REPORT_ID : targetReport?.reportID; diff --git a/src/pages/iou/request/step/IOURequestStepHours.tsx b/src/pages/iou/request/step/IOURequestStepHours.tsx index 497792adaa44..e20067d50788 100644 --- a/src/pages/iou/request/step/IOURequestStepHours.tsx +++ b/src/pages/iou/request/step/IOURequestStepHours.tsx @@ -167,7 +167,7 @@ function IOURequestStepHours({ large={!isExtraSmallScreenHeight} style={[styles.w100, canUseTouchScreen ? styles.mt5 : styles.mt0]} onPress={() => { - if (policyID && shouldRestrictUserBillableActions(policyID, ownerBillingGracePeriodEnd, userBillingGracePeriodEnds, amountOwed)) { + if (policyID && shouldRestrictUserBillableActions(policyID, ownerBillingGracePeriodEnd, userBillingGracePeriodEnds, amountOwed, undefined, accountID)) { Navigation.navigate(ROUTES.RESTRICTED_ACTION.getRoute(policyID)); return; } diff --git a/tests/unit/SubscriptionUtilsTest.ts b/tests/unit/SubscriptionUtilsTest.ts index e856ecabba44..b1ab2684ec2c 100644 --- a/tests/unit/SubscriptionUtilsTest.ts +++ b/tests/unit/SubscriptionUtilsTest.ts @@ -341,7 +341,7 @@ describe('SubscriptionUtils', () => { [ONYXKEYS.SESSION]: {email: '', accountID}, }); - expect(shouldRestrictUserBillableActions(policyID, getUnixTime(addDays(new Date(), 3)), undefined, undefined, policy)).toBeFalsy(); + expect(shouldRestrictUserBillableActions(policyID, getUnixTime(addDays(new Date(), 3)), undefined, undefined, policy, accountID)).toBeFalsy(); }); it("should return false if the user is the workspace's owner that is past due billing but isn't owning any amount", async () => { @@ -354,7 +354,7 @@ describe('SubscriptionUtils', () => { [ONYXKEYS.NVP_PRIVATE_AMOUNT_OWED]: 0, }); - expect(shouldRestrictUserBillableActions(policyID, getUnixTime(subDays(new Date(), 3)), undefined, undefined, policy)).toBeFalsy(); + expect(shouldRestrictUserBillableActions(policyID, getUnixTime(subDays(new Date(), 3)), undefined, undefined, policy, accountID)).toBeFalsy(); }); it("should return true if the user is the workspace's owner that is past due billing and is owning some amount", async () => { @@ -367,7 +367,7 @@ describe('SubscriptionUtils', () => { [ONYXKEYS.NVP_PRIVATE_AMOUNT_OWED]: 8010, }); - expect(shouldRestrictUserBillableActions(policyID, getUnixTime(subDays(new Date(), 3)), undefined, undefined, policy)).toBeTruthy(); + expect(shouldRestrictUserBillableActions(policyID, getUnixTime(subDays(new Date(), 3)), undefined, undefined, policy, accountID)).toBeTruthy(); }); it("should return false if the user is past due billing but is not the workspace's owner", async () => { @@ -380,7 +380,7 @@ describe('SubscriptionUtils', () => { [ONYXKEYS.NVP_PRIVATE_AMOUNT_OWED]: 8010, }); - expect(shouldRestrictUserBillableActions(policyID, getUnixTime(subDays(new Date(), 3)), undefined, undefined, policy)).toBeFalsy(); + expect(shouldRestrictUserBillableActions(policyID, getUnixTime(subDays(new Date(), 3)), undefined, undefined, policy, accountID)).toBeFalsy(); }); it('should restrict when ownerBillingGracePeriodEnd is passed directly as 3rd param and is past due', async () => { @@ -393,7 +393,7 @@ describe('SubscriptionUtils', () => { [ONYXKEYS.NVP_PRIVATE_AMOUNT_OWED]: 8010, }); - expect(shouldRestrictUserBillableActions(policyID, getUnixTime(subDays(new Date(), 3)), undefined, undefined, policy)).toBeTruthy(); + expect(shouldRestrictUserBillableActions(policyID, getUnixTime(subDays(new Date(), 3)), undefined, undefined, policy, accountID)).toBeTruthy(); }); it("should return false if the user is past due billing but is not the workspace's owner (2nd check)", async () => { @@ -406,7 +406,7 @@ describe('SubscriptionUtils', () => { [ONYXKEYS.NVP_PRIVATE_AMOUNT_OWED]: 8010, }); - expect(shouldRestrictUserBillableActions(policyID, getUnixTime(subDays(new Date(), 3)), undefined, undefined, policy)).toBeFalsy(); + expect(shouldRestrictUserBillableActions(policyID, getUnixTime(subDays(new Date(), 3)), undefined, undefined, policy, accountID)).toBeFalsy(); }); it('should restrict when ownerBillingGracePeriodEnd is passed directly as 4th param and is past due', async () => { @@ -419,7 +419,7 @@ describe('SubscriptionUtils', () => { [ONYXKEYS.NVP_PRIVATE_AMOUNT_OWED]: 8010, }); - expect(shouldRestrictUserBillableActions(policyID, getUnixTime(subDays(new Date(), 3)), undefined, undefined, policy)).toBeTruthy(); + expect(shouldRestrictUserBillableActions(policyID, getUnixTime(subDays(new Date(), 3)), undefined, undefined, policy, accountID)).toBeTruthy(); }); it('should not restrict when ownerBillingGracePeriodEnd is passed directly as 4th param but is not past due', async () => { @@ -432,7 +432,7 @@ describe('SubscriptionUtils', () => { [ONYXKEYS.NVP_PRIVATE_AMOUNT_OWED]: 8010, }); - expect(shouldRestrictUserBillableActions(policyID, getUnixTime(addDays(new Date(), 3)), undefined, undefined, policy)).toBeFalsy(); + expect(shouldRestrictUserBillableActions(policyID, getUnixTime(addDays(new Date(), 3)), undefined, undefined, policy, accountID)).toBeFalsy(); }); it('should not restrict when ownerBillingGracePeriodEnd is passed directly as 4th param but amount owed is 0', async () => { @@ -445,7 +445,7 @@ describe('SubscriptionUtils', () => { [ONYXKEYS.NVP_PRIVATE_AMOUNT_OWED]: 0, }); - expect(shouldRestrictUserBillableActions(policyID, getUnixTime(subDays(new Date(), 3)), undefined, undefined, policy)).toBeFalsy(); + expect(shouldRestrictUserBillableActions(policyID, getUnixTime(subDays(new Date(), 3)), undefined, undefined, policy, accountID)).toBeFalsy(); }); it('should restrict when amountOwed is passed directly and is greater than 0', async () => { @@ -457,7 +457,7 @@ describe('SubscriptionUtils', () => { [ONYXKEYS.SESSION]: {email: '', accountID}, }); - expect(shouldRestrictUserBillableActions(policyID, getUnixTime(subDays(new Date(), 3)), undefined, 500, policy)).toBeTruthy(); + expect(shouldRestrictUserBillableActions(policyID, getUnixTime(subDays(new Date(), 3)), undefined, 500, policy, accountID)).toBeTruthy(); }); it('should not restrict when amountOwed is passed directly as 0', async () => { @@ -469,7 +469,7 @@ describe('SubscriptionUtils', () => { [ONYXKEYS.SESSION]: {email: '', accountID}, }); - expect(shouldRestrictUserBillableActions(policyID, getUnixTime(subDays(new Date(), 3)), undefined, 0, policy)).toBeFalsy(); + expect(shouldRestrictUserBillableActions(policyID, getUnixTime(subDays(new Date(), 3)), undefined, 0, policy, accountID)).toBeFalsy(); }); it('should not restrict when amountOwed is passed directly as undefined', async () => { @@ -481,7 +481,7 @@ describe('SubscriptionUtils', () => { [ONYXKEYS.SESSION]: {email: '', accountID}, }); - expect(shouldRestrictUserBillableActions(policyID, getUnixTime(subDays(new Date(), 3)), undefined, undefined, policy)).toBeFalsy(); + expect(shouldRestrictUserBillableActions(policyID, getUnixTime(subDays(new Date(), 3)), undefined, undefined, policy, accountID)).toBeFalsy(); }); }); @@ -509,7 +509,7 @@ describe('SubscriptionUtils', () => { [ONYXKEYS.NVP_PRIVATE_AMOUNT_OWED]: 8010, }); - expect(shouldRestrictUserBillableActions(policyID, getUnixTime(subDays(new Date(), 3)), undefined, undefined, policy)).toBeTruthy(); + expect(shouldRestrictUserBillableActions(policyID, getUnixTime(subDays(new Date(), 3)), undefined, undefined, policy, accountID)).toBeTruthy(); }); it('should not restrict when policy is passed directly but owner is not past due', async () => { @@ -525,7 +525,7 @@ describe('SubscriptionUtils', () => { [ONYXKEYS.NVP_PRIVATE_AMOUNT_OWED]: 8010, }); - expect(shouldRestrictUserBillableActions(policyID, getUnixTime(addDays(new Date(), 3)), undefined, undefined, policy)).toBeFalsy(); + expect(shouldRestrictUserBillableActions(policyID, getUnixTime(addDays(new Date(), 3)), undefined, undefined, policy, accountID)).toBeFalsy(); }); it('should not restrict when policy is passed as undefined', () => { @@ -597,7 +597,7 @@ describe('SubscriptionUtils', () => { }, }); - expect(shouldRestrictUserBillableActions(policyID, getUnixTime(subDays(new Date(), 3)), undefined, undefined, differentOwnerPolicy)).toBeFalsy(); + expect(shouldRestrictUserBillableActions(policyID, getUnixTime(subDays(new Date(), 3)), undefined, undefined, differentOwnerPolicy, accountID)).toBeFalsy(); }); }); From 9bc726eb1545add30b632344ffc088f1df6097d7 Mon Sep 17 00:00:00 2001 From: Hans Date: Tue, 12 May 2026 23:18:05 +0700 Subject: [PATCH 02/22] remove Onyx connect --- src/libs/SubscriptionUtils.ts | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/src/libs/SubscriptionUtils.ts b/src/libs/SubscriptionUtils.ts index 13471a911521..8d0e87b85103 100644 --- a/src/libs/SubscriptionUtils.ts +++ b/src/libs/SubscriptionUtils.ts @@ -52,15 +52,6 @@ type SubscriptionPlanIllustrations = { ShieldYellow: IconAsset; }; -// TODO: Remove this one eventually -let deprecatedCurrentUserAccountID = -1; -Onyx.connect({ - key: ONYXKEYS.SESSION, - callback: (value) => { - deprecatedCurrentUserAccountID = value?.accountID ?? CONST.DEFAULT_NUMBER_ID; - }, -}); - /** * @returns Whether the workspace owner's grace period is overdue. */ @@ -487,7 +478,7 @@ function shouldRestrictUserBillableActions( ownerBillingGracePeriodEnd: OnyxEntry, userBillingGracePeriodEnds: OnyxCollection, amountOwed: OnyxEntry, - currentUserAccountID: number = deprecatedCurrentUserAccountID, + currentUserAccountID: number, ): boolean { const currentDate = new Date(); From c5a7d70754f4cb2c680433e88a3b73569454200b Mon Sep 17 00:00:00 2001 From: Hans Date: Wed, 13 May 2026 10:36:52 +0700 Subject: [PATCH 03/22] linting --- src/libs/SubscriptionUtils.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/libs/SubscriptionUtils.ts b/src/libs/SubscriptionUtils.ts index 8d0e87b85103..12add0ff1741 100644 --- a/src/libs/SubscriptionUtils.ts +++ b/src/libs/SubscriptionUtils.ts @@ -1,7 +1,6 @@ import {differenceInSeconds, fromUnixTime, isAfter, isBefore} from 'date-fns'; import {fromZonedTime} from 'date-fns-tz'; import type {OnyxCollection, OnyxEntry} from 'react-native-onyx'; -import Onyx from 'react-native-onyx'; import type {ValueOf} from 'type-fest'; import type {LocalizedTranslate} from '@components/LocaleContextProvider'; import type {PreferredCurrency} from '@hooks/usePreferredCurrency'; @@ -478,7 +477,7 @@ function shouldRestrictUserBillableActions( ownerBillingGracePeriodEnd: OnyxEntry, userBillingGracePeriodEnds: OnyxCollection, amountOwed: OnyxEntry, - currentUserAccountID: number, + currentUserAccountID?: number, ): boolean { const currentDate = new Date(); From c636ac052be28c9b5a7d8bc14063089450de5332 Mon Sep 17 00:00:00 2001 From: Hans Date: Wed, 13 May 2026 11:41:50 +0700 Subject: [PATCH 04/22] sync main --- Mobile-Expensify | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Mobile-Expensify b/Mobile-Expensify index 33106afba799..f44d016aea19 160000 --- a/Mobile-Expensify +++ b/Mobile-Expensify @@ -1 +1 @@ -Subproject commit 33106afba7997e666890ef31935a6eb80c689243 +Subproject commit f44d016aea198982ed810190e45ad3b43a6ea528 From af93956f9aab106768cd32e7bf84e069e2d99373 Mon Sep 17 00:00:00 2001 From: Hans Date: Wed, 13 May 2026 13:20:59 +0700 Subject: [PATCH 05/22] prettier --- .../MoneyRequestReportTransactionList.tsx | 14 +++++++++++++- .../ReportPreviewActionButton.tsx | 1 + src/hooks/useExpenseActions.ts | 1 + src/libs/ReportUtils.ts | 8 ++++++-- src/libs/SubscriptionUtils.ts | 2 +- src/pages/AddExistingExpense.tsx | 5 ++++- tests/unit/ReportUtilsTest.ts | 2 ++ 7 files changed, 28 insertions(+), 5 deletions(-) diff --git a/src/components/MoneyRequestReportView/MoneyRequestReportTransactionList.tsx b/src/components/MoneyRequestReportView/MoneyRequestReportTransactionList.tsx index 6131ffeae2da..b651e350ca68 100644 --- a/src/components/MoneyRequestReportView/MoneyRequestReportTransactionList.tsx +++ b/src/components/MoneyRequestReportView/MoneyRequestReportTransactionList.tsx @@ -198,8 +198,20 @@ function MoneyRequestReportTransactionList({ amountOwed, ownerBillingGracePeriodEnd, lastDistanceExpenseType, + currentUserAccountID: currentUserDetails?.accountID, }), - [translate, expensifyIcons, report?.reportID, policy, userBillingGracePeriodEnds, amountOwed, lastDistanceExpenseType, ownerBillingGracePeriodEnd, draftTransactionIDs], + [ + translate, + expensifyIcons, + report?.reportID, + policy, + userBillingGracePeriodEnds, + amountOwed, + lastDistanceExpenseType, + ownerBillingGracePeriodEnd, + draftTransactionIDs, + currentUserDetails?.accountID, + ], ); const hasPendingAction = useMemo(() => { diff --git a/src/components/ReportActionItem/MoneyRequestReportPreview/ReportPreviewActionButton.tsx b/src/components/ReportActionItem/MoneyRequestReportPreview/ReportPreviewActionButton.tsx index c38a34d396d6..dbf673149294 100644 --- a/src/components/ReportActionItem/MoneyRequestReportPreview/ReportPreviewActionButton.tsx +++ b/src/components/ReportActionItem/MoneyRequestReportPreview/ReportPreviewActionButton.tsx @@ -218,6 +218,7 @@ function ReportPreviewActionButton({ iouRequestBackToReport: chatReportID, unreportedExpenseBackToReport: iouReport?.parentReportID, lastDistanceExpenseType, + currentUserAccountID: currentUserDetails.accountID, })} isSplitButton={false} anchorAlignment={{ diff --git a/src/hooks/useExpenseActions.ts b/src/hooks/useExpenseActions.ts index 2633ce04f183..fada77481690 100644 --- a/src/hooks/useExpenseActions.ts +++ b/src/hooks/useExpenseActions.ts @@ -271,6 +271,7 @@ function useExpenseActions({reportID, isReportInSearch = false, backTo, onDuplic amountOwed, ownerBillingGracePeriodEnd, lastDistanceExpenseType, + currentUserAccountID: accountID, }); const expensifyIcons = useMemoizedLazyExpensifyIcons([ diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index b686be139c12..5590e4c84017 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -2930,7 +2930,7 @@ type GetAddExpenseDropdownOptionsParams = { iouRequestBackToReport?: string; unreportedExpenseBackToReport?: string; lastDistanceExpenseType?: IOURequestType; - currentUserAccountID?: number; + currentUserAccountID: number; }; function getAddExpenseDropdownOptions({ @@ -2957,7 +2957,11 @@ function getAddExpenseDropdownOptions({ if (!iouReportID) { return; } - if (policy && policy.type !== CONST.POLICY.TYPE.PERSONAL && shouldRestrictUserBillableActions(policy, ownerBillingGracePeriodEnd, userBillingGracePeriodEnds, amountOwed, currentUserAccountID)) { + if ( + policy && + policy.type !== CONST.POLICY.TYPE.PERSONAL && + shouldRestrictUserBillableActions(policy, ownerBillingGracePeriodEnd, userBillingGracePeriodEnds, amountOwed, currentUserAccountID) + ) { Navigation.navigate(ROUTES.RESTRICTED_ACTION.getRoute(policy.id)); return; } diff --git a/src/libs/SubscriptionUtils.ts b/src/libs/SubscriptionUtils.ts index 12add0ff1741..9f4e454513b0 100644 --- a/src/libs/SubscriptionUtils.ts +++ b/src/libs/SubscriptionUtils.ts @@ -477,7 +477,7 @@ function shouldRestrictUserBillableActions( ownerBillingGracePeriodEnd: OnyxEntry, userBillingGracePeriodEnds: OnyxCollection, amountOwed: OnyxEntry, - currentUserAccountID?: number, + currentUserAccountID: number, ): boolean { const currentDate = new Date(); diff --git a/src/pages/AddExistingExpense.tsx b/src/pages/AddExistingExpense.tsx index cdf23853dece..a978164c806c 100644 --- a/src/pages/AddExistingExpense.tsx +++ b/src/pages/AddExistingExpense.tsx @@ -424,7 +424,10 @@ function AddExistingExpense({route}: AddExistingExpensePageType) { { buttonText: translate('iou.createExpense'), buttonAction: () => { - if (report?.policyID && shouldRestrictUserBillableActions(policy, ownerBillingGracePeriodEnd, userBillingGracePeriodEnds, amountOwed, currentUserAccountID)) { + if ( + report?.policyID && + shouldRestrictUserBillableActions(policy, ownerBillingGracePeriodEnd, userBillingGracePeriodEnds, amountOwed, currentUserAccountID) + ) { Navigation.navigate(ROUTES.RESTRICTED_ACTION.getRoute(report.policyID)); return; } diff --git a/tests/unit/ReportUtilsTest.ts b/tests/unit/ReportUtilsTest.ts index 6478f908203a..d308301183a2 100644 --- a/tests/unit/ReportUtilsTest.ts +++ b/tests/unit/ReportUtilsTest.ts @@ -16263,6 +16263,7 @@ describe('ReportUtils', () => { draftTransactionIDs: undefined, amountOwed, ownerBillingGracePeriodEnd: pastGracePeriod, + currentUserAccountID, }); // Trigger CREATE_NEW_EXPENSE onSelected @@ -16714,6 +16715,7 @@ describe('ReportUtils', () => { draftTransactionIDs: undefined, amountOwed: 100, ownerBillingGracePeriodEnd: gracePeriodEnd, + currentUserAccountID, }); options.at(2)?.onSelected?.(); From b434de63a662d4167cc7dac1fe4d91e8224ddd56 Mon Sep 17 00:00:00 2001 From: Hans Date: Wed, 13 May 2026 13:35:48 +0700 Subject: [PATCH 06/22] fix ts --- src/libs/shouldUseDefaultExpensePolicy.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/shouldUseDefaultExpensePolicy.ts b/src/libs/shouldUseDefaultExpensePolicy.ts index 68e454f0260c..33fa6fa78d3c 100644 --- a/src/libs/shouldUseDefaultExpensePolicy.ts +++ b/src/libs/shouldUseDefaultExpensePolicy.ts @@ -11,7 +11,7 @@ function shouldUseDefaultExpensePolicy( amountOwed: OnyxEntry, userBillingGracePeriodEnds: OnyxCollection, ownerBillingGracePeriodEnd: OnyxEntry, - currentUserAccountID?: number, + currentUserAccountID: number, ) { return ( iouType === CONST.IOU.TYPE.CREATE && From 1306929e01a6a5454bf299f05b946dfb6c46df01 Mon Sep 17 00:00:00 2001 From: Hans Date: Wed, 13 May 2026 14:00:21 +0700 Subject: [PATCH 07/22] fix test --- tests/unit/ReportUtilsTest.ts | 14 ++++++++++++++ tests/unit/shouldUseDefaultExpensePolicyTest.ts | 17 +++++++++-------- 2 files changed, 23 insertions(+), 8 deletions(-) diff --git a/tests/unit/ReportUtilsTest.ts b/tests/unit/ReportUtilsTest.ts index d308301183a2..99c655c43793 100644 --- a/tests/unit/ReportUtilsTest.ts +++ b/tests/unit/ReportUtilsTest.ts @@ -16082,6 +16082,7 @@ describe('ReportUtils', () => { draftTransactionIDs: undefined, amountOwed: 0, ownerBillingGracePeriodEnd: undefined, + currentUserAccountID, }); expect(result).toHaveLength(3); }); @@ -16096,6 +16097,7 @@ describe('ReportUtils', () => { draftTransactionIDs: undefined, amountOwed: undefined, ownerBillingGracePeriodEnd: undefined, + currentUserAccountID, }); expect(result.at(0)?.value).toBe(CONST.REPORT.ADD_EXPENSE_OPTIONS.CREATE_NEW_EXPENSE); expect(result.at(1)?.value).toBe(CONST.REPORT.ADD_EXPENSE_OPTIONS.TRACK_DISTANCE_EXPENSE); @@ -16112,6 +16114,7 @@ describe('ReportUtils', () => { draftTransactionIDs: undefined, amountOwed: 0, ownerBillingGracePeriodEnd: undefined, + currentUserAccountID, }); expect(result.at(0)?.text).toBe(translate(CONST.LOCALES.EN, 'iou.createExpense')); expect(result.at(1)?.text).toBe(translate(CONST.LOCALES.EN, 'iou.trackDistance')); @@ -16128,6 +16131,7 @@ describe('ReportUtils', () => { draftTransactionIDs: undefined, amountOwed: 0, ownerBillingGracePeriodEnd: undefined, + currentUserAccountID, }); expect(result.at(0)?.sentryLabel).toBe(CONST.SENTRY_LABEL.MORE_MENU.ADD_EXPENSE_CREATE); expect(result.at(1)?.sentryLabel).toBe(CONST.SENTRY_LABEL.MORE_MENU.ADD_EXPENSE_TRACK_DISTANCE); @@ -16147,6 +16151,7 @@ describe('ReportUtils', () => { draftTransactionIDs: undefined, amountOwed, ownerBillingGracePeriodEnd: undefined, + currentUserAccountID, }); // Trigger each onSelected - the function should not throw @@ -16167,6 +16172,7 @@ describe('ReportUtils', () => { draftTransactionIDs: undefined, amountOwed: 0, ownerBillingGracePeriodEnd: undefined, + currentUserAccountID, }); expect(result).toHaveLength(3); @@ -16186,6 +16192,7 @@ describe('ReportUtils', () => { draftTransactionIDs: undefined, amountOwed: 0, ownerBillingGracePeriodEnd: undefined, + currentUserAccountID, }); // CREATE_NEW_EXPENSE and TRACK_DISTANCE_EXPENSE should early-return when iouReportID is undefined @@ -16205,6 +16212,7 @@ describe('ReportUtils', () => { draftTransactionIDs: undefined, amountOwed: 0, ownerBillingGracePeriodEnd: undefined, + currentUserAccountID, }); expect(result).toHaveLength(3); @@ -16224,6 +16232,7 @@ describe('ReportUtils', () => { draftTransactionIDs: undefined, amountOwed, ownerBillingGracePeriodEnd: undefined, + currentUserAccountID, }); expect(result).toHaveLength(3); @@ -16239,6 +16248,7 @@ describe('ReportUtils', () => { draftTransactionIDs: undefined, amountOwed: 0, ownerBillingGracePeriodEnd: undefined, + currentUserAccountID, }); expect(result.at(1)?.icon).toBe(mockIcons.Location); expect(result.at(2)?.icon).toBe(mockIcons.ReceiptPlus); @@ -16607,6 +16617,7 @@ describe('ReportUtils', () => { draftTransactionIDs: undefined, amountOwed: undefined, ownerBillingGracePeriodEnd: undefined, + currentUserAccountID, }); expect(options).toHaveLength(3); @@ -16626,6 +16637,7 @@ describe('ReportUtils', () => { draftTransactionIDs: undefined, amountOwed: undefined, ownerBillingGracePeriodEnd: undefined, + currentUserAccountID, }); options.at(0)?.onSelected?.(); @@ -16657,6 +16669,7 @@ describe('ReportUtils', () => { draftTransactionIDs: undefined, amountOwed: undefined, ownerBillingGracePeriodEnd: undefined, + currentUserAccountID, }); options.at(0)?.onSelected?.(); @@ -16689,6 +16702,7 @@ describe('ReportUtils', () => { draftTransactionIDs: undefined, amountOwed: undefined, ownerBillingGracePeriodEnd: undefined, + currentUserAccountID, }); options.at(2)?.onSelected?.(); diff --git a/tests/unit/shouldUseDefaultExpensePolicyTest.ts b/tests/unit/shouldUseDefaultExpensePolicyTest.ts index b1ac34d6b90a..0169321a23b2 100644 --- a/tests/unit/shouldUseDefaultExpensePolicyTest.ts +++ b/tests/unit/shouldUseDefaultExpensePolicyTest.ts @@ -33,27 +33,27 @@ describe('shouldUseDefaultExpensePolicy', () => { it('returns false when iouType is not CREATE', () => { const policy = makePaidGroupPolicy(); - expect(shouldUseDefaultExpensePolicy(CONST.IOU.TYPE.SUBMIT, policy, undefined, undefined, undefined)).toBeFalsy(); - expect(shouldUseDefaultExpensePolicy(CONST.IOU.TYPE.TRACK, policy, undefined, undefined, undefined)).toBeFalsy(); + expect(shouldUseDefaultExpensePolicy(CONST.IOU.TYPE.SUBMIT, policy, undefined, undefined, undefined, OWNER_ACCOUNT_ID)).toBeFalsy(); + expect(shouldUseDefaultExpensePolicy(CONST.IOU.TYPE.TRACK, policy, undefined, undefined, undefined, OWNER_ACCOUNT_ID)).toBeFalsy(); }); it('returns false when defaultExpensePolicy is null', () => { - expect(shouldUseDefaultExpensePolicy(CONST.IOU.TYPE.CREATE, null, undefined, undefined, undefined)).toBeFalsy(); + expect(shouldUseDefaultExpensePolicy(CONST.IOU.TYPE.CREATE, null, undefined, undefined, undefined, OWNER_ACCOUNT_ID)).toBeFalsy(); }); it('returns false when defaultExpensePolicy is not a paid group policy (personal type)', () => { const policy = makePaidGroupPolicy({type: CONST.POLICY.TYPE.PERSONAL}); - expect(shouldUseDefaultExpensePolicy(CONST.IOU.TYPE.CREATE, policy, undefined, undefined, undefined)).toBeFalsy(); + expect(shouldUseDefaultExpensePolicy(CONST.IOU.TYPE.CREATE, policy, undefined, undefined, undefined, OWNER_ACCOUNT_ID)).toBeFalsy(); }); it('returns false when isPolicyExpenseChatEnabled is false', () => { const policy = makePaidGroupPolicy({isPolicyExpenseChatEnabled: false}); - expect(shouldUseDefaultExpensePolicy(CONST.IOU.TYPE.CREATE, policy, undefined, undefined, undefined)).toBeFalsy(); + expect(shouldUseDefaultExpensePolicy(CONST.IOU.TYPE.CREATE, policy, undefined, undefined, undefined, OWNER_ACCOUNT_ID)).toBeFalsy(); }); it('returns true when all conditions are met and user is not restricted', () => { const policy = makePaidGroupPolicy(); - expect(shouldUseDefaultExpensePolicy(CONST.IOU.TYPE.CREATE, policy, undefined, undefined, undefined)).toBeTruthy(); + expect(shouldUseDefaultExpensePolicy(CONST.IOU.TYPE.CREATE, policy, undefined, undefined, undefined, OWNER_ACCOUNT_ID)).toBeTruthy(); }); it('returns false when the user is restricted (owner past due with amount owed)', async () => { @@ -67,7 +67,7 @@ describe('shouldUseDefaultExpensePolicy', () => { const amountOwed = 500; // User is the owner, past due, and owes money → shouldRestrictUserBillableActions returns true - expect(shouldUseDefaultExpensePolicy(CONST.IOU.TYPE.CREATE, policy, amountOwed, undefined, pastDueGracePeriodEnd)).toBeFalsy(); + expect(shouldUseDefaultExpensePolicy(CONST.IOU.TYPE.CREATE, policy, amountOwed, undefined, pastDueGracePeriodEnd, OWNER_ACCOUNT_ID)).toBeFalsy(); }); it('returns true when the owner is past due but amount owed is 0', async () => { @@ -79,7 +79,7 @@ describe('shouldUseDefaultExpensePolicy', () => { const policy = makePaidGroupPolicy({ownerAccountID: OWNER_ACCOUNT_ID}); const pastDueGracePeriodEnd = getUnixTime(subDays(new Date(), 3)); - expect(shouldUseDefaultExpensePolicy(CONST.IOU.TYPE.CREATE, policy, 0, undefined, pastDueGracePeriodEnd)).toBeTruthy(); + expect(shouldUseDefaultExpensePolicy(CONST.IOU.TYPE.CREATE, policy, 0, undefined, pastDueGracePeriodEnd, OWNER_ACCOUNT_ID)).toBeTruthy(); }); it('returns false when a non-owner member workspace owner is past due', async () => { @@ -104,6 +104,7 @@ describe('shouldUseDefaultExpensePolicy', () => { [gracePeriodKey]: {...billingGraceEndPeriod, value: pastDueGracePeriodEnd}, }, undefined, + memberAccountID, ), ).toBeFalsy(); }); From feedd1fcfa0616fc91e5ee0721febc89443ecd58 Mon Sep 17 00:00:00 2001 From: Hans Date: Thu, 14 May 2026 13:27:29 +0700 Subject: [PATCH 08/22] more refactor --- .../useUpdateGpsNotification/index.ios.ts | 11 +++++++++- .../MoneyRequestHeaderSecondaryActions.tsx | 2 +- .../ReportActionItem/MoneyRequestView.tsx | 2 +- src/hooks/useExpenseActions.ts | 2 +- src/hooks/useParticipantSubmission.ts | 2 +- src/hooks/useSearchBulkActions.ts | 2 +- src/hooks/useSelectedTransactionsActions.ts | 2 +- src/libs/actions/SplitExpenses.ts | 4 ++-- .../index.native.tsx | 9 ++++++++- .../step/IOURequestStepDistanceManual.tsx | 9 ++++++++- .../step/IOURequestStepDistanceOdometer.tsx | 4 ++-- tests/actions/IOU/MoneyRequestTest.ts | 20 +++++++++---------- tests/actions/IOUTest/SplitTest.ts | 8 ++++---- tests/unit/SubscriptionUtilsTest.ts | 9 +++++++-- 14 files changed, 57 insertions(+), 29 deletions(-) diff --git a/src/components/GPSTripStateChecker/useUpdateGpsNotification/index.ios.ts b/src/components/GPSTripStateChecker/useUpdateGpsNotification/index.ios.ts index 8ecafc70f9d2..bd8a7100c9d9 100644 --- a/src/components/GPSTripStateChecker/useUpdateGpsNotification/index.ios.ts +++ b/src/components/GPSTripStateChecker/useUpdateGpsNotification/index.ios.ts @@ -1,4 +1,5 @@ import {useEffect, useRef} from 'react'; +import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails'; import useDefaultExpensePolicy from '@hooks/useDefaultExpensePolicy'; import useLocalize from '@hooks/useLocalize'; import useOnyx from '@hooks/useOnyx'; @@ -34,6 +35,7 @@ function useUpdateGpsNotificationOnLanguageChange() { function useUpdateGpsNotificationOnUnitChange() { const {translate} = useLocalize(); + const currentUserPersonalDetails = useCurrentUserPersonalDetails(); const [amountOwed] = useOnyx(ONYXKEYS.NVP_PRIVATE_AMOUNT_OWED); const [userBillingGracePeriodEnds] = useOnyx(ONYXKEYS.COLLECTION.SHARED_NVP_PRIVATE_USER_BILLING_GRACE_PERIOD_END); @@ -41,7 +43,14 @@ function useUpdateGpsNotificationOnUnitChange() { const [transaction] = useOnyx(`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${CONST.IOU.OPTIMISTIC_TRANSACTION_ID}`); const defaultExpensePolicy = useDefaultExpensePolicy(); - const shouldUseDefaultExpensePolicy = shouldUseDefaultExpensePolicyUtil(CONST.IOU.TYPE.CREATE, defaultExpensePolicy, amountOwed, userBillingGracePeriodEnds, ownerBillingGracePeriodEnd); + const shouldUseDefaultExpensePolicy = shouldUseDefaultExpensePolicyUtil( + CONST.IOU.TYPE.CREATE, + defaultExpensePolicy, + amountOwed, + userBillingGracePeriodEnds, + ownerBillingGracePeriodEnd, + currentUserPersonalDetails.accountID, + ); const unit = DistanceRequestUtils.getRate({transaction, policy: shouldUseDefaultExpensePolicy ? defaultExpensePolicy : undefined}).unit; diff --git a/src/components/MoneyRequestHeaderSecondaryActions.tsx b/src/components/MoneyRequestHeaderSecondaryActions.tsx index 1526b9f84b35..6e002ab95463 100644 --- a/src/components/MoneyRequestHeaderSecondaryActions.tsx +++ b/src/components/MoneyRequestHeaderSecondaryActions.tsx @@ -333,7 +333,7 @@ function MoneyRequestHeaderSecondaryActions({reportID, onBackButtonPress}: Money icon: expensifyIcons.ArrowSplit, value: CONST.REPORT.TRANSACTION_SECONDARY_ACTIONS.SPLIT, onSelected: () => { - initSplitExpense(transaction, policy); + initSplitExpense(transaction, policy, accountID); }, }, [CONST.REPORT.TRANSACTION_SECONDARY_ACTIONS.MERGE]: { diff --git a/src/components/ReportActionItem/MoneyRequestView.tsx b/src/components/ReportActionItem/MoneyRequestView.tsx index 03cba0a7d862..236559214a6c 100644 --- a/src/components/ReportActionItem/MoneyRequestView.tsx +++ b/src/components/ReportActionItem/MoneyRequestView.tsx @@ -932,7 +932,7 @@ function MoneyRequestView({ } if (shouldShowSplitIndicator && isSplitAvailable) { - initSplitExpense(transaction, policy); + initSplitExpense(transaction, policy, currentUserAccountIDParam); return; } diff --git a/src/hooks/useExpenseActions.ts b/src/hooks/useExpenseActions.ts index fada77481690..ca3326da4201 100644 --- a/src/hooks/useExpenseActions.ts +++ b/src/hooks/useExpenseActions.ts @@ -301,7 +301,7 @@ function useExpenseActions({reportID, isReportInSearch = false, backTo, onDuplic if (transactions.length !== 1) { return; } - initSplitExpense(currentTransaction, policy); + initSplitExpense(currentTransaction, policy, accountID); }, }, [CONST.REPORT.SECONDARY_ACTIONS.MERGE]: { diff --git a/src/hooks/useParticipantSubmission.ts b/src/hooks/useParticipantSubmission.ts index 614a4f4719a3..886bceeacf8d 100644 --- a/src/hooks/useParticipantSubmission.ts +++ b/src/hooks/useParticipantSubmission.ts @@ -98,7 +98,7 @@ function useParticipantSubmission({ iouType === CONST.IOU.TYPE.CREATE && isPaidGroupPolicy(activePolicy) && activePolicy?.isPolicyExpenseChatEnabled && - !shouldRestrictUserBillableActions(activePolicy, ownerBillingGracePeriodEnd, userBillingGracePeriodEnds, amountOwed); + !shouldRestrictUserBillableActions(activePolicy, ownerBillingGracePeriodEnd, userBillingGracePeriodEnds, amountOwed, currentUserPersonalDetails.accountID); const dataRef = useRef({ allPolicies, diff --git a/src/hooks/useSearchBulkActions.ts b/src/hooks/useSearchBulkActions.ts index 65dd42878834..f8708fcff040 100644 --- a/src/hooks/useSearchBulkActions.ts +++ b/src/hooks/useSearchBulkActions.ts @@ -1419,7 +1419,7 @@ function useSearchBulkActions({queryJSON}: UseSearchBulkActionsParams) { icon: expensifyIcons.ArrowSplit, value: CONST.SEARCH.BULK_ACTION_TYPES.SPLIT, onSelected: () => { - initSplitExpense(firstTransaction, firstTransactionPolicy); + initSplitExpense(firstTransaction, firstTransactionPolicy, accountID); }, }); } diff --git a/src/hooks/useSelectedTransactionsActions.ts b/src/hooks/useSelectedTransactionsActions.ts index fefb1ed701a4..5c8587446802 100644 --- a/src/hooks/useSelectedTransactionsActions.ts +++ b/src/hooks/useSelectedTransactionsActions.ts @@ -469,7 +469,7 @@ function useSelectedTransactionsActions({ icon: expensifyIcons.ArrowSplit, value: SPLIT, onSelected: () => { - initSplitExpense(firstTransaction, policy); + initSplitExpense(firstTransaction, policy, currentUserAccountID); }, }); } diff --git a/src/libs/actions/SplitExpenses.ts b/src/libs/actions/SplitExpenses.ts index e973908d4e5d..3daf39566275 100644 --- a/src/libs/actions/SplitExpenses.ts +++ b/src/libs/actions/SplitExpenses.ts @@ -67,12 +67,12 @@ Onyx.connectWithoutView({ /** * Create a draft transaction to set up split expense details for the split expense flow */ -function initSplitExpense(transaction: OnyxEntry, policy: OnyxEntry): void { +function initSplitExpense(transaction: OnyxEntry, policy: OnyxEntry, currentUserAccountID: number): void { if (!transaction) { return; } - if (!!policy && shouldRestrictUserBillableActions(policy, ownerBillingGracePeriodEnd, userBillingGracePeriodEnds, amountOwed)) { + if (!!policy && shouldRestrictUserBillableActions(policy, ownerBillingGracePeriodEnd, userBillingGracePeriodEnds, amountOwed, currentUserAccountID)) { Navigation.navigate(ROUTES.RESTRICTED_ACTION.getRoute(policy.id)); return; } diff --git a/src/pages/iou/request/step/IOURequestStepDistanceGPS/index.native.tsx b/src/pages/iou/request/step/IOURequestStepDistanceGPS/index.native.tsx index cce3dfb38629..e6f8e3b0a78d 100644 --- a/src/pages/iou/request/step/IOURequestStepDistanceGPS/index.native.tsx +++ b/src/pages/iou/request/step/IOURequestStepDistanceGPS/index.native.tsx @@ -86,7 +86,14 @@ function IOURequestStepDistanceGPS({ const currentUserAccountIDParam = currentUserPersonalDetails.accountID; const currentUserEmailParam = currentUserPersonalDetails.login ?? ''; - const shouldUseDefaultExpensePolicy = shouldUseDefaultExpensePolicyUtil(iouType, defaultExpensePolicy, amountOwed, userBillingGracePeriodEnds, ownerBillingGracePeriodEnd); + const shouldUseDefaultExpensePolicy = shouldUseDefaultExpensePolicyUtil( + iouType, + defaultExpensePolicy, + amountOwed, + userBillingGracePeriodEnds, + ownerBillingGracePeriodEnd, + currentUserAccountIDParam, + ); const unit = DistanceRequestUtils.getRate({transaction, policy: shouldUseDefaultExpensePolicy ? defaultExpensePolicy : policy}).unit; diff --git a/src/pages/iou/request/step/IOURequestStepDistanceManual.tsx b/src/pages/iou/request/step/IOURequestStepDistanceManual.tsx index 13b18e579d4d..d0add6651e47 100644 --- a/src/pages/iou/request/step/IOURequestStepDistanceManual.tsx +++ b/src/pages/iou/request/step/IOURequestStepDistanceManual.tsx @@ -106,7 +106,14 @@ function IOURequestStepDistanceManual({ const currentUserEmailParam = currentUserPersonalDetails.login ?? ''; const isASAPSubmitBetaEnabled = isBetaEnabled(CONST.BETAS.ASAP_SUBMIT); - const shouldUseDefaultExpensePolicy = shouldUseDefaultExpensePolicyUtil(iouType, defaultExpensePolicy, amountOwed, userBillingGracePeriodEnds, ownerBillingGracePeriodEnd); + const shouldUseDefaultExpensePolicy = shouldUseDefaultExpensePolicyUtil( + iouType, + defaultExpensePolicy, + amountOwed, + userBillingGracePeriodEnds, + ownerBillingGracePeriodEnd, + currentUserAccountIDParam, + ); // to make sure the correct distance amount and unit will be shown we use distance unit // from defaultExpensePolicy or current report's policy instead of from transaction and diff --git a/src/pages/iou/request/step/IOURequestStepDistanceOdometer.tsx b/src/pages/iou/request/step/IOURequestStepDistanceOdometer.tsx index d7e37cd8b106..db490ff6237d 100644 --- a/src/pages/iou/request/step/IOURequestStepDistanceOdometer.tsx +++ b/src/pages/iou/request/step/IOURequestStepDistanceOdometer.tsx @@ -129,8 +129,8 @@ function IOURequestStepDistanceOdometer({ const isFocused = useIsFocused(); const shouldUseDefaultExpensePolicy = useMemo( - () => shouldUseDefaultExpensePolicyUtil(iouType, defaultExpensePolicy, amountOwed, userBillingGracePeriodEnds, ownerBillingGracePeriodEnd), - [iouType, defaultExpensePolicy, amountOwed, userBillingGracePeriodEnds, ownerBillingGracePeriodEnd], + () => shouldUseDefaultExpensePolicyUtil(iouType, defaultExpensePolicy, amountOwed, userBillingGracePeriodEnds, ownerBillingGracePeriodEnd, currentUserAccountIDParam), + [iouType, defaultExpensePolicy, amountOwed, userBillingGracePeriodEnds, ownerBillingGracePeriodEnd, currentUserAccountIDParam], ); const mileageRate = DistanceRequestUtils.getRate({transaction: currentTransaction, policy: shouldUseDefaultExpensePolicy ? defaultExpensePolicy : policy}); diff --git a/tests/actions/IOU/MoneyRequestTest.ts b/tests/actions/IOU/MoneyRequestTest.ts index 2af279762b92..3ce85e1bd829 100644 --- a/tests/actions/IOU/MoneyRequestTest.ts +++ b/tests/actions/IOU/MoneyRequestTest.ts @@ -1608,7 +1608,7 @@ describe('MoneyRequest', () => { isPolicyExpenseChatEnabled: true, }; - expect(shouldUseDefaultExpensePolicy(CONST.IOU.TYPE.CREATE, policy, 0, undefined, undefined)).toBe(true); + expect(shouldUseDefaultExpensePolicy(CONST.IOU.TYPE.CREATE, policy, 0, undefined, undefined, policy.ownerAccountID)).toBe(true); }); it('should return false when iouType is not CREATE', () => { @@ -1618,9 +1618,9 @@ describe('MoneyRequest', () => { isPolicyExpenseChatEnabled: true, }; - expect(shouldUseDefaultExpensePolicy(CONST.IOU.TYPE.SUBMIT, policy, 0, undefined, undefined)).toBe(false); - expect(shouldUseDefaultExpensePolicy(CONST.IOU.TYPE.TRACK, policy, 0, undefined, undefined)).toBe(false); - expect(shouldUseDefaultExpensePolicy(CONST.IOU.TYPE.SPLIT, policy, 0, undefined, undefined)).toBe(false); + expect(shouldUseDefaultExpensePolicy(CONST.IOU.TYPE.SUBMIT, policy, 0, undefined, undefined, policy.ownerAccountID)).toBe(false); + expect(shouldUseDefaultExpensePolicy(CONST.IOU.TYPE.TRACK, policy, 0, undefined, undefined, policy.ownerAccountID)).toBe(false); + expect(shouldUseDefaultExpensePolicy(CONST.IOU.TYPE.SPLIT, policy, 0, undefined, undefined, policy.ownerAccountID)).toBe(false); }); it('should return false when policy is not a paid group policy', () => { @@ -1630,7 +1630,7 @@ describe('MoneyRequest', () => { isPolicyExpenseChatEnabled: true, }; - expect(shouldUseDefaultExpensePolicy(CONST.IOU.TYPE.CREATE, policy, 0, undefined, undefined)).toBe(false); + expect(shouldUseDefaultExpensePolicy(CONST.IOU.TYPE.CREATE, policy, 0, undefined, undefined, policy.ownerAccountID)).toBe(false); }); it('should return false when isPolicyExpenseChatEnabled is false', () => { @@ -1640,15 +1640,15 @@ describe('MoneyRequest', () => { isPolicyExpenseChatEnabled: false, }; - expect(shouldUseDefaultExpensePolicy(CONST.IOU.TYPE.CREATE, policy, 0, undefined, undefined)).toBe(false); + expect(shouldUseDefaultExpensePolicy(CONST.IOU.TYPE.CREATE, policy, 0, undefined, undefined, policy.ownerAccountID)).toBe(false); }); it('should return false when policy is undefined', () => { - expect(shouldUseDefaultExpensePolicy(CONST.IOU.TYPE.CREATE, undefined, 0, undefined, undefined)).toBe(false); + expect(shouldUseDefaultExpensePolicy(CONST.IOU.TYPE.CREATE, undefined, 0, undefined, undefined, currentUserAccountID)).toBe(false); }); it('should return false when policy is null', () => { - expect(shouldUseDefaultExpensePolicy(CONST.IOU.TYPE.CREATE, null, 0, undefined, undefined)).toBe(false); + expect(shouldUseDefaultExpensePolicy(CONST.IOU.TYPE.CREATE, null, 0, undefined, undefined, currentUserAccountID)).toBe(false); }); it('should handle amountOwed being undefined', () => { @@ -1658,7 +1658,7 @@ describe('MoneyRequest', () => { isPolicyExpenseChatEnabled: true, }; - expect(shouldUseDefaultExpensePolicy(CONST.IOU.TYPE.CREATE, policy, undefined, undefined, undefined)).toBe(true); + expect(shouldUseDefaultExpensePolicy(CONST.IOU.TYPE.CREATE, policy, undefined, undefined, undefined, policy.ownerAccountID)).toBe(true); }); it('should pass ownerBillingGracePeriodEnd through to shouldRestrictUserBillableActions', async () => { @@ -1673,7 +1673,7 @@ describe('MoneyRequest', () => { await Onyx.set(ONYXKEYS.SESSION, {accountID: TEST_USER_ACCOUNT_ID}); await Onyx.set(`${ONYXKEYS.COLLECTION.POLICY}${policy.id}`, policy); - expect(shouldUseDefaultExpensePolicy(CONST.IOU.TYPE.CREATE, policy, 100, undefined, pastDate)).toBe(false); + expect(shouldUseDefaultExpensePolicy(CONST.IOU.TYPE.CREATE, policy, 100, undefined, pastDate, TEST_USER_ACCOUNT_ID)).toBe(false); await Onyx.clear(); }); diff --git a/tests/actions/IOUTest/SplitTest.ts b/tests/actions/IOUTest/SplitTest.ts index 62ad0e84a896..802372e8dee7 100644 --- a/tests/actions/IOUTest/SplitTest.ts +++ b/tests/actions/IOUTest/SplitTest.ts @@ -4848,7 +4848,7 @@ describe('initSplitExpense', () => { reportID: '456', }; - initSplitExpense(transaction, undefined); + initSplitExpense(transaction, undefined, CONST.DEFAULT_NUMBER_ID); await waitForBatchedUpdates(); const draftTransaction = await getOnyxValue(`${ONYXKEYS.COLLECTION.SPLIT_TRANSACTION_DRAFT}${transaction.transactionID}`); @@ -4873,7 +4873,7 @@ describe('initSplitExpense', () => { }); it('should not initialize split expense for null transaction', async () => { const transaction: Transaction | undefined = undefined; - initSplitExpense(transaction, undefined); + initSplitExpense(transaction, undefined, CONST.DEFAULT_NUMBER_ID); await waitForBatchedUpdates(); expect(transaction).toBeFalsy(); @@ -4897,7 +4897,7 @@ describe('initSplitExpense', () => { reportID: '456', }; - initSplitExpense(transaction, undefined); + initSplitExpense(transaction, undefined, CONST.DEFAULT_NUMBER_ID); await waitForBatchedUpdates(); const draftTransaction = await getOnyxValue(`${ONYXKEYS.COLLECTION.SPLIT_TRANSACTION_DRAFT}${transaction.transactionID}`); @@ -4966,7 +4966,7 @@ describe('initSplitExpense', () => { reportID: '456', }; - initSplitExpense(transaction, policy); + initSplitExpense(transaction, policy, policy.ownerAccountID); await waitForBatchedUpdates(); const draftTransaction = await getOnyxValue(`${ONYXKEYS.COLLECTION.SPLIT_TRANSACTION_DRAFT}${transaction.transactionID}`); diff --git a/tests/unit/SubscriptionUtilsTest.ts b/tests/unit/SubscriptionUtilsTest.ts index 62d5de315e8c..0749ebae0721 100644 --- a/tests/unit/SubscriptionUtilsTest.ts +++ b/tests/unit/SubscriptionUtilsTest.ts @@ -326,7 +326,7 @@ describe('SubscriptionUtils', () => { }); it("should return false if the user isn't a workspace's owner or isn't a member of any past due billing workspace", () => { - expect(shouldRestrictUserBillableActions(undefined, undefined, undefined, undefined)).toBeFalsy(); + expect(shouldRestrictUserBillableActions(undefined, undefined, undefined, undefined, undefined)).toBeFalsy(); }); it('should return false if the user is a non-owner of a workspace that is not in the shared NVP collection', () => { @@ -345,6 +345,7 @@ describe('SubscriptionUtils', () => { }, }, undefined, + undefined, ), ).toBeFalsy(); }); @@ -365,6 +366,7 @@ describe('SubscriptionUtils', () => { }, }, undefined, + undefined, ), ).toBeFalsy(); }); @@ -385,6 +387,7 @@ describe('SubscriptionUtils', () => { }, }, undefined, + undefined, ), ).toBeTruthy(); }); @@ -586,7 +589,7 @@ describe('SubscriptionUtils', () => { }); it('should not restrict when policy is passed as undefined', () => { - expect(shouldRestrictUserBillableActions(undefined, getUnixTime(subDays(new Date(), 3)), undefined, 500)).toBeFalsy(); + expect(shouldRestrictUserBillableActions(undefined, getUnixTime(subDays(new Date(), 3)), undefined, 500, undefined)).toBeFalsy(); }); it('should restrict for non-owner when policy is passed directly and billing grace period is overdue', async () => { @@ -608,6 +611,7 @@ describe('SubscriptionUtils', () => { }, }, undefined, + undefined, ), ).toBeTruthy(); }); @@ -631,6 +635,7 @@ describe('SubscriptionUtils', () => { }, }, undefined, + undefined, ), ).toBeFalsy(); }); From 3658986893c3aa4c63f34cd40d172e8bd9e5b031 Mon Sep 17 00:00:00 2001 From: Hans Date: Thu, 14 May 2026 13:28:46 +0700 Subject: [PATCH 09/22] fix tests --- tests/unit/SubscriptionUtilsTest.ts | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/tests/unit/SubscriptionUtilsTest.ts b/tests/unit/SubscriptionUtilsTest.ts index 0749ebae0721..5ce2e6b5d62d 100644 --- a/tests/unit/SubscriptionUtilsTest.ts +++ b/tests/unit/SubscriptionUtilsTest.ts @@ -326,7 +326,7 @@ describe('SubscriptionUtils', () => { }); it("should return false if the user isn't a workspace's owner or isn't a member of any past due billing workspace", () => { - expect(shouldRestrictUserBillableActions(undefined, undefined, undefined, undefined, undefined)).toBeFalsy(); + expect(shouldRestrictUserBillableActions(undefined, undefined, undefined, undefined, CONST.DEFAULT_NUMBER_ID)).toBeFalsy(); }); it('should return false if the user is a non-owner of a workspace that is not in the shared NVP collection', () => { @@ -345,7 +345,7 @@ describe('SubscriptionUtils', () => { }, }, undefined, - undefined, + CONST.DEFAULT_NUMBER_ID, ), ).toBeFalsy(); }); @@ -366,7 +366,7 @@ describe('SubscriptionUtils', () => { }, }, undefined, - undefined, + CONST.DEFAULT_NUMBER_ID, ), ).toBeFalsy(); }); @@ -387,7 +387,7 @@ describe('SubscriptionUtils', () => { }, }, undefined, - undefined, + CONST.DEFAULT_NUMBER_ID, ), ).toBeTruthy(); }); @@ -589,7 +589,7 @@ describe('SubscriptionUtils', () => { }); it('should not restrict when policy is passed as undefined', () => { - expect(shouldRestrictUserBillableActions(undefined, getUnixTime(subDays(new Date(), 3)), undefined, 500, undefined)).toBeFalsy(); + expect(shouldRestrictUserBillableActions(undefined, getUnixTime(subDays(new Date(), 3)), undefined, 500, CONST.DEFAULT_NUMBER_ID)).toBeFalsy(); }); it('should restrict for non-owner when policy is passed directly and billing grace period is overdue', async () => { @@ -611,7 +611,7 @@ describe('SubscriptionUtils', () => { }, }, undefined, - undefined, + CONST.DEFAULT_NUMBER_ID, ), ).toBeTruthy(); }); @@ -635,7 +635,7 @@ describe('SubscriptionUtils', () => { }, }, undefined, - undefined, + CONST.DEFAULT_NUMBER_ID, ), ).toBeFalsy(); }); From 6ad20e881e6fd4ad8e487c5194f6ff80a2e163fd Mon Sep 17 00:00:00 2001 From: Hans Date: Thu, 14 May 2026 13:45:18 +0700 Subject: [PATCH 10/22] Fix lint after merging main --- src/pages/Search/EmptySearchView.tsx | 7 ++----- .../ReportActionCompose/AttachmentPickerWithMenuItems.tsx | 6 +++--- src/pages/iou/request/step/IOURequestStepConfirmation.tsx | 2 +- 3 files changed, 6 insertions(+), 9 deletions(-) diff --git a/src/pages/Search/EmptySearchView.tsx b/src/pages/Search/EmptySearchView.tsx index 3e957b916c8b..97b1f1d23cce 100644 --- a/src/pages/Search/EmptySearchView.tsx +++ b/src/pages/Search/EmptySearchView.tsx @@ -1,5 +1,4 @@ import {hasSeenTourSelector} from '@selectors/Onboarding'; -import {accountIDSelector} from '@selectors/Session'; import {validTransactionDraftIDsSelector} from '@selectors/TransactionDraft'; import React from 'react'; import type {ImageStyle, NativeScrollEvent, NativeSyntheticEvent, StyleProp, TextStyle, ViewStyle} from 'react-native'; @@ -134,10 +133,8 @@ function EmptySearchViewContent({ const {isBetaEnabled} = usePermissions(); const isASAPSubmitBetaEnabled = isBetaEnabled(CONST.BETAS.ASAP_SUBMIT); const [betas] = useOnyx(ONYXKEYS.BETAS); - const [accountID] = useOnyx(ONYXKEYS.SESSION, { - selector: accountIDSelector, - }); - const hasViolations = hasViolationsReportUtils(undefined, transactionViolations, accountID ?? CONST.DEFAULT_NUMBER_ID, ''); + const {accountID} = useCurrentUserPersonalDetails(); + const hasViolations = hasViolationsReportUtils(undefined, transactionViolations, accountID, ''); const [draftTransactionIDs] = useOnyx(ONYXKEYS.COLLECTION.TRANSACTION_DRAFT, {selector: validTransactionDraftIDsSelector}); const [userBillingGracePeriodEnds] = useOnyx(ONYXKEYS.COLLECTION.SHARED_NVP_PRIVATE_USER_BILLING_GRACE_PERIOD_END); const [ownerBillingGracePeriodEnd] = useOnyx(ONYXKEYS.NVP_PRIVATE_OWNER_BILLING_GRACE_PERIOD_END); diff --git a/src/pages/inbox/report/ReportActionCompose/AttachmentPickerWithMenuItems.tsx b/src/pages/inbox/report/ReportActionCompose/AttachmentPickerWithMenuItems.tsx index 120fdf89f811..a7f388424b6c 100644 --- a/src/pages/inbox/report/ReportActionCompose/AttachmentPickerWithMenuItems.tsx +++ b/src/pages/inbox/report/ReportActionCompose/AttachmentPickerWithMenuItems.tsx @@ -1,5 +1,4 @@ import {useIsFocused} from '@react-navigation/native'; -import {accountIDSelector} from '@selectors/Session'; import React, {useCallback, useEffect, useMemo, useState} from 'react'; import {View} from 'react-native'; import type {OnyxEntry} from 'react-native-onyx'; @@ -50,6 +49,7 @@ import {validTransactionDraftIDsSelector} from '@src/selectors/TransactionDraft' import type {AnchorPosition} from '@src/styles'; import type * as OnyxTypes from '@src/types/onyx'; import type {FileObject} from '@src/types/utils/Attachment'; +import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails'; type MoneyRequestOptions = Record< Exclude, @@ -172,10 +172,10 @@ function AttachmentPickerWithMenuItems({ const [betas] = useOnyx(ONYXKEYS.BETAS); const {isBetaEnabled} = usePermissions(); const isASAPSubmitBetaEnabled = isBetaEnabled(CONST.BETAS.ASAP_SUBMIT); - const [accountID] = useOnyx(ONYXKEYS.SESSION, {selector: accountIDSelector}); + const {accountID} = currentUserPersonalDetails; const [hasDismissedEmptyReportsConfirmation] = useOnyx(ONYXKEYS.NVP_EMPTY_REPORTS_CONFIRMATION_DISMISSED); const [userBillingGracePeriodEnds] = useOnyx(ONYXKEYS.COLLECTION.SHARED_NVP_PRIVATE_USER_BILLING_GRACE_PERIOD_END); - const hasViolations = hasViolationsReportUtils(undefined, transactionViolations, accountID ?? CONST.DEFAULT_NUMBER_ID, ''); + const hasViolations = hasViolationsReportUtils(undefined, transactionViolations, accountID, ''); const hasEmptyReport = useHasEmptyReportsForPolicy(report?.policyID); const shouldShowEmptyReportConfirmation = hasEmptyReport && hasDismissedEmptyReportsConfirmation !== true; diff --git a/src/pages/iou/request/step/IOURequestStepConfirmation.tsx b/src/pages/iou/request/step/IOURequestStepConfirmation.tsx index 85bf2a940419..d2bda52094e3 100644 --- a/src/pages/iou/request/step/IOURequestStepConfirmation.tsx +++ b/src/pages/iou/request/step/IOURequestStepConfirmation.tsx @@ -282,7 +282,7 @@ function IOURequestStepConfirmation({ const isGlobalCreateFlow = transaction?.isFromGlobalCreate ?? transaction?.isFromFloatingActionButton ?? iouType === CONST.IOU.TYPE.CREATE; if (!defaultParticipantsOptions.length && isGlobalCreateFlow) { - const canUseDefaultPolicy = shouldUseDefaultExpensePolicy(iouType, defaultExpensePolicy, amountOwed, userBillingGracePeriodEnds, ownerBillingGracePeriodEnd); + const canUseDefaultPolicy = shouldUseDefaultExpensePolicy(iouType, defaultExpensePolicy, amountOwed, userBillingGracePeriodEnds, ownerBillingGracePeriodEnd, currentUserPersonalDetails.accountID); if (canUseDefaultPolicy) { const shouldAutoReport = !!defaultExpensePolicy?.autoReporting || !!personalPolicy?.autoReporting; From a2249366cb2133a918032055b731b6e5dfb26eee Mon Sep 17 00:00:00 2001 From: Hans Date: Thu, 14 May 2026 14:03:37 +0700 Subject: [PATCH 11/22] update lint --- src/libs/actions/Search.ts | 2 +- .../Workspace/WorkspaceRestrictedActionPage.tsx | 14 +++++++------- .../AttachmentPickerWithMenuItems.tsx | 2 +- .../menuItems/QuickActionMenuItem.tsx | 12 +++++------- .../sidebar/FABPopoverContent/useScanActions.ts | 7 ++++--- .../iou/request/step/IOURequestEditReport.tsx | 13 +++++++------ .../request/step/IOURequestStepConfirmation.tsx | 9 ++++++++- .../hooks/useCreateReportRestrictionCheck.ts | 3 ++- tests/actions/IOU/MoneyRequestTest.ts | 14 +++++++------- tests/actions/IOUTest/SplitTest.ts | 2 +- 10 files changed, 43 insertions(+), 35 deletions(-) diff --git a/src/libs/actions/Search.ts b/src/libs/actions/Search.ts index 20059d76789c..613732d24969 100644 --- a/src/libs/actions/Search.ts +++ b/src/libs/actions/Search.ts @@ -114,7 +114,7 @@ type HandleActionButtonPressParams = { ownerBillingGracePeriodEnd: OnyxEntry; amountOwed: OnyxEntry; onUndelete?: () => void; - currentUserAccountID?: number; + currentUserAccountID: number; }; type BulkDeleteReportsParams = { diff --git a/src/pages/RestrictedAction/Workspace/WorkspaceRestrictedActionPage.tsx b/src/pages/RestrictedAction/Workspace/WorkspaceRestrictedActionPage.tsx index fb85aaea5c36..8e7b32f34f5c 100644 --- a/src/pages/RestrictedAction/Workspace/WorkspaceRestrictedActionPage.tsx +++ b/src/pages/RestrictedAction/Workspace/WorkspaceRestrictedActionPage.tsx @@ -12,12 +12,12 @@ import {isPolicyAdmin, isPolicyAuditor, isPolicyOwner, isPolicyUser} from '@libs import {shouldRestrictUserBillableActions} from '@libs/SubscriptionUtils'; import type {SkeletonSpanReasonAttributes} from '@libs/telemetry/useSkeletonSpan'; import NotFoundPage from '@pages/ErrorPage/NotFoundPage'; -import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import type SCREENS from '@src/SCREENS'; import WorkspaceAdminRestrictedAction from './WorkspaceAdminRestrictedAction'; import WorkspaceOwnerRestrictedAction from './WorkspaceOwnerRestrictedAction'; import WorkspaceUserRestrictedAction from './WorkspaceUserRestrictedAction'; +import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails'; type WorkspaceRestrictedActionPageProps = PlatformStackScreenProps; @@ -26,7 +26,7 @@ function WorkspaceRestrictedActionPage({ params: {policyID}, }, }: WorkspaceRestrictedActionPageProps) { - const [session] = useOnyx(ONYXKEYS.SESSION); + const {accountID, email} = useCurrentUserPersonalDetails(); const policy = usePolicy(policyID); const styles = useThemeStyles(); const [isLoadingSubscriptionData] = useOnyx(ONYXKEYS.IS_LOADING_SUBSCRIPTION_DATA); @@ -65,10 +65,10 @@ function WorkspaceRestrictedActionPage({ if (isLoadingSubscriptionData !== false) { return; } - if (!shouldRestrictUserBillableActions(policy, ownerBillingGracePeriodEnd, userBillingGracePeriods, amountOwed, session?.accountID)) { + if (!shouldRestrictUserBillableActions(policy, ownerBillingGracePeriodEnd, userBillingGracePeriods, amountOwed, accountID)) { Navigation.goBack(); } - }, [policy, isLoadingSubscriptionData, userBillingGracePeriods, ownerBillingGracePeriodEnd, amountOwed, session?.accountID]); + }, [policy, isLoadingSubscriptionData, userBillingGracePeriods, ownerBillingGracePeriodEnd, amountOwed, accountID]); // Show a loading indicator while waiting for fresh billing data from the server, // instead of flashing the restriction UI which may no longer apply. @@ -83,17 +83,17 @@ function WorkspaceRestrictedActionPage({ } // Workspace Owner - if (isPolicyOwner(policy, session?.accountID ?? CONST.DEFAULT_NUMBER_ID)) { + if (isPolicyOwner(policy, accountID)) { return ; } // Workspace Admin - if (isPolicyAdmin(policy, session?.email)) { + if (isPolicyAdmin(policy, email)) { return ; } // Workspace User or Auditor - if (isPolicyUser(policy, session?.email) || isPolicyAuditor(policy, session?.email)) { + if (isPolicyUser(policy, email) || isPolicyAuditor(policy, email)) { return ; } diff --git a/src/pages/inbox/report/ReportActionCompose/AttachmentPickerWithMenuItems.tsx b/src/pages/inbox/report/ReportActionCompose/AttachmentPickerWithMenuItems.tsx index a7f388424b6c..e3925ae6945a 100644 --- a/src/pages/inbox/report/ReportActionCompose/AttachmentPickerWithMenuItems.tsx +++ b/src/pages/inbox/report/ReportActionCompose/AttachmentPickerWithMenuItems.tsx @@ -11,6 +11,7 @@ import PopoverMenu from '@components/PopoverMenu'; import PressableWithFeedback from '@components/Pressable/PressableWithFeedback'; import Tooltip from '@components/Tooltip/PopoverAnchorTooltip'; import useCreateEmptyReportConfirmation from '@hooks/useCreateEmptyReportConfirmation'; +import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails'; import useEnvironment from '@hooks/useEnvironment'; import useHasEmptyReportsForPolicy from '@hooks/useHasEmptyReportsForPolicy'; import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset'; @@ -49,7 +50,6 @@ import {validTransactionDraftIDsSelector} from '@src/selectors/TransactionDraft' import type {AnchorPosition} from '@src/styles'; import type * as OnyxTypes from '@src/types/onyx'; import type {FileObject} from '@src/types/utils/Attachment'; -import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails'; type MoneyRequestOptions = Record< Exclude, diff --git a/src/pages/inbox/sidebar/FABPopoverContent/menuItems/QuickActionMenuItem.tsx b/src/pages/inbox/sidebar/FABPopoverContent/menuItems/QuickActionMenuItem.tsx index bfd33f61e2ec..f27c51828766 100644 --- a/src/pages/inbox/sidebar/FABPopoverContent/menuItems/QuickActionMenuItem.tsx +++ b/src/pages/inbox/sidebar/FABPopoverContent/menuItems/QuickActionMenuItem.tsx @@ -22,7 +22,6 @@ import FABFocusableMenuItem from '@pages/inbox/sidebar/FABPopoverContent/FABFocu import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; -import {sessionEmailAndAccountIDSelector} from '@src/selectors/Session'; import {validTransactionDraftIDsSelector} from '@src/selectors/TransactionDraft'; import type * as OnyxTypes from '@src/types/onyx'; import type {QuickActionName} from '@src/types/onyx/QuickAction'; @@ -38,20 +37,19 @@ type QuickActionMenuItemProps = { function QuickActionMenuItem({reportID}: QuickActionMenuItemProps) { const styles = useThemeStyles(); const {shouldUseNarrowLayout} = useResponsiveLayout(); + const currentUserPersonalDetails = useCurrentUserPersonalDetails(); const {translate, formatPhoneNumber} = useLocalize(); const icons = useMemoizedLazyExpensifyIcons(['CalendarSolid', 'ReceiptScan', 'Car', 'Task', 'Clock', 'MoneyCircle', 'Coins', 'Receipt', 'Cash', 'Transfer']); - const [session] = useOnyx(ONYXKEYS.SESSION, {selector: sessionEmailAndAccountIDSelector}); const [activePolicyID] = useOnyx(ONYXKEYS.NVP_ACTIVE_POLICY_ID); const [activePolicy] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY}${activePolicyID}`); const [draftTransactionIDs] = useOnyx(ONYXKEYS.COLLECTION.TRANSACTION_DRAFT, {selector: validTransactionDraftIDsSelector}); - const workspaceChatsSelector = (reports: OnyxCollection) => getWorkspaceChats(activePolicyID, [session?.accountID ?? CONST.DEFAULT_NUMBER_ID], reports); + const workspaceChatsSelector = (reports: OnyxCollection) => getWorkspaceChats(activePolicyID, [currentUserPersonalDetails.accountID], reports); const [policyChats = getEmptyArray()] = useOnyx(ONYXKEYS.COLLECTION.REPORT, {selector: workspaceChatsSelector}); const [quickAction] = useOnyx(ONYXKEYS.NVP_QUICK_ACTION_GLOBAL_CREATE); const [quickActionReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${quickAction?.chatReportID}`); const [personalDetails] = useOnyx(ONYXKEYS.PERSONAL_DETAILS_LIST); const [lastDistanceExpenseType] = useOnyx(ONYXKEYS.NVP_LAST_DISTANCE_EXPENSE_TYPE); const [allBetas] = useOnyx(ONYXKEYS.BETAS); - const currentUserPersonalDetails = useCurrentUserPersonalDetails(); const {isDelegateAccessRestricted} = useDelegateNoAccessState(); const {showDelegateNoAccessModal} = useDelegateNoAccessActions(); const isReportArchived = useReportIsArchived(quickActionReport?.reportID); @@ -84,7 +82,7 @@ function QuickActionMenuItem({reportID}: QuickActionMenuItemProps) { let quickActionAvatars: ReturnType = []; if (isValidReport) { const avatars = getIcons(quickActionReport, formatPhoneNumber, personalDetails, null, undefined, undefined, undefined, undefined, isReportArchived); - quickActionAvatars = avatars.length <= 1 || isPolicyExpenseChat(quickActionReport) ? avatars : avatars.filter((avatar) => avatar.id !== session?.accountID); + quickActionAvatars = avatars.length <= 1 || isPolicyExpenseChat(quickActionReport) ? avatars : avatars.filter((avatar) => avatar.id !== currentUserPersonalDetails.accountID); } else if (!isEmptyObject(policyChatForActivePolicy)) { quickActionAvatars = getIcons(policyChatForActivePolicy, formatPhoneNumber, personalDetails, null, undefined, undefined, undefined, undefined, isReportArchived); } @@ -118,7 +116,7 @@ function QuickActionMenuItem({reportID}: QuickActionMenuItemProps) { shouldRestrictAction && quickActionReportPolicyID && quickActionReportPolicy && - shouldRestrictUserBillableActions(quickActionReportPolicy, ownerBillingGracePeriodEnd, userBillingGracePeriodEnds, amountOwed, session?.accountID) + shouldRestrictUserBillableActions(quickActionReportPolicy, ownerBillingGracePeriodEnd, userBillingGracePeriodEnds, amountOwed, currentUserPersonalDetails.accountID) ) { Navigation.navigate(ROUTES.RESTRICTED_ACTION.getRoute(quickActionReportPolicyID)); return; @@ -197,7 +195,7 @@ function QuickActionMenuItem({reportID}: QuickActionMenuItemProps) { if ( policyChatForActivePolicyPolicyID && policyChatForActivePolicyPolicy && - shouldRestrictUserBillableActions(policyChatForActivePolicyPolicy, ownerBillingGracePeriodEnd, userBillingGracePeriodEnds, amountOwed, session?.accountID) + shouldRestrictUserBillableActions(policyChatForActivePolicyPolicy, ownerBillingGracePeriodEnd, userBillingGracePeriodEnds, amountOwed, currentUserPersonalDetails.accountID) ) { Navigation.navigate(ROUTES.RESTRICTED_ACTION.getRoute(policyChatForActivePolicyPolicyID)); return; diff --git a/src/pages/inbox/sidebar/FABPopoverContent/useScanActions.ts b/src/pages/inbox/sidebar/FABPopoverContent/useScanActions.ts index c50a7a9399fa..a1e2b0574f7a 100644 --- a/src/pages/inbox/sidebar/FABPopoverContent/useScanActions.ts +++ b/src/pages/inbox/sidebar/FABPopoverContent/useScanActions.ts @@ -16,13 +16,14 @@ import {validTransactionDraftIDsSelector} from '@src/selectors/TransactionDraft' import type * as OnyxTypes from '@src/types/onyx'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; import getEmptyArray from '@src/types/utils/getEmptyArray'; +import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails'; function useScanActions() { - const [session] = useOnyx(ONYXKEYS.SESSION, {selector: sessionEmailAndAccountIDSelector}); + const currentUserPersonalDetails = useCurrentUserPersonalDetails(); const [activePolicyID] = useOnyx(ONYXKEYS.NVP_ACTIVE_POLICY_ID); const [activePolicy] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY}${activePolicyID}`); const [draftTransactionIDs] = useOnyx(ONYXKEYS.COLLECTION.TRANSACTION_DRAFT, {selector: validTransactionDraftIDsSelector}); - const workspaceChatsSelector = (reports: OnyxCollection) => getWorkspaceChats(activePolicyID, [session?.accountID ?? CONST.DEFAULT_NUMBER_ID], reports); + const workspaceChatsSelector = (reports: OnyxCollection) => getWorkspaceChats(activePolicyID, [currentUserPersonalDetails.accountID], reports); const [policyChats = getEmptyArray()] = useOnyx(ONYXKEYS.COLLECTION.REPORT, {selector: workspaceChatsSelector}); const [userBillingGracePeriodEnds] = useOnyx(ONYXKEYS.COLLECTION.SHARED_NVP_PRIVATE_USER_BILLING_GRACE_PERIOD_END); @@ -47,7 +48,7 @@ function useScanActions() { const startQuickScan = () => { interceptAnonymousUser(() => { - if (policyChatPolicyID && shouldRestrictUserBillableActions(policyChatPolicy, ownerBillingGracePeriodEnd, userBillingGracePeriodEnds, amountOwed, session?.accountID)) { + if (policyChatPolicyID && shouldRestrictUserBillableActions(policyChatPolicy, ownerBillingGracePeriodEnd, userBillingGracePeriodEnds, amountOwed, currentUserPersonalDetails.accountID)) { Navigation.navigate(ROUTES.RESTRICTED_ACTION.getRoute(policyChatPolicyID)); return; } diff --git a/src/pages/iou/request/step/IOURequestEditReport.tsx b/src/pages/iou/request/step/IOURequestEditReport.tsx index 09a28958d9bc..899b031d13b3 100644 --- a/src/pages/iou/request/step/IOURequestEditReport.tsx +++ b/src/pages/iou/request/step/IOURequestEditReport.tsx @@ -23,6 +23,7 @@ import type {PersonalDetails, Report} from '@src/types/onyx'; import IOURequestEditReportCommon from './IOURequestEditReportCommon'; import withWritableReportOrNotFound from './withWritableReportOrNotFound'; import type {WithWritableReportOrNotFoundProps} from './withWritableReportOrNotFound'; +import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails'; type TransactionGroupListItem = ListItem & { /** reportID of the report */ @@ -41,7 +42,7 @@ function IOURequestEditReport({route}: IOURequestEditReportProps) { const [reportNextStep] = useOnyx(`${ONYXKEYS.COLLECTION.NEXT_STEP}${reportID}`); const {isBetaEnabled} = usePermissions(); const isASAPSubmitBetaEnabled = isBetaEnabled(CONST.BETAS.ASAP_SUBMIT); - const session = useSession(); + const currentUserPersonalDetails = useCurrentUserPersonalDetails(); const [personalPolicyID] = useOnyx(ONYXKEYS.PERSONAL_POLICY_ID); const [userBillingGracePeriodEnds] = useOnyx(ONYXKEYS.COLLECTION.SHARED_NVP_PRIVATE_USER_BILLING_GRACE_PERIOD_END); const [ownerBillingGracePeriodEnd] = useOnyx(ONYXKEYS.NVP_PRIVATE_OWNER_BILLING_GRACE_PERIOD_END); @@ -62,12 +63,12 @@ function IOURequestEditReport({route}: IOURequestEditReportProps) { // transactions, use the policy of their report (or the transaction's policy as fallback) so the // selected workspace is preserved. // For the current user's own non-per-diem expenses, fall back to undefined to let the default workspace apply. - const isOwnedByOther = selectedReport?.ownerAccountID !== session?.accountID; + const isOwnedByOther = selectedReport?.ownerAccountID !== currentUserPersonalDetails.accountID; const isOwnedByOtherOrHasPerDiem = isOwnedByOther || hasPerDiemTransactions; const targetExpensePolicyID = isOwnedByOtherOrHasPerDiem ? selectedReport?.policyID : undefined; const {policyForMovingExpensesID, shouldSelectPolicy} = usePolicyForMovingExpenses(hasPerDiemTransactions, undefined, targetExpensePolicyID); const [transactionViolations] = useOnyx(ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS); - const hasViolations = hasViolationsReportUtils(undefined, transactionViolations, session?.accountID ?? CONST.DEFAULT_NUMBER_ID, session?.email ?? ''); + const hasViolations = hasViolationsReportUtils(undefined, transactionViolations, currentUserPersonalDetails.accountID, currentUserPersonalDetails.email); const policyForMovingExpenses = policyForMovingExpensesID ? allPolicies?.[`${ONYXKEYS.COLLECTION.POLICY}${policyForMovingExpensesID}`] : undefined; const [allTransactions] = useOnyx(ONYXKEYS.COLLECTION.TRANSACTION); const [betas] = useOnyx(ONYXKEYS.BETAS); @@ -108,8 +109,8 @@ function IOURequestEditReport({route}: IOURequestEditReportProps) { changeTransactionsReport({ transactionIDs, isASAPSubmitBetaEnabled, - accountID: session?.accountID ?? CONST.DEFAULT_NUMBER_ID, - email: session?.email ?? '', + accountID: currentUserPersonalDetails.accountID, + email: currentUserPersonalDetails.email ?? '', policy: allPolicies?.[`${ONYXKEYS.COLLECTION.POLICY}${personalPolicyID}`], allTransactions, policyTagList, @@ -146,7 +147,7 @@ function IOURequestEditReport({route}: IOURequestEditReportProps) { const createReport = () => { const restrictionPolicy = hasPerDiemTransactions ? selectedReportPolicy : policyForMovingExpenses; - if (restrictionPolicy && shouldRestrictUserBillableActions(restrictionPolicy, ownerBillingGracePeriodEnd, userBillingGracePeriodEnds, amountOwed, session?.accountID)) { + if (restrictionPolicy && shouldRestrictUserBillableActions(restrictionPolicy, ownerBillingGracePeriodEnd, userBillingGracePeriodEnds, amountOwed, currentUserPersonalDetails.accountID)) { Navigation.navigate(ROUTES.RESTRICTED_ACTION.getRoute(restrictionPolicy.id)); return; } diff --git a/src/pages/iou/request/step/IOURequestStepConfirmation.tsx b/src/pages/iou/request/step/IOURequestStepConfirmation.tsx index d2bda52094e3..1c5ea480e901 100644 --- a/src/pages/iou/request/step/IOURequestStepConfirmation.tsx +++ b/src/pages/iou/request/step/IOURequestStepConfirmation.tsx @@ -282,7 +282,14 @@ function IOURequestStepConfirmation({ const isGlobalCreateFlow = transaction?.isFromGlobalCreate ?? transaction?.isFromFloatingActionButton ?? iouType === CONST.IOU.TYPE.CREATE; if (!defaultParticipantsOptions.length && isGlobalCreateFlow) { - const canUseDefaultPolicy = shouldUseDefaultExpensePolicy(iouType, defaultExpensePolicy, amountOwed, userBillingGracePeriodEnds, ownerBillingGracePeriodEnd, currentUserPersonalDetails.accountID); + const canUseDefaultPolicy = shouldUseDefaultExpensePolicy( + iouType, + defaultExpensePolicy, + amountOwed, + userBillingGracePeriodEnds, + ownerBillingGracePeriodEnd, + currentUserPersonalDetails.accountID, + ); if (canUseDefaultPolicy) { const shouldAutoReport = !!defaultExpensePolicy?.autoReporting || !!personalPolicy?.autoReporting; diff --git a/src/pages/iou/request/step/IOURequestStepReport/hooks/useCreateReportRestrictionCheck.ts b/src/pages/iou/request/step/IOURequestStepReport/hooks/useCreateReportRestrictionCheck.ts index c6ee88565824..321a4a493e0b 100644 --- a/src/pages/iou/request/step/IOURequestStepReport/hooks/useCreateReportRestrictionCheck.ts +++ b/src/pages/iou/request/step/IOURequestStepReport/hooks/useCreateReportRestrictionCheck.ts @@ -3,6 +3,7 @@ import useOnyx from '@hooks/useOnyx'; import {shouldRestrictUserBillableActions} from '@libs/SubscriptionUtils'; import ONYXKEYS from '@src/ONYXKEYS'; import type {Policy, Session} from '@src/types/onyx'; +import CONST from '@src/CONST'; /** * @param session — current user session; provides the accountID used by `shouldRestrictUserBillableActions`. @@ -17,7 +18,7 @@ function useCreateReportRestrictionCheck(session: OnyxEntry): (restrict if (!restrictionPolicy) { return false; } - return shouldRestrictUserBillableActions(restrictionPolicy, ownerBillingGracePeriodEnd, userBillingGracePeriodEnds, amountOwed, session?.accountID); + return shouldRestrictUserBillableActions(restrictionPolicy, ownerBillingGracePeriodEnd, userBillingGracePeriodEnds, amountOwed, session?.accountID ?? CONST.DEFAULT_NUMBER_ID); }; } diff --git a/tests/actions/IOU/MoneyRequestTest.ts b/tests/actions/IOU/MoneyRequestTest.ts index 3ce85e1bd829..f5d70045bc48 100644 --- a/tests/actions/IOU/MoneyRequestTest.ts +++ b/tests/actions/IOU/MoneyRequestTest.ts @@ -1608,7 +1608,7 @@ describe('MoneyRequest', () => { isPolicyExpenseChatEnabled: true, }; - expect(shouldUseDefaultExpensePolicy(CONST.IOU.TYPE.CREATE, policy, 0, undefined, undefined, policy.ownerAccountID)).toBe(true); + expect(shouldUseDefaultExpensePolicy(CONST.IOU.TYPE.CREATE, policy, 0, undefined, undefined, policy.ownerAccountID ?? CONST.DEFAULT_NUMBER_ID)).toBe(true); }); it('should return false when iouType is not CREATE', () => { @@ -1618,9 +1618,9 @@ describe('MoneyRequest', () => { isPolicyExpenseChatEnabled: true, }; - expect(shouldUseDefaultExpensePolicy(CONST.IOU.TYPE.SUBMIT, policy, 0, undefined, undefined, policy.ownerAccountID)).toBe(false); - expect(shouldUseDefaultExpensePolicy(CONST.IOU.TYPE.TRACK, policy, 0, undefined, undefined, policy.ownerAccountID)).toBe(false); - expect(shouldUseDefaultExpensePolicy(CONST.IOU.TYPE.SPLIT, policy, 0, undefined, undefined, policy.ownerAccountID)).toBe(false); + expect(shouldUseDefaultExpensePolicy(CONST.IOU.TYPE.SUBMIT, policy, 0, undefined, undefined, policy.ownerAccountID ?? CONST.DEFAULT_NUMBER_ID)).toBe(false); + expect(shouldUseDefaultExpensePolicy(CONST.IOU.TYPE.TRACK, policy, 0, undefined, undefined, policy.ownerAccountID ?? CONST.DEFAULT_NUMBER_ID)).toBe(false); + expect(shouldUseDefaultExpensePolicy(CONST.IOU.TYPE.SPLIT, policy, 0, undefined, undefined, policy.ownerAccountID ?? CONST.DEFAULT_NUMBER_ID)).toBe(false); }); it('should return false when policy is not a paid group policy', () => { @@ -1630,7 +1630,7 @@ describe('MoneyRequest', () => { isPolicyExpenseChatEnabled: true, }; - expect(shouldUseDefaultExpensePolicy(CONST.IOU.TYPE.CREATE, policy, 0, undefined, undefined, policy.ownerAccountID)).toBe(false); + expect(shouldUseDefaultExpensePolicy(CONST.IOU.TYPE.CREATE, policy, 0, undefined, undefined, policy.ownerAccountID ?? CONST.DEFAULT_NUMBER_ID)).toBe(false); }); it('should return false when isPolicyExpenseChatEnabled is false', () => { @@ -1640,7 +1640,7 @@ describe('MoneyRequest', () => { isPolicyExpenseChatEnabled: false, }; - expect(shouldUseDefaultExpensePolicy(CONST.IOU.TYPE.CREATE, policy, 0, undefined, undefined, policy.ownerAccountID)).toBe(false); + expect(shouldUseDefaultExpensePolicy(CONST.IOU.TYPE.CREATE, policy, 0, undefined, undefined, policy.ownerAccountID ?? CONST.DEFAULT_NUMBER_ID)).toBe(false); }); it('should return false when policy is undefined', () => { @@ -1658,7 +1658,7 @@ describe('MoneyRequest', () => { isPolicyExpenseChatEnabled: true, }; - expect(shouldUseDefaultExpensePolicy(CONST.IOU.TYPE.CREATE, policy, undefined, undefined, undefined, policy.ownerAccountID)).toBe(true); + expect(shouldUseDefaultExpensePolicy(CONST.IOU.TYPE.CREATE, policy, undefined, undefined, undefined, policy.ownerAccountID ?? CONST.DEFAULT_NUMBER_ID)).toBe(true); }); it('should pass ownerBillingGracePeriodEnd through to shouldRestrictUserBillableActions', async () => { diff --git a/tests/actions/IOUTest/SplitTest.ts b/tests/actions/IOUTest/SplitTest.ts index 802372e8dee7..b6014bc9a1d6 100644 --- a/tests/actions/IOUTest/SplitTest.ts +++ b/tests/actions/IOUTest/SplitTest.ts @@ -4966,7 +4966,7 @@ describe('initSplitExpense', () => { reportID: '456', }; - initSplitExpense(transaction, policy, policy.ownerAccountID); + initSplitExpense(transaction, policy, policy.ownerAccountID ?? CONST.DEFAULT_NUMBER_ID); await waitForBatchedUpdates(); const draftTransaction = await getOnyxValue(`${ONYXKEYS.COLLECTION.SPLIT_TRANSACTION_DRAFT}${transaction.transactionID}`); From d1b810c06c2f0e141cdae8a59f8ae3091b00ace8 Mon Sep 17 00:00:00 2001 From: Hans Date: Fri, 15 May 2026 09:52:50 +0700 Subject: [PATCH 12/22] fix linting --- src/libs/SubscriptionUtils.ts | 2 +- src/libs/actions/Search.ts | 2 +- .../iou/request/step/IOURequestEditReport.tsx | 15 +++++++++------ 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/src/libs/SubscriptionUtils.ts b/src/libs/SubscriptionUtils.ts index 37b750c94c3f..548df2e33c55 100644 --- a/src/libs/SubscriptionUtils.ts +++ b/src/libs/SubscriptionUtils.ts @@ -472,7 +472,7 @@ function shouldRestrictUserBillableActions( ownerBillingGracePeriodEnd: OnyxEntry, userBillingGracePeriodEnds: OnyxCollection, amountOwed: OnyxEntry, - currentUserAccountID: number, + currentUserAccountID: number | undefined, ): boolean { const currentDate = new Date(); diff --git a/src/libs/actions/Search.ts b/src/libs/actions/Search.ts index 613732d24969..20059d76789c 100644 --- a/src/libs/actions/Search.ts +++ b/src/libs/actions/Search.ts @@ -114,7 +114,7 @@ type HandleActionButtonPressParams = { ownerBillingGracePeriodEnd: OnyxEntry; amountOwed: OnyxEntry; onUndelete?: () => void; - currentUserAccountID: number; + currentUserAccountID?: number; }; type BulkDeleteReportsParams = { diff --git a/src/pages/iou/request/step/IOURequestEditReport.tsx b/src/pages/iou/request/step/IOURequestEditReport.tsx index 899b031d13b3..1b7b413181f4 100644 --- a/src/pages/iou/request/step/IOURequestEditReport.tsx +++ b/src/pages/iou/request/step/IOURequestEditReport.tsx @@ -1,9 +1,10 @@ import React, {useMemo} from 'react'; import type {OnyxEntry} from 'react-native-onyx'; -import {usePersonalDetails, useSession} from '@components/OnyxListItemProvider'; +import {usePersonalDetails} from '@components/OnyxListItemProvider'; import {useSearchActionsContext, useSearchStateContext} from '@components/Search/SearchContext'; import type {ListItem} from '@components/SelectionList/types'; import useConditionalCreateEmptyReportConfirmation from '@hooks/useConditionalCreateEmptyReportConfirmation'; +import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails'; import useHasPerDiemTransactions from '@hooks/useHasPerDiemTransactions'; import useOnyx from '@hooks/useOnyx'; import usePermissions from '@hooks/usePermissions'; @@ -23,7 +24,6 @@ import type {PersonalDetails, Report} from '@src/types/onyx'; import IOURequestEditReportCommon from './IOURequestEditReportCommon'; import withWritableReportOrNotFound from './withWritableReportOrNotFound'; import type {WithWritableReportOrNotFoundProps} from './withWritableReportOrNotFound'; -import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails'; type TransactionGroupListItem = ListItem & { /** reportID of the report */ @@ -68,7 +68,7 @@ function IOURequestEditReport({route}: IOURequestEditReportProps) { const targetExpensePolicyID = isOwnedByOtherOrHasPerDiem ? selectedReport?.policyID : undefined; const {policyForMovingExpensesID, shouldSelectPolicy} = usePolicyForMovingExpenses(hasPerDiemTransactions, undefined, targetExpensePolicyID); const [transactionViolations] = useOnyx(ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS); - const hasViolations = hasViolationsReportUtils(undefined, transactionViolations, currentUserPersonalDetails.accountID, currentUserPersonalDetails.email); + const hasViolations = hasViolationsReportUtils(undefined, transactionViolations, currentUserPersonalDetails.accountID ?? CONST.DEFAULT_NUMBER_ID, currentUserPersonalDetails.email ?? ''); const policyForMovingExpenses = policyForMovingExpensesID ? allPolicies?.[`${ONYXKEYS.COLLECTION.POLICY}${policyForMovingExpensesID}`] : undefined; const [allTransactions] = useOnyx(ONYXKEYS.COLLECTION.TRANSACTION); const [betas] = useOnyx(ONYXKEYS.BETAS); @@ -85,8 +85,8 @@ function IOURequestEditReport({route}: IOURequestEditReportProps) { changeTransactionsReport({ transactionIDs, isASAPSubmitBetaEnabled, - accountID: session?.accountID ?? CONST.DEFAULT_NUMBER_ID, - email: session?.email ?? '', + accountID: currentUserPersonalDetails.accountID ?? CONST.DEFAULT_NUMBER_ID, + email: currentUserPersonalDetails.email ?? '', newReport, policy: allPolicies?.[`${ONYXKEYS.COLLECTION.POLICY}${item.policyID}`], reportNextStep, @@ -147,7 +147,10 @@ function IOURequestEditReport({route}: IOURequestEditReportProps) { const createReport = () => { const restrictionPolicy = hasPerDiemTransactions ? selectedReportPolicy : policyForMovingExpenses; - if (restrictionPolicy && shouldRestrictUserBillableActions(restrictionPolicy, ownerBillingGracePeriodEnd, userBillingGracePeriodEnds, amountOwed, currentUserPersonalDetails.accountID)) { + if ( + restrictionPolicy && + shouldRestrictUserBillableActions(restrictionPolicy, ownerBillingGracePeriodEnd, userBillingGracePeriodEnds, amountOwed, currentUserPersonalDetails.accountID) + ) { Navigation.navigate(ROUTES.RESTRICTED_ACTION.getRoute(restrictionPolicy.id)); return; } From d5a57fc5b1f2723024b915beb7e5fb82aae01d60 Mon Sep 17 00:00:00 2001 From: Hans Date: Fri, 15 May 2026 09:57:34 +0700 Subject: [PATCH 13/22] update submodule --- Mobile-Expensify | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Mobile-Expensify b/Mobile-Expensify index daba35913c52..1898b9de1b4a 160000 --- a/Mobile-Expensify +++ b/Mobile-Expensify @@ -1 +1 @@ -Subproject commit daba35913c520280351924bcca6b59aaf2ff489f +Subproject commit 1898b9de1b4a81fb9f4b008013a082151bc77dde From fd0793501097440d359ed2ca9264e70edc3e7a35 Mon Sep 17 00:00:00 2001 From: Hans Date: Fri, 15 May 2026 10:10:34 +0700 Subject: [PATCH 14/22] lint and prettier --- .../Workspace/WorkspaceRestrictedActionPage.tsx | 2 +- .../FABPopoverContent/menuItems/QuickActionMenuItem.tsx | 8 +++++++- .../inbox/sidebar/FABPopoverContent/useScanActions.ts | 8 +++++--- .../hooks/useCreateReportRestrictionCheck.ts | 4 ++-- 4 files changed, 15 insertions(+), 7 deletions(-) diff --git a/src/pages/RestrictedAction/Workspace/WorkspaceRestrictedActionPage.tsx b/src/pages/RestrictedAction/Workspace/WorkspaceRestrictedActionPage.tsx index 8e7b32f34f5c..eb5850164790 100644 --- a/src/pages/RestrictedAction/Workspace/WorkspaceRestrictedActionPage.tsx +++ b/src/pages/RestrictedAction/Workspace/WorkspaceRestrictedActionPage.tsx @@ -1,5 +1,6 @@ import React, {useEffect, useRef} from 'react'; import FullScreenLoadingIndicator from '@components/FullscreenLoadingIndicator'; +import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails'; import useNetwork from '@hooks/useNetwork'; import useOnyx from '@hooks/useOnyx'; import usePolicy from '@hooks/usePolicy'; @@ -17,7 +18,6 @@ import type SCREENS from '@src/SCREENS'; import WorkspaceAdminRestrictedAction from './WorkspaceAdminRestrictedAction'; import WorkspaceOwnerRestrictedAction from './WorkspaceOwnerRestrictedAction'; import WorkspaceUserRestrictedAction from './WorkspaceUserRestrictedAction'; -import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails'; type WorkspaceRestrictedActionPageProps = PlatformStackScreenProps; diff --git a/src/pages/inbox/sidebar/FABPopoverContent/menuItems/QuickActionMenuItem.tsx b/src/pages/inbox/sidebar/FABPopoverContent/menuItems/QuickActionMenuItem.tsx index f27c51828766..a7d7ae451132 100644 --- a/src/pages/inbox/sidebar/FABPopoverContent/menuItems/QuickActionMenuItem.tsx +++ b/src/pages/inbox/sidebar/FABPopoverContent/menuItems/QuickActionMenuItem.tsx @@ -195,7 +195,13 @@ function QuickActionMenuItem({reportID}: QuickActionMenuItemProps) { if ( policyChatForActivePolicyPolicyID && policyChatForActivePolicyPolicy && - shouldRestrictUserBillableActions(policyChatForActivePolicyPolicy, ownerBillingGracePeriodEnd, userBillingGracePeriodEnds, amountOwed, currentUserPersonalDetails.accountID) + shouldRestrictUserBillableActions( + policyChatForActivePolicyPolicy, + ownerBillingGracePeriodEnd, + userBillingGracePeriodEnds, + amountOwed, + currentUserPersonalDetails.accountID, + ) ) { Navigation.navigate(ROUTES.RESTRICTED_ACTION.getRoute(policyChatForActivePolicyPolicyID)); return; diff --git a/src/pages/inbox/sidebar/FABPopoverContent/useScanActions.ts b/src/pages/inbox/sidebar/FABPopoverContent/useScanActions.ts index a1e2b0574f7a..d96b42471d1f 100644 --- a/src/pages/inbox/sidebar/FABPopoverContent/useScanActions.ts +++ b/src/pages/inbox/sidebar/FABPopoverContent/useScanActions.ts @@ -1,5 +1,6 @@ import {useState} from 'react'; import type {OnyxCollection} from 'react-native-onyx'; +import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails'; import useOnyx from '@hooks/useOnyx'; import {startMoneyRequest} from '@libs/actions/IOU/MoneyRequest'; import getNonEmptyStringOnyxID from '@libs/getNonEmptyStringOnyxID'; @@ -11,12 +12,10 @@ import Tab from '@userActions/Tab'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; -import {sessionEmailAndAccountIDSelector} from '@src/selectors/Session'; import {validTransactionDraftIDsSelector} from '@src/selectors/TransactionDraft'; import type * as OnyxTypes from '@src/types/onyx'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; import getEmptyArray from '@src/types/utils/getEmptyArray'; -import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails'; function useScanActions() { const currentUserPersonalDetails = useCurrentUserPersonalDetails(); @@ -48,7 +47,10 @@ function useScanActions() { const startQuickScan = () => { interceptAnonymousUser(() => { - if (policyChatPolicyID && shouldRestrictUserBillableActions(policyChatPolicy, ownerBillingGracePeriodEnd, userBillingGracePeriodEnds, amountOwed, currentUserPersonalDetails.accountID)) { + if ( + policyChatPolicyID && + shouldRestrictUserBillableActions(policyChatPolicy, ownerBillingGracePeriodEnd, userBillingGracePeriodEnds, amountOwed, currentUserPersonalDetails.accountID) + ) { Navigation.navigate(ROUTES.RESTRICTED_ACTION.getRoute(policyChatPolicyID)); return; } diff --git a/src/pages/iou/request/step/IOURequestStepReport/hooks/useCreateReportRestrictionCheck.ts b/src/pages/iou/request/step/IOURequestStepReport/hooks/useCreateReportRestrictionCheck.ts index 321a4a493e0b..a356e89a01e4 100644 --- a/src/pages/iou/request/step/IOURequestStepReport/hooks/useCreateReportRestrictionCheck.ts +++ b/src/pages/iou/request/step/IOURequestStepReport/hooks/useCreateReportRestrictionCheck.ts @@ -1,9 +1,9 @@ import type {OnyxEntry} from 'react-native-onyx'; import useOnyx from '@hooks/useOnyx'; import {shouldRestrictUserBillableActions} from '@libs/SubscriptionUtils'; +import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import type {Policy, Session} from '@src/types/onyx'; -import CONST from '@src/CONST'; /** * @param session — current user session; provides the accountID used by `shouldRestrictUserBillableActions`. @@ -18,7 +18,7 @@ function useCreateReportRestrictionCheck(session: OnyxEntry): (restrict if (!restrictionPolicy) { return false; } - return shouldRestrictUserBillableActions(restrictionPolicy, ownerBillingGracePeriodEnd, userBillingGracePeriodEnds, amountOwed, session?.accountID ?? CONST.DEFAULT_NUMBER_ID); + return shouldRestrictUserBillableActions(restrictionPolicy, ownerBillingGracePeriodEnd, userBillingGracePeriodEnds, amountOwed, session?.accountID ?? CONST.DEFAULT_NUMBER_ID); }; } From 46c5a24fd6d87bfb96da8e4ceeaa61c31d7b5dbf Mon Sep 17 00:00:00 2001 From: Hans Date: Fri, 15 May 2026 10:24:04 +0700 Subject: [PATCH 15/22] eslint --- .../report/ReportActionCompose/AttachmentPickerWithMenuItems.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/pages/inbox/report/ReportActionCompose/AttachmentPickerWithMenuItems.tsx b/src/pages/inbox/report/ReportActionCompose/AttachmentPickerWithMenuItems.tsx index e3925ae6945a..33a402ccd07b 100644 --- a/src/pages/inbox/report/ReportActionCompose/AttachmentPickerWithMenuItems.tsx +++ b/src/pages/inbox/report/ReportActionCompose/AttachmentPickerWithMenuItems.tsx @@ -11,7 +11,6 @@ import PopoverMenu from '@components/PopoverMenu'; import PressableWithFeedback from '@components/Pressable/PressableWithFeedback'; import Tooltip from '@components/Tooltip/PopoverAnchorTooltip'; import useCreateEmptyReportConfirmation from '@hooks/useCreateEmptyReportConfirmation'; -import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails'; import useEnvironment from '@hooks/useEnvironment'; import useHasEmptyReportsForPolicy from '@hooks/useHasEmptyReportsForPolicy'; import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset'; From 61975c4ca02a0d9b69b43d1e0c7c8829eb733a98 Mon Sep 17 00:00:00 2001 From: Hans Date: Tue, 19 May 2026 21:38:38 +0700 Subject: [PATCH 16/22] Update submodule version --- Mobile-Expensify | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Mobile-Expensify b/Mobile-Expensify index 1898b9de1b4a..d67ad9012f48 160000 --- a/Mobile-Expensify +++ b/Mobile-Expensify @@ -1 +1 @@ -Subproject commit 1898b9de1b4a81fb9f4b008013a082151bc77dde +Subproject commit d67ad9012f48a7cbe627fdc9314281ca15c2a3b1 From 90d18f0f23360756e5ae76729ee07dcc59855285 Mon Sep 17 00:00:00 2001 From: Hans Date: Thu, 21 May 2026 09:49:57 +0700 Subject: [PATCH 17/22] update the usages --- src/components/MoneyRequestHeaderSecondaryActions.tsx | 2 +- src/hooks/useExpenseActions.ts | 4 ++-- src/hooks/useSearchBulkActions.ts | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/components/MoneyRequestHeaderSecondaryActions.tsx b/src/components/MoneyRequestHeaderSecondaryActions.tsx index c11a32947f4b..70b0d154c111 100644 --- a/src/components/MoneyRequestHeaderSecondaryActions.tsx +++ b/src/components/MoneyRequestHeaderSecondaryActions.tsx @@ -359,7 +359,7 @@ function MoneyRequestHeaderSecondaryActions({reportID, onBackButtonPress}: Money iconFill: isDuplicateActive ? undefined : theme.icon, value: CONST.REPORT.TRANSACTION_SECONDARY_ACTIONS.DUPLICATE, onSelected: () => { - if (defaultExpensePolicy && shouldRestrictUserBillableActions(defaultExpensePolicy, ownerBillingGracePeriodEnd, userBillingGracePeriodEnds, amountOwed)) { + if (defaultExpensePolicy && shouldRestrictUserBillableActions(defaultExpensePolicy, ownerBillingGracePeriodEnd, userBillingGracePeriodEnds, amountOwed, accountID)) { dropdownMenuRef.current?.setIsMenuVisible(false); Navigation.navigate(ROUTES.RESTRICTED_ACTION.getRoute(defaultExpensePolicy.id)); return; diff --git a/src/hooks/useExpenseActions.ts b/src/hooks/useExpenseActions.ts index cfd1f2bc2585..41dc0152ed52 100644 --- a/src/hooks/useExpenseActions.ts +++ b/src/hooks/useExpenseActions.ts @@ -322,7 +322,7 @@ function useExpenseActions({reportID, isReportInSearch = false, backTo, onDuplic iconFill: isDuplicateActive ? undefined : theme.icon, value: CONST.REPORT.SECONDARY_ACTIONS.DUPLICATE_EXPENSE, onSelected: () => { - if (defaultExpensePolicy && shouldRestrictUserBillableActions(defaultExpensePolicy, ownerBillingGracePeriodEnd, userBillingGracePeriodEnds, amountOwed)) { + if (defaultExpensePolicy && shouldRestrictUserBillableActions(defaultExpensePolicy, ownerBillingGracePeriodEnd, userBillingGracePeriodEnds, amountOwed, accountID)) { onDuplicateReset?.(); Navigation.navigate(ROUTES.RESTRICTED_ACTION.getRoute(defaultExpensePolicy.id)); return; @@ -383,7 +383,7 @@ function useExpenseActions({reportID, isReportInSearch = false, backTo, onDuplic const isSourcePolicyValid = !!policy && isPolicyAccessible(policy, currentUserLogin ?? ''); const targetPolicyForDuplicate = isSourcePolicyValid ? policy : defaultExpensePolicy; - if (targetPolicyForDuplicate && shouldRestrictUserBillableActions(targetPolicyForDuplicate, ownerBillingGracePeriodEnd, userBillingGracePeriodEnds, amountOwed)) { + if (targetPolicyForDuplicate && shouldRestrictUserBillableActions(targetPolicyForDuplicate, ownerBillingGracePeriodEnd, userBillingGracePeriodEnds, amountOwed, accountID)) { onDuplicateReset?.(); Navigation.navigate(ROUTES.RESTRICTED_ACTION.getRoute(targetPolicyForDuplicate.id)); return; diff --git a/src/hooks/useSearchBulkActions.ts b/src/hooks/useSearchBulkActions.ts index 2c2ab8746f55..27e775e55ade 100644 --- a/src/hooks/useSearchBulkActions.ts +++ b/src/hooks/useSearchBulkActions.ts @@ -1135,7 +1135,7 @@ function useSearchBulkActions({queryJSON}: UseSearchBulkActionsParams) { value: CONST.SEARCH.BULK_ACTION_TYPES.DUPLICATE, shouldCloseModalOnSelect: true, onSelected: () => { - if (defaultExpensePolicy && shouldRestrictUserBillableActions(defaultExpensePolicy, ownerBillingGracePeriodEnd, userBillingGracePeriodEnds, amountOwed)) { + if (defaultExpensePolicy && shouldRestrictUserBillableActions(defaultExpensePolicy, ownerBillingGracePeriodEnd, userBillingGracePeriodEnds, amountOwed, accountID)) { Navigation.navigate(ROUTES.RESTRICTED_ACTION.getRoute(defaultExpensePolicy.id)); return; } @@ -1484,7 +1484,7 @@ function useSearchBulkActions({queryJSON}: UseSearchBulkActionsParams) { value: CONST.SEARCH.BULK_ACTION_TYPES.DUPLICATE, shouldCloseModalOnSelect: true, onSelected: () => { - if (defaultExpensePolicy && shouldRestrictUserBillableActions(defaultExpensePolicy, ownerBillingGracePeriodEnd, userBillingGracePeriodEnds, amountOwed)) { + if (defaultExpensePolicy && shouldRestrictUserBillableActions(defaultExpensePolicy, ownerBillingGracePeriodEnd, userBillingGracePeriodEnds, amountOwed, accountID)) { Navigation.navigate(ROUTES.RESTRICTED_ACTION.getRoute(defaultExpensePolicy.id)); return; } From 533162d346e956c98ba2f01902496218af951d5c Mon Sep 17 00:00:00 2001 From: Hans Date: Sun, 24 May 2026 22:09:56 +0700 Subject: [PATCH 18/22] complete Part 8 --- .../MoneyRequestHeaderSecondaryActions.tsx | 4 ++-- .../MoneyRequestReportTransactionList.tsx | 14 +----------- .../ReportPreviewActionButton.tsx | 1 - .../ReportActionItem/MoneyRequestView.tsx | 2 +- src/pages/AddExistingExpense.tsx | 5 +---- .../WorkspaceRestrictedActionPage.tsx | 14 ++++++------ src/pages/Search/EmptySearchView.tsx | 7 ++++-- .../AttachmentPickerWithMenuItems.tsx | 5 +++-- .../menuItems/QuickActionMenuItem.tsx | 18 ++++++--------- .../FABPopoverContent/useScanActions.ts | 11 ++++------ .../iou/request/step/IOURequestEditReport.tsx | 22 ++++++++----------- .../iou/request/step/IOURequestStepAmount.tsx | 2 +- .../step/IOURequestStepConfirmation.tsx | 9 +------- .../index.native.tsx | 9 +------- .../step/IOURequestStepDistanceManual.tsx | 9 +------- .../step/IOURequestStepDistanceOdometer.tsx | 4 ++-- .../iou/request/step/IOURequestStepHours.tsx | 2 +- 17 files changed, 47 insertions(+), 91 deletions(-) diff --git a/src/components/MoneyRequestHeaderSecondaryActions.tsx b/src/components/MoneyRequestHeaderSecondaryActions.tsx index 01f87378e41c..376a617e5b2d 100644 --- a/src/components/MoneyRequestHeaderSecondaryActions.tsx +++ b/src/components/MoneyRequestHeaderSecondaryActions.tsx @@ -336,7 +336,7 @@ function MoneyRequestHeaderSecondaryActions({reportID, onBackButtonPress}: Money icon: expensifyIcons.ArrowSplit, value: CONST.REPORT.TRANSACTION_SECONDARY_ACTIONS.SPLIT, onSelected: () => { - initSplitExpense(transaction, policy, accountID); + initSplitExpense(transaction, policy); }, }, [CONST.REPORT.TRANSACTION_SECONDARY_ACTIONS.MERGE]: { @@ -357,7 +357,7 @@ function MoneyRequestHeaderSecondaryActions({reportID, onBackButtonPress}: Money iconFill: isDuplicateActive ? undefined : theme.icon, value: CONST.REPORT.TRANSACTION_SECONDARY_ACTIONS.DUPLICATE, onSelected: () => { - if (defaultExpensePolicy && shouldRestrictUserBillableActions(defaultExpensePolicy, ownerBillingGracePeriodEnd, userBillingGracePeriodEnds, amountOwed, accountID)) { + if (defaultExpensePolicy && shouldRestrictUserBillableActions(defaultExpensePolicy, ownerBillingGracePeriodEnd, userBillingGracePeriodEnds, amountOwed)) { dropdownMenuRef.current?.setIsMenuVisible(false); Navigation.navigate(ROUTES.RESTRICTED_ACTION.getRoute(defaultExpensePolicy.id)); return; diff --git a/src/components/MoneyRequestReportView/MoneyRequestReportTransactionList.tsx b/src/components/MoneyRequestReportView/MoneyRequestReportTransactionList.tsx index 5b4df0746e29..42b6cc141d14 100644 --- a/src/components/MoneyRequestReportView/MoneyRequestReportTransactionList.tsx +++ b/src/components/MoneyRequestReportView/MoneyRequestReportTransactionList.tsx @@ -198,20 +198,8 @@ function MoneyRequestReportTransactionList({ amountOwed, ownerBillingGracePeriodEnd, lastDistanceExpenseType, - currentUserAccountID: currentUserDetails?.accountID, }), - [ - translate, - expensifyIcons, - report?.reportID, - policy, - userBillingGracePeriodEnds, - amountOwed, - lastDistanceExpenseType, - ownerBillingGracePeriodEnd, - draftTransactionIDs, - currentUserDetails?.accountID, - ], + [translate, expensifyIcons, report?.reportID, policy, userBillingGracePeriodEnds, amountOwed, lastDistanceExpenseType, ownerBillingGracePeriodEnd, draftTransactionIDs], ); const hasPendingAction = useMemo(() => { diff --git a/src/components/ReportActionItem/MoneyRequestReportPreview/ReportPreviewActionButton.tsx b/src/components/ReportActionItem/MoneyRequestReportPreview/ReportPreviewActionButton.tsx index 6bc93cac0698..d95b5b8a7269 100644 --- a/src/components/ReportActionItem/MoneyRequestReportPreview/ReportPreviewActionButton.tsx +++ b/src/components/ReportActionItem/MoneyRequestReportPreview/ReportPreviewActionButton.tsx @@ -217,7 +217,6 @@ function ReportPreviewActionButton({ iouRequestBackToReport: chatReportID, unreportedExpenseBackToReport: iouReport?.parentReportID, lastDistanceExpenseType, - currentUserAccountID: currentUserDetails.accountID, })} isSplitButton={false} anchorAlignment={{ diff --git a/src/components/ReportActionItem/MoneyRequestView.tsx b/src/components/ReportActionItem/MoneyRequestView.tsx index afdc2882387d..0b5153099fb7 100644 --- a/src/components/ReportActionItem/MoneyRequestView.tsx +++ b/src/components/ReportActionItem/MoneyRequestView.tsx @@ -954,7 +954,7 @@ function MoneyRequestView({ } if (shouldShowSplitIndicator && isSplitAvailable) { - initSplitExpense(transaction, policy, currentUserAccountIDParam); + initSplitExpense(transaction, policy); return; } diff --git a/src/pages/AddExistingExpense.tsx b/src/pages/AddExistingExpense.tsx index 462d9a3f8663..ac734b1d3aab 100644 --- a/src/pages/AddExistingExpense.tsx +++ b/src/pages/AddExistingExpense.tsx @@ -424,10 +424,7 @@ function AddExistingExpense({route}: AddExistingExpensePageType) { { buttonText: translate('iou.createExpense'), buttonAction: () => { - if ( - report?.policyID && - shouldRestrictUserBillableActions(policy, ownerBillingGracePeriodEnd, userBillingGracePeriodEnds, amountOwed, currentUserAccountID) - ) { + if (report?.policyID && shouldRestrictUserBillableActions(policy, ownerBillingGracePeriodEnd, userBillingGracePeriodEnds, amountOwed)) { Navigation.navigate(ROUTES.RESTRICTED_ACTION.getRoute(report.policyID)); return; } diff --git a/src/pages/RestrictedAction/Workspace/WorkspaceRestrictedActionPage.tsx b/src/pages/RestrictedAction/Workspace/WorkspaceRestrictedActionPage.tsx index eb5850164790..fb85aaea5c36 100644 --- a/src/pages/RestrictedAction/Workspace/WorkspaceRestrictedActionPage.tsx +++ b/src/pages/RestrictedAction/Workspace/WorkspaceRestrictedActionPage.tsx @@ -1,6 +1,5 @@ import React, {useEffect, useRef} from 'react'; import FullScreenLoadingIndicator from '@components/FullscreenLoadingIndicator'; -import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails'; import useNetwork from '@hooks/useNetwork'; import useOnyx from '@hooks/useOnyx'; import usePolicy from '@hooks/usePolicy'; @@ -13,6 +12,7 @@ import {isPolicyAdmin, isPolicyAuditor, isPolicyOwner, isPolicyUser} from '@libs import {shouldRestrictUserBillableActions} from '@libs/SubscriptionUtils'; import type {SkeletonSpanReasonAttributes} from '@libs/telemetry/useSkeletonSpan'; import NotFoundPage from '@pages/ErrorPage/NotFoundPage'; +import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import type SCREENS from '@src/SCREENS'; import WorkspaceAdminRestrictedAction from './WorkspaceAdminRestrictedAction'; @@ -26,7 +26,7 @@ function WorkspaceRestrictedActionPage({ params: {policyID}, }, }: WorkspaceRestrictedActionPageProps) { - const {accountID, email} = useCurrentUserPersonalDetails(); + const [session] = useOnyx(ONYXKEYS.SESSION); const policy = usePolicy(policyID); const styles = useThemeStyles(); const [isLoadingSubscriptionData] = useOnyx(ONYXKEYS.IS_LOADING_SUBSCRIPTION_DATA); @@ -65,10 +65,10 @@ function WorkspaceRestrictedActionPage({ if (isLoadingSubscriptionData !== false) { return; } - if (!shouldRestrictUserBillableActions(policy, ownerBillingGracePeriodEnd, userBillingGracePeriods, amountOwed, accountID)) { + if (!shouldRestrictUserBillableActions(policy, ownerBillingGracePeriodEnd, userBillingGracePeriods, amountOwed, session?.accountID)) { Navigation.goBack(); } - }, [policy, isLoadingSubscriptionData, userBillingGracePeriods, ownerBillingGracePeriodEnd, amountOwed, accountID]); + }, [policy, isLoadingSubscriptionData, userBillingGracePeriods, ownerBillingGracePeriodEnd, amountOwed, session?.accountID]); // Show a loading indicator while waiting for fresh billing data from the server, // instead of flashing the restriction UI which may no longer apply. @@ -83,17 +83,17 @@ function WorkspaceRestrictedActionPage({ } // Workspace Owner - if (isPolicyOwner(policy, accountID)) { + if (isPolicyOwner(policy, session?.accountID ?? CONST.DEFAULT_NUMBER_ID)) { return ; } // Workspace Admin - if (isPolicyAdmin(policy, email)) { + if (isPolicyAdmin(policy, session?.email)) { return ; } // Workspace User or Auditor - if (isPolicyUser(policy, email) || isPolicyAuditor(policy, email)) { + if (isPolicyUser(policy, session?.email) || isPolicyAuditor(policy, session?.email)) { return ; } diff --git a/src/pages/Search/EmptySearchView.tsx b/src/pages/Search/EmptySearchView.tsx index d7670cd30750..3639cb1dbb7c 100644 --- a/src/pages/Search/EmptySearchView.tsx +++ b/src/pages/Search/EmptySearchView.tsx @@ -1,4 +1,5 @@ import {hasSeenTourSelector} from '@selectors/Onboarding'; +import {accountIDSelector} from '@selectors/Session'; import {validTransactionDraftIDsSelector} from '@selectors/TransactionDraft'; import React from 'react'; import type {ImageStyle, NativeScrollEvent, NativeSyntheticEvent, StyleProp, TextStyle, ViewStyle} from 'react-native'; @@ -131,8 +132,10 @@ function EmptySearchViewContent({ const {isBetaEnabled} = usePermissions(); const isASAPSubmitBetaEnabled = isBetaEnabled(CONST.BETAS.ASAP_SUBMIT); const [betas] = useOnyx(ONYXKEYS.BETAS); - const {accountID} = useCurrentUserPersonalDetails(); - const hasViolations = hasViolationsReportUtils(undefined, transactionViolations, accountID, ''); + const [accountID] = useOnyx(ONYXKEYS.SESSION, { + selector: accountIDSelector, + }); + const hasViolations = hasViolationsReportUtils(undefined, transactionViolations, accountID ?? CONST.DEFAULT_NUMBER_ID, ''); const [draftTransactionIDs] = useOnyx(ONYXKEYS.COLLECTION.TRANSACTION_DRAFT, {selector: validTransactionDraftIDsSelector}); const [hasTransactions] = useOnyx(ONYXKEYS.COLLECTION.TRANSACTION, { selector: hasTransactionsSelector, diff --git a/src/pages/inbox/report/ReportActionCompose/AttachmentPickerWithMenuItems.tsx b/src/pages/inbox/report/ReportActionCompose/AttachmentPickerWithMenuItems.tsx index 0c0bfb1416e7..dc22d3ec4b2f 100644 --- a/src/pages/inbox/report/ReportActionCompose/AttachmentPickerWithMenuItems.tsx +++ b/src/pages/inbox/report/ReportActionCompose/AttachmentPickerWithMenuItems.tsx @@ -1,4 +1,5 @@ import {useIsFocused} from '@react-navigation/native'; +import {accountIDSelector} from '@selectors/Session'; import React, {useCallback, useEffect, useMemo, useState} from 'react'; import {View} from 'react-native'; import type {OnyxEntry} from 'react-native-onyx'; @@ -175,9 +176,9 @@ function AttachmentPickerWithMenuItems({ const [betas] = useOnyx(ONYXKEYS.BETAS); const {isBetaEnabled} = usePermissions(); const isASAPSubmitBetaEnabled = isBetaEnabled(CONST.BETAS.ASAP_SUBMIT); - const {accountID} = currentUserPersonalDetails; + const [accountID] = useOnyx(ONYXKEYS.SESSION, {selector: accountIDSelector}); const [userBillingGracePeriodEnds] = useOnyx(ONYXKEYS.COLLECTION.SHARED_NVP_PRIVATE_USER_BILLING_GRACE_PERIOD_END); - const hasViolations = hasViolationsReportUtils(undefined, transactionViolations, accountID, ''); + const hasViolations = hasViolationsReportUtils(undefined, transactionViolations, accountID ?? CONST.DEFAULT_NUMBER_ID, ''); const shouldShowEmptyReportConfirmation = useShouldShowEmptyReportConfirmation(report?.policyID); const selectOption = useCallback( diff --git a/src/pages/inbox/sidebar/FABPopoverContent/menuItems/QuickActionMenuItem.tsx b/src/pages/inbox/sidebar/FABPopoverContent/menuItems/QuickActionMenuItem.tsx index a7d7ae451132..bfd33f61e2ec 100644 --- a/src/pages/inbox/sidebar/FABPopoverContent/menuItems/QuickActionMenuItem.tsx +++ b/src/pages/inbox/sidebar/FABPopoverContent/menuItems/QuickActionMenuItem.tsx @@ -22,6 +22,7 @@ import FABFocusableMenuItem from '@pages/inbox/sidebar/FABPopoverContent/FABFocu import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; +import {sessionEmailAndAccountIDSelector} from '@src/selectors/Session'; import {validTransactionDraftIDsSelector} from '@src/selectors/TransactionDraft'; import type * as OnyxTypes from '@src/types/onyx'; import type {QuickActionName} from '@src/types/onyx/QuickAction'; @@ -37,19 +38,20 @@ type QuickActionMenuItemProps = { function QuickActionMenuItem({reportID}: QuickActionMenuItemProps) { const styles = useThemeStyles(); const {shouldUseNarrowLayout} = useResponsiveLayout(); - const currentUserPersonalDetails = useCurrentUserPersonalDetails(); const {translate, formatPhoneNumber} = useLocalize(); const icons = useMemoizedLazyExpensifyIcons(['CalendarSolid', 'ReceiptScan', 'Car', 'Task', 'Clock', 'MoneyCircle', 'Coins', 'Receipt', 'Cash', 'Transfer']); + const [session] = useOnyx(ONYXKEYS.SESSION, {selector: sessionEmailAndAccountIDSelector}); const [activePolicyID] = useOnyx(ONYXKEYS.NVP_ACTIVE_POLICY_ID); const [activePolicy] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY}${activePolicyID}`); const [draftTransactionIDs] = useOnyx(ONYXKEYS.COLLECTION.TRANSACTION_DRAFT, {selector: validTransactionDraftIDsSelector}); - const workspaceChatsSelector = (reports: OnyxCollection) => getWorkspaceChats(activePolicyID, [currentUserPersonalDetails.accountID], reports); + const workspaceChatsSelector = (reports: OnyxCollection) => getWorkspaceChats(activePolicyID, [session?.accountID ?? CONST.DEFAULT_NUMBER_ID], reports); const [policyChats = getEmptyArray()] = useOnyx(ONYXKEYS.COLLECTION.REPORT, {selector: workspaceChatsSelector}); const [quickAction] = useOnyx(ONYXKEYS.NVP_QUICK_ACTION_GLOBAL_CREATE); const [quickActionReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${quickAction?.chatReportID}`); const [personalDetails] = useOnyx(ONYXKEYS.PERSONAL_DETAILS_LIST); const [lastDistanceExpenseType] = useOnyx(ONYXKEYS.NVP_LAST_DISTANCE_EXPENSE_TYPE); const [allBetas] = useOnyx(ONYXKEYS.BETAS); + const currentUserPersonalDetails = useCurrentUserPersonalDetails(); const {isDelegateAccessRestricted} = useDelegateNoAccessState(); const {showDelegateNoAccessModal} = useDelegateNoAccessActions(); const isReportArchived = useReportIsArchived(quickActionReport?.reportID); @@ -82,7 +84,7 @@ function QuickActionMenuItem({reportID}: QuickActionMenuItemProps) { let quickActionAvatars: ReturnType = []; if (isValidReport) { const avatars = getIcons(quickActionReport, formatPhoneNumber, personalDetails, null, undefined, undefined, undefined, undefined, isReportArchived); - quickActionAvatars = avatars.length <= 1 || isPolicyExpenseChat(quickActionReport) ? avatars : avatars.filter((avatar) => avatar.id !== currentUserPersonalDetails.accountID); + quickActionAvatars = avatars.length <= 1 || isPolicyExpenseChat(quickActionReport) ? avatars : avatars.filter((avatar) => avatar.id !== session?.accountID); } else if (!isEmptyObject(policyChatForActivePolicy)) { quickActionAvatars = getIcons(policyChatForActivePolicy, formatPhoneNumber, personalDetails, null, undefined, undefined, undefined, undefined, isReportArchived); } @@ -116,7 +118,7 @@ function QuickActionMenuItem({reportID}: QuickActionMenuItemProps) { shouldRestrictAction && quickActionReportPolicyID && quickActionReportPolicy && - shouldRestrictUserBillableActions(quickActionReportPolicy, ownerBillingGracePeriodEnd, userBillingGracePeriodEnds, amountOwed, currentUserPersonalDetails.accountID) + shouldRestrictUserBillableActions(quickActionReportPolicy, ownerBillingGracePeriodEnd, userBillingGracePeriodEnds, amountOwed, session?.accountID) ) { Navigation.navigate(ROUTES.RESTRICTED_ACTION.getRoute(quickActionReportPolicyID)); return; @@ -195,13 +197,7 @@ function QuickActionMenuItem({reportID}: QuickActionMenuItemProps) { if ( policyChatForActivePolicyPolicyID && policyChatForActivePolicyPolicy && - shouldRestrictUserBillableActions( - policyChatForActivePolicyPolicy, - ownerBillingGracePeriodEnd, - userBillingGracePeriodEnds, - amountOwed, - currentUserPersonalDetails.accountID, - ) + shouldRestrictUserBillableActions(policyChatForActivePolicyPolicy, ownerBillingGracePeriodEnd, userBillingGracePeriodEnds, amountOwed, session?.accountID) ) { Navigation.navigate(ROUTES.RESTRICTED_ACTION.getRoute(policyChatForActivePolicyPolicyID)); return; diff --git a/src/pages/inbox/sidebar/FABPopoverContent/useScanActions.ts b/src/pages/inbox/sidebar/FABPopoverContent/useScanActions.ts index d96b42471d1f..c50a7a9399fa 100644 --- a/src/pages/inbox/sidebar/FABPopoverContent/useScanActions.ts +++ b/src/pages/inbox/sidebar/FABPopoverContent/useScanActions.ts @@ -1,6 +1,5 @@ import {useState} from 'react'; import type {OnyxCollection} from 'react-native-onyx'; -import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails'; import useOnyx from '@hooks/useOnyx'; import {startMoneyRequest} from '@libs/actions/IOU/MoneyRequest'; import getNonEmptyStringOnyxID from '@libs/getNonEmptyStringOnyxID'; @@ -12,17 +11,18 @@ import Tab from '@userActions/Tab'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; +import {sessionEmailAndAccountIDSelector} from '@src/selectors/Session'; import {validTransactionDraftIDsSelector} from '@src/selectors/TransactionDraft'; import type * as OnyxTypes from '@src/types/onyx'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; import getEmptyArray from '@src/types/utils/getEmptyArray'; function useScanActions() { - const currentUserPersonalDetails = useCurrentUserPersonalDetails(); + const [session] = useOnyx(ONYXKEYS.SESSION, {selector: sessionEmailAndAccountIDSelector}); const [activePolicyID] = useOnyx(ONYXKEYS.NVP_ACTIVE_POLICY_ID); const [activePolicy] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY}${activePolicyID}`); const [draftTransactionIDs] = useOnyx(ONYXKEYS.COLLECTION.TRANSACTION_DRAFT, {selector: validTransactionDraftIDsSelector}); - const workspaceChatsSelector = (reports: OnyxCollection) => getWorkspaceChats(activePolicyID, [currentUserPersonalDetails.accountID], reports); + const workspaceChatsSelector = (reports: OnyxCollection) => getWorkspaceChats(activePolicyID, [session?.accountID ?? CONST.DEFAULT_NUMBER_ID], reports); const [policyChats = getEmptyArray()] = useOnyx(ONYXKEYS.COLLECTION.REPORT, {selector: workspaceChatsSelector}); const [userBillingGracePeriodEnds] = useOnyx(ONYXKEYS.COLLECTION.SHARED_NVP_PRIVATE_USER_BILLING_GRACE_PERIOD_END); @@ -47,10 +47,7 @@ function useScanActions() { const startQuickScan = () => { interceptAnonymousUser(() => { - if ( - policyChatPolicyID && - shouldRestrictUserBillableActions(policyChatPolicy, ownerBillingGracePeriodEnd, userBillingGracePeriodEnds, amountOwed, currentUserPersonalDetails.accountID) - ) { + if (policyChatPolicyID && shouldRestrictUserBillableActions(policyChatPolicy, ownerBillingGracePeriodEnd, userBillingGracePeriodEnds, amountOwed, session?.accountID)) { Navigation.navigate(ROUTES.RESTRICTED_ACTION.getRoute(policyChatPolicyID)); return; } diff --git a/src/pages/iou/request/step/IOURequestEditReport.tsx b/src/pages/iou/request/step/IOURequestEditReport.tsx index 1b7b413181f4..09a28958d9bc 100644 --- a/src/pages/iou/request/step/IOURequestEditReport.tsx +++ b/src/pages/iou/request/step/IOURequestEditReport.tsx @@ -1,10 +1,9 @@ import React, {useMemo} from 'react'; import type {OnyxEntry} from 'react-native-onyx'; -import {usePersonalDetails} from '@components/OnyxListItemProvider'; +import {usePersonalDetails, useSession} from '@components/OnyxListItemProvider'; import {useSearchActionsContext, useSearchStateContext} from '@components/Search/SearchContext'; import type {ListItem} from '@components/SelectionList/types'; import useConditionalCreateEmptyReportConfirmation from '@hooks/useConditionalCreateEmptyReportConfirmation'; -import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails'; import useHasPerDiemTransactions from '@hooks/useHasPerDiemTransactions'; import useOnyx from '@hooks/useOnyx'; import usePermissions from '@hooks/usePermissions'; @@ -42,7 +41,7 @@ function IOURequestEditReport({route}: IOURequestEditReportProps) { const [reportNextStep] = useOnyx(`${ONYXKEYS.COLLECTION.NEXT_STEP}${reportID}`); const {isBetaEnabled} = usePermissions(); const isASAPSubmitBetaEnabled = isBetaEnabled(CONST.BETAS.ASAP_SUBMIT); - const currentUserPersonalDetails = useCurrentUserPersonalDetails(); + const session = useSession(); const [personalPolicyID] = useOnyx(ONYXKEYS.PERSONAL_POLICY_ID); const [userBillingGracePeriodEnds] = useOnyx(ONYXKEYS.COLLECTION.SHARED_NVP_PRIVATE_USER_BILLING_GRACE_PERIOD_END); const [ownerBillingGracePeriodEnd] = useOnyx(ONYXKEYS.NVP_PRIVATE_OWNER_BILLING_GRACE_PERIOD_END); @@ -63,12 +62,12 @@ function IOURequestEditReport({route}: IOURequestEditReportProps) { // transactions, use the policy of their report (or the transaction's policy as fallback) so the // selected workspace is preserved. // For the current user's own non-per-diem expenses, fall back to undefined to let the default workspace apply. - const isOwnedByOther = selectedReport?.ownerAccountID !== currentUserPersonalDetails.accountID; + const isOwnedByOther = selectedReport?.ownerAccountID !== session?.accountID; const isOwnedByOtherOrHasPerDiem = isOwnedByOther || hasPerDiemTransactions; const targetExpensePolicyID = isOwnedByOtherOrHasPerDiem ? selectedReport?.policyID : undefined; const {policyForMovingExpensesID, shouldSelectPolicy} = usePolicyForMovingExpenses(hasPerDiemTransactions, undefined, targetExpensePolicyID); const [transactionViolations] = useOnyx(ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS); - const hasViolations = hasViolationsReportUtils(undefined, transactionViolations, currentUserPersonalDetails.accountID ?? CONST.DEFAULT_NUMBER_ID, currentUserPersonalDetails.email ?? ''); + const hasViolations = hasViolationsReportUtils(undefined, transactionViolations, session?.accountID ?? CONST.DEFAULT_NUMBER_ID, session?.email ?? ''); const policyForMovingExpenses = policyForMovingExpensesID ? allPolicies?.[`${ONYXKEYS.COLLECTION.POLICY}${policyForMovingExpensesID}`] : undefined; const [allTransactions] = useOnyx(ONYXKEYS.COLLECTION.TRANSACTION); const [betas] = useOnyx(ONYXKEYS.BETAS); @@ -85,8 +84,8 @@ function IOURequestEditReport({route}: IOURequestEditReportProps) { changeTransactionsReport({ transactionIDs, isASAPSubmitBetaEnabled, - accountID: currentUserPersonalDetails.accountID ?? CONST.DEFAULT_NUMBER_ID, - email: currentUserPersonalDetails.email ?? '', + accountID: session?.accountID ?? CONST.DEFAULT_NUMBER_ID, + email: session?.email ?? '', newReport, policy: allPolicies?.[`${ONYXKEYS.COLLECTION.POLICY}${item.policyID}`], reportNextStep, @@ -109,8 +108,8 @@ function IOURequestEditReport({route}: IOURequestEditReportProps) { changeTransactionsReport({ transactionIDs, isASAPSubmitBetaEnabled, - accountID: currentUserPersonalDetails.accountID, - email: currentUserPersonalDetails.email ?? '', + accountID: session?.accountID ?? CONST.DEFAULT_NUMBER_ID, + email: session?.email ?? '', policy: allPolicies?.[`${ONYXKEYS.COLLECTION.POLICY}${personalPolicyID}`], allTransactions, policyTagList, @@ -147,10 +146,7 @@ function IOURequestEditReport({route}: IOURequestEditReportProps) { const createReport = () => { const restrictionPolicy = hasPerDiemTransactions ? selectedReportPolicy : policyForMovingExpenses; - if ( - restrictionPolicy && - shouldRestrictUserBillableActions(restrictionPolicy, ownerBillingGracePeriodEnd, userBillingGracePeriodEnds, amountOwed, currentUserPersonalDetails.accountID) - ) { + if (restrictionPolicy && shouldRestrictUserBillableActions(restrictionPolicy, ownerBillingGracePeriodEnd, userBillingGracePeriodEnds, amountOwed, session?.accountID)) { Navigation.navigate(ROUTES.RESTRICTED_ACTION.getRoute(restrictionPolicy.id)); return; } diff --git a/src/pages/iou/request/step/IOURequestStepAmount.tsx b/src/pages/iou/request/step/IOURequestStepAmount.tsx index 478dedf3f6f0..ceab6f331c13 100644 --- a/src/pages/iou/request/step/IOURequestStepAmount.tsx +++ b/src/pages/iou/request/step/IOURequestStepAmount.tsx @@ -407,7 +407,7 @@ function IOURequestStepAmount({ // Starting from global + menu means no participant context exists yet, // so we need to handle participant selection based on available workspace settings - if (shouldUseDefaultExpensePolicy(iouType, defaultExpensePolicy, amountOwed, userBillingGracePeriodEnds, ownerBillingGracePeriodEnd, currentUserAccountIDParam)) { + if (shouldUseDefaultExpensePolicy(iouType, defaultExpensePolicy, amountOwed, userBillingGracePeriodEnds, ownerBillingGracePeriodEnd)) { const shouldAutoReport = !!defaultExpensePolicy?.autoReporting || !!personalPolicy?.autoReporting; const targetReport = shouldAutoReport ? getPolicyExpenseChat(currentUserAccountIDParam, defaultExpensePolicy?.id) : selfDMReport; const transactionReportID = isSelfDM(targetReport) ? CONST.REPORT.UNREPORTED_REPORT_ID : targetReport?.reportID; diff --git a/src/pages/iou/request/step/IOURequestStepConfirmation.tsx b/src/pages/iou/request/step/IOURequestStepConfirmation.tsx index c32db93dc8ac..ad1da43a3e92 100644 --- a/src/pages/iou/request/step/IOURequestStepConfirmation.tsx +++ b/src/pages/iou/request/step/IOURequestStepConfirmation.tsx @@ -286,14 +286,7 @@ function IOURequestStepConfirmation({ const isGlobalCreateFlow = transaction?.isFromGlobalCreate ?? transaction?.isFromFloatingActionButton ?? iouType === CONST.IOU.TYPE.CREATE; if (!defaultParticipantsOptions.length && isGlobalCreateFlow) { - const canUseDefaultPolicy = shouldUseDefaultExpensePolicy( - iouType, - defaultExpensePolicy, - amountOwed, - userBillingGracePeriodEnds, - ownerBillingGracePeriodEnd, - currentUserPersonalDetails.accountID, - ); + const canUseDefaultPolicy = shouldUseDefaultExpensePolicy(iouType, defaultExpensePolicy, amountOwed, userBillingGracePeriodEnds, ownerBillingGracePeriodEnd); if (canUseDefaultPolicy) { const shouldAutoReport = !!defaultExpensePolicy?.autoReporting || !!personalPolicy?.autoReporting; diff --git a/src/pages/iou/request/step/IOURequestStepDistanceGPS/index.native.tsx b/src/pages/iou/request/step/IOURequestStepDistanceGPS/index.native.tsx index 4386707a7a88..44319518e31b 100644 --- a/src/pages/iou/request/step/IOURequestStepDistanceGPS/index.native.tsx +++ b/src/pages/iou/request/step/IOURequestStepDistanceGPS/index.native.tsx @@ -87,14 +87,7 @@ function IOURequestStepDistanceGPS({ const currentUserAccountIDParam = currentUserPersonalDetails.accountID; const currentUserEmailParam = currentUserPersonalDetails.login ?? ''; - const shouldUseDefaultExpensePolicy = shouldUseDefaultExpensePolicyUtil( - iouType, - defaultExpensePolicy, - amountOwed, - userBillingGracePeriodEnds, - ownerBillingGracePeriodEnd, - currentUserAccountIDParam, - ); + const shouldUseDefaultExpensePolicy = shouldUseDefaultExpensePolicyUtil(iouType, defaultExpensePolicy, amountOwed, userBillingGracePeriodEnds, ownerBillingGracePeriodEnd); const unit = DistanceRequestUtils.getRate({transaction, policy: shouldUseDefaultExpensePolicy ? defaultExpensePolicy : policy}).unit; diff --git a/src/pages/iou/request/step/IOURequestStepDistanceManual.tsx b/src/pages/iou/request/step/IOURequestStepDistanceManual.tsx index 4748c3906b10..fb35f299a410 100644 --- a/src/pages/iou/request/step/IOURequestStepDistanceManual.tsx +++ b/src/pages/iou/request/step/IOURequestStepDistanceManual.tsx @@ -110,14 +110,7 @@ function IOURequestStepDistanceManual({ const delegateAccountID = useDelegateAccountID(); const isASAPSubmitBetaEnabled = isBetaEnabled(CONST.BETAS.ASAP_SUBMIT); - const shouldUseDefaultExpensePolicy = shouldUseDefaultExpensePolicyUtil( - iouType, - defaultExpensePolicy, - amountOwed, - userBillingGracePeriodEnds, - ownerBillingGracePeriodEnd, - currentUserAccountIDParam, - ); + const shouldUseDefaultExpensePolicy = shouldUseDefaultExpensePolicyUtil(iouType, defaultExpensePolicy, amountOwed, userBillingGracePeriodEnds, ownerBillingGracePeriodEnd); // to make sure the correct distance amount and unit will be shown we use distance unit // from defaultExpensePolicy or current report's policy instead of from transaction and diff --git a/src/pages/iou/request/step/IOURequestStepDistanceOdometer.tsx b/src/pages/iou/request/step/IOURequestStepDistanceOdometer.tsx index 5b114b77ba71..fdb7fa06c9b0 100644 --- a/src/pages/iou/request/step/IOURequestStepDistanceOdometer.tsx +++ b/src/pages/iou/request/step/IOURequestStepDistanceOdometer.tsx @@ -133,8 +133,8 @@ function IOURequestStepDistanceOdometer({ const isFocused = useIsFocused(); const shouldUseDefaultExpensePolicy = useMemo( - () => shouldUseDefaultExpensePolicyUtil(iouType, defaultExpensePolicy, amountOwed, userBillingGracePeriodEnds, ownerBillingGracePeriodEnd, currentUserAccountIDParam), - [iouType, defaultExpensePolicy, amountOwed, userBillingGracePeriodEnds, ownerBillingGracePeriodEnd, currentUserAccountIDParam], + () => shouldUseDefaultExpensePolicyUtil(iouType, defaultExpensePolicy, amountOwed, userBillingGracePeriodEnds, ownerBillingGracePeriodEnd), + [iouType, defaultExpensePolicy, amountOwed, userBillingGracePeriodEnds, ownerBillingGracePeriodEnd], ); const mileageRate = DistanceRequestUtils.getRate({transaction: currentTransaction, policy: shouldUseDefaultExpensePolicy ? defaultExpensePolicy : policy}); diff --git a/src/pages/iou/request/step/IOURequestStepHours.tsx b/src/pages/iou/request/step/IOURequestStepHours.tsx index 47c657660af9..efc88043187f 100644 --- a/src/pages/iou/request/step/IOURequestStepHours.tsx +++ b/src/pages/iou/request/step/IOURequestStepHours.tsx @@ -169,7 +169,7 @@ function IOURequestStepHours({ large={!isExtraSmallScreenHeight} style={[styles.w100, canUseTouchScreen ? styles.mt5 : styles.mt0]} onPress={() => { - if (policy && shouldRestrictUserBillableActions(policy, ownerBillingGracePeriodEnd, userBillingGracePeriodEnds, amountOwed, accountID)) { + if (policy && shouldRestrictUserBillableActions(policy, ownerBillingGracePeriodEnd, userBillingGracePeriodEnds, amountOwed)) { Navigation.navigate(ROUTES.RESTRICTED_ACTION.getRoute(policy.id)); return; } From 7b2c1186f11a9611b37b7350a2ded41d47be4735 Mon Sep 17 00:00:00 2001 From: Hans Date: Sun, 24 May 2026 22:30:41 +0700 Subject: [PATCH 19/22] fix ts --- src/libs/ReportUtils.ts | 2 +- src/libs/SubscriptionUtils.ts | 11 ++++++++++- src/libs/shouldUseDefaultExpensePolicy.ts | 2 +- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index 391c706ef1fe..f20f47e8fa89 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -2936,7 +2936,7 @@ type GetAddExpenseDropdownOptionsParams = { iouRequestBackToReport?: string; unreportedExpenseBackToReport?: string; lastDistanceExpenseType?: IOURequestType; - currentUserAccountID: number; + currentUserAccountID?: number; }; function getAddExpenseDropdownOptions({ diff --git a/src/libs/SubscriptionUtils.ts b/src/libs/SubscriptionUtils.ts index b014e9224c2a..bdeeb14e4039 100644 --- a/src/libs/SubscriptionUtils.ts +++ b/src/libs/SubscriptionUtils.ts @@ -1,5 +1,6 @@ import {differenceInSeconds, fromUnixTime, isAfter, isBefore} from 'date-fns'; import {fromZonedTime} from 'date-fns-tz'; +import Onyx from 'react-native-onyx'; import type {OnyxCollection, OnyxEntry} from 'react-native-onyx'; import type {ValueOf} from 'type-fest'; import type {LocalizedTranslate} from '@components/LocaleContextProvider'; @@ -46,6 +47,14 @@ type SubscriptionPlanInfo = { description: string; }; +let deprecatedCurrentUserAccountID = -1; +Onyx.connect({ + key: ONYXKEYS.SESSION, + callback: (value) => { + deprecatedCurrentUserAccountID = value?.accountID ?? CONST.DEFAULT_NUMBER_ID; + }, +}); + /** * @returns Whether the workspace owner's grace period is overdue. */ @@ -472,7 +481,7 @@ function shouldRestrictUserBillableActions( ownerBillingGracePeriodEnd: OnyxEntry, userBillingGracePeriodEnds: OnyxCollection, amountOwed: OnyxEntry, - currentUserAccountID: number | undefined, + currentUserAccountID: number | undefined = deprecatedCurrentUserAccountID, ): boolean { const currentDate = new Date(); diff --git a/src/libs/shouldUseDefaultExpensePolicy.ts b/src/libs/shouldUseDefaultExpensePolicy.ts index 33fa6fa78d3c..68e454f0260c 100644 --- a/src/libs/shouldUseDefaultExpensePolicy.ts +++ b/src/libs/shouldUseDefaultExpensePolicy.ts @@ -11,7 +11,7 @@ function shouldUseDefaultExpensePolicy( amountOwed: OnyxEntry, userBillingGracePeriodEnds: OnyxCollection, ownerBillingGracePeriodEnd: OnyxEntry, - currentUserAccountID: number, + currentUserAccountID?: number, ) { return ( iouType === CONST.IOU.TYPE.CREATE && From c03e89483518c80b7c5792f228d7ffe2e1e5474b Mon Sep 17 00:00:00 2001 From: Hans Date: Sun, 24 May 2026 22:49:57 +0700 Subject: [PATCH 20/22] update the tests accordingly --- tests/unit/ReportUtilsTest.ts | 16 -------- tests/unit/SubscriptionUtilsTest.ts | 39 ++++++++----------- .../unit/shouldUseDefaultExpensePolicyTest.ts | 17 ++++---- 3 files changed, 25 insertions(+), 47 deletions(-) diff --git a/tests/unit/ReportUtilsTest.ts b/tests/unit/ReportUtilsTest.ts index 56cb690c78be..b5327e413e2c 100644 --- a/tests/unit/ReportUtilsTest.ts +++ b/tests/unit/ReportUtilsTest.ts @@ -16314,7 +16314,6 @@ describe('ReportUtils', () => { draftTransactionIDs: undefined, amountOwed: 0, ownerBillingGracePeriodEnd: undefined, - currentUserAccountID, }); expect(result).toHaveLength(3); }); @@ -16329,7 +16328,6 @@ describe('ReportUtils', () => { draftTransactionIDs: undefined, amountOwed: undefined, ownerBillingGracePeriodEnd: undefined, - currentUserAccountID, }); expect(result.at(0)?.value).toBe(CONST.REPORT.ADD_EXPENSE_OPTIONS.CREATE_NEW_EXPENSE); expect(result.at(1)?.value).toBe(CONST.REPORT.ADD_EXPENSE_OPTIONS.TRACK_DISTANCE_EXPENSE); @@ -16346,7 +16344,6 @@ describe('ReportUtils', () => { draftTransactionIDs: undefined, amountOwed: 0, ownerBillingGracePeriodEnd: undefined, - currentUserAccountID, }); expect(result.at(0)?.text).toBe(translate(CONST.LOCALES.EN, 'iou.createExpense')); expect(result.at(1)?.text).toBe(translate(CONST.LOCALES.EN, 'iou.trackDistance')); @@ -16363,7 +16360,6 @@ describe('ReportUtils', () => { draftTransactionIDs: undefined, amountOwed: 0, ownerBillingGracePeriodEnd: undefined, - currentUserAccountID, }); expect(result.at(0)?.sentryLabel).toBe(CONST.SENTRY_LABEL.MORE_MENU.ADD_EXPENSE_CREATE); expect(result.at(1)?.sentryLabel).toBe(CONST.SENTRY_LABEL.MORE_MENU.ADD_EXPENSE_TRACK_DISTANCE); @@ -16383,7 +16379,6 @@ describe('ReportUtils', () => { draftTransactionIDs: undefined, amountOwed, ownerBillingGracePeriodEnd: undefined, - currentUserAccountID, }); // Trigger each onSelected - the function should not throw @@ -16404,7 +16399,6 @@ describe('ReportUtils', () => { draftTransactionIDs: undefined, amountOwed: 0, ownerBillingGracePeriodEnd: undefined, - currentUserAccountID, }); expect(result).toHaveLength(3); @@ -16424,7 +16418,6 @@ describe('ReportUtils', () => { draftTransactionIDs: undefined, amountOwed: 0, ownerBillingGracePeriodEnd: undefined, - currentUserAccountID, }); // CREATE_NEW_EXPENSE and TRACK_DISTANCE_EXPENSE should early-return when iouReportID is undefined @@ -16444,7 +16437,6 @@ describe('ReportUtils', () => { draftTransactionIDs: undefined, amountOwed: 0, ownerBillingGracePeriodEnd: undefined, - currentUserAccountID, }); expect(result).toHaveLength(3); @@ -16464,7 +16456,6 @@ describe('ReportUtils', () => { draftTransactionIDs: undefined, amountOwed, ownerBillingGracePeriodEnd: undefined, - currentUserAccountID, }); expect(result).toHaveLength(3); @@ -16480,7 +16471,6 @@ describe('ReportUtils', () => { draftTransactionIDs: undefined, amountOwed: 0, ownerBillingGracePeriodEnd: undefined, - currentUserAccountID, }); expect(result.at(1)?.icon).toBe(mockIcons.Location); expect(result.at(2)?.icon).toBe(mockIcons.ReceiptPlus); @@ -16505,7 +16495,6 @@ describe('ReportUtils', () => { draftTransactionIDs: undefined, amountOwed, ownerBillingGracePeriodEnd: pastGracePeriod, - currentUserAccountID, }); // Trigger CREATE_NEW_EXPENSE onSelected @@ -16849,7 +16838,6 @@ describe('ReportUtils', () => { draftTransactionIDs: undefined, amountOwed: undefined, ownerBillingGracePeriodEnd: undefined, - currentUserAccountID, }); expect(options).toHaveLength(3); @@ -16869,7 +16857,6 @@ describe('ReportUtils', () => { draftTransactionIDs: undefined, amountOwed: undefined, ownerBillingGracePeriodEnd: undefined, - currentUserAccountID, }); options.at(0)?.onSelected?.(); @@ -16901,7 +16888,6 @@ describe('ReportUtils', () => { draftTransactionIDs: undefined, amountOwed: undefined, ownerBillingGracePeriodEnd: undefined, - currentUserAccountID, }); options.at(0)?.onSelected?.(); @@ -16934,7 +16920,6 @@ describe('ReportUtils', () => { draftTransactionIDs: undefined, amountOwed: undefined, ownerBillingGracePeriodEnd: undefined, - currentUserAccountID, }); options.at(2)?.onSelected?.(); @@ -16961,7 +16946,6 @@ describe('ReportUtils', () => { draftTransactionIDs: undefined, amountOwed: 100, ownerBillingGracePeriodEnd: gracePeriodEnd, - currentUserAccountID, }); options.at(2)?.onSelected?.(); diff --git a/tests/unit/SubscriptionUtilsTest.ts b/tests/unit/SubscriptionUtilsTest.ts index 5ce2e6b5d62d..97d0486830fb 100644 --- a/tests/unit/SubscriptionUtilsTest.ts +++ b/tests/unit/SubscriptionUtilsTest.ts @@ -326,7 +326,7 @@ describe('SubscriptionUtils', () => { }); it("should return false if the user isn't a workspace's owner or isn't a member of any past due billing workspace", () => { - expect(shouldRestrictUserBillableActions(undefined, undefined, undefined, undefined, CONST.DEFAULT_NUMBER_ID)).toBeFalsy(); + expect(shouldRestrictUserBillableActions(undefined, undefined, undefined, undefined)).toBeFalsy(); }); it('should return false if the user is a non-owner of a workspace that is not in the shared NVP collection', () => { @@ -345,7 +345,6 @@ describe('SubscriptionUtils', () => { }, }, undefined, - CONST.DEFAULT_NUMBER_ID, ), ).toBeFalsy(); }); @@ -366,7 +365,6 @@ describe('SubscriptionUtils', () => { }, }, undefined, - CONST.DEFAULT_NUMBER_ID, ), ).toBeFalsy(); }); @@ -387,7 +385,6 @@ describe('SubscriptionUtils', () => { }, }, undefined, - CONST.DEFAULT_NUMBER_ID, ), ).toBeTruthy(); }); @@ -401,7 +398,7 @@ describe('SubscriptionUtils', () => { [ONYXKEYS.SESSION]: {email: '', accountID}, }); - expect(shouldRestrictUserBillableActions(policy, getUnixTime(addDays(new Date(), 3)), undefined, undefined, accountID)).toBeFalsy(); + expect(shouldRestrictUserBillableActions(policy, getUnixTime(addDays(new Date(), 3)), undefined, undefined)).toBeFalsy(); }); it("should return false if the user is the workspace's owner that is past due billing but isn't owning any amount", async () => { @@ -414,7 +411,7 @@ describe('SubscriptionUtils', () => { [ONYXKEYS.NVP_PRIVATE_AMOUNT_OWED]: 0, }); - expect(shouldRestrictUserBillableActions(policy, getUnixTime(subDays(new Date(), 3)), undefined, 0, accountID)).toBeFalsy(); + expect(shouldRestrictUserBillableActions(policy, getUnixTime(subDays(new Date(), 3)), undefined, 0)).toBeFalsy(); }); it("should return true if the user is the workspace's owner that is past due billing and is owning some amount", async () => { @@ -427,7 +424,7 @@ describe('SubscriptionUtils', () => { [ONYXKEYS.NVP_PRIVATE_AMOUNT_OWED]: 8010, }); - expect(shouldRestrictUserBillableActions(policy, getUnixTime(subDays(new Date(), 3)), undefined, 8010, accountID)).toBeTruthy(); + expect(shouldRestrictUserBillableActions(policy, getUnixTime(subDays(new Date(), 3)), undefined, 8010)).toBeTruthy(); }); it("should return false if the user is past due billing but is not the workspace's owner", async () => { @@ -440,7 +437,7 @@ describe('SubscriptionUtils', () => { [ONYXKEYS.NVP_PRIVATE_AMOUNT_OWED]: 8010, }); - expect(shouldRestrictUserBillableActions(policy, getUnixTime(subDays(new Date(), 3)), undefined, 8010, accountID)).toBeFalsy(); + expect(shouldRestrictUserBillableActions(policy, getUnixTime(subDays(new Date(), 3)), undefined, 8010)).toBeFalsy(); }); it('should restrict when ownerBillingGracePeriodEnd is passed directly as 3rd param and is past due', async () => { @@ -453,7 +450,7 @@ describe('SubscriptionUtils', () => { [ONYXKEYS.NVP_PRIVATE_AMOUNT_OWED]: 8010, }); - expect(shouldRestrictUserBillableActions(policy, getUnixTime(subDays(new Date(), 3)), undefined, 8010, accountID)).toBeTruthy(); + expect(shouldRestrictUserBillableActions(policy, getUnixTime(subDays(new Date(), 3)), undefined, 8010)).toBeTruthy(); }); it("should return false if the user is past due billing but is not the workspace's owner (2nd check)", async () => { @@ -466,7 +463,7 @@ describe('SubscriptionUtils', () => { [ONYXKEYS.NVP_PRIVATE_AMOUNT_OWED]: 8010, }); - expect(shouldRestrictUserBillableActions(policy, getUnixTime(subDays(new Date(), 3)), undefined, 8010, accountID)).toBeFalsy(); + expect(shouldRestrictUserBillableActions(policy, getUnixTime(subDays(new Date(), 3)), undefined, 8010)).toBeFalsy(); }); it('should restrict when ownerBillingGracePeriodEnd is passed directly as 4th param and is past due', async () => { @@ -479,7 +476,7 @@ describe('SubscriptionUtils', () => { [ONYXKEYS.NVP_PRIVATE_AMOUNT_OWED]: 8010, }); - expect(shouldRestrictUserBillableActions(policy, getUnixTime(subDays(new Date(), 3)), undefined, 8010, accountID)).toBeTruthy(); + expect(shouldRestrictUserBillableActions(policy, getUnixTime(subDays(new Date(), 3)), undefined, 8010)).toBeTruthy(); }); it('should not restrict when ownerBillingGracePeriodEnd is passed directly as 4th param but is not past due', async () => { @@ -492,7 +489,7 @@ describe('SubscriptionUtils', () => { [ONYXKEYS.NVP_PRIVATE_AMOUNT_OWED]: 8010, }); - expect(shouldRestrictUserBillableActions(policy, getUnixTime(addDays(new Date(), 3)), undefined, 8010, accountID)).toBeFalsy(); + expect(shouldRestrictUserBillableActions(policy, getUnixTime(addDays(new Date(), 3)), undefined, 8010)).toBeFalsy(); }); it('should not restrict when ownerBillingGracePeriodEnd is passed directly as 4th param but amount owed is 0', async () => { @@ -505,7 +502,7 @@ describe('SubscriptionUtils', () => { [ONYXKEYS.NVP_PRIVATE_AMOUNT_OWED]: 0, }); - expect(shouldRestrictUserBillableActions(policy, getUnixTime(subDays(new Date(), 3)), undefined, 0, accountID)).toBeFalsy(); + expect(shouldRestrictUserBillableActions(policy, getUnixTime(subDays(new Date(), 3)), undefined, 0)).toBeFalsy(); }); it('should restrict when amountOwed is passed directly and is greater than 0', async () => { @@ -517,7 +514,7 @@ describe('SubscriptionUtils', () => { [ONYXKEYS.SESSION]: {email: '', accountID}, }); - expect(shouldRestrictUserBillableActions(policy, getUnixTime(subDays(new Date(), 3)), undefined, 500, accountID)).toBeTruthy(); + expect(shouldRestrictUserBillableActions(policy, getUnixTime(subDays(new Date(), 3)), undefined, 500)).toBeTruthy(); }); it('should not restrict when amountOwed is passed directly as 0', async () => { @@ -529,7 +526,7 @@ describe('SubscriptionUtils', () => { [ONYXKEYS.SESSION]: {email: '', accountID}, }); - expect(shouldRestrictUserBillableActions(policy, getUnixTime(subDays(new Date(), 3)), undefined, 0, accountID)).toBeFalsy(); + expect(shouldRestrictUserBillableActions(policy, getUnixTime(subDays(new Date(), 3)), undefined, 0)).toBeFalsy(); }); it('should not restrict when amountOwed is passed directly as undefined', async () => { @@ -541,7 +538,7 @@ describe('SubscriptionUtils', () => { [ONYXKEYS.SESSION]: {email: '', accountID}, }); - expect(shouldRestrictUserBillableActions(policy, getUnixTime(subDays(new Date(), 3)), undefined, undefined, accountID)).toBeFalsy(); + expect(shouldRestrictUserBillableActions(policy, getUnixTime(subDays(new Date(), 3)), undefined, undefined)).toBeFalsy(); }); }); @@ -569,7 +566,7 @@ describe('SubscriptionUtils', () => { [ONYXKEYS.NVP_PRIVATE_AMOUNT_OWED]: 8010, }); - expect(shouldRestrictUserBillableActions(policy, getUnixTime(subDays(new Date(), 3)), undefined, 8010, accountID)).toBeTruthy(); + expect(shouldRestrictUserBillableActions(policy, getUnixTime(subDays(new Date(), 3)), undefined, 8010)).toBeTruthy(); }); it('should not restrict when policy is passed directly but owner is not past due', async () => { @@ -585,11 +582,11 @@ describe('SubscriptionUtils', () => { [ONYXKEYS.NVP_PRIVATE_AMOUNT_OWED]: 8010, }); - expect(shouldRestrictUserBillableActions(policy, getUnixTime(addDays(new Date(), 3)), undefined, 8010, accountID)).toBeFalsy(); + expect(shouldRestrictUserBillableActions(policy, getUnixTime(addDays(new Date(), 3)), undefined, 8010)).toBeFalsy(); }); it('should not restrict when policy is passed as undefined', () => { - expect(shouldRestrictUserBillableActions(undefined, getUnixTime(subDays(new Date(), 3)), undefined, 500, CONST.DEFAULT_NUMBER_ID)).toBeFalsy(); + expect(shouldRestrictUserBillableActions(undefined, getUnixTime(subDays(new Date(), 3)), undefined, 500)).toBeFalsy(); }); it('should restrict for non-owner when policy is passed directly and billing grace period is overdue', async () => { @@ -611,7 +608,6 @@ describe('SubscriptionUtils', () => { }, }, undefined, - CONST.DEFAULT_NUMBER_ID, ), ).toBeTruthy(); }); @@ -635,7 +631,6 @@ describe('SubscriptionUtils', () => { }, }, undefined, - CONST.DEFAULT_NUMBER_ID, ), ).toBeFalsy(); }); @@ -657,7 +652,7 @@ describe('SubscriptionUtils', () => { }, }); - expect(shouldRestrictUserBillableActions(differentOwnerPolicy, getUnixTime(subDays(new Date(), 3)), undefined, 8010, accountID)).toBeFalsy(); + expect(shouldRestrictUserBillableActions(differentOwnerPolicy, getUnixTime(subDays(new Date(), 3)), undefined, 8010)).toBeFalsy(); }); }); diff --git a/tests/unit/shouldUseDefaultExpensePolicyTest.ts b/tests/unit/shouldUseDefaultExpensePolicyTest.ts index 0169321a23b2..b1ac34d6b90a 100644 --- a/tests/unit/shouldUseDefaultExpensePolicyTest.ts +++ b/tests/unit/shouldUseDefaultExpensePolicyTest.ts @@ -33,27 +33,27 @@ describe('shouldUseDefaultExpensePolicy', () => { it('returns false when iouType is not CREATE', () => { const policy = makePaidGroupPolicy(); - expect(shouldUseDefaultExpensePolicy(CONST.IOU.TYPE.SUBMIT, policy, undefined, undefined, undefined, OWNER_ACCOUNT_ID)).toBeFalsy(); - expect(shouldUseDefaultExpensePolicy(CONST.IOU.TYPE.TRACK, policy, undefined, undefined, undefined, OWNER_ACCOUNT_ID)).toBeFalsy(); + expect(shouldUseDefaultExpensePolicy(CONST.IOU.TYPE.SUBMIT, policy, undefined, undefined, undefined)).toBeFalsy(); + expect(shouldUseDefaultExpensePolicy(CONST.IOU.TYPE.TRACK, policy, undefined, undefined, undefined)).toBeFalsy(); }); it('returns false when defaultExpensePolicy is null', () => { - expect(shouldUseDefaultExpensePolicy(CONST.IOU.TYPE.CREATE, null, undefined, undefined, undefined, OWNER_ACCOUNT_ID)).toBeFalsy(); + expect(shouldUseDefaultExpensePolicy(CONST.IOU.TYPE.CREATE, null, undefined, undefined, undefined)).toBeFalsy(); }); it('returns false when defaultExpensePolicy is not a paid group policy (personal type)', () => { const policy = makePaidGroupPolicy({type: CONST.POLICY.TYPE.PERSONAL}); - expect(shouldUseDefaultExpensePolicy(CONST.IOU.TYPE.CREATE, policy, undefined, undefined, undefined, OWNER_ACCOUNT_ID)).toBeFalsy(); + expect(shouldUseDefaultExpensePolicy(CONST.IOU.TYPE.CREATE, policy, undefined, undefined, undefined)).toBeFalsy(); }); it('returns false when isPolicyExpenseChatEnabled is false', () => { const policy = makePaidGroupPolicy({isPolicyExpenseChatEnabled: false}); - expect(shouldUseDefaultExpensePolicy(CONST.IOU.TYPE.CREATE, policy, undefined, undefined, undefined, OWNER_ACCOUNT_ID)).toBeFalsy(); + expect(shouldUseDefaultExpensePolicy(CONST.IOU.TYPE.CREATE, policy, undefined, undefined, undefined)).toBeFalsy(); }); it('returns true when all conditions are met and user is not restricted', () => { const policy = makePaidGroupPolicy(); - expect(shouldUseDefaultExpensePolicy(CONST.IOU.TYPE.CREATE, policy, undefined, undefined, undefined, OWNER_ACCOUNT_ID)).toBeTruthy(); + expect(shouldUseDefaultExpensePolicy(CONST.IOU.TYPE.CREATE, policy, undefined, undefined, undefined)).toBeTruthy(); }); it('returns false when the user is restricted (owner past due with amount owed)', async () => { @@ -67,7 +67,7 @@ describe('shouldUseDefaultExpensePolicy', () => { const amountOwed = 500; // User is the owner, past due, and owes money → shouldRestrictUserBillableActions returns true - expect(shouldUseDefaultExpensePolicy(CONST.IOU.TYPE.CREATE, policy, amountOwed, undefined, pastDueGracePeriodEnd, OWNER_ACCOUNT_ID)).toBeFalsy(); + expect(shouldUseDefaultExpensePolicy(CONST.IOU.TYPE.CREATE, policy, amountOwed, undefined, pastDueGracePeriodEnd)).toBeFalsy(); }); it('returns true when the owner is past due but amount owed is 0', async () => { @@ -79,7 +79,7 @@ describe('shouldUseDefaultExpensePolicy', () => { const policy = makePaidGroupPolicy({ownerAccountID: OWNER_ACCOUNT_ID}); const pastDueGracePeriodEnd = getUnixTime(subDays(new Date(), 3)); - expect(shouldUseDefaultExpensePolicy(CONST.IOU.TYPE.CREATE, policy, 0, undefined, pastDueGracePeriodEnd, OWNER_ACCOUNT_ID)).toBeTruthy(); + expect(shouldUseDefaultExpensePolicy(CONST.IOU.TYPE.CREATE, policy, 0, undefined, pastDueGracePeriodEnd)).toBeTruthy(); }); it('returns false when a non-owner member workspace owner is past due', async () => { @@ -104,7 +104,6 @@ describe('shouldUseDefaultExpensePolicy', () => { [gracePeriodKey]: {...billingGraceEndPeriod, value: pastDueGracePeriodEnd}, }, undefined, - memberAccountID, ), ).toBeFalsy(); }); From d0404c753169163b3df712c8ea4d48ffd7aa1550 Mon Sep 17 00:00:00 2001 From: Hans Date: Thu, 28 May 2026 10:07:10 +0700 Subject: [PATCH 21/22] fix ts --- src/components/MoneyRequestHeaderSecondaryActions.tsx | 2 +- src/components/ReportActionItem/MoneyRequestView.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/MoneyRequestHeaderSecondaryActions.tsx b/src/components/MoneyRequestHeaderSecondaryActions.tsx index d6a774d8ae29..6553228b9538 100644 --- a/src/components/MoneyRequestHeaderSecondaryActions.tsx +++ b/src/components/MoneyRequestHeaderSecondaryActions.tsx @@ -341,7 +341,7 @@ function MoneyRequestHeaderSecondaryActions({reportID, onBackButtonPress}: Money icon: expensifyIcons.ArrowSplit, value: CONST.REPORT.TRANSACTION_SECONDARY_ACTIONS.SPLIT, onSelected: () => { - initSplitExpense(transaction, policy, report); + initSplitExpense(transaction, policy, report, accountID); }, }, [CONST.REPORT.TRANSACTION_SECONDARY_ACTIONS.MERGE]: { diff --git a/src/components/ReportActionItem/MoneyRequestView.tsx b/src/components/ReportActionItem/MoneyRequestView.tsx index 0e24f5e95356..ad996a6c9a20 100644 --- a/src/components/ReportActionItem/MoneyRequestView.tsx +++ b/src/components/ReportActionItem/MoneyRequestView.tsx @@ -956,7 +956,7 @@ function MoneyRequestView({ } if (shouldShowSplitIndicator && isSplitAvailable) { - initSplitExpense(transaction, policy, transactionThreadReport); + initSplitExpense(transaction, policy, transactionThreadReport, currentUserAccountIDParam); return; } From 80bc5401236442e97db489615255fc9916e0ce5d Mon Sep 17 00:00:00 2001 From: Hans Date: Thu, 28 May 2026 10:10:46 +0700 Subject: [PATCH 22/22] revert submodule --- Mobile-Expensify | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Mobile-Expensify b/Mobile-Expensify index a545ffae87da..223a21ffd0d0 160000 --- a/Mobile-Expensify +++ b/Mobile-Expensify @@ -1 +1 @@ -Subproject commit a545ffae87da4d20cfda53c45c127a319dfe9c6e +Subproject commit 223a21ffd0d045cf4c9be1ddb9eabe5dbfc406a0