diff --git a/src/CONST/index.ts b/src/CONST/index.ts index c56be545e2d9..5ef28ca97950 100644 --- a/src/CONST/index.ts +++ b/src/CONST/index.ts @@ -1952,6 +1952,7 @@ const CONST = { EXPORT_OPTION_LABELS: { REPORT_LEVEL_EXPORT: 'All Data - Report Level Export', EXPENSE_LEVEL_EXPORT: 'All Data - Expense Level Export', + MULTIPLE_TAX_EXPORT: 'Canadian Multiple Tax Export', DEFAULT_CSV: 'Default CSV', }, ROOM_MEMBERS_BULK_ACTION_TYPES: { diff --git a/src/components/Search/FilterComponents/ExportedToSelector.tsx b/src/components/Search/FilterComponents/ExportedToSelector.tsx index d062414b6967..946b1356376f 100644 --- a/src/components/Search/FilterComponents/ExportedToSelector.tsx +++ b/src/components/Search/FilterComponents/ExportedToSelector.tsx @@ -9,7 +9,7 @@ import useStyleUtils from '@hooks/useStyleUtils'; import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; -import {getSearchValueForConnection} from '@libs/AccountingUtils'; +import {getSearchValueForConnection, getStandardExportTemplateDisplayName, isStandardExportTemplate} from '@libs/AccountingUtils'; import {getIntegrationIcon} from '@libs/ReportUtils'; import {getAllPolicyValues, getConnectedIntegrationNamesForPolicies} from '@libs/SearchQueryUtils'; @@ -28,11 +28,6 @@ type ExportedToSelectorProps = SearchFilterCommonProps & { policyID: Filter | undefined; }; -const STANDARD_EXPORT_TEMPLATE_ID_TO_DISPLAY_LABEL: Record = { - [CONST.REPORT.EXPORT_OPTIONS.REPORT_LEVEL_EXPORT]: CONST.REPORT.EXPORT_OPTION_LABELS.REPORT_LEVEL_EXPORT, - [CONST.REPORT.EXPORT_OPTIONS.EXPENSE_LEVEL_EXPORT]: CONST.REPORT.EXPORT_OPTION_LABELS.EXPENSE_LEVEL_EXPORT, -}; - function ExportedToSelector({value = [], policyID, selectionListTextInputStyle, selectionListStyle, autoFocus, footer, onChange}: ExportedToSelectorProps) { const styles = useThemeStyles(); const {localeCompare} = useLocalize(); @@ -105,13 +100,14 @@ function ExportedToSelector({value = [], policyID, selectionListTextInputStyle, } const displayName = template.name ?? template.templateName ?? ''; - const filterValue = STANDARD_EXPORT_TEMPLATE_ID_TO_DISPLAY_LABEL[template.templateName] ?? displayName; + // Standard templates are filtered on by the label the backend records for them, while custom templates are filtered on by their display name + const isStandardTemplate = isStandardExportTemplate(template.templateName); + const filterValue = isStandardTemplate ? getStandardExportTemplateDisplayName(template.templateName) : displayName; if (usedPickerValueKeys.has(filterValue)) { continue; } usedPickerValueKeys.add(filterValue); - const isStandardTemplate = !!STANDARD_EXPORT_TEMPLATE_ID_TO_DISPLAY_LABEL[template.templateName]; standardAndIntegrationCustomTemplatePickerItems.push({ text: displayName, value: filterValue, diff --git a/src/components/Search/SearchList/ListItem/ExportedIconCell.tsx b/src/components/Search/SearchList/ListItem/ExportedIconCell.tsx index e093b7d60149..03ab171a0976 100644 --- a/src/components/Search/SearchList/ListItem/ExportedIconCell.tsx +++ b/src/components/Search/SearchList/ListItem/ExportedIconCell.tsx @@ -5,6 +5,7 @@ import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset'; import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; +import {isStandardExportTemplateLabel} from '@libs/AccountingUtils'; import {getOriginalMessage, isExportedToIntegrationAction} from '@libs/ReportActionsUtils'; import CONST from '@src/CONST'; @@ -17,8 +18,6 @@ type ExportedIconCellProps = { reportActions?: ReportAction[]; }; -const STANDARD_EXPORT_TEMPLATE_LABELS = new Set([CONST.REPORT.EXPORT_OPTION_LABELS.EXPENSE_LEVEL_EXPORT, CONST.REPORT.EXPORT_OPTION_LABELS.REPORT_LEVEL_EXPORT]); - function ExportedIconCell({reportActions}: ExportedIconCellProps) { const theme = useTheme(); const styles = useThemeStyles(); @@ -58,7 +57,7 @@ function ExportedIconCell({reportActions}: ExportedIconCellProps) { const message = getOriginalMessage(action); const label = message?.label; const type = message?.type; - const isStandardExportTemplate = !!label && STANDARD_EXPORT_TEMPLATE_LABELS.has(label); + const isStandardExportTemplate = !!label && isStandardExportTemplateLabel(label); if (type === CONST.EXPORT_TEMPLATE && isStandardExportTemplate) { isExportedToStandardTemplate = true; diff --git a/src/libs/AccountingUtils.ts b/src/libs/AccountingUtils.ts index 6665ee3a4e5b..d30609256230 100644 --- a/src/libs/AccountingUtils.ts +++ b/src/libs/AccountingUtils.ts @@ -32,8 +32,11 @@ const NAME_ROUTE_MAPPING = { const STANDARD_EXPORT_TEMPLATE_NAME_MAPPING = { [CONST.REPORT.EXPORT_OPTIONS.EXPENSE_LEVEL_EXPORT]: CONST.REPORT.EXPORT_OPTION_LABELS.EXPENSE_LEVEL_EXPORT, [CONST.REPORT.EXPORT_OPTIONS.REPORT_LEVEL_EXPORT]: CONST.REPORT.EXPORT_OPTION_LABELS.REPORT_LEVEL_EXPORT, + [CONST.REPORT.EXPORT_OPTIONS.MULTIPLE_TAX_EXPORT]: CONST.REPORT.EXPORT_OPTION_LABELS.MULTIPLE_TAX_EXPORT, }; +const STANDARD_EXPORT_TEMPLATE_LABELS = new Set(Object.values(STANDARD_EXPORT_TEMPLATE_NAME_MAPPING)); + function getConnectionNameFromRouteParam(routeParam: ValueOf) { return ROUTE_NAME_MAPPING[routeParam]; } @@ -50,4 +53,21 @@ function getStandardExportTemplateDisplayName(templateName: string): string { return STANDARD_EXPORT_TEMPLATE_NAME_MAPPING[templateName as keyof typeof STANDARD_EXPORT_TEMPLATE_NAME_MAPPING] ?? templateName; } -export {getConnectionNameFromRouteParam, getRouteParamForConnection, getSearchValueForConnection, getStandardExportTemplateDisplayName}; +/** Whether the given template ID belongs to one of the standard (i.e. not user-defined) export templates */ +function isStandardExportTemplate(templateName: string): boolean { + return templateName in STANDARD_EXPORT_TEMPLATE_NAME_MAPPING; +} + +/** Whether the given export label, as sent by the backend on an export report action, belongs to one of the standard (i.e. not user-defined) export templates */ +function isStandardExportTemplateLabel(label: string): boolean { + return STANDARD_EXPORT_TEMPLATE_LABELS.has(label); +} + +export { + getConnectionNameFromRouteParam, + getRouteParamForConnection, + getSearchValueForConnection, + getStandardExportTemplateDisplayName, + isStandardExportTemplate, + isStandardExportTemplateLabel, +}; diff --git a/tests/unit/SearchAutocompleteUtilsTest.ts b/tests/unit/SearchAutocompleteUtilsTest.ts index f0b28ea709df..759d48acc635 100644 --- a/tests/unit/SearchAutocompleteUtilsTest.ts +++ b/tests/unit/SearchAutocompleteUtilsTest.ts @@ -1,6 +1,6 @@ import type {SubstitutionMap} from '@components/Search/SearchRouter/getQueryWithSubstitutions'; -import {getSearchValueForConnection, getStandardExportTemplateDisplayName} from '@libs/AccountingUtils'; +import {getSearchValueForConnection, getStandardExportTemplateDisplayName, isStandardExportTemplate, isStandardExportTemplateLabel} from '@libs/AccountingUtils'; import {getTrimmedUserSearchQueryPreservingComma, parseForLiveMarkdown} from '@libs/SearchAutocompleteUtils'; import CONST from '@src/CONST'; @@ -554,10 +554,38 @@ describe('SearchAutocompleteUtils', () => { expect(getStandardExportTemplateDisplayName(CONST.REPORT.EXPORT_OPTIONS.REPORT_LEVEL_EXPORT)).toBe(CONST.REPORT.EXPORT_OPTION_LABELS.REPORT_LEVEL_EXPORT); }); + it('returns display name for the Canadian multiple tax export template', () => { + expect(getStandardExportTemplateDisplayName(CONST.REPORT.EXPORT_OPTIONS.MULTIPLE_TAX_EXPORT)).toBe(CONST.REPORT.EXPORT_OPTION_LABELS.MULTIPLE_TAX_EXPORT); + }); + it('returns template name as-is when no standard mapping', () => { const customName = 'Custom Export Layout'; expect(getStandardExportTemplateDisplayName(customName)).toBe(customName); }); }); + + describe('isStandardExportTemplate', () => { + it('returns true for every standard export template ID', () => { + expect(isStandardExportTemplate(CONST.REPORT.EXPORT_OPTIONS.EXPENSE_LEVEL_EXPORT)).toBe(true); + expect(isStandardExportTemplate(CONST.REPORT.EXPORT_OPTIONS.REPORT_LEVEL_EXPORT)).toBe(true); + expect(isStandardExportTemplate(CONST.REPORT.EXPORT_OPTIONS.MULTIPLE_TAX_EXPORT)).toBe(true); + }); + + it('returns false for a custom template ID', () => { + expect(isStandardExportTemplate('Custom Export Layout')).toBe(false); + }); + }); + + describe('isStandardExportTemplateLabel', () => { + it('returns true for every standard export template label', () => { + expect(isStandardExportTemplateLabel(CONST.REPORT.EXPORT_OPTION_LABELS.EXPENSE_LEVEL_EXPORT)).toBe(true); + expect(isStandardExportTemplateLabel(CONST.REPORT.EXPORT_OPTION_LABELS.REPORT_LEVEL_EXPORT)).toBe(true); + expect(isStandardExportTemplateLabel(CONST.REPORT.EXPORT_OPTION_LABELS.MULTIPLE_TAX_EXPORT)).toBe(true); + }); + + it('returns false for a custom template label', () => { + expect(isStandardExportTemplateLabel('Custom Export Layout')).toBe(false); + }); + }); }); });