diff --git a/src/components/MoneyRequestConfirmationList.tsx b/src/components/MoneyRequestConfirmationList.tsx index 5ffd9beda6fe..fda8ea531f5a 100755 --- a/src/components/MoneyRequestConfirmationList.tsx +++ b/src/components/MoneyRequestConfirmationList.tsx @@ -293,13 +293,13 @@ function MoneyRequestConfirmationList({ const canUpdateSenderWorkspace = useMemo(() => PolicyUtils.canSendInvoice(allPolicies) && !!transaction?.isFromGlobalCreate, [allPolicies, transaction?.isFromGlobalCreate]); + const canModifyTaxFields = !isReadOnly && !isDistanceRequest; + // A flag for showing the tags field // TODO: remove the !isTypeInvoice from this condition after BE supports tags for invoices: https://github.com/Expensify/App/issues/41281 const shouldShowTags = useMemo(() => isPolicyExpenseChat && OptionsListUtils.hasEnabledTags(policyTagLists) && !isTypeInvoice, [isPolicyExpenseChat, policyTagLists, isTypeInvoice]); - // A flag for showing tax rate - // TODO: remove the !isTypeInvoice from this condition after BE supports tax for invoices: https://github.com/Expensify/App/issues/41281 - const shouldShowTax = isTaxTrackingEnabled(isPolicyExpenseChat, policy) && !isTypeInvoice; + const shouldShowTax = isTaxTrackingEnabled(isPolicyExpenseChat, policy, isDistanceRequest) && !isTypeInvoice; // A flag for showing the billable field const shouldShowBillable = policy?.disabledFields?.defaultBillable === false; @@ -1023,14 +1023,14 @@ function MoneyRequestConfirmationList({ item: ( Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_TAX_RATE.getRoute(action, iouType, transactionID, reportID, Navigation.getActiveRouteWithoutParams()))} disabled={didConfirm} - interactive={!isReadOnly} + interactive={canModifyTaxFields} /> ), shouldShow: shouldShowTax, @@ -1040,14 +1040,14 @@ function MoneyRequestConfirmationList({ item: ( Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_TAX_AMOUNT.getRoute(action, iouType, transactionID, reportID, Navigation.getActiveRouteWithoutParams()))} disabled={didConfirm} - interactive={!isReadOnly} + interactive={canModifyTaxFields} /> ), shouldShow: shouldShowTax, diff --git a/src/components/ReportActionItem/MoneyRequestView.tsx b/src/components/ReportActionItem/MoneyRequestView.tsx index 0380780e0ccb..93222e285573 100644 --- a/src/components/ReportActionItem/MoneyRequestView.tsx +++ b/src/components/ReportActionItem/MoneyRequestView.tsx @@ -141,6 +141,8 @@ function MoneyRequestView({ // Used for non-restricted fields such as: description, category, tag, billable, etc. const canEdit = ReportUtils.canEditMoneyRequest(parentReportAction); + const canEditTaxFields = canEdit && !isDistanceRequest; + const canEditAmount = ReportUtils.canEditFieldOfMoneyRequest(parentReportAction, CONST.EDIT_REQUEST_FIELD.AMOUNT); const canEditMerchant = ReportUtils.canEditFieldOfMoneyRequest(parentReportAction, CONST.EDIT_REQUEST_FIELD.MERCHANT); const canEditDate = ReportUtils.canEditFieldOfMoneyRequest(parentReportAction, CONST.EDIT_REQUEST_FIELD.DATE); @@ -170,8 +172,7 @@ function MoneyRequestView({ const shouldShowTag = isPolicyExpenseChat && (transactionTag || OptionsListUtils.hasEnabledTags(policyTagLists)); const shouldShowBillable = isPolicyExpenseChat && (!!transactionBillable || !(policy?.disabledFields?.defaultBillable ?? true)); - // A flag for showing tax rate - const shouldShowTax = isTaxTrackingEnabled(isPolicyExpenseChat, policy); + const shouldShowTax = isTaxTrackingEnabled(isPolicyExpenseChat, policy, isDistanceRequest); const {getViolationsForField} = useViolations(transactionViolations ?? []); const hasViolations = useCallback( @@ -504,8 +505,8 @@ function MoneyRequestView({ Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_TAX_RATE.getRoute(CONST.IOU.ACTION.EDIT, iouType, transaction?.transactionID ?? '', report.reportID)) @@ -521,8 +522,8 @@ function MoneyRequestView({ Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_TAX_AMOUNT.getRoute(CONST.IOU.ACTION.EDIT, iouType, transaction?.transactionID ?? '', report.reportID)) diff --git a/src/libs/PolicyUtils.ts b/src/libs/PolicyUtils.ts index 6a26b1a6cfc2..3f7cfb092d22 100644 --- a/src/libs/PolicyUtils.ts +++ b/src/libs/PolicyUtils.ts @@ -263,8 +263,13 @@ function isPaidGroupPolicy(policy: OnyxEntry | EmptyObject): boolean { return policy?.type === CONST.POLICY.TYPE.TEAM || policy?.type === CONST.POLICY.TYPE.CORPORATE; } -function isTaxTrackingEnabled(isPolicyExpenseChat: boolean, policy: OnyxEntry): boolean { - return (isPolicyExpenseChat && (policy?.tax?.trackingEnabled ?? policy?.isTaxTrackingEnabled)) ?? false; +function isTaxTrackingEnabled(isPolicyExpenseChat: boolean, policy: OnyxEntry, isDistanceRequest: boolean): boolean { + const distanceUnit = Object.values(policy?.customUnits ?? {}).find((unit) => unit.name === CONST.CUSTOM_UNITS.NAME_DISTANCE); + const customUnitID = distanceUnit?.customUnitID ?? 0; + const isPolicyTaxTrackingEnabled = isPolicyExpenseChat && policy?.tax?.trackingEnabled; + const isTaxEnabledForDistance = isPolicyTaxTrackingEnabled && policy?.customUnits?.[customUnitID]?.attributes?.taxEnabled; + + return !!(isDistanceRequest ? isTaxEnabledForDistance : isPolicyTaxTrackingEnabled); } /** diff --git a/src/pages/iou/request/step/IOURequestStepDistanceRate.tsx b/src/pages/iou/request/step/IOURequestStepDistanceRate.tsx index 1b9ccf1876cf..1879f56f86f9 100644 --- a/src/pages/iou/request/step/IOURequestStepDistanceRate.tsx +++ b/src/pages/iou/request/step/IOURequestStepDistanceRate.tsx @@ -7,9 +7,12 @@ import Text from '@components/Text'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; import * as IOU from '@libs/actions/IOU'; +import * as CurrencyUtils from '@libs/CurrencyUtils'; import type {MileageRate} from '@libs/DistanceRequestUtils'; import DistanceRequestUtils from '@libs/DistanceRequestUtils'; import Navigation from '@libs/Navigation/Navigation'; +import {isTaxTrackingEnabled} from '@libs/PolicyUtils'; +import * as ReportUtils from '@libs/ReportUtils'; import * as TransactionUtils from '@libs/TransactionUtils'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; @@ -37,6 +40,7 @@ type IOURequestStepDistanceRateProps = IOURequestStepDistanceRateOnyxProps & function IOURequestStepDistanceRate({ policy, + report, route: { params: {backTo, transactionID}, }, @@ -45,6 +49,11 @@ function IOURequestStepDistanceRate({ }: IOURequestStepDistanceRateProps) { const styles = useThemeStyles(); const {translate, toLocaleDigit} = useLocalize(); + const isDistanceRequest = TransactionUtils.isDistanceRequest(transaction); + const distanceUnit = Object.values(policy?.customUnits ?? {}).find((unit) => unit.name === CONST.CUSTOM_UNITS.NAME_DISTANCE); + const customUnitID = distanceUnit?.customUnitID; + const isPolicyExpenseChat = ReportUtils.isReportInGroupPolicy(report); + const shouldShowTax = isTaxTrackingEnabled(isPolicyExpenseChat, policy, isDistanceRequest); const lastSelectedRateID = TransactionUtils.getRateID(transaction) ?? ''; @@ -69,6 +78,15 @@ function IOURequestStepDistanceRate({ const initiallyFocusedOption = sections.find((item) => item.isSelected)?.keyForList; function selectDistanceRate(customUnitRateID: string) { + if (transaction?.amount && policy?.customUnits && customUnitID && shouldShowTax) { + const taxClaimablePercentage = policy?.customUnits[customUnitID].rates[customUnitRateID].attributes?.taxClaimablePercentage ?? 0; + const taxRateExternalID = policy?.customUnits[customUnitID].rates[customUnitRateID].attributes?.taxRateExternalID ?? ''; + const taxableAmount = -1 * transaction.amount * taxClaimablePercentage; + const taxPercentage = TransactionUtils.getTaxValue(policy, transaction, taxRateExternalID) ?? ''; + const taxAmount = CurrencyUtils.convertToBackendAmount(TransactionUtils.calculateTaxAmount(taxPercentage, taxableAmount)); + IOU.setMoneyRequestTaxAmount(transactionID, taxAmount, true); + IOU.setMoneyRequestTaxRate(transactionID, taxRateExternalID); + } IOU.updateDistanceRequestRate(transactionID, customUnitRateID, policy?.id ?? ''); navigateBack(); } diff --git a/src/types/onyx/Policy.ts b/src/types/onyx/Policy.ts index 53c76286985d..734520532be8 100644 --- a/src/types/onyx/Policy.ts +++ b/src/types/onyx/Policy.ts @@ -7,6 +7,11 @@ import type {WorkspaceTravelSettings} from './TravelSettings'; type Unit = 'mi' | 'km'; +type TaxRateAttributes = { + taxClaimablePercentage?: number; + taxRateExternalID?: string; +}; + type Rate = OnyxCommon.OnyxValueWithOfflineFeedback<{ name?: string; rate?: number; @@ -15,10 +20,12 @@ type Rate = OnyxCommon.OnyxValueWithOfflineFeedback<{ enabled?: boolean; errors?: OnyxCommon.Errors; errorFields?: OnyxCommon.ErrorFields; + attributes?: TaxRateAttributes; }>; type Attributes = { unit: Unit; + taxEnabled?: boolean; }; type CustomUnit = OnyxCommon.OnyxValueWithOfflineFeedback<{