Skip to content

Commit 963a160

Browse files
committed
Fix - After moving distance expense to Self DM, "Distance" field is shown as "Pending"
1 parent 5715b45 commit 963a160

6 files changed

Lines changed: 50 additions & 10 deletions

File tree

src/components/ReportActionItem/MoneyRequestView.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,7 @@ function MoneyRequestView({report, shouldShowAnimatedBackground, readonly = fals
250250
const {unit, rate} = DistanceRequestUtils.getRate({transaction, policy});
251251
const distance = getDistanceInMeters(transactionBackup ?? transaction, unit);
252252
const currency = transactionCurrency ?? CONST.CURRENCY.USD;
253-
const isCustomUnitOutOfPolicy = transactionViolations.some((violation) => violation.name === CONST.VIOLATIONS.CUSTOM_UNIT_OUT_OF_POLICY);
253+
const isCustomUnitOutOfPolicy = transactionViolations.some((violation) => violation.name === CONST.VIOLATIONS.CUSTOM_UNIT_OUT_OF_POLICY) || !rate;
254254
const rateToDisplay = isCustomUnitOutOfPolicy ? translate('common.rateOutOfPolicy') : DistanceRequestUtils.getRateForDisplay(unit, rate, currency, translate, toLocaleDigit, isOffline);
255255
const distanceToDisplay = DistanceRequestUtils.getDistanceForDisplay(hasRoute, distance, unit, rate, translate);
256256
let merchantTitle = isEmptyMerchant ? '' : transactionMerchant;
@@ -345,6 +345,10 @@ function MoneyRequestView({report, shouldShowAnimatedBackground, readonly = fals
345345
return translate(translationPath);
346346
}
347347

348+
if (isCustomUnitOutOfPolicy && field === 'customUnitRateID') {
349+
return translate('violations.customUnitOutOfPolicy');
350+
}
351+
348352
// Return violations if there are any
349353
if (field !== 'merchant' && hasViolations(field, data, policyHasDependentTags, tagValue)) {
350354
const violations = getViolationsForField(field, data, policyHasDependentTags, tagValue);
@@ -373,6 +377,7 @@ function MoneyRequestView({report, shouldShowAnimatedBackground, readonly = fals
373377
canEditDate,
374378
canEditMerchant,
375379
canEdit,
380+
isCustomUnitOutOfPolicy,
376381
],
377382
);
378383

src/components/TransactionItemRow/index.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import {
3030
isMerchantMissing,
3131
isReceiptBeingScanned,
3232
isTransactionPendingDelete,
33+
isUnreportedAndHasInvalidDistanceRateTransaction,
3334
} from '@libs/TransactionUtils';
3435
import variables from '@styles/variables';
3536
import CONST from '@src/CONST';
@@ -176,7 +177,8 @@ function TransactionItemRow({
176177

177178
const merchantOrDescriptionName = useMemo(() => getMerchantNameWithFallback(transactionItem, translate, shouldUseNarrowLayout), [shouldUseNarrowLayout, transactionItem, translate]);
178179
const missingFieldError = useMemo(() => {
179-
const hasFieldErrors = hasMissingSmartscanFields(transactionItem);
180+
const isCustomUnitOutOfPolicy = isUnreportedAndHasInvalidDistanceRateTransaction(transactionItem);
181+
const hasFieldErrors = hasMissingSmartscanFields(transactionItem) || isCustomUnitOutOfPolicy;
180182
if (hasFieldErrors) {
181183
const amountMissing = isAmountMissing(transactionItem);
182184
const merchantMissing = isMerchantMissing(transactionItem);
@@ -188,6 +190,8 @@ function TransactionItemRow({
188190
error = translate('iou.missingAmount');
189191
} else if (merchantMissing) {
190192
error = translate('iou.missingMerchant');
193+
} else if (isCustomUnitOutOfPolicy) {
194+
error = translate('violations.customUnitOutOfPolicy');
191195
}
192196
return error;
193197
}

src/libs/DistanceRequestUtils.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@ function getDistanceForDisplay(
186186
translate: LocaleContextProps['translate'],
187187
useShortFormUnit?: boolean,
188188
): string {
189-
if (!hasRoute || !rate || !unit || !distanceInMeters) {
189+
if (!hasRoute || !unit || !distanceInMeters) {
190190
return translate('iou.fieldPending');
191191
}
192192

src/libs/SearchUIUtils.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ import {
7171
getCreated as getTransactionCreatedDate,
7272
getMerchant as getTransactionMerchant,
7373
isPendingCardOrScanningTransaction,
74+
isUnreportedAndHasInvalidDistanceRateTransaction,
7475
isViolationDismissed,
7576
} from './TransactionUtils';
7677
import shouldShowTransactionYear from './TransactionUtils/shouldShowTransactionYear';
@@ -647,6 +648,11 @@ function getAction(data: OnyxTypes.SearchResults['data'], allViolations: OnyxCol
647648
if (!isTransaction && !isReportEntry(key)) {
648649
return CONST.SEARCH.ACTION_TYPES.VIEW;
649650
}
651+
652+
const transaction = isTransaction ? data[key] : undefined;
653+
if (isUnreportedAndHasInvalidDistanceRateTransaction(transaction)) {
654+
return CONST.SEARCH.ACTION_TYPES.REVIEW;
655+
}
650656
// Tracked and unreported expenses don't have a report, so we return early.
651657
if (!report) {
652658
return CONST.SEARCH.ACTION_TYPES.VIEW;
@@ -656,7 +662,6 @@ function getAction(data: OnyxTypes.SearchResults['data'], allViolations: OnyxCol
656662
return CONST.SEARCH.ACTION_TYPES.PAID;
657663
}
658664

659-
const transaction = isTransaction ? data[key] : undefined;
660665
// We need to check both options for a falsy value since the transaction might not have an error but the report associated with it might. We return early if there are any errors for performance reasons, so we don't need to compute any other possible actions.
661666
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
662667
if (transaction?.errors || report?.errors) {

src/libs/TransactionPreviewUtils.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ import {
3333
isPending,
3434
isPerDiemRequest,
3535
isScanning,
36+
isUnreportedAndHasInvalidDistanceRateTransaction,
3637
} from './TransactionUtils';
3738

3839
const emptyPersonalDetails: OnyxTypes.PersonalDetails = {
@@ -204,12 +205,14 @@ function getTransactionPreviewTextAndTranslationPaths({
204205
RBRMessage = actionsWithErrors.length > 1 ? {translationPath: 'violations.reviewRequired'} : {text: actionsWithErrors.at(0)};
205206
}
206207

207-
RBRMessage ??= {text: ''};
208-
209208
let previewHeaderText: TranslationPathOrText[] = [showCashOrCard];
210209

211210
if (isDistanceRequest(transaction)) {
212211
previewHeaderText = [{translationPath: 'common.distance'}];
212+
213+
if (RBRMessage === undefined && isUnreportedAndHasInvalidDistanceRateTransaction(transaction)) {
214+
RBRMessage = {translationPath: 'violations.customUnitOutOfPolicy'};
215+
}
213216
} else if (isPerDiemRequest(transaction)) {
214217
previewHeaderText = [{translationPath: 'common.perDiem'}];
215218
} else if (isTransactionScanning) {
@@ -218,6 +221,8 @@ function getTransactionPreviewTextAndTranslationPaths({
218221
previewHeaderText = [{translationPath: 'iou.split'}];
219222
}
220223

224+
RBRMessage ??= {text: ''};
225+
221226
if (!isCreatedMissing(transaction)) {
222227
const created = getFormattedCreated(transaction);
223228
const date = DateUtils.formatWithUTCTimeZone(created, DateUtils.doesDateBelongToAPastYear(created) ? CONST.DATE.MONTH_DAY_YEAR_ABBR_FORMAT : CONST.DATE.MONTH_DAY_ABBR_FORMAT);
@@ -310,7 +315,7 @@ function createTransactionPreviewConditionals({
310315
const shouldShowCategory = !!category && isReportAPolicyExpenseChat;
311316

312317
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
313-
const hasAnyViolations = hasViolationsOfTypeNotice || hasWarningTypeViolation(transaction?.transactionID, violations, true) || hasViolation(transaction, violations, true);
318+
const hasAnyViolations = isUnreportedAndHasInvalidDistanceRateTransaction(transaction) || hasViolationsOfTypeNotice || hasWarningTypeViolation(transaction?.transactionID, violations, true) || hasViolation(transaction, violations, true);
314319
const hasErrorOrOnHold = hasFieldErrors || (!isFullySettled && !isFullyApproved && isTransactionOnHold);
315320
const hasReportViolationsOrActionErrors = (isReportOwner(iouReport) && hasReportViolations(iouReport?.reportID)) || hasActionsWithErrors(iouReport?.reportID);
316321
const shouldShowRBR = hasAnyViolations || hasErrorOrOnHold || hasReportViolationsOrActionErrors;

src/libs/TransactionUtils/index.ts

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -656,6 +656,24 @@ function isFetchingWaypointsFromServer(transaction: OnyxInputOrEntry<Transaction
656656
return !!transaction?.pendingFields?.waypoints;
657657
}
658658

659+
/**
660+
* Verify that the transaction is in Self DM and that its distance rate is invalid.
661+
*/
662+
function isUnreportedAndHasInvalidDistanceRateTransaction(transaction: OnyxInputOrEntry<Transaction>, policyParam: OnyxEntry<Policy> = undefined) {
663+
if (transaction && isDistanceRequest(transaction)) {
664+
const report = getReportOrDraftReport(transaction.reportID);
665+
const policy = policyParam ?? getPolicy(report?.policyID);
666+
const {rate} = DistanceRequestUtils.getRate({transaction, policy});
667+
const isUnreported = !transaction.reportID || transaction.reportID === CONST.REPORT.UNREPORTED_REPORT_ID;
668+
669+
if (isUnreported && !rate) {
670+
return true;
671+
}
672+
}
673+
674+
return false;
675+
}
676+
659677
/**
660678
* Return the merchant field from the transaction, return the modifiedMerchant if present.
661679
*/
@@ -668,9 +686,11 @@ function getMerchant(transaction: OnyxInputOrEntry<Transaction>, policyParam: On
668686
const mileageRate = DistanceRequestUtils.getRate({transaction, policy});
669687
const {unit, rate} = mileageRate;
670688
const distanceInMeters = getDistanceInMeters(transaction, unit);
671-
return DistanceRequestUtils.getDistanceMerchant(true, distanceInMeters, unit, rate, transaction.currency, translateLocal, (digit) =>
672-
toLocaleDigit(TranslationStore.getCurrentLocale(), digit),
673-
);
689+
if (!isUnreportedAndHasInvalidDistanceRateTransaction(transaction, policy)) {
690+
return DistanceRequestUtils.getDistanceMerchant(true, distanceInMeters, unit, rate, transaction.currency, translateLocal, (digit) =>
691+
toLocaleDigit(TranslationStore.getCurrentLocale(), digit),
692+
);
693+
}
674694
}
675695
return transaction?.modifiedMerchant ? transaction.modifiedMerchant : (transaction?.merchant ?? '');
676696
}
@@ -1728,6 +1748,7 @@ export {
17281748
getTransactionPendingAction,
17291749
isTransactionPendingDelete,
17301750
createUnreportedExpenseSections,
1751+
isUnreportedAndHasInvalidDistanceRateTransaction,
17311752
};
17321753

17331754
export type {TransactionChanges};

0 commit comments

Comments
 (0)