From 43b3edb94f3e518a912727a85ae04440198a8d80 Mon Sep 17 00:00:00 2001 From: Krishna Chaitanya Date: Wed, 16 Sep 2026 14:42:20 +0530 Subject: [PATCH 1/8] Add Vendor column and filter to expense Search --- src/CONST/index.ts | 10 + src/ONYXKEYS.ts | 8 + src/components/ColumnsSettingsList.tsx | 22 +- .../AdvancedFilters/FilterList.tsx | 21 +- .../FilterComponents/ListFilterContent.tsx | 3 + .../FilterComponents/VendorSelector.tsx | 96 + .../SearchPageHeader/useSearchFiltersBar.tsx | 18 +- src/components/Search/SearchTableHeader.tsx | 24 +- .../TransactionItemRowWide.tsx | 11 +- src/hooks/useAdvancedSearchFilters.ts | 12 +- src/hooks/useLoadSearchVendorData.ts | 59 + src/languages/de.ts | 2 + src/languages/el.ts | 2 + src/languages/en.ts | 2 + src/languages/es.ts | 2 + src/languages/fr.ts | 2 + src/languages/it.ts | 2 + src/languages/ja.ts | 2 + src/languages/nl.ts | 2 + src/languages/pl.ts | 2 + src/languages/pt-BR.ts | 2 + src/languages/zh-hans.ts | 2 + src/libs/API/types.ts | 2 + src/libs/PolicyUtils.ts | 46 + src/libs/SearchParser/autocompleteParser.js | 1550 +++++++++-------- .../SearchParser/autocompleteParser.peggy | 1 + src/libs/SearchParser/baseRules.peggy | 1 + src/libs/SearchParser/searchParser.js | 1526 ++++++++-------- src/libs/SearchParser/searchParser.peggy | 1 + src/libs/SearchQueryUtils.ts | 5 + src/libs/SearchUIUtils.ts | 45 +- src/libs/actions/Search.ts | 29 + src/libs/getSearchColumnContentToMeasure.ts | 6 +- src/pages/Search/SearchColumnsPage.tsx | 18 +- src/pages/Search/SearchSavePage.tsx | 12 + src/styles/utils/index.ts | 1 + src/types/form/SearchAdvancedFiltersForm.ts | 5 + tests/unit/PolicyUtilsTest.ts | 62 + tests/unit/Search/SearchQueryUtilsTest.ts | 27 + tests/unit/Search/SearchUIUtilsTest.ts | 27 + .../ColumnAvailabilityTest.ts.snap | 1 + .../hooks/useAdvancedSearchFilters.test.ts | 33 + 42 files changed, 2171 insertions(+), 1533 deletions(-) create mode 100644 src/components/Search/FilterComponents/VendorSelector.tsx create mode 100644 src/hooks/useLoadSearchVendorData.ts diff --git a/src/CONST/index.ts b/src/CONST/index.ts index 4dfc5132a368..eba7849b8136 100644 --- a/src/CONST/index.ts +++ b/src/CONST/index.ts @@ -7357,6 +7357,11 @@ const CONST = { search: true, reportView: true, }, + VENDOR: { + column: this.TABLE_COLUMNS.VENDOR, + search: true, + reportView: false, + }, DESCRIPTION: { column: this.TABLE_COLUMNS.DESCRIPTION, search: true, @@ -7718,6 +7723,7 @@ const CONST = { POSTED: 'posted', EXPORTED: 'exported', MERCHANT: 'merchant', + VENDOR: 'vendor', DESCRIPTION: 'description', FROM: 'from', TO: 'to', @@ -7828,6 +7834,7 @@ const CONST = { EXPORTER: 'exporter', CATEGORY: 'category', TAG: 'tag', + VENDOR: 'vendor', TAX_RATE: 'taxRate', CARD_ID: 'cardID', FEED: 'feed', @@ -7879,6 +7886,7 @@ const CONST = { TAG_EMPTY_VALUE: 'none', CATEGORY_EMPTY_VALUE: 'none', CATEGORY_DEFAULT_VALUE: 'Uncategorized', + VENDOR_EMPTY_VALUE: 'none', MERCHANT_EMPTY_VALUE: 'none', SEARCH_ROUTER_ITEM_TYPE: { CONTEXTUAL_SUGGESTION: 'contextualSuggestion', @@ -7914,6 +7922,7 @@ const CONST = { EXPORTER: 'exporter', CATEGORY: 'category', TAG: 'tag', + VENDOR: 'vendor', TAX_RATE: 'tax-rate', CARD_ID: 'card', FEED: 'feed', @@ -7960,6 +7969,7 @@ const CONST = { [this.TABLE_COLUMNS.POSTED]: 'posted', [this.TABLE_COLUMNS.EXPORTED]: 'exported', [this.TABLE_COLUMNS.MERCHANT]: 'merchant', + [this.TABLE_COLUMNS.VENDOR]: 'vendor', [this.TABLE_COLUMNS.DESCRIPTION]: 'description', [this.TABLE_COLUMNS.FROM]: 'from', [this.TABLE_COLUMNS.TO]: 'to', diff --git a/src/ONYXKEYS.ts b/src/ONYXKEYS.ts index ffa163f75107..5644cb547c7d 100755 --- a/src/ONYXKEYS.ts +++ b/src/ONYXKEYS.ts @@ -495,6 +495,12 @@ const ONYXKEYS = { /** Set while search filter category data is loading */ RAM_ONLY_IS_LOADING_SEARCH_FILTERS_CATEGORY_DATA: 'isLoadingSearchFiltersCategoryData', + /** Set whether the search filters vendor data has loaded */ + IS_SEARCH_FILTERS_VENDOR_DATA_LOADED: 'isSearchFiltersVendorDataLoaded', + + /** Set while search filter vendor data is loading */ + RAM_ONLY_IS_LOADING_SEARCH_FILTERS_VENDOR_DATA: 'isLoadingSearchFiltersVendorData', + HAS_LOADED_APP: 'hasLoadedApp', IS_TEST_TOOLS_MODAL_OPEN: 'isTestToolsModalOpen', @@ -1735,6 +1741,8 @@ type OnyxValuesMapping = { [ONYXKEYS.IS_SEARCH_FILTERS_CARD_DATA_LOADED]: boolean; [ONYXKEYS.IS_SEARCH_FILTERS_CATEGORY_DATA_LOADED]: boolean; [ONYXKEYS.RAM_ONLY_IS_LOADING_SEARCH_FILTERS_CATEGORY_DATA]: boolean; + [ONYXKEYS.IS_SEARCH_FILTERS_VENDOR_DATA_LOADED]: boolean; + [ONYXKEYS.RAM_ONLY_IS_LOADING_SEARCH_FILTERS_VENDOR_DATA]: boolean; [ONYXKEYS.IS_LOADING_SUBSCRIPTION_DATA]: boolean; [ONYXKEYS.IS_PENDING_UPDATE_PERSONAL_KARMA]: boolean; [ONYXKEYS.IS_TEST_TOOLS_MODAL_OPEN]: boolean; diff --git a/src/components/ColumnsSettingsList.tsx b/src/components/ColumnsSettingsList.tsx index 304de4ec2acb..117bd74585fe 100644 --- a/src/components/ColumnsSettingsList.tsx +++ b/src/components/ColumnsSettingsList.tsx @@ -1,12 +1,19 @@ import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset'; import useListKeyboardNav from '@hooks/useListKeyboardNav'; import useLocalize from '@hooks/useLocalize'; +import useOnyx from '@hooks/useOnyx'; +import usePermissions from '@hooks/usePermissions'; import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; +import {getVendorSearchAvailability} from '@libs/PolicyUtils'; import {getSearchColumnTranslationKey} from '@libs/SearchUIUtils'; import CONST from '@src/CONST'; +import ONYXKEYS from '@src/ONYXKEYS'; +import type {Policy} from '@src/types/onyx'; + +import type {OnyxCollection} from 'react-native-onyx'; import React, {useRef, useState} from 'react'; import {View} from 'react-native'; @@ -74,6 +81,11 @@ function ColumnsSettingsList({allColumns, defaultSelectedColumns, currentColumns const styles = useThemeStyles(); const icons = useMemoizedLazyExpensifyIcons(['DragHandles']); const {translate, localeCompare} = useLocalize(); + const {isBetaEnabled} = usePermissions(); + const isVendorMatchingBetaEnabled = isBetaEnabled(CONST.BETAS.VENDOR_MATCHING); + const [shouldUseSupplierLabel = false] = useOnyx(ONYXKEYS.COLLECTION.POLICY, { + selector: (allPolicies: OnyxCollection) => getVendorSearchAvailability(allPolicies, isVendorMatchingBetaEnabled).shouldUseSupplierLabel, + }); const isGrouped = !!groupBy; @@ -85,8 +97,8 @@ function ColumnsSettingsList({allColumns, defaultSelectedColumns, currentColumns const unselected = columnsToSort .filter((col) => !col.isSelected) .sort((a, b) => { - const textA = translate(getSearchColumnTranslationKey(a.value)); - const textB = translate(getSearchColumnTranslationKey(b.value)); + const textA = translate(getSearchColumnTranslationKey(a.value, shouldUseSupplierLabel)); + const textB = translate(getSearchColumnTranslationKey(b.value, shouldUseSupplierLabel)); return localeCompare(textA, textB); }); return [...selected, ...unselected]; @@ -118,7 +130,7 @@ function ColumnsSettingsList({allColumns, defaultSelectedColumns, currentColumns const isEffectivelySelected = isRequired || isSelected; const isDragDisabled = !isEffectivelySelected; return { - text: translate(getSearchColumnTranslationKey(columnId)), + text: translate(getSearchColumnTranslationKey(columnId, shouldUseSupplierLabel)), value: columnId, keyForList: columnId, isSelected: isEffectivelySelected, @@ -164,8 +176,8 @@ function ColumnsSettingsList({allColumns, defaultSelectedColumns, currentColumns const selectedCols = prevColumns.filter((col) => col.isSelected); const unselected = prevColumns.filter((col) => !col.isSelected && col.columnId !== updatedColumnId); const unselectedSorted = unselected.sort((a, b) => { - const textA = translate(getSearchColumnTranslationKey(a.columnId)); - const textB = translate(getSearchColumnTranslationKey(b.columnId)); + const textA = translate(getSearchColumnTranslationKey(a.columnId, shouldUseSupplierLabel)); + const textB = translate(getSearchColumnTranslationKey(b.columnId, shouldUseSupplierLabel)); return localeCompare(textA, textB); }); return [...selectedCols, {columnId: updatedColumnId, isSelected: true}, ...unselectedSorted]; diff --git a/src/components/Search/FilterComponents/AdvancedFilters/FilterList.tsx b/src/components/Search/FilterComponents/AdvancedFilters/FilterList.tsx index 63001fbc257d..232bce2ac744 100644 --- a/src/components/Search/FilterComponents/AdvancedFilters/FilterList.tsx +++ b/src/components/Search/FilterComponents/AdvancedFilters/FilterList.tsx @@ -8,19 +8,26 @@ import Text from '@components/Text'; import useAdvancedSearchFilters from '@hooks/useAdvancedSearchFilters'; import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset'; import useLocalize from '@hooks/useLocalize'; +import useOnyx from '@hooks/useOnyx'; +import usePermissions from '@hooks/usePermissions'; import useStyleUtils from '@hooks/useStyleUtils'; import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; import getButtonState from '@libs/getButtonState'; -import {FILTER_VIEW_MAP} from '@libs/SearchUIUtils'; +import {getVendorSearchAvailability} from '@libs/PolicyUtils'; +import {FILTER_VIEW_MAP, getSearchFilterLabelKey} from '@libs/SearchUIUtils'; import type {SearchFilter} from '@libs/SearchUIUtils'; import variables from '@styles/variables'; +import CONST from '@src/CONST'; +import ONYXKEYS from '@src/ONYXKEYS'; +import type {Policy} from '@src/types/onyx'; import type {SearchDataTypes} from '@src/types/onyx/SearchResults'; import type {StyleProp, ViewStyle} from 'react-native'; +import type {OnyxCollection} from 'react-native-onyx'; import React from 'react'; import {View} from 'react-native'; @@ -49,15 +56,17 @@ type FilterListProps = FilterItemCallbacks & { type FilterItemProps = FilterItemCallbacks & { filterKey: SearchFilter['key']; isSelected?: boolean; + shouldUseSupplierLabel: boolean; }; -function FilterItem({filterKey, isSelected, onPress, onHoverIn, onFocus}: FilterItemProps) { +function FilterItem({filterKey, isSelected, shouldUseSupplierLabel, onPress, onHoverIn, onFocus}: FilterItemProps) { const {translate} = useLocalize(); const styles = useThemeStyles(); const StyleUtils = useStyleUtils(); const theme = useTheme(); - const {labelKey, icon} = FILTER_VIEW_MAP[filterKey]; + const labelKey = getSearchFilterLabelKey(filterKey, shouldUseSupplierLabel); + const {icon} = FILTER_VIEW_MAP[filterKey]; const icons = useMemoizedLazyExpensifyIcons(['ArrowRight', icon]); const getPressableBackgroundStyle = (pressed: boolean) => { @@ -111,6 +120,11 @@ function FilterItem({filterKey, isSelected, onPress, onHoverIn, onFocus}: Filter function FilterList({type, policyID, selectedFilter, style, contentContainerStyle, onHoverIn, onFocus, onPress, onPointerMove, onPointerLeave}: FilterListProps) { const styles = useThemeStyles(); const typeFiltersKeys = useAdvancedSearchFilters(type, policyID); + const {isBetaEnabled} = usePermissions(); + const isVendorMatchingBetaEnabled = isBetaEnabled(CONST.BETAS.VENDOR_MATCHING); + const [shouldUseSupplierLabel = false] = useOnyx(ONYXKEYS.COLLECTION.POLICY, { + selector: (allPolicies: OnyxCollection) => getVendorSearchAvailability(allPolicies, isVendorMatchingBetaEnabled).shouldUseSupplierLabel, + }); return ( ; @@ -174,6 +175,7 @@ function ListFilterContent({ case CONST.SEARCH.SYNTAX_FILTER_KEYS.TAX_RATE: case CONST.SEARCH.SYNTAX_FILTER_KEYS.EXPORTED_TO: case CONST.SEARCH.SYNTAX_FILTER_KEYS.TAG: + case CONST.SEARCH.SYNTAX_FILTER_KEYS.VENDOR: case CONST.SEARCH.SYNTAX_FILTER_KEYS.CATEGORY: { const Component = { [CONST.SEARCH.SYNTAX_FILTER_KEYS.FEED]: FeedSelector, @@ -183,6 +185,7 @@ function ListFilterContent({ [CONST.SEARCH.SYNTAX_FILTER_KEYS.TAX_RATE]: TaxRateSelector, [CONST.SEARCH.SYNTAX_FILTER_KEYS.EXPORTED_TO]: ExportedToSelector, [CONST.SEARCH.SYNTAX_FILTER_KEYS.TAG]: TagSelector, + [CONST.SEARCH.SYNTAX_FILTER_KEYS.VENDOR]: VendorSelector, [CONST.SEARCH.SYNTAX_FILTER_KEYS.CATEGORY]: CategorySelector, }[baseFilterKey]; content = ( diff --git a/src/components/Search/FilterComponents/VendorSelector.tsx b/src/components/Search/FilterComponents/VendorSelector.tsx new file mode 100644 index 000000000000..40e7a913bd53 --- /dev/null +++ b/src/components/Search/FilterComponents/VendorSelector.tsx @@ -0,0 +1,96 @@ +import ActivityIndicator from '@components/ActivityIndicator'; +import type {Filter, SearchFilterCommonProps} from '@components/Search/types'; + +import useLoadSearchVendorData from '@hooks/useLoadSearchVendorData'; +import useLocalize from '@hooks/useLocalize'; +import useOnyx from '@hooks/useOnyx'; +import usePermissions from '@hooks/usePermissions'; +import useTheme from '@hooks/useTheme'; +import useThemeStyles from '@hooks/useThemeStyles'; + +import {getVendorSearchAvailability} from '@libs/PolicyUtils'; +import {getAllPolicyValues, sortOptionsWithEmptyValue} from '@libs/SearchQueryUtils'; + +import CONST from '@src/CONST'; +import ONYXKEYS from '@src/ONYXKEYS'; +import type {Policy, PolicyVendors} from '@src/types/onyx'; +import {getEmptyObject} from '@src/types/utils/EmptyObject'; + +import type {OnyxCollection} from 'react-native-onyx'; + +import React from 'react'; +import {View} from 'react-native'; + +import MultiSelect from './MultiSelect'; + +type VendorSelectorProps = SearchFilterCommonProps & { + policyID: Filter | undefined; +}; + +function VendorSelector({value = [], policyID, selectionListTextInputStyle, selectionListStyle, autoFocus, footer, onChange}: VendorSelectorProps) { + const {translate, localeCompare} = useLocalize(); + const {isBetaEnabled} = usePermissions(); + const isVendorMatchingBetaEnabled = isBetaEnabled(CONST.BETAS.VENDOR_MATCHING); + const {isLoadingInitialVendors} = useLoadSearchVendorData({shouldRefresh: true}); + const theme = useTheme(); + const styles = useThemeStyles(); + const [vendorAvailability] = useOnyx(ONYXKEYS.COLLECTION.POLICY, { + selector: (allPolicies: OnyxCollection) => getVendorSearchAvailability(allPolicies, isVendorMatchingBetaEnabled), + }); + const [allPolicyVendors = getEmptyObject>>()] = useOnyx(ONYXKEYS.COLLECTION.POLICY_VENDORS); + + const noVendorLabel = translate(vendorAvailability?.shouldUseSupplierLabel ? 'search.noSupplier' : 'search.noVendor'); + const selectedVendorItems = value.map((vendor) => { + if (vendor === CONST.SEARCH.VENDOR_EMPTY_VALUE) { + return {text: noVendorLabel, value: vendor}; + } + return {text: vendor, value: vendor}; + }); + + // Vendor lists are only offered for the workspaces where the vendor feature is on, so stale lists left behind by a + // disconnected integration never surface in the picker. + const eligiblePolicyIDs = new Set(vendorAvailability?.eligiblePolicyIDs ?? []); + const eligiblePolicyVendors: OnyxCollection = Object.fromEntries( + Object.entries(allPolicyVendors).filter(([key]) => eligiblePolicyIDs.has(key.replace(ONYXKEYS.COLLECTION.POLICY_VENDORS, ''))), + ); + + const vendorItems = [{text: noVendorLabel, value: CONST.SEARCH.VENDOR_EMPTY_VALUE as string}]; + const uniqueVendorNames = new Set( + getAllPolicyValues(policyID?.value?.length ? policyID : undefined, ONYXKEYS.COLLECTION.POLICY_VENDORS, eligiblePolicyVendors).flatMap((policyVendors) => + Object.values(policyVendors ?? {}).map((vendor) => vendor.name), + ), + ); + vendorItems.push( + ...Array.from(uniqueVendorNames) + .filter(Boolean) + .map((vendorName) => ({text: vendorName, value: vendorName})) + .toSorted((a, b) => sortOptionsWithEmptyValue(a.text, b.text, localeCompare)), + ); + + if (isLoadingInitialVendors) { + return ( + + + + ); + } + + return ( + = CONST.STANDARD_LIST_ITEM_LIMIT} + autoFocus={autoFocus} + selectionListTextInputStyle={selectionListTextInputStyle} + selectionListStyle={selectionListStyle} + footer={footer} + onChange={(vendors) => onChange(vendors.map((vendor) => vendor.value))} + /> + ); +} + +export default VendorSelector; diff --git a/src/components/Search/SearchPageHeader/useSearchFiltersBar.tsx b/src/components/Search/SearchPageHeader/useSearchFiltersBar.tsx index dad5542ab987..7dc3cd136a81 100644 --- a/src/components/Search/SearchPageHeader/useSearchFiltersBar.tsx +++ b/src/components/Search/SearchPageHeader/useSearchFiltersBar.tsx @@ -12,23 +12,27 @@ import {useCurrencyListActions} from '@hooks/useCurrencyList'; import useLocalize from '@hooks/useLocalize'; import useNetwork from '@hooks/useNetwork'; import useOnyx from '@hooks/useOnyx'; +import usePermissions from '@hooks/usePermissions'; import {shouldShowInitialCategoryFilterLoading} from '@hooks/useSearchFilterSync'; import {close} from '@libs/actions/Modal'; import {setSearchContext} from '@libs/actions/Search'; import Navigation from '@libs/Navigation/Navigation'; +import {getVendorSearchAvailability} from '@libs/PolicyUtils'; import {buildQueryStringWithResetFilters, hasFiltersChangedFromDefault, removeNegation} from '@libs/SearchQueryUtils'; -import {FILTER_VIEW_MAP, isAmountFilterKey, isDateFilterKey, isReportFieldKey, isTextFilterKey, mapFiltersFormToLabelValueList, SKIPPED_SEARCH_FILTERS} from '@libs/SearchUIUtils'; +import {getSearchFilterLabelKey, isAmountFilterKey, isDateFilterKey, isReportFieldKey, isTextFilterKey, mapFiltersFormToLabelValueList, SKIPPED_SEARCH_FILTERS} from '@libs/SearchUIUtils'; import type {SearchFilter} from '@libs/SearchUIUtils'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import type {SearchAdvancedFiltersForm} from '@src/types/form'; import type {SearchAdvancedFiltersKey} from '@src/types/form/SearchAdvancedFiltersForm'; +import type {Policy} from '@src/types/onyx'; import {getEmptyObject} from '@src/types/utils/EmptyObject'; import type WithSentryLabel from '@src/types/utils/SentryLabel'; import type {ReactNode} from 'react'; +import type {OnyxCollection} from 'react-native-onyx'; import React from 'react'; @@ -51,6 +55,7 @@ type FilterPopupProps = { baseFilterKey: SearchFilter['key']; isDefault: boolean; searchAdvancedFiltersForm: Partial; + shouldUseSupplierLabel: boolean; closeOverlay: () => void; setPopoverWidth: PopoverComponentProps['setPopoverWidth']; updateFilterForm: (values: Partial) => void; @@ -60,9 +65,9 @@ function getFilterSentryLabel(filterKey: SearchAdvancedFiltersKey | SearchFilter return `Search-Filter-${filterKey}`; } -function FilterPopup({baseFilterKey, isDefault, searchAdvancedFiltersForm, closeOverlay, setPopoverWidth, updateFilterForm}: FilterPopupProps) { +function FilterPopup({baseFilterKey, isDefault, searchAdvancedFiltersForm, shouldUseSupplierLabel, closeOverlay, setPopoverWidth, updateFilterForm}: FilterPopupProps) { const {translate} = useLocalize(); - const label = translate(FILTER_VIEW_MAP[baseFilterKey].labelKey); + const label = translate(getSearchFilterLabelKey(baseFilterKey, shouldUseSupplierLabel)); const closeModalAndUpdateFilterForm = (values: Partial) => { close(() => updateFilterForm(values)); @@ -150,6 +155,11 @@ function useSearchFiltersBar(queryJSON: SearchQueryJSON): UseSearchFiltersBarRes const {shouldShowFiltersBarLoading, currentSearchResults} = useSearchResultsContext(); const {currentSearchQueryJSON, currentDefaultSearchQueryJSON, currentDefaultSearchQueryFilterKeys} = useSearchQueryContext(); const {updateFilterQueryParams} = useUpdateFilterQuery(queryJSON); + const {isBetaEnabled} = usePermissions(); + const isVendorMatchingBetaEnabled = isBetaEnabled(CONST.BETAS.VENDOR_MATCHING); + const [shouldUseSupplierLabel = false] = useOnyx(ONYXKEYS.COLLECTION.POLICY, { + selector: (allPolicies: OnyxCollection) => getVendorSearchAvailability(allPolicies, isVendorMatchingBetaEnabled).shouldUseSupplierLabel, + }); const filters = mapFiltersFormToLabelValueList( searchAdvancedFiltersForm, currentDefaultSearchQueryFilterKeys, @@ -165,6 +175,7 @@ function useSearchFiltersBar(queryJSON: SearchQueryJSON): UseSearchFiltersBarRes baseFilterKey={removeNegation(filterKey)} isDefault={isDefault} searchAdvancedFiltersForm={searchAdvancedFiltersForm} + shouldUseSupplierLabel={shouldUseSupplierLabel} closeOverlay={closeOverlay} setPopoverWidth={setPopoverWidth} updateFilterForm={updateFilterQueryParams} @@ -206,6 +217,7 @@ function useSearchFiltersBar(queryJSON: SearchQueryJSON): UseSearchFiltersBarRes updateFilterQueryParams({[filterKey]: undefined}); }, }), + shouldUseSupplierLabel, ); const resetFilters = () => { diff --git a/src/components/Search/SearchTableHeader.tsx b/src/components/Search/SearchTableHeader.tsx index 1969275c0f7b..b452dc6b2041 100644 --- a/src/components/Search/SearchTableHeader.tsx +++ b/src/components/Search/SearchTableHeader.tsx @@ -1,12 +1,20 @@ import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset'; +import useOnyx from '@hooks/useOnyx'; +import usePermissions from '@hooks/usePermissions'; import useResponsiveLayout from '@hooks/useResponsiveLayout'; import useThemeStyles from '@hooks/useThemeStyles'; +import {getVendorSearchAvailability} from '@libs/PolicyUtils'; +import {getSearchColumnTranslationKey} from '@libs/SearchUIUtils'; + import CONST from '@src/CONST'; import type {TranslationPaths} from '@src/languages/types'; +import ONYXKEYS from '@src/ONYXKEYS'; +import type {Policy} from '@src/types/onyx'; import type {SearchDataTypes} from '@src/types/onyx/SearchResults'; import type IconAsset from '@src/types/utils/IconAsset'; +import type {OnyxCollection} from 'react-native-onyx'; import type {ValueOf} from 'type-fest'; import React, {useCallback, useMemo} from 'react'; @@ -67,6 +75,11 @@ const getExpenseHeaders = (groupBy?: SearchGroupBy): SearchColumnConfig[] => [ translationKey: 'common.merchant', canEdit: true, }, + { + columnName: CONST.SEARCH.TABLE_COLUMNS.VENDOR, + translationKey: 'common.vendor', + isColumnSortable: false, + }, { columnName: CONST.SEARCH.TABLE_COLUMNS.DESCRIPTION, translationKey: 'common.description', @@ -572,6 +585,11 @@ function SearchTableHeader({ // eslint-disable-next-line rulesdir/prefer-shouldUseNarrowLayout-instead-of-isSmallScreenWidth const {isSmallScreenWidth, isMediumScreenWidth} = useResponsiveLayout(); const displayNarrowVersion = isMediumScreenWidth || isSmallScreenWidth; + const {isBetaEnabled} = usePermissions(); + const isVendorMatchingBetaEnabled = isBetaEnabled(CONST.BETAS.VENDOR_MATCHING); + const [shouldUseSupplierLabel = false] = useOnyx(ONYXKEYS.COLLECTION.POLICY, { + selector: (allPolicies: OnyxCollection) => getVendorSearchAvailability(allPolicies, isVendorMatchingBetaEnabled).shouldUseSupplierLabel, + }); // Only load Profile icon when it's needed for EXPENSE_REPORT type or grouped transactions const icons = useMemoizedLazyExpensifyIcons(type === CONST.SEARCH.DATA_TYPES.EXPENSE_REPORT || !!groupBy ? ['Profile', 'Bank', 'CreditCard'] : []) satisfies SearchHeaderIcons; @@ -601,7 +619,9 @@ function SearchTableHeader({ for (const col of columns) { const config = configMap.get(col); if (config) { - orderedConfig.push(config); + orderedConfig.push( + config.columnName === CONST.SEARCH.TABLE_COLUMNS.VENDOR ? {...config, translationKey: getSearchColumnTranslationKey(config.columnName, shouldUseSupplierLabel)} : config, + ); addedColumns.add(col); } } @@ -613,7 +633,7 @@ function SearchTableHeader({ } return orderedConfig; - }, [columnConfig, columns]); + }, [columnConfig, columns, shouldUseSupplierLabel]); if (displayNarrowVersion) { return; diff --git a/src/components/TransactionItemRow/TransactionItemRowWide.tsx b/src/components/TransactionItemRow/TransactionItemRowWide.tsx index bcf69deb6697..13610187f0f8 100644 --- a/src/components/TransactionItemRow/TransactionItemRowWide.tsx +++ b/src/components/TransactionItemRow/TransactionItemRowWide.tsx @@ -25,7 +25,7 @@ import useThemeStyles from '@hooks/useThemeStyles'; import {getCategoryGLCode} from '@libs/CategoryUtils'; import getBase62ReportID from '@libs/getBase62ReportID'; -import {isTaxCodeCustomized, getTagGLCode} from '@libs/PolicyUtils'; +import {getTagGLCode, getVendorDisplayName, isTaxCodeCustomized} from '@libs/PolicyUtils'; import {getReportName} from '@libs/ReportNameUtils'; import {getReimbursableTotal, isExpenseReport} from '@libs/ReportUtils'; import {getViolationsForTransaction} from '@libs/SearchUIUtils'; @@ -391,6 +391,15 @@ function TransactionItemRowWide({ /> ); + case CONST.SEARCH.TABLE_COLUMNS.VENDOR: + return ( + + + + ); case CONST.SEARCH.TABLE_COLUMNS.DESCRIPTION: return ( >>()] = useOnyx(ONYXKEYS.COLLECTION.POLICY, {selector: advancedSearchPoliciesSelector}); const [policyDerived] = useOnyx(ONYXKEYS.COLLECTION.POLICY, {selector: policyDerivedSelector}); + const {isBetaEnabled} = usePermissions(); + const isVendorMatchingBetaEnabled = isBetaEnabled(CONST.BETAS.VENDOR_MATCHING); + const [isVendorFilterAvailable = false] = useOnyx(ONYXKEYS.COLLECTION.POLICY, { + selector: (allPolicies: OnyxCollection) => getVendorSearchAvailability(allPolicies, isVendorMatchingBetaEnabled).isAvailable, + }); const [allPolicyTagLists = getEmptyObject>>()] = useOnyx(ONYXKEYS.COLLECTION.POLICY_TAGS); const selectedPolicyTagLists = policyID?.value?.length ? getAllPolicyValues(policyID, ONYXKEYS.COLLECTION.POLICY_TAGS, allPolicyTagLists) : []; const [hasTags] = useOnyx(ONYXKEYS.COLLECTION.POLICY_TAGS, {selector: hasTagsSelector}); @@ -353,6 +360,9 @@ function useAdvancedSearchFilters(type: SearchDataTypes | undefined, policyID: F if (key === CONST.SEARCH.SYNTAX_FILTER_KEYS.TAG && !shouldDisplayTagFilter) { return; } + if (key === CONST.SEARCH.SYNTAX_FILTER_KEYS.VENDOR && !isVendorFilterAvailable) { + return; + } if ( (key === CONST.SEARCH.SYNTAX_FILTER_KEYS.CARD_ID || key === CONST.SEARCH.SYNTAX_FILTER_KEYS.POSTED || key === CONST.SEARCH.SYNTAX_FILTER_KEYS.FEED) && !shouldDisplayCardFilter diff --git a/src/hooks/useLoadSearchVendorData.ts b/src/hooks/useLoadSearchVendorData.ts new file mode 100644 index 000000000000..0995cfab7082 --- /dev/null +++ b/src/hooks/useLoadSearchVendorData.ts @@ -0,0 +1,59 @@ +import {openSearchVendorFiltersPage} from '@libs/actions/Search'; + +import ONYXKEYS from '@src/ONYXKEYS'; + +import {useEffect, useRef} from 'react'; + +import useNetwork from './useNetwork'; +import useOnyx from './useOnyx'; + +type UseLoadSearchVendorDataParams = { + /** Whether vendor data should be loaded. */ + shouldLoad?: boolean; + + /** Whether already loaded vendor data should be refreshed. */ + shouldRefresh?: boolean; +}; + +function useLoadSearchVendorData({shouldLoad = true, shouldRefresh = false}: UseLoadSearchVendorDataParams = {}) { + const {isOffline} = useNetwork(); + const [areVendorsLoaded] = useOnyx(ONYXKEYS.IS_SEARCH_FILTERS_VENDOR_DATA_LOADED); + const [isLoadingVendors] = useOnyx(ONYXKEYS.RAM_ONLY_IS_LOADING_SEARCH_FILTERS_VENDOR_DATA); + const hasRequestedVendorDataRef = useRef(false); + const hasObservedVendorRequestStateRef = useRef(!!areVendorsLoaded || isLoadingVendors !== undefined); + + useEffect(() => { + if (areVendorsLoaded || isLoadingVendors !== undefined) { + hasObservedVendorRequestStateRef.current = true; + } + + const wasVendorRequestStateCleared = hasRequestedVendorDataRef.current && hasObservedVendorRequestStateRef.current && !areVendorsLoaded && isLoadingVendors === undefined; + if (wasVendorRequestStateCleared) { + hasRequestedVendorDataRef.current = false; + hasObservedVendorRequestStateRef.current = false; + } + + if (!shouldLoad) { + hasRequestedVendorDataRef.current = false; + hasObservedVendorRequestStateRef.current = false; + return; + } + + if (isLoadingVendors) { + hasRequestedVendorDataRef.current = true; + return; + } + + if (isOffline || hasRequestedVendorDataRef.current || (areVendorsLoaded && !shouldRefresh)) { + return; + } + hasRequestedVendorDataRef.current = true; + openSearchVendorFiltersPage(); + }, [areVendorsLoaded, isLoadingVendors, isOffline, shouldLoad, shouldRefresh]); + + const isLoadingInitialVendors = shouldLoad && !areVendorsLoaded && !isOffline && isLoadingVendors !== false; + + return {areVendorsLoaded, isLoadingInitialVendors, isOffline}; +} + +export default useLoadSearchVendorData; diff --git a/src/languages/de.ts b/src/languages/de.ts index 727915c764f4..a871c727ceec 100644 --- a/src/languages/de.ts +++ b/src/languages/de.ts @@ -9685,6 +9685,8 @@ Fügen Sie weitere Ausgabelimits hinzu, um den Cashflow Ihres Unternehmens zu sc noCategory: 'Keine Kategorie', noMerchant: 'Kein Händler', noTag: 'Kein Tag', + noVendor: 'Kein Lieferant', + noSupplier: 'Kein Lieferant', expenseType: 'Ausgabenart', receiptType: 'Belegart', receiptTypeValues: { diff --git a/src/languages/el.ts b/src/languages/el.ts index 6525d0b305e8..5d199b6ee635 100644 --- a/src/languages/el.ts +++ b/src/languages/el.ts @@ -9899,6 +9899,8 @@ ${reportName}`, noCategory: 'Χωρίς κατηγορία', noMerchant: 'Χωρίς έμπορο', noTag: 'Χωρίς ετικέτα', + noVendor: 'Χωρίς προμηθευτή', + noSupplier: 'Χωρίς προμηθευτή', expenseType: 'Τύπος εξόδου', receiptType: 'Τύπος απόδειξης', receiptTypeValues: { diff --git a/src/languages/en.ts b/src/languages/en.ts index 81600cdbecca..277e66633d14 100644 --- a/src/languages/en.ts +++ b/src/languages/en.ts @@ -9850,6 +9850,8 @@ const translations = { noCategory: 'No category', noMerchant: 'No merchant', noTag: 'No tag', + noVendor: 'No vendor', + noSupplier: 'No supplier', expenseType: 'Expense type', receiptType: 'Receipt type', receiptTypeValues: { diff --git a/src/languages/es.ts b/src/languages/es.ts index 714eaf0725d3..aea08590ed66 100644 --- a/src/languages/es.ts +++ b/src/languages/es.ts @@ -9534,6 +9534,8 @@ ${reportName}`, noCategory: 'Sin categoría', noMerchant: 'Sin comerciante', noTag: 'Sin etiqueta', + noVendor: 'Sin proveedor', + noSupplier: 'Sin proveedor', expenseType: 'Tipo de gasto', receiptType: 'Tipo de recibo', receiptTypeValues: { diff --git a/src/languages/fr.ts b/src/languages/fr.ts index 5aeebe79771d..6508806e9a43 100644 --- a/src/languages/fr.ts +++ b/src/languages/fr.ts @@ -9705,6 +9705,8 @@ Ajoutez davantage de règles de dépenses pour protéger la trésorerie de l’e noCategory: 'Aucune catégorie', noMerchant: 'Aucun commerçant', noTag: 'Aucun tag', + noVendor: 'Aucun fournisseur', + noSupplier: 'Aucun fournisseur', expenseType: 'Type de dépense', receiptType: 'Type de reçu', receiptTypeValues: { diff --git a/src/languages/it.ts b/src/languages/it.ts index aee10e7ea046..7f4b7c66bd92 100644 --- a/src/languages/it.ts +++ b/src/languages/it.ts @@ -9641,6 +9641,8 @@ Aggiungi altre regole di spesa per proteggere il flusso di cassa aziendale.`, noCategory: 'Nessuna categoria', noMerchant: 'Nessun esercente', noTag: 'Nessun tag', + noVendor: 'Nessun fornitore', + noSupplier: 'Nessun fornitore', expenseType: 'Tipo di spesa', receiptType: 'Tipo di ricevuta', receiptTypeValues: { diff --git a/src/languages/ja.ts b/src/languages/ja.ts index 2690b7ebdbf0..1d806b21cbc6 100644 --- a/src/languages/ja.ts +++ b/src/languages/ja.ts @@ -9508,6 +9508,8 @@ ${reportName}`, noCategory: 'カテゴリなし', noMerchant: '店舗なし', noTag: 'タグなし', + noVendor: 'ベンダーなし', + noSupplier: 'サプライヤーなし', expenseType: '経費の種類', receiptType: '領収書の種類', receiptTypeValues: { diff --git a/src/languages/nl.ts b/src/languages/nl.ts index a1b9e0ca819f..3c2c3a89d182 100644 --- a/src/languages/nl.ts +++ b/src/languages/nl.ts @@ -9597,6 +9597,8 @@ er bestedingsregels toe om de kasstroom van het bedrijf te beschermen.`, noCategory: 'Geen categorie', noMerchant: 'Geen handelaar', noTag: 'Geen tag', + noVendor: 'Geen leverancier', + noSupplier: 'Geen leverancier', expenseType: 'Onkostentype', receiptType: 'Bontype', receiptTypeValues: { diff --git a/src/languages/pl.ts b/src/languages/pl.ts index 74c8ffca208d..7860d6fdcdc2 100644 --- a/src/languages/pl.ts +++ b/src/languages/pl.ts @@ -9629,6 +9629,8 @@ Dodaj więcej zasad wydatków, żeby chronić płynność finansową firmy.`, noCategory: 'Brak kategorii', noMerchant: 'Brak sprzedawcy', noTag: 'Brak tagu', + noVendor: 'Brak dostawcy', + noSupplier: 'Brak dostawcy', expenseType: 'Typ wydatku', receiptType: 'Typ paragonu', receiptTypeValues: { diff --git a/src/languages/pt-BR.ts b/src/languages/pt-BR.ts index 82ffdec4dbc6..9f164432f968 100644 --- a/src/languages/pt-BR.ts +++ b/src/languages/pt-BR.ts @@ -9594,6 +9594,8 @@ Adicione mais regras de gasto para proteger o fluxo de caixa da empresa.`, noCategory: 'Sem categoria', noMerchant: 'Sem comerciante', noTag: 'Sem tag', + noVendor: 'Sem fornecedor', + noSupplier: 'Sem fornecedor', expenseType: 'Tipo de despesa', receiptType: 'Tipo de recibo', receiptTypeValues: { diff --git a/src/languages/zh-hans.ts b/src/languages/zh-hans.ts index 2dab91373c51..3a54d0524357 100644 --- a/src/languages/zh-hans.ts +++ b/src/languages/zh-hans.ts @@ -9257,6 +9257,8 @@ ${reportName}`, noCategory: '无类别', noMerchant: '无商家', noTag: '无标签', + noVendor: '无供应商', + noSupplier: '无供应商', expenseType: '报销类型', receiptType: '收据类型', receiptTypeValues: { diff --git a/src/libs/API/types.ts b/src/libs/API/types.ts index 1bce324cbe41..c81854a48727 100644 --- a/src/libs/API/types.ts +++ b/src/libs/API/types.ts @@ -1489,6 +1489,7 @@ const READ_COMMANDS = { OPEN_SEARCH_PAGE: 'OpenSearchPage', OPEN_SEARCH_CARD_FILTERS_PAGE: 'OpenSearchCardFiltersPage', OPEN_SEARCH_CATEGORY_FILTERS_PAGE: 'OpenSearchCategoryFiltersPage', + OPEN_SEARCH_VENDOR_FILTERS_PAGE: 'OpenSearchVendorFiltersPage', SEARCH: 'Search', GET_TRANSACTIONS_CONVERTED_AMOUNT: 'GetTransactionsConvertedAmount', GET_OLDER_ACTIONS: 'GetOlderActions', @@ -1662,6 +1663,7 @@ type ReadCommandParameters = { [READ_COMMANDS.OPEN_DRAFT_DISTANCE_EXPENSE]: null; [READ_COMMANDS.OPEN_SEARCH_CARD_FILTERS_PAGE]: null; [READ_COMMANDS.OPEN_SEARCH_CATEGORY_FILTERS_PAGE]: null; + [READ_COMMANDS.OPEN_SEARCH_VENDOR_FILTERS_PAGE]: null; [READ_COMMANDS.START_ISSUE_NEW_CARD_FLOW]: Parameters.StartIssueNewCardFlowParams; [READ_COMMANDS.OPEN_CARD_DETAILS_PAGE]: Parameters.OpenCardDetailsPageParams; [READ_COMMANDS.GET_CORPAY_ONBOARDING_FIELDS]: Parameters.GetCorpayOnboardingFieldsParams; diff --git a/src/libs/PolicyUtils.ts b/src/libs/PolicyUtils.ts index 39c4a449a18a..d5ed5f5210c5 100644 --- a/src/libs/PolicyUtils.ts +++ b/src/libs/PolicyUtils.ts @@ -41,6 +41,7 @@ import type { } from '@src/types/onyx/Policy'; import type PolicyEmployee from '@src/types/onyx/PolicyEmployee'; import type Rule from '@src/types/onyx/Rule'; +import type {TransactionCommentVendor} from '@src/types/onyx/Transaction'; import type {WorkspaceTravelSettings} from '@src/types/onyx/TravelSettings'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; @@ -2724,6 +2725,37 @@ function hasVendorFeature(policy: OnyxEntry, isVendorMatchingBetaEnabled ); } +type VendorSearchAvailability = { + /** Whether at least one workspace the user can see has the vendor feature, so Search can offer the vendor filter and column. */ + isAvailable: boolean; + + /** Whether every eligible workspace takes its vendors from Xero, which calls them suppliers. */ + shouldUseSupplierLabel: boolean; + + /** IDs of the workspaces that have the vendor feature. */ + eligiblePolicyIDs: string[]; +}; + +/** + * Search spans every workspace at once, so the vendor filter and column are offered when any workspace has the vendor + * feature, and the "Supplier" wording is only used when no eligible workspace would call them vendors. + */ +function getVendorSearchAvailability(policies: OnyxCollection, isVendorMatchingBetaEnabled: boolean): VendorSearchAvailability { + const eligiblePolicyIDs: string[] = []; + let areAllEligiblePoliciesXero = true; + for (const policy of Object.values(policies ?? {})) { + if (!policy?.id || !hasVendorFeature(policy, isVendorMatchingBetaEnabled)) { + continue; + } + eligiblePolicyIDs.push(policy.id); + if (!isXeroActiveMatchingSource(policy)) { + areAllEligiblePoliciesXero = false; + } + } + const isAvailable = eligiblePolicyIDs.length > 0; + return {isAvailable, shouldUseSupplierLabel: isAvailable && areAllEligiblePoliciesXero, eligiblePolicyIDs}; +} + /** * Single source of truth for which connected integration scopes the vendor field for this workspace * (QBO, Sage Intacct, Xero, Rillet, or DualEntry) and what its vendor list looks like. Returns `undefined` when no @@ -2894,6 +2926,18 @@ function findVendorByID(policy: OnyxEntry, vendorID: string | undefined) return getDualEntryVendors(policy).find((vendor) => vendor.id === vendorID); } +/** + * Display name of the vendor assigned to a transaction, or an empty string when none is assigned. The workspace's + * synced vendor list wins so renames in the accounting system show through, then the name persisted on the + * transaction when the vendor was assigned covers vendors that have since left the synced list. + */ +function getVendorDisplayName(policy: OnyxEntry, vendor: TransactionCommentVendor | undefined): string { + if (!vendor?.externalID) { + return ''; + } + return findVendorByID(policy, vendor.externalID)?.name ?? vendor.name ?? ''; +} + /** * Resolves the text shown for a stored merchant-rule vendor ID. Prefer the active vendor-matching * source, use the unavailable label when its loaded list no longer contains the vendor, and retain @@ -3459,6 +3503,7 @@ export { getConnectedIntegration, getConnectionExporters, findVendorByID, + getVendorDisplayName, getActiveVendorMatchingIntegration, getMatchingVendorByID, getMatchingVendors, @@ -3472,6 +3517,7 @@ export { isXeroActiveMatchingSource, isXeroVendorMatchingActive, hasVendorFeature, + getVendorSearchAvailability, isMatchingVendorListLoaded, getValidConnectedIntegration, getCountOfEnabledTagsOfList, diff --git a/src/libs/SearchParser/autocompleteParser.js b/src/libs/SearchParser/autocompleteParser.js index 61d1cdd36444..a4d0c2eb3221 100644 --- a/src/libs/SearchParser/autocompleteParser.js +++ b/src/libs/SearchParser/autocompleteParser.js @@ -200,112 +200,113 @@ function peg$parse(input, options) { var peg$c14 = "group-currency"; var peg$c15 = "tag"; var peg$c16 = "category"; - var peg$c17 = "to"; - var peg$c18 = "exporter"; - var peg$c19 = "payer"; - var peg$c20 = "paidBy"; - var peg$c21 = "paid-by"; - var peg$c22 = "taxrate"; - var peg$c23 = "tax-rate"; - var peg$c24 = "cardID"; - var peg$c25 = "card"; - var peg$c26 = "bankAccount"; - var peg$c27 = "bank-account"; - var peg$c28 = "from"; - var peg$c29 = "attendee"; - var peg$c30 = "expenseType"; - var peg$c31 = "expense-type"; - var peg$c32 = "receiptType"; - var peg$c33 = "receipt-type"; - var peg$c34 = "withdrawalType"; - var peg$c35 = "withdrawal-type"; - var peg$c36 = "withdrawalStatus"; - var peg$c37 = "withdrawal-status"; - var peg$c38 = "paidStatus"; - var peg$c39 = "paid-status"; - var peg$c40 = "withdrawalid"; - var peg$c41 = "withdrawal-id"; - var peg$c42 = "billable"; - var peg$c43 = "reimbursable"; - var peg$c44 = "type"; - var peg$c45 = "status"; - var peg$c46 = "sortBy"; - var peg$c47 = "sort-by"; - var peg$c48 = "sortOrder"; - var peg$c49 = "sort-order"; - var peg$c50 = "policyID"; - var peg$c51 = "workspace"; - var peg$c52 = "submitted"; - var peg$c53 = "approved"; - var peg$c54 = "paid"; - var peg$c55 = "exported"; - var peg$c56 = "posted"; - var peg$c57 = "withdrawn"; - var peg$c58 = "groupby"; - var peg$c59 = "group-by"; - var peg$c60 = "limit"; - var peg$c61 = "feed"; - var peg$c62 = "title"; - var peg$c63 = "submitteruserid"; - var peg$c64 = "submitter-user-id"; - var peg$c65 = "submitterpayrollid"; - var peg$c66 = "submitter-payroll-id"; - var peg$c67 = "orderdealnumbers"; - var peg$c68 = "order-deal-numbers"; - var peg$c69 = "assignee"; - var peg$c70 = "createdby"; - var peg$c71 = "created-by"; - var peg$c72 = "action"; - var peg$c73 = "total"; - var peg$c74 = "has"; - var peg$c75 = "is"; - var peg$c76 = "purchaseamount"; - var peg$c77 = "purchase-amount"; - var peg$c78 = "purchasecurrency"; - var peg$c79 = "purchase-currency"; - var peg$c80 = "amountdebited"; - var peg$c81 = "amount-debited"; - var peg$c82 = "amountreimbursed"; - var peg$c83 = "amount-reimbursed"; - var peg$c84 = "columns"; - var peg$c85 = "view"; - var peg$c86 = "per-diem"; - var peg$c87 = "drafts"; - var peg$c88 = "draft"; - var peg$c89 = "tax"; - var peg$c90 = "policy-name"; - var peg$c91 = "long-report-id"; - var peg$c92 = "exported-to"; - var peg$c93 = "exportedto"; - var peg$c94 = "exchange-rate"; - var peg$c95 = "reimbursable-total"; - var peg$c96 = "non-reimbursable-total"; - var peg$c97 = "group-from"; - var peg$c98 = "group-expenses"; - var peg$c99 = "group-total"; - var peg$c100 = "group-card"; - var peg$c101 = "group-feed"; - var peg$c102 = "group-bank-account"; - var peg$c103 = "group-withdrawn"; - var peg$c104 = "group-withdrawal-id"; - var peg$c105 = "group-amount-debited"; - var peg$c106 = "group-amount-reimbursed"; - var peg$c107 = "group-category"; - var peg$c108 = "group-tag"; - var peg$c109 = "group-merchant"; - var peg$c110 = "group-month"; - var peg$c111 = "group-week"; - var peg$c112 = "group-year"; - var peg$c113 = "group-quarter"; - var peg$c114 = "!="; - var peg$c115 = ">="; - var peg$c116 = ">"; - var peg$c117 = "<="; - var peg$c118 = "<"; - var peg$c119 = "\\"; - var peg$c120 = "\u201C"; - var peg$c121 = "\u201D"; - var peg$c122 = "\""; + var peg$c17 = "vendor"; + var peg$c18 = "to"; + var peg$c19 = "exporter"; + var peg$c20 = "payer"; + var peg$c21 = "paidBy"; + var peg$c22 = "paid-by"; + var peg$c23 = "taxrate"; + var peg$c24 = "tax-rate"; + var peg$c25 = "cardID"; + var peg$c26 = "card"; + var peg$c27 = "bankAccount"; + var peg$c28 = "bank-account"; + var peg$c29 = "from"; + var peg$c30 = "attendee"; + var peg$c31 = "expenseType"; + var peg$c32 = "expense-type"; + var peg$c33 = "receiptType"; + var peg$c34 = "receipt-type"; + var peg$c35 = "withdrawalType"; + var peg$c36 = "withdrawal-type"; + var peg$c37 = "withdrawalStatus"; + var peg$c38 = "withdrawal-status"; + var peg$c39 = "paidStatus"; + var peg$c40 = "paid-status"; + var peg$c41 = "withdrawalid"; + var peg$c42 = "withdrawal-id"; + var peg$c43 = "billable"; + var peg$c44 = "reimbursable"; + var peg$c45 = "type"; + var peg$c46 = "status"; + var peg$c47 = "sortBy"; + var peg$c48 = "sort-by"; + var peg$c49 = "sortOrder"; + var peg$c50 = "sort-order"; + var peg$c51 = "policyID"; + var peg$c52 = "workspace"; + var peg$c53 = "submitted"; + var peg$c54 = "approved"; + var peg$c55 = "paid"; + var peg$c56 = "exported"; + var peg$c57 = "posted"; + var peg$c58 = "withdrawn"; + var peg$c59 = "groupby"; + var peg$c60 = "group-by"; + var peg$c61 = "limit"; + var peg$c62 = "feed"; + var peg$c63 = "title"; + var peg$c64 = "submitteruserid"; + var peg$c65 = "submitter-user-id"; + var peg$c66 = "submitterpayrollid"; + var peg$c67 = "submitter-payroll-id"; + var peg$c68 = "orderdealnumbers"; + var peg$c69 = "order-deal-numbers"; + var peg$c70 = "assignee"; + var peg$c71 = "createdby"; + var peg$c72 = "created-by"; + var peg$c73 = "action"; + var peg$c74 = "total"; + var peg$c75 = "has"; + var peg$c76 = "is"; + var peg$c77 = "purchaseamount"; + var peg$c78 = "purchase-amount"; + var peg$c79 = "purchasecurrency"; + var peg$c80 = "purchase-currency"; + var peg$c81 = "amountdebited"; + var peg$c82 = "amount-debited"; + var peg$c83 = "amountreimbursed"; + var peg$c84 = "amount-reimbursed"; + var peg$c85 = "columns"; + var peg$c86 = "view"; + var peg$c87 = "per-diem"; + var peg$c88 = "drafts"; + var peg$c89 = "draft"; + var peg$c90 = "tax"; + var peg$c91 = "policy-name"; + var peg$c92 = "long-report-id"; + var peg$c93 = "exported-to"; + var peg$c94 = "exportedto"; + var peg$c95 = "exchange-rate"; + var peg$c96 = "reimbursable-total"; + var peg$c97 = "non-reimbursable-total"; + var peg$c98 = "group-from"; + var peg$c99 = "group-expenses"; + var peg$c100 = "group-total"; + var peg$c101 = "group-card"; + var peg$c102 = "group-feed"; + var peg$c103 = "group-bank-account"; + var peg$c104 = "group-withdrawn"; + var peg$c105 = "group-withdrawal-id"; + var peg$c106 = "group-amount-debited"; + var peg$c107 = "group-amount-reimbursed"; + var peg$c108 = "group-category"; + var peg$c109 = "group-tag"; + var peg$c110 = "group-merchant"; + var peg$c111 = "group-month"; + var peg$c112 = "group-week"; + var peg$c113 = "group-year"; + var peg$c114 = "group-quarter"; + var peg$c115 = "!="; + var peg$c116 = ">="; + var peg$c117 = ">"; + var peg$c118 = "<="; + var peg$c119 = "<"; + var peg$c120 = "\\"; + var peg$c121 = "\u201C"; + var peg$c122 = "\u201D"; + var peg$c123 = "\""; var peg$r0 = /^[ \t\r\n\xA0,:=<>!]/; var peg$r1 = /^[:=]/; @@ -342,129 +343,130 @@ function peg$parse(input, options) { var peg$e17 = peg$literalExpectation("group-currency", true); var peg$e18 = peg$literalExpectation("tag", true); var peg$e19 = peg$literalExpectation("category", true); - var peg$e20 = peg$literalExpectation("to", true); - var peg$e21 = peg$literalExpectation("exporter", true); - var peg$e22 = peg$literalExpectation("payer", true); - var peg$e23 = peg$literalExpectation("paidBy", false); - var peg$e24 = peg$literalExpectation("paid-by", true); - var peg$e25 = peg$literalExpectation("taxRate", true); - var peg$e26 = peg$literalExpectation("tax-rate", true); - var peg$e27 = peg$literalExpectation("cardID", false); - var peg$e28 = peg$literalExpectation("card", true); - var peg$e29 = peg$literalExpectation("bankAccount", false); - var peg$e30 = peg$literalExpectation("bank-account", true); - var peg$e31 = peg$literalExpectation("from", true); - var peg$e32 = peg$literalExpectation("attendee", true); - var peg$e33 = peg$literalExpectation("expenseType", false); - var peg$e34 = peg$literalExpectation("expense-type", true); - var peg$e35 = peg$literalExpectation("receiptType", false); - var peg$e36 = peg$literalExpectation("receipt-type", true); - var peg$e37 = peg$literalExpectation("withdrawalType", false); - var peg$e38 = peg$literalExpectation("withdrawal-type", true); - var peg$e39 = peg$literalExpectation("withdrawalStatus", false); - var peg$e40 = peg$literalExpectation("withdrawal-status", true); - var peg$e41 = peg$literalExpectation("paidStatus", false); - var peg$e42 = peg$literalExpectation("paid-status", true); - var peg$e43 = peg$literalExpectation("withdrawalID", true); - var peg$e44 = peg$literalExpectation("withdrawal-id", true); - var peg$e45 = peg$literalExpectation("billable", true); - var peg$e46 = peg$literalExpectation("reimbursable", true); - var peg$e47 = peg$literalExpectation("type", true); - var peg$e48 = peg$literalExpectation("status", true); - var peg$e49 = peg$literalExpectation("sortBy", false); - var peg$e50 = peg$literalExpectation("sort-by", true); - var peg$e51 = peg$literalExpectation("sortOrder", false); - var peg$e52 = peg$literalExpectation("sort-order", true); - var peg$e53 = peg$literalExpectation("policyID", false); - var peg$e54 = peg$literalExpectation("workspace", true); - var peg$e55 = peg$literalExpectation("submitted", true); - var peg$e56 = peg$literalExpectation("approved", true); - var peg$e57 = peg$literalExpectation("paid", true); - var peg$e58 = peg$literalExpectation("exported", true); - var peg$e59 = peg$literalExpectation("posted", true); - var peg$e60 = peg$literalExpectation("withdrawn", true); - var peg$e61 = peg$literalExpectation("groupBy", true); - var peg$e62 = peg$literalExpectation("group-by", true); - var peg$e63 = peg$literalExpectation("limit", true); - var peg$e64 = peg$literalExpectation("feed", true); - var peg$e65 = peg$literalExpectation("title", true); - var peg$e66 = peg$literalExpectation("submitterUserID", true); - var peg$e67 = peg$literalExpectation("submitter-user-id", true); - var peg$e68 = peg$literalExpectation("submitterPayrollID", true); - var peg$e69 = peg$literalExpectation("submitter-payroll-id", true); - var peg$e70 = peg$literalExpectation("orderDealNumbers", true); - var peg$e71 = peg$literalExpectation("order-deal-numbers", true); - var peg$e72 = peg$literalExpectation("assignee", true); - var peg$e73 = peg$literalExpectation("createdBy", true); - var peg$e74 = peg$literalExpectation("created-by", true); - var peg$e75 = peg$literalExpectation("action", true); - var peg$e76 = peg$literalExpectation("total", true); - var peg$e77 = peg$literalExpectation("has", true); - var peg$e78 = peg$literalExpectation("is", true); - var peg$e79 = peg$literalExpectation("purchaseAmount", true); - var peg$e80 = peg$literalExpectation("purchase-amount", true); - var peg$e81 = peg$literalExpectation("purchaseCurrency", true); - var peg$e82 = peg$literalExpectation("purchase-currency", true); - var peg$e83 = peg$literalExpectation("amountDebited", true); - var peg$e84 = peg$literalExpectation("amount-debited", true); - var peg$e85 = peg$literalExpectation("amountReimbursed", true); - var peg$e86 = peg$literalExpectation("amount-reimbursed", true); - var peg$e87 = peg$literalExpectation("columns", true); - var peg$e88 = peg$literalExpectation("view", true); - var peg$e89 = peg$literalExpectation("per-diem", true); - var peg$e90 = peg$literalExpectation("drafts", true); - var peg$e91 = peg$literalExpectation("draft", true); - var peg$e92 = peg$literalExpectation("tax", true); - var peg$e93 = peg$literalExpectation("policy-name", true); - var peg$e94 = peg$literalExpectation("long-report-id", true); - var peg$e95 = peg$literalExpectation("exported-to", true); - var peg$e96 = peg$classExpectation([":", "="], false, false); - var peg$e97 = peg$literalExpectation("exportedTo", true); - var peg$e98 = peg$literalExpectation("exchange-rate", true); - var peg$e99 = peg$literalExpectation("reimbursable-total", true); - var peg$e100 = peg$literalExpectation("non-reimbursable-total", true); - var peg$e101 = peg$literalExpectation("group-from", true); - var peg$e102 = peg$literalExpectation("group-expenses", true); - var peg$e103 = peg$literalExpectation("group-total", true); - var peg$e104 = peg$literalExpectation("group-card", true); - var peg$e105 = peg$literalExpectation("group-feed", true); - var peg$e106 = peg$literalExpectation("group-bank-account", true); - var peg$e107 = peg$literalExpectation("group-withdrawn", true); - var peg$e108 = peg$literalExpectation("group-withdrawal-id", true); - var peg$e109 = peg$literalExpectation("group-amount-debited", true); - var peg$e110 = peg$literalExpectation("group-amount-reimbursed", true); - var peg$e111 = peg$literalExpectation("group-category", true); - var peg$e112 = peg$literalExpectation("group-tag", true); - var peg$e113 = peg$literalExpectation("group-merchant", true); - var peg$e114 = peg$literalExpectation("group-month", true); - var peg$e115 = peg$literalExpectation("group-week", true); - var peg$e116 = peg$literalExpectation("group-year", true); - var peg$e117 = peg$literalExpectation("group-quarter", true); - var peg$e118 = peg$otherExpectation("operator"); - var peg$e119 = peg$literalExpectation("!=", false); - var peg$e120 = peg$literalExpectation(">=", false); - var peg$e121 = peg$literalExpectation(">", false); - var peg$e122 = peg$literalExpectation("<=", false); - var peg$e123 = peg$literalExpectation("<", false); - var peg$e124 = peg$literalExpectation("\\", false); - var peg$e125 = peg$classExpectation([",", "\"", "\u201D", "\u201C", "\\"], false, false); - var peg$e126 = peg$otherExpectation("word"); - var peg$e127 = peg$classExpectation([" ", ",", "\t", "\n", "\r", "\xA0"], true, false); - var peg$e128 = peg$otherExpectation("whitespace"); - var peg$e129 = peg$classExpectation([" ", "\t", "\r", "\n", "\xA0"], false, false); - var peg$e130 = peg$otherExpectation("quote"); - var peg$e131 = peg$classExpectation([" ", ",", "\"", "\u201D", "\u201C", "\t", "\n", "\r", "\xA0"], true, false); - var peg$e132 = peg$classExpectation(["\"", ["\u201C", "\u201D"]], false, false); - var peg$e133 = peg$classExpectation(["\"", "\u201D", "\u201C", "\r", "\n"], true, false); - var peg$e134 = peg$literalExpectation("\u201C", false); - var peg$e135 = peg$literalExpectation("\u201D", false); - var peg$e136 = peg$literalExpectation("\"", false); - var peg$e137 = peg$classExpectation([" ", "\t", "\n", "\r", "\xA0", ["a", "z"], ["A", "Z"], ["0", "9"]], false, false); - var peg$e138 = peg$classExpectation([["a", "z"], ["A", "Z"], ["0", "9"]], false, false); - var peg$e139 = peg$classExpectation([" ", "\t", "\n", "\r", "\xA0"], false, false); - var peg$e140 = peg$classExpectation([" ", "\t", "\n", "\r", "\xA0", ["a", "z"], ["A", "Z"]], false, false); - var peg$e141 = peg$classExpectation([","], false, false); - var peg$e142 = peg$classExpectation([" ", "\t", "\n", "\r", "\xA0", ","], false, false); + var peg$e20 = peg$literalExpectation("vendor", true); + var peg$e21 = peg$literalExpectation("to", true); + var peg$e22 = peg$literalExpectation("exporter", true); + var peg$e23 = peg$literalExpectation("payer", true); + var peg$e24 = peg$literalExpectation("paidBy", false); + var peg$e25 = peg$literalExpectation("paid-by", true); + var peg$e26 = peg$literalExpectation("taxRate", true); + var peg$e27 = peg$literalExpectation("tax-rate", true); + var peg$e28 = peg$literalExpectation("cardID", false); + var peg$e29 = peg$literalExpectation("card", true); + var peg$e30 = peg$literalExpectation("bankAccount", false); + var peg$e31 = peg$literalExpectation("bank-account", true); + var peg$e32 = peg$literalExpectation("from", true); + var peg$e33 = peg$literalExpectation("attendee", true); + var peg$e34 = peg$literalExpectation("expenseType", false); + var peg$e35 = peg$literalExpectation("expense-type", true); + var peg$e36 = peg$literalExpectation("receiptType", false); + var peg$e37 = peg$literalExpectation("receipt-type", true); + var peg$e38 = peg$literalExpectation("withdrawalType", false); + var peg$e39 = peg$literalExpectation("withdrawal-type", true); + var peg$e40 = peg$literalExpectation("withdrawalStatus", false); + var peg$e41 = peg$literalExpectation("withdrawal-status", true); + var peg$e42 = peg$literalExpectation("paidStatus", false); + var peg$e43 = peg$literalExpectation("paid-status", true); + var peg$e44 = peg$literalExpectation("withdrawalID", true); + var peg$e45 = peg$literalExpectation("withdrawal-id", true); + var peg$e46 = peg$literalExpectation("billable", true); + var peg$e47 = peg$literalExpectation("reimbursable", true); + var peg$e48 = peg$literalExpectation("type", true); + var peg$e49 = peg$literalExpectation("status", true); + var peg$e50 = peg$literalExpectation("sortBy", false); + var peg$e51 = peg$literalExpectation("sort-by", true); + var peg$e52 = peg$literalExpectation("sortOrder", false); + var peg$e53 = peg$literalExpectation("sort-order", true); + var peg$e54 = peg$literalExpectation("policyID", false); + var peg$e55 = peg$literalExpectation("workspace", true); + var peg$e56 = peg$literalExpectation("submitted", true); + var peg$e57 = peg$literalExpectation("approved", true); + var peg$e58 = peg$literalExpectation("paid", true); + var peg$e59 = peg$literalExpectation("exported", true); + var peg$e60 = peg$literalExpectation("posted", true); + var peg$e61 = peg$literalExpectation("withdrawn", true); + var peg$e62 = peg$literalExpectation("groupBy", true); + var peg$e63 = peg$literalExpectation("group-by", true); + var peg$e64 = peg$literalExpectation("limit", true); + var peg$e65 = peg$literalExpectation("feed", true); + var peg$e66 = peg$literalExpectation("title", true); + var peg$e67 = peg$literalExpectation("submitterUserID", true); + var peg$e68 = peg$literalExpectation("submitter-user-id", true); + var peg$e69 = peg$literalExpectation("submitterPayrollID", true); + var peg$e70 = peg$literalExpectation("submitter-payroll-id", true); + var peg$e71 = peg$literalExpectation("orderDealNumbers", true); + var peg$e72 = peg$literalExpectation("order-deal-numbers", true); + var peg$e73 = peg$literalExpectation("assignee", true); + var peg$e74 = peg$literalExpectation("createdBy", true); + var peg$e75 = peg$literalExpectation("created-by", true); + var peg$e76 = peg$literalExpectation("action", true); + var peg$e77 = peg$literalExpectation("total", true); + var peg$e78 = peg$literalExpectation("has", true); + var peg$e79 = peg$literalExpectation("is", true); + var peg$e80 = peg$literalExpectation("purchaseAmount", true); + var peg$e81 = peg$literalExpectation("purchase-amount", true); + var peg$e82 = peg$literalExpectation("purchaseCurrency", true); + var peg$e83 = peg$literalExpectation("purchase-currency", true); + var peg$e84 = peg$literalExpectation("amountDebited", true); + var peg$e85 = peg$literalExpectation("amount-debited", true); + var peg$e86 = peg$literalExpectation("amountReimbursed", true); + var peg$e87 = peg$literalExpectation("amount-reimbursed", true); + var peg$e88 = peg$literalExpectation("columns", true); + var peg$e89 = peg$literalExpectation("view", true); + var peg$e90 = peg$literalExpectation("per-diem", true); + var peg$e91 = peg$literalExpectation("drafts", true); + var peg$e92 = peg$literalExpectation("draft", true); + var peg$e93 = peg$literalExpectation("tax", true); + var peg$e94 = peg$literalExpectation("policy-name", true); + var peg$e95 = peg$literalExpectation("long-report-id", true); + var peg$e96 = peg$literalExpectation("exported-to", true); + var peg$e97 = peg$classExpectation([":", "="], false, false); + var peg$e98 = peg$literalExpectation("exportedTo", true); + var peg$e99 = peg$literalExpectation("exchange-rate", true); + var peg$e100 = peg$literalExpectation("reimbursable-total", true); + var peg$e101 = peg$literalExpectation("non-reimbursable-total", true); + var peg$e102 = peg$literalExpectation("group-from", true); + var peg$e103 = peg$literalExpectation("group-expenses", true); + var peg$e104 = peg$literalExpectation("group-total", true); + var peg$e105 = peg$literalExpectation("group-card", true); + var peg$e106 = peg$literalExpectation("group-feed", true); + var peg$e107 = peg$literalExpectation("group-bank-account", true); + var peg$e108 = peg$literalExpectation("group-withdrawn", true); + var peg$e109 = peg$literalExpectation("group-withdrawal-id", true); + var peg$e110 = peg$literalExpectation("group-amount-debited", true); + var peg$e111 = peg$literalExpectation("group-amount-reimbursed", true); + var peg$e112 = peg$literalExpectation("group-category", true); + var peg$e113 = peg$literalExpectation("group-tag", true); + var peg$e114 = peg$literalExpectation("group-merchant", true); + var peg$e115 = peg$literalExpectation("group-month", true); + var peg$e116 = peg$literalExpectation("group-week", true); + var peg$e117 = peg$literalExpectation("group-year", true); + var peg$e118 = peg$literalExpectation("group-quarter", true); + var peg$e119 = peg$otherExpectation("operator"); + var peg$e120 = peg$literalExpectation("!=", false); + var peg$e121 = peg$literalExpectation(">=", false); + var peg$e122 = peg$literalExpectation(">", false); + var peg$e123 = peg$literalExpectation("<=", false); + var peg$e124 = peg$literalExpectation("<", false); + var peg$e125 = peg$literalExpectation("\\", false); + var peg$e126 = peg$classExpectation([",", "\"", "\u201D", "\u201C", "\\"], false, false); + var peg$e127 = peg$otherExpectation("word"); + var peg$e128 = peg$classExpectation([" ", ",", "\t", "\n", "\r", "\xA0"], true, false); + var peg$e129 = peg$otherExpectation("whitespace"); + var peg$e130 = peg$classExpectation([" ", "\t", "\r", "\n", "\xA0"], false, false); + var peg$e131 = peg$otherExpectation("quote"); + var peg$e132 = peg$classExpectation([" ", ",", "\"", "\u201D", "\u201C", "\t", "\n", "\r", "\xA0"], true, false); + var peg$e133 = peg$classExpectation(["\"", ["\u201C", "\u201D"]], false, false); + var peg$e134 = peg$classExpectation(["\"", "\u201D", "\u201C", "\r", "\n"], true, false); + var peg$e135 = peg$literalExpectation("\u201C", false); + var peg$e136 = peg$literalExpectation("\u201D", false); + var peg$e137 = peg$literalExpectation("\"", false); + var peg$e138 = peg$classExpectation([" ", "\t", "\n", "\r", "\xA0", ["a", "z"], ["A", "Z"], ["0", "9"]], false, false); + var peg$e139 = peg$classExpectation([["a", "z"], ["A", "Z"], ["0", "9"]], false, false); + var peg$e140 = peg$classExpectation([" ", "\t", "\n", "\r", "\xA0"], false, false); + var peg$e141 = peg$classExpectation([" ", "\t", "\n", "\r", "\xA0", ["a", "z"], ["A", "Z"]], false, false); + var peg$e142 = peg$classExpectation([","], false, false); + var peg$e143 = peg$classExpectation([" ", "\t", "\n", "\r", "\xA0", ","], false, false); var peg$f0 = function(ranges) { return { autocomplete, ranges }; }; var peg$f1 = function(filters) { return filters.filter(Boolean).flat(); }; @@ -540,119 +542,120 @@ function peg$parse(input, options) { var peg$f16 = function() { return "groupCurrency"; }; var peg$f17 = function() { return "tag"; }; var peg$f18 = function() { return "category"; }; - var peg$f19 = function() { return "to"; }; - var peg$f20 = function() { return "exporter"; }; - var peg$f21 = function() { return "payer"; }; - var peg$f22 = function() { return "paidBy"; }; - var peg$f23 = function() { return "taxRate"; }; - var peg$f24 = function() { return "cardID"; }; - var peg$f25 = function() { return "bankAccount"; }; - var peg$f26 = function() { return "from"; }; - var peg$f27 = function() {return "attendee"}; - var peg$f28 = function() { return "expenseType"; }; - var peg$f29 = function() { return "receiptType"; }; - var peg$f30 = function() { return "withdrawalType"; }; - var peg$f31 = function() { return "withdrawalStatus"; }; - var peg$f32 = function() { return "paidStatus"; }; - var peg$f33 = function() { return "withdrawalID"; }; - var peg$f34 = function() { return "billable"; }; - var peg$f35 = function() { return "reimbursable"; }; - var peg$f36 = function() { return "type"; }; - var peg$f37 = function() { return "status"; }; - var peg$f38 = function() { return "sortBy"; }; - var peg$f39 = function() { return "sortOrder"; }; - var peg$f40 = function() { return "policyID"; }; - var peg$f41 = function() { return "submitted"; }; - var peg$f42 = function() { return "approved"; }; - var peg$f43 = function() { return "paid"; }; - var peg$f44 = function() { return "exported"; }; - var peg$f45 = function() { return "posted"; }; - var peg$f46 = function() { return "withdrawn"; }; - var peg$f47 = function() { return "groupBy"; }; - var peg$f48 = function() { return "limit"; }; - var peg$f49 = function() { return "feed"; }; - var peg$f50 = function() { return "title"; }; - var peg$f51 = function() { return "submitterUserID"; }; - var peg$f52 = function() { return "submitterPayrollID"; }; - var peg$f53 = function() { return "orderDealNumbers"; }; - var peg$f54 = function() { return "assignee"; }; - var peg$f55 = function() { return "createdBy"; }; - var peg$f56 = function() { return "action"; }; - var peg$f57 = function() {return "total"; }; - var peg$f58 = function() {return "has"; }; - var peg$f59 = function() {return "is"; }; - var peg$f60 = function() {return "purchaseAmount"}; - var peg$f61 = function() {return "purchaseCurrency"}; - var peg$f62 = function() {return "amountDebited"}; - var peg$f63 = function() {return "amountReimbursed"}; - var peg$f64 = function() { + var peg$f19 = function() { return "vendor"; }; + var peg$f20 = function() { return "to"; }; + var peg$f21 = function() { return "exporter"; }; + var peg$f22 = function() { return "payer"; }; + var peg$f23 = function() { return "paidBy"; }; + var peg$f24 = function() { return "taxRate"; }; + var peg$f25 = function() { return "cardID"; }; + var peg$f26 = function() { return "bankAccount"; }; + var peg$f27 = function() { return "from"; }; + var peg$f28 = function() {return "attendee"}; + var peg$f29 = function() { return "expenseType"; }; + var peg$f30 = function() { return "receiptType"; }; + var peg$f31 = function() { return "withdrawalType"; }; + var peg$f32 = function() { return "withdrawalStatus"; }; + var peg$f33 = function() { return "paidStatus"; }; + var peg$f34 = function() { return "withdrawalID"; }; + var peg$f35 = function() { return "billable"; }; + var peg$f36 = function() { return "reimbursable"; }; + var peg$f37 = function() { return "type"; }; + var peg$f38 = function() { return "status"; }; + var peg$f39 = function() { return "sortBy"; }; + var peg$f40 = function() { return "sortOrder"; }; + var peg$f41 = function() { return "policyID"; }; + var peg$f42 = function() { return "submitted"; }; + var peg$f43 = function() { return "approved"; }; + var peg$f44 = function() { return "paid"; }; + var peg$f45 = function() { return "exported"; }; + var peg$f46 = function() { return "posted"; }; + var peg$f47 = function() { return "withdrawn"; }; + var peg$f48 = function() { return "groupBy"; }; + var peg$f49 = function() { return "limit"; }; + var peg$f50 = function() { return "feed"; }; + var peg$f51 = function() { return "title"; }; + var peg$f52 = function() { return "submitterUserID"; }; + var peg$f53 = function() { return "submitterPayrollID"; }; + var peg$f54 = function() { return "orderDealNumbers"; }; + var peg$f55 = function() { return "assignee"; }; + var peg$f56 = function() { return "createdBy"; }; + var peg$f57 = function() { return "action"; }; + var peg$f58 = function() {return "total"; }; + var peg$f59 = function() {return "has"; }; + var peg$f60 = function() {return "is"; }; + var peg$f61 = function() {return "purchaseAmount"}; + var peg$f62 = function() {return "purchaseCurrency"}; + var peg$f63 = function() {return "amountDebited"}; + var peg$f64 = function() {return "amountReimbursed"}; + var peg$f65 = function() { isColumnsContext = true; return "columns"; }; - var peg$f65 = function() {return "view"}; - var peg$f66 = function() { return isColumnsContext; }; - var peg$f67 = function() { return "perDiem"; }; - var peg$f68 = function() { return "drafts"; }; - var peg$f69 = function() { return "originalamount"; }; - var peg$f70 = function() { return "taxAmount"; }; - var peg$f71 = function() { return "taxrate"; }; - var peg$f72 = function() { return "policyname"; }; - var peg$f73 = function() { return "withdrawalID"; }; - var peg$f74 = function() { return "bankAccount"; }; - var peg$f75 = function() { return "reportID"; }; - var peg$f76 = function() { return "base62ReportID"; }; - var peg$f77 = function() { return "exportedto"; }; - var peg$f78 = function() { return "exportedTo"; }; + var peg$f66 = function() {return "view"}; + var peg$f67 = function() { return isColumnsContext; }; + var peg$f68 = function() { return "perDiem"; }; + var peg$f69 = function() { return "drafts"; }; + var peg$f70 = function() { return "originalamount"; }; + var peg$f71 = function() { return "taxAmount"; }; + var peg$f72 = function() { return "taxrate"; }; + var peg$f73 = function() { return "policyname"; }; + var peg$f74 = function() { return "withdrawalID"; }; + var peg$f75 = function() { return "bankAccount"; }; + var peg$f76 = function() { return "reportID"; }; + var peg$f77 = function() { return "base62ReportID"; }; + var peg$f78 = function() { return "exportedto"; }; var peg$f79 = function() { return "exportedTo"; }; - var peg$f80 = function() { return "exchangeRate"; }; - var peg$f81 = function() { return "reimbursableTotal"; }; - var peg$f82 = function() { return "nonReimbursableTotal"; }; - var peg$f83 = function() { return "groupFrom"; }; - var peg$f84 = function() { return "groupExpenses"; }; - var peg$f85 = function() { return "groupTotal"; }; - var peg$f86 = function() { return "groupCard"; }; - var peg$f87 = function() { return "groupFeed"; }; - var peg$f88 = function() { return "groupBankAccount"; }; - var peg$f89 = function() { return "groupWithdrawn"; }; - var peg$f90 = function() { return "groupWithdrawalID"; }; - var peg$f91 = function() { return "groupAmountDebited"; }; - var peg$f92 = function() { return "groupAmountReimbursed"; }; - var peg$f93 = function() { return "amountDebited"; }; - var peg$f94 = function() { return "amountReimbursed"; }; - var peg$f95 = function() { return "groupCategory"; }; - var peg$f96 = function() { return "groupTag"; }; - var peg$f97 = function() { return "groupMerchant"; }; - var peg$f98 = function() { return "groupmonth"; }; - var peg$f99 = function() { return "groupweek"; }; - var peg$f100 = function() { return "groupyear"; }; - var peg$f101 = function() { return "groupquarter"; }; - var peg$f102 = function() { return "eq"; }; - var peg$f103 = function() { return "neq"; }; - var peg$f104 = function() { return "gte"; }; - var peg$f105 = function() { return "gt"; }; - var peg$f106 = function() { return "lte"; }; - var peg$f107 = function() { return "lt"; }; - var peg$f108 = function(o) { + var peg$f80 = function() { return "exportedTo"; }; + var peg$f81 = function() { return "exchangeRate"; }; + var peg$f82 = function() { return "reimbursableTotal"; }; + var peg$f83 = function() { return "nonReimbursableTotal"; }; + var peg$f84 = function() { return "groupFrom"; }; + var peg$f85 = function() { return "groupExpenses"; }; + var peg$f86 = function() { return "groupTotal"; }; + var peg$f87 = function() { return "groupCard"; }; + var peg$f88 = function() { return "groupFeed"; }; + var peg$f89 = function() { return "groupBankAccount"; }; + var peg$f90 = function() { return "groupWithdrawn"; }; + var peg$f91 = function() { return "groupWithdrawalID"; }; + var peg$f92 = function() { return "groupAmountDebited"; }; + var peg$f93 = function() { return "groupAmountReimbursed"; }; + var peg$f94 = function() { return "amountDebited"; }; + var peg$f95 = function() { return "amountReimbursed"; }; + var peg$f96 = function() { return "groupCategory"; }; + var peg$f97 = function() { return "groupTag"; }; + var peg$f98 = function() { return "groupMerchant"; }; + var peg$f99 = function() { return "groupmonth"; }; + var peg$f100 = function() { return "groupweek"; }; + var peg$f101 = function() { return "groupyear"; }; + var peg$f102 = function() { return "groupquarter"; }; + var peg$f103 = function() { return "eq"; }; + var peg$f104 = function() { return "neq"; }; + var peg$f105 = function() { return "gte"; }; + var peg$f106 = function() { return "gt"; }; + var peg$f107 = function() { return "lte"; }; + var peg$f108 = function() { return "lt"; }; + var peg$f109 = function(o) { if (nameOperator) { expectingNestedQuote = (o === "eq"); // Use simple parser if no valid operator is found } isColumnsContext = false; return o; }; - var peg$f109 = function(c) { return c; }; - var peg$f110 = function(chars) { return chars.join("").trim(); }; - var peg$f111 = function() { + var peg$f110 = function(c) { return c; }; + var peg$f111 = function(chars) { return chars.join("").trim(); }; + var peg$f112 = function() { isColumnsContext = false; return "and"; }; - var peg$f112 = function() { return expectingNestedQuote; }; - var peg$f113 = function(start, inner, end) { //handle no-breaking space + var peg$f113 = function() { return expectingNestedQuote; }; + var peg$f114 = function(start, inner, end) { //handle no-breaking space return [...start, '"', ...inner, '"', ...end].join(""); }; - var peg$f114 = function(start) {return "“"}; - var peg$f115 = function(start) {return "”"}; - var peg$f116 = function(start) {return "\""}; - var peg$f117 = function(start, inner, end) { + var peg$f115 = function(start) {return "“"}; + var peg$f116 = function(start) {return "”"}; + var peg$f117 = function(start) {return "\""}; + var peg$f118 = function(start, inner, end) { return [...start, '"', ...inner, '"'].join(""); }; var peg$currPos = options.peg$currPos | 0; @@ -1077,107 +1080,110 @@ function peg$parse(input, options) { if (s1 === peg$FAILED) { s1 = peg$parsecategory(); if (s1 === peg$FAILED) { - s1 = peg$parseto(); + s1 = peg$parsevendor(); if (s1 === peg$FAILED) { - s1 = peg$parsetaxRate(); + s1 = peg$parseto(); if (s1 === peg$FAILED) { - s1 = peg$parsefrom(); + s1 = peg$parsetaxRate(); if (s1 === peg$FAILED) { - s1 = peg$parseattendee(); + s1 = peg$parsefrom(); if (s1 === peg$FAILED) { - s1 = peg$parsepayer(); + s1 = peg$parseattendee(); if (s1 === peg$FAILED) { - s1 = peg$parsepaidBy(); + s1 = peg$parsepayer(); if (s1 === peg$FAILED) { - s1 = peg$parseexporter(); + s1 = peg$parsepaidBy(); if (s1 === peg$FAILED) { - s1 = peg$parsecreatedBy(); + s1 = peg$parseexporter(); if (s1 === peg$FAILED) { - s1 = peg$parseassignee(); + s1 = peg$parsecreatedBy(); if (s1 === peg$FAILED) { - s1 = peg$parseexpenseType(); + s1 = peg$parseassignee(); if (s1 === peg$FAILED) { - s1 = peg$parsereceiptType(); + s1 = peg$parseexpenseType(); if (s1 === peg$FAILED) { - s1 = peg$parsewithdrawalType(); + s1 = peg$parsereceiptType(); if (s1 === peg$FAILED) { - s1 = peg$parsewithdrawalStatus(); + s1 = peg$parsewithdrawalType(); if (s1 === peg$FAILED) { - s1 = peg$parsepaidStatus(); + s1 = peg$parsewithdrawalStatus(); if (s1 === peg$FAILED) { - s1 = peg$parsetype(); + s1 = peg$parsepaidStatus(); if (s1 === peg$FAILED) { - s1 = peg$parsestatus(); + s1 = peg$parsetype(); if (s1 === peg$FAILED) { - s1 = peg$parsecardID(); + s1 = peg$parsestatus(); if (s1 === peg$FAILED) { - s1 = peg$parsebankAccount(); + s1 = peg$parsecardID(); if (s1 === peg$FAILED) { - s1 = peg$parsefeed(); + s1 = peg$parsebankAccount(); if (s1 === peg$FAILED) { - s1 = peg$parsegroupBy(); + s1 = peg$parsefeed(); if (s1 === peg$FAILED) { - s1 = peg$parseview(); + s1 = peg$parsegroupBy(); if (s1 === peg$FAILED) { - s1 = peg$parsereimbursable(); + s1 = peg$parseview(); if (s1 === peg$FAILED) { - s1 = peg$parsebillable(); + s1 = peg$parsereimbursable(); if (s1 === peg$FAILED) { - s1 = peg$parsepolicyID(); + s1 = peg$parsebillable(); if (s1 === peg$FAILED) { - s1 = peg$parseaction(); + s1 = peg$parsepolicyID(); if (s1 === peg$FAILED) { - s1 = peg$parsedate(); + s1 = peg$parseaction(); if (s1 === peg$FAILED) { - s1 = peg$parsesubmitted(); + s1 = peg$parsedate(); if (s1 === peg$FAILED) { - s1 = peg$parseapproved(); + s1 = peg$parsesubmitted(); if (s1 === peg$FAILED) { - s1 = peg$parsepaid(); + s1 = peg$parseapproved(); if (s1 === peg$FAILED) { - s1 = peg$parseexportedTo(); + s1 = peg$parsepaid(); if (s1 === peg$FAILED) { - s1 = peg$parseexported(); + s1 = peg$parseexportedTo(); if (s1 === peg$FAILED) { - s1 = peg$parsewithdrawn(); + s1 = peg$parseexported(); if (s1 === peg$FAILED) { - s1 = peg$parseposted(); + s1 = peg$parsewithdrawn(); if (s1 === peg$FAILED) { - s1 = peg$parsehas(); + s1 = peg$parseposted(); if (s1 === peg$FAILED) { - s1 = peg$parseis(); + s1 = peg$parsehas(); if (s1 === peg$FAILED) { - s1 = peg$parsepurchaseCurrency(); + s1 = peg$parseis(); if (s1 === peg$FAILED) { - s1 = peg$parsepurchaseAmount(); + s1 = peg$parsepurchaseCurrency(); if (s1 === peg$FAILED) { - s1 = peg$parseamountDebited(); + s1 = peg$parsepurchaseAmount(); if (s1 === peg$FAILED) { - s1 = peg$parseamountReimbursed(); + s1 = peg$parseamountDebited(); if (s1 === peg$FAILED) { - s1 = peg$parseamount(); + s1 = peg$parseamountReimbursed(); if (s1 === peg$FAILED) { - s1 = peg$parsemerchant(); + s1 = peg$parseamount(); if (s1 === peg$FAILED) { - s1 = peg$parsedescription(); + s1 = peg$parsemerchant(); if (s1 === peg$FAILED) { - s1 = peg$parsereportID(); + s1 = peg$parsedescription(); if (s1 === peg$FAILED) { - s1 = peg$parsewithdrawalID(); + s1 = peg$parsereportID(); if (s1 === peg$FAILED) { - s1 = peg$parsetitle(); + s1 = peg$parsewithdrawalID(); if (s1 === peg$FAILED) { - s1 = peg$parsesubmitterUserID(); + s1 = peg$parsetitle(); if (s1 === peg$FAILED) { - s1 = peg$parsesubmitterPayrollID(); + s1 = peg$parsesubmitterUserID(); if (s1 === peg$FAILED) { - s1 = peg$parseorderDealNumbers(); + s1 = peg$parsesubmitterPayrollID(); if (s1 === peg$FAILED) { - s1 = peg$parsereportFieldDynamic(); + s1 = peg$parseorderDealNumbers(); if (s1 === peg$FAILED) { - s1 = peg$parsecolumns(); + s1 = peg$parsereportFieldDynamic(); if (s1 === peg$FAILED) { - s1 = peg$parselimit(); + s1 = peg$parsecolumns(); + if (s1 === peg$FAILED) { + s1 = peg$parselimit(); + } } } } @@ -1574,13 +1580,13 @@ function peg$parse(input, options) { return s0; } - function peg$parseto() { + function peg$parsevendor() { var s0, s1; s0 = peg$currPos; - s1 = input.substr(peg$currPos, 2); + s1 = input.substr(peg$currPos, 6); if (s1.toLowerCase() === peg$c17) { - peg$currPos += 2; + peg$currPos += 6; } else { s1 = peg$FAILED; if (peg$silentFails === 0) { peg$fail(peg$e20); } @@ -1594,13 +1600,13 @@ function peg$parse(input, options) { return s0; } - function peg$parseexporter() { + function peg$parseto() { var s0, s1; s0 = peg$currPos; - s1 = input.substr(peg$currPos, 8); + s1 = input.substr(peg$currPos, 2); if (s1.toLowerCase() === peg$c18) { - peg$currPos += 8; + peg$currPos += 2; } else { s1 = peg$FAILED; if (peg$silentFails === 0) { peg$fail(peg$e21); } @@ -1614,13 +1620,13 @@ function peg$parse(input, options) { return s0; } - function peg$parsepayer() { + function peg$parseexporter() { var s0, s1; s0 = peg$currPos; - s1 = input.substr(peg$currPos, 5); + s1 = input.substr(peg$currPos, 8); if (s1.toLowerCase() === peg$c19) { - peg$currPos += 5; + peg$currPos += 8; } else { s1 = peg$FAILED; if (peg$silentFails === 0) { peg$fail(peg$e22); } @@ -1634,28 +1640,48 @@ function peg$parse(input, options) { return s0; } + function peg$parsepayer() { + var s0, s1; + + s0 = peg$currPos; + s1 = input.substr(peg$currPos, 5); + if (s1.toLowerCase() === peg$c20) { + peg$currPos += 5; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e23); } + } + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$f22(); + } + s0 = s1; + + return s0; + } + function peg$parsepaidBy() { var s0, s1; - if (input.substr(peg$currPos, 6) === peg$c20) { - s0 = peg$c20; + if (input.substr(peg$currPos, 6) === peg$c21) { + s0 = peg$c21; peg$currPos += 6; } else { s0 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e23); } + if (peg$silentFails === 0) { peg$fail(peg$e24); } } if (s0 === peg$FAILED) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 7); - if (s1.toLowerCase() === peg$c21) { + if (s1.toLowerCase() === peg$c22) { peg$currPos += 7; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e24); } + if (peg$silentFails === 0) { peg$fail(peg$e25); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f22(); + s1 = peg$f23(); } s0 = s1; } @@ -1667,24 +1693,24 @@ function peg$parse(input, options) { var s0, s1; s0 = input.substr(peg$currPos, 7); - if (s0.toLowerCase() === peg$c22) { + if (s0.toLowerCase() === peg$c23) { peg$currPos += 7; } else { s0 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e25); } + if (peg$silentFails === 0) { peg$fail(peg$e26); } } if (s0 === peg$FAILED) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 8); - if (s1.toLowerCase() === peg$c23) { + if (s1.toLowerCase() === peg$c24) { peg$currPos += 8; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e26); } + if (peg$silentFails === 0) { peg$fail(peg$e27); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f23(); + s1 = peg$f24(); } s0 = s1; } @@ -1695,25 +1721,25 @@ function peg$parse(input, options) { function peg$parsecardID() { var s0, s1; - if (input.substr(peg$currPos, 6) === peg$c24) { - s0 = peg$c24; + if (input.substr(peg$currPos, 6) === peg$c25) { + s0 = peg$c25; peg$currPos += 6; } else { s0 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e27); } + if (peg$silentFails === 0) { peg$fail(peg$e28); } } if (s0 === peg$FAILED) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 4); - if (s1.toLowerCase() === peg$c25) { + if (s1.toLowerCase() === peg$c26) { peg$currPos += 4; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e28); } + if (peg$silentFails === 0) { peg$fail(peg$e29); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f24(); + s1 = peg$f25(); } s0 = s1; } @@ -1724,25 +1750,25 @@ function peg$parse(input, options) { function peg$parsebankAccount() { var s0, s1; - if (input.substr(peg$currPos, 11) === peg$c26) { - s0 = peg$c26; + if (input.substr(peg$currPos, 11) === peg$c27) { + s0 = peg$c27; peg$currPos += 11; } else { s0 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e29); } + if (peg$silentFails === 0) { peg$fail(peg$e30); } } if (s0 === peg$FAILED) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 12); - if (s1.toLowerCase() === peg$c27) { + if (s1.toLowerCase() === peg$c28) { peg$currPos += 12; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e30); } + if (peg$silentFails === 0) { peg$fail(peg$e31); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f25(); + s1 = peg$f26(); } s0 = s1; } @@ -1755,15 +1781,15 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 4); - if (s1.toLowerCase() === peg$c28) { + if (s1.toLowerCase() === peg$c29) { peg$currPos += 4; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e31); } + if (peg$silentFails === 0) { peg$fail(peg$e32); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f26(); + s1 = peg$f27(); } s0 = s1; @@ -1775,15 +1801,15 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 8); - if (s1.toLowerCase() === peg$c29) { + if (s1.toLowerCase() === peg$c30) { peg$currPos += 8; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e32); } + if (peg$silentFails === 0) { peg$fail(peg$e33); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f27(); + s1 = peg$f28(); } s0 = s1; @@ -1793,25 +1819,25 @@ function peg$parse(input, options) { function peg$parseexpenseType() { var s0, s1; - if (input.substr(peg$currPos, 11) === peg$c30) { - s0 = peg$c30; + if (input.substr(peg$currPos, 11) === peg$c31) { + s0 = peg$c31; peg$currPos += 11; } else { s0 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e33); } + if (peg$silentFails === 0) { peg$fail(peg$e34); } } if (s0 === peg$FAILED) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 12); - if (s1.toLowerCase() === peg$c31) { + if (s1.toLowerCase() === peg$c32) { peg$currPos += 12; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e34); } + if (peg$silentFails === 0) { peg$fail(peg$e35); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f28(); + s1 = peg$f29(); } s0 = s1; } @@ -1822,25 +1848,25 @@ function peg$parse(input, options) { function peg$parsereceiptType() { var s0, s1; - if (input.substr(peg$currPos, 11) === peg$c32) { - s0 = peg$c32; + if (input.substr(peg$currPos, 11) === peg$c33) { + s0 = peg$c33; peg$currPos += 11; } else { s0 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e35); } + if (peg$silentFails === 0) { peg$fail(peg$e36); } } if (s0 === peg$FAILED) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 12); - if (s1.toLowerCase() === peg$c33) { + if (s1.toLowerCase() === peg$c34) { peg$currPos += 12; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e36); } + if (peg$silentFails === 0) { peg$fail(peg$e37); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f29(); + s1 = peg$f30(); } s0 = s1; } @@ -1851,25 +1877,25 @@ function peg$parse(input, options) { function peg$parsewithdrawalType() { var s0, s1; - if (input.substr(peg$currPos, 14) === peg$c34) { - s0 = peg$c34; + if (input.substr(peg$currPos, 14) === peg$c35) { + s0 = peg$c35; peg$currPos += 14; } else { s0 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e37); } + if (peg$silentFails === 0) { peg$fail(peg$e38); } } if (s0 === peg$FAILED) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 15); - if (s1.toLowerCase() === peg$c35) { + if (s1.toLowerCase() === peg$c36) { peg$currPos += 15; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e38); } + if (peg$silentFails === 0) { peg$fail(peg$e39); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f30(); + s1 = peg$f31(); } s0 = s1; } @@ -1880,25 +1906,25 @@ function peg$parse(input, options) { function peg$parsewithdrawalStatus() { var s0, s1; - if (input.substr(peg$currPos, 16) === peg$c36) { - s0 = peg$c36; + if (input.substr(peg$currPos, 16) === peg$c37) { + s0 = peg$c37; peg$currPos += 16; } else { s0 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e39); } + if (peg$silentFails === 0) { peg$fail(peg$e40); } } if (s0 === peg$FAILED) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 17); - if (s1.toLowerCase() === peg$c37) { + if (s1.toLowerCase() === peg$c38) { peg$currPos += 17; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e40); } + if (peg$silentFails === 0) { peg$fail(peg$e41); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f31(); + s1 = peg$f32(); } s0 = s1; } @@ -1909,25 +1935,25 @@ function peg$parse(input, options) { function peg$parsepaidStatus() { var s0, s1; - if (input.substr(peg$currPos, 10) === peg$c38) { - s0 = peg$c38; + if (input.substr(peg$currPos, 10) === peg$c39) { + s0 = peg$c39; peg$currPos += 10; } else { s0 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e41); } + if (peg$silentFails === 0) { peg$fail(peg$e42); } } if (s0 === peg$FAILED) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 11); - if (s1.toLowerCase() === peg$c39) { + if (s1.toLowerCase() === peg$c40) { peg$currPos += 11; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e42); } + if (peg$silentFails === 0) { peg$fail(peg$e43); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f32(); + s1 = peg$f33(); } s0 = s1; } @@ -1939,24 +1965,24 @@ function peg$parse(input, options) { var s0, s1; s0 = input.substr(peg$currPos, 12); - if (s0.toLowerCase() === peg$c40) { + if (s0.toLowerCase() === peg$c41) { peg$currPos += 12; } else { s0 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e43); } + if (peg$silentFails === 0) { peg$fail(peg$e44); } } if (s0 === peg$FAILED) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 13); - if (s1.toLowerCase() === peg$c41) { + if (s1.toLowerCase() === peg$c42) { peg$currPos += 13; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e44); } + if (peg$silentFails === 0) { peg$fail(peg$e45); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f33(); + s1 = peg$f34(); } s0 = s1; } @@ -1969,15 +1995,15 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 8); - if (s1.toLowerCase() === peg$c42) { + if (s1.toLowerCase() === peg$c43) { peg$currPos += 8; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e45); } + if (peg$silentFails === 0) { peg$fail(peg$e46); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f34(); + s1 = peg$f35(); } s0 = s1; @@ -1989,15 +2015,15 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 12); - if (s1.toLowerCase() === peg$c43) { + if (s1.toLowerCase() === peg$c44) { peg$currPos += 12; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e46); } + if (peg$silentFails === 0) { peg$fail(peg$e47); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f35(); + s1 = peg$f36(); } s0 = s1; @@ -2009,15 +2035,15 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 4); - if (s1.toLowerCase() === peg$c44) { + if (s1.toLowerCase() === peg$c45) { peg$currPos += 4; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e47); } + if (peg$silentFails === 0) { peg$fail(peg$e48); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f36(); + s1 = peg$f37(); } s0 = s1; @@ -2029,15 +2055,15 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 6); - if (s1.toLowerCase() === peg$c45) { + if (s1.toLowerCase() === peg$c46) { peg$currPos += 6; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e48); } + if (peg$silentFails === 0) { peg$fail(peg$e49); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f37(); + s1 = peg$f38(); } s0 = s1; @@ -2047,25 +2073,25 @@ function peg$parse(input, options) { function peg$parsesortBy() { var s0, s1; - if (input.substr(peg$currPos, 6) === peg$c46) { - s0 = peg$c46; + if (input.substr(peg$currPos, 6) === peg$c47) { + s0 = peg$c47; peg$currPos += 6; } else { s0 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e49); } + if (peg$silentFails === 0) { peg$fail(peg$e50); } } if (s0 === peg$FAILED) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 7); - if (s1.toLowerCase() === peg$c47) { + if (s1.toLowerCase() === peg$c48) { peg$currPos += 7; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e50); } + if (peg$silentFails === 0) { peg$fail(peg$e51); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f38(); + s1 = peg$f39(); } s0 = s1; } @@ -2076,25 +2102,25 @@ function peg$parse(input, options) { function peg$parsesortOrder() { var s0, s1; - if (input.substr(peg$currPos, 9) === peg$c48) { - s0 = peg$c48; + if (input.substr(peg$currPos, 9) === peg$c49) { + s0 = peg$c49; peg$currPos += 9; } else { s0 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e51); } + if (peg$silentFails === 0) { peg$fail(peg$e52); } } if (s0 === peg$FAILED) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 10); - if (s1.toLowerCase() === peg$c49) { + if (s1.toLowerCase() === peg$c50) { peg$currPos += 10; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e52); } + if (peg$silentFails === 0) { peg$fail(peg$e53); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f39(); + s1 = peg$f40(); } s0 = s1; } @@ -2105,25 +2131,25 @@ function peg$parse(input, options) { function peg$parsepolicyID() { var s0, s1; - if (input.substr(peg$currPos, 8) === peg$c50) { - s0 = peg$c50; + if (input.substr(peg$currPos, 8) === peg$c51) { + s0 = peg$c51; peg$currPos += 8; } else { s0 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e53); } + if (peg$silentFails === 0) { peg$fail(peg$e54); } } if (s0 === peg$FAILED) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 9); - if (s1.toLowerCase() === peg$c51) { + if (s1.toLowerCase() === peg$c52) { peg$currPos += 9; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e54); } + if (peg$silentFails === 0) { peg$fail(peg$e55); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f40(); + s1 = peg$f41(); } s0 = s1; } @@ -2136,15 +2162,15 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 9); - if (s1.toLowerCase() === peg$c52) { + if (s1.toLowerCase() === peg$c53) { peg$currPos += 9; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e55); } + if (peg$silentFails === 0) { peg$fail(peg$e56); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f41(); + s1 = peg$f42(); } s0 = s1; @@ -2156,15 +2182,15 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 8); - if (s1.toLowerCase() === peg$c53) { + if (s1.toLowerCase() === peg$c54) { peg$currPos += 8; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e56); } + if (peg$silentFails === 0) { peg$fail(peg$e57); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f42(); + s1 = peg$f43(); } s0 = s1; @@ -2176,15 +2202,15 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 4); - if (s1.toLowerCase() === peg$c54) { + if (s1.toLowerCase() === peg$c55) { peg$currPos += 4; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e57); } + if (peg$silentFails === 0) { peg$fail(peg$e58); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f43(); + s1 = peg$f44(); } s0 = s1; @@ -2196,15 +2222,15 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 8); - if (s1.toLowerCase() === peg$c55) { + if (s1.toLowerCase() === peg$c56) { peg$currPos += 8; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e58); } + if (peg$silentFails === 0) { peg$fail(peg$e59); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f44(); + s1 = peg$f45(); } s0 = s1; @@ -2216,15 +2242,15 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 6); - if (s1.toLowerCase() === peg$c56) { + if (s1.toLowerCase() === peg$c57) { peg$currPos += 6; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e59); } + if (peg$silentFails === 0) { peg$fail(peg$e60); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f45(); + s1 = peg$f46(); } s0 = s1; @@ -2236,15 +2262,15 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 9); - if (s1.toLowerCase() === peg$c57) { + if (s1.toLowerCase() === peg$c58) { peg$currPos += 9; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e60); } + if (peg$silentFails === 0) { peg$fail(peg$e61); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f46(); + s1 = peg$f47(); } s0 = s1; @@ -2255,24 +2281,24 @@ function peg$parse(input, options) { var s0, s1; s0 = input.substr(peg$currPos, 7); - if (s0.toLowerCase() === peg$c58) { + if (s0.toLowerCase() === peg$c59) { peg$currPos += 7; } else { s0 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e61); } + if (peg$silentFails === 0) { peg$fail(peg$e62); } } if (s0 === peg$FAILED) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 8); - if (s1.toLowerCase() === peg$c59) { + if (s1.toLowerCase() === peg$c60) { peg$currPos += 8; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e62); } + if (peg$silentFails === 0) { peg$fail(peg$e63); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f47(); + s1 = peg$f48(); } s0 = s1; } @@ -2285,15 +2311,15 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 5); - if (s1.toLowerCase() === peg$c60) { + if (s1.toLowerCase() === peg$c61) { peg$currPos += 5; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e63); } + if (peg$silentFails === 0) { peg$fail(peg$e64); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f48(); + s1 = peg$f49(); } s0 = s1; @@ -2305,15 +2331,15 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 4); - if (s1.toLowerCase() === peg$c61) { + if (s1.toLowerCase() === peg$c62) { peg$currPos += 4; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e64); } + if (peg$silentFails === 0) { peg$fail(peg$e65); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f49(); + s1 = peg$f50(); } s0 = s1; @@ -2325,15 +2351,15 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 5); - if (s1.toLowerCase() === peg$c62) { + if (s1.toLowerCase() === peg$c63) { peg$currPos += 5; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e65); } + if (peg$silentFails === 0) { peg$fail(peg$e66); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f50(); + s1 = peg$f51(); } s0 = s1; @@ -2344,24 +2370,24 @@ function peg$parse(input, options) { var s0, s1; s0 = input.substr(peg$currPos, 15); - if (s0.toLowerCase() === peg$c63) { + if (s0.toLowerCase() === peg$c64) { peg$currPos += 15; } else { s0 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e66); } + if (peg$silentFails === 0) { peg$fail(peg$e67); } } if (s0 === peg$FAILED) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 17); - if (s1.toLowerCase() === peg$c64) { + if (s1.toLowerCase() === peg$c65) { peg$currPos += 17; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e67); } + if (peg$silentFails === 0) { peg$fail(peg$e68); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f51(); + s1 = peg$f52(); } s0 = s1; } @@ -2373,24 +2399,24 @@ function peg$parse(input, options) { var s0, s1; s0 = input.substr(peg$currPos, 18); - if (s0.toLowerCase() === peg$c65) { + if (s0.toLowerCase() === peg$c66) { peg$currPos += 18; } else { s0 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e68); } + if (peg$silentFails === 0) { peg$fail(peg$e69); } } if (s0 === peg$FAILED) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 20); - if (s1.toLowerCase() === peg$c66) { + if (s1.toLowerCase() === peg$c67) { peg$currPos += 20; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e69); } + if (peg$silentFails === 0) { peg$fail(peg$e70); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f52(); + s1 = peg$f53(); } s0 = s1; } @@ -2402,24 +2428,24 @@ function peg$parse(input, options) { var s0, s1; s0 = input.substr(peg$currPos, 16); - if (s0.toLowerCase() === peg$c67) { + if (s0.toLowerCase() === peg$c68) { peg$currPos += 16; } else { s0 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e70); } + if (peg$silentFails === 0) { peg$fail(peg$e71); } } if (s0 === peg$FAILED) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 18); - if (s1.toLowerCase() === peg$c68) { + if (s1.toLowerCase() === peg$c69) { peg$currPos += 18; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e71); } + if (peg$silentFails === 0) { peg$fail(peg$e72); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f53(); + s1 = peg$f54(); } s0 = s1; } @@ -2432,15 +2458,15 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 8); - if (s1.toLowerCase() === peg$c69) { + if (s1.toLowerCase() === peg$c70) { peg$currPos += 8; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e72); } + if (peg$silentFails === 0) { peg$fail(peg$e73); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f54(); + s1 = peg$f55(); } s0 = s1; @@ -2451,24 +2477,24 @@ function peg$parse(input, options) { var s0, s1; s0 = input.substr(peg$currPos, 9); - if (s0.toLowerCase() === peg$c70) { + if (s0.toLowerCase() === peg$c71) { peg$currPos += 9; } else { s0 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e73); } + if (peg$silentFails === 0) { peg$fail(peg$e74); } } if (s0 === peg$FAILED) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 10); - if (s1.toLowerCase() === peg$c71) { + if (s1.toLowerCase() === peg$c72) { peg$currPos += 10; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e74); } + if (peg$silentFails === 0) { peg$fail(peg$e75); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f55(); + s1 = peg$f56(); } s0 = s1; } @@ -2481,15 +2507,15 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 6); - if (s1.toLowerCase() === peg$c72) { + if (s1.toLowerCase() === peg$c73) { peg$currPos += 6; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e75); } + if (peg$silentFails === 0) { peg$fail(peg$e76); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f56(); + s1 = peg$f57(); } s0 = s1; @@ -2501,15 +2527,15 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 5); - if (s1.toLowerCase() === peg$c73) { + if (s1.toLowerCase() === peg$c74) { peg$currPos += 5; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e76); } + if (peg$silentFails === 0) { peg$fail(peg$e77); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f57(); + s1 = peg$f58(); } s0 = s1; @@ -2521,15 +2547,15 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 3); - if (s1.toLowerCase() === peg$c74) { + if (s1.toLowerCase() === peg$c75) { peg$currPos += 3; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e77); } + if (peg$silentFails === 0) { peg$fail(peg$e78); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f58(); + s1 = peg$f59(); } s0 = s1; @@ -2541,15 +2567,15 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 2); - if (s1.toLowerCase() === peg$c75) { + if (s1.toLowerCase() === peg$c76) { peg$currPos += 2; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e78); } + if (peg$silentFails === 0) { peg$fail(peg$e79); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f59(); + s1 = peg$f60(); } s0 = s1; @@ -2560,24 +2586,24 @@ function peg$parse(input, options) { var s0, s1; s0 = input.substr(peg$currPos, 14); - if (s0.toLowerCase() === peg$c76) { + if (s0.toLowerCase() === peg$c77) { peg$currPos += 14; } else { s0 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e79); } + if (peg$silentFails === 0) { peg$fail(peg$e80); } } if (s0 === peg$FAILED) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 15); - if (s1.toLowerCase() === peg$c77) { + if (s1.toLowerCase() === peg$c78) { peg$currPos += 15; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e80); } + if (peg$silentFails === 0) { peg$fail(peg$e81); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f60(); + s1 = peg$f61(); } s0 = s1; } @@ -2589,24 +2615,24 @@ function peg$parse(input, options) { var s0, s1; s0 = input.substr(peg$currPos, 16); - if (s0.toLowerCase() === peg$c78) { + if (s0.toLowerCase() === peg$c79) { peg$currPos += 16; } else { s0 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e81); } + if (peg$silentFails === 0) { peg$fail(peg$e82); } } if (s0 === peg$FAILED) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 17); - if (s1.toLowerCase() === peg$c79) { + if (s1.toLowerCase() === peg$c80) { peg$currPos += 17; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e82); } + if (peg$silentFails === 0) { peg$fail(peg$e83); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f61(); + s1 = peg$f62(); } s0 = s1; } @@ -2618,24 +2644,24 @@ function peg$parse(input, options) { var s0, s1; s0 = input.substr(peg$currPos, 13); - if (s0.toLowerCase() === peg$c80) { + if (s0.toLowerCase() === peg$c81) { peg$currPos += 13; } else { s0 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e83); } + if (peg$silentFails === 0) { peg$fail(peg$e84); } } if (s0 === peg$FAILED) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 14); - if (s1.toLowerCase() === peg$c81) { + if (s1.toLowerCase() === peg$c82) { peg$currPos += 14; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e84); } + if (peg$silentFails === 0) { peg$fail(peg$e85); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f62(); + s1 = peg$f63(); } s0 = s1; } @@ -2647,24 +2673,24 @@ function peg$parse(input, options) { var s0, s1; s0 = input.substr(peg$currPos, 16); - if (s0.toLowerCase() === peg$c82) { + if (s0.toLowerCase() === peg$c83) { peg$currPos += 16; } else { s0 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e85); } + if (peg$silentFails === 0) { peg$fail(peg$e86); } } if (s0 === peg$FAILED) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 17); - if (s1.toLowerCase() === peg$c83) { + if (s1.toLowerCase() === peg$c84) { peg$currPos += 17; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e86); } + if (peg$silentFails === 0) { peg$fail(peg$e87); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f63(); + s1 = peg$f64(); } s0 = s1; } @@ -2677,15 +2703,15 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 7); - if (s1.toLowerCase() === peg$c84) { + if (s1.toLowerCase() === peg$c85) { peg$currPos += 7; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e87); } + if (peg$silentFails === 0) { peg$fail(peg$e88); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f64(); + s1 = peg$f65(); } s0 = s1; @@ -2697,15 +2723,15 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 4); - if (s1.toLowerCase() === peg$c85) { + if (s1.toLowerCase() === peg$c86) { peg$currPos += 4; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e88); } + if (peg$silentFails === 0) { peg$fail(peg$e89); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f65(); + s1 = peg$f66(); } s0 = s1; @@ -2717,7 +2743,7 @@ function peg$parse(input, options) { s0 = peg$currPos; peg$savedPos = peg$currPos; - s1 = peg$f66(); + s1 = peg$f67(); if (s1) { s1 = undefined; } else { @@ -2849,11 +2875,11 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 8); - if (s1.toLowerCase() === peg$c86) { + if (s1.toLowerCase() === peg$c87) { peg$currPos += 8; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e89); } + if (peg$silentFails === 0) { peg$fail(peg$e90); } } if (s1 !== peg$FAILED) { s2 = peg$currPos; @@ -2868,7 +2894,7 @@ function peg$parse(input, options) { } if (s2 !== peg$FAILED) { peg$savedPos = s0; - s0 = peg$f67(); + s0 = peg$f68(); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -2886,19 +2912,19 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 6); - if (s1.toLowerCase() === peg$c87) { + if (s1.toLowerCase() === peg$c88) { peg$currPos += 6; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e90); } + if (peg$silentFails === 0) { peg$fail(peg$e91); } } if (s1 === peg$FAILED) { s1 = input.substr(peg$currPos, 5); - if (s1.toLowerCase() === peg$c88) { + if (s1.toLowerCase() === peg$c89) { peg$currPos += 5; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e91); } + if (peg$silentFails === 0) { peg$fail(peg$e92); } } } if (s1 !== peg$FAILED) { @@ -2914,7 +2940,7 @@ function peg$parse(input, options) { } if (s2 !== peg$FAILED) { peg$savedPos = s0; - s0 = peg$f68(); + s0 = peg$f69(); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -2932,11 +2958,11 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 15); - if (s1.toLowerCase() === peg$c77) { + if (s1.toLowerCase() === peg$c78) { peg$currPos += 15; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e80); } + if (peg$silentFails === 0) { peg$fail(peg$e81); } } if (s1 !== peg$FAILED) { s2 = peg$currPos; @@ -2951,7 +2977,7 @@ function peg$parse(input, options) { } if (s2 !== peg$FAILED) { peg$savedPos = s0; - s0 = peg$f69(); + s0 = peg$f70(); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -2969,11 +2995,11 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 3); - if (s1.toLowerCase() === peg$c89) { + if (s1.toLowerCase() === peg$c90) { peg$currPos += 3; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e92); } + if (peg$silentFails === 0) { peg$fail(peg$e93); } } if (s1 !== peg$FAILED) { s2 = peg$currPos; @@ -2988,7 +3014,7 @@ function peg$parse(input, options) { } if (s2 !== peg$FAILED) { peg$savedPos = s0; - s0 = peg$f70(); + s0 = peg$f71(); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -3006,11 +3032,11 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 8); - if (s1.toLowerCase() === peg$c23) { + if (s1.toLowerCase() === peg$c24) { peg$currPos += 8; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e26); } + if (peg$silentFails === 0) { peg$fail(peg$e27); } } if (s1 !== peg$FAILED) { s2 = peg$currPos; @@ -3025,7 +3051,7 @@ function peg$parse(input, options) { } if (s2 !== peg$FAILED) { peg$savedPos = s0; - s0 = peg$f71(); + s0 = peg$f72(); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -3043,11 +3069,11 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 11); - if (s1.toLowerCase() === peg$c90) { + if (s1.toLowerCase() === peg$c91) { peg$currPos += 11; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e93); } + if (peg$silentFails === 0) { peg$fail(peg$e94); } } if (s1 !== peg$FAILED) { s2 = peg$currPos; @@ -3062,7 +3088,7 @@ function peg$parse(input, options) { } if (s2 !== peg$FAILED) { peg$savedPos = s0; - s0 = peg$f72(); + s0 = peg$f73(); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -3080,11 +3106,11 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 13); - if (s1.toLowerCase() === peg$c41) { + if (s1.toLowerCase() === peg$c42) { peg$currPos += 13; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e44); } + if (peg$silentFails === 0) { peg$fail(peg$e45); } } if (s1 !== peg$FAILED) { s2 = peg$currPos; @@ -3099,7 +3125,7 @@ function peg$parse(input, options) { } if (s2 !== peg$FAILED) { peg$savedPos = s0; - s0 = peg$f73(); + s0 = peg$f74(); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -3117,11 +3143,11 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 12); - if (s1.toLowerCase() === peg$c27) { + if (s1.toLowerCase() === peg$c28) { peg$currPos += 12; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e30); } + if (peg$silentFails === 0) { peg$fail(peg$e31); } } if (s1 !== peg$FAILED) { s2 = peg$currPos; @@ -3136,7 +3162,7 @@ function peg$parse(input, options) { } if (s2 !== peg$FAILED) { peg$savedPos = s0; - s0 = peg$f74(); + s0 = peg$f75(); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -3154,11 +3180,11 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 14); - if (s1.toLowerCase() === peg$c91) { + if (s1.toLowerCase() === peg$c92) { peg$currPos += 14; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e94); } + if (peg$silentFails === 0) { peg$fail(peg$e95); } } if (s1 !== peg$FAILED) { s2 = peg$currPos; @@ -3173,7 +3199,7 @@ function peg$parse(input, options) { } if (s2 !== peg$FAILED) { peg$savedPos = s0; - s0 = peg$f75(); + s0 = peg$f76(); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -3210,7 +3236,7 @@ function peg$parse(input, options) { } if (s2 !== peg$FAILED) { peg$savedPos = s0; - s0 = peg$f76(); + s0 = peg$f77(); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -3228,11 +3254,11 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 11); - if (s1.toLowerCase() === peg$c92) { + if (s1.toLowerCase() === peg$c93) { peg$currPos += 11; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e95); } + if (peg$silentFails === 0) { peg$fail(peg$e96); } } if (s1 !== peg$FAILED) { s2 = peg$currPos; @@ -3247,7 +3273,7 @@ function peg$parse(input, options) { } if (s2 !== peg$FAILED) { peg$savedPos = s0; - s0 = peg$f77(); + s0 = peg$f78(); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -3272,7 +3298,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e96); } + if (peg$silentFails === 0) { peg$fail(peg$e97); } } if (s2 !== peg$FAILED) { s1 = [s1, s2]; @@ -3291,11 +3317,11 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 10); - if (s1.toLowerCase() === peg$c93) { + if (s1.toLowerCase() === peg$c94) { peg$currPos += 10; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e97); } + if (peg$silentFails === 0) { peg$fail(peg$e98); } } if (s1 !== peg$FAILED) { s2 = peg$currPos; @@ -3310,7 +3336,7 @@ function peg$parse(input, options) { } if (s2 !== peg$FAILED) { peg$savedPos = s0; - s0 = peg$f78(); + s0 = peg$f79(); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -3322,11 +3348,11 @@ function peg$parse(input, options) { if (s0 === peg$FAILED) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 11); - if (s1.toLowerCase() === peg$c92) { + if (s1.toLowerCase() === peg$c93) { peg$currPos += 11; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e95); } + if (peg$silentFails === 0) { peg$fail(peg$e96); } } if (s1 !== peg$FAILED) { s2 = peg$currPos; @@ -3341,7 +3367,7 @@ function peg$parse(input, options) { } if (s2 !== peg$FAILED) { peg$savedPos = s0; - s0 = peg$f79(); + s0 = peg$f80(); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -3360,11 +3386,11 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 13); - if (s1.toLowerCase() === peg$c94) { + if (s1.toLowerCase() === peg$c95) { peg$currPos += 13; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e98); } + if (peg$silentFails === 0) { peg$fail(peg$e99); } } if (s1 !== peg$FAILED) { s2 = peg$currPos; @@ -3379,7 +3405,7 @@ function peg$parse(input, options) { } if (s2 !== peg$FAILED) { peg$savedPos = s0; - s0 = peg$f80(); + s0 = peg$f81(); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -3397,11 +3423,11 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 18); - if (s1.toLowerCase() === peg$c95) { + if (s1.toLowerCase() === peg$c96) { peg$currPos += 18; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e99); } + if (peg$silentFails === 0) { peg$fail(peg$e100); } } if (s1 !== peg$FAILED) { s2 = peg$currPos; @@ -3416,7 +3442,7 @@ function peg$parse(input, options) { } if (s2 !== peg$FAILED) { peg$savedPos = s0; - s0 = peg$f81(); + s0 = peg$f82(); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -3434,11 +3460,11 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 22); - if (s1.toLowerCase() === peg$c96) { + if (s1.toLowerCase() === peg$c97) { peg$currPos += 22; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e100); } + if (peg$silentFails === 0) { peg$fail(peg$e101); } } if (s1 !== peg$FAILED) { s2 = peg$currPos; @@ -3453,7 +3479,7 @@ function peg$parse(input, options) { } if (s2 !== peg$FAILED) { peg$savedPos = s0; - s0 = peg$f82(); + s0 = peg$f83(); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -3471,11 +3497,11 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 10); - if (s1.toLowerCase() === peg$c97) { + if (s1.toLowerCase() === peg$c98) { peg$currPos += 10; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e101); } + if (peg$silentFails === 0) { peg$fail(peg$e102); } } if (s1 !== peg$FAILED) { s2 = peg$currPos; @@ -3490,7 +3516,7 @@ function peg$parse(input, options) { } if (s2 !== peg$FAILED) { peg$savedPos = s0; - s0 = peg$f83(); + s0 = peg$f84(); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -3508,11 +3534,11 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 14); - if (s1.toLowerCase() === peg$c98) { + if (s1.toLowerCase() === peg$c99) { peg$currPos += 14; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e102); } + if (peg$silentFails === 0) { peg$fail(peg$e103); } } if (s1 !== peg$FAILED) { s2 = peg$currPos; @@ -3527,7 +3553,7 @@ function peg$parse(input, options) { } if (s2 !== peg$FAILED) { peg$savedPos = s0; - s0 = peg$f84(); + s0 = peg$f85(); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -3545,11 +3571,11 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 11); - if (s1.toLowerCase() === peg$c99) { + if (s1.toLowerCase() === peg$c100) { peg$currPos += 11; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e103); } + if (peg$silentFails === 0) { peg$fail(peg$e104); } } if (s1 !== peg$FAILED) { s2 = peg$currPos; @@ -3564,7 +3590,7 @@ function peg$parse(input, options) { } if (s2 !== peg$FAILED) { peg$savedPos = s0; - s0 = peg$f85(); + s0 = peg$f86(); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -3582,11 +3608,11 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 10); - if (s1.toLowerCase() === peg$c100) { + if (s1.toLowerCase() === peg$c101) { peg$currPos += 10; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e104); } + if (peg$silentFails === 0) { peg$fail(peg$e105); } } if (s1 !== peg$FAILED) { s2 = peg$currPos; @@ -3601,7 +3627,7 @@ function peg$parse(input, options) { } if (s2 !== peg$FAILED) { peg$savedPos = s0; - s0 = peg$f86(); + s0 = peg$f87(); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -3619,11 +3645,11 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 10); - if (s1.toLowerCase() === peg$c101) { + if (s1.toLowerCase() === peg$c102) { peg$currPos += 10; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e105); } + if (peg$silentFails === 0) { peg$fail(peg$e106); } } if (s1 !== peg$FAILED) { s2 = peg$currPos; @@ -3638,7 +3664,7 @@ function peg$parse(input, options) { } if (s2 !== peg$FAILED) { peg$savedPos = s0; - s0 = peg$f87(); + s0 = peg$f88(); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -3656,11 +3682,11 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 18); - if (s1.toLowerCase() === peg$c102) { + if (s1.toLowerCase() === peg$c103) { peg$currPos += 18; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e106); } + if (peg$silentFails === 0) { peg$fail(peg$e107); } } if (s1 !== peg$FAILED) { s2 = peg$currPos; @@ -3675,7 +3701,7 @@ function peg$parse(input, options) { } if (s2 !== peg$FAILED) { peg$savedPos = s0; - s0 = peg$f88(); + s0 = peg$f89(); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -3693,11 +3719,11 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 15); - if (s1.toLowerCase() === peg$c103) { + if (s1.toLowerCase() === peg$c104) { peg$currPos += 15; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e107); } + if (peg$silentFails === 0) { peg$fail(peg$e108); } } if (s1 !== peg$FAILED) { s2 = peg$currPos; @@ -3712,7 +3738,7 @@ function peg$parse(input, options) { } if (s2 !== peg$FAILED) { peg$savedPos = s0; - s0 = peg$f89(); + s0 = peg$f90(); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -3730,11 +3756,11 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 19); - if (s1.toLowerCase() === peg$c104) { + if (s1.toLowerCase() === peg$c105) { peg$currPos += 19; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e108); } + if (peg$silentFails === 0) { peg$fail(peg$e109); } } if (s1 !== peg$FAILED) { s2 = peg$currPos; @@ -3749,7 +3775,7 @@ function peg$parse(input, options) { } if (s2 !== peg$FAILED) { peg$savedPos = s0; - s0 = peg$f90(); + s0 = peg$f91(); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -3767,11 +3793,11 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 20); - if (s1.toLowerCase() === peg$c105) { + if (s1.toLowerCase() === peg$c106) { peg$currPos += 20; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e109); } + if (peg$silentFails === 0) { peg$fail(peg$e110); } } if (s1 !== peg$FAILED) { s2 = peg$currPos; @@ -3786,7 +3812,7 @@ function peg$parse(input, options) { } if (s2 !== peg$FAILED) { peg$savedPos = s0; - s0 = peg$f91(); + s0 = peg$f92(); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -3804,11 +3830,11 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 23); - if (s1.toLowerCase() === peg$c106) { + if (s1.toLowerCase() === peg$c107) { peg$currPos += 23; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e110); } + if (peg$silentFails === 0) { peg$fail(peg$e111); } } if (s1 !== peg$FAILED) { s2 = peg$currPos; @@ -3823,7 +3849,7 @@ function peg$parse(input, options) { } if (s2 !== peg$FAILED) { peg$savedPos = s0; - s0 = peg$f92(); + s0 = peg$f93(); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -3841,11 +3867,11 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 14); - if (s1.toLowerCase() === peg$c81) { + if (s1.toLowerCase() === peg$c82) { peg$currPos += 14; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e84); } + if (peg$silentFails === 0) { peg$fail(peg$e85); } } if (s1 !== peg$FAILED) { s2 = peg$currPos; @@ -3860,7 +3886,7 @@ function peg$parse(input, options) { } if (s2 !== peg$FAILED) { peg$savedPos = s0; - s0 = peg$f93(); + s0 = peg$f94(); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -3878,11 +3904,11 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 17); - if (s1.toLowerCase() === peg$c83) { + if (s1.toLowerCase() === peg$c84) { peg$currPos += 17; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e86); } + if (peg$silentFails === 0) { peg$fail(peg$e87); } } if (s1 !== peg$FAILED) { s2 = peg$currPos; @@ -3897,7 +3923,7 @@ function peg$parse(input, options) { } if (s2 !== peg$FAILED) { peg$savedPos = s0; - s0 = peg$f94(); + s0 = peg$f95(); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -3915,11 +3941,11 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 14); - if (s1.toLowerCase() === peg$c107) { + if (s1.toLowerCase() === peg$c108) { peg$currPos += 14; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e111); } + if (peg$silentFails === 0) { peg$fail(peg$e112); } } if (s1 !== peg$FAILED) { s2 = peg$currPos; @@ -3934,7 +3960,7 @@ function peg$parse(input, options) { } if (s2 !== peg$FAILED) { peg$savedPos = s0; - s0 = peg$f95(); + s0 = peg$f96(); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -3952,11 +3978,11 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 9); - if (s1.toLowerCase() === peg$c108) { + if (s1.toLowerCase() === peg$c109) { peg$currPos += 9; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e112); } + if (peg$silentFails === 0) { peg$fail(peg$e113); } } if (s1 !== peg$FAILED) { s2 = peg$currPos; @@ -3971,7 +3997,7 @@ function peg$parse(input, options) { } if (s2 !== peg$FAILED) { peg$savedPos = s0; - s0 = peg$f96(); + s0 = peg$f97(); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -3989,11 +4015,11 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 14); - if (s1.toLowerCase() === peg$c109) { + if (s1.toLowerCase() === peg$c110) { peg$currPos += 14; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e113); } + if (peg$silentFails === 0) { peg$fail(peg$e114); } } if (s1 !== peg$FAILED) { s2 = peg$currPos; @@ -4008,7 +4034,7 @@ function peg$parse(input, options) { } if (s2 !== peg$FAILED) { peg$savedPos = s0; - s0 = peg$f97(); + s0 = peg$f98(); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -4026,11 +4052,11 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 11); - if (s1.toLowerCase() === peg$c110) { + if (s1.toLowerCase() === peg$c111) { peg$currPos += 11; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e114); } + if (peg$silentFails === 0) { peg$fail(peg$e115); } } if (s1 !== peg$FAILED) { s2 = peg$currPos; @@ -4045,7 +4071,7 @@ function peg$parse(input, options) { } if (s2 !== peg$FAILED) { peg$savedPos = s0; - s0 = peg$f98(); + s0 = peg$f99(); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -4063,11 +4089,11 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 10); - if (s1.toLowerCase() === peg$c111) { + if (s1.toLowerCase() === peg$c112) { peg$currPos += 10; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e115); } + if (peg$silentFails === 0) { peg$fail(peg$e116); } } if (s1 !== peg$FAILED) { s2 = peg$currPos; @@ -4082,7 +4108,7 @@ function peg$parse(input, options) { } if (s2 !== peg$FAILED) { peg$savedPos = s0; - s0 = peg$f99(); + s0 = peg$f100(); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -4100,11 +4126,11 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 10); - if (s1.toLowerCase() === peg$c112) { + if (s1.toLowerCase() === peg$c113) { peg$currPos += 10; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e116); } + if (peg$silentFails === 0) { peg$fail(peg$e117); } } if (s1 !== peg$FAILED) { s2 = peg$currPos; @@ -4119,7 +4145,7 @@ function peg$parse(input, options) { } if (s2 !== peg$FAILED) { peg$savedPos = s0; - s0 = peg$f100(); + s0 = peg$f101(); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -4137,11 +4163,11 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 13); - if (s1.toLowerCase() === peg$c113) { + if (s1.toLowerCase() === peg$c114) { peg$currPos += 13; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e117); } + if (peg$silentFails === 0) { peg$fail(peg$e118); } } if (s1 !== peg$FAILED) { s2 = peg$currPos; @@ -4156,7 +4182,7 @@ function peg$parse(input, options) { } if (s2 !== peg$FAILED) { peg$savedPos = s0; - s0 = peg$f101(); + s0 = peg$f102(); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -4179,81 +4205,81 @@ function peg$parse(input, options) { peg$currPos++; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e96); } + if (peg$silentFails === 0) { peg$fail(peg$e97); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f102(); + s1 = peg$f103(); } s0 = s1; if (s0 === peg$FAILED) { s0 = peg$currPos; - if (input.substr(peg$currPos, 2) === peg$c114) { - s1 = peg$c114; + if (input.substr(peg$currPos, 2) === peg$c115) { + s1 = peg$c115; peg$currPos += 2; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e119); } + if (peg$silentFails === 0) { peg$fail(peg$e120); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f103(); + s1 = peg$f104(); } s0 = s1; if (s0 === peg$FAILED) { s0 = peg$currPos; - if (input.substr(peg$currPos, 2) === peg$c115) { - s1 = peg$c115; + if (input.substr(peg$currPos, 2) === peg$c116) { + s1 = peg$c116; peg$currPos += 2; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e120); } + if (peg$silentFails === 0) { peg$fail(peg$e121); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f104(); + s1 = peg$f105(); } s0 = s1; if (s0 === peg$FAILED) { s0 = peg$currPos; if (input.charCodeAt(peg$currPos) === 62) { - s1 = peg$c116; + s1 = peg$c117; peg$currPos++; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e121); } + if (peg$silentFails === 0) { peg$fail(peg$e122); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f105(); + s1 = peg$f106(); } s0 = s1; if (s0 === peg$FAILED) { s0 = peg$currPos; - if (input.substr(peg$currPos, 2) === peg$c117) { - s1 = peg$c117; + if (input.substr(peg$currPos, 2) === peg$c118) { + s1 = peg$c118; peg$currPos += 2; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e122); } + if (peg$silentFails === 0) { peg$fail(peg$e123); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f106(); + s1 = peg$f107(); } s0 = s1; if (s0 === peg$FAILED) { s0 = peg$currPos; if (input.charCodeAt(peg$currPos) === 60) { - s1 = peg$c118; + s1 = peg$c119; peg$currPos++; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e123); } + if (peg$silentFails === 0) { peg$fail(peg$e124); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f107(); + s1 = peg$f108(); } s0 = s1; } @@ -4264,7 +4290,7 @@ function peg$parse(input, options) { peg$silentFails--; if (s0 === peg$FAILED) { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e118); } + if (peg$silentFails === 0) { peg$fail(peg$e119); } } return s0; @@ -4277,7 +4303,7 @@ function peg$parse(input, options) { s1 = peg$parseoperator(); if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f108(s1); + s1 = peg$f109(s1); } s0 = s1; @@ -4289,11 +4315,11 @@ function peg$parse(input, options) { s0 = peg$currPos; if (input.charCodeAt(peg$currPos) === 92) { - s1 = peg$c119; + s1 = peg$c120; peg$currPos++; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e124); } + if (peg$silentFails === 0) { peg$fail(peg$e125); } } if (s1 !== peg$FAILED) { s2 = input.charAt(peg$currPos); @@ -4301,11 +4327,11 @@ function peg$parse(input, options) { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e125); } + if (peg$silentFails === 0) { peg$fail(peg$e126); } } if (s2 !== peg$FAILED) { peg$savedPos = s0; - s0 = peg$f109(s2); + s0 = peg$f110(s2); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -4331,7 +4357,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e127); } + if (peg$silentFails === 0) { peg$fail(peg$e128); } } } if (s2 !== peg$FAILED) { @@ -4344,7 +4370,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e127); } + if (peg$silentFails === 0) { peg$fail(peg$e128); } } } } @@ -4353,13 +4379,13 @@ function peg$parse(input, options) { } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f110(s1); + s1 = peg$f111(s1); } s0 = s1; peg$silentFails--; if (s0 === peg$FAILED) { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e126); } + if (peg$silentFails === 0) { peg$fail(peg$e127); } } return s0; @@ -4371,7 +4397,7 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = peg$parse_(); peg$savedPos = s0; - s1 = peg$f111(); + s1 = peg$f112(); s0 = s1; return s0; @@ -4387,7 +4413,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e129); } + if (peg$silentFails === 0) { peg$fail(peg$e130); } } while (s1 !== peg$FAILED) { s0.push(s1); @@ -4396,12 +4422,12 @@ function peg$parse(input, options) { peg$currPos++; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e129); } + if (peg$silentFails === 0) { peg$fail(peg$e130); } } } peg$silentFails--; s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e128); } + if (peg$silentFails === 0) { peg$fail(peg$e129); } return s0; } @@ -4411,7 +4437,7 @@ function peg$parse(input, options) { s0 = peg$currPos; peg$savedPos = peg$currPos; - s1 = peg$f112(); + s1 = peg$f113(); if (s1) { s1 = undefined; } else { @@ -4448,7 +4474,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e131); } + if (peg$silentFails === 0) { peg$fail(peg$e132); } } while (s2 !== peg$FAILED) { s1.push(s2); @@ -4457,7 +4483,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e131); } + if (peg$silentFails === 0) { peg$fail(peg$e132); } } } s2 = input.charAt(peg$currPos); @@ -4465,7 +4491,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e132); } + if (peg$silentFails === 0) { peg$fail(peg$e133); } } if (s2 !== peg$FAILED) { s3 = []; @@ -4476,7 +4502,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s4 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e133); } + if (peg$silentFails === 0) { peg$fail(peg$e134); } } } while (s4 !== peg$FAILED) { @@ -4488,7 +4514,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s4 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e133); } + if (peg$silentFails === 0) { peg$fail(peg$e134); } } } } @@ -4497,7 +4523,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s4 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e132); } + if (peg$silentFails === 0) { peg$fail(peg$e133); } } if (s4 !== peg$FAILED) { s5 = []; @@ -4506,7 +4532,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s6 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e127); } + if (peg$silentFails === 0) { peg$fail(peg$e128); } } while (s6 !== peg$FAILED) { s5.push(s6); @@ -4515,11 +4541,11 @@ function peg$parse(input, options) { peg$currPos++; } else { s6 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e127); } + if (peg$silentFails === 0) { peg$fail(peg$e128); } } } peg$savedPos = s0; - s0 = peg$f113(s1, s3, s5); + s0 = peg$f114(s1, s3, s5); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -4531,7 +4557,7 @@ function peg$parse(input, options) { peg$silentFails--; if (s0 === peg$FAILED) { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e130); } + if (peg$silentFails === 0) { peg$fail(peg$e131); } } return s0; @@ -4548,7 +4574,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e131); } + if (peg$silentFails === 0) { peg$fail(peg$e132); } } while (s2 !== peg$FAILED) { s1.push(s2); @@ -4557,7 +4583,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e131); } + if (peg$silentFails === 0) { peg$fail(peg$e132); } } } s2 = input.charAt(peg$currPos); @@ -4565,7 +4591,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e132); } + if (peg$silentFails === 0) { peg$fail(peg$e133); } } if (s2 !== peg$FAILED) { s3 = []; @@ -4576,7 +4602,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s4 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e133); } + if (peg$silentFails === 0) { peg$fail(peg$e134); } } if (s4 === peg$FAILED) { s4 = peg$currPos; @@ -4592,15 +4618,15 @@ function peg$parse(input, options) { } if (s5 !== peg$FAILED) { if (input.charCodeAt(peg$currPos) === 8220) { - s6 = peg$c120; + s6 = peg$c121; peg$currPos++; } else { s6 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e134); } + if (peg$silentFails === 0) { peg$fail(peg$e135); } } if (s6 !== peg$FAILED) { peg$savedPos = s4; - s4 = peg$f114(s1); + s4 = peg$f115(s1); } else { peg$currPos = s4; s4 = peg$FAILED; @@ -4623,15 +4649,15 @@ function peg$parse(input, options) { } if (s5 !== peg$FAILED) { if (input.charCodeAt(peg$currPos) === 8221) { - s6 = peg$c121; + s6 = peg$c122; peg$currPos++; } else { s6 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e135); } + if (peg$silentFails === 0) { peg$fail(peg$e136); } } if (s6 !== peg$FAILED) { peg$savedPos = s4; - s4 = peg$f115(s1); + s4 = peg$f116(s1); } else { peg$currPos = s4; s4 = peg$FAILED; @@ -4654,15 +4680,15 @@ function peg$parse(input, options) { } if (s5 !== peg$FAILED) { if (input.charCodeAt(peg$currPos) === 34) { - s6 = peg$c122; + s6 = peg$c123; peg$currPos++; } else { s6 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e136); } + if (peg$silentFails === 0) { peg$fail(peg$e137); } } if (s6 !== peg$FAILED) { peg$savedPos = s4; - s4 = peg$f116(s1); + s4 = peg$f117(s1); } else { peg$currPos = s4; s4 = peg$FAILED; @@ -4684,7 +4710,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s4 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e133); } + if (peg$silentFails === 0) { peg$fail(peg$e134); } } if (s4 === peg$FAILED) { s4 = peg$currPos; @@ -4700,15 +4726,15 @@ function peg$parse(input, options) { } if (s5 !== peg$FAILED) { if (input.charCodeAt(peg$currPos) === 8220) { - s6 = peg$c120; + s6 = peg$c121; peg$currPos++; } else { s6 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e134); } + if (peg$silentFails === 0) { peg$fail(peg$e135); } } if (s6 !== peg$FAILED) { peg$savedPos = s4; - s4 = peg$f114(s1); + s4 = peg$f115(s1); } else { peg$currPos = s4; s4 = peg$FAILED; @@ -4731,15 +4757,15 @@ function peg$parse(input, options) { } if (s5 !== peg$FAILED) { if (input.charCodeAt(peg$currPos) === 8221) { - s6 = peg$c121; + s6 = peg$c122; peg$currPos++; } else { s6 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e135); } + if (peg$silentFails === 0) { peg$fail(peg$e136); } } if (s6 !== peg$FAILED) { peg$savedPos = s4; - s4 = peg$f115(s1); + s4 = peg$f116(s1); } else { peg$currPos = s4; s4 = peg$FAILED; @@ -4762,15 +4788,15 @@ function peg$parse(input, options) { } if (s5 !== peg$FAILED) { if (input.charCodeAt(peg$currPos) === 34) { - s6 = peg$c122; + s6 = peg$c123; peg$currPos++; } else { s6 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e136); } + if (peg$silentFails === 0) { peg$fail(peg$e137); } } if (s6 !== peg$FAILED) { peg$savedPos = s4; - s4 = peg$f116(s1); + s4 = peg$f117(s1); } else { peg$currPos = s4; s4 = peg$FAILED; @@ -4787,7 +4813,7 @@ function peg$parse(input, options) { s4 = peg$parseclosingQuote(); if (s4 !== peg$FAILED) { peg$savedPos = s0; - s0 = peg$f117(s1, s3, s4); + s0 = peg$f118(s1, s3, s4); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -4799,7 +4825,7 @@ function peg$parse(input, options) { peg$silentFails--; if (s0 === peg$FAILED) { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e130); } + if (peg$silentFails === 0) { peg$fail(peg$e131); } } return s0; @@ -4814,7 +4840,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e132); } + if (peg$silentFails === 0) { peg$fail(peg$e133); } } if (s1 !== peg$FAILED) { s2 = peg$currPos; @@ -4852,7 +4878,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e137); } + if (peg$silentFails === 0) { peg$fail(peg$e138); } } while (s2 !== peg$FAILED) { s1.push(s2); @@ -4861,7 +4887,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e137); } + if (peg$silentFails === 0) { peg$fail(peg$e138); } } } s2 = []; @@ -4870,7 +4896,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s3 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e138); } + if (peg$silentFails === 0) { peg$fail(peg$e139); } } while (s3 !== peg$FAILED) { s2.push(s3); @@ -4879,7 +4905,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s3 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e138); } + if (peg$silentFails === 0) { peg$fail(peg$e139); } } } s3 = []; @@ -4888,7 +4914,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s4 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e139); } + if (peg$silentFails === 0) { peg$fail(peg$e140); } } while (s4 !== peg$FAILED) { s3.push(s4); @@ -4897,7 +4923,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s4 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e139); } + if (peg$silentFails === 0) { peg$fail(peg$e140); } } } s4 = peg$parseoperator(); @@ -4916,7 +4942,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e140); } + if (peg$silentFails === 0) { peg$fail(peg$e141); } } while (s2 !== peg$FAILED) { s1.push(s2); @@ -4925,7 +4951,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e140); } + if (peg$silentFails === 0) { peg$fail(peg$e141); } } } s2 = peg$currPos; @@ -4972,7 +4998,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s0 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e141); } + if (peg$silentFails === 0) { peg$fail(peg$e142); } } } } @@ -4988,7 +5014,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s0 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e142); } + if (peg$silentFails === 0) { peg$fail(peg$e143); } } if (s0 === peg$FAILED) { s0 = peg$currPos; diff --git a/src/libs/SearchParser/autocompleteParser.peggy b/src/libs/SearchParser/autocompleteParser.peggy index 725be1cedd3a..88ab9d41a2a7 100644 --- a/src/libs/SearchParser/autocompleteParser.peggy +++ b/src/libs/SearchParser/autocompleteParser.peggy @@ -81,6 +81,7 @@ autocompleteKey "key" / total / tag / category + / vendor / to / taxRate / from diff --git a/src/libs/SearchParser/baseRules.peggy b/src/libs/SearchParser/baseRules.peggy index 19ed053e07a1..ec180a33cbc5 100644 --- a/src/libs/SearchParser/baseRules.peggy +++ b/src/libs/SearchParser/baseRules.peggy @@ -29,6 +29,7 @@ groupCurrency / "group-currency"i { return "groupCurrency"; } tag = "tag"i { return "tag"; } category = "category"i { return "category"; } +vendor = "vendor"i { return "vendor"; } to = "to"i { return "to"; } exporter = "exporter"i { return "exporter"; } payer = "payer"i { return "payer"; } diff --git a/src/libs/SearchParser/searchParser.js b/src/libs/SearchParser/searchParser.js index e39f25116fe3..c6d6ce5f1d03 100644 --- a/src/libs/SearchParser/searchParser.js +++ b/src/libs/SearchParser/searchParser.js @@ -201,112 +201,113 @@ function peg$parse(input, options) { var peg$c14 = "group-currency"; var peg$c15 = "tag"; var peg$c16 = "category"; - var peg$c17 = "to"; - var peg$c18 = "exporter"; - var peg$c19 = "payer"; - var peg$c20 = "paidBy"; - var peg$c21 = "paid-by"; - var peg$c22 = "taxrate"; - var peg$c23 = "tax-rate"; - var peg$c24 = "cardID"; - var peg$c25 = "card"; - var peg$c26 = "bankAccount"; - var peg$c27 = "bank-account"; - var peg$c28 = "from"; - var peg$c29 = "attendee"; - var peg$c30 = "expenseType"; - var peg$c31 = "expense-type"; - var peg$c32 = "receiptType"; - var peg$c33 = "receipt-type"; - var peg$c34 = "withdrawalType"; - var peg$c35 = "withdrawal-type"; - var peg$c36 = "withdrawalStatus"; - var peg$c37 = "withdrawal-status"; - var peg$c38 = "paidStatus"; - var peg$c39 = "paid-status"; - var peg$c40 = "withdrawalid"; - var peg$c41 = "withdrawal-id"; - var peg$c42 = "billable"; - var peg$c43 = "reimbursable"; - var peg$c44 = "type"; - var peg$c45 = "status"; - var peg$c46 = "sortBy"; - var peg$c47 = "sort-by"; - var peg$c48 = "sortOrder"; - var peg$c49 = "sort-order"; - var peg$c50 = "policyID"; - var peg$c51 = "workspace"; - var peg$c52 = "submitted"; - var peg$c53 = "approved"; - var peg$c54 = "paid"; - var peg$c55 = "exported"; - var peg$c56 = "posted"; - var peg$c57 = "withdrawn"; - var peg$c58 = "groupby"; - var peg$c59 = "group-by"; - var peg$c60 = "limit"; - var peg$c61 = "feed"; - var peg$c62 = "title"; - var peg$c63 = "submitteruserid"; - var peg$c64 = "submitter-user-id"; - var peg$c65 = "submitterpayrollid"; - var peg$c66 = "submitter-payroll-id"; - var peg$c67 = "orderdealnumbers"; - var peg$c68 = "order-deal-numbers"; - var peg$c69 = "assignee"; - var peg$c70 = "createdby"; - var peg$c71 = "created-by"; - var peg$c72 = "action"; - var peg$c73 = "total"; - var peg$c74 = "has"; - var peg$c75 = "is"; - var peg$c76 = "purchaseamount"; - var peg$c77 = "purchase-amount"; - var peg$c78 = "purchasecurrency"; - var peg$c79 = "purchase-currency"; - var peg$c80 = "amountdebited"; - var peg$c81 = "amount-debited"; - var peg$c82 = "amountreimbursed"; - var peg$c83 = "amount-reimbursed"; - var peg$c84 = "columns"; - var peg$c85 = "view"; - var peg$c86 = "per-diem"; - var peg$c87 = "drafts"; - var peg$c88 = "draft"; - var peg$c89 = "tax"; - var peg$c90 = "policy-name"; - var peg$c91 = "long-report-id"; - var peg$c92 = "exported-to"; - var peg$c93 = "exportedto"; - var peg$c94 = "exchange-rate"; - var peg$c95 = "reimbursable-total"; - var peg$c96 = "non-reimbursable-total"; - var peg$c97 = "group-from"; - var peg$c98 = "group-expenses"; - var peg$c99 = "group-total"; - var peg$c100 = "group-card"; - var peg$c101 = "group-feed"; - var peg$c102 = "group-bank-account"; - var peg$c103 = "group-withdrawn"; - var peg$c104 = "group-withdrawal-id"; - var peg$c105 = "group-amount-debited"; - var peg$c106 = "group-amount-reimbursed"; - var peg$c107 = "group-category"; - var peg$c108 = "group-tag"; - var peg$c109 = "group-merchant"; - var peg$c110 = "group-month"; - var peg$c111 = "group-week"; - var peg$c112 = "group-year"; - var peg$c113 = "group-quarter"; - var peg$c114 = "!="; - var peg$c115 = ">="; - var peg$c116 = ">"; - var peg$c117 = "<="; - var peg$c118 = "<"; - var peg$c119 = "\\"; - var peg$c120 = "\u201C"; - var peg$c121 = "\u201D"; - var peg$c122 = "\""; + var peg$c17 = "vendor"; + var peg$c18 = "to"; + var peg$c19 = "exporter"; + var peg$c20 = "payer"; + var peg$c21 = "paidBy"; + var peg$c22 = "paid-by"; + var peg$c23 = "taxrate"; + var peg$c24 = "tax-rate"; + var peg$c25 = "cardID"; + var peg$c26 = "card"; + var peg$c27 = "bankAccount"; + var peg$c28 = "bank-account"; + var peg$c29 = "from"; + var peg$c30 = "attendee"; + var peg$c31 = "expenseType"; + var peg$c32 = "expense-type"; + var peg$c33 = "receiptType"; + var peg$c34 = "receipt-type"; + var peg$c35 = "withdrawalType"; + var peg$c36 = "withdrawal-type"; + var peg$c37 = "withdrawalStatus"; + var peg$c38 = "withdrawal-status"; + var peg$c39 = "paidStatus"; + var peg$c40 = "paid-status"; + var peg$c41 = "withdrawalid"; + var peg$c42 = "withdrawal-id"; + var peg$c43 = "billable"; + var peg$c44 = "reimbursable"; + var peg$c45 = "type"; + var peg$c46 = "status"; + var peg$c47 = "sortBy"; + var peg$c48 = "sort-by"; + var peg$c49 = "sortOrder"; + var peg$c50 = "sort-order"; + var peg$c51 = "policyID"; + var peg$c52 = "workspace"; + var peg$c53 = "submitted"; + var peg$c54 = "approved"; + var peg$c55 = "paid"; + var peg$c56 = "exported"; + var peg$c57 = "posted"; + var peg$c58 = "withdrawn"; + var peg$c59 = "groupby"; + var peg$c60 = "group-by"; + var peg$c61 = "limit"; + var peg$c62 = "feed"; + var peg$c63 = "title"; + var peg$c64 = "submitteruserid"; + var peg$c65 = "submitter-user-id"; + var peg$c66 = "submitterpayrollid"; + var peg$c67 = "submitter-payroll-id"; + var peg$c68 = "orderdealnumbers"; + var peg$c69 = "order-deal-numbers"; + var peg$c70 = "assignee"; + var peg$c71 = "createdby"; + var peg$c72 = "created-by"; + var peg$c73 = "action"; + var peg$c74 = "total"; + var peg$c75 = "has"; + var peg$c76 = "is"; + var peg$c77 = "purchaseamount"; + var peg$c78 = "purchase-amount"; + var peg$c79 = "purchasecurrency"; + var peg$c80 = "purchase-currency"; + var peg$c81 = "amountdebited"; + var peg$c82 = "amount-debited"; + var peg$c83 = "amountreimbursed"; + var peg$c84 = "amount-reimbursed"; + var peg$c85 = "columns"; + var peg$c86 = "view"; + var peg$c87 = "per-diem"; + var peg$c88 = "drafts"; + var peg$c89 = "draft"; + var peg$c90 = "tax"; + var peg$c91 = "policy-name"; + var peg$c92 = "long-report-id"; + var peg$c93 = "exported-to"; + var peg$c94 = "exportedto"; + var peg$c95 = "exchange-rate"; + var peg$c96 = "reimbursable-total"; + var peg$c97 = "non-reimbursable-total"; + var peg$c98 = "group-from"; + var peg$c99 = "group-expenses"; + var peg$c100 = "group-total"; + var peg$c101 = "group-card"; + var peg$c102 = "group-feed"; + var peg$c103 = "group-bank-account"; + var peg$c104 = "group-withdrawn"; + var peg$c105 = "group-withdrawal-id"; + var peg$c106 = "group-amount-debited"; + var peg$c107 = "group-amount-reimbursed"; + var peg$c108 = "group-category"; + var peg$c109 = "group-tag"; + var peg$c110 = "group-merchant"; + var peg$c111 = "group-month"; + var peg$c112 = "group-week"; + var peg$c113 = "group-year"; + var peg$c114 = "group-quarter"; + var peg$c115 = "!="; + var peg$c116 = ">="; + var peg$c117 = ">"; + var peg$c118 = "<="; + var peg$c119 = "<"; + var peg$c120 = "\\"; + var peg$c121 = "\u201C"; + var peg$c122 = "\u201D"; + var peg$c123 = "\""; var peg$r0 = /^[^ \t\r\n\xA0]/; var peg$r1 = /^[ \t\r\n\xA0,:=<>!]/; @@ -346,129 +347,130 @@ function peg$parse(input, options) { var peg$e19 = peg$literalExpectation("group-currency", true); var peg$e20 = peg$literalExpectation("tag", true); var peg$e21 = peg$literalExpectation("category", true); - var peg$e22 = peg$literalExpectation("to", true); - var peg$e23 = peg$literalExpectation("exporter", true); - var peg$e24 = peg$literalExpectation("payer", true); - var peg$e25 = peg$literalExpectation("paidBy", false); - var peg$e26 = peg$literalExpectation("paid-by", true); - var peg$e27 = peg$literalExpectation("taxRate", true); - var peg$e28 = peg$literalExpectation("tax-rate", true); - var peg$e29 = peg$literalExpectation("cardID", false); - var peg$e30 = peg$literalExpectation("card", true); - var peg$e31 = peg$literalExpectation("bankAccount", false); - var peg$e32 = peg$literalExpectation("bank-account", true); - var peg$e33 = peg$literalExpectation("from", true); - var peg$e34 = peg$literalExpectation("attendee", true); - var peg$e35 = peg$literalExpectation("expenseType", false); - var peg$e36 = peg$literalExpectation("expense-type", true); - var peg$e37 = peg$literalExpectation("receiptType", false); - var peg$e38 = peg$literalExpectation("receipt-type", true); - var peg$e39 = peg$literalExpectation("withdrawalType", false); - var peg$e40 = peg$literalExpectation("withdrawal-type", true); - var peg$e41 = peg$literalExpectation("withdrawalStatus", false); - var peg$e42 = peg$literalExpectation("withdrawal-status", true); - var peg$e43 = peg$literalExpectation("paidStatus", false); - var peg$e44 = peg$literalExpectation("paid-status", true); - var peg$e45 = peg$literalExpectation("withdrawalID", true); - var peg$e46 = peg$literalExpectation("withdrawal-id", true); - var peg$e47 = peg$literalExpectation("billable", true); - var peg$e48 = peg$literalExpectation("reimbursable", true); - var peg$e49 = peg$literalExpectation("type", true); - var peg$e50 = peg$literalExpectation("status", true); - var peg$e51 = peg$literalExpectation("sortBy", false); - var peg$e52 = peg$literalExpectation("sort-by", true); - var peg$e53 = peg$literalExpectation("sortOrder", false); - var peg$e54 = peg$literalExpectation("sort-order", true); - var peg$e55 = peg$literalExpectation("policyID", false); - var peg$e56 = peg$literalExpectation("workspace", true); - var peg$e57 = peg$literalExpectation("submitted", true); - var peg$e58 = peg$literalExpectation("approved", true); - var peg$e59 = peg$literalExpectation("paid", true); - var peg$e60 = peg$literalExpectation("exported", true); - var peg$e61 = peg$literalExpectation("posted", true); - var peg$e62 = peg$literalExpectation("withdrawn", true); - var peg$e63 = peg$literalExpectation("groupBy", true); - var peg$e64 = peg$literalExpectation("group-by", true); - var peg$e65 = peg$literalExpectation("limit", true); - var peg$e66 = peg$literalExpectation("feed", true); - var peg$e67 = peg$literalExpectation("title", true); - var peg$e68 = peg$literalExpectation("submitterUserID", true); - var peg$e69 = peg$literalExpectation("submitter-user-id", true); - var peg$e70 = peg$literalExpectation("submitterPayrollID", true); - var peg$e71 = peg$literalExpectation("submitter-payroll-id", true); - var peg$e72 = peg$literalExpectation("orderDealNumbers", true); - var peg$e73 = peg$literalExpectation("order-deal-numbers", true); - var peg$e74 = peg$literalExpectation("assignee", true); - var peg$e75 = peg$literalExpectation("createdBy", true); - var peg$e76 = peg$literalExpectation("created-by", true); - var peg$e77 = peg$literalExpectation("action", true); - var peg$e78 = peg$literalExpectation("total", true); - var peg$e79 = peg$literalExpectation("has", true); - var peg$e80 = peg$literalExpectation("is", true); - var peg$e81 = peg$literalExpectation("purchaseAmount", true); - var peg$e82 = peg$literalExpectation("purchase-amount", true); - var peg$e83 = peg$literalExpectation("purchaseCurrency", true); - var peg$e84 = peg$literalExpectation("purchase-currency", true); - var peg$e85 = peg$literalExpectation("amountDebited", true); - var peg$e86 = peg$literalExpectation("amount-debited", true); - var peg$e87 = peg$literalExpectation("amountReimbursed", true); - var peg$e88 = peg$literalExpectation("amount-reimbursed", true); - var peg$e89 = peg$literalExpectation("columns", true); - var peg$e90 = peg$literalExpectation("view", true); - var peg$e91 = peg$literalExpectation("per-diem", true); - var peg$e92 = peg$literalExpectation("drafts", true); - var peg$e93 = peg$literalExpectation("draft", true); - var peg$e94 = peg$literalExpectation("tax", true); - var peg$e95 = peg$literalExpectation("policy-name", true); - var peg$e96 = peg$literalExpectation("long-report-id", true); - var peg$e97 = peg$literalExpectation("exported-to", true); - var peg$e98 = peg$classExpectation([":", "="], false, false); - var peg$e99 = peg$literalExpectation("exportedTo", true); - var peg$e100 = peg$literalExpectation("exchange-rate", true); - var peg$e101 = peg$literalExpectation("reimbursable-total", true); - var peg$e102 = peg$literalExpectation("non-reimbursable-total", true); - var peg$e103 = peg$literalExpectation("group-from", true); - var peg$e104 = peg$literalExpectation("group-expenses", true); - var peg$e105 = peg$literalExpectation("group-total", true); - var peg$e106 = peg$literalExpectation("group-card", true); - var peg$e107 = peg$literalExpectation("group-feed", true); - var peg$e108 = peg$literalExpectation("group-bank-account", true); - var peg$e109 = peg$literalExpectation("group-withdrawn", true); - var peg$e110 = peg$literalExpectation("group-withdrawal-id", true); - var peg$e111 = peg$literalExpectation("group-amount-debited", true); - var peg$e112 = peg$literalExpectation("group-amount-reimbursed", true); - var peg$e113 = peg$literalExpectation("group-category", true); - var peg$e114 = peg$literalExpectation("group-tag", true); - var peg$e115 = peg$literalExpectation("group-merchant", true); - var peg$e116 = peg$literalExpectation("group-month", true); - var peg$e117 = peg$literalExpectation("group-week", true); - var peg$e118 = peg$literalExpectation("group-year", true); - var peg$e119 = peg$literalExpectation("group-quarter", true); - var peg$e120 = peg$otherExpectation("operator"); - var peg$e121 = peg$literalExpectation("!=", false); - var peg$e122 = peg$literalExpectation(">=", false); - var peg$e123 = peg$literalExpectation(">", false); - var peg$e124 = peg$literalExpectation("<=", false); - var peg$e125 = peg$literalExpectation("<", false); - var peg$e126 = peg$literalExpectation("\\", false); - var peg$e127 = peg$classExpectation([",", "\"", "\u201D", "\u201C", "\\"], false, false); - var peg$e128 = peg$otherExpectation("word"); - var peg$e129 = peg$classExpectation([" ", ",", "\t", "\n", "\r", "\xA0"], true, false); - var peg$e130 = peg$otherExpectation("whitespace"); - var peg$e131 = peg$classExpectation([" ", "\t", "\r", "\n", "\xA0"], false, false); - var peg$e132 = peg$otherExpectation("quote"); - var peg$e133 = peg$classExpectation([" ", ",", "\"", "\u201D", "\u201C", "\t", "\n", "\r", "\xA0"], true, false); - var peg$e134 = peg$classExpectation(["\"", ["\u201C", "\u201D"]], false, false); - var peg$e135 = peg$classExpectation(["\"", "\u201D", "\u201C", "\r", "\n"], true, false); - var peg$e136 = peg$literalExpectation("\u201C", false); - var peg$e137 = peg$literalExpectation("\u201D", false); - var peg$e138 = peg$literalExpectation("\"", false); - var peg$e139 = peg$classExpectation([" ", "\t", "\n", "\r", "\xA0", ["a", "z"], ["A", "Z"], ["0", "9"]], false, false); - var peg$e140 = peg$classExpectation([["a", "z"], ["A", "Z"], ["0", "9"]], false, false); - var peg$e141 = peg$classExpectation([" ", "\t", "\n", "\r", "\xA0"], false, false); - var peg$e142 = peg$classExpectation([" ", "\t", "\n", "\r", "\xA0", ["a", "z"], ["A", "Z"]], false, false); - var peg$e143 = peg$classExpectation([","], false, false); - var peg$e144 = peg$classExpectation([" ", "\t", "\n", "\r", "\xA0", ","], false, false); + var peg$e22 = peg$literalExpectation("vendor", true); + var peg$e23 = peg$literalExpectation("to", true); + var peg$e24 = peg$literalExpectation("exporter", true); + var peg$e25 = peg$literalExpectation("payer", true); + var peg$e26 = peg$literalExpectation("paidBy", false); + var peg$e27 = peg$literalExpectation("paid-by", true); + var peg$e28 = peg$literalExpectation("taxRate", true); + var peg$e29 = peg$literalExpectation("tax-rate", true); + var peg$e30 = peg$literalExpectation("cardID", false); + var peg$e31 = peg$literalExpectation("card", true); + var peg$e32 = peg$literalExpectation("bankAccount", false); + var peg$e33 = peg$literalExpectation("bank-account", true); + var peg$e34 = peg$literalExpectation("from", true); + var peg$e35 = peg$literalExpectation("attendee", true); + var peg$e36 = peg$literalExpectation("expenseType", false); + var peg$e37 = peg$literalExpectation("expense-type", true); + var peg$e38 = peg$literalExpectation("receiptType", false); + var peg$e39 = peg$literalExpectation("receipt-type", true); + var peg$e40 = peg$literalExpectation("withdrawalType", false); + var peg$e41 = peg$literalExpectation("withdrawal-type", true); + var peg$e42 = peg$literalExpectation("withdrawalStatus", false); + var peg$e43 = peg$literalExpectation("withdrawal-status", true); + var peg$e44 = peg$literalExpectation("paidStatus", false); + var peg$e45 = peg$literalExpectation("paid-status", true); + var peg$e46 = peg$literalExpectation("withdrawalID", true); + var peg$e47 = peg$literalExpectation("withdrawal-id", true); + var peg$e48 = peg$literalExpectation("billable", true); + var peg$e49 = peg$literalExpectation("reimbursable", true); + var peg$e50 = peg$literalExpectation("type", true); + var peg$e51 = peg$literalExpectation("status", true); + var peg$e52 = peg$literalExpectation("sortBy", false); + var peg$e53 = peg$literalExpectation("sort-by", true); + var peg$e54 = peg$literalExpectation("sortOrder", false); + var peg$e55 = peg$literalExpectation("sort-order", true); + var peg$e56 = peg$literalExpectation("policyID", false); + var peg$e57 = peg$literalExpectation("workspace", true); + var peg$e58 = peg$literalExpectation("submitted", true); + var peg$e59 = peg$literalExpectation("approved", true); + var peg$e60 = peg$literalExpectation("paid", true); + var peg$e61 = peg$literalExpectation("exported", true); + var peg$e62 = peg$literalExpectation("posted", true); + var peg$e63 = peg$literalExpectation("withdrawn", true); + var peg$e64 = peg$literalExpectation("groupBy", true); + var peg$e65 = peg$literalExpectation("group-by", true); + var peg$e66 = peg$literalExpectation("limit", true); + var peg$e67 = peg$literalExpectation("feed", true); + var peg$e68 = peg$literalExpectation("title", true); + var peg$e69 = peg$literalExpectation("submitterUserID", true); + var peg$e70 = peg$literalExpectation("submitter-user-id", true); + var peg$e71 = peg$literalExpectation("submitterPayrollID", true); + var peg$e72 = peg$literalExpectation("submitter-payroll-id", true); + var peg$e73 = peg$literalExpectation("orderDealNumbers", true); + var peg$e74 = peg$literalExpectation("order-deal-numbers", true); + var peg$e75 = peg$literalExpectation("assignee", true); + var peg$e76 = peg$literalExpectation("createdBy", true); + var peg$e77 = peg$literalExpectation("created-by", true); + var peg$e78 = peg$literalExpectation("action", true); + var peg$e79 = peg$literalExpectation("total", true); + var peg$e80 = peg$literalExpectation("has", true); + var peg$e81 = peg$literalExpectation("is", true); + var peg$e82 = peg$literalExpectation("purchaseAmount", true); + var peg$e83 = peg$literalExpectation("purchase-amount", true); + var peg$e84 = peg$literalExpectation("purchaseCurrency", true); + var peg$e85 = peg$literalExpectation("purchase-currency", true); + var peg$e86 = peg$literalExpectation("amountDebited", true); + var peg$e87 = peg$literalExpectation("amount-debited", true); + var peg$e88 = peg$literalExpectation("amountReimbursed", true); + var peg$e89 = peg$literalExpectation("amount-reimbursed", true); + var peg$e90 = peg$literalExpectation("columns", true); + var peg$e91 = peg$literalExpectation("view", true); + var peg$e92 = peg$literalExpectation("per-diem", true); + var peg$e93 = peg$literalExpectation("drafts", true); + var peg$e94 = peg$literalExpectation("draft", true); + var peg$e95 = peg$literalExpectation("tax", true); + var peg$e96 = peg$literalExpectation("policy-name", true); + var peg$e97 = peg$literalExpectation("long-report-id", true); + var peg$e98 = peg$literalExpectation("exported-to", true); + var peg$e99 = peg$classExpectation([":", "="], false, false); + var peg$e100 = peg$literalExpectation("exportedTo", true); + var peg$e101 = peg$literalExpectation("exchange-rate", true); + var peg$e102 = peg$literalExpectation("reimbursable-total", true); + var peg$e103 = peg$literalExpectation("non-reimbursable-total", true); + var peg$e104 = peg$literalExpectation("group-from", true); + var peg$e105 = peg$literalExpectation("group-expenses", true); + var peg$e106 = peg$literalExpectation("group-total", true); + var peg$e107 = peg$literalExpectation("group-card", true); + var peg$e108 = peg$literalExpectation("group-feed", true); + var peg$e109 = peg$literalExpectation("group-bank-account", true); + var peg$e110 = peg$literalExpectation("group-withdrawn", true); + var peg$e111 = peg$literalExpectation("group-withdrawal-id", true); + var peg$e112 = peg$literalExpectation("group-amount-debited", true); + var peg$e113 = peg$literalExpectation("group-amount-reimbursed", true); + var peg$e114 = peg$literalExpectation("group-category", true); + var peg$e115 = peg$literalExpectation("group-tag", true); + var peg$e116 = peg$literalExpectation("group-merchant", true); + var peg$e117 = peg$literalExpectation("group-month", true); + var peg$e118 = peg$literalExpectation("group-week", true); + var peg$e119 = peg$literalExpectation("group-year", true); + var peg$e120 = peg$literalExpectation("group-quarter", true); + var peg$e121 = peg$otherExpectation("operator"); + var peg$e122 = peg$literalExpectation("!=", false); + var peg$e123 = peg$literalExpectation(">=", false); + var peg$e124 = peg$literalExpectation(">", false); + var peg$e125 = peg$literalExpectation("<=", false); + var peg$e126 = peg$literalExpectation("<", false); + var peg$e127 = peg$literalExpectation("\\", false); + var peg$e128 = peg$classExpectation([",", "\"", "\u201D", "\u201C", "\\"], false, false); + var peg$e129 = peg$otherExpectation("word"); + var peg$e130 = peg$classExpectation([" ", ",", "\t", "\n", "\r", "\xA0"], true, false); + var peg$e131 = peg$otherExpectation("whitespace"); + var peg$e132 = peg$classExpectation([" ", "\t", "\r", "\n", "\xA0"], false, false); + var peg$e133 = peg$otherExpectation("quote"); + var peg$e134 = peg$classExpectation([" ", ",", "\"", "\u201D", "\u201C", "\t", "\n", "\r", "\xA0"], true, false); + var peg$e135 = peg$classExpectation(["\"", ["\u201C", "\u201D"]], false, false); + var peg$e136 = peg$classExpectation(["\"", "\u201D", "\u201C", "\r", "\n"], true, false); + var peg$e137 = peg$literalExpectation("\u201C", false); + var peg$e138 = peg$literalExpectation("\u201D", false); + var peg$e139 = peg$literalExpectation("\"", false); + var peg$e140 = peg$classExpectation([" ", "\t", "\n", "\r", "\xA0", ["a", "z"], ["A", "Z"], ["0", "9"]], false, false); + var peg$e141 = peg$classExpectation([["a", "z"], ["A", "Z"], ["0", "9"]], false, false); + var peg$e142 = peg$classExpectation([" ", "\t", "\n", "\r", "\xA0"], false, false); + var peg$e143 = peg$classExpectation([" ", "\t", "\n", "\r", "\xA0", ["a", "z"], ["A", "Z"]], false, false); + var peg$e144 = peg$classExpectation([","], false, false); + var peg$e145 = peg$classExpectation([" ", "\t", "\n", "\r", "\xA0", ","], false, false); var peg$f0 = function(filters) { return applyDefaults(filters); }; var peg$f1 = function(head, tail) { @@ -566,119 +568,120 @@ function peg$parse(input, options) { var peg$f16 = function() { return "groupCurrency"; }; var peg$f17 = function() { return "tag"; }; var peg$f18 = function() { return "category"; }; - var peg$f19 = function() { return "to"; }; - var peg$f20 = function() { return "exporter"; }; - var peg$f21 = function() { return "payer"; }; - var peg$f22 = function() { return "paidBy"; }; - var peg$f23 = function() { return "taxRate"; }; - var peg$f24 = function() { return "cardID"; }; - var peg$f25 = function() { return "bankAccount"; }; - var peg$f26 = function() { return "from"; }; - var peg$f27 = function() {return "attendee"}; - var peg$f28 = function() { return "expenseType"; }; - var peg$f29 = function() { return "receiptType"; }; - var peg$f30 = function() { return "withdrawalType"; }; - var peg$f31 = function() { return "withdrawalStatus"; }; - var peg$f32 = function() { return "paidStatus"; }; - var peg$f33 = function() { return "withdrawalID"; }; - var peg$f34 = function() { return "billable"; }; - var peg$f35 = function() { return "reimbursable"; }; - var peg$f36 = function() { return "type"; }; - var peg$f37 = function() { return "status"; }; - var peg$f38 = function() { return "sortBy"; }; - var peg$f39 = function() { return "sortOrder"; }; - var peg$f40 = function() { return "policyID"; }; - var peg$f41 = function() { return "submitted"; }; - var peg$f42 = function() { return "approved"; }; - var peg$f43 = function() { return "paid"; }; - var peg$f44 = function() { return "exported"; }; - var peg$f45 = function() { return "posted"; }; - var peg$f46 = function() { return "withdrawn"; }; - var peg$f47 = function() { return "groupBy"; }; - var peg$f48 = function() { return "limit"; }; - var peg$f49 = function() { return "feed"; }; - var peg$f50 = function() { return "title"; }; - var peg$f51 = function() { return "submitterUserID"; }; - var peg$f52 = function() { return "submitterPayrollID"; }; - var peg$f53 = function() { return "orderDealNumbers"; }; - var peg$f54 = function() { return "assignee"; }; - var peg$f55 = function() { return "createdBy"; }; - var peg$f56 = function() { return "action"; }; - var peg$f57 = function() {return "total"; }; - var peg$f58 = function() {return "has"; }; - var peg$f59 = function() {return "is"; }; - var peg$f60 = function() {return "purchaseAmount"}; - var peg$f61 = function() {return "purchaseCurrency"}; - var peg$f62 = function() {return "amountDebited"}; - var peg$f63 = function() {return "amountReimbursed"}; - var peg$f64 = function() { + var peg$f19 = function() { return "vendor"; }; + var peg$f20 = function() { return "to"; }; + var peg$f21 = function() { return "exporter"; }; + var peg$f22 = function() { return "payer"; }; + var peg$f23 = function() { return "paidBy"; }; + var peg$f24 = function() { return "taxRate"; }; + var peg$f25 = function() { return "cardID"; }; + var peg$f26 = function() { return "bankAccount"; }; + var peg$f27 = function() { return "from"; }; + var peg$f28 = function() {return "attendee"}; + var peg$f29 = function() { return "expenseType"; }; + var peg$f30 = function() { return "receiptType"; }; + var peg$f31 = function() { return "withdrawalType"; }; + var peg$f32 = function() { return "withdrawalStatus"; }; + var peg$f33 = function() { return "paidStatus"; }; + var peg$f34 = function() { return "withdrawalID"; }; + var peg$f35 = function() { return "billable"; }; + var peg$f36 = function() { return "reimbursable"; }; + var peg$f37 = function() { return "type"; }; + var peg$f38 = function() { return "status"; }; + var peg$f39 = function() { return "sortBy"; }; + var peg$f40 = function() { return "sortOrder"; }; + var peg$f41 = function() { return "policyID"; }; + var peg$f42 = function() { return "submitted"; }; + var peg$f43 = function() { return "approved"; }; + var peg$f44 = function() { return "paid"; }; + var peg$f45 = function() { return "exported"; }; + var peg$f46 = function() { return "posted"; }; + var peg$f47 = function() { return "withdrawn"; }; + var peg$f48 = function() { return "groupBy"; }; + var peg$f49 = function() { return "limit"; }; + var peg$f50 = function() { return "feed"; }; + var peg$f51 = function() { return "title"; }; + var peg$f52 = function() { return "submitterUserID"; }; + var peg$f53 = function() { return "submitterPayrollID"; }; + var peg$f54 = function() { return "orderDealNumbers"; }; + var peg$f55 = function() { return "assignee"; }; + var peg$f56 = function() { return "createdBy"; }; + var peg$f57 = function() { return "action"; }; + var peg$f58 = function() {return "total"; }; + var peg$f59 = function() {return "has"; }; + var peg$f60 = function() {return "is"; }; + var peg$f61 = function() {return "purchaseAmount"}; + var peg$f62 = function() {return "purchaseCurrency"}; + var peg$f63 = function() {return "amountDebited"}; + var peg$f64 = function() {return "amountReimbursed"}; + var peg$f65 = function() { isColumnsContext = true; return "columns"; }; - var peg$f65 = function() {return "view"}; - var peg$f66 = function() { return isColumnsContext; }; - var peg$f67 = function() { return "perDiem"; }; - var peg$f68 = function() { return "drafts"; }; - var peg$f69 = function() { return "originalamount"; }; - var peg$f70 = function() { return "taxAmount"; }; - var peg$f71 = function() { return "taxrate"; }; - var peg$f72 = function() { return "policyname"; }; - var peg$f73 = function() { return "withdrawalID"; }; - var peg$f74 = function() { return "bankAccount"; }; - var peg$f75 = function() { return "reportID"; }; - var peg$f76 = function() { return "base62ReportID"; }; - var peg$f77 = function() { return "exportedto"; }; - var peg$f78 = function() { return "exportedTo"; }; + var peg$f66 = function() {return "view"}; + var peg$f67 = function() { return isColumnsContext; }; + var peg$f68 = function() { return "perDiem"; }; + var peg$f69 = function() { return "drafts"; }; + var peg$f70 = function() { return "originalamount"; }; + var peg$f71 = function() { return "taxAmount"; }; + var peg$f72 = function() { return "taxrate"; }; + var peg$f73 = function() { return "policyname"; }; + var peg$f74 = function() { return "withdrawalID"; }; + var peg$f75 = function() { return "bankAccount"; }; + var peg$f76 = function() { return "reportID"; }; + var peg$f77 = function() { return "base62ReportID"; }; + var peg$f78 = function() { return "exportedto"; }; var peg$f79 = function() { return "exportedTo"; }; - var peg$f80 = function() { return "exchangeRate"; }; - var peg$f81 = function() { return "reimbursableTotal"; }; - var peg$f82 = function() { return "nonReimbursableTotal"; }; - var peg$f83 = function() { return "groupFrom"; }; - var peg$f84 = function() { return "groupExpenses"; }; - var peg$f85 = function() { return "groupTotal"; }; - var peg$f86 = function() { return "groupCard"; }; - var peg$f87 = function() { return "groupFeed"; }; - var peg$f88 = function() { return "groupBankAccount"; }; - var peg$f89 = function() { return "groupWithdrawn"; }; - var peg$f90 = function() { return "groupWithdrawalID"; }; - var peg$f91 = function() { return "groupAmountDebited"; }; - var peg$f92 = function() { return "groupAmountReimbursed"; }; - var peg$f93 = function() { return "amountDebited"; }; - var peg$f94 = function() { return "amountReimbursed"; }; - var peg$f95 = function() { return "groupCategory"; }; - var peg$f96 = function() { return "groupTag"; }; - var peg$f97 = function() { return "groupMerchant"; }; - var peg$f98 = function() { return "groupmonth"; }; - var peg$f99 = function() { return "groupweek"; }; - var peg$f100 = function() { return "groupyear"; }; - var peg$f101 = function() { return "groupquarter"; }; - var peg$f102 = function() { return "eq"; }; - var peg$f103 = function() { return "neq"; }; - var peg$f104 = function() { return "gte"; }; - var peg$f105 = function() { return "gt"; }; - var peg$f106 = function() { return "lte"; }; - var peg$f107 = function() { return "lt"; }; - var peg$f108 = function(o) { + var peg$f80 = function() { return "exportedTo"; }; + var peg$f81 = function() { return "exchangeRate"; }; + var peg$f82 = function() { return "reimbursableTotal"; }; + var peg$f83 = function() { return "nonReimbursableTotal"; }; + var peg$f84 = function() { return "groupFrom"; }; + var peg$f85 = function() { return "groupExpenses"; }; + var peg$f86 = function() { return "groupTotal"; }; + var peg$f87 = function() { return "groupCard"; }; + var peg$f88 = function() { return "groupFeed"; }; + var peg$f89 = function() { return "groupBankAccount"; }; + var peg$f90 = function() { return "groupWithdrawn"; }; + var peg$f91 = function() { return "groupWithdrawalID"; }; + var peg$f92 = function() { return "groupAmountDebited"; }; + var peg$f93 = function() { return "groupAmountReimbursed"; }; + var peg$f94 = function() { return "amountDebited"; }; + var peg$f95 = function() { return "amountReimbursed"; }; + var peg$f96 = function() { return "groupCategory"; }; + var peg$f97 = function() { return "groupTag"; }; + var peg$f98 = function() { return "groupMerchant"; }; + var peg$f99 = function() { return "groupmonth"; }; + var peg$f100 = function() { return "groupweek"; }; + var peg$f101 = function() { return "groupyear"; }; + var peg$f102 = function() { return "groupquarter"; }; + var peg$f103 = function() { return "eq"; }; + var peg$f104 = function() { return "neq"; }; + var peg$f105 = function() { return "gte"; }; + var peg$f106 = function() { return "gt"; }; + var peg$f107 = function() { return "lte"; }; + var peg$f108 = function() { return "lt"; }; + var peg$f109 = function(o) { if (nameOperator) { expectingNestedQuote = (o === "eq"); // Use simple parser if no valid operator is found } isColumnsContext = false; return o; }; - var peg$f109 = function(c) { return c; }; - var peg$f110 = function(chars) { return chars.join("").trim(); }; - var peg$f111 = function() { + var peg$f110 = function(c) { return c; }; + var peg$f111 = function(chars) { return chars.join("").trim(); }; + var peg$f112 = function() { isColumnsContext = false; return "and"; }; - var peg$f112 = function() { return expectingNestedQuote; }; - var peg$f113 = function(start, inner, end) { //handle no-breaking space + var peg$f113 = function() { return expectingNestedQuote; }; + var peg$f114 = function(start, inner, end) { //handle no-breaking space return [...start, '"', ...inner, '"', ...end].join(""); }; - var peg$f114 = function(start) {return "“"}; - var peg$f115 = function(start) {return "”"}; - var peg$f116 = function(start) {return "\""}; - var peg$f117 = function(start, inner, end) { + var peg$f115 = function(start) {return "“"}; + var peg$f116 = function(start) {return "”"}; + var peg$f117 = function(start) {return "\""}; + var peg$f118 = function(start, inner, end) { return [...start, '"', ...inner, '"'].join(""); }; var peg$currPos = options.peg$currPos | 0; @@ -1194,83 +1197,86 @@ function peg$parse(input, options) { if (s1 === peg$FAILED) { s1 = peg$parsecategory(); if (s1 === peg$FAILED) { - s1 = peg$parseto(); + s1 = peg$parsevendor(); if (s1 === peg$FAILED) { - s1 = peg$parsetaxRate(); + s1 = peg$parseto(); if (s1 === peg$FAILED) { - s1 = peg$parsecardID(); + s1 = peg$parsetaxRate(); if (s1 === peg$FAILED) { - s1 = peg$parsebankAccount(); + s1 = peg$parsecardID(); if (s1 === peg$FAILED) { - s1 = peg$parsefrom(); + s1 = peg$parsebankAccount(); if (s1 === peg$FAILED) { - s1 = peg$parseattendee(); + s1 = peg$parsefrom(); if (s1 === peg$FAILED) { - s1 = peg$parsepayer(); + s1 = peg$parseattendee(); if (s1 === peg$FAILED) { - s1 = peg$parsepaidBy(); + s1 = peg$parsepayer(); if (s1 === peg$FAILED) { - s1 = peg$parseexporter(); + s1 = peg$parsepaidBy(); if (s1 === peg$FAILED) { - s1 = peg$parseexpenseType(); + s1 = peg$parseexporter(); if (s1 === peg$FAILED) { - s1 = peg$parsereceiptType(); + s1 = peg$parseexpenseType(); if (s1 === peg$FAILED) { - s1 = peg$parsewithdrawalType(); + s1 = peg$parsereceiptType(); if (s1 === peg$FAILED) { - s1 = peg$parsewithdrawalStatus(); + s1 = peg$parsewithdrawalType(); if (s1 === peg$FAILED) { - s1 = peg$parsepaidStatus(); + s1 = peg$parsewithdrawalStatus(); if (s1 === peg$FAILED) { - s1 = peg$parsewithdrawalID(); + s1 = peg$parsepaidStatus(); if (s1 === peg$FAILED) { - s1 = peg$parsesubmitted(); + s1 = peg$parsewithdrawalID(); if (s1 === peg$FAILED) { - s1 = peg$parseapproved(); + s1 = peg$parsesubmitted(); if (s1 === peg$FAILED) { - s1 = peg$parsepaid(); + s1 = peg$parseapproved(); if (s1 === peg$FAILED) { - s1 = peg$parseexportedTo(); + s1 = peg$parsepaid(); if (s1 === peg$FAILED) { - s1 = peg$parseexported(); + s1 = peg$parseexportedTo(); if (s1 === peg$FAILED) { - s1 = peg$parseposted(); + s1 = peg$parseexported(); if (s1 === peg$FAILED) { - s1 = peg$parsewithdrawn(); + s1 = peg$parseposted(); if (s1 === peg$FAILED) { - s1 = peg$parsefeed(); + s1 = peg$parsewithdrawn(); if (s1 === peg$FAILED) { - s1 = peg$parsetitle(); + s1 = peg$parsefeed(); if (s1 === peg$FAILED) { - s1 = peg$parsesubmitterUserID(); + s1 = peg$parsetitle(); if (s1 === peg$FAILED) { - s1 = peg$parsesubmitterPayrollID(); + s1 = peg$parsesubmitterUserID(); if (s1 === peg$FAILED) { - s1 = peg$parseorderDealNumbers(); + s1 = peg$parsesubmitterPayrollID(); if (s1 === peg$FAILED) { - s1 = peg$parseassignee(); + s1 = peg$parseorderDealNumbers(); if (s1 === peg$FAILED) { - s1 = peg$parsecreatedBy(); + s1 = peg$parseassignee(); if (s1 === peg$FAILED) { - s1 = peg$parsereimbursable(); + s1 = peg$parsecreatedBy(); if (s1 === peg$FAILED) { - s1 = peg$parsebillable(); + s1 = peg$parsereimbursable(); if (s1 === peg$FAILED) { - s1 = peg$parseaction(); + s1 = peg$parsebillable(); if (s1 === peg$FAILED) { - s1 = peg$parsehas(); + s1 = peg$parseaction(); if (s1 === peg$FAILED) { - s1 = peg$parseis(); + s1 = peg$parsehas(); if (s1 === peg$FAILED) { - s1 = peg$parsepurchaseCurrency(); + s1 = peg$parseis(); if (s1 === peg$FAILED) { - s1 = peg$parsepurchaseAmount(); + s1 = peg$parsepurchaseCurrency(); if (s1 === peg$FAILED) { - s1 = peg$parsepolicyID(); + s1 = peg$parsepurchaseAmount(); if (s1 === peg$FAILED) { - s1 = peg$parsestatus(); + s1 = peg$parsepolicyID(); if (s1 === peg$FAILED) { - s1 = peg$parsereportFieldDynamic(); + s1 = peg$parsestatus(); + if (s1 === peg$FAILED) { + s1 = peg$parsereportFieldDynamic(); + } } } } @@ -1752,13 +1758,13 @@ function peg$parse(input, options) { return s0; } - function peg$parseto() { + function peg$parsevendor() { var s0, s1; s0 = peg$currPos; - s1 = input.substr(peg$currPos, 2); + s1 = input.substr(peg$currPos, 6); if (s1.toLowerCase() === peg$c17) { - peg$currPos += 2; + peg$currPos += 6; } else { s1 = peg$FAILED; if (peg$silentFails === 0) { peg$fail(peg$e22); } @@ -1772,13 +1778,13 @@ function peg$parse(input, options) { return s0; } - function peg$parseexporter() { + function peg$parseto() { var s0, s1; s0 = peg$currPos; - s1 = input.substr(peg$currPos, 8); + s1 = input.substr(peg$currPos, 2); if (s1.toLowerCase() === peg$c18) { - peg$currPos += 8; + peg$currPos += 2; } else { s1 = peg$FAILED; if (peg$silentFails === 0) { peg$fail(peg$e23); } @@ -1792,13 +1798,13 @@ function peg$parse(input, options) { return s0; } - function peg$parsepayer() { + function peg$parseexporter() { var s0, s1; s0 = peg$currPos; - s1 = input.substr(peg$currPos, 5); + s1 = input.substr(peg$currPos, 8); if (s1.toLowerCase() === peg$c19) { - peg$currPos += 5; + peg$currPos += 8; } else { s1 = peg$FAILED; if (peg$silentFails === 0) { peg$fail(peg$e24); } @@ -1812,28 +1818,48 @@ function peg$parse(input, options) { return s0; } + function peg$parsepayer() { + var s0, s1; + + s0 = peg$currPos; + s1 = input.substr(peg$currPos, 5); + if (s1.toLowerCase() === peg$c20) { + peg$currPos += 5; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e25); } + } + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$f22(); + } + s0 = s1; + + return s0; + } + function peg$parsepaidBy() { var s0, s1; - if (input.substr(peg$currPos, 6) === peg$c20) { - s0 = peg$c20; + if (input.substr(peg$currPos, 6) === peg$c21) { + s0 = peg$c21; peg$currPos += 6; } else { s0 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e25); } + if (peg$silentFails === 0) { peg$fail(peg$e26); } } if (s0 === peg$FAILED) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 7); - if (s1.toLowerCase() === peg$c21) { + if (s1.toLowerCase() === peg$c22) { peg$currPos += 7; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e26); } + if (peg$silentFails === 0) { peg$fail(peg$e27); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f22(); + s1 = peg$f23(); } s0 = s1; } @@ -1845,24 +1871,24 @@ function peg$parse(input, options) { var s0, s1; s0 = input.substr(peg$currPos, 7); - if (s0.toLowerCase() === peg$c22) { + if (s0.toLowerCase() === peg$c23) { peg$currPos += 7; } else { s0 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e27); } + if (peg$silentFails === 0) { peg$fail(peg$e28); } } if (s0 === peg$FAILED) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 8); - if (s1.toLowerCase() === peg$c23) { + if (s1.toLowerCase() === peg$c24) { peg$currPos += 8; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e28); } + if (peg$silentFails === 0) { peg$fail(peg$e29); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f23(); + s1 = peg$f24(); } s0 = s1; } @@ -1873,25 +1899,25 @@ function peg$parse(input, options) { function peg$parsecardID() { var s0, s1; - if (input.substr(peg$currPos, 6) === peg$c24) { - s0 = peg$c24; + if (input.substr(peg$currPos, 6) === peg$c25) { + s0 = peg$c25; peg$currPos += 6; } else { s0 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e29); } + if (peg$silentFails === 0) { peg$fail(peg$e30); } } if (s0 === peg$FAILED) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 4); - if (s1.toLowerCase() === peg$c25) { + if (s1.toLowerCase() === peg$c26) { peg$currPos += 4; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e30); } + if (peg$silentFails === 0) { peg$fail(peg$e31); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f24(); + s1 = peg$f25(); } s0 = s1; } @@ -1902,25 +1928,25 @@ function peg$parse(input, options) { function peg$parsebankAccount() { var s0, s1; - if (input.substr(peg$currPos, 11) === peg$c26) { - s0 = peg$c26; + if (input.substr(peg$currPos, 11) === peg$c27) { + s0 = peg$c27; peg$currPos += 11; } else { s0 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e31); } + if (peg$silentFails === 0) { peg$fail(peg$e32); } } if (s0 === peg$FAILED) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 12); - if (s1.toLowerCase() === peg$c27) { + if (s1.toLowerCase() === peg$c28) { peg$currPos += 12; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e32); } + if (peg$silentFails === 0) { peg$fail(peg$e33); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f25(); + s1 = peg$f26(); } s0 = s1; } @@ -1933,15 +1959,15 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 4); - if (s1.toLowerCase() === peg$c28) { + if (s1.toLowerCase() === peg$c29) { peg$currPos += 4; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e33); } + if (peg$silentFails === 0) { peg$fail(peg$e34); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f26(); + s1 = peg$f27(); } s0 = s1; @@ -1953,15 +1979,15 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 8); - if (s1.toLowerCase() === peg$c29) { + if (s1.toLowerCase() === peg$c30) { peg$currPos += 8; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e34); } + if (peg$silentFails === 0) { peg$fail(peg$e35); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f27(); + s1 = peg$f28(); } s0 = s1; @@ -1971,25 +1997,25 @@ function peg$parse(input, options) { function peg$parseexpenseType() { var s0, s1; - if (input.substr(peg$currPos, 11) === peg$c30) { - s0 = peg$c30; + if (input.substr(peg$currPos, 11) === peg$c31) { + s0 = peg$c31; peg$currPos += 11; } else { s0 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e35); } + if (peg$silentFails === 0) { peg$fail(peg$e36); } } if (s0 === peg$FAILED) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 12); - if (s1.toLowerCase() === peg$c31) { + if (s1.toLowerCase() === peg$c32) { peg$currPos += 12; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e36); } + if (peg$silentFails === 0) { peg$fail(peg$e37); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f28(); + s1 = peg$f29(); } s0 = s1; } @@ -2000,25 +2026,25 @@ function peg$parse(input, options) { function peg$parsereceiptType() { var s0, s1; - if (input.substr(peg$currPos, 11) === peg$c32) { - s0 = peg$c32; + if (input.substr(peg$currPos, 11) === peg$c33) { + s0 = peg$c33; peg$currPos += 11; } else { s0 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e37); } + if (peg$silentFails === 0) { peg$fail(peg$e38); } } if (s0 === peg$FAILED) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 12); - if (s1.toLowerCase() === peg$c33) { + if (s1.toLowerCase() === peg$c34) { peg$currPos += 12; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e38); } + if (peg$silentFails === 0) { peg$fail(peg$e39); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f29(); + s1 = peg$f30(); } s0 = s1; } @@ -2029,25 +2055,25 @@ function peg$parse(input, options) { function peg$parsewithdrawalType() { var s0, s1; - if (input.substr(peg$currPos, 14) === peg$c34) { - s0 = peg$c34; + if (input.substr(peg$currPos, 14) === peg$c35) { + s0 = peg$c35; peg$currPos += 14; } else { s0 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e39); } + if (peg$silentFails === 0) { peg$fail(peg$e40); } } if (s0 === peg$FAILED) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 15); - if (s1.toLowerCase() === peg$c35) { + if (s1.toLowerCase() === peg$c36) { peg$currPos += 15; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e40); } + if (peg$silentFails === 0) { peg$fail(peg$e41); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f30(); + s1 = peg$f31(); } s0 = s1; } @@ -2058,25 +2084,25 @@ function peg$parse(input, options) { function peg$parsewithdrawalStatus() { var s0, s1; - if (input.substr(peg$currPos, 16) === peg$c36) { - s0 = peg$c36; + if (input.substr(peg$currPos, 16) === peg$c37) { + s0 = peg$c37; peg$currPos += 16; } else { s0 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e41); } + if (peg$silentFails === 0) { peg$fail(peg$e42); } } if (s0 === peg$FAILED) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 17); - if (s1.toLowerCase() === peg$c37) { + if (s1.toLowerCase() === peg$c38) { peg$currPos += 17; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e42); } + if (peg$silentFails === 0) { peg$fail(peg$e43); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f31(); + s1 = peg$f32(); } s0 = s1; } @@ -2087,25 +2113,25 @@ function peg$parse(input, options) { function peg$parsepaidStatus() { var s0, s1; - if (input.substr(peg$currPos, 10) === peg$c38) { - s0 = peg$c38; + if (input.substr(peg$currPos, 10) === peg$c39) { + s0 = peg$c39; peg$currPos += 10; } else { s0 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e43); } + if (peg$silentFails === 0) { peg$fail(peg$e44); } } if (s0 === peg$FAILED) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 11); - if (s1.toLowerCase() === peg$c39) { + if (s1.toLowerCase() === peg$c40) { peg$currPos += 11; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e44); } + if (peg$silentFails === 0) { peg$fail(peg$e45); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f32(); + s1 = peg$f33(); } s0 = s1; } @@ -2117,24 +2143,24 @@ function peg$parse(input, options) { var s0, s1; s0 = input.substr(peg$currPos, 12); - if (s0.toLowerCase() === peg$c40) { + if (s0.toLowerCase() === peg$c41) { peg$currPos += 12; } else { s0 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e45); } + if (peg$silentFails === 0) { peg$fail(peg$e46); } } if (s0 === peg$FAILED) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 13); - if (s1.toLowerCase() === peg$c41) { + if (s1.toLowerCase() === peg$c42) { peg$currPos += 13; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e46); } + if (peg$silentFails === 0) { peg$fail(peg$e47); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f33(); + s1 = peg$f34(); } s0 = s1; } @@ -2147,15 +2173,15 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 8); - if (s1.toLowerCase() === peg$c42) { + if (s1.toLowerCase() === peg$c43) { peg$currPos += 8; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e47); } + if (peg$silentFails === 0) { peg$fail(peg$e48); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f34(); + s1 = peg$f35(); } s0 = s1; @@ -2167,15 +2193,15 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 12); - if (s1.toLowerCase() === peg$c43) { + if (s1.toLowerCase() === peg$c44) { peg$currPos += 12; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e48); } + if (peg$silentFails === 0) { peg$fail(peg$e49); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f35(); + s1 = peg$f36(); } s0 = s1; @@ -2187,15 +2213,15 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 4); - if (s1.toLowerCase() === peg$c44) { + if (s1.toLowerCase() === peg$c45) { peg$currPos += 4; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e49); } + if (peg$silentFails === 0) { peg$fail(peg$e50); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f36(); + s1 = peg$f37(); } s0 = s1; @@ -2207,15 +2233,15 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 6); - if (s1.toLowerCase() === peg$c45) { + if (s1.toLowerCase() === peg$c46) { peg$currPos += 6; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e50); } + if (peg$silentFails === 0) { peg$fail(peg$e51); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f37(); + s1 = peg$f38(); } s0 = s1; @@ -2225,25 +2251,25 @@ function peg$parse(input, options) { function peg$parsesortBy() { var s0, s1; - if (input.substr(peg$currPos, 6) === peg$c46) { - s0 = peg$c46; + if (input.substr(peg$currPos, 6) === peg$c47) { + s0 = peg$c47; peg$currPos += 6; } else { s0 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e51); } + if (peg$silentFails === 0) { peg$fail(peg$e52); } } if (s0 === peg$FAILED) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 7); - if (s1.toLowerCase() === peg$c47) { + if (s1.toLowerCase() === peg$c48) { peg$currPos += 7; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e52); } + if (peg$silentFails === 0) { peg$fail(peg$e53); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f38(); + s1 = peg$f39(); } s0 = s1; } @@ -2254,25 +2280,25 @@ function peg$parse(input, options) { function peg$parsesortOrder() { var s0, s1; - if (input.substr(peg$currPos, 9) === peg$c48) { - s0 = peg$c48; + if (input.substr(peg$currPos, 9) === peg$c49) { + s0 = peg$c49; peg$currPos += 9; } else { s0 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e53); } + if (peg$silentFails === 0) { peg$fail(peg$e54); } } if (s0 === peg$FAILED) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 10); - if (s1.toLowerCase() === peg$c49) { + if (s1.toLowerCase() === peg$c50) { peg$currPos += 10; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e54); } + if (peg$silentFails === 0) { peg$fail(peg$e55); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f39(); + s1 = peg$f40(); } s0 = s1; } @@ -2283,25 +2309,25 @@ function peg$parse(input, options) { function peg$parsepolicyID() { var s0, s1; - if (input.substr(peg$currPos, 8) === peg$c50) { - s0 = peg$c50; + if (input.substr(peg$currPos, 8) === peg$c51) { + s0 = peg$c51; peg$currPos += 8; } else { s0 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e55); } + if (peg$silentFails === 0) { peg$fail(peg$e56); } } if (s0 === peg$FAILED) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 9); - if (s1.toLowerCase() === peg$c51) { + if (s1.toLowerCase() === peg$c52) { peg$currPos += 9; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e56); } + if (peg$silentFails === 0) { peg$fail(peg$e57); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f40(); + s1 = peg$f41(); } s0 = s1; } @@ -2314,15 +2340,15 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 9); - if (s1.toLowerCase() === peg$c52) { + if (s1.toLowerCase() === peg$c53) { peg$currPos += 9; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e57); } + if (peg$silentFails === 0) { peg$fail(peg$e58); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f41(); + s1 = peg$f42(); } s0 = s1; @@ -2334,15 +2360,15 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 8); - if (s1.toLowerCase() === peg$c53) { + if (s1.toLowerCase() === peg$c54) { peg$currPos += 8; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e58); } + if (peg$silentFails === 0) { peg$fail(peg$e59); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f42(); + s1 = peg$f43(); } s0 = s1; @@ -2354,15 +2380,15 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 4); - if (s1.toLowerCase() === peg$c54) { + if (s1.toLowerCase() === peg$c55) { peg$currPos += 4; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e59); } + if (peg$silentFails === 0) { peg$fail(peg$e60); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f43(); + s1 = peg$f44(); } s0 = s1; @@ -2374,15 +2400,15 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 8); - if (s1.toLowerCase() === peg$c55) { + if (s1.toLowerCase() === peg$c56) { peg$currPos += 8; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e60); } + if (peg$silentFails === 0) { peg$fail(peg$e61); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f44(); + s1 = peg$f45(); } s0 = s1; @@ -2394,15 +2420,15 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 6); - if (s1.toLowerCase() === peg$c56) { + if (s1.toLowerCase() === peg$c57) { peg$currPos += 6; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e61); } + if (peg$silentFails === 0) { peg$fail(peg$e62); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f45(); + s1 = peg$f46(); } s0 = s1; @@ -2414,15 +2440,15 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 9); - if (s1.toLowerCase() === peg$c57) { + if (s1.toLowerCase() === peg$c58) { peg$currPos += 9; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e62); } + if (peg$silentFails === 0) { peg$fail(peg$e63); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f46(); + s1 = peg$f47(); } s0 = s1; @@ -2433,24 +2459,24 @@ function peg$parse(input, options) { var s0, s1; s0 = input.substr(peg$currPos, 7); - if (s0.toLowerCase() === peg$c58) { + if (s0.toLowerCase() === peg$c59) { peg$currPos += 7; } else { s0 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e63); } + if (peg$silentFails === 0) { peg$fail(peg$e64); } } if (s0 === peg$FAILED) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 8); - if (s1.toLowerCase() === peg$c59) { + if (s1.toLowerCase() === peg$c60) { peg$currPos += 8; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e64); } + if (peg$silentFails === 0) { peg$fail(peg$e65); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f47(); + s1 = peg$f48(); } s0 = s1; } @@ -2463,15 +2489,15 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 5); - if (s1.toLowerCase() === peg$c60) { + if (s1.toLowerCase() === peg$c61) { peg$currPos += 5; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e65); } + if (peg$silentFails === 0) { peg$fail(peg$e66); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f48(); + s1 = peg$f49(); } s0 = s1; @@ -2483,15 +2509,15 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 4); - if (s1.toLowerCase() === peg$c61) { + if (s1.toLowerCase() === peg$c62) { peg$currPos += 4; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e66); } + if (peg$silentFails === 0) { peg$fail(peg$e67); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f49(); + s1 = peg$f50(); } s0 = s1; @@ -2503,15 +2529,15 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 5); - if (s1.toLowerCase() === peg$c62) { + if (s1.toLowerCase() === peg$c63) { peg$currPos += 5; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e67); } + if (peg$silentFails === 0) { peg$fail(peg$e68); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f50(); + s1 = peg$f51(); } s0 = s1; @@ -2522,24 +2548,24 @@ function peg$parse(input, options) { var s0, s1; s0 = input.substr(peg$currPos, 15); - if (s0.toLowerCase() === peg$c63) { + if (s0.toLowerCase() === peg$c64) { peg$currPos += 15; } else { s0 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e68); } + if (peg$silentFails === 0) { peg$fail(peg$e69); } } if (s0 === peg$FAILED) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 17); - if (s1.toLowerCase() === peg$c64) { + if (s1.toLowerCase() === peg$c65) { peg$currPos += 17; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e69); } + if (peg$silentFails === 0) { peg$fail(peg$e70); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f51(); + s1 = peg$f52(); } s0 = s1; } @@ -2551,24 +2577,24 @@ function peg$parse(input, options) { var s0, s1; s0 = input.substr(peg$currPos, 18); - if (s0.toLowerCase() === peg$c65) { + if (s0.toLowerCase() === peg$c66) { peg$currPos += 18; } else { s0 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e70); } + if (peg$silentFails === 0) { peg$fail(peg$e71); } } if (s0 === peg$FAILED) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 20); - if (s1.toLowerCase() === peg$c66) { + if (s1.toLowerCase() === peg$c67) { peg$currPos += 20; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e71); } + if (peg$silentFails === 0) { peg$fail(peg$e72); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f52(); + s1 = peg$f53(); } s0 = s1; } @@ -2580,24 +2606,24 @@ function peg$parse(input, options) { var s0, s1; s0 = input.substr(peg$currPos, 16); - if (s0.toLowerCase() === peg$c67) { + if (s0.toLowerCase() === peg$c68) { peg$currPos += 16; } else { s0 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e72); } + if (peg$silentFails === 0) { peg$fail(peg$e73); } } if (s0 === peg$FAILED) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 18); - if (s1.toLowerCase() === peg$c68) { + if (s1.toLowerCase() === peg$c69) { peg$currPos += 18; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e73); } + if (peg$silentFails === 0) { peg$fail(peg$e74); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f53(); + s1 = peg$f54(); } s0 = s1; } @@ -2610,15 +2636,15 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 8); - if (s1.toLowerCase() === peg$c69) { + if (s1.toLowerCase() === peg$c70) { peg$currPos += 8; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e74); } + if (peg$silentFails === 0) { peg$fail(peg$e75); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f54(); + s1 = peg$f55(); } s0 = s1; @@ -2629,24 +2655,24 @@ function peg$parse(input, options) { var s0, s1; s0 = input.substr(peg$currPos, 9); - if (s0.toLowerCase() === peg$c70) { + if (s0.toLowerCase() === peg$c71) { peg$currPos += 9; } else { s0 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e75); } + if (peg$silentFails === 0) { peg$fail(peg$e76); } } if (s0 === peg$FAILED) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 10); - if (s1.toLowerCase() === peg$c71) { + if (s1.toLowerCase() === peg$c72) { peg$currPos += 10; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e76); } + if (peg$silentFails === 0) { peg$fail(peg$e77); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f55(); + s1 = peg$f56(); } s0 = s1; } @@ -2659,15 +2685,15 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 6); - if (s1.toLowerCase() === peg$c72) { + if (s1.toLowerCase() === peg$c73) { peg$currPos += 6; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e77); } + if (peg$silentFails === 0) { peg$fail(peg$e78); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f56(); + s1 = peg$f57(); } s0 = s1; @@ -2679,15 +2705,15 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 5); - if (s1.toLowerCase() === peg$c73) { + if (s1.toLowerCase() === peg$c74) { peg$currPos += 5; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e78); } + if (peg$silentFails === 0) { peg$fail(peg$e79); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f57(); + s1 = peg$f58(); } s0 = s1; @@ -2699,15 +2725,15 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 3); - if (s1.toLowerCase() === peg$c74) { + if (s1.toLowerCase() === peg$c75) { peg$currPos += 3; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e79); } + if (peg$silentFails === 0) { peg$fail(peg$e80); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f58(); + s1 = peg$f59(); } s0 = s1; @@ -2719,15 +2745,15 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 2); - if (s1.toLowerCase() === peg$c75) { + if (s1.toLowerCase() === peg$c76) { peg$currPos += 2; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e80); } + if (peg$silentFails === 0) { peg$fail(peg$e81); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f59(); + s1 = peg$f60(); } s0 = s1; @@ -2738,24 +2764,24 @@ function peg$parse(input, options) { var s0, s1; s0 = input.substr(peg$currPos, 14); - if (s0.toLowerCase() === peg$c76) { + if (s0.toLowerCase() === peg$c77) { peg$currPos += 14; } else { s0 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e81); } + if (peg$silentFails === 0) { peg$fail(peg$e82); } } if (s0 === peg$FAILED) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 15); - if (s1.toLowerCase() === peg$c77) { + if (s1.toLowerCase() === peg$c78) { peg$currPos += 15; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e82); } + if (peg$silentFails === 0) { peg$fail(peg$e83); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f60(); + s1 = peg$f61(); } s0 = s1; } @@ -2767,24 +2793,24 @@ function peg$parse(input, options) { var s0, s1; s0 = input.substr(peg$currPos, 16); - if (s0.toLowerCase() === peg$c78) { + if (s0.toLowerCase() === peg$c79) { peg$currPos += 16; } else { s0 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e83); } + if (peg$silentFails === 0) { peg$fail(peg$e84); } } if (s0 === peg$FAILED) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 17); - if (s1.toLowerCase() === peg$c79) { + if (s1.toLowerCase() === peg$c80) { peg$currPos += 17; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e84); } + if (peg$silentFails === 0) { peg$fail(peg$e85); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f61(); + s1 = peg$f62(); } s0 = s1; } @@ -2796,24 +2822,24 @@ function peg$parse(input, options) { var s0, s1; s0 = input.substr(peg$currPos, 13); - if (s0.toLowerCase() === peg$c80) { + if (s0.toLowerCase() === peg$c81) { peg$currPos += 13; } else { s0 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e85); } + if (peg$silentFails === 0) { peg$fail(peg$e86); } } if (s0 === peg$FAILED) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 14); - if (s1.toLowerCase() === peg$c81) { + if (s1.toLowerCase() === peg$c82) { peg$currPos += 14; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e86); } + if (peg$silentFails === 0) { peg$fail(peg$e87); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f62(); + s1 = peg$f63(); } s0 = s1; } @@ -2825,24 +2851,24 @@ function peg$parse(input, options) { var s0, s1; s0 = input.substr(peg$currPos, 16); - if (s0.toLowerCase() === peg$c82) { + if (s0.toLowerCase() === peg$c83) { peg$currPos += 16; } else { s0 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e87); } + if (peg$silentFails === 0) { peg$fail(peg$e88); } } if (s0 === peg$FAILED) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 17); - if (s1.toLowerCase() === peg$c83) { + if (s1.toLowerCase() === peg$c84) { peg$currPos += 17; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e88); } + if (peg$silentFails === 0) { peg$fail(peg$e89); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f63(); + s1 = peg$f64(); } s0 = s1; } @@ -2855,15 +2881,15 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 7); - if (s1.toLowerCase() === peg$c84) { + if (s1.toLowerCase() === peg$c85) { peg$currPos += 7; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e89); } + if (peg$silentFails === 0) { peg$fail(peg$e90); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f64(); + s1 = peg$f65(); } s0 = s1; @@ -2875,15 +2901,15 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 4); - if (s1.toLowerCase() === peg$c85) { + if (s1.toLowerCase() === peg$c86) { peg$currPos += 4; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e90); } + if (peg$silentFails === 0) { peg$fail(peg$e91); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f65(); + s1 = peg$f66(); } s0 = s1; @@ -2895,7 +2921,7 @@ function peg$parse(input, options) { s0 = peg$currPos; peg$savedPos = peg$currPos; - s1 = peg$f66(); + s1 = peg$f67(); if (s1) { s1 = undefined; } else { @@ -3027,11 +3053,11 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 8); - if (s1.toLowerCase() === peg$c86) { + if (s1.toLowerCase() === peg$c87) { peg$currPos += 8; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e91); } + if (peg$silentFails === 0) { peg$fail(peg$e92); } } if (s1 !== peg$FAILED) { s2 = peg$currPos; @@ -3046,7 +3072,7 @@ function peg$parse(input, options) { } if (s2 !== peg$FAILED) { peg$savedPos = s0; - s0 = peg$f67(); + s0 = peg$f68(); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -3064,19 +3090,19 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 6); - if (s1.toLowerCase() === peg$c87) { + if (s1.toLowerCase() === peg$c88) { peg$currPos += 6; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e92); } + if (peg$silentFails === 0) { peg$fail(peg$e93); } } if (s1 === peg$FAILED) { s1 = input.substr(peg$currPos, 5); - if (s1.toLowerCase() === peg$c88) { + if (s1.toLowerCase() === peg$c89) { peg$currPos += 5; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e93); } + if (peg$silentFails === 0) { peg$fail(peg$e94); } } } if (s1 !== peg$FAILED) { @@ -3092,7 +3118,7 @@ function peg$parse(input, options) { } if (s2 !== peg$FAILED) { peg$savedPos = s0; - s0 = peg$f68(); + s0 = peg$f69(); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -3110,11 +3136,11 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 15); - if (s1.toLowerCase() === peg$c77) { + if (s1.toLowerCase() === peg$c78) { peg$currPos += 15; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e82); } + if (peg$silentFails === 0) { peg$fail(peg$e83); } } if (s1 !== peg$FAILED) { s2 = peg$currPos; @@ -3129,7 +3155,7 @@ function peg$parse(input, options) { } if (s2 !== peg$FAILED) { peg$savedPos = s0; - s0 = peg$f69(); + s0 = peg$f70(); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -3147,11 +3173,11 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 3); - if (s1.toLowerCase() === peg$c89) { + if (s1.toLowerCase() === peg$c90) { peg$currPos += 3; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e94); } + if (peg$silentFails === 0) { peg$fail(peg$e95); } } if (s1 !== peg$FAILED) { s2 = peg$currPos; @@ -3166,7 +3192,7 @@ function peg$parse(input, options) { } if (s2 !== peg$FAILED) { peg$savedPos = s0; - s0 = peg$f70(); + s0 = peg$f71(); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -3184,11 +3210,11 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 8); - if (s1.toLowerCase() === peg$c23) { + if (s1.toLowerCase() === peg$c24) { peg$currPos += 8; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e28); } + if (peg$silentFails === 0) { peg$fail(peg$e29); } } if (s1 !== peg$FAILED) { s2 = peg$currPos; @@ -3203,7 +3229,7 @@ function peg$parse(input, options) { } if (s2 !== peg$FAILED) { peg$savedPos = s0; - s0 = peg$f71(); + s0 = peg$f72(); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -3221,11 +3247,11 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 11); - if (s1.toLowerCase() === peg$c90) { + if (s1.toLowerCase() === peg$c91) { peg$currPos += 11; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e95); } + if (peg$silentFails === 0) { peg$fail(peg$e96); } } if (s1 !== peg$FAILED) { s2 = peg$currPos; @@ -3240,7 +3266,7 @@ function peg$parse(input, options) { } if (s2 !== peg$FAILED) { peg$savedPos = s0; - s0 = peg$f72(); + s0 = peg$f73(); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -3258,11 +3284,11 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 13); - if (s1.toLowerCase() === peg$c41) { + if (s1.toLowerCase() === peg$c42) { peg$currPos += 13; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e46); } + if (peg$silentFails === 0) { peg$fail(peg$e47); } } if (s1 !== peg$FAILED) { s2 = peg$currPos; @@ -3277,7 +3303,7 @@ function peg$parse(input, options) { } if (s2 !== peg$FAILED) { peg$savedPos = s0; - s0 = peg$f73(); + s0 = peg$f74(); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -3295,11 +3321,11 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 12); - if (s1.toLowerCase() === peg$c27) { + if (s1.toLowerCase() === peg$c28) { peg$currPos += 12; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e32); } + if (peg$silentFails === 0) { peg$fail(peg$e33); } } if (s1 !== peg$FAILED) { s2 = peg$currPos; @@ -3314,7 +3340,7 @@ function peg$parse(input, options) { } if (s2 !== peg$FAILED) { peg$savedPos = s0; - s0 = peg$f74(); + s0 = peg$f75(); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -3332,11 +3358,11 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 14); - if (s1.toLowerCase() === peg$c91) { + if (s1.toLowerCase() === peg$c92) { peg$currPos += 14; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e96); } + if (peg$silentFails === 0) { peg$fail(peg$e97); } } if (s1 !== peg$FAILED) { s2 = peg$currPos; @@ -3351,7 +3377,7 @@ function peg$parse(input, options) { } if (s2 !== peg$FAILED) { peg$savedPos = s0; - s0 = peg$f75(); + s0 = peg$f76(); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -3388,7 +3414,7 @@ function peg$parse(input, options) { } if (s2 !== peg$FAILED) { peg$savedPos = s0; - s0 = peg$f76(); + s0 = peg$f77(); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -3406,11 +3432,11 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 11); - if (s1.toLowerCase() === peg$c92) { + if (s1.toLowerCase() === peg$c93) { peg$currPos += 11; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e97); } + if (peg$silentFails === 0) { peg$fail(peg$e98); } } if (s1 !== peg$FAILED) { s2 = peg$currPos; @@ -3425,7 +3451,7 @@ function peg$parse(input, options) { } if (s2 !== peg$FAILED) { peg$savedPos = s0; - s0 = peg$f77(); + s0 = peg$f78(); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -3450,7 +3476,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e98); } + if (peg$silentFails === 0) { peg$fail(peg$e99); } } if (s2 !== peg$FAILED) { s1 = [s1, s2]; @@ -3469,11 +3495,11 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 10); - if (s1.toLowerCase() === peg$c93) { + if (s1.toLowerCase() === peg$c94) { peg$currPos += 10; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e99); } + if (peg$silentFails === 0) { peg$fail(peg$e100); } } if (s1 !== peg$FAILED) { s2 = peg$currPos; @@ -3488,7 +3514,7 @@ function peg$parse(input, options) { } if (s2 !== peg$FAILED) { peg$savedPos = s0; - s0 = peg$f78(); + s0 = peg$f79(); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -3500,11 +3526,11 @@ function peg$parse(input, options) { if (s0 === peg$FAILED) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 11); - if (s1.toLowerCase() === peg$c92) { + if (s1.toLowerCase() === peg$c93) { peg$currPos += 11; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e97); } + if (peg$silentFails === 0) { peg$fail(peg$e98); } } if (s1 !== peg$FAILED) { s2 = peg$currPos; @@ -3519,7 +3545,7 @@ function peg$parse(input, options) { } if (s2 !== peg$FAILED) { peg$savedPos = s0; - s0 = peg$f79(); + s0 = peg$f80(); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -3538,11 +3564,11 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 13); - if (s1.toLowerCase() === peg$c94) { + if (s1.toLowerCase() === peg$c95) { peg$currPos += 13; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e100); } + if (peg$silentFails === 0) { peg$fail(peg$e101); } } if (s1 !== peg$FAILED) { s2 = peg$currPos; @@ -3557,7 +3583,7 @@ function peg$parse(input, options) { } if (s2 !== peg$FAILED) { peg$savedPos = s0; - s0 = peg$f80(); + s0 = peg$f81(); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -3575,11 +3601,11 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 18); - if (s1.toLowerCase() === peg$c95) { + if (s1.toLowerCase() === peg$c96) { peg$currPos += 18; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e101); } + if (peg$silentFails === 0) { peg$fail(peg$e102); } } if (s1 !== peg$FAILED) { s2 = peg$currPos; @@ -3594,7 +3620,7 @@ function peg$parse(input, options) { } if (s2 !== peg$FAILED) { peg$savedPos = s0; - s0 = peg$f81(); + s0 = peg$f82(); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -3612,11 +3638,11 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 22); - if (s1.toLowerCase() === peg$c96) { + if (s1.toLowerCase() === peg$c97) { peg$currPos += 22; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e102); } + if (peg$silentFails === 0) { peg$fail(peg$e103); } } if (s1 !== peg$FAILED) { s2 = peg$currPos; @@ -3631,7 +3657,7 @@ function peg$parse(input, options) { } if (s2 !== peg$FAILED) { peg$savedPos = s0; - s0 = peg$f82(); + s0 = peg$f83(); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -3649,11 +3675,11 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 10); - if (s1.toLowerCase() === peg$c97) { + if (s1.toLowerCase() === peg$c98) { peg$currPos += 10; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e103); } + if (peg$silentFails === 0) { peg$fail(peg$e104); } } if (s1 !== peg$FAILED) { s2 = peg$currPos; @@ -3668,7 +3694,7 @@ function peg$parse(input, options) { } if (s2 !== peg$FAILED) { peg$savedPos = s0; - s0 = peg$f83(); + s0 = peg$f84(); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -3686,11 +3712,11 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 14); - if (s1.toLowerCase() === peg$c98) { + if (s1.toLowerCase() === peg$c99) { peg$currPos += 14; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e104); } + if (peg$silentFails === 0) { peg$fail(peg$e105); } } if (s1 !== peg$FAILED) { s2 = peg$currPos; @@ -3705,7 +3731,7 @@ function peg$parse(input, options) { } if (s2 !== peg$FAILED) { peg$savedPos = s0; - s0 = peg$f84(); + s0 = peg$f85(); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -3723,11 +3749,11 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 11); - if (s1.toLowerCase() === peg$c99) { + if (s1.toLowerCase() === peg$c100) { peg$currPos += 11; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e105); } + if (peg$silentFails === 0) { peg$fail(peg$e106); } } if (s1 !== peg$FAILED) { s2 = peg$currPos; @@ -3742,7 +3768,7 @@ function peg$parse(input, options) { } if (s2 !== peg$FAILED) { peg$savedPos = s0; - s0 = peg$f85(); + s0 = peg$f86(); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -3760,11 +3786,11 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 10); - if (s1.toLowerCase() === peg$c100) { + if (s1.toLowerCase() === peg$c101) { peg$currPos += 10; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e106); } + if (peg$silentFails === 0) { peg$fail(peg$e107); } } if (s1 !== peg$FAILED) { s2 = peg$currPos; @@ -3779,7 +3805,7 @@ function peg$parse(input, options) { } if (s2 !== peg$FAILED) { peg$savedPos = s0; - s0 = peg$f86(); + s0 = peg$f87(); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -3797,11 +3823,11 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 10); - if (s1.toLowerCase() === peg$c101) { + if (s1.toLowerCase() === peg$c102) { peg$currPos += 10; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e107); } + if (peg$silentFails === 0) { peg$fail(peg$e108); } } if (s1 !== peg$FAILED) { s2 = peg$currPos; @@ -3816,7 +3842,7 @@ function peg$parse(input, options) { } if (s2 !== peg$FAILED) { peg$savedPos = s0; - s0 = peg$f87(); + s0 = peg$f88(); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -3834,11 +3860,11 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 18); - if (s1.toLowerCase() === peg$c102) { + if (s1.toLowerCase() === peg$c103) { peg$currPos += 18; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e108); } + if (peg$silentFails === 0) { peg$fail(peg$e109); } } if (s1 !== peg$FAILED) { s2 = peg$currPos; @@ -3853,7 +3879,7 @@ function peg$parse(input, options) { } if (s2 !== peg$FAILED) { peg$savedPos = s0; - s0 = peg$f88(); + s0 = peg$f89(); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -3871,11 +3897,11 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 15); - if (s1.toLowerCase() === peg$c103) { + if (s1.toLowerCase() === peg$c104) { peg$currPos += 15; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e109); } + if (peg$silentFails === 0) { peg$fail(peg$e110); } } if (s1 !== peg$FAILED) { s2 = peg$currPos; @@ -3890,7 +3916,7 @@ function peg$parse(input, options) { } if (s2 !== peg$FAILED) { peg$savedPos = s0; - s0 = peg$f89(); + s0 = peg$f90(); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -3908,11 +3934,11 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 19); - if (s1.toLowerCase() === peg$c104) { + if (s1.toLowerCase() === peg$c105) { peg$currPos += 19; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e110); } + if (peg$silentFails === 0) { peg$fail(peg$e111); } } if (s1 !== peg$FAILED) { s2 = peg$currPos; @@ -3927,7 +3953,7 @@ function peg$parse(input, options) { } if (s2 !== peg$FAILED) { peg$savedPos = s0; - s0 = peg$f90(); + s0 = peg$f91(); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -3945,11 +3971,11 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 20); - if (s1.toLowerCase() === peg$c105) { + if (s1.toLowerCase() === peg$c106) { peg$currPos += 20; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e111); } + if (peg$silentFails === 0) { peg$fail(peg$e112); } } if (s1 !== peg$FAILED) { s2 = peg$currPos; @@ -3964,7 +3990,7 @@ function peg$parse(input, options) { } if (s2 !== peg$FAILED) { peg$savedPos = s0; - s0 = peg$f91(); + s0 = peg$f92(); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -3982,11 +4008,11 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 23); - if (s1.toLowerCase() === peg$c106) { + if (s1.toLowerCase() === peg$c107) { peg$currPos += 23; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e112); } + if (peg$silentFails === 0) { peg$fail(peg$e113); } } if (s1 !== peg$FAILED) { s2 = peg$currPos; @@ -4001,7 +4027,7 @@ function peg$parse(input, options) { } if (s2 !== peg$FAILED) { peg$savedPos = s0; - s0 = peg$f92(); + s0 = peg$f93(); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -4019,11 +4045,11 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 14); - if (s1.toLowerCase() === peg$c81) { + if (s1.toLowerCase() === peg$c82) { peg$currPos += 14; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e86); } + if (peg$silentFails === 0) { peg$fail(peg$e87); } } if (s1 !== peg$FAILED) { s2 = peg$currPos; @@ -4038,7 +4064,7 @@ function peg$parse(input, options) { } if (s2 !== peg$FAILED) { peg$savedPos = s0; - s0 = peg$f93(); + s0 = peg$f94(); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -4056,11 +4082,11 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 17); - if (s1.toLowerCase() === peg$c83) { + if (s1.toLowerCase() === peg$c84) { peg$currPos += 17; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e88); } + if (peg$silentFails === 0) { peg$fail(peg$e89); } } if (s1 !== peg$FAILED) { s2 = peg$currPos; @@ -4075,7 +4101,7 @@ function peg$parse(input, options) { } if (s2 !== peg$FAILED) { peg$savedPos = s0; - s0 = peg$f94(); + s0 = peg$f95(); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -4093,11 +4119,11 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 14); - if (s1.toLowerCase() === peg$c107) { + if (s1.toLowerCase() === peg$c108) { peg$currPos += 14; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e113); } + if (peg$silentFails === 0) { peg$fail(peg$e114); } } if (s1 !== peg$FAILED) { s2 = peg$currPos; @@ -4112,7 +4138,7 @@ function peg$parse(input, options) { } if (s2 !== peg$FAILED) { peg$savedPos = s0; - s0 = peg$f95(); + s0 = peg$f96(); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -4130,11 +4156,11 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 9); - if (s1.toLowerCase() === peg$c108) { + if (s1.toLowerCase() === peg$c109) { peg$currPos += 9; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e114); } + if (peg$silentFails === 0) { peg$fail(peg$e115); } } if (s1 !== peg$FAILED) { s2 = peg$currPos; @@ -4149,7 +4175,7 @@ function peg$parse(input, options) { } if (s2 !== peg$FAILED) { peg$savedPos = s0; - s0 = peg$f96(); + s0 = peg$f97(); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -4167,11 +4193,11 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 14); - if (s1.toLowerCase() === peg$c109) { + if (s1.toLowerCase() === peg$c110) { peg$currPos += 14; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e115); } + if (peg$silentFails === 0) { peg$fail(peg$e116); } } if (s1 !== peg$FAILED) { s2 = peg$currPos; @@ -4186,7 +4212,7 @@ function peg$parse(input, options) { } if (s2 !== peg$FAILED) { peg$savedPos = s0; - s0 = peg$f97(); + s0 = peg$f98(); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -4204,11 +4230,11 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 11); - if (s1.toLowerCase() === peg$c110) { + if (s1.toLowerCase() === peg$c111) { peg$currPos += 11; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e116); } + if (peg$silentFails === 0) { peg$fail(peg$e117); } } if (s1 !== peg$FAILED) { s2 = peg$currPos; @@ -4223,7 +4249,7 @@ function peg$parse(input, options) { } if (s2 !== peg$FAILED) { peg$savedPos = s0; - s0 = peg$f98(); + s0 = peg$f99(); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -4241,11 +4267,11 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 10); - if (s1.toLowerCase() === peg$c111) { + if (s1.toLowerCase() === peg$c112) { peg$currPos += 10; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e117); } + if (peg$silentFails === 0) { peg$fail(peg$e118); } } if (s1 !== peg$FAILED) { s2 = peg$currPos; @@ -4260,7 +4286,7 @@ function peg$parse(input, options) { } if (s2 !== peg$FAILED) { peg$savedPos = s0; - s0 = peg$f99(); + s0 = peg$f100(); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -4278,11 +4304,11 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 10); - if (s1.toLowerCase() === peg$c112) { + if (s1.toLowerCase() === peg$c113) { peg$currPos += 10; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e118); } + if (peg$silentFails === 0) { peg$fail(peg$e119); } } if (s1 !== peg$FAILED) { s2 = peg$currPos; @@ -4297,7 +4323,7 @@ function peg$parse(input, options) { } if (s2 !== peg$FAILED) { peg$savedPos = s0; - s0 = peg$f100(); + s0 = peg$f101(); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -4315,11 +4341,11 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = input.substr(peg$currPos, 13); - if (s1.toLowerCase() === peg$c113) { + if (s1.toLowerCase() === peg$c114) { peg$currPos += 13; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e119); } + if (peg$silentFails === 0) { peg$fail(peg$e120); } } if (s1 !== peg$FAILED) { s2 = peg$currPos; @@ -4334,7 +4360,7 @@ function peg$parse(input, options) { } if (s2 !== peg$FAILED) { peg$savedPos = s0; - s0 = peg$f101(); + s0 = peg$f102(); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -4357,81 +4383,81 @@ function peg$parse(input, options) { peg$currPos++; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e98); } + if (peg$silentFails === 0) { peg$fail(peg$e99); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f102(); + s1 = peg$f103(); } s0 = s1; if (s0 === peg$FAILED) { s0 = peg$currPos; - if (input.substr(peg$currPos, 2) === peg$c114) { - s1 = peg$c114; + if (input.substr(peg$currPos, 2) === peg$c115) { + s1 = peg$c115; peg$currPos += 2; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e121); } + if (peg$silentFails === 0) { peg$fail(peg$e122); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f103(); + s1 = peg$f104(); } s0 = s1; if (s0 === peg$FAILED) { s0 = peg$currPos; - if (input.substr(peg$currPos, 2) === peg$c115) { - s1 = peg$c115; + if (input.substr(peg$currPos, 2) === peg$c116) { + s1 = peg$c116; peg$currPos += 2; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e122); } + if (peg$silentFails === 0) { peg$fail(peg$e123); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f104(); + s1 = peg$f105(); } s0 = s1; if (s0 === peg$FAILED) { s0 = peg$currPos; if (input.charCodeAt(peg$currPos) === 62) { - s1 = peg$c116; + s1 = peg$c117; peg$currPos++; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e123); } + if (peg$silentFails === 0) { peg$fail(peg$e124); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f105(); + s1 = peg$f106(); } s0 = s1; if (s0 === peg$FAILED) { s0 = peg$currPos; - if (input.substr(peg$currPos, 2) === peg$c117) { - s1 = peg$c117; + if (input.substr(peg$currPos, 2) === peg$c118) { + s1 = peg$c118; peg$currPos += 2; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e124); } + if (peg$silentFails === 0) { peg$fail(peg$e125); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f106(); + s1 = peg$f107(); } s0 = s1; if (s0 === peg$FAILED) { s0 = peg$currPos; if (input.charCodeAt(peg$currPos) === 60) { - s1 = peg$c118; + s1 = peg$c119; peg$currPos++; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e125); } + if (peg$silentFails === 0) { peg$fail(peg$e126); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f107(); + s1 = peg$f108(); } s0 = s1; } @@ -4442,7 +4468,7 @@ function peg$parse(input, options) { peg$silentFails--; if (s0 === peg$FAILED) { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e120); } + if (peg$silentFails === 0) { peg$fail(peg$e121); } } return s0; @@ -4455,7 +4481,7 @@ function peg$parse(input, options) { s1 = peg$parseoperator(); if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f108(s1); + s1 = peg$f109(s1); } s0 = s1; @@ -4467,11 +4493,11 @@ function peg$parse(input, options) { s0 = peg$currPos; if (input.charCodeAt(peg$currPos) === 92) { - s1 = peg$c119; + s1 = peg$c120; peg$currPos++; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e126); } + if (peg$silentFails === 0) { peg$fail(peg$e127); } } if (s1 !== peg$FAILED) { s2 = input.charAt(peg$currPos); @@ -4479,11 +4505,11 @@ function peg$parse(input, options) { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e127); } + if (peg$silentFails === 0) { peg$fail(peg$e128); } } if (s2 !== peg$FAILED) { peg$savedPos = s0; - s0 = peg$f109(s2); + s0 = peg$f110(s2); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -4509,7 +4535,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e129); } + if (peg$silentFails === 0) { peg$fail(peg$e130); } } } if (s2 !== peg$FAILED) { @@ -4522,7 +4548,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e129); } + if (peg$silentFails === 0) { peg$fail(peg$e130); } } } } @@ -4531,13 +4557,13 @@ function peg$parse(input, options) { } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f110(s1); + s1 = peg$f111(s1); } s0 = s1; peg$silentFails--; if (s0 === peg$FAILED) { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e128); } + if (peg$silentFails === 0) { peg$fail(peg$e129); } } return s0; @@ -4549,7 +4575,7 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = peg$parse_(); peg$savedPos = s0; - s1 = peg$f111(); + s1 = peg$f112(); s0 = s1; return s0; @@ -4565,7 +4591,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e131); } + if (peg$silentFails === 0) { peg$fail(peg$e132); } } while (s1 !== peg$FAILED) { s0.push(s1); @@ -4574,12 +4600,12 @@ function peg$parse(input, options) { peg$currPos++; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e131); } + if (peg$silentFails === 0) { peg$fail(peg$e132); } } } peg$silentFails--; s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e130); } + if (peg$silentFails === 0) { peg$fail(peg$e131); } return s0; } @@ -4589,7 +4615,7 @@ function peg$parse(input, options) { s0 = peg$currPos; peg$savedPos = peg$currPos; - s1 = peg$f112(); + s1 = peg$f113(); if (s1) { s1 = undefined; } else { @@ -4626,7 +4652,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e133); } + if (peg$silentFails === 0) { peg$fail(peg$e134); } } while (s2 !== peg$FAILED) { s1.push(s2); @@ -4635,7 +4661,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e133); } + if (peg$silentFails === 0) { peg$fail(peg$e134); } } } s2 = input.charAt(peg$currPos); @@ -4643,7 +4669,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e134); } + if (peg$silentFails === 0) { peg$fail(peg$e135); } } if (s2 !== peg$FAILED) { s3 = []; @@ -4654,7 +4680,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s4 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e135); } + if (peg$silentFails === 0) { peg$fail(peg$e136); } } } while (s4 !== peg$FAILED) { @@ -4666,7 +4692,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s4 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e135); } + if (peg$silentFails === 0) { peg$fail(peg$e136); } } } } @@ -4675,7 +4701,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s4 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e134); } + if (peg$silentFails === 0) { peg$fail(peg$e135); } } if (s4 !== peg$FAILED) { s5 = []; @@ -4684,7 +4710,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s6 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e129); } + if (peg$silentFails === 0) { peg$fail(peg$e130); } } while (s6 !== peg$FAILED) { s5.push(s6); @@ -4693,11 +4719,11 @@ function peg$parse(input, options) { peg$currPos++; } else { s6 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e129); } + if (peg$silentFails === 0) { peg$fail(peg$e130); } } } peg$savedPos = s0; - s0 = peg$f113(s1, s3, s5); + s0 = peg$f114(s1, s3, s5); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -4709,7 +4735,7 @@ function peg$parse(input, options) { peg$silentFails--; if (s0 === peg$FAILED) { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e132); } + if (peg$silentFails === 0) { peg$fail(peg$e133); } } return s0; @@ -4726,7 +4752,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e133); } + if (peg$silentFails === 0) { peg$fail(peg$e134); } } while (s2 !== peg$FAILED) { s1.push(s2); @@ -4735,7 +4761,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e133); } + if (peg$silentFails === 0) { peg$fail(peg$e134); } } } s2 = input.charAt(peg$currPos); @@ -4743,7 +4769,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e134); } + if (peg$silentFails === 0) { peg$fail(peg$e135); } } if (s2 !== peg$FAILED) { s3 = []; @@ -4754,7 +4780,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s4 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e135); } + if (peg$silentFails === 0) { peg$fail(peg$e136); } } if (s4 === peg$FAILED) { s4 = peg$currPos; @@ -4770,15 +4796,15 @@ function peg$parse(input, options) { } if (s5 !== peg$FAILED) { if (input.charCodeAt(peg$currPos) === 8220) { - s6 = peg$c120; + s6 = peg$c121; peg$currPos++; } else { s6 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e136); } + if (peg$silentFails === 0) { peg$fail(peg$e137); } } if (s6 !== peg$FAILED) { peg$savedPos = s4; - s4 = peg$f114(s1); + s4 = peg$f115(s1); } else { peg$currPos = s4; s4 = peg$FAILED; @@ -4801,15 +4827,15 @@ function peg$parse(input, options) { } if (s5 !== peg$FAILED) { if (input.charCodeAt(peg$currPos) === 8221) { - s6 = peg$c121; + s6 = peg$c122; peg$currPos++; } else { s6 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e137); } + if (peg$silentFails === 0) { peg$fail(peg$e138); } } if (s6 !== peg$FAILED) { peg$savedPos = s4; - s4 = peg$f115(s1); + s4 = peg$f116(s1); } else { peg$currPos = s4; s4 = peg$FAILED; @@ -4832,15 +4858,15 @@ function peg$parse(input, options) { } if (s5 !== peg$FAILED) { if (input.charCodeAt(peg$currPos) === 34) { - s6 = peg$c122; + s6 = peg$c123; peg$currPos++; } else { s6 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e138); } + if (peg$silentFails === 0) { peg$fail(peg$e139); } } if (s6 !== peg$FAILED) { peg$savedPos = s4; - s4 = peg$f116(s1); + s4 = peg$f117(s1); } else { peg$currPos = s4; s4 = peg$FAILED; @@ -4862,7 +4888,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s4 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e135); } + if (peg$silentFails === 0) { peg$fail(peg$e136); } } if (s4 === peg$FAILED) { s4 = peg$currPos; @@ -4878,15 +4904,15 @@ function peg$parse(input, options) { } if (s5 !== peg$FAILED) { if (input.charCodeAt(peg$currPos) === 8220) { - s6 = peg$c120; + s6 = peg$c121; peg$currPos++; } else { s6 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e136); } + if (peg$silentFails === 0) { peg$fail(peg$e137); } } if (s6 !== peg$FAILED) { peg$savedPos = s4; - s4 = peg$f114(s1); + s4 = peg$f115(s1); } else { peg$currPos = s4; s4 = peg$FAILED; @@ -4909,15 +4935,15 @@ function peg$parse(input, options) { } if (s5 !== peg$FAILED) { if (input.charCodeAt(peg$currPos) === 8221) { - s6 = peg$c121; + s6 = peg$c122; peg$currPos++; } else { s6 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e137); } + if (peg$silentFails === 0) { peg$fail(peg$e138); } } if (s6 !== peg$FAILED) { peg$savedPos = s4; - s4 = peg$f115(s1); + s4 = peg$f116(s1); } else { peg$currPos = s4; s4 = peg$FAILED; @@ -4940,15 +4966,15 @@ function peg$parse(input, options) { } if (s5 !== peg$FAILED) { if (input.charCodeAt(peg$currPos) === 34) { - s6 = peg$c122; + s6 = peg$c123; peg$currPos++; } else { s6 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e138); } + if (peg$silentFails === 0) { peg$fail(peg$e139); } } if (s6 !== peg$FAILED) { peg$savedPos = s4; - s4 = peg$f116(s1); + s4 = peg$f117(s1); } else { peg$currPos = s4; s4 = peg$FAILED; @@ -4965,7 +4991,7 @@ function peg$parse(input, options) { s4 = peg$parseclosingQuote(); if (s4 !== peg$FAILED) { peg$savedPos = s0; - s0 = peg$f117(s1, s3, s4); + s0 = peg$f118(s1, s3, s4); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -4977,7 +5003,7 @@ function peg$parse(input, options) { peg$silentFails--; if (s0 === peg$FAILED) { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e132); } + if (peg$silentFails === 0) { peg$fail(peg$e133); } } return s0; @@ -4992,7 +5018,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e134); } + if (peg$silentFails === 0) { peg$fail(peg$e135); } } if (s1 !== peg$FAILED) { s2 = peg$currPos; @@ -5030,7 +5056,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e139); } + if (peg$silentFails === 0) { peg$fail(peg$e140); } } while (s2 !== peg$FAILED) { s1.push(s2); @@ -5039,7 +5065,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e139); } + if (peg$silentFails === 0) { peg$fail(peg$e140); } } } s2 = []; @@ -5048,7 +5074,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s3 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e140); } + if (peg$silentFails === 0) { peg$fail(peg$e141); } } while (s3 !== peg$FAILED) { s2.push(s3); @@ -5057,7 +5083,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s3 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e140); } + if (peg$silentFails === 0) { peg$fail(peg$e141); } } } s3 = []; @@ -5066,7 +5092,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s4 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e141); } + if (peg$silentFails === 0) { peg$fail(peg$e142); } } while (s4 !== peg$FAILED) { s3.push(s4); @@ -5075,7 +5101,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s4 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e141); } + if (peg$silentFails === 0) { peg$fail(peg$e142); } } } s4 = peg$parseoperator(); @@ -5094,7 +5120,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e142); } + if (peg$silentFails === 0) { peg$fail(peg$e143); } } while (s2 !== peg$FAILED) { s1.push(s2); @@ -5103,7 +5129,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e142); } + if (peg$silentFails === 0) { peg$fail(peg$e143); } } } s2 = peg$currPos; @@ -5150,7 +5176,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s0 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e143); } + if (peg$silentFails === 0) { peg$fail(peg$e144); } } } } @@ -5166,7 +5192,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s0 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e144); } + if (peg$silentFails === 0) { peg$fail(peg$e145); } } if (s0 === peg$FAILED) { s0 = peg$currPos; diff --git a/src/libs/SearchParser/searchParser.peggy b/src/libs/SearchParser/searchParser.peggy index d8a0233f34bb..d0cf93147524 100644 --- a/src/libs/SearchParser/searchParser.peggy +++ b/src/libs/SearchParser/searchParser.peggy @@ -270,6 +270,7 @@ key "key" / groupCurrency / tag / category + / vendor / to / taxRate / cardID diff --git a/src/libs/SearchQueryUtils.ts b/src/libs/SearchQueryUtils.ts index 4beebe7150de..509dd093678d 100644 --- a/src/libs/SearchQueryUtils.ts +++ b/src/libs/SearchQueryUtils.ts @@ -1121,6 +1121,7 @@ function buildQueryStringFromFilterFormValues(filterValues: Partial uniqueCategories.has(name)) .concat(hasEmptyCategoriesInFilter ? [CONST.SEARCH.CATEGORY_EMPTY_VALUE] : []); } + if (filterKey === CONST.SEARCH.SYNTAX_FILTER_KEYS.VENDOR) { + // Vendor names are matched by text on the server and the synced vendor lists load lazily, so the typed values are kept as-is. + filtersForm[filterKey] = filterValues; + } if (filterKey === CONST.SEARCH.SYNTAX_FILTER_KEYS.KEYWORD) { filtersForm[filterKey] = filterValues ?.map((filter) => { diff --git a/src/libs/SearchUIUtils.ts b/src/libs/SearchUIUtils.ts index e17b013d49d4..e6a273bc25fa 100644 --- a/src/libs/SearchUIUtils.ts +++ b/src/libs/SearchUIUtils.ts @@ -319,6 +319,7 @@ const transactionColumnNamesToSortingProperty: TransactionSorting = { [CONST.SEARCH.TABLE_COLUMNS.EXPORTED]: 'exported' as const, [CONST.SEARCH.TABLE_COLUMNS.TAG]: 'tag' as const, [CONST.SEARCH.TABLE_COLUMNS.MERCHANT]: 'formattedMerchant' as const, + [CONST.SEARCH.TABLE_COLUMNS.VENDOR]: null, [CONST.SEARCH.TABLE_COLUMNS.TOTAL_AMOUNT]: 'formattedTotal' as const, [CONST.SEARCH.TABLE_COLUMNS.CATEGORY]: 'category' as const, [CONST.SEARCH.TABLE_COLUMNS.ORIGINAL_AMOUNT]: 'originalAmount' as const, @@ -4305,7 +4306,10 @@ function getCustomColumnDefault(value?: SearchDataTypes | SearchGroupBy): Search } } -function getSearchColumnTranslationKey(column: SearchSortBy): TranslationPaths { +/** + * Xero calls vendors suppliers, so the vendor column reads "Supplier" when every eligible workspace takes its vendors from Xero. + */ +function getSearchColumnTranslationKey(column: SearchSortBy, shouldUseSupplierLabel = false): TranslationPaths { switch (column) { case CONST.SEARCH.TABLE_COLUMNS.AVATAR: return 'common.avatar'; @@ -4327,6 +4331,8 @@ function getSearchColumnTranslationKey(column: SearchSortBy): TranslationPaths { return 'search.filters.exported'; case CONST.SEARCH.TABLE_COLUMNS.MERCHANT: return 'common.merchant'; + case CONST.SEARCH.TABLE_COLUMNS.VENDOR: + return shouldUseSupplierLabel ? 'common.supplier' : 'common.vendor'; case CONST.SEARCH.TABLE_COLUMNS.DESCRIPTION: return 'common.description'; case CONST.SEARCH.TABLE_COLUMNS.FROM: @@ -5499,6 +5505,10 @@ const FILTER_VIEW_MAP = { labelKey: 'common.tag', icon: 'Tag', }, + [CONST.SEARCH.SYNTAX_FILTER_KEYS.VENDOR]: { + labelKey: 'common.vendor', + icon: 'Building', + }, [CONST.SEARCH.SYNTAX_FILTER_KEYS.TAX_RATE]: { labelKey: 'workspace.taxes.taxRate', icon: 'Percent', @@ -5712,6 +5722,7 @@ function getDisplayValue( type: SearchDataTypes, translate: LocalizedTranslate, localeCompare: LocaleContextProps['localeCompare'], + shouldUseSupplierLabel = false, ) { if (key === FILTER_KEYS.TYPE) { const filterValue = form[key]; @@ -5733,6 +5744,13 @@ function getDisplayValue( .join(', '); } + if (key === FILTER_KEYS.VENDOR) { + return form[key] + ?.sort((a, b) => sortOptionsWithEmptyValue(a, b, localeCompare)) + .map((value) => (value === CONST.SEARCH.VENDOR_EMPTY_VALUE ? translate(shouldUseSupplierLabel ? 'search.noSupplier' : 'search.noVendor') : value)) + .join(', '); + } + if (key === FILTER_KEYS.CURRENCY || key === FILTER_KEYS.CURRENCY_NOT || key === FILTER_KEYS.PURCHASE_CURRENCY || key === FILTER_KEYS.PURCHASE_CURRENCY_NOT) { return form[key]?.sort(localeCompare).join(', '); } @@ -5918,6 +5936,16 @@ function isMappedFilterKey(key: string): key is MappedFilterKey { return hasKey(FILTER_VIEW_MAP, removeNegation(key)); } +/** + * Xero calls vendors suppliers, so the vendor filter reads "Supplier" when every eligible workspace takes its vendors from Xero. + */ +function getSearchFilterLabelKey(filterKey: SearchFilter['key'], shouldUseSupplierLabel = false): TranslationPaths { + if (filterKey === CONST.SEARCH.SYNTAX_FILTER_KEYS.VENDOR && shouldUseSupplierLabel) { + return 'common.supplier'; + } + return FILTER_VIEW_MAP[filterKey].labelKey; +} + function mapFiltersFormToLabelValueList( searchAdvancedFiltersForm: Partial, defaultSearchQueryFilterKeys: Set, @@ -5926,6 +5954,8 @@ function mapFiltersFormToLabelValueList( dateFnsLocale: DateFnsLocale | undefined, localeCompare: LocaleContextProps['localeCompare'], convertToDisplayStringWithoutCurrency: CurrencyListActionsContextType['convertToDisplayStringWithoutCurrency'], + mapper?: undefined, + shouldUseSupplierLabel?: boolean, ): SearchFilter[]; function mapFiltersFormToLabelValueList>( searchAdvancedFiltersForm: Partial, @@ -5936,6 +5966,7 @@ function mapFiltersFormToLabelValueList>( localeCompare: LocaleContextProps['localeCompare'], convertToDisplayStringWithoutCurrency: CurrencyListActionsContextType['convertToDisplayStringWithoutCurrency'], mapper: (filterKey: MappedFilterKey, isDefault: boolean) => T, + shouldUseSupplierLabel?: boolean, ): Array; function mapFiltersFormToLabelValueList( searchAdvancedFiltersForm: Partial, @@ -5946,6 +5977,7 @@ function mapFiltersFormToLabelValueList( localeCompare: LocaleContextProps['localeCompare'], convertToDisplayStringWithoutCurrency: CurrencyListActionsContextType['convertToDisplayStringWithoutCurrency'], mapper?: (filterKey: MappedFilterKey, isDefault: boolean) => Record, + shouldUseSupplierLabel = false, ): SearchFilter[] { const defaultFilters: SearchFilter[] = []; const nonDefaultFilters: SearchFilter[] = []; @@ -6000,8 +6032,8 @@ function mapFiltersFormToLabelValueList( } const baseKey = removeNegation(key); - const labelKey = FILTER_VIEW_MAP[baseKey].labelKey; - const value = getDisplayValue(key, searchAdvancedFiltersForm, type, translate, localeCompare); + const labelKey = getSearchFilterLabelKey(baseKey, shouldUseSupplierLabel); + const value = getDisplayValue(key, searchAdvancedFiltersForm, type, translate, localeCompare, shouldUseSupplierLabel); const label = getLabelValue(key, labelKey, translate); if (label && value && !(Array.isArray(value) && value.length === 0)) { @@ -6394,6 +6426,7 @@ function getColumnsToShow({ [CONST.SEARCH.TABLE_COLUMNS.SUBMITTED]: false, [CONST.SEARCH.TABLE_COLUMNS.APPROVED]: false, [CONST.SEARCH.TABLE_COLUMNS.MERCHANT]: false, + [CONST.SEARCH.TABLE_COLUMNS.VENDOR]: false, [CONST.SEARCH.TABLE_COLUMNS.DESCRIPTION]: false, [CONST.SEARCH.TABLE_COLUMNS.FROM]: false, [CONST.SEARCH.TABLE_COLUMNS.TO]: false, @@ -6495,6 +6528,10 @@ function getColumnsToShow({ columns[CONST.SEARCH.TABLE_COLUMNS.DESCRIPTION] = true; } + if (!isExpenseReportView && !!transaction.comment?.vendor?.externalID) { + columns[CONST.SEARCH.TABLE_COLUMNS.VENDOR] = true; + } + const hasCategory = (() => { const category = getCategory(transaction); return category !== '' && category !== CONST.SEARCH.CATEGORY_EMPTY_VALUE; @@ -7008,6 +7045,7 @@ function shouldShowDeleteOption( const FLEX_COLUMNS = new Set([ CONST.SEARCH.TABLE_COLUMNS.MERCHANT, + CONST.SEARCH.TABLE_COLUMNS.VENDOR, CONST.SEARCH.TABLE_COLUMNS.DESCRIPTION, CONST.SEARCH.TABLE_COLUMNS.CATEGORY, CONST.SEARCH.TABLE_COLUMNS.CATEGORY_GL_CODE, @@ -7195,6 +7233,7 @@ export { MONTHLY_ACCRUAL_SEARCH_KEYS, RECONCILIATION_SEARCH_KEYS, FILTER_VIEW_MAP, + getSearchFilterLabelKey, doesSearchItemMatchSort, isPolicyEligibleForSpendOverTime, hasFlexColumn, diff --git a/src/libs/actions/Search.ts b/src/libs/actions/Search.ts index 8135e84842eb..58bc8e81ec0a 100644 --- a/src/libs/actions/Search.ts +++ b/src/libs/actions/Search.ts @@ -1078,6 +1078,34 @@ function openSearchCategoryFiltersPage() { read(READ_COMMANDS.OPEN_SEARCH_CATEGORY_FILTERS_PAGE, null, {optimisticData, successData, finallyData}); } +function openSearchVendorFiltersPage() { + const optimisticData: Array> = [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: ONYXKEYS.RAM_ONLY_IS_LOADING_SEARCH_FILTERS_VENDOR_DATA, + value: true, + }, + ]; + + const successData: Array> = [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: ONYXKEYS.IS_SEARCH_FILTERS_VENDOR_DATA_LOADED, + value: true, + }, + ]; + + const finallyData: Array> = [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: ONYXKEYS.RAM_ONLY_IS_LOADING_SEARCH_FILTERS_VENDOR_DATA, + value: false, + }, + ]; + + read(READ_COMMANDS.OPEN_SEARCH_VENDOR_FILTERS_PAGE, null, {optimisticData, successData, finallyData}); +} + function openBulkChangeApproverPage(reportIDList: OpenBulkChangeApproverPageParams['reportIDList']) { const optimisticData: Array> = [ { @@ -2501,6 +2529,7 @@ export { handlePreventSearchAPI, openSearchCardFiltersPage, openSearchCategoryFiltersPage, + openSearchVendorFiltersPage, getPolicyFromSearchSnapshot, getReportFromSearchSnapshot, getReportActionsFromSearchSnapshot, diff --git a/src/libs/getSearchColumnContentToMeasure.ts b/src/libs/getSearchColumnContentToMeasure.ts index 79aaacabfe8c..b63c270e4de2 100644 --- a/src/libs/getSearchColumnContentToMeasure.ts +++ b/src/libs/getSearchColumnContentToMeasure.ts @@ -17,7 +17,7 @@ import type {MeasurableFont} from './measureTextWidth/types'; import {getCompanyCardDescription} from './CardUtils'; import {getCategoryGLCode, getDecodedLeafCategoryName, isCategoryMissing} from './CategoryUtils'; import getBase62ReportID from './getBase62ReportID'; -import {getTagGLCode} from './PolicyUtils'; +import {getTagGLCode, getVendorDisplayName} from './PolicyUtils'; import {getReportName} from './ReportNameUtils'; import {getReportStatusTranslation} from './ReportUtils'; import { @@ -90,6 +90,7 @@ const EDITABLE_SEARCH_COLUMNS = new Set([ const DYNAMICALLY_SIZED_SEARCH_COLUMNS = new Set([ CONST.SEARCH.TABLE_COLUMNS.STATUS, CONST.SEARCH.TABLE_COLUMNS.MERCHANT, + CONST.SEARCH.TABLE_COLUMNS.VENDOR, CONST.SEARCH.TABLE_COLUMNS.DESCRIPTION, CONST.SEARCH.TABLE_COLUMNS.CATEGORY, CONST.SEARCH.TABLE_COLUMNS.TAG, @@ -131,6 +132,7 @@ const HUGGED_SEARCH_COLUMNS = new Set([CONST.SEARCH.TABLE_COLU const SEARCH_COLUMN_HEADER_TRANSLATION_KEYS: Partial> = { [CONST.SEARCH.TABLE_COLUMNS.STATUS]: 'common.status', [CONST.SEARCH.TABLE_COLUMNS.MERCHANT]: 'common.merchant', + [CONST.SEARCH.TABLE_COLUMNS.VENDOR]: 'common.vendor', [CONST.SEARCH.TABLE_COLUMNS.DESCRIPTION]: 'common.description', [CONST.SEARCH.TABLE_COLUMNS.CATEGORY]: 'common.category', [CONST.SEARCH.TABLE_COLUMNS.TAG]: 'common.tag', @@ -216,6 +218,8 @@ function getTransactionColumnContentToMeasure( ]; case CONST.SEARCH.TABLE_COLUMNS.MERCHANT: return [{text: getMerchantName(item, translate)}]; + case CONST.SEARCH.TABLE_COLUMNS.VENDOR: + return [{text: getVendorDisplayName(item.policy, item.comment?.vendor)}]; case CONST.SEARCH.TABLE_COLUMNS.DESCRIPTION: return [{text: getDescription(item)}]; case CONST.SEARCH.TABLE_COLUMNS.CATEGORY: diff --git a/src/pages/Search/SearchColumnsPage.tsx b/src/pages/Search/SearchColumnsPage.tsx index 43a606058690..8f899941152d 100644 --- a/src/pages/Search/SearchColumnsPage.tsx +++ b/src/pages/Search/SearchColumnsPage.tsx @@ -2,8 +2,10 @@ import ColumnsSettingsList from '@components/ColumnsSettingsList'; import type {SearchCustomColumnIds} from '@components/Search/types'; import useOnyx from '@hooks/useOnyx'; +import usePermissions from '@hooks/usePermissions'; import Navigation from '@libs/Navigation/Navigation'; +import {getVendorSearchAvailability} from '@libs/PolicyUtils'; import {buildQueryStringFromFilterFormValues, getCurrentSearchQueryJSON, hasValuesIncludeViolationFilter} from '@libs/SearchQueryUtils'; import {getCustomColumnDefault, getCustomColumns, insertColumnBeforeTotalAmount} from '@libs/SearchUIUtils'; @@ -11,11 +13,19 @@ import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; import type {SearchAdvancedFiltersForm} from '@src/types/form'; +import type {Policy} from '@src/types/onyx'; + +import type {OnyxCollection} from 'react-native-onyx'; import React from 'react'; function SearchColumnsPage() { const [searchAdvancedFiltersForm] = useOnyx(ONYXKEYS.FORMS.SEARCH_ADVANCED_FILTERS_FORM); + const {isBetaEnabled} = usePermissions(); + const isVendorMatchingBetaEnabled = isBetaEnabled(CONST.BETAS.VENDOR_MATCHING); + const [isVendorColumnAvailable = false] = useOnyx(ONYXKEYS.COLLECTION.POLICY, { + selector: (allPolicies: OnyxCollection) => getVendorSearchAvailability(allPolicies, isVendorMatchingBetaEnabled).isAvailable, + }); const groupBy = searchAdvancedFiltersForm?.groupBy; const queryType = searchAdvancedFiltersForm?.type ?? CONST.SEARCH.DATA_TYPES.EXPENSE; @@ -23,11 +33,15 @@ function SearchColumnsPage() { // Violations data is only returned when these filters are set, so hide the column otherwise. const shouldRequireViolationsColumn = hasValuesIncludeViolationFilter(searchAdvancedFiltersForm?.has); - const allTypeCustomColumns = getCustomColumns(queryType).filter((column) => shouldRequireViolationsColumn || column !== CONST.SEARCH.TABLE_COLUMNS.VIOLATIONS); + // The vendor column only exists for workspaces with the vendor feature, so hide it when none of the user's workspaces has it. + const isColumnAvailable = (column: SearchCustomColumnIds) => + (shouldRequireViolationsColumn || column !== CONST.SEARCH.TABLE_COLUMNS.VIOLATIONS) && (isVendorColumnAvailable || column !== CONST.SEARCH.TABLE_COLUMNS.VENDOR); + + const allTypeCustomColumns = getCustomColumns(queryType).filter(isColumnAvailable); const allGroupCustomColumns = getCustomColumns(groupBy); const defaultGroupCustomColumns = getCustomColumnDefault(groupBy); const defaultTypeCustomColumns = [...getCustomColumnDefault(queryType)]; - const currentColumns = [...(searchAdvancedFiltersForm?.columns ?? [])].filter((column) => shouldRequireViolationsColumn || column !== CONST.SEARCH.TABLE_COLUMNS.VIOLATIONS); + const currentColumns = [...(searchAdvancedFiltersForm?.columns ?? [])].filter(isColumnAvailable); // We need at least one element with flex1 in the table to ensure the table looks good in the UI, so we don't allow removing the total columns // since it makes sense for them to show up in an expense management App and it fixes the layout issues. diff --git a/src/pages/Search/SearchSavePage.tsx b/src/pages/Search/SearchSavePage.tsx index b91b2d5210ea..f51e9bfcc56a 100644 --- a/src/pages/Search/SearchSavePage.tsx +++ b/src/pages/Search/SearchSavePage.tsx @@ -20,11 +20,13 @@ import useAutoFocusInput from '@hooks/useAutoFocusInput'; import {useCurrencyListActions} from '@hooks/useCurrencyList'; import useLocalize from '@hooks/useLocalize'; import useOnyx from '@hooks/useOnyx'; +import usePermissions from '@hooks/usePermissions'; import useThemeStyles from '@hooks/useThemeStyles'; import {saveSearch} from '@libs/actions/Search'; import Navigation from '@libs/Navigation/Navigation'; import {rand64} from '@libs/NumberUtils'; +import {getVendorSearchAvailability} from '@libs/PolicyUtils'; import {getCustomColumnDefault, getSearchColumnTranslationKey, mapFiltersFormToLabelValueList, savedSearchIDToSearchKey} from '@libs/SearchUIUtils'; import type {SearchFilter} from '@libs/SearchUIUtils'; import {getFieldRequiredErrors} from '@libs/ValidationUtils'; @@ -33,8 +35,11 @@ import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import type {SearchAdvancedFiltersForm} from '@src/types/form'; import INPUT_IDS from '@src/types/form/SearchSaveForm'; +import type {Policy} from '@src/types/onyx'; import {getEmptyObject} from '@src/types/utils/EmptyObject'; +import type {OnyxCollection} from 'react-native-onyx'; + import React from 'react'; import {View} from 'react-native'; @@ -181,6 +186,11 @@ function SearchSavePage() { const validate = (values: FormOnyxValues): FormInputErrors => getFieldRequiredErrors(values, [INPUT_IDS.NAME], translate); + const {isBetaEnabled} = usePermissions(); + const isVendorMatchingBetaEnabled = isBetaEnabled(CONST.BETAS.VENDOR_MATCHING); + const [shouldUseSupplierLabel = false] = useOnyx(ONYXKEYS.COLLECTION.POLICY, { + selector: (allPolicies: OnyxCollection) => getVendorSearchAvailability(allPolicies, isVendorMatchingBetaEnabled).shouldUseSupplierLabel, + }); const appliedFilters = mapFiltersFormToLabelValueList( searchAdvancedFiltersForm, currentDefaultSearchQueryFilterKeys, @@ -189,6 +199,8 @@ function SearchSavePage() { dateFnsLocale, localeCompare, convertToDisplayStringWithoutCurrency, + undefined, + shouldUseSupplierLabel, ); const appliedDisplays = getAppliedDisplays(searchAdvancedFiltersForm, currentSearchQueryJSON, translate); diff --git a/src/styles/utils/index.ts b/src/styles/utils/index.ts index 970df31ff455..972ce8704e8e 100644 --- a/src/styles/utils/index.ts +++ b/src/styles/utils/index.ts @@ -2111,6 +2111,7 @@ const createStyleUtils = (theme: ThemeColors, styles: ThemeStyles) => ({ case CONST.SEARCH.TABLE_COLUMNS.REPORT_ID: case CONST.SEARCH.TABLE_COLUMNS.BASE_62_REPORT_ID: case CONST.SEARCH.TABLE_COLUMNS.MERCHANT: + case CONST.SEARCH.TABLE_COLUMNS.VENDOR: case CONST.SEARCH.TABLE_COLUMNS.FROM: case CONST.SEARCH.TABLE_COLUMNS.TO: case CONST.SEARCH.TABLE_COLUMNS.FIRST_APPROVER: diff --git a/src/types/form/SearchAdvancedFiltersForm.ts b/src/types/form/SearchAdvancedFiltersForm.ts index 010091d7e4ef..647e1f232a83 100644 --- a/src/types/form/SearchAdvancedFiltersForm.ts +++ b/src/types/form/SearchAdvancedFiltersForm.ts @@ -138,6 +138,8 @@ const FILTER_KEYS = { CATEGORY_NOT: 'categoryNot', CATEGORY: 'category', + VENDOR: 'vendor', + CARD_ID_NOT: 'cardIDNot', CARD_ID: 'cardID', @@ -300,6 +302,7 @@ const ALLOWED_TYPE_FILTERS: Record> = { FILTER_KEYS.CATEGORY_NOT, FILTER_KEYS.TAG, FILTER_KEYS.TAG_NOT, + FILTER_KEYS.VENDOR, FILTER_KEYS.PAYER, FILTER_KEYS.PAYER_NOT, FILTER_KEYS.PAID_BY, @@ -785,6 +788,8 @@ type SearchAdvancedFiltersForm = Form< [FILTER_KEYS.CATEGORY]: string[]; [FILTER_KEYS.CATEGORY_NOT]: string[]; + [FILTER_KEYS.VENDOR]: string[]; + [FILTER_KEYS.POLICY_ID]: string[]; [FILTER_KEYS.POLICY_ID_NOT]: string[]; diff --git a/tests/unit/PolicyUtilsTest.ts b/tests/unit/PolicyUtilsTest.ts index f96bd9b46c3a..aa3caaea8a84 100644 --- a/tests/unit/PolicyUtilsTest.ts +++ b/tests/unit/PolicyUtilsTest.ts @@ -15,6 +15,8 @@ import { canSendInvoiceFromWorkspace, evaluateApprovalWorkflowRule, findVendorByID, + getVendorDisplayName, + getVendorSearchAvailability, getActivePolicies, getActivePoliciesWithExpenseChat, getActivePoliciesWithExpenseChatAndPerDiemEnabled, @@ -4506,6 +4508,66 @@ describe('PolicyUtils', () => { }); }); + describe('getVendorSearchAvailability', () => { + const qboPolicy: Policy = {...buildQBOPolicy(CONST.QUICKBOOKS_NON_REIMBURSABLE_EXPORT_ACCOUNT_TYPE.CREDIT_CARD), id: 'qbo'}; + const xeroPolicy: Policy = {...buildXeroPolicy(), id: 'xero'}; + const plainPolicy: Policy = {...createRandomPolicy(3), connections: undefined, id: 'plain'}; + const qboKey = `${ONYXKEYS.COLLECTION.POLICY}qbo`; + const xeroKey = `${ONYXKEYS.COLLECTION.POLICY}xero`; + const plainKey = `${ONYXKEYS.COLLECTION.POLICY}plain`; + + it('is unavailable when no workspace has the vendor feature', () => { + expect(getVendorSearchAvailability({[plainKey]: plainPolicy}, true)).toEqual({isAvailable: false, shouldUseSupplierLabel: false, eligiblePolicyIDs: []}); + }); + + it('is available with the vendor label for a QBO workspace exporting card expenses as credit card transactions, without the beta', () => { + expect(getVendorSearchAvailability({[qboKey]: qboPolicy, [plainKey]: plainPolicy}, false)).toEqual({ + isAvailable: true, + shouldUseSupplierLabel: false, + eligiblePolicyIDs: ['qbo'], + }); + }); + + it('uses the supplier label when every eligible workspace takes its vendors from Xero', () => { + expect(getVendorSearchAvailability({[xeroKey]: xeroPolicy, [plainKey]: plainPolicy}, true)).toEqual({ + isAvailable: true, + shouldUseSupplierLabel: true, + eligiblePolicyIDs: ['xero'], + }); + }); + + it('keeps the vendor label when Xero and QBO workspaces are both eligible', () => { + const result = getVendorSearchAvailability({[xeroKey]: xeroPolicy, [qboKey]: qboPolicy}, true); + expect(result.isAvailable).toBe(true); + expect(result.shouldUseSupplierLabel).toBe(false); + expect(result.eligiblePolicyIDs.toSorted()).toEqual(['qbo', 'xero']); + }); + + it('ignores beta-gated integrations while the beta is off', () => { + expect(getVendorSearchAvailability({[xeroKey]: xeroPolicy}, false).isAvailable).toBe(false); + }); + }); + + describe('getVendorDisplayName', () => { + const qboPolicy = buildQBOPolicy(CONST.QUICKBOOKS_NON_REIMBURSABLE_EXPORT_ACCOUNT_TYPE.CREDIT_CARD); + + it('returns an empty string when no vendor is assigned', () => { + expect(getVendorDisplayName(qboPolicy, undefined)).toBe(''); + }); + + it('prefers the synced vendor name over the name stored on the transaction', () => { + expect(getVendorDisplayName(qboPolicy, {externalID: 'v-1', name: 'Old Acme', wasManuallySet: true})).toBe('Acme Co'); + }); + + it('falls back to the stored name when the vendor is no longer in the synced list', () => { + expect(getVendorDisplayName(qboPolicy, {externalID: 'gone', name: 'Former Vendor', wasManuallySet: true})).toBe('Former Vendor'); + }); + + it('returns an empty string for a legacy vendor with neither a synced nor a stored name', () => { + expect(getVendorDisplayName(undefined, {externalID: 'v-9', wasManuallySet: true})).toBe(''); + }); + }); + describe('findVendorByID', () => { it('resolves a QBO vendor even when the current export mode is no longer vendor-matching (Vendor Bill)', () => { const policy = buildQBOPolicy(CONST.QUICKBOOKS_NON_REIMBURSABLE_EXPORT_ACCOUNT_TYPE.VENDOR_BILL, [{id: 'v-1', name: 'Acme', currency: 'USD'}]); diff --git a/tests/unit/Search/SearchQueryUtilsTest.ts b/tests/unit/Search/SearchQueryUtilsTest.ts index d2dd473da64f..20dcdf5f55d8 100644 --- a/tests/unit/Search/SearchQueryUtilsTest.ts +++ b/tests/unit/Search/SearchQueryUtilsTest.ts @@ -417,6 +417,17 @@ describe('SearchQueryUtils', () => { expect(result).toEqual('type:expense policyID:12345 amount<100'); }); + test('vendor filter value', () => { + const filterValues: Partial = { + type: 'expense', + vendor: ['Acme', 'none'], + }; + + const result = buildQueryStringFromFilterFormValues(filterValues); + + expect(result).toEqual('type:expense vendor:Acme,none'); + }); + test('receipt type filter value', () => { const filterValues: Partial = { type: 'expense', @@ -1228,6 +1239,22 @@ describe('SearchQueryUtils', () => { }); }); + test('vendor filter keeps the typed names and the empty value', () => { + const queryString = 'sortBy:date sortOrder:desc type:expense vendor:"Acme Tools",none'; + const queryJSON = buildSearchQueryJSON(queryString); + + if (!queryJSON) { + throw new Error('Failed to parse query string'); + } + + const result = buildFilterFormValuesFromQuery(queryJSON, {}, {}, {}, {}, {}, {}, {}); + + expect(result).toEqual({ + type: 'expense', + vendor: ['Acme Tools', 'none'], + }); + }); + test('action filter should be set to undefined if the input value is invalid', () => { const policyCategories = {}; const policyTags = {}; diff --git a/tests/unit/Search/SearchUIUtilsTest.ts b/tests/unit/Search/SearchUIUtilsTest.ts index 3e5453de743e..556a6a1956e3 100644 --- a/tests/unit/Search/SearchUIUtilsTest.ts +++ b/tests/unit/Search/SearchUIUtilsTest.ts @@ -48,6 +48,7 @@ import type {OnyxCollection} from 'react-native-onyx'; import Onyx from 'react-native-onyx'; import createRandomPolicy from '../../utils/collections/policies'; +import createRandomTransaction from '../../utils/collections/transaction'; import createMock from '../../utils/createMock'; import getOnyxValue from '../../utils/getOnyxValue'; import {convertToDisplayString, formatPhoneNumber, getCurrencyDecimalsLocal, localeCompare, translateLocal} from '../../utils/TestHelper'; @@ -11089,6 +11090,18 @@ describe('SearchUIUtils', () => { }); describe('Test getColumnsToShow', () => { + test('Should show the vendor column only when an expense has a vendor assigned', () => { + const transactionWithoutVendor = createRandomTransaction(1); + const transactionWithVendor = {...createRandomTransaction(2), comment: {vendor: {externalID: 'qbo-1', name: 'Acme Tools', wasManuallySet: true}}}; + + expect(SearchUIUtils.getColumnsToShow({currentAccountID: 1, data: [transactionWithoutVendor], visibleColumns: [], type: CONST.SEARCH.DATA_TYPES.EXPENSE})).not.toContain( + CONST.SEARCH.TABLE_COLUMNS.VENDOR, + ); + expect(SearchUIUtils.getColumnsToShow({currentAccountID: 1, data: [transactionWithVendor], visibleColumns: [], type: CONST.SEARCH.DATA_TYPES.EXPENSE})).toContain( + CONST.SEARCH.TABLE_COLUMNS.VENDOR, + ); + }); + test('Should show all default columns when no custom columns are saved & viewing expense reports', () => { expect(SearchUIUtils.getColumnsToShow({currentAccountID: 1, data: [], visibleColumns: [], type: CONST.SEARCH.DATA_TYPES.EXPENSE_REPORT})).toEqual([ CONST.SEARCH.TABLE_COLUMNS.AVATAR, @@ -13966,6 +13979,20 @@ describe('SearchUIUtils', () => { }); }); + describe('vendor column and filter labels', () => { + test('Should label the vendor column and filter as Vendor by default and as Supplier for Xero-only workspaces', () => { + expect(SearchUIUtils.getSearchColumnTranslationKey(CONST.SEARCH.TABLE_COLUMNS.VENDOR)).toBe('common.vendor'); + expect(SearchUIUtils.getSearchColumnTranslationKey(CONST.SEARCH.TABLE_COLUMNS.VENDOR, true)).toBe('common.supplier'); + expect(SearchUIUtils.getSearchFilterLabelKey(CONST.SEARCH.SYNTAX_FILTER_KEYS.VENDOR)).toBe('common.vendor'); + expect(SearchUIUtils.getSearchFilterLabelKey(CONST.SEARCH.SYNTAX_FILTER_KEYS.VENDOR, true)).toBe('common.supplier'); + }); + + test('Should leave other labels untouched when the supplier wording is on', () => { + expect(SearchUIUtils.getSearchColumnTranslationKey(CONST.SEARCH.TABLE_COLUMNS.CATEGORY, true)).toBe('common.category'); + expect(SearchUIUtils.getSearchFilterLabelKey(CONST.SEARCH.SYNTAX_FILTER_KEYS.CATEGORY, true)).toBe('common.category'); + }); + }); + describe('getDisplayValue', () => { test('returns translated has option labels from getHasOptions', () => { const result = SearchUIUtils.getDisplayValue('has', {has: [CONST.SEARCH.HAS_VALUES.SUBMITTED_VIOLATION]}, CONST.SEARCH.DATA_TYPES.EXPENSE, translateLocal, localeCompare); diff --git a/tests/unit/Search/__snapshots__/ColumnAvailabilityTest.ts.snap b/tests/unit/Search/__snapshots__/ColumnAvailabilityTest.ts.snap index d415876f37bb..031470e3f5cf 100644 --- a/tests/unit/Search/__snapshots__/ColumnAvailabilityTest.ts.snap +++ b/tests/unit/Search/__snapshots__/ColumnAvailabilityTest.ts.snap @@ -41,6 +41,7 @@ exports[`Column availability single source of truth the derived picker lists mat "posted", "exported", "merchant", + "vendor", "description", "from", "to", diff --git a/tests/unit/hooks/useAdvancedSearchFilters.test.ts b/tests/unit/hooks/useAdvancedSearchFilters.test.ts index 5b301f6ab233..0bc13c298d46 100644 --- a/tests/unit/hooks/useAdvancedSearchFilters.test.ts +++ b/tests/unit/hooks/useAdvancedSearchFilters.test.ts @@ -7,6 +7,7 @@ import useAdvancedSearchFilters from '@hooks/useAdvancedSearchFilters'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import type {Policy, PolicyTagLists} from '@src/types/onyx'; +import type {Connections} from '@src/types/onyx/Policy'; import type * as NativeNavigation from '@react-navigation/native'; @@ -14,6 +15,7 @@ import React from 'react'; import Onyx from 'react-native-onyx'; import createRandomPolicy from '../../utils/collections/policies'; +import createMock from '../../utils/createMock'; import waitForBatchedUpdates from '../../utils/waitForBatchedUpdates'; jest.mock('@src/libs/Log'); @@ -199,6 +201,37 @@ describe('useAdvancedSearchFilters', () => { }); }); + describe('vendor filter visibility', () => { + it('hides the vendor filter when no workspace has the vendor feature', async () => { + await Onyx.merge(`${ONYXKEYS.COLLECTION.POLICY}1`, buildPolicy(1, {connections: undefined})); + + const {result} = renderHook(() => useAdvancedSearchFilters(undefined, undefined), {wrapper}); + + await waitFor(() => { + const allKeys = result.current.flat(); + expect(allKeys).toContain(CONST.SEARCH.SYNTAX_FILTER_KEYS.CATEGORY); + expect(allKeys).not.toContain(CONST.SEARCH.SYNTAX_FILTER_KEYS.VENDOR); + }); + }); + + it('shows the vendor filter when a workspace exports QBO card expenses as credit card transactions', async () => { + const connections = createMock({ + [CONST.POLICY.CONNECTIONS.NAME.QBO]: { + config: {nonReimbursableExpensesExportDestination: CONST.QUICKBOOKS_NON_REIMBURSABLE_EXPORT_ACCOUNT_TYPE.CREDIT_CARD}, + data: {vendors: []}, + }, + }); + await Onyx.merge(`${ONYXKEYS.COLLECTION.POLICY}1`, buildPolicy(1, {connections})); + + const {result} = renderHook(() => useAdvancedSearchFilters(undefined, undefined), {wrapper}); + + await waitFor(() => { + const allKeys = result.current.flat(); + expect(allKeys).toContain(CONST.SEARCH.SYNTAX_FILTER_KEYS.VENDOR); + }); + }); + }); + describe('tax filter visibility', () => { it('hides tax filter when no policies have taxes enabled', async () => { const policy = buildPolicy(1, {tax: {trackingEnabled: false}}); From eb8c18b5a08bac1d7b5d5f0c480f10f5c424e165 Mon Sep 17 00:00:00 2001 From: Krishna Chaitanya Date: Thu, 17 Sep 2026 15:26:26 +0530 Subject: [PATCH 2/8] Add Vendor column to expense Search and report tables --- src/CONST/index.ts | 7 +++ src/components/ColumnsSettingsList.tsx | 25 ++++++--- .../MoneyRequestReportTableHeader.tsx | 8 ++- .../MoneyRequestReportTransactionList.tsx | 3 +- src/components/Search/SearchTableHeader.tsx | 24 ++++++++- .../TransactionItemRowWide.tsx | 11 +++- src/libs/PolicyUtils.ts | 42 +++++++++++++++ src/libs/SearchUIUtils.ts | 15 +++++- src/libs/getSearchColumnContentToMeasure.ts | 6 ++- src/pages/Search/SearchColumnsPage.tsx | 20 +++++++- .../Report/ReportDetailsColumnsPage.tsx | 17 +++++-- src/styles/utils/index.ts | 1 + tests/unit/PolicyUtilsTest.ts | 51 +++++++++++++++++++ tests/unit/Search/SearchUIUtilsTest.ts | 27 ++++++++++ .../ColumnAvailabilityTest.ts.snap | 2 + 15 files changed, 240 insertions(+), 19 deletions(-) diff --git a/src/CONST/index.ts b/src/CONST/index.ts index 1cb71e53c2da..af84328ef060 100644 --- a/src/CONST/index.ts +++ b/src/CONST/index.ts @@ -7360,6 +7360,11 @@ const CONST = { search: true, reportView: true, }, + VENDOR: { + column: this.TABLE_COLUMNS.VENDOR, + search: true, + reportView: true, + }, DESCRIPTION: { column: this.TABLE_COLUMNS.DESCRIPTION, search: true, @@ -7721,6 +7726,7 @@ const CONST = { POSTED: 'posted', EXPORTED: 'exported', MERCHANT: 'merchant', + VENDOR: 'vendor', DESCRIPTION: 'description', FROM: 'from', TO: 'to', @@ -7963,6 +7969,7 @@ const CONST = { [this.TABLE_COLUMNS.POSTED]: 'posted', [this.TABLE_COLUMNS.EXPORTED]: 'exported', [this.TABLE_COLUMNS.MERCHANT]: 'merchant', + [this.TABLE_COLUMNS.VENDOR]: 'vendor', [this.TABLE_COLUMNS.DESCRIPTION]: 'description', [this.TABLE_COLUMNS.FROM]: 'from', [this.TABLE_COLUMNS.TO]: 'to', diff --git a/src/components/ColumnsSettingsList.tsx b/src/components/ColumnsSettingsList.tsx index 304de4ec2acb..018d92173702 100644 --- a/src/components/ColumnsSettingsList.tsx +++ b/src/components/ColumnsSettingsList.tsx @@ -65,11 +65,24 @@ type ColumnsSettingsListProps = { /** The default columns for the active group-by mode when no customization has been applied */ defaultGroupColumns?: SearchCustomColumnIds[]; + /** Whether the vendor column is labelled "Supplier", which is what Xero calls vendors */ + shouldUseSupplierLabel?: boolean; + /** Callback fired with the updated column list when the user saves changes */ onSave: (columns: SearchCustomColumnIds[]) => void; }; -function ColumnsSettingsList({allColumns, defaultSelectedColumns, currentColumns, requiredColumns, groupBy, groupColumns = [], defaultGroupColumns = [], onSave}: ColumnsSettingsListProps) { +function ColumnsSettingsList({ + allColumns, + defaultSelectedColumns, + currentColumns, + requiredColumns, + groupBy, + groupColumns = [], + defaultGroupColumns = [], + shouldUseSupplierLabel = false, + onSave, +}: ColumnsSettingsListProps) { const theme = useTheme(); const styles = useThemeStyles(); const icons = useMemoizedLazyExpensifyIcons(['DragHandles']); @@ -85,8 +98,8 @@ function ColumnsSettingsList({allColumns, defaultSelectedColumns, currentColumns const unselected = columnsToSort .filter((col) => !col.isSelected) .sort((a, b) => { - const textA = translate(getSearchColumnTranslationKey(a.value)); - const textB = translate(getSearchColumnTranslationKey(b.value)); + const textA = translate(getSearchColumnTranslationKey(a.value, shouldUseSupplierLabel)); + const textB = translate(getSearchColumnTranslationKey(b.value, shouldUseSupplierLabel)); return localeCompare(textA, textB); }); return [...selected, ...unselected]; @@ -118,7 +131,7 @@ function ColumnsSettingsList({allColumns, defaultSelectedColumns, currentColumns const isEffectivelySelected = isRequired || isSelected; const isDragDisabled = !isEffectivelySelected; return { - text: translate(getSearchColumnTranslationKey(columnId)), + text: translate(getSearchColumnTranslationKey(columnId, shouldUseSupplierLabel)), value: columnId, keyForList: columnId, isSelected: isEffectivelySelected, @@ -164,8 +177,8 @@ function ColumnsSettingsList({allColumns, defaultSelectedColumns, currentColumns const selectedCols = prevColumns.filter((col) => col.isSelected); const unselected = prevColumns.filter((col) => !col.isSelected && col.columnId !== updatedColumnId); const unselectedSorted = unselected.sort((a, b) => { - const textA = translate(getSearchColumnTranslationKey(a.columnId)); - const textB = translate(getSearchColumnTranslationKey(b.columnId)); + const textA = translate(getSearchColumnTranslationKey(a.columnId, shouldUseSupplierLabel)); + const textB = translate(getSearchColumnTranslationKey(b.columnId, shouldUseSupplierLabel)); return localeCompare(textA, textB); }); return [...selectedCols, {columnId: updatedColumnId, isSelected: true}, ...unselectedSorted]; diff --git a/src/components/MoneyRequestReportView/MoneyRequestReportTableHeader.tsx b/src/components/MoneyRequestReportView/MoneyRequestReportTableHeader.tsx index d328b2b08a9e..cc9bab2c5d0a 100644 --- a/src/components/MoneyRequestReportView/MoneyRequestReportTableHeader.tsx +++ b/src/components/MoneyRequestReportView/MoneyRequestReportTableHeader.tsx @@ -5,6 +5,7 @@ import type {SearchColumnType, SearchSortBy, SortOrder, TableColumnSize} from '@ import useThemeStyles from '@hooks/useThemeStyles'; import {isSortableColumnName} from '@libs/ReportUtils'; +import {getSearchColumnTranslationKey} from '@libs/SearchUIUtils'; import CONST from '@src/CONST'; @@ -22,6 +23,9 @@ type SearchTableHeaderProps = { shouldShowSorting: boolean; columns: SearchColumnType[]; shouldRemoveTotalColumnFlex?: boolean; + + /** Whether the vendor column is labelled "Supplier", which is what Xero calls vendors */ + shouldUseSupplierLabel?: boolean; }; function MoneyRequestReportTableHeader({ sortBy, @@ -34,6 +38,7 @@ function MoneyRequestReportTableHeader({ amountColumnSize, taxAmountColumnSize, shouldRemoveTotalColumnFlex, + shouldUseSupplierLabel = false, }: SearchTableHeaderProps) { const styles = useThemeStyles(); @@ -41,6 +46,7 @@ function MoneyRequestReportTableHeader({ () => [ ...getExpenseHeaders().map((header) => ({ ...header, + translationKey: header.columnName === CONST.SEARCH.TABLE_COLUMNS.VENDOR ? getSearchColumnTranslationKey(header.columnName, shouldUseSupplierLabel) : header.translationKey, isColumnSortable: isSortableColumnName(header.columnName), })), { @@ -49,7 +55,7 @@ function MoneyRequestReportTableHeader({ isColumnSortable: false, }, ], - [], + [shouldUseSupplierLabel], ); const orderedColumnConfig = useMemo(() => { diff --git a/src/components/MoneyRequestReportView/MoneyRequestReportTransactionList.tsx b/src/components/MoneyRequestReportView/MoneyRequestReportTransactionList.tsx index fe676d9b3280..2945401d0c29 100644 --- a/src/components/MoneyRequestReportView/MoneyRequestReportTransactionList.tsx +++ b/src/components/MoneyRequestReportView/MoneyRequestReportTransactionList.tsx @@ -36,7 +36,7 @@ import {resolveTransactionCardFields} from '@libs/CardUtils'; import {isBillableEnabledOnPolicy} from '@libs/MoneyRequestReportUtils'; import {navigationRef} from '@libs/Navigation/Navigation'; import {getDistanceExpenseTypeForPolicy} from '@libs/PolicyDistanceRatesUtils'; -import {isPolicyTaxEnabled} from '@libs/PolicyUtils'; +import {isPolicyTaxEnabled, isXeroActiveMatchingSource} from '@libs/PolicyUtils'; import {getOriginalMessage, isMoneyRequestAction} from '@libs/ReportActionsUtils'; import {groupTransactionsByCategory, groupTransactionsByTag} from '@libs/ReportLayoutUtils'; import { @@ -943,6 +943,7 @@ function MoneyRequestReportTransactionList({ sortOrder={sortOrder} shouldRemoveTotalColumnFlex={hasFlexColumn(columnsToShow)} columns={columnsToShow} + shouldUseSupplierLabel={isXeroActiveMatchingSource(policy)} dateColumnSize={dateColumnSize} postedColumnSize={postedColumnSize} amountColumnSize={amountColumnSize} diff --git a/src/components/Search/SearchTableHeader.tsx b/src/components/Search/SearchTableHeader.tsx index 1969275c0f7b..b452dc6b2041 100644 --- a/src/components/Search/SearchTableHeader.tsx +++ b/src/components/Search/SearchTableHeader.tsx @@ -1,12 +1,20 @@ import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset'; +import useOnyx from '@hooks/useOnyx'; +import usePermissions from '@hooks/usePermissions'; import useResponsiveLayout from '@hooks/useResponsiveLayout'; import useThemeStyles from '@hooks/useThemeStyles'; +import {getVendorSearchAvailability} from '@libs/PolicyUtils'; +import {getSearchColumnTranslationKey} from '@libs/SearchUIUtils'; + import CONST from '@src/CONST'; import type {TranslationPaths} from '@src/languages/types'; +import ONYXKEYS from '@src/ONYXKEYS'; +import type {Policy} from '@src/types/onyx'; import type {SearchDataTypes} from '@src/types/onyx/SearchResults'; import type IconAsset from '@src/types/utils/IconAsset'; +import type {OnyxCollection} from 'react-native-onyx'; import type {ValueOf} from 'type-fest'; import React, {useCallback, useMemo} from 'react'; @@ -67,6 +75,11 @@ const getExpenseHeaders = (groupBy?: SearchGroupBy): SearchColumnConfig[] => [ translationKey: 'common.merchant', canEdit: true, }, + { + columnName: CONST.SEARCH.TABLE_COLUMNS.VENDOR, + translationKey: 'common.vendor', + isColumnSortable: false, + }, { columnName: CONST.SEARCH.TABLE_COLUMNS.DESCRIPTION, translationKey: 'common.description', @@ -572,6 +585,11 @@ function SearchTableHeader({ // eslint-disable-next-line rulesdir/prefer-shouldUseNarrowLayout-instead-of-isSmallScreenWidth const {isSmallScreenWidth, isMediumScreenWidth} = useResponsiveLayout(); const displayNarrowVersion = isMediumScreenWidth || isSmallScreenWidth; + const {isBetaEnabled} = usePermissions(); + const isVendorMatchingBetaEnabled = isBetaEnabled(CONST.BETAS.VENDOR_MATCHING); + const [shouldUseSupplierLabel = false] = useOnyx(ONYXKEYS.COLLECTION.POLICY, { + selector: (allPolicies: OnyxCollection) => getVendorSearchAvailability(allPolicies, isVendorMatchingBetaEnabled).shouldUseSupplierLabel, + }); // Only load Profile icon when it's needed for EXPENSE_REPORT type or grouped transactions const icons = useMemoizedLazyExpensifyIcons(type === CONST.SEARCH.DATA_TYPES.EXPENSE_REPORT || !!groupBy ? ['Profile', 'Bank', 'CreditCard'] : []) satisfies SearchHeaderIcons; @@ -601,7 +619,9 @@ function SearchTableHeader({ for (const col of columns) { const config = configMap.get(col); if (config) { - orderedConfig.push(config); + orderedConfig.push( + config.columnName === CONST.SEARCH.TABLE_COLUMNS.VENDOR ? {...config, translationKey: getSearchColumnTranslationKey(config.columnName, shouldUseSupplierLabel)} : config, + ); addedColumns.add(col); } } @@ -613,7 +633,7 @@ function SearchTableHeader({ } return orderedConfig; - }, [columnConfig, columns]); + }, [columnConfig, columns, shouldUseSupplierLabel]); if (displayNarrowVersion) { return; diff --git a/src/components/TransactionItemRow/TransactionItemRowWide.tsx b/src/components/TransactionItemRow/TransactionItemRowWide.tsx index bcf69deb6697..13610187f0f8 100644 --- a/src/components/TransactionItemRow/TransactionItemRowWide.tsx +++ b/src/components/TransactionItemRow/TransactionItemRowWide.tsx @@ -25,7 +25,7 @@ import useThemeStyles from '@hooks/useThemeStyles'; import {getCategoryGLCode} from '@libs/CategoryUtils'; import getBase62ReportID from '@libs/getBase62ReportID'; -import {isTaxCodeCustomized, getTagGLCode} from '@libs/PolicyUtils'; +import {getTagGLCode, getVendorDisplayName, isTaxCodeCustomized} from '@libs/PolicyUtils'; import {getReportName} from '@libs/ReportNameUtils'; import {getReimbursableTotal, isExpenseReport} from '@libs/ReportUtils'; import {getViolationsForTransaction} from '@libs/SearchUIUtils'; @@ -391,6 +391,15 @@ function TransactionItemRowWide({ /> ); + case CONST.SEARCH.TABLE_COLUMNS.VENDOR: + return ( + + + + ); case CONST.SEARCH.TABLE_COLUMNS.DESCRIPTION: return ( , isVendorMatchingBetaEnabled ); } +type VendorSearchAvailability = { + /** Whether at least one workspace the user can see has the vendor feature, so Search can offer the vendor column. */ + isAvailable: boolean; + + /** Whether every eligible workspace takes its vendors from Xero, which calls them suppliers. */ + shouldUseSupplierLabel: boolean; +}; + +/** + * Search spans every workspace at once, so the vendor column is offered when any workspace has the vendor feature, + * and the "Supplier" wording is only used when no eligible workspace would call them vendors. + */ +function getVendorSearchAvailability(policies: OnyxCollection, isVendorMatchingBetaEnabled: boolean): VendorSearchAvailability { + let isAvailable = false; + let areAllEligiblePoliciesXero = true; + for (const policy of Object.values(policies ?? {})) { + if (!hasVendorFeature(policy, isVendorMatchingBetaEnabled)) { + continue; + } + isAvailable = true; + if (!isXeroActiveMatchingSource(policy)) { + areAllEligiblePoliciesXero = false; + } + } + return {isAvailable, shouldUseSupplierLabel: isAvailable && areAllEligiblePoliciesXero}; +} + /** * Single source of truth for which connected integration scopes the vendor field for this workspace * (QBO, Sage Intacct, Xero, Rillet, or DualEntry) and what its vendor list looks like. Returns `undefined` when no @@ -2910,6 +2938,18 @@ function findVendorByID(policy: OnyxEntry, vendorID: string | undefined) return getDualEntryVendors(policy).find((vendor) => vendor.id === vendorID); } +/** + * Display name of the vendor assigned to a transaction, or an empty string when none is assigned. The workspace's + * synced vendor list wins so renames in the accounting system show through, then the name persisted on the + * transaction when the vendor was assigned covers vendors that have since left the synced list. + */ +function getVendorDisplayName(policy: OnyxEntry, vendor: TransactionCommentVendor | undefined): string { + if (!vendor?.externalID) { + return ''; + } + return findVendorByID(policy, vendor.externalID)?.name ?? vendor.name ?? ''; +} + /** * Resolves the text shown for a stored merchant-rule vendor ID. Prefer the active vendor-matching * source, use the unavailable label when its loaded list no longer contains the vendor, and retain @@ -3475,6 +3515,7 @@ export { getConnectedIntegration, getConnectionExporters, findVendorByID, + getVendorDisplayName, getActiveVendorMatchingIntegration, getMatchingVendorByID, getMatchingVendors, @@ -3489,6 +3530,7 @@ export { isXeroActiveMatchingSource, isXeroVendorMatchingActive, hasVendorFeature, + getVendorSearchAvailability, isMatchingVendorListLoaded, getValidConnectedIntegration, getCountOfEnabledTagsOfList, diff --git a/src/libs/SearchUIUtils.ts b/src/libs/SearchUIUtils.ts index 701928b00741..1e607081f927 100644 --- a/src/libs/SearchUIUtils.ts +++ b/src/libs/SearchUIUtils.ts @@ -319,6 +319,7 @@ const transactionColumnNamesToSortingProperty: TransactionSorting = { [CONST.SEARCH.TABLE_COLUMNS.EXPORTED]: 'exported' as const, [CONST.SEARCH.TABLE_COLUMNS.TAG]: 'tag' as const, [CONST.SEARCH.TABLE_COLUMNS.MERCHANT]: 'formattedMerchant' as const, + [CONST.SEARCH.TABLE_COLUMNS.VENDOR]: null, [CONST.SEARCH.TABLE_COLUMNS.TOTAL_AMOUNT]: 'formattedTotal' as const, [CONST.SEARCH.TABLE_COLUMNS.CATEGORY]: 'category' as const, [CONST.SEARCH.TABLE_COLUMNS.ORIGINAL_AMOUNT]: 'originalAmount' as const, @@ -4305,7 +4306,10 @@ function getCustomColumnDefault(value?: SearchDataTypes | SearchGroupBy): Search } } -function getSearchColumnTranslationKey(column: SearchSortBy): TranslationPaths { +/** + * Xero calls vendors suppliers, so the vendor column reads "Supplier" when every eligible workspace takes its vendors from Xero. + */ +function getSearchColumnTranslationKey(column: SearchSortBy, shouldUseSupplierLabel = false): TranslationPaths { switch (column) { case CONST.SEARCH.TABLE_COLUMNS.AVATAR: return 'common.avatar'; @@ -4327,6 +4331,8 @@ function getSearchColumnTranslationKey(column: SearchSortBy): TranslationPaths { return 'search.filters.exported'; case CONST.SEARCH.TABLE_COLUMNS.MERCHANT: return 'common.merchant'; + case CONST.SEARCH.TABLE_COLUMNS.VENDOR: + return shouldUseSupplierLabel ? 'common.supplier' : 'common.vendor'; case CONST.SEARCH.TABLE_COLUMNS.DESCRIPTION: return 'common.description'; case CONST.SEARCH.TABLE_COLUMNS.FROM: @@ -6386,6 +6392,7 @@ function getColumnsToShow({ [CONST.SEARCH.TABLE_COLUMNS.DATE]: true, [CONST.SEARCH.TABLE_COLUMNS.POSTED]: false, [CONST.SEARCH.TABLE_COLUMNS.MERCHANT]: false, + [CONST.SEARCH.TABLE_COLUMNS.VENDOR]: false, [CONST.SEARCH.TABLE_COLUMNS.DESCRIPTION]: false, [CONST.SEARCH.TABLE_COLUMNS.CATEGORY]: false, [CONST.SEARCH.TABLE_COLUMNS.CATEGORY_GL_CODE]: false, @@ -6416,6 +6423,7 @@ function getColumnsToShow({ [CONST.SEARCH.TABLE_COLUMNS.SUBMITTED]: false, [CONST.SEARCH.TABLE_COLUMNS.APPROVED]: false, [CONST.SEARCH.TABLE_COLUMNS.MERCHANT]: false, + [CONST.SEARCH.TABLE_COLUMNS.VENDOR]: false, [CONST.SEARCH.TABLE_COLUMNS.DESCRIPTION]: false, [CONST.SEARCH.TABLE_COLUMNS.FROM]: false, [CONST.SEARCH.TABLE_COLUMNS.TO]: false, @@ -6517,6 +6525,10 @@ function getColumnsToShow({ columns[CONST.SEARCH.TABLE_COLUMNS.DESCRIPTION] = true; } + if (transaction.comment?.vendor?.externalID) { + columns[CONST.SEARCH.TABLE_COLUMNS.VENDOR] = true; + } + const hasCategory = (() => { const category = getCategory(transaction); return category !== '' && category !== CONST.SEARCH.CATEGORY_EMPTY_VALUE; @@ -7030,6 +7042,7 @@ function shouldShowDeleteOption( const FLEX_COLUMNS = new Set([ CONST.SEARCH.TABLE_COLUMNS.MERCHANT, + CONST.SEARCH.TABLE_COLUMNS.VENDOR, CONST.SEARCH.TABLE_COLUMNS.DESCRIPTION, CONST.SEARCH.TABLE_COLUMNS.CATEGORY, CONST.SEARCH.TABLE_COLUMNS.CATEGORY_GL_CODE, diff --git a/src/libs/getSearchColumnContentToMeasure.ts b/src/libs/getSearchColumnContentToMeasure.ts index 79aaacabfe8c..b63c270e4de2 100644 --- a/src/libs/getSearchColumnContentToMeasure.ts +++ b/src/libs/getSearchColumnContentToMeasure.ts @@ -17,7 +17,7 @@ import type {MeasurableFont} from './measureTextWidth/types'; import {getCompanyCardDescription} from './CardUtils'; import {getCategoryGLCode, getDecodedLeafCategoryName, isCategoryMissing} from './CategoryUtils'; import getBase62ReportID from './getBase62ReportID'; -import {getTagGLCode} from './PolicyUtils'; +import {getTagGLCode, getVendorDisplayName} from './PolicyUtils'; import {getReportName} from './ReportNameUtils'; import {getReportStatusTranslation} from './ReportUtils'; import { @@ -90,6 +90,7 @@ const EDITABLE_SEARCH_COLUMNS = new Set([ const DYNAMICALLY_SIZED_SEARCH_COLUMNS = new Set([ CONST.SEARCH.TABLE_COLUMNS.STATUS, CONST.SEARCH.TABLE_COLUMNS.MERCHANT, + CONST.SEARCH.TABLE_COLUMNS.VENDOR, CONST.SEARCH.TABLE_COLUMNS.DESCRIPTION, CONST.SEARCH.TABLE_COLUMNS.CATEGORY, CONST.SEARCH.TABLE_COLUMNS.TAG, @@ -131,6 +132,7 @@ const HUGGED_SEARCH_COLUMNS = new Set([CONST.SEARCH.TABLE_COLU const SEARCH_COLUMN_HEADER_TRANSLATION_KEYS: Partial> = { [CONST.SEARCH.TABLE_COLUMNS.STATUS]: 'common.status', [CONST.SEARCH.TABLE_COLUMNS.MERCHANT]: 'common.merchant', + [CONST.SEARCH.TABLE_COLUMNS.VENDOR]: 'common.vendor', [CONST.SEARCH.TABLE_COLUMNS.DESCRIPTION]: 'common.description', [CONST.SEARCH.TABLE_COLUMNS.CATEGORY]: 'common.category', [CONST.SEARCH.TABLE_COLUMNS.TAG]: 'common.tag', @@ -216,6 +218,8 @@ function getTransactionColumnContentToMeasure( ]; case CONST.SEARCH.TABLE_COLUMNS.MERCHANT: return [{text: getMerchantName(item, translate)}]; + case CONST.SEARCH.TABLE_COLUMNS.VENDOR: + return [{text: getVendorDisplayName(item.policy, item.comment?.vendor)}]; case CONST.SEARCH.TABLE_COLUMNS.DESCRIPTION: return [{text: getDescription(item)}]; case CONST.SEARCH.TABLE_COLUMNS.CATEGORY: diff --git a/src/pages/Search/SearchColumnsPage.tsx b/src/pages/Search/SearchColumnsPage.tsx index 41939acbbef9..8e222ba8a8c0 100644 --- a/src/pages/Search/SearchColumnsPage.tsx +++ b/src/pages/Search/SearchColumnsPage.tsx @@ -3,8 +3,10 @@ import {useSearchQueryContext} from '@components/Search/SearchContext'; import type {SearchCustomColumnIds} from '@components/Search/types'; import useOnyx from '@hooks/useOnyx'; +import usePermissions from '@hooks/usePermissions'; import Navigation from '@libs/Navigation/Navigation'; +import {getVendorSearchAvailability} from '@libs/PolicyUtils'; import {buildQueryStringFromFilterFormValues, getCurrentSearchQueryJSON, hasValuesIncludeViolationFilter} from '@libs/SearchQueryUtils'; import {getCustomColumnDefault, getCustomColumns, insertColumnBeforeTotalAmount} from '@libs/SearchUIUtils'; @@ -12,12 +14,21 @@ import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; import type {SearchAdvancedFiltersForm} from '@src/types/form'; +import type {Policy} from '@src/types/onyx'; + +import type {OnyxCollection} from 'react-native-onyx'; import React from 'react'; function SearchColumnsPage() { const [searchAdvancedFiltersForm] = useOnyx(ONYXKEYS.FORMS.SEARCH_ADVANCED_FILTERS_FORM); const {currentSearchKey} = useSearchQueryContext(); + const {isBetaEnabled} = usePermissions(); + const isVendorMatchingBetaEnabled = isBetaEnabled(CONST.BETAS.VENDOR_MATCHING); + const [vendorSearchAvailability] = useOnyx(ONYXKEYS.COLLECTION.POLICY, { + selector: (allPolicies: OnyxCollection) => getVendorSearchAvailability(allPolicies, isVendorMatchingBetaEnabled), + }); + const isVendorColumnAvailable = vendorSearchAvailability?.isAvailable ?? false; const groupBy = searchAdvancedFiltersForm?.groupBy; const queryType = searchAdvancedFiltersForm?.type ?? CONST.SEARCH.DATA_TYPES.EXPENSE; @@ -25,11 +36,15 @@ function SearchColumnsPage() { // Violations data is only returned when these filters are set, so hide the column otherwise. const shouldRequireViolationsColumn = hasValuesIncludeViolationFilter(searchAdvancedFiltersForm?.has); - const allTypeCustomColumns = getCustomColumns(queryType).filter((column) => shouldRequireViolationsColumn || column !== CONST.SEARCH.TABLE_COLUMNS.VIOLATIONS); + // The vendor column only exists for workspaces with the vendor feature, so hide it when none of the user's workspaces has it. + const isColumnAvailable = (column: SearchCustomColumnIds) => + (shouldRequireViolationsColumn || column !== CONST.SEARCH.TABLE_COLUMNS.VIOLATIONS) && (isVendorColumnAvailable || column !== CONST.SEARCH.TABLE_COLUMNS.VENDOR); + + const allTypeCustomColumns = getCustomColumns(queryType).filter(isColumnAvailable); const allGroupCustomColumns = getCustomColumns(groupBy); const defaultGroupCustomColumns = getCustomColumnDefault(groupBy); const defaultTypeCustomColumns = [...getCustomColumnDefault(queryType)]; - const currentColumns = [...(searchAdvancedFiltersForm?.columns ?? [])].filter((column) => shouldRequireViolationsColumn || column !== CONST.SEARCH.TABLE_COLUMNS.VIOLATIONS); + const currentColumns = [...(searchAdvancedFiltersForm?.columns ?? [])].filter(isColumnAvailable); // We need at least one element with flex1 in the table to ensure the table looks good in the UI, so we don't allow removing the total columns // since it makes sense for them to show up in an expense management App and it fixes the layout issues. @@ -82,6 +97,7 @@ function SearchColumnsPage() { groupBy={groupBy} groupColumns={allGroupCustomColumns} defaultGroupColumns={defaultGroupCustomColumns} + shouldUseSupplierLabel={vendorSearchAvailability?.shouldUseSupplierLabel} onSave={applyChanges} /> ); diff --git a/src/pages/settings/Report/ReportDetailsColumnsPage.tsx b/src/pages/settings/Report/ReportDetailsColumnsPage.tsx index 84fd8918fc7d..73bea8de328e 100644 --- a/src/pages/settings/Report/ReportDetailsColumnsPage.tsx +++ b/src/pages/settings/Report/ReportDetailsColumnsPage.tsx @@ -3,12 +3,13 @@ import type {SearchCustomColumnIds} from '@components/Search/types'; import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails'; import useOnyx from '@hooks/useOnyx'; +import usePermissions from '@hooks/usePermissions'; import {setReportDetailsColumns} from '@libs/actions/ReportLayout'; import {isBillableEnabledOnPolicy} from '@libs/MoneyRequestReportUtils'; import Navigation from '@libs/Navigation/Navigation'; import type {PlatformStackRouteProp} from '@libs/Navigation/PlatformStackNavigation/types'; -import {isPolicyTaxEnabled} from '@libs/PolicyUtils'; +import {hasVendorFeature, isPolicyTaxEnabled, isXeroActiveMatchingSource} from '@libs/PolicyUtils'; import {isIOUReport} from '@libs/ReportUtils'; import {getColumnsToShow} from '@libs/SearchUIUtils'; import {hasNonReimbursableTransactions} from '@libs/TransactionUtils'; @@ -65,6 +66,11 @@ function ReportDetailsColumnsPage() { }, }); const currentUserDetails = useCurrentUserPersonalDetails(); + const {isBetaEnabled} = usePermissions(); + + // The vendor column only exists for workspaces with the vendor feature, so hide it when this report's workspace lacks it. + const isVendorColumnAvailable = hasVendorFeature(policy, isBetaEnabled(CONST.BETAS.VENDOR_MATCHING)); + const isColumnAvailable = (column: SearchCustomColumnIds) => isVendorColumnAvailable || column !== CONST.SEARCH.TABLE_COLUMNS.VENDOR; // Wait for transactions to load before rendering. ColumnsSettingsList snapshots // currentColumns in useState on mount and does not sync prop updates, so we must @@ -100,12 +106,14 @@ function ReportDetailsColumnsPage() { return visibleColumns.filter(isReportDetailsCustomColumn); }, [reportDetailsColumns, reportTransactions, currentUserDetails?.accountID, report, policy]); + const allColumns = ALL_REPORT_DETAILS_CUSTOM_COLUMNS.filter(isColumnAvailable); + const currentColumns = effectiveColumns.filter(isColumnAvailable); const requiredColumns = new Set([CONST.SEARCH.TABLE_COLUMNS.TOTAL_AMOUNT]); const handleSave = (selectedColumnIds: SearchCustomColumnIds[]) => { // Skip saving if columns haven't changed from the effective state, to avoid // switching from the default path to the custom path in getColumnsToShow unnecessarily. - if (!arraysEqual(selectedColumnIds, effectiveColumns)) { + if (!arraysEqual(selectedColumnIds, currentColumns)) { setReportDetailsColumns(selectedColumnIds, reportDetailsColumns); } Navigation.goBack(); @@ -117,10 +125,11 @@ function ReportDetailsColumnsPage() { return ( ); diff --git a/src/styles/utils/index.ts b/src/styles/utils/index.ts index 314ec3de6b00..4cd604c0f0e0 100644 --- a/src/styles/utils/index.ts +++ b/src/styles/utils/index.ts @@ -2148,6 +2148,7 @@ const createStyleUtils = (theme: ThemeColors, styles: ThemeStyles) => ({ case CONST.SEARCH.TABLE_COLUMNS.REPORT_ID: case CONST.SEARCH.TABLE_COLUMNS.BASE_62_REPORT_ID: case CONST.SEARCH.TABLE_COLUMNS.MERCHANT: + case CONST.SEARCH.TABLE_COLUMNS.VENDOR: case CONST.SEARCH.TABLE_COLUMNS.FROM: case CONST.SEARCH.TABLE_COLUMNS.TO: case CONST.SEARCH.TABLE_COLUMNS.FIRST_APPROVER: diff --git a/tests/unit/PolicyUtilsTest.ts b/tests/unit/PolicyUtilsTest.ts index ee9ccad7691d..2599daba5b5a 100644 --- a/tests/unit/PolicyUtilsTest.ts +++ b/tests/unit/PolicyUtilsTest.ts @@ -15,6 +15,8 @@ import { canSendInvoiceFromWorkspace, evaluateApprovalWorkflowRule, findVendorByID, + getVendorDisplayName, + getVendorSearchAvailability, getActivePolicies, getActivePoliciesWithExpenseChat, getActivePoliciesWithExpenseChatAndPerDiemEnabled, @@ -4613,6 +4615,55 @@ describe('PolicyUtils', () => { }); }); + describe('getVendorSearchAvailability', () => { + const qboPolicy: Policy = {...buildQBOPolicy(CONST.QUICKBOOKS_NON_REIMBURSABLE_EXPORT_ACCOUNT_TYPE.CREDIT_CARD), id: 'qbo'}; + const xeroPolicy: Policy = {...buildXeroPolicy(), id: 'xero'}; + const plainPolicy: Policy = {...createRandomPolicy(3), connections: undefined, id: 'plain'}; + const qboKey = `${ONYXKEYS.COLLECTION.POLICY}qbo`; + const xeroKey = `${ONYXKEYS.COLLECTION.POLICY}xero`; + const plainKey = `${ONYXKEYS.COLLECTION.POLICY}plain`; + + it('is unavailable when no workspace has the vendor feature', () => { + expect(getVendorSearchAvailability({[plainKey]: plainPolicy}, true)).toEqual({isAvailable: false, shouldUseSupplierLabel: false}); + }); + + it('is available with the vendor label for a QBO workspace exporting card expenses as credit card transactions, without the beta', () => { + expect(getVendorSearchAvailability({[qboKey]: qboPolicy, [plainKey]: plainPolicy}, false)).toEqual({isAvailable: true, shouldUseSupplierLabel: false}); + }); + + it('uses the supplier label when every eligible workspace takes its vendors from Xero', () => { + expect(getVendorSearchAvailability({[xeroKey]: xeroPolicy, [plainKey]: plainPolicy}, true)).toEqual({isAvailable: true, shouldUseSupplierLabel: true}); + }); + + it('keeps the vendor label when Xero and QBO workspaces are both eligible', () => { + expect(getVendorSearchAvailability({[xeroKey]: xeroPolicy, [qboKey]: qboPolicy}, true)).toEqual({isAvailable: true, shouldUseSupplierLabel: false}); + }); + + it('ignores beta-gated integrations while the beta is off', () => { + expect(getVendorSearchAvailability({[xeroKey]: xeroPolicy}, false).isAvailable).toBe(false); + }); + }); + + describe('getVendorDisplayName', () => { + const qboPolicy = buildQBOPolicy(CONST.QUICKBOOKS_NON_REIMBURSABLE_EXPORT_ACCOUNT_TYPE.CREDIT_CARD); + + it('returns an empty string when no vendor is assigned', () => { + expect(getVendorDisplayName(qboPolicy, undefined)).toBe(''); + }); + + it('prefers the synced vendor name over the name stored on the transaction', () => { + expect(getVendorDisplayName(qboPolicy, {externalID: 'v-1', name: 'Old Acme', wasManuallySet: true})).toBe('Acme Co'); + }); + + it('falls back to the stored name when the vendor is no longer in the synced list', () => { + expect(getVendorDisplayName(qboPolicy, {externalID: 'gone', name: 'Former Vendor', wasManuallySet: true})).toBe('Former Vendor'); + }); + + it('returns an empty string for a legacy vendor with neither a synced nor a stored name', () => { + expect(getVendorDisplayName(undefined, {externalID: 'v-9', wasManuallySet: true})).toBe(''); + }); + }); + describe('findVendorByID', () => { it('resolves a QBO vendor even when the current export mode is no longer vendor-matching (Vendor Bill)', () => { const policy = buildQBOPolicy(CONST.QUICKBOOKS_NON_REIMBURSABLE_EXPORT_ACCOUNT_TYPE.VENDOR_BILL, [{id: 'v-1', name: 'Acme', currency: 'USD'}]); diff --git a/tests/unit/Search/SearchUIUtilsTest.ts b/tests/unit/Search/SearchUIUtilsTest.ts index 8792aaed1d16..c0646bcd59e0 100644 --- a/tests/unit/Search/SearchUIUtilsTest.ts +++ b/tests/unit/Search/SearchUIUtilsTest.ts @@ -48,6 +48,7 @@ import type {OnyxCollection} from 'react-native-onyx'; import Onyx from 'react-native-onyx'; import createRandomPolicy from '../../utils/collections/policies'; +import createRandomTransaction from '../../utils/collections/transaction'; import createMock from '../../utils/createMock'; import getOnyxValue from '../../utils/getOnyxValue'; import {convertToDisplayString, formatPhoneNumber, getCurrencyDecimalsLocal, localeCompare, translateLocal} from '../../utils/TestHelper'; @@ -11089,6 +11090,21 @@ describe('SearchUIUtils', () => { }); describe('Test getColumnsToShow', () => { + test('Should show the vendor column only when an expense has a vendor assigned', () => { + const transactionWithoutVendor = createRandomTransaction(1); + const transactionWithVendor = {...createRandomTransaction(2), comment: {vendor: {externalID: 'qbo-1', name: 'Acme Tools', wasManuallySet: true}}}; + + expect(SearchUIUtils.getColumnsToShow({currentAccountID: 1, data: [transactionWithoutVendor], visibleColumns: [], type: CONST.SEARCH.DATA_TYPES.EXPENSE})).not.toContain( + CONST.SEARCH.TABLE_COLUMNS.VENDOR, + ); + expect(SearchUIUtils.getColumnsToShow({currentAccountID: 1, data: [transactionWithVendor], visibleColumns: [], type: CONST.SEARCH.DATA_TYPES.EXPENSE})).toContain( + CONST.SEARCH.TABLE_COLUMNS.VENDOR, + ); + expect( + SearchUIUtils.getColumnsToShow({currentAccountID: 1, data: [transactionWithVendor], visibleColumns: [], type: CONST.SEARCH.DATA_TYPES.EXPENSE, isExpenseReportView: true}), + ).toContain(CONST.SEARCH.TABLE_COLUMNS.VENDOR); + }); + test('Should show all default columns when no custom columns are saved & viewing expense reports', () => { expect(SearchUIUtils.getColumnsToShow({currentAccountID: 1, data: [], visibleColumns: [], type: CONST.SEARCH.DATA_TYPES.EXPENSE_REPORT})).toEqual([ CONST.SEARCH.TABLE_COLUMNS.AVATAR, @@ -13966,6 +13982,17 @@ describe('SearchUIUtils', () => { }); }); + describe('vendor column label', () => { + test('Should label the vendor column as Vendor by default and as Supplier for Xero-only workspaces', () => { + expect(SearchUIUtils.getSearchColumnTranslationKey(CONST.SEARCH.TABLE_COLUMNS.VENDOR)).toBe('common.vendor'); + expect(SearchUIUtils.getSearchColumnTranslationKey(CONST.SEARCH.TABLE_COLUMNS.VENDOR, true)).toBe('common.supplier'); + }); + + test('Should leave other labels untouched when the supplier wording is on', () => { + expect(SearchUIUtils.getSearchColumnTranslationKey(CONST.SEARCH.TABLE_COLUMNS.CATEGORY, true)).toBe('common.category'); + }); + }); + describe('getDisplayValue', () => { test('returns translated has option labels from getHasOptions', () => { const result = SearchUIUtils.getDisplayValue('has', {has: [CONST.SEARCH.HAS_VALUES.SUBMITTED_VIOLATION]}, CONST.SEARCH.DATA_TYPES.EXPENSE, translateLocal, localeCompare); diff --git a/tests/unit/Search/__snapshots__/ColumnAvailabilityTest.ts.snap b/tests/unit/Search/__snapshots__/ColumnAvailabilityTest.ts.snap index d415876f37bb..c85a7d23b544 100644 --- a/tests/unit/Search/__snapshots__/ColumnAvailabilityTest.ts.snap +++ b/tests/unit/Search/__snapshots__/ColumnAvailabilityTest.ts.snap @@ -6,6 +6,7 @@ exports[`Column availability single source of truth the derived picker lists mat "date", "posted", "merchant", + "vendor", "description", "card", "category", @@ -41,6 +42,7 @@ exports[`Column availability single source of truth the derived picker lists mat "posted", "exported", "merchant", + "vendor", "description", "from", "to", From e15eaa009e4da5be72c619c4af48bdd90f9cdbc2 Mon Sep 17 00:00:00 2001 From: Krishna Chaitanya Date: Thu, 17 Sep 2026 16:49:37 +0530 Subject: [PATCH 3/8] Move VendorSearchAvailability type into the PolicyUtils type block --- src/libs/PolicyUtils.ts | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/libs/PolicyUtils.ts b/src/libs/PolicyUtils.ts index d6ad51dd519f..dc72380636bf 100644 --- a/src/libs/PolicyUtils.ts +++ b/src/libs/PolicyUtils.ts @@ -108,6 +108,14 @@ type ApprovalWorkflowRuleMatch = { forwardsTo?: string; }; +type VendorSearchAvailability = { + /** Whether at least one workspace the user can see has the vendor feature, so Search can offer the vendor column. */ + isAvailable: boolean; + + /** Whether every eligible workspace takes its vendors from Xero, which calls them suppliers. */ + shouldUseSupplierLabel: boolean; +}; + /** * Returns true if the policy has no fieldList or its fieldList is empty. */ @@ -2726,14 +2734,6 @@ function hasVendorFeature(policy: OnyxEntry, isVendorMatchingBetaEnabled ); } -type VendorSearchAvailability = { - /** Whether at least one workspace the user can see has the vendor feature, so Search can offer the vendor column. */ - isAvailable: boolean; - - /** Whether every eligible workspace takes its vendors from Xero, which calls them suppliers. */ - shouldUseSupplierLabel: boolean; -}; - /** * Search spans every workspace at once, so the vendor column is offered when any workspace has the vendor feature, * and the "Supplier" wording is only used when no eligible workspace would call them vendors. From 6a95b61e72e59bfb29e079a0529af6010c6c7222 Mon Sep 17 00:00:00 2001 From: Krishna Chaitanya Date: Thu, 17 Sep 2026 17:22:56 +0530 Subject: [PATCH 4/8] Tighten the getVendorDisplayName comment --- src/libs/PolicyUtils.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libs/PolicyUtils.ts b/src/libs/PolicyUtils.ts index dc72380636bf..1db762632dac 100644 --- a/src/libs/PolicyUtils.ts +++ b/src/libs/PolicyUtils.ts @@ -2939,9 +2939,9 @@ function findVendorByID(policy: OnyxEntry, vendorID: string | undefined) } /** - * Display name of the vendor assigned to a transaction, or an empty string when none is assigned. The workspace's - * synced vendor list wins so renames in the accounting system show through, then the name persisted on the - * transaction when the vendor was assigned covers vendors that have since left the synced list. + * Display name of a transaction's vendor, or an empty string when none is assigned. The workspace's synced vendor list + * wins so renames in the accounting system show through. The name stored on the transaction covers vendors since + * removed from that list. */ function getVendorDisplayName(policy: OnyxEntry, vendor: TransactionCommentVendor | undefined): string { if (!vendor?.externalID) { From 7470a2cb1301831b834401798cc1e7fb94a83c2f Mon Sep 17 00:00:00 2001 From: Krishna Chaitanya Date: Thu, 17 Sep 2026 17:53:31 +0530 Subject: [PATCH 5/8] Show the Vendor column on Search only when picked --- src/libs/SearchUIUtils.ts | 8 ++++---- tests/unit/Search/SearchUIUtilsTest.ts | 10 +++++++--- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/libs/SearchUIUtils.ts b/src/libs/SearchUIUtils.ts index 1e607081f927..3d39900c784c 100644 --- a/src/libs/SearchUIUtils.ts +++ b/src/libs/SearchUIUtils.ts @@ -6525,10 +6525,6 @@ function getColumnsToShow({ columns[CONST.SEARCH.TABLE_COLUMNS.DESCRIPTION] = true; } - if (transaction.comment?.vendor?.externalID) { - columns[CONST.SEARCH.TABLE_COLUMNS.VENDOR] = true; - } - const hasCategory = (() => { const category = getCategory(transaction); return category !== '' && category !== CONST.SEARCH.CATEGORY_EMPTY_VALUE; @@ -6573,6 +6569,10 @@ function getColumnsToShow({ columns[CONST.SEARCH.TABLE_COLUMNS.CARD] = true; } + if (transaction.comment?.vendor?.externalID) { + columns[CONST.SEARCH.TABLE_COLUMNS.VENDOR] = true; + } + // Only show tax columns when the user explicitly chooses to display them. if (customResult) { // Show both TAX_RATE and TAX_AMOUNT when the transaction has a meaningful tax signal. diff --git a/tests/unit/Search/SearchUIUtilsTest.ts b/tests/unit/Search/SearchUIUtilsTest.ts index c0646bcd59e0..90db2dd63bc8 100644 --- a/tests/unit/Search/SearchUIUtilsTest.ts +++ b/tests/unit/Search/SearchUIUtilsTest.ts @@ -11090,16 +11090,20 @@ describe('SearchUIUtils', () => { }); describe('Test getColumnsToShow', () => { - test('Should show the vendor column only when an expense has a vendor assigned', () => { + test('Should show the vendor column on Search only when picked, and in the report view when an expense has a vendor assigned', () => { const transactionWithoutVendor = createRandomTransaction(1); const transactionWithVendor = {...createRandomTransaction(2), comment: {vendor: {externalID: 'qbo-1', name: 'Acme Tools', wasManuallySet: true}}}; + const pickedColumns = [CONST.SEARCH.TABLE_COLUMNS.DATE, CONST.SEARCH.TABLE_COLUMNS.VENDOR, CONST.SEARCH.TABLE_COLUMNS.TOTAL_AMOUNT]; - expect(SearchUIUtils.getColumnsToShow({currentAccountID: 1, data: [transactionWithoutVendor], visibleColumns: [], type: CONST.SEARCH.DATA_TYPES.EXPENSE})).not.toContain( + expect(SearchUIUtils.getColumnsToShow({currentAccountID: 1, data: [transactionWithVendor], visibleColumns: [], type: CONST.SEARCH.DATA_TYPES.EXPENSE})).not.toContain( CONST.SEARCH.TABLE_COLUMNS.VENDOR, ); - expect(SearchUIUtils.getColumnsToShow({currentAccountID: 1, data: [transactionWithVendor], visibleColumns: [], type: CONST.SEARCH.DATA_TYPES.EXPENSE})).toContain( + expect(SearchUIUtils.getColumnsToShow({currentAccountID: 1, data: [transactionWithVendor], visibleColumns: pickedColumns, type: CONST.SEARCH.DATA_TYPES.EXPENSE})).toContain( CONST.SEARCH.TABLE_COLUMNS.VENDOR, ); + expect( + SearchUIUtils.getColumnsToShow({currentAccountID: 1, data: [transactionWithoutVendor], visibleColumns: [], type: CONST.SEARCH.DATA_TYPES.EXPENSE, isExpenseReportView: true}), + ).not.toContain(CONST.SEARCH.TABLE_COLUMNS.VENDOR); expect( SearchUIUtils.getColumnsToShow({currentAccountID: 1, data: [transactionWithVendor], visibleColumns: [], type: CONST.SEARCH.DATA_TYPES.EXPENSE, isExpenseReportView: true}), ).toContain(CONST.SEARCH.TABLE_COLUMNS.VENDOR); From 3267b865f8ab36de316f5bbb7b4f811717a040eb Mon Sep 17 00:00:00 2001 From: Krishna Chaitanya Date: Thu, 17 Sep 2026 18:11:40 +0530 Subject: [PATCH 6/8] Hide the saved Vendor column on reports whose workspace lacks the vendor feature --- .../MoneyRequestReportTransactionList.tsx | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/components/MoneyRequestReportView/MoneyRequestReportTransactionList.tsx b/src/components/MoneyRequestReportView/MoneyRequestReportTransactionList.tsx index 2945401d0c29..c3db0a3e97d4 100644 --- a/src/components/MoneyRequestReportView/MoneyRequestReportTransactionList.tsx +++ b/src/components/MoneyRequestReportView/MoneyRequestReportTransactionList.tsx @@ -22,6 +22,7 @@ import useMobileSelectionMode from '@hooks/useMobileSelectionMode'; import useNavigateToTransactionThread from '@hooks/useNavigateToTransactionThread'; import useNetwork from '@hooks/useNetwork'; import useOnyx from '@hooks/useOnyx'; +import usePermissions from '@hooks/usePermissions'; import useReportIsArchived from '@hooks/useReportIsArchived'; import useResponsiveLayout from '@hooks/useResponsiveLayout'; import useResponsiveLayoutOnWideRHP from '@hooks/useResponsiveLayoutOnWideRHP'; @@ -36,7 +37,7 @@ import {resolveTransactionCardFields} from '@libs/CardUtils'; import {isBillableEnabledOnPolicy} from '@libs/MoneyRequestReportUtils'; import {navigationRef} from '@libs/Navigation/Navigation'; import {getDistanceExpenseTypeForPolicy} from '@libs/PolicyDistanceRatesUtils'; -import {isPolicyTaxEnabled, isXeroActiveMatchingSource} from '@libs/PolicyUtils'; +import {hasVendorFeature, isPolicyTaxEnabled, isXeroActiveMatchingSource} from '@libs/PolicyUtils'; import {getOriginalMessage, isMoneyRequestAction} from '@libs/ReportActionsUtils'; import {groupTransactionsByCategory, groupTransactionsByTag} from '@libs/ReportLayoutUtils'; import { @@ -291,6 +292,7 @@ function MoneyRequestReportTransactionList({ const longPressModalRef = useRef(null); const {reportPendingAction} = getReportOfflinePendingActionAndErrors(report); const {isOffline} = useNetwork(); + const {isBetaEnabled} = usePermissions(); const isTaxEnabled = isPolicyTaxEnabled(policy); const {totalDisplaySpend, nonReimbursableSpend, reimbursableSpend} = getMoneyRequestSpendBreakdown(report); @@ -518,12 +520,15 @@ function MoneyRequestReportTransactionList({ const isExpenseReportViewFromIOUReport = isIOUReport(report); const shouldShowBillableColumn = isBillableEnabledOnPolicy(policy); const shouldShowCommentsColumn = useMemo(() => Object.values(reportActions ?? {}).some((action) => (action?.childVisibleActionCount ?? 0) > 0), [reportActions]); + // The saved column list is account-wide, so drop the vendor column on reports whose workspace lacks the vendor feature. + const isVendorColumnAvailable = hasVendorFeature(policy, isBetaEnabled(CONST.BETAS.VENDOR_MATCHING)); const columnsToShow = useMemo(() => { + const savedColumns = (reportDetailsColumns ?? []).filter((column) => isVendorColumnAvailable || column !== CONST.SEARCH.TABLE_COLUMNS.VENDOR); return getColumnsToShow({ currentAccountID: currentUserDetails?.accountID, data: transactions, report, - visibleColumns: (isExpenseReportViewFromIOUReport ? [] : (reportDetailsColumns ?? [])) as SearchCustomColumnIds[], + visibleColumns: (isExpenseReportViewFromIOUReport ? [] : savedColumns) as SearchCustomColumnIds[], isExpenseReportView: true, isExpenseReportViewFromIOUReport, shouldShowBillableColumn, @@ -539,6 +544,7 @@ function MoneyRequestReportTransactionList({ shouldShowBillableColumn, shouldShowCommentsColumn, reportDetailsColumns, + isVendorColumnAvailable, report, isTaxEnabled, shouldShowExpenseReportBreakDown, From 4e26954d6b793cf4ed7047bb574cc21f1d05d75f Mon Sep 17 00:00:00 2001 From: Krishna Chaitanya Date: Fri, 18 Sep 2026 21:48:30 +0530 Subject: [PATCH 7/8] Label the vendor column Vendor on every workspace Product standardised on "Vendor" across integrations, so the Search header, the report table header, and both Columns pickers no longer switch to "Supplier" for Xero workspaces. --- src/components/ColumnsSettingsList.tsx | 25 ++++------------- .../MoneyRequestReportTableHeader.tsx | 8 +----- .../MoneyRequestReportTableHeaderRow.tsx | 5 ---- .../MoneyRequestReportTransactionList.tsx | 3 +- src/components/Search/SearchTableHeader.tsx | 19 ++----------- src/libs/PolicyUtils.ts | 28 +++---------------- src/libs/SearchUIUtils.ts | 7 ++--- src/pages/Search/SearchColumnsPage.tsx | 8 ++---- .../Report/ReportDetailsColumnsPage.tsx | 3 +- tests/unit/PolicyUtilsTest.ts | 22 ++++++--------- tests/unit/Search/SearchUIUtilsTest.ts | 7 +---- 11 files changed, 30 insertions(+), 105 deletions(-) diff --git a/src/components/ColumnsSettingsList.tsx b/src/components/ColumnsSettingsList.tsx index 41007c9b5981..42889d995cd9 100644 --- a/src/components/ColumnsSettingsList.tsx +++ b/src/components/ColumnsSettingsList.tsx @@ -65,24 +65,11 @@ type ColumnsSettingsListProps = { /** The default columns for the active group-by mode when no customization has been applied */ defaultGroupColumns?: SearchCustomColumnIds[]; - /** Whether the vendor column is labelled "Supplier", which is what Xero calls vendors */ - shouldUseSupplierLabel?: boolean; - /** Callback fired with the updated column list when the user saves changes */ onSave: (columns: SearchCustomColumnIds[]) => void; }; -function ColumnsSettingsList({ - allColumns, - defaultSelectedColumns, - currentColumns, - requiredColumns, - groupBy, - groupColumns = [], - defaultGroupColumns = [], - shouldUseSupplierLabel = false, - onSave, -}: ColumnsSettingsListProps) { +function ColumnsSettingsList({allColumns, defaultSelectedColumns, currentColumns, requiredColumns, groupBy, groupColumns = [], defaultGroupColumns = [], onSave}: ColumnsSettingsListProps) { const theme = useTheme(); const styles = useThemeStyles(); const icons = useMemoizedLazyExpensifyIcons(['DragHandles']); @@ -98,8 +85,8 @@ function ColumnsSettingsList({ const unselected = columnsToSort .filter((col) => !col.isSelected) .sort((a, b) => { - const textA = translate(getSearchColumnTranslationKey(a.value, shouldUseSupplierLabel)); - const textB = translate(getSearchColumnTranslationKey(b.value, shouldUseSupplierLabel)); + const textA = translate(getSearchColumnTranslationKey(a.value)); + const textB = translate(getSearchColumnTranslationKey(b.value)); return localeCompare(textA, textB); }); return [...selected, ...unselected]; @@ -131,7 +118,7 @@ function ColumnsSettingsList({ const isEffectivelySelected = isRequired || isSelected; const isDragDisabled = !isEffectivelySelected; return { - text: translate(getSearchColumnTranslationKey(columnId, shouldUseSupplierLabel)), + text: translate(getSearchColumnTranslationKey(columnId)), value: columnId, keyForList: columnId, isSelected: isEffectivelySelected, @@ -177,8 +164,8 @@ function ColumnsSettingsList({ const selectedCols = prevColumns.filter((col) => col.isSelected); const unselected = prevColumns.filter((col) => !col.isSelected && col.columnId !== updatedColumnId); const unselectedSorted = unselected.sort((a, b) => { - const textA = translate(getSearchColumnTranslationKey(a.columnId, shouldUseSupplierLabel)); - const textB = translate(getSearchColumnTranslationKey(b.columnId, shouldUseSupplierLabel)); + const textA = translate(getSearchColumnTranslationKey(a.columnId)); + const textB = translate(getSearchColumnTranslationKey(b.columnId)); return localeCompare(textA, textB); }); return [...selectedCols, {columnId: updatedColumnId, isSelected: true}, ...unselectedSorted]; diff --git a/src/components/MoneyRequestReportView/MoneyRequestReportTableHeader.tsx b/src/components/MoneyRequestReportView/MoneyRequestReportTableHeader.tsx index cc9bab2c5d0a..d328b2b08a9e 100644 --- a/src/components/MoneyRequestReportView/MoneyRequestReportTableHeader.tsx +++ b/src/components/MoneyRequestReportView/MoneyRequestReportTableHeader.tsx @@ -5,7 +5,6 @@ import type {SearchColumnType, SearchSortBy, SortOrder, TableColumnSize} from '@ import useThemeStyles from '@hooks/useThemeStyles'; import {isSortableColumnName} from '@libs/ReportUtils'; -import {getSearchColumnTranslationKey} from '@libs/SearchUIUtils'; import CONST from '@src/CONST'; @@ -23,9 +22,6 @@ type SearchTableHeaderProps = { shouldShowSorting: boolean; columns: SearchColumnType[]; shouldRemoveTotalColumnFlex?: boolean; - - /** Whether the vendor column is labelled "Supplier", which is what Xero calls vendors */ - shouldUseSupplierLabel?: boolean; }; function MoneyRequestReportTableHeader({ sortBy, @@ -38,7 +34,6 @@ function MoneyRequestReportTableHeader({ amountColumnSize, taxAmountColumnSize, shouldRemoveTotalColumnFlex, - shouldUseSupplierLabel = false, }: SearchTableHeaderProps) { const styles = useThemeStyles(); @@ -46,7 +41,6 @@ function MoneyRequestReportTableHeader({ () => [ ...getExpenseHeaders().map((header) => ({ ...header, - translationKey: header.columnName === CONST.SEARCH.TABLE_COLUMNS.VENDOR ? getSearchColumnTranslationKey(header.columnName, shouldUseSupplierLabel) : header.translationKey, isColumnSortable: isSortableColumnName(header.columnName), })), { @@ -55,7 +49,7 @@ function MoneyRequestReportTableHeader({ isColumnSortable: false, }, ], - [shouldUseSupplierLabel], + [], ); const orderedColumnConfig = useMemo(() => { diff --git a/src/components/MoneyRequestReportView/MoneyRequestReportTableHeaderRow.tsx b/src/components/MoneyRequestReportView/MoneyRequestReportTableHeaderRow.tsx index b5437388cf06..d36e6fc79b24 100644 --- a/src/components/MoneyRequestReportView/MoneyRequestReportTableHeaderRow.tsx +++ b/src/components/MoneyRequestReportView/MoneyRequestReportTableHeaderRow.tsx @@ -34,9 +34,6 @@ type MoneyRequestReportTableHeaderRowProps = { /** The columns the table renders, in order */ columns: SearchColumnType[]; - /** Whether the vendor column is labelled "Supplier", which is what Xero calls vendors */ - shouldUseSupplierLabel?: boolean; - /** The column the table is currently sorted by */ sortBy: SortableColumnName; @@ -69,7 +66,6 @@ function MoneyRequestReportTableHeaderRow({ transactions, pendingAction, columns, - shouldUseSupplierLabel = false, sortBy, sortOrder, onSortPress, @@ -137,7 +133,6 @@ function MoneyRequestReportTableHeaderRow({ sortOrder={sortOrder} shouldRemoveTotalColumnFlex={hasFlexColumn(columns)} columns={columns} - shouldUseSupplierLabel={shouldUseSupplierLabel} dateColumnSize={dateColumnSize} postedColumnSize={postedColumnSize} amountColumnSize={amountColumnSize} diff --git a/src/components/MoneyRequestReportView/MoneyRequestReportTransactionList.tsx b/src/components/MoneyRequestReportView/MoneyRequestReportTransactionList.tsx index ea0d9287ad83..a50c26142ada 100644 --- a/src/components/MoneyRequestReportView/MoneyRequestReportTransactionList.tsx +++ b/src/components/MoneyRequestReportView/MoneyRequestReportTransactionList.tsx @@ -24,7 +24,7 @@ import {clearActiveTransactionIDs, getActiveTransactionIDs, setActiveTransaction import {resolveTransactionCardFields} from '@libs/CardUtils'; import {isBillableEnabledOnPolicy} from '@libs/MoneyRequestReportUtils'; import {navigationRef} from '@libs/Navigation/Navigation'; -import {hasVendorFeature, isPolicyTaxEnabled, isXeroActiveMatchingSource} from '@libs/PolicyUtils'; +import {hasVendorFeature, isPolicyTaxEnabled} from '@libs/PolicyUtils'; import {getOriginalMessage, isMoneyRequestAction} from '@libs/ReportActionsUtils'; import {groupTransactionsByCategory, groupTransactionsByTag} from '@libs/ReportLayoutUtils'; import { @@ -818,7 +818,6 @@ function MoneyRequestReportTransactionList({ transactions={transactions} pendingAction={reportPendingAction} columns={columnsToShow} - shouldUseSupplierLabel={isXeroActiveMatchingSource(policy)} sortBy={sortBy} sortOrder={sortOrder} onSortPress={(selectedSortBy, selectedSortOrder) => { diff --git a/src/components/Search/SearchTableHeader.tsx b/src/components/Search/SearchTableHeader.tsx index b452dc6b2041..93cdab2a6dfe 100644 --- a/src/components/Search/SearchTableHeader.tsx +++ b/src/components/Search/SearchTableHeader.tsx @@ -1,20 +1,12 @@ import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset'; -import useOnyx from '@hooks/useOnyx'; -import usePermissions from '@hooks/usePermissions'; import useResponsiveLayout from '@hooks/useResponsiveLayout'; import useThemeStyles from '@hooks/useThemeStyles'; -import {getVendorSearchAvailability} from '@libs/PolicyUtils'; -import {getSearchColumnTranslationKey} from '@libs/SearchUIUtils'; - import CONST from '@src/CONST'; import type {TranslationPaths} from '@src/languages/types'; -import ONYXKEYS from '@src/ONYXKEYS'; -import type {Policy} from '@src/types/onyx'; import type {SearchDataTypes} from '@src/types/onyx/SearchResults'; import type IconAsset from '@src/types/utils/IconAsset'; -import type {OnyxCollection} from 'react-native-onyx'; import type {ValueOf} from 'type-fest'; import React, {useCallback, useMemo} from 'react'; @@ -585,11 +577,6 @@ function SearchTableHeader({ // eslint-disable-next-line rulesdir/prefer-shouldUseNarrowLayout-instead-of-isSmallScreenWidth const {isSmallScreenWidth, isMediumScreenWidth} = useResponsiveLayout(); const displayNarrowVersion = isMediumScreenWidth || isSmallScreenWidth; - const {isBetaEnabled} = usePermissions(); - const isVendorMatchingBetaEnabled = isBetaEnabled(CONST.BETAS.VENDOR_MATCHING); - const [shouldUseSupplierLabel = false] = useOnyx(ONYXKEYS.COLLECTION.POLICY, { - selector: (allPolicies: OnyxCollection) => getVendorSearchAvailability(allPolicies, isVendorMatchingBetaEnabled).shouldUseSupplierLabel, - }); // Only load Profile icon when it's needed for EXPENSE_REPORT type or grouped transactions const icons = useMemoizedLazyExpensifyIcons(type === CONST.SEARCH.DATA_TYPES.EXPENSE_REPORT || !!groupBy ? ['Profile', 'Bank', 'CreditCard'] : []) satisfies SearchHeaderIcons; @@ -619,9 +606,7 @@ function SearchTableHeader({ for (const col of columns) { const config = configMap.get(col); if (config) { - orderedConfig.push( - config.columnName === CONST.SEARCH.TABLE_COLUMNS.VENDOR ? {...config, translationKey: getSearchColumnTranslationKey(config.columnName, shouldUseSupplierLabel)} : config, - ); + orderedConfig.push(config); addedColumns.add(col); } } @@ -633,7 +618,7 @@ function SearchTableHeader({ } return orderedConfig; - }, [columnConfig, columns, shouldUseSupplierLabel]); + }, [columnConfig, columns]); if (displayNarrowVersion) { return; diff --git a/src/libs/PolicyUtils.ts b/src/libs/PolicyUtils.ts index 1aa2b19611cc..475330e90757 100644 --- a/src/libs/PolicyUtils.ts +++ b/src/libs/PolicyUtils.ts @@ -108,14 +108,6 @@ type ApprovalWorkflowRuleMatch = { forwardsTo?: string; }; -type VendorSearchAvailability = { - /** Whether at least one workspace the user can see has the vendor feature, so Search can offer the vendor column. */ - isAvailable: boolean; - - /** Whether every eligible workspace takes its vendors from Xero, which calls them suppliers. */ - shouldUseSupplierLabel: boolean; -}; - /** * Returns true if the policy has no fieldList or its fieldList is empty. */ @@ -2742,22 +2734,10 @@ function hasVendorFeature(policy: OnyxEntry, isVendorMatchingBetaEnabled } /** - * Search spans every workspace at once, so the vendor column is offered when any workspace has the vendor feature, - * and the "Supplier" wording is only used when no eligible workspace would call them vendors. + * Search spans every workspace at once, so the vendor column is offered when any workspace has the vendor feature. */ -function getVendorSearchAvailability(policies: OnyxCollection, isVendorMatchingBetaEnabled: boolean): VendorSearchAvailability { - let isAvailable = false; - let areAllEligiblePoliciesXero = true; - for (const policy of Object.values(policies ?? {})) { - if (!hasVendorFeature(policy, isVendorMatchingBetaEnabled)) { - continue; - } - isAvailable = true; - if (!isXeroActiveMatchingSource(policy)) { - areAllEligiblePoliciesXero = false; - } - } - return {isAvailable, shouldUseSupplierLabel: isAvailable && areAllEligiblePoliciesXero}; +function hasVendorFeatureOnAnyPolicy(policies: OnyxCollection, isVendorMatchingBetaEnabled: boolean): boolean { + return Object.values(policies ?? {}).some((policy) => hasVendorFeature(policy, isVendorMatchingBetaEnabled)); } /** @@ -3537,7 +3517,7 @@ export { isXeroActiveMatchingSource, isXeroVendorMatchingActive, hasVendorFeature, - getVendorSearchAvailability, + hasVendorFeatureOnAnyPolicy, isMatchingVendorListLoaded, getValidConnectedIntegration, getCountOfEnabledTagsOfList, diff --git a/src/libs/SearchUIUtils.ts b/src/libs/SearchUIUtils.ts index 855118ffbe04..a8c426554884 100644 --- a/src/libs/SearchUIUtils.ts +++ b/src/libs/SearchUIUtils.ts @@ -4307,10 +4307,7 @@ function getCustomColumnDefault(value?: SearchDataTypes | SearchGroupBy): Search } } -/** - * Xero calls vendors suppliers, so the vendor column reads "Supplier" when every eligible workspace takes its vendors from Xero. - */ -function getSearchColumnTranslationKey(column: SearchSortBy, shouldUseSupplierLabel = false): TranslationPaths { +function getSearchColumnTranslationKey(column: SearchSortBy): TranslationPaths { switch (column) { case CONST.SEARCH.TABLE_COLUMNS.AVATAR: return 'common.avatar'; @@ -4333,7 +4330,7 @@ function getSearchColumnTranslationKey(column: SearchSortBy, shouldUseSupplierLa case CONST.SEARCH.TABLE_COLUMNS.MERCHANT: return 'common.merchant'; case CONST.SEARCH.TABLE_COLUMNS.VENDOR: - return shouldUseSupplierLabel ? 'common.supplier' : 'common.vendor'; + return 'common.vendor'; case CONST.SEARCH.TABLE_COLUMNS.DESCRIPTION: return 'common.description'; case CONST.SEARCH.TABLE_COLUMNS.FROM: diff --git a/src/pages/Search/SearchColumnsPage.tsx b/src/pages/Search/SearchColumnsPage.tsx index 8e222ba8a8c0..bc133ee88116 100644 --- a/src/pages/Search/SearchColumnsPage.tsx +++ b/src/pages/Search/SearchColumnsPage.tsx @@ -6,7 +6,7 @@ import useOnyx from '@hooks/useOnyx'; import usePermissions from '@hooks/usePermissions'; import Navigation from '@libs/Navigation/Navigation'; -import {getVendorSearchAvailability} from '@libs/PolicyUtils'; +import {hasVendorFeatureOnAnyPolicy} from '@libs/PolicyUtils'; import {buildQueryStringFromFilterFormValues, getCurrentSearchQueryJSON, hasValuesIncludeViolationFilter} from '@libs/SearchQueryUtils'; import {getCustomColumnDefault, getCustomColumns, insertColumnBeforeTotalAmount} from '@libs/SearchUIUtils'; @@ -25,10 +25,9 @@ function SearchColumnsPage() { const {currentSearchKey} = useSearchQueryContext(); const {isBetaEnabled} = usePermissions(); const isVendorMatchingBetaEnabled = isBetaEnabled(CONST.BETAS.VENDOR_MATCHING); - const [vendorSearchAvailability] = useOnyx(ONYXKEYS.COLLECTION.POLICY, { - selector: (allPolicies: OnyxCollection) => getVendorSearchAvailability(allPolicies, isVendorMatchingBetaEnabled), + const [isVendorColumnAvailable = false] = useOnyx(ONYXKEYS.COLLECTION.POLICY, { + selector: (allPolicies: OnyxCollection) => hasVendorFeatureOnAnyPolicy(allPolicies, isVendorMatchingBetaEnabled), }); - const isVendorColumnAvailable = vendorSearchAvailability?.isAvailable ?? false; const groupBy = searchAdvancedFiltersForm?.groupBy; const queryType = searchAdvancedFiltersForm?.type ?? CONST.SEARCH.DATA_TYPES.EXPENSE; @@ -97,7 +96,6 @@ function SearchColumnsPage() { groupBy={groupBy} groupColumns={allGroupCustomColumns} defaultGroupColumns={defaultGroupCustomColumns} - shouldUseSupplierLabel={vendorSearchAvailability?.shouldUseSupplierLabel} onSave={applyChanges} /> ); diff --git a/src/pages/settings/Report/ReportDetailsColumnsPage.tsx b/src/pages/settings/Report/ReportDetailsColumnsPage.tsx index 73bea8de328e..2428e21379e2 100644 --- a/src/pages/settings/Report/ReportDetailsColumnsPage.tsx +++ b/src/pages/settings/Report/ReportDetailsColumnsPage.tsx @@ -9,7 +9,7 @@ import {setReportDetailsColumns} from '@libs/actions/ReportLayout'; import {isBillableEnabledOnPolicy} from '@libs/MoneyRequestReportUtils'; import Navigation from '@libs/Navigation/Navigation'; import type {PlatformStackRouteProp} from '@libs/Navigation/PlatformStackNavigation/types'; -import {hasVendorFeature, isPolicyTaxEnabled, isXeroActiveMatchingSource} from '@libs/PolicyUtils'; +import {hasVendorFeature, isPolicyTaxEnabled} from '@libs/PolicyUtils'; import {isIOUReport} from '@libs/ReportUtils'; import {getColumnsToShow} from '@libs/SearchUIUtils'; import {hasNonReimbursableTransactions} from '@libs/TransactionUtils'; @@ -129,7 +129,6 @@ function ReportDetailsColumnsPage() { defaultSelectedColumns={REPORT_DETAILS_DEFAULT_COLUMNS} currentColumns={currentColumns} requiredColumns={requiredColumns} - shouldUseSupplierLabel={isXeroActiveMatchingSource(policy)} onSave={handleSave} /> ); diff --git a/tests/unit/PolicyUtilsTest.ts b/tests/unit/PolicyUtilsTest.ts index c04066044f01..c123ac79551b 100644 --- a/tests/unit/PolicyUtilsTest.ts +++ b/tests/unit/PolicyUtilsTest.ts @@ -16,7 +16,7 @@ import { evaluateApprovalWorkflowRule, findVendorByID, getVendorDisplayName, - getVendorSearchAvailability, + hasVendorFeatureOnAnyPolicy, getActivePolicies, getActivePoliciesWithExpenseChat, getActivePoliciesWithExpenseChatAndPerDiemEnabled, @@ -4623,7 +4623,7 @@ describe('PolicyUtils', () => { }); }); - describe('getVendorSearchAvailability', () => { + describe('hasVendorFeatureOnAnyPolicy', () => { const qboPolicy: Policy = {...buildQBOPolicy(CONST.QUICKBOOKS_NON_REIMBURSABLE_EXPORT_ACCOUNT_TYPE.CREDIT_CARD), id: 'qbo'}; const xeroPolicy: Policy = {...buildXeroPolicy(), id: 'xero'}; const plainPolicy: Policy = {...createRandomPolicy(3), connections: undefined, id: 'plain'}; @@ -4631,24 +4631,20 @@ describe('PolicyUtils', () => { const xeroKey = `${ONYXKEYS.COLLECTION.POLICY}xero`; const plainKey = `${ONYXKEYS.COLLECTION.POLICY}plain`; - it('is unavailable when no workspace has the vendor feature', () => { - expect(getVendorSearchAvailability({[plainKey]: plainPolicy}, true)).toEqual({isAvailable: false, shouldUseSupplierLabel: false}); + it('is false when no workspace has the vendor feature', () => { + expect(hasVendorFeatureOnAnyPolicy({[plainKey]: plainPolicy}, true)).toBe(false); }); - it('is available with the vendor label for a QBO workspace exporting card expenses as credit card transactions, without the beta', () => { - expect(getVendorSearchAvailability({[qboKey]: qboPolicy, [plainKey]: plainPolicy}, false)).toEqual({isAvailable: true, shouldUseSupplierLabel: false}); + it('is true for a QBO workspace exporting card expenses as credit card transactions, without the beta', () => { + expect(hasVendorFeatureOnAnyPolicy({[qboKey]: qboPolicy, [plainKey]: plainPolicy}, false)).toBe(true); }); - it('uses the supplier label when every eligible workspace takes its vendors from Xero', () => { - expect(getVendorSearchAvailability({[xeroKey]: xeroPolicy, [plainKey]: plainPolicy}, true)).toEqual({isAvailable: true, shouldUseSupplierLabel: true}); - }); - - it('keeps the vendor label when Xero and QBO workspaces are both eligible', () => { - expect(getVendorSearchAvailability({[xeroKey]: xeroPolicy, [qboKey]: qboPolicy}, true)).toEqual({isAvailable: true, shouldUseSupplierLabel: false}); + it('is true for a Xero workspace with the beta', () => { + expect(hasVendorFeatureOnAnyPolicy({[xeroKey]: xeroPolicy, [plainKey]: plainPolicy}, true)).toBe(true); }); it('ignores beta-gated integrations while the beta is off', () => { - expect(getVendorSearchAvailability({[xeroKey]: xeroPolicy}, false).isAvailable).toBe(false); + expect(hasVendorFeatureOnAnyPolicy({[xeroKey]: xeroPolicy}, false)).toBe(false); }); }); diff --git a/tests/unit/Search/SearchUIUtilsTest.ts b/tests/unit/Search/SearchUIUtilsTest.ts index bd66dd756ba7..de756d9eacca 100644 --- a/tests/unit/Search/SearchUIUtilsTest.ts +++ b/tests/unit/Search/SearchUIUtilsTest.ts @@ -13988,13 +13988,8 @@ describe('SearchUIUtils', () => { }); describe('vendor column label', () => { - test('Should label the vendor column as Vendor by default and as Supplier for Xero-only workspaces', () => { + test('Should label the vendor column as Vendor', () => { expect(SearchUIUtils.getSearchColumnTranslationKey(CONST.SEARCH.TABLE_COLUMNS.VENDOR)).toBe('common.vendor'); - expect(SearchUIUtils.getSearchColumnTranslationKey(CONST.SEARCH.TABLE_COLUMNS.VENDOR, true)).toBe('common.supplier'); - }); - - test('Should leave other labels untouched when the supplier wording is on', () => { - expect(SearchUIUtils.getSearchColumnTranslationKey(CONST.SEARCH.TABLE_COLUMNS.CATEGORY, true)).toBe('common.category'); }); }); From 6f79486332705f6b2298afb08fb400f3f3861e4c Mon Sep 17 00:00:00 2001 From: Krishna Chaitanya Date: Fri, 18 Sep 2026 21:57:50 +0530 Subject: [PATCH 8/8] Memoize the vendor column availability selector --- src/pages/Search/SearchColumnsPage.tsx | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/pages/Search/SearchColumnsPage.tsx b/src/pages/Search/SearchColumnsPage.tsx index bc133ee88116..6af89ca55bd7 100644 --- a/src/pages/Search/SearchColumnsPage.tsx +++ b/src/pages/Search/SearchColumnsPage.tsx @@ -18,16 +18,18 @@ import type {Policy} from '@src/types/onyx'; import type {OnyxCollection} from 'react-native-onyx'; -import React from 'react'; +import React, {useCallback} from 'react'; function SearchColumnsPage() { const [searchAdvancedFiltersForm] = useOnyx(ONYXKEYS.FORMS.SEARCH_ADVANCED_FILTERS_FORM); const {currentSearchKey} = useSearchQueryContext(); const {isBetaEnabled} = usePermissions(); const isVendorMatchingBetaEnabled = isBetaEnabled(CONST.BETAS.VENDOR_MATCHING); - const [isVendorColumnAvailable = false] = useOnyx(ONYXKEYS.COLLECTION.POLICY, { - selector: (allPolicies: OnyxCollection) => hasVendorFeatureOnAnyPolicy(allPolicies, isVendorMatchingBetaEnabled), - }); + const isVendorColumnAvailableSelector = useCallback( + (allPolicies: OnyxCollection) => hasVendorFeatureOnAnyPolicy(allPolicies, isVendorMatchingBetaEnabled), + [isVendorMatchingBetaEnabled], + ); + const [isVendorColumnAvailable = false] = useOnyx(ONYXKEYS.COLLECTION.POLICY, {selector: isVendorColumnAvailableSelector}); const groupBy = searchAdvancedFiltersForm?.groupBy; const queryType = searchAdvancedFiltersForm?.type ?? CONST.SEARCH.DATA_TYPES.EXPENSE;