diff --git a/src/hooks/useBlockDistanceRequest.ts b/src/hooks/useBlockDistanceRequest.ts index b36d8b8a2b87..ebf1ae85c595 100644 --- a/src/hooks/useBlockDistanceRequest.ts +++ b/src/hooks/useBlockDistanceRequest.ts @@ -32,6 +32,9 @@ type UseBlockDistanceRequestParams = { /** Whether the current flow is for any distance request */ isDistanceRequest?: boolean; + + /** Whether an existing distance request is being edited */ + isEditingExistingDistanceRequest?: boolean; }; type PolicyRequiringMapOrGPS = { @@ -69,7 +72,13 @@ const hasHomeAddressSelector = (privatePersonalDetails: OnyxEntry { - if (!policyIDToCheck || !policiesRequiringMapOrGPS?.[policyIDToCheck]) { + if (!policyIDToCheck || !policiesRequiringMapOrGPS?.[policyIDToCheck] || isEditingExistingDistanceRequest) { return; } @@ -91,7 +100,7 @@ function useBlockDistanceRequest({policyID, isManualDistanceRequest = false, isO return 'homeAddressRequired'; } }, - [hasHomeAddress, isDistanceRequest, isManualDistanceRequest, isOdometerDistanceRequest, policiesRequiringMapOrGPS], + [hasHomeAddress, isDistanceRequest, isManualDistanceRequest, isOdometerDistanceRequest, isEditingExistingDistanceRequest, policiesRequiringMapOrGPS], ); const showBlockModal = useCallback( diff --git a/src/pages/iou/request/step/DynamicIOURequestStepDistanceManual.tsx b/src/pages/iou/request/step/DynamicIOURequestStepDistanceManual.tsx index 27442cf67a3e..91d6236e572c 100644 --- a/src/pages/iou/request/step/DynamicIOURequestStepDistanceManual.tsx +++ b/src/pages/iou/request/step/DynamicIOURequestStepDistanceManual.tsx @@ -159,6 +159,7 @@ function DynamicIOURequestStepDistanceManual({ const blockDistanceRequestIfNeeded = useBlockDistanceRequest({ policyID: report?.policyID ?? (shouldAutoReportToDefaultWorkspace ? defaultExpensePolicy?.id : undefined), isManualDistanceRequest: true, + isEditingExistingDistanceRequest: isEditing, }); // to make sure the correct distance amount and unit will be shown we use distance unit diff --git a/src/pages/iou/request/step/IOURequestStepDistanceOdometer.tsx b/src/pages/iou/request/step/IOURequestStepDistanceOdometer.tsx index cf034911a59e..122bd519bd8b 100644 --- a/src/pages/iou/request/step/IOURequestStepDistanceOdometer.tsx +++ b/src/pages/iou/request/step/IOURequestStepDistanceOdometer.tsx @@ -175,6 +175,7 @@ function IOURequestStepDistanceOdometer({ const blockDistanceRequestIfNeeded = useBlockDistanceRequest({ policyID: report?.policyID ?? (shouldAutoReportToDefaultWorkspace ? defaultExpensePolicy?.id : undefined), isOdometerDistanceRequest: true, + isEditingExistingDistanceRequest: isEditing, }); const mileageRate = DistanceRequestUtils.getRate({ diff --git a/tests/unit/TransactionUtilsTest.ts b/tests/unit/TransactionUtilsTest.ts index 13f42b8ce699..aad9d0f634a0 100644 --- a/tests/unit/TransactionUtilsTest.ts +++ b/tests/unit/TransactionUtilsTest.ts @@ -806,6 +806,58 @@ describe('TransactionUtils', () => { }, ); + it('does not apply a newly enabled commuter exclusion when a historical manual distance is changed', () => { + const fakePolicy: Policy = { + ...createRandomPolicy(0), + commuterExclusions: { + method: CONST.POLICY.COMMUTER_EXCLUSION_METHOD.FIXED_DISTANCE, + fixedDistance: 3, + fixedDistanceUnit: CONST.CUSTOM_UNITS.DISTANCE_UNIT_MILES, + }, + customUnits: { + distance: { + name: CONST.CUSTOM_UNITS.NAME_DISTANCE, + customUnitID: 'distance', + rates: { + default: { + customUnitRateID: '1', + currency: CONST.CURRENCY.USD, + rate: 1, + }, + }, + attributes: { + unit: CONST.CUSTOM_UNITS.DISTANCE_UNIT_MILES, + }, + }, + }, + }; + const transaction = generateTransaction({ + iouRequestType: CONST.IOU.REQUEST_TYPE.DISTANCE_MANUAL, + comment: { + customUnit: { + distanceUnit: CONST.CUSTOM_UNITS.DISTANCE_UNIT_MILES, + quantity: 10, + }, + }, + currency: CONST.CURRENCY.USD, + }); + + const updatedTransaction = TransactionUtils.getUpdatedTransaction({ + transaction, + isFromExpenseReport: false, + policy: fakePolicy, + transactionChanges: {distance: 20}, + personalPolicyOutputCurrency: undefined, + getCurrencyDecimals: getCurrencyDecimalsLocal, + getCurrencySymbol: getCurrencySymbolLocal, + }); + + expect(updatedTransaction.comment?.customUnit?.quantity).toBe(20); + expect(updatedTransaction.comment?.customUnit?.commuterExclusion).toBeUndefined(); + expect(updatedTransaction.comment?.customUnit?.reimbursableDistance).toBeUndefined(); + expect(updatedTransaction.modifiedAmount).toBe(20); + }); + it('recalculates commuter exclusion data when an alternate route is selected', () => { const fakePolicy: Policy = { ...createRandomPolicy(0), diff --git a/tests/unit/hooks/useBlockDistanceRequest.test.ts b/tests/unit/hooks/useBlockDistanceRequest.test.ts index 4076899d3c98..2e82ff3d055c 100644 --- a/tests/unit/hooks/useBlockDistanceRequest.test.ts +++ b/tests/unit/hooks/useBlockDistanceRequest.test.ts @@ -300,4 +300,28 @@ describe('useBlockDistanceRequest', () => { expect(result.current()).toBe(false); expect(mockShowConfirmModal).not.toHaveBeenCalled(); }); + + it('does not block editing an existing manual distance request', async () => { + await Onyx.merge(`${ONYXKEYS.COLLECTION.POLICY}policy_forced`, { + id: 'policy_forced', + name: 'Forced workspace', + commuterExclusions: { + method: 'fixedDistance', + fixedDistance: 1, + fixedDistanceUnit: 'mi', + }, + }); + await waitForBatchedUpdates(); + + const {result} = renderHook(() => + useBlockDistanceRequest({ + policyID: 'policy_forced', + isManualDistanceRequest: true, + isEditingExistingDistanceRequest: true, + }), + ); + + expect(result.current()).toBe(false); + expect(mockShowConfirmModal).not.toHaveBeenCalled(); + }); });