Skip to content

Commit 1373eb8

Browse files
authored
Merge pull request Expensify#69156 from c3024/use-perDiemEnabled-flag-instead-of-custom-units
Use arePerDiemsEnabled flag instead of custom units for showing the per diem option in Create Expense Flow from FAB
2 parents ac3686a + 25e625b commit 1373eb8

9 files changed

Lines changed: 64 additions & 29 deletions

File tree

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
type OpenDraftPerDiemExpenseParams = {
2+
policyID: string;
3+
};
4+
5+
export default OpenDraftPerDiemExpenseParams;

src/libs/API/parameters/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,7 @@ export type {default as OpenWorkspaceMembersPageParams} from './OpenWorkspaceMem
158158
export type {default as OpenPolicyCategoriesPageParams} from './OpenPolicyCategoriesPageParams';
159159
export type {default as OpenPolicyTagsPageParams} from './OpenPolicyTagsPageParams';
160160
export type {default as OpenDraftWorkspaceRequestParams} from './OpenDraftWorkspaceRequestParams';
161+
export type {default as OpenDraftPerDiemExpenseParams} from './OpenDraftPerDiemExpenseParams';
161162
export type {default as CreateWorkspaceFromIOUPaymentParams} from './CreateWorkspaceFromIOUPaymentParams';
162163
export type {default as UpdatePolicyMembersCustomFieldsParams} from './UpdatePolicyMembersCustomFieldsParams';
163164
export type {default as CreateTaskParams} from './CreateTaskParams';

src/libs/API/types.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1101,6 +1101,7 @@ const READ_COMMANDS = {
11011101
OPEN_POLICY_EDIT_CARD_LIMIT_TYPE_PAGE: 'OpenPolicyEditCardLimitTypePage',
11021102
OPEN_WORKSPACE_INVITE_PAGE: 'OpenWorkspaceInvitePage',
11031103
OPEN_DRAFT_WORKSPACE_REQUEST: 'OpenDraftWorkspaceRequest',
1104+
OPEN_DRAFT_PER_DIEM_EXPENSE: 'OpenDraftPerDiemExpense',
11041105
OPEN_POLICY_WORKFLOWS_PAGE: 'OpenPolicyWorkflowsPage',
11051106
OPEN_POLICY_RECEIPT_PARTNERS_PAGE: 'OpenPolicyReceiptPartnersPage',
11061107
OPEN_POLICY_DISTANCE_RATES_PAGE: 'OpenPolicyDistanceRatesPage',
@@ -1173,6 +1174,7 @@ type ReadCommandParameters = {
11731174
[READ_COMMANDS.OPEN_POLICY_REPORT_FIELDS_PAGE]: Parameters.OpenPolicyReportFieldsPageParams;
11741175
[READ_COMMANDS.OPEN_WORKSPACE_INVITE_PAGE]: Parameters.OpenWorkspaceInvitePageParams;
11751176
[READ_COMMANDS.OPEN_DRAFT_WORKSPACE_REQUEST]: Parameters.OpenDraftWorkspaceRequestParams;
1177+
[READ_COMMANDS.OPEN_DRAFT_PER_DIEM_EXPENSE]: Parameters.OpenDraftPerDiemExpenseParams;
11761178
[READ_COMMANDS.OPEN_POLICY_WORKFLOWS_PAGE]: Parameters.OpenPolicyWorkflowsPageParams;
11771179
[READ_COMMANDS.OPEN_POLICY_DISTANCE_RATES_PAGE]: Parameters.OpenPolicyDistanceRatesPageParams;
11781180
[READ_COMMANDS.OPEN_POLICY_PER_DIEM_RATES_PAGE]: Parameters.OpenPolicyPerDiemRatesPageParams;

src/libs/PolicyUtils.ts

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -93,13 +93,8 @@ function getActivePoliciesWithExpenseChat(policies: OnyxCollection<Policy> | nul
9393
);
9494
}
9595

96-
function getPerDiemCustomUnits(policies: OnyxCollection<Policy> | null, email: string | undefined): Array<{policyID: string; customUnit: CustomUnit}> {
97-
return (
98-
getActivePoliciesWithExpenseChat(policies, email)
99-
.map((mappedPolicy) => ({policyID: mappedPolicy.id, customUnit: getPerDiemCustomUnit(mappedPolicy)}))
100-
// We filter out custom units that are undefine but ts cant' figure it out.
101-
.filter(({customUnit}) => !isEmptyObject(customUnit) && !!customUnit.enabled) as Array<{policyID: string; customUnit: CustomUnit}>
102-
);
96+
function getActivePoliciesWithExpenseChatAndPerDiemEnabled(policies: OnyxCollection<Policy> | null, currentUserLogin: string | undefined): Policy[] {
97+
return getActivePoliciesWithExpenseChat(policies, currentUserLogin).filter((policy) => policy?.arePerDiemRatesEnabled);
10398
}
10499

105100
/**
@@ -1559,7 +1554,6 @@ export {
15591554
canEditTaxRate,
15601555
escapeTagName,
15611556
getActivePolicies,
1562-
getPerDiemCustomUnits,
15631557
getAdminEmployees,
15641558
getCleanedTagName,
15651559
getCommaSeparatedTagNameWithSanitizedColons,
@@ -1711,6 +1705,7 @@ export {
17111705
isPolicyMemberWithoutPendingDelete,
17121706
getPolicyEmployeeAccountIDs,
17131707
isMemberPolicyAdmin,
1708+
getActivePoliciesWithExpenseChatAndPerDiemEnabled,
17141709
};
17151710

17161711
export type {MemberEmailsToAccountIDs};

src/libs/actions/Policy/PerDiem.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -364,6 +364,16 @@ function editPerDiemRateCurrency(policyID: string, rateID: string, customUnit: C
364364
API.write(WRITE_COMMANDS.UPDATE_WORKSPACE_CUSTOM_UNIT, parameters, onyxData);
365365
}
366366

367+
function fetchPerDiemRates(policyID: string | undefined) {
368+
if (!policyID) {
369+
return;
370+
}
371+
const parameters = {
372+
policyID,
373+
};
374+
API.read(READ_COMMANDS.OPEN_DRAFT_PER_DIEM_EXPENSE, parameters);
375+
}
376+
367377
export {
368378
generateCustomUnitID,
369379
enablePerDiem,
@@ -376,4 +386,5 @@ export {
376386
editPerDiemRateSubrate,
377387
editPerDiemRateAmount,
378388
editPerDiemRateCurrency,
389+
fetchPerDiemRates,
379390
};

src/pages/iou/request/IOURequestStartPage.tsx

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import HeaderWithBackButton from '@components/HeaderWithBackButton';
88
import {useProductTrainingContext} from '@components/ProductTrainingContext';
99
import ScreenWrapper from '@components/ScreenWrapper';
1010
import TabSelector from '@components/TabSelector/TabSelector';
11+
import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails';
1112
import useLocalize from '@hooks/useLocalize';
1213
import useOnyx from '@hooks/useOnyx';
1314
import usePermissions from '@hooks/usePermissions';
@@ -22,7 +23,7 @@ import Navigation from '@libs/Navigation/Navigation';
2223
import OnyxTabNavigator, {TabScreenWithFocusTrapWrapper, TopTab} from '@libs/Navigation/OnyxTabNavigator';
2324
import {getIsUserSubmittedExpenseOrScannedReceipt} from '@libs/OptionsListUtils';
2425
import Performance from '@libs/Performance';
25-
import {getPerDiemCustomUnit, getPerDiemCustomUnits} from '@libs/PolicyUtils';
26+
import {getActivePoliciesWithExpenseChatAndPerDiemEnabled} from '@libs/PolicyUtils';
2627
import {getPayeeName} from '@libs/ReportUtils';
2728
import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper';
2829
import type {IOURequestType} from '@userActions/IOU';
@@ -61,7 +62,6 @@ function IOURequestStartPage({
6162
const [parentReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${report?.parentReportID}`, {canBeMissing: true});
6263
const policy = usePolicy(report?.policyID);
6364
const [selectedTab, selectedTabResult] = useOnyx(`${ONYXKEYS.COLLECTION.SELECTED_TAB}${CONST.TAB.IOU_REQUEST_TYPE}`, {canBeMissing: true});
64-
const [session] = useOnyx(ONYXKEYS.SESSION, {canBeMissing: false});
6565
const isLoadingSelectedTab = shouldUseTab ? isLoadingOnyxValue(selectedTabResult) : false;
6666
const [transaction] = useOnyx(`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${getNonEmptyStringOnyxID(route?.params.transactionID)}`, {canBeMissing: true});
6767
const [allPolicies] = useOnyx(ONYXKEYS.COLLECTION.POLICY, {canBeMissing: false});
@@ -85,14 +85,14 @@ function IOURequestStartPage({
8585
[CONST.IOU.TYPE.CREATE]: translate('iou.createExpense'),
8686
};
8787

88-
const isFromGlobalCreate = isEmptyObject(report);
89-
const perDiemCustomUnits = getPerDiemCustomUnits(allPolicies, session?.email);
90-
const doesPerDiemPolicyExist = perDiemCustomUnits.length > 0;
91-
const moreThanOnePerDiemExist = perDiemCustomUnits.length > 1;
92-
const currentPolicyPerDiemUnit = getPerDiemCustomUnit(policy);
93-
const doesCurrentPolicyPerDiemExist = !isEmptyObject(currentPolicyPerDiemUnit) && !!currentPolicyPerDiemUnit.enabled;
88+
const isFromGlobalCreate = isEmptyObject(report?.reportID);
89+
const {login: currentUserLogin} = useCurrentUserPersonalDetails();
90+
const policiesWithPerDiemEnabled = useMemo(() => getActivePoliciesWithExpenseChatAndPerDiemEnabled(allPolicies, currentUserLogin), [allPolicies, currentUserLogin]);
91+
const doesPerDiemPolicyExist = policiesWithPerDiemEnabled.length > 0;
92+
const moreThanOnePerDiemExist = policiesWithPerDiemEnabled.length > 1;
93+
const hasCurrentPolicyPerDiemEnabled = !!policy?.arePerDiemRatesEnabled;
9494
const shouldShowPerDiemOption =
95-
iouType !== CONST.IOU.TYPE.SPLIT && iouType !== CONST.IOU.TYPE.TRACK && ((!isFromGlobalCreate && doesCurrentPolicyPerDiemExist) || (isFromGlobalCreate && doesPerDiemPolicyExist));
95+
iouType !== CONST.IOU.TYPE.SPLIT && iouType !== CONST.IOU.TYPE.TRACK && ((!isFromGlobalCreate && hasCurrentPolicyPerDiemEnabled) || (isFromGlobalCreate && doesPerDiemPolicyExist));
9696

9797
const transactionRequestType = useMemo(() => {
9898
if (!transaction?.iouRequestType) {
@@ -283,15 +283,15 @@ function IOURequestStartPage({
283283
<TopTab.Screen name={CONST.TAB_REQUEST.PER_DIEM}>
284284
{() => (
285285
<TabScreenWithFocusTrapWrapper>
286-
{moreThanOnePerDiemExist && !doesCurrentPolicyPerDiemExist ? (
286+
{moreThanOnePerDiemExist && !hasCurrentPolicyPerDiemEnabled ? (
287287
<IOURequestStepPerDiemWorkspace
288288
route={route}
289289
navigation={navigation}
290290
/>
291291
) : (
292292
<IOURequestStepDestination
293293
openedFromStartPage
294-
explicitPolicyID={moreThanOnePerDiemExist ? undefined : perDiemCustomUnits.at(0)?.policyID}
294+
explicitPolicyID={moreThanOnePerDiemExist ? undefined : policiesWithPerDiemEnabled.at(0)?.id}
295295
route={route}
296296
navigation={navigation}
297297
/>

src/pages/iou/request/step/IOURequestStepDestination.tsx

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React from 'react';
1+
import React, {useEffect} from 'react';
22
import {InteractionManager, View} from 'react-native';
33
import ActivityIndicator from '@components/ActivityIndicator';
44
import FullPageOfflineBlockingView from '@components/BlockingViews/FullPageOfflineBlockingView';
@@ -16,6 +16,7 @@ import useOnyx from '@hooks/useOnyx';
1616
import usePersonalPolicy from '@hooks/usePersonalPolicy';
1717
import useSafeAreaInsets from '@hooks/useSafeAreaInsets';
1818
import useThemeStyles from '@hooks/useThemeStyles';
19+
import {fetchPerDiemRates} from '@libs/actions/Policy/PerDiem';
1920
import {setTransactionReport} from '@libs/actions/Transaction';
2021
import Navigation from '@libs/Navigation/Navigation';
2122
import {getPerDiemCustomUnit, isPolicyAdmin} from '@libs/PolicyUtils';
@@ -119,6 +120,26 @@ function IOURequestStepDestination({
119120
[CONST.IOU.TYPE.CREATE]: translate('iou.createExpense'),
120121
};
121122

123+
useEffect(() => {
124+
if (!isEmptyObject(customUnit?.rates) || isOffline) {
125+
return;
126+
}
127+
fetchPerDiemRates(policy?.id);
128+
// eslint-disable-next-line react-compiler/react-compiler, react-hooks/exhaustive-deps
129+
}, [isOffline]);
130+
131+
useEffect(() => {
132+
// When the rates are not available for the policy, the transaction does not have valid customUnitID and moneyRequestCategory
133+
// So, we set these in the transaction when the rates are fetched in fetchPerDiemRates
134+
const perDiemUnit = getPerDiemCustomUnit(policy);
135+
if (!perDiemUnit || transaction?.comment?.customUnit?.customUnitID === perDiemUnit.customUnitID || !!transaction?.category) {
136+
return;
137+
}
138+
setCustomUnitID(transactionID, perDiemUnit?.customUnitID ?? CONST.CUSTOM_UNITS.FAKE_P2P_ID);
139+
setMoneyRequestCategory(transactionID, perDiemUnit?.defaultCategory ?? '');
140+
// eslint-disable-next-line react-compiler/react-compiler, react-hooks/exhaustive-deps
141+
}, [transactionID, policy?.customUnits]);
142+
122143
return (
123144
<ScreenWrapper
124145
includePaddingTop={false}

src/pages/iou/request/step/IOURequestStepPerDiemWorkspace.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails'
77
import useLocalize from '@hooks/useLocalize';
88
import useOnyx from '@hooks/useOnyx';
99
import Navigation from '@libs/Navigation/Navigation';
10-
import {canSubmitPerDiemExpenseFromWorkspace, getActivePolicies, getPerDiemCustomUnit, getPolicy, sortWorkspacesBySelected} from '@libs/PolicyUtils';
10+
import {getActivePoliciesWithExpenseChatAndPerDiemEnabled, getPerDiemCustomUnit, getPolicy, sortWorkspacesBySelected} from '@libs/PolicyUtils';
1111
import {getDefaultWorkspaceAvatar, getPolicyExpenseChat} from '@libs/ReportUtils';
1212
import {setCustomUnitID, setMoneyRequestCategory, setMoneyRequestParticipants} from '@userActions/IOU';
1313
import CONST from '@src/CONST';
@@ -38,7 +38,7 @@ function IOURequestStepPerDiemWorkspace({
3838
const selectedWorkspace = useMemo(() => transaction?.participants?.[0], [transaction]);
3939

4040
const workspaceOptions: WorkspaceListItem[] = useMemo(() => {
41-
const availableWorkspaces = getActivePolicies(allPolicies, currentUserLogin).filter((policy) => canSubmitPerDiemExpenseFromWorkspace(policy));
41+
const availableWorkspaces = getActivePoliciesWithExpenseChatAndPerDiemEnabled(allPolicies, currentUserLogin);
4242

4343
return availableWorkspaces
4444
.sort((policy1, policy2) =>

src/pages/iou/request/step/IOURequestStepTime.tsx

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React from 'react';
1+
import React, {useMemo} from 'react';
22
import {View} from 'react-native';
33
import type {OnyxEntry} from 'react-native-onyx';
44
import DatePicker from '@components/DatePicker';
@@ -7,14 +7,15 @@ import InputWrapper from '@components/Form/InputWrapper';
77
import type {FormOnyxValues} from '@components/Form/types';
88
import FullScreenLoadingIndicator from '@components/FullscreenLoadingIndicator';
99
import TimeModalPicker from '@components/TimeModalPicker';
10+
import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails';
1011
import useLocalize from '@hooks/useLocalize';
1112
import useOnyx from '@hooks/useOnyx';
1213
import useThemeStyles from '@hooks/useThemeStyles';
1314
import DateUtils from '@libs/DateUtils';
1415
import {addErrorMessage} from '@libs/ErrorUtils';
1516
import {isValidMoneyRequestType} from '@libs/IOUUtils';
1617
import Navigation from '@libs/Navigation/Navigation';
17-
import {getPerDiemCustomUnits} from '@libs/PolicyUtils';
18+
import {getActivePoliciesWithExpenseChatAndPerDiemEnabled} from '@libs/PolicyUtils';
1819
import {getIOURequestPolicyID, setMoneyRequestDateAttribute} from '@userActions/IOU';
1920
import CONST from '@src/CONST';
2021
import ONYXKEYS from '@src/ONYXKEYS';
@@ -51,17 +52,16 @@ function IOURequestStepTime({
5152
const styles = useThemeStyles();
5253
const [policy] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY}${getIOURequestPolicyID(transaction, report)}`, {canBeMissing: true});
5354
const [allPolicies] = useOnyx(ONYXKEYS.COLLECTION.POLICY, {canBeMissing: false});
54-
const [session] = useOnyx(ONYXKEYS.SESSION, {canBeMissing: false});
5555
const {translate} = useLocalize();
5656
const currentDateAttributes = transaction?.comment?.customUnit?.attributes?.dates;
5757
const currentStartDate = currentDateAttributes?.start ? DateUtils.extractDate(currentDateAttributes.start) : undefined;
5858
const currentEndDate = currentDateAttributes?.end ? DateUtils.extractDate(currentDateAttributes.end) : undefined;
5959
// eslint-disable-next-line rulesdir/no-negated-variables
6060
const shouldShowNotFound = !isValidMoneyRequestType(iouType) || isEmptyObject(transaction?.comment?.customUnit) || isEmptyObject(policy);
6161
const isEditPage = name === SCREENS.MONEY_REQUEST.STEP_TIME_EDIT;
62-
63-
const perDiemCustomUnits = getPerDiemCustomUnits(allPolicies, session?.email);
64-
const moreThanOnePerDiemExist = perDiemCustomUnits.length > 1;
62+
const {login: currentUserLogin} = useCurrentUserPersonalDetails();
63+
const policiesWithPerDiemEnabled = useMemo(() => getActivePoliciesWithExpenseChatAndPerDiemEnabled(allPolicies, currentUserLogin), [allPolicies, currentUserLogin]);
64+
const hasMoreThanOnePolicyWithPerDiemEnabled = policiesWithPerDiemEnabled.length > 1;
6565

6666
const navigateBack = () => {
6767
if (isEditPage) {
@@ -75,7 +75,7 @@ function IOURequestStepTime({
7575
}
7676

7777
if (transaction?.isFromGlobalCreate) {
78-
if (moreThanOnePerDiemExist) {
78+
if (hasMoreThanOnePolicyWithPerDiemEnabled) {
7979
Navigation.goBack(ROUTES.MONEY_REQUEST_STEP_DESTINATION.getRoute(action, iouType, transactionID, reportID));
8080
return;
8181
}

0 commit comments

Comments
 (0)