diff --git a/src/ONYXKEYS.ts b/src/ONYXKEYS.ts index f0b400687b12..f2d606bd62a6 100755 --- a/src/ONYXKEYS.ts +++ b/src/ONYXKEYS.ts @@ -282,7 +282,6 @@ const ONYXKEYS = { POLICY_CATEGORIES: 'policyCategories_', POLICY_RECENTLY_USED_CATEGORIES: 'policyRecentlyUsedCategories_', POLICY_TAGS: 'policyTags_', - POLICY_TAX_RATE: 'policyTaxRates_', POLICY_RECENTLY_USED_TAGS: 'policyRecentlyUsedTags_', POLICY_REPORT_FIELDS: 'policyReportFields_', WORKSPACE_INVITE_MEMBERS_DRAFT: 'workspaceInviteMembersDraft_', @@ -477,7 +476,6 @@ type OnyxCollectionValuesMapping = { [ONYXKEYS.COLLECTION.SELECTED_TAB]: string; [ONYXKEYS.COLLECTION.PRIVATE_NOTES_DRAFT]: string; [ONYXKEYS.COLLECTION.NEXT_STEP]: OnyxTypes.ReportNextStep; - [ONYXKEYS.COLLECTION.POLICY_TAX_RATE]: string[]; }; type OnyxValuesMapping = { diff --git a/src/components/MoneyRequestConfirmationList.js b/src/components/MoneyRequestConfirmationList.js index 2b18ab9bc003..df2781d3ea89 100755 --- a/src/components/MoneyRequestConfirmationList.js +++ b/src/components/MoneyRequestConfirmationList.js @@ -24,6 +24,7 @@ import * as ReceiptUtils from '@libs/ReceiptUtils'; import * as ReportUtils from '@libs/ReportUtils'; import * as TransactionUtils from '@libs/TransactionUtils'; import {iouDefaultProps, iouPropTypes} from '@pages/iou/propTypes'; +import {policyPropTypes} from '@pages/workspace/withPolicy'; import * as IOU from '@userActions/IOU'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; @@ -41,7 +42,6 @@ import SettlementButton from './SettlementButton'; import ShowMoreButton from './ShowMoreButton'; import Switch from './Switch'; import tagPropTypes from './tagPropTypes'; -import taxPropTypes from './taxPropTypes'; import Text from './Text'; import transactionPropTypes from './transactionPropTypes'; import withCurrentUserPersonalDetails, {withCurrentUserPersonalDetailsDefaultProps, withCurrentUserPersonalDetailsPropTypes} from './withCurrentUserPersonalDetails'; @@ -167,8 +167,8 @@ const propTypes = { policyTags: tagPropTypes, /* Onyx Props */ - /** Collection of tax rates attached to a policy */ - policyTaxRates: taxPropTypes, + /** The policy of the report */ + policy: policyPropTypes.policy, /** Holds data related to Money Request view state, rather than the underlying Money Request data. */ iou: iouPropTypes, @@ -196,6 +196,7 @@ const defaultProps = { receiptPath: '', receiptFilename: '', listStyles: [], + policy: {}, policyCategories: {}, policyTags: {}, transactionID: '', @@ -206,7 +207,6 @@ const defaultProps = { shouldShowSmartScanFields: true, isPolicyExpenseChat: false, iou: iouDefaultProps, - policyTaxRates: {}, }; function MoneyRequestConfirmationList(props) { @@ -228,6 +228,7 @@ function MoneyRequestConfirmationList(props) { const {unit, rate, currency} = props.mileageRate; const distance = lodashGet(transaction, 'routes.route0.distance', 0); const shouldCalculateDistanceAmount = props.isDistanceRequest && props.iouAmount === 0; + const taxRates = lodashGet(props.policy, 'taxRates', {}); // A flag for showing the categories field const shouldShowCategories = props.isPolicyExpenseChat && (props.iouCategory || OptionsListUtils.hasEnabledOptions(_.values(props.policyCategories))); @@ -262,8 +263,8 @@ function MoneyRequestConfirmationList(props) { ); const formattedTaxAmount = CurrencyUtils.convertToDisplayString(props.transaction.taxAmount, props.iouCurrencyCode); - const defaultTaxKey = props.policyTaxRates.defaultExternalID; - const defaultTaxName = (defaultTaxKey && `${props.policyTaxRates.taxes[defaultTaxKey].name} (${props.policyTaxRates.taxes[defaultTaxKey].value}) • ${translate('common.default')}`) || ''; + const defaultTaxKey = taxRates.defaultExternalID; + const defaultTaxName = (defaultTaxKey && `${taxRates.taxes[defaultTaxKey].name} (${taxRates.taxes[defaultTaxKey].value}) • ${translate('common.default')}`) || ''; const taxRateTitle = (props.transaction.taxRate && props.transaction.taxRate.text) || defaultTaxName; const isFocused = useIsFocused(); @@ -818,7 +819,7 @@ function MoneyRequestConfirmationList(props) { @@ -835,7 +836,7 @@ function MoneyRequestConfirmationList(props) { @@ -890,9 +891,6 @@ export default compose( policy: { key: ({policyID}) => `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, }, - policyTaxRates: { - key: ({policyID}) => `${ONYXKEYS.COLLECTION.POLICY_TAX_RATE}${policyID}`, - }, iou: { key: ONYXKEYS.IOU, }, diff --git a/src/components/MoneyTemporaryForRefactorRequestConfirmationList.js b/src/components/MoneyTemporaryForRefactorRequestConfirmationList.js index c69b0476f9c7..8eeaeaf87eff 100755 --- a/src/components/MoneyTemporaryForRefactorRequestConfirmationList.js +++ b/src/components/MoneyTemporaryForRefactorRequestConfirmationList.js @@ -23,6 +23,7 @@ import * as ReceiptUtils from '@libs/ReceiptUtils'; import * as ReportUtils from '@libs/ReportUtils'; import playSound, {SOUNDS} from '@libs/Sound'; import * as TransactionUtils from '@libs/TransactionUtils'; +import {policyPropTypes} from '@pages/workspace/withPolicy'; import * as IOU from '@userActions/IOU'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; @@ -41,7 +42,6 @@ import ReceiptEmptyState from './ReceiptEmptyState'; import SettlementButton from './SettlementButton'; import Switch from './Switch'; import tagPropTypes from './tagPropTypes'; -import taxPropTypes from './taxPropTypes'; import Text from './Text'; import transactionPropTypes from './transactionPropTypes'; import withCurrentUserPersonalDetails, {withCurrentUserPersonalDetailsDefaultProps, withCurrentUserPersonalDetailsPropTypes} from './withCurrentUserPersonalDetails'; @@ -161,8 +161,8 @@ const propTypes = { policyTags: tagPropTypes, /* Onyx Props */ - /** Collection of tax rates attached to a policy */ - policyTaxRates: taxPropTypes, + /** The policy of the report */ + policy: policyPropTypes.policy, /** Transaction that represents the money request */ transaction: transactionPropTypes, @@ -189,6 +189,7 @@ const defaultProps = { receiptPath: '', receiptFilename: '', listStyles: [], + policy: {}, policyCategories: {}, policyTags: {}, transactionID: '', @@ -197,7 +198,6 @@ const defaultProps = { isDistanceRequest: false, shouldShowSmartScanFields: true, isPolicyExpenseChat: false, - policyTaxRates: {}, }; function MoneyTemporaryForRefactorRequestConfirmationList({ @@ -238,7 +238,6 @@ function MoneyTemporaryForRefactorRequestConfirmationList({ session: {accountID}, shouldShowSmartScanFields, transaction, - policyTaxRates, }) { const theme = useTheme(); const styles = useThemeStyles(); @@ -252,6 +251,7 @@ function MoneyTemporaryForRefactorRequestConfirmationList({ const {unit, rate, currency} = mileageRate; const distance = lodashGet(transaction, 'routes.route0.distance', 0); const shouldCalculateDistanceAmount = isDistanceRequest && iouAmount === 0; + const taxRates = lodashGet(policy, 'taxRates', {}); // A flag for showing the categories field const shouldShowCategories = isPolicyExpenseChat && (iouCategory || OptionsListUtils.hasEnabledOptions(_.values(policyCategories))); @@ -286,8 +286,8 @@ function MoneyTemporaryForRefactorRequestConfirmationList({ ); const formattedTaxAmount = CurrencyUtils.convertToDisplayString(transaction.taxAmount, iouCurrencyCode); - const defaultTaxKey = policyTaxRates.defaultExternalID; - const defaultTaxName = (defaultTaxKey && `${policyTaxRates.taxes[defaultTaxKey].name} (${policyTaxRates.taxes[defaultTaxKey].value}) • ${translate('common.default')}`) || ''; + const defaultTaxKey = taxRates.defaultExternalID; + const defaultTaxName = (defaultTaxKey && `${taxRates.taxes[defaultTaxKey].name} (${taxRates.taxes[defaultTaxKey].value}) • ${translate('common.default')}`) || ''; const taxRateTitle = (transaction.taxRate && transaction.taxRate.text) || defaultTaxName; const isFocused = useIsFocused(); @@ -787,10 +787,10 @@ function MoneyTemporaryForRefactorRequestConfirmationList({ { item: ( Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_TAX_RATE.getRoute(iouType, transaction.transactionID, reportID, Navigation.getActiveRouteWithoutParams()))} @@ -804,10 +804,10 @@ function MoneyTemporaryForRefactorRequestConfirmationList({ { item: ( Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_TAX_AMOUNT.getRoute(iouType, transaction.transactionID, reportID, Navigation.getActiveRouteWithoutParams()))} @@ -936,8 +936,5 @@ export default compose( policy: { key: ({policyID}) => `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, }, - policyTaxRates: { - key: ({policyID}) => `${ONYXKEYS.COLLECTION.POLICY_TAX_RATE}${policyID}`, - }, }), )(MoneyTemporaryForRefactorRequestConfirmationList); diff --git a/src/components/TaxPicker/index.js b/src/components/TaxPicker/index.js index f25a1b84bf64..be15cd546b36 100644 --- a/src/components/TaxPicker/index.js +++ b/src/components/TaxPicker/index.js @@ -10,14 +10,14 @@ import * as TransactionUtils from '@libs/TransactionUtils'; import CONST from '@src/CONST'; import {defaultProps, propTypes} from './taxPickerPropTypes'; -function TaxPicker({selectedTaxRate, policyTaxRates, insets, onSubmit}) { +function TaxPicker({selectedTaxRate, taxRates, insets, onSubmit}) { const styles = useThemeStyles(); const StyleUtils = useStyleUtils(); const {translate} = useLocalize(); const [searchValue, setSearchValue] = useState(''); - const policyTaxRatesCount = TransactionUtils.getEnabledTaxRateCount(policyTaxRates.taxes); - const isTaxRatesCountBelowThreshold = policyTaxRatesCount < CONST.TAX_RATES_LIST_THRESHOLD; + const taxRatesCount = TransactionUtils.getEnabledTaxRateCount(taxRates.taxes); + const isTaxRatesCountBelowThreshold = taxRatesCount < CONST.TAX_RATES_LIST_THRESHOLD; const shouldShowTextInput = !isTaxRatesCountBelowThreshold; @@ -36,28 +36,9 @@ function TaxPicker({selectedTaxRate, policyTaxRates, insets, onSubmit}) { }, [selectedTaxRate]); const sections = useMemo(() => { - const {policyTaxRatesOptions} = OptionsListUtils.getFilteredOptions( - {}, - {}, - [], - searchValue, - selectedOptions, - [], - false, - false, - false, - {}, - [], - false, - {}, - [], - false, - false, - true, - policyTaxRates, - ); - return policyTaxRatesOptions; - }, [policyTaxRates, searchValue, selectedOptions]); + const {taxRatesOptions} = OptionsListUtils.getFilteredOptions({}, {}, [], searchValue, selectedOptions, [], false, false, false, {}, [], false, {}, [], false, false, true, taxRates); + return taxRatesOptions; + }, [taxRates, searchValue, selectedOptions]); const selectedOptionKey = lodashGet(_.filter(lodashGet(sections, '[0].data', []), (taxRate) => taxRate.searchText === selectedTaxRate)[0], 'keyForList'); diff --git a/src/components/TaxPicker/taxPickerPropTypes.js b/src/components/TaxPicker/taxPickerPropTypes.js index 289b4e19aaa4..06b7c00b7826 100644 --- a/src/components/TaxPicker/taxPickerPropTypes.js +++ b/src/components/TaxPicker/taxPickerPropTypes.js @@ -1,5 +1,6 @@ import PropTypes from 'prop-types'; import taxPropTypes from '@components/taxPropTypes'; +import safeAreaInsetPropTypes from '@pages/safeAreaInsetPropTypes'; const propTypes = { /** The selected tax rate of an expense */ @@ -8,14 +9,19 @@ const propTypes = { /** Callback to fire when a tax is pressed */ onSubmit: PropTypes.func.isRequired, - /* Onyx Props */ /** Collection of tax rates attached to a policy */ - policyTaxRates: taxPropTypes, + taxRates: taxPropTypes, + + /** + * Safe area insets required for reflecting the portion of the view, + * that is not covered by navigation bars, tab bars, toolbars, and other ancestor views. + */ + insets: safeAreaInsetPropTypes.isRequired, }; const defaultProps = { selectedTaxRate: '', - policyTaxRates: {}, + taxRates: {}, }; export {propTypes, defaultProps}; diff --git a/src/libs/OptionsListUtils.ts b/src/libs/OptionsListUtils.ts index 8698cd21729c..3d11795f5452 100644 --- a/src/libs/OptionsListUtils.ts +++ b/src/libs/OptionsListUtils.ts @@ -22,12 +22,14 @@ import type { Report, ReportAction, ReportActions, + TaxRate, + TaxRates, + TaxRatesWithDefault, Transaction, TransactionViolation, } from '@src/types/onyx'; import type {Participant} from '@src/types/onyx/IOU'; import type * as OnyxCommon from '@src/types/onyx/OnyxCommon'; -import type {PolicyTaxRate, PolicyTaxRates} from '@src/types/onyx/PolicyTaxRates'; import type DeepValueOf from '@src/types/utils/DeepValueOf'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; import times from '@src/utils/times'; @@ -112,8 +114,8 @@ type GetOptionsConfig = { recentlyUsedTags?: string[]; canInviteUser?: boolean; includeSelectedOptions?: boolean; - includePolicyTaxRates?: boolean; - policyTaxRates?: PolicyTaxRateWithDefault; + includeTaxRates?: boolean; + taxRates?: TaxRatesWithDefault; transactionViolations?: OnyxCollection; }; @@ -142,7 +144,7 @@ type GetOptions = { currentUserOption: ReportUtils.OptionData | null | undefined; categoryOptions: CategorySection[]; tagOptions: CategorySection[]; - policyTaxRatesOptions: CategorySection[]; + taxRatesOptions: CategorySection[]; }; type PreviewConfig = {showChatPreviewLine?: boolean; forcePolicyNamePreview?: boolean}; @@ -1171,31 +1173,23 @@ function hasEnabledTags(policyTagList: Array return hasEnabledOptions(policyTagValueList); } -type PolicyTaxRateWithDefault = { - name: string; - defaultExternalID: string; - defaultValue: string; - foreignTaxDefault: string; - taxes: PolicyTaxRates; -}; - /** * Transforms tax rates to a new object format - to add codes and new name with concatenated name and value. * - * @param policyTaxRates - The original tax rates object. + * @param taxRates - The original tax rates object. * @returns The transformed tax rates object.g */ -function transformedTaxRates(policyTaxRates: PolicyTaxRateWithDefault | undefined): Record { - const defaultTaxKey = policyTaxRates?.defaultExternalID; - const getModifiedName = (data: PolicyTaxRate, code: string) => `${data.name} (${data.value})${defaultTaxKey === code ? ` • ${Localize.translateLocal('common.default')}` : ''}`; - const taxes = Object.fromEntries(Object.entries(policyTaxRates?.taxes ?? {}).map(([code, data]) => [code, {...data, code, modifiedName: getModifiedName(data, code), name: data.name}])); +function transformedTaxRates(taxRates: TaxRatesWithDefault | undefined): Record { + const defaultTaxKey = taxRates?.defaultExternalID; + const getModifiedName = (data: TaxRate, code: string) => `${data.name} (${data.value})${defaultTaxKey === code ? ` • ${Localize.translateLocal('common.default')}` : ''}`; + const taxes = Object.fromEntries(Object.entries(taxRates?.taxes ?? {}).map(([code, data]) => [code, {...data, code, modifiedName: getModifiedName(data, code), name: data.name}])); return taxes; } /** * Sorts tax rates alphabetically by name. */ -function sortTaxRates(taxRates: PolicyTaxRates): PolicyTaxRate[] { +function sortTaxRates(taxRates: TaxRates): TaxRate[] { const sortedtaxRates = lodashSortBy(taxRates, (taxRate) => taxRate.name); return sortedtaxRates; } @@ -1203,7 +1197,7 @@ function sortTaxRates(taxRates: PolicyTaxRates): PolicyTaxRate[] { /** * Builds the options for taxRates */ -function getTaxRatesOptions(taxRates: Array>): Option[] { +function getTaxRatesOptions(taxRates: Array>): Option[] { return taxRates.map((taxRate) => ({ text: taxRate.modifiedName, keyForList: taxRate.code, @@ -1217,10 +1211,10 @@ function getTaxRatesOptions(taxRates: Array>): Option[] { /** * Builds the section list for tax rates */ -function getTaxRatesSection(policyTaxRates: PolicyTaxRateWithDefault | undefined, selectedOptions: Category[], searchInputValue: string): CategorySection[] { +function getTaxRatesSection(taxRates: TaxRatesWithDefault | undefined, selectedOptions: Category[], searchInputValue: string): CategorySection[] { const policyRatesSections = []; - const taxes = transformedTaxRates(policyTaxRates); + const taxes = transformedTaxRates(taxRates); const sortedTaxRates = sortTaxRates(taxes); const enabledTaxRates = sortedTaxRates.filter((taxRate) => !taxRate.isDisabled); @@ -1359,8 +1353,8 @@ function getOptions( canInviteUser = true, includeSelectedOptions = false, transactionViolations = {}, - includePolicyTaxRates, - policyTaxRates, + includeTaxRates, + taxRates, }: GetOptionsConfig, ): GetOptions { if (includeCategories) { @@ -1373,7 +1367,7 @@ function getOptions( currentUserOption: null, categoryOptions, tagOptions: [], - policyTaxRatesOptions: [], + taxRatesOptions: [], }; } @@ -1387,12 +1381,12 @@ function getOptions( currentUserOption: null, categoryOptions: [], tagOptions, - policyTaxRatesOptions: [], + taxRatesOptions: [], }; } - if (includePolicyTaxRates) { - const policyTaxRatesOptions = getTaxRatesSection(policyTaxRates, selectedOptions as Category[], searchInputValue); + if (includeTaxRates) { + const taxRatesOptions = getTaxRatesSection(taxRates, selectedOptions as Category[], searchInputValue); return { recentReports: [], @@ -1401,7 +1395,7 @@ function getOptions( currentUserOption: null, categoryOptions: [], tagOptions: [], - policyTaxRatesOptions, + taxRatesOptions, }; } @@ -1413,7 +1407,7 @@ function getOptions( currentUserOption: null, categoryOptions: [], tagOptions: [], - policyTaxRatesOptions: [], + taxRatesOptions: [], }; } @@ -1702,7 +1696,7 @@ function getOptions( currentUserOption, categoryOptions: [], tagOptions: [], - policyTaxRatesOptions: [], + taxRatesOptions: [], }; } @@ -1799,8 +1793,8 @@ function getFilteredOptions( recentlyUsedTags: string[] = [], canInviteUser = true, includeSelectedOptions = false, - includePolicyTaxRates = false, - policyTaxRates: PolicyTaxRateWithDefault = {} as PolicyTaxRateWithDefault, + includeTaxRates = false, + taxRates: TaxRatesWithDefault = {} as TaxRatesWithDefault, ) { return getOptions(reports, personalDetails, { betas, @@ -1820,8 +1814,8 @@ function getFilteredOptions( recentlyUsedTags, canInviteUser, includeSelectedOptions, - includePolicyTaxRates, - policyTaxRates, + includeTaxRates, + taxRates, }); } diff --git a/src/libs/TransactionUtils.ts b/src/libs/TransactionUtils.ts index ee0ec6d9755b..3489053951b6 100644 --- a/src/libs/TransactionUtils.ts +++ b/src/libs/TransactionUtils.ts @@ -4,9 +4,8 @@ import Onyx from 'react-native-onyx'; import type {ValueOf} from 'type-fest'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; -import type {RecentWaypoint, Report, ReportAction, Transaction, TransactionViolation} from '@src/types/onyx'; +import type {RecentWaypoint, Report, ReportAction, TaxRate, TaxRates, Transaction, TransactionViolation} from '@src/types/onyx'; import type {IOUMessage} from '@src/types/onyx/OriginalMessage'; -import type {PolicyTaxRate, PolicyTaxRates} from '@src/types/onyx/PolicyTaxRates'; import type {Comment, Receipt, TransactionChanges, TransactionPendingFieldsKey, Waypoint, WaypointCollection} from '@src/types/onyx/Transaction'; import type {EmptyObject} from '@src/types/utils/EmptyObject'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; @@ -606,8 +605,8 @@ function calculateTaxAmount(percentage: string, amount: number) { /** * Calculates count of all tax enabled options */ -function getEnabledTaxRateCount(options: PolicyTaxRates) { - return Object.values(options).filter((option: PolicyTaxRate) => !option.isDisabled).length; +function getEnabledTaxRateCount(options: TaxRates) { + return Object.values(options).filter((option: TaxRate) => !option.isDisabled).length; } export { diff --git a/src/pages/iou/request/step/IOURequestStepAmount.js b/src/pages/iou/request/step/IOURequestStepAmount.js index ec52b49d8b7a..9fdd2bea24f4 100644 --- a/src/pages/iou/request/step/IOURequestStepAmount.js +++ b/src/pages/iou/request/step/IOURequestStepAmount.js @@ -34,10 +34,6 @@ const propTypes = { /** The transaction object being modified in Onyx */ transaction: transactionPropTypes, - /* Onyx Props */ - /** Collection of tax rates attached to a policy */ - policyTaxRates: taxPropTypes, - /** The policy of the report */ policy: PropTypes.shape({ /** @@ -51,13 +47,15 @@ const propTypes = { tax: PropTypes.shape({ trackingEnabled: PropTypes.bool, }), + + /** Collection of tax rates attached to a policy */ + taxRates: taxPropTypes, }), }; const defaultProps = { report: {}, transaction: {}, - policyTaxRates: {}, policy: {}, }; @@ -73,7 +71,6 @@ function IOURequestStepAmount({ }, transaction, transaction: {currency}, - policyTaxRates, policy, }) { const {translate} = useLocalize(); @@ -83,6 +80,7 @@ function IOURequestStepAmount({ const originalCurrency = useRef(null); const iouRequestType = getRequestType(transaction); + const taxRates = lodashGet(policy, 'taxRates', {}); const isPolicyExpenseChat = ReportUtils.isPolicyExpenseChat(ReportUtils.getRootParentReport(report)); const isTaxTrackingEnabled = isPolicyExpenseChat && lodashGet(policy, 'tax.trackingEnabled', policy.isTaxTrackingEnabled); @@ -130,7 +128,7 @@ function IOURequestStepAmount({ const amountInSmallestCurrencyUnits = CurrencyUtils.convertToBackendAmount(Number.parseFloat(amount)); if ((iouRequestType === CONST.IOU.REQUEST_TYPE.MANUAL || backTo) && isTaxTrackingEnabled) { - const taxAmount = getTaxAmount(transaction, policyTaxRates.defaultValue, amountInSmallestCurrencyUnits); + const taxAmount = getTaxAmount(transaction, taxRates.defaultValue, amountInSmallestCurrencyUnits); const taxAmountInSmallestCurrencyUnits = CurrencyUtils.convertToBackendAmount(Number.parseFloat(taxAmount)); IOU.setMoneyRequestTaxAmount(transaction.transactionID, taxAmountInSmallestCurrencyUnits); } @@ -185,9 +183,6 @@ export default compose( withWritableReportOrNotFound, withFullTransactionOrNotFound, withOnyx({ - policyTaxRates: { - key: ({report}) => `${ONYXKEYS.COLLECTION.POLICY_TAX_RATE}${report ? report.policyID : '0'}`, - }, policy: { key: ({report}) => `${ONYXKEYS.COLLECTION.POLICY}${report ? report.policyID : '0'}`, }, diff --git a/src/pages/iou/request/step/IOURequestStepTaxAmountPage.js b/src/pages/iou/request/step/IOURequestStepTaxAmountPage.js index 02b0c3c38dd5..29263d92078f 100644 --- a/src/pages/iou/request/step/IOURequestStepTaxAmountPage.js +++ b/src/pages/iou/request/step/IOURequestStepTaxAmountPage.js @@ -1,4 +1,6 @@ import {useFocusEffect} from '@react-navigation/native'; +import lodashGet from 'lodash/get'; +import PropTypes from 'prop-types'; import React, {useCallback, useEffect, useRef} from 'react'; import {View} from 'react-native'; import {withOnyx} from 'react-native-onyx'; @@ -36,14 +38,17 @@ const propTypes = { transaction: transactionPropTypes, /* Onyx Props */ - /** Collection of tax rates attached to a policy */ - policyTaxRates: taxPropTypes, + /** The policy of the report */ + policy: PropTypes.shape({ + /** Collection of tax rates attached to a policy */ + taxRates: taxPropTypes, + }), }; const defaultProps = { report: {}, transaction: {}, - policyTaxRates: {}, + policy: {}, }; const getTaxAmount = (transaction, defaultTaxValue) => { @@ -58,7 +63,7 @@ function IOURequestStepTaxAmountPage({ transaction, transaction: {currency}, report, - policyTaxRates, + policy, }) { const {translate} = useLocalize(); const styles = useThemeStyles(); @@ -69,6 +74,7 @@ function IOURequestStepTaxAmountPage({ const isSaveButtonPressed = useRef(false); const originalCurrency = useRef(null); + const taxRates = lodashGet(policy, 'taxRates', {}); useEffect(() => { if (transaction.originalCurrency) { @@ -140,7 +146,7 @@ function IOURequestStepTaxAmountPage({ isEditing={isEditing} currency={currency} amount={transaction.taxAmount} - taxAmount={getTaxAmount(transaction, policyTaxRates.defaultValue)} + taxAmount={getTaxAmount(transaction, taxRates.defaultValue)} transaction={transaction} ref={(e) => (textInput.current = e)} onCurrencyButtonPress={navigateToCurrencySelectionPage} @@ -177,8 +183,8 @@ export default compose( withWritableReportOrNotFound, withFullTransactionOrNotFound, withOnyx({ - policyTaxRates: { - key: ({report}) => `${ONYXKEYS.COLLECTION.POLICY_TAX_RATE}${report ? report.policyID : '0'}`, + policy: { + key: ({report}) => `${ONYXKEYS.COLLECTION.POLICY}${report ? report.policyID : '0'}`, }, }), )(IOURequestStepTaxAmountPage); diff --git a/src/pages/iou/request/step/IOURequestStepTaxRatePage.js b/src/pages/iou/request/step/IOURequestStepTaxRatePage.js index edcc8c8fa592..0cc2375b5510 100644 --- a/src/pages/iou/request/step/IOURequestStepTaxRatePage.js +++ b/src/pages/iou/request/step/IOURequestStepTaxRatePage.js @@ -1,3 +1,5 @@ +import lodashGet from 'lodash/get'; +import PropTypes from 'prop-types'; import React from 'react'; import {withOnyx} from 'react-native-onyx'; import _ from 'underscore'; @@ -22,16 +24,19 @@ const propTypes = { /** Navigation route context info provided by react navigation */ route: IOURequestStepRoutePropTypes.isRequired, - /* Onyx Props */ - /** Collection of tax rates attached to a policy */ - policyTaxRates: taxPropTypes, - /** The transaction object being modified in Onyx */ transaction: transactionPropTypes, + + /* Onyx Props */ + /** The policy of the report */ + policy: PropTypes.shape({ + /** Collection of tax rates attached to a policy */ + taxRates: taxPropTypes, + }), }; const defaultProps = { - policyTaxRates: {}, + policy: {}, transaction: {}, }; @@ -44,7 +49,7 @@ function IOURequestStepTaxRatePage({ route: { params: {backTo}, }, - policyTaxRates, + policy, transaction, }) { const {translate} = useLocalize(); @@ -52,13 +57,13 @@ function IOURequestStepTaxRatePage({ const navigateBack = () => { Navigation.goBack(backTo); }; - - const defaultTaxKey = policyTaxRates.defaultExternalID; - const defaultTaxName = (defaultTaxKey && `${policyTaxRates.taxes[defaultTaxKey].name} (${policyTaxRates.taxes[defaultTaxKey].value}) • ${translate('common.default')}`) || ''; + const taxRates = lodashGet(policy, 'taxRates', {}); + const defaultTaxKey = taxRates.defaultExternalID; + const defaultTaxName = (defaultTaxKey && `${taxRates.taxes[defaultTaxKey].name} (${taxRates.taxes[defaultTaxKey].value}) • ${translate('common.default')}`) || ''; const selectedTaxRate = (transaction.taxRate && transaction.taxRate.text) || defaultTaxName; const updateTaxRates = (taxes) => { - const taxAmount = getTaxAmount(policyTaxRates, taxes.text, transaction.amount); + const taxAmount = getTaxAmount(taxRates, taxes.text, transaction.amount); const amountInSmallestCurrencyUnits = CurrencyUtils.convertToBackendAmount(Number.parseFloat(taxAmount)); IOU.setMoneyRequestTaxRate(transaction.transactionID, taxes); IOU.setMoneyRequestTaxAmount(transaction.transactionID, amountInSmallestCurrencyUnits); @@ -80,7 +85,7 @@ function IOURequestStepTaxRatePage({ /> @@ -98,8 +103,8 @@ export default compose( withWritableReportOrNotFound, withFullTransactionOrNotFound, withOnyx({ - policyTaxRates: { - key: ({report}) => `${ONYXKEYS.COLLECTION.POLICY_TAX_RATE}${report ? report.policyID : '0'}`, + policy: { + key: ({report}) => `${ONYXKEYS.COLLECTION.POLICY}${report ? report.policyID : '0'}`, }, }), )(IOURequestStepTaxRatePage); diff --git a/src/pages/workspace/withPolicy.tsx b/src/pages/workspace/withPolicy.tsx index 3b10b9fb209c..76126040652b 100644 --- a/src/pages/workspace/withPolicy.tsx +++ b/src/pages/workspace/withPolicy.tsx @@ -6,6 +6,7 @@ import React, {forwardRef} from 'react'; import type {OnyxEntry} from 'react-native-onyx'; import {withOnyx} from 'react-native-onyx'; import type {ValueOf} from 'type-fest'; +import taxPropTypes from '@components/taxPropTypes'; import {translatableTextPropTypes} from '@libs/Localize'; import type {BottomTabNavigatorParamList, CentralPaneNavigatorParamList, SettingsNavigatorParamList} from '@navigation/types'; import policyMemberPropType from '@pages/policyMemberPropType'; @@ -80,6 +81,9 @@ const policyPropTypes = { tax: PropTypes.shape({ trackingEnabled: PropTypes.bool, }), + + /** Collection of tax rates attached to a policy */ + taxRates: taxPropTypes, }), /** The employee list of this policy */ diff --git a/src/types/onyx/Policy.ts b/src/types/onyx/Policy.ts index 2844f63ab433..b79325611e9f 100644 --- a/src/types/onyx/Policy.ts +++ b/src/types/onyx/Policy.ts @@ -34,6 +34,42 @@ type DisabledFields = { reimbursable?: boolean; }; +type TaxRate = { + /** Name of the a tax rate. */ + name: string; + + /** The value of the tax rate as percentage. */ + value: string; + + /** The code associated with the tax rate. */ + code: string; + + /** This contains the tax name and tax value as one name */ + modifiedName: string; + + /** Indicates if the tax rate is disabled. */ + isDisabled?: boolean; +}; + +type TaxRates = Record; + +type TaxRatesWithDefault = { + /** Name of the tax */ + name: string; + + /** Default policy tax code */ + defaultExternalID: string; + + /** Default value of taxes */ + defaultValue: string; + + /** Default foreign policy tax code */ + foreignTaxDefault: string; + + /** List of tax names and values */ + taxes: TaxRates; +}; + // These types are for the Integration connections for a policy (eg. Quickbooks, Xero, etc). // This data is not yet used in the codebase which is why it is given a very generic type, but the data is being put into Onyx for future use. // Once the data is being used, these types should be defined appropriately. @@ -183,6 +219,9 @@ type Policy = { trackingEnabled: boolean; }; + /** Collection of tax rates attached to a policy */ + taxRates?: TaxRatesWithDefault; + /** ReportID of the admins room for this workspace */ chatReportIDAdmins?: number; @@ -195,4 +234,4 @@ type Policy = { export default Policy; -export type {Unit, CustomUnit, Attributes, Rate}; +export type {Unit, CustomUnit, Attributes, Rate, TaxRate, TaxRates, TaxRatesWithDefault}; diff --git a/src/types/onyx/PolicyTaxRates.ts b/src/types/onyx/PolicyTaxRates.ts deleted file mode 100644 index e2bea4a3fa44..000000000000 --- a/src/types/onyx/PolicyTaxRates.ts +++ /dev/null @@ -1,20 +0,0 @@ -type PolicyTaxRate = { - /** The name of the tax rate. */ - name: string; - - /** The value of the tax rate. */ - value: string; - - /** The code associated with the tax rate. */ - code: string; - - /** This contains the tax name and tax value as one name */ - modifiedName: string; - - /** Indicates if the tax rate is disabled. */ - isDisabled?: boolean; -}; - -type PolicyTaxRates = Record; - -export type {PolicyTaxRates, PolicyTaxRate}; diff --git a/src/types/onyx/index.ts b/src/types/onyx/index.ts index c24e0871e0ed..6846fc302639 100644 --- a/src/types/onyx/index.ts +++ b/src/types/onyx/index.ts @@ -31,6 +31,7 @@ import type {PersonalDetailsList} from './PersonalDetails'; import type PersonalDetails from './PersonalDetails'; import type PlaidData from './PlaidData'; import type Policy from './Policy'; +import type {TaxRate, TaxRates, TaxRatesWithDefault} from './Policy'; import type {PolicyCategories, PolicyCategory} from './PolicyCategory'; import type {PolicyMembers} from './PolicyMember'; import type PolicyMember from './PolicyMember'; @@ -129,6 +130,9 @@ export type { SecurityGroup, Session, Task, + TaxRate, + TaxRates, + TaxRatesWithDefault, Transaction, TransactionViolation, TransactionViolations, diff --git a/tests/unit/OptionsListUtilsTest.js b/tests/unit/OptionsListUtilsTest.js index 00f1307ab59f..7244b7830a29 100644 --- a/tests/unit/OptionsListUtilsTest.js +++ b/tests/unit/OptionsListUtilsTest.js @@ -2063,7 +2063,7 @@ describe('OptionsListUtils', () => { const emptySearch = ''; const wrongSearch = 'bla bla'; - const policyTaxRatesWithDefault = { + const taxRatesWithDefault = { name: 'Tax', defaultExternalID: 'CODE1', defaultValue: '0%', @@ -2170,34 +2170,15 @@ describe('OptionsListUtils', () => { }, ]; - const result = OptionsListUtils.getFilteredOptions({}, {}, [], emptySearch, [], [], false, false, false, {}, [], false, {}, [], false, false, true, policyTaxRatesWithDefault); + const result = OptionsListUtils.getFilteredOptions({}, {}, [], emptySearch, [], [], false, false, false, {}, [], false, {}, [], false, false, true, taxRatesWithDefault); - expect(result.policyTaxRatesOptions).toStrictEqual(resultList); + expect(result.taxRatesOptions).toStrictEqual(resultList); - const searchResult = OptionsListUtils.getFilteredOptions({}, {}, [], search, [], [], false, false, false, {}, [], false, {}, [], false, false, true, policyTaxRatesWithDefault); - expect(searchResult.policyTaxRatesOptions).toStrictEqual(searchResultList); + const searchResult = OptionsListUtils.getFilteredOptions({}, {}, [], search, [], [], false, false, false, {}, [], false, {}, [], false, false, true, taxRatesWithDefault); + expect(searchResult.taxRatesOptions).toStrictEqual(searchResultList); - const wrongSearchResult = OptionsListUtils.getFilteredOptions( - {}, - {}, - [], - wrongSearch, - [], - [], - false, - false, - false, - {}, - [], - false, - {}, - [], - false, - false, - true, - policyTaxRatesWithDefault, - ); - expect(wrongSearchResult.policyTaxRatesOptions).toStrictEqual(wrongSearchResultList); + const wrongSearchResult = OptionsListUtils.getFilteredOptions({}, {}, [], wrongSearch, [], [], false, false, false, {}, [], false, {}, [], false, false, true, taxRatesWithDefault); + expect(wrongSearchResult.taxRatesOptions).toStrictEqual(wrongSearchResultList); }); it('formatMemberForList()', () => {