From d662517b82bf85938e16737a6dbbb37d34d35a04 Mon Sep 17 00:00:00 2001 From: Nicolay Arefyeu Date: Fri, 17 May 2024 14:59:10 +0300 Subject: [PATCH 1/9] Add tax fields for distance requests --- .../MoneyRequestConfirmationList.tsx | 18 ++++++++--------- .../ReportActionItem/MoneyRequestView.tsx | 14 +++++++------ src/libs/PolicyUtils.ts | 6 ++++-- src/libs/actions/IOU.ts | 5 ++++- .../step/IOURequestStepDistanceRate.tsx | 20 ++++++++++++++++++- src/types/onyx/Policy.ts | 2 ++ 6 files changed, 46 insertions(+), 19 deletions(-) diff --git a/src/components/MoneyRequestConfirmationList.tsx b/src/components/MoneyRequestConfirmationList.tsx index 5ffd9beda6f..35d51a44510 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, customUnitRateID, isDistanceRequest) && !isTypeInvoice; // A flag for showing the billable field const shouldShowBillable = policy?.disabledFields?.defaultBillable === false; @@ -371,7 +371,7 @@ function MoneyRequestConfirmationList({ // Calculate and set tax amount in transaction draft useEffect(() => { - const taxAmount = getTaxAmount(transaction, policy).toString(); + const taxAmount = isDistanceRequest && isOffline ? (transaction?.taxAmount ?? 0).toString() : getTaxAmount(transaction, policy).toString(); const amountInSmallestCurrencyUnits = CurrencyUtils.convertToBackendAmount(Number.parseFloat(taxAmount)); if (transaction?.taxAmount && previousTransactionAmount === transaction?.amount && previousTransactionCurrency === transaction?.currency) { @@ -379,7 +379,7 @@ function MoneyRequestConfirmationList({ } IOU.setMoneyRequestTaxAmount(transactionID, amountInSmallestCurrencyUnits, true); - }, [policy, transaction, transactionID, previousTransactionAmount, previousTransactionCurrency]); + }, [policy, transaction, transactionID, previousTransactionAmount, previousTransactionCurrency, isOffline, isDistanceRequest]); // If completing a split expense fails, set didConfirm to false to allow the user to edit the fields again if (isEditingSplitBill && didConfirm) { @@ -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 0380780e0cc..3dba19d5a06 100644 --- a/src/components/ReportActionItem/MoneyRequestView.tsx +++ b/src/components/ReportActionItem/MoneyRequestView.tsx @@ -132,6 +132,7 @@ function MoneyRequestView({ const taxRates = policy?.taxRates; const formattedTaxAmount = CurrencyUtils.convertToDisplayString(transactionTaxAmount, transactionCurrency); + const customUnitRateID = TransactionUtils.getRateID(transaction) ?? ''; const taxRatesDescription = taxRates?.name; const taxRateTitle = TransactionUtils.getTaxName(policy, transaction); @@ -141,6 +142,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 +173,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, customUnitRateID, isDistanceRequest); const {getViolationsForField} = useViolations(transactionViolations ?? []); const hasViolations = useCallback( @@ -504,8 +506,8 @@ function MoneyRequestView({ Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_TAX_RATE.getRoute(CONST.IOU.ACTION.EDIT, iouType, transaction?.transactionID ?? '', report.reportID)) @@ -521,8 +523,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 6a26b1a6cfc..02d1c84b614 100644 --- a/src/libs/PolicyUtils.ts +++ b/src/libs/PolicyUtils.ts @@ -263,8 +263,10 @@ 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, customUnitRateID: string, isDistanceRequest: boolean): boolean { + const isTaxEnabled = policy?.customUnits?.[customUnitRateID]?.attributes?.taxEnabled; + const isPolicyTaxTrackingEnabled = isPolicyExpenseChat && policy?.tax?.trackingEnabled; + return (isDistanceRequest ? isPolicyTaxTrackingEnabled && isTaxEnabled : isPolicyTaxTrackingEnabled) ?? false; } /** diff --git a/src/libs/actions/IOU.ts b/src/libs/actions/IOU.ts index 2464dbff7db..dbf0cc44f93 100644 --- a/src/libs/actions/IOU.ts +++ b/src/libs/actions/IOU.ts @@ -421,9 +421,12 @@ function setCustomUnitRateID(transactionID: string, customUnitRateID: string) { } /** Update transaction distance rate */ -function updateDistanceRequestRate(transactionID: string, rateID: string, policyID: string) { +function updateDistanceRequestRate(transactionID: string, rateID: string, policyID: string, taxAmount?: number) { Onyx.merge(ONYXKEYS.NVP_LAST_SELECTED_DISTANCE_RATES, {[policyID]: rateID}); Onyx.merge(`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${transactionID}`, {comment: {customUnit: {customUnitRateID: rateID}}}); + if (taxAmount) { + Onyx.merge(`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${transactionID}`, {taxAmount}); + } } /** Helper function to get the receipt error for expenses, or the generic error if there's no receipt */ diff --git a/src/pages/iou/request/step/IOURequestStepDistanceRate.tsx b/src/pages/iou/request/step/IOURequestStepDistanceRate.tsx index 1b9ccf1876c..71414eb68c0 100644 --- a/src/pages/iou/request/step/IOURequestStepDistanceRate.tsx +++ b/src/pages/iou/request/step/IOURequestStepDistanceRate.tsx @@ -5,11 +5,14 @@ import SelectionList from '@components/SelectionList'; import RadioListItem from '@components/SelectionList/RadioListItem'; import Text from '@components/Text'; import useLocalize from '@hooks/useLocalize'; +import useNetwork from '@hooks/useNetwork'; 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 * as ReportUtils from '@libs/ReportUtils'; import * as TransactionUtils from '@libs/TransactionUtils'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; @@ -45,6 +48,15 @@ function IOURequestStepDistanceRate({ }: IOURequestStepDistanceRateProps) { const styles = useThemeStyles(); const {translate, toLocaleDigit} = useLocalize(); + const isDistanceRequest = TransactionUtils.isDistanceRequest(transaction); + const transactionDetails = ReportUtils.getTransactionDetails(transaction); + const currency = transactionDetails?.currency; + const distanceUnit = Object.values(policy?.customUnits ?? {}).find((unit) => unit.name === CONST.CUSTOM_UNITS.NAME_DISTANCE); + const customUnitID = distanceUnit?.customUnitID; + const {isOffline} = useNetwork(); + + const defaultTaxCode = TransactionUtils.getDefaultTaxCode(policy, transaction, currency) ?? ''; + const taxPercentage = TransactionUtils.getTaxValue(policy, transaction, defaultTaxCode) ?? ''; const lastSelectedRateID = TransactionUtils.getRateID(transaction) ?? ''; @@ -69,7 +81,13 @@ function IOURequestStepDistanceRate({ const initiallyFocusedOption = sections.find((item) => item.isSelected)?.keyForList; function selectDistanceRate(customUnitRateID: string) { - IOU.updateDistanceRequestRate(transactionID, customUnitRateID, policy?.id ?? ''); + let taxAmount; + if (isDistanceRequest && transaction?.amount && policy?.customUnits && customUnitID && isOffline) { + const taxClaimablePercentage = policy?.customUnits[customUnitID].rates[customUnitRateID].attributes?.taxClaimablePercentage ?? 0; + const taxableAmount = -1 * transaction.amount * taxClaimablePercentage; + taxAmount = CurrencyUtils.convertToBackendAmount(TransactionUtils.calculateTaxAmount(taxPercentage, taxableAmount)); + } + IOU.updateDistanceRequestRate(transactionID, customUnitRateID, policy?.id ?? '', taxAmount); navigateBack(); } diff --git a/src/types/onyx/Policy.ts b/src/types/onyx/Policy.ts index 53c76286985..5ee0cad3fae 100644 --- a/src/types/onyx/Policy.ts +++ b/src/types/onyx/Policy.ts @@ -15,10 +15,12 @@ type Rate = OnyxCommon.OnyxValueWithOfflineFeedback<{ enabled?: boolean; errors?: OnyxCommon.Errors; errorFields?: OnyxCommon.ErrorFields; + attributes?: {taxClaimablePercentage?: number}; }>; type Attributes = { unit: Unit; + taxEnabled?: boolean; }; type CustomUnit = OnyxCommon.OnyxValueWithOfflineFeedback<{ From 94e26428b04980cd42aabf0aa932d9d57ab31fec Mon Sep 17 00:00:00 2001 From: Nicolay Arefyeu Date: Fri, 17 May 2024 15:16:55 +0300 Subject: [PATCH 2/9] use correct tax checks --- src/components/MoneyRequestConfirmationList.tsx | 2 +- src/components/ReportActionItem/MoneyRequestView.tsx | 2 +- src/libs/PolicyUtils.ts | 6 ++++-- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/components/MoneyRequestConfirmationList.tsx b/src/components/MoneyRequestConfirmationList.tsx index 35d51a44510..e5fd264cb4a 100755 --- a/src/components/MoneyRequestConfirmationList.tsx +++ b/src/components/MoneyRequestConfirmationList.tsx @@ -299,7 +299,7 @@ function MoneyRequestConfirmationList({ // 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]); - const shouldShowTax = isTaxTrackingEnabled(isPolicyExpenseChat, policy, customUnitRateID, isDistanceRequest) && !isTypeInvoice; + const shouldShowTax = isTaxTrackingEnabled(isPolicyExpenseChat, policy, isDistanceRequest) && !isTypeInvoice; // A flag for showing the billable field const shouldShowBillable = policy?.disabledFields?.defaultBillable === false; diff --git a/src/components/ReportActionItem/MoneyRequestView.tsx b/src/components/ReportActionItem/MoneyRequestView.tsx index 3dba19d5a06..793f1d15904 100644 --- a/src/components/ReportActionItem/MoneyRequestView.tsx +++ b/src/components/ReportActionItem/MoneyRequestView.tsx @@ -173,7 +173,7 @@ function MoneyRequestView({ const shouldShowTag = isPolicyExpenseChat && (transactionTag || OptionsListUtils.hasEnabledTags(policyTagLists)); const shouldShowBillable = isPolicyExpenseChat && (!!transactionBillable || !(policy?.disabledFields?.defaultBillable ?? true)); - const shouldShowTax = isTaxTrackingEnabled(isPolicyExpenseChat, policy, customUnitRateID, isDistanceRequest); + const shouldShowTax = isTaxTrackingEnabled(isPolicyExpenseChat, policy, isDistanceRequest); const {getViolationsForField} = useViolations(transactionViolations ?? []); const hasViolations = useCallback( diff --git a/src/libs/PolicyUtils.ts b/src/libs/PolicyUtils.ts index 02d1c84b614..e2e7f284692 100644 --- a/src/libs/PolicyUtils.ts +++ b/src/libs/PolicyUtils.ts @@ -263,8 +263,10 @@ 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, customUnitRateID: string, isDistanceRequest: boolean): boolean { - const isTaxEnabled = policy?.customUnits?.[customUnitRateID]?.attributes?.taxEnabled; +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 isTaxEnabled = policy?.customUnits?.[customUnitID]?.attributes?.taxEnabled; const isPolicyTaxTrackingEnabled = isPolicyExpenseChat && policy?.tax?.trackingEnabled; return (isDistanceRequest ? isPolicyTaxTrackingEnabled && isTaxEnabled : isPolicyTaxTrackingEnabled) ?? false; } From 98a4c4d37de4571a4c810ed4a6276d96e6fa0745 Mon Sep 17 00:00:00 2001 From: Nicolay Arefyeu Date: Fri, 17 May 2024 15:18:11 +0300 Subject: [PATCH 3/9] remove not needed fields --- src/components/ReportActionItem/MoneyRequestView.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/components/ReportActionItem/MoneyRequestView.tsx b/src/components/ReportActionItem/MoneyRequestView.tsx index 793f1d15904..93222e28557 100644 --- a/src/components/ReportActionItem/MoneyRequestView.tsx +++ b/src/components/ReportActionItem/MoneyRequestView.tsx @@ -132,7 +132,6 @@ function MoneyRequestView({ const taxRates = policy?.taxRates; const formattedTaxAmount = CurrencyUtils.convertToDisplayString(transactionTaxAmount, transactionCurrency); - const customUnitRateID = TransactionUtils.getRateID(transaction) ?? ''; const taxRatesDescription = taxRates?.name; const taxRateTitle = TransactionUtils.getTaxName(policy, transaction); From 92dd6015322621967c1f7d09c3c99f62ab5649b3 Mon Sep 17 00:00:00 2001 From: Nicolay Arefyeu Date: Mon, 20 May 2024 09:39:54 +0300 Subject: [PATCH 4/9] update --- src/libs/PolicyUtils.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/libs/PolicyUtils.ts b/src/libs/PolicyUtils.ts index e2e7f284692..4d78d38df01 100644 --- a/src/libs/PolicyUtils.ts +++ b/src/libs/PolicyUtils.ts @@ -266,9 +266,10 @@ function isPaidGroupPolicy(policy: OnyxEntry | EmptyObject): boolean { 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 isTaxEnabled = policy?.customUnits?.[customUnitID]?.attributes?.taxEnabled; const isPolicyTaxTrackingEnabled = isPolicyExpenseChat && policy?.tax?.trackingEnabled; - return (isDistanceRequest ? isPolicyTaxTrackingEnabled && isTaxEnabled : isPolicyTaxTrackingEnabled) ?? false; + const isTaxEnabledForDistance = isPolicyTaxTrackingEnabled && policy?.customUnits?.[customUnitID]?.attributes?.taxEnabled; + + return Boolean(isDistanceRequest ? isTaxEnabledForDistance : isPolicyTaxTrackingEnabled); } /** From ae991aa9b8cddc2a60c9af3b60b61b0ed067afc4 Mon Sep 17 00:00:00 2001 From: Nicolay Arefyeu Date: Mon, 20 May 2024 13:59:50 +0300 Subject: [PATCH 5/9] update after c+ review --- src/libs/PolicyUtils.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/PolicyUtils.ts b/src/libs/PolicyUtils.ts index 4d78d38df01..3f7cfb092d2 100644 --- a/src/libs/PolicyUtils.ts +++ b/src/libs/PolicyUtils.ts @@ -269,7 +269,7 @@ function isTaxTrackingEnabled(isPolicyExpenseChat: boolean, policy: OnyxEntry Date: Wed, 22 May 2024 16:47:55 +0300 Subject: [PATCH 6/9] updates after review --- src/libs/actions/IOU.ts | 5 +---- .../request/step/IOURequestStepDistanceRate.tsx | 16 ++++++++++++---- src/types/onyx/Policy.ts | 7 ++++++- 3 files changed, 19 insertions(+), 9 deletions(-) diff --git a/src/libs/actions/IOU.ts b/src/libs/actions/IOU.ts index dbf0cc44f93..2464dbff7db 100644 --- a/src/libs/actions/IOU.ts +++ b/src/libs/actions/IOU.ts @@ -421,12 +421,9 @@ function setCustomUnitRateID(transactionID: string, customUnitRateID: string) { } /** Update transaction distance rate */ -function updateDistanceRequestRate(transactionID: string, rateID: string, policyID: string, taxAmount?: number) { +function updateDistanceRequestRate(transactionID: string, rateID: string, policyID: string) { Onyx.merge(ONYXKEYS.NVP_LAST_SELECTED_DISTANCE_RATES, {[policyID]: rateID}); Onyx.merge(`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${transactionID}`, {comment: {customUnit: {customUnitRateID: rateID}}}); - if (taxAmount) { - Onyx.merge(`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${transactionID}`, {taxAmount}); - } } /** Helper function to get the receipt error for expenses, or the generic error if there's no receipt */ diff --git a/src/pages/iou/request/step/IOURequestStepDistanceRate.tsx b/src/pages/iou/request/step/IOURequestStepDistanceRate.tsx index 71414eb68c0..349ab98202d 100644 --- a/src/pages/iou/request/step/IOURequestStepDistanceRate.tsx +++ b/src/pages/iou/request/step/IOURequestStepDistanceRate.tsx @@ -5,13 +5,13 @@ import SelectionList from '@components/SelectionList'; import RadioListItem from '@components/SelectionList/RadioListItem'; import Text from '@components/Text'; import useLocalize from '@hooks/useLocalize'; -import useNetwork from '@hooks/useNetwork'; 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'; @@ -40,6 +40,7 @@ type IOURequestStepDistanceRateProps = IOURequestStepDistanceRateOnyxProps & function IOURequestStepDistanceRate({ policy, + report, route: { params: {backTo, transactionID}, }, @@ -53,7 +54,8 @@ function IOURequestStepDistanceRate({ const currency = transactionDetails?.currency; const distanceUnit = Object.values(policy?.customUnits ?? {}).find((unit) => unit.name === CONST.CUSTOM_UNITS.NAME_DISTANCE); const customUnitID = distanceUnit?.customUnitID; - const {isOffline} = useNetwork(); + const isPolicyExpenseChat = ReportUtils.isReportInGroupPolicy(report); + const shouldShowTax = isTaxTrackingEnabled(isPolicyExpenseChat, policy, isDistanceRequest); const defaultTaxCode = TransactionUtils.getDefaultTaxCode(policy, transaction, currency) ?? ''; const taxPercentage = TransactionUtils.getTaxValue(policy, transaction, defaultTaxCode) ?? ''; @@ -82,12 +84,18 @@ function IOURequestStepDistanceRate({ function selectDistanceRate(customUnitRateID: string) { let taxAmount; - if (isDistanceRequest && transaction?.amount && policy?.customUnits && customUnitID && isOffline) { + let taxCode; + if (transaction?.amount && policy?.customUnits && customUnitID && shouldShowTax) { const taxClaimablePercentage = policy?.customUnits[customUnitID].rates[customUnitRateID].attributes?.taxClaimablePercentage ?? 0; + taxCode = policy?.customUnits[customUnitID].rates[customUnitRateID].attributes?.taxRateExternalID ?? ''; const taxableAmount = -1 * transaction.amount * taxClaimablePercentage; taxAmount = CurrencyUtils.convertToBackendAmount(TransactionUtils.calculateTaxAmount(taxPercentage, taxableAmount)); } - IOU.updateDistanceRequestRate(transactionID, customUnitRateID, policy?.id ?? '', taxAmount); + IOU.updateDistanceRequestRate(transactionID, customUnitRateID, policy?.id ?? ''); + if (taxAmount && taxCode) { + IOU.setMoneyRequestTaxAmount(transactionID, taxAmount, true); + IOU.setMoneyRequestTaxRate(transactionID, taxCode); + } navigateBack(); } diff --git a/src/types/onyx/Policy.ts b/src/types/onyx/Policy.ts index 5ee0cad3fae..734520532be 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,7 +20,7 @@ type Rate = OnyxCommon.OnyxValueWithOfflineFeedback<{ enabled?: boolean; errors?: OnyxCommon.Errors; errorFields?: OnyxCommon.ErrorFields; - attributes?: {taxClaimablePercentage?: number}; + attributes?: TaxRateAttributes; }>; type Attributes = { From c33f821b6c87f92069c40eb793ffc91af329c934 Mon Sep 17 00:00:00 2001 From: Nicolay Arefyeu Date: Wed, 22 May 2024 18:09:22 +0300 Subject: [PATCH 7/9] updates after review --- src/components/MoneyRequestConfirmationList.tsx | 4 ++-- .../request/step/IOURequestStepDistanceRate.tsx | 16 ++++++---------- 2 files changed, 8 insertions(+), 12 deletions(-) diff --git a/src/components/MoneyRequestConfirmationList.tsx b/src/components/MoneyRequestConfirmationList.tsx index e5fd264cb4a..fda8ea531f5 100755 --- a/src/components/MoneyRequestConfirmationList.tsx +++ b/src/components/MoneyRequestConfirmationList.tsx @@ -371,7 +371,7 @@ function MoneyRequestConfirmationList({ // Calculate and set tax amount in transaction draft useEffect(() => { - const taxAmount = isDistanceRequest && isOffline ? (transaction?.taxAmount ?? 0).toString() : getTaxAmount(transaction, policy).toString(); + const taxAmount = getTaxAmount(transaction, policy).toString(); const amountInSmallestCurrencyUnits = CurrencyUtils.convertToBackendAmount(Number.parseFloat(taxAmount)); if (transaction?.taxAmount && previousTransactionAmount === transaction?.amount && previousTransactionCurrency === transaction?.currency) { @@ -379,7 +379,7 @@ function MoneyRequestConfirmationList({ } IOU.setMoneyRequestTaxAmount(transactionID, amountInSmallestCurrencyUnits, true); - }, [policy, transaction, transactionID, previousTransactionAmount, previousTransactionCurrency, isOffline, isDistanceRequest]); + }, [policy, transaction, transactionID, previousTransactionAmount, previousTransactionCurrency]); // If completing a split expense fails, set didConfirm to false to allow the user to edit the fields again if (isEditingSplitBill && didConfirm) { diff --git a/src/pages/iou/request/step/IOURequestStepDistanceRate.tsx b/src/pages/iou/request/step/IOURequestStepDistanceRate.tsx index 349ab98202d..ec76a65d5c2 100644 --- a/src/pages/iou/request/step/IOURequestStepDistanceRate.tsx +++ b/src/pages/iou/request/step/IOURequestStepDistanceRate.tsx @@ -50,15 +50,13 @@ function IOURequestStepDistanceRate({ const styles = useThemeStyles(); const {translate, toLocaleDigit} = useLocalize(); const isDistanceRequest = TransactionUtils.isDistanceRequest(transaction); - const transactionDetails = ReportUtils.getTransactionDetails(transaction); - const currency = transactionDetails?.currency; 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 defaultTaxCode = TransactionUtils.getDefaultTaxCode(policy, transaction, currency) ?? ''; - const taxPercentage = TransactionUtils.getTaxValue(policy, transaction, defaultTaxCode) ?? ''; + const transactionTaxCode = transaction?.taxCode ?? ''; + const taxPercentage = TransactionUtils.getTaxValue(policy, transaction, transactionTaxCode) ?? ''; const lastSelectedRateID = TransactionUtils.getRateID(transaction) ?? ''; @@ -84,18 +82,16 @@ function IOURequestStepDistanceRate({ function selectDistanceRate(customUnitRateID: string) { let taxAmount; - let taxCode; + let taxRateExternalID; if (transaction?.amount && policy?.customUnits && customUnitID && shouldShowTax) { const taxClaimablePercentage = policy?.customUnits[customUnitID].rates[customUnitRateID].attributes?.taxClaimablePercentage ?? 0; - taxCode = policy?.customUnits[customUnitID].rates[customUnitRateID].attributes?.taxRateExternalID ?? ''; + taxRateExternalID = policy?.customUnits[customUnitID].rates[customUnitRateID].attributes?.taxRateExternalID ?? ''; const taxableAmount = -1 * transaction.amount * taxClaimablePercentage; taxAmount = CurrencyUtils.convertToBackendAmount(TransactionUtils.calculateTaxAmount(taxPercentage, taxableAmount)); - } - IOU.updateDistanceRequestRate(transactionID, customUnitRateID, policy?.id ?? ''); - if (taxAmount && taxCode) { IOU.setMoneyRequestTaxAmount(transactionID, taxAmount, true); - IOU.setMoneyRequestTaxRate(transactionID, taxCode); + IOU.setMoneyRequestTaxRate(transactionID, taxRateExternalID); } + IOU.updateDistanceRequestRate(transactionID, customUnitRateID, policy?.id ?? ''); navigateBack(); } From 0011a9b2169182834517c2a74f5cb71ad4ed138b Mon Sep 17 00:00:00 2001 From: Nicolay Arefyeu Date: Wed, 22 May 2024 18:19:43 +0300 Subject: [PATCH 8/9] updates after review --- src/pages/iou/request/step/IOURequestStepDistanceRate.tsx | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/pages/iou/request/step/IOURequestStepDistanceRate.tsx b/src/pages/iou/request/step/IOURequestStepDistanceRate.tsx index ec76a65d5c2..f9a60fb1c28 100644 --- a/src/pages/iou/request/step/IOURequestStepDistanceRate.tsx +++ b/src/pages/iou/request/step/IOURequestStepDistanceRate.tsx @@ -55,9 +55,6 @@ function IOURequestStepDistanceRate({ const isPolicyExpenseChat = ReportUtils.isReportInGroupPolicy(report); const shouldShowTax = isTaxTrackingEnabled(isPolicyExpenseChat, policy, isDistanceRequest); - const transactionTaxCode = transaction?.taxCode ?? ''; - const taxPercentage = TransactionUtils.getTaxValue(policy, transaction, transactionTaxCode) ?? ''; - const lastSelectedRateID = TransactionUtils.getRateID(transaction) ?? ''; const navigateBack = () => { @@ -87,6 +84,7 @@ function IOURequestStepDistanceRate({ const taxClaimablePercentage = policy?.customUnits[customUnitID].rates[customUnitRateID].attributes?.taxClaimablePercentage ?? 0; taxRateExternalID = policy?.customUnits[customUnitID].rates[customUnitRateID].attributes?.taxRateExternalID ?? ''; const taxableAmount = -1 * transaction.amount * taxClaimablePercentage; + const taxPercentage = TransactionUtils.getTaxValue(policy, transaction, taxRateExternalID) ?? ''; taxAmount = CurrencyUtils.convertToBackendAmount(TransactionUtils.calculateTaxAmount(taxPercentage, taxableAmount)); IOU.setMoneyRequestTaxAmount(transactionID, taxAmount, true); IOU.setMoneyRequestTaxRate(transactionID, taxRateExternalID); From 80d29bd2873562d4b53e43deab9b128816223c4e Mon Sep 17 00:00:00 2001 From: Nicolay Arefyeu Date: Wed, 22 May 2024 19:13:03 +0300 Subject: [PATCH 9/9] updates after review --- src/pages/iou/request/step/IOURequestStepDistanceRate.tsx | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/pages/iou/request/step/IOURequestStepDistanceRate.tsx b/src/pages/iou/request/step/IOURequestStepDistanceRate.tsx index f9a60fb1c28..1879f56f86f 100644 --- a/src/pages/iou/request/step/IOURequestStepDistanceRate.tsx +++ b/src/pages/iou/request/step/IOURequestStepDistanceRate.tsx @@ -78,14 +78,12 @@ function IOURequestStepDistanceRate({ const initiallyFocusedOption = sections.find((item) => item.isSelected)?.keyForList; function selectDistanceRate(customUnitRateID: string) { - let taxAmount; - let taxRateExternalID; if (transaction?.amount && policy?.customUnits && customUnitID && shouldShowTax) { const taxClaimablePercentage = policy?.customUnits[customUnitID].rates[customUnitRateID].attributes?.taxClaimablePercentage ?? 0; - taxRateExternalID = policy?.customUnits[customUnitID].rates[customUnitRateID].attributes?.taxRateExternalID ?? ''; + const taxRateExternalID = policy?.customUnits[customUnitID].rates[customUnitRateID].attributes?.taxRateExternalID ?? ''; const taxableAmount = -1 * transaction.amount * taxClaimablePercentage; const taxPercentage = TransactionUtils.getTaxValue(policy, transaction, taxRateExternalID) ?? ''; - taxAmount = CurrencyUtils.convertToBackendAmount(TransactionUtils.calculateTaxAmount(taxPercentage, taxableAmount)); + const taxAmount = CurrencyUtils.convertToBackendAmount(TransactionUtils.calculateTaxAmount(taxPercentage, taxableAmount)); IOU.setMoneyRequestTaxAmount(transactionID, taxAmount, true); IOU.setMoneyRequestTaxRate(transactionID, taxRateExternalID); }