Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/ROUTES.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2650,8 +2650,8 @@ const ROUTES = {
},
WORKSPACE_CREATE_DISTANCE_RATE_UPGRADE: {
route: 'workspaces/:policyID/distance-rates/new/upgrade',
getRoute: (policyID: string, transactionID?: string, reportID?: string, iouType?: string, action?: string) =>
`workspaces/${policyID}/distance-rates/new/upgrade${transactionID ? `?transactionID=${transactionID}` : ''}${reportID ? `&reportID=${reportID}` : ''}${iouType ? `&iouType=${iouType}` : ''}${action ? `&action=${action}` : ''}` as const,
getRoute: (policyID: string, transactionID?: string, reportID?: string) =>
`workspaces/${policyID}/distance-rates/new/upgrade${transactionID ? `?transactionID=${transactionID}` : ''}${reportID ? `&reportID=${reportID}` : ''}` as const,
},
WORKSPACE_DISTANCE_RATES_SETTINGS: {
route: 'workspaces/:policyID/distance-rates/settings',
Expand Down
11 changes: 4 additions & 7 deletions src/components/MoneyRequestConfirmationList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -277,7 +277,7 @@ function MoneyRequestConfirmationList({
const [defaultMileageRateDraft] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY_DRAFTS}${policyID}`, {
selector: mileageRateSelector,
});
const {policyForMovingExpenses, shouldSelectPolicy} = usePolicyForMovingExpenses();
const {policyForMovingExpenses} = usePolicyForMovingExpenses();
const isMovingTransactionFromTrackExpense = isMovingTransactionFromTrackExpenseUtil(action);
const [defaultMileageRateReal] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY}${policyID}`, {
selector: mileageRateSelector,
Expand Down Expand Up @@ -347,12 +347,7 @@ function MoneyRequestConfirmationList({
const defaultRate = defaultMileageRate?.customUnitRateID;
const lastSelectedRate = policy?.id ? (lastSelectedDistanceRates?.[policy.id] ?? defaultRate) : defaultRate;

const mileageRate = DistanceRequestUtils.getRate({
transaction,
policy,
...(isMovingTransactionFromTrackExpense && {policyForMovingExpenses}),
policyDraft,
});
const mileageRate = DistanceRequestUtils.getRate({transaction, policy, policyDraft});
const rate = mileageRate.rate;
const prevRate = usePrevious(rate);
const unit = mileageRate.unit;
Expand All @@ -361,6 +356,8 @@ function MoneyRequestConfirmationList({
const prevCurrency = usePrevious(currency);
const prevSubRates = usePrevious(subRates);

const {shouldSelectPolicy} = usePolicyForMovingExpenses();

// A flag for showing the categories field
const shouldShowCategories = isTrackExpense
? !policy || shouldSelectPolicy || hasEnabledOptions(Object.values(policyCategories ?? {}))
Expand Down
16 changes: 5 additions & 11 deletions src/components/MoneyRequestConfirmationListFooter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -604,7 +604,7 @@ function MoneyRequestConfirmationListFooter({
return;
}

if ((!isPolicyExpenseChat && !isTrackExpense) || (shouldNavigateToUpgradePath && isTrackExpense)) {
if (!isPolicyExpenseChat) {
Navigation.navigate(
ROUTES.MONEY_REQUEST_UPGRADE.getRoute({
action,
Expand All @@ -613,22 +613,16 @@ function MoneyRequestConfirmationListFooter({
reportID,
upgradePath: CONST.UPGRADE_PATHS.DISTANCE_RATES,
backTo: Navigation.getActiveRoute(),
shouldSubmitExpense: !isTrackExpense,
shouldSubmitExpense: true,
}),
);
} else if (!policy && shouldSelectPolicy && isTrackExpense) {
Navigation.navigate(
ROUTES.SET_DEFAULT_WORKSPACE.getRoute(
ROUTES.MONEY_REQUEST_STEP_DISTANCE_RATE.getRoute(action, iouType, transactionID, reportID, Navigation.getActiveRoute(), reportActionID),
),
);
} else {
Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_DISTANCE_RATE.getRoute(action, iouType, transactionID, reportID, Navigation.getActiveRoute(), reportActionID));
return;
}
Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_DISTANCE_RATE.getRoute(action, iouType, transactionID, reportID, Navigation.getActiveRoute(), reportActionID));
}}
brickRoadIndicator={shouldDisplayDistanceRateError ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined}
disabled={didConfirm}
interactive={!!rate && !isReadOnly && iouType !== CONST.IOU.TYPE.SPLIT}
interactive={!!rate && !isReadOnly && iouType !== CONST.IOU.TYPE.SPLIT && !isUnreported}
sentryLabel={CONST.SENTRY_LABEL.REQUEST_CONFIRMATION_LIST.RATE_FIELD}
/>
),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React, {useEffect, useRef} from 'react';
import type {View} from 'react-native';
import type {OnyxEntry} from 'react-native-onyx';
import {getButtonRole} from '@components/Button/utils';
import OfflineWithFeedback from '@components/OfflineWithFeedback';
import {PressableWithFeedback} from '@components/Pressable';
Expand All @@ -17,7 +18,7 @@ import canUseTouchScreen from '@libs/DeviceCapabilities/canUseTouchScreen';
import {getTransactionPendingAction, isTransactionPendingDelete} from '@libs/TransactionUtils';
import variables from '@styles/variables';
import CONST from '@src/CONST';
import type {Report} from '@src/types/onyx';
import type {Policy, Report} from '@src/types/onyx';
import type {TransactionWithOptionalHighlight} from './MoneyRequestReportTransactionList';

type MoneyRequestReportTransactionItemProps = {
Expand All @@ -27,6 +28,9 @@ type MoneyRequestReportTransactionItemProps = {
/** Report to which the transaction belongs */
report: Report;

/** Policy to which the transaction belongs */
policy: OnyxEntry<Policy>;

/** Whether the mobile selection mode is enabled */
isSelectionModeEnabled: boolean;

Expand Down Expand Up @@ -67,6 +71,7 @@ type MoneyRequestReportTransactionItemProps = {
function MoneyRequestReportTransactionItem({
transaction,
report,
policy,
isSelectionModeEnabled,
toggleTransaction,
isSelected,
Expand Down Expand Up @@ -139,6 +144,7 @@ function MoneyRequestReportTransactionItem({
transactionItem={transaction}
violations={filteredViolations}
report={report}
policy={policy}
isSelected={isSelected}
dateColumnSize={dateColumnSize}
amountColumnSize={amountColumnSize}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -538,6 +538,7 @@ function MoneyRequestReportTransactionList({
shouldBeHighlighted={highlightedTransactionIDs.has(transaction.transactionID)}
columns={columnsToShow}
report={report}
policy={policy}
isSelectionModeEnabled={isMobileSelectionModeEnabled}
toggleTransaction={toggleTransaction}
isSelected={isTransactionSelected(transaction.transactionID)}
Expand All @@ -561,6 +562,7 @@ function MoneyRequestReportTransactionList({
shouldBeHighlighted={highlightedTransactionIDs.has(transaction.transactionID)}
columns={columnsToShow}
report={report}
policy={policy}
isSelectionModeEnabled={isMobileSelectionModeEnabled}
toggleTransaction={toggleTransaction}
isSelected={isTransactionSelected(transaction.transactionID)}
Expand Down
49 changes: 3 additions & 46 deletions src/components/ReportActionItem/MoneyRequestView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -345,7 +345,7 @@ function MoneyRequestView({
const canEditDate =
isEditable && canEditFieldOfMoneyRequest(parentReportAction, CONST.EDIT_REQUEST_FIELD.DATE, undefined, isChatReportArchived, undefined, transaction, moneyRequestReport, policy);

const canEditDistanceOrRate = isPolicyAccessible(policy, currentUserEmailParam) || isTrackExpense || isP2PDistanceRequest;
const canEditDistanceOrRate = isPolicyAccessible(policy, currentUserEmailParam) || isP2PDistanceRequest;

const canEditDistance =
!isGPSDistanceRequest &&
Expand Down Expand Up @@ -421,22 +421,8 @@ function MoneyRequestView({
const distance = getDistanceInMeters(transactionBackup ?? updatedTransaction ?? transaction, unit);
const currency = transactionCurrency ?? CONST.CURRENCY.USD;
const hasRequiredCompanyCardViolation = transactionViolations.some((violation) => violation.name === CONST.VIOLATIONS.COMPANY_CARD_REQUIRED);
const isCustomUnitOutOfPolicy =
(transactionViolations.some((violation) => violation.name === CONST.VIOLATIONS.CUSTOM_UNIT_OUT_OF_POLICY) || (isDistanceRequest && !rate)) && !isTrackExpense;
const calculateFromTransactionData = isTrackExpense && !rate;
const distanceUnit = calculateFromTransactionData ? transaction?.comment?.customUnit?.distanceUnit : unit;
const distanceRate = calculateFromTransactionData ? (transactionAmount ?? 0) / (transaction?.comment?.customUnit?.quantity ?? 1) : rate;
let rateToDisplay = DistanceRequestUtils.getRateForExpenseDisplay(
rateName,
isCustomUnitOutOfPolicy,
distanceUnit,
distanceRate,
currency,
translate,
toLocaleDigit,
getCurrencySymbol,
isOffline,
);
const isCustomUnitOutOfPolicy = transactionViolations.some((violation) => violation.name === CONST.VIOLATIONS.CUSTOM_UNIT_OUT_OF_POLICY) || (isDistanceRequest && !rate);
let rateToDisplay = DistanceRequestUtils.getRateForExpenseDisplay(rateName, isCustomUnitOutOfPolicy, unit, rate, currency, translate, toLocaleDigit, getCurrencySymbol, isOffline);
const distanceToDisplay = DistanceRequestUtils.getDistanceForDisplay(hasRoute, distance, unit, rate, translate, undefined, isManualDistanceRequest);
let merchantTitle = isEmptyMerchant ? '' : transactionMerchant;
let amountTitle = formattedTransactionAmount?.toString() || '';
Expand Down Expand Up @@ -667,35 +653,6 @@ function MoneyRequestView({
return;
}

if (isTrackExpense) {
if (shouldNavigateToUpgradePath && transactionThreadReport) {
Navigation.navigate(
ROUTES.MONEY_REQUEST_UPGRADE.getRoute({
action: CONST.IOU.ACTION.EDIT,
iouType,
transactionID: transaction.transactionID,
reportID: transactionThreadReport?.reportID,
upgradePath: CONST.UPGRADE_PATHS.DISTANCE_RATES,
}),
);
return;
}
if (!policy && shouldSelectPolicy) {
Navigation.navigate(
ROUTES.SET_DEFAULT_WORKSPACE.getRoute(
ROUTES.MONEY_REQUEST_STEP_DISTANCE_RATE.getRoute(
CONST.IOU.ACTION.EDIT,
iouType,
transaction.transactionID,
transactionThreadReport?.reportID,
Navigation.getActiveRoute(),
),
),
);
return;
}
}

Navigation.navigate(
ROUTES.MONEY_REQUEST_STEP_DISTANCE_RATE.getRoute(
CONST.IOU.ACTION.EDIT,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,7 @@ function TransactionGroupListExpanded<TItem extends ListItem>({
const transactionRow = (
<TransactionItemRow
report={transaction.report}
policy={transaction.policy}
transactionItem={transaction}
violations={getTransactionViolations(transaction, violations, currentUserDetails.email ?? '', currentUserDetails.accountID, transaction.report, transaction.policy)}
isSelected={!!transaction.isSelected}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,7 @@ function TransactionListItem<TItem extends ListItem>({
<TransactionItemRow
transactionItem={transactionItem}
report={transactionItem.report}
policy={transactionItem.policy}
shouldShowTooltip={showTooltip}
onButtonPress={handleActionButtonPress}
onCheckboxPress={() => onCheckboxPress?.(item)}
Expand Down
12 changes: 9 additions & 3 deletions src/components/TransactionItemRow/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ import {
isMerchantMissing,
isScanning,
isTimeRequest,
isUnreportedAndHasInvalidDistanceRateTransaction,
} from '@libs/TransactionUtils';
import CONST from '@src/CONST';
import type {TranslationPaths} from '@src/languages/types';
Expand Down Expand Up @@ -107,6 +108,7 @@ type TransactionWithOptionalSearchFields = TransactionWithOptionalHighlight & {
type TransactionItemRowProps = {
transactionItem: TransactionWithOptionalSearchFields;
report?: Report;
policy?: Policy;
shouldUseNarrowLayout: boolean;
isSelected: boolean;
shouldShowTooltip: boolean;
Expand Down Expand Up @@ -158,6 +160,7 @@ function getMerchantName(transactionItem: TransactionWithOptionalSearchFields, t
function TransactionItemRow({
transactionItem,
report,
policy,
shouldUseNarrowLayout,
isSelected,
shouldShowTooltip,
Expand Down Expand Up @@ -226,7 +229,9 @@ function TransactionItemRow({
return '';
}

const hasFieldErrors = hasMissingSmartscanFields(transactionItem, report);
const policyParam = policy ?? transactionItem.policy;
const isCustomUnitOutOfPolicy = isUnreportedAndHasInvalidDistanceRateTransaction(transactionItem, policyParam);
const hasFieldErrors = hasMissingSmartscanFields(transactionItem, report) || isCustomUnitOutOfPolicy;
if (hasFieldErrors) {
const amountMissing = isAmountMissing(transactionItem);
const merchantMissing = isMerchantMissing(transactionItem);
Expand All @@ -238,11 +243,12 @@ function TransactionItemRow({
error = translate('iou.missingAmount');
} else if (merchantMissing && !isSettled(report)) {
error = translate('iou.missingMerchant');
} else if (isCustomUnitOutOfPolicy) {
error = translate('violations.customUnitOutOfPolicy');
}

return error;
}
}, [transactionItem, translate, report]);
}, [transactionItem, translate, report, policy]);

const exchangeRateMessage = getExchangeRate(transactionItem);

Expand Down
7 changes: 2 additions & 5 deletions src/hooks/usePolicyForTransaction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,6 @@ type UsePolicyForTransactionParams = {
/** The type of IOU (split, track, submit, etc.) */
iouType: string;

/** The draft policy linked to the report */
policyDraft?: OnyxEntry<Policy>;

/** Indicates if the request is a per diem request */
isPerDiemRequest?: boolean;
};
Expand All @@ -33,7 +30,7 @@ type UsePolicyForTransactionResult = {
policy: OnyxEntry<Policy>;
};

function usePolicyForTransaction({transaction, reportPolicyID, action, iouType, policyDraft, isPerDiemRequest}: UsePolicyForTransactionParams): UsePolicyForTransactionResult {
function usePolicyForTransaction({transaction, reportPolicyID, action, iouType, isPerDiemRequest}: UsePolicyForTransactionParams): UsePolicyForTransactionResult {
const {policyForMovingExpenses} = usePolicyForMovingExpenses();

const [allPolicies] = useOnyx(ONYXKEYS.COLLECTION.POLICY);
Expand All @@ -48,7 +45,7 @@ function usePolicyForTransaction({transaction, reportPolicyID, action, iouType,
const isCreatingTrackExpense = action === CONST.IOU.ACTION.CREATE && iouType === CONST.IOU.TYPE.TRACK;

const policyForSelfDMExpense = isPerDiemRequest ? customUnitPolicy : policyForMovingExpenses;
const policy = isUnreportedExpense || isCreatingTrackExpense ? policyForSelfDMExpense : (reportPolicy ?? policyDraft);
const policy = isUnreportedExpense || isCreatingTrackExpense ? policyForSelfDMExpense : reportPolicy;

return {policy};
}
Expand Down
14 changes: 3 additions & 11 deletions src/libs/DistanceRequestUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -338,14 +338,12 @@ function getCustomUnitRateID({
reportID,
isPolicyExpenseChat,
policy,
isTrackDistanceExpense = false,
lastSelectedDistanceRates,
}: {
reportID: string | undefined;
isPolicyExpenseChat: boolean;
policy: OnyxEntry<Policy> | undefined;
lastSelectedDistanceRates?: OnyxEntry<LastSelectedDistanceRates>;
isTrackDistanceExpense?: boolean;
}): string {
let customUnitRateID: string = CONST.CUSTOM_UNITS.FAKE_P2P_ID;

Expand All @@ -361,12 +359,11 @@ function getCustomUnitRateID({
return customUnitRateID;
}

// For TrackDistanceExpense we will return the default rate of the policyForMovingExpenses.
if (isPolicyExpenseChat || isTrackDistanceExpense) {
if (isPolicyExpenseChat) {
const distanceUnit = Object.values(policy.customUnits ?? {}).find((unit) => unit.name === CONST.CUSTOM_UNITS.NAME_DISTANCE);
const lastSelectedDistanceRateID = lastSelectedDistanceRates?.[policy.id];
const lastSelectedDistanceRate = lastSelectedDistanceRateID ? distanceUnit?.rates[lastSelectedDistanceRateID] : undefined;
if (!isTrackDistanceExpense && lastSelectedDistanceRate?.enabled && lastSelectedDistanceRateID) {
if (lastSelectedDistanceRate?.enabled && lastSelectedDistanceRateID) {
customUnitRateID = lastSelectedDistanceRateID;
} else {
const defaultMileageRate = getDefaultMileageRate(policy);
Expand Down Expand Up @@ -411,19 +408,16 @@ function getRate({
policy,
policyDraft,
useTransactionDistanceUnit = true,
policyForMovingExpenses,
}: {
transaction: OnyxEntry<Transaction>;
policy: OnyxEntry<Policy>;
policyDraft?: OnyxEntry<Policy>;
policyForMovingExpenses?: OnyxEntry<Policy>;
useTransactionDistanceUnit?: boolean;
}): MileageRate {
let mileageRates = getMileageRates(policy, true, transaction?.comment?.customUnit?.customUnitRateID);
if (isEmptyObject(mileageRates) && policyDraft) {
mileageRates = getMileageRates(policyDraft, true, transaction?.comment?.customUnit?.customUnitRateID);
}
const mileageRatesForMovingExpenses = getMileageRates(policyForMovingExpenses, true, transaction?.comment?.customUnit?.customUnitRateID);
// This will be fixed as part of https://github.com/Expensify/App/issues/66397
// eslint-disable-next-line @typescript-eslint/no-deprecated
const policyCurrency = policy?.outputCurrency ?? getPersonalPolicy()?.outputCurrency ?? CONST.CURRENCY.USD;
Expand All @@ -434,10 +428,8 @@ function getRate({
const currency = isExpenseUnreported(transaction) ? transactionCurrency : policyCurrency;
const defaultMileageRate = getDefaultMileageRate(policy);
const customUnitRateID = getRateID(transaction);
const isUnreportedExpense = isExpenseUnreported(transaction);
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
const customMileageRate =
(customUnitRateID && (mileageRates?.[customUnitRateID] ?? mileageRatesForMovingExpenses?.[customUnitRateID])) || (isUnreportedExpense ? undefined : defaultMileageRate);
const customMileageRate = (customUnitRateID && mileageRates?.[customUnitRateID]) || defaultMileageRate;
const mileageRate = isCustomUnitRateIDForP2P(transaction) ? getRateForP2P(currency, transaction) : customMileageRate;
const unit = getDistanceUnit(useTransactionDistanceUnit ? transaction : undefined, mileageRate);
return {
Expand Down
Loading
Loading