From 430a63ed0683dd14ff372f54266b8df4d414da4e Mon Sep 17 00:00:00 2001 From: TaduJR Date: Wed, 28 Jan 2026 00:03:27 +0300 Subject: [PATCH 01/24] feat: [Insights] [Release 2] Top Merchants - Add group-by:merchant and suggested search --- src/CONST/index.ts | 10 + src/components/Search/index.tsx | 14 + src/components/Search/types.ts | 3 +- .../Search/BaseListItemHeader.tsx | 165 ++++++ .../Search/CategoryListItemHeader.tsx | 104 +--- .../Search/MerchantListItemHeader.tsx | 68 +++ .../Search/TransactionGroupListItem.tsx | 15 + .../SearchTableHeader.tsx | 18 + .../SelectionListWithSections/types.ts | 17 +- src/hooks/useSearchTypeMenu.tsx | 3 + src/languages/de.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/SearchUIUtils.ts | 125 ++++- src/pages/Search/SearchColumnsPage.tsx | 1 + src/pages/Search/SearchTypeMenu.tsx | 3 + src/types/onyx/SearchResults.ts | 18 +- tests/ui/MerchantListItemHeaderTest.tsx | 364 ++++++++++++++ tests/unit/Search/SearchUIUtilsTest.ts | 474 ++++++++++++++++++ 26 files changed, 1325 insertions(+), 97 deletions(-) create mode 100644 src/components/SelectionListWithSections/Search/BaseListItemHeader.tsx create mode 100644 src/components/SelectionListWithSections/Search/MerchantListItemHeader.tsx create mode 100644 tests/ui/MerchantListItemHeaderTest.tsx diff --git a/src/CONST/index.ts b/src/CONST/index.ts index a4281c1ad1fae..a5f849b9520f3 100755 --- a/src/CONST/index.ts +++ b/src/CONST/index.ts @@ -6842,6 +6842,7 @@ const CONST = { CARD: 'card', WITHDRAWAL_ID: 'withdrawal-id', CATEGORY: 'category', + MERCHANT: 'merchant', }, get TYPE_CUSTOM_COLUMNS() { return { @@ -6923,6 +6924,11 @@ const CONST = { EXPENSES: this.TABLE_COLUMNS.GROUP_EXPENSES, TOTAL: this.TABLE_COLUMNS.GROUP_TOTAL, }, + MERCHANT: { + MERCHANT: this.TABLE_COLUMNS.GROUP_MERCHANT, + EXPENSES: this.TABLE_COLUMNS.GROUP_EXPENSES, + TOTAL: this.TABLE_COLUMNS.GROUP_TOTAL, + }, }; }, get TYPE_DEFAULT_COLUMNS() { @@ -6965,6 +6971,7 @@ const CONST = { this.TABLE_COLUMNS.GROUP_TOTAL, ], CATEGORY: [this.TABLE_COLUMNS.GROUP_CATEGORY, this.TABLE_COLUMNS.GROUP_EXPENSES, this.TABLE_COLUMNS.GROUP_TOTAL], + MERCHANT: [this.TABLE_COLUMNS.GROUP_MERCHANT, this.TABLE_COLUMNS.GROUP_EXPENSES, this.TABLE_COLUMNS.GROUP_TOTAL], }; }, BOOLEAN: { @@ -7061,6 +7068,7 @@ const CONST = { GROUP_WITHDRAWN: 'groupWithdrawn', GROUP_WITHDRAWAL_ID: 'groupWithdrawalID', GROUP_CATEGORY: 'groupCategory', + GROUP_MERCHANT: 'groupMerchant', }, SYNTAX_OPERATORS: { AND: 'and', @@ -7244,6 +7252,7 @@ const CONST = { [this.TABLE_COLUMNS.GROUP_WITHDRAWN]: 'group-withdrawn', [this.TABLE_COLUMNS.GROUP_WITHDRAWAL_ID]: 'group-withdrawal-id', [this.TABLE_COLUMNS.GROUP_CATEGORY]: 'group-category', + [this.TABLE_COLUMNS.GROUP_MERCHANT]: 'group-merchant', }; }, NOT_MODIFIER: 'Not', @@ -7286,6 +7295,7 @@ const CONST = { RECONCILIATION: 'reconciliation', TOP_SPENDERS: 'topSpenders', TOP_CATEGORIES: 'topCategories', + TOP_MERCHANTS: 'topMerchants', }, GROUP_PREFIX: 'group_', ANIMATION: { diff --git a/src/components/Search/index.tsx b/src/components/Search/index.tsx index b08800ec89c4c..87e089d94a9d3 100644 --- a/src/components/Search/index.tsx +++ b/src/components/Search/index.tsx @@ -55,6 +55,7 @@ import { isTransactionGroupListItemType, isTransactionListItemType, isTransactionMemberGroupListItemType, + isTransactionMerchantGroupListItemType, isTransactionWithdrawalIDGroupListItemType, shouldShowEmptyState, shouldShowYear as shouldShowYearUtil, @@ -826,6 +827,19 @@ function Search({ return; } + if (isTransactionMerchantGroupListItemType(item)) { + const newFlatFilters = queryJSON.flatFilters.filter((filter) => filter.key !== CONST.SEARCH.SYNTAX_FILTER_KEYS.MERCHANT); + newFlatFilters.push({key: CONST.SEARCH.SYNTAX_FILTER_KEYS.MERCHANT, filters: [{operator: CONST.SEARCH.SYNTAX_OPERATORS.EQUAL_TO, value: item.merchant}]}); + const newQueryJSON: SearchQueryJSON = {...queryJSON, groupBy: undefined, flatFilters: newFlatFilters}; + const newQuery = buildSearchQueryString(newQueryJSON); + const newQueryJSONWithHash = buildSearchQueryJSON(newQuery); + if (!newQueryJSONWithHash) { + return; + } + handleSearch({queryJSON: newQueryJSONWithHash, searchKey, offset: 0, shouldCalculateTotals: false, isLoading: false}); + return; + } + let reportID = item.reportID; if (isTransactionItem && item?.reportAction?.childReportID) { const isFromSelfDM = item.reportID === CONST.REPORT.UNREPORTED_REPORT_ID; diff --git a/src/components/Search/types.ts b/src/components/Search/types.ts index 8fc0158c72fab..bc6cf9d85dcc2 100644 --- a/src/components/Search/types.ts +++ b/src/components/Search/types.ts @@ -123,7 +123,8 @@ type SearchCustomColumnIds = | ValueOf | ValueOf | ValueOf - | ValueOf; + | ValueOf + | ValueOf; type SearchContextData = { currentSearchHash: number; diff --git a/src/components/SelectionListWithSections/Search/BaseListItemHeader.tsx b/src/components/SelectionListWithSections/Search/BaseListItemHeader.tsx new file mode 100644 index 0000000000000..a8bf835fe4fa4 --- /dev/null +++ b/src/components/SelectionListWithSections/Search/BaseListItemHeader.tsx @@ -0,0 +1,165 @@ +import React from 'react'; +import {View} from 'react-native'; +import Checkbox from '@components/Checkbox'; +import type {SearchColumnType} from '@components/Search/types'; +import type {ListItem, TransactionGroupListItemType} from '@components/SelectionListWithSections/types'; +import TextWithTooltip from '@components/TextWithTooltip'; +import useLocalize from '@hooks/useLocalize'; +import useResponsiveLayout from '@hooks/useResponsiveLayout'; +import useStyleUtils from '@hooks/useStyleUtils'; +import useThemeStyles from '@hooks/useThemeStyles'; +import CONST from '@src/CONST'; +import ExpandCollapseArrowButton from './ExpandCollapseArrowButton'; +import TextCell from './TextCell'; +import TotalCell from './TotalCell'; + +/** Base group item type that includes common fields used by simple text-based group headers */ +type BaseGroupListItemType = TransactionGroupListItemType & { + /** Number of transactions in the group */ + count: number; + + /** Total value of transactions */ + total: number; + + /** Currency of total value */ + currency: string; +}; + +type BaseListItemHeaderProps = { + /** The group item being rendered */ + item: BaseGroupListItemType; + + /** The display name to show for this group */ + displayName: string; + + /** The column key for the group name column (e.g., GROUP_CATEGORY, GROUP_MERCHANT) */ + groupColumnKey: typeof CONST.SEARCH.TABLE_COLUMNS.GROUP_CATEGORY | typeof CONST.SEARCH.TABLE_COLUMNS.GROUP_MERCHANT; + + /** The column style key for sizing (e.g., CATEGORY, MERCHANT) */ + columnStyleKey: typeof CONST.SEARCH.TABLE_COLUMNS.CATEGORY | typeof CONST.SEARCH.TABLE_COLUMNS.MERCHANT; + + /** Callback to fire when a checkbox is pressed */ + onCheckboxPress?: (item: TItem) => void; + + /** Whether this section items disabled for selection */ + isDisabled?: boolean | null; + + /** Whether selecting multiple transactions at once is allowed */ + canSelectMultiple: boolean | undefined; + + /** Whether all transactions are selected */ + isSelectAllChecked?: boolean; + + /** Whether only some transactions are selected */ + isIndeterminate?: boolean; + + /** Callback for when the down arrow is clicked */ + onDownArrowClick?: () => void; + + /** Whether the down arrow is expanded */ + isExpanded?: boolean; + + /** The visible columns for the header */ + columns?: SearchColumnType[]; +}; + +function BaseListItemHeader({ + item, + displayName, + groupColumnKey, + columnStyleKey, + onCheckboxPress, + isDisabled, + canSelectMultiple, + isSelectAllChecked, + isIndeterminate, + isExpanded, + onDownArrowClick, + columns, +}: BaseListItemHeaderProps) { + const styles = useThemeStyles(); + const StyleUtils = useStyleUtils(); + const {isLargeScreenWidth} = useResponsiveLayout(); + const {translate} = useLocalize(); + + const columnComponents = { + [groupColumnKey]: ( + + + + + + ), + [CONST.SEARCH.TABLE_COLUMNS.GROUP_EXPENSES]: ( + + + + ), + [CONST.SEARCH.TABLE_COLUMNS.GROUP_TOTAL]: ( + + + + ), + }; + + return ( + + + + {!!canSelectMultiple && ( + onCheckboxPress?.(item as unknown as TItem)} + isChecked={isSelectAllChecked} + isIndeterminate={isIndeterminate} + disabled={!!isDisabled || item.isDisabledCheckbox} + accessibilityLabel={translate('common.select')} + style={isLargeScreenWidth && styles.mr1} + /> + )} + {!isLargeScreenWidth && ( + + + + + + )} + {isLargeScreenWidth && columns?.map((column) => columnComponents[column as keyof typeof columnComponents])} + + {!isLargeScreenWidth && ( + + + {!!onDownArrowClick && ( + + )} + + )} + + + ); +} + +export default BaseListItemHeader; diff --git a/src/components/SelectionListWithSections/Search/CategoryListItemHeader.tsx b/src/components/SelectionListWithSections/Search/CategoryListItemHeader.tsx index ed15962e8f86b..1e4d94b87f292 100644 --- a/src/components/SelectionListWithSections/Search/CategoryListItemHeader.tsx +++ b/src/components/SelectionListWithSections/Search/CategoryListItemHeader.tsx @@ -1,17 +1,9 @@ import React from 'react'; -import {View} from 'react-native'; -import Checkbox from '@components/Checkbox'; import type {SearchColumnType} from '@components/Search/types'; import type {ListItem, TransactionCategoryGroupListItemType} from '@components/SelectionListWithSections/types'; -import TextWithTooltip from '@components/TextWithTooltip'; import useLocalize from '@hooks/useLocalize'; -import useResponsiveLayout from '@hooks/useResponsiveLayout'; -import useStyleUtils from '@hooks/useStyleUtils'; -import useThemeStyles from '@hooks/useThemeStyles'; import CONST from '@src/CONST'; -import ExpandCollapseArrowButton from './ExpandCollapseArrowButton'; -import TextCell from './TextCell'; -import TotalCell from './TotalCell'; +import BaseListItemHeader from './BaseListItemHeader'; type CategoryListItemHeaderProps = { /** The category currently being looked at */ @@ -53,91 +45,27 @@ function CategoryListItemHeader({ onDownArrowClick, columns, }: CategoryListItemHeaderProps) { - const styles = useThemeStyles(); - const StyleUtils = useStyleUtils(); - const {isLargeScreenWidth} = useResponsiveLayout(); const {translate} = useLocalize(); + // formattedCategory is pre-decoded in SearchUIUtils, just translate empty values const rawCategory = categoryItem.formattedCategory ?? categoryItem.category; const categoryName = !rawCategory || rawCategory === CONST.SEARCH.CATEGORY_EMPTY_VALUE ? translate('reportLayout.uncategorized') : rawCategory; - const columnComponents = { - [CONST.SEARCH.TABLE_COLUMNS.GROUP_CATEGORY]: ( - - - - - - ), - [CONST.SEARCH.TABLE_COLUMNS.GROUP_EXPENSES]: ( - - - - ), - [CONST.SEARCH.TABLE_COLUMNS.GROUP_TOTAL]: ( - - - - ), - }; - return ( - - - - {!!canSelectMultiple && ( - onCheckboxPress?.(categoryItem as unknown as TItem)} - isChecked={isSelectAllChecked} - isIndeterminate={isIndeterminate} - disabled={!!isDisabled || categoryItem.isDisabledCheckbox} - accessibilityLabel={translate('common.select')} - style={isLargeScreenWidth && styles.mr1} - /> - )} - {!isLargeScreenWidth && ( - - - - - - )} - {isLargeScreenWidth && columns?.map((column) => columnComponents[column as keyof typeof columnComponents])} - - {!isLargeScreenWidth && ( - - - {!!onDownArrowClick && ( - - )} - - )} - - + ); } diff --git a/src/components/SelectionListWithSections/Search/MerchantListItemHeader.tsx b/src/components/SelectionListWithSections/Search/MerchantListItemHeader.tsx new file mode 100644 index 0000000000000..3c61f44b776c0 --- /dev/null +++ b/src/components/SelectionListWithSections/Search/MerchantListItemHeader.tsx @@ -0,0 +1,68 @@ +import React from 'react'; +import type {SearchColumnType} from '@components/Search/types'; +import type {ListItem, TransactionMerchantGroupListItemType} from '@components/SelectionListWithSections/types'; +import CONST from '@src/CONST'; +import BaseListItemHeader from './BaseListItemHeader'; + +type MerchantListItemHeaderProps = { + /** The merchant currently being looked at */ + merchant: TransactionMerchantGroupListItemType; + + /** Callback to fire when a checkbox is pressed */ + onCheckboxPress?: (item: TItem) => void; + + /** Whether this section items disabled for selection */ + isDisabled?: boolean | null; + + /** Whether selecting multiple transactions at once is allowed */ + canSelectMultiple: boolean | undefined; + + /** Whether all transactions are selected */ + isSelectAllChecked?: boolean; + + /** Whether only some transactions are selected */ + isIndeterminate?: boolean; + + /** Callback for when the down arrow is clicked */ + onDownArrowClick?: () => void; + + /** Whether the down arrow is expanded */ + isExpanded?: boolean; + + /** The visible columns for the header */ + columns?: SearchColumnType[]; +}; + +function MerchantListItemHeader({ + merchant: merchantItem, + onCheckboxPress, + isDisabled, + canSelectMultiple, + isSelectAllChecked, + isIndeterminate, + isExpanded, + onDownArrowClick, + columns, +}: MerchantListItemHeaderProps) { + const rawMerchant = merchantItem.formattedMerchant ?? merchantItem.merchant; + const merchantName = rawMerchant || CONST.TRANSACTION.UNKNOWN_MERCHANT; + + return ( + + ); +} + +export default MerchantListItemHeader; diff --git a/src/components/SelectionListWithSections/Search/TransactionGroupListItem.tsx b/src/components/SelectionListWithSections/Search/TransactionGroupListItem.tsx index 6c01b1b80c42d..978b419d111b5 100644 --- a/src/components/SelectionListWithSections/Search/TransactionGroupListItem.tsx +++ b/src/components/SelectionListWithSections/Search/TransactionGroupListItem.tsx @@ -18,6 +18,7 @@ import type { TransactionGroupListItemType, TransactionListItemType, TransactionMemberGroupListItemType, + TransactionMerchantGroupListItemType, TransactionReportGroupListItemType, TransactionWithdrawalIDGroupListItemType, } from '@components/SelectionListWithSections/types'; @@ -42,6 +43,7 @@ import type {ReportAction, ReportActions} from '@src/types/onyx'; import CardListItemHeader from './CardListItemHeader'; import CategoryListItemHeader from './CategoryListItemHeader'; import MemberListItemHeader from './MemberListItemHeader'; +import MerchantListItemHeader from './MerchantListItemHeader'; import ReportListItemHeader from './ReportListItemHeader'; import TransactionGroupListExpandedItem from './TransactionGroupListExpanded'; import WithdrawalIDListItemHeader from './WithdrawalIDListItemHeader'; @@ -296,6 +298,19 @@ function TransactionGroupListItem({ isExpanded={isExpanded} /> ), + [CONST.SEARCH.GROUP_BY.MERCHANT]: ( + + ), }; if (searchType === CONST.SEARCH.DATA_TYPES.EXPENSE_REPORT) { diff --git a/src/components/SelectionListWithSections/SearchTableHeader.tsx b/src/components/SelectionListWithSections/SearchTableHeader.tsx index 758af3afc6b53..5c16dcadb1122 100644 --- a/src/components/SelectionListWithSections/SearchTableHeader.tsx +++ b/src/components/SelectionListWithSections/SearchTableHeader.tsx @@ -355,6 +355,24 @@ const getTransactionGroupHeaders = (groupBy: SearchGroupBy, icons: SearchHeaderI isColumnSortable: true, }, ]; + case CONST.SEARCH.GROUP_BY.MERCHANT: + return [ + { + columnName: CONST.SEARCH.TABLE_COLUMNS.GROUP_MERCHANT, + translationKey: 'common.merchant', + isColumnSortable: true, + }, + { + columnName: CONST.SEARCH.TABLE_COLUMNS.GROUP_EXPENSES, + translationKey: 'common.expenses', + isColumnSortable: true, + }, + { + columnName: CONST.SEARCH.TABLE_COLUMNS.GROUP_TOTAL, + translationKey: 'common.total', + isColumnSortable: true, + }, + ]; default: return []; } diff --git a/src/components/SelectionListWithSections/types.ts b/src/components/SelectionListWithSections/types.ts index ab63f246a7fdd..d9ff62342cebe 100644 --- a/src/components/SelectionListWithSections/types.ts +++ b/src/components/SelectionListWithSections/types.ts @@ -28,7 +28,16 @@ import type CONST from '@src/CONST'; import type {PersonalDetails, PersonalDetailsList, Policy, Report, ReportAction, SearchResults, TransactionViolation, TransactionViolations} from '@src/types/onyx'; import type {Attendee} from '@src/types/onyx/IOU'; import type {Errors, Icon, PendingAction} from '@src/types/onyx/OnyxCommon'; -import type {SearchCardGroup, SearchCategoryGroup, SearchDataTypes, SearchMemberGroup, SearchTask, SearchTransactionAction, SearchWithdrawalIDGroup} from '@src/types/onyx/SearchResults'; +import type { + SearchCardGroup, + SearchCategoryGroup, + SearchDataTypes, + SearchMemberGroup, + SearchMerchantGroup, + SearchTask, + SearchTransactionAction, + SearchWithdrawalIDGroup, +} from '@src/types/onyx/SearchResults'; import type {ReceiptErrors} from '@src/types/onyx/Transaction'; import type Transaction from '@src/types/onyx/Transaction'; import type ChildrenProps from '@src/types/utils/ChildrenProps'; @@ -494,6 +503,11 @@ type TransactionCategoryGroupListItemType = TransactionGroupListItemType & {grou formattedCategory?: string; }; +type TransactionMerchantGroupListItemType = TransactionGroupListItemType & {groupedBy: typeof CONST.SEARCH.GROUP_BY.MERCHANT} & SearchMerchantGroup & { + /** Final and formatted "merchant" value used for displaying and sorting */ + formattedMerchant?: string; + }; + type ListItemProps = CommonListItemProps & { /** The section list item */ item: TItem; @@ -1136,6 +1150,7 @@ export type { TransactionCardGroupListItemType, TransactionWithdrawalIDGroupListItemType, TransactionCategoryGroupListItemType, + TransactionMerchantGroupListItemType, Section, SectionListDataType, SectionWithIndexOffset, diff --git a/src/hooks/useSearchTypeMenu.tsx b/src/hooks/useSearchTypeMenu.tsx index 3eeaaf89f6e90..9733b1e08bb9b 100644 --- a/src/hooks/useSearchTypeMenu.tsx +++ b/src/hooks/useSearchTypeMenu.tsx @@ -61,6 +61,9 @@ export default function useSearchTypeMenu(queryJSON: SearchQueryJSON) { 'MoneyHourglass', 'CreditCardHourglass', 'Bank', + 'User', + 'Folder', + 'Building', ] as const); const [isPopoverVisible, setIsPopoverVisible] = useState(false); diff --git a/src/languages/de.ts b/src/languages/de.ts index 9dbe2a90e6014..0e3c1d8c5197c 100644 --- a/src/languages/de.ts +++ b/src/languages/de.ts @@ -6864,6 +6864,7 @@ Fordere Spesendetails wie Belege und Beschreibungen an, lege Limits und Standard searchName: 'Name suchen', savedSearchesMenuItemTitle: 'Gespeichert', topCategories: 'Top-Kategorien', + topMerchants: 'Top-Händler', groupedExpenses: 'gruppierte Ausgaben', bulkActions: { approve: 'Genehmigen', @@ -6925,6 +6926,7 @@ Fordere Spesendetails wie Belege und Beschreibungen an, lege Limits und Standard [CONST.SEARCH.GROUP_BY.CARD]: 'Karte', [CONST.SEARCH.GROUP_BY.WITHDRAWAL_ID]: 'Auszahlungs-ID', [CONST.SEARCH.GROUP_BY.CATEGORY]: 'Kategorie', + [CONST.SEARCH.GROUP_BY.MERCHANT]: 'Händler', }, feed: 'Feed', withdrawalType: { diff --git a/src/languages/en.ts b/src/languages/en.ts index c5025b2ffeffc..3388529e0903b 100644 --- a/src/languages/en.ts +++ b/src/languages/en.ts @@ -6750,6 +6750,7 @@ const translations = { searchName: 'Search name', savedSearchesMenuItemTitle: 'Saved', topCategories: 'Top categories', + topMerchants: 'Top merchants', groupedExpenses: 'grouped expenses', bulkActions: { approve: 'Approve', @@ -6811,6 +6812,7 @@ const translations = { [CONST.SEARCH.GROUP_BY.CARD]: 'Card', [CONST.SEARCH.GROUP_BY.WITHDRAWAL_ID]: 'Withdrawal ID', [CONST.SEARCH.GROUP_BY.CATEGORY]: 'Category', + [CONST.SEARCH.GROUP_BY.MERCHANT]: 'Merchant', }, feed: 'Feed', withdrawalType: { diff --git a/src/languages/es.ts b/src/languages/es.ts index c8961f508b267..cccc5c5fd392d 100644 --- a/src/languages/es.ts +++ b/src/languages/es.ts @@ -6497,6 +6497,7 @@ ${amount} para ${merchant} - ${date}`, saveSearch: 'Guardar búsqueda', savedSearchesMenuItemTitle: 'Guardadas', topCategories: 'Categorías principales', + topMerchants: 'Principales comerciantes', searchName: 'Nombre de la búsqueda', deleteSavedSearch: 'Eliminar búsqueda guardada', deleteSavedSearchConfirm: '¿Estás seguro de que quieres eliminar esta búsqueda?', @@ -6559,6 +6560,7 @@ ${amount} para ${merchant} - ${date}`, [CONST.SEARCH.GROUP_BY.CARD]: 'Tarjeta', [CONST.SEARCH.GROUP_BY.WITHDRAWAL_ID]: 'ID de retiro', [CONST.SEARCH.GROUP_BY.CATEGORY]: 'Categoría', + [CONST.SEARCH.GROUP_BY.MERCHANT]: 'Comerciante', }, feed: 'Feed', withdrawalType: { diff --git a/src/languages/fr.ts b/src/languages/fr.ts index 8e5ea4c8f31b2..6085e903e24a7 100644 --- a/src/languages/fr.ts +++ b/src/languages/fr.ts @@ -6875,6 +6875,7 @@ Exigez des informations de dépense comme les reçus et les descriptions, défin searchName: 'Rechercher un nom', savedSearchesMenuItemTitle: 'Enregistré', topCategories: 'Catégories principales', + topMerchants: 'Principaux commerçants', groupedExpenses: 'dépenses groupées', bulkActions: { approve: 'Approuver', @@ -6936,6 +6937,7 @@ Exigez des informations de dépense comme les reçus et les descriptions, défin [CONST.SEARCH.GROUP_BY.CARD]: 'Carte', [CONST.SEARCH.GROUP_BY.WITHDRAWAL_ID]: 'ID de retrait', [CONST.SEARCH.GROUP_BY.CATEGORY]: 'Catégorie', + [CONST.SEARCH.GROUP_BY.MERCHANT]: 'Commerçant', }, feed: 'Flux', withdrawalType: { diff --git a/src/languages/it.ts b/src/languages/it.ts index ee09a7f6314eb..3c895e9b4d394 100644 --- a/src/languages/it.ts +++ b/src/languages/it.ts @@ -6854,6 +6854,7 @@ Richiedi dettagli di spesa come ricevute e descrizioni, imposta limiti e valori searchName: 'Cerca nome', savedSearchesMenuItemTitle: 'Salvato', topCategories: 'Categorie principali', + topMerchants: 'Principali commercianti', groupedExpenses: 'spese raggruppate', bulkActions: { approve: 'Approva', @@ -6915,6 +6916,7 @@ Richiedi dettagli di spesa come ricevute e descrizioni, imposta limiti e valori [CONST.SEARCH.GROUP_BY.CARD]: 'Carta', [CONST.SEARCH.GROUP_BY.WITHDRAWAL_ID]: 'ID prelievo', [CONST.SEARCH.GROUP_BY.CATEGORY]: 'Categoria', + [CONST.SEARCH.GROUP_BY.MERCHANT]: 'Commerciante', }, feed: 'Feed', withdrawalType: { diff --git a/src/languages/ja.ts b/src/languages/ja.ts index a4aecc65c5324..304d17a9f82ba 100644 --- a/src/languages/ja.ts +++ b/src/languages/ja.ts @@ -6795,6 +6795,7 @@ ${reportName} searchName: '名前を検索', savedSearchesMenuItemTitle: '保存済み', topCategories: 'トップカテゴリ', + topMerchants: 'トップマーチャント', groupedExpenses: 'グループ化された経費', bulkActions: { approve: '承認', @@ -6856,6 +6857,7 @@ ${reportName} [CONST.SEARCH.GROUP_BY.CARD]: 'カード', [CONST.SEARCH.GROUP_BY.WITHDRAWAL_ID]: '出金ID', [CONST.SEARCH.GROUP_BY.CATEGORY]: 'カテゴリー', + [CONST.SEARCH.GROUP_BY.MERCHANT]: '加盟店', }, feed: 'フィード', withdrawalType: { diff --git a/src/languages/nl.ts b/src/languages/nl.ts index 5b0db59e1cded..fee8f39278455 100644 --- a/src/languages/nl.ts +++ b/src/languages/nl.ts @@ -6836,6 +6836,7 @@ Vraag verplichte uitgavedetails zoals bonnetjes en beschrijvingen, stel limieten searchName: 'Naam zoeken', savedSearchesMenuItemTitle: 'Opgeslagen', topCategories: 'Topcategorieën', + topMerchants: 'Topverkopers', groupedExpenses: 'gegroepeerde uitgaven', bulkActions: { approve: 'Goedkeuren', @@ -6897,6 +6898,7 @@ Vraag verplichte uitgavedetails zoals bonnetjes en beschrijvingen, stel limieten [CONST.SEARCH.GROUP_BY.CARD]: 'Kaart', [CONST.SEARCH.GROUP_BY.WITHDRAWAL_ID]: 'Opname-ID', [CONST.SEARCH.GROUP_BY.CATEGORY]: 'Categorie', + [CONST.SEARCH.GROUP_BY.MERCHANT]: 'Verkoper', }, feed: 'Feed', withdrawalType: { diff --git a/src/languages/pl.ts b/src/languages/pl.ts index dea21683527cd..1c3a19c4b4709 100644 --- a/src/languages/pl.ts +++ b/src/languages/pl.ts @@ -6825,6 +6825,7 @@ Wymagaj szczegółów wydatków, takich jak paragony i opisy, ustawiaj limity i searchName: 'Wyszukaj nazwę', savedSearchesMenuItemTitle: 'Zapisano', topCategories: 'Najlepsze kategorie', + topMerchants: 'Najlepsi sprzedawcy', groupedExpenses: 'pogrupowane wydatki', bulkActions: { approve: 'Zatwierdź', @@ -6886,6 +6887,7 @@ Wymagaj szczegółów wydatków, takich jak paragony i opisy, ustawiaj limity i [CONST.SEARCH.GROUP_BY.CARD]: 'Karta', [CONST.SEARCH.GROUP_BY.WITHDRAWAL_ID]: 'ID wypłaty', [CONST.SEARCH.GROUP_BY.CATEGORY]: 'Kategoria', + [CONST.SEARCH.GROUP_BY.MERCHANT]: 'Sprzedawca', }, feed: 'Kanał', withdrawalType: { diff --git a/src/languages/pt-BR.ts b/src/languages/pt-BR.ts index a4c33c4793ef1..1600af8846115 100644 --- a/src/languages/pt-BR.ts +++ b/src/languages/pt-BR.ts @@ -6827,6 +6827,7 @@ Exija detalhes de despesas como recibos e descrições, defina limites e padrõe searchName: 'Pesquisar nome', savedSearchesMenuItemTitle: 'Salvo', topCategories: 'Principais categorias', + topMerchants: 'Principais comerciantes', groupedExpenses: 'despesas agrupadas', bulkActions: { approve: 'Aprovar', @@ -6888,6 +6889,7 @@ Exija detalhes de despesas como recibos e descrições, defina limites e padrõe [CONST.SEARCH.GROUP_BY.CARD]: 'Cartão', [CONST.SEARCH.GROUP_BY.WITHDRAWAL_ID]: 'ID de saque', [CONST.SEARCH.GROUP_BY.CATEGORY]: 'Categoria', + [CONST.SEARCH.GROUP_BY.MERCHANT]: 'Comerciante', }, feed: 'Feed', withdrawalType: { diff --git a/src/languages/zh-hans.ts b/src/languages/zh-hans.ts index cefb15fbbc51c..668dfb959bf50 100644 --- a/src/languages/zh-hans.ts +++ b/src/languages/zh-hans.ts @@ -6676,6 +6676,7 @@ ${reportName} searchName: '搜索名称', savedSearchesMenuItemTitle: '已保存', topCategories: '热门类别', + topMerchants: '热门商家', groupedExpenses: '已分组报销费用', bulkActions: { approve: '批准', @@ -6737,6 +6738,7 @@ ${reportName} [CONST.SEARCH.GROUP_BY.CARD]: '卡片', [CONST.SEARCH.GROUP_BY.WITHDRAWAL_ID]: '提款 ID', [CONST.SEARCH.GROUP_BY.CATEGORY]: '类别', + [CONST.SEARCH.GROUP_BY.MERCHANT]: '商家', }, feed: '动态', withdrawalType: { diff --git a/src/libs/SearchUIUtils.ts b/src/libs/SearchUIUtils.ts index 98550f27fee9c..0c82d81859665 100644 --- a/src/libs/SearchUIUtils.ts +++ b/src/libs/SearchUIUtils.ts @@ -36,6 +36,7 @@ import type { TransactionGroupListItemType, TransactionListItemType, TransactionMemberGroupListItemType, + TransactionMerchantGroupListItemType, TransactionReportGroupListItemType, TransactionWithdrawalIDGroupListItemType, } from '@components/SelectionListWithSections/types'; @@ -56,6 +57,7 @@ import type { SearchCategoryGroup, SearchDataTypes, SearchMemberGroup, + SearchMerchantGroup, SearchTask, SearchTransactionAction, SearchWithdrawalIDGroup, @@ -149,6 +151,7 @@ type TransactionMemberGroupSorting = ColumnSortMapping; type TransactionWithdrawalIDGroupSorting = ColumnSortMapping; type TransactionCategoryGroupSorting = ColumnSortMapping; +type TransactionMerchantGroupSorting = ColumnSortMapping; type GetReportSectionsParams = { data: OnyxTypes.SearchResults['data']; @@ -243,6 +246,13 @@ const transactionCategoryGroupColumnNamesToSortingProperty: TransactionCategoryG [CONST.SEARCH.TABLE_COLUMNS.GROUP_TOTAL]: 'total' as const, }; +const transactionMerchantGroupColumnNamesToSortingProperty: TransactionMerchantGroupSorting = { + [CONST.SEARCH.TABLE_COLUMNS.GROUP_MERCHANT]: 'formattedMerchant' as const, + [CONST.SEARCH.TABLE_COLUMNS.MERCHANT]: 'formattedMerchant' as const, + [CONST.SEARCH.TABLE_COLUMNS.GROUP_EXPENSES]: 'count' as const, + [CONST.SEARCH.TABLE_COLUMNS.GROUP_TOTAL]: 'total' as const, +}; + const expenseStatusActionMapping = { [CONST.SEARCH.STATUS.EXPENSE.DRAFTS]: (expenseReport?: OnyxTypes.Report) => expenseReport?.stateNum === CONST.REPORT.STATE_NUM.OPEN && expenseReport.statusNum === CONST.REPORT.STATUS_NUM.OPEN, @@ -345,7 +355,7 @@ type SearchTypeMenuItem = { key: SearchKey; translationPath: TranslationPaths; type: SearchDataTypes; - icon?: IconAsset | Extract; + icon?: IconAsset | Extract; searchQuery: string; searchQueryJSON: SearchQueryJSON | undefined; hash: number; @@ -395,7 +405,7 @@ type GetSectionsParams = { function createTopSearchMenuItem( key: SearchKey, translationPath: TranslationPaths, - icon: IconAsset | Extract, + icon: Extract, groupBy: ValueOf, limit?: number, ): SearchTypeMenuItem { @@ -664,14 +674,21 @@ function getSuggestedSearches( return this.searchQueryJSON?.similarSearchHash ?? CONST.DEFAULT_NUMBER_ID; }, }, - [CONST.SEARCH.SEARCH_KEYS.TOP_SPENDERS]: createTopSearchMenuItem(CONST.SEARCH.SEARCH_KEYS.TOP_SPENDERS, 'search.topSpenders', Expensicons.User, CONST.SEARCH.GROUP_BY.FROM), + [CONST.SEARCH.SEARCH_KEYS.TOP_SPENDERS]: createTopSearchMenuItem(CONST.SEARCH.SEARCH_KEYS.TOP_SPENDERS, 'search.topSpenders', 'User', CONST.SEARCH.GROUP_BY.FROM), [CONST.SEARCH.SEARCH_KEYS.TOP_CATEGORIES]: createTopSearchMenuItem( CONST.SEARCH.SEARCH_KEYS.TOP_CATEGORIES, 'search.topCategories', - Expensicons.Folder, + 'Folder', CONST.SEARCH.GROUP_BY.CATEGORY, CONST.SEARCH.TOP_SEARCH_LIMIT, ), + [CONST.SEARCH.SEARCH_KEYS.TOP_MERCHANTS]: createTopSearchMenuItem( + CONST.SEARCH.SEARCH_KEYS.TOP_MERCHANTS, + 'search.topMerchants', + 'Building', + CONST.SEARCH.GROUP_BY.MERCHANT, + CONST.SEARCH.TOP_SEARCH_LIMIT, + ), }; } @@ -695,6 +712,7 @@ function getSuggestedSearchesVisibility( let shouldShowReconciliationSuggestion = false; let shouldShowTopSpendersSuggestion = false; let shouldShowTopCategoriesSuggestion = false; + let shouldShowTopMerchantsSuggestion = false; const hasCardFeed = Object.values(cardFeedsByPolicy ?? {}).some((feeds) => feeds.length > 0); @@ -732,6 +750,7 @@ function getSuggestedSearchesVisibility( const isAuditor = policy.role === CONST.POLICY.ROLE.AUDITOR; const isEligibleForTopSpendersSuggestion = isPaidPolicy && (isAdmin || isAuditor || isApprover); const isEligibleForTopCategoriesSuggestion = isPaidPolicy; + const isEligibleForTopMerchantsSuggestion = isPaidPolicy; shouldShowSubmitSuggestion ||= isEligibleForSubmitSuggestion; shouldShowPaySuggestion ||= isEligibleForPaySuggestion; @@ -743,6 +762,7 @@ function getSuggestedSearchesVisibility( shouldShowReconciliationSuggestion ||= isEligibleForReconciliationSuggestion; shouldShowTopSpendersSuggestion ||= isEligibleForTopSpendersSuggestion; shouldShowTopCategoriesSuggestion ||= isEligibleForTopCategoriesSuggestion; + shouldShowTopMerchantsSuggestion ||= isEligibleForTopMerchantsSuggestion; // We don't need to check the rest of the policies if we already determined that all suggestions should be displayed return ( @@ -755,7 +775,8 @@ function getSuggestedSearchesVisibility( shouldShowUnapprovedCardSuggestion && shouldShowReconciliationSuggestion && shouldShowTopSpendersSuggestion && - shouldShowTopCategoriesSuggestion + shouldShowTopCategoriesSuggestion && + shouldShowTopMerchantsSuggestion ); }); @@ -773,6 +794,7 @@ function getSuggestedSearchesVisibility( [CONST.SEARCH.SEARCH_KEYS.RECONCILIATION]: shouldShowReconciliationSuggestion, [CONST.SEARCH.SEARCH_KEYS.TOP_SPENDERS]: shouldShowTopSpendersSuggestion, [CONST.SEARCH.SEARCH_KEYS.TOP_CATEGORIES]: shouldShowTopCategoriesSuggestion, + [CONST.SEARCH.SEARCH_KEYS.TOP_MERCHANTS]: shouldShowTopMerchantsSuggestion, }; } @@ -919,6 +941,13 @@ function isTransactionCategoryGroupListItemType(item: ListItem): item is Transac return isTransactionGroupListItemType(item) && 'groupedBy' in item && item.groupedBy === CONST.SEARCH.GROUP_BY.CATEGORY; } +/** + * Type guard that checks if something is a TransactionMerchantGroupListItemType + */ +function isTransactionMerchantGroupListItemType(item: ListItem): item is TransactionMerchantGroupListItemType { + return isTransactionGroupListItemType(item) && 'groupedBy' in item && item.groupedBy === CONST.SEARCH.GROUP_BY.MERCHANT; +} + /** * Type guard that checks if something is a TransactionListItemType */ @@ -2169,6 +2198,45 @@ function getCategorySections(data: OnyxTypes.SearchResults['data'], queryJSON: S return [categorySectionsValues, categorySectionsValues.length]; } +/** + * @private + * Organizes data into List Sections grouped by merchant for display, for the TransactionGroupListItemType of Search Results. + * + * Do not use directly, use only via `getSections()` facade. + */ +function getMerchantSections(data: OnyxTypes.SearchResults['data'], queryJSON: SearchQueryJSON | undefined): [TransactionMerchantGroupListItemType[], number] { + const merchantSections: Record = {}; + + for (const key in data) { + if (isGroupEntry(key)) { + const merchantGroup = data[key] as SearchMerchantGroup; + + let transactionsQueryJSON: SearchQueryJSON | undefined; + if (queryJSON && merchantGroup.merchant !== undefined) { + const newFlatFilters = queryJSON.flatFilters.filter((filter) => filter.key !== CONST.SEARCH.SYNTAX_FILTER_KEYS.MERCHANT); + newFlatFilters.push({key: CONST.SEARCH.SYNTAX_FILTER_KEYS.MERCHANT, filters: [{operator: CONST.SEARCH.SYNTAX_OPERATORS.EQUAL_TO, value: merchantGroup.merchant}]}); + + const newQueryJSON: SearchQueryJSON = {...queryJSON, groupBy: undefined, flatFilters: newFlatFilters}; + + const newQuery = buildSearchQueryString(newQueryJSON); + + transactionsQueryJSON = buildSearchQueryJSON(newQuery); + } + + merchantSections[key] = { + groupedBy: CONST.SEARCH.GROUP_BY.MERCHANT, + transactions: [], + transactionsQueryJSON, + ...merchantGroup, + formattedMerchant: merchantGroup.merchant, + }; + } + } + + const merchantSectionsValues = Object.values(merchantSections); + return [merchantSectionsValues, merchantSectionsValues.length]; +} + /** * Returns the appropriate list item component based on the type and status of the search data. */ @@ -2244,6 +2312,8 @@ function getSections({ return getWithdrawalIDSections(data, queryJSON); case CONST.SEARCH.GROUP_BY.CATEGORY: return getCategorySections(data, queryJSON); + case CONST.SEARCH.GROUP_BY.MERCHANT: + return getMerchantSections(data, queryJSON); } } @@ -2285,6 +2355,8 @@ function getSortedSections( return getSortedWithdrawalIDData(data as TransactionWithdrawalIDGroupListItemType[], localeCompare, sortBy, sortOrder); case CONST.SEARCH.GROUP_BY.CATEGORY: return getSortedCategoryData(data as TransactionCategoryGroupListItemType[], localeCompare, sortBy, sortOrder); + case CONST.SEARCH.GROUP_BY.MERCHANT: + return getSortedMerchantData(data as TransactionMerchantGroupListItemType[], localeCompare, sortBy, sortOrder); } } @@ -2656,6 +2728,21 @@ function getSortedCategoryData(data: TransactionCategoryGroupListItemType[], loc ); } +/** + * @private + * Sorts merchant sections based on a specified column and sort order. + */ +function getSortedMerchantData(data: TransactionMerchantGroupListItemType[], localeCompare: LocaleContextProps['localeCompare'], sortBy?: SearchColumnType, sortOrder?: SortOrder) { + return getSortedData( + data, + localeCompare, + transactionMerchantGroupColumnNamesToSortingProperty, + (a, b) => localeCompare(a.formattedMerchant ?? '', b.formattedMerchant ?? ''), + sortBy, + sortOrder, + ); +} + /** * @private * Sorts report actions sections based on a specified column and sort order. @@ -2709,6 +2796,8 @@ function getCustomColumns(value?: SearchDataTypes | SearchGroupBy): SearchCustom return Object.values(CONST.SEARCH.GROUP_CUSTOM_COLUMNS.WITHDRAWAL_ID); case CONST.SEARCH.GROUP_BY.CATEGORY: return Object.values(CONST.SEARCH.GROUP_CUSTOM_COLUMNS.CATEGORY); + case CONST.SEARCH.GROUP_BY.MERCHANT: + return Object.values(CONST.SEARCH.GROUP_CUSTOM_COLUMNS.MERCHANT); default: return []; } @@ -2736,6 +2825,8 @@ function getCustomColumnDefault(value?: SearchDataTypes | SearchGroupBy): Search return CONST.SEARCH.GROUP_DEFAULT_COLUMNS.WITHDRAWAL_ID; case CONST.SEARCH.GROUP_BY.CATEGORY: return CONST.SEARCH.GROUP_DEFAULT_COLUMNS.CATEGORY; + case CONST.SEARCH.GROUP_BY.MERCHANT: + return CONST.SEARCH.GROUP_DEFAULT_COLUMNS.MERCHANT; default: return []; } @@ -2820,6 +2911,8 @@ function getSearchColumnTranslationKey(columnId: SearchCustomColumnIds): Transla return 'search.filters.feed'; case CONST.SEARCH.TABLE_COLUMNS.GROUP_CATEGORY: return 'common.category'; + case CONST.SEARCH.TABLE_COLUMNS.GROUP_MERCHANT: + return 'common.merchant'; case CONST.SEARCH.TABLE_COLUMNS.EXPORTED_TO: return 'search.exportedTo'; } @@ -3047,7 +3140,7 @@ function createTypeMenuSections( menuItems: [], }; - const insightsSearchKeys = [CONST.SEARCH.SEARCH_KEYS.TOP_SPENDERS, CONST.SEARCH.SEARCH_KEYS.TOP_CATEGORIES]; + const insightsSearchKeys = [CONST.SEARCH.SEARCH_KEYS.TOP_SPENDERS, CONST.SEARCH.SEARCH_KEYS.TOP_CATEGORIES, CONST.SEARCH.SEARCH_KEYS.TOP_MERCHANTS]; for (const key of insightsSearchKeys) { if (!suggestedSearchesVisibility[key]) { @@ -3297,6 +3390,7 @@ function getColumnsToShow( [CONST.SEARCH.GROUP_BY.FROM]: CONST.SEARCH.GROUP_CUSTOM_COLUMNS.FROM, [CONST.SEARCH.GROUP_BY.WITHDRAWAL_ID]: CONST.SEARCH.GROUP_CUSTOM_COLUMNS.WITHDRAWAL_ID, [CONST.SEARCH.GROUP_BY.CATEGORY]: CONST.SEARCH.GROUP_CUSTOM_COLUMNS.CATEGORY, + [CONST.SEARCH.GROUP_BY.MERCHANT]: CONST.SEARCH.GROUP_CUSTOM_COLUMNS.MERCHANT, }[groupBy]; const defaultCustomColumns = { @@ -3304,6 +3398,7 @@ function getColumnsToShow( [CONST.SEARCH.GROUP_BY.FROM]: CONST.SEARCH.GROUP_DEFAULT_COLUMNS.FROM, [CONST.SEARCH.GROUP_BY.WITHDRAWAL_ID]: CONST.SEARCH.GROUP_DEFAULT_COLUMNS.WITHDRAWAL_ID, [CONST.SEARCH.GROUP_BY.CATEGORY]: CONST.SEARCH.GROUP_DEFAULT_COLUMNS.CATEGORY, + [CONST.SEARCH.GROUP_BY.MERCHANT]: CONST.SEARCH.GROUP_DEFAULT_COLUMNS.MERCHANT, }[groupBy]; const filteredVisibleColumns = visibleColumns.filter((column) => Object.values(customColumns).includes(column as ValueOf)); @@ -3376,6 +3471,23 @@ function getColumnsToShow( return result; } + + if (groupBy === CONST.SEARCH.GROUP_BY.MERCHANT) { + const requiredColumns = new Set([CONST.SEARCH.TABLE_COLUMNS.GROUP_MERCHANT]); + const result: SearchColumnType[] = []; + + for (const col of requiredColumns) { + if (!columnsToShow.includes(col as SearchCustomColumnIds)) { + result.push(col); + } + } + + for (const col of columnsToShow) { + result.push(col); + } + + return result; + } } const columns: ColumnVisibility = isExpenseReportView @@ -3659,6 +3771,7 @@ export { isTransactionCardGroupListItemType, isTransactionWithdrawalIDGroupListItemType, isTransactionCategoryGroupListItemType, + isTransactionMerchantGroupListItemType, isSearchResultsEmpty, isTransactionListItemType, isReportActionListItemType, diff --git a/src/pages/Search/SearchColumnsPage.tsx b/src/pages/Search/SearchColumnsPage.tsx index b1ba25d719089..5c1b7b9b89244 100644 --- a/src/pages/Search/SearchColumnsPage.tsx +++ b/src/pages/Search/SearchColumnsPage.tsx @@ -62,6 +62,7 @@ function SearchColumnsPage() { CONST.SEARCH.TABLE_COLUMNS.GROUP_WITHDRAWAL_ID, CONST.SEARCH.TABLE_COLUMNS.GROUP_FROM, CONST.SEARCH.TABLE_COLUMNS.GROUP_CATEGORY, + CONST.SEARCH.TABLE_COLUMNS.GROUP_MERCHANT, ]); const sortColumns = (columnsToSort: ColumnItem[]): ColumnItem[] => { diff --git a/src/pages/Search/SearchTypeMenu.tsx b/src/pages/Search/SearchTypeMenu.tsx index d58ad796ebada..5d2a8ab39d949 100644 --- a/src/pages/Search/SearchTypeMenu.tsx +++ b/src/pages/Search/SearchTypeMenu.tsx @@ -69,6 +69,9 @@ function SearchTypeMenu({queryJSON}: SearchTypeMenuProps) { 'MoneyHourglass', 'CreditCardHourglass', 'Bank', + 'User', + 'Folder', + 'Building', ] as const); const {showDeleteModal, DeleteConfirmModal} = useDeleteSavedSearch(); const [allPolicies] = useOnyx(ONYXKEYS.COLLECTION.POLICY, {canBeMissing: true}); diff --git a/src/types/onyx/SearchResults.ts b/src/types/onyx/SearchResults.ts index 7d03a1b02f0e6..4ed3879498479 100644 --- a/src/types/onyx/SearchResults.ts +++ b/src/types/onyx/SearchResults.ts @@ -187,6 +187,21 @@ type SearchCategoryGroup = { currency: string; }; +/** Model of merchant grouped search result */ +type SearchMerchantGroup = { + /** Merchant name */ + merchant: string; + + /** Number of transactions */ + count: number; + + /** Total value of transactions */ + total: number; + + /** Currency of total value */ + currency: string; +}; + /** Model of search results */ type SearchResults = { /** Current search results state */ @@ -201,7 +216,7 @@ type SearchResults = { PrefixedRecord & PrefixedRecord & PrefixedRecord & - PrefixedRecord; + PrefixedRecord; /** Whether search data is being fetched from server */ isLoading?: boolean; @@ -223,4 +238,5 @@ export type { SearchCardGroup, SearchWithdrawalIDGroup, SearchCategoryGroup, + SearchMerchantGroup, }; diff --git a/tests/ui/MerchantListItemHeaderTest.tsx b/tests/ui/MerchantListItemHeaderTest.tsx new file mode 100644 index 0000000000000..7c78716194e04 --- /dev/null +++ b/tests/ui/MerchantListItemHeaderTest.tsx @@ -0,0 +1,364 @@ +import {act, fireEvent, render, screen} from '@testing-library/react-native'; +import React from 'react'; +import Onyx from 'react-native-onyx'; +import ComposeProviders from '@components/ComposeProviders'; +import {LocaleContextProvider} from '@components/LocaleContextProvider'; +import OnyxListItemProvider from '@components/OnyxListItemProvider'; +import {SearchContext} from '@components/Search/SearchContext'; +import type {SearchColumnType} from '@components/Search/types'; +import MerchantListItemHeader from '@components/SelectionListWithSections/Search/MerchantListItemHeader'; +import type {TransactionMerchantGroupListItemType} from '@components/SelectionListWithSections/types'; +import useResponsiveLayout from '@hooks/useResponsiveLayout'; +import CONST from '@src/CONST'; +import ONYXKEYS from '@src/ONYXKEYS'; +import waitForBatchedUpdatesWithAct from '../utils/waitForBatchedUpdatesWithAct'; + +jest.mock('@components/ConfirmedRoute.tsx'); +jest.mock('@libs/Navigation/Navigation'); + +// Mock useResponsiveLayout to control screen size in tests +jest.mock('@hooks/useResponsiveLayout', () => jest.fn()); +const mockedUseResponsiveLayout = useResponsiveLayout as jest.MockedFunction; + +// Mock search context with all required SearchContextProps fields +const mockSearchContext = { + currentSearchHash: 12345, + currentSearchKey: undefined, + currentSearchQueryJSON: undefined, + currentSearchResults: undefined, + selectedReports: [], + selectedTransactionIDs: [], + selectedTransactions: {}, + isOnSearch: false, + shouldTurnOffSelectionMode: false, + shouldResetSearchQuery: false, + lastSearchType: undefined, + areAllMatchingItemsSelected: false, + showSelectAllMatchingItems: false, + shouldShowFiltersBarLoading: false, + shouldUseLiveData: false, + setLastSearchType: jest.fn(), + setCurrentSearchHashAndKey: jest.fn(), + setCurrentSearchQueryJSON: jest.fn(), + setSelectedTransactions: jest.fn(), + removeTransaction: jest.fn(), + clearSelectedTransactions: jest.fn(), + setShouldShowFiltersBarLoading: jest.fn(), + shouldShowSelectAllMatchingItems: jest.fn(), + selectAllMatchingItems: jest.fn(), + setShouldResetSearchQuery: jest.fn(), +}; + +const createMerchantListItem = (merchant: string, options: Partial = {}): TransactionMerchantGroupListItemType => ({ + merchant, + formattedMerchant: options.formattedMerchant ?? merchant, + count: options.count ?? 5, + currency: options.currency ?? 'USD', + total: options.total ?? 250, + groupedBy: CONST.SEARCH.GROUP_BY.MERCHANT, + transactions: [], + transactionsQueryJSON: undefined, + keyForList: `merchant-${merchant}`, + ...options, +}); + +// Helper function to wrap component with context +const renderMerchantListItemHeader = ( + merchantItem: TransactionMerchantGroupListItemType, + props: Partial<{ + onCheckboxPress: jest.Mock; + isDisabled: boolean; + canSelectMultiple: boolean; + isSelectAllChecked: boolean; + isIndeterminate: boolean; + onDownArrowClick: jest.Mock; + isExpanded: boolean; + columns: SearchColumnType[]; + }> = {}, +) => { + return render( + + + + + , + ); +}; + +describe('MerchantListItemHeader', () => { + beforeAll(() => + Onyx.init({ + keys: ONYXKEYS, + evictableKeys: [ONYXKEYS.COLLECTION.REPORT_ACTIONS], + }), + ); + + beforeEach(() => { + // Default to small screen (mobile) layout + mockedUseResponsiveLayout.mockReturnValue({ + isLargeScreenWidth: false, + shouldUseNarrowLayout: true, + isSmallScreenWidth: true, + isMediumScreenWidth: false, + isExtraSmallScreenWidth: false, + isExtraSmallScreenHeight: false, + isExtraLargeScreenWidth: false, + isSmallScreen: true, + isInNarrowPaneModal: false, + onboardingIsMediumOrLargerScreenWidth: false, + }); + }); + + afterEach(async () => { + await act(async () => { + await Onyx.clear(); + }); + jest.clearAllMocks(); + }); + + describe('Merchant name display', () => { + it('should display the merchant name from formattedMerchant', async () => { + const merchantItem = createMerchantListItem('Starbucks', {formattedMerchant: 'Starbucks'}); + renderMerchantListItemHeader(merchantItem); + await waitForBatchedUpdatesWithAct(); + + expect(screen.getByText('Starbucks')).toBeOnTheScreen(); + }); + + it('should display merchant name when formattedMerchant has different value', async () => { + // formattedMerchant contains the formatted version + const merchantItem = createMerchantListItem('starbucks_coffee', { + formattedMerchant: 'Starbucks Coffee', + }); + renderMerchantListItemHeader(merchantItem); + await waitForBatchedUpdatesWithAct(); + + expect(screen.getByText('Starbucks Coffee')).toBeOnTheScreen(); + }); + + it('should display "Unknown Merchant" for empty merchant string', async () => { + const merchantItem = createMerchantListItem('', {formattedMerchant: ''}); + renderMerchantListItemHeader(merchantItem); + await waitForBatchedUpdatesWithAct(); + + expect(screen.getByText(CONST.TRANSACTION.UNKNOWN_MERCHANT)).toBeOnTheScreen(); + }); + + it('should display "Unknown Merchant" when merchant is undefined', async () => { + const merchantItem = createMerchantListItem('', {formattedMerchant: undefined}); + renderMerchantListItemHeader(merchantItem); + await waitForBatchedUpdatesWithAct(); + + expect(screen.getByText(CONST.TRANSACTION.UNKNOWN_MERCHANT)).toBeOnTheScreen(); + }); + + it('should display "Unknown Merchant" when both merchant and formattedMerchant are empty', async () => { + const merchantItem = createMerchantListItem('', {merchant: '', formattedMerchant: ''}); + renderMerchantListItemHeader(merchantItem); + await waitForBatchedUpdatesWithAct(); + + expect(screen.getByText(CONST.TRANSACTION.UNKNOWN_MERCHANT)).toBeOnTheScreen(); + }); + }); + + describe('Checkbox functionality', () => { + it('should render checkbox when canSelectMultiple is true', async () => { + const merchantItem = createMerchantListItem('Starbucks'); + renderMerchantListItemHeader(merchantItem, {canSelectMultiple: true}); + await waitForBatchedUpdatesWithAct(); + + expect(screen.getByRole('checkbox')).toBeOnTheScreen(); + }); + + it('should not render checkbox when canSelectMultiple is false', async () => { + const merchantItem = createMerchantListItem('Starbucks'); + renderMerchantListItemHeader(merchantItem, {canSelectMultiple: false}); + await waitForBatchedUpdatesWithAct(); + + expect(screen.queryByRole('checkbox')).not.toBeOnTheScreen(); + }); + + it('should call onCheckboxPress when checkbox is pressed', async () => { + const onCheckboxPress = jest.fn(); + const merchantItem = createMerchantListItem('Starbucks'); + renderMerchantListItemHeader(merchantItem, {canSelectMultiple: true, onCheckboxPress}); + await waitForBatchedUpdatesWithAct(); + + const checkbox = screen.getByRole('checkbox'); + fireEvent.press(checkbox); + + expect(onCheckboxPress).toHaveBeenCalledWith(merchantItem); + }); + + it('should show checkbox as checked when isSelectAllChecked is true', async () => { + const merchantItem = createMerchantListItem('Starbucks'); + renderMerchantListItemHeader(merchantItem, {canSelectMultiple: true, isSelectAllChecked: true}); + await waitForBatchedUpdatesWithAct(); + + expect(screen.getByRole('checkbox')).toBeChecked(); + }); + }); + + describe('Total and count display', () => { + it('should display the total amount', async () => { + const merchantItem = createMerchantListItem('Starbucks', {total: 50000, currency: 'USD'}); + renderMerchantListItemHeader(merchantItem); + await waitForBatchedUpdatesWithAct(); + + // TotalCell formats the amount, so we check for the formatted version + // $500.00 is 50000 cents + expect(screen.getByText('$500.00')).toBeOnTheScreen(); + }); + + it('should display the total amount with different currencies', async () => { + const merchantItem = createMerchantListItem('Starbucks', {total: 10000, currency: 'EUR'}); + renderMerchantListItemHeader(merchantItem); + await waitForBatchedUpdatesWithAct(); + + // Should display EUR formatted amount + expect(screen.getByTestId('TotalCell')).toBeOnTheScreen(); + }); + }); + + describe('Disabled state', () => { + it('should render checkbox with disabled styling when isDisabled is true', async () => { + const onCheckboxPress = jest.fn(); + const merchantItem = createMerchantListItem('Starbucks'); + renderMerchantListItemHeader(merchantItem, {canSelectMultiple: true, isDisabled: true, onCheckboxPress}); + await waitForBatchedUpdatesWithAct(); + + const checkbox = screen.getByRole('checkbox'); + // The checkbox should still be rendered + expect(checkbox).toBeOnTheScreen(); + }); + + it('should render checkbox with disabled styling when isDisabledCheckbox is true on merchant item', async () => { + const onCheckboxPress = jest.fn(); + const merchantItem = createMerchantListItem('Starbucks', {isDisabledCheckbox: true}); + renderMerchantListItemHeader(merchantItem, {canSelectMultiple: true, onCheckboxPress}); + await waitForBatchedUpdatesWithAct(); + + const checkbox = screen.getByRole('checkbox'); + // The checkbox should still be rendered + expect(checkbox).toBeOnTheScreen(); + }); + }); + + describe('Large screen layout', () => { + beforeEach(() => { + mockedUseResponsiveLayout.mockReturnValue({ + isLargeScreenWidth: true, + shouldUseNarrowLayout: false, + isSmallScreenWidth: false, + isMediumScreenWidth: false, + isExtraSmallScreenWidth: false, + isExtraSmallScreenHeight: false, + isExtraLargeScreenWidth: true, + isSmallScreen: false, + isInNarrowPaneModal: false, + onboardingIsMediumOrLargerScreenWidth: true, + }); + }); + + it('should render column components on large screen', async () => { + const merchantItem = createMerchantListItem('Starbucks', {count: 5, total: 25000}); + renderMerchantListItemHeader(merchantItem, { + columns: [CONST.SEARCH.TABLE_COLUMNS.GROUP_MERCHANT, CONST.SEARCH.TABLE_COLUMNS.GROUP_EXPENSES, CONST.SEARCH.TABLE_COLUMNS.GROUP_TOTAL], + }); + await waitForBatchedUpdatesWithAct(); + + // Should display merchant name, expense count, and total + expect(screen.getByText('Starbucks')).toBeOnTheScreen(); + expect(screen.getByText('5')).toBeOnTheScreen(); + expect(screen.getByText('$250.00')).toBeOnTheScreen(); + }); + + it('should render checkbox on large screen when canSelectMultiple is true', async () => { + const merchantItem = createMerchantListItem('Starbucks'); + renderMerchantListItemHeader(merchantItem, {canSelectMultiple: true}); + await waitForBatchedUpdatesWithAct(); + + expect(screen.getByRole('checkbox')).toBeOnTheScreen(); + }); + }); + + describe('Expand/Collapse functionality', () => { + it('should render expand/collapse button when onDownArrowClick is provided', async () => { + const onDownArrowClick = jest.fn(); + const merchantItem = createMerchantListItem('Starbucks'); + renderMerchantListItemHeader(merchantItem, {onDownArrowClick, isExpanded: false}); + await waitForBatchedUpdatesWithAct(); + + // The expand/collapse button should be rendered with "Expand" label when not expanded + const expandButton = screen.getByLabelText('Expand'); + expect(expandButton).toBeOnTheScreen(); + }); + + it('should call onDownArrowClick when expand/collapse button is pressed', async () => { + const onDownArrowClick = jest.fn(); + const merchantItem = createMerchantListItem('Starbucks'); + renderMerchantListItemHeader(merchantItem, {onDownArrowClick, isExpanded: false}); + await waitForBatchedUpdatesWithAct(); + + const expandButton = screen.getByLabelText('Expand'); + fireEvent.press(expandButton); + + expect(onDownArrowClick).toHaveBeenCalled(); + }); + + it('should show "Collapse" label when isExpanded is true', async () => { + const onDownArrowClick = jest.fn(); + const merchantItem = createMerchantListItem('Starbucks'); + renderMerchantListItemHeader(merchantItem, {onDownArrowClick, isExpanded: true}); + await waitForBatchedUpdatesWithAct(); + + const collapseButton = screen.getByLabelText('Collapse'); + expect(collapseButton).toBeOnTheScreen(); + }); + + it('should not render expand/collapse button when onDownArrowClick is not provided', async () => { + const merchantItem = createMerchantListItem('Starbucks'); + renderMerchantListItemHeader(merchantItem); + await waitForBatchedUpdatesWithAct(); + + expect(screen.queryByLabelText('Expand')).not.toBeOnTheScreen(); + expect(screen.queryByLabelText('Collapse')).not.toBeOnTheScreen(); + }); + }); + + describe('Special merchant names', () => { + it('should handle merchants with special characters', async () => { + const merchantItem = createMerchantListItem("McDonald's & Co.", {formattedMerchant: "McDonald's & Co."}); + renderMerchantListItemHeader(merchantItem); + await waitForBatchedUpdatesWithAct(); + + expect(screen.getByText("McDonald's & Co.")).toBeOnTheScreen(); + }); + + it('should handle merchants with Unicode characters', async () => { + const merchantItem = createMerchantListItem('カフェ東京', {formattedMerchant: 'カフェ東京'}); + renderMerchantListItemHeader(merchantItem); + await waitForBatchedUpdatesWithAct(); + + expect(screen.getByText('カフェ東京')).toBeOnTheScreen(); + }); + + it('should handle merchants with emoji', async () => { + const merchantItem = createMerchantListItem('Coffee ☕', {formattedMerchant: 'Coffee ☕'}); + renderMerchantListItemHeader(merchantItem); + await waitForBatchedUpdatesWithAct(); + + expect(screen.getByText('Coffee ☕')).toBeOnTheScreen(); + }); + }); +}); diff --git a/tests/unit/Search/SearchUIUtilsTest.ts b/tests/unit/Search/SearchUIUtilsTest.ts index fc2a946e2cf35..7fef6f21d1a60 100644 --- a/tests/unit/Search/SearchUIUtilsTest.ts +++ b/tests/unit/Search/SearchUIUtilsTest.ts @@ -12,6 +12,7 @@ import type { TransactionGroupListItemType, TransactionListItemType, TransactionMemberGroupListItemType, + TransactionMerchantGroupListItemType, TransactionReportGroupListItemType, TransactionWithdrawalIDGroupListItemType, } from '@components/SelectionListWithSections/types'; @@ -1721,6 +1722,85 @@ const transactionCategoryGroupListItemsSorted: TransactionCategoryGroupListItemT }, ]; +// Merchant test data +const merchantName1 = 'Starbucks'; +const merchantName2 = 'Whole Foods'; + +const searchResultsGroupByMerchant: OnyxTypes.SearchResults = { + data: { + personalDetailsList: {}, + [`${CONST.SEARCH.GROUP_PREFIX}${merchantName1}` as const]: { + merchant: merchantName1, + count: 7, + currency: 'USD', + total: 350, + }, + [`${CONST.SEARCH.GROUP_PREFIX}${merchantName2}` as const]: { + merchant: merchantName2, + count: 4, + currency: 'USD', + total: 120, + }, + }, + search: { + count: 11, + currency: 'USD', + hasMoreResults: false, + hasResults: true, + offset: 0, + status: CONST.SEARCH.STATUS.EXPENSE.ALL, + total: 470, + isLoading: false, + type: 'expense', + }, +}; + +const transactionMerchantGroupListItems: TransactionMerchantGroupListItemType[] = [ + { + merchant: merchantName1, + count: 7, + currency: 'USD', + total: 350, + groupedBy: CONST.SEARCH.GROUP_BY.MERCHANT, + formattedMerchant: merchantName1, + transactions: [], + transactionsQueryJSON: undefined, + }, + { + merchant: merchantName2, + count: 4, + currency: 'USD', + total: 120, + groupedBy: CONST.SEARCH.GROUP_BY.MERCHANT, + formattedMerchant: merchantName2, + transactions: [], + transactionsQueryJSON: undefined, + }, +]; + +const transactionMerchantGroupListItemsSorted: TransactionMerchantGroupListItemType[] = [ + { + merchant: merchantName1, + count: 7, + currency: 'USD', + total: 350, + groupedBy: CONST.SEARCH.GROUP_BY.MERCHANT, + formattedMerchant: merchantName1, + transactions: [], + transactionsQueryJSON: undefined, + }, + { + merchant: merchantName2, + count: 4, + currency: 'USD', + total: 120, + groupedBy: CONST.SEARCH.GROUP_BY.MERCHANT, + formattedMerchant: merchantName2, + transactions: [], + transactionsQueryJSON: undefined, + }, +]; + describe('SearchUIUtils', () => { beforeAll(async () => { Onyx.init({ @@ -2073,6 +2153,14 @@ describe('SearchUIUtils', () => { it('should return TransactionGroupListItem when type is INVOICE and groupBy is member', () => { expect(SearchUIUtils.getListItem(CONST.SEARCH.DATA_TYPES.INVOICE, CONST.SEARCH.STATUS.EXPENSE.ALL, CONST.SEARCH.GROUP_BY.FROM)).toStrictEqual(TransactionGroupListItem); }); + + it('should return TransactionGroupListItem when type is EXPENSE and groupBy is category', () => { + expect(SearchUIUtils.getListItem(CONST.SEARCH.DATA_TYPES.EXPENSE, CONST.SEARCH.STATUS.EXPENSE.ALL, CONST.SEARCH.GROUP_BY.CATEGORY)).toStrictEqual(TransactionGroupListItem); + }); + + it('should return TransactionGroupListItem when type is EXPENSE and groupBy is merchant', () => { + expect(SearchUIUtils.getListItem(CONST.SEARCH.DATA_TYPES.EXPENSE, CONST.SEARCH.STATUS.EXPENSE.ALL, CONST.SEARCH.GROUP_BY.MERCHANT)).toStrictEqual(TransactionGroupListItem); + }); }); describe('Test getSections', () => { @@ -2576,6 +2664,201 @@ describe('SearchUIUtils', () => { const quotesItem = result.find((item) => item.category === '"Special" Category'); expect(quotesItem?.formattedCategory).toBe('"Special" Category'); }); + + // Merchant groupBy tests + it('should return getMerchantSections result when type is EXPENSE and groupBy is merchant', () => { + expect( + SearchUIUtils.getSections({ + type: CONST.SEARCH.DATA_TYPES.EXPENSE, + data: searchResultsGroupByMerchant.data, + currentAccountID: 2074551, + currentUserEmail: '', + translate: translateLocal, + formatPhoneNumber, + bankAccountList: {}, + groupBy: CONST.SEARCH.GROUP_BY.MERCHANT, + })[0], + ).toStrictEqual(transactionMerchantGroupListItems); + }); + + it('should handle empty merchant values correctly', () => { + const dataWithEmptyMerchant: OnyxTypes.SearchResults['data'] = { + personalDetailsList: {}, + [`${CONST.SEARCH.GROUP_PREFIX}empty` as const]: { + merchant: '', + count: 2, + currency: 'USD', + total: 50, + }, + [`${CONST.SEARCH.GROUP_PREFIX}valid` as const]: { + merchant: 'Starbucks', + count: 1, + currency: 'USD', + total: 25, + }, + }; + + const [result] = SearchUIUtils.getSections({ + type: CONST.SEARCH.DATA_TYPES.EXPENSE, + data: dataWithEmptyMerchant, + currentAccountID: 2074551, + currentUserEmail: '', + translate: translateLocal, + formatPhoneNumber, + bankAccountList: {}, + groupBy: CONST.SEARCH.GROUP_BY.MERCHANT, + }) as [TransactionMerchantGroupListItemType[], number]; + + expect(result).toHaveLength(2); + expect(result.some((item) => item.merchant === '')).toBe(true); + expect(result.some((item) => item.merchant === 'Starbucks')).toBe(true); + }); + + it('should return isTransactionMerchantGroupListItemType true for merchant group items', () => { + const merchantItem: TransactionMerchantGroupListItemType = { + merchant: 'Starbucks', + count: 5, + currency: 'USD', + total: 250, + groupedBy: CONST.SEARCH.GROUP_BY.MERCHANT, + formattedMerchant: 'Starbucks', + transactions: [], + transactionsQueryJSON: undefined, + }; + + expect(SearchUIUtils.isTransactionMerchantGroupListItemType(merchantItem)).toBe(true); + }); + + it('should return isTransactionMerchantGroupListItemType false for non-merchant group items', () => { + const categoryItem: TransactionCategoryGroupListItemType = { + category: 'Travel', + count: 3, + currency: 'USD', + total: 100, + groupedBy: CONST.SEARCH.GROUP_BY.CATEGORY, + formattedCategory: 'Travel', + transactions: [], + transactionsQueryJSON: undefined, + }; + + expect(SearchUIUtils.isTransactionMerchantGroupListItemType(categoryItem)).toBe(false); + }); + + it('should generate transactionsQueryJSON with valid hash for merchant sections', () => { + const [result] = SearchUIUtils.getSections({ + type: CONST.SEARCH.DATA_TYPES.EXPENSE, + data: searchResultsGroupByMerchant.data, + currentAccountID: 2074551, + currentUserEmail: '', + translate: translateLocal, + formatPhoneNumber, + bankAccountList: {}, + groupBy: CONST.SEARCH.GROUP_BY.MERCHANT, + queryJSON: { + type: CONST.SEARCH.DATA_TYPES.EXPENSE, + status: '', + sortBy: CONST.SEARCH.TABLE_COLUMNS.DATE, + sortOrder: CONST.SEARCH.SORT_ORDER.DESC, + hash: 12345, + flatFilters: [], + inputQuery: 'type:expense groupBy:merchant', + recentSearchHash: 12345, + similarSearchHash: 12345, + filters: { + operator: CONST.SEARCH.SYNTAX_OPERATORS.AND, + left: CONST.SEARCH.SYNTAX_FILTER_KEYS.TYPE, + right: CONST.SEARCH.DATA_TYPES.EXPENSE, + }, + }, + }) as [TransactionMerchantGroupListItemType[], number]; + + // Each merchant section should have a transactionsQueryJSON with a hash + for (const item of result) { + expect(item.transactionsQueryJSON).toBeDefined(); + expect(item.transactionsQueryJSON?.hash).toBeDefined(); + expect(typeof item.transactionsQueryJSON?.hash).toBe('number'); + } + }); + + it('should handle Unicode characters in merchant names', () => { + const dataWithUnicode: OnyxTypes.SearchResults['data'] = { + personalDetailsList: {}, + [`${CONST.SEARCH.GROUP_PREFIX}japanese` as const]: { + merchant: 'カフェ東京', + count: 3, + currency: 'JPY', + total: 50000, + }, + [`${CONST.SEARCH.GROUP_PREFIX}chinese` as const]: { + merchant: '北京饭店', + count: 2, + currency: 'CNY', + total: 1000, + }, + [`${CONST.SEARCH.GROUP_PREFIX}emoji` as const]: { + merchant: 'Coffee ☕', + count: 1, + currency: 'USD', + total: 500, + }, + }; + + const [result] = SearchUIUtils.getSections({ + type: CONST.SEARCH.DATA_TYPES.EXPENSE, + data: dataWithUnicode, + currentAccountID: 2074551, + currentUserEmail: '', + translate: translateLocal, + formatPhoneNumber, + bankAccountList: {}, + groupBy: CONST.SEARCH.GROUP_BY.MERCHANT, + }) as [TransactionMerchantGroupListItemType[], number]; + + expect(result).toHaveLength(3); + expect(result.some((item) => item.merchant === 'カフェ東京')).toBe(true); + expect(result.some((item) => item.merchant === '北京饭店')).toBe(true); + expect(result.some((item) => item.merchant === 'Coffee ☕')).toBe(true); + }); + + it('should handle special characters in merchant names', () => { + const dataWithSpecialChars: OnyxTypes.SearchResults['data'] = { + personalDetailsList: {}, + [`${CONST.SEARCH.GROUP_PREFIX}ampersand` as const]: { + merchant: "McDonald's & Co.", + count: 5, + currency: 'USD', + total: 2500, + }, + [`${CONST.SEARCH.GROUP_PREFIX}parentheses` as const]: { + merchant: 'Walmart (Express)', + count: 2, + currency: 'USD', + total: 1000, + }, + [`${CONST.SEARCH.GROUP_PREFIX}quotes` as const]: { + merchant: '"Best" Coffee', + count: 1, + currency: 'USD', + total: 300, + }, + }; + + const [result] = SearchUIUtils.getSections({ + type: CONST.SEARCH.DATA_TYPES.EXPENSE, + data: dataWithSpecialChars, + currentAccountID: 2074551, + currentUserEmail: '', + translate: translateLocal, + formatPhoneNumber, + bankAccountList: {}, + groupBy: CONST.SEARCH.GROUP_BY.MERCHANT, + }) as [TransactionMerchantGroupListItemType[], number]; + + expect(result).toHaveLength(3); + expect(result.some((item) => item.merchant === "McDonald's & Co.")).toBe(true); + expect(result.some((item) => item.merchant === 'Walmart (Express)')).toBe(true); + expect(result.some((item) => item.merchant === '"Best" Coffee')).toBe(true); + }); }); describe('Test getSortedSections', () => { @@ -2754,6 +3037,109 @@ describe('SearchUIUtils', () => { expect(result.at(0)?.count).toBe(5); expect(result.at(1)?.count).toBe(3); }); + + // Merchant sorting tests + it('should return getSortedMerchantData result when type is EXPENSE and groupBy is merchant', () => { + expect( + SearchUIUtils.getSortedSections( + CONST.SEARCH.DATA_TYPES.EXPENSE, + '', + transactionMerchantGroupListItems, + localeCompare, + translateLocal, + CONST.SEARCH.TABLE_COLUMNS.DATE, + CONST.SEARCH.SORT_ORDER.ASC, + CONST.SEARCH.GROUP_BY.MERCHANT, + ), + ).toStrictEqual(transactionMerchantGroupListItemsSorted); + }); + + it('should sort merchant data by merchant name in ascending order', () => { + const result = SearchUIUtils.getSortedSections( + CONST.SEARCH.DATA_TYPES.EXPENSE, + '', + transactionMerchantGroupListItems, + localeCompare, + translateLocal, + CONST.SEARCH.TABLE_COLUMNS.GROUP_MERCHANT, + CONST.SEARCH.SORT_ORDER.ASC, + CONST.SEARCH.GROUP_BY.MERCHANT, + ) as TransactionMerchantGroupListItemType[]; + + // "Starbucks" should come before "Whole Foods" in ascending alphabetical order + expect(result.at(0)?.merchant).toBe(merchantName1); // Starbucks + expect(result.at(1)?.merchant).toBe(merchantName2); // Whole Foods + }); + + it('should sort merchant data by merchant name in descending order', () => { + const result = SearchUIUtils.getSortedSections( + CONST.SEARCH.DATA_TYPES.EXPENSE, + '', + transactionMerchantGroupListItems, + localeCompare, + translateLocal, + CONST.SEARCH.TABLE_COLUMNS.GROUP_MERCHANT, + CONST.SEARCH.SORT_ORDER.DESC, + CONST.SEARCH.GROUP_BY.MERCHANT, + ) as TransactionMerchantGroupListItemType[]; + + // "Whole Foods" should come before "Starbucks" in descending alphabetical order + expect(result.at(0)?.merchant).toBe(merchantName2); // Whole Foods + expect(result.at(1)?.merchant).toBe(merchantName1); // Starbucks + }); + + it('should sort merchant data by total amount', () => { + const result = SearchUIUtils.getSortedSections( + CONST.SEARCH.DATA_TYPES.EXPENSE, + '', + transactionMerchantGroupListItems, + localeCompare, + translateLocal, + CONST.SEARCH.TABLE_COLUMNS.GROUP_TOTAL, + CONST.SEARCH.SORT_ORDER.DESC, + CONST.SEARCH.GROUP_BY.MERCHANT, + ) as TransactionMerchantGroupListItemType[]; + + // Starbucks (350) should come before Whole Foods (120) when sorted by total descending + expect(result.at(0)?.total).toBe(350); + expect(result.at(1)?.total).toBe(120); + }); + + it('should sort merchant data using non-group column name (parser default sortBy)', () => { + // The parser sets default sortBy to 'merchant' (not 'groupMerchant') when groupBy is merchant + // This test verifies that the sorting works with the parser's default value + const result = SearchUIUtils.getSortedSections( + CONST.SEARCH.DATA_TYPES.EXPENSE, + '', + transactionMerchantGroupListItems, + localeCompare, + translateLocal, + CONST.SEARCH.TABLE_COLUMNS.MERCHANT, // Parser default: 'merchant' not 'groupMerchant' + CONST.SEARCH.SORT_ORDER.ASC, + CONST.SEARCH.GROUP_BY.MERCHANT, + ) as TransactionMerchantGroupListItemType[]; + + // "Starbucks" should come before "Whole Foods" in ascending alphabetical order + expect(result.at(0)?.merchant).toBe(merchantName1); // Starbucks + expect(result.at(1)?.merchant).toBe(merchantName2); // Whole Foods + }); + + it('should sort merchant data by expenses count', () => { + const result = SearchUIUtils.getSortedSections( + CONST.SEARCH.DATA_TYPES.EXPENSE, + '', + transactionMerchantGroupListItems, + localeCompare, + translateLocal, + CONST.SEARCH.TABLE_COLUMNS.GROUP_EXPENSES, + CONST.SEARCH.SORT_ORDER.DESC, + CONST.SEARCH.GROUP_BY.MERCHANT, + ) as TransactionMerchantGroupListItemType[]; + + // Starbucks (7 expenses) should come before Whole Foods (4 expenses) when sorted by count descending + expect(result.at(0)?.count).toBe(7); + expect(result.at(1)?.count).toBe(4); + }); }); describe('Test createTypeMenuItems', () => { @@ -3701,6 +4087,94 @@ describe('SearchUIUtils', () => { }); }); + describe('Test getCustomColumns', () => { + it('should return custom columns for EXPENSE type', () => { + const columns = SearchUIUtils.getCustomColumns(CONST.SEARCH.DATA_TYPES.EXPENSE); + expect(columns).toEqual(Object.values(CONST.SEARCH.TYPE_CUSTOM_COLUMNS.EXPENSE)); + }); + + it('should return custom columns for CATEGORY groupBy', () => { + const columns = SearchUIUtils.getCustomColumns(CONST.SEARCH.GROUP_BY.CATEGORY); + expect(columns).toEqual(Object.values(CONST.SEARCH.GROUP_CUSTOM_COLUMNS.CATEGORY)); + expect(columns).toContain(CONST.SEARCH.TABLE_COLUMNS.GROUP_CATEGORY); + expect(columns).toContain(CONST.SEARCH.TABLE_COLUMNS.GROUP_EXPENSES); + expect(columns).toContain(CONST.SEARCH.TABLE_COLUMNS.GROUP_TOTAL); + }); + + it('should return custom columns for MERCHANT groupBy', () => { + const columns = SearchUIUtils.getCustomColumns(CONST.SEARCH.GROUP_BY.MERCHANT); + expect(columns).toEqual(Object.values(CONST.SEARCH.GROUP_CUSTOM_COLUMNS.MERCHANT)); + expect(columns).toContain(CONST.SEARCH.TABLE_COLUMNS.GROUP_MERCHANT); + expect(columns).toContain(CONST.SEARCH.TABLE_COLUMNS.GROUP_EXPENSES); + expect(columns).toContain(CONST.SEARCH.TABLE_COLUMNS.GROUP_TOTAL); + }); + + it('should return empty array for undefined value', () => { + const columns = SearchUIUtils.getCustomColumns(undefined); + expect(columns).toEqual([]); + }); + }); + + describe('Test getCustomColumnDefault', () => { + it('should return default columns for EXPENSE type', () => { + const columns = SearchUIUtils.getCustomColumnDefault(CONST.SEARCH.DATA_TYPES.EXPENSE); + expect(columns).toEqual(CONST.SEARCH.TYPE_DEFAULT_COLUMNS.EXPENSE); + }); + + it('should return default columns for CATEGORY groupBy', () => { + const columns = SearchUIUtils.getCustomColumnDefault(CONST.SEARCH.GROUP_BY.CATEGORY); + expect(columns).toEqual(CONST.SEARCH.GROUP_DEFAULT_COLUMNS.CATEGORY); + expect(columns).toContain(CONST.SEARCH.TABLE_COLUMNS.GROUP_CATEGORY); + expect(columns).toContain(CONST.SEARCH.TABLE_COLUMNS.GROUP_EXPENSES); + expect(columns).toContain(CONST.SEARCH.TABLE_COLUMNS.GROUP_TOTAL); + }); + + it('should return default columns for MERCHANT groupBy', () => { + const columns = SearchUIUtils.getCustomColumnDefault(CONST.SEARCH.GROUP_BY.MERCHANT); + expect(columns).toEqual(CONST.SEARCH.GROUP_DEFAULT_COLUMNS.MERCHANT); + expect(columns).toContain(CONST.SEARCH.TABLE_COLUMNS.GROUP_MERCHANT); + expect(columns).toContain(CONST.SEARCH.TABLE_COLUMNS.GROUP_EXPENSES); + expect(columns).toContain(CONST.SEARCH.TABLE_COLUMNS.GROUP_TOTAL); + }); + + it('should return empty array for undefined value', () => { + const columns = SearchUIUtils.getCustomColumnDefault(undefined); + expect(columns).toEqual([]); + }); + }); + + describe('Test getSearchColumnTranslationKey', () => { + it('should return correct translation key for GROUP_CATEGORY', () => { + const translationKey = SearchUIUtils.getSearchColumnTranslationKey(CONST.SEARCH.TABLE_COLUMNS.GROUP_CATEGORY); + expect(translationKey).toBe('common.category'); + }); + + it('should return correct translation key for GROUP_MERCHANT', () => { + const translationKey = SearchUIUtils.getSearchColumnTranslationKey(CONST.SEARCH.TABLE_COLUMNS.GROUP_MERCHANT); + expect(translationKey).toBe('common.merchant'); + }); + + it('should return correct translation key for GROUP_EXPENSES', () => { + const translationKey = SearchUIUtils.getSearchColumnTranslationKey(CONST.SEARCH.TABLE_COLUMNS.GROUP_EXPENSES); + expect(translationKey).toBe('common.expenses'); + }); + + it('should return correct translation key for GROUP_TOTAL', () => { + const translationKey = SearchUIUtils.getSearchColumnTranslationKey(CONST.SEARCH.TABLE_COLUMNS.GROUP_TOTAL); + expect(translationKey).toBe('common.total'); + }); + + it('should return correct translation key for MERCHANT column', () => { + const translationKey = SearchUIUtils.getSearchColumnTranslationKey(CONST.SEARCH.TABLE_COLUMNS.MERCHANT); + expect(translationKey).toBe('common.merchant'); + }); + + it('should return correct translation key for CATEGORY column', () => { + const translationKey = SearchUIUtils.getSearchColumnTranslationKey(CONST.SEARCH.TABLE_COLUMNS.CATEGORY); + expect(translationKey).toBe('common.category'); + }); + }); + describe('createAndOpenSearchTransactionThread', () => { const threadReportID = 'thread-report-123'; const threadReport = {reportID: threadReportID}; From e53a673789da712447352cac8dc714e0111a63b5 Mon Sep 17 00:00:00 2001 From: TaduJR Date: Wed, 28 Jan 2026 00:43:19 +0300 Subject: [PATCH 02/24] fix: normalize empty merchant values to avoid invalid search query --- src/CONST/index.ts | 1 + src/components/Search/index.tsx | 3 ++- src/libs/SearchUIUtils.ts | 7 +++++-- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/CONST/index.ts b/src/CONST/index.ts index a5f849b9520f3..be8ed90a24414 100755 --- a/src/CONST/index.ts +++ b/src/CONST/index.ts @@ -7145,6 +7145,7 @@ const CONST = { TAG_EMPTY_VALUE: 'none', CATEGORY_EMPTY_VALUE: 'none', CATEGORY_DEFAULT_VALUE: 'Uncategorized', + MERCHANT_EMPTY_VALUE: 'none', SEARCH_ROUTER_ITEM_TYPE: { CONTEXTUAL_SUGGESTION: 'contextualSuggestion', AUTOCOMPLETE_SUGGESTION: 'autocompleteSuggestion', diff --git a/src/components/Search/index.tsx b/src/components/Search/index.tsx index 87e089d94a9d3..fd86cb997df8c 100644 --- a/src/components/Search/index.tsx +++ b/src/components/Search/index.tsx @@ -828,8 +828,9 @@ function Search({ } if (isTransactionMerchantGroupListItemType(item)) { + const merchantValue = item.merchant === '' ? CONST.SEARCH.MERCHANT_EMPTY_VALUE : item.merchant; const newFlatFilters = queryJSON.flatFilters.filter((filter) => filter.key !== CONST.SEARCH.SYNTAX_FILTER_KEYS.MERCHANT); - newFlatFilters.push({key: CONST.SEARCH.SYNTAX_FILTER_KEYS.MERCHANT, filters: [{operator: CONST.SEARCH.SYNTAX_OPERATORS.EQUAL_TO, value: item.merchant}]}); + newFlatFilters.push({key: CONST.SEARCH.SYNTAX_FILTER_KEYS.MERCHANT, filters: [{operator: CONST.SEARCH.SYNTAX_OPERATORS.EQUAL_TO, value: merchantValue}]}); const newQueryJSON: SearchQueryJSON = {...queryJSON, groupBy: undefined, flatFilters: newFlatFilters}; const newQuery = buildSearchQueryString(newQueryJSON); const newQueryJSONWithHash = buildSearchQueryJSON(newQuery); diff --git a/src/libs/SearchUIUtils.ts b/src/libs/SearchUIUtils.ts index 0c82d81859665..fd0d2922274b6 100644 --- a/src/libs/SearchUIUtils.ts +++ b/src/libs/SearchUIUtils.ts @@ -405,7 +405,7 @@ type GetSectionsParams = { function createTopSearchMenuItem( key: SearchKey, translationPath: TranslationPaths, - icon: Extract, + icon: IconAsset | Extract, groupBy: ValueOf, limit?: number, ): SearchTypeMenuItem { @@ -2213,8 +2213,11 @@ function getMerchantSections(data: OnyxTypes.SearchResults['data'], queryJSON: S let transactionsQueryJSON: SearchQueryJSON | undefined; if (queryJSON && merchantGroup.merchant !== undefined) { + // Normalize empty merchant to MERCHANT_EMPTY_VALUE to avoid invalid query like "merchant:" + const merchantValue = merchantGroup.merchant === '' ? CONST.SEARCH.MERCHANT_EMPTY_VALUE : merchantGroup.merchant; + const newFlatFilters = queryJSON.flatFilters.filter((filter) => filter.key !== CONST.SEARCH.SYNTAX_FILTER_KEYS.MERCHANT); - newFlatFilters.push({key: CONST.SEARCH.SYNTAX_FILTER_KEYS.MERCHANT, filters: [{operator: CONST.SEARCH.SYNTAX_OPERATORS.EQUAL_TO, value: merchantGroup.merchant}]}); + newFlatFilters.push({key: CONST.SEARCH.SYNTAX_FILTER_KEYS.MERCHANT, filters: [{operator: CONST.SEARCH.SYNTAX_OPERATORS.EQUAL_TO, value: merchantValue}]}); const newQueryJSON: SearchQueryJSON = {...queryJSON, groupBy: undefined, flatFilters: newFlatFilters}; From a7728524a1da41cec34b9785429fd07e13c7bdec Mon Sep 17 00:00:00 2001 From: TaduJR Date: Wed, 28 Jan 2026 01:37:44 +0300 Subject: [PATCH 03/24] fix: address PR review feedback for merchant grouping - Display "No merchant" instead of "(none)" for empty merchants - Fix sorting to put empty merchants at bottom instead of top - Add noMerchant translations to all language files - Update comment to include TOP_MERCHANTS - Add test for empty merchant query normalization --- .../Search/MerchantListItemHeader.tsx | 4 +- src/languages/de.ts | 1 + src/languages/en.ts | 1 + src/languages/es.ts | 1 + src/languages/fr.ts | 1 + src/languages/it.ts | 1 + src/languages/ja.ts | 1 + src/languages/nl.ts | 1 + src/languages/pl.ts | 1 + src/languages/pt-BR.ts | 1 + src/languages/zh-hans.ts | 1 + src/libs/SearchUIUtils.ts | 15 +++++- tests/ui/MerchantListItemHeaderTest.tsx | 12 ++--- tests/unit/Search/SearchUIUtilsTest.ts | 46 +++++++++++++++++++ 14 files changed, 78 insertions(+), 9 deletions(-) diff --git a/src/components/SelectionListWithSections/Search/MerchantListItemHeader.tsx b/src/components/SelectionListWithSections/Search/MerchantListItemHeader.tsx index 3c61f44b776c0..2a5db71bb1bbf 100644 --- a/src/components/SelectionListWithSections/Search/MerchantListItemHeader.tsx +++ b/src/components/SelectionListWithSections/Search/MerchantListItemHeader.tsx @@ -1,6 +1,7 @@ import React from 'react'; import type {SearchColumnType} from '@components/Search/types'; import type {ListItem, TransactionMerchantGroupListItemType} from '@components/SelectionListWithSections/types'; +import useLocalize from '@hooks/useLocalize'; import CONST from '@src/CONST'; import BaseListItemHeader from './BaseListItemHeader'; @@ -44,8 +45,9 @@ function MerchantListItemHeader({ onDownArrowClick, columns, }: MerchantListItemHeaderProps) { + const {translate} = useLocalize(); const rawMerchant = merchantItem.formattedMerchant ?? merchantItem.merchant; - const merchantName = rawMerchant || CONST.TRANSACTION.UNKNOWN_MERCHANT; + const merchantName = rawMerchant || translate('search.noMerchant'); return ( localeCompare(a.formattedMerchant ?? '', b.formattedMerchant ?? ''), + (a, b) => { + const merchantA = a.formattedMerchant ?? ''; + const merchantB = b.formattedMerchant ?? ''; + // Empty merchants should sort to the bottom + if (!merchantA && merchantB) { + return 1; + } + if (merchantA && !merchantB) { + return -1; + } + return localeCompare(merchantA, merchantB); + }, sortBy, sortOrder, ); diff --git a/tests/ui/MerchantListItemHeaderTest.tsx b/tests/ui/MerchantListItemHeaderTest.tsx index 7c78716194e04..7c706ec288b4f 100644 --- a/tests/ui/MerchantListItemHeaderTest.tsx +++ b/tests/ui/MerchantListItemHeaderTest.tsx @@ -146,28 +146,28 @@ describe('MerchantListItemHeader', () => { expect(screen.getByText('Starbucks Coffee')).toBeOnTheScreen(); }); - it('should display "Unknown Merchant" for empty merchant string', async () => { + it('should display "No merchant" for empty merchant string', async () => { const merchantItem = createMerchantListItem('', {formattedMerchant: ''}); renderMerchantListItemHeader(merchantItem); await waitForBatchedUpdatesWithAct(); - expect(screen.getByText(CONST.TRANSACTION.UNKNOWN_MERCHANT)).toBeOnTheScreen(); + expect(screen.getByText('No merchant')).toBeOnTheScreen(); }); - it('should display "Unknown Merchant" when merchant is undefined', async () => { + it('should display "No merchant" when merchant is undefined', async () => { const merchantItem = createMerchantListItem('', {formattedMerchant: undefined}); renderMerchantListItemHeader(merchantItem); await waitForBatchedUpdatesWithAct(); - expect(screen.getByText(CONST.TRANSACTION.UNKNOWN_MERCHANT)).toBeOnTheScreen(); + expect(screen.getByText('No merchant')).toBeOnTheScreen(); }); - it('should display "Unknown Merchant" when both merchant and formattedMerchant are empty', async () => { + it('should display "No merchant" when both merchant and formattedMerchant are empty', async () => { const merchantItem = createMerchantListItem('', {merchant: '', formattedMerchant: ''}); renderMerchantListItemHeader(merchantItem); await waitForBatchedUpdatesWithAct(); - expect(screen.getByText(CONST.TRANSACTION.UNKNOWN_MERCHANT)).toBeOnTheScreen(); + expect(screen.getByText('No merchant')).toBeOnTheScreen(); }); }); diff --git a/tests/unit/Search/SearchUIUtilsTest.ts b/tests/unit/Search/SearchUIUtilsTest.ts index d4b1413f8a77a..61dd50bc35eb9 100644 --- a/tests/unit/Search/SearchUIUtilsTest.ts +++ b/tests/unit/Search/SearchUIUtilsTest.ts @@ -2858,6 +2858,52 @@ describe('SearchUIUtils', () => { expect(result.some((item) => item.merchant === 'Starbucks')).toBe(true); }); + it('should normalize empty merchant to MERCHANT_EMPTY_VALUE in transactionsQueryJSON', () => { + const dataWithEmptyMerchant: OnyxTypes.SearchResults['data'] = { + personalDetailsList: {}, + [`${CONST.SEARCH.GROUP_PREFIX}empty` as const]: { + merchant: '', + count: 2, + currency: 'USD', + total: 50, + }, + }; + + const [result] = SearchUIUtils.getSections({ + type: CONST.SEARCH.DATA_TYPES.EXPENSE, + data: dataWithEmptyMerchant, + currentAccountID: 2074551, + currentUserEmail: '', + translate: translateLocal, + formatPhoneNumber, + bankAccountList: {}, + groupBy: CONST.SEARCH.GROUP_BY.MERCHANT, + queryJSON: { + type: CONST.SEARCH.DATA_TYPES.EXPENSE, + status: '', + sortBy: CONST.SEARCH.TABLE_COLUMNS.DATE, + sortOrder: CONST.SEARCH.SORT_ORDER.DESC, + view: CONST.SEARCH.VIEW.TABLE, + hash: 12345, + flatFilters: [], + inputQuery: 'type:expense groupBy:merchant', + recentSearchHash: 12345, + similarSearchHash: 12345, + filters: { + operator: CONST.SEARCH.SYNTAX_OPERATORS.AND, + left: CONST.SEARCH.SYNTAX_FILTER_KEYS.TYPE, + right: CONST.SEARCH.DATA_TYPES.EXPENSE, + }, + }, + }) as [TransactionMerchantGroupListItemType[], number]; + + expect(result).toHaveLength(1); + const emptyMerchantItem = result.find((item) => item.merchant === ''); + expect(emptyMerchantItem?.transactionsQueryJSON).toBeDefined(); + // The query should use 'none' (MERCHANT_EMPTY_VALUE) instead of empty string + expect(emptyMerchantItem?.transactionsQueryJSON?.inputQuery).toContain(CONST.SEARCH.MERCHANT_EMPTY_VALUE); + }); + it('should return isTransactionMerchantGroupListItemType true for merchant group items', () => { const merchantItem: TransactionMerchantGroupListItemType = { merchant: 'Starbucks', From 3b74d40f03970866ac701b5cc4e21bf6628311ef Mon Sep 17 00:00:00 2001 From: TaduJR Date: Wed, 28 Jan 2026 03:00:47 +0300 Subject: [PATCH 04/24] Merge branch 'main' into feat-Insights-Release-2-Top-Merchants-Add-group-by-merchant-and-suggested-search --- android/app/build.gradle | 4 +- ...nsifyHelp-WorkspaceSubmissions_Classic.png | Bin 0 -> 307882 bytes .../ExpensifyHelp-WorkspaceSubmissions_ND.png | Bin 0 -> 169824 bytes .../Automatically-submit-employee-reports.md | 93 ++- ...-to-Set-Up-Automatic-Report-Submissions.md | 94 +++ ios/NewExpensify/Info.plist | 2 +- ios/NotificationServiceExtension/Info.plist | 2 +- ios/ShareViewController/Info.plist | 2 +- package-lock.json | 4 +- package.json | 2 +- src/CONST/index.ts | 22 + src/ONYXKEYS.ts | 3 + src/ROUTES.ts | 36 ++ src/SCREENS.ts | 9 + src/components/Rule/RuleBooleanBase.tsx | 77 +-- src/components/Rule/RuleSelectionBase.tsx | 73 +++ src/components/Rule/RuleTextBase.tsx | 37 +- src/components/Rule/TextBase.tsx | 28 +- src/components/Search/index.tsx | 15 + src/components/Search/types.ts | 1 + .../Search/TagListItemHeader.tsx | 144 +++++ .../Search/TransactionGroupListItem.tsx | 15 + .../SearchTableHeader.tsx | 18 + .../SelectionListWithSections/types.ts | 7 + src/languages/de.ts | 39 +- src/languages/en.ts | 44 ++ src/languages/es.ts | 44 ++ src/languages/fr.ts | 41 +- src/languages/it.ts | 39 +- src/languages/ja.ts | 39 +- src/languages/nl.ts | 37 ++ src/languages/pl.ts | 37 ++ src/languages/pt-BR.ts | 39 +- src/languages/zh-hans.ts | 39 +- .../parameters/SetPolicyCodingRuleParams.ts | 15 + src/libs/API/parameters/index.ts | 1 + src/libs/API/types.ts | 3 + src/libs/ExpenseRuleUtils.ts | 2 +- src/libs/ModifiedExpenseMessage.ts | 25 +- .../ModalStackNavigators/index.tsx | 9 + .../RELATIONS/WORKSPACE_TO_RHP.ts | 9 + src/libs/Navigation/linkingConfig/config.ts | 27 + src/libs/Navigation/types.ts | 27 + src/libs/SearchUIUtils.ts | 129 ++++- src/libs/actions/Policy/Rules.ts | 144 ++++- src/libs/actions/User.ts | 12 +- src/pages/ReportDetailsPage.tsx | 6 +- src/pages/Search/SearchColumnsPage.tsx | 1 + .../settings/Rules/Fields/AddBillablePage.tsx | 25 +- .../settings/Rules/Fields/AddCategoryPage.tsx | 49 +- .../Rules/Fields/AddDescriptionPage.tsx | 21 +- .../settings/Rules/Fields/AddMerchantPage.tsx | 21 +- .../Rules/Fields/AddReimbursablePage.tsx | 25 +- .../Rules/Fields/AddRenameMerchantPage.tsx | 21 +- .../settings/Rules/Fields/AddReportPage.tsx | 21 +- .../settings/Rules/Fields/AddTagPage.tsx | 49 +- .../settings/Rules/Fields/AddTaxRatePage.tsx | 43 +- .../rules/MerchantRules/AddBillablePage.tsx | 39 ++ .../rules/MerchantRules/AddCategoryPage.tsx | 53 ++ .../MerchantRules/AddDescriptionPage.tsx | 42 ++ .../rules/MerchantRules/AddMerchantPage.tsx | 42 ++ .../MerchantRules/AddMerchantRulePage.tsx | 237 ++++++++ .../MerchantRules/AddMerchantToMatchPage.tsx | 44 ++ .../MerchantRules/AddReimbursablePage.tsx | 39 ++ .../rules/MerchantRules/AddTagPage.tsx | 59 ++ .../rules/MerchantRules/AddTaxPage.tsx | 51 ++ .../workspace/rules/MerchantRulesSection.tsx | 10 +- src/types/form/MerchantRuleForm.ts | 24 + src/types/form/index.ts | 1 + src/types/onyx/ExpenseRule.ts | 20 +- src/types/onyx/OriginalMessage.ts | 36 ++ src/types/onyx/Policy.ts | 8 +- src/types/onyx/SearchResults.ts | 18 +- tests/unit/ModifiedExpenseMessageTest.ts | 115 ++++ tests/unit/Search/SearchUIUtilsTest.ts | 540 ++++++++++++++++++ 75 files changed, 2899 insertions(+), 250 deletions(-) create mode 100644 assets/images/ExpensifyHelp-WorkspaceSubmissions_Classic.png create mode 100644 assets/images/ExpensifyHelp-WorkspaceSubmissions_ND.png create mode 100644 docs/articles/new-expensify/reports-and-expenses/How-to-Set-Up-Automatic-Report-Submissions.md create mode 100644 src/components/Rule/RuleSelectionBase.tsx create mode 100644 src/components/SelectionListWithSections/Search/TagListItemHeader.tsx create mode 100644 src/libs/API/parameters/SetPolicyCodingRuleParams.ts create mode 100644 src/pages/workspace/rules/MerchantRules/AddBillablePage.tsx create mode 100644 src/pages/workspace/rules/MerchantRules/AddCategoryPage.tsx create mode 100644 src/pages/workspace/rules/MerchantRules/AddDescriptionPage.tsx create mode 100644 src/pages/workspace/rules/MerchantRules/AddMerchantPage.tsx create mode 100644 src/pages/workspace/rules/MerchantRules/AddMerchantRulePage.tsx create mode 100644 src/pages/workspace/rules/MerchantRules/AddMerchantToMatchPage.tsx create mode 100644 src/pages/workspace/rules/MerchantRules/AddReimbursablePage.tsx create mode 100644 src/pages/workspace/rules/MerchantRules/AddTagPage.tsx create mode 100644 src/pages/workspace/rules/MerchantRules/AddTaxPage.tsx create mode 100644 src/types/form/MerchantRuleForm.ts diff --git a/android/app/build.gradle b/android/app/build.gradle index 77e800db9a398..9a23db24562d3 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -114,8 +114,8 @@ android { minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion multiDexEnabled rootProject.ext.multiDexEnabled - versionCode 1009031001 - versionName "9.3.10-1" + versionCode 1009031003 + versionName "9.3.10-3" // Supported language variants must be declared here to avoid from being removed during the compilation. // This also helps us to not include unnecessary language variants in the APK. resConfigs "en", "es" diff --git a/assets/images/ExpensifyHelp-WorkspaceSubmissions_Classic.png b/assets/images/ExpensifyHelp-WorkspaceSubmissions_Classic.png new file mode 100644 index 0000000000000000000000000000000000000000..9395b4e95b07a87450c47c2cfbb60a17fc4ded46 GIT binary patch literal 307882 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

=L^5`ukInFC8*BrSC_+=z*|i=*G&5uC@H1S~niy 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

8y zU9og1BQ$cYEQ_msMxHHCqFvt?{(qOJ&5tO)GfH)5-HsTvef7gChC6+a8F*P73`B?MzUQ^M^-b}(~>Xpt9I$%g>lJQE{E(I zwVlPe3jag{NkZDmD|TYcsT*vRjTuV6cbzTYodY3_b$?99nX0|IlzY8ZUeL1WI5XGr zA3e)r)5XC{A;<*X)6TB@jwPcq%utETB8=iI%Y3nhWAKfBFr@-BdSr$^&m5rPLMuDD ziD;oN{7zmG%S<6i^9i;}y+!wx!b=_3y?R$wy3bp7TsDgG%Qen*T+4UEUMjA)Y>o6M zdYDhT+3+gE$RnttcE2YuWrf3Z{us&Dbp_qi@1lJxc1u;_R(VY?g<~gC#VcZ6C)ag5 z_q&&;9^k0?O3J_3QuyNCN_CYc=zYFfX^*BD14aKxj(wpqVXtvRG8g;yA=7$T-DlC} zZ_oaSqp~2Wg!iuQ^NngvyI=;|r1D0k!}S|y3~QrT3<+;kfaM|DS1XN=7S4)N#H`Lt zvn2J?{jXOg@QcAqChH3+9)DWC-pNVlr@c@xa+aY~;JH0U)ij_IN%>B_?&l^ug~W9c zpr`CFyv$kw_iW%}MD0B--ECOXb`(Old9gTlDOu%3s4fR zIn%gcBmJ9j|MEWwtd{HKeiTt3Zv7GqxV+J|px+d=%*CNbj}R94X4K=CA*64Bjf5V2 zdO8~z9H{LSzOUvL)3?m_ojRvm@wQgROfcOW{Noa7&XV>eZ)3B zI~~4PQ51iJOAIh>NvUWwhVp&RpL(IUlmC3`YR zd*pS>`5)u4`h}&f7`TiF>gSm=%(uDdP2B^A(fp_{MIf{ZpmR(E?>`a5aZ{-9s5aA| zb86I9JQmlp7&FX2m#$stFeA3)z(w+bM4cl6XO0Xm!J6kDmVYzNRg{Uq85uX^nu1_?F7v? z?tnXo)Cu5ZXQg59pvV)JawiY7E7W5juWoD3W6rwW6*F?5U+ZS%WH+*GQq4QVAWWj^ zWDD$g3?AbO^bsiRJli>@b-%^dD2~6yz57&pP z<0tHthoRI03MW3Yr24yBYbt~eMb@$Hx+#p*W3I)0vubP#DKhUvT^C{3p?bGXE#7hd z0StxA>ArgSnsG&r!{=6ASC^Q#9PSQ@H2!}LQkLX>=Sdy(IyH5g#0Ps5hOegRXGc24 z|HtZNc(omAie74dsf#;Oe~e4Z7#dNT#23KRls4qTwKL3x<)&{eR?}f9=(wKt@_hMx z_#At2IrMiqmcm5wki+mF&vMx}e$GSo(PLt zuD4s+g-fYPNN-wN+Z-+hP}=9m^`cTDKW?dt6w2u*E9q8W8_-0?HLD1lG5=?2cu~=N zBgS0;eiD*W#nR*Yiany67)gVLHOP~E18F<On?a$9qC8f$_2(qY)6ygM;LMelH!nC8~ z*X2gVMJ2HAsNA=`UMrdm{+^Xb24-&NtsSIdbuoGkCidjqxMzO6LC#hx>GW_`}e>v-RTi2N0HLS%;y z*eg;M)nSOOp)p7_uUZszS^Hmq) zy%ZAdWp_GXYy+)Yw{5ti{i)C3ok2U>Ar0+*4<;I-Ad-v!nR_ zUweD|hHFHJwm)_Q^(lzUC8n|gUR&fOq4~;i`Z9ED#3a3A7RP(}@LRL9_M6ZbOZNL7 zq%MaK`o*;HuZgZt;7Z->DUS$K%+%+-){0%0EE*sUTPrK zm~-vMk(UrrjPR9^a%>O2;9CZE?NPfE6p8O```K3sIWti|N zz-zFtIhtH6V>uo_aa)^@wQ}qsjSX8~TG?IyDD;V5^q&qf1!s3RHCHGZm;zE^Ib>ci z!NzAU2$GJ+ukP-S*ERK4E$!r3t*`HTpv*O zkjH>^KCLdqX3_eSvky}#PMz_g`Zou#Z*e}wKttrdu6BG9KHP!pwXbb}qT33L8{aR} zNtdc2^6gdqW#S1;w5b-^?x|`_UxCW%6&TBP43ThVAItReboEU=jye8Os&%A9b(4K1 z)JOF!RS+HC_&}E<%cn+6emzSq<+LB+%W(P+s~3j;k#{im9;>Ec`^CXscFW@HgJZo~ zn{G*-ACphD^hs6J?{D4Pk$EbCBS9k9g;X~u?`+b@U*Gtw@gAS|_WxM6r$2pVq97nP zbrT*2hW?^;cA$^@65q5CFZ8LF780F8(wI&mECb8JE)e)KFjpU$iNGUnPF5b>Vv2Ss zB%~ttB=9h-&g;*|*I1b4pSes_$dD_S9@k~HlHgh!&;HdJ0a(VRMI#p{`>9lh_g34I zPv;X8@<)5)qE__=%fz)uufNNXa!!&P;hC&~%>g6fbCC=G;w03~`&xxVdG~DLm|S7^ z%9Nqo_tSpOBv24fR1{PM)&CQxmJpK5U^d&vW-iw3Mqr7|O*;&Ez2mj4TGz16pcOtl@ zeqLYx%XAWaG2*%iRQEd#Jk@wj7XNiKZ?{2!7ZVFQEhn=ugmn~H!ip60J;A7 zi$cP5U}Qu5*(q43u&}VWgq7j`{Jm9n{XLiYOoGAmRZRMy1Z;=U@u{S&=J63tMcQN6 zN%`4UU8*l{m@jST*zi;1?;iPhRY_QS(k!{`h8wcIW*Ko`p?>zJSVxbI(|atO zkwg!^g+sYThGf!Le5ReC5H=%0kwT!$OHA-z6F>De+UJW+ISczKA-&7KD|Jlb(#w$ zPkX5oa$l7wJr&nL|A-uZWFikUTmz^6DD~8OohVJWcb5 z=Pqc?k&PlO>|M9lms73RQ&k=jXw6s0PpA05cYX1mX|Rr@!qI-G!SM6Si$x__@ztj;58Y6h@(<6|%zo`!ABc6a7S- z*W{D_Ytxp=c`%%ibxa~Iz|`9bZobQK)0V`6lQRaF31j?H0+x1M%K5V#pZj9#%;;?p zOA>Qu@|9M*k)=x5{zN0v(b3c^<^Qjm4V|k|q@UHrdE=)t7@WtxpvfB|V^a%GdZI($ zm16bR;IYDLseO5yg=)x80kA^k#mPsNsK@LNQiR*=N~O0Re}2L;AbaCJ18tGe)T2`N zGy0%$8v~26)IvpFIJ@$C8tE(r^tuT#9X^bgf{DxC$>T9FD@}D`UzhF@_n@Gu$kp=& z57c$$Yd#-DJ~69*1wKaySU@y)nYH>EGW$YEwx6pU-Ji8iNcr?ZADVuK{ZB$?@^f6p zThw+*+27lBOEgsqdqtitaCd~h^17Cw-~a?oZe<+4!!->kdP|e{2ycm5iXgV<&NqA> zsJ|PQWPUh`XJzu>x+>NhRgaCH9v%7qWq8%AN5_p8-X7mUJJ~f`X>3I*hx1UyG%Xbv z2lGq5;AVWr!1IdJ@i{SDvAd3+TQtPHs|7Iu6MC7|Tf|pwogE-g8jizIzC?9|#Mihk z@ZIB`{}aX^y=7xGitC#4-#kq&ev-bI`YDJi1RG!zYD9_|LJun6D$|Yu1jS>_cRIsP zj0}vwH+TiKHT%{ZKz6YhVojozy4Cgs(Z_sN?5ob7Ev)D2$z316z1@F8KOT~x>i-|%+B4*lZ>#>ZMlq2?UR3h^ z-=g8@qA|g&VLjN{hWnlQ& z>bCRgD0`O!N6)PI-#`K`QZycL9|#)MuC}dqB*um~ zuX9reAL6uH4Y&x%V1~t%J?aUl_F4Q%l*Dhvd2A5LV|U;6msH*G^IacZG4Z-vx)f8} zBTeQFkanWKL7#%F2T{h+U=Nk?Ns!S}lGkeWK9~Pa3hS*=E$RHGXRgbI1Xgs1#=HL} z$9Z#eAN}}Gr6FSOZmN*Yc!}1+&pU-jw(KedP3GG6y@tz=(hV%FX?I95Df91);f?R1&lyFO9=T`%sj`GiDzX-~~dyj)Km9vhRv_F&U-JWIlcH+EL zTD2RLqRfkvwW7wjimn@3^Ww%^u%kFc*kRBjle%xKoCYUP{jGkxS4Bs{Ql@fR5-Zme z;J9e)@+S*9lz?!0h32#;(hmxvuPYv-OB zD`qcp{QT|fpM_CU!)xvH9@@8SWcnO&AO4+<@N@^G?B-Ny)YbVF6r?JU?JvbLzBYRD zc#<+msLM<>)80@sl8h!{;OaGYNH;fuTidBqn?E%oUdV~ZHlV#|)D@sE98y~1^HxE-cT&(PFi5WE4oYK92A5L%jS_2&0?MqS}u+2L95j92(iZ|8! z98hPdx`jcn6z$h4;#qTJhHiSrs!D$HJ-j|vRo?H1VWdhBh>@7d3uTT&e*=I;`7xit z3k8)1!Mvv&^Ykfq|B%&rwx6ADe_LSMe30{3TZMO0x9CgH9fpHzPRYqj@51R;f-hDgmo6+it*q~(a9WtmRU zYrZdO!UIl*CBvH}BPB^M%N+B;v9#gZ6xtNyDf8%QVO=fw#WY+}sn2%%Lu~X#Ekc*ZSzyo3_euUC6MC_ zmRf?x*uNX4BCe-43v^lE1Wn1+arNvs{r{C9ifi^O=j()fh4(i5oy<;m z<*_@oXqF64zCGL0o(fgL`(VjHjwF*P0x&Vgp&KxemRbRtlodE>8PRq5&LN8^_LWq7 z&$~0`a{9s9=7yI1g%t&kpKa)d|Jal~rZ!mxGF-i#BzW|7?52eu(4XX164R969aCDY z>|>hLQothrJ%An;REVNMtKPmHaBDk`?x&B04jT4vXS!O%nzn~7xehT#SKP16UUU+gp52p0U+U1ARiZ@-%To(BUcCT$$zJ6@ zAOAny_4nUec>!SPs^o8Oj_}tf9wilsU7vY?aB*+J9icUj$HS}h9yHo6CMtuW?~{k( zj%6-IZsK#cA0o+ja%h}ES1T;cv3yh|r(|_TIKJEHzNjOve9{c$@U%$- zf_FH%j=ni|0I*?~-hk3tqdxNwUIb9snaxdc1-v2`NtNq0!q<6BhUvHt9X4q-OOfcW z9NIOp`E6L$JV4A@23*+adUoj@>EQfvjw;L zjVJ2oj0E?qVofzFKGwYtoPD3IHf6MC_NPy6Ou6jKm!nGJL1To~FK7>FBJWwiPrA#1 z8Dx_;In_J8)77a1J;jZiM;F8()YVm_XV?`P=(LyekH(*K@vF?Xt~u8Gi)X_RiJ-ZZ z8OFEE|IXDGa&js}#@aq~MlVQ@6^xL(s>NC)^B|p?mOQvP{C9)oPk+CD73-t?AB^}f zMCq)*9QJH(YrnoA8xn^1L)CNzBNmjMdUGwX?o=#ctN;XHG~!HaN%@_bzfy2I6{Fq- zLE{qZ3^`Ysj|ppB{V4jiiMyou%<^T)myvE4m}GnbC?%qkzQ*A!l|`sGw`dKIU0+<~)_ihE}x&rszNB6w*o zB@PHa2iU}0v3$pP^Z7h1ZQh*oRtO;~2CxIrrH=)NSQSj^rWmSvz^w|H%A>)Xn*h=~ zwA!nElk3cdzQLOZg@lCW&o1E_P8(JOQRh2Kpu-uaO-?sbVlBuK5>4~Zwc1YYxAGM>%vJaH zizZM^CL}1&W*Lp`EZ-7q*hikuS{v0f4$thGSpBA|?(C-vb1(R9w4d?LKa&IFuhqn! zowx48w4;2sRj&MntnxJi4O^SpA}kw(;&SzfYU`zM{$a;(-CB#z4r)=5kRumZ_qWR93o*rpkC;&b;wl@b zS&c;h4Am6|7>3(sr_%Rl_#|%8p;`?)Yf>QUj-!*6igs-XzitD*OofbfREUgr)ELmP zR21YVKDO;>-#>@G?M(`!67R^h&0Dv%>Kyf_;Sr1LzBF)R60YhV8k;1K^VwsYLvQV zM~5R|)eJ08=_?a3ZXJiC*_+?yYmL})1NXhbVtZjQTm&jlWU;aK zP2xwm1Kowb?e9NWEBZzeNUPg|w;?|ogTDTmoEJ8NEl=+}x7I@uQn266S&R{+&%X@( zBQs?26o2#jqWTy=?I5naUMi;u=dj^3d_FfVX^cQlb1<$TPk)ZE!N3lG;58g1cf>Xe zn-m=PBKz4!UYPQpR#=@~4jYDFvEHZDs@DcPXyhh=4(V$H)o9xLg@NwZf~FIUk)_l@ zn_<{++OsyRnj|V{daa@@(Z#=s18O)8I2QQ=)-22FLPP(Nh zcS_67ShXE^K4+v-e%*u>r9*8)tKVchBF|R0iM!Bh5S_?84DoPD^h$rN^%u%Dtc?R}H2gyN?l1Z3S#^6 z?>Dk+u67ug&gv$TGYHoo;qxvS^M7}tmLe7hA;44-Esx^=6u8u*4j`#+?zdaa-iT;-~R?go_wq)Hzng9w(=bg;)vns zOn1`pnVr2ZT^Cojm|6_*^;s5j{`F!hIQXh$dk~adi*?5-ZRM46Euq&R+z^iB+%Z}V zHkq&!om6NQj}CDa@?@GYF3|T+61j0B={e(nHeuLiEGBApzLA8xi47z~mf* z#wV7H8qBcAdY0Pnd9qG#3fgs~x+nFxVb8Pon(yt=V5klsFa@4?W#mQT8OClnt=63m z)Y|DD4E>4@lQtR}^@2V%T&P#x92I_10e5*Yf^!>zOZ^mgW|zI|>9U^$ z3Sp#-Veo|0U$x_|gE=h0JKsw~Q}8<;0WGh7F)E18#{5tK?feDj?T%SSV|bw>qLz&p zo|OTU8QV4$x(5q*_(BSV(Gx6pq`)*t`~&>}y=RXWaxOqbmqIEDe{gE(yS5Af>9Ea! z&Z~_`PO43JWoxz{oquu5Jh2gp>WAk;*NE*ZgT5^~%bNG`)eUX9wIM=IMSn0CHOA*l z`4`aAnAP%RG+Mee&&uKsg$V{7Wt3%h{;{_sV5i#|;)@@J!qPnd?9C950jK8$zhND! z9gXEVO{+qc|KblGN%QuNTnFR=_#s|sSEbQx}?+mnTTz)egwG45-8dY+j>N)~O#Gi~)9D{RE&%-BSN(?tH$N5V~UDAxQK;Pf28eXgk~4le1Aa2lvfT3;68!RC()KC}3Kx=%>{rBAp7@5Pi_gSx|Lr6JJhAIFU1 zhia`h{)iUX+TWz?*JFw(uA;H#&w%XA#o%o-KBM`(;tV^-awB8wfLRZibM1kJv6*M5 z#ckJl&L<;_L`2z}5H9}N&tfm?TNh-QFC7BL+_bhL3#urViE zRfLW6DkkI_6RY2JYPQxRUp}Y1T)-2Ns6smYUi|rUaqllrRfTw4=NV?9m%>KceXB8m z_{J}Nuldz7wGHiTwV`wAa*U&ymlslM7H=J8Ty`BVQtxhIMkiO^MO>0&dM67%{^X>z z;SQ*`v#xI2mIjzK8u3~bm2nI?XO~}PS%W}&G77o}vKAfSM7nH>mcdyV2JEoSfi3|u zv>~*6S-qFMF1Y+dlpB_97=JAg=bM5=q<*(;FPjSb}Gv;ZM@H6+|=1`ix^8Szfa)o7&Knn$a_nmo- z*O`~=$fS;Y&{BLmHu#F`vgVWtw%-Ux`rgdU1LbvAJvHvP3Y(t+UnU^ALb?uOMMLxL zXb$%4+xjwM`Fcq+$t}6dg=p_#m{lXmhw{U5iy!LK9byCC+a`m8h+BXw zZ>V95uP;71@k3f_>TbkeTnSVLIH%rNK66O6nnEOR6kxETBW%}}HUh3tw=*x?RNRJ- z)2TYvEx$ttInEG6*gYz7pY1CrqBp4R^l)>V3V02-SzoC2pn1+Z16*mkuI~7Lp!l)2 zEve4y`1^Hx1*AU-x9v+s?IC+Cvec+jNq9b(EVWZJHWs0qZOrolFR{=BocTE04aZ@y z&=8H@c#$7XLc-(%CFXkS*`+iwsnFQuTuxC_f9q$trwvlJ|(BIu@ zf)tuu%AMYPuAZt0XytfFq9r4#zRX^@#6HPs8v9vz$DT2N#tVO%NZ0Dts`-XsxzE^+ zY$eWH&0^6hml=*ll5;_mtiy}vUAY+9il5>(ASB9pifvAt6&QM6)fV=->fHY?*?tMwnpU@F&-xUrkuLetR?uo3YFAedoORiHe7#(E=aWhE_{YTtq2PsFs)L2WQJ(~p zC#N(9p1!k?rZMxs?WNDI&dJCF%wlHCtcI{`{v$4{jwEq)Ly%jYbgPe6B*#yb_HQes z&9SKeET=z*quK{#t;=TOn^a#U028n|-09ES+Wy2X->In4-70M_6V>8@SMp3qJHSKE zuF=ZtF0hG+Q|>0s-@UOpD{NeuAGSvuaZ8tXnSR9Fir!h19L3Fkw7HV#u^Ezbc^j%z z=?ni&$b+dlxVJH8W0Eoz7B6}R_u-zMNIHeiM+(vhims>`&yWpp*ob9{&9B|#?en89 z7?at0ONSlgVqQ&eA}fBKkh3n$m+0}@E#CoBlBi<@60a@~*fb4L!lfyoh}eW=f>ce$ zm=EI!YIB-f;QTl+sxzi`Y&_9)x z#CCAdKcf(lJtfTSQDs1-A#%BkfTdSweOCrH-NEgZij205o1|Hk)Zf18|Fhv0{<6v* zDQr=3v(U~!2~gdVh)LUvutsk>`k<7-_>SL32eT=?s?CzIG$sxB!rV;AcIWgwdzG~N zG1e;D?xjY9(a{2vdimoz38=fELx$qZs+*2;`Rk!{%2X0DH0=8!gt_4PhiyOMA*`)&qvE;o|CURLU7 zW$MFjQPnD;gkhETf6mMUYzFbopYO6IjRo`1qs_)<>UuHrHE`VR`JVr%M%;hF9$wNN z*|b**d^-IBr9UH0f)c97Jy&41bQp!M&TmSHi2vHA@A)BrX*Q}eAp%Z$LN(T`NWiAp z*Yb6kt;J9X6~LlpWlI{mFEZ9KV6wuB|ELst_-}8rpa`WqUv-oZ!#@Km*?KhhE;vSr z;MagYW){pT?+jY#-zw_-G~zeyB?S?M>^ce$jvMZ=Wd|TlHM-2I(w^JnbGmVVmT!() zRCg?!Ji`j9H{PM8St14&A_d$5jjQS&m{(K;dFa7g%mpJQf6Jh12%&Fj*b#`f%Zv`N z2}_r68+1f7*eTs^ZBaQK1)zROE;b1wDgPwVl-EFC*_MCZT`sHVZ2l(=aE&~GOLK%@ zx06N-)++uv^Yn1O**qLjz~qI4QhUPUvx>SQWmBrB9?dVS&a^hG4Eh-5Ezj#6T^nx7tVS@S@W?MF^{7Pfgl1`Wdn4~SZq7I@Mrt$L$A>t z4*25Agv2iW2WiY~yq8~j)CgE(+6A96uMAVDO-Lkm-hK#W*vo>hw5Q?7gW+FXLyayi z<{cq3x@E=}yN{L_(-`tw0lM3kC?Nt3YMtDseaCS3n*y4}v znC{XQ?kV{qc%diS6=BOil<|g9Y%!pBM2x+v$klVH!a%xp_&J+2-3GKOP2ut5xs2r5 zuXr7I?bizY2j@*k{7bjrHz~!^uvXxgYA4$D)0e8+jJWgs)`W=1qeCNSoADfD$=3u< zF2=8fWv6Y9^7ExBZx6@xH)gg8&#;HHj)3<@p<4+le#xR86_G5ISg@2yAMVK3dmY;rwdQ<$%H z!5{L8{c5_{9=h`jLAfIfMa@t1NKbo2U_S-@1m-(qk;+4~$Wk@t?FftPrZrtC$CG^M zo!ipxZWK&CfY4(OdF;m2>tqfQuKg=t%j-2qAo3fA+ysf@Y~GdT^2}63;PlG-pzA|} zJYi4T);GDJiL%B z%{|(q-T+A0AWI4SckNmF_l#9GhB$~`?H`|f%2x|gs@Jc6venqZ510o(&c@(C-OI^R-14BEm&6}KgN%4(y9%8e!e~|7 z!9q{f>-~DD&?{olEcqsDScc`4S)^TdTJc6;ts7+4I*AW{}6YLtV%uztasFC8>gs(gTTC~G zZj0#MIoma9^~7=fsd9Vr>&dQ?2OMIBLgJeo4(4F+ce0y$ciW6>T_W58VnNmZoOpD` z?9QEl5p!JdR8uL9h6l28zh+WeH422P&l~c`G@RCJW;sIw>%zd^9d6+$E=cpSGSdfI zVUE#ucNR}bG6&Fc=y2%`h12XOV@@s2DE#((GKWC&axj#urK{#8Dqy>w8k?dT6N83o!T{l_7 zXSd(dK?#qp*cU#LhN3uR|Dd9qrAM_(7*e|4p-Z`U{gP`P(B>Y{VUM5u3+Kebu&8xd z!qp{gKT9yrydYh{bI^v03G$Hb+^0SRF5Mb;0K{=trj`)gP^F%iy%66EoaR+q{d(;& z`T%*QY&U!A535`M*{Ps4@0Sf4tL;~xZF$x;S|aDkh1sl%ehqVD4$*CHGj?5xaCU2$ z&)2=^XJ|?)rBl+6$1rOz*Ucoay+?JE)L$boce-UYJs=W>n^)Qx9r~lRp3q5d3J=#> zdTLQRJk8+$Cg`VvSjCh1{U*1cq@P?HRG!_uc};xR+KI$9c!1j#jQ3e*s@4xcrbQ!g z&o(4>Xj!Z(I`JUcn4bxoOoN-7p#S5351Qt(I0%NK%);l2V@qR|L)GR2$X1FzF`^FjD;5xCKUqf@a^fw}1Fp~0eO z#jglt!XUxzcsItlF5=Ql%BR~BRbLfsS(w*x%>}dXi@2!(!BoLhYlB`^M!;eJ#T>-0 zc8P8b_;6ZzX2bH&-X)Gl5i{*w_!8_t<`F|NNanw zBZlTPN1ho>%yy$+V@p=$1DWD9rMybjKVuy(z3P~)*WkZz!}Y};iz{rOezIp^V{}rV zb7uZ{$eOhu?;%dw_uPXo8S&4JM;gc1wGEz=mVZ{|;m~J2!i)Z=7p9KQMg|AWxO0yk z901@OVtQ^(Gn)w|%+-8;Mz!w`MKPGv{l`E@*Qth;%GSHUCM&LxXO~+!LOeRzp#*#X zdO}5PW^@HuI101~Zu&A@;m$=p|I8msY&vkam`5KlAI>>vVT6wkB-~(OGPOvTw$WC~k}I6`P>CJA}e7VBgzVcOe9|du;BImc|Ido)UKO5?$KC)odwv+oRRYTKfXAfg~(LzHScC`hwV1PoD8K#?ZB zi}c<*1W<~ifT)0o^xlycS^z--X`v=S2m$GYCM|>z@)qadx%a*w@5kFe;M>X0UVE** z%A8}2ITuR$%xv$OQmTe<=)&7S=_xi>F06IJMz_MX-W3BYLH zX&!D}O1(LR!uXyTvwS#fn7>E$t=bk^H+?d_>z>RW4oa#Q}DI^bA{VG_9$|BL;dTa zO(`8K%l;EXZPKmU&*wHN_QpkFTP;c5#g+aAsXb$&HRYkFC&<5jstQ!({U)>Vx3esb z@ru=g9J;Mr5#OtVk$M*99sJm0(-#89$~*qHBE*$b9(Fnk<=J;Ti;B0h7R60W=x54u z-!?WH@~ltP4z)h+=8YkpErk{75w%*T`-PYlEKR-?jE7%`BIf~ z6N?$^h@5`kP*gBQ#$s0r_xw&)1jyejKXU0tFFoAshd<8PV;VELgy2$)p%h#rbBQ>K zY&k-<3y=0ho%+#Sm9ez;#@5E?bHH&3I5-6XVTx}1nod!jN0T>46ov63NQ3*FBaYOZO&r)ENU8hrD}38E9PseN|YQrrEvzvJz8s=$^K%Z(FRvny{|Pe^d#ED z7e4s7zt_-FO#zzqg^uXUe%oc)-Yth9kU+zWcVXdglck0ci}}&2T`U~t47;O3{GV@| zeuhBqdZSIVyqmAoW9Gh{8{=qiRw?7Sw89((W;YV{#q%f;dZ(r3rBaVU@|o<8xnyI{Ppp zSzHqzxpR*$BxLVg2`O-;X75U(^zH_ZS<>&qpfJC$DT|VqJ@ho8@91R7@9a0ls?Y7} zWT<=6$n|-8_~%0$E+bo*N(bZm6%oWX$(eHZ0R~ zZ{NH8kqLo(HvgRJ`%=oC@~$APnR8wK#m90D`$tM@78Y3z%Vla8?Y4ELxtV$OuiBnd z>!+Kicj0s8)I~dvrj)-u4wI-=GJZZA%|4j7HnWbZeW!^KC7SocA&|zT;V+f$w!Ft6?WJQ;VR`gsnjg+3j|VWbi9grw z4~+=EoGjLEg-MGkA^tL*+(k{au-_VCQPo=dT;Wy~!T1c?^TDR?1SbSCt{@i(Kl8Oc zW&GU4mwFcB27a=%;ua|EWd9@ugH* z=PC$9UVvsJU19077%TgkG_I=|M~@$Uy0jqn-&foMSF{CNt56L3ezyG2|B_VBl=r+?_ZwKC3Ln8xh3T6$oc#jqFSv!y1 z2eS292J>Sy93-(f`!)wv@U}}ko7eaRH8z7EFhOT@28+~OvoT+8`es>lC!|jm>T95c zifzftHt3RQ8XB5w2CW5)g8mWk^Dom!U8(l!nW360gC z9k92yQOzzovbmhi{(8_uZ>uR&QPjQrNud!!xxyAb@YR2Z@t`Uto=5+#$915|z-`UZ z)~pWP67yfS>-r=u53Ks1^m7UCB?u89Mk=4`s~@kcTk2KYM!}RA`9nR($OUwLx^YXm zSibutttZKxj-Ku(_ow8zVz2|4I&p8>f(bA*upL^EJZ|mIvK1!%M_A9E-C3>m?+_1SLn$LRQZOtnSD0*GpN#WL$vx`ZV8u8UDb9o~Y4dU-b4X7ATSpT!kV z!mfJvhHOK^Ohm#$U&F4NqP8&GL2Xl9{^_>QWfL&PhS_dMH{FHL;Oorau*AZ4mK7iF z?%L)cUAov|sO@seGQYsFLRm}Rnv&fZDzZ@17L((NShnde4-uA`{L(j@VQFCnXmA^B zS`16B;t;{zIo0oJgq~i_^XlZXx-0WHhpw;6J!`%~J)OO>7h-CO0(>sJze zcCY{V@!h6(Efbz-nr`Z$H|x$JvEy!3_dGWeb5}^GUWYD(j=j(EnYEY0h`3`e*rxnM z3YdQOk4B>lcj=kmDe1olDMHL(UsfBFkean}U47*Jo#W+n$3nrYl2v~nO2HR9%59H=r~UnIb}RLHnn<~js4@&E)I06UljN-X zMErT-I(`>~N|L1P>#x7rhiVawW=)47^5J@eHhkqz-q}q%!;O;GMp2$HYDUkywKy2i zyM$^<(E4r;DzZRRvq5?tSOibHNK!t2bmx3gN z6DA|&?r(0omR>V}F;<6h-_l9;Cq~rsK--D8sqjuzc;wqP1eRipE?y^mS&S{qcW1`K z;X@@RFKK9K{Tw$-1$&D1%l=)LV&nsvIWGtp9^GqWM3IbwqeflAgr(OpV{eMW;gWs=Oafxv#Lh(hkxv6Q2vNgD1B{SL{r8z0L>aXWLgdI;-u8NcOe!y|L9 zY$5}i2x?cDXx6>N8odVRbZ)<8Ygm*+9P^SUSXUZP{v|5};^_RR(r%~}g39%aXo z8t?3BGYboH%Gmwg)pv$*iBM^Gwdc>%T9o56essiH7YGnJ(8a|`iM88g+bde@gwaA% zdFTeBLA$D(_mB@*M}S=7W2umm*ywuuNFCA+OksZ?8pw`&+$A5W>89*?%bpeD!u@_Vusc2Dn=ue|C_f9!~O<~y_Nz30hsWPA4aB*m}x zijaQ-3xHT~!b?)yNpI;#EH5{#Pk7(=djaGbVqjoYLsG8g8fO==#LkKs7QF2g)KpXu zr07=KWR6i6Tnlv&EwHT^;uyLaMd^=0#V_=JEh|D!5qA)bxZ2vg{;wHp*ot+Es)laE zu97yY%fxKI-GRNAfBpJawhbjK!e+YtsqJ5yf{jES5yADU;3}^~*FJu@*QNx_+qewp zqC5vveZB0_U*~+fp}T*kbIdx?QsmPL#(Qw5V(%-LK4KF(2lKcX0Jd(Qw-t2mNGh}1 zQ^sB%Obn~c$~t<`R3*R|Y1T*4HU3jIlz_6YW>1wRG3O4sfgMQ|ycu zl^Ge^CVoOE_~RQeL+gq!wkZ6PnYSOzPrpdxDBgy-TMb%7p?;RR^PfJv#Ntiz-lK%6x&-ZE6VxpTxI-18Oya3) zhpOqiw3M$p4(ByC-sK(4nU_Wwd(3z<@G@C}~2*M0ohy zjgGhB;Ts*Koz{~hb-dMX$nJAeqanY)`cT(ZaHi>^cH_>O#E0?^$?lb{aRuwYSUYy5 zs1qv^B=<;$sMRPg_^7Iw{g49HZ}TB^y(M4f8IPFB7Y9l!ML5M+%|T!1Wp2I$Io|>J z_2#ove;Qkr`%EME7A`I>GVnOEQYvf*wfc`RiMpdZal##)${IzkU_l$agXq5dU|I5%LkQS zYW?njzue{qrlWYo+JC0nz2xGr4+sa%6=6fl_4S4)N#iRV687Pt#@@Ny_48;3{2RJ$ z*juhb2^giPA&W@}Utvg}D7pC8=Hk%96~Dc&W8`1A1`8820>+%9c$i7Gy)XjFbL?pX zSoqg9F?`}zQstpcM9KkPJ#?W^=X-&GQEQVrC+3>G+FG^BX z^4y&-&WqEyL+_g{zO)f1u&2TzL;jfLMZ)_`EK#>FE^_=e*zZh<>cznPjB7fXekM?= zWq{c=fBrl?{$KR0U9>wllw??AP0EY0nR>Cj<4&+%s;SuNrTfhL%_~gYe(+n! z`;$ed@S#zZpE!gN6vrZl&9{~4GA{24t2pZ-k%zxa@!8m5C80SAjfqCUUH+`!UeJfJ zTZzR~_{+0#PR+;tHmzt6DO}R8=nWjBoH>2Eus<{@gHG|R%|d5hC_^saY>3h)iNuo7`z&J2MH`zaG z`UDt4l-b*T{-KyL|Afk_M(L)In`m19Z+*OwceQ;&3XsdGjXDQUXVJasD$w zCWU3U?~EUBkoiNr7xVQGM@vHsOL|5&HKlWz0PV4a#N*Ldu!4Q2eG1*BcLs&4Z4tFOSKSuKk zifYUz`F++Cbyx`dXben57>ei|)#0AH_w!|>=Su#)-{gGEU6DJxRrg0p4L;A)4tg47 z`eX{v#pj04plx&mK|!>;*Gn#5ytq&YHKX`_M+mDH=fCN`BhQb08uR{rR=w~EL{cM& zbx2xavV``m8H`&WssXzf_Ug{sEQPwaceZ<^df5^kWA(cw+J|Mn*lq?N)}9Ec0lwuX zG}HbzsR8EJaLUl!*G{9HhZ*tkLzeImF75mFVMFH$-g+8*to6mObd9LGwfAISWTZu^ zL&C=5z{AUMl5W4@wzESw|IUw)=3cdEcKG6n>8Y8WXa1d2kJyLO5iD+kC+4x$36(W> z$syGG`R4VBmr)p@fbH~B+$4|pgswl#;-k^d3U*;QRdL>S*a~uXZFDURmK#a#q@f95 ziqdk_$!Ej+tA8+XvY+U_Ed1`P(Z}Mw$w$zQ-G+^67QC$j-qejC7O;Uzl<{<^CYlh; zkuB;7`+nA0qm+D9!vhXOoeg64Uh2H-%p8noPX%M>k;&N0VH3jms^DTEoviw7=f+B_ zPaVp*w2g%fYYkaGE6B7stZ!=gsbLt0se=1M-N{g4!SG%~6=)G%$64FoYnkjlNXu%I z#Y4|LKUdvsgM0Aa=2JjQxobu-C;F3Y&7V5a^+yjBXc+=UYB&P}BSnK_t1g_|(p(p& zt-Luuf{XjM^(mz>(X#cc(el+=m(f^r*O<7HwXUqLA>6?ERN=XzPN{@$dn|cu4!zpN zt$pg3{>vAqJaE@@JYfJG`}?>CV29w6#~y@u3s*BLagxQqcwMnu#(2pflZ=4vr5tf5 z)P}D?{8vfYdR1nxKa1HE0JY|zdYf%jh)nw)pl;9Wv={J!0vqvuyAv%A0; zktli(c;Om|NW(MSXNB8BMic!4>%aSZfYi=w>9pmxgL?J}6+JD>35F;3Vy|?4DUy7{ zX5AkvBvWNQmXXW&F3$SL=fV1~-;Im6U#|4p3rj5>kMO__(~uTN*VZw66E76qiWvPn zLDo7&#{dvLTj4c)v%-8 zL-S2=HE=#^Sr{{B_s1K?s)i<-B4)SY#V)mcV98+s*abJKhfX($tTpqcRF0@!Z{#XTvY1pwJfh{TD>P zT(hV$IkQ^RX(IAg~o$mp67cVJaXHZn%&Oz-I6A>*LZ?4+=cKi^)x+q_5*}cx1@8` ziY^E-cZG#CekiU>>8Gx^7=S+}GmzpXh&GX51wzK{Pu0A}FJAP7aF^i5~Ki+w^=oe9!s$9q=?y4$HP^Tcs1<25_FxS@a2-peT= zfArU?kFXsAs5tzWjWeNrp6gGsD+2WhGcPa3Md|8sx1BG;KEDew?wE8IGFH0w**OOe zjPlcttS${zo$;`?V*Oi>lor@fy&PPunWjD)TT2%TJgY)b;$ekMSO?@!tf=F%Ja-i} z{;HTc`iat~8%p~-Nv$wBG-qCIY1Ovj;zn*NE8)q%SaQDa2tguR1N!XzTz_X!p(*(lcpY@KDR zu+8{Zl*5v=T{5Hp8|>`+UB3ozZ&Jr;L zT9(;}{o|VgG@I2mMVn3-Rau=YB2A=;NW7`07$>6b$|g5*eMMhg-P6a5sGKNfJ7%Et zNotsCsH&QBnC-iTg}K(k^i9K~cI#i0eRs}(7PZd<=9F9evF6<`gj)u$jDUzZr1pZB zx=X3*odHsck^kn8wv&5~3DjD-=fCSF#YK=Igk#Rm@U|_0`&QVF_2DficEs2Wvz+_0 z=4Ovgin{I@;0ain{wqxE3*oLJ8V`79;}Is~WViXOGUYqERLbsY3V8{m3Ck@~mf5Oe z;4v1-jZBvH1gqB$hNF0)pUnt38O9kLXGI2PVQ+hM5GzyDv!tZ;tsxLofDPNTsM608 zn|k%?m1?V2A!YZQIKszE=M(;_eU*nVwbBq6{5kbJSkWS0N|O5yH%pi zgMeQ8PY2`_y!Wk;fEQXU>*+f03+41M7c0=lhvfa#E47P%@ltlzuU}DHu)n1%fkLUs z!>H=$+R!}Ia*=#3q(Nl?L=@;N+XwGcZCu} zwOhrP1~O%@GC@5`^tC?e@44^}7G!=IHBd?vYi@`PnQ*t^wGIl{JCbRyxV~~q zY}#-2Y^!OoCeAiJCHQ|imz<(D*|N}jBb|Au(i)Q&6S{P17stkUOWWE64RAVrIW!SQ zR$O8i69b{0cnSG~;6ZOZB zmONublFwFB*g&p32hV-%mtTyr!duDMcv+RFPu$A)J^sk7u7vav2iSQjr+4pd2A%>i zv;2pU0N-^504?>uri~i(BN}k{H~Q4;w>d1-s@@qxYH4Z30_-hya%anvtay4KoF{%n z$gvInIxS|`^9<@i;IiqhdNePE9i3q`Ty;n#4PQ-4`wSe;8tm1quEfc$;f0!=-8X|J z4p6EN$5_2BnHj7}>+8tb8r3nMSz~H#zT3}vOA;|GUHcxqer?U=%*pdYobdp&$A!qf zI+&I@B^ekQccb`ovx}?hW$tQB@+5KZtTLJ4>4KAc$&G(~k$;`z&EfaStEyzI{%o+N zxutfMQBY7&&9sVy)x`TB>|*eO1|dE^h1M-Xu~wJf9KN_AuR>S{cUpiC0O?e&DJy%$SApCyn*cT+n{v(!U@1oHH|G<3Cz>kFZFa=zYL*=C zk-ss-x~{M7uCAq;(_AOl70!A)DU>`<-%=^DCM)X6)nF|daW~UR?amc!@sUdIZCX{(bLoA z!xN<*dzxf!>Qs7H+vltvabF-CE#_M1#`thC%DcF@w&N^OB6qNFl-#5NW4LzQ@ zFVewoqT#W;+0MYsyamPlvFjj#vS6X(`;ZWqkHPzDza+Et@XjVVCccSDj42f3Kojz# zFMo{It@Z{S$Dbo5574Cy5y>}y{x=5&XXX2I0r-D6koiAnffx5Fgg?jK|KWtZ{^#uW zH<}cm39&)xBKzuw|CGpS2*B!WSGQZ#1K=0jYkcmq7|8sWYkkr55Kp@=zb9U*!TcYuAYUR(h z|F3rW|E%2jVaCQoVzzq*)3aivo`O}*0`K5&7$6HY$y$Z(zs4ueaGcKP70~7r5Ktt)+*Cy*L!n3hebC14 zxgciFOVKA!0`o^Tlo92+zWx#Eo?pK=;alN=zHcb)u@UtXg~AXU-u8udakx*Mx8&!$ zp3`J*udIv)M5~zZw>$V| zZ5;DwW#a%LntzTBz&*qR`?x{~D*N@u4F*Og^?Uc~-y`hQd@SVVO&Q*Ve|#Ui;DE2` zNScfn4x}#DI*NKu(73M*Jf!$+xpgR`uNntr4wQ>hKbZ??&m|#^6)B;#DhZp@(qN9{gBRz-)<_{M7ZF?5tiPO2#%P9g!~}? zoji}O&%y;FJ>Spwe~gY!nrtY9Wz~nrH|A%=Z18@ zeLM4?!E^Um->vZrR;tBG!nc=>Q+)UaM zj>o9Z4cE+K9pvL6^A^QNuimKN2U0V`z_9^ji*ELpwBE^9+noYk;6E0mT}pRbdp9{) zZgLr>@}D8;R1St6^NYJ|@8lmm*v2nWfvK2kF8si_#xF$NZYV|S(Ieqq=8e;#I#JGy zU9_Vs=(0Q6W|3Cy#D}u>8|vxp>um-1f6OLDaiN zG-8`{^&yM2nmgDn8?x1KNjr(PW=&A_pyNay*UF~n?8@mq!hDEB87YhPXcy_kOzGaz zn4?*L)pj%_EYzlJXY(s9ZJvurA2o%^(PtvZtu?5P@%jX&;N_`ghjg=uS2>f`^Y9+gN zh39=-iSnFUbaZ=X=RlNcE8h*7d%%HJi?HbzGjBN#!}#b}y#f-B4A8fk7O^P$1@R~3 zFLaC>y>Z4MEV`z>`)BWa^A3%Ukom#W`Nts4!M`9lz5G5SmVch;_9-1VBLx;W&gr8) zL9_*i9pb{rqsHdE-?hnYCa5qFTzDh0V-l6>w%+uoEoD~5- z=hdHU=xc6a&hJe)%UVSS9oD@!-qLn!*IVWcs;zC~qBrq_vM^ICw$d)MYDh=v^9{p< z4jW7m%Sy{wIXMA)sHzOVT`>J$CPMNr+qpC@2Z6kCA|ym!?qEbVPKaOzJI!jI7;^FkXZ>@LbApS~HNjkTc1KsG#BBNR+!s?+VvLEm78iGMbGE#|2pF@z6hL2n|IK7nE4ONjgl;$&4)p?Eo+<@d= zZN4|+PjvA~PQR9Zh0OO%*2A$wK?G!9yMVAAdkT~!eC8r4_B*e3M-2`d`1YOY>eW$H zKt0zX$w-UCbMirTyMFd#rJ1AemY5a>)eY!b+%>Yb?EkJUvQ2monlifNU0p5nfa+fK$Aq9y z%ug;md3oKXjB@5}P>?j5u(T`fRDSeq-dmevuk(_0l(bq{tC}1JN5tTJt{;q5Q#Lsy za`pV4&rdctHx1-j-zs#AqTL^!1VUfIC`C;}BWLsrCmrjQfT*a!p`h~V1N(>hnzl(? zoaIC{6V|A_Ie7N)4CIgxYhT7aS@)%$UN(Dl*$N;kMIC=P^^q|J#@XUsdQ~OAFiohL z`zlWqdSVOp=^%|`M^}Tq)Oa0;mRIOTmafUjvrf$lWM5Yd`gV`u*s&NM=@2w%<^7{E zXkuY%5ynvpg-KvM-F{D0pVrY6VN)#%chE+n=3^rBA{~r1+h&9kH0Ky(OhdFMcQ#pd zvMlkj182<5EMt5lyF$h){OM=z(?d9~Pji&)?Z}&${QlwNVG#=K)zKfm^$igdxPM-L zASJa86+v_tey{8_~IoE|EVZsD`Lgf!QE+kVP0c~7}y8#Z#9~(T{c%v9-gG zlMkd9_0Qf!hWD*ryt???TbykN1SNwUstc7GU?!1$6D!0Dfy7jFobV3|2+-8ng?Z{< zj5uKC1My}mvL!42UdkfwoLonH^54B^x?hMdSKFT{7>^Bt{SQxPb0 zet!Zm!(7P+CiF8ZKg_`QZiu_nK*yoZAfxHv!}J1t&!_W%hUU$XkRo*O$A!YtQRlez|gxdXr@QLlr9^eo_n#WO8oS0 ze2vFf%_Q1obaHKN{hEP;-j29Z0#p$K(fD4J|0aC#SGAQy)UbEa#@*V&?Vp*%lW7ON zlD?%V)DAyrFAbAxR11P28D59K)u3cZWd`W4QU=>jj>JY!P$S>I>iJE3gg@7!%LS!~ zYVQGDVM>>NP|1KC%ix`%H*RyR*VAVb=$O#SuQt#Rfkq551q6?ZE2z^W^eKExV|YcSt-4|QnmeFa+X zX9v)e%(ITMv9srmh_%ztfgAmr?l=r-+^d*P9rYx2GU$Jg6;$_S?LKIH`Ioe8E~k?w z=N<&YKPu#@sZW@gOgrdT+VHw2gPv6TzL9)47+3Cf0G2R^LO@w+ZzRFAepY+{XgIB$ z6z1(gG3CQ$pU9jLCx~+h(?7N4^gfDmcDoFmz6Zf!`<6aa62mvWPE&xDB1gG85Ink1->DS z!LCCA69@AvewXqq3W($6S6m^D-_{6U=C(xc9T;v-UKelEw_myodu(QDDWDJLaH)nP z^TBifJYnO+i&aj(sC}o8Q-gOs?R3ULtAsHiyMutd7rgth@5T3Or~!Xgn0H6Jg4%(6 z2z;UOvu8QfX#U_5BU(7}U=DZHnQb0~S=*K0hPYNxWv)$0rj z+&?tAE=oE%?dy^PFLN7n|MMZx+|nMBatiGF4AUl&==O*ZqVW^AkH8jTJ$W*9d#EZg zRA8(WNPbF7HAHfiW0K>{a4k$DCD!WIl2HJUIKy>5^ZWP1R1w#*KR1MoKLd4PE-99a zRJE}1n8%+z3hZ=#VR5ZQY=w3lGnauC=fX+{aClTETWkhLDr(l6-kdpqQa2Z);E`Gz z(ldDKR8&r*_e`B6JIuS3fw3bB$;o*p8r=9u$Y5;ya z_3O0Tla(=`YRr6EX}^v{NjQuw`W83r;1Pph0cTp4Xl!WDnC};L-qEmEM6J3O6PMAl zT-fqWWPKOg<$CuH1$7QY!7=r0K5xa+Q@FJ-ZfTteoXg`EQ*S$;@K~U9uN%kf#^{e=e06ty)~3My5C+$w?(^SpQL=v)oJ zt}ZIZiuCV`*@XD@DV%FUpGEsq>M4HPG6BDz`)>@+?tPuideZl{x(v6qld@aT!uF;}y>kIXSAi*4DypV|i&!m!{dyRH^#Z%?KG}fP6oM;Crq7GQ!Hn zepIA|$fxX{9#z1@w4!pkPjMFPTLh5NrkUi{sKHNa6nc4_Z4ePu%;JJ-k0^p?mQD8U))u)|zFaw_hgD0q*yrCxVB{k-LZ8J4zf$P=zSB)5 z`;#NUNLb=&@Eg45FS+K+`~8P)+l`lgb20!oi8!~}FH;Qrx7i}^?7M0g31ZwlY=rw` zG&~kpLokA#4V!PrO1wV+p`2)mCl6ay7}?3Qshoeg`dj$x@PU$hFDoo?dNBH(N3xMb z*Az>0bJ7I5)?+RO008_$AkWbvDIEn(2XtGGeyeh3v59LW3k;sanDHj;QL!$vrk>=S z@gCuz27qLXuH<~WH*E9eCd~u&?)ubE4vEr)IA_y}5v0S@Etrc;d~QWo}K4_wsZLy}ak+&)cA@ zUMowQ;&w_Li$e00&tt%%K=sLoD}XU_uD4A0eHW~>JS*oph& z-aF5yjsmS$8(saTSX;=iT8^{07h9${Q^5xaQZLX2xPJ4gV)=gSW`74%{Q7lOciTZ> z;Pv?FpG%H099{RJv_uFuMyVCDS3KrX2U=lSgDS&0ZcEuJY{~3dD-oS?1xCX_d%<^= z=8g(u8Mv?9zshD&*!e9ZTurWGYh-2sNQH#l`2AD(ItwGCriR%^#@`qc*2CPkUCVsd zj2wDY{5XlDtE8LGVZ3W8FPzi^jo+U<#zsO4X3pd7B_R1^0 zr&|Pgg}UgvqT7FVXv)cD?ML*ROxfeFo#Z^DQTO%*4b`zmzx6uN8*6E#rSZUd+!2ae z@*lFX8@(v#IFb|nE6ub*I@$rJEIsi+EJq(hO`I9SvzW@;Zq<3)jHU$XiPc;*KC|TjK1j zGGc6D@`}@f3iDwf7Bfx5Fv+?)07*Ap2n zx3_MJHtlXAfz|xOk&T5y!_BKK$BwB*DH{$HncMDzkENOd{wfQv`?I!FF|sc_W!|dy zJr%Rr^?F$AwDYN+a%S@W3@00R!1grTi2m2!Ug5g267?!a*=|6}AaR9Pz3!O=DRW6Z z2|5%sB7JBXdPKmEe0^SQv;oZd=utYxa)iaiJ|MW z`cEr&k_OPyyDw3&eihS}DpY=I@`u_>;w!{;$K6(XJesk_gtD_RoSDDkp7=RdYeezR z_3LfK!w6Ch*m(hOKer}TVVmz>Hj}5GU&&a-7!wnpiyW+bblTj^%xbN39_L@dDf+-y0Y zYZd5b9!3Np+{t#$KAVP4j;_eK0NA&CLG>5!hhx!|UG}ebff!<&d!yg7YoqlI-3&jr zl0@oU7Sa{K&m zl*nEnF&h}A3q&>i{tUSP&9FBj>L8XVX0oYiJms1HCdG4SD?6IqrSmRNCyYGOv1iO^ zQB1+b_{^pgDLwevWaro&55mMt^#oU+nNdlfy)NoekPJUd$%ov`vb%ylJ^I3dF|AOo zsc{MVUEmZu=db3KVaA#2+3agKF5dg8Us+WmWym#B&d;TV)VrUiRj6CY(y(m+kowJt z3whNSycQPYM?jL%+)_HC^VhGw$mPxV3wi3b9>Rf1g_`-8nhUT-VqZ5(L=_|;J2UZO zaX*1yH7ej7<;{%XrxoASVqDeOl1i`5V$-I7Z{N(Nb#USij+m);prJxmSSAmqg$JcqndBxMEYHek!b)9AWbw(PEKyF-l7i38^dS9 zrexsbUw7v6QT``}8!R1p-eO1lX?->|nb;b@S9TuB$a!l;oq?WSMH@=_rFNf_xeRCDVA~RiG^;OnW8t=m1 z`gARbjlz30A_x+zNUa5WbS)%JVg#jn zVU5tLe~F0Tixr^=IQm@*z@FjD#EmC}d&$Kh=5HC$q_NBX*qy5_SGP$cg^21+F9bKG za&eOWxC>T5`L-y-+B(iMKK)gj)q$S}32gVCYnBN1muK0yW~I2GMY-cpo=lH@@=5C9 zWcHJ_)SQs$TQlA0*Du4i8=YGghieu`*9QyKO!4Z~h8a#8g-P^cyS2ng!o=!o}gBU|!D!yDl zh30$iL_JimT^rJImI31y^!w4WYq#q~vmEl`Vx^q$8IgQPBDZwm%aEVhEYi87_FJF9 zIMdWe1PrOJp7n_f-s4>q+woYL4|{-+Uy%b>D^Zj-7eDO(K3 zkFQQpB3DlSI|jhg=EM3iF){t)KzUyS;jcloWcHUC-_uzCuQz%b${~FrDdJa&Q`Y?h z>53Beqouk^91`eOaUbo1)E`05ojt60$52IRXB9#N*iZN0$A}cnNYQ+^xmN+H``#1Ox?_Yu z)$P0obQ~$QSVV>}+D8rmE)~YWBgDsjz6b>I6qZ(JawW(k<({V*`Ohlh1tk8u{lMM! zDnC@9A2n%jmt*_yy&*XaG$GeSq^^w+M=K<=gdi)p3i)bptTvd_ri6a74`mm(D8(DF z*Q+E*HlwJ13q2nOYP=b_Fad#kUL@9qo|*`N|5HZC+-=Yrlp1$`)F1c|6mk1~FD>P0 zY*MtE6w3Q`!J?gghk~|AZ!xq7M&1%g6x-EE^jwGs6bO3m^&~5ZKV(mHbnS>2x2yzW z2QkyFg1%WHol+eXaw}Y!%j11=9Cjv}8weNVRL-sVmZQE%XfFX*5IWLu?ss7+&XyKZ zBC`0!Z1y4%yQNQaV4;j7wkwJX+ot8jSp@^3j7MSVp3xAKVAjS_Yp5MNG3kTq3 z<;Dim$e3Wr&2c)tpui4DX+PGYW{b!}0?pOyf`UM(k=xp2ibLN!~F&<$gM{)xQes|X| zGb78!c<9}7txr+NZ~6PQG?2!LbhE=}YE@Yn7_^=_mC$H#{(%vPV2`DW4%;V(V(xD= z(U5-%Xv@>5{LRce^?Wq?RQqOYd|Z|Kr({}Gmg;c^=8emYY-grwFF=#I=kL<}jnUjw zJC#IF7shv;?-QfzKhHUSVl`2pMpnb>o)5f!C4Sj4yPo-P^1ks9(bkK50bcdT&S5Tu z;D7!I^%8085Grh-y>P?f8hE!U?OS(P7?@8T)Vf*r*|T@Wh_bu5h2KZ}4*d-oL1GM? z;*ci}z(%L-lBBt}?8kP)|Hh_H@J>{BC7zjUK6oBT*k#6ETADZVQ5kGfkskY6h-VD~ zzR_Ic!u7PY)l>hJ17X%iAG-o{E4&px!E?7it0e$nZY!Tlr0C^~b9)Dz(CtyW8VL0I z1y$ZbUvQD$K7JfX+az4Fl!nzSJ^&iQMcci9@xE~7#Qohwa6lm>ll{nbkN%Vta1Sf} zU5CQW)#F_Lw^)I!^gF~oUVs1*7CWf*`FNHd{s=d~;2bhfUqMs1g1v$rq zT1Q?uq?Jvy^|Nw^o6X%G`5PCbn9ZKeJp|m=f9?{=cWBz@$C=lXz0T#SS|C7u(X;&V z0X7+FU``;OYvGdT*l*F*1Xh-5jjj8i-`M=~)A2UVdU(`vF8R~{e0|3Fjw{^(RHAEqmYpSJc8i*LX<6wA*fa zW;Sk*3vgJU=B$2HCx8F`fbPg)tALJnz@$zq#>6B}QkenGXkhpDQZs-Txl^~RsuGhv zRN5yz?d#LX_7I|@R}=mB8OG;iA0Od-hTj!^8XrGA?ZC*u@D$MKU?$B2ab30niaK5TKBCbadt^4NuO^-Y1&ZtaiF;2wl7famvuI@Q4_r zuDMRnOkb0_`Sc}#K?oK?!O#vc(IxOS6i*51vz|It0CqfxPa73Kn5P2sA_0nalzpHu z-&F;QqZ$Db!G18O!`fc}@hH1wn1ib{7vMSysB83mv+`3lwN%EzTcZSr-q8@ojox!Y+oBhAQBtEt|c<$3@Y@(g}VZn!e0LXq$c1# znwEzpC#OB}=%&m!6z~1`_J1`&x37V|Lx1m?>btb`w8zxSi=(u(v=v)rDivNN7oY*} z3zOyz4-aprAYn!lSES?~RoLV^Q;uBY%Xs}1`L%HsGl@7SPSF289wxbVd z$s3w>Pu>QMUB&xl`Vof!xNF_=Mbbv2p+5BZxg4a)1QL4n@-6j#i!Rk>A9qUK9Dq&> z1_|i-kCS2iCS=a}H?e}f+twh^2gLs_`h7UU1k@gmgGIU>co@*jD1Ev)Of*Ptu!=@I zj?CTPzP-6Tq9m5DjS0?G_fv3$j!ReC7sH`G*Br>chnzB`>rQX{5Qv@6{%zWU6E_{R zQ%aW52GOwxCWli=r*2Z#Y=c2wvZdWqxCzOp;z~uj+Y-OhAi~i7haC5#uZc*OQ*Ihc zK{QSZfGN;cc1UWv+{Ak3Tu!DyECFDPtfyHs@A>bLRDHg^e<-Y){LA+(dDae_HJz_z zy*u@j!2|U=>NPGKQ|a9^X{e9{QVPFx`w$cB_$ zYup=*0v3b>1_m~#l23S#u==9ULqLv|xoWf4xKq4GbwL080I)Dk3^SKzgR-GgvRJ>w z2|lUO+CrL~Qy?z~$Mn<`-_4tSKm{EUxcGUm))+pL@PiL4Wa_AMJ}%}1$WQLmv$7_4-?wMsYt(B%NjdO2mR4to;j6{C&GAd1*o5KfA07DeO<51Hk(5LvfBcD26zViZ_&STR$fa9 z9xka00mW>rQNsph$30d+Mf>H!m7DA;8SOa{jP0&=C*o#}M}Z|JC?1K-9?(;Mm@)3b z6#Fbmdd2|y{@Te4IzvZ0NnUGJ2wC4;;io$#@lmL+8+cE1bd&1#s$ZAwRXdxppphN; zE70_F6GZ$t%igRhwIt_ZY|TD$FMxfSfSQx%8}4y7E7J_NNy0iffo?t!cqD+knue2B zUBSthk__b8qyR=IEXdhm^(jn^A8iObR+?!>s zNkB#Wl8BS_XB-q=2m){lP^BlT&M~0uGP_Iq2B1Z?1KAp4g#0vzZLlz7OGqOiLuUAs z%hJkra!wBy&1sz~|Fl(}j2z+u+tf_ddY)&hNLoLzz}D0pzM4F*L$?G}{p|c7so6mO!WsR%@SQjznoqSwx}gS&hCU{&s8QK?ujxcL z{N}rdB_&?OlE@uuYp4G<(6YRFb>i?Ha+Vl5!El_J`mKkz(Ga%Sd#u~ zyng+ghx5=Y=UZHp&8L+d-}9C0it{h>E(E>a#coHCK(*{LmTn<6SvIY)e8g?otG9oq zv+AaQEG2aN9Dr-o{D6_ye=4Ef20!~SmS*H(k38kvC+0JcQaT!OtZ7v{Q>%NPy8|O2 zP2K9di>xQ_sdn%Gp?^3rz441$yD|VWq$>N>OUJv3Se~-WePFgTvGHx6)V$DCQleQs zFKW1Cm~CzD;kXJ09EETqwAgXrDP#s46sphcu^F+IQx}$T{0OF+WQ5mPR(7$-MTYH` zyo!IEp`nqEa5A-9D<)ZT2;>7TYW-Q)$GOu-=%l>L_0$Ao<_QDP?5S`Wqo~k?KiqA z+qECUL$TH%T3tHSoUL*6#N^pe$e9Sn#+urRRJ-7>7WEXmS+QROuWEBSFax=8>tDYv zqm3vjsHIVOc@AE&N#dNi6@H5$>F!JebMaR(u@C*%yRrK#{rnQix6d-mC)PyB4rF|Z zkAui((aQ*?0rl3c@EJ$~fqC%oVS_>5mPXE{$ipk#lN^<+>uH&Y-`JW`<(o6LM?)j> zfSZnvuu}K9wOX_8aa@&@Uua%wkB#EFsfV%l!%C@;m4|eSQP%u7K$W7^)3{S1Y>F*e zN_PiP>4*Cu8yi?6x@rD8@c;fgqXT$HcLDb(?@+Wt<|L(Z;RYmtve?0>>FAN}-36uC z?U)N7Q#)RgjMxzc~$>pzD;Q0B9JUvZ8>&XRjIEfO92(+);6g} zRRWeV5OsJB+r{45Y*ST^`-2ZJn`~W1N5U)+>;b#bTF-Nhkt>xo(UgYAew~QlV4Ot< z!uOO6g@1I#; z7mW#6>#Q6nZK;||FZg(>49}H5FoK^G>;s}|uyMQfNMm$ke%vvcuBCZL>~rKVTKwX| z^IH*t^*DFw`=kLSb=>z~rv|FJIqwjac#MLb=k@5(4c;O*E*gXG$xTq72c7mM4$t8O z4i%0w%maZOd6J{^TgM=v)ofFNeL*6_^P}0EC;ajTO=^C}e*C1zSjF9P0`xt#P^V!7 zvXCuWqkrpNj+YiISBLFeilc%@aKPy39Llpa*SE(7AgqKMShi}#FCu??q*nLB*r5-= z*tM_l;Pm#VCD|h=pxa4g=@Wf$e7zA78VO56%#|R!tx1)$SJihZsu_Tq+%%5cd|fHK zy&6;fWahf0MU(Y~_MML)9;Hn`=9=TiVO*o|*Vm?~OI@sW0Y84pbb{fXs0e<>X#MiS`?w{(H?7z@9)8^M4JF_v7Z!WBIryh0f^tTetQ!(L+N0 zzv=a)HJtAnYB?q*_g?i=bM|dO$2d@e3G95@1w^@_0j{L(Xysw3*U$B$RE&4H-WkaI zOg@;G#S4eFHme>la%{@%-dIKM6VBb+A+BS!<(XPocLlri{hafXY4StQzZ+FKZyE9* zuHMi%ENxyf5=k8xs&q4}b{(_k@UGno9E`K9uBmnOs??0Favn7-_0RTnh193Yxi9VW zPmB6Vu!Hx?@<@{ww&WbYd@0B@dV1*9RZy9 z5a91dTi{G}%*uMx?{aT5c@AyUI?cbY1?It*FOtk30jHK_mH*2qTi-Wt7Dla9ZU*#a z*|N4_!yMdypO{H!On?|l<=+@Ur<2Mm3&pBPDxS!eaAxs5H2e(@`Bpxu8RXBKgj7Pw{2pUI_QE*F(x*-Ij3LZnH9sS1G~WW{i|`tMzm#Ot_$I)0Xk#v_BK3x|F#~%4 zLU^F0WsyCRVL7!I!d*2dWu4U*FM3RW-%liB@vS{h)rn}SvQ90Kbs0OB*TD2JXG~5$ za&&Y|RK0}z(MUdCWY+M;6R?5&cL`DWDq1jknr|IIehN)vPcIGum_*~MWwop31@XTR zwzq$!?QFxV7Pl|a%&k6Q7{Y!*U_r$7b0ovXaF4*v{h*#4E^|Ed#rSGZu*C^Y`4Tg` zlLsabzWRwI=4vCIQ7(Is{|8 z)@fS0KKF_b56eE~H|P8dp=P=y)D8RlWN?^R5H!m{EmzEARoO{w3f8ShvO>#;J-df1 z0!}HZpf%zZ?gD#d8^%iI9BkR(_`4^2xJK@`^AxQ+Oi%y3;on;h-wfm)iimjDL0hK~ za-8y#jxOv)p4)f8)vF3bDX|ldA3vVgM1&?pDV#`8u*v)iI>4C~t=3_xU~~{@xznr) zG(*H7RcoJIiy_?9o~P7`-iyKcs> z+Y9lq>AcpDx7E<}eiQL+mMqG|$lZAB(FnxXYPvwDM**LVd)l#-Vp*9Ttl;lv4irpp zHaUjC0HW{(!IyC_TAmOlV=q2agiegCwSysNZd@R}sg zuB2kmmyR!IpS$%c_K&`C50?&-ec?v^(D^~MjVveEb+)4SWzY(UKE*8$qzC>WK=`2I z>tQYqvB%+?eA9rqQlDrgZv!jUQ`-5QAw(ZzQWw#5(o{5*{VlSaKNDW&iZ6Ufxdy;^ z4gu~1wt|*5!(V?r!LCfPL-jodz7uULAzSTMUTc|OhiFxG6wU+Dp5IQ0L5iECvq=ICN$BD+G*{ba5O0IV^fqL+P&HCRx8u%vV?c9904pJ zlW5aY7@${RlNE?qgxd>8Irl3v&qLLH&|5!#941AC_P=&fDvgO;KiBdl`K27I9izt1 zI?5$j@Li^WJRD73!_cV{M(kRe=dP52Ya8r69BrRThx~H|7i<*epf7p!&JL#c6H3e& zDJ-&>#6<&{r2HiAJ|(%AMkq%4UT^2WyNwqnwnbuY0M8;D3M4RtC_nrmVJCpB>h$RT z?Wi;EH(SdAd$ho6!eF>Ny%4|l@c+@iCA2IzS4RX4fFd=Uz{tlR1BFt@qhJU|HUIi> zJ9W!`8k3*TxJqi>*u^VkpUciWw_P^kFKlKL{POFAl&m~)GiMN;nF?}7_$uTtd70YZ z%BD&pHhzQggu`6_oP{^cowSFs#Prhfs#N?|8U#B?jLc-p5>tsNs<^WSkv-$ov?Iymc@!sIoOWuI=iyL8lAIf2<)y->gM#lo`gTFwn+%vG#b=YAWgtI-~X z^?4!C0(%q8X0FQ2%+4}MOn-9r^Uddngz=v|ZPXeYIDZcNZC6rpE7(4r{hXXGBU$Hm zTlT3mazav*?p+E9+Nv4O!A#6#HspNjy-HgiHUb+q(Dk@~f2Grl*cd4UQuzc41voL3 zZsiHcVmH?yO2fb6zx22R{0;nGT44)c=t`(AYyQibubnUC| zdb2JD)xiCGA8~mtNn)_JC|(w^a$AiAa6v@cCW&eSl8*kls@?>ic+E$CXoW%IwOIs{ zHN@PnCTjLdv`R=dRVy+jQRHd@mPIZhZ7*A2@K} z$_?e)Ty38hj1trA#@ia;hBl3i zZoUdsUM|Ea9@qY?cQA z6uvw?gre?qcEEGX;kN2^zpTY#JjZSi9SP)RcrZ&xKXudJW9&x<1_p*kN+W20cnuf! z=}m>aJm`7mSDnY7lRIw9&o)1AZu-&-+;!G&VY>EY0xMb4&}YthL6#rjIxVaAotG^m z83bT@(vWs<(IGMXTZ%)KeicLIx=ONzMvXRRrFN)DoupcCM1~yDN^OpuWZUjKol=Kf z69{_$oCcsQnswWFW!z={{v*$ox(?sb2XjwXT!+q@c9HKe&$7JVWhRpm5AG99zvE^& z3tQ8CzJ0O1YCaNlcnY3y@bE#y_<=E$W&7A6??i&toO|!bpaRrc`ZsPM@V)#nQ17=& zQ6Ybb#fhCjPeKdZIH^n4GrX3yr2W>ajB{xi+(-=2*W zxg&OU^YoH0X%L7i6%NP%t{w!j{#%Rix=OtRSGn# z7k3opxFBHN+5I)UFRfi?!KJg84Rm|l(X}UrSfq!v>0`@#X+sxIh$&n*_UQ^jT3z@U zSamvm(6Y`-CUFq=@;v$TCSf_`uWE-I%h|#vAMDO@a16a@96CvG# z2nNcte$|ql4v?z<)UsgJ3Ee+$^1#{s!+E#%goZ9iyu43#J7?5)MWHKRa0}e(@9PL ztfGG(5QXu-vdnI!<(CZ=Q%@9L#u?zgFs^l0`}F^(nX>z)=Dsk+UR3UR&Zzo0Iq&F| z5#Y8=OU)U&!0$o;q1O2yz8)+dK)-B7X;IcU&su4Q{r$~<|ClUP53{|y{{WX*Iqdy; z*E?4f#Egf=@TSeY;kA)-F>EE9@0IxEiKH6;nEvE~;?XU^<0;3CC@U`oT~SwY%{?e2 zR@UhIz;N+dwEDl_YH%F<(R)rL$lt7sb)|ddHh((Hx!-u)Ba}5VGj=^_S`SkoHCkeF z;Y87lh)oA^_rTUiq!kqw-V?jr|MjVC)q0LaN6%9|Fpc`}%Y+Z$AoiTQW?$S_ihR}@ z5p)Wfmavs(Y;3;LIA6pqx4ars^MivtHBnyE>UQV9X9aw^_&m6xnju+SQTvxyd?Fi8 z!Lgr?XjF0?;JR}5#r^-v@4*|5b-}fu4u6U? zx9S1kQZvZc#T!6z$g==Pt~XW*{P!{h9&wX9;5_`wf8w$bEyJRMGPf<>3PmZ`W&Ngz zd?dG{zHnw#ucmR1)jUQS8~^e`spUpKPQ65_`q5>CXFO^;EB-$>y1~%yHFKBqZpTD| z)bSH_H?Tj_XDImjs1?@`7qjC}<{Gve@7=O*IrQdmk+-77nE{gzm2-9fb11UJ9`UY= zT`seb9a79M+WSmwCpe-t;`nLdvQN)n*hJ0c2WD!%@<>1X-;)ET!KeSsGP@Qobpx%G zTX#PGacJBc>Ab|X+g;L&fSUcEIVX7gKiB=imj})KiM1pFB-HcNU$QyJPM?wb_qz%g zffMLM<7LLXB6s|L=j+ z+BK}5Y}!VJfPa6AUDF)8HMds1-Zq-b9=nq#HQqSj*Kd~ZO3^u5^{dUolF=eTPgh1j zyN4wt12Lo5|NW}0V(t^g>AzgusslC-M2c#PLEZ8X`5}0kby`;{4*4E3erprToIORU zTay=)P`y2Bb^Tz^zn>P61^>lm?j{*|cOX+O=~_@C)u@(^lQ+zfU1gzwqC5)M_Y{mc8{ z&{6{5WB}JJd+$_wloxtOSq$1Ph4r(~);r=x6CFI^I|1UN)Ia5d0IoEa)O*RyaoEWRjzfO-M!fw{M%z1JD@rS{aJI{fgAYk@;8yIWY{Cj*9ZtNObF9Ip> zJI5#oAlk)z9_J$n2_840l!LJ(umpVZOg018`aZe}v1Xd}G$`)h4;#D&-TlK77EKTA z-UtAi5#K}5OiFy0k_}k-=GCr)2Dj|9XC*BQo5R%A#-VH^77!yJ0BVgHp~kTg*t>T^ z0^IN$ofW;IQxzh+?hl}&D*$eHS(gz57L;ZRyyyQO*sRCk;Mkv)Rw^=qG>Kc^0T0Y=xaHNt3*uw&u207vH$0%;8@xVtTHEor*5#W07;p<*VEMn z{2yR@S>rjBH-|(6z!)%*sDs}2ZhKA+bb~A(e}t!8wFREkn{Jy$+OOm2oiAU$8Dgt$ zeT!bsApDP(C@f>QrYi>mGF4^y?Cfl*KjM3ra51|)Ll&9_I7 z9XayTtEa2S2uy5RZ)^PTnF!x&;CScGokGuyiy~gcVvxgHnDxmZlH#;Wd7jJR15#h# ze=n25lK>7N_IdUWb+j%`4M$KS0oSGsl;nvi8F?aL z>Wl4B8;*0(LKPM|$92AV^}^WM`33M0BxJ-ddtrpW4Qqs~0o*_!*T!Y2ZM?6g45UhFx+%l|bx+S1Ig8@9*lZ^s02TZ%8x%4zjs?pes zwZ>WPHB`U8fwK;YRfR9;g4xM5ySt-fc>FH6ENDp!_fxsWuX==J5Nh~&)y_#N@SRis z_n{&dd2XCfhKGzd1Ca$){xjMt>q|!9=FC~d7v(^Ad}9`e%5nfP5^%XqRBLPOCjeXf z81R_Ce*FNXFRWm9-jACa*x85IHN1U`6uvtO11Y z>PMpfcY~D`pMxEpJw~fZPv~AvxGr1yb5av(!;o?%%ZI{JGt+4g}G!U~B zu0^BiU!Zj~crAQypag}7)a-=zcNZj83UfZ+c~uZL{BajO}I|SON(RU!#+>_2l05QPn%7^olRIug_fuZUBd! z@Ovxj`p5@oPR;|Dfv$1I$7gZ84Eymy&U)JiyKUc|n=8kLiY&nR{wR&PCS{mmc^@)W zieFzMqs1g7jKSjO8M3wu$3HFS{9?DAVI@?r74P)G3|&SfE@OkP$^Xk#;Sf-r4~Ksk ztqqCa*_q$R@L6)E%@5vPwyZHso0S|Y)ey}H0wn*1@CLxV*AxUm1^|tA9{=^S<3~;1 z5B~XDc)Rl_X2=%KtJt0hY2s(#NWpg<00=g&+s0U?yj}=4WoKFMTbC;DX*hLrq;Xze zEjUi@l2<<&%o>1EeU~Qj*VJF|KQ?!%C>i={#<;&THN8!`!bY z;umiWVr@SSds?H1$oL`$vRpme3&RWG5xrY%#V_Y=xiS z4VSMsR2bVhV{_xn|871M(!uUV^V!~r8{4%<{ilZzgQ6sOo{}(PgnnKBzRnQnQVcfe z$dlTjZi}X%$GfG@?7$JTJWegBK0yPn_%P69j5k{2l*u%~KR>NqX5G5gAY6yb`qaxl zNxxpvg7?@T$h~YttT%swJeiyY=-06As_;tb4s%q? zb`%}Wgb=GNkKJM5e@v%juK<%QdS1?6p-DpU zjVm^R8(XKxgTg=}#AU#PlqS%wYf`6k6c?{c;S_htn;_iIsSc8K0pxe z&JQjJSfw8M`O`%H3c$PY0`7NgAY{9Z4YvfA3I>i_`Y5kH2ywte?cn)R9!j<3obU$N zQc}V(EOV=!a`Q=3rqJ9Xx71K74|%<`;l$}d6dF=b&em{go7H8^r%4|>BbWn*vko{} z%E;TLBqlA{6A?F1q!G1M1mo3`;r~Iy$F|qG5j_QOE*O03i?@Z)CC!9x433Is6z6mm z2e{qv96JVpwe4|FIJZrQ|J*L{$zcT8DAIDEz!1O^jVP!$xJNf8?BBG2E{L@}HU3G}A%6pL4)D|8Nq~EmF2Cqes zEIp(snwf79v?IR4$DbwdJtqyGZutI0an_vwmLmU>oI2*fQGMLTN88{z9{MO(kxSbp z)m)^UQxXCmY(8QSbfC;qb|KtQ5F|a_;B-~voQKz;i(FWmH=Ed58bVnGPETF?Dnzu4 zEjs0&T)yVFqs+Fr`1$KHo&(03jcw{H^1v@rEd7Jt6KUn8ZExZ20`ED98v`J1FbFGL z0Q$m$4>&nFA#?G3v;-wR3T{P?H6dse4axBSRms5uiYOzT5VqJo%+oP7v0U!s_ry87 z^FRNVCKuNK(aWa+dY52$w&S$2>Imv7ZP#LU(F@MWPJGF#nqy`qV6wA~TE#4N-2HmW zkxPzwd0uO3Ut4|CoM68`JWRznXH#LehNtR99AoU7Xz)zjlXp*mg;n6mz+CsR2%^rE zEbp;y6q9~+(wskE`*CS0b=|>z z^2B`J(y;_?FQ4BJGGuMcCKzU{g?v(a`f*dxq0e2hhU-{tlM2TO~y!+Pt~?SK<&X@ zDRt?~61}^V0y}odL-3bt4?|bGMTIu@EJjEvU?&GEv2K@@pQy%TEuey`^3g71bj2%Y;h*nr8AD2ailC zzTWa$v8u6iq_?qJPCxY=Z@hoXA_W@i?nsJX#xy_%hZBymA)|GQHw8wZ*Nz_WQgb<9Y#z~NEK*%=97^|XRxV{t@Q2go;F_8DLLa@lMiO{k{Ra@Tvt=#Kmd)|(^ zlo*8S#ewh5!+hy}q_to_fTP=TV{j&uEey;mv}ld>N#NKVpNHc%W`5*lY1(++7KxUwgBepPr&HZ(Kn`R`*t11 zH!&_|5GI&Y5(Cq-OuJH1M&zFa5C8PP9N@zpvZ%zF+Z4?JavdFSwo>ks*F#t=6Ln`2 zpu57EOZ9HAt2_w)jNYR`b)LJqC_h5{5{xTriodjz(;lkTPs-V}SUscl$=el!mM?r_ zjaUxCkQ*i?o(T@*o7Q&&JV#)CZI^nJT#+k%Mkx_av zhLuyHA(Ffljgl)d33mRFD(_yh2i)nAdsj`V4-Z5G9rG>gCYS;HY3!yjZ_gJNXWTH@pC5?mjcG=lvi4% zceqmEi9)xAH`=~vm5Jp_rLuTIqxN+P+X7v{P*|2$+bxh)jmrRGLGZ&B>b2InS7 z5Tz`NwwO54pP20o z1u;Kg+cCFlf+UKQ^XvUSyP5=%%JoiNA53(7={W3^XBP!Ct$vqnhHLp$axC3K(~TIY)}%M2H! zg8YMZLg3FIF7RJB#OWpW#=2%@)NiUJm$j$V^3d^L6k(tzO)9Z2yG-AzaT~P+vq-}c z-nl1Ac*_*GfmU;rAk-Q_w8gARJZbU`4(`v`yJ&S|oTnhq;wU~7;m!ha)@%0?2xyN( z?^Z*v;DxVIFulZ2W)ej8K`X% z&$m_U%d|PDXV4Vkj$NIH(TB$0!{qv@4z_s4g%R6!u|Y4$Z%^UZ=E0tV-4eYOZ#TZ8 z$^x?W*ZLjdYXkRK(~(Y9t(+JCnz9%3&b9(o@S6bpF%P^gT9dZObbJ#u^(~W9KcwFU z2vF0>F0liE*~NOPM4{Ou%khmn6NDQc-R@uRwqNcoos;9gYV~4cFoSRN?UNwF{InOY zUqxS~c>TxWFP8TfZ-+}#WT62|#dE@;#s?ezXnSw7$ry?0*?Kfn-Hw#vF~%QcauFO1T`VC zPy~H@?V4=hx#UR6>2arrc+T(wfuP%wWXJH&nbanmbJ^!0j503Rz0FoDcHi*eF`Oh7 z@>6)XV&yv>RIO{fMIt~ZR76LCg;)JpZ5C-G2i1);$6Nc>aZ_(^GgHWW+cE5|#+x2q zmp{4BXcJdPG*mx8nMDZZr=F3U3wYa&%+kpDueURC4RezI+3vtSYu#+M4VUvAT_WWW z12mS9B8?r2-*3~iz-?u(oAWW&!J5g&H=Gju580%(pPf+;i+?%x9 zxC~o=CJ81#vAB=<$~+{XeVUIsqa1)|y*e!I8D@XMTxE58KRh?1Yv$u{6TE4%WBe#LQksi5joP zW&GMpBnZLOb&@34Vh!BQL%H9V+P7;U8i?`}SBLLSZfFVha`4YeS=Wz5VywoSkmNU| z?rL4l3!>@sbX3WY2c)dex3_?e0o8!U6;+j#<16TL?!7*#nBZ`)TnBXW)NpAMp?z1w zm$BH9_8vAg(RNf?4IS%grOB+Qzvn{em+gh|#!Wy9_yTk`_J|vmoa@R>86cARH+@A2 zH4Wl^R5rQvRZu%&?gDOL&NE{tgubs#Lddcn>yFrLTbAGQrKHE}(dH7OC<6B3*sY(@ z)a@72fuV$Jj&o{OL2d%Hbrn9Qrg6jL*t;c53!`~yN(hNHp4bxQj&B{kTvB21rQwG0 zt+LvwyZ5&?8C+Dc=8S>Pq&T^N=Yql_ndrnG1a#h3#7o!I|49|Dt2-KmUf!3lTXr@= zoOHYDTM2%J!qfJE=i))j%3ke-rCOs=f9Tl!$!4Z`{T|5u0@M!2PA+wmuIz*|ehJc< zQO3K(^;o{~g*TbO*qzTZI|6?lH5kAA|VyI=}T^KmA2TvulX0(K)8JKeq`5vig^BO$K5yMfGIGD@KnN9EG;w zc#^mnR~y#)%$)4wlwDqmAL6%OgkH5&c#QQWu@{X<5$lvQo~!4+Mccuq_F-c5)wG;4 z6vpYH&^At0YQx!Iv3#U~HhI#NMpc0w^kI&uo_8Wkl-w`Vv$CgNl8Ob6ms{U5q_Qf* zs?MJf!)@a*Rim6-CweWZTHJdAG&a%RrYJ-v^0w@$^Udb z2W^MIN4rHzeW>*Q4&k~qR9GZV40M~kU6FMNLLPOZ1@S+!qE2ghHs}zQ{C&gk<<=n6 zip?ev1bQKEqo0II;*JSiTDE)KQX$fGE8L@!VDomo_SU{q>q<>wIIC`FMm31rd1>ua zSnut-+zS$e6}^t#AGezLam!G!0mX0-AtF}hE`)lUm|>}VqcCX=vd`(M3A!D+@hjKY zPE&MmCp#c~hroV#hTlKwxrv&-0J$w|7w+^P6y!Xol4{lQdoK~-Acn%Q`uXQWc5NGN zO32`E(aJT#fiCzKE*PLcdDO9fk4&&=n>y^_p6PbrVA)k}ieXfiWNO|W(B8ZLQfhoR zOi@n-J|aaTBua$|snn%dQRTPq?E`RvZ-^6)7WzKiWl_8*f3>wG6IGR6Tg`<-cUnqO z2r7ljhOLwX@ouh~wSST24cEmp<>rqzI-p)CG}B$;8*cU|X`wVu?YBKEMQV@=hz(S1 zy{OUCE`O$;6VZRDT6M4@Yy8biCK7H9YuNa$@=9_)rk8N~bNX%oDkvI{{Zu7LBN(<` zu+?lNj4Z3-+nLc6-YrhW=G^tfG1g|x$WQop#(vYNh^-VTU*={Ql|uF!1nH{xs>gR& zlmg*8kAWVKwD4kF+PnQFK@}d+Qp-y7w)`Kgq=$vSf~d0J$*gNIAW3Q}C|yRJ_+k0T zBFTgBlfbR*RY`xML7Z#2N;o}j?cH&ziOX{|pcsRdsP=}|5a{g5j#!x}9y5Tk7ACfI zq?@tn-C&taJD&sQhp9_@CxJ;YapMNY;m6*)4LG==imR}X6baPItZ(&$LEqD#7*OX{k)OdIrz z8GJd@_m#`oMUT`fm!DS^9z8u^Q6mwP5`Bw3s+Dwpv_g_lA^DxGQ&6F~FKB+EE+_*V z=Pxp^f7*%Me)7;phG>Mu6V`TGH2dSQMJ0`VWvEB=Lfpe)>LuD(N1(dufXSlF&KzP# z5V76f_RWYI$2U&X^Dk`Ph{kPkZU~H^pV2VW9d~usv!00}t%~q|xE(7hvt?{8wQz3h zAWi6P3r8laS!?}l3Q3J&rp)T#Uc~OC9$GJ$MiQvchupt9h-dcCeTSCHt5ab=#O>g> zA}MB%zvyC$@g2oTydcE8M<31>|B-(E_}xXB^TcEDl}X`s-%j;w2iviWDx2(`bq=Ia z_y)|&Dtox4lQFUH$T8gSuVRhtctO}&JZQOnuJ&iqC3%AO04&nB*B8jS(+$ScqLG)N{H(Cevha*?(l3Wh$kde&w)xcs$1{o*ZP8yms-wU(Q>S(SsI_Kh3aTsH1N9jd#(9W^w#<3% zL$ie(MqQdvQ6aGW8qNR_Q4W?K>>(+eY4{1?N&zVqZjuQ?<*R5vNai8Vb z`kD2WTpP-f02>z-ESzcj!z5hY!6^QaaL}SD4!S{YlRECK6DGC%g0Ikf2{aYMbyU}_}Z zY)Bc}vf`KyrP0DHN;`7iM(h)#1x;;_@oI`<4ti*Fu-+evzv!LVvEpP0J0_~1 z!JlAt$>fEqmOaa9`NlM`JSWUnZFC>D7PQ`I;^Q7-dQ==r#}wg>#p?64O^RjnhE_lO zO#5@z9X|ZR$exS>kT3pq5Si1P_!{SjKqgBBv?cRovQ^l^qTCEiHv7{bk&0W8v4acq-cnDR{^49K_O#iZf1o0J{2qfxmPDms23!cvN^g61Cjn8UPpwjP$7|R8SZJvz;p=KxJ zN#?sCEWMPrI9^w~)<$h_WABJg1mTI_x_*33c~3WZYI#~{d!>hVbHmurh)oej4D11E z*lQX@i(3FaE6cGZz0~;G`xE*|_rx z#qd;8Q{pG>j3=+VT>?UPWDm@`)Jt;n3kH$JCH}4Ac%i{&NC2x88kq4Z^!lW_*v?GN z^ZoRS*J`Xbufd!1B7z?}>lZ3U{Y>V!<&Gb~HBi^2lA(lX5~|_g`hj`ulipS{RYpqF zmD8z18}p)k+ebtk^KPo+0!MwHI6Ym|UZ=vR-0F2+8NXL!kBLJp<09J+7=N$7uXlSd zd*e+Y@tVVG?PHeWd&hU-Lf3<}Z(jUXPaovEP#-{mEEx6^Dr_cDnVXr?qPn);1I?=f{aoyxsLqAYGi&@CoDzmA>4`~YsKaSP zdwdV}(gkm3iMQl^EM+TWT*NNF-|CllCw@ffi>N2NIv(t~*h>-q+0nw_l$o2%78TMM z?YmH~ZCdP{X+wL(yZ54U!mGyzS0^w(kxeu2iWOb*Y-b8v=q4Wsb}n0g*(^v&#_MYq zujUdl`<0I*e79~pa`}|;q{OY;er_mUyPsSKd%tX-@_Qtg>Tg9+znV1{ob+laZk%Zw zy2VB6TQk?;kZv)ga_m1>+LPD+Q0xzA#HDkI5jul@mxd6AEksiA@z44aVnR2R)yz$! zdhRJLFc`?+q2FhmWHa5NX3?H5$fWllpS3K&dMd}AJT+@PyRi1m6E|+ipOcZb;q!cZ z>ws>lisXkGpC)>D(7frGK92Db$!BeOr&D=wm9b%Z8Tsl5R0Y=mYtNkI!|bX?d~U1F zH-RO?DQWZ&yC|zfEyd1!)=^4Qtt6spcM+OEwBz`Uj>I2m?)W36(J)C9>t zE#lC&gy=X+pyR7rr4$YGZ~u@WMygM=$G0D!w*HYK2UC}SVST*+JGpmo{39Y6e|y$8 zIo`N0DM7H`M&P1I~JkSPHLY~WK*&>C2|paVW_6yJemaaf;QNq zRknUsitWc~shRb6-5M6`r>PI~ff#R`8KDHxFo7av7&!t-rBoRu(Rn+a&+7YwD4Te>qBHDy-UrPQqt$D<{ENX z6wd0rX;bqM>l;@poSO&N!v!+2WS&!10gZ|SPZv)tU`t#ZL^ESE3+IB+j0cNkrzcaQ zcFZIpg|mbRM*e|Xf$pX`lbWNf?_pOCHbdL|&PCjR!W12vZq2tvLA|WPg;^W?kUtY2 z=$FGtLV}u|H~x$$CFh=Lqb1vwwyt(<4ztt@(OYRB(8JRG;dc(4`*L`t@~Tbb2xSv< z;LG<=YDH7>9%~hoMXyp22u#QE)|QnB_j$2`C%uc{8ID<92=+P`EIHmq;hESU=#rv- z`(P88JRf~ABH7a|ybQ$e0Z*e^+n__TQ@EWh6B>woEAyF!EjfJtl zPTL1;YTy+sbh!8Bixv-}C z7fm-Gc~vpA#KzmkL0{x4Rk@Z$>lU6E=`Z0M))BWpD77TV^uf6FFF$e=a&_T!Gp0)q zJ?nQh7vsw_*^m*t%q(BSGdOk-*lC-3Sr1(eEbrZ1$4$@U*6VY|Q|+%`8cm+em4!*y zmF+jfv6&?QyQN#^zc1~vheD%wnBQ-kU%Sis?bO0T{j-N-U7fz#Uw#W5pY6(2}>W)kVV%&g9G`}PwoBipr0 z$A5nd?Z~g()F#uIv~kRlFdAPRL`2xiwkRR-(bCQ1$5eiQ(*XNT%MXuVLu|>8+$W0E zvG>iywP$L^kw4nSvv&**2a=9dXyf;|hzgpv=)wGQc*##ZH>T}^T!fV!`i*VA3#pdn zRnNnOJD|V)sT!xApAToKfr#dy6ZZ_Vhh}Y*Rubdj+MMow0Z^DrnsjL~pNYW3p7zzI zt!F(+N`a3sf21gxe{&ntnH@_qWwYV-c@Q*YJ?mJJwa3HoK>5e(xSqS(k5>=QeV;Sk z+brdk4A1oU4_pk%R_e+a33|j1>pcBu4(dtXTKL;u&*Do^NKS@|5UC{C(X~N(*(aj>$XE~ za>-H0qxea|x@wnBUA!>Vhy@5<%>zo~-dnyZk`ew+FXCd1_N<*TFDnyoDKA0fE?U{* z_k;3t0`@KpK~ucfKlk{3B*0qbw2?9kP3QJOAu8;zV%sYZtC4D!`Iv}R zczl?-06XMe50(huu5T$J^{@!PNZwyef;YdnucSlN?8=6r*Te1|cue#m@-VPhKhR5R ztw=jY(kca9)+{a7Ya?=c8oKF3W+-sv|ogd9jHB6ymRHHxy5@%>LLd27>+2Zil!!M9rPLV8$pnTU*qrA2VugnZAFLuEwVC zQ_1`t*R&ejB-T7ZP!M$CmP#cM^fs-G-1KJ}eq52nh?KhHA@W6&-_<64kML@5itTx| zzxTFSv)T%hZxS0sjE!)N4v3_xWx`G)g4fYv93EfMIF`oopZRo?UpsVBHTn5f8ahfD zSyi8;IGXpEF-_g!IApSUA~ulRvBD*cI971s+)Lw8ww~mGYk*);aHH?kW5Mh9Y9+#_ zP-4c?4?8oHGhz-#PD7A!4pSxrXA@fu%LNTv(yb!zeT8R#toljiG2(*0W(V{%(5~x{ z=N95c$%-XC37r#0iKG2v`BrFQ{oAmF?cW1RY8V#5(~7t>>60~Tvm z1KKS!`DCxY^EQ1Z5EJs~t;AHC(nKlg!YVQzuOg!&sIUBcG7EDd`HY16GPvJhhi71y zkAFP!=lw8>zaou%p_Dm8OHi!0vuQZ3dR(Hqkj|*?lv0~MyBS>2@c-C)>#!)d_6<~| zlm?|66cA)c0qGJ@5RmRhLb|&Vlol!J?(Q5yK%`@+p^=WEh8P$)ukO9S-`?k(^~X3D z&h^H#p1kj8t<`}Ri;n~0p;vOVSK(Nvd_`L~dbk>0AoetKod@JB zjF85OzNM1;uEh<=)udZpcUu7in1xc%h5KU1{YFD)kvB0^T^SQdkHdP+qr!fguDFsn zH&?P3dnBV4k_NIVvId*AqAq9Q8BDAB{DzaKCH{x4%boFHe>tTMqsX0y6g~auo8{Eh z0;EJn9a16}jRwxac6;oqs%>qXxHs!N%#KYtR2)e7v8sU~YxTwnum>Nj%9r>v@khlb zi8F>eDe@n@i|^ZM!ur==@WMkN&-yXy&hR3!!lY0^Gt+)2{T?N7lS+XkdHs|VnuGc1 z`&WQ3SCzIE2}M)`zODdOli3)Q`e#FBQ`Q6Lg5fd!mw7^c5%v`m!I30XAC^VQikoi7 zgkU{FcFk|`=fBuO4Ix|S5^(L<&TGod+aQ`M2iC&9c?YJw{yNjW6Au4h@w>Icvvh@I zA`jjQD#{&kpjw!f;OD~2?-_P`UD3pi*_V)!M=}Mkn6BWt%l{68A+m3=5LQlhm4Q{<1=>T-R2Dxw8bd=GQ8g8(wK@ z4GM3mWFu1nY(UffXP0M6D?FVw;CkAkBV5l__gYF!0jr9)4 z)m!;mVuzShrv?T0Ulc1Gq#J4ky>E`L^GkGVZGUp+xf3-*_y7&wb|huH<9&Ma;W!`P zpUM!qT?jut0-%vc)GT=F_O7*Rd~f6}Q(FD5mjX|5XLzSf`a2eX4E)^1F32ly!-<}) zvMse67cu?$n0iTW(87xUZen-l2=TGL#n;{qoH$g-!2WRqzF&U!^2BXEy-=|1Oe|jbo$b;>aR(^IfC@2A2opSut3(Fh)zVmLd6!ZmF4nl(afE^N84_4 zyf{Y2Vhry~SiS0S8)|RQ>ei>PCQaBEc9r{T9)FHsB66467I< zW$$g<;eju7GcOsBBGFN$Dw`5_Q1j}Y@0PGr-4DhfB@-$JE%ZN}>F8mE@TJ7hI~}7L zy(PeZ9?$+PR2zdvo{!+c$uA=i!eT`;__YO!s+skTd%J2@55dlNG``4;tpZu`@+8Gq zOO+gL)o&VimO9*HXp$LDRs8pA4Z9O|n~N$+A^QB%I&YN3J(}9uU*=^ZU%ydtS==nv)mb2E3e4D-HxmRZzsr zJ-*POG3tYIkPXzjZm{ob#Qdv|mTyXKBNf>XQ%0|?>P3z*mvxrDA#}NKJE1P_OI34aE{Q z)zhl{Ze+pm+#z$0%F}{$sEhcL_shBSGPS+dgvz#i_MI^|X~H4`;-dT$U)qy!q&?2- zHP7hk47iI{3E@6B=c|}-Z&|_m1<#)0%MlB3BzZj3-a(#%7#%E?ubvvVE!^1k{7*3| z?Xp^R|98afL$d-S>Xm$CG-d9VY5jv;S<#yPb`n~K9ld44@FX(4c0A=kCj%F^NqE?! zQ$YS*%=S8exL%D@K8qQ1lGc0k_5RB$B_xt{F-Kdk5Ogg>T!1{?DRdcQUF{f(M_z;P z)I)2%kGkC38yl_Qi@fZH?M-hRi@fii}NM+V%1RX-u$)b z*XA*ymX@QV_&cg2(Z?rRmD*mRct4*$M($&Z=CD6e7!oz=e|}8Vy!|>;CJNq^u68%j%PphM}#eJ@2ZmjV1N}D@3uRgLS~Bk?=*do z%*#C%Vwdmq%Wt~(N~bJfFxC~<^@b0XVfrGPcYZtCHqdr?&4%UD3VZcI7H814y7+V3 z9B(1?@3cU>)N+$SI}_!K#^@F=yoE+-GpC}gcpT=qlXi^cK=Pk(*SaQ@hPa<}L<{jX z)+nSJDUT+p6(~`ONwniXI^Hiyg114W9B;Uv_AwVZIOW_Tt>D@T@b6G{4-hr>c>i=oU@h_gH7j=NXYfG{y4 zk?L8Gl+umV=;Upn`$8!PzxTY0h_Z~%mqA_({?d(uXzAlvghG4GIqpKujUfDn{ksFS z%~`0UV9B4>bIaSPQRvKV{n#RN8s>PV7qMg|Y$l%Mf)zX3DPL;XkMzG48G%G;>P2xt zJA(T&J#{dLX7v3|;0@z8-@%3+8t$rARv$Dguc%v8ye|Tg;YAlwE|1CHSOjEm>x=oV z`FG@qrJ_#9u-@}O@5+F$yCxY1iiwCC_>2A$ahVxz+_{*0wEOa=Ri|>6-TQ0fx65_^2401E#Yb?)X(c(jEz>rGG|GXn6O_0y7=s<6p^#49Q>Az~S7{KWW;t z#44+LERDP`%98lSL5WyB_Wp;1S{|PpY6}@`r|vF$GFRi55iJ$m2_*{j&YMeZHxxH8 z(vInwdG-4-u>Zz-<~w?ACGqnpB_F)uVRjGKgH(^T=E7@GQh9gLHTYQMm&I0^ z%N*%&N?2;5VL6n=@U(&$A#COB5A>iIK@cy>{W=;Eg9Xob~ zY7ZuD)OVIz-mueZ_>&JgfW7Q*W;8{in$@6$vn59XVPtE_rwQv@F<{+{uD969 zDJG{9^0wCAhjjVsN(p|gT;hu9O?&?3jq}5Pv#g+-*2a3E!&-uwxHRCZ6NOk>KOePd zGR}Hqhjl7J8IgFgTq@>1Dt1Qp@lDD5KmeJesWZZv}8eCGagZ^)KXRrGMY()b*Pm+@u>D>&~nTd&nULaElNPDns`RMfS=h?w!zfw`9L>>uWKe6*e{GzQUi=P1l zyL`))8I`gS@3W3kAL-1b{G~@Vc3wxv;B^-1_ZjSi-k^VrxL$!}+H3 z?W|?T!vDs087UtYY45WeQF!o+KB;}LPuJxKOW-=xzC#^9Xy=6}m_Y1ym;WfA)=zV> zpVp0c<3b7;OvnoXkYxNo3y3zNdo5Td)kozvzj3iiZ%Vr|@M?!7H{LYt`yJ8?n z|DEgQ!|SwxgF&Nj?nR>!u`@?uhF1miBR-g5b!gzV`U=QQq+P2V6Ab8Nnq%s1b~3*+ z-%nOnhf~a@{2BF=*$C{2BXH(j2~E)xlHv5qR$e*gh*$1Qv$bt@{GuMCtw*I{w~@~D z&!7o*drgb70(gcp%73k#v%s-U&X4B8NBV_y475e3OZ?V~##dW=O zYvd(0d;x&z&GoPQX>Y`k+DW?}K;>w*5~sj(l*{2?YwvgJzU$7|9{b~dpzv|=0kgBljDw@k$-E!3YU};GoVZqiGvaG+r zgQ)vl4UPKKxPl*=-x}*@OOs9?%q#}b`W%0t%c*8tx#-&42@raQ%Ug5y*w7W<$?qZ{ z6N8vRXR2!>LPF=6{X#Wy>jkayot@M-L5GZlxaek83%q#)-5}D3Z|&O=Eht-+b2YCU zhZ9$Lk7tF)CFhw2g~wI&nK8%ui60x?o@smC?yaj&sTnU$4-4q|p;fa|CA>KRHmrlJ zD*LNEV?G`HIZ7rKiMPU$Dx#@LdY-wgvpH-~>xt?{JzK~o8L`n}G1MnOESauoE7fin z|J-@}O)S0h{2NHA8iRbNh&=kw230l32mrsR($_cWR<;UUf_k-=RAAWKEo8ABVN9dp%XfP(ryE3fmk==G`$ODXkX2!6IyEdkc21rWOf_3$UGnvSkOOLFV)yNDkm>x z9IZBFFwMX0#9{UFIV5c&8u2+a0x^>Ga!RvYANO@ZC9pM62FI;hUP3z>k4m+$@7j~H zaY2H~05%f2lr&(|}PLQ{UaO^YeoX zdI^9QCYJ6Asx>jQ7XUq(>&sz8OoJ=&;+)~7Bpj;rZb}3!*;AC1Gr7&>#F`~z+JX!? zp+f`DFW8)4C{gemxYNa&Yu9?l+c`duX-sOn9j)+sh4}%fpLUuJ;a-PoutxZ9?K`M) z;g(C{uD{hx$JUCU{`iuvIcTuSaf=V>hle4x>&uND5glsLA7Al!B3ip7_o-Rp=+bRZ zSZsDirPZUtZ9CL{a5Q()4Upx-4+i1brzf1U<*Hsi^7LH=b+(Bc?D3;Dh|0nZq>Dld zXE99VDf_v(QD7ZSl98X&afqs$iKUhOWO%}5HDRHL{d*mW>qOIH;0`i(q9(5MBWKzzm?UskxZ&}P69Usn1H{>8OLf&ZvL z2lfNO`53FT|LbSZNsH~RpEiQXWE-o>_FomcF4zc*+p`}J7a4vzv!p+Aquti7xYQ!; zBaNIy^*2dJg~kk0!AqwrA(`alK0H$G8r3Ba8;+v@#dq4WAq;*}OBwa#2XPMV(& zc6lC`hAAxBh*^o=jK|Xz(01Y-Xa|rKHIkkH-Y&aNG|Qw*gaE&y}K$quNd4o zr7OR3uC1Bca*$Zw$d?aSOJFX^QkT@HhZe@%jV2v!#Q46k&o!fa^;Vzyq{jK|+TR*H z8v7hyNBJkj;4csd5*stT3xeEX}Wh9=I6?U%2cPZkF?O~b)l zdEq4|#artXW|Qf!JG;(J>b@hbaEn~`=3jg>)TM}|9TT&3Ze4v1L4hAgOey-d4#)Dt zX}XK2>5_kvBbk;egdL?QU#}+2eYvY}IYMH{Vbu6l55r-)X5a`7>Y4NRd&o7T07c$& zE^*ps8L0q8fQ0Oa-Q99_ob=eQU+-RD%Pzr1$Hw6JW8jlGrB#!-F8U3&K0KioJZz)Bu|cZWwX%+0Jk`{dxH?Yup@wj#g#C*H3@4#V|0wpr-X7 z#T5UmKINU}694;B#t`a*kMw<6TRdQ352m9)_cm<4Qe2n!PTbs%$OKJeJv&hlNy?13 zo&>$<@gcs^>d;HNKM%n`vG93nfClQSV z0@C^SK>L$<{`)T!fB4(KuKd?0r#Q19Y}#%73m^o)ltiuVKWF~mLC?#9BD%2KV>DR0{N zwzpabmH79ANEi0sLsGfAx^RhuAKdp7>%+3Dr+M@!*x9iL%JO4aWPLAf!2B0%_r5@5 z{$Dcu`$;Is0eR>fmGYPM2i8a>i{*}+KBDgxT2;Q=@dpIKnsfx?QIUh?qsStq-JyH<5gpo3g-Ej|Y z&%cYsrKW_I0tdo1(o;V=PoViu;VNWHO28h0g6AoF6Y?V^p(*Fe#>}$#TVIjCjN|W588!{zMbK2}JB&v3^c_LO&}v2I z+v7}Tb?h1o-sjJxkUSP}E=kn0|fU zSt#jJ{KWqpqIqWi#LV8>HguU*Twb>n>so);&&lQ0&7<2wpuNjqyKj&~H&3_iujKA; z_G#{R%#?uGL=Z_{bmmBk8%Q$;+@OxDPO-!n-vu7 zUOT@`Z#qCwy3YDt{vf29YkOE(t{*(dx&XeZ>GdN2@1!#Veu4Du(Ca%B?i5ZC_}&Xw z*V!6pOzS<$Dx-5Mt#Xm7L^%Qqs#bPbuYH{16Y$|4c zimp)HpKZkyy4aVf!J6M1{f7E)x0W;h;~oQrV_t8|5Elrt^nu@Y3arFJF>`V8X}zy! z{nX@i|2W6r|BhRJ$8yObWCih&yz;!#(r-iw_4Jf`{bu(XdKo0CkSY8MeNo8O0Ytn< zou1D6B&N45rPhcm)wS2dpXeipVa;PULm!ko&)b)a*6pgHn<{}FmWMt~>yOUTw&h8m ze;>5(2<+Ds4HZbj2K?0#`u!&BV-qcQk|)eh8MP(P^;=yCI8HP8dHG5>7o%?$+B&Wv z0PX*OLxwWfN@b)`++uj*mvQgGD^Axn>4mBr>qtDVAA>(7y{zY}mjk||@jG$z81qtG zgUtC--eujlOu5rDR74*K)*er_JH^Ubzf7wM*-s- zC}A$Vw#tgjw^-1+pxbiCzqH~cGp?Td_k##Lo?`C0=j-y>drLj5wx8rsIyde33CczB zkB=iJ)oJJ4)2ezh%O6t`^8XzwdELnVPALBO*FVh~|2J#l;b{MVasA)+z`!u^Pag3< zbqqui{NMLKU*h`yFwpK@e=*`EGpe04ZqzpBOEu<88C%2+VKffuF-8lf z_h_Smd!zmDLH~S7V!+roO?!>Lp>1XLLt#|BMu_m?@o|-IIVXj;0YZ-VK49U|BZ^b} zFMxPPzM-BVsP>k0UV{)7-*D^9%EK z#oO!4sm+NuSe^;t#LQs-=k;^sQBcpgSlC~p^AspZ7`*3;lv$6hWJYNnu#|kG@V_lml;RL(T}Nyhdb_<;&&jv<`#6|jaxnjBw{M@ zTO(a$3C*J=qA0I2gI2QD(;V`c@C?O*Q-JZ4Ou@oU3pb7Z;C8SA@r?r3EP7 z`zT8DN|LK<*}c#*imL8p>7O04Q*hZZdauVdQT}?@{(YpG(?W&r!TJxkLS5UKrgnM; zismQHpWZEk6z-}qT_TcGuq=)e*u3WbL;9esYdYQ&0JizHam}bAm5r4uIB>p5Eqb{o=pRlsg zra!IeVUwU|2iC+Ru8AKVQOh%-4xHg~Ps%W{oN2?tEkjhVxw*C2`Yb~REI;;IhxKlb zU5iNbas#@+sK5kln*5F1X4TWbT9Gty1dIbP;8;Psg95)@EJFerQQCF8J}WOiqYOHE zjj0K*?v&!^$decMskY^TOSoRR;Kqs5JwE$w+pb^@> z2`H6@dmS)qAp~*A)GYj^3b)I)^s1L>Ra#VD{$b%DkRMimc-fiDFLQHX8#M~z2M`u{dt+GleVQcTn>I)$s!>ft7JBBv&KA7?@-fm%SL4!l!_te9ix0Y zQ|k#FoT}#0v8)=cNx|P$*$uA3ur!$ckrI)7BNKh(xHa<(h%2qw76Ivx;!oN zrK0R1VaOT({$Nobo3AraAVf-JQCgV#;3!qti&i$;w0bRgdu^4!luKMDfn;N|$3ztD z%tgFGoYhuCgrbrCh;W>R;K+NtxSP1RQ%>%Ust{8df{}sZ!0g`F-uE+w;+@!)f}KD@gj;yAN=LK6kR{GR4wH2v>M4j`JM8(NpOfq` z5s_xz597gGs^Gg6PWPI}V`w=7oDqslE}>%BqpehkwW_fQ>H|Owb3rJX6+gGF_Vzj~ zZGAt5Z{P5g90~K$ziO?HGXlaWU+(+_9uVP2 zGSoKx1A%419&XIT2(OOQb7fLH1?|Y<3Q555W;IuSbPG*XPM^j?arpE@mxy*dub80x zR!~sF7Pm(vzzB<`E~2;cXoPN4lh#2=2;oK)f*3!N+%m-iPT3!0(Nld20Gb{1cK0pE z%ggg9#*H|G!oxwhfKxmEWc46S%8L$iMYI#WQom_i1n1wm=PS{zwvg;au22SG11)9> zF_d9KlabHGEFUu9W4xuu%#agNSV**pTiaXG8XHi) z@Cn2M#KC}}#;s!yhYrs+1GHeO9UvSqssJRT+sywo43B#=xXk@#{3@0aK`%YJ**!rVRd$YJ*EHc zL67#Zqz~5#2=%|2eUmI*3>=AWIL$yI9M}D=ghUi-kmHAzdmSbeb#fE-HGIrx?EoVz9TP?-h|8+AR_%+7EJ!ZGMA`niIcwkm|L z>oaNwRvJDx-H=Unm(iLUJ@8Z&WLo8T(u~F=s>4Gh!*QG`FFqP!m-ym7aF>lUaWrk?!2}*@ z$0^m6>lq(ydA4F*m~fFAG<@}Ol*}2OvDM;;L^p6>zKG!pp*T4UB8C>u%YzR%FC8uk z@Tf&{N{>FO%4#yRey|3THeQv`Ae7``k^oy=K*XLHxqwkV%vQeFQ~YcU&ye?CX;=JLW=9dX zB&q;0P9MyOoN+sNz6j25x5HWnl%5}cc%pm?XX!IihN9)t=)FkWl`7xH@g~^EGfiWp z1eERSTp@(;Rg+NA=M_%PEZRM8E0b$C28JNCZIT8D=9U0p&bZ>_&{ExOdiM5aa%xK- z^>pnxbiS_*{B1Cwr5QQNB7f_PoGmtvm)(h+nFl6{caI-hj`1Y}$`frO;H4kiJ28}< zzq&t8*V1i(!)&z*5@9l(@&odKxGqac0qz^sOQP`=fe=R=tWZe-745*5j~I_hiL*KR z@juz|4>9qKFlkijJePZ|AStE#2*|}`at0HOVBm=dF& z$p_5rL70o>mYt36UUM+7YXkicq811ovqFnbyV?sRI}f93jK{&|gF^b#qAj20E+Q9C zVdnNo9JAz?=B!k1LZHN&T-kTaQ{mdGggDx3CI57+HZQgah3GOnWUaKR&iFi4Y~jVIX(_+`G$+Z|~G3T~UF? z(B~cMS+07*Y`s5iAL(NN<@;AUoFfn5fP#T&?J98#O%2+OKABveC3dSIdJfdHZ232G zou75>BzTD+;3O(gZ*65;WIi_O?v|RI`d#nunDei(&5kp+lb18jQnI%@HZhHn)DxI^ z?lv|?j)Nh9sPAgjvHg;~*KhzTtcBeuv!MBNK4=vbqxwWggxBM_4?Cgo@D&Z|rg!z0 z0cuoVBJMGX77VSS_r8XbI{UQ#9ceQgaE2T^s3mW=3HOfq--zg6FOm~TmNjX0b>ruo zbD9eKfg%w9pqcYSD!*4!Z!fD=slD5?TSKNg7Ux zDA~1c>#$>&T;-flofsRN4UyWAbxCNBeYr1>M>|b?2mr!Q!|+zGG!13m>tGzV?T|dr zXe5wjW2?3vPCdHx`S0sD0=-X`Xb(!o^)^$%r<=O22_8=8M zG{mvA6YPtp&Q1h-PT6&3IH&K2KkB1zZX^)5Abd8z79;pH?e${X_VpGVd!i5sqB_bb zE>>~F;D_s}y)kW`X;6VUG#lgb+=D0&sHwefT_Uj7G&^oomVN8% z8+V}F+uLaWm24=A;P?Y0UJAlJCk7@anLALznrta+wO0?Y!_*8t2!sc?a{waQj&{4y zw|8>nayx)VAj96!Z}AmnA%8xVH>%YcpIs=km!0o|s)aAHi9A)${6h5T|H|>-Ms05l zPz(3v96*qbb^!V1vxR=#oF-{QHb4n!p^vh_)yC9#UlY&uK?CVUy3O(%&7T)t>pd0U zH*~Z&&1xkNG3DhKtd-;sA{O1qZpD>D_kp_LUt?Sshc1VZ`7u^@eLJpOD(c)$iXaPq z@k(n+!~4z+vyQWe>wVe9%?~LX>|V8C4aP6nAsao2v$nQ=?P9q$XN2tDir=#@(+%s_ zyv2m$;v$@6a#2uRJLV=WxXGh_4FBxT_=4(jCU*C6a#dVcwiRoLdVBW- zr^&|8ExJP39=89zshdG0vn96EXLY~X(#Enz-y5>Bn1NXEbs~-omZlw7&QN zBltIr{2TC%O~^p`m-ArAktYQ70Q(91OY$TRy^x{0KonOe69#}k4;z{~>o|Qv0Ja|B zHZwQNDJhT{wG#cX%RBpAvktgv<5K|Y-z-(uKNHLR zw~BA8^xR9g4B?@OB*SYb-U>E$_z$C!$Nl0z^9xM%{|9&JA~|GCu7fCsM}$GFUp*m` zN$N+YBWbLd_EPweRw#%we@~$g)$S#z!b$nQ?0%|;U>z+j{B%DY7!OY z-;x2MFgC_E<5w|)03lJDXRik=ZSAF49!tJbf7)>dUX~W18c%8l+z?7ad8N;eCmLk= zRIT$i8hY3%mU)Z+la0**>dN13!`)-UWs1lfK=1);0fS~{%4O)tr0q2L4x3E@##gVh zv~Tg@aZ!0`51^J2yYm#%>JBg`!9Nrk;%hNyA6XS_MWU_R54S`;z@C@lIHPenmxFDP zJU6kpy%c-qc`FfK7^>mbFAIQ4!Dzeb+xw5xWT4p5Vi3N6dFnCt>riZo+>US@ndR5GsdTf4?PgQTh&{@Vrj2M zxR%@8TE?L6^W-d$|KN)mWBUQWwyIs?SsS;u553U1Z)sTZ10jveUYH~!DKQYr>Gj?j z4db;Y$0k^X`?irj>yR^dtpgO!U);G6jm*b%h4_3DL{}FF8$(IHYN`SC$-jmruMs-p z!Q)Rd)z_VVH^2D7-_2{cvN<{MH9-cS_mT{we4k=godB)xP-U?^=KP_a?5u=ieo&v7H!SOOp>eUSsIN3^a;NGcy)&h66J zLO6%tzUq(B5mgD#XE?ij_(`&F=0>1F` z@;|>#{g;e>=clIF7lbSW>ERr{Hr4Vf@4tpOPulgT^Dh@{aljJ3e2v^MdkzGwo#j+r z-PpK9jIfrnI*UwEE3Bb{z_;jqq$CVNJo0x!0PEmfI4bTd#W+6?MSyBuRvCytL%r-w zPacP;I~Zu|M}2GYs&jWUx*eL^bsI*&fL}|y*HOAg+1JM=5wwe0NpMWo4B8U?EBgG# zhJL#ZR~NUn@w*#rSeq%j-}wP-&vU4?HCON+hlmpzz$Qo-+8u00X$kw&`yt9-- zp=QY)a)9|LqxGMW9GGT;4M#OTL>dDkZSmHLR{-(M-I4?5D}H_Id(A5|2onr z7r-GFeUZw)ga`X~hU6SO^fPa>!U_`KQz>sTv&ozA3byJioZ~VG+{_ z{`}1g&79(CE(#YHM)LFbi-aXYR9$hqIxey~tP1>$Y$E9E*v>$P*lo%AKgTnI0|4gx zaQFwstBbx(rkjIL{eRIAjPknP%nkd3S^hF=%Ai0`Ckedgc$hd$jL-Sl7+3-8RMz*C z36iKQj%_c?!FYlDR_?8n>28Q5b>2U8=J?n@jS&>|LD`%?**-W_mEHFvj_fzj>rPKC zzV9;lFiFJE0wl_V+tGl>Te_z?&9{5x`!j^$*ZX{+5(UP#PpofpL$qRu*|*|DGJ$009BR5-m3I;97prHGt;Dce1vJ>S|&g#6M=r%_FO>q%a}(Im9E=i*xU4^gt+@ak&azH zxYu*8|J2gjw!fl1|3MgIQH8y9;`|aZiCM0kZS6_TBpj%(Mj{n1o}?F=Q9~>I3ZAsC zy3E4ADsJhz>Z9_(W@8-cDEWw!g$_X9$xK#YC)o`h%qa z4~N+gj*2*u9?h%*N=mQ4f7Y$&#$5Jfv(dl?L~8jndU|Cn4$H;G6AqJQ{h%IT*R!w_ zADi(lN1T386Q{EdZdKqGbLdlt2tA91g>q z>Dzqdaa@iIRUupLW!0d(QfS#bAYM^lSDD=^XtBQsY$TmS#j(Q+iRS~y1b1bhuzt^f z%4q7uwM5L&d#x3>0twA=dPzi6QVK52PIE zM<`^Y(;?n-d|lLyNs>U*BG;%e;1FWJF-K z=Ha&0oT%U2eTDLt`?AyaQjiQHAEnT3s9VwsrXiB$bA%I6y#&XDG`P69s`}@QsxMq% zoZq4lQ{%IteVfxfSY!E5ucO;1nty)MR{b1DKvp@#hfru_AFYK1~DElzQ9J zTB@)g8vy4&{!RalzhWr2xkyUfyBc}q%;PBf1BKlRdpRF3>p)2BpJKtuo`T&~{do*&| z7QiKgx_?}4`Qd}CuPILra1aF{AueOF@Etspwx3Z+I0jhU@37H-C}pF=J@U18r!(iG zOnfu%SnFa8eAH~e7_*GLWb-;A1+b=Gf=9Vqg0SfOi-ZY57peKrs3NyBHA*+~X6!Ak zyBZcT$JzNEB10D1^SXWZDo}q6zv(Y4?&Z9|1`oeyv|&|?DRT86BUPqHtf)%6$})zR z49dm&0dPARmhsk-$}bBGx(yuG%}?PY%&33fB78e2z9i=JuAtUbAcut$!wBh=mBtsp<@TC|Y{dmefNX^Kg)(Cxnf3?MicI{d5`e z60lS{t3?p|bgp$~_vE3Jbm-U#}q36Rux z`ZGl^Z_Y()e;Ev0z*6nY{>GVF9s~svw6uwm4Zlx5;7hY7Db#P&KD$Cih^LPKIGzGr z&Y|0ZP{`fYF)UUzTRCh?$`$E9xC2^7LLJm!v>b}IH_@RlCr7j8WVAVD zqHpWhR`*rVd6|i@^;Dl02s7xD2lo33cv#NLS704j@s3 zRy$rBJl=dy&(DVYiM0s!G}~(+JJ(AQUTmGZ?lLPO?b7i-7yF<)j#F~AYMzZ}2UTq= zb-)@D7^3z~j`&lGGXW9dI48?Xy})lD-z&5s1&MP=jhp12B7(f_dcf{UD={&mQ82%q z9>INjhMWw}=Js0bPoEqutv^f>|7zd2*57gKF9v(7D<2B3w$#Ar%je9!aIV~8R9p4% zw;s;xcx1R3W)=m;hi9LxHG2iNk%JxILmaOj>7gI7tC63e!vk~9uyK&dewK!*1K3_)8hdhjEoK-T@un$Ol~ zQ=*|?Gbo2Ks10Ph-(9NTYxlf1NLKs7p0K9+8GDs1Zyj>H)!UK=R0fjPHI%PB=a_Lv zz4Ma<5_S_a)OGy)BF$QL4W-^($G(lee$uJxyblzbw>41#(B!UGWOz+^+5gh<6r}{pw zQS2-tdVvkmAgyweywWVGlCp>hCoT#(_?5i9jbt@e<0KQFA>5NAVlsP6(toud+>=V_ z2B=kze1=Q>eDyWm?zeBQ;)mh2JvJ{&?jg&obT_5&(R&_TO0o#)1fS#KgHn0kYC2|q z9<=JO39VIZ#Zl3MjPFQ%(8aXgO&wcW^6WPE@dM*s#V;KD68{R0ixuVP!BtGf#l%b4 zt7`LKO}uGUOlK~<6&9t{(Gi+*-1Z_*6=?gtB39A8}}bJ|hK)PRU@XQm(}TVm)B zk8g5b0f{YX2G#Q#ouLO;H%-bpaV%83D__Su-{1lS*{hNUwi4^(%b)66S0}(35CrY= zw%AX^W9p$U0iw1i0zPZL?#3;MmtUZX_Dj`DcSGO!2)E>K+foo)x$Q!jtW!204Eh-*$xunb+BBrR(u(`6t0a9^i=TcC|o7Zl8 zzBx~bLq;_RXT~?iPtyiXg*)oK{Z}2(WZ6E%5^M=>^#d-N>~}|;xQv(JVKdT}Ijs_G z6q&_(;P50!bEXVn=uqsza6SR*5mf_G4k64L!)7YbR_EaBBRjqnt}l?OnbqY{kqEY= z=jw(u7QZ)_+m_@hMHL}|rw_p3tCGj1s48}a>v^b8f3vr{DtkAXcek`2EA~n`&H2;= zFRkQK(_*^w1fd3loOFmq|S5|Vij5qqCE_{up=9NGM!FH}y&i8xM>J~rG{K@%cwb969r0S-6 z(r4F)6RA4$RlZ6C4{aB{U(+Wq82H%%T`_>eFbx3MyB|r!VaQ+QFU^^?=SQ^ElI`ks zFw=k*9kminNeQ60Xx5hR@VX%cOcc&KvnUw5cvCDc;93j+K#oeCGNUQ{Ej( z2*dqH=QmouSE+PDa;{n}ZtRLN6QCMD(#Fk;R%HrbJF1 zuhKb2L+g-nFKxXlX&;~wC?_R&`tMtl#~6+%3!r6=R?5Erd1|jZXeDwkJm5Sxy;NbZ zY1h9F@6NepYGg~gC|TYp6c+Wg+u-_Lf#dRD-L5KQX3Rq_;=&Ob7IkUMDB;Gg_eynr z`#%}OUlNYLI_(e3>_+D`*Y zm>2`wxI8{>s469MQdmJgbk^u{YFo1@DbetB@N6L zlv%(QSL*xR4nNZ~&}7@NnFfp3pB5`5#Sfc@RrW+oBS@%(^#bMGACK?~we&1n+8%tr zop1v7i>j{tqUZO98d0IZ=GzPhPp-ELU7 zk3US7jUUi?c3%M6@XnKzUV81N!rkT0%PEaTSgijl;=*-U_ zRc>jR^!+N{l{b1+GF7wa0{YhCY5cIdEK^ zTMlC*VINPLYqBl%J8Tiw-yQr$o?>MMfP@T>H#UA7vZcU4S}2L@*s}=;(C6f_gnAZ$ zFnAm#J#`^dcqs7OOC}DH-qzFJkQ_!ndET)H)HzRZyk1&JmWi4x{^(7#m@ZyNw>LuM zIbN=`H%2uP=$CApUz-bzLWxT!1ADID0C`FAmnwl3{9V{_ACHYTsP`2{yaaXFfwVaK z$~4bHqTEJv$X1u!<6=*8>vS8+y0sfKm)H!Gz~%MHbd9x|wD3WI&?K(LzE()!OI-QP$*4F_~GV3&1i{yrjYW zAWxwJg|v{Ip!-PlJ+r)$w(9)Xq3cMcVT6x%BG6|5uaSc{K94{fXJ?&CGLLgGlvr&coh>tngP?OGiM=mq&RJPqGXht) zal6E)*km~?BSr-C{~_wF!m4W9aBT$<0cns11p%c6q`MnwNdf7WZloI|CrEd9x0G~u zcg;z6^FO}dTI+X{EsrrrJogpneVN6?PUf^|L$N*bJG?Rk88_Z~{3`Kxv=2xW!$QtL z#9bzZl_2==g)%^SYz>X{wJ+7Rp{g-z2go@HfZZUnuEYP}d6{eP5&g%NVldJCCfl># zB+DzhEEk};ciRiE>=d+afaB9~jLXQ=`L2>pW4hsk0#BlvJ6J#Y89VJqREgci2G-fR|iZ<@O z&chDh-54@#v~*K6sw}1Aj{%cIwe6LIt6pf`TfQ0pUyOd2S=u%UmQW7MWh8iaN*>0t zV%{yD-Hxn?EOxdUpCFTZU^MN*0o~*_iD(8mFGEJ6zme^7WUpCq*GUUFLfEHEx-%#Y z8=<%H=4HOzd^&+0LY~7(pQY7e2Jqtcpj<$lzXM)*YyPXldS`9H1IH!@(T1h@30Gjo zqek+d#iAWhb{)p$Tiw+HjIdr)z55u}MR&H8m!5i|&(*|`w~mgw_h}E!%Vg?<8MXYo zc(dan?pl~()QWbG6)o>)+$Z;2{@Ds+_EOahS4LBDuPYL3m}dOn_|$101Q(Y^a_z$2 zEzaAqGB0no3wO_3Uoypkozb(}nfzzkg)=$0Zp8yR@@n)g%{w<03vNE1xQ7r@&SHi( z;*C=j`#+4h&~DL<+id{|jg#p+{?_tW-O%hbK%6C^5i!nE0>3R6S>f5!<>!l_ z0U0H|zMBHNumB3^PZh{5Lwt5C5fzwc7>e21_y26rs=YH-UUHzP+je)Ao6 z20J;%W?b!A!HC)C;AI3u7gaZ`|Evl#Tx4u{7TK5cGsEy-1#(QZx z#!bleBamD8zzg}NxaUZi+VjY^%uyJ4q4Cp>+8Mmcj!7yc(lzfW9CqRB{fL_^Ev$r< zAMCrh0-DpX&;r)L_ubc-9_kqmy)LP?uA^3WKxizRL-%sS*!w6cAxYd!5z5VnCcQoK zb7Te#Tz@fqzZ#F6=q~+zoUQD|A(v|+F_tFP6rs;sA^Xx3T=ta@w zgsC0)t5GIQi1HLJoo!WT<29B;>v#(WrB3*lDY!5>0F$F4i;!$xXi{5ahrL zc&KMYt&D;kFOj|4Wkm3}+ObVlVoC<_33a7hR6=*R=FhM44Y}qjU--a7D0P;mbqDmh ztsWh2D&Ny@BPQpS;_bz&Pq<0It|2S#!XE9X)J=*)5#URFZl+eZ;9f07 zmQ2$-1hN6z&Ti=Ourx`|0uH4&O`>&!yc#NjYm?Js{)nWv>;`K0El2ePrXPbjltdBc z%)FNUeXXrJCW%UaZhfu)lw9aYHag&Vl*0ZqXjjpwO2eML0A)%+>ZQ7i@-a!4klCC( zLE$#k^_t7Wwe(U#De3Ve{U&zh#(Bk3ZIA$LncT9UoZn`Pu>_q0C$SuCabD z<=)3}Nv;B*N$+j-4z072i$Dm$>7T-{8VB@Mt8T|Jgv_KWt-3+Hph11k0}{pAn$w}> zqw@|?WMQ7$zMOWgX~@jC^Kf)(_q1+VU>>?Wc4xz!tRo#(nwhTgv@k)1Qnb%dFDuSQ?tX49v zMV`K`(@fOeBAM%}g}9w2tr-l4s3li;lVhYEFS;!O&X;u#ES^twfi~AB4W;MuL6O2z zwv}98^(NyU{&_|_q1^A}0(Zq6>2bKAyj#5t@iu@i1WjRmA`_5 z0s;qd8Q^sIhvQ$@OYx(_Y`xy*FAR7=Vf@{eM-Q3Ele7Wu+UmJZCH1801(LH*z#W=q z*W(~rswE0H#I3*io%4aAAH*oNImSs;G!h4@6Hz8 zTX(g%#{#M-|GH+)4SFP?@dx4*MwePT{;gQok9%W*7xxC^>tZxBWo@<%XrbMeqM^r| zb|cW3MY%dF7-@GiLDiREcF+`Af++@wdX*^!>HXcx#o`M4H#hAS;!Wd@Lb!bdyKP|d zAdj@1GOL!Tm!NHeO>1Q8@h3O_9AqF$Xkcup|E*7uxTMr);!r?@7m-=Maph?mulju* z5knqIQl0h8yQgt~h@S1qi`e+MwUan`3d)Zac^6H}_r?bK@WaN-Mv?ypeHokrU)EC+ z>xqbmV@LbFv*h3tri5XOI(kCY6+JV;Q7r|8&^f;X?4EZIa5XOP$urw?D6d|uv^tIu zsAb%7wH#MF>R;{`;LDA>^7fI;Ts8H;I%~Bl>km`qH{#79>pf3rNF=|~hBF%`D%Q8R zuDg9Bzu(0$>h1+Db8foW%8LobS6(cXpN!>w^7yB`JkSEa4=-L>b7#jOy&?zK(t*B_ z`Oe-ow4&Kk=i2FJO`?+gNAi4LaIoMgk=QKWbc&Q=n>bf!f(#y8=Be|;Y$NO$p(gjQ z*redD=6xlrDt)CGhd`!1eGMJ$yxNqC1f~f1#vld+Fj5Xzb)UU~BA>VSLj02l>9n8I z>(wY*Tn!WOiTl{&3Q4$VdXP#6l5GgAsq;EC->!o|2A=X*t zs@e>cfhvNFt*2`xv#q$-V?H8GS+-U&GXV_`8I}g$gZmDV#^gm%lQdu;Em37RWsBq z0KYSRrdbV=mGtQ|@*moooH&#~l6a3J)O!?I zmqWtmARsGc;b!}(DAj&6tB^puYN;+%BjR+sk_JMdoP&Ln{TRe zb#F2`ogFsNHswl%H58_QmCo2?zX`03U;RC>1Dhz2=&5VtJ>hvg>mY(3X5`i=d16b* zopwwf1T%x)mbAG|74j(mNo&*O_XKxf@qNBy=YJA(Ke%h_hN1KL#6vX(wSQ31$srE= zSr~-Unzy1|d?PL5_UWC=YPZH_&{bs`6m%i3u3tzNY z648SQBYYsm=YA_b){6J|wukB0p^#l<81xCvgDJ^kWPKufOiRJH|F1Nmn*Nnm;4wIl;2i-j>D^V-4B`3T?i#Azb-ApfJEE$!~A^T#ai+QeSyfU`Ro|x zrJbH?>yUvHemG=h)^CmcEQ>$G=X^UJjpsbn`t1#lcMo_c9;YyRydryCM=#$ffM6;N z@LQc|8OV_G$2R%2WuZ`(m2^&1r_QY1%G$JDRGy@pf8v zoZpEF3X-#@>T%wx#QwY0uK)S_%%kw}ollS*CxetT0}$F*uMpRy96Q|u;0p}AX!$5m zWyOoeMko8hV}SJsgb!muHpPaExDoZgZl*Tjx|ZBvDw|-P{uKh8i7KK8$XYj(ww0y_ zg**J&+UJ~`5`3FAmJfe@CfQ+^$X;Gp`#jkHht2y1j8k!p-Pf79g_u(g;UGaWgX?)3 zgA4j5yx9nMGyD%a_vhZ?6>EJnpIr82-tT00Y!iOXp>KClGK5F7nh)HjsJUM6S^jJx zcsgeWVxwcwMx~d#LWSMmp02D?Aq4_7hQ3t;Be zrnUN`&CWP8b@qA!xT0jHb5@^{&OJqJ_2C%e)8|1~cB#C(J5>RACRy_7h{?`2D;{Kcp4=;Jf%o$kYLfgnse_HDH3atu6yw1iTzt~G& zotOsO{N=nb6oRgLN;^;#O4DFq2Nw>kgj}_36AYnvxtwIGNqSZFUCq?qE@wmXD|;94Jx7(7Mhsh0kV*aW^G1zf@?ah1EO2_= z^8;YiC^_48qGiiTcTF~-V4nN^u-Q^reClc2K*BwhXJF{cdx9N&Wp!%w3phL@;zL2pvUXaN?5Y<_w{;>f5%iU;mW%u(Chr9*pdmQAwv&N<-Oei~~ zMA`0D)m*WcRQJ`*Z$9yPT+)JKZ~AsPr?p_cR^G8(AA1y`<#MzS1~-9jW^cizq0{ys zU{<@PpJAB79Yg26d_9k@oN+(f?p(yhlop-vv&pJi5uuNE*rfH)j{}07ffBVJF|!c< zSPW&eP=z7QoFKxv>KwQCK6u_gIIW$Lxln7NaS!`xUA5xQ6!kQS@DE$k2&~k!;h;iW ze-kBn$Fp&${8ZrJ`=;i#;`xA^z-O4;nzlwvcRWs%bR7BA99E1_kZ^K%5;Sy3a2>}r z6&^C>kiRq?hPN{N(*tq9eyiE<34FWQ_AI|U;b7JTcpzaZ?a0o!nfnmp=*&syC!U!D5kZQc|OKdKFfg-uU4Ip1*bWH!i6 zqmNjnjgbAB*1j7ni2rD3g*b|tKV;<&^X}!BNX9BB0p2L^;`N4dbrZ+~KL((2E z$FPS-R5C8{lx)nY_=xZc=khy7W z{MFa4Dgya`=oq}H7aODw74Mlp45BnbK)Y_q_R&kA z>uAOz43V?{eETak+D~1HI(f(8_*^0eCG_D86~R<`bgG@KBHc;T}y zA;e?+l#{YjVLfr7JNk1ziH%ZjAEtH{*HS%SB3`0H)Y5F0KSLP*ptoKskZh(&*K5zr z`T%u?wcsFH+>*c0obdc+$W})aF&cY)^712TqS@W1E!X*XY2MoV9Swg5%Tuq1RcsK= z`ZMYD2JO{|XfO8P?QaLdXNQi>PluYv?QYgB`Ie`^f)gn*(|iZtLDz%&>hPd>$~^y$ zn3*zuAKm4*CT3bx?xpFl#kZWI3?zjbo{9=NaNOznKMng`auW+vVLLk_vq|rS_-Ql} zMQMSYYnp`1k}Rbp!#DdK6n3$0253D=^6&s!i7>xllF`(6`T2k zUMcypcY}%5E|3uChSqLVA)&|BvvNe0FX%D-6_H4-MR4iEkP;(!0#KK~$b zUw+Fd*Bf*`f%NjIHKzf}D?5 z&i{s*K`oskC|>xWJP{ma40$^3$Qw5=RFj`hqVmd5w?1=dXrl)%_$ST`2XgaDriB@0 zp_PAsZR={jH1A=tv{X_{kTOJKQk*X?+o#Z6Zp5N$J)5ym2vDR#bidgjl6_Z}VbVnx zM;;g7>o@)mjN}`-LFP;MX*qpl7p|ZUe_=@)qtjcWUoCyt6=U?&7HVAv@Y+kQCP?v6 zlDIBrR5c^5a3fx*Fe!MYzeY{b{;*Pw(yBJyUXa?9R>0%|;u7_+?JZY8gYkL5!d(U` zsFN0Zh;`q@!Tg>1{7iuGh?-viH9466oC++b6NipKB624Ulzrff3`Q#$F^G@Z%jS*F zqxT98$jtL?ryL6ka}_MT2=#t6tjh3s95Zmil2#Q4n87mI;dD6dc-h+H02cga84(Kj z|5KI7L=ixHlo(ikiOb;Z@tkAwc}Dgk9SK#!fhun5>mxy2l0QV>b(uAO{YuG@e~xSB ztT`q40e2k|tCHT@fY6Y*msc#or~)aa&%9@*Eyg14rshi;MVtIKy9eIr-c}>s zt^}JkQ7qKsZ}in!HzaVaUP&|KCmOUU9XI!IOOnxI90yVfq5^^`<^;2 zej>-37P{Uc5oyhykMOp0fx-N~0-8cMKFu=w^dE(V_b?4)2+L|!s8_s#{W^{d9_r%@ z3A5`rF3zchQ9BJa8@?Y2*4!^8@bIBmFw}Zd|No)I6md^40kwCB{K};}?CjhJ5+i*+ z6rV`NLbr-(hDPF*b2TR)dO+f`_Om3}D}X7qRd4l4ex031g`Q7(w0pX0B1V0*eXUO|lcVPcme-F=g5>2}i8#uq$A?r%U;!BSw71{EapqzGzHNc=CT!r76^4o4|7I&RZzqZ-;J|5U!y2?G1fg=e|6h zvS_a)ZODp*?9Gd@Q{x?3NeV{KUgsA1Dxc-bD>iJl{`Q(Rm>`8~JS==>*eg-L{;cI0a4rAauBiySqv2`{Txw}CvROV1Vp%aPb)PPJh(D@HLhc+D*Zay%|76)A|KH8wa(|^+yzN=pI+X0#Wfd ztof@>6A>-P=P19GVwMszrl-bB@7-0nr2Q`r;R6*^7J}+Gooje)J8dlb(U4L#&65;X z#sd!A(DnE36PXg_R`%Y{FNK#fkV&DFO=*`4K^^5pX&NkzIhoW`A;n=h9%dG1f-Wk& zTrE0&KJOl`-d_-NS+enR4E+f3?fU(D;oM$*nuBFgl=n^{;yn@J6)WsOfdl6`X1M$R zyX*?`-R+pfJc=2#_~R=02R1#C^~cTpG2K3!9mHR!1oNk%8bJDW8+p!D)3Yl>^#yjv1wU_@qfMj)4Lck(S^m#09jvS`F?ECKu-X%a5g424&UqZ4t*RaZR%6Kpz=)2maj@Ux9P!A&U}$qB9o(^D zdXh<`Goq{aAgJYSBYko`bf8n`K&jJddeOPI2bo!&`1bViw~7GE)_hI^NcnQah|6u& zDrc`egj#>U>Q}3{EPGO1pyH=0`5++F{ztX_K%7hA)ZQO0n(yQh7sTvov%f3n_2daz za9fmqUzsC$gU?HYV|4-j`5*&#zCDdryi^TOVD`ZEUFs9vcKZfJ0gkmPOr#FEHwCFQ z1`Q`dHq5uKMLKYln!-1dh)}cK(g~??^07xZTgB~%0x23JFOJn3{#&FkI`tmdH!6@_d<%9yvDem86#7^vwlzBuL@y!%AmpfBX-|p)+0hr5 z&%ZV1R~f>5hnCKMOE@np90)4t#9OV%iDbb8Y=DHj1@X9|;$;6)j_N5JzP|o>^9Re6 z6cY<8Ria8Z`=W5N|Mi0!mKzRf%%N*iwnfK0N6mvsZmn}F$JVS#Q*G`+1GZ?c1lBQR zdR{LYHpXwarGbT}`~V$^%+mJX#m1BOg^}BDmP?kG+YstJ!OpH{Sc?Anae=I5Hw6G4 z5twS+tm99Jvg|@@wCG4*JRHUO)?%JsO%E)8fOJ>vh|Iq@$CD-YS40UIeu_bX4$sQ#r0A-+c5%bd9MMOmSJ>oCN!;e#T7Y$Y87w$V* zDw-nx7PQ&PP@u$gG1k*-Xk+4`A1nSeIr#{3s4*JIFumauqn}# z59O*^FV&3yKG%`>-%Y<%KVd3fok27f#1*k}WbStUb*lOS=ggO#wJ!ewB1{wHMO%M3 z1aF{gV<}u^)yCIQFW|Lv#2?r&W-!_&-jwBW^|?NEp=!aBy2L0l)FBlkRr*6pOkzL* zHnLt_%LP92S*1P9(exxWEyX+ISI@s97N~47<-_`Q*DPwvj4BrNxVCh69)15RoS1%3hvvFyBT&;i~<)zuUaMDAZ$MZdl#|uz%ox zP5nG7!~}!Z*22b@vm06x_}zB%qCSH51->#bYw}FwYoRVEkuxeYEYy0Qa#SE$;{c-n zG#6A1zmdg-=ooVMC0#x&=wvRerds}FfQM^!dh%^Nz5hMp{;Yw*{ddIhEtRsxg4=k* zND(_5+_Kf8`;cOGPFV8gnTSYdI|*$3%skLn@2dr`LgfA75%R8APmxDVyM)~6WTvf; zQne~xWg10>ji=S$KhLxQ{gCE5B7ox9(ODValBC*ZWadzm14l?|yl)3xUS3x5MidLG z{DD3hjhpJt);mUS4*>_KGA#$s_gEz5JibxL53UYLcT$nNj%R2WT3tDL9Z~pYw8J9- zvP%KU23#=_jbha*GX*xSiio#|*IzFtvWi9wAMG$r(8)JZDJWRN*Eq*MbOE$m<--04 z2D*-Wz>Q=k99x_Y5f<)SNvD0&)(p9tWv-R)?^w359CnyZt{SHrp!kc;Xxhxi6a_I zelF!oCc#qm{gyF>0`C(zvF8^Qj~y)JKzY~}kbFOip|3;p_k`SwrPWSAo}d$4@ZYRf zJVr8!ne0Eers8HBoEV{mL~?U--8*M`8<&myXHzXcM-q+~ zk!oDSV&^VwMF{Ey)K9Gpf|bh7(r)$z%tw}G40drx^Ij59n%n!SpB;QkG04JHmU`;% z=`2?4Fl47LY#KIn6?O`U0?P(aKsJLd2|+0o#X;q!pm)Vsjv=7i_V9;_wNp6-&1~(g zCC%=zH_NBzJHCS_sp+Xb<@0zJMJ0js%b7(ZIVb|+DtMWXRyc2rJ3fUVe#O@A|3^#& zJ&TPqlz-u}-mirvO-_ZVvsQi-QSY?*GZ|)PC$r^Sq8F_knv7W4*i(%7u>aksnbM)e z$sc(Y3pC04n|EqsswIf&LGB@d^{PQRP5whaSZP||ke6qyfl~FbKi`f<9n%eG>?2+G z4Pw^i$1=+xN#ts}L<)%yLpW+iRn3E^Sn^hzP8YUplKXtskZ*1F5?ng0*ZvB5(_UM+ zHThsd5@a}^lz!%~zC+YzP8j(U$uzGjJ$@^rm&`oW*Y zJ!}UFPa0-+*MPQ>ji~7Tzh7R9J2O}=)PW9dt!Yh=tgINc zo(EK=lI58PnpQTv+YJOPR7V`yXK{VoF9lW$9Dfc+>&APqiYQo=~5BI9c;L% z;t~Ek6RN71v^UB|XO*-Os=CuEfF8SgTB=ubRaOe103U$Y! zoQLU?CggT$PHfe?4I`9(_!fs}!y1u~bK}zh^Z|`ZS;pp*$VoXPAMqwd3dB5qsT&&3 zpLMKt4-_tY6TYJZ_V&Yw9tpf-=N~3Zs=QY&m-pT!-Z_?5H-&`Pnr_?AJXg!)*GrS) zDGuJN#DcbLuwR!OTI`yHXbnR$%feuJLouiW+8Z`h%R^$?CL(L)7}=~=LXl{?Qa~%P zx{d@72IAl>4x+cZXOU!OSrb{zzK(t!8P9jbbNrj;)uNwks}`v&9r_c*QcjpjIx{R( z;ant)I5{)8Tc!YKMNhu`&-%X0FzAu^WdUH37$@Ma`B@PE!%Bb6L&5#5^0mzY_Vd{N zW<95o>p?l&yKyf#v~+TW&(D!WX`D%ynpB@h zqCZBUeVy_qGv5!6qhh{ls2eMLqQ83uI#j(}Ls|i#OaYfTqpYz-x}*}~$6A+)ccK65 zvZ5wOC7)l>cccwA%+gp|ZRxe1sM4Ft_MDR?PnXq%rbs~8l(Q0&-I2<3%n4~2iEP#g z9sIcQ$!bii_z8yXeCp4B9Ocx83NGi;Hp$)O$&)Kdat}4PE;BkGSv_Z;zXTJUd=t7G zT73Hvy8d?cIyTMNT}&INJPT#qi)*YfvVvkkSz-C9hA|VLAyc(?t&5If$dSUY@;w4t za>UR3Nbo|}Gl@5M&SmP}H3)0E<;{C)$h&z7Z=t_XD6B=j!0?>ks+P`|-=_=k&}i~aRzPta!9`%Ocmy)i>KDXGbqKs%!p zyajNY4}(L(Rz|f}JHs^p($M7Oe|FH*yg9dG-d3jp5k9Gk zwaFyE@zM_xtSaX6JO7!AvdveZ!dNfIg3btLy6MI72#uOncJ;6z2X2h-JPtkTS&hlG zW8TA5=n>PC1xH6GG+o1g=Aw_?J8OBl1R#PnSigI6x&ZM6_PkrMcc$bqG{7y_2i5uE z*vWaU@RH2&klXJzmyOrhtpRx@Qh93k87~E;q-E3JHLbp9D-jHg(Px!p0KmmZyzU852QL57_D=ZR~^;r7Icyw_C5dP_! z1?OrrU&`RG9}A}rRHjuas3}mCLa6nJw!@QA{sY}IxP%Xt9OuKI$T|EG*Qk#)TGPci za6m2Z*3^~eIMIz6^jOx}8dHhei}{o(%vx$0!+jDKWiny4g?e3oo2^ zD~xTbs|mMAv>UMwg(OwIC5&8=Rka#kkhxrud|=?Jimzz81j`dgdKfi-qHOivS~_1q zyaaQR?@<_&!e3vocm^%RruT$;l$DBV)nX^2ywu4%kf1JP`~22zUS#Rr-?fN9Zf;?< z^pzi-TlKbmfSDIAHjd@-lwm6}<;75UR=wuJSb!WU>zG;6iVfoNyhYEnnSG&+V*9*b z0vsa|BfjE|+t0*dBToFye|jCCO5+sM{V!Q~SZq+O%)YnU+?s*(_yyx|l7obmj7uZu zs_4yNY9{=3)jQv$oc?7@vOvFm`{YooI1l?m!~F=y&Np}{MX=3-od+5o@U&_Z$UQXi zq?U4(xh}q`E;xcy%;6WdTnRF<2T+ig_*2iDz=pu3+iX?;os2KLv5=!v$F&Pob4=tw z#N-uj{{9oRI5I&;4XWrRD_$BIIOl&42GEGyk4p1P#RW*Zq~v5q;WZdv-W-xD4CsEj zvSvzKDor7N3(YqlKilTgCxJfuGKh4wW_iAM1IBme^O5Uwsx2?;Gpn0cpq2Fd?OIh)jAmMCgy#u}5T zYoyOY9@CcSm6+iFeoOyNf)_7!nk|7u3_lVT|M>GA#%aLR7WUfFIY3bfj`&)&NlY|h zj5Pp~;>!eCqna!nM6W-Qf8*mPbe1u``>7zT{q>Av#>!2jb3Rfe3fJX$kvD;mH1vO{ z*bJuQA@YU9VKmjX)Lm=(NQgcrJkDSJR}{K(sR|5(XAY3R53l}-8BBy(M#1w_)sM>; zm;Sm81qZrPh96XyFEH6I61H>|RV;aPWoZCMt^nS`tR*2XHB&xIvTqIffyMfgRqGX& z46#O&x<8sMzLPK;RVzJN;J0F-gUdJjZd<7PUJfKi%dVfPv|B_h7orhc9$O)*Fqe@H zTlr+i%|C7ZdX=-k6pvMLJ)!k*U-#LFc`m;K<2ef;(Mj)V;I*9E6=H=nVmKe}*OA)L4wKf@Wzl5H`C5`UWK5>A=lz`7%S|6{ zSS4#-)er7nmoYcyE^ zXUrW#xvJ;e3d^a{|IRSGT781FZOEfry7%3a8tU-!ZV==u?`~26tKkNWZwaP;%-Hm}shPXGV=Fb!(UwdNOsSuhy%H~5cjp_r-ql&z zUdXxOlLI@IPL0U7($?(PB{U*wt}Czc2jT0i!<#g9D-%9ho%~@tV172367yVMG~CK- z-xk#LS?7D5PB=l(nDUb#$$+)@$`RSALy0PiehM1Smf?ns1c$cz#81$Hlr#-?6&U{_ zGW8hUHjr0lU72uR>9)|M>qwyIkhErf0@LLhBS5_3^xF|?^mXCs(OA$N<~xk`?v@Sg zzlc>WWd*VsWyxI1M>Y>={^g${pL3&{rSpF}VaJaG9*CSy<85@ z(up3ER&v8gj*9O0IR)NdY-|$+=!*%8`;Cg^yGWf2`$~v8&H414FN!*UjEC44R31Ay zwr9ey{;d!|<~Ht1|^AD|_9KCQ*^B-^x(~ADv$w%*s}#@`rlh5pdAqPGbE` z3YgW`KJ^{mMyvkJ3R|I6`?Z(WVdk>5XVr2vKEA8w?eJpz#RMnbeqUwZv*-2~ukU$b z3sElXDrn;+a7XbJB;{{t9ik0*wnWxN#;Vbg}v zTe|{S_f`si`oP;t$pIq@J_^e}E7?*^yJvenPU+T(8z6ZE?gO;1bZ@Gw zYoLyY|EaGK=D>sXArDg2z%l3R4~>}qO-u@b+rAZlF9%HzWva5k(U9lh04nf>dXX~` z`bUmXUpWY%kP4;6bfsT%myME@%6F zuAi6lu3fp58}3md%^%sdGCB}he)rQPj1p)_yM+*0UHX z>le0AxS*N^cg(_z(_(ml|O3jXFT_q?g*;!9x3L7&V;bj~F z#{pY)(U-ZIHI+MrJoLOK4Q`bL5*0lcy5c_7uUPc1RyM+Q$PG*V>BD#LBxQ|&5!0g3p`I@Kvs*dVTed#d!o_e9Jz zq6O@HvIQ&foIE%avn{O^6=e{lgwso?EVSBLD#(lAp#$+-K+NoOEh_~#1@_Gx=Lb&r zSKhkE*$^kr6tG1rep&ZoW_H{MFloQxf|6m5fWtxgnl#+$g-^QD(My* zjmPo3DPv^?SE(L@tNrb;@-fsCVlr2pA#C8yG4ktQx ztU%F;rw=yD>K_OJ^Jz43h{_(Bd(3u_`C5}x{z_A zqtpxDcereAahe9%R4`MvVHGhmtXz4zj#OVm6D~#X>3*o473zvKsT~J?K;Bs7FZQsm zOlNHuhLT-Tr|c$10f+~^sS4vr)SwD~0mnB0RAuElnc#le`?8?1^bMG}$ayJo`+_BJ zuVQ}89we~+7)RQH6dvCnkDWf>p=`hg+r~WxN(TtQ-V^m$c7}YpWMJcd{ zC{3RSf6!t=$thxA+pXm_q2~_DvY!4v9^(EU7rhvVeJ<=nJrznKijuAqda-J3!#F&N zpn*2$n%^C=bMx%OJ*;v5F@mTRY(z;(+&@>YL91EMSJp@L**#Cr{ZqPPB(iOKlz$3! zs8+Tdc((M5F|%`PJyVM$9UYRqZ~wllC$q2=Q`?NdqxBh}k_;zS2l2o0K~(v*tTm4& zUa7)Qy0=bAzn7I^wUk2#0+?TGo?=tuLCO^VGIX{fENGYn+~k?Lt*v>;yu9!e)UqPN zcGyBYvvOl5tooOLb-XiH*gsJl@E<+55vSMP*LF0oL3_Ik_LFz5quTeg`k=(%@aS2a z*kpTtd?lL4=wCwf>5_RvzVr4D8`+#KP|}0vJ%}U4^>d=&yXm?-=$IiMEm=tE3#Ps= zDJev29cGXrgaFnn;S%uIPqyS21D`KBV0vc(UEWNRQg`a_1M^Fm6R zDxRilJ}i`zq)d_GtVD-4(=yxJEDsp47fu9EgiKnRkJGPHYu98S@g$nJxKGFtJ3EjN zqQ|cRng^aVUTP1P8+qm@DYc9|s=bLsGfP+(;G@N=D8m5!rA_ow5G<1ujYr-NjIke$ zd&axQQ!8U_e$?e!(*m7?_$=2UyHIcmkg@X-#r)mz4f>1rPbRC@UU55q7LARKNtW~z zK#p1Ks?Q%RuO2-<&~v-@15h)RaI|$vpN)c#56!b?qN1+)#ec8tY{yI)u`tGd!JSep zU{tj0GQ-$*K6Q?I9xEFx+nTld6f$*;9yw;8siaT%*3P@~;^|wd5`xp?x!V!9m6*F0 z-Q!MAoA6Sru$ks5G8VIv$_ElewP+$dsbb~*9IC9G!Z+NcJVBQs3^HC<*U#VGo`93e zq?LI?1#+6MNKrneso(+7Y-Twa$8>aLa)b%hr7 zH@(?8>2r2|j<9_D!utnrN|>5LYb!E{)mc-lgOaepK|<7N5^aRTD$Is-51vv)o?QlQxdSdz^mjLyFGEdl|+jPa4S+PdoKp zgVl*Jo*_9$vmPw^@TZ1>?hh3?C+G765^b=<41em(Cohi*CTI++-50Wx<$g`WU6C*d z$_Mb6;Q$oh^UH=KtaEGYc14i{i;M`dX(^(%mhDAn#`CEy->9)~R9Tn=rlyS#P1XK@ zMDsu9G?#*cCmZn091rfg(9mwu)&15kTUxrS)Rl}U+>=+_LdaWsB#I9o zXEUba}3Z?ZddN$U^HW+w_e&M-V5IvMqD);Vu^IBU1; z=hqY$O!f$cK|>BAUMigd-q`J(^b z9pB$`9M$MvTHtJL!)`_aSXWS86oIRe3$Z12$*9vW^9P{r3W}K#x<4l)b-ho6xBAx% z3<`QFB`+%^RY?TUj3#EL!qS?ELNxAg_`FuDeZL0AD?W*T zr_wFnIhKm-=6xS+-7h%2p z=k7+RsuuccL4T$uFG>Q%6?vYEd$PSnwc4?I4~paD4i`P?UGA(#r{$Qp{K*uQNm|FT z0(Sm;YY6Mcy4))VG342Bj9>9`VFj=1BL#HMf`lIEWQ^6fq5eoj>)J|ow>sBZrowGR z%t~OQM0epNaOLAiT2^lt2baIo!$~I+38CS7vF@;ES-c+u8lt->%US;S!d|UlVcu_U zf|?10pfgeA8lz)ii zXW18V?Zowe$W!B7uTl3;JC{}MA(Usv=@kVCAmkn)(-TDGlW+^q@0wejHY?hqV;J0!TfySpSf1PO%T?(S~E-Mw*_zjN+A_nr5> zJN_Cyy7y?ho2uHYR#mN-84+C-f8`B`x01qht({BD7E~FyVYB$)x%r zSk<8Uw-+;3bFK~5U+|rSXBioV-rsV2M(bVV+}f(}eqIn4Jd6uT*3@eGa-EEjp6Psm z&*X0J!E^o&&G1O~MEeaM?(f?}12ES0hrx-2b*SFkX?e!CKkPK%?5vC8LCS70L00t- z?SGM?A50t7Xt9`BvXp*8{*$6u*ZK}l6~)?i*?$C9K*U)p0IZ#iBKe2CP!cm^Dc0v@ z2J~CV?+<$11DuHe_}2{v^TntI|M~rJ^XMdxCF+=of#iq~W*34f?_%g|Po}(tv-S}f zUQuR(XlV_RVBKu+2MZExX5Bij$-Fn#mcaxy-?GO41)2{fqWd>+i4hX+eWW7&uvqC# zfZh}O_g#DVL}TL(={hhuC-4OMm}i9{^9k%}B`eotuMtCd?0HWAg?Tbx_?vmQS-iKn zlb?_Ly+f749|-N(CY8I+i+v#xuO1w$Zq~EkavLj zZr>3cq%jT_HJasQKRyD3&Y;{Px)6HM#L(5aF*q8BI7PZr0 zYJvJGLks2@u4)1tbJ~H`dxL6H(leufebxJEw{LFN=iebuXb=s~-7Q_N1rX=p{9VC+ zy?#RibH^)z`M|-V)`sB`BCemQzzS}EG)w)G{8z2(i~X{E{Id^Sw}1R97csJB^u5~1 znOs_%yKA_Bl>o1of%PW~|2BfZZ0XMvBQ2PaIn|s!GAzgaysz1ZOa+lj;Yz^BVC20zN_oH zS%J#Sk6#sije)@4-d+?>KBkTb-o5e6i0;;B)wT6mnWT&I_jUs<>%QopKW3LqI8irV z)MwaAhXqzNG+HD6P{@3qyP;B;9w8k8lfM3=uuror5{5Wdvw}0QbuQA-eNZG| zLzwa8dHFlGLo;0B8T#L2ZCs9Ei&Y<=ot=r;?LTN3bnOxGoe!b=;^J8xQa`Vnvu}Y( zw*nP?HpIeRnhZa6_}#C9`UD!*5r=lZjT(f5GpP?os9N4Rtm}a~m+jj0;P+fJh`8uG zB-hK;!28mFmcMAXf8IB`w^l!*@}E!UIMkM4KFOg2*#zEc9Z@(Hjp**35@i*amJ1%* zzyyi3-Y?OGyKp=Fo;IU?7T}=8L*5_lYX+;6eDmXv3?qJnpR-=^=VANYU0Ci^d4fTO z6*Kc~Oc~Pm+dT5OnFw$~Ja&|p#_)*l(LcHbe3=i{W>hXIYeUVbw+WfwpLxHg<96yl zg%R|?_Jxdr<9$uhSSOgfY4hqy(Sz@gxbub``qprt+>Og*#j=;BV>Mb&6cW;T+S?;d z`~8%n@#Q_Dv~pMTm}Q@<%M(~A6dXw%7^R&#Kl#O!C%c+m>o74fF2PMGxj5zczfB_s zj%u=a2OS3E(DxTd^T2W6t5{(wzY(y+@>fDib^utD*iNjuZ1w5(=);vxc@yzi8H3OM zfb`p4DsC%S+Qst7a=lp;%-1>#!W?(=Xl8bM{8&I)w9z-OAF^mFsjT0QHYYbSvT^hD zuW9A)USP+sgz`zox7NR^%iuiV8K}_qnW+T+bZPJ4+1mfr2ByNeZYKg zU305^Hz3U3j^fws?DWX=W-vSCKT8ZY*j+IHJoi1knOER`lQs(xB$_A-yb8?JCH%lw zx?GX-QB{u3_pYHM)4p9Tr$YOxA9258u@>^U;SVo>FbyH`q@e!ZN572FMQ@iW|IstxeIo6ja3t8l z&J=y@xgJuz*g>AyvVQ>l@2XFw86n@X2$%F|wBNT1{|dF}|9JcF%z^*B zW$`!Q_dm`PoN4@@>%T6f!O5b3o8!M;3sQw~^gLxhoVX4k?n~t>v$Jz_@81~}I5z2? zd$xIMh5WYcYkU?JZ^`FY^27iqfBZk4feLOKM1!s$bR=>l21*EACJ9(i;2=pcxAuft zG7l_FvF0+*SLyk}dm>ng4%RCHJ8SSjSC9hl*}-6PFz-5;NA(|N%DfZ82gaVd5r6=5 zel5p@f-ps%fN+F=#G(Q#CUUaWpb@eg^LTeM`f)Uq|2??dyO+i?Fd`)XpOK~wUayiZ zfl1}8-t_NZUf;cbu30p!(Y!V*plt3k6b2)7n_G!jc?H1w%wTXUS_?E)5J0~}aWz&E zc0s`Aw+UE-mNO0GIP&+~*JBx%7F`YBZ_AhP(3QWQrslzDMn`G?3edV`$jqkyl)0!h z>~mH&V{ngA@T>(`9>krWxb341qD*+nu9dZApdwS8-f9J&4biDj9Oc~M^xfjrZ^VC@ z$K%^c7Oc10m$`m)2Wqn3016lc7&kWt6&ePYqE*j^>Xb6CmeaWw7o4T(X<*;#DiJ2; z7Wj9)2HmpRoWh1MLWC_kuGS6ejab?4*6!NxQmzP>7*0UUxujGH6d-TiNAm zA@5D~+vpTaeY17$3zoU=s1PbreP48ttz(Y46_pwDx#y-@n>z(S ze?^-&z6)qJM6(SizL1&<8;kf<*@=1DY5hs`UmFknQlu1T_;nx}&pm-t4vWqvak- zI;Roqm`;7_EeWsmSZkZb$~oY9HKEpQ9u0dxL*;l9F>(c zHO0g7;-LHKk9|2q%X^EPW!Tjrr$#Na zi$>N~Tbc=0O4Wys;da!Sr5%-VHBIM?D?{MzyU zTXJGj(xDy3j?l|30Y0xigr3_2JD?ko)^5J*Sb|&-XVCt+PQ2%-%5c5TggTPPH+uSB z`+r8qKMjiWk3sq0qC&3lhO}@n1O*mK@>s^?6F;zG|EQ^!2OQm^q3!H$QXVeQJ@Dyf z>J5&JBuPAA4G)cdudZf&G&uxnH<;BtudazwD(}F+c>y56!y^9gO)nN zwCl`81bE%@5%ULR$8NSGF4S z0YxJ>pXyUMC)RJq>fty=RXgk|y#pld?`(?M$-KMa%sGxjFpf?xDHFVvq=JnGeja|m z;<4GiCk-v}2t`}a&%R0D1WBRK9FXhD`Ge|H?Mb~(N*up^=Ozn z{Egqm)+{OR94HB`NAU~3f;Cmlw^HSbb1UPwFpscT|Lc%^MPY|}0YYxMhSi^zw1zHi zua7?`Tp}YEyO^hn+fo0Zka@g5oL>_Lt7I4k@Jp@1J3Q7O+a^!&@bJpUTnG2UL~!TS zxC2)0`_!HHV;WSn(rAyoU#lrE@wm7ev?q@3o!KdWP|e6|=#N18VtaVHOMiGcXw)o0 z=jIasj!wWV9sIntg{ku2?rsyVGUN+zBWOa1@(w@vq&3jHgx@6+ZJ<|)40#O#uv&F- z0W5ubdQ^dpnziCADAODKKL(0Puvi9<9a(QDRc~)NT%u1b6?c}s; zCm|tm-8u7y&9Z9vJG8FWV&Kz5TS0BG;L{nw<>fUH^g|yr!V+P;UTB`Z}w8c%e?GkBrdK za0rz3PvGF-sH(_b;#F+7D42d$^I+)674}ugF-Uk`@O}GvshS8}gQ%OUc^JTlhlf9! zCW~Z!@TPoe`7dsUW>_K;419M`$SNt=n#L?CrYVYwiA^{?yhKbIZ28IMBV_f1Qbq5- zTBor%c$(psE_&UK2GQ(_^Xgd_T=FnzH;Lx$g1w8(fB%l;pYKTY^*L`G0Ge@!Mu!tg z{%P`mUnh4!xfc9iulUzHNC*Gb-9$pE32Xc}OHjsAf&8y6kWhwsKlv}a#*f(AGX6lz zP}o79l9HmPtSk~4QGMz7frdU;wMZc$k7hXJN9MrxJ1sml6%|oGsbP=kKJH)tQ$asC zw0~DO^F8yq)WE=0Y+DPh09#U|Y~)XwB&waWE!luq$k`S-4W#QUYMd`PygK&L?+NBq zbd3X_y+$ViSlH8nj1*dni?!xANW+8Ud0lN!D)YBQL*r)^hhb@79Rl|%G(Vg!wQ8}Y z^V%A>3Btn%o~-EdVmPIu5ekmlIH>5m+1uyt362$;EK6GwU@Hj9xBc=iuWU^9HMoY4 zIt`hf9Z8Zz!TsnvmY$SHBP-U4o1FYrwu3%ZtOk2L|Dcf@Fu?*>hl2L~qDN}V%!K;< zo{+L4i{X%8a_zF>$wOfz_fr?c!B|mFQ6+ZSfoQ<7ZnNwA)u)w?p^=^>U(YvH%Xjz+ ze(GxvN2-sT4F)@RIu*^aXU(sBo__VUwaI55w+>5nb`{Sp26y_`m*k4^--@VdBlC1= z6im&gw>ap2#?M!y-QKe2YLG-)uS(wX-@qyufSG%9eZtU(JHoC{rB2D05**V7!q6ta zuJRpXHK-G;sTxiw8AQ5wR9UZnkd;yV<`)J7JGIc&Ghrcc{uWW@y23gxblek!WOaYU<}&PLw>i z0(e#X!_*epinO;VTN-D|Vm(2Oy>(p}J40JLIx?l`15H%iHv=W%aCIiSc^Y2{W&H8) zsrlCnznCT;PjyO6+dFZw2>dc%@5XT0{T?tqFANkX?~TYOmd@$czu`_u-m{nNycw0Y z#$#c>pQ^sGq9JEXQZO~0>?c~Lhw|(n`Y5X)zwJ?#xS#RaS{E%ZDhmZWyOJ2fUeXF7 zRh5*xk2-B{edU?I`8YI#c9<;@+*yn;3-g93e^z!#S1a#&oD`0~e&5+qdvjs;1H8w^ z(Yj@mpu};teV|iPQIVx~ax8Am%M8?1vq4yVZZf&JP}5YQe`DNk)B1EPb7@x&W$i;l z!@J5A)r3lS_^dka)eTF>IeDb+^s{MO-?54bXosF>BNZ|2sC$^~L?PiqBtQQVPmFOK z)qU>Ijgypsb^gnJB-a@BjN8=OR1B%E4oxL!!-d3$weS&q`#{6T7bdaq909lBwL|*w zc&`LvTz#!pUItJ6KW)r$cdHOq%3WZ1((~~!5(Jz!b%)1B$Vr%(ny;EO4nYWcf?pWY znWoq}SAWNNr*l%ewXd7eGl~d@9RwZRde9rj;IjwkEt#vuuZcEUzb{|Q^<)r-WWM^5({+;2eN|G^`Qy8qm<@fR1`m+v2Feb$ z2a2u2Xe>+hDA!}=G{g_Gl$y!q?ZISwCZgD&(Xhpafnt1t18|j;0RoA}y&j^2^r5*EOeD z4mz&#Z#>veh`6{wr-m!FOf%DO7D2HrwJf$8)`0jnP?%=X_EW>N5VHdHm?DDT@RnqQB=VKS^V z$FGCL(br$lW5mHz&%-;Ve@`@p0a#Vi+G^IaWnt#lvk@WgXea3l%4~Kd_$w_r1)U5` zLK3@XyNP>*J3G5m5lK{HYO3f=mgC0ZWYYUPyDI%d^a=3k9vms4Dp*Np+?r|DY0A3t zZyE3$+o1EkI~^w=U6AAD)q{7slC*HVcs!{JzHwB;Hyqge$An+M=nUilg;hrMTwEH# z5kIoCu}(-dC7vaaJZ6P(sw1Ag(<4|=6Htp!QHO^=-fW2c$~D9mv|QiV<|n=0dB3MB zBZJq})EJJ7HEJ9Yl)~(P#X0@M%gM{5xh2Xlt0yoqE2~Z15Dp&Z{L8rRob1t4DZOnN zKfsujUrTCoHVj%SZqOz0N4CCm-+jc6oq7+U0zjJSWN%B>=_^BGv3IRHN`pk0r{wpX z(eWRpE7rqIG!$MfR4d>32PYbuyo(s5GjcN1WgkLdRd^u=+}xb@IT1?dM4-_K)9!uG zG(spPc8+#L_4TuNChpcnU~wfL)|O&^M>lC--nz~{QhQy#v2o@GZcYUC@`!b+K z!!vps$6TIIB^FRP$P#+2QnRME)Lab~WLe&??7sut z^@lylFjo+H+7oCR(Csy5J>3m{QL3k`c7Zt+tc;t-p*DAa6RB>8XpDo;i?i>L$$OWE z$6w)5wSXEN1vX`}M{F?5KZ5)6V6H^+zZ1EVlMD zB|MZgOPgyIU8Uo#gZ56kuQL2nF5tZKth4il*_iCsaMJdePQEcy;Z((=515&Tb}!7V z%xl~l!5yZxcF+zc%|p3=WZd_8H;#-~r|S_Dqe41nMI&UEsU!HNF&?*0())yZ+*EP& zbVZ{+{!^MT)0AQ2DmvqrRUK%8-$O-Kb{A(SiO%4uNj$R01MP_jqKIu)X+R$lig!4C zK|lXyt%Me2(B_`qw+1!8(dk6Hv=p~I?U@5+EbG5SYHyHVmCupc1r3gmkxNN=c`*2c za$Lq-P5=%$3Ky@_8FAbFPw#6j92{6c^3Z(%JhjxBvHTr%GQa+iyI|ty24P|_;abRi z(%3Q7m$Rsay9JFyy0jII%N@640rowF(Hz(njSnB_27CJCZ(~zCUQ0*q*T*yEQqnpm zg`FavPNx*GvV@Y;A0(#Z<(98rxubm78o#ys`D}oidNMNRc=wJmfymr^ z9TI!nhn}Et&SsfDG~HI2$ih5_jT|9KRn;6G`JFUftVxeKjFJ0j?ssESmUb&Xf^l?` zC~OnFi{a>EZ#P75O5m0#XJ#fQ zIco5R>t>k*y}g6$*E`_l^!-|_4f(E5F`q$aD4~D&xvljEXr@pnC7d5uZmw!0aTF*J zEy$dBfBAxlZabA*>><98oEAbSo-*&O$NWe(B5dqfyL6+Q^tI;bd zxgx;LS!)WtQ0WW(3qhM1H*XcadI~e)?0{N+fhPP3?*ODouGxBC=h!Ul`LGIqH_|pS zJPs&=rREg(s7{@xVpm&Q98xC7!`d~b?i{Wp&aek_vVY6cSReq zPaLgif7WFDOws&Oa!gAxh~Nc}8wQZW&Pk3|Hx_%JW)G_4NaeJT&92I=%r=!Od z*XjQ)&sQJiALOxlHNRG_4Ab?rU#2OVGjac^R~z^60w0DbnWAZXDZ~7zF~X4%SG6qe zWr65!y4uA`e6U{^hO7XZ1QgNoCPNN~Qcno&)Voxcac~p2UIfiAWHcVo=s(yoJsmp# z(D(3CZ{Gfl_NAUhEHr8X1(IkB!pzlIMof5~aEUH@ccE?@W}|y^ z>f7z)b;|*!FIu#dI@azAGh!~@WlK^L^v%Iaib7>EDL8kwnf zkPl@49)p*wtbiT2ud#ew`XS|KcpB&eJcDM}lu|zybUj|y@M{SXU0#dssuXx;~ZrBw@5o696m%wo2%~fZtT?GO+w1bDyD$y zYplAjDhWdBtSPm?Jn?RsOnWmf%MIZsY?P4l;-^Yc?4}1)c*HHA^^;aOa%?#MwCM3yp#{i}z%}agE^+vA?%5a9hKnxv{N>p_|a5K=Dj6 zdA`_AVVJ6FXQ>ug}LdQK*upKlmW%Qj|cFE#BG&I~%#Ft&us027T91RVwVg57=K)6vc zK96BIAwj6iwwJu$FRXl=Xl7>YF7BF834c=T${y|7?LR@;I^GK7R1uX28 z?uAPDuN4O5fKZ4usMfaDCYuHSv=oUchpH_#dmdyF=2?+o?KThc_5HT#9E@Ga3rL%^ zp-{FNMNWBqp1o+n5}M&Y32uT-vQOpf^%B{eT$;r`cO#0$KH@M0-@GEG@V9vOD34Fb z+;0KOUlS}Mg$Ei9QTr92%L4Z)!wKstF7NMd_eo^faarw2(=kHd+&Z3BUkGPKDx?@D1c<`-B zMLTJNWj;J=N@l~{!0X*H(@34sbFc`>ezng8WAk0wfJN85kk(#i+SQkt9wtGPv{i>NKH2I^_1nkPm64S!M}kB3t9q-Hs+gJlWWoecyqRVgA~6oKFz(no2^J>f(|y1} zV-kn~GjBKS38BHjD(6*8M+e6r^_xH1F!nf1(5sA-ep0{@MpeCa5(CrX8j=U{t(dYb zhoT|(*R-PcN8Dpyu&Y}QJA(YSy|+{o4;))AW<%owKzzMWZzqLOJ2eYm$g1)7;Rn=b zW5YK5u4d_erY#QP=P}-jNLtW@znOPXVBft{CD6}=1kZTlW8WS^pKVeeU{Zd8 zCqB{h9qOrhmtanMF5W>*au6JtKpI2qz!+o^${joBDph2Tt5|4M7@mZvg=U4`AgsP} zH1CPENgUew@lzuK-hki{pLMp=0qKcNOn877KF!2lzA^4Q83RrB{>K%Z6|V3j`=xFl zDK9cMNWz|}CHrnGM@Y7By@ZN+#r~R?yUPg!4TiV%_MV3!evSs^>5vG{D5rA&+aK0IC{GMoj|%kmlj9;7V))|*kl+RY-bcp>s6@KP zL|fL5@kGCG<8yoe9nxaPh+cMtp9}!Ow*X;;Z~#XI9Tp_c247u_{+&emJ#%npF+>k% zFdiY2h3C5zX|)ytc|sQL*R$1Hi%M#d|YpTcq&8{ zw1olc1>qqcU?|R97P<#qCTne7w`e zX0c8$*iqcWdbLI;`s;y#13e}L0x-PXd@K+DY|}0ZN7`A!Q!+IC5M%OPViKjOl!{LE z)M4WHo~E{!2T!Cv&D24lCVdnhhFN@|hH`Qg&M3)S`xE5jKC+_9N8Qp^xSp%*AoyMQ zEhv>1Fc&y7x_~Wa9zg_zpWov~lLjT_!&ki)@kS}HbCZRjKSaGU(RXQ|>W<)#k#KdvNe7oR3NBs&;0r8*c> zsmDL}JfRnO*=CMQy2M$IWZ^#7-=hO2y0Ye1KQ>h1Mn8a#4Se(7e4awMbs3CAKEXH> zOrE_x4hXP+K4%7qWcxe`0S~s=Fnn0{4e8&k``xI>1>$y-26RPdz+vW0_p?lvCymFw z`5b)uJTd10==TRhR|5UEjSfZ%{jF7?Nf7{fDXg>AMlYxBfwbqrZA-7#299kF$nQ&YqpAkoh}e z1tSKXNRx$Dv#4EAc{$_tR?pjy?5yU!mP|Y|BfPH6l^# zu5_DRF-@cj8;gSj>zXlg5dFtoROCehH`^2!3vb7~6R+rLQVi;b(`8C8^yr*$$+M+3 zwP9oOsP9r+vFZ=6RL?@AIv9myD)~Fm!yFI=SD^@~q8=Sac6QWHbm23(1aV<)Ew1^h z?^CuGYO@B25o)EjjA;TVrZ}r{TbPqsx)%IZu;k{;Fh%Z7ZR@#VMBMub>tY6Idhn3& znmpYO$pAAM?wNsXxcwzDt#L?*NQv7$oE?3SH| zTHAK3EmC`=wY0K|q@qNCIs1P77MG|KS^_B6P+W^MF)?jf8G7ztWU!usQS%=3j70@S z8i2{Nt~Sd)uU|&ca6>$OghC1#9wbokLHPqFKUF>9kuK2rx7iqi#LSf@+EtPWUJS?f zXt(D@M|9~AyMAA05~_AmeI z)W{LL(~EejMcF29CLonOxnB|@yj?m6IUh6c4I3T2vYZ>@c>l=(iI2SXMdc5p<_E69|*f_)!4J71!eJFyHX>^Ui^jR(pCf z1y-cooZQc5q{z&TaOfJU>E7IWxvLnvMNrLoy3d_c7DH}q6891U_CLwT`^}yJ1z&4*oWyE$&qk@{bEdl3|A|O9KXzu77)L9pZ)YAF@|&t zevUn0LpXrAQ6?+BJ6qBd^!wdAbo~K2XA9>2JJoHEP6redAsE~sY>_VhH`MRVjh<+!S5u;KB_)cglF@7UJ2Q-3xGF`O+|LnHIs+O~FO)!W18a7LvP_MdaQp^q8_=e$J zdxWM??l)6K^aJK#UdqgtxvLjT1dLW?a%`vT0>F<4OiF1+A^`=~D$=CR(hw)JlZseI zWun9UZw3wG`z}#O^jcqBPuJ;Q-~c}LP`u)W^KUPi1zKEF~n_U3dDrl6(EM0l#=C=6Tq-qK=Okyl4IJ? z`>jm#{I9AwHu?A5n?cFoXjc(SP-q0(^lN^Y1dT+nYZ#{ur7BXdf_PWZ9Q^^oF8--~(?m^$ z*ey%VG9}psfcfZYs&n(-z=7)Y{N^l*%QcK3zB&-;mM?8wT9`@xgfyR>zuLY@SWIOy z8S?qfI}!Y!S5+i@!(Ng)kVLVnG(?|AUGD7^Y>92wJEWF~$Ctpj>sE;z9<82R%^#J1 z_FKAy?MlY@X+FJ8#77!~m&c@MK1SN?{rPckP!Q#q03qDQU>G7zc6DO9usP(8K&cUh>Y{6UH8ozr-@ty?8O*-5e4jB)eyI;i*?>YOVyn&H&dZKjK zni+#(W^66hriCyLk+2Z1T?3bgtU`}p2Xze9-^AKp;qIrb%)$Z3d_tZEf_c2r?5!2 z5AVpE*{Fb)4aqWzNxv-+Q)#3Plh(kA(yU20j7N0!YpgfXoJ&98H^PU$^K3diL6rwV z+^I;L?rw%aD1Qiy-<;JV;Bk#T%Lt!Z!F94Q?6m73!{K#)07&Z~Q_JUv&ucDQp3mh& z-V1-_5)Osp9sv)+FEeb4nVY2ZKpN>I2!i{|Hj&viT_?+}`+@??37o0@{&bkbM3y3G z?)fgGuJm|+VaxY~qG2X^eUOmHD1^{J_%le>DN<2^!S$S5A|8sIL(Ij1C2~IG9FXso z6~+|c=54itjbS~@R>1&Wi9l=9O^Ct|D4X+R#l4Qvun zCQPQ{;b9@Q#arCbbvC3?C1B$Rc3h0^_wC7{o>34J1U~pk)~D=^rAOc*OO+^Pi`jon zHtp7@o9BN^*5X+;j)~r1=k&uqDr!mZvyaxYr{SPsk9u7YQ%{}WTVTR{qJ#+hEhiO2 z?i3{LK@%O-|FntqboI=m9&3?I)b$E!WygJwm9dP~-9(lR9p2dG3%Mn3SZkz5nvc`3 z(nKX#M1h@BGp5z9w1#|#y6^vjJwDT(&H@-mmwfc}zYB(ei||K-4}I=tBPyxlx~wVr z6?+>Tlo{02irwq1vk`76FyQ}guUdOB8QYY6+JsR8n|<_M<5ysIOXUQj`I;__Gr~5+|s#O%$a(;*4muq?TXJ*YWCi{ssM zy)EiP!99q{wa;Yo{m@HljMwDP7MR`Lj%S*b;4Ro@~uSTP${UY^+n0%$Ab#CQ@o+mLufzfO| zEQd1cNm;*j!OyzvIPpwQ^r@ToDELTui3Xl;3^MaNGcY<@$}c1oPO%e3ymaRMGm7I zvf7xPqljd{VUNK8m;mDV+TZEh`MGjn0d8OGm}Pu0*X%L;@MR9o2xD1!9L!%ULbS7^ zgV-m35bboy5%-;&aSzcH{UDEi>xgU#j%h0|xBJ+aIyecNB%m@|zC-#tdM^?tYG zm{7B7t7}k6+$P+r7ea2YOwv;pntjPcKTA9H4p2Mm_tw{R{``|Z{JLI2-o6pyfIuNu zeF8F%U!{G!Sypb+*6dO+8Ac?Hjys5~Q1A@#R*ah@8RwkyE+smN+Tx-4H&#Znriu2m zY;)xnPu_$aGONX0KdW|Y=-r8#eDRe(aE(AiO^ZM)$rTv2SMi}huVt8~qW}@Me);3O z0hF)TXMe>5ME(;Wh3dJ<K(KRA%+a(!!-cey z$MC%JU$=U(;Xld1@QItOx-KN;c^tNIb731>Twl^HNr~E|aB*={@_>JEybTQbr5Z5u3mw%=S-{}vjZB>n2r{e{Ta^@F zA(t-<)4C3XEKzMiQwgi)owQrUuc`-Q^ zm;i{Nc=z7_d>MMHQIOZRrgSwK9i$ulb<>!t6MaGjcc_K;b-j&WK!Rdyqju+ zgy*LR(v-`+e;2zgct72&+=K1XUY3v@=RlHKIkTzp?*EUuK}U^ z(exMhXR}3JK1)J^MP+aIS1!Va(CbshoR@0>GtBfm8j7kH6nKHthXT!!>iQO6m~nb_G2lg5-6mLlAKS*S6}fr8I{4rG(~JZm~2 zSSUyu;w|dvI2H@TDJ(2iTYuUZ;}lpE7^Ob^^!z-tzjw5yODXr&!CKr_htE=^fUCOM z-957jhogyKV-?4UxU;>YwN#X_q*R3D12YKG!8VruM-X<`5B4*jR`kH0xijdeT^C&( z!lerXgxBMGn>>?-=H@@0aBHEX;rLUpfd#n6JTl%})jNs9Fev82{`zb#ebjMOu)`3$*q^1gZt4 zE%H>$fR@XO#C0L9hZBJBT_928k(30FJ(jqW`Uw1R87dcrh9q}`lM8s`+N|CLS^RPH zsC!py-%*J`>)*>0;GVjc3S0 z{^rY5i(g`Sbk7tI62tOO0101j@@8R`2H^VKYoZV-$|g(qG>u@-Fmv9*!^1>~z)LdY zqG?#`Qg88`-`ymAgrNc_v-eU`wlKRSSw?`Mq9m~@CCam4+T3B$^=T=w+5ujcF>g($q4C|L^0LHjQz=-;Y*9wf^ z*;_|vB0rj}p9#o-!(-oG1)e6Q*8Lbdn6z3Vu}gI&^Wo7`5(yv@hOa&`)BchAnij=|-)Y}<#Rl5dI&~k+A)wr)W`M~21DgD^d`Bl4U#GoCnIaJN7hfunY z6OQgO#uF~P-0W4k`u*J*WN8=6Wm}a!N?C1R??gZ=CT6|pb{{`WB=zH+|6>n0f>Zz8rn)R$f_%-V`&8k5YQ7BG zdzKY@M8!}>T{Mb^-AHX(;|D6Njw;70^M8rKXHNBfG^sDJ=TZSm)!9(j#X&CBa2f1Z z*Zt}<+Gd`}2ychSki#z5R*-vGgn03~{$cTskrKRFL`yan#^N>y<4=_VHWTg>RlzVz zUOTy_&fWS2s1rPze&mVurKOo@{o<-|v3m5oAz(OGuf2<5%#t9OBx#?+ld3|CZETzi zvUN>D);8XSH6u|~{^^4_l>v)wqQpw*wx-F(fR$6}>87>ofhN0)#k%s5Lr^~dkJsjN z^amn~2__P*fM;(XGf+qy;jjm(TtotGY5e}K3tzo#FVA>`VgoT|NQ?);I0UsjTDSW; z=jaY8#1{_2{B|!aZk~cPqWso-ucs^RHO}r1e^?LG50DWnt`@D52#6@%`GhF4 z@es4|aj{&569a;4D*33XM|WvQ$)es;daAQ}K~qr12*9cYOhGb^rg4*^$_taTO9`xgNvMMH z)vxwvy~xw8QhL_)Z+lNx(vnm`vrz#*Cg z!8&|CmI_A?3-mmc31%=9EN8W3g@O#t`4w(CH^d|vGyU8Kz z88!6Aib}o=Gs~@Aq}iUftIOo#2n;u+~md+rl1&Y8i5%Nodb_`Nd5n z;_Q2M6=z9LK8-<&>vlRBv24arSWq|}#Kcc|8s}Ldr`6~W{mDnGYdyh;ctQ$|P;_3` z^8pXkwZ6}&Lvgny{uz!zv*{WIQXnLx#82=JCWe?DB_OfZa>i5kBPY*67hc}Cu_s92 z!|ThV96K240EqY1VK=Z$ffheQJ(vnRg1Y$As{g3fidOI0yYyK`*FAJ?CsCH>qg5DUYp9U`pQGMhe2R1=wfPlCN1QMc?dV;xOahY!pfOz&8nA@@?2NP?+g3v zOTXKOw|y+elTH4J1CyKa*hC;}wHu+LEHC)P%-49RSsg1Uk>WU_u@^>8&xISQlXf24 z^j)Vm#4*6_s>wtMdSfugqe;-&dOjd8js)im6t|6G1?IwvL1u1D^6SF7YwU>)4fGR&^#FYtHv)RPmb_zWPsIjEs8-ZvI}Uqh1wjdM#NA zuCKZX7bTp*fA^9e}!vqQ0Gtt)AP899d(_ZQw->tL6` zNbx^gSX>&6&0uo_alPc^lxo~;DxrGeNy0_Dc*;87>4Ca0K^T_EqLa)htoI7&*pdKs z4P`ksLKK85M8r!IRLjuY181X|rml?jZ!vTp^xd5_wz_fy^$EX`4w$XQE6Gj`uK_Hh zr~7YP@T92Bgcx85@S(1MRfU*1ALnNxqaYv5-S^m)WY#&mAdCgF_SptFUa(WnOMr%p zx<>`@=X9`jR9YTMq;g^4p?#;D#q_Z)NkiU84~hW{&VQ)J0G!>w79P)q2SJMyT9Lt@2765v zib<(p?QX$c4IrcQ%c8emqeP`k(eenW`&tKlcT)oSUT<9UF&wrG)Q~>*jgrtZZZ;yc z8oXWRAMy$Cn~n|-4wqgu+Rup;Ts3rzm0t3)`Un@W_ZK1e2@}u6U)IsoNdrgQGkJm} zzR}2784zJ`!&RlWeZGpeg+1d35Ow%!w}HuiKKb}gS7PJ#acI))<(3;ehv zq^~c~d>(c$j7JVTVk6+Db9b9cPc&?(P~AAV6@J1P>709fn}R2_7Iw@Zj!)Ggxr9 z!5sz|aLE*ig z9_F1dT0M??aY?*E_>0>@e*)VQu^oskB%UMnIDGZVctDsLyK!?(OJ4b_fIy!?z9XPH zdI~6mUr$aWBph`=1=FEgW*OC(x9>PH|1!58_jBPiqd5B8jEOnOvdJCocEO^PF9`lE z-LZ?09HD3DR*;NR$&)#Ela35b0SbGxnv z-c`ZYdn7*j(=(l))*$FbwsVkKf)AiEN|k^jND|wx4`yYWN@sc=mt2V2WfV9h`wCpX zSVZ(qs1OvGlhAvAy3(Ba>$AV{ddKx9jBBlFcDoSI|6>5wx*Gx%8+1F1GaoFTCbKMb z|E(aDARIN9(`SNZwK?rZPX3-6gMjT#eQ**>!mXT-fMs^ZEoo_8dlw1h*r`xamaeKz z*w2vDnu6fSxXxY_-PhE-tXKqxEqJ%iyAO<^O*#soL;CYqTylPB96uDC3 zG)LtSq>^?OJ`2XEb9Em;750qU^JK-}>M%Fz_Esg4RMG6F`y`%^g&(^MQS1V|Y78qP zbX??`TvU^|%3EGR*kS{EAXW=x;wkus!KCDI&(fdZ;#kmpLn#g#>|kJSLprLo$RJ#? z@AF6=UPceyOin1ge?0;o$BiK`Lu2qlkwLvoG~{tX8O@RbOQ!@AWRReGl<~cwogVW7 zadXCe#(KaX1o)Fqpa9I6p`I^B7PKm}Xe3{DbuiVg(iaXGU%A>_-HWT9;W>qWpZq8N zhRQVz48D*ddr{fo6ZUOx=w*m{gpk}~+q5gY5 z1*EOjt^MAO%vB}u5JlXSG&t_(Ha>-}K0H`{vz#1g>1e#JndF=`6Bl^eb<~D80J5B` zox{_qCDVZ6%aJc4IAQMS{UniVJ9ELA_G5JX`6XU5A}CpwDK>94HJ#QHjV5KZIGcnbxIk2=ZM`}V`ahvF00M!cs(`zMVHH*T@9SM= zK6eR$@50&O$|^zg7P5BZW2o&c$Arj0U;V zW5WwIEZ_9}B`eQ7>3Aa2_w?tvM0-n$Wi4Dzigzsvh+OyoxDfoF+0iEaW!}fcs6V^H z;ca4jpz&z15DW#OueO>=1^di1seS%Nk2jl^7DqyF|M#jK>yBIn{bwP{Y$xz=$R~oa zaP%54d?jOm1N{_XD?FinkwLESixG{fhvA^uJ8~p`m85V(5pF$X zCibHx56VR@80K+wy^K@lu+8}=j{8-=E*zL*4dNs}5^xG>&7E;^Y#RHFR z48%@XPdjRS7jQZbQw@%IqrpAK8ZxyBCP~*1GlbKqGh=5X@YBHf`1ZpD$M4!Y30}9K zaqTkET{L8~#hu9v%*^bG?c3p5?{L7``FG^+?MtRG@+C@f_~*;gXV0m89ZX|||8dpu z*>3XI2Qsi&$HKe$-^Ft7^tfDavs|r4S0&~%2b!wrWwEjkGElD}XmWDCmqAYX+h(G_ z)5)D7)@($Qwm(`Y|JCJ^##7ztzBZ`)jS!bEpf`SLR##KiYfpI^zA+RkbT*Dn$h$!q zKjV()P!=uP^nE?2cOF?TqP2C2RMyj7+H7!mC;{h%<=?v&)aA6K1txtn&lLC+Nf91M zUO6RZChAtrsLEJkiX@Y6ZA8!6Q$o&4sDl7Z<|J78_r_n(H^1T%sy$d6Bd?WzTiXNB?*eTz{Nj)Fjsb+(TS0_+`45!g?vy5%lfQlE*Nh(F_9rbDbICi@y1Y&@ zX4`O{7dT3>0#0U6y=1~dQo8bf$wPLsP^CS2>@P>OteNTg8QBzeov2457l6^JvyFJ$ z-`0^%xJ#0oi7T>AyzO@(v(y^J*4+ctyLQJD1WnSPP->Mmio7I7`MOl|EPaJ<@aK!b zYnLU!;yrc6R+aRKp5Kd;B4i!oQtEr!vm{iF$A8ch+Kq zjclXI@!ORpZ3$>R6h3k00hxmzc!lp($XrllItLdBgH$BkT~EP?{X%zc|BCXJZwrF)9fs6w;CjZ zHZC%&;f#&AMUX$wNn|#!XuJ{;bU~yT6@3|=d||WhFXBW)_x;5~B{ussVkGyB_!oAX zo-L?fkU-jL|HSOK{EwKts`H;Sg>|`~Wz5_?%a-(EMhQnmfZ^ z&VUP5x$vmSORbP#W<6TYLjULK#Z^hk;@@6y;QPN`$%-gD!zygX%*(|gaZD+?@Ek+N z^sMsGHr7E%dtxOyvJ#wcP4~mmAYCVsB5>zu{_tF5!a9q^1 zwI%fy$O}vUni24Luen&1vi-qG@!U3LhBfa%y!|x&EjL#McY989z&D?|#;S{)Plh8b z{N)59!t;P{8%Xm1+hzE#^RmM=4Cqoyb<-*@#O(SC1Rag9PFItB>KYNix$vQx4xHYzo? zPb!dAlVKP$S_orpFP;?8;$k4SX8MQAz)6wO^FO%(JK_lE@Ow6?CdR|5(lb&(ZtOF%(C{ ze~4fMPu9Jqw;4L%sPmZSY&q^c9PF=&xmOgR^-RN1QTEI$M^Zmn^F%lH+!Drkd6k6j z0UW*4Qve92{)O zfA8!6`@u$LH0fJ_16QHBsha*@jr$+(|IR4<=Vkd{r#|n0X~}=I=lj16WdCa2f4$TF zZ&&Dl^rrCt^;_uwTeJV^0!Hb7YU}>T*$DZ+|31r;m5q%>NGdmuBD#n`|Hp;Xe|EBY z{@=s1L%{;zAabA6RjC7>1&$@$@)lu)X~`3SaCbR(Dm+t*B&5gyVpt_WqOtFH*_*Yt zeK*9#PNQ)5JPP=kN|zXVZI7^Zr#gDk%KRZm4ACX0+cj6+bGehHD$}?8mN)DNqF+d) zl%x{Ap0wRh`cCDrc~dpv0kNgLCF(#B0EoDM{yN?*@Z91|wQ@1|Sa&)|E1KKK#5COA z4*fBpY-?2Q;R7pEx1Djm&y{7Q)qP!B22j#MQHl5gqBu3S7FH=PFATump zthHONrwXdrSY)h#g}dgNwkA?z^mSo;%D^mER#qG5+yEz1TRmjPxGiC92+s#wWc z=^g+9ND%$ilLcDDU)^r)IUtzxU4)q=>N!+Ygrt)Z<4j&U!1{IZoDIaHzolpR&}Hw| zq%YPO!})e8MuqT%0eL$|)$6p>L3<|G8Ri8Nz>lr$OGKPD5sqMa{O7uig}?AcER}dn zme+W2^;M@+XP()!bc^{xihF?4dq4I^-asn%aGfuD@8;fTsAM;- z<*GY7Y4I5(O*I`!eNC5qIALSm5ts?XFL+M0&+QZ&#NhTFl6ASNcR$HmzAB zW0}YN+J=TEqX-pfUB(xx9Wn3D_|Pm*4`L7Zibkp|5CwvgJB8%nSb6n)(1gxhYLOpM z3Sl`Q5`|j|gn_PKO-%Fh-abATjDS@iMqchYYx*9a7w?~tfB7|A(Nj_*LPV`3;_W@t zZfUJKP7O%-SgL4pi;TarwBKD}vgVlfc{Md_0fM@CA?wQSGjUYFB%l9~B9ib!#y6f~ zQ=*M4mV#UF#-nRxBvc$ze6WA$2dBrna--Fl3M(5|F#tnJC~l2xJK5f5&TnolBNuso zQE3V3MyAX6v|Gw)QE&&KKdd?bXwLH3fK?8d^U1Dx)g>T{&G=gUQW1cNrXb$FmH3J! zuepD#ouFjTKr2BA(;^=EV zs81ESCHseQ>ZO~b#KFr__MoEAg_GZ~58oX2_tWGRoSKzOTUi)q9j3=yZa^J6k+&-S z=^-Lt)gDY+0rIlI7(}_*X|C}8yg}iEbIRNw*FWURKakblUcY@dS*w?e&6SFT8!okn zf1hLIZySfWT51?u$GbZ840OSXDokV`9gm{k-aZpkrvbn2ohuz@zMtA8TWAmzj^I7_WyufpB`8$YbB zJ!4PRn;!91^mXxf)uSFUv$u+^4}QPR5LbKxoDMb=054R+`N9U*dP%bBM`oOTJc#3* zD6k*|GX8t1$U;`qZ<4m#&&fvB(o=qSapRz(WErm!IqNuoHshty3Dt`DZNMKh;=5Ty~0z%|lD*@QBUvW-i%ok4{|@&~%e4u3Q*9p}3J zlhZTa<9Ngo&i-Kt)D^Xn zq8KcbCZc%b)3|!l-HzAnX1t=h)o$%@zkf*E5&xVbPQnbL?c&X?udV!}9?GfgD zZDH*FX~>1XJQICv4YE^RRg;xP%Be&@DpsN2@*jJqU)G;KXsL7AtrcOrA5Of@w>@iD zrfjhrQIvc(I#~IIRu~xAL8VqLRfaSPSn>lrR>5#DNab18Y z;iI7!omx+(W!466HyJtpDlVci_1Cwh_1*8i%44ywm%GQZeT?bqeHMMN`V4;P{Ry=)Z{J44fiFAT? zuPkLLZe*gYn-_H`=|>pF0=?=5z0%5X56w6(MvXOo(6^c%9F=78 zr^p@P+uGSMw+(e)YB-ZnO_uZ$=aB(-cKhFJEs1KDvBn~+Fg`Tw;o5|{tt5|paxiH6 zD)QK3Min3bSXv_ttlNJ**1l zP62{?W+5(htlYHPuK1Z^a~)LMn1RmmT&1<=r|1~A+tm?pZ1KLX2@@okr>N~_(wDbm z)q7>^YOFlhc6!|LpU^>#i&*lkBY;r}yg)n_t=0wq0@!nIy~%7ldi7D_B)E-dZMO$X zr^9!aZHg-Ehs8!Rx@uXnWBwUK*X_^O(1-UGMNFr@-{IcWBTy)(u{^aOoMDCg8lz?7 z&+mj)eG#VpP$$V^u7Dri5O>CSrtCdn0V>`=Rx5rVtFD%xN!603cxKNbC%Xq<3-~D~ zuGDBxDTBM>K@6xI^mc=CcgJ_nU2)?j#`e1nPYTO8vn}3Iw>rW&eV$f?Y%bEz{o1E* z{UnQF9Z$00=#|Ku>9aDfg3oOyw?|S=8hliNw4|}a#3r;z}qk7TAHt7{srLXqTm5!N!2Y0%Tkp=a7Zz^Cb?sq;)6e2HuN3$M z|36z?YUtDW8onH0+MSABF0Rbr53j1V>szTrh8L<=ZZ@wIMvHjuRze~4zCrlS?dEVD zpNm-Cy&Q5UTHk=<%iNB%>vdOLaaKz>6JN(q(#wE?UI}%v1g!k`x;>!pHxs0o5Df_ zZA+i5zXxxYbnQVjX-;YUYK)uCuV5kC}IZ-N|x}9ag2x#$7h9%l5?~Zmhk{X3rpx9)s67 z&BCby3vH2X930U4BHYv0-@LIuNK1+nk=b`;RB8{0o|Awq$$dq#aA#BIYx#Fvx(2ht z=hSz1L2|+Yk-e<5w|`go+R$A6Y`uTTfA&4==(_jUREds{J?z&D-P#b{urV|&dPyOa zyB2*@weErg*Wr>xTRQAp4sS=iN4n3d73oah%3^>0(l5-vX z^o5mGO~XeK6=tfta4M}gAQ4^=Uq792<^F^P*75ZfJ9)=hmpZU6H>u>MI%$A%Wzn&_ zyliwLRXG(|UPa)VQcw`uf7g`Wi8dDt6Lra?Lu$SF_={rBO^R)sV)ABwK*S}J|N7#O zJlImLR}uqGu-saH#J(SzbK)1@Y-%1K3ee7?kGR!5v zS<*W+dv-XWH%TPxkX&!!@yxH;H8930$AtCp#<5A#sS@h7V?8KT{V(j4^YN}`96@&}m37?6gh>9?+hELpm*_H!H zza;V}!oWOORy6<6yqcGk2V;JsLo?&fS&e+Ghf{r8RYG5;73sVv& z=BeZ_fKiZ9`Gk0O@s2S{rZXlML0GUa<+r0L=iJsuRh5>)IxCg;s)^X5C>dCSj1J2k zvAo`{I4+Cf*w&!kkcrrgC}mrFYiq9K7h6M&M6S_#A5%O&ZONFq21+)*UmOcjWgz!Z z#3o}^L?7S#7?lC>+k#gJ9NEPlkjK#*{B9Io`6?3&R-@hf_^#Vi4ODG!&f{C=*%PwDa^*{LwmoE)2g;~Y+s*2r!@-e(%U2NC!yDC4=V-F2F2;MOgTlc! zYcv6~=Q%0lb5SIc9)r$2s6VChR?Zw`!$N{FAg^*rmpjADbidcuCV>uj{Hl_gv3EHP zW$E?xLX)EFFfs2&gvvj4^Jrli+=^3>rB?5yB&S-uZI7|m1&L{6>^p00*iF`qiB$E(=Do%Vd zV377Cn~vXZ^qjD`Ph<%RYVwb+vO=FCM3>Rx zs6JaZ+KvZnz~Y#m87^1%y5+nnu=6N=J*Okr0u_|DEcPCurUdkoIgx>#H;IL$*gMwl zo1jVYrvV@}8K9yRPq_taXAPkM6ONWS^LNi9$zUt`#Mt7cKHv2uiKBj+2Dmmuv1{=i zx7&fH8v$8zxX)WBtULVW-PWhRCu^98lU7Q#icr~w=pkbdVV-? zVV2=}0F}$vSJ*#qk~s!@#d)KQbI^+G^ai6t?`~I~3&kp%HDabo)@bjyNPD~@6S z9`Pn~{kA?C@VPY!%bH;Uq%OAT2j9JYA=6(7Qc|Q&h+!{<^mjSt+Z@C$mxf`}1~nyRkQaJ|8OjZ0}hA zssP7x8=pp0WbQu!pgJg(Pu5A>jiNV49K;s#6PZz_Z?t=_z)f5v_$1(-2Vc#{t z>`3GmV;9)=g{nNcU3XY?OFl%6o}F!`vyKExaS1Ss4lpbL4(GaX*!&Srz|==8T=4KP zaGH1#a26IIuA805V6QtxW%4}s_#kFC1S5OgnNzsjJJ&T$7GTU`X7l#H82Hm)7ZDEk z%nb|&;|joJa=4t?#g*{BRPP=ylxAMdF_{GF&l*oN8X35fZ~uHI9y#3u@QKbHVP^dH z=hRmR&#MUnYH2tc+cwZH`}F#{lsPLdsSCm?%J*yb;_uRxtVe$^sF|jnEuMUIe>7>P z$%`L1ZT>iGuD1lHh);rltEZmza8|y$7CD|lhH?o9m|^Q_>d4--p+?fowb~20EY~v7 zizNvj&9l;Z*?O0jzpd^#oUTx+h)YDUFIH`B&|rrMDJ)yp1PtU91jd{EaSEP@u|_zw z6t?M}#Dw6DuSABc2)h6vHp4PdhsOw`DA;}upg5k9_$yP8@|emlJCc(r%E56;{!oXw za#Lt0YH9VG&kRle$f#A8Y&(@El{+(%^D?P%X$PGP&sF$(Mp>R>YZd)v&D$bXxU`u9V=pUHd1_a=GdOX}HB`a1y_y?{(jZol&H$_)4Gad2oS}Re*e}`STnr zb2|8}W%2%rDoTQp;ZOB0I13GJNjfl)Y^pWaDgarrwVM_Tr_=eB5_u0BCh6<-n9zW4 z^_aVqSK8Il1MHz$WqHNvN6j%{v_cFmo57d*w@7C5^#M2FuR zc8{3#dbzg!2ZN~mORS-s#i!Wufl`oMj)W5erI>`d>LP>wLs8);3->|bO+p_UWsqx_~KL~0gY}^&>ztHk`iVE)<%3;c=hSa2H-H`@J7dCtk zhM%d}?OB5ASHRgzR_YK^W99no2^W2-u_dw)sL?Z1lu8s z|8}3$q9}%4jlL(cMP9($phv}ZKs8@p0ZQxDTO;p=qfS;0Bqi$SIjAJ*u{)g{(}Q24 zBZ)02N0&&U@69heE!1i~Nq*Twk1iJLJ6j_fv!*}RAsPqkls={oMU)LW#K_!#G-AU- zf4j@f2g;9-LF-|Q+2@YwR@R_oa1aik?1_$j12~wLt(JE$jYhz1GqkE34cAz(yjny@ zZoBml2dgznByDDRCZlx6l7i!1HaJ_=i1O3lgUr5^@z9yb-DY=MkRI>CBbBenIWrj* zsYwd|0aeAJOSrb=(C#6V_~CIhx~-7$oOOYW3<)K%Xm0PUz>S*7kKj_>w=>8=%B=xV z9UdCm5L{G@q^2ZUsWG@Q7TwS8xtYDZpqucTp0U5-{TES01(JO~sXs$DJE|LX5GfT~ zP)_K%$u@Jgo}|Tt%&{U|>y)G~GpbbkCDO@g`HD?1>_Y? zBt7WrFdcI%Ko6^T9gY;~4Lg_KE9PQ_AqHHoo7A9sEk3Jxn@66q~G8nYHSTmFt znNh^gMZL9s0Gjg|?t{fI{+pz5Z9tG=h7LH!S)Iifmw&RmFcaVM@Sj}#o z{NC}{M*})EhA7rzFEySAHfCr_XT%OT;|y6%Zbg(9wJc?r!Fta5;$^&UDl>!??92+* zOr)+cd@iSPo2e_U=&zG8a{{O*m*M&|loB>1V-M@D-q`MixdE52Mf)O*K^WYFPuy_g zsGQEngTwt4rQF0C%*Ug8+_j%Vl6Sf2QJ(1vnh3}un!mqfHqN|4eBOjRy)FDZ4U-xT zIZ(Zze9JEVaF}A=C`q^Fe-Opr0^J{Ai3?BRCptVN zW3xj7UsJC=huym!(;nmEU+xC3sGs`ZmCB!5v~dfMZ!M}*`!RwY+dKiyxZ9;1Y|@&q zqd+Lf&x9_(#h8Q*yyhq1F9p|)4*G&kHKOQdeSl)Q&lJmVDzhQ%nEc*k|X9U0r7$E>f`D?D|?pk|}; zA9*M?zrS36LDa@W-NP;Qm=HKz@37KdrXt@dfLAtq_VA%A1k49}jy`ERVI@U-aC5Ms2GVGv`d?{a66oZ(XyVl4=g@ zJ~Ji98xGu+i$W+hhC~r zU6oZPNk%~mZaBuf$NFQ5{H_rp+1cB7!h^2!WAV#MK(V$*2X>VOOSj#tr!{5NaN%h@b|^wfcMJZDNFR^y>i1QHo}e~jKuHQt3+gs&R&sDhc( z%A+Xqm*$qr?mR2kqf?=bBE7Ig2L;{v3S1Cem;|+7M@=^-%XBHbP!kGjkV=- z6>R{-{|aHw{Fq^&<*^a2@8~#(C3x~vy>b$<*z`L)ujO@o=XBbJ1p8bOCJ`nl@z`nQ zX)-WqQn;rMn_FicCXyi+-n1bv-7E3UV=s?-H$6TsHCWFOIiWY9ao3TN`!Kmm)Y}MR zM5RwRm+iExsl^q+GOAwMHfDMY{Tg*}MM>6Ym-ayPg33vU%WU`|R|TTiW$Qigx4|b* zl!>Elq5CHNOZs6*zNp{a0#U8lhuihx2wVGU#`{fx8%!#8jhWu$UH6P+*LN?Iic zCB1X7Kq5a?i@pYt$j%g>n~;cP`U)l4P#&UN7;+O)d_rc8`Dk2_&yJt(MP;TJib$X+ zn3Ys79c<0GO;^(V`1}$y1;huEtP5(J-=N&1411bA1*h}dZqFM`Gv(rP3x@Q%Ogdb} zCAd9#9j|#x(co}%j~3)se5PjwhrZRpciFSnRZH*LJR*M8Zo`ph+1Bne^@&%A#7wPQ z8QVIQFsFc<3iaIUc9>p0iWzTyxf6UTPu}h9yFN%uw3wvu(cxt4os-mK{-_+3R~PqK zXo4;$R5?I!0Gm=R_vtn}274CC2SMsIq5yNxQY|#T`R)(T7KdXfvvADcbVG;`9S+xn zT>j;k&KuNsqDG^LKxq3tK>AOxnIL7r&xe3$a(3?!w_e5UI>(45q-boN z^Tf%LFk7D6%>f=2Qj{%0@DI-%e|=5w)){(jcDkFGbE<&|xv36%G;f@db)MDj859>Y z1k5`borFzeZ+`?A42_y}-7+2S8EqmRzQ(>Yemy*X0;q znPgCh=WCd|JWAzKLsU^rbJ&XrOTye_d5LCfy=bsr==JGjk|g}x_lGNh&_a*#`Wzz} z=8b77CXZ2Q5{XQ^TWxkl}lE49xb z#6xCQ@y>tuj(-6uNDBo`h+=8@1xq#W{5{O=UB%$8NU)YViJ0$wFM3n6&VZ1EKXuQnN$aKTLF zW#1FY^%L*U9%8MTvkcCck7?CJox6T(eu*BCI^s)s>|3dKfs2COf^0SgcX`Rvm0aEn zzq9BJg?i5gKVCEjtoRNu;+a7rZLG=<6SB*-T7Uogy%^b;P~uR$n7`9ZS*@l37L@NN zk84g}BCa%`{S{KJezslnLf`7Uy8}1okaGwU2{m`o&o!Eml|_9*OJ$~jH8WT0-s?|0 z+utsQP@X^&-1v6CjEFGz_G$^WvHuuLZC;tNWC2C}lRp)L>P_F>*^MA5Ej@)y9}r;eDS z+1V6)292!|ZPR9Rv5`*YjNx$x7~s;JOAKce7GqZJp4xz9t@gi2HeC_;^(^LkgM)$! zoCqX7$6l94T^0jBEtNje`_j@QY1m_f%NP!IrbGU+v1?$02yF=#4Fvz5BVnKWgFct}h;8{)Q zDl__Zi2;Yd_lC}$?mr?))BXu z&MUWSb@~c-cdGi1GwNY^W`zoMjD1piC~hD`ftP!Dv)@&Od9bhhJ-=`X`?6rct zl=wr8vHfdbtSQNpIjq(vb!1!yFJ&7?%c(?Fxi$cv-S z|7d2#lfP|lG`4xDq@v!7u1|?aIH{wwFn>9lmizIJJV#FcnZ&~1v5PeC2js^wy5-b~ zoPMGxp`sam1yo7O&(gJA#rv}vI(wsvH4fs$^l#i?N#j-xpuShBE>`FpUa2m0(jnAl zgxVT(*y}Y?LK3eCjp4M|7;Yn(?O-#TAhMwb2v&@R*X+o!J<&vh#cK!(_yvhmMfYX& z96m=xOIXAPCb-+|Ib)iT4H^klU{U5LKk04ke3bo1^*?v%oduppLA=ix(kcbK9&WV3 zT4;7&fq+W?AaFq#nA0;=^r$#Q1zZ5%<%M%!@bpMsYjG|Q6P+b$ep>W5^=QI$Q_))d zzdkXtSNE&*Xg24+QxZ*p$s`5fKj~4j8(teILRoR8-m3eEr&D)=c#!8f5tl-s@OZbnm5Qblc zD!)I~2~o`By&x0G4@?2#cirLvXM-E8pHyfpd<{ezWw@W`q)vXOtp#SD_-&eA?Uivk z8+s&QN!aMhZ7(-F#n;KLRj!m}5ie4d#sp?vX3FE`JM`>dVwb(5L|0OnVOMnHLMd&T zvRewd?-oWAw$RH(4p2hHG~)U*rx*GP-8xf1wv<|OxnuB)hVdI4cS}SHcjR)4AJyP) z>x7!TWs2*V`c+^jk>>mDn&w_C%Ow`_lRZ{|MBP`>y>wGPlyCxYG<>rpqA;|7H9_E2 zf%S5tdol;7Kj%b>FQsse8CL4dQk&-ijsHmGi%I2!&pUM*#L7}m?O*yA z@q2iA>3(JrX1RWE#)P2#`Ap;9f;j6Iw_DCSoAG3{rZQ>l4gn8hlXr)Hqnz&Y^Bd<07Ag&Phfk}dgX(E@#;6#Fa6 zgq%z*^RlR8rA2$lF1#Ibon~zA0`8`wy|ij5m!Q2djDtX9+>yqq;|6;7uSmknU*gSU zqhZ(4s}uwJJC#5O=3i~F-X|3Qu}M3>%S||Tap~rtSETT99ciUuUn`Po56w=Cwq}PH z0LsSzA@F@LjUs)>tvKJxsrEM6~|T@D;-K2XmST^ybsE zpLT1==6JSp#)tSK?hPcix8=cIBIdWuJT`r2iXyZO8g_76(TOt};`8KKO>SwyD#gMV z4sw@}dKDb6aUfi(YID^UCz_+h+AHls zcw3_6g$W&ao3F9NRd0PR#sp%sv+dLoqu>#H67qoq42+uZWhsuueA00!qlwIsEwqhG zuMb{{$1JArWtQlIKBkVV#Z5)x=?A;jnh206?2xg&pNoH59nShTmkQjYw7wYFX!_^! z#OO^ySXE_3H0ccH`07v{KXK%DOWRprwsW`9zIfmfyy`!{eA#=tOR%(K(%ltijkGCM zT_z~vLm+}W-rq9LgEi{mf$cd{nrvO-ql9reEnD=YtR1(rp0_lJiLGfP+b7pIughos z5uW32D44B_NGWThAV4Zil@$;Ps&Y-^$Oqu~)9S8)X__QJ%qlpi`58azGnMdmT25u&5_}U~Dba^tS4mC&BVPSXQDJ z$9e9f((;b_du@X+9vHQ?Qm*5nwWPbUqbyC40tw#}4I$Q55{d<^WIS>9vANN- z7|`*pyDz^5@Xu8W%OSl=(*}J`px00A7e=B7uZS|n32}LJ^1gs2&_Lx!UL6il7ltC(<{X~*;%dR(X=K^f zilsDw!|H$l>}UVMSjB0yz}hf;Sr|>pH_~pr+s)+lYi&xS??rkdozivT==y8SfiX_A z_SV9(n>7NlJjK3fyS&2q859H~48Ex~;Ng5+GqpGWZ$Vf&9al9 zr=BzB0&<@JcXtf;X^l>D9L&GL_xrPExEi^V$Vz(U-t7`))Sj_|k*<^!pN+G!e}m?_ zg5e}_FMiI7%IOibGFp!|lDwPXQp*lMi)n8YJN*^&o*^PhU{^RRmnpgj+nwSMsv5Wf zt|pvLBc|kLlqKATRPLhkPUW`cm`r?ib5R2o9Y?(ZE=@sxtT*Ieomc%k6!GSH7XHT4 zq{~Qq>222r5mMFDC7@A_Q@(GprE2@;Xd zq+|*y*J-Nw{Ps%8Wy2$q`Ki6a|J_!t(;A@wD?c{#&jfdgF7=&^)l8~{n0$~--`%#x z)|;u9nTrT(yV{zNVIHron8o4-Fs@+&z9JK_Z9_oDC&*`|d!1UY&tP#2)J3z=TMPbc z9Jf;oLbV~a`dyDoPhv-NBJ%aSAMAGG>?yR6lZ?5c`HRCz^ta zm(865_GYF)Q#|)XSPf{U(w%(7nz+)4GrsYCKBiRRMEMo^o&#kSxK6n&pM0 zuhzN>z59K25R`xmoBx3=qpW1_^yz_1kbKJM0H4JaC;{92!kh5DHaXe83*~$|E-m_i zj2r4bGhIwf-917N8J4G4ReQ>LnWz@qB3>MpO>54s547Yu?rI1R1z*NydG0`yYqy5x zMK9|j7PzWs^ZwWCikISBw^Z^6z18-|N1ETn{-y{_4nv6v1!U77Zw#yOF+a`{?V=jtkHKVPu_xNSUo%{?`plCgjWW**YakI1(aVH^g$-_ zRv&F<@_t^B{gD-an3`t4dL9gMCvFKCew|1p7&pK#tc1Pi-9jXolY3SEo+reRytTi% zG|D&y*8L&2c^?orOx7oHr8N_|%TfF7v-lj=#+SHSCChi}q8$_vyNIb#3gt+NY3E23 zhWYRH7w?bc2Aci+!xT%wFW+YhTAf9;lGkIXnQUu|xS)*8FJSQRKX^jU6Mg&%`S)-*G=RQdlY0cMx8dHcihZ1%cfJ&J@4X1;m%e z6>D171S+gn$)zq^0?UFK?QX&H$`Rpp-xv4iOa&_x2Sf@R|G}q6qFx;-Xn|uIAF!d{ zO7zPM#Fr0=YHlbcy}?0elRagEeO50}-Ef;C21YXfY^xThqPi~m_nJgDNFMuh+vGO${t&D=#Dd_}Z+|JU z>BD@;`RiUi)$uIV(H_d#&q+%06@sof4U#0MXC}f)?>jFHTr_*1uw9onEC*~LKSRZ# z?~`3CFqbmsx|E+!4i4yW=$t>w>=q2s4}8p2z<`E`%;Qb+;EK*0Du`b`;iyds(7L`S z=>4&CB^-ZO)*|8{4OvahpiJm;K9Jx2jSb*?3NK!Z&(X0FpRn;JnB_t>Vw0o^GOh6e zD=f|oD!56#3c0^FUCb)}h`OfihFV^2)HLtxKwy77%Zcv*TcNRcKDm5Xsfe@sL zVBKoe1+(-=-)QXtza&5YR*pXP?2yB9)m=MO6bZ#Wth=zIAaZ7Bfo!@xgKo_OM`nzD)RMUs`v8QJ(qk^1ca)P^@hJ##iv7S^O&piY}x7dpSC0GEznI%JN zj3((kQmEsRccZ|p=eD=wCHbSpr#2U>;2Q;##0-%MK!i&CS+1TVoWXnT3WiVWIJniu zorNS&!(K)Z94fmmvyo8K`uWVg%EtcL7=s=6#i6=ZO(A~K^V)?K5v#*T-qYd>FA zuj#?WFRq6}`Z@geMYq=`NQ2)NAS|b5ayt-Wr_MkcCf#P&Y5n0*URcG^5|Qug zRbpdMNQ7cL97&{Om5VZh@`A3G@J8dA81zlnT6~Eqzm>8&)AsXg8U(_Z-jCRqI7Z(O zB3$Cdi4{5p;$HKIu%ZhfoMuCkb;}&@p z6>7&qwE?@Aela@LgZ6gRVnand-~0VY);F?{WN;wjeH5b=iu~kQv*Zpc*&l5~|FZ4r z^|*|50yP0_MB=4xIcLfxbJyb*FAGDh>m~P%jz{BO{(o$}Wl$X9*0zg7&_MzN3?706 z*THQF79fy7aM$3$-7UCF2yO`w+}#G(5ZpbuyPVFhcc1S)^_{BuK|w+HG~GQ0fT4D}|A3)|LAXPu}N=tQqk^b-#s_3_YF>HVtkyS}R z&SJM~Rvx2LjU^-Elv>va-#N(Ys^!zFFVDcsehi ze7|;8Ak@RAW0~HR(iZ#%?)vB^5ByjT?a)H&_yxBoOf4A@GXWaP} zn1MOYIS4qLVc_IdyHe4ecLf!d0QQ+v=;Dm3_5yL(P8!45!9M&B1IbH~nnFMnuju^& zXCxKBo|G|;)<+#$GVa_Gl|FLZ{{EkTimY6j?k9Me<>6HO<`sPQO4C+ykplxQnLTbH z&P2IIaqASgJs{4Kj0A!C=3U6lOc<_67$HU+kQ=B%pVGHc1MAlQUJVSL9h8mMJ-mR^nJ~(Y2&xzlz>@;8`AWS!;9{jx|)f%lS6P znca}Tr!`b3EMY_KsUaK_T_UNq5%=-L^yG_wMUpenp1n(}p2J$MU zXVV|LZxSNn)6~|>KbvhKSZ?kfvHw&}~?(K%={=@7PeDM>kIHsEPu2I?h;N z#2w&m&zq78$uXL{0Me)@a{_{ljNmkB%56Zbepk(V~nKqIKK zV_pv-j&Nc~wiZWghX?1PT z-yWK-+;T|{KMBwwg8xV(<&OXd-&jc!qu-~SFb83P;h8{|57SaU|*gFV;1fRvmv@Sw1_`?d7loaC5UQpbw z@Fp=-piRheo}LoWhtFr+TEB`gmHH_{P7NS7Z3KLdN0%BOxh&SwU)Hd1hlO3wE#k#| zS-ChrEr?ys){1hyA^&W>ew$irFDhLZ4GLsFdclQOV@qoG_cx$lOLl7JZWyE6Lk|&{ z@`KsDgC0`jI2!|bw8T7(0m;`e3KNo!b5seClBAT!rNDlA^k8G4!+kYXThakSLSJOb zl?eEnA&N|)d3gbdpX^dK#Mo!vnRe=se)!kVcR1$sIue+@_WFqk; zaMo}B#o~gpKIONC#M*q1_nh*hxwtZ?`b}8g4!e(mCxm|i8LVJ}gbz2jy0o=U`cE_MRyOEicT0lKxyNSD@_>sCMG-8Z1z?ZOQ_inl z3>?bp1d2TSlrB#3^nbVO`KZG|8Rq}ee(*6`xCOWXanke|dd=@~Jv7#1h@hfhtdF(P z*y??`oe(tjD&1-SQuPxVe#nsKNg#*AzS@jRmhFz~s6>0m148F>q3@DHnOlon;<2-$ za|8Zqn1i#3{_nDwr-WR$jFug^_TN7;nXC74@2*82p(8im$tK-?2oZH%55ZdVyah$Q z0@O>#!o>br-uJx3BlQvZl#i&Rl8SrwSC*rWW*?hn@2;-X)`wC2Nvvo}S*bnn4*q=W z(yqyML<|6mMoK4R0B^KlxeA}A@r_+M6jY02$GT;{DvQW~AS~snap1Fh%dk6#PFYaG zp!>Qu)c4kyulMX8{cJX@5$zFAvQw9TS#_uBg}7U~*Fw}ku?eQdbVl9598;PuXv<^6 z^wXfHq#K*0rayY7Z+hXw23k6wPgOp&dVtUapqJh|oW7dQBF1 z%Ls(li{8HSMJ7O_IR+a8{s)usQg3NW4LPQrBdwL2 zaSw}d7V5sHMpvoyyE!r56+`ewdsCvw*)MB-^@a7T1S2W9GG?ON;^iqlg-e$phx_J& zD|L4DrKD?MO%-?fjQ7Uw-lXu2FOH5i0#$f9k$CbXQR`OM8_vwIH460Wfu?5V8C#w& z9U#C4UtS>tnH75Fnby$(sM-|oqxGs~hS-@{}-EBTIzcFOr z@B#3d7M(v$*H1zo(I=yJPG>8um&hFIGI%_ONtMbk5ew8zVn|3Bm=0BBDEeds%2|b< z$u2h?j_spM>TMHmUq;)7>4h4Pr?Y-zrSBbO=#TYFU!KtuRGUVvExYz^%o1=A6GuZ% z#FZfPWzw$jrTRl6>}h}WX3aD7krOgl`K;gfNE{tLtu)pD*{>Bl<3+3hBAJIG(}kzg z(K{i$qa-dq3w;waKkmM@RImdE?nWcARWBUj{EqTzv~02O=D( z9UI7@k|F;WT1D2cLfla?XWjR0Jv~>vav~Vx#VLNRgyC%8wpbbt&I#k#uppCfC`P+O zp9}u4g`nU+jM?2Bh=J=}YD3bq0XZ1tI#aK8>U_$!yg5whdMTf9@hJjC{9-5TwO#Q? zq8yJ1Na^D&IA*EoDf|pc*4;nx!KPlWeU0MZ6Zoe3n6{UN3}eGR=6}z(#_L~vRv8#N z>G8xeN+2;sD1aQG-vGS-udZBDXI*^NOgC#Eyg%D!7X#C#3)cTO z&S9D2sA!`@)up)_gp6>+os0DC56$}3?o^Ue#&Eo6aMrK5LZ_d3fKIBoM3Ln!H6{+6 ztOhS~nP$=TGcp`J_2)^XPl@HJ7>-o*~Kmxg@oLE~`J;c`L&rrGo|AScExqWQ|c z0|xfL#6kNrwM7?H`QOBBBDnqp^tMWVJVYR_Gl)GHf}a!4%}wGNa0L5ByHJiiVmPO` zQVCOskV1(s3=r|V?7jE!C5uDPF=3Hq4=k&~!i&N%7>3P6*O_Sk2}NJXAGO8TeK!!J zIll-`f(ho2cgZp4zXfB0cPO0u>W`L~OsO|N-wFw)(;4Czcm;>m#G<|v)^1=Ej%gKi z#ozIV59cBvpWdv|6|k|Xy5!=mXT(l}C4F>hqrUhE5RlM~QB9I`gS06c^aJN^aEfT4 z(!D@w7tsD%p6xnZh(wrkYo2%-+)*q(3sz!4rBT*Vg;N$?MsNUjAVSvCP!}>p0i+wf zbD8EV+BG&Os#X2>Vm5-O&`#u>p!IG|=;E+6i?y6i>%x@S)DxD5;uJY>EP7uRHmm=5 zmRFF>Jo+~{lq$vIqzTOLl#fAi>~ooxuN#^}F-jrQ>{KvA>G>A>l$Wz~gIo;T+5cz18f(2r8_{q3h*F4NxT3jn@6cXYT@k~x{BNM_ zCLi{LB1Ql;ZdSSVmdj?bE$Mg+t!kt0JC`kzNYBcSu7ZtyZ&}YsS>KCKk*&X9 zzbm8x#Pa51ULW>(v!e>5zcFfxwLO@k0fTWnXM!266-VxOPod;2lXC&)D78NK&ijgh zDEB4J;+pRDmgjk|C zED%r}CB?awH!Zac9z_0#()MD6T}+OMWs)$jw4=R|N>k_!&Y@7OsM{&8$F1)%uut9$ z^0Yyz`$bB5p?2*hO6JgvW5rkN}9>Ic6>jIqFEOEwyDr3 z>XiIP3ArSY_MP`O$ilFYC9$39(L=FYw2G9eGk8Wa*MK@n5S11~r5kT=X;JVFg*sH* z&>cy)nG!Q@0<#>TEvt@?ZX-25_k8KiUg0h1aijLs{^!hBt9d);zaR`W+Hy1P1l#xB~+Qif$M(K9p6?s)Ij&E!XHgrcwZ=D%O-%UJqe;L8s{ zX*{`2@T8{ruTnz@Kf^4Fy%;hoeF3Frq)30N|2=~FpZY`= zW~Q%a*9AfRq`|0-n;YcffXver=e9F4(HZW$hI6?2<*8RbHZ56}jm53eGxMAOrKI0g zry12-WMe`cPD)AkNJ?j$Qp4DRF?JB0itai!_H7uS-zgl~ve;@iAGjyY=RgD@0*x=Ycyj4gQK>C{XG2(v9D)WvaXS_w+dA3DK^mJtbX8_rX!g z(19i?Dfz>PlHCd! znlG#ONa_4`6&&g`e`SZ;C5HL_N*m=5tWG|ND!W;HVK5tOY@=-D9MTamAq<+4c9*%!(wt*j@f2GE_~n zp?stf@9-<5b*Z`J12U_mj#P(NpvRR`^e9o!j`r`2Kx3L<55gbrkaxal&`=(qHkFX= zF~QL4wPX?Y0blf6r<}j6>;>>#YW8nmvCaqhvr%;!s~o>r?D)4XURx;6df<~P!CGOur?Lankn)}q8b>y#8q4MZ0FH%4x4u;&p0)%| zQrTzobTlAz68>1kCyluzM%l5Y$TblyvHA7jJVE8ea|PBFyZw@;9eawnFRV{ReHdfX3Q(-MaAYCO~JV;|vPO@h0-wQJ+CKNgKuZ@Wlo zVw$k~{r>#M@inW7%e=b*m2{o0qD@%_(VB)2?VAWV9y!g7zj1dsMb`DzSZE~mHSz2K!#?fe5UJv^!)KCVmu%c+ndgYkSbgudNfA29tewUNN|0_)heu9I;N z^6>%UrrfN=cD#Rx3?l@UtwVOv9K80&_%@GoZ!)-1CNIdAt?~9V{t5qx-bZ7z5XVk+ z@lQ{B58qKPun8pUsjlvwZ^723QHR z*B#T+LXesup?h%9c#(3m`kt{=WGJ_V?q~*-0s3AlJGfiZc;+Nz7ssFEP2|jMwW>Z7t8v47qnY`IyE>9Z5nTJ85wC z_Vkw|u8qV|oeFY*188f3>G~gh3sARbgNDQ%Sy-1&X~?9%eIO6Xor-k&st{HrE+!^- zTl5b$wSzRdNXvYZBDNh%hlQ;tt1w3UPTe*-kzTxJsU|#OEW+&O^TxsdPU7%@W;mMaUuoq@yt zC!O@4w*c6dcygb`=j-hFfoJ4-h@8<^TM3lln3Vdd6GzKz|Jt@y4e0Ag?JF&9HDETx z4lAf0FmL5a_2pVJjq&f-+t8Ss(0+% zt)L_V$*S1U-WE}OSAOq!8%Uy8aFUz@sGnER^N+5sFSmI2gQLExvq324>j=>S6OJ!L zz$a2(LE#nIO7Jz;^71lIjj}K0g7!aY-r4p4V#q!5#Io`Kw0Wg#L7f5E!v6E~XJixd zzmuZ!K5RVxBaar7{gwZ=6!8S0OMnNIfuZie#CC>RZl|a{7=F&$M^!EPt(RL<`Qa1- z0)nyMO1@2BssnF?{Qn2j#)AM2V15=mv3E_O`gfq7@w5(rl-YmJ!vFn+?Em@C{_k%S zN#p-_`u+d?90x z7R&EiJ~g@xyy;K5*C25dJ;%ZbGmPZ<43Vj%U4XE?)a{ z`Z@uj?Ct*9#^TDRsQSl`Q+I6*L2h@ZYdZ7J_F`%kslOO~`Kg2S+^=mediL3?!}KJ5 zT{&D_DflCwPLD(7ETQ(o9;-l?V#@i`c#iSJKLgHxUaBPjMFHuclrB}N^l-wan0C-| zt9Dp4WlQ*e<*iS)msd>oj79_JUjOLPMZC|@(f7%iNiL<>v*#4~rxFIaLR99LXpf6bqU9Qap`;PNh zo2jb1Ea4XI5FRL-4c~wFSA#Uy+sP=YBsywmPU}NTFJzt~p zUS3e6hr)TSOaOqJ>Hf@n3)wdSiv#`NRlXB5ImxBjt|io(oSak%cFj0QpH;DlAl}^E zeN}GkP3|Zho$leTQsff1xxKEnbDffy{Iy!mQj_U1EyF0ME>+qI;~7X)T$sPt(PFV# zO0`i@v1Q)B{4^>Xa&DJPS!Av#Cl_9mlMFBzwvNO8i|R9fAv~=TN|x&?-OI#x1dWYI zGEf_pWaCS`sjux1FK%2n`n`{fd-ag1I>^o;O-n@lQdJ_Sq-EuX5`wORwe=tXjtAM8 zKYC|J;wW6YmiB`8`hrj1xAU(f!H&?x#} z4~1LqBrioMLrr6zrg&$qS;Y;aF>a94)DygReICc4fqB!hbLG?>-E)zDhq*6_Z^QGe zONc~y#zJnmE+Jr*Pj=)SMc#=C@TQ zFO9?x+2z^W&XnXB{y(T*#uK*BOuW?zpuvAc&T_ObZNr;I3dER)te64{y2DVUUlw95cq>uYq&5MLPL5?B zx@y1t$BK%JHI`%e_%8Fv?)*w3YJ`rk?&40rL!&Qn{vs>pQ|Q?Hs2@g}Q+O|_uSzwq zp2G!l#nv8976-i79J|cP=8H+j2GW6i&Y}GMKVsUNKp_PE<{8U zFqG$osT&fJQc3{zBQv@-Iq|G|qaPTYZjp=>=MGKQWYpDNQ zZOO{&7+D~f-r&NPkZiQ?z*8OmGqUvEe4T53#s?KSrY!DX zo!>m1|GrhRSy1`xA;_xR9un|~Y_ZuvqZX7HI3Z)PR5vnJudTdC`A6=l)%{ut{}nZ; zq4NE|r3ipu({Cd@1j<6hjZ^~+la|{70<>=WB7eEgOyV%EO%~cj;$L&cNE3oLAH2T( zu4sE?8fWjI1((j(_#53mt&39A8_Ii-2~^pS({iMST#$>SvNT!GRwf-kzTjK_BwJ(m zY};DwTr!SUJM@sG@I(4NM-+wd;+F#;5C)7DzO1#QkdV67P#lg&8Z{Qmx-UkQDrUXr z-hh-te1BZ9PD#m7#htITNX+NR^sz0v6roZ>NvLg%fy}OL9vA-X-Sw_C1+ds;&X(Lw z9rGsiemy>xbp;XZ$W^Jscx&;@>9r!fsEozf=tel_7^yR-P9!{;Zc9sP2d>*Jl9 z&1$nl*)F$i5r#wyDV9NN!5BVAd*QWCe|m;?a~6&g+s8DU!rHPPBZT`vd{Vchl>8>ImfRl|iF%CF5K&xOj{lLz zHU{KqH9|vb@|*1%l3oKHP(8B=qDKrS=jZD~5~rZ77qA=}tgb1A*Z+X!TLL|=81n#U z)JFZqIaRegwtUKr7Fx*o)&|44H~-40WNEW7mD|BODt8&j{=J%$_R{oW@ z-EQw-V!hmsW4~ht8h!8fv}q51Ew!al`mB*Qou0j6+IC|pTdGQn|NX(;>mo)MNFV|1o@WyUPIvqw>IbC%42$h!l4(%3%)9Hn$I;SyKb~Vt|$DNI9%cW^W z9w5iwsLYbDD?Dm=08jO~|HD5HB<}}q5TfZJMdr&-c()$>8|O!Fvqo-|RBM}>8wZ6Q zS6J(RBj_m`l)`Urwu`7H_eRM7<}4iNza*cY7zEIx{(oJ^SwHE}8Q<-Qc`H{FkL=Vc zWI(Bc>#ckHS~3eGN!hROLmR7iBdFQ|yq&HxzjAZoVAE>w_0yXbfsNJ}(+vHFeG z(`tMc)QNAgOrnAs*TX%j@|A?qn7@8Gl9fySoWW}4@u=gUM+GO4p*(iLMlOA>z_qcq z4}v#+g+Kff3xqcmT|P$Nwc*{XG<*0^k+sW-9Elq*7KPNP1uiQ@+1uU_^T^PNWbN#0 z{sWrNs$hlx&;2-d&}jZxf%q#;lhn65mRD{n1Xx+1El@aL?lU##luWJVSndtM4;(&+ zO$~f|!%`WT6$3F6ej|AY5@~K5wV>O%xd9^_kMF0prrUDQ+dIJ6JkgQq{mSSH6tRk> z&Q_!n7!u}&BtNL|k93T^TCi2fXv$CWVM^T)pSHS6dRQjk$dgzB-H~4 z`y#p?kVO(x@Ku8MMgyE>p2~~DSQa!s+QCE4DJg_hq%^Bd=_tY@@>~qph~Oc&84tqq zo;TF2D;4UrLrCfOLug{JpP-j}=?WvaP=tx*P@`yh?c3^(7YzMI5X z4wxN{$_5UE_{p-mnW^ctHnXLcAHsF&jJZ*Ar_|5Ap>7u#SZfk2PEPoJs9sMoNkbYe zq)Gsoc60VtI(Ra3Xu6DejTp%S6H8PkrcdQH7HflkL;LqRXiQy{;=Amm-u)l+5!H1n z7rg$CwZ@e+GysydeW! zqA<4_ZU{0!VD1$_yrzf?vOl{qzU4~i@XCiGOrc;GzTx|oaxDcr8eGSR0on3hZjKDe z6Ex6~y}mu(xYD6^eOx3mXoi}a&avYJ5xGQ1>NVB?$X)BS^)uCSNW60XK;x)>Z6xa9 zDX~A!VZ^>}XCEx_P1{O?s24v>w549*o>8!Og`zLu;tR1eW`qJv7W3qC=e{W^w=qhv z&c-}EQ+}-9K;@0*JVbJ0V9}bC?&P6Ife5&!>> zOf?zDJI3WL9p05pVu68MtzZU@=oUEAUkAz^Z4~qmjw@zdg_71@cO##A!!dCcM%=x$ z+r8g--~Fy%4Bhw(Fs!z2hd;olX2g7A+U~Yw90VI}&pyfz$rjmoy8Ld}_l>(hec>_A z($BuS^LYB)@=8e_7{yiGt^tf-m0{0f4tySaZK0d@ZK(o*q7P4R@OkYFRfv?{gWOl1 z9*jSCjZJU3F0*%CM;t$W$|!h?N2w$tByDssx6{y10v<#Bi8h47Q{FG4!b z5B(e1zwXP%#Nyoz49Z1WN*7MuYBH7|_da~JUP?xtcR16FWCwIxybgSgcauN3>TR~H z?hUWlxft{WKWFH;+FWmh&*&$g+VyluOchz-37A9wwwxS&yI2y!UnfGNUZ)atNqo8- ztbWjD>2A8rRSmhPrUw* zXVd0X;dzqxd^SCth@`LE(k{7M&)Qv!Kipq&sUt%_c5-6P;P)FJCQfYhhT9(2jr;>n zX~TT|DrwXD1}?Sve`6jwsvORrW(Y(A9?v0Xh#;}zO53H_9`PT!Al$GU;KChOIBusm z7KB?Xe{xOB%kwbRs5?7)uK$2xN)qZNh^TrQ)su@!N z{hkab z3inmMf!r*RS3?3JRXsCPX*zjN> zK*BbOL1Ul_b?jd?MPMi|TeMxS3bCUzcD2dGx5}HbZ><| zuM1lt&jh)MfxSP@qt1!hXN<;C?6sD6KJiCiOW6|)LETlk+6~xA=X2Fw_Gu1(0PokI zUS@1MGaVVmwzoswnlw#4x`cfbXNsHg4pJV;rYBNA-CrKi-OHte=1q>a zvELhJ%Ps(vE>#)}Xk_W1UDL-5RzkIpw!&h_Q<%JA-LRfkwWM!-*{ox&V^$ zu*d-pgwn+Ze;je4SL>umg4k4+)^6hIni*7)3kc)~D=91>&SvexSm;z!6I`V?dN zB&akxXpyn=`sLq$^RxAn%{KH#vv01iuXzR%uoVX1U#SFxmJN8MDXzkj%U-2}Bt`G2 zB27V}t2Ov=v^Ovcb@WLLb5nCUG*qwU24Bzkj)ysdF$hQ+?et=K8J4WnoyI}>A3ot*gSn} zf2P0Tg(1qspToJ`yL0rcfmEFFc7|mSk;mia^4;itTLOoxKX@yIbcdxe?F7a`se-ly z|FjNg!}ifqxEz>OVaM0#i!IbDuOcs9t4B!;?HS-6M(1_2irp z(V4+b%~i3Fe@pDXB0^wav>!HB@P4kz)r^!J*@@xBP%!T+TPA1UPEW) zp_1wu{{{u0n>Hv($sH(m8G!j1Oz+X1C%_(`>BByz4KiF!^k?Bhz&~!UV2s{>yr``= z8SNG5h&%l0SvWLrHh&{$bZ|V^7!es5YHY+}Ecz71B9uyQKgL%P8^S{QNvR<*v!O4s zU=1LiP1IgLOL2vENFep85*0j&mqvq|}+AuOtt; z$zJYPByaO_TnW1U0!}j=IH&~|vE?;lYXzu)?TqDEd8j}3^d)`ydt79t68qRB0ts`b zY^hz{7PErHLO%6OLv&R2&5}HHJ(B`k_%+qVrNP<`7o_G|A&cam?iOoJi z%xFYF>i%l~#XM+3O}Kmmjz{G@8rR$~4PK^#7QP+=N8Lh@c;U)WnRQ{#kkD!k8=~`& z4S>p?OX&gx)rH|=pSFu9w(QuKr#Ou#(+m}LDXjtm3Db4~gI}^^p56(K0NGsi4 z%v)`rY14OzN)znaW=T5yDOXZ5uFw@XeFzPgJqNgZ?r9G0IhExtnM5feRBO}`kL*2P zjK$E*1%;*TtE4r-iEa|@UCTU7yh(>RflNWtUt+CXp5Qwt{54c}6yo6tnh}bgsyh7g zv)SGi*Wmf)b|}5kQnJf>P~uWJwwb-i?E-D4 zuc5CWA~3uzKni>2 zgAsb-ay-QrkJCi4CyWb|3nKtZ5`_NUk_Aj2q;H*JHQGg^w)jM^(9ZXUdBVWl*wh?G zHJjJAb5hAQE3@yrE241(a&Zhw13J(;aRO`|Oxt}k0&$dGATpV36u zBs0E9;6x3eqeZ6{6h{d#d;*h$zuu(Uba$BqMq40HDT|PiFi0|?yaUMmWOKe1u%kb( z`sEYC{pt07vG%iz=kj77+(JN)=yWMI9!-n`1O{BVs}Sn2j$QnL8AGsEB+m(lSGM;a z7VP&l3s<-73n>(o*WmZ#GH4Z*mZ$T7ChJ$lL0K8p>#7UWWq)b;3|Pw)Uky0LofzFs3ELCbcHW*7qAyyS|VO=LNoS z2VBcw8r-gv2#mz>Y>~_)OvbSQIl%a+L(iMlnCxy@oiC^>4s%os z?sza$Dgb~E$vER_3EVDL4Tbf~5-^qldcHCK7-DWT-&317ilOk1n;D1(*Pm$pun^#H zd2{U6t#SH1uLT;Vwpad1;#y`k!bbpHjE9MF%(?yzT{ADR8Au}))2-V>I%X%QNY7AKtFct zwi_JmSUO;6t??|uWozIAn{x3{_s`H~)HjxstAt9=eYyWLqj^NJ91$jtu?u3PKI^(= z497W5shFK?H@6$wp*CCe8HoaXEr#RIXP2(8Fd^sOXj$l772+C}@LZ+%KOU$Ci;ZeW zrVG(^;%2XA3DSYP#$9$Dlk%<`4a60gN&mX-Lh(TGxxlOm{PBDf* z*Eq)mgpT#fy9EluBaOqdrC(!~CLE4&u9J;c^tYf^5*iQhN_4wXt<&t+?!l)+0(c=+ zHZQBiq3%-}dg#IZ5d3ek)M?T7tc321HZLJ8xPtbJ0UVYCL`jL%nm(}unDnk3(;bFD z!eF$DFQ`~=;4pYn3%IMtTkI-DZT2T5eP`X0v~7C$JQvFIHUwvQjZu#HPa!MLKL7i9 zQcqmioZWJ*l)TPmH8Z*zp*^v*x?l9Rs>0tEW!*}{C|G_T>%?e3r1toPCY&eK5z57B z7#^@;y?MKBabOwB6tsIF+3P6C$bB7gRZQ^i<3`I$ zFTQZspgXDOE(`IG(6crqN8#mf-S>XH+I$rpZQ5K2&UJev_P=U3%+b>{SE1VQYXnl9 zY3rq7o9d+3C+VZJ-H5RG>zzh?C1y7z>Z$TAckum3;jG=P)aU9Ocip}f|6<3|9eb)+ zRwMljdZ z62lV|VY#?Q_|?euFM6!~h&;mr0{yV1P;&WW;bcF^w9#rgUQ|4|=Gz4sVlf>U>iA8F zMdE-d7Nn=iNb&LnC+}$kj4zX;%wYi??}OSqZ&t07t`-H)NV4LbPP`y^B_BO*%2o0v znppRda~~YqK?VL+Qcm2_c&7*gY9Q|O*Y+-yqf z6KF1qFzcV2Phl719L#ICesR4cf3_mW_<6DF?dOZ-#QEo6GCktg;>zI4T&SJz*X>}& z!GAx#E5e1zuQso?7~w=l6)#xbQ-mG#xoZlkbYMg>f;Lum89*;im7(#oR|3ywMR^kv zR(z73#a~&F!-hu&hVc7R>ekkXWr!f;aa#8I;+rD07ORZ$4qP8l-qA_>8XF#BBSfC& zwt0)+p8KgR^kW3cz+e5l&vnxTx3E#LGm;DL{Bzq zJ?T7>5;9a2t_u#ihAb+-Oe!+*`e~yi@k$dZWW5Kt@ijo1z~gdV<4mFeD`8Yy>^Is zDJ>vW;rqgFZZKX1b0hXmM63om-F@=6xj3TeOh$pEF;7(JafVgb7tMrI&I+_{o#4xS zZJdct@K~%1#JGaj{xi1CMDF|}F|Aj^ggP4oO63)QLw@-Y>YM#4ClwFPL7m`e&slmlM2RP%-ieFPzB7V*L#y{wDsf> ztunX~+zv%RZKkwHNT!aYNC=wsM@GDFF+${5WsKyHd?lL&g%AdqWhe^TP|Iw)jI!QN zQz3Sr|;!@BbsLF9x`NAr3nXjZT7j}`OGW)R+w98Kl1wi_C{VEn)kf! z)_O};(HGb1pX3+q6BBP3BE_MOp}XLkn7F5rKx3R->$jZIPVUP;Pu}Hj^!aDLW1lxi z=7K?rxWnwd!?Lwt#~9{x9K}L?(NZX0n4`e7Q3E^E!@F!RH9H@)@izL!6o+y^&MDUp zf9$9P#!l&xC=pSC7VIP7&1-Ec3GiEyywI z7v~9x0m1icctpakO8%A9orJQoa(Mh(9BXhWwczdjT_xx5n9*QI5j$AG%xmVH=*sVb z-(k8P#g^s5>QgNk6gCyh3ZNvvEOgNhzknx+at>g7C_0@fm!+b`if7dl#98u^9g zg|jnE_vA8ZX5k(Cb*Q($;wwRvj~`vV&Cm(+sAvLy;zWqZHiwI*cX-z&qMqTd*{~jB zF!;|Yyo-i%cr;cv;Kh|R#Ln&0gr*`liJf7Uq&A%fW7IqD)~k$dbdMqWJ@b@(25DrUG`_(G~A2 z)259ka?3yPO9Gr)_db_9KoQ@xHE6Y)cK<{_hO62@d*1z&7YcYl)r9pSg=0Q<(Y+V? ze*x^VQJ`(P*4T?K8(nI7ih!$`_NP~4uY0Jc@TF_Wwn_6B%c7P-amNp1#29%Mnq{2h znvOy3aU;kfyL(XXKbC3|i~fB|kyyQE5=-gv9+;gs2Xy74%0Tubj?bEo-i*0`&(3*8 zMMdvXgbmO?BFtX#UW5;FXLvB1wn(m2`H0=cIm_#Cwh5(wo=#EUs4#BXHfi$($$`Sf z%>PQ_?^L)*7N*J^H}ui^Sg(mX9X`4~PJV&hYGR#rjs99t z90n}%)Dl6%fzuz0qqnLAKqnYaXAj)Q)2N+<{(aw6S~KNTc^bk2J8d-pPG)lBTMc}P@z ziPZ^mPeOTH{`CVj7Mp^yeC_%Ap3U<3X3I<->TjkPW^M#Tid3_OKRzcPJR8ee zyOAp3_09p_TlN``jfmNg1OdF`T0Jjo@Oj7*BM{hTCzmN*Py+1xKD`JF536vnP`#fg zL`mt55vso#HGKa3=e4A!+n9F@IsY=adGtuBSqXpl@I}Bh2l`B;x`7m$AiOfaYFI0A z?dDXZ>kd>LW{N)?J?uN1W1$`BPPuZ4hH|s#h`?O9X1UXqP6(3h-@-$6lEk11igiR$ z+2r6@la2mJ2OXBG2@WJ1C3#kn5rB*{L}2EtQnWMv#ihIGIL#xr6w`a4jJeFe`Xb1o z3OBW)*;_zqcQD!xu9@9eUnAIR2}DNP@_8wxW12}mrFn4^F*b0E(1*=s%c+Nf)Pbe+ z3VOa)JO_m0!nde7MJ2wgbiStDXlR{ck=e$wzq+xiJ`LtZ>O#=7?{B$)n+-9G!}|l~ ziWD~RJT1T&F!8I)SV4=2KPucl!rD`Dfeu#!eNRW+66&9uh=@ou#SyE}iM7+j%wHE~ zm3Kqlu^yIrv|!QOHx-bLQLpM)Km3^>BmlF}FKtb?fAN}?F;4hB09|(9dcj4c@|kR= zmx4LJ5#>Zxs4s~yIW(_Yvpni_D|zA>uN%ZYe?N};lZiTFk^3BVWsc2RxHo3MOq5cG z%8+?+)dOZQaATvs-xioUK^bW;TR>kl_@Z@rf{tj$GEy*~VBBTs4di`=*e{lAcu&TT$_8kVhRc5y>|?o(?)j z%xj;I>S;;wY`8BWT=Bo(MY1xpXI4D(2w$11=w^kLtRcF)M!xiu3jf}6i zkEg@Je2J?>{BqvaVqy{1MXdY5PqmQhesX7XY)qKm_k3Lc2lCv^VEpT!C;nBfZiXT& zH-GUqeSNNd&-%}mv(&`1aQnr3T=^M9K42<*Wep@vv&36=sBd{LJFYnB<@P^5G?{l2N`@=#_8X+>bX63`CD#6 z=gcK({U`Tn`=$n%A1=#4_>$gv<8?+#=-nA$GkkR;wnkXjA%|l zeSPy8(x9S5rr{-6(%KuN`Dc;aN0aXCD`1K`f$wpR`O|YT!K8pdbZuyNtiRGqjxq<0 zVQ;G{^Sw2nMu>63g&X`RM#(}%vY}wuRgBIe7y~bt>Ut~tqzr4@6PZOLgH9}(=rJ_^Y|1jrPT;zLRbTa|I~qB;bs~_A5hAT;qn^FVPt6(@;fL+rF!Eh z-lCO>X(A)w0Map`6VZ4p`!?U4Cx(_DzH#d+sW+$iKnM^^SqM~PRTFvt;7%$%p{NSS1-)(sJg8c^$@78EQ7 z%zZ(&5JWJE&GlP1>Glh%9htt#SEObw{qh_`D&Y9Lzhv}xt!d)aI;Pm@@FzLu8rb>s zsvz(&vH1FJU4RH-xVF>{AyscdHFcF>c-p~gBoIJ1FgUO!(fcAL~b}fE;|+J!dK}d-pUen;xW1g1X zyDWR&2|rBO>-?B`1)tfMI((sfeLVC7X6FtX2J-{}H`17>?zhQb)2qFQ9wYq@RdbS) z?j>+llw*9`aUaD*B>4j|UoHy_v{KY#`6A*)iO7kCsDkVS92Te#P!uP=3 z|Iub{Bk4M6z!7=c%!u*X=u8nz?FSE;G-hzUS(kXDy*S_ndl1@wV@0 zkPDhrR1N4~FQ*h2bw8>z;a)30-%$G{tqWg-C#UHZPAE2G=EHY8S9ciE1}o34|NJov zI@Uheq$h944GcSNS@g25}o0k{^)}CJki! zEoC2`cM#^-DkAZ|mguHBED7^yT!W5}6Vl-(&|1lFmQgsQHvkirz9RB1+nutEE42-ckK z1K$dK3uY53RR9s+Psp;&^$2X>)CjF@?^1Rj(F8g>R3OI-bV?t8VO!?>!N$jRld2B|wbft!eaF74R1jbE*J8*K1;|sV%7g zyn3Rh$6TVFZe-`JBPtw);B=c`B5d*9_Hh|vJ8Nqy#umnyg|u~NMsq}6B0YVQFyA`2ICmFfmWP=cs6eMVuVu zj~>!_5sc+jDFU5^1yQbcNCTAG-F`B@D=*jBwC(y-&<7phyTk5HFp*8~sLTPmiS&1u zxJdKO+-H0uOhj85^$-;NPjn@Dv1Dk5CYW#e&l({9WwB2!ALLSG6(mzCbULRwD_-*z z^siHbsG?N@*cVc_>$uW5Y&%?Lkwcgbl9D9h_+$xhZ*Q~^{OJc>&|KiOYPv_38;8e0 z+$G)QT!(z|@BEE@o_6<{!EPq~BmIaxDk%V@6oS*x+z5)bR` zTVh;$Q>p~Ln4I{O;cx3W1sC6a5lcdzfBs~7Tx{So^y}$G=PZs!&#ctW9{jS(s32e| zwx5ea<;u7svZE)2e&NzeNpcn~$Uml?csbXk_%2r}I7C)nt=^Qu+tcQgsfX)M8NrF3Pgwp8+YOF1m<}qQHx7I zYW*xmXxnOcLRgH4gm&I!a6{>|p2Gu`wipP;%1#?{5fG?A&y}hI@@Eq<)toAeNa=!osS&^sND`YaVbDYE4`^^_FYGzYzY;T`|b4^Kow&{iAiuHYaPInJ>qoLvyeK*7z zb@_je6b8dRJPo|)cU}ga4Ymp0U~BULs!SvERwayd+rJf6f$q5|p2FdId=B{y5`_gG z()fn^D$N;}Y`jmYbLzo-q!acnoA|g>UFT!fTJ~BK=W5@ttQ$q`c=mqsm-!p0VYmj^crxd)d`7Xb_=Ir3@JDG;!@Opz#Uy)uadU$DFaq zM!xEQT77*uc|FVoN`=_@q5eX_Kx@2m5i(SGyexiECV%W-9~Aa`7T$?f6tv5i(>4uR zb2loUm83P-NKuFPM|yqnyAQ6!tyJD1%&CA!3Vf{)796jQm`B>Z#8^IVs67ep{_v>8W-w{iBLX$6;6}D)Z_6@Q znnl3NSDa77oxRyev0xqW>mcAnTLxLMhANku$2@&Jugc$Ofm!P6(uQ2;$HZ3EqKQ(- z^yU<&_5!_{J_<4hr|7MBw{FBkb7SpVuo;}@+wPJYlZ0CG=R>R2fEG-ccQ$d`j{@<> zR7Xaq{#lX3RP)uXrxoA;-=z|j1U}+Ps0%VtL@kOv)MMiyp*}Gs$;M9W6%NGTbFr0# zfw_$XYD$=M;3pqG#Ell>>d)45>HceryJ$$_H6H>CE^k_V7Xv??dg9!|GV)R}fg7VU zGIytpjZd@@)y=Ug_S)$XPaa_A7Z%}M>McbZ7)Q(BkGF{sV|tfsDa{{Gl`|ATYhy1E!r z3u&G|M5%|cUUHG7wzIuu)7M&R4GoO9yui%V@iv8!P|v+<$shP=qj;z((vntXJ{U1~ zvy3r!rFqfh-h<3;_nsrYyv{7Rc%g#92o(1F#>5f`Nsg<4>s*xU)!UCqJq{Z5Ue_0p za9A;2HIM#apAar$KUC6rzgc^=cIV`bP(#4>QZ#UX(wAv@ZF)Z=-0b`E#Us~3>Ni;F)(wGEc|nvEhfZi8fkU_W^`aOXB~yOm$SB5tT*^+=e9 zC;7bkag7n6_GD>g+laG-^&>t#JjzA$!H7qKyW$Hq0F$B~$qzIlcoeSH;_>a%ImL*u z+!Wbo=r+DcFDz=5Lw2>_#33FK~@Y5NXjGzkqzO<#*~l;@{x_$9tWwIdAS4P zfbWkO*sA1^y8VT-s_j9IFjTJsaY_<4KE=k^x@*4W8mHtWHI45xeaU&=KdhnV->nJj z@Iy0)RV1Cq)dsv-+d7U9lP8<-O(U7FNH%e8776d+^{2K_aBI|UGAU|%zmeYUC`u|+ zIFAn`X}f6)+?Fx}lK|Y)k*_cw>iK;3Y|{jzVUe+3WJ4$=$Gj5WA!0^V<)*E3;g{u8%lGnu7;Ah{ zy4vmGezvTp?m%1F*$X7mH|Yf=v&zWy2g-U~#ffgS`9&!Yf!!&kKmqaVG~BOn9o`2{pY&-s>0xC@9kpYBr#VbarS_^dy1F6vzMh{RFXI~q)^NauBBWZan1HSRJJ(rg&6!&A9ZJ;$n(ad*7E4ZpCQCJ2SPo z(npJicHlF5xqsjsKB6pHJQSC<)y+ zx@!w-5b$~_>Qy^WnTV2|weLfNHo+MKugtTI%=h;mBRAG_BkLXe&vV~Ry+34-%vGi8 zd|WfU8^=Tag|NCQ@V3MOlAWniwH;z!H{o|Y^XNTEr`U1X4ki!Z&v0My$!VB*H+P27 zU+&5HecgHFgsyQw;^IYWP#y=5=&LB>0P59=C;V$wRds{@`1W>!?!<2oZYieX#X8{0 zBI=gqC)b8!f#wMqS;tpi3Ws$j%?umJ{aQe`pR#rISj>&$@E67UKFatz=!*cM7oss4f6wbm@V21GM1;y*IU%E3(b97QD3SazbPp{Hozw&Pq zQK)y^k_s8-^VxI_78nZj-9KCA+_8m+!)wihZ`$#D({A^e8{V+au$BUxG^*a zFiKf`3vd*f;~1ZD^w~R}H@6eu&z+r;$(rEj<9A`zVy}D_ae#)AoBBx34ZX*{5L;3a z;{P70*#n`QFn3z!+=90D?P_X-Bg=Q)-6_WQVJ92&yV`Au+_yF` zaEH`91QXbz0jfjaMN7AAQ#O&?dGcp0nO zY~Z3a>-Fzy?3JcaMJbRlBwX{p|7t~c!^rkw4?aiD{moy7`T&&0r`locVcG})E!1zp zAPH%kkIOh&dLFEScfhX~AE<(LJFahTr6F*NgyaBfOS?lv0Ci%!Fy|gUoVrwZ(Yvrk zHO+U>R&a=6l7ku0q~bnDPyy6Sj@jwvtQD!t;WH&<_M?3q0c*y4NX_9Lt&SMjGQtAK z$L@PvAv`grhH8rY&6^Vb&d>uPYOK0*J=x~&j)=<5t>6{3e zMYxDI=@;7}#=#p_;QX8}!fj-F7$EU!+YN^Mw_Z8;UkC%S#yK&n2Sx!A$Om%YK#QC1 zcI)U#di~~(cH>E&-zrW7!!UaBdt?~mK(za`8I^0|xlXP1#dRXHcc z4rro4ld0;tH&^G6GM1&lWo`l@!KzZ`#qi%K%LNP*&M-(f?q8_G5uBO&FG~0Fop+_W zo{N%MUkAFLn@#5nu0N7H@Tm*^;4sdffRy|F_{sNLE~hT)ILBwZYv(rl!1M@JS@Tx!$L$mK%^k%CefSOM*XGMMWCCbeegy&WiAWAt+b{^ z#7?hk$TP}oU9^Y=j)q#5NR<2DH=l8$uDZiU`=A+f&2yUtAL;P`b)u||THT4)R^H=o0Gxca(?b$*vG zxQ)&RHaTdL9KJF_w`j?cnSm)AM3qF&Hkg{)WLt}7P+#Ajwz2qI?iH{vc-O||KM-WD zrRLhp(=In){v;4Zeu8vhWoO;6jt#lse$Crcbihx+EM>)SIqO#F^uqpl+0>R*EGTGa z+wX=7K#|j@wL_2v)Zc_!94b#?O>EI_QC(w0jfmWxg2Ya^j%aE_5%*tgPIVq(nPT7X zjoZw%Sl(^I-X5PaV&)K%Snux~Y8o`kQrUOSJUokTkY`^_%?<7v_%lTAKdZ~7v;=v5 z)gd3^w=3Gz1NFNG_?P2FrnFY89^>BH-sQng|6VczNno81hsc?%Z;EsBaGLaZtBz6K zJ_Lc){q2G4R3-LWwM$>BHXol?q=dfCw}SYC4K+r4!eS^s_(AV!z%8uSy9L1?Z3*faX1a@Bq}x-0iB3ur_G1=M z@Y#80hwirs9kKD^Mb)=}{l>+=8=yx~3nk9S+5g_*J? z^+Nl_D8H4t4T+ppk-M-qo+sYQ8n2Jj=o+sQ)UChkuQU#MNFnko{psw`f&{xpz&`H4 z8O=uF%}p5!xP8h%(WMY2xbF~5JsVyW!8DMP9(e29FL$*0 z2ajSjb8Y~;fwx53JA_B4d*aVQ^6;WnZ-7~iq>XmqRBfue))jH^8TDAT>4-*Qy}98M1$n~Xr76~j`4=U7_D&V{jT zZlJm}u~UdqcN0DTk~F@(F!w9jx&lVp;~+h#Xz~bk>-3&{n-w^1F5_*JSzq6z<4-Hw zON~kzc#u{*XMUMcy_|bHWOSj6I=)FZzs>+shikHu=2N5=Uxn!#H`>qJos(L>@^zmi zE%R}8bzSt>@&+u45_UlVrt+**rb<2qkGa_2EpXtF2+nMVD?M)f#2X~Q4@R7E!|EE26O(R}5e59H;0f^!5(*3FD)k`B;jq#JVs2Jx>@(^h z9-8}O_4hSnb?UeEZ=08!yw~3##q3|dfH}YS`Ngrl z@+;b!9?l^OOPZQ`oTbL{X(4x@UE*h^qbF)N3TD%M{p|<7y{PnuY>RM=nOY`$q8g}PON#U$ zQXjWXZ-My=H!)Vk$z?AKlR@CwV93?YgpW+;#SFzDq=ehf&#`K`b&(uM^!{o}R{Xp5 zr&Kl_gV}N-6QdtAbPCp0PJC0wm4$3NQV<`~=;YiQYw6GsC!2ZWU+C#&(BIxABu~`< zW8ayhhB<5WU6^W@i%ea*KL#aI8Av{)bC`bl=0BwIRYxSFvAS}vD{!` zpDPkRLFkR@%_QWDf9CwJAFTf8aqP$w=oxds1Iz5J>_7itRn%&W`=5>eZjOy|@UOT2 z`~7gyf41@8+W)_sjxu!kbWAU<(u#|V|Bs;{QEB3I{{8oOdP0N~uf7)hE@uEVhIWTZ zOE4V#$ZY@MV7S_EH5nbLVn~z*PFPM(hj2-tr?O=&>5L;0A!!`#75-r6sLg-P4l>R- zCis8Gy)SC5Q%*W2O!e}D;dswSr$uw)b!(w!Dx0-#H)s*}^g8IX}X zIZv|IUW7`^DjWQYX=oz4`Z#tk)f+xQ_M7Q~qxR4I;>t<>84^KvU?wlnW1$(p6|j#Gu_G+YDNI z7S-v5gr6fLpr{csdEd)q0+Wl(2d6$)(2i_jQ?;TS*$Tbj<5hspI%ko;5IZ|%Y}a)= z+&%w}_?gFFz3m+R%e@NkZxh*ELfDexPtEe-onD!r*{GAoU&+pHg56=E8)+18h^mD_T6g)W>iKNky@dlt@ZflhWimZan z?*nkws-6ZuIqg(mU+=EP8nUH@9S|o1BKl}QI2z$2aZ*Jv4bxN~BwgR$Et$u|;}GL) z>HjF|_>4iy&wMy!iGxQ@g{Vl{a1(myrOB%Qwsso^>dR8*$j8R_k*Q5hG(Twv^B0|I znSZB$7Utn$pjW_?meMRX-2fk4kPh+FHK5k6&j=tT!ciA{93Q| zt4{vBQtwsi0do6?z%>yzslGZ*d~W)dbJnn_e>?qZx7utuT;cs^F?0o$MCkv}L<>}C zXs8+`dD^+q3ZrkQ@9mj1UgZcQlj-XeHC^b0?B~R)Q#()B0g~z28R{lmc`oIS$^!A* zBhKUxALxuQW6>h}Hses9pDlc|nGI^B?R4ALI-+C76+CxB%nPe(MUC?Fe@+ZY-I571 zgJVcj+Uz^kfzzBeEqinLi_Z6PRmEQ*kx6P5x7hZsPlh=tBeFZEB=+(0dTtV_g6d!1 zDt2DB-#^~VNNA-+p<#|d9JagN7u1&7|DnN9<>6@pi?t zjqYXb^7CiZbt=Q!g^x7iT&13ue%sf*Mv?vZ9_PfozJmY@z1%b6S zeH;QZY8ERlm%Cf(z$M};&Li}(=v&{jZvXpoJv;*3f?Jtp0GYT|vD*A>nk{Z|qmnhC zZAn8f;Y|)DhHw~w0yJxOcyz>_LCyG9w~2ti6iFz*kzjbb$*q1FSR1e0xSri8tL>V+ zq}z#G=IDCpM(o0jg%xcpB_*+7F4)9X0Y(KNiw;9L0M5br{O(&?mDD0Zi9h@6`(OJ@ zX_Km!r078rli0N4kZ7uhhzPH3&`q!JrT=N0Y|oG{!Clvi_{j7*Vm2W=iF2>cVU&3= zi@F@21zT88QOCTky?)mfx7OU;Oa{nT{Rjq|PD}+&ugozr;j^S9qo$^9!)tG_b=3X@ zwrv|5(b6z1bm;Tcri>ZTMDC5&y&Q)WeF8#?%-}Xt<@S}TD(TYniT45RW>L};vzVwK z&$dGzfS^feUa!kw&kLWGWmY;z($6IW3c*czZ{t5rv0|f zP-}OSHnshOcNth69ock+hK14auuJcm?GKjy9HHqhc*EaV_qw3`P9p;z4~WH1n!l`5 zysX0xsM0|ixahro*jQfQ6(lOsSq)+`?cMDx+W4=VK+7A~z53eqSsB;9rJKwC5w^i>YD7q=+9b*MjG~fy ziG=NK(*{0&F{#u~if%}ch`&Wu*B2P5EQ{f(22`S6rvapsZ~`}QpupSOn7viA2kn@_PbBJMJehyZ?G)1 z?{;Tr8-B(8Y5APiZaRE&tP9N*o80Fu1{OD z8e(#lC*V6Rcn(t4{H4&pc(r%#KMovdN?4BOuD4cbsX5CSJg+Y;5|CM^PpteUfFC*Y0X|>I=)ohs(FRB~j!IZ15ZiA!-L>?Rk5vg<^7U;vQ|6IY-bj!@=$+)SIcViZ?Gj@DP)Elt)h z%=6V>tf9N0M90|deDorQWli%Uc3Gd);|w_b@+$Odmwdy}L!z9HQHQG_Y~@14q`IQK zZew3PGPM=9z~}jCCtcGZMVvl1!*;$P-^;+SdPyiRfuBjWSFG=vaGOTNRum4=W69~S zoe}u2o$2-r?sT2e;g*J|(S>E5bDRW|1ooU8hL^wRV3)authSzCoxla542?s6uDtBngrzL zQpzaG@OLP@LLtu?zi+e7H5iwuB**kBrXJofam)ihk5}1U%=p-ySa7u=iuOSaKH4};4p(y3FBM0`VCJcc!*f~=CHch@8v1)GsL{(|DU->;`)k&_i*Fh# zwFPZD3ME${ix-(iARu+cb*6GZlLDIpQjU&tq@1xZ|A!=sob0h+QpjIA5=5Np^Gps8 z^+^UyqLUa}5biEX(LJNV_$X7M-u6Ro=~mCXMM_fNh71)NH~BpT^zA0 zGkJ~go37+eoIkkLSzeZG;%Y2<6BsK98&>OnqDO{P(l~80+o}6JDj498Iknh4vv4Pm;Lc7i|A2W%U#N{DJVP3>3+v?BxP_Y?St9k)+J}DeMxHl zjvAOuA-6qW40jHKCm0ivC~w9eg@21%3PmWjx2j>bXNM^8VG5*8D*j9aYz@<(nWE}0 zMg8TLRUos{5j!L2u>MyFZ|TJ90DF10PH6R>%jc2`dSQwMuX{S=@YVB~o?Ir|(PIPU zzJK{nBkbuS`}i)i3YmCWhAf5NTK$y`uU| zMc{Ym-B02kTAXQ^c_gfkKsy^l#t=!yAh*v_Z`vy^Zt6Qu`iIFcwmXMaXaUt=W-kKC zL1C8)(!o{soMFFzd!##;e6mMc+WnxucK{KMiCC^U=&@0QEeQ#63{*!? zWu@hbN`gQ7o8j)(hs&9EA%RaO8dl#|YRt&$*dUYmBP@H*l^q4%GV9uAb6bLJQk&BV z0Tk&AtAeW+F^*B0CDXs5h>iBB@=OPuH|pK&NiK#j&;UI6CF#fb?`+Y%2;TibY9yfNdq zZ^!VXP-5ebqvRn5s>wurkV=tX5DQ#f59ZXfH=NHOU2T-~zciEKC1OAp@->FNja>>g zqm?;L@$i->>L?M!G@}_IV2#&<+#eJJ3#cs2iG=tN;XL=N&sNM97aQAACP_3Z8ecr2 z#?yZ~@9S9J6+F=Il%^Wg+{FjPSB$K++ZFJc_3rBW7nt=8f6(~BZa}6vfO2{4W71ww z!QXEi#u_B#yB{I`^Qncm&h#u^JmJRx`3c0oH!umY>ifJZ`l$Q1SpJ1Iv?O$2z4Wf| z(z)0#H!UA0Ku|i%Q;S4cDGWIo)0P$BR|rd04d~p?m9?$t_7@?VT#p=U1gK@vP*7{Uo{NM@nx=^X}@p|;y6-%qW{cLF(qP`f24v$URIPJT7 ztGqgX84^jOd{S}?F`{h2BsipRXg*f2Gaz#~YLs>QIf%5kOV#~WXA{57-(tFp>w(xhaUvqGn=a8;WPL{w#;*m5Aj9D5YZ3{4tzki$yk` zEvswt80s2?5YPBjWl;M?1qXL^gi6{CQnrMKnpRI%9qshs0L#zkMGAoj*!$J5S*yk3 zn>-z+G4F!R!_QB2oqc=5@^Ve&APd+K!>=2YK40>|!I!61K2B%Vr-*ZyRF7(wwe^R- zl+;3^A;&A)i)M*XPr8t}x^LIpC-Iru>2!8dpE5DN|GGeU1jq8Og*fkNLpeh1()Ude z+#&|M%zcwb7bIbS|9QT$?pd_OEvbG$i;|FNAawf9@FDOg4hgPx0K#7ucicyUe;Dmf zegGO8PbbQ(0m@d-h*Oykt!Du=%!4fQI%a&(S*`vDKnH% zR!xQXqeJ~Zn;Aq3b7x|>SWjbONUx2>>g(>aR#(A$Yq{9$LyYN_H&7~#9>3aPr%2h( zrULEF34zEZIDd71T)couvK$!E_FWt4f4mT3&q+*Xfnbs@x}i!6^4>0f0wGQn)S?DS zOlv2JQ>%UyPabUm9Y%Kl!dTK3n4bLNk#gz8(e~+`W#y$g4zHg*NahigxX9{p~M8 zpxSZr|0j3A6vivNTCY>3ijFfu_2eHy`MZ%OjHZ;;Uku=H^7;EIL>CD72Lt%mgTDtG z{10CIZ%>W>f7AcJ0{18_M;EsjbFZF}v3*jnC$##H_H0kT@1#OQZ$7-G?(5_HElkq~ z`#62~?}P@StDP@FFpuhJa91_g7RZW`NgMa<$O>qw-6e*OaQywkoJ!t7q|@_D)IoaB z(*?o+V!p!4dS!#L>Gf4MTiVZm6XyTybROl+WcAxP%TwG9`b{Fn@5NFwy_agppQ96? z@J1$r{UmZb0u%dgn&4!TNpWYx5JC%!a`nHXk`!72;;$RsQ2&j%|8%cArXyw5P<+bN=iC|XOE(9Ws~Jk4Y)V#`SyKKVJVxBegRV>x{ggMLOCSf0={ z+M}19vvsC56HT~>%X~=s(si|oO(Z$t94oYswLC?#x;$Y%Js~Qcb61s|(9W%Db(n8Ut>q2>IjAeQi!hWUdE>DL$BxuEIuydmsH`Ja1YrTl9D%cvVfAfu*bW>LX^ zzWMTP_*({LHm1wXh|-yVJ^lyT#T1ys3Y)~LB{w2+@@%K9S%BP6wgm&2UUm5#GWwP~ z)<#z_Jpanb#$A$YI!@KH6z^Tkk;Z>~CaxSB`sunpL()L)$jY>nu0&t8ft$?7_VA7IGP^pPb@MFM#@}r%y0LZFH4lgmMKhM$P z_B$i3@9LlwJ>9@qGTA1i=Qb5B>)RGZPb<$dw%oBa+PJXUv*8|50sny<{(F@NXJO#4 znZg%74FT`%=cC`1V(<;??3}Z?Njv*yp<$wr$iq5z9xNKGG!$qV5zxqqnB@K@tBAXe z!2e(72=T>eB5_GLU zCgb*BK}f=B3lqS?^fX3y_wqBrXa4Pl+r6}+YU=UJQslJu{9l6R-^SoXD+>M0NpGt6 zLt-qN;!1z}+ZW#Jx)bv^6FzE#x0slawXAN?2}KAUzlS9F$LeG<#<2T=1!<_%%vL!J zE?EGfoa ztFFJgFz+yBG;K5bM-^+i*4!|eBK@R zM!->v_-cI3m~;y)zcI`#j60}Mz2GHlL_jB}lvy__;FV{-@?M8=jll%}uROc|?hV41 zB6@TNO=T>cf=$*t3`YUBv|}nQ9n!2HzpGDHFX;>Hb;K1q$mpj3+p7J=j+}}hCx?@k zfmXGE}GK~>23L;{+t}wLgjbQfw_-q^#^sPu2+6DS~;$SAv-Ps^tHAKa2 z>l9~A8b9K;9Iwu~y|gv`JoCkF@U~WZE2Xd*khg7q{UmXy%n?&uXYn^4u4eB?wRC%11`Oo2ukfk_up?%9r<=MM? z>`R{3;N*hg6OjbBwEyT>+x%*&g1wqp6UA_WiT)p3iPW<472(k|l$zO4Z2f$0+N?#z zVz`{_s;w!u2~Gl0&OoaA&pVpbNR%YR#0gZ-hoEh0p~uV1%LHe5P!GskSP`;+N5$1$ z29MxJ6Ny){jWafkF!AwZhzB5}>3n8lLXj0;OL(6P(hFC}i2mhG)=E}%3;I<|(_PU7 zL0@K=PaENKlPgH>^=spnnjuAv!0o2WXiusafFL8%le`)Z0RizCuygLLn>YaZ)^?u1 zZ+d`@?X}1qM4Bj6y=k>tF6t^!B+VPgx%L&s_%;}x(m0(ylKTe~VkLm!8AXj%3Xfi3 z6N`RG(vF0rw3Ao@an?Sa?0fEyGOo6jqeJ8I{{HFJYcS%??PV%~Ffg=2tbfo3UEb^4 zo8g|mu%enmEibROla9#^C2b!2&e5?fA4y2*@JBWOb-=m53&_iEspc?Kh+pr!j*iLl zX%^6TmiSvl6b@v{J7T33RgDj(J((@IdsRI>qVJelabBVPhU7=$$c6qhol zR>0r+mXp&5gnDlGF*P()Vq|12EH9S>a&b<`Af2gWcb1mQJkD^jM)+eCtLW&IU*Fxy z*vLnHN@{9ok_kJt)|EfzMSV%d9eh(#THfG{O-AG?I(4bHsyDr`!i?;AvE@geo)wJ6 zIny2g&}+>$QkzIm3&BTvd&NvGEVRzlqc4A>PJCgX{{@=+3| z7#$i*OG`9-jIuDWFvZU;`VGmB0<}|9PE`=vN=G8Y!=|F@p>m=P@L^-BW;YO(kZ2ZE z-Rk)D!wgxKDhncWcfN$c{5hV3R6@QG7f$CKIngmuQuHL5gepDzJQHakxlaV#ye9}SYvqH)U zydU0!v$GQmbq_6&G6;4N?W@&>!4M2zrtHrmQ@*{ty_#k$cDmw-2>HT%h*P75)WX(2 z*#{AG_&Z+t&aWF1S_X!}HL02jXSOcNw%e0h`Rjubh8ccp7QMBb4gM8v4+g<5p9zJF z%Ztt}c$aX(iO%c%_N#yzRGi6+(VDY!=);491PHqM$98iHnVg)YY`Ag7!NJ+WpJZEX zBq5=t64HlXtG&X6DJZwHV&;iFs8h8rPfAK&TJd6qc?_AHnqvJ)`*SNb1Mn010Ban4 zot%(Fb69Gr(M!&KoBwb%!RIU9Cq6y3Xekt06Q=|L2g;FA4pNDPUVOK~y z)5Gu+U<^cwhWz%=U2sm?h;C8dMFdehb5y#kN~ zLTI^SHm_=^l*xj%iAxJP(}(aA*F&#%AD@bLunAEV0|^iNdj@C>Kb?<4+c*xCP}kQt z!<3Ds%e|fX=HJ0}jNj1?h4`+0j@e#Lwzru?0|Icp?!OAOx)N2Og0V|RHWmctXRFz~ z@wa2q(30pR8j)p*jVSorTIKJ5`9?*>aFN1vYc`SO=G+L1pNUjZq@!?;^Tn)jhl<|f z8iz7?+Zaeq!eDH$J4X|6J~`Ua@v}n62^YNUJ&v2@VR{z z&c&p-!QJg(J%8X@Dy)Fwj@|^@le46eBy+TR|ErK#i%Ke?zYS0$YvRe9j5{oE7U|S4 z{wp>PKEB!A{N9{doBNhN5iXvy7Y32*#`bF(J%o`Jc68{8iHWm-$?k3!WctnLx%KWq zZXNW-UAo}a#nn>qa@7d>fiJ>${}W#Oud8Vz4#$xC7~BSkh@n~tOZN|zb!{Va>(wKM zB+A&z#=p=8K%f(2MSX495hB<_1xcuO*yr^Y`fg=0pKfg%m%owKuj#&eF&Klb+3HGXGkla z%vxp)JA7Un*zU9$>DE`$feH9kqYd*kp{tJDh+xAn?_8tf?c?)n!7A-ew~^HU`Mr?H zunl>`Pj;zI^4Ko$XKDby)`_6KJ=?o?EFS{q)bq*Qu!rZjo7oL8&|+?=jdKuO&}s~* zsr$^zJ(qH;o&(TBJPEgVD`6N@dVt)aKF?;Dyia7@6AGjt>=DVZ%5Yxx$(SKUI(~|p z;`WZL?LDHJsF&sYjMtK}Zzr1%FnEZW+*!^P-m@5eLYbB?ecVcw-M2Cm*yEaphW>&& zX`erO`LeV67J$CnRGm(7^l$|pxCT6DGESl|+t}KZ2>udUrelO|{sje&F%1n1{i&Hl zZ#bf8{&G5V(uYq$ObSHviz+w&AsmAU4!45b(N>#7&dvA|Gl2+WvmNGVj}#;&r^<>|1VKR(bqf5v6@wF>U>VQVc0grZKlY z&=Nux?RYc|g5N$82!-}po3=f24Oj}Xe@eRikw*+7Gc&N_J}{}GL@LNQ%S95Ez=wqFsig^8jxaGXZ)2om zG~C?Ky?V97f zf&sEbdzn3>aFRPiFwZG(dTr@a<&$_5ckl ztHz&5+s{6gY8vXxzP(ibj=knwDl>FE%#`iSH|Wxk+%3$?yk4+#R}<^sPs49 zS&4RQ9znbc{Cs>nwdUD#cd$2Wf+lwW8-iu=p?enoChe|y@{WP9GWM604Es7>^rV#3 z5rb?mdGhvsU%dD}X5%)!rhtcySMrxi6H}96aZCZ8O|9C`%#mO_Y3Z8Pbxjr>NJ^<5 z+b2_6plh35UF&qPU-+=KMpXhNpniEJ@&O){U4ErsH(oI7+JGMyvTL{C(7`;_vgmro zR>_b!-)L8BBZ#}`8Uv~Op0aG;K1jSt=Ca9Eu;Xeh480Ak0qh@1?RcTNX z=1=1<3GmuNb3nhR5>hZLGF|Wv1;6tW`1qdt@VQxY{VHXWy`kgUlN?$pG2XqbJFuFP z8UIL-Li?aaoAi@0`IMrvgNl$0gG4oHl&f<-JwOscoD;3 z!IbJoovbBt%Xg(_Qga_a$N~WWhpo2^iYsciK+yofA-I#^4#8al3GVI^AV6>%T!JLH zhTs8$ySoN=g1ZhngAdL-eBXU_->rK5po$up;heK~@9x!Wtu9=mvE`d+sE;L>tY)=O zi-}Rj*F!`MDbo=aiw$&G@Gj~isPG^UUai6!P4#+;_z@lddkfD8I~!9i-3@YsVMl?! zAj#+#JZ`khd=)1N-Xr6id1 zWfn@H-xEIWIG=QlL~my%CR%hmCz{>s>RBzb&RFOC`lT;i$Tc;^*D)9-cPg}0C!{G8 z^Zom@cfedIb;yjgkogD^0g-_qNMu{WS9W9LMGOpf%1Gwb@(_7@XwY>*=8K=!f)R+F zQ+1Q{dg<*}-avR@7Y$PXk#~>^wef_rk#y#p0|CkW%74xkjy7?(LdH1T*c77X*B-xP z_-+2#mFJg@E@hcfJyO7bzQ{X|8+p}#K^lxoIF<>$cJ1m6V)m;AQnW$*`ycKW$7)*e zot3%`qcVOO*`%T>sDoXCK~OVoP=9_nKju;Fm`3ha;=b&(BB` zC1WWeqF0$f1PnD)>Y9qrOtTW5jLjBdLiYc*_b#v+o8dc)9f__?J!wU6h_uBVJXjoK z|LnsxHFqy#*hb(n-z9BGQ?>n+xdB6{xq!IoWDjoO{z=Vu7yJVnp*#jkasr%?P3k}z z^tS|aBELt>eBb85$yQVf?UK!!CFRn(M+mW-CaJt?Kx4qEA)}U%J9OS^`abI=OVx8+ z#>#7B!G=%X4;y;$#oykX?7G(1*B`ruGyA&29|_Gk5)* zlTRt*l(a%+a*Z?omYi%H4T&JB0$m-9M^5gv^QJ@tP5B)vPehMgvA+N|&PR9@tPBoa z|B@&IDO5o!&PIDpc<`~@~4W9Wh(t+)zb`FakNqcN~TF56E%_LjiC39K)X!tm1- z(t7cAu|1&D3S`vyCHngg8hwiR#g?nfWuJ4i^EN#JVGWz9{ZWj=d7taVf>$pIRVA1r z&8$Pm=^nV_%|CNUQDsI3BT)4^yduYb;8dIe+z-;P2=rNC8VPzjdcC7^V2Y?iLs8)>);C@A{dH|}6?uc6*3p~pvttBdtYD_&(rs^sRg37Wy84DssY^k` z1`CB={>7@2->6hH7)domNfk>wpCzok_OR2FuUPOgj(uYqadYUR#Sr(%Dq1 z1Sk_m3WTgRrX$nCubC=Y=dCl~YSoOy0<|f0kfd3)vJtYza6*HeWhy;Itg#BP76pII zTAAlr&@l=Oc3|%fOdb(#tltW~0_gF2^}YpG3ERS&71@Yb;o0|~E^9dv5sD&OI1_{l zUNBUdD)PviLy+my!z1~04#H#cmU-(q5r?j62hy>%WcAD(Hd=Fy{5GJ4@dePc&zGK; z!>Z7nn^(dL3rL|T-yOS>R}97x;bKI;8T#Ao^<)KsQ9;nEhdWO|YKA!r{lD;hpc{Nv?Mhpvxu zf4me7e!TbQSI8G4F!fSFMzSGKWZ5Pya5T_QA6rn0_|fQYzI<}1TU=bqkK0?{SrLe6 znTcp=>sdU56fBHkO?;L~L4jA;?<#Lzg9gRnGPUd#{I{~QP++sSDrR{=2&)uR>hyj#y zicI;|z};w!P3cgREspn)*gZ(_j?W3|w#UX|+09^}k>Pt$VJe|6m#3xrxNr zcF{1Jv}nK=_$3&6Pml07e%6f-N5*5GtiSRAbA`$EACtq#zQ|mO>y|UcIvqMu>-~_0 zu_U42@26E{atPe^o)Dpcml_qZo*NDiXKJUB_z!}WH{hSw}! z75fKA@fJAvdmL4)0U4=%0t9n@zPs45kAD&NsB;`OCD(_$?xqW*QE99Z;4Q1rohth> z0;BfF$Jx>9hM7aA7Z&!*ypmHO_8$sh4{iisfisfEA(JBU^}ZUY^6Q+BPwTjK{AT=T z4zFN&U8bR8ZDk6Qi9y9M;@8yb{6!~mzY@$5a@i_9keGWU43!T~1nsbG7o-k~52mNQ zdt^K{AA26MvxL0)_)4m~2z#qrm%2>v2Lr=((Uymr%{kJcX42+<#bQJ1Mn)EZbNYET zWO5P*omKV&`@+Yp2?}EAd9LoShX*Gb@l8vsz%2U{X_49-p_okURp>i{Uo`TK2F({U z7MW!umit@?bp<31H76Y&{#8_7lszIRH6#5Ytj=}(c9W02xAmqje@jw}F)`s+Ybh2Z z+eAut=qaVCDlhzH<$v9KnJQ4ug2@+FUg(IG40Upx@2Y}~mdlFE>bq_M)?61XSIkq*+}o~~H_9bmm}I=nhjrLp zwj<*%u_WW}<=<}x-wgQJ$c1#_h#WOHpy00HFFd2Zk;H)y#(^KVPWB(KIojkD7$BEG z`m~{kVX;xyT6*jg!t6GuK1elhS0ZXL$IJK95H@tNaWMK!jp*lPBg0O}>oZIT<+z_{ zG4zxU&%hSDlfWnU0de=9VO(Rq2EcO{UWB)V95TzjH(#~R>a{WTbQYbG1jTiJ%VBC0 zadvH5N(hRkQez^{%s64IN|O@UNr{lN-(b|_-4Bp-fYF(k{(2E_8XfvdeOhk`1KDbJ z|3$`d5XjH)d(ODGnA)PeM<0-L)6BnuN>A`vqV_}vcC@e$V3V^AB6M+4qnh?@*T!pH zCb{F?|qc^2mIAUfQw{} zD@YP$88L<%_plr~5qIkv_Up}UvV3YD6a3k^C29~?WFf>w^NFHGj_oI-*S}^A>n}wE zqU7T?0&zyb+yy@pKOtxF3^afkTW;8lj#NZbdw82_l0+m5so!@H%DISR7}UQwwxYy) zV;Rgx-Ue4-g!`Uwn`?cGGREFT)Ac~px?Mp+?pk|?WcUUYJlY0;KqHA0qHl#^khyhN zI-S3uq!RJeW_Sd|J&GiOD^|K6Iq;~|^_cb7!WrPTjto~oY)H742m643NDnVnTKb&< zlEx@(G(Sl#eAyAjYJk)xl@X$gevc?Qh?5Va5Zf?DVRj7qdKpTIsVGK7Z3(*84eweM z7vdMXcfmFwbWRL^MDoGBur^VtRMyY6UVVj-i;urmZYf|t`S0Hw^d3@i_M27PT13+)H`o&PhXT2>*ios>1DmboHJo+sOwAW# zbNC@{;ehk^P%-0x#@2uOwC42lyp#Y+BKFck)Zt+ioL`#z5?09qT9q;5g;Psu(1{ki z%y9ocn25OT$c;Z^*8^3aQCmfaz}o!iNu&1^v&&9K21k+hynCIuszE%)v%xW_vE+#) z;w@8L{bDkKLos&5bSttM%H+h`+tFr)v7;jg7^I?DWh2(4B%T6PjM!8TB*|lQ&~j}G zj?GOo?N``6Q*K=i)wWTUg+I*#X4cihzRIv0pT4CD%^_#Wh{Vw{N>+;dROfQQO`x5) z!yj-LlBAO~61?cj@F)T?>y?(qf94!Y+7t#=!rDp&9~iVXf;3?EM=dxHh~yTKW~b9U zLqYi@p?)n-5^)CQlpqu?3nw>>$!&Z;iT3_fEjig#thuUzw#XcWN?U<1xEWUvly$Sk zdq$oX=!XAdwRIt@L6a_|d7C|rogJkkwh`Locj01fjSKWwzFTN=ew*a$xOxMLMcuig z%FM=5%t%hN@=GN9^(()=eJr?I^_qNlR%vJMUi8ji?t`q-LJCX7v0)k`Br|Koa0Xq* zRAp-B!=#`+4=>Z-;Xl%CGROc0ZAo=JYx9iD8GlbDJSM*MZ-iYI2{v~ngZM9J$C&#N zmN+v@uR&4I-1F#K+Qo%$y`uJ?>?d3)2gGQ+aAvJcC%P-7M|c)~UF?l!Hr$|7%M+z0 zee|(zeLeB?MdMDFv+MM9GITr5v^7R75hEI7sM*w`VzBSJ3}Ri*gA~%Gv%&kfcXluh z@l%@-U&+8aSIipakuX&?SrCKS;WHx(M{OXgI7KIY`>QGSS9~zddtnig+o?Oj2NA3x zZ(#C`{=}8@kwxiyDZo|)Xh20l?yy+4Dc}G4dxF2u5)VKp?WHmmNC_3`R`f>S{4U%p>e#In z`@j!x3jvZkDDN`0vUJRtG(V3r={sJu*{Gv z?+qWykAN;l@h;AVE))etgv12?wDf~0E{yeRY~suGJ9^f9Ajw3UGV5pKsT6@GA$bVgPA=+e_E*wT#08)m3z~_Uf=J`xhJgD(?}k zEfT&r$9OE8qDu^9euYz{BeP_}s!&+d{cr0AyYYRER^;q-^`GvJu$5pNHC*HivSWIr zu4V}>5>4l{GRudwK&2YXP1^KMa{t6e%w7-EfbM>&4Y=V6#8EY`iGcyn>73f)pT`mL zG*LB>tl1XRnXLyTWMl(gZW987@^In3<|%Ko2?_xf4XcFSFvz6eU+-v&a#Xl<$Y8aF zHbj_T*ykJ@)U5e9<6~%~Vc|Ea!)ow3?IcJ0?@e3qL-jxrl_Y0d={I7D0>Luw_cq_D z?JKK2-UUu#Pf<!D)20bBfZ`Lxgo1;wdFEA##M-a%4Shr%_%Qm zoja+iHOuojxCu&a82WyoaM+&cCc9c@i8`qwyRE`)V_HS1*QDTj%$eo2b>A(AQ6SxWR2uM4$wGEV7e zs+&LFh>YCyoQ8)WLd^sP5GP0YWd1r>FE&&2_94!a%;iX_{9v0YKMD?k^Laxl=6-8P zJbkJoQ8eHk=!DQsHjZ=o!`nW&6xSwdXe z9($L1^QKEsT+7h%9?+xn47IH^@45N=Eo%#Ad8#jIUV4o2FMFQU`3Qhgq&~`hz*%W@ z5|<)KN|^%~`X|w!=9i0IM=RP}PoBbj$mWd7g5QI_s+6(1m~G5`_p$QSX%v(!EScmc zAvqwy!y}|M@I0y79(W==FuWM#Q5nv)kQ-oKUikMeJcg2QKtv{POn9wI(5#!>y7Rob z*4h9$-a*Ktfj#r>`H$BQe*3dx9oZ*ds?&sEMDyswY5$9V+2E+gz0tH(0-fY??J z$0fqZ*##2UIYOV4Aflu1cL?@%y8t;sl2a9%YlLLn!W62Ab36c|}^Ru&yzTYjvOk>nntHRSY6@i)o zR90ZMd)KBevTGRTEmB!EY5z5<{sda2DypZ&MFhSB# z^msZXJv=7gbo3f8DJtTG7kPg&EqkX zDG(ms4<~Vic{rovRlNePs-B_t=WF_7y@bVsg3E#!7c#grI5s?;9rRUFjB}ESwyoL~C8fsxVsH?3C@c9uj6F$u>oaDsYz+&;$!g_Z%{78pH*m{~ozYwSr zybE5o8!Jgp$Vjq`$#ik|O-d4+;Jp?WBUaXepzOj=&H+Ub_S2T8grYZgp+j zPbfQA{0+m|SzdjhFa*o$+~mO)ExWQh!Jp-@j%n`;E7+4?4FD{R&`*pHyIJpeBZM<> z=X5;wLeoN~btujj)AU?MF!{4wWtSEu2-TFe8|)XK!hBC!*XMlP8rq&Sp=sA(wXEwb zz<*b#!9Ks%@w1htIVh#G+NWd(U~iCk3S)5vAYmI<+?s1pM1m~Hfmg9=Wz5^@_!syUvB$u z5$NPUU*5Q^a=Z*U`=F2$CBM3NlEAT z8LzvhYOiqB@|B5O?tUA7BDx^j{pH!J*Z=iTf5GzugjRZfVFg&DegkCT>o!~(KQpuZ zbb|T{-3kX1Qc93tIM#j}ul;s}1pMfI%+%AG-WS-WUq&r{ueZm_{!nIo{MYOGw62WI zgams8K6{}BQyYbli%iaMO5vvHNSYf$lJ%qukjO|h?GC^7AjF1=pM|)b`@)bk6nMOa z!rp<{l6?pUNUlLZ|3HzzG8~K&#gEWLbGOyf#X}ytw>7Q4*x^&i7S8;-C@`^j0?!(> zCKU@?6ci*ht+Insg29)DW`4EPGi;2wvkt26<@zT^np5z^*?<75FRtqHqYU#%wrZT8+OR$yF)1xJ)O3 z(*d-L5NQ3z{ZPxVy_RSm^_h@|K|A0(m=zgDBLXQ?2)1t<|X7tBLt}gXpnIt}r2tnT09tPX3C2-#%lx-S!E2@(Ti#V1OHwYNmQ9B&^6v-?SuENNL!hlUXxhy2a%DtBMNX*w= z9cU3Qjb89iEsSIEuJBv*fkl{KHy1T}KFX1cfW2r|fm=LU%-PSfw#~9jy+cOy#;fpe zVLy3j+3051q&?`6P|2w>Y&FnU7!5FR^8h`xo@m#^`f$x#7A{)a>A78pUDOc!XG7(} zrk}b#P;<@K)S+>Udd+zFByWM<79W(F8WrY0iZT=#3Aq=_xOi!wq8(~};7w%A)R<1x zC@5*@mq85lVH}Ri8}(@$=O1k773JXWAz66Cy~K^Ar`>26kcS-RU31oQ<&k|2#8olC zYf8>876sZoadI508kBYN6D7{inxd)-sZLvsTLvOa-mOu z*6!o2cG2Y9D)d`c`b!!cO$Hd{zwI4!wVSBDrdo7z67clA(hbx7^_m_xk4>|xli#7O z`$=@IIl6g=jeq?!mUjdfBW9FEz{a>wS-XOQL8(>dfQ;<2mojqSxBDws8@u4@ZdbUP zN=WM?I}^o@!iT9nQz!a}lq~2uEa=bmq%7j#R)IYwWF4iTaf8=ckP3mNoWT zYt`T6t{8K?V#I<*C%6;LCJS;4DySVN+GiJv*NF^IEl&XJ!J0tk43;1IE;8~viG}s1 zDAH|1y(h4<1-?|uwjid_5L#qQ1*@bo$mNjQ(+)J9A68Yqx+Lkd>fI7V*baho*4*h4 zl%&=RrA)NO2}Zs=$UucB)*3nW9(7d1Ev!wokoDmMEjDE z+vcc$?^`{pDo@!=)3f-P?Z4Djon6AiAx%%rojD!h~d!He%xI!HvSn8bsPyp{DR(!+1Wzg!{ z=Rv%+Pul@Vj~aE2e8Z<3IWm3k1{Kd_R<*s=O*RZ%#n`#9#syRH8I|rUO`gA(spe9e z^8pKySda{>IO`QJ-s}@m6-^lF)qd7f@pw6>a{~Q?3|UP$k@lDTcE7?? zgwlsAoG&Rdfv$fVDw}5aSbvE1#)gN>{EwzI&Mxa8pt<(`^K|$^2viI-u7LUsw3dl8 z{D*vS^(YW%83p)3)>t4-6(aS8%6z-k)80v1V!!izFKqjxWn!3 z;Bg~+@?M+1Ez=i~ZSbAGPyUl?@+i{kRi?%hg&sJPg~xu~Fb8%U84i0vsHHvzc6Pqp z+0R;x=+jfp(T1AaNiX{L3o$rG3(5B=xlJ;~AP$7PDMY=hL#|@PzwZ z!^j%6ojDbOL*^H9<{H(dNacc|(_(Vk|H$P3_mRcb0>T4?vyKP^Ay95=$1jH5V%!9G zFoI8IW4&CMX1>@mSQX((opW-PL#tJR?j4?^r^h*LrG%X#@ykN)qsI2KIc--<|` z|I4xo+4`p;_d?2k2!1ShQvFt!{C;Q`q3>>sC`MuXjFbhurmo8I|M}bhzKaVTpxr?@ zJMXwb0I9g9?udg_*>&Ph){=Bs{(pW~8u;CVeP}#?VnmcpJ8#iv@+o}HLr zI^6OPs?ztkP_2UmKQO{sENUH0D&ei=Gq!Q3W&7O!5e$AQ09f0<4D{b|b4$_ozWsBR z76cf4l~<ynU^zf;Q&fN8Amn3&V^^9*Os&UnN))H*yytE3-*4WY`$29sOOuZc z=xLfa0I!}kkYUhNcZzdX3zOV4#XDoM!aNvlt$CmL`~RvLxnts|7`>ez-vOD?XIY-l zKLuU=ql#)5(!Bcx!*Qhk^n51aaQtkSFhYphm8_LakKpMct6<|4adVfo>MjoW5hTwh z5?SLzRG6B)zIbh0^kdnZx!;{Gz1<=nvIjK?uZ1chVBz|th zM=5~B64aK40Mc<-4uw4gQ*eVF6i(Ko2kd}tQ&0yeq8#lS-LxB(nEu?qy7_c@?1h$1 zz^3Mk_l}uC86f^8vKs{C%L~~pztn9s%CfRyRv)9UHghFONGac|Ni*62Tl!5=#O8^E z6`!B)LmyeCUCz#)BIo-Bj&{*i?ws+h+-`Uh(iVa8Hh?eqrF&$L)a2~qf+##7Pyhiz z>mxWrnw<(@mKPKke2|g~E@-aT0^Nh?`uJrAFD3TGf^mEweG77nKPBMd6%qsj&ZIgl zatbPF&71;145_8DsJv_6T~5!R7c`d3xj>9q;p2l+cp;yFLnm_ddvZsNG07oGT-F}@ zK?O7^=CHcQ$40&B5o01Ep=&|axd;_{^3zN6EprE~;Y$7l!aWplobz&-GORPcHeMfJ z-TPSSesB}m^7W%Q%)dzUsN@5pAED&lW!0Ma87c8Ter1sV*#-6+s`h}_(CkEn0Vfm3 z)JwPeb7w_P(@Ttk(H~0qY)6^@Q#m!eD!QpHB96Kl;3vKMCooW95_|Stm5>=!|kT z`ylv=zr==;l91jkH&@+Q&x~&TtQE{nENmkBN)sY^;6vV4`4t5~A+BBZu(r1f2fhdN z5^bEiHZ_J%YMH_k}@!~)8rgDaIdzFetrgrU%9AyYp3D& zEK&Ls0=EA|!@_vz=+jYc6k&i|oY(#78DOIE=SK^|3AhTG_NusQssKwW{6-K#*W8mF z$6rWT-!0>gj+#*h;p*?pmKu-FiF3lAY!zC{FE3V>>Y@EBP8}inaYqT++(TL;MCOAm z;EWe4BlqD~VAih;TC4$EH9`c}PkP1g-}5bWPJxAmn3rUVQyAuGR zHSXrPC97{kOM@(PX=y=W;lNUGSXk)C&!8~&?c>du2_0>n7n2V589ON_P0M`C`~roK zs#QMEPHk4nyTF2}oCxvXowxk;tj)VAR-ZsZ+QZ5{oy0HvP!X!7lOPx73Im z)W$KD{c+`?`Qn}KKv_esF*6Ix)y4QzFO3j=?WNb-x3mT2c}B{~Zxq@pP{8w7Z3dO# zy1L(nHP%*3V&-it+lMCw+oa4uA$mdz9H<9Qp$K=#(suUEDzD*Y6M@QqKw!L7X zgQ72LH0^4Dmh{ug)*G}K^fc-}*(`$sQ0RVQOGvVMM}frrdS4b8IG-X=LJoB$NQ_Lx z1ANqufp@*=U0xojnP`9Io3Xf`lDVTIY4HY$*v-9eI8Mk{x+kwMsCsJwh(v-RJ`9lD zqLryUS|Lbz5%sqONNAg0T`}D9@-l-nQ+0|r=2>$=y^{X&^1H8^Ro{LZ=9%+`en#Eg zWZwUM>|^AYc?rwDo|p1vD=(^|Tx1Vw(VE9LBc)|US_Gs&eru#jQJ3!t_8$ux8s=&m zdV711FG`4(&oeWP=*bHU{~SR5m=EXDh_NJzNtTq@#?%e7M^FrKP9af#F7YdHGvMMz@Kn|5?~i-gkJr89I~Wz?}U{kG|w9PS_R2@bXNd z(O4sHd3z)J`)S7HYl4H40V0k?NP{9)F>#RSuZRc6L%pX1~+pmzMsEmy8DN9>7HH$kw(c4 zN;pAXdL126%|#2GqGmZDO((CUs5;(H);>Q%?{5!%GF%4>P^9doE%K7#bFiY*U@YqnA;*OSCXJ~nYGICBMe`PtIuY_ik9|m zf%Z2KOYgiSUoEX)(n_SJ zi+fhIvI^HcUZ@c0_KPCCHbgo+Yi{vC&#S8inC z*_S>iPz({{8*)kD8eJ+nqLH6^N3#TTBj9P;tAp$wekG0l9kaeuE?@4GsbPfRpBB4W z+!1ov@*JBTjwlr&aU=)VCrJ1Ljo4lc6MmfF&T)&5b zzJZku@zXl)JB!#MOO)>JAd5N7>JI0sA^Co6tZR9|Pw8DBL)3vcWx+iPF6DYbMFqR) zAF+cO>olOkTph_F7wND)$;`~tJ8MtK53aUWak31N&JZIToQ6(qM@2+bDZ0VoQkYl) ztKf~u@N_Hc%t>>o16gGbHCZiS|Ao#jAX>3$0s3VTKyScKD`KxG>m?kF)6+X(k4P)f z_ZTzIF5HN7^Fv;qm4{-$aS0SmAd2!F`|j_Qq=&4CG&Iaey#myua7L zp>9L4G1Iuh1HC@$*lx^gh3uYKJxsS!D2}4WY_c5*R-aUAJ*$t{KWUoTOJo|sZfPzZ{Kg$&$N z9z^m`1Y{$anoSU8t!6X)Kx!ygC1RIMrNh> zogHxd*iK2z8HIFZeFZXrQ+}`>4#Pj?D+3S^&@&<+HNWQ>2fO65)l5(_)>v5-QE7+} zBLa(jgXaL8Mn2ALWpUPOaZpW74UoL;`G1J%m|t9^1I!$?@yH9hOTXADzL%YFOY*HO zDyd1>&yt8!j`)$<-!E&x$1c>*b}2RZ;o2+b^~SjWva$BzgJDn=1p$HCZ+7`fX_@d1 zBTapC(Z%>#tTXc69fK?AV1(QrpZx(KA_CavaaLLe6R>?7BbD0s2i&^Y!3grh!-`d6 z_&7y0|6oVl)zw_uE~~B&RpXO!IK>V{jmLgO#0r;O10GczsHTA%(H%Qkb#-;Rrw9!p zreVXsz8J87UUAu$^u8XCQ9dgE8iX(x(y=zYxb4XPn>J5Tv9heB!FBsk4jbeqd_yJ= zvB=;`VZ?+EKcVc`#w0-e5XZTCekN-tDflqpKcF_JR3Bd?j*4Y75o-%dONfL=jI+K> z@ZLE@F%Qf3418I|US9V%!ylMn|A_fg8vbsPAJ(+*=b@iVO!&#_%vEh67R$xP#F6}a+FWwP zwa%&6C4LiE12gj7p)<`$dtI5~u$%80s&GD;{1jJY>Y0bKa>e_G_XZw(Nc%tc8IP`_?Ojx)f~6JP zWO0n0RO9abP?ud@tPMPb`m~P`k!+5o_lr)yi*4F6F{NAqab@E#%h;+Mxo9i+@aZ4# zKLx-JGx;a>>`8xre+wc)up1Tl@S0R}6iUe^PE~vq`Te`c^1p@aj1@!tzI)L9vF?@| z#bDNenDVPEocMZ*BB?qkN#C&{(TFq9_P`jv`5WOAN@Q6%z5WUamXJYT;F3jjl+Uy4~@-;PSb`-PE2 zVG%;Fjn5#5FC@bMy*kT3fx4hvf~n8u6j@#>7Df%DZ$`#0#gx7|D71aHZ|3p4mJ z5>H$P?i7VU?S#o2?%FD>l@F%WbUigdo({ZI1s#rAES^t$d%HDjz1%p4JSu=NC_Hxs z3L69g@pxw=YY}h+EI&D!>rBcZ`)Ri%v{cYo`Cr~Yg(Csr(b`#i4f13M<4`qB0IQg$ z&cl5u)8sZPE-jp7pC|}doGQiT1g(dZ`&ZaB(#Rlufe|&R8U0peSvL6(_nAeCn z4P`LhN=3X2?<^ZuehI~aH zthF@zL33nmEYsrprB{XK`&eyK?RNhG@Gbg)P_WW|hw>KyH2(8w`e%UI6u``okBXLk z1S~mu;YJE}rN=@|Dx~_q=(vQmrxP^j7^x+YW0Y;bd`%7+h>-^h62LduL>(`2N52rT zmjDKeu)NshQ{h{;-^V?|4r9vcU62kJBw>=D>43}(DI`R?=BP`|+hRg_vF`IK@F{OC z?q*L6c2PQ?n%9IMErEHQz`$(0BQ=gngTme@(aV|f1!V$#|6Z(ow`aVA9JqEY z-;*hmk=X12#lgRTLD2_GYA!=d8yR2y*8jkPJ74nZek&RS6a>ox>p@^LCGAwa8h(nc ztzB}tkH-+;xSR}Ixz|Q}jgerN_Or-Fuhz2QDatJs`FJ0a^6L(ShK`xM%(p_#6(5i1 z6&(vWx_M0(!-h;A4q)dyBNHR75I+e>+a}?ss2^0d7$v!FzY*@S11``HAkf5syVHSp ztT#&)J7?XVZ3=*CGCdPoBm~9>U8135{=HuF1iCGZ_4Vx$c(D!vo-TX9h;1b{~{J1ry*U098Z>7&AK_o>?7)FE#qr350CFaa1BzfSiPqhD^tZ zq4LC6+Jka|;Rvwfw5rsKGwZPLmO8sWcS$9tRGYGP@=~Rhrd8ZIz1n>Xm`yAp5Gb`x zsCxK$S?WGLjN+f4YQzq91{}J&Y`0);on9mcbxR%`LK5OOaL%sIs@A+^pu)?Zb%dB$ei3#w2iUjU^^dab`^1=rV3y7ewjD2~ z*z)5mTAMfoT#0AG?@D>|Owjx{bU4z>4S(N(`kyP&5D|gE?C^ez)mu7?!;1gO5lG?v zDyHljO8&^c3VZdhnTi>(nohtW;y*aY98*g0ESbD(kp;|DGRlt8c6YR*e^Q8(0JW}#^3SbUynmhnN^Pmu; z24WH3AM<`-ltDqxP105VSX#2Jm50efjo#kg&fzuQ%F&mv4#~boSac`OiU&-#2`M|Q zS1}#!4DN<4J}vHwE-Mzn=X-MJ%KHMagO0KKiA+XTP8zEYh+TV(wX=651}4@gbKhXg zf`U>f3W0+raB4k|Ar9BMlQDmFnGFQlu*{fce;w80d`?I{!2k)IJnnMLV9@B(}?8>kV~9 zOgb@DmQ;;)UGDtjy4M7tw2GFVem*8KvmWPq&jtlE+v2N+tF!B=?eD1>QDta7zMWa? zQmgAr{jXTgqRMW(1#9Uh^HjcC>lD5@tj7pq=AzeD-oLe(bB#V?W$;Upk(K!v&YozZ z$r#PX)?!#ip@YXmiq>qYdH8r256(&eq-L%2Ic$T=khTHH`gRcUBQOtcFc*IyA8`6l z88u+UUhxNqcKzv3q4&Ot9I(%vWOSwiJug!xRN+|5!XVQ3SMI8mZQEblu`{1K9M?PL zu&Bh@9XpSV+Y2))I{(*nHi(Aqsw27Mqt>8&s(=HiE^ zAvrdTwWtU}_qa`!3CAP`2Qm@6Z!ld1!=aDem`!Jbk*J;h!cHUd? zEuGeyGx!mYjN-)jmFvw91LM?NU<$66_}#+{-xFGO^?6Q=L5!H3S1{|jH88*voT-kk zKQim=a|8&^{ZH8`XMjhs{fOP6F<}((uvaZULgwRf!1Fimc%e}T1On}}Sg|+=^8)oI z#AjXT&o7M7>v_+wwVmrl=DvITJmFyHlYeI`4W5mfhde5Vighdgk4iP>o8}}cN`9G{ zJfp2mF)8Cl)QyfUwxji)=bAzGi}licMvdCp3_?5g6b1!K;4$Rp+TBbLyPu!0)xcAG z!`OKVGuc3=AK2$a@TD98umL-G%Pb9%&i6ozONJWXuW$2h$N!)Pr9=@46CF?AlXP@` zT~LrXx3^olv~j9@*s-ed8gJu@xl$*1LyhNIjPIlSd?cRi7<1$EwMFUgC91(ItYaO| zHZ$7bh*SZ$c0^{0V{v~)z6yPZM+KBuuXc1Lv%Y5sF}KkF%%e&=@V8&Aok21YxUW`m z@}goHZQO+}yfKTp^d$&aNlyKwWfZNcsZ)%)ZGpg-5@PxtgRgVyQPxxjbZ#jO;L zr2fz?0CF{-ACO~$=S~(~KE|BV`De@P2QpG%-vZKsni>g0P1F}5;AkEOJe3O?3w01e z5P)XRO7AU$Wu(xo4x90p<=&33>y2_HM~6FKS1J1|a+*FOKb(LRi)-A1W)+S&juh8$=Qp7}d1}JMwZ5H^&6U+sBM|vuQN#gG#|zc>2V59BSR);8QLK7P>bW_D z=h-rjg*`rg*kN~nm_HOOZ-C)+1v=}MN}-K25tEbGIg2HDs>7D$2L76DdjbaKdO`s~ z-&srT*A12oX3sj;k}`&fV?T7FtKH7jc3p zP@ig5dji8cYkUMk@527bcCXC+fu-s+I!-zGYJb&l?S@D)u0DkqQl`FXXIS+-GGKMQ z)royj>wx{p{^;aXg{;*62LYP0DqNrnt_H>cYc!1QGH-l+TI55w?*T0d3-8#8KRMne zzFwzceupCPuzNdilDsZ{R^)qzpB=xf`4Kkda|u|ZTc&=m{i(3-4;CeCyH2L^*P-;j zX1ZOG6SswRhy9_yopSVN%58bnvpwLGGh+`We!LKWQWkrFz={{1bqGz74%10@#QjfA z&V$Dj0ZA`<1?YM!czQmxtS1Z03kd*yl6M7V#`u>TMl$i~sm-{@Xftol^r zyX|U{a8)|DP;(zknGoxLkX@h$-a0*XVqDZ-qwL0Azex?4@pkK=fW4g%W2-#!^#)_| zrw2ZTGf>qw19f0QdF9cgPvaOmh3M*edG^EPUT|zDGz4Pz=l37^j*E+DT#ok6^)~Uo0o3RE@FqppRWg`*f9ZWB29>MF0I(wRvvB3{3Kw<_JVli zwR9*0Q>%(?(%+%-!|>w0EZOP{x1XN4CgPDrC=ENGRFIuBcEUS*EfldyIV$p<>7y zp)83+_T41=zQtsl!C;2LScb`rnYqup?)!dlUH`!K;5QHEnBzR>!5rV?d!FZf-tW)* z^GZ(O*kzC$=UONC??`qB zQ=!E^Y;(jxK)t-`XEBo>GfA5V<>Nz#=*z;Rqk%5(^cRrSjePa87uJ9LK~0K# zF-&w)1UK90SH~uuGBG_ZRf+Xeh1A?jvB`gmjtzL)+QFbj{L~?qVZmFr+!J!HNDL{? zEhcr*WWb~B&I{Nn4WZkoFA1amOeuwD(}-d53s#uO(Jh%&d(R z?QGv}h$33+vdyIT0y*VT9)L&H=|_mMGa#`ruk7;Xr>8P8?UiyxJlt+s4SXY{7f6JL z(KPn9@~JneJ1=Pg3aFx|xOVZl+gJ0x`QN=2+!Tg}wtKIRShx(P5% zL*6 zAGAe%{5bi3ITL3X)fSu%rENDjt+z6rDZ!Djp|nSwxvG~zf2KyA)}xu4DQts`;5w)G zK+SwY1xEisN4NOBgVwb7@jm>~*y*yaFfb_2`ZF6Yi^tcSav%g42+& z!yib$VP7o-|M?I`odc&2LqqOiWa5yhIL`=Vt4B`j!C}iPibnNc-a?=4IE~$zlcrvj z&5*mkOEbHS6@R=~110+|jM!&P(SW;fYCdJDLH!jxokp5~{`LzJ(FKbaB7VTbNg`Wz z)TL76RUrtIeQ4cBvPgtn`@=#1!1%y{_6gFCD9a0qe*De* zc!j0f=TK7%1pcL%ST7n`N!@ALyVF)N5g^>Y-(y=;T|eE!zt0-8-K{>Ys=${D(xx;z zVUPceLW#FzX-SIM2}}$Kv|kkVsM0-c#e2MI3kTfq+o%!l{sUn6mc3tz!wpu!V?2#q zs!17mGcCLpu3rDIWQ?&(tSy6Y<6smMCPHtFojP{Bx$Be>%b@wgNL7>UuCLI4!;k#} zqTb5XiW~OteEIIPdtdRav-=6lw5{#+s<$u9L?4S!j-)TNSslE24Mfc}{S`kltPL2x zarQb~-@^bP!;GVFb3;z25?!C%;$#3>ds%Mau*@6yl6e zZYO_yY&*hKT`ZQ=NP4YOSNrhQqg1v&?y;1UuZS5Vwr)w!$)B2Pq1USW$ z49QuHIxWm(Z>bTV+^3XBlYjnZsPd*!Sbt>>g9 z`un5yp4T~iN=H_1M6;Y`^-g{;#d#)l<@)*?v@^Tz z%vZ#@9YlDyIx{n~^W;XryS!z&a9AX(U5m^**Y2}0S%$x^Bz;x!x9(^!QLBP*1_nFs zowQuV!RV}H_e};=K-yjev5jjs+@<@cq|_H0P4=dkS-E15PVMoN~mNG_dDj(H|k+6?a9+n2i^LK&Fa zKC?q-vx+)eruk?IHe6=qSQWue+|QJ=*e5G5sX7@LF5Y0bZ^8v&ExdHQ;)7)-MslHq9~=4&$H(^>X`S*Ob^q-WYBtJ+4!S zIXbX2tpM_M8YECu$|IER{^VAb-2JLgcHQi)imq1m&K=?!;Y*upm%k$(N$ty>JO!+P!joen9g|(li$rIlma^qC5%?+mR@q)!=#V&gf8Yj8GqH|=kO{| zRhpQD;IPJ(;td^0)TV|YZ%9E)l87!dt7wo{O^uwUK}N8eT51y1W#hLa+r(D4p^<6& zYxTY_y`(Ayeeq7Ki-!+vN<(L&#&sCd%0*zV^*0U$Y?AugH`mweh{;U+g>$;hAd^3Z z*LTP`0vAe8HFU zAtmeahM+JV<5vzm++$*-(CG4GbFQU9#3-VE)%=OJ9N~peB>Xj`@fG<6g&P>f&&w5G zgR^#!h6e5V9yPzN?ZX-+;OhphHXu|LVmO_pgpSk0#-ZU6-%-Q9KZ$P=Ql3y+PL71Y z;@l{)FlY}o$wV^X4#zSEEqnUO-Ce#_gnhYf)kJkMMEJKi11V3R9B?H*lLg;s9Jr10 z=&&Zv`?YLpgp6&!=ibzMpPH`xnHEs{daqIXNd(`8Zxd0X@{GjCNcyAh61imQ8~X&o z#b(#h!TtcawWaMAr)nn&Fv`9OQfTB3NYCa811b?H zvmmI&`C)rebd*f{kUoLQbWNc;Scv`(MV-qkGjrwx3w7OtrtLDr6MJ-6Q&jeRh@90c zn%$za%JTvDx5Ge+&TW71_x@-f1WM)M$;ecAbTMbTJUuj^wM}cAHYqs<`cd5`61?p` z^9jSjpss`%pVYQB^kAG1j;BT(9rCreTNSg`lX3q4T_Mpn7;o*fV<>}H7a5#Ye~W3$FGzj9 zfAg;&P!T4o)QYYkI}w*CQlB%v@`!{xS~yTh*AX`78(eKXtc~i~{X;vCwERd~tQhRM zqCkia9D3t;5K}&;etB&S*!M$5m zyN>l77Tr_iIZ9q;=GG*zC(Hv8rc7Q4#oC6tIR|nGYt=WB@W2PxlFvC=uSW}v)#_P3 z@iXXv!SIv&-!4BFRh~@+sLiq-oTrg>AQ>U{apAeqn#SOKt)iVCm!ym*k7R{A^jY^JI^)Yr+RVBUL2!g28=DZ5aeuA1D|b5g!h zSd7o6GK5R?nVJ!koB#vnD)u@WeZGD(yiMi%-4FhV>-wxss*Bn&Nk;Mu(m(t!=8}& zpwzH+H0`lJ)k!z>e$?Z*Q79R-YGIGy1?_U}kw!evhwbdbNw|}^pYsb-3*rgtl`Kq* zdA_+>7=a5p<$IA|Tie-(65LSH?`Vm`jxX!Y*SnQ}40;pP6Zqxj@eaLMC4FH8V9xwA z4wSe@XqZ^zm0kr+DNp;{e@H5Lzo-DAb)CX@Cs)EV{EP^0vFvpW@=8zKJGwxm1Ayb(2I)=2@7H%AHsjCyw)H^Y5K* zxdk<=M$RVe?)sHqHQRghM$VQ?FLcMv{g*#Ie@~~rxRUB(n8V5O03sK`)X}siUB5R% zjQz9?GNmwS8&HtXMeRFLs?#$JS&SQ;3vtcc=BGtN-t9)lqtA?19Rp_FZOu4k>R3P8 zYDBpAdY)GR7RGyRj7M^4uQHc5^&ZFZS@QZ(0k(FVG`_ono3>uG=!F}|H{%s z;*!eUHJ9NGM|FtjOkJloxt~beit)VT3LWEQ>{ZmvPDvWzSMXeryPkM(rgBa#==jU= z_AXr2HV*sY#F9{SGpsUyzJ1+=d@3e%e&77`N)?SVRWuisjOWYsFT>$pN1GFogC&y_O zw8I8Gf7;2@pvx+FPYy2vh6fV*;TIb}CDJv(q@Bp|Zf%}GK0 zDxF?8FnGpu!8Q<|2GZV-ImU}XWxwSLo%yE6Y|@Xvr%168g3S|blr#oy{CG!|-_3rU@tY??;aCB-8kcWVsLi}V2#H5m9Smxiw}+1|GH6|FGD9{y~}E| zc11KI&C>GGnn2l!$ETJZmmfH7SC?-q&TV7Uw#bJj4&#^9tjBN%?}sa~5$9(bFJ?Uk zAc%gsuci1D;@2^$DT&DX-El>~g6}`Nf}G}t^TX8(&!S`ZwjbVzk#v#~R_GH+O^l07 z03RPc3I0>sdpk02G4?t2J^=i!+h*wClD@k-w=Xem$lBD}(YEtX^=qo6wWJdruDVwI z^|kl5MxisLDBko80INK#_RXI*-sz`@7xQjfk~(T3wt~H8zTfhC)X=eTW1i;$ds9Fs zhgAU?1SO!96d?7$)ZXme5X5i;R?u96w%h!QM!--aj^I_BF~h;k;qGe z;C~$f@(7h@CirpwdR^aH+5izQKBevjCeLTC?h6mV^mV-4J^Z}|DoY$9blZ19sLbPuW&aC2^Sv|_6gtNs zw1Y2JztO%m61w6FCRbQW0~coeFgvD`EF9Li7OxP2!A(Obq$v;Q{??;ywCuf4!n*D< z6p(@}q9PsODZ*@eJI%B&pOnQ6!m(8P+Ot3A34jP8q6{iD;R>mc#%U`MzN7)6lD{|T zItGJ%5fJUm{89R7-%qo4)AmEGw@e<`=;{fIlGD|`QHLL{J_cdrIEjhV5+^&B&Madp zrH5@9+QPqe3BC;?SP7V8LQpzzs^E9loenWqRR7mHAE|*aN)IEGzY3($2Qsmx$flVF zZM0t5ty7w+4-0R#ye*^hHz2*!<~LZs0Aq4CgJ{*SoOQT22Uw{Ka8yGBH7k`{7$fo87wwXX}a|gk}4-=z$SvsX*X^nCIaQ#?bf{&rjiHz7Ue&vfX2@`y>Z%@Z?Y?{4S zCm@1YwOC!cLV7CIVK##vW zNtD>ExkU6|l3fP@zD)JC@xid9JXqn;(d7$U*OwT2@0X)(?t{H4&+jj%-UY)_H*=7m z(L3+<+Z*OEt*(I%JNE_T`lJ^LBn2i12Uof7#G##@HKSnP zL6mF$hfNgs>WKfF9zGlm}(BTI7r)%rR` z2#99`5#PFQl{=@>AN@hCI)HdLSg+gbtpY=j&vsQl_rd9`n2&NpajYNp4g;NnisqrX zT&r0@T{DqT6w7KTh*p|_#6#!wrTj3wx$p3l<&ufgrvzgpCF&%4IibN*;o%mQeojTH zUJaFd76voWk3_z=`WWGGDF~R)s z3=N#Y-*9L^=GoIRbW<&34{(U`R9HLlgnANGKF89Db|eDz*gwPYCut==8B}JTwD>v) z;aNNCX;)))9^2Y-AM+IqB1z|>tZliG-ooS>OOK;D2qk^U9G9g h(7zS<-?|b(ENH0x+cb;Sz`sB9mf>B43cbhC{|66erq=)f literal 0 HcmV?d00001 diff --git a/assets/images/ExpensifyHelp-WorkspaceSubmissions_ND.png b/assets/images/ExpensifyHelp-WorkspaceSubmissions_ND.png new file mode 100644 index 0000000000000000000000000000000000000000..140640369ab56f1c465774d1335cbb2342ee38df GIT binary patch literal 169824 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%0DhmZ>*gMz-7E@HVTMXdGLS(ENcHeIKkb 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 literal 0 HcmV?d00001 diff --git a/docs/articles/expensify-classic/reports/Automatically-submit-employee-reports.md b/docs/articles/expensify-classic/reports/Automatically-submit-employee-reports.md index cbc2ae5fbee66..885c75a9e0503 100644 --- a/docs/articles/expensify-classic/reports/Automatically-submit-employee-reports.md +++ b/docs/articles/expensify-classic/reports/Automatically-submit-employee-reports.md @@ -1,7 +1,8 @@ --- -title: Automatically Submit Employee Reports -description: Learn how to configure automatic report submissions in Expensify Classic using Submission Frequency in your Workspace settings. -keywords: [Expensify Classic, automatic report submission, delay submissions, submission frequency, expense report schedule] +title: Automatically submit employee reports +description: Learn how to configure automatic employee report submissions in Expensify Classic using the Submissions setting in your Workspace workflows. +internalScope: Audience is Workspace Admins. Covers how to enable and configure automatic employee report submissions in Expensify Classic. Does not cover manual report workflows or approval routing. +keywords: [Expensify Classic, automatic report submission, submission frequency, delay submissions, expense report schedule, Workspace workflows] --- @@ -9,11 +10,26 @@ By setting a submission schedule for your workspace, expenses are automatically --- -# Automatically Submit Employee Reports +# Automatically submit employee reports -When an employee creates an expense, it's automatically added to a report. If no report exists, a new one is created. Reports are then submitted according to the schedule you choose—daily, weekly, monthly, twice per month, by trip, or manually. +When Submissions is enabled, employee expenses are automatically added to a report and submitted for approval based on the schedule you choose. This saves your team from submitting reports manually. -**Note:** If you're using **Submission Frequency** and an expense has a violation, it won't be submitted until the violation is fixed. That expense is removed from the current report and added to a new open report. +If there’s no open report, a new one is created automatically. Reports are submitted according to your selected frequency - daily, weekly, twice per month, by trip, instantly, or manually. + +**Note:** Expenses with violations (like missing receipts or incorrect categories) won’t be submitted. They’re removed from the report and moved to a new open report. Once the violation is fixed, they'll be submitted on the next scheduled date. + +--- + +# Who can enable automatic report submissions + +Only **Workspace Admins** can turn on Submissions and choose a submission frequency for their Workspace. + +--- + +# Where to find the Submissions setting + +- **Web:** Go to the navigation tabs on the left and select **Workspaces > [Workspace Name] > Workflows** +- **Mobile:** Tap the hamburger menu in the top-left corner, then select **Workspaces > [Workspace Name] > Workflows** --- @@ -22,37 +38,62 @@ When an employee creates an expense, it's automatically added to a report. If no To enable and configure automatic submissions: 1. Go to **Settings > Workspace > [Workspace Name] > Workflows**. -2. Turn on **Submission Frequency** by toggling it on. -3. Select a **Submission frequency** from the following options: - - **Instantly** - Expenses are submitted upon creation. - - **Daily** – Reports are submitted every evening. Violations are submitted once corrected. - - **Weekly** – Reports are submitted weekly. Violations are submitted on Sunday after correction. - - **Twice a month** – Reports are submitted on the 15th and the last day of the month. Violations are submitted at the next applicable date. - - **Monthly** – Reports are submitted once a month on your selected day. Violations are submitted the following month. - - **By trip** – A report is submitted when no new expenses are added for two full days. A new trip report starts after that. - - **Manually** – Expenses are auto-added to a report, but employees must submit them manually. +2. Find the **Submissions** section +3. Toggle it on (green) +4. Choose **how often expenses submit**: + - **Instantly** — Expenses are submitted as soon as they’re created + - **Daily** — Reports are submitted each evening (Pacific Time) + - **Weekly** — Reports are submitted weekly on Sundays + - **Twice a month** — Reports are submitted on the 15th and last day of the month + - **By trip** — A report is submitted after two full days without new expenses + - **Manually** — Expenses are auto-added to reports, but members must submit manually + +![Submissions section in Expensify Workflows settings, showing the toggle enabled and Frequency set to By trip]({{site.url}}/assets/images/ExpensifyHelp-WorkspaceSubmissions_Classic.png){:width="100%"} + +--- + +## How to use the By trip submission frequency + +If your team travels often, choose **By trip** as your submission frequency. A report is submitted after two full days without any new expenses. A new trip report begins after that. + +That way, travel expenses are grouped together without needing to sort them manually. --- # FAQ -## I turned off Submission Frequency. Why are reports still being submitted automatically? +## What happens to expenses with violations? + +Expenses with violations—like missing receipts, incorrect categories, or amounts over Workspace limits—won’t be submitted. They’re removed from the current report and moved to a new open report. Once the violation is fixed, they’ll be submitted on the next scheduled date. + +## Why are reports still submitting automatically after disabling Submissions? + +If Submissions is disabled or set to **Manually** on the Workspace, check the member’s **Individual Workspace**. Their personal settings may still have Submissions enabled, which will apply by default. + +## What time of day does automatic submission happen? + +All scheduled report submissions occur in the **evening (Pacific Time)**, regardless of which frequency you choose. + +## Can I create separate automatic reports for each employee credit card? + +No. Expenses from multiple cards are combined into a single report, based on the selected frequency. -Turning off Submission Frequency for a Workspace doesn't affect an employee's Workspace settings. If reports are still auto-submitted, the employee will likely have Submission Frequency enabled in their workspace. +To separate them: +- Manually create reports for each card +- Filter by card and assign expenses to the correct report -## What time of day are reports submitted via Submission Frequency? +## Can employees override the Workspace submission schedule? -All automatic report submissions occur in the evening Pacific Standard Time (PST). +No. Once Submissions is enabled on the Workspace, it overrides any individual submission settings members may have in their own Workspaces. -## What happens if Submission Frequency is enabled on both the Individual and Company Workspace? +## Can automatic submissions be paused during month-end review? -The Company Workspace settings override the Individual Workspace settings. However, suppose your Company Workspace is configured to **Manually** submit reports, but an employee has Submission Frequency enabled on their **Individual Workspace** with a set frequency (like daily or weekly. In that case, their personal settings will control submission timing. Reports will be submitted automatically based on the frequency selected in their workspace. +There’s no pause button, but you can temporarily change the Frequency setting to **Manually** to prevent automatic submissions. Just switch it back after your review period. -## Does Submission Frequency automatically create separate reports for each of my credit cards? +## Can employees still submit manually if Submissions is turned on? -No. All expenses are collected into a single report and submitted based on the selected frequency. +Yes. Employees can submit reports manually at any time—even if a scheduled frequency (like Daily or By trip) is selected. The schedule just automates submission if they don’t act first. -If you need reports separated by card: -- Manually create reports for each card and assign expenses accordingly. -- Use filters to group expenses by card before assigning them to reports. +## Do scheduled submissions include all unsubmitted expenses? +Only compliant expenses will be submitted. Expenses with violations, missing data, or issues will stay in an open report until fixed. diff --git a/docs/articles/new-expensify/reports-and-expenses/How-to-Set-Up-Automatic-Report-Submissions.md b/docs/articles/new-expensify/reports-and-expenses/How-to-Set-Up-Automatic-Report-Submissions.md new file mode 100644 index 0000000000000..e8f56f4d816e4 --- /dev/null +++ b/docs/articles/new-expensify/reports-and-expenses/How-to-Set-Up-Automatic-Report-Submissions.md @@ -0,0 +1,94 @@ +--- +title: How to set up automatic employee report submissions +description: Enable Submissions to automatically submit employee expenses on a custom schedule—daily, weekly, by trip, and more. +keywords: [submit reports automatically, expense submission schedule, Submissions toggle, report frequency, Workspace Admin, expense automation, submit by trip] +internalScope: Audience is Workspace Admins. Covers how to enable and configure automatic report submissions using the Submissions setting. Does not cover manual report workflows or approval routing. +--- + +# How to set up automatic employee report submissions + +When Submissions is enabled, employee expenses are automatically added to a report and submitted for approval based on the schedule you choose. This saves your team from submitting reports manually. + +If there’s no open report, a new one is created automatically. Reports are submitted according to your selected frequency—daily, weekly, twice per month, by trip, instantly, or manually. + +**Note:** Expenses with violations (like missing receipts or categories) won’t be submitted. See the FAQ below for how those expenses are handled. + +--- + +# Who can enable automatic report submissions + +Only **Workspace Admins** can turn on Submissions and choose a submission frequency for their Workspace. + +--- + +# Where to find the Submissions setting + +- **Web:** Go to the navigation tabs on the left and select **Workspaces > [Workspace Name] > Workflows** +- **Mobile:** Tap the hamburger menu in the top-left corner, then select **Workspaces > [Workspace Name] > Workflows** + +--- + +# How to enable Submissions and choose a schedule + +1. Go to **Workspaces > [Workspace Name] > Workflows** +2. Find the **Submissions** section +3. Toggle it on (green) +4. Select your preferred **Frequency**: + - **Instantly** — Expenses are submitted as soon as they’re created + - **Daily** — Reports are submitted each evening (Pacific Time) + - **Weekly** — Reports are submitted weekly on Sundays + - **Twice a month** — Reports are submitted on the 15th and last day of the month + - **By trip** — A report is submitted after two full days without new expenses + - **Manually** — Expenses are auto-added to reports, but members must submit manually + +![Submissions section in Expensify Workflows settings, showing the toggle enabled and Frequency set to By trip]({{site.url}}/assets/images/ExpensifyHelp-WorkspaceSubmissions_ND.png){:width="100%"} + +assets/images/ExpensifyHelp-WorkspaceSubmissions_Classic.png +--- + +## How to use the By trip submission frequency + +If your team travels often, choose **By trip** as your submission frequency. A report is submitted after two full days without any new expenses. A new trip report begins after that. + +That way, travel expenses are grouped together without needing to sort them manually. + +--- + +# FAQ + +## What happens to expenses with violations? + +Expenses with violations—like missing receipts, incorrect categories, or amounts over Workspace limits—won’t be submitted. They’re removed from the current report and moved to a new open report. Once the violation is fixed, they’ll be submitted on the next scheduled date. + +## Why are reports still submitting automatically after disabling Submissions + +If Submissions is disabled or set to **Manually** on the Workspace, check the member’s **Individual Workspace**. Their personal settings may still have Submissions enabled, which will apply by default. + +## What time of day does automatic submission happen? + +All scheduled report submissions occur in the **evening (Pacific Time)**, regardless of which frequency you choose. + +## Can separate reports be created automatically for each employee credit card? + +No. Expenses from multiple cards are combined into a single report, based on the selected frequency. + +To separate them: +- Manually create reports for each card +- Filter by card and assign expenses to the correct report + +## Can employees override the Workspace submission schedule? + +No. Once Submissions is enabled on the Workspace, it overrides any individual submission settings members may have in their own Workspaces. + +## Can automatic submissions be paused during month-end review? + +There’s no pause button, but you can temporarily change the Frequency setting to **Manually** to prevent automatic submissions. Just switch it back after your review period. + +## Can employees still submit manually if Submissions is turned on? + +Yes. Employees can submit reports manually at any time—even if a scheduled frequency (like Daily or By trip) is selected. The schedule just automates submission if they don’t act first. + +## Do scheduled submissions include all unsubmitted expenses? + +Only compliant expenses will be submitted. Expenses with violations, missing data, or issues will stay in an open report until fixed. + diff --git a/ios/NewExpensify/Info.plist b/ios/NewExpensify/Info.plist index 26ac97151fe08..57a7167ba5584 100644 --- a/ios/NewExpensify/Info.plist +++ b/ios/NewExpensify/Info.plist @@ -44,7 +44,7 @@ CFBundleVersion - 9.3.10.1 + 9.3.10.3 FullStory OrgId diff --git a/ios/NotificationServiceExtension/Info.plist b/ios/NotificationServiceExtension/Info.plist index 97c57789d0770..200918ea5cd0a 100644 --- a/ios/NotificationServiceExtension/Info.plist +++ b/ios/NotificationServiceExtension/Info.plist @@ -13,7 +13,7 @@ CFBundleShortVersionString 9.3.10 CFBundleVersion - 9.3.10.1 + 9.3.10.3 NSExtension NSExtensionPointIdentifier diff --git a/ios/ShareViewController/Info.plist b/ios/ShareViewController/Info.plist index 620c91b72c9fc..33798a26ef59f 100644 --- a/ios/ShareViewController/Info.plist +++ b/ios/ShareViewController/Info.plist @@ -13,7 +13,7 @@ CFBundleShortVersionString 9.3.10 CFBundleVersion - 9.3.10.1 + 9.3.10.3 NSExtension NSExtensionAttributes diff --git a/package-lock.json b/package-lock.json index 2d87f27945ce6..a29dd074780b0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "new.expensify", - "version": "9.3.10-1", + "version": "9.3.10-3", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "new.expensify", - "version": "9.3.10-1", + "version": "9.3.10-3", "hasInstallScript": true, "license": "MIT", "dependencies": { diff --git a/package.json b/package.json index 1601fd30082ee..dce249efff898 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "new.expensify", - "version": "9.3.10-1", + "version": "9.3.10-3", "author": "Expensify, Inc.", "homepage": "https://new.expensify.com", "description": "New Expensify is the next generation of Expensify: a reimagination of payments based atop a foundation of chat.", diff --git a/src/CONST/index.ts b/src/CONST/index.ts index 418d651fcb5a0..33e7de6cc1003 100755 --- a/src/CONST/index.ts +++ b/src/CONST/index.ts @@ -743,6 +743,7 @@ const CONST = { NEW_DOT_DEW: 'newDotDEW', GPS_MILEAGE: 'gpsMileage', NEW_DOT_HOME: 'newDotHome', + PERSONAL_CARD_IMPORT: 'personalCardImport', }, BUTTON_STATES: { DEFAULT: 'default', @@ -3768,6 +3769,18 @@ const CONST = { DELETE: 'delete', }, }, + MERCHANT_RULES: { + FIELDS: { + BILLABLE: 'billable', + CATEGORY: 'category', + DESCRIPTION: 'comment', + MERCHANT_TO_MATCH: 'merchantToMatch', + MERCHANT: 'merchant', + REIMBURSABLE: 'reimbursable', + TAG: 'tag', + TAX: 'tax', + }, + }, get SUBSCRIPTION_PRICES() { return { @@ -6870,6 +6883,7 @@ const CONST = { WITHDRAWAL_ID: 'withdrawal-id', CATEGORY: 'category', MERCHANT: 'merchant', + TAG: 'tag', MONTH: 'month', }, get TYPE_CUSTOM_COLUMNS() { @@ -6957,6 +6971,11 @@ const CONST = { EXPENSES: this.TABLE_COLUMNS.GROUP_EXPENSES, TOTAL: this.TABLE_COLUMNS.GROUP_TOTAL, }, + TAG: { + TAG: this.TABLE_COLUMNS.GROUP_TAG, + EXPENSES: this.TABLE_COLUMNS.GROUP_EXPENSES, + TOTAL: this.TABLE_COLUMNS.GROUP_TOTAL, + }, MONTH: { MONTH: this.TABLE_COLUMNS.GROUP_MONTH, EXPENSES: this.TABLE_COLUMNS.GROUP_EXPENSES, @@ -7005,6 +7024,7 @@ const CONST = { ], CATEGORY: [this.TABLE_COLUMNS.GROUP_CATEGORY, this.TABLE_COLUMNS.GROUP_EXPENSES, this.TABLE_COLUMNS.GROUP_TOTAL], MERCHANT: [this.TABLE_COLUMNS.GROUP_MERCHANT, this.TABLE_COLUMNS.GROUP_EXPENSES, this.TABLE_COLUMNS.GROUP_TOTAL], + TAG: [this.TABLE_COLUMNS.GROUP_TAG, this.TABLE_COLUMNS.GROUP_EXPENSES, this.TABLE_COLUMNS.GROUP_TOTAL], MONTH: [this.TABLE_COLUMNS.GROUP_MONTH, this.TABLE_COLUMNS.GROUP_EXPENSES, this.TABLE_COLUMNS.GROUP_TOTAL], }; }, @@ -7103,6 +7123,7 @@ const CONST = { GROUP_WITHDRAWAL_ID: 'groupWithdrawalID', GROUP_CATEGORY: 'groupCategory', GROUP_MERCHANT: 'groupMerchant', + GROUP_TAG: 'groupTag', GROUP_MONTH: 'groupmonth', }, SYNTAX_OPERATORS: { @@ -7294,6 +7315,7 @@ const CONST = { [this.TABLE_COLUMNS.GROUP_WITHDRAWAL_ID]: 'group-withdrawal-id', [this.TABLE_COLUMNS.GROUP_CATEGORY]: 'group-category', [this.TABLE_COLUMNS.GROUP_MERCHANT]: 'group-merchant', + [this.TABLE_COLUMNS.GROUP_TAG]: 'group-tag', }; }, NOT_MODIFIER: 'Not', diff --git a/src/ONYXKEYS.ts b/src/ONYXKEYS.ts index 6ed6bf06f807a..836b321d7018e 100755 --- a/src/ONYXKEYS.ts +++ b/src/ONYXKEYS.ts @@ -980,6 +980,8 @@ const ONYXKEYS = { SPLIT_EXPENSE_EDIT_DATES_DRAFT: 'splitExpenseEditDatesDraft', EXPENSE_RULE_FORM: 'expenseRuleForm', EXPENSE_RULE_FORM_DRAFT: 'expenseRuleFormDraft', + MERCHANT_RULE_FORM: 'merchantRuleForm', + MERCHANT_RULE_FORM_DRAFT: 'merchantRuleFormDraft', ADD_DOMAIN_MEMBER_FORM: 'addDomainMemberForm', ADD_DOMAIN_MEMBER_FORM_DRAFT: 'addDomainMemberFormDraft', }, @@ -1103,6 +1105,7 @@ type OnyxFormValuesMapping = { [ONYXKEYS.FORMS.CREATE_DOMAIN_FORM]: FormTypes.CreateDomainForm; [ONYXKEYS.FORMS.SPLIT_EXPENSE_EDIT_DATES]: FormTypes.SplitExpenseEditDateForm; [ONYXKEYS.FORMS.EXPENSE_RULE_FORM]: FormTypes.ExpenseRuleForm; + [ONYXKEYS.FORMS.MERCHANT_RULE_FORM]: FormTypes.MerchantRuleForm; [ONYXKEYS.FORMS.ADD_DOMAIN_MEMBER_FORM]: FormTypes.AddDomainMemberForm; }; diff --git a/src/ROUTES.ts b/src/ROUTES.ts index d0bb5e0ed1e8d..2c545c30d0c4d 100644 --- a/src/ROUTES.ts +++ b/src/ROUTES.ts @@ -2670,6 +2670,42 @@ const ROUTES = { route: 'workspaces/:policyID/overview/policy', getRoute: (policyID: string) => `workspaces/${policyID}/overview/policy` as const, }, + RULES_MERCHANT_NEW: { + route: 'workspaces/:policyID/rules/merchant-rules/new', + getRoute: (policyID: string) => `workspaces/${policyID}/rules/merchant-rules/new` as const, + }, + RULES_MERCHANT_MERCHANT_TO_MATCH: { + route: 'workspaces/:policyID/rules/merchant-rules/new/merchant-to-match', + getRoute: (policyID: string) => `workspaces/${policyID}/rules/merchant-rules/new/merchant-to-match` as const, + }, + RULES_MERCHANT_MERCHANT: { + route: 'workspaces/:policyID/rules/merchant-rules/new/merchant', + getRoute: (policyID: string) => `workspaces/${policyID}/rules/merchant-rules/new/merchant` as const, + }, + RULES_MERCHANT_CATEGORY: { + route: 'workspaces/:policyID/rules/merchant-rules/new/category', + getRoute: (policyID: string) => `workspaces/${policyID}/rules/merchant-rules/new/category` as const, + }, + RULES_MERCHANT_TAG: { + route: 'workspaces/:policyID/rules/merchant-rules/new/tag', + getRoute: (policyID: string) => `workspaces/${policyID}/rules/merchant-rules/new/tag` as const, + }, + RULES_MERCHANT_TAX: { + route: 'workspaces/:policyID/rules/merchant-rules/new/tax', + getRoute: (policyID: string) => `workspaces/${policyID}/rules/merchant-rules/new/tax` as const, + }, + RULES_MERCHANT_DESCRIPTION: { + route: 'workspaces/:policyID/rules/merchant-rules/new/description', + getRoute: (policyID: string) => `workspaces/${policyID}/rules/merchant-rules/new/description` as const, + }, + RULES_MERCHANT_REIMBURSABLE: { + route: 'workspaces/:policyID/rules/merchant-rules/new/reimbursable', + getRoute: (policyID: string) => `workspaces/${policyID}/rules/merchant-rules/new/reimbursable` as const, + }, + RULES_MERCHANT_BILLABLE: { + route: 'workspaces/:policyID/rules/merchant-rules/new/billable', + getRoute: (policyID: string) => `workspaces/${policyID}/rules/merchant-rules/new/billable` as const, + }, // Referral program promotion REFERRAL_DETAILS_MODAL: { route: 'referral/:contentType', diff --git a/src/SCREENS.ts b/src/SCREENS.ts index c672d4e1a0c80..8990581734f30 100644 --- a/src/SCREENS.ts +++ b/src/SCREENS.ts @@ -758,6 +758,15 @@ const SCREENS = { RULES_REIMBURSABLE_DEFAULT: 'Rules_Reimbursable_Default', RULES_CUSTOM: 'Rules_Custom', RULES_PROHIBITED_DEFAULT: 'Rules_Prohibited_Default', + RULES_MERCHANT_NEW: 'Rules_Merchant_New', + RULES_MERCHANT_MERCHANT_TO_MATCH: 'Rules_Merchant_Merchant_To_Match', + RULES_MERCHANT_MERCHANT: 'Rules_Merchant_Merchant', + RULES_MERCHANT_CATEGORY: 'Rules_Merchant_Category', + RULES_MERCHANT_TAG: 'Rules_Merchant_Tag', + RULES_MERCHANT_TAX: 'Rules_Merchant_Tax', + RULES_MERCHANT_DESCRIPTION: 'Rules_Merchant_Description', + RULES_MERCHANT_REIMBURSABLE: 'Rules_Merchant_Reimbursable', + RULES_MERCHANT_BILLABLE: 'Rules_Merchant_Billable', PER_DIEM: 'Per_Diem', PER_DIEM_IMPORT: 'Per_Diem_Import', PER_DIEM_IMPORTED: 'Per_Diem_Imported', diff --git a/src/components/Rule/RuleBooleanBase.tsx b/src/components/Rule/RuleBooleanBase.tsx index 1e06c4fa3137a..7800c80e486df 100644 --- a/src/components/Rule/RuleBooleanBase.tsx +++ b/src/components/Rule/RuleBooleanBase.tsx @@ -9,45 +9,54 @@ import type {ListItem} from '@components/SelectionList/ListItem/types'; import useLocalize from '@hooks/useLocalize'; import useOnyx from '@hooks/useOnyx'; import useThemeStyles from '@hooks/useThemeStyles'; -import {updateDraftRule} from '@libs/actions/User'; -import Navigation from '@libs/Navigation/Navigation'; import CONST from '@src/CONST'; import type {TranslationPaths} from '@src/languages/types'; -import ONYXKEYS from '@src/ONYXKEYS'; -import ROUTES from '@src/ROUTES'; -import type {InputID} from '@src/types/form/ExpenseRuleForm'; +import type {OnyxFormKey} from '@src/ONYXKEYS'; import RuleNotFoundPageWrapper from './RuleNotFoundPageWrapper'; type BooleanFilterItem = ListItem & { value: ValueOf; }; -type RuleBooleanBasePageProps = { - /** The key from boolean-based InputID */ - fieldID: InputID; +type RuleBooleanBaseProps = { + /** The field ID from the form */ + fieldID: string; /** The translation key for the page title */ titleKey: TranslationPaths; - /** The rule identifier */ + /** The form ID to read from Onyx */ + formID: OnyxFormKey; + + /** Callback when a value is selected - receives boolean for merchant rules, string for personal rules */ + onSelect: (fieldID: string, value: boolean | 'true' | 'false' | null) => void; + + /** Callback to go back */ + onBack: () => void; + + /** Optional hash for rule not found validation */ hash?: string; + + /** Whether to use string values ('true'/'false') instead of boolean values (for ExpenseRuleForm compatibility) */ + useStringValues?: boolean; }; const booleanValues = Object.values(CONST.SEARCH.BOOLEAN); -function RuleBooleanBasePage({fieldID, titleKey, hash}: RuleBooleanBasePageProps) { +function RuleBooleanBase({fieldID, titleKey, formID, onSelect, onBack, hash, useStringValues = false}: RuleBooleanBaseProps) { const {translate} = useLocalize(); - const [form] = useOnyx(ONYXKEYS.FORMS.EXPENSE_RULE_FORM, {canBeMissing: true}); + const [form] = useOnyx(formID, {canBeMissing: true}); const styles = useThemeStyles(); - const selectedItem = - booleanValues.find((value) => { - if (!form?.[fieldID]) { - return false; - } - const booleanValue = form[fieldID] === 'true' ? CONST.SEARCH.BOOLEAN.YES : CONST.SEARCH.BOOLEAN.NO; - return booleanValue === value; - }) ?? null; + const formValue = (form as Record)?.[fieldID]; + + let selectedItem = null; + if (formValue !== undefined) { + // Handle both string ('true'/'false') and boolean (true/false) values + const isTruthy = useStringValues ? formValue === 'true' : formValue === true; + const booleanValue = isTruthy ? CONST.SEARCH.BOOLEAN.YES : CONST.SEARCH.BOOLEAN.NO; + selectedItem = booleanValues.find((value) => booleanValue === value) ?? null; + } const items = booleanValues.map((value) => ({ value, @@ -56,26 +65,26 @@ function RuleBooleanBasePage({fieldID, titleKey, hash}: RuleBooleanBasePageProps isSelected: selectedItem === value, })); - const goBack = () => { - Navigation.goBack(hash ? ROUTES.SETTINGS_RULES_EDIT.getRoute(hash) : ROUTES.SETTINGS_RULES_ADD.getRoute()); - }; - const onSelectItem = (selectedValue: BooleanFilterItem) => { - const newValue = selectedValue.isSelected ? null : selectedValue.value; - let value = ''; - if (newValue === CONST.SEARCH.BOOLEAN.YES) { - value = 'true'; - } else if (newValue === CONST.SEARCH.BOOLEAN.NO) { - value = 'false'; + // If clicking on already-selected item, unselect it (set to undefined) + if (selectedValue.isSelected) { + onSelect(fieldID, null); + return; + } + const isYes = selectedValue.value === CONST.SEARCH.BOOLEAN.YES; + let value: boolean | 'true' | 'false'; + if (useStringValues) { + value = isYes ? 'true' : 'false'; + } else { + value = isYes; } - updateDraftRule({[fieldID]: value}); - goBack(); + onSelect(fieldID, value); }; return ( void; + + /** Callback to go back */ + onBack: () => void; + + /** The route to navigate back to */ + backToRoute: Route; + + /** Optional hash for rule not found validation */ + hash?: string; +}; + +function RuleSelectionBase({titleKey, testID, selectedItem, items, onSave, onBack, backToRoute, hash}: RuleSelectionBaseProps) { + const styles = useThemeStyles(); + const {translate} = useLocalize(); + + return ( + + + + + + + + + ); +} + +export default RuleSelectionBase; diff --git a/src/components/Rule/RuleTextBase.tsx b/src/components/Rule/RuleTextBase.tsx index 9775aa2027c23..98ed7f2c84760 100644 --- a/src/components/Rule/RuleTextBase.tsx +++ b/src/components/Rule/RuleTextBase.tsx @@ -4,20 +4,14 @@ import HeaderWithBackButton from '@components/HeaderWithBackButton'; import ScreenWrapper from '@components/ScreenWrapper'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; -import {updateDraftRule} from '@libs/actions/User'; -import Navigation from '@libs/Navigation/Navigation'; -import CONST from '@src/CONST'; import type {TranslationPaths} from '@src/languages/types'; -import type ONYXKEYS from '@src/ONYXKEYS'; -import ROUTES from '@src/ROUTES'; -import type {InputID} from '@src/types/form/ExpenseRuleForm'; +import type {OnyxFormKey} from '@src/ONYXKEYS'; import RuleNotFoundPageWrapper from './RuleNotFoundPageWrapper'; import TextBase from './TextBase'; -// Text-based field IDs that accept string input -type RuleTextBaseProps = { +type RuleTextBaseProps = { /** The key from text-based InputID */ - fieldID: InputID; + fieldID: string; /** The translation key for the page title and input label if labelKey is missing */ titleKey: TranslationPaths; @@ -37,23 +31,23 @@ type RuleTextBaseProps = { /** The character limit for the input */ characterLimit?: number; - /** The rule identifier */ + /** The form ID to read from Onyx */ + formID: TFormID; + + /** Callback when the form is saved */ + onSave: (values: FormOnyxValues) => void; + + /** Callback to go back */ + onBack: () => void; + + /** Optional hash for rule not found validation */ hash?: string; }; -function RuleTextBase({fieldID, hintKey, isRequired, titleKey, labelKey, testID, hash, characterLimit = CONST.MERCHANT_NAME_MAX_BYTES}: RuleTextBaseProps) { +function RuleTextBase({fieldID, hintKey, isRequired, titleKey, labelKey, testID, characterLimit, formID, onSave, onBack, hash}: RuleTextBaseProps) { const {translate} = useLocalize(); const styles = useThemeStyles(); - const goBack = () => { - Navigation.goBack(hash ? ROUTES.SETTINGS_RULES_EDIT.getRoute(hash) : ROUTES.SETTINGS_RULES_ADD.getRoute()); - }; - - const onSave = (values: FormOnyxValues) => { - updateDraftRule(values); - goBack(); - }; - return ( = { + fieldID: string; hint?: string; isRequired?: boolean; title: string; label: string; characterLimit?: number; - onSubmit: (values: FormOnyxValues) => void; + formID: TFormID; + onSubmit: (values: FormOnyxValues) => void; }; -function TextBase({fieldID, hint, isRequired, title, label, onSubmit, characterLimit = CONST.MERCHANT_NAME_MAX_BYTES}: TextBaseProps) { +function TextBase({fieldID, hint, isRequired, title, label, onSubmit, formID, characterLimit = CONST.MERCHANT_NAME_MAX_BYTES}: TextBaseProps) { const {translate} = useLocalize(); - const [form] = useOnyx(ONYXKEYS.FORMS.EXPENSE_RULE_FORM, {canBeMissing: true}); + const [form] = useOnyx(formID, {canBeMissing: true}); const styles = useThemeStyles(); - const currentValue = form?.[fieldID] ?? ''; + const currentValue = (form as Record)?.[fieldID] ?? ''; const {inputCallbackRef} = useAutoFocusInput(); - const validate = (values: FormOnyxValues) => { - const errors: FormInputErrors = {}; - const fieldValue = values[fieldID] ?? ''; + const validate = (values: FormOnyxValues) => { + const errors: FormInputErrors = {}; + const fieldValue = values[fieldID as keyof FormOnyxValues] ?? ''; if (typeof fieldValue !== 'string') { return errors; @@ -42,12 +42,12 @@ function TextBase({fieldID, hint, isRequired, title, label, onSubmit, characterL const trimmedValue = fieldValue.trim(); if (isRequired && !isRequiredFulfilled(fieldValue)) { - errors[fieldID] = translate('common.error.fieldRequired'); + (errors as Record)[fieldID] = translate('common.error.fieldRequired'); } else { const {isValid, byteLength} = isValidInputLength(trimmedValue, characterLimit); if (!isValid) { - errors[fieldID] = translate('common.error.characterLimitExceedCounter', byteLength, characterLimit); + (errors as Record)[fieldID] = translate('common.error.characterLimitExceedCounter', byteLength, characterLimit); } } @@ -57,7 +57,7 @@ function TextBase({fieldID, hint, isRequired, title, label, onSubmit, characterL return ( filter.key !== CONST.SEARCH.SYNTAX_FILTER_KEYS.TAG); + newFlatFilters.push({key: CONST.SEARCH.SYNTAX_FILTER_KEYS.TAG, filters: [{operator: CONST.SEARCH.SYNTAX_OPERATORS.EQUAL_TO, value: tagValue}]}); + const newQueryJSON: SearchQueryJSON = {...queryJSON, groupBy: undefined, flatFilters: newFlatFilters}; + const newQuery = buildSearchQueryString(newQueryJSON); + const newQueryJSONWithHash = buildSearchQueryJSON(newQuery); + if (!newQueryJSONWithHash) { + return; + } + handleSearch({queryJSON: newQueryJSONWithHash, searchKey, offset: 0, shouldCalculateTotals: false, isLoading: false}); + return; + } + if (isTransactionMonthGroupListItemType(item)) { const newFlatFilters = queryJSON.flatFilters.filter((filter) => filter.key !== CONST.SEARCH.SYNTAX_FILTER_KEYS.DATE); const {start: monthStart, end: monthEnd} = DateUtils.getMonthDateRange(item.year, item.month); diff --git a/src/components/Search/types.ts b/src/components/Search/types.ts index c4d635dff4a0f..0019a764dc943 100644 --- a/src/components/Search/types.ts +++ b/src/components/Search/types.ts @@ -126,6 +126,7 @@ type SearchCustomColumnIds = | ValueOf | ValueOf | ValueOf + | ValueOf | ValueOf; type SearchContextData = { diff --git a/src/components/SelectionListWithSections/Search/TagListItemHeader.tsx b/src/components/SelectionListWithSections/Search/TagListItemHeader.tsx new file mode 100644 index 0000000000000..cdd6bf743c2af --- /dev/null +++ b/src/components/SelectionListWithSections/Search/TagListItemHeader.tsx @@ -0,0 +1,144 @@ +import React from 'react'; +import {View} from 'react-native'; +import Checkbox from '@components/Checkbox'; +import type {SearchColumnType} from '@components/Search/types'; +import type {ListItem, TransactionTagGroupListItemType} from '@components/SelectionListWithSections/types'; +import TextWithTooltip from '@components/TextWithTooltip'; +import useLocalize from '@hooks/useLocalize'; +import useResponsiveLayout from '@hooks/useResponsiveLayout'; +import useStyleUtils from '@hooks/useStyleUtils'; +import useThemeStyles from '@hooks/useThemeStyles'; +import CONST from '@src/CONST'; +import ExpandCollapseArrowButton from './ExpandCollapseArrowButton'; +import TextCell from './TextCell'; +import TotalCell from './TotalCell'; + +type TagListItemHeaderProps = { + /** The tag currently being looked at */ + tag: TransactionTagGroupListItemType; + + /** Callback to fire when a checkbox is pressed */ + onCheckboxPress?: (item: TItem) => void; + + /** Whether this section items disabled for selection */ + isDisabled?: boolean | null; + + /** Whether selecting multiple transactions at once is allowed */ + canSelectMultiple: boolean | undefined; + + /** Whether all transactions are selected */ + isSelectAllChecked?: boolean; + + /** Whether only some transactions are selected */ + isIndeterminate?: boolean; + + /** Callback for when the down arrow is clicked */ + onDownArrowClick?: () => void; + + /** Whether the down arrow is expanded */ + isExpanded?: boolean; + + /** The visible columns for the header */ + columns?: SearchColumnType[]; +}; + +function TagListItemHeader({ + tag: tagItem, + onCheckboxPress, + isDisabled, + canSelectMultiple, + isSelectAllChecked, + isIndeterminate, + isExpanded, + onDownArrowClick, + columns, +}: TagListItemHeaderProps) { + const styles = useThemeStyles(); + const StyleUtils = useStyleUtils(); + const {isLargeScreenWidth} = useResponsiveLayout(); + const {translate} = useLocalize(); + + // formattedTag is already translated to "No tag" for empty values in SearchUIUtils + const tagName = tagItem.formattedTag ?? tagItem.tag ?? ''; + + const columnComponents = { + [CONST.SEARCH.TABLE_COLUMNS.GROUP_TAG]: ( + + + + + + ), + [CONST.SEARCH.TABLE_COLUMNS.GROUP_EXPENSES]: ( + + + + ), + [CONST.SEARCH.TABLE_COLUMNS.GROUP_TOTAL]: ( + + + + ), + }; + + return ( + + + + {!!canSelectMultiple && ( + onCheckboxPress?.(tagItem as unknown as TItem)} + isChecked={isSelectAllChecked} + isIndeterminate={isIndeterminate} + disabled={!!isDisabled || tagItem.isDisabledCheckbox} + accessibilityLabel={translate('common.select')} + style={isLargeScreenWidth && styles.mr1} + /> + )} + {!isLargeScreenWidth && ( + + + + + + )} + {isLargeScreenWidth && columns?.map((column) => columnComponents[column as keyof typeof columnComponents])} + + {!isLargeScreenWidth && ( + + + {!!onDownArrowClick && ( + + )} + + )} + + + ); +} + +export default TagListItemHeader; diff --git a/src/components/SelectionListWithSections/Search/TransactionGroupListItem.tsx b/src/components/SelectionListWithSections/Search/TransactionGroupListItem.tsx index 530eee586623b..e6c8dd5daaadf 100644 --- a/src/components/SelectionListWithSections/Search/TransactionGroupListItem.tsx +++ b/src/components/SelectionListWithSections/Search/TransactionGroupListItem.tsx @@ -21,6 +21,7 @@ import type { TransactionMerchantGroupListItemType, TransactionMonthGroupListItemType, TransactionReportGroupListItemType, + TransactionTagGroupListItemType, TransactionWithdrawalIDGroupListItemType, } from '@components/SelectionListWithSections/types'; import useAnimatedHighlightStyle from '@hooks/useAnimatedHighlightStyle'; @@ -47,6 +48,7 @@ import MemberListItemHeader from './MemberListItemHeader'; import MerchantListItemHeader from './MerchantListItemHeader'; import MonthListItemHeader from './MonthListItemHeader'; import ReportListItemHeader from './ReportListItemHeader'; +import TagListItemHeader from './TagListItemHeader'; import TransactionGroupListExpandedItem from './TransactionGroupListExpanded'; import WithdrawalIDListItemHeader from './WithdrawalIDListItemHeader'; @@ -313,6 +315,19 @@ function TransactionGroupListItem({ isExpanded={isExpanded} /> ), + [CONST.SEARCH.GROUP_BY.TAG]: ( + + ), [CONST.SEARCH.GROUP_BY.MONTH]: ( = CommonListItemProps & { /** The section list item */ item: TItem; @@ -1161,6 +1167,7 @@ export type { TransactionWithdrawalIDGroupListItemType, TransactionCategoryGroupListItemType, TransactionMerchantGroupListItemType, + TransactionTagGroupListItemType, Section, SectionListDataType, SectionWithIndexOffset, diff --git a/src/languages/de.ts b/src/languages/de.ts index 5e88b4bbc8343..c0f4542560317 100644 --- a/src/languages/de.ts +++ b/src/languages/de.ts @@ -17,6 +17,8 @@ import dedent from '@libs/StringUtils/dedent'; import CONST from '@src/CONST'; import type {Country} from '@src/CONST'; import type OriginalMessage from '@src/types/onyx/OriginalMessage'; +import {PolicyRulesModifiedFields} from '@src/types/onyx/OriginalMessage'; +import ObjectUtils from '@src/types/utils/ObjectUtils'; import type en from './en'; import type { ChangeFieldParams, @@ -794,7 +796,7 @@ const translations: TranslationDeepObject = { expiredCodeDescription: 'Gehe zurück zum ursprünglichen Gerät und fordere einen neuen Code an', successfulNewCodeRequest: 'Code angefordert. Bitte überprüfe dein Gerät.', tfaRequiredTitle: dedent(` - Zwei-Faktor-Authentifizierung + Zwei-Faktor-Authentifizierung erforderlich `), tfaRequiredDescription: dedent(` @@ -1500,6 +1502,32 @@ const translations: TranslationDeepObject = { }, correctDistanceRateError: 'Beheben Sie den Fehler beim Entfernungssatz und versuchen Sie es erneut.', AskToExplain: `. Erklären ✨`, + policyRulesModifiedFields: (policyRulesModifiedFields: PolicyRulesModifiedFields, policyRulesRoute: string, formatList: (list: string[]) => string) => { + const entries = ObjectUtils.typedEntries(policyRulesModifiedFields); + const fragments = entries.map(([key, value], i) => { + const isFirst = i === 0; + if (key === 'reimbursable') { + return value ? 'hat die Ausgabe als „erstattungsfähig“ markiert' : 'hat die Ausgabe als „nicht erstattungsfähig“ markiert'; + } + if (key === 'billable') { + return value ? 'hat die Ausgabe als „verrechenbar“ markiert' : 'hat die Ausgabe als „nicht abrechenbar“ markiert'; + } + if (key === 'tax') { + const taxEntry = value as PolicyRulesModifiedFields['tax']; + const taxRateName = taxEntry?.field_id_TAX.name ?? ''; + if (isFirst) { + return `Steuersatz auf „${taxRateName}“ festlegen`; + } + return `Steuersatz zu „${taxRateName}“`; + } + const updatedValue = value as string | boolean; + if (isFirst) { + return `Setzen Sie ${translations.common[key].toLowerCase()} auf „${updatedValue}“`; + } + return `${translations.common[key].toLowerCase()} zu "${updatedValue}"`; + }); + return `${formatList(fragments)} über Workspace-Regeln`; + }, }, transactionMerge: { listPage: { @@ -6355,6 +6383,14 @@ Fordere Spesendetails wie Belege und Beschreibungen an, lege Limits und Standard ruleSummarySubtitleUpdateField: (fieldName: string, fieldValue: string) => `Aktualisiere ${fieldName} zu „${fieldValue}“`, ruleSummarySubtitleReimbursable: (reimbursable: boolean) => `Als "${reimbursable ? 'erstattungsfähig' : 'nicht erstattungsfähig'}" markieren`, ruleSummarySubtitleBillable: (billable: boolean) => `Als „${billable ? 'Abrechenbar' : 'nicht abrechenbar'}“ markieren`, + addRuleTitle: 'Regel hinzufügen', + expensesWith: 'Für Ausgaben mit:', + applyUpdates: 'Diese Updates anwenden:', + merchantHint: 'Einem Händlernamen mit groß-/kleinschreibungsunabhängiger „Enthält“-Übereinstimmung zuordnen', + saveRule: 'Regel speichern', + confirmError: 'Geben Sie den Händler ein und nehmen Sie mindestens eine Änderung vor', + confirmErrorMerchant: 'Bitte geben Sie den Händler ein', + confirmErrorUpdate: 'Bitte wenden Sie mindestens eine Aktualisierung an', }, }, planTypePage: { @@ -6957,6 +6993,7 @@ Fordere Spesendetails wie Belege und Beschreibungen an, lege Limits und Standard [CONST.SEARCH.GROUP_BY.WITHDRAWAL_ID]: 'Auszahlungs-ID', [CONST.SEARCH.GROUP_BY.CATEGORY]: 'Kategorie', [CONST.SEARCH.GROUP_BY.MERCHANT]: 'Händler', + [CONST.SEARCH.GROUP_BY.TAG]: 'Stichwort', [CONST.SEARCH.GROUP_BY.MONTH]: 'Monat', }, feed: 'Feed', diff --git a/src/languages/en.ts b/src/languages/en.ts index 717011b6bb760..eda7decf92a8e 100644 --- a/src/languages/en.ts +++ b/src/languages/en.ts @@ -6,6 +6,8 @@ import dedent from '@libs/StringUtils/dedent'; import CONST from '@src/CONST'; import type {Country} from '@src/CONST'; import type OriginalMessage from '@src/types/onyx/OriginalMessage'; +import type {PolicyRulesModifiedFields} from '@src/types/onyx/OriginalMessage'; +import ObjectUtils from '@src/types/utils/ObjectUtils'; import type { ChangeFieldParams, ConnectionNameParams, @@ -1482,6 +1484,39 @@ const translations = { }, correctDistanceRateError: 'Fix the distance rate error and try again.', AskToExplain: `. Explain ✨`, + policyRulesModifiedFields: (policyRulesModifiedFields: PolicyRulesModifiedFields, policyRulesRoute: string, formatList: (list: string[]) => string) => { + const entries = ObjectUtils.typedEntries(policyRulesModifiedFields); + + const fragments = entries.map(([key, value], i) => { + const isFirst = i === 0; + + if (key === 'reimbursable') { + return value ? 'marked the expense as "reimbursable"' : 'marked the expense as "non-reimbursable"'; + } + + if (key === 'billable') { + return value ? 'marked the expense as "billable"' : 'marked the expense as "non-billable"'; + } + + if (key === 'tax') { + const taxEntry = value as PolicyRulesModifiedFields['tax']; + const taxRateName = taxEntry?.field_id_TAX.name ?? ''; + if (isFirst) { + return `set the tax rate to "${taxRateName}"`; + } + return `tax rate to "${taxRateName}"`; + } + + const updatedValue = value as string | boolean; + if (isFirst) { + return `set the ${translations.common[key].toLowerCase()} to "${updatedValue}"`; + } + + return `${translations.common[key].toLowerCase()} to "${updatedValue}"`; + }); + + return `${formatList(fragments)} via workspace rules`; + }, }, transactionMerge: { listPage: { @@ -6190,6 +6225,14 @@ const translations = { title: 'Merchant', subtitle: 'Set the merchant rules so expenses arrive correctly coded and require less cleanup.', addRule: 'Add merchant rule', + addRuleTitle: 'Add rule', + expensesWith: 'For expenses with:', + applyUpdates: 'Apply these updates:', + merchantHint: 'Match a merchant name with case-insensitive "contains" matching', + saveRule: 'Save rule', + confirmError: 'Enter merchant and apply at least one update', + confirmErrorMerchant: 'Please enter merchant', + confirmErrorUpdate: 'Please apply at least one update', ruleSummaryTitle: (merchantName: string) => `If merchant contains "${merchantName}"`, ruleSummarySubtitleMerchant: (merchantName: string) => `Rename merchant to "${merchantName}"`, ruleSummarySubtitleUpdateField: (fieldName: string, fieldValue: string) => `Update ${fieldName} to "${fieldValue}"`, @@ -6841,6 +6884,7 @@ const translations = { [CONST.SEARCH.GROUP_BY.WITHDRAWAL_ID]: 'Withdrawal ID', [CONST.SEARCH.GROUP_BY.CATEGORY]: 'Category', [CONST.SEARCH.GROUP_BY.MERCHANT]: 'Merchant', + [CONST.SEARCH.GROUP_BY.TAG]: 'Tag', [CONST.SEARCH.GROUP_BY.MONTH]: 'Month', }, feed: 'Feed', diff --git a/src/languages/es.ts b/src/languages/es.ts index edea6d2a7af32..b20192c054230 100644 --- a/src/languages/es.ts +++ b/src/languages/es.ts @@ -1,6 +1,8 @@ import {CONST as COMMON_CONST} from 'expensify-common'; import dedent from '@libs/StringUtils/dedent'; import CONST from '@src/CONST'; +import type {PolicyRulesModifiedFields} from '@src/types/onyx/OriginalMessage'; +import ObjectUtils from '@src/types/utils/ObjectUtils'; import type en from './en'; import type {CreatedReportForUnapprovedTransactionsParams, PaidElsewhereParams, RoutedDueToDEWParams, SplitDateRangeParams, ViolationsRterParams} from './params'; import type {TranslationDeepObject} from './types'; @@ -1229,6 +1231,39 @@ const translations: TranslationDeepObject = { }, correctDistanceRateError: 'Corrige el error de la tasa de distancia y vuelve a intentarlo.', AskToExplain: `. Explicar ✨`, + policyRulesModifiedFields: (policyRulesModifiedFields: PolicyRulesModifiedFields, policyRulesRoute: string, formatList: (list: string[]) => string) => { + const entries = ObjectUtils.typedEntries(policyRulesModifiedFields); + + const fragments = entries.map(([key, value], i) => { + const isFirst = i === 0; + + if (key === 'reimbursable') { + return value ? 'marcó el gasto como "reembolsable"' : 'marcó el gasto como "no reembolsable"'; + } + + if (key === 'billable') { + return value ? 'marcó el gasto como "facturable"' : 'marcó el gasto como "no facturable"'; + } + + if (key === 'tax') { + const taxEntry = value as PolicyRulesModifiedFields['tax']; + const taxRateName = taxEntry?.field_id_TAX.name ?? ''; + if (isFirst) { + return `estableció la tasa de impuesto a "${taxRateName}"`; + } + return `tasa de impuesto a "${taxRateName}"`; + } + + const updatedValue = value as string | boolean; + if (isFirst) { + return `estableció el ${translations.common[key].toLowerCase()} a "${updatedValue}"`; + } + + return `${translations.common[key].toLowerCase()} a "${updatedValue}"`; + }); + + return `${formatList(fragments)} a través de reglas del espacio de trabajo`; + }, }, transactionMerge: { listPage: { @@ -5967,6 +6002,14 @@ ${amount} para ${merchant} - ${date}`, title: 'Comerciante', subtitle: 'Configura las reglas de comerciante para que los gastos lleguen correctamente codificados y requieran menos limpieza.', addRule: 'Añadir regla de comerciante', + addRuleTitle: 'Añadir regla', + expensesWith: 'Para gastos con:', + applyUpdates: 'Aplicar estas actualizaciones:', + merchantHint: 'Coincide con un nombre de comerciante con coincidencia "contiene" sin distinción de mayúsculas y minúsculas', + saveRule: 'Guardar regla', + confirmError: 'Ingresa comerciante y aplica al menos una actualización', + confirmErrorMerchant: 'Por favor ingresa comerciante', + confirmErrorUpdate: 'Por favor aplica al menos una actualización', ruleSummaryTitle: (merchantName: string) => `Si el comerciante contiene "${merchantName}"`, ruleSummarySubtitleMerchant: (merchantName: string) => `Renombrar comerciante a "${merchantName}"`, ruleSummarySubtitleUpdateField: (fieldName: string, fieldValue: string) => `Actualizar ${fieldName} a "${fieldValue}"`, @@ -6591,6 +6634,7 @@ ${amount} para ${merchant} - ${date}`, [CONST.SEARCH.GROUP_BY.WITHDRAWAL_ID]: 'ID de retiro', [CONST.SEARCH.GROUP_BY.CATEGORY]: 'Categoría', [CONST.SEARCH.GROUP_BY.MERCHANT]: 'Comerciante', + [CONST.SEARCH.GROUP_BY.TAG]: 'Etiqueta', [CONST.SEARCH.GROUP_BY.MONTH]: 'Mes', }, feed: 'Feed', diff --git a/src/languages/fr.ts b/src/languages/fr.ts index 704b6ecf8aaaa..2479facd40e7a 100644 --- a/src/languages/fr.ts +++ b/src/languages/fr.ts @@ -17,6 +17,8 @@ import dedent from '@libs/StringUtils/dedent'; import CONST from '@src/CONST'; import type {Country} from '@src/CONST'; import type OriginalMessage from '@src/types/onyx/OriginalMessage'; +import {PolicyRulesModifiedFields} from '@src/types/onyx/OriginalMessage'; +import ObjectUtils from '@src/types/utils/ObjectUtils'; import type en from './en'; import type { ChangeFieldParams, @@ -797,7 +799,7 @@ const translations: TranslationDeepObject = { expiredCodeDescription: 'Retournez sur l’appareil d’origine et demandez un nouveau code', successfulNewCodeRequest: 'Code demandé. Veuillez vérifier votre appareil.', tfaRequiredTitle: dedent(` - Authentification à deux facteurs + Authentification à deux facteurs requise `), tfaRequiredDescription: dedent(` @@ -1503,6 +1505,32 @@ const translations: TranslationDeepObject = { }, correctDistanceRateError: 'Corrigez l’erreur de taux de distance et réessayez.', AskToExplain: `. Expliquer ✨`, + policyRulesModifiedFields: (policyRulesModifiedFields: PolicyRulesModifiedFields, policyRulesRoute: string, formatList: (list: string[]) => string) => { + const entries = ObjectUtils.typedEntries(policyRulesModifiedFields); + const fragments = entries.map(([key, value], i) => { + const isFirst = i === 0; + if (key === 'reimbursable') { + return value ? 'a marqué la dépense comme « remboursable »' : 'a marqué la dépense comme « non remboursable »'; + } + if (key === 'billable') { + return value ? 'a marqué la dépense comme « facturable »' : 'a marqué la dépense comme « non refacturable »'; + } + if (key === 'tax') { + const taxEntry = value as PolicyRulesModifiedFields['tax']; + const taxRateName = taxEntry?.field_id_TAX.name ?? ''; + if (isFirst) { + return `définir le taux de taxe sur « ${taxRateName} »`; + } + return `taux de taxe vers « ${taxRateName} »`; + } + const updatedValue = value as string | boolean; + if (isFirst) { + return `définir ${translations.common[key].toLowerCase()} sur « ${updatedValue} »`; + } + return `${translations.common[key].toLowerCase()} à « ${updatedValue} »`; + }); + return `${formatList(fragments)} via les règles de l’espace de travail`; + }, }, transactionMerge: { listPage: { @@ -4672,7 +4700,7 @@ _Pour des instructions plus détaillées, [visitez notre site d’aide](${CONST. _Pour des instructions plus détaillées, [visitez notre site d’aide](${CONST.NETSUITE_IMPORT.HELP_LINKS.CUSTOM_SEGMENTS})_.`, customSegmentScriptIDTitle: 'Quel est l’ID du script ?', - customSegmentScriptIDFooter: `Vous pouvez trouver les ID de script de segment personnalisé dans NetSuite sous : + customSegmentScriptIDFooter: `Vous pouvez trouver les ID de script de segment personnalisé dans NetSuite sous : 1. *Customization > Lists, Records, & Fields > Custom Segments*. 2. Cliquez sur un segment personnalisé. @@ -6365,6 +6393,14 @@ Exigez des informations de dépense comme les reçus et les descriptions, défin ruleSummarySubtitleUpdateField: (fieldName: string, fieldValue: string) => `Mettre à jour ${fieldName} sur « ${fieldValue} »`, ruleSummarySubtitleReimbursable: (reimbursable: boolean) => `Marquer comme « ${reimbursable ? 'remboursable' : 'non remboursable'} »`, ruleSummarySubtitleBillable: (billable: boolean) => `Marquer comme « ${billable ? 'facturable' : 'non facturable'} »`, + addRuleTitle: 'Ajouter une règle', + expensesWith: 'Pour les dépenses avec :', + applyUpdates: 'Appliquer ces mises à jour :', + merchantHint: 'Faire correspondre un nom de commerçant avec une correspondance « contient » insensible à la casse', + saveRule: 'Enregistrer la règle', + confirmError: 'Saisissez un marchand et appliquez au moins une mise à jour', + confirmErrorMerchant: 'Veuillez saisir le commerçant', + confirmErrorUpdate: 'Veuillez appliquer au moins une mise à jour', }, }, planTypePage: { @@ -6968,6 +7004,7 @@ Exigez des informations de dépense comme les reçus et les descriptions, défin [CONST.SEARCH.GROUP_BY.WITHDRAWAL_ID]: 'ID de retrait', [CONST.SEARCH.GROUP_BY.CATEGORY]: 'Catégorie', [CONST.SEARCH.GROUP_BY.MERCHANT]: 'Commerçant', + [CONST.SEARCH.GROUP_BY.TAG]: 'Étiquette', [CONST.SEARCH.GROUP_BY.MONTH]: 'Mois', }, feed: 'Flux', diff --git a/src/languages/it.ts b/src/languages/it.ts index 8bf8d502e02a0..1d7e5a5bfb9d7 100644 --- a/src/languages/it.ts +++ b/src/languages/it.ts @@ -17,6 +17,8 @@ import dedent from '@libs/StringUtils/dedent'; import CONST from '@src/CONST'; import type {Country} from '@src/CONST'; import type OriginalMessage from '@src/types/onyx/OriginalMessage'; +import {PolicyRulesModifiedFields} from '@src/types/onyx/OriginalMessage'; +import ObjectUtils from '@src/types/utils/ObjectUtils'; import type en from './en'; import type { ChangeFieldParams, @@ -794,7 +796,7 @@ const translations: TranslationDeepObject = { expiredCodeDescription: 'Torna al dispositivo originale e richiedi un nuovo codice', successfulNewCodeRequest: 'Codice richiesto. Controlla il tuo dispositivo.', tfaRequiredTitle: dedent(` - Autenticazione a due fattori + Autenticazione a due fattori richiesta `), tfaRequiredDescription: dedent(` @@ -1496,6 +1498,32 @@ const translations: TranslationDeepObject = { }, correctDistanceRateError: "Correggi l'errore nella tariffa della distanza e riprova.", AskToExplain: `. Spiega ✨`, + policyRulesModifiedFields: (policyRulesModifiedFields: PolicyRulesModifiedFields, policyRulesRoute: string, formatList: (list: string[]) => string) => { + const entries = ObjectUtils.typedEntries(policyRulesModifiedFields); + const fragments = entries.map(([key, value], i) => { + const isFirst = i === 0; + if (key === 'reimbursable') { + return value ? 'ha contrassegnato la spesa come "rimborsabile"' : 'ha contrassegnato la spesa come "non rimborsabile"'; + } + if (key === 'billable') { + return value ? 'ha contrassegnato la spesa come "fatturabile"' : 'ha contrassegnato la spesa come "non addebitabile"'; + } + if (key === 'tax') { + const taxEntry = value as PolicyRulesModifiedFields['tax']; + const taxRateName = taxEntry?.field_id_TAX.name ?? ''; + if (isFirst) { + return `imposta l'aliquota fiscale su "${taxRateName}"`; + } + return `aliquota fiscale in "${taxRateName}"`; + } + const updatedValue = value as string | boolean; + if (isFirst) { + return `imposta ${translations.common[key].toLowerCase()} su "${updatedValue}"`; + } + return `${translations.common[key].toLowerCase()} a "${updatedValue}"`; + }); + return `${formatList(fragments)} tramite regole dello spazio di lavoro`; + }, }, transactionMerge: { listPage: { @@ -6337,6 +6365,14 @@ Richiedi dettagli di spesa come ricevute e descrizioni, imposta limiti e valori ruleSummarySubtitleUpdateField: (fieldName: string, fieldValue: string) => `Aggiorna ${fieldName} a "${fieldValue}"`, ruleSummarySubtitleReimbursable: (reimbursable: boolean) => `Segna come "${reimbursable ? 'rimborsabile' : 'non rimborsabile'}"`, ruleSummarySubtitleBillable: (billable: boolean) => `Contrassegna come "${billable ? 'fatturabile' : 'non fatturabile'}"`, + addRuleTitle: 'Aggiungi regola', + expensesWith: 'Per spese con:', + applyUpdates: 'Applica questi aggiornamenti:', + merchantHint: 'Abbina un nome commerciante con una corrispondenza "contiene" che non distingue tra maiuscole e minuscole', + saveRule: 'Salva regola', + confirmError: 'Inserisci l’esercente e applica almeno un aggiornamento', + confirmErrorMerchant: 'Per favore inserisci l’esercente', + confirmErrorUpdate: 'Applica almeno un aggiornamento', }, }, planTypePage: { @@ -6946,6 +6982,7 @@ Richiedi dettagli di spesa come ricevute e descrizioni, imposta limiti e valori [CONST.SEARCH.GROUP_BY.WITHDRAWAL_ID]: 'ID prelievo', //_/\__/_/ \_,_/\__/\__/\_,_/ [CONST.SEARCH.GROUP_BY.CATEGORY]: 'Categoria', [CONST.SEARCH.GROUP_BY.MERCHANT]: 'Commerciante', + [CONST.SEARCH.GROUP_BY.TAG]: 'Etichetta', [CONST.SEARCH.GROUP_BY.MONTH]: 'Mese', }, feed: 'Feed', diff --git a/src/languages/ja.ts b/src/languages/ja.ts index 5345c518b3964..8565bf56a6c28 100644 --- a/src/languages/ja.ts +++ b/src/languages/ja.ts @@ -17,6 +17,8 @@ import dedent from '@libs/StringUtils/dedent'; import CONST from '@src/CONST'; import type {Country} from '@src/CONST'; import type OriginalMessage from '@src/types/onyx/OriginalMessage'; +import {PolicyRulesModifiedFields} from '@src/types/onyx/OriginalMessage'; +import ObjectUtils from '@src/types/utils/ObjectUtils'; import type en from './en'; import type { ChangeFieldParams, @@ -1493,6 +1495,32 @@ const translations: TranslationDeepObject = { }, correctDistanceRateError: '距離レートのエラーを修正して、もう一度お試しください。', AskToExplain: `. 説明する ✨`, + policyRulesModifiedFields: (policyRulesModifiedFields: PolicyRulesModifiedFields, policyRulesRoute: string, formatList: (list: string[]) => string) => { + const entries = ObjectUtils.typedEntries(policyRulesModifiedFields); + const fragments = entries.map(([key, value], i) => { + const isFirst = i === 0; + if (key === 'reimbursable') { + return value ? '経費を「立替精算対象」にマークしました' : '経費を「非精算」としてマークしました'; + } + if (key === 'billable') { + return value ? '経費を「請求可能」とマークしました' : '経費を「請求対象外」としてマークしました'; + } + if (key === 'tax') { + const taxEntry = value as PolicyRulesModifiedFields['tax']; + const taxRateName = taxEntry?.field_id_TAX.name ?? ''; + if (isFirst) { + return `税率を「${taxRateName}」に設定`; + } + return `税率を「${taxRateName}」に`; + } + const updatedValue = value as string | boolean; + if (isFirst) { + return `${translations.common[key].toLowerCase()} を「${updatedValue}」に設定`; + } + return `${translations.common[key].toLowerCase()} を「${updatedValue}」に`; + }); + return `${formatList(fragments)}(ワークスペースルール経由)`; + }, }, transactionMerge: { listPage: { @@ -6293,6 +6321,14 @@ ${reportName} ruleSummarySubtitleUpdateField: (fieldName: string, fieldValue: string) => `${fieldName} を「${fieldValue}」に更新`, ruleSummarySubtitleReimbursable: (reimbursable: boolean) => `「${reimbursable ? '払い戻し対象' : '精算対象外'}」としてマーク`, ruleSummarySubtitleBillable: (billable: boolean) => `「${billable ? '請求可能' : '請求対象外'}」としてマーク`, + addRuleTitle: 'ルールを追加', + expensesWith: '次の条件の経費について:', + applyUpdates: 'これらの更新を適用:', + merchantHint: '大文字小文字を区別しない「含む」一致で支払先名を照合する', + saveRule: 'ルールを保存', + confirmError: '支払先を入力し、少なくとも 1 つの更新を適用してください', + confirmErrorMerchant: '商人を入力してください', + confirmErrorUpdate: '少なくとも 1 件の更新を適用してください', }, }, planTypePage: { @@ -6881,11 +6917,12 @@ ${reportName} reimbursable: '精算対象', purchaseCurrency: '購入通貨', groupBy: { - [CONST.SEARCH.GROUP_BY.FROM]: '差出人', + [CONST.SEARCH.GROUP_BY.FROM]: '送信者', [CONST.SEARCH.GROUP_BY.CARD]: 'カード', [CONST.SEARCH.GROUP_BY.WITHDRAWAL_ID]: '出金ID', [CONST.SEARCH.GROUP_BY.CATEGORY]: 'カテゴリー', [CONST.SEARCH.GROUP_BY.MERCHANT]: '加盟店', + [CONST.SEARCH.GROUP_BY.TAG]: 'タグ', [CONST.SEARCH.GROUP_BY.MONTH]: '月', }, feed: 'フィード', diff --git a/src/languages/nl.ts b/src/languages/nl.ts index 20c4b428616a5..8e7d774d58fba 100644 --- a/src/languages/nl.ts +++ b/src/languages/nl.ts @@ -17,6 +17,8 @@ import dedent from '@libs/StringUtils/dedent'; import CONST from '@src/CONST'; import type {Country} from '@src/CONST'; import type OriginalMessage from '@src/types/onyx/OriginalMessage'; +import {PolicyRulesModifiedFields} from '@src/types/onyx/OriginalMessage'; +import ObjectUtils from '@src/types/utils/ObjectUtils'; import type en from './en'; import type { ChangeFieldParams, @@ -1495,6 +1497,32 @@ const translations: TranslationDeepObject = { }, correctDistanceRateError: 'Los het foutieve kilometertarief op en probeer het opnieuw.', AskToExplain: `. Uitleggen ✨`, + policyRulesModifiedFields: (policyRulesModifiedFields: PolicyRulesModifiedFields, policyRulesRoute: string, formatList: (list: string[]) => string) => { + const entries = ObjectUtils.typedEntries(policyRulesModifiedFields); + const fragments = entries.map(([key, value], i) => { + const isFirst = i === 0; + if (key === 'reimbursable') { + return value ? 'heeft de uitgave als „vergoedbaar” gemarkeerd' : 'markeerde de uitgave als ‘niet-terugbetaalbaar’'; + } + if (key === 'billable') { + return value ? 'heeft de uitgave gemarkeerd als ‘factureerbaar’' : 'heeft de uitgave als ‘niet-declarabel’ gemarkeerd'; + } + if (key === 'tax') { + const taxEntry = value as PolicyRulesModifiedFields['tax']; + const taxRateName = taxEntry?.field_id_TAX.name ?? ''; + if (isFirst) { + return `stel het belastingtarief in op "${taxRateName}"`; + } + return `belastingtarief naar "${taxRateName}"`; + } + const updatedValue = value as string | boolean; + if (isFirst) { + return `stel de ${translations.common[key].toLowerCase()} in op "${updatedValue}"`; + } + return `${translations.common[key].toLowerCase()} naar "${updatedValue}"`; + }); + return `${formatList(fragments)} via werkruimteregels`; + }, }, transactionMerge: { listPage: { @@ -6324,6 +6352,14 @@ Vraag verplichte uitgavedetails zoals bonnetjes en beschrijvingen, stel limieten ruleSummarySubtitleUpdateField: (fieldName: string, fieldValue: string) => `Werk ${fieldName} bij naar "${fieldValue}"`, ruleSummarySubtitleReimbursable: (reimbursable: boolean) => `Markeren als "${reimbursable ? 'Vergoedbaar' : 'niet-vergoedbaar'}"`, ruleSummarySubtitleBillable: (billable: boolean) => `Markeren als "${billable ? 'factureerbaar' : 'niet-factureerbaar'}"`, + addRuleTitle: 'Regel toevoegen', + expensesWith: 'Voor uitgaven met:', + applyUpdates: 'Deze updates toepassen:', + merchantHint: 'Een handelsnaam koppelen met hoofdletterongevoelige "bevat"-overeenkomst', + saveRule: 'Regel opslaan', + confirmError: 'Voer een leverancier in en pas ten minste één wijziging toe', + confirmErrorMerchant: 'Voer handelaar in', + confirmErrorUpdate: 'Breng ten minste één wijziging aan alstublieft', }, }, planTypePage: { @@ -6928,6 +6964,7 @@ Vraag verplichte uitgavedetails zoals bonnetjes en beschrijvingen, stel limieten [CONST.SEARCH.GROUP_BY.WITHDRAWAL_ID]: 'Opname-ID', [CONST.SEARCH.GROUP_BY.CATEGORY]: 'Categorie', [CONST.SEARCH.GROUP_BY.MERCHANT]: 'Verkoper', + [CONST.SEARCH.GROUP_BY.TAG]: 'Label', [CONST.SEARCH.GROUP_BY.MONTH]: 'Maand', }, feed: 'Feed', diff --git a/src/languages/pl.ts b/src/languages/pl.ts index 722360dea2f03..743d00eff2d6f 100644 --- a/src/languages/pl.ts +++ b/src/languages/pl.ts @@ -17,6 +17,8 @@ import dedent from '@libs/StringUtils/dedent'; import CONST from '@src/CONST'; import type {Country} from '@src/CONST'; import type OriginalMessage from '@src/types/onyx/OriginalMessage'; +import {PolicyRulesModifiedFields} from '@src/types/onyx/OriginalMessage'; +import ObjectUtils from '@src/types/utils/ObjectUtils'; import type en from './en'; import type { ChangeFieldParams, @@ -1495,6 +1497,32 @@ const translations: TranslationDeepObject = { }, correctDistanceRateError: 'Napraw błąd stawki za dystans i spróbuj ponownie.', AskToExplain: `. Wyjaśnij ✨`, + policyRulesModifiedFields: (policyRulesModifiedFields: PolicyRulesModifiedFields, policyRulesRoute: string, formatList: (list: string[]) => string) => { + const entries = ObjectUtils.typedEntries(policyRulesModifiedFields); + const fragments = entries.map(([key, value], i) => { + const isFirst = i === 0; + if (key === 'reimbursable') { + return value ? 'oznaczył wydatek jako „podlegający zwrotowi”' : 'oznaczył wydatek jako „niepodlegający zwrotowi”'; + } + if (key === 'billable') { + return value ? 'oznaczył wydatek jako „refakturowalny”' : 'oznaczył wydatek jako „niepodlegający refakturowaniu”'; + } + if (key === 'tax') { + const taxEntry = value as PolicyRulesModifiedFields['tax']; + const taxRateName = taxEntry?.field_id_TAX.name ?? ''; + if (isFirst) { + return `ustaw stawkę podatku na „${taxRateName}”`; + } + return `stawka podatku na „${taxRateName}”`; + } + const updatedValue = value as string | boolean; + if (isFirst) { + return `ustaw ${translations.common[key].toLowerCase()} na „${updatedValue}”`; + } + return `${translations.common[key].toLowerCase()} na „${updatedValue}”`; + }); + return `${formatList(fragments)} przez zasady przestrzeni roboczej`; + }, }, transactionMerge: { listPage: { @@ -6318,6 +6346,14 @@ Wymagaj szczegółów wydatków, takich jak paragony i opisy, ustawiaj limity i ruleSummarySubtitleUpdateField: (fieldName: string, fieldValue: string) => `Zaktualizuj ${fieldName} na „${fieldValue}”`, ruleSummarySubtitleReimbursable: (reimbursable: boolean) => `Oznacz jako "${reimbursable ? 'kwalifikujący się do zwrotu kosztów' : 'niepodlegający zwrotowi'}"`, ruleSummarySubtitleBillable: (billable: boolean) => `Oznacz jako „${billable ? 'fakturowalne' : 'poza fakturą'}”`, + addRuleTitle: 'Dodaj regułę', + expensesWith: 'Dla wydatków z:', + applyUpdates: 'Zastosuj te aktualizacje:', + merchantHint: 'Dopasuj nazwę sprzedawcy przy użyciu nieczułego na wielkość liter dopasowania typu „zawiera”', + saveRule: 'Zapisz regułę', + confirmError: 'Wprowadź sprzedawcę i zastosuj co najmniej jedną aktualizację', + confirmErrorMerchant: 'Wprowadź sprzedawcę', + confirmErrorUpdate: 'Proszę wprowadzić co najmniej jedną zmianę', }, }, planTypePage: { @@ -6918,6 +6954,7 @@ Wymagaj szczegółów wydatków, takich jak paragony i opisy, ustawiaj limity i [CONST.SEARCH.GROUP_BY.WITHDRAWAL_ID]: 'ID wypłaty', [CONST.SEARCH.GROUP_BY.CATEGORY]: 'Kategoria', [CONST.SEARCH.GROUP_BY.MERCHANT]: 'Sprzedawca', + [CONST.SEARCH.GROUP_BY.TAG]: 'Etykieta', [CONST.SEARCH.GROUP_BY.MONTH]: 'Miesiąc', }, feed: 'Kanał', diff --git a/src/languages/pt-BR.ts b/src/languages/pt-BR.ts index f8f754e84fea1..13d7a6ec0fb5b 100644 --- a/src/languages/pt-BR.ts +++ b/src/languages/pt-BR.ts @@ -17,6 +17,8 @@ import dedent from '@libs/StringUtils/dedent'; import CONST from '@src/CONST'; import type {Country} from '@src/CONST'; import type OriginalMessage from '@src/types/onyx/OriginalMessage'; +import {PolicyRulesModifiedFields} from '@src/types/onyx/OriginalMessage'; +import ObjectUtils from '@src/types/utils/ObjectUtils'; import type en from './en'; import type { ChangeFieldParams, @@ -1492,6 +1494,32 @@ const translations: TranslationDeepObject = { }, correctDistanceRateError: 'Corrija o erro na taxa de distância e tente novamente.', AskToExplain: `. Explicar ✨`, + policyRulesModifiedFields: (policyRulesModifiedFields: PolicyRulesModifiedFields, policyRulesRoute: string, formatList: (list: string[]) => string) => { + const entries = ObjectUtils.typedEntries(policyRulesModifiedFields); + const fragments = entries.map(([key, value], i) => { + const isFirst = i === 0; + if (key === 'reimbursable') { + return value ? 'marcou a despesa como "reembolsável"' : 'marcou a despesa como “não reembolsável”'; + } + if (key === 'billable') { + return value ? 'marcou a despesa como “faturável”' : 'marcou a despesa como "não faturável"'; + } + if (key === 'tax') { + const taxEntry = value as PolicyRulesModifiedFields['tax']; + const taxRateName = taxEntry?.field_id_TAX.name ?? ''; + if (isFirst) { + return `definir a taxa de imposto como "${taxRateName}"`; + } + return `alíquota de imposto para "${taxRateName}"`; + } + const updatedValue = value as string | boolean; + if (isFirst) { + return `defina o ${translations.common[key].toLowerCase()} como "${updatedValue}"`; + } + return `${translations.common[key].toLowerCase()} para "${updatedValue}"`; + }); + return `${formatList(fragments)} via regras do workspace`; + }, }, transactionMerge: { listPage: { @@ -6318,6 +6346,14 @@ Exija detalhes de despesas como recibos e descrições, defina limites e padrõe ruleSummarySubtitleUpdateField: (fieldName: string, fieldValue: string) => `Atualizar ${fieldName} para "${fieldValue}"`, ruleSummarySubtitleReimbursable: (reimbursable: boolean) => `Marcar como "${reimbursable ? 'reembolsável' : 'não reembolsável'}"`, ruleSummarySubtitleBillable: (billable: boolean) => `Marcar como "${billable ? 'faturável' : 'não faturável'}"`, + addRuleTitle: 'Adicionar regra', + expensesWith: 'Para despesas com:', + applyUpdates: 'Aplicar estas atualizações:', + merchantHint: 'Corresponder um nome de comerciante com correspondência "contém" sem diferenciação entre maiúsculas e minúsculas', + saveRule: 'Salvar regra', + confirmError: 'Insira o estabelecimento e aplique pelo menos uma atualização', + confirmErrorMerchant: 'Insira o comerciante', + confirmErrorUpdate: 'Por favor, aplique pelo menos uma atualização', }, }, planTypePage: { @@ -6916,9 +6952,10 @@ Exija detalhes de despesas como recibos e descrições, defina limites e padrõe groupBy: { [CONST.SEARCH.GROUP_BY.FROM]: 'De', [CONST.SEARCH.GROUP_BY.CARD]: 'Cartão', - [CONST.SEARCH.GROUP_BY.WITHDRAWAL_ID]: 'ID de retirada', + [CONST.SEARCH.GROUP_BY.WITHDRAWAL_ID]: 'ID da retirada', [CONST.SEARCH.GROUP_BY.CATEGORY]: 'Categoria', [CONST.SEARCH.GROUP_BY.MERCHANT]: 'Comerciante', + [CONST.SEARCH.GROUP_BY.TAG]: 'Etiqueta', [CONST.SEARCH.GROUP_BY.MONTH]: 'Mês', }, feed: 'Feed', diff --git a/src/languages/zh-hans.ts b/src/languages/zh-hans.ts index 8e6ca43bb5273..a57c91ddcb858 100644 --- a/src/languages/zh-hans.ts +++ b/src/languages/zh-hans.ts @@ -17,6 +17,8 @@ import dedent from '@libs/StringUtils/dedent'; import CONST from '@src/CONST'; import type {Country} from '@src/CONST'; import type OriginalMessage from '@src/types/onyx/OriginalMessage'; +import {PolicyRulesModifiedFields} from '@src/types/onyx/OriginalMessage'; +import ObjectUtils from '@src/types/utils/ObjectUtils'; import type en from './en'; import type { ChangeFieldParams, @@ -1470,6 +1472,32 @@ const translations: TranslationDeepObject = { }, correctDistanceRateError: '修复里程费率错误后请重试。', AskToExplain: `. 解释 ✨`, + policyRulesModifiedFields: (policyRulesModifiedFields: PolicyRulesModifiedFields, policyRulesRoute: string, formatList: (list: string[]) => string) => { + const entries = ObjectUtils.typedEntries(policyRulesModifiedFields); + const fragments = entries.map(([key, value], i) => { + const isFirst = i === 0; + if (key === 'reimbursable') { + return value ? '将该报销单标记为“可报销”' : '将该报销单标记为“不可报销”'; + } + if (key === 'billable') { + return value ? '将该报销标记为“可向客户收费”' : '已将该报销标记为“不可计费”'; + } + if (key === 'tax') { + const taxEntry = value as PolicyRulesModifiedFields['tax']; + const taxRateName = taxEntry?.field_id_TAX.name ?? ''; + if (isFirst) { + return `将税率设置为“${taxRateName}”`; + } + return `税率为“${taxRateName}”`; + } + const updatedValue = value as string | boolean; + if (isFirst) { + return `将 ${translations.common[key].toLowerCase()} 设置为 “${updatedValue}”`; + } + return `${translations.common[key].toLowerCase()} 为 “${updatedValue}”`; + }); + return `${formatList(fragments)} 通过工作区规则`; + }, }, transactionMerge: { listPage: { @@ -6183,6 +6211,14 @@ ${reportName} ruleSummarySubtitleUpdateField: (fieldName: string, fieldValue: string) => `将 ${fieldName} 更新为“${fieldValue}”`, ruleSummarySubtitleReimbursable: (reimbursable: boolean) => `标记为“${reimbursable ? '可报销' : '不予报销'}”`, ruleSummarySubtitleBillable: (billable: boolean) => `标记为“${billable ? '可计费' : '不可计费'}”`, + addRuleTitle: '添加规则', + expensesWith: '对于以下费用:', + applyUpdates: '应用这些更新:', + merchantHint: '使用不区分大小写的“包含”匹配来匹配商户名称', + saveRule: '保存规则', + confirmError: '输入商家并至少应用一项更新', + confirmErrorMerchant: '请输入商家', + confirmErrorUpdate: '请至少进行一次更新', }, }, planTypePage: { @@ -6762,10 +6798,11 @@ ${reportName} purchaseCurrency: '购买货币', groupBy: { [CONST.SEARCH.GROUP_BY.FROM]: '来自', - [CONST.SEARCH.GROUP_BY.CARD]: '卡', + [CONST.SEARCH.GROUP_BY.CARD]: '卡片', [CONST.SEARCH.GROUP_BY.WITHDRAWAL_ID]: '提现 ID', [CONST.SEARCH.GROUP_BY.CATEGORY]: '类别', [CONST.SEARCH.GROUP_BY.MERCHANT]: '商家', + [CONST.SEARCH.GROUP_BY.TAG]: '标签', [CONST.SEARCH.GROUP_BY.MONTH]: '月', }, feed: '动态', diff --git a/src/libs/API/parameters/SetPolicyCodingRuleParams.ts b/src/libs/API/parameters/SetPolicyCodingRuleParams.ts new file mode 100644 index 0000000000000..d0f8f5ac9c1a2 --- /dev/null +++ b/src/libs/API/parameters/SetPolicyCodingRuleParams.ts @@ -0,0 +1,15 @@ +type SetPolicyCodingRuleParams = { + /** The policy ID that the rule will be created or updated for */ + policyID: string; + + /** The existing ruleID, or an optimistic one to create the rule */ + ruleID: string; + + /** The JSON value of the merchant rule, stringified */ + value: string; + + /** Whether to update the transactions that match the rule */ + shouldUpdateMatchingTransactions: boolean; +}; + +export default SetPolicyCodingRuleParams; diff --git a/src/libs/API/parameters/index.ts b/src/libs/API/parameters/index.ts index 01c8110626bb3..b409eb168ffe5 100644 --- a/src/libs/API/parameters/index.ts +++ b/src/libs/API/parameters/index.ts @@ -467,6 +467,7 @@ export type {default as ToggleConsolidatedDomainBillingParams} from './ToggleCon export type {default as RemoveDomainAdminParams} from './RemoveDomainAdminParams'; export type {default as DeleteDomainParams} from './DeleteDomainParams'; export type {default as GetDuplicateTransactionDetailsParams} from './GetDuplicateTransactionDetailsParams'; +export type {default as SetPolicyCodingRuleParams} from './SetPolicyCodingRuleParams'; export type {default as RegisterAuthenticationKeyParams} from './RegisterAuthenticationKeyParams'; export type {default as TroubleshootMultifactorAuthenticationParams} from './TroubleshootMultifactorAuthenticationParams'; export type {default as RequestAuthenticationChallengeParams} from './RequestAuthenticationChallengeParams'; diff --git a/src/libs/API/types.ts b/src/libs/API/types.ts index 9e7a77b446443..c0682c87fede7 100644 --- a/src/libs/API/types.ts +++ b/src/libs/API/types.ts @@ -254,6 +254,7 @@ const WRITE_COMMANDS = { ENABLE_POLICY_INVOICING: 'EnablePolicyInvoicing', ENABLE_POLICY_TIME_TRACKING: 'EnablePolicyTimeTracking', SET_POLICY_RULES_ENABLED: 'SetPolicyRulesEnabled', + SET_POLICY_CODING_RULE: 'SetPolicyCodingRule', SET_POLICY_EXPENSE_MAX_AMOUNT_NO_RECEIPT: 'SetPolicyExpenseMaxAmountNoReceipt', SET_POLICY_EXPENSE_MAX_AMOUNT_NO_ITEMIZED_RECEIPT: 'SetPolicyExpenseMaxAmountNoItemizedReceipt', SET_POLICY_EXPENSE_MAX_AMOUNT: 'SetPolicyExpenseMaxAmount', @@ -799,6 +800,7 @@ type WriteCommandParameters = { [WRITE_COMMANDS.ENABLE_POLICY_INVOICING]: Parameters.EnablePolicyInvoicingParams; [WRITE_COMMANDS.ENABLE_POLICY_TIME_TRACKING]: Parameters.EnablePolicyTimeTrackingParams; [WRITE_COMMANDS.SET_POLICY_RULES_ENABLED]: Parameters.SetPolicyRulesEnabledParams; + [WRITE_COMMANDS.SET_POLICY_CODING_RULE]: Parameters.SetPolicyCodingRuleParams; [WRITE_COMMANDS.SET_POLICY_REQUIRE_COMPANY_CARDS_ENABLED]: Parameters.SetPolicyRequireCompanyCardsEnabledParams; [WRITE_COMMANDS.SET_POLICY_CATEGORY_DESCRIPTION_REQUIRED]: Parameters.SetPolicyCategoryDescriptionRequiredParams; [WRITE_COMMANDS.SET_POLICY_CATEGORY_ATTENDEES_REQUIRED]: Parameters.SetPolicyCategoryAttendeesRequiredParams; @@ -837,6 +839,7 @@ type WriteCommandParameters = { [WRITE_COMMANDS.CLEAR_OUTSTANDING_BALANCE]: null; [WRITE_COMMANDS.CANCEL_BILLING_SUBSCRIPTION]: Parameters.CancelBillingSubscriptionParams; [WRITE_COMMANDS.SET_POLICY_RULES_ENABLED]: Parameters.SetPolicyRulesEnabledParams; + [WRITE_COMMANDS.SET_POLICY_CODING_RULE]: Parameters.SetPolicyCodingRuleParams; [WRITE_COMMANDS.SET_POLICY_EXPENSE_MAX_AMOUNT_NO_RECEIPT]: Parameters.SetPolicyExpenseMaxAmountNoReceipt; [WRITE_COMMANDS.SET_POLICY_EXPENSE_MAX_AMOUNT_NO_ITEMIZED_RECEIPT]: Parameters.SetPolicyExpenseMaxAmountNoItemizedReceipt; [WRITE_COMMANDS.SET_POLICY_EXPENSE_MAX_AMOUNT]: Parameters.SetPolicyExpenseMaxAmount; diff --git a/src/libs/ExpenseRuleUtils.ts b/src/libs/ExpenseRuleUtils.ts index 918d649c4c9d7..ef106bb07dd94 100644 --- a/src/libs/ExpenseRuleUtils.ts +++ b/src/libs/ExpenseRuleUtils.ts @@ -54,7 +54,7 @@ function formatExpenseRuleChanges(rule: ExpenseRule, translate: LocaleContextPro if (rule.tag) { addChange('tag', getCleanedTagName(rule.tag)); } - if (rule.tax?.field_id_TAX) { + if (rule.tax?.field_id_TAX?.value) { addChange('tax', rule.tax.field_id_TAX.value); } if (rule.report) { diff --git a/src/libs/ModifiedExpenseMessage.ts b/src/libs/ModifiedExpenseMessage.ts index 4df78d4fa1469..c23c05bbc2b42 100644 --- a/src/libs/ModifiedExpenseMessage.ts +++ b/src/libs/ModifiedExpenseMessage.ts @@ -12,7 +12,7 @@ import {convertToDisplayString} from './CurrencyUtils'; import DateUtils from './DateUtils'; import {getEnvironmentURL} from './Environment/Environment'; // eslint-disable-next-line @typescript-eslint/no-deprecated -import {translateLocal} from './Localize'; +import {formatList, translateLocal} from './Localize'; import Log from './Log'; import Parser from './Parser'; import {getPersonalDetailByEmail} from './PersonalDetailsUtils'; @@ -469,6 +469,18 @@ function getForReportAction({ buildMessageFragmentForValue(translateLocal, oldAttendees, attendees, translateLocal('iou.attendees'), false, setFragments, removalFragments, changeFragments); } + const hasPolicyRulesModifiedFields = isReportActionOriginalMessageAnObject && 'policyRulesModifiedFields' in reportActionOriginalMessage && 'policyID' in reportActionOriginalMessage; + if (hasPolicyRulesModifiedFields) { + const rulePolicyID = reportActionOriginalMessage.policyID; + const policyRulesModifiedFields = reportActionOriginalMessage.policyRulesModifiedFields; + + if (policyRulesModifiedFields && rulePolicyID) { + const policyRulesRoute = `${environmentURL}/${ROUTES.WORKSPACE_RULES.getRoute(rulePolicyID)}`; + // eslint-disable-next-line @typescript-eslint/no-deprecated + return translateLocal('iou.policyRulesModifiedFields', policyRulesModifiedFields, policyRulesRoute, formatList); + } + } + const message = // eslint-disable-next-line @typescript-eslint/no-deprecated getMessageLine(translateLocal, `\n${translateLocal('iou.changed')}`, changeFragments) + @@ -713,10 +725,21 @@ function getForReportActionTemp({ buildMessageFragmentForValue(translate, oldAttendees, attendees, translate('iou.attendees'), false, setFragments, removalFragments, changeFragments); } + const hasPolicyRulesModifiedFields = isReportActionOriginalMessageAnObject && 'policyRulesModifiedFields' in reportActionOriginalMessage && 'policyID' in reportActionOriginalMessage; + if (hasPolicyRulesModifiedFields) { + const {policyRulesModifiedFields, policyID} = reportActionOriginalMessage; + + if (policyRulesModifiedFields && policyID) { + const policyRulesRoute = `${environmentURL}/${ROUTES.WORKSPACE_RULES.getRoute(policyID)}`; + return translate('iou.policyRulesModifiedFields', policyRulesModifiedFields, policyRulesRoute, formatList); + } + } + const message = getMessageLine(translate, `\n${translate('iou.changed')}`, changeFragments) + getMessageLine(translate, `\n${translate('iou.set')}`, setFragments) + getMessageLine(translate, `\n${translate('iou.removed')}`, removalFragments); + if (message === '') { return translate('iou.changedTheExpense'); } diff --git a/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx b/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx index dae14da4174bc..1276203031fd7 100644 --- a/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx +++ b/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx @@ -822,6 +822,15 @@ const SettingsModalStackNavigator = createModalStackNavigator require('../../../../pages/workspace/rules/RulesReimbursableDefaultPage').default, [SCREENS.WORKSPACE.RULES_CUSTOM]: () => require('../../../../pages/workspace/rules/RulesCustomPage').default, [SCREENS.WORKSPACE.RULES_PROHIBITED_DEFAULT]: () => require('../../../../pages/workspace/rules/RulesProhibitedDefaultPage').default, + [SCREENS.WORKSPACE.RULES_MERCHANT_NEW]: () => require('../../../../pages/workspace/rules/MerchantRules/AddMerchantRulePage').default, + [SCREENS.WORKSPACE.RULES_MERCHANT_MERCHANT_TO_MATCH]: () => require('../../../../pages/workspace/rules/MerchantRules/AddMerchantToMatchPage').default, + [SCREENS.WORKSPACE.RULES_MERCHANT_MERCHANT]: () => require('../../../../pages/workspace/rules/MerchantRules/AddMerchantPage').default, + [SCREENS.WORKSPACE.RULES_MERCHANT_CATEGORY]: () => require('../../../../pages/workspace/rules/MerchantRules/AddCategoryPage').default, + [SCREENS.WORKSPACE.RULES_MERCHANT_TAG]: () => require('../../../../pages/workspace/rules/MerchantRules/AddTagPage').default, + [SCREENS.WORKSPACE.RULES_MERCHANT_TAX]: () => require('../../../../pages/workspace/rules/MerchantRules/AddTaxPage').default, + [SCREENS.WORKSPACE.RULES_MERCHANT_DESCRIPTION]: () => require('../../../../pages/workspace/rules/MerchantRules/AddDescriptionPage').default, + [SCREENS.WORKSPACE.RULES_MERCHANT_REIMBURSABLE]: () => require('../../../../pages/workspace/rules/MerchantRules/AddReimbursablePage').default, + [SCREENS.WORKSPACE.RULES_MERCHANT_BILLABLE]: () => require('../../../../pages/workspace/rules/MerchantRules/AddBillablePage').default, [SCREENS.WORKSPACE.PER_DIEM_IMPORT]: () => require('../../../../pages/workspace/perDiem/ImportPerDiemPage').default, [SCREENS.WORKSPACE.PER_DIEM_IMPORTED]: () => require('../../../../pages/workspace/perDiem/ImportedPerDiemPage').default, [SCREENS.WORKSPACE.PER_DIEM_SETTINGS]: () => require('../../../../pages/workspace/perDiem/WorkspacePerDiemSettingsPage').default, diff --git a/src/libs/Navigation/linkingConfig/RELATIONS/WORKSPACE_TO_RHP.ts b/src/libs/Navigation/linkingConfig/RELATIONS/WORKSPACE_TO_RHP.ts index d6d510acce167..42d165fde9b47 100755 --- a/src/libs/Navigation/linkingConfig/RELATIONS/WORKSPACE_TO_RHP.ts +++ b/src/libs/Navigation/linkingConfig/RELATIONS/WORKSPACE_TO_RHP.ts @@ -281,6 +281,15 @@ const WORKSPACE_TO_RHP: Partial['config'] = { [SCREENS.WORKSPACE.RULES_PROHIBITED_DEFAULT]: { path: ROUTES.RULES_PROHIBITED_DEFAULT.route, }, + [SCREENS.WORKSPACE.RULES_MERCHANT_NEW]: { + path: ROUTES.RULES_MERCHANT_NEW.route, + }, + [SCREENS.WORKSPACE.RULES_MERCHANT_MERCHANT_TO_MATCH]: { + path: ROUTES.RULES_MERCHANT_MERCHANT_TO_MATCH.route, + }, + [SCREENS.WORKSPACE.RULES_MERCHANT_MERCHANT]: { + path: ROUTES.RULES_MERCHANT_MERCHANT.route, + }, + [SCREENS.WORKSPACE.RULES_MERCHANT_CATEGORY]: { + path: ROUTES.RULES_MERCHANT_CATEGORY.route, + }, + [SCREENS.WORKSPACE.RULES_MERCHANT_TAG]: { + path: ROUTES.RULES_MERCHANT_TAG.route, + }, + [SCREENS.WORKSPACE.RULES_MERCHANT_TAX]: { + path: ROUTES.RULES_MERCHANT_TAX.route, + }, + [SCREENS.WORKSPACE.RULES_MERCHANT_DESCRIPTION]: { + path: ROUTES.RULES_MERCHANT_DESCRIPTION.route, + }, + [SCREENS.WORKSPACE.RULES_MERCHANT_REIMBURSABLE]: { + path: ROUTES.RULES_MERCHANT_REIMBURSABLE.route, + }, + [SCREENS.WORKSPACE.RULES_MERCHANT_BILLABLE]: { + path: ROUTES.RULES_MERCHANT_BILLABLE.route, + }, [SCREENS.WORKSPACE.PER_DIEM_IMPORT]: { path: ROUTES.WORKSPACE_PER_DIEM_IMPORT.route, }, diff --git a/src/libs/Navigation/types.ts b/src/libs/Navigation/types.ts index 1cee192f433b9..1e21b4c3f8b7c 100644 --- a/src/libs/Navigation/types.ts +++ b/src/libs/Navigation/types.ts @@ -1394,6 +1394,33 @@ type SettingsNavigatorParamList = { [SCREENS.WORKSPACE.RULES_CUSTOM]: { policyID: string; }; + [SCREENS.WORKSPACE.RULES_MERCHANT_NEW]: { + policyID: string; + }; + [SCREENS.WORKSPACE.RULES_MERCHANT_MERCHANT_TO_MATCH]: { + policyID: string; + }; + [SCREENS.WORKSPACE.RULES_MERCHANT_MERCHANT]: { + policyID: string; + }; + [SCREENS.WORKSPACE.RULES_MERCHANT_CATEGORY]: { + policyID: string; + }; + [SCREENS.WORKSPACE.RULES_MERCHANT_TAG]: { + policyID: string; + }; + [SCREENS.WORKSPACE.RULES_MERCHANT_TAX]: { + policyID: string; + }; + [SCREENS.WORKSPACE.RULES_MERCHANT_DESCRIPTION]: { + policyID: string; + }; + [SCREENS.WORKSPACE.RULES_MERCHANT_REIMBURSABLE]: { + policyID: string; + }; + [SCREENS.WORKSPACE.RULES_MERCHANT_BILLABLE]: { + policyID: string; + }; [SCREENS.WORKSPACE.PER_DIEM_IMPORT]: { policyID: string; }; diff --git a/src/libs/SearchUIUtils.ts b/src/libs/SearchUIUtils.ts index a93870509053c..feaab48f618bb 100644 --- a/src/libs/SearchUIUtils.ts +++ b/src/libs/SearchUIUtils.ts @@ -40,6 +40,7 @@ import type { TransactionMerchantGroupListItemType, TransactionMonthGroupListItemType, TransactionReportGroupListItemType, + TransactionTagGroupListItemType, TransactionWithdrawalIDGroupListItemType, } from '@components/SelectionListWithSections/types'; import type {ThemeColors} from '@styles/theme/types'; @@ -60,6 +61,7 @@ import type { SearchDataTypes, SearchMemberGroup, SearchMerchantGroup, + SearchTagGroup, SearchTask, SearchTransactionAction, SearchWithdrawalIDGroup, @@ -154,6 +156,7 @@ type TransactionCardGroupSorting = ColumnSortMapping; type TransactionCategoryGroupSorting = ColumnSortMapping; type TransactionMerchantGroupSorting = ColumnSortMapping; +type TransactionTagGroupSorting = ColumnSortMapping; type TransactionMonthGroupSorting = ColumnSortMapping; type GetReportSectionsParams = { @@ -215,12 +218,17 @@ const expenseReportColumnNamesToSortingProperty: ExpenseReportSorting = { [CONST.SEARCH.TABLE_COLUMNS.ACTION]: 'action' as const, }; +// Base sorting properties common to all transaction group types +const transactionGroupBaseSortingProperties = { + [CONST.SEARCH.TABLE_COLUMNS.GROUP_EXPENSES]: 'count' as const, + [CONST.SEARCH.TABLE_COLUMNS.GROUP_TOTAL]: 'total' as const, +}; + const transactionMemberGroupColumnNamesToSortingProperty: TransactionMemberGroupSorting = { [CONST.SEARCH.TABLE_COLUMNS.AVATAR]: null, [CONST.SEARCH.TABLE_COLUMNS.GROUP_FROM]: 'formattedFrom' as const, [CONST.SEARCH.TABLE_COLUMNS.FROM]: 'formattedFrom' as const, - [CONST.SEARCH.TABLE_COLUMNS.GROUP_EXPENSES]: 'count' as const, - [CONST.SEARCH.TABLE_COLUMNS.GROUP_TOTAL]: 'total' as const, + ...transactionGroupBaseSortingProperties, }; const transactionCardGroupColumnNamesToSortingProperty: TransactionCardGroupSorting = { @@ -228,8 +236,7 @@ const transactionCardGroupColumnNamesToSortingProperty: TransactionCardGroupSort [CONST.SEARCH.TABLE_COLUMNS.GROUP_CARD]: 'formattedCardName' as const, [CONST.SEARCH.TABLE_COLUMNS.CARD]: 'formattedCardName' as const, [CONST.SEARCH.TABLE_COLUMNS.GROUP_FEED]: 'formattedFeedName' as const, - [CONST.SEARCH.TABLE_COLUMNS.GROUP_EXPENSES]: 'count' as const, - [CONST.SEARCH.TABLE_COLUMNS.GROUP_TOTAL]: 'total' as const, + ...transactionGroupBaseSortingProperties, }; const transactionWithdrawalIDGroupColumnNamesToSortingProperty: TransactionWithdrawalIDGroupSorting = { @@ -238,15 +245,19 @@ const transactionWithdrawalIDGroupColumnNamesToSortingProperty: TransactionWithd [CONST.SEARCH.TABLE_COLUMNS.GROUP_WITHDRAWN]: 'debitPosted' as const, [CONST.SEARCH.TABLE_COLUMNS.WITHDRAWN]: 'debitPosted' as const, [CONST.SEARCH.TABLE_COLUMNS.GROUP_WITHDRAWAL_ID]: 'formattedWithdrawalID' as const, - [CONST.SEARCH.TABLE_COLUMNS.GROUP_EXPENSES]: 'count' as const, - [CONST.SEARCH.TABLE_COLUMNS.GROUP_TOTAL]: 'total' as const, + ...transactionGroupBaseSortingProperties, }; const transactionCategoryGroupColumnNamesToSortingProperty: TransactionCategoryGroupSorting = { [CONST.SEARCH.TABLE_COLUMNS.GROUP_CATEGORY]: 'formattedCategory' as const, [CONST.SEARCH.TABLE_COLUMNS.CATEGORY]: 'formattedCategory' as const, - [CONST.SEARCH.TABLE_COLUMNS.GROUP_EXPENSES]: 'count' as const, - [CONST.SEARCH.TABLE_COLUMNS.GROUP_TOTAL]: 'total' as const, + ...transactionGroupBaseSortingProperties, +}; + +const transactionTagGroupColumnNamesToSortingProperty: TransactionTagGroupSorting = { + [CONST.SEARCH.TABLE_COLUMNS.GROUP_TAG]: 'formattedTag' as const, + [CONST.SEARCH.TABLE_COLUMNS.TAG]: 'formattedTag' as const, + ...transactionGroupBaseSortingProperties, }; const transactionMerchantGroupColumnNamesToSortingProperty: TransactionMerchantGroupSorting = { @@ -957,6 +968,13 @@ function isTransactionMerchantGroupListItemType(item: ListItem): item is Transac return isTransactionGroupListItemType(item) && 'groupedBy' in item && item.groupedBy === CONST.SEARCH.GROUP_BY.MERCHANT; } +/** + * Type guard that checks if something is a TransactionTagGroupListItemType + */ +function isTransactionTagGroupListItemType(item: ListItem): item is TransactionTagGroupListItemType { + return isTransactionGroupListItemType(item) && 'groupedBy' in item && item.groupedBy === CONST.SEARCH.GROUP_BY.TAG; +} + /** * Type guard that checks if something is a TransactionMonthGroupListItemType */ @@ -1333,8 +1351,13 @@ function getToFieldValueForTransaction( const isIOUReport = report?.type === CONST.REPORT.TYPE.IOU; if (isIOUReport) { return ( - getIOUPayerAndReceiver(report?.managerID ?? CONST.DEFAULT_NUMBER_ID, report?.ownerAccountID ?? CONST.DEFAULT_NUMBER_ID, personalDetailsList, transactionItem.amount)?.to ?? - emptyPersonalDetails + getIOUPayerAndReceiver( + report?.managerID ?? CONST.DEFAULT_NUMBER_ID, + report?.ownerAccountID ?? CONST.DEFAULT_NUMBER_ID, + personalDetailsList, + // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing + Number(transactionItem.modifiedAmount) || transactionItem.amount, + )?.to ?? emptyPersonalDetails ); } return personalDetailsList?.[report?.managerID] ?? emptyPersonalDetails; @@ -2265,6 +2288,53 @@ function getMerchantSections(data: OnyxTypes.SearchResults['data'], queryJSON: S return [merchantSectionsValues, merchantSectionsValues.length]; } +/** + * @private + * Organizes data into List Sections grouped by tag for display, for the TransactionGroupListItemType of Search Results. + * + * Do not use directly, use only via `getSections()` facade. + */ +function getTagSections(data: OnyxTypes.SearchResults['data'], queryJSON: SearchQueryJSON | undefined, translate: LocalizedTranslate): [TransactionTagGroupListItemType[], number] { + const tagSections: Record = {}; + + for (const key in data) { + if (isGroupEntry(key)) { + const tagGroup = data[key] as SearchTagGroup; + + let transactionsQueryJSON: SearchQueryJSON | undefined; + if (queryJSON && tagGroup.tag !== undefined) { + // Normalize empty tag or "(untagged)" to TAG_EMPTY_VALUE to avoid invalid query like "tag:" + const tagValue = tagGroup.tag === '' || tagGroup.tag === '(untagged)' ? CONST.SEARCH.TAG_EMPTY_VALUE : tagGroup.tag; + + const newFlatFilters = queryJSON.flatFilters.filter((filter) => filter.key !== CONST.SEARCH.SYNTAX_FILTER_KEYS.TAG); + newFlatFilters.push({key: CONST.SEARCH.SYNTAX_FILTER_KEYS.TAG, filters: [{operator: CONST.SEARCH.SYNTAX_OPERATORS.EQUAL_TO, value: tagValue}]}); + + const newQueryJSON: SearchQueryJSON = {...queryJSON, groupBy: undefined, flatFilters: newFlatFilters}; + + const newQuery = buildSearchQueryString(newQueryJSON); + + transactionsQueryJSON = buildSearchQueryJSON(newQuery); + } + + // Format the tag name - use translated "No tag" for empty values so it sorts alphabetically + const rawTag = tagGroup.tag; + const isEmptyTag = !rawTag || rawTag === CONST.SEARCH.TAG_EMPTY_VALUE || rawTag === '(untagged)'; + const formattedTag = isEmptyTag ? translate('search.noTag') : rawTag; + + tagSections[key] = { + groupedBy: CONST.SEARCH.GROUP_BY.TAG, + transactions: [], + transactionsQueryJSON, + ...tagGroup, + formattedTag, + }; + } + } + + const tagSectionsValues = Object.values(tagSections); + return [tagSectionsValues, tagSectionsValues.length]; +} + /** * @private * Organizes data into List Sections grouped by month for display, for the TransactionGroupListItemType of Search Results. @@ -2393,6 +2463,8 @@ function getSections({ return getCategorySections(data, queryJSON); case CONST.SEARCH.GROUP_BY.MERCHANT: return getMerchantSections(data, queryJSON); + case CONST.SEARCH.GROUP_BY.TAG: + return getTagSections(data, queryJSON, translate); case CONST.SEARCH.GROUP_BY.MONTH: return getMonthSections(data, queryJSON); } @@ -2438,6 +2510,8 @@ function getSortedSections( return getSortedCategoryData(data as TransactionCategoryGroupListItemType[], localeCompare, sortBy, sortOrder); case CONST.SEARCH.GROUP_BY.MERCHANT: return getSortedMerchantData(data as TransactionMerchantGroupListItemType[], localeCompare, sortBy, sortOrder); + case CONST.SEARCH.GROUP_BY.TAG: + return getSortedTagData(data as TransactionTagGroupListItemType[], localeCompare, sortBy, sortOrder); case CONST.SEARCH.GROUP_BY.MONTH: return getSortedMonthData(data as TransactionMonthGroupListItemType[], localeCompare, sortBy, sortOrder); } @@ -2837,6 +2911,14 @@ function getSortedMerchantData(data: TransactionMerchantGroupListItemType[], loc ); } +/** + * @private + * Sorts tag sections based on a specified column and sort order. + */ +function getSortedTagData(data: TransactionTagGroupListItemType[], localeCompare: LocaleContextProps['localeCompare'], sortBy?: SearchColumnType, sortOrder?: SortOrder) { + return getSortedData(data, localeCompare, transactionTagGroupColumnNamesToSortingProperty, (a, b) => localeCompare(a.formattedTag ?? '', b.formattedTag ?? ''), sortBy, sortOrder); +} + /** * @private * Sorts month sections based on a specified column and sort order. @@ -2900,6 +2982,8 @@ function getCustomColumns(value?: SearchDataTypes | SearchGroupBy): SearchCustom return Object.values(CONST.SEARCH.GROUP_CUSTOM_COLUMNS.CATEGORY); case CONST.SEARCH.GROUP_BY.MERCHANT: return Object.values(CONST.SEARCH.GROUP_CUSTOM_COLUMNS.MERCHANT); + case CONST.SEARCH.GROUP_BY.TAG: + return Object.values(CONST.SEARCH.GROUP_CUSTOM_COLUMNS.TAG); case CONST.SEARCH.GROUP_BY.MONTH: return Object.values(CONST.SEARCH.GROUP_CUSTOM_COLUMNS.MONTH); default: @@ -2931,6 +3015,8 @@ function getCustomColumnDefault(value?: SearchDataTypes | SearchGroupBy): Search return CONST.SEARCH.GROUP_DEFAULT_COLUMNS.CATEGORY; case CONST.SEARCH.GROUP_BY.MERCHANT: return CONST.SEARCH.GROUP_DEFAULT_COLUMNS.MERCHANT; + case CONST.SEARCH.GROUP_BY.TAG: + return CONST.SEARCH.GROUP_DEFAULT_COLUMNS.TAG; case CONST.SEARCH.GROUP_BY.MONTH: return CONST.SEARCH.GROUP_DEFAULT_COLUMNS.MONTH; default: @@ -3021,6 +3107,8 @@ function getSearchColumnTranslationKey(columnId: SearchCustomColumnIds): Transla return 'common.category'; case CONST.SEARCH.TABLE_COLUMNS.GROUP_MERCHANT: return 'common.merchant'; + case CONST.SEARCH.TABLE_COLUMNS.GROUP_TAG: + return 'common.tag'; case CONST.SEARCH.TABLE_COLUMNS.EXPORTED_TO: return 'search.exportedTo'; } @@ -3499,6 +3587,7 @@ function getColumnsToShow( [CONST.SEARCH.GROUP_BY.WITHDRAWAL_ID]: CONST.SEARCH.GROUP_CUSTOM_COLUMNS.WITHDRAWAL_ID, [CONST.SEARCH.GROUP_BY.CATEGORY]: CONST.SEARCH.GROUP_CUSTOM_COLUMNS.CATEGORY, [CONST.SEARCH.GROUP_BY.MERCHANT]: CONST.SEARCH.GROUP_CUSTOM_COLUMNS.MERCHANT, + [CONST.SEARCH.GROUP_BY.TAG]: CONST.SEARCH.GROUP_CUSTOM_COLUMNS.TAG, [CONST.SEARCH.GROUP_BY.MONTH]: CONST.SEARCH.GROUP_CUSTOM_COLUMNS.MONTH, }[groupBy]; @@ -3508,6 +3597,7 @@ function getColumnsToShow( [CONST.SEARCH.GROUP_BY.WITHDRAWAL_ID]: CONST.SEARCH.GROUP_DEFAULT_COLUMNS.WITHDRAWAL_ID, [CONST.SEARCH.GROUP_BY.CATEGORY]: CONST.SEARCH.GROUP_DEFAULT_COLUMNS.CATEGORY, [CONST.SEARCH.GROUP_BY.MERCHANT]: CONST.SEARCH.GROUP_DEFAULT_COLUMNS.MERCHANT, + [CONST.SEARCH.GROUP_BY.TAG]: CONST.SEARCH.GROUP_DEFAULT_COLUMNS.TAG, [CONST.SEARCH.GROUP_BY.MONTH]: CONST.SEARCH.GROUP_DEFAULT_COLUMNS.MONTH, }[groupBy]; @@ -3599,6 +3689,23 @@ function getColumnsToShow( return result; } + if (groupBy === CONST.SEARCH.GROUP_BY.TAG) { + const requiredColumns = new Set([CONST.SEARCH.TABLE_COLUMNS.GROUP_TAG]); + const result: SearchColumnType[] = []; + + for (const col of requiredColumns) { + if (!columnsToShow.includes(col as SearchCustomColumnIds)) { + result.push(col); + } + } + + for (const col of columnsToShow) { + result.push(col); + } + + return result; + } + if (groupBy === CONST.SEARCH.GROUP_BY.MONTH) { const requiredColumns = new Set([CONST.SEARCH.TABLE_COLUMNS.GROUP_MONTH]); const result: SearchColumnType[] = []; @@ -3899,6 +4006,7 @@ export { isTransactionWithdrawalIDGroupListItemType, isTransactionCategoryGroupListItemType, isTransactionMerchantGroupListItemType, + isTransactionTagGroupListItemType, isTransactionMonthGroupListItemType, isSearchResultsEmpty, isTransactionListItemType, @@ -3935,6 +4043,7 @@ export { getTableMinWidth, getCustomColumns, getCustomColumnDefault, + getToFieldValueForTransaction, isTodoSearch, }; export type {SavedSearchMenuItem, SearchTypeMenuSection, SearchTypeMenuItem, SearchDateModifier, SearchDateModifierLower, SearchKey, ArchivedReportsIDSet}; diff --git a/src/libs/actions/Policy/Rules.ts b/src/libs/actions/Policy/Rules.ts index db75f1082bf04..8a368d346bbf9 100644 --- a/src/libs/actions/Policy/Rules.ts +++ b/src/libs/actions/Policy/Rules.ts @@ -1,7 +1,54 @@ +import Onyx from 'react-native-onyx'; import * as API from '@libs/API'; import type OpenPolicyRulesPageParams from '@libs/API/parameters/OpenPolicyRulesPageParams'; -import {READ_COMMANDS} from '@libs/API/types'; +import type SetPolicyCodingRuleParams from '@libs/API/parameters/SetPolicyCodingRuleParams'; +import {READ_COMMANDS, WRITE_COMMANDS} from '@libs/API/types'; +import * as ErrorUtils from '@libs/ErrorUtils'; import Log from '@libs/Log'; +import * as NumberUtils from '@libs/NumberUtils'; +import CONST from '@src/CONST'; +import ONYXKEYS from '@src/ONYXKEYS'; +import type {MerchantRuleForm} from '@src/types/form'; +import type Policy from '@src/types/onyx/Policy'; +import type {CodingRule, CodingRuleTax} from '@src/types/onyx/Policy'; + +/** + * Builds the tax object from a tax key and policy + */ +function buildTaxObject(taxKey: string | undefined, policy: Policy | undefined): CodingRuleTax | undefined { + if (!taxKey || !policy?.taxRates?.taxes) { + return undefined; + } + + const tax = policy.taxRates.taxes[taxKey]; + if (!tax) { + return undefined; + } + + return { + // eslint-disable-next-line @typescript-eslint/naming-convention + field_id_TAX: { + externalID: taxKey, + value: tax.value, + name: tax.name, + }, + }; +} + +/** + * Maps form fields to rule properties + */ +function mapFormFieldsToRule(form: MerchantRuleForm, policy: Policy | undefined) { + return { + merchant: form.merchant || undefined, + category: form.category || undefined, + tag: form.tag || undefined, + tax: buildTaxObject(form.tax, policy), + comment: form.comment || undefined, + reimbursable: form.reimbursable, + billable: form.billable, + }; +} /** * Fetches policy rules data when the rules page is opened. @@ -17,5 +64,96 @@ function openPolicyRulesPage(policyID: string | undefined) { API.read(READ_COMMANDS.OPEN_POLICY_RULES_PAGE, params); } -// eslint-disable-next-line import/prefer-default-export -export {openPolicyRulesPage}; +/** + * Creates or updates a coding rule for the given policy + * @param policyID - The ID of the policy to create/update the rule for + * @param form - The form data for the merchant rule + * @param policy - The policy object (needed to build tax data) + * @param ruleID - Optional existing rule ID for updates + * @param shouldUpdateMatchingTransactions - Whether to update transactions that match the rule + */ +function setPolicyCodingRule(policyID: string, form: MerchantRuleForm, policy: Policy | undefined, ruleID?: string, shouldUpdateMatchingTransactions = false) { + if (!policyID || !form.merchantToMatch) { + Log.warn('Invalid params for setPolicyCodingRule', {policyID, merchantToMatch: form.merchantToMatch}); + return; + } + + const optimisticRuleID = ruleID ?? NumberUtils.rand64(); + const ruleFields = mapFormFieldsToRule(form, policy); + + const optimisticRule: CodingRule = { + ruleID: optimisticRuleID, + filters: { + left: 'merchant', + operator: 'eq', + right: form.merchantToMatch, + }, + ...ruleFields, + created: new Date().toISOString(), + }; + + const policyKey = `${ONYXKEYS.COLLECTION.POLICY}${policyID}` as const; + + const onyxData = { + optimisticData: [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: policyKey, + value: { + rules: { + codingRules: { + [optimisticRuleID]: optimisticRule, + }, + }, + pendingFields: { + rules: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD, + }, + }, + }, + ], + successData: [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: policyKey, + value: { + pendingFields: { + rules: null, + }, + errorFields: { + rules: null, + }, + }, + }, + ], + failureData: [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: policyKey, + value: { + rules: { + codingRules: { + [optimisticRuleID]: null, + }, + }, + pendingFields: { + rules: null, + }, + errorFields: { + rules: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('common.genericErrorMessage'), + }, + }, + }, + ], + }; + + const parameters: SetPolicyCodingRuleParams = { + policyID, + ruleID: optimisticRuleID, + value: JSON.stringify(optimisticRule), + shouldUpdateMatchingTransactions, + }; + + API.write(WRITE_COMMANDS.SET_POLICY_CODING_RULE, parameters, onyxData); +} + +export {openPolicyRulesPage, setPolicyCodingRule}; diff --git a/src/libs/actions/User.ts b/src/libs/actions/User.ts index a0e14ff5cbc9d..993272f45b1f5 100644 --- a/src/libs/actions/User.ts +++ b/src/libs/actions/User.ts @@ -48,7 +48,7 @@ import CONFIG from '@src/CONFIG'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; -import type {ExpenseRuleForm} from '@src/types/form'; +import type {ExpenseRuleForm, MerchantRuleForm} from '@src/types/form'; import type {AppReview, BlockedFromConcierge, CustomStatusDraft, LoginList, Policy} from '@src/types/onyx'; import type Login from '@src/types/onyx/Login'; import type {Errors} from '@src/types/onyx/OnyxCommon'; @@ -1682,6 +1682,14 @@ function clearDraftRule() { Onyx.set(ONYXKEYS.FORMS.EXPENSE_RULE_FORM, null); } +function updateDraftMerchantRule(ruleData: Partial) { + Onyx.merge(ONYXKEYS.FORMS.MERCHANT_RULE_FORM, ruleData); +} + +function clearDraftMerchantRule() { + Onyx.set(ONYXKEYS.FORMS.MERCHANT_RULE_FORM, null); +} + export { closeAccount, setServerErrorsOnForm, @@ -1728,4 +1736,6 @@ export { setDraftRule, updateDraftRule, clearDraftRule, + updateDraftMerchantRule, + clearDraftMerchantRule, }; diff --git a/src/pages/ReportDetailsPage.tsx b/src/pages/ReportDetailsPage.tsx index c2f630a0d8be6..6c01d8593e450 100644 --- a/src/pages/ReportDetailsPage.tsx +++ b/src/pages/ReportDetailsPage.tsx @@ -999,8 +999,10 @@ function ReportDetailsPage({policy, report, route, reportMetadata}: ReportDetail if (action !== ModalActions.CONFIRM) { return; } - navigateToTargetUrl(); - deleteTransaction(); + Navigation.setNavigationActionToMicrotaskQueue(() => { + navigateToTargetUrl(); + deleteTransaction(); + }); }, [showConfirmModal, translate, caseID, navigateToTargetUrl, deleteTransaction]); const mentionReportContextValue = useMemo(() => ({currentReportID: report.reportID, exactlyMatch: true}), [report.reportID]); diff --git a/src/pages/Search/SearchColumnsPage.tsx b/src/pages/Search/SearchColumnsPage.tsx index ce1b7e19d767a..405aea75a7cb1 100644 --- a/src/pages/Search/SearchColumnsPage.tsx +++ b/src/pages/Search/SearchColumnsPage.tsx @@ -63,6 +63,7 @@ function SearchColumnsPage() { CONST.SEARCH.TABLE_COLUMNS.GROUP_FROM, CONST.SEARCH.TABLE_COLUMNS.GROUP_CATEGORY, CONST.SEARCH.TABLE_COLUMNS.GROUP_MERCHANT, + CONST.SEARCH.TABLE_COLUMNS.GROUP_TAG, CONST.SEARCH.TABLE_COLUMNS.GROUP_MONTH, ]); diff --git a/src/pages/settings/Rules/Fields/AddBillablePage.tsx b/src/pages/settings/Rules/Fields/AddBillablePage.tsx index 81ba9c07df5c2..42a64acc9ac1b 100644 --- a/src/pages/settings/Rules/Fields/AddBillablePage.tsx +++ b/src/pages/settings/Rules/Fields/AddBillablePage.tsx @@ -1,18 +1,37 @@ import React from 'react'; -import RuleBooleanBasePage from '@components/Rule/RuleBooleanBase'; +import RuleBooleanBase from '@components/Rule/RuleBooleanBase'; +import {updateDraftRule} from '@libs/actions/User'; +import Navigation from '@libs/Navigation/Navigation'; import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types'; import type {SettingsNavigatorParamList} from '@libs/Navigation/types'; import CONST from '@src/CONST'; +import ONYXKEYS from '@src/ONYXKEYS'; +import ROUTES from '@src/ROUTES'; import type SCREENS from '@src/SCREENS'; type AddBillablePageProps = PlatformStackScreenProps; function AddBillablePage({route}: AddBillablePageProps) { + const hash = route.params?.hash; + + const goBack = () => { + Navigation.goBack(hash ? ROUTES.SETTINGS_RULES_EDIT.getRoute(hash) : ROUTES.SETTINGS_RULES_ADD.getRoute()); + }; + + const onSelect = (fieldID: string, value: boolean | 'true' | 'false' | null) => { + updateDraftRule({[fieldID]: value}); + goBack(); + }; + return ( - ); } diff --git a/src/pages/settings/Rules/Fields/AddCategoryPage.tsx b/src/pages/settings/Rules/Fields/AddCategoryPage.tsx index 4d9a505071790..47e2cd93fe45b 100644 --- a/src/pages/settings/Rules/Fields/AddCategoryPage.tsx +++ b/src/pages/settings/Rules/Fields/AddCategoryPage.tsx @@ -1,13 +1,7 @@ -import React, {useCallback, useMemo} from 'react'; -import {View} from 'react-native'; +import React, {useCallback} from 'react'; import type {OnyxCollection} from 'react-native-onyx'; -import HeaderWithBackButton from '@components/HeaderWithBackButton'; -import RuleNotFoundPageWrapper from '@components/Rule/RuleNotFoundPageWrapper'; -import ScreenWrapper from '@components/ScreenWrapper'; -import SearchSingleSelectionPicker from '@components/Search/SearchSingleSelectionPicker'; -import useLocalize from '@hooks/useLocalize'; +import RuleSelectionBase from '@components/Rule/RuleSelectionBase'; import useOnyx from '@hooks/useOnyx'; -import useThemeStyles from '@hooks/useThemeStyles'; import {updateDraftRule} from '@libs/actions/User'; import {getAvailableNonPersonalPolicyCategories, getDecodedCategoryName} from '@libs/CategoryUtils'; import Navigation from '@libs/Navigation/Navigation'; @@ -22,9 +16,6 @@ import {getEmptyObject} from '@src/types/utils/EmptyObject'; type AddCategoryPageProps = PlatformStackScreenProps; function AddCategoryPage({route}: AddCategoryPageProps) { - const styles = useThemeStyles(); - const {translate} = useLocalize(); - const [form] = useOnyx(ONYXKEYS.FORMS.EXPENSE_RULE_FORM, {canBeMissing: true}); const [personalPolicyID] = useOnyx(ONYXKEYS.PERSONAL_POLICY_ID, {canBeMissing: true}); const availableNonPersonalPolicyCategoriesSelector = useCallback( @@ -38,7 +29,7 @@ function AddCategoryPage({route}: AddCategoryPageProps) { const selectedCategoryItem = form?.category ? {name: getDecodedCategoryName(form.category), value: form.category} : undefined; - const categoryItems = useMemo(() => { + const categoryItems = () => { const uniqueCategoryNames = new Set(); const categories = Object.values(allPolicyCategories ?? {}).flatMap((policyCategories) => Object.values(policyCategories ?? {})); @@ -52,7 +43,7 @@ function AddCategoryPage({route}: AddCategoryPageProps) { const decodedCategoryName = getDecodedCategoryName(categoryName); return {name: decodedCategoryName, value: categoryName}; }); - }, [allPolicyCategories]); + }; const hash = route.params?.hash; const backToRoute = hash ? ROUTES.SETTINGS_RULES_EDIT.getRoute(hash) : ROUTES.SETTINGS_RULES_ADD.getRoute(); @@ -62,28 +53,16 @@ function AddCategoryPage({route}: AddCategoryPageProps) { }; return ( - - - Navigation.goBack(backToRoute)} - /> - - - - - + Navigation.goBack(backToRoute)} + backToRoute={backToRoute} + hash={hash} + /> ); } diff --git a/src/pages/settings/Rules/Fields/AddDescriptionPage.tsx b/src/pages/settings/Rules/Fields/AddDescriptionPage.tsx index a62365e955f88..b910763b20fc0 100644 --- a/src/pages/settings/Rules/Fields/AddDescriptionPage.tsx +++ b/src/pages/settings/Rules/Fields/AddDescriptionPage.tsx @@ -1,20 +1,39 @@ import React from 'react'; +import type {FormOnyxValues} from '@components/Form/types'; import RuleTextBase from '@components/Rule/RuleTextBase'; +import {updateDraftRule} from '@libs/actions/User'; +import Navigation from '@libs/Navigation/Navigation'; import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types'; import type {SettingsNavigatorParamList} from '@libs/Navigation/types'; import CONST from '@src/CONST'; +import ONYXKEYS from '@src/ONYXKEYS'; +import ROUTES from '@src/ROUTES'; import type SCREENS from '@src/SCREENS'; type AddDescriptionPageProps = PlatformStackScreenProps; function AddDescriptionPage({route}: AddDescriptionPageProps) { + const hash = route.params?.hash; + + const goBack = () => { + Navigation.goBack(hash ? ROUTES.SETTINGS_RULES_EDIT.getRoute(hash) : ROUTES.SETTINGS_RULES_ADD.getRoute()); + }; + + const onSave = (values: FormOnyxValues) => { + updateDraftRule(values); + goBack(); + }; + return ( ); } diff --git a/src/pages/settings/Rules/Fields/AddMerchantPage.tsx b/src/pages/settings/Rules/Fields/AddMerchantPage.tsx index 79db39824fb60..805c850c688ea 100644 --- a/src/pages/settings/Rules/Fields/AddMerchantPage.tsx +++ b/src/pages/settings/Rules/Fields/AddMerchantPage.tsx @@ -1,22 +1,41 @@ import React from 'react'; +import type {FormOnyxValues} from '@components/Form/types'; import RuleTextBase from '@components/Rule/RuleTextBase'; +import {updateDraftRule} from '@libs/actions/User'; +import Navigation from '@libs/Navigation/Navigation'; import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types'; import type {SettingsNavigatorParamList} from '@libs/Navigation/types'; import CONST from '@src/CONST'; +import ONYXKEYS from '@src/ONYXKEYS'; +import ROUTES from '@src/ROUTES'; import type SCREENS from '@src/SCREENS'; type AddMerchantPageProps = PlatformStackScreenProps; function AddMerchantPage({route}: AddMerchantPageProps) { + const hash = route.params?.hash; + + const goBack = () => { + Navigation.goBack(hash ? ROUTES.SETTINGS_RULES_EDIT.getRoute(hash) : ROUTES.SETTINGS_RULES_ADD.getRoute()); + }; + + const onSave = (values: FormOnyxValues) => { + updateDraftRule(values); + goBack(); + }; + return ( ); } diff --git a/src/pages/settings/Rules/Fields/AddReimbursablePage.tsx b/src/pages/settings/Rules/Fields/AddReimbursablePage.tsx index 968b0a6ddb1f4..bef1e0a8358f2 100644 --- a/src/pages/settings/Rules/Fields/AddReimbursablePage.tsx +++ b/src/pages/settings/Rules/Fields/AddReimbursablePage.tsx @@ -1,18 +1,37 @@ import React from 'react'; -import RuleBooleanBasePage from '@components/Rule/RuleBooleanBase'; +import RuleBooleanBase from '@components/Rule/RuleBooleanBase'; +import {updateDraftRule} from '@libs/actions/User'; +import Navigation from '@libs/Navigation/Navigation'; import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types'; import type {SettingsNavigatorParamList} from '@libs/Navigation/types'; import CONST from '@src/CONST'; +import ONYXKEYS from '@src/ONYXKEYS'; +import ROUTES from '@src/ROUTES'; import type SCREENS from '@src/SCREENS'; type AddReimbursablePageProps = PlatformStackScreenProps; function AddReimbursablePage({route}: AddReimbursablePageProps) { + const hash = route.params?.hash; + + const goBack = () => { + Navigation.goBack(hash ? ROUTES.SETTINGS_RULES_EDIT.getRoute(hash) : ROUTES.SETTINGS_RULES_ADD.getRoute()); + }; + + const onSelect = (fieldID: string, value: boolean | 'true' | 'false' | null) => { + updateDraftRule({[fieldID]: value}); + goBack(); + }; + return ( - ); } diff --git a/src/pages/settings/Rules/Fields/AddRenameMerchantPage.tsx b/src/pages/settings/Rules/Fields/AddRenameMerchantPage.tsx index 1418a8f9b357d..24fb50e2198d1 100644 --- a/src/pages/settings/Rules/Fields/AddRenameMerchantPage.tsx +++ b/src/pages/settings/Rules/Fields/AddRenameMerchantPage.tsx @@ -1,20 +1,39 @@ import React from 'react'; +import type {FormOnyxValues} from '@components/Form/types'; import RuleTextBase from '@components/Rule/RuleTextBase'; +import {updateDraftRule} from '@libs/actions/User'; +import Navigation from '@libs/Navigation/Navigation'; import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types'; import type {SettingsNavigatorParamList} from '@libs/Navigation/types'; import CONST from '@src/CONST'; +import ONYXKEYS from '@src/ONYXKEYS'; +import ROUTES from '@src/ROUTES'; import type SCREENS from '@src/SCREENS'; type AddRenameMerchantPageProps = PlatformStackScreenProps; function AddRenameMerchantPage({route}: AddRenameMerchantPageProps) { + const hash = route.params?.hash; + + const goBack = () => { + Navigation.goBack(hash ? ROUTES.SETTINGS_RULES_EDIT.getRoute(hash) : ROUTES.SETTINGS_RULES_ADD.getRoute()); + }; + + const onSave = (values: FormOnyxValues) => { + updateDraftRule(values); + goBack(); + }; + return ( ); } diff --git a/src/pages/settings/Rules/Fields/AddReportPage.tsx b/src/pages/settings/Rules/Fields/AddReportPage.tsx index 46fc5dbc08a93..2d6578688c185 100644 --- a/src/pages/settings/Rules/Fields/AddReportPage.tsx +++ b/src/pages/settings/Rules/Fields/AddReportPage.tsx @@ -1,21 +1,40 @@ import React from 'react'; +import type {FormOnyxValues} from '@components/Form/types'; import RuleTextBase from '@components/Rule/RuleTextBase'; +import {updateDraftRule} from '@libs/actions/User'; +import Navigation from '@libs/Navigation/Navigation'; import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types'; import type {SettingsNavigatorParamList} from '@libs/Navigation/types'; import CONST from '@src/CONST'; +import ONYXKEYS from '@src/ONYXKEYS'; +import ROUTES from '@src/ROUTES'; import type SCREENS from '@src/SCREENS'; type AddReportPageProps = PlatformStackScreenProps; function AddReportPage({route}: AddReportPageProps) { + const hash = route.params?.hash; + + const goBack = () => { + Navigation.goBack(hash ? ROUTES.SETTINGS_RULES_EDIT.getRoute(hash) : ROUTES.SETTINGS_RULES_ADD.getRoute()); + }; + + const onSave = (values: FormOnyxValues) => { + updateDraftRule(values); + goBack(); + }; + return ( ); } diff --git a/src/pages/settings/Rules/Fields/AddTagPage.tsx b/src/pages/settings/Rules/Fields/AddTagPage.tsx index a96648ecce14c..290bb6d16c8b4 100644 --- a/src/pages/settings/Rules/Fields/AddTagPage.tsx +++ b/src/pages/settings/Rules/Fields/AddTagPage.tsx @@ -1,13 +1,7 @@ -import React, {useMemo} from 'react'; -import {View} from 'react-native'; +import React from 'react'; import type {OnyxCollection} from 'react-native-onyx'; -import HeaderWithBackButton from '@components/HeaderWithBackButton'; -import RuleNotFoundPageWrapper from '@components/Rule/RuleNotFoundPageWrapper'; -import ScreenWrapper from '@components/ScreenWrapper'; -import SearchSingleSelectionPicker from '@components/Search/SearchSingleSelectionPicker'; -import useLocalize from '@hooks/useLocalize'; +import RuleSelectionBase from '@components/Rule/RuleSelectionBase'; import useOnyx from '@hooks/useOnyx'; -import useThemeStyles from '@hooks/useThemeStyles'; import {updateDraftRule} from '@libs/actions/User'; import Navigation from '@libs/Navigation/Navigation'; import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types'; @@ -22,9 +16,6 @@ import {getEmptyObject} from '@src/types/utils/EmptyObject'; type AddTagPageProps = PlatformStackScreenProps; function AddTagPage({route}: AddTagPageProps) { - const styles = useThemeStyles(); - const {translate} = useLocalize(); - const [form] = useOnyx(ONYXKEYS.FORMS.EXPENSE_RULE_FORM, {canBeMissing: true}); const [allPolicyTagLists = getEmptyObject>>()] = useOnyx(ONYXKEYS.COLLECTION.POLICY_TAGS, { canBeMissing: true, @@ -32,7 +23,7 @@ function AddTagPage({route}: AddTagPageProps) { const selectedTagItem = form?.tag ? {name: getCleanedTagName(form.tag), value: form.tag} : undefined; - const tagItems = useMemo(() => { + const tagItems = () => { const uniqueTagNames = new Set(); const tagListsUnpacked = Object.values(allPolicyTagLists ?? {}).filter((item) => !!item); @@ -41,7 +32,7 @@ function AddTagPage({route}: AddTagPageProps) { } return Array.from(uniqueTagNames).map((tagName) => ({name: getCleanedTagName(tagName), value: tagName})); - }, [allPolicyTagLists]); + }; const hash = route.params?.hash; const backToRoute = hash ? ROUTES.SETTINGS_RULES_EDIT.getRoute(hash) : ROUTES.SETTINGS_RULES_ADD.getRoute(); @@ -51,28 +42,16 @@ function AddTagPage({route}: AddTagPageProps) { }; return ( - - - Navigation.goBack(backToRoute)} - /> - - - - - + Navigation.goBack(backToRoute)} + backToRoute={backToRoute} + hash={hash} + /> ); } diff --git a/src/pages/settings/Rules/Fields/AddTaxRatePage.tsx b/src/pages/settings/Rules/Fields/AddTaxRatePage.tsx index 8b799e9bf16ea..73469a95f21f2 100644 --- a/src/pages/settings/Rules/Fields/AddTaxRatePage.tsx +++ b/src/pages/settings/Rules/Fields/AddTaxRatePage.tsx @@ -1,12 +1,6 @@ import React from 'react'; -import {View} from 'react-native'; -import HeaderWithBackButton from '@components/HeaderWithBackButton'; -import RuleNotFoundPageWrapper from '@components/Rule/RuleNotFoundPageWrapper'; -import ScreenWrapper from '@components/ScreenWrapper'; -import SearchSingleSelectionPicker from '@components/Search/SearchSingleSelectionPicker'; -import useLocalize from '@hooks/useLocalize'; +import RuleSelectionBase from '@components/Rule/RuleSelectionBase'; import useOnyx from '@hooks/useOnyx'; -import useThemeStyles from '@hooks/useThemeStyles'; import {updateDraftRule} from '@libs/actions/User'; import Navigation from '@libs/Navigation/Navigation'; import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types'; @@ -19,9 +13,6 @@ import type SCREENS from '@src/SCREENS'; type AddTaxRatePageProps = PlatformStackScreenProps; function AddTaxRatePage({route}: AddTaxRatePageProps) { - const styles = useThemeStyles(); - const {translate} = useLocalize(); - const [form] = useOnyx(ONYXKEYS.FORMS.EXPENSE_RULE_FORM, {canBeMissing: true}); const [allTaxRates] = useOnyx(ONYXKEYS.COLLECTION.POLICY, {canBeMissing: true, selector: getAllTaxRatesNamesAndValues}); @@ -39,28 +30,16 @@ function AddTaxRatePage({route}: AddTaxRatePageProps) { }; return ( - - - Navigation.goBack(backToRoute)} - /> - - - - - + Navigation.goBack(backToRoute)} + backToRoute={backToRoute} + hash={hash} + /> ); } diff --git a/src/pages/workspace/rules/MerchantRules/AddBillablePage.tsx b/src/pages/workspace/rules/MerchantRules/AddBillablePage.tsx new file mode 100644 index 0000000000000..8284708709f5a --- /dev/null +++ b/src/pages/workspace/rules/MerchantRules/AddBillablePage.tsx @@ -0,0 +1,39 @@ +import React from 'react'; +import RuleBooleanBase from '@components/Rule/RuleBooleanBase'; +import {updateDraftMerchantRule} from '@libs/actions/User'; +import Navigation from '@libs/Navigation/Navigation'; +import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types'; +import type {SettingsNavigatorParamList} from '@libs/Navigation/types'; +import CONST from '@src/CONST'; +import ONYXKEYS from '@src/ONYXKEYS'; +import ROUTES from '@src/ROUTES'; +import type SCREENS from '@src/SCREENS'; + +type AddBillablePageProps = PlatformStackScreenProps; + +function AddBillablePage({route}: AddBillablePageProps) { + const policyID = route.params.policyID; + + const goBack = () => { + Navigation.goBack(ROUTES.RULES_MERCHANT_NEW.getRoute(policyID)); + }; + + const onSelect = (fieldID: string, value: boolean | 'true' | 'false' | null) => { + updateDraftMerchantRule({[fieldID]: value}); + goBack(); + }; + + return ( + + ); +} + +AddBillablePage.displayName = 'AddBillablePage'; + +export default AddBillablePage; diff --git a/src/pages/workspace/rules/MerchantRules/AddCategoryPage.tsx b/src/pages/workspace/rules/MerchantRules/AddCategoryPage.tsx new file mode 100644 index 0000000000000..48e57731f530c --- /dev/null +++ b/src/pages/workspace/rules/MerchantRules/AddCategoryPage.tsx @@ -0,0 +1,53 @@ +import React, {useMemo} from 'react'; +import RuleSelectionBase from '@components/Rule/RuleSelectionBase'; +import useOnyx from '@hooks/useOnyx'; +import {updateDraftMerchantRule} from '@libs/actions/User'; +import {getDecodedCategoryName} from '@libs/CategoryUtils'; +import Navigation from '@libs/Navigation/Navigation'; +import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types'; +import type {SettingsNavigatorParamList} from '@libs/Navigation/types'; +import ONYXKEYS from '@src/ONYXKEYS'; +import ROUTES from '@src/ROUTES'; +import type SCREENS from '@src/SCREENS'; + +type AddCategoryPageProps = PlatformStackScreenProps; + +function AddCategoryPage({route}: AddCategoryPageProps) { + const policyID = route.params.policyID; + + const [form] = useOnyx(ONYXKEYS.FORMS.MERCHANT_RULE_FORM, {canBeMissing: true}); + const [policyCategories] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY_CATEGORIES}${policyID}`, {canBeMissing: true}); + + const selectedCategoryItem = form?.category ? {name: getDecodedCategoryName(form.category), value: form.category} : undefined; + + const categoryItems = useMemo(() => { + return Object.values(policyCategories ?? {}) + .filter((category) => category.enabled) + .map((category) => { + const decodedCategoryName = getDecodedCategoryName(category.name); + return {name: decodedCategoryName, value: category.name}; + }); + }, [policyCategories]); + + const backToRoute = ROUTES.RULES_MERCHANT_NEW.getRoute(policyID); + + const onSave = (value?: string) => { + updateDraftMerchantRule({category: value}); + }; + + return ( + Navigation.goBack(backToRoute)} + backToRoute={backToRoute} + /> + ); +} + +AddCategoryPage.displayName = 'AddCategoryPage'; + +export default AddCategoryPage; diff --git a/src/pages/workspace/rules/MerchantRules/AddDescriptionPage.tsx b/src/pages/workspace/rules/MerchantRules/AddDescriptionPage.tsx new file mode 100644 index 0000000000000..9b4328e1910f0 --- /dev/null +++ b/src/pages/workspace/rules/MerchantRules/AddDescriptionPage.tsx @@ -0,0 +1,42 @@ +import React from 'react'; +import type {FormOnyxValues} from '@components/Form/types'; +import RuleTextBase from '@components/Rule/RuleTextBase'; +import {updateDraftMerchantRule} from '@libs/actions/User'; +import Navigation from '@libs/Navigation/Navigation'; +import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types'; +import type {SettingsNavigatorParamList} from '@libs/Navigation/types'; +import CONST from '@src/CONST'; +import ONYXKEYS from '@src/ONYXKEYS'; +import ROUTES from '@src/ROUTES'; +import type SCREENS from '@src/SCREENS'; + +type AddDescriptionPageProps = PlatformStackScreenProps; + +function AddDescriptionPage({route}: AddDescriptionPageProps) { + const policyID = route.params.policyID; + + const goBack = () => { + Navigation.goBack(ROUTES.RULES_MERCHANT_NEW.getRoute(policyID)); + }; + + const onSave = (values: FormOnyxValues) => { + updateDraftMerchantRule(values); + goBack(); + }; + + return ( + + ); +} + +AddDescriptionPage.displayName = 'AddDescriptionPage'; + +export default AddDescriptionPage; diff --git a/src/pages/workspace/rules/MerchantRules/AddMerchantPage.tsx b/src/pages/workspace/rules/MerchantRules/AddMerchantPage.tsx new file mode 100644 index 0000000000000..5a6756906377e --- /dev/null +++ b/src/pages/workspace/rules/MerchantRules/AddMerchantPage.tsx @@ -0,0 +1,42 @@ +import React from 'react'; +import type {FormOnyxValues} from '@components/Form/types'; +import RuleTextBase from '@components/Rule/RuleTextBase'; +import {updateDraftMerchantRule} from '@libs/actions/User'; +import Navigation from '@libs/Navigation/Navigation'; +import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types'; +import type {SettingsNavigatorParamList} from '@libs/Navigation/types'; +import CONST from '@src/CONST'; +import ONYXKEYS from '@src/ONYXKEYS'; +import ROUTES from '@src/ROUTES'; +import type SCREENS from '@src/SCREENS'; + +type AddMerchantPageProps = PlatformStackScreenProps; + +function AddMerchantPage({route}: AddMerchantPageProps) { + const policyID = route.params.policyID; + + const goBack = () => { + Navigation.goBack(ROUTES.RULES_MERCHANT_NEW.getRoute(policyID)); + }; + + const onSave = (values: FormOnyxValues) => { + updateDraftMerchantRule(values); + goBack(); + }; + + return ( + + ); +} + +AddMerchantPage.displayName = 'AddMerchantPage'; + +export default AddMerchantPage; diff --git a/src/pages/workspace/rules/MerchantRules/AddMerchantRulePage.tsx b/src/pages/workspace/rules/MerchantRules/AddMerchantRulePage.tsx new file mode 100644 index 0000000000000..1f0da99badaaa --- /dev/null +++ b/src/pages/workspace/rules/MerchantRules/AddMerchantRulePage.tsx @@ -0,0 +1,237 @@ +import React, {useEffect, useState} from 'react'; +import {View} from 'react-native'; +import FormAlertWithSubmitButton from '@components/FormAlertWithSubmitButton'; +import HeaderWithBackButton from '@components/HeaderWithBackButton'; +import type {LocalizedTranslate} from '@components/LocaleContextProvider'; +import MenuItemWithTopDescription from '@components/MenuItemWithTopDescription'; +import ScreenWrapper from '@components/ScreenWrapper'; +import ScrollView from '@components/ScrollView'; +import Text from '@components/Text'; +import useLocalize from '@hooks/useLocalize'; +import useOnyx from '@hooks/useOnyx'; +import usePolicy from '@hooks/usePolicy'; +import useThemeStyles from '@hooks/useThemeStyles'; +import {setPolicyCodingRule} from '@libs/actions/Policy/Rules'; +import {clearDraftMerchantRule} from '@libs/actions/User'; +import {getDecodedCategoryName} from '@libs/CategoryUtils'; +import Navigation from '@libs/Navigation/Navigation'; +import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types'; +import type {SettingsNavigatorParamList} from '@libs/Navigation/types'; +import {getCleanedTagName, getTagNamesFromTagsLists} from '@libs/PolicyUtils'; +import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper'; +import CONST from '@src/CONST'; +import ONYXKEYS from '@src/ONYXKEYS'; +import ROUTES from '@src/ROUTES'; +import type SCREENS from '@src/SCREENS'; +import type {MerchantRuleForm} from '@src/types/form'; + +type AddMerchantRulePageProps = PlatformStackScreenProps; + +type SectionItemType = { + descriptionTranslationKey: 'common.merchant' | 'common.category' | 'common.tag' | 'common.tax' | 'common.description' | 'common.reimbursable' | 'common.billable'; + required?: boolean; + title?: string; + onPress: () => void; +}; + +type SectionType = { + titleTranslationKey: 'workspace.rules.merchantRules.expensesWith' | 'workspace.rules.merchantRules.applyUpdates'; + items: Array; +}; + +const getBooleanTitle = (value: boolean | undefined, translate: LocalizedTranslate): string => { + if (value === undefined) { + return ''; + } + return translate(value ? 'common.yes' : 'common.no'); +}; + +const getErrorMessage = (translate: LocalizedTranslate, form?: MerchantRuleForm) => { + const merchantToMatchField = CONST.MERCHANT_RULES.FIELDS.MERCHANT_TO_MATCH; + const hasAtLeastOneUpdate = Object.entries(form ?? {}).some(([key, value]) => key !== merchantToMatchField && !!value); + if (form?.merchantToMatch && hasAtLeastOneUpdate) { + return ''; + } + if (hasAtLeastOneUpdate) { + return translate('workspace.rules.merchantRules.confirmErrorMerchant'); + } + if (form?.merchantToMatch) { + return translate('workspace.rules.merchantRules.confirmErrorUpdate'); + } + return translate('workspace.rules.merchantRules.confirmError'); +}; + +function AddMerchantRulePage({route}: AddMerchantRulePageProps) { + const {translate} = useLocalize(); + const styles = useThemeStyles(); + const policyID = route.params.policyID; + const policy = usePolicy(policyID); + + const [form] = useOnyx(ONYXKEYS.FORMS.MERCHANT_RULE_FORM, {canBeMissing: true}); + const [policyCategories] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY_CATEGORIES}${policyID}`, {canBeMissing: true}); + const [policyTags] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY_TAGS}${policyID}`, {canBeMissing: true}); + const [shouldShowError, setShouldShowError] = useState(false); + + useEffect(() => () => clearDraftMerchantRule(), []); + + const hasCategories = () => { + if (!policy?.areCategoriesEnabled) { + return false; + } + return Object.keys(policyCategories ?? {}).length > 0; + }; + + const hasTags = () => { + if (!policy?.areTagsEnabled) { + return false; + } + const tagNames = getTagNamesFromTagsLists(policyTags ?? {}); + return tagNames.length > 0; + }; + + const hasTaxes = () => { + if (!policy?.tax?.trackingEnabled) { + return false; + } + return Object.keys(policy?.taxRates?.taxes ?? {}).length > 0; + }; + + const isBillableEnabled = policy?.disabledFields?.defaultBillable !== true; + + const categoryDisplayName = form?.category ? getDecodedCategoryName(form.category) : undefined; + const tagDisplayName = form?.tag ? getCleanedTagName(form.tag) : undefined; + const taxDisplayName = () => { + if (!form?.tax || !policy?.taxRates?.taxes) { + return undefined; + } + const tax = policy.taxRates.taxes[form.tax]; + return tax ? `${tax.name} (${tax.value})` : undefined; + }; + + const errorMessage = getErrorMessage(translate, form); + + const handleSubmit = () => { + if (errorMessage) { + setShouldShowError(true); + return; + } + if (!form) { + return; + } + + setPolicyCodingRule(policyID, form, policy); + Navigation.goBack(); + }; + + const sections: SectionType[] = [ + { + titleTranslationKey: 'workspace.rules.merchantRules.expensesWith', + items: [ + { + descriptionTranslationKey: 'common.merchant', + required: true, + title: form?.merchantToMatch, + onPress: () => Navigation.navigate(ROUTES.RULES_MERCHANT_MERCHANT_TO_MATCH.getRoute(policyID)), + }, + ], + }, + { + titleTranslationKey: 'workspace.rules.merchantRules.applyUpdates', + items: [ + { + descriptionTranslationKey: 'common.merchant', + title: form?.merchant, + onPress: () => Navigation.navigate(ROUTES.RULES_MERCHANT_MERCHANT.getRoute(policyID)), + }, + hasCategories() + ? { + descriptionTranslationKey: 'common.category', + title: categoryDisplayName, + onPress: () => Navigation.navigate(ROUTES.RULES_MERCHANT_CATEGORY.getRoute(policyID)), + } + : undefined, + hasTags() + ? { + descriptionTranslationKey: 'common.tag', + title: tagDisplayName, + onPress: () => Navigation.navigate(ROUTES.RULES_MERCHANT_TAG.getRoute(policyID)), + } + : undefined, + hasTaxes() + ? { + descriptionTranslationKey: 'common.tax', + title: taxDisplayName(), + onPress: () => Navigation.navigate(ROUTES.RULES_MERCHANT_TAX.getRoute(policyID)), + } + : undefined, + { + descriptionTranslationKey: 'common.description', + title: form?.comment, + onPress: () => Navigation.navigate(ROUTES.RULES_MERCHANT_DESCRIPTION.getRoute(policyID)), + }, + { + descriptionTranslationKey: 'common.reimbursable', + title: getBooleanTitle(form?.reimbursable, translate), + onPress: () => Navigation.navigate(ROUTES.RULES_MERCHANT_REIMBURSABLE.getRoute(policyID)), + }, + isBillableEnabled + ? { + descriptionTranslationKey: 'common.billable', + title: getBooleanTitle(form?.billable, translate), + onPress: () => Navigation.navigate(ROUTES.RULES_MERCHANT_BILLABLE.getRoute(policyID)), + } + : undefined, + ], + }, + ]; + + return ( + + + + + {sections.map((section) => ( + + {translate(section.titleTranslationKey)} + {section.items + .filter((item): item is SectionItemType => !!item) + .map((item) => ( + + ))} + + ))} + + + + + ); +} + +AddMerchantRulePage.displayName = 'AddMerchantRulePage'; + +export default AddMerchantRulePage; diff --git a/src/pages/workspace/rules/MerchantRules/AddMerchantToMatchPage.tsx b/src/pages/workspace/rules/MerchantRules/AddMerchantToMatchPage.tsx new file mode 100644 index 0000000000000..45ddd6b04f2c6 --- /dev/null +++ b/src/pages/workspace/rules/MerchantRules/AddMerchantToMatchPage.tsx @@ -0,0 +1,44 @@ +import React from 'react'; +import type {FormOnyxValues} from '@components/Form/types'; +import RuleTextBase from '@components/Rule/RuleTextBase'; +import {updateDraftMerchantRule} from '@libs/actions/User'; +import Navigation from '@libs/Navigation/Navigation'; +import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types'; +import type {SettingsNavigatorParamList} from '@libs/Navigation/types'; +import CONST from '@src/CONST'; +import ONYXKEYS from '@src/ONYXKEYS'; +import ROUTES from '@src/ROUTES'; +import type SCREENS from '@src/SCREENS'; + +type AddMerchantToMatchPageProps = PlatformStackScreenProps; + +function AddMerchantToMatchPage({route}: AddMerchantToMatchPageProps) { + const policyID = route.params.policyID; + + const goBack = () => { + Navigation.goBack(ROUTES.RULES_MERCHANT_NEW.getRoute(policyID)); + }; + + const onSave = (values: FormOnyxValues) => { + updateDraftMerchantRule(values); + goBack(); + }; + + return ( + + ); +} + +AddMerchantToMatchPage.displayName = 'AddMerchantToMatchPage'; + +export default AddMerchantToMatchPage; diff --git a/src/pages/workspace/rules/MerchantRules/AddReimbursablePage.tsx b/src/pages/workspace/rules/MerchantRules/AddReimbursablePage.tsx new file mode 100644 index 0000000000000..843bcd7a4fd62 --- /dev/null +++ b/src/pages/workspace/rules/MerchantRules/AddReimbursablePage.tsx @@ -0,0 +1,39 @@ +import React from 'react'; +import RuleBooleanBase from '@components/Rule/RuleBooleanBase'; +import {updateDraftMerchantRule} from '@libs/actions/User'; +import Navigation from '@libs/Navigation/Navigation'; +import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types'; +import type {SettingsNavigatorParamList} from '@libs/Navigation/types'; +import CONST from '@src/CONST'; +import ONYXKEYS from '@src/ONYXKEYS'; +import ROUTES from '@src/ROUTES'; +import type SCREENS from '@src/SCREENS'; + +type AddReimbursablePageProps = PlatformStackScreenProps; + +function AddReimbursablePage({route}: AddReimbursablePageProps) { + const policyID = route.params.policyID; + + const goBack = () => { + Navigation.goBack(ROUTES.RULES_MERCHANT_NEW.getRoute(policyID)); + }; + + const onSelect = (fieldID: string, value: boolean | 'true' | 'false' | null) => { + updateDraftMerchantRule({[fieldID]: value}); + goBack(); + }; + + return ( + + ); +} + +AddReimbursablePage.displayName = 'AddReimbursablePage'; + +export default AddReimbursablePage; diff --git a/src/pages/workspace/rules/MerchantRules/AddTagPage.tsx b/src/pages/workspace/rules/MerchantRules/AddTagPage.tsx new file mode 100644 index 0000000000000..8d8cd62d37ad5 --- /dev/null +++ b/src/pages/workspace/rules/MerchantRules/AddTagPage.tsx @@ -0,0 +1,59 @@ +import React, {useMemo} from 'react'; +import RuleSelectionBase from '@components/Rule/RuleSelectionBase'; +import useOnyx from '@hooks/useOnyx'; +import {updateDraftMerchantRule} from '@libs/actions/User'; +import Navigation from '@libs/Navigation/Navigation'; +import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types'; +import type {SettingsNavigatorParamList} from '@libs/Navigation/types'; +import {getCleanedTagName} from '@libs/PolicyUtils'; +import ONYXKEYS from '@src/ONYXKEYS'; +import ROUTES from '@src/ROUTES'; +import type SCREENS from '@src/SCREENS'; + +type AddTagPageProps = PlatformStackScreenProps; + +function AddTagPage({route}: AddTagPageProps) { + const policyID = route.params.policyID; + + const [form] = useOnyx(ONYXKEYS.FORMS.MERCHANT_RULE_FORM, {canBeMissing: true}); + const [policyTags] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY_TAGS}${policyID}`, {canBeMissing: true}); + + const selectedTagItem = form?.tag ? {name: getCleanedTagName(form.tag), value: form.tag} : undefined; + + const tagItems = useMemo(() => { + const tags: Array<{name: string; value: string}> = []; + + for (const tagList of Object.values(policyTags ?? {})) { + for (const tag of Object.values(tagList?.tags ?? {})) { + if (!tag.enabled) { + continue; + } + tags.push({name: getCleanedTagName(tag.name), value: tag.name}); + } + } + + return tags; + }, [policyTags]); + + const backToRoute = ROUTES.RULES_MERCHANT_NEW.getRoute(policyID); + + const onSave = (value?: string) => { + updateDraftMerchantRule({tag: value}); + }; + + return ( + Navigation.goBack(backToRoute)} + backToRoute={backToRoute} + /> + ); +} + +AddTagPage.displayName = 'AddTagPage'; + +export default AddTagPage; diff --git a/src/pages/workspace/rules/MerchantRules/AddTaxPage.tsx b/src/pages/workspace/rules/MerchantRules/AddTaxPage.tsx new file mode 100644 index 0000000000000..4d936107069f2 --- /dev/null +++ b/src/pages/workspace/rules/MerchantRules/AddTaxPage.tsx @@ -0,0 +1,51 @@ +import React from 'react'; +import RuleSelectionBase from '@components/Rule/RuleSelectionBase'; +import useOnyx from '@hooks/useOnyx'; +import {updateDraftMerchantRule} from '@libs/actions/User'; +import Navigation from '@libs/Navigation/Navigation'; +import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types'; +import type {SettingsNavigatorParamList} from '@libs/Navigation/types'; +import ONYXKEYS from '@src/ONYXKEYS'; +import ROUTES from '@src/ROUTES'; +import type SCREENS from '@src/SCREENS'; + +type AddTaxPageProps = PlatformStackScreenProps; + +function AddTaxPage({route}: AddTaxPageProps) { + const policyID = route.params.policyID; + + const [form] = useOnyx(ONYXKEYS.FORMS.MERCHANT_RULE_FORM, {canBeMissing: true}); + const [policy] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY}${policyID}`, {canBeMissing: true}); + + const taxes = policy?.taxRates?.taxes ?? {}; + const taxItems = Object.entries(taxes) + .filter(([, tax]) => !tax.isDisabled) + .map(([taxKey, tax]) => ({ + name: `${tax.name} (${tax.value})`, + value: taxKey, + })); + + const selectedTaxItem = form?.tax ? taxItems.find(({value}) => value === form.tax) : undefined; + + const backToRoute = ROUTES.RULES_MERCHANT_NEW.getRoute(policyID); + + const onSave = (value?: string) => { + updateDraftMerchantRule({tax: value}); + }; + + return ( + Navigation.goBack(backToRoute)} + backToRoute={backToRoute} + /> + ); +} + +AddTaxPage.displayName = 'AddTaxPage'; + +export default AddTaxPage; diff --git a/src/pages/workspace/rules/MerchantRulesSection.tsx b/src/pages/workspace/rules/MerchantRulesSection.tsx index c07048146de2e..af0f84c4506bb 100644 --- a/src/pages/workspace/rules/MerchantRulesSection.tsx +++ b/src/pages/workspace/rules/MerchantRulesSection.tsx @@ -12,7 +12,9 @@ import usePolicy from '@hooks/usePolicy'; import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; import {getDecodedCategoryName} from '@libs/CategoryUtils'; +import Navigation from '@libs/Navigation/Navigation'; import {getCleanedTagName} from '@libs/PolicyUtils'; +import ROUTES from '@src/ROUTES'; import type {CodingRule} from '@src/types/onyx/Policy'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; @@ -46,7 +48,7 @@ function getRuleDescription(rule: CodingRule, translate: ReturnType @@ -147,7 +149,7 @@ function MerchantRulesSection({policyID}: MerchantRulesSectionProps) { iconHeight={20} iconWidth={20} style={[styles.sectionMenuItemTopDescription, !hasRules && styles.mt6, styles.mbn3]} - onPress={() => {}} + onPress={() => Navigation.navigate(ROUTES.RULES_MERCHANT_NEW.getRoute(policyID))} /> ); diff --git a/src/types/form/MerchantRuleForm.ts b/src/types/form/MerchantRuleForm.ts new file mode 100644 index 0000000000000..43e3e87c11357 --- /dev/null +++ b/src/types/form/MerchantRuleForm.ts @@ -0,0 +1,24 @@ +import type {ValueOf} from 'type-fest'; +import CONST from '@src/CONST'; +import type Form from './Form'; + +const INPUT_IDS = CONST.MERCHANT_RULES.FIELDS; + +type InputID = ValueOf; + +type MerchantRuleForm = Form< + InputID, + { + [INPUT_IDS.BILLABLE]: boolean; + [INPUT_IDS.CATEGORY]: string; + [INPUT_IDS.DESCRIPTION]: string; + [INPUT_IDS.MERCHANT]: string; + [INPUT_IDS.MERCHANT_TO_MATCH]: string; + [INPUT_IDS.REIMBURSABLE]: boolean; + [INPUT_IDS.TAG]: string; + [INPUT_IDS.TAX]: string; + } +>; + +export type {MerchantRuleForm, InputID}; +export default INPUT_IDS; diff --git a/src/types/form/index.ts b/src/types/form/index.ts index b165f9068d6be..cac1d914cea61 100644 --- a/src/types/form/index.ts +++ b/src/types/form/index.ts @@ -104,4 +104,5 @@ export type {CreateDomainForm} from './CreateDomainForm'; export type {SplitExpenseEditDateForm} from './SplitExpenseEditDateForm'; export type {ResetDomainForm} from './ResetDomainForm'; export type {ExpenseRuleForm} from './ExpenseRuleForm'; +export type {MerchantRuleForm} from './MerchantRuleForm'; export type {AddDomainMemberForm} from './AddDomainMemberForm'; diff --git a/src/types/onyx/ExpenseRule.ts b/src/types/onyx/ExpenseRule.ts index 7880a17e988e1..9d54945fac588 100644 --- a/src/types/onyx/ExpenseRule.ts +++ b/src/types/onyx/ExpenseRule.ts @@ -1,5 +1,5 @@ -/** Model of tax rate */ -type TaxRate = { +/** Model of tax rate on a personal rule */ +type PersonalRuleTaxRate = { /** The tax ID */ externalID: string; @@ -7,6 +7,18 @@ type TaxRate = { value: string; }; +/** Model of tax rate on a policy rule */ +type PolicyRuleTaxRate = { + /** The tax ID */ + externalID: string; + + /** The tax rate */ + value: string; + + /** The name of the tax rate */ + name: string; +}; + /** Model of expense rule */ type ExpenseRule = { /** Whether the transaction is set to be billable */ @@ -37,8 +49,8 @@ type ExpenseRule = { tag?: string; /** The tax rate set by the rule */ - tax?: Record; + tax?: Record; }; -export type {TaxRate}; +export type {PersonalRuleTaxRate, PolicyRuleTaxRate}; export default ExpenseRule; diff --git a/src/types/onyx/OriginalMessage.ts b/src/types/onyx/OriginalMessage.ts index 912dbdd73757c..38e14f12eb7d3 100644 --- a/src/types/onyx/OriginalMessage.ts +++ b/src/types/onyx/OriginalMessage.ts @@ -1,6 +1,7 @@ import type {ValueOf} from 'type-fest'; import type CONST from '@src/CONST'; import type DeepValueOf from '@src/types/utils/DeepValueOf'; +import type {PolicyRuleTaxRate} from './ExpenseRule'; import type {Attendee} from './IOU'; import type {OldDotOriginalMessageMap} from './OldDotAction'; import type {AllConnectionName} from './Policy'; @@ -731,10 +732,44 @@ type OriginalMessageModifiedExpense = { /** Whether the updated description was generated by AI */ aiGenerated?: boolean; + /** The policy ID that the expense was modified in */ + policyID?: string; + + /** The fields that were modified by policy rules */ + policyRulesModifiedFields?: PolicyRulesModifiedFields; + /** The Concierge reasoning for the action */ reasoning?: string; }; +/** Policy rules modified fields */ +type PolicyRulesModifiedFields = { + /** The value that the merchant was changed to */ + merchant?: string; + + /** The value that the amount was changed to */ + category?: string; + + /** The value that the tag was changed to */ + tag?: string; + + /** The value that the description was changed to */ + description?: string; + + /** The value that the billable status was changed to */ + billable?: boolean; + + /** The value that the reimbursable status was changed to */ + reimbursable?: boolean; + + /** The value that the tax was changed to */ + tax?: { + /** The tax rate being used */ + // eslint-disable-next-line @typescript-eslint/naming-convention + field_id_TAX: PolicyRuleTaxRate; + }; +}; + /** Model of a `travel update` report action */ type OriginalMessageTravelUpdate = Reservation & UpdateOperationType; @@ -1236,6 +1271,7 @@ export type { PaymentMethodType, OriginalMessageSource, Decision, + PolicyRulesModifiedFields, OriginalMessageChangeLog, JoinWorkspaceResolution, OriginalMessageModifiedExpense, diff --git a/src/types/onyx/Policy.ts b/src/types/onyx/Policy.ts index bff48c2d6e493..d8fde9159d653 100644 --- a/src/types/onyx/Policy.ts +++ b/src/types/onyx/Policy.ts @@ -1705,13 +1705,19 @@ type CodingRuleTax = { /** The external ID of the tax rate */ externalID: string; - /** The display value of the tax rate */ + /** The tax rate value (e.g., "8.5%") */ value: string; + + /** The name of the tax rate */ + name: string; }; }; /** Policy coding rule data model */ type CodingRule = { + /** Unique identifier for the rule */ + ruleID?: string; + /** Filter conditions for when this rule applies */ filters: CodingRuleFilter; diff --git a/src/types/onyx/SearchResults.ts b/src/types/onyx/SearchResults.ts index 6c3bb4652f59b..f09bb3fa35d7d 100644 --- a/src/types/onyx/SearchResults.ts +++ b/src/types/onyx/SearchResults.ts @@ -202,6 +202,21 @@ type SearchMerchantGroup = { currency: string; }; +/** Model of tag grouped search result */ +type SearchTagGroup = { + /** Tag name */ + tag: string; + + /** Number of transactions */ + count: number; + + /** Total value of transactions */ + total: number; + + /** Currency of total value */ + currency: string; +}; + /** Model of month grouped search result */ type SearchMonthGroup = { /** Year */ @@ -234,7 +249,7 @@ type SearchResults = { PrefixedRecord & PrefixedRecord & PrefixedRecord & - PrefixedRecord; + PrefixedRecord; /** Whether search data is being fetched from server */ isLoading?: boolean; @@ -257,5 +272,6 @@ export type { SearchWithdrawalIDGroup, SearchCategoryGroup, SearchMerchantGroup, + SearchTagGroup, SearchMonthGroup, }; diff --git a/tests/unit/ModifiedExpenseMessageTest.ts b/tests/unit/ModifiedExpenseMessageTest.ts index 2ea0f4a436206..962e2cbe25923 100644 --- a/tests/unit/ModifiedExpenseMessageTest.ts +++ b/tests/unit/ModifiedExpenseMessageTest.ts @@ -1,3 +1,4 @@ +import {getEnvironmentURL} from '@libs/Environment/Environment'; import {getForReportAction, getMovedFromOrToReportMessage, getMovedReportID} from '@libs/ModifiedExpenseMessage'; // eslint-disable-next-line no-restricted-syntax -- this is required to allow mocking import * as PolicyUtils from '@libs/PolicyUtils'; @@ -798,6 +799,120 @@ describe('ModifiedExpenseMessage', () => { }); }); + describe('when policy rules modify an expense', () => { + let environmentURL: string; + beforeAll(async () => { + environmentURL = await getEnvironmentURL(); + }); + + it('returns the correct text message with multiple overrides', () => { + const reportAction = { + ...createRandomReportAction(1), + actionName: CONST.REPORT.ACTIONS.TYPE.MODIFIED_EXPENSE, + originalMessage: { + policyID: '1234', + policyRulesModifiedFields: { + category: 'Travel', + merchant: "McDonald's", + billable: true, + reimbursable: true, + }, + } as OriginalMessageModifiedExpense, + }; + + const result = getForReportAction({reportAction, policyID: report.policyID}); + + const expectedResult = `set the category to "Travel", merchant to "McDonald's", marked the expense as "billable", and marked the expense as "reimbursable" via workspace rules`; + + expect(result).toEqual(expectedResult); + }); + + it('returns the correct text message with tax rate overrides', () => { + const reportAction = { + ...createRandomReportAction(1), + actionName: CONST.REPORT.ACTIONS.TYPE.MODIFIED_EXPENSE, + originalMessage: { + policyID: '1234', + policyRulesModifiedFields: { + tax: { + // eslint-disable-next-line @typescript-eslint/naming-convention + field_id_TAX: { + externalID: '', + name: 'New Tax Rate', + value: '10', + }, + }, + }, + } as OriginalMessageModifiedExpense, + }; + + const result = getForReportAction({reportAction, policyID: report.policyID}); + + const expectedResult = `set the tax rate to "New Tax Rate" via workspace rules`; + + expect(result).toEqual(expectedResult); + }); + + it('returns the correct text message with two overrides', () => { + const reportAction = { + ...createRandomReportAction(1), + actionName: CONST.REPORT.ACTIONS.TYPE.MODIFIED_EXPENSE, + originalMessage: { + policyID: '1234', + policyRulesModifiedFields: { + category: 'Travel', + merchant: "McDonald's", + }, + } as OriginalMessageModifiedExpense, + }; + + const result = getForReportAction({reportAction, policyID: report.policyID}); + + const expectedResult = `set the category to "Travel" and merchant to "McDonald's" via workspace rules`; + + expect(result).toEqual(expectedResult); + }); + + it('returns the correct text message with a single override', () => { + const reportAction = { + ...createRandomReportAction(1), + actionName: CONST.REPORT.ACTIONS.TYPE.MODIFIED_EXPENSE, + originalMessage: { + policyID: '1234', + policyRulesModifiedFields: { + billable: true, + }, + } as OriginalMessageModifiedExpense, + }; + + const result = getForReportAction({reportAction, policyID: report.policyID}); + + const expectedResult = `marked the expense as "billable" via workspace rules`; + + expect(result).toEqual(expectedResult); + }); + + it('returns the correct text message with boolean overrides', () => { + const reportAction = { + ...createRandomReportAction(1), + actionName: CONST.REPORT.ACTIONS.TYPE.MODIFIED_EXPENSE, + originalMessage: { + policyID: '1234', + policyRulesModifiedFields: { + reimbursable: true, + billable: true, + }, + } as OriginalMessageModifiedExpense, + }; + + const result = getForReportAction({reportAction, policyID: report.policyID}); + + const expectedResult = `marked the expense as "reimbursable" and marked the expense as "billable" via workspace rules`; + + expect(result).toEqual(expectedResult); + }); + }); + describe('when the category is changed without source (backward compatibility)', () => { const reportAction = { ...createRandomReportAction(1), diff --git a/tests/unit/Search/SearchUIUtilsTest.ts b/tests/unit/Search/SearchUIUtilsTest.ts index 61dd50bc35eb9..0c6ec66a626cc 100644 --- a/tests/unit/Search/SearchUIUtilsTest.ts +++ b/tests/unit/Search/SearchUIUtilsTest.ts @@ -15,6 +15,7 @@ import type { TransactionMerchantGroupListItemType, TransactionMonthGroupListItemType, TransactionReportGroupListItemType, + TransactionTagGroupListItemType, TransactionWithdrawalIDGroupListItemType, } from '@components/SelectionListWithSections/types'; import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset'; @@ -54,6 +55,8 @@ jest.mock('@userActions/Search', () => ({ const adminAccountID = 18439984; const adminEmail = 'admin@policy.com'; +const receiverAccountID = 18439985; +const receiverEmail = 'receiver@policy.com'; const emptyPersonalDetails = { accountID: 0, @@ -1779,6 +1782,61 @@ const transactionMerchantGroupListItems: TransactionMerchantGroupListItemType[] }, ]; +const tagName1 = 'Project A'; +const tagName2 = 'Project B'; + +const searchResultsGroupByTag: OnyxTypes.SearchResults = { + data: { + personalDetailsList: {}, + [`${CONST.SEARCH.GROUP_PREFIX}${tagName1}` as const]: { + tag: tagName1, + count: 5, + currency: 'USD', + total: 250, + }, + [`${CONST.SEARCH.GROUP_PREFIX}${tagName2}` as const]: { + tag: tagName2, + count: 3, + currency: 'USD', + total: 75, + }, + }, + search: { + count: 8, + currency: 'USD', + hasMoreResults: false, + hasResults: true, + offset: 0, + status: CONST.SEARCH.STATUS.EXPENSE.ALL, + total: 325, + isLoading: false, + type: 'expense', + }, +}; + +const transactionTagGroupListItems: TransactionTagGroupListItemType[] = [ + { + tag: tagName1, + count: 5, + currency: 'USD', + total: 250, + groupedBy: CONST.SEARCH.GROUP_BY.TAG, + formattedTag: tagName1, + transactions: [], + transactionsQueryJSON: undefined, + }, + { + tag: tagName2, + count: 3, + currency: 'USD', + total: 75, + groupedBy: CONST.SEARCH.GROUP_BY.TAG, + formattedTag: tagName2, + transactions: [], + transactionsQueryJSON: undefined, + }, +]; + const transactionMerchantGroupListItemsSorted: TransactionMerchantGroupListItemType[] = [ { merchant: merchantName1, @@ -3050,6 +3108,148 @@ describe('SearchUIUtils', () => { expect(result.some((item) => item.merchant === 'Walmart (Express)')).toBe(true); expect(result.some((item) => item.merchant === '"Best" Coffee')).toBe(true); }); + + // Tag groupBy tests + it('should return getTagSections result when type is EXPENSE and groupBy is tag', () => { + expect( + SearchUIUtils.getSections({ + type: CONST.SEARCH.DATA_TYPES.EXPENSE, + data: searchResultsGroupByTag.data, + currentAccountID: 2074551, + currentUserEmail: '', + translate: translateLocal, + formatPhoneNumber, + bankAccountList: {}, + groupBy: CONST.SEARCH.GROUP_BY.TAG, + })[0], + ).toStrictEqual(transactionTagGroupListItems); + }); + + it('should handle empty tag values correctly', () => { + const dataWithEmptyTag: OnyxTypes.SearchResults['data'] = { + personalDetailsList: {}, + [`${CONST.SEARCH.GROUP_PREFIX}empty` as const]: { + tag: '', + count: 2, + currency: 'USD', + total: 50, + }, + [`${CONST.SEARCH.GROUP_PREFIX}none` as const]: { + tag: CONST.SEARCH.TAG_EMPTY_VALUE, + count: 1, + currency: 'USD', + total: 25, + }, + }; + + const [result] = SearchUIUtils.getSections({ + type: CONST.SEARCH.DATA_TYPES.EXPENSE, + data: dataWithEmptyTag, + currentAccountID: 2074551, + currentUserEmail: '', + translate: translateLocal, + formatPhoneNumber, + bankAccountList: {}, + groupBy: CONST.SEARCH.GROUP_BY.TAG, + }) as [TransactionTagGroupListItemType[], number]; + + expect(result).toHaveLength(2); + expect(result.some((item) => item.tag === '')).toBe(true); + expect(result.some((item) => item.tag === CONST.SEARCH.TAG_EMPTY_VALUE)).toBe(true); + }); + + it('should handle "(untagged)" value from backend', () => { + const dataWithUntagged: OnyxTypes.SearchResults['data'] = { + personalDetailsList: {}, + [`${CONST.SEARCH.GROUP_PREFIX}untagged` as const]: { + tag: '(untagged)', + count: 3, + currency: 'USD', + total: 100, + }, + }; + + const [result] = SearchUIUtils.getSections({ + type: CONST.SEARCH.DATA_TYPES.EXPENSE, + data: dataWithUntagged, + currentAccountID: 2074551, + currentUserEmail: '', + translate: translateLocal, + formatPhoneNumber, + bankAccountList: {}, + groupBy: CONST.SEARCH.GROUP_BY.TAG, + }) as [TransactionTagGroupListItemType[], number]; + + expect(result).toHaveLength(1); + expect(result.at(0)?.tag).toBe('(untagged)'); + }); + + it('should return isTransactionTagGroupListItemType true for tag group items', () => { + const tagItem: TransactionTagGroupListItemType = { + tag: 'Project A', + count: 5, + currency: 'USD', + total: 250, + groupedBy: CONST.SEARCH.GROUP_BY.TAG, + formattedTag: 'Project A', + transactions: [], + transactionsQueryJSON: undefined, + }; + + expect(SearchUIUtils.isTransactionTagGroupListItemType(tagItem)).toBe(true); + }); + + it('should return isTransactionTagGroupListItemType false for non-tag group items', () => { + const categoryItem: TransactionCategoryGroupListItemType = { + category: 'Travel', + count: 5, + currency: 'USD', + total: 250, + groupedBy: CONST.SEARCH.GROUP_BY.CATEGORY, + formattedCategory: 'Travel', + transactions: [], + transactionsQueryJSON: undefined, + }; + + expect(SearchUIUtils.isTransactionTagGroupListItemType(categoryItem)).toBe(false); + }); + + it('should generate transactionsQueryJSON with valid hash for tag sections', () => { + const [result] = SearchUIUtils.getSections({ + type: CONST.SEARCH.DATA_TYPES.EXPENSE, + data: searchResultsGroupByTag.data, + currentAccountID: 2074551, + currentUserEmail: '', + translate: translateLocal, + formatPhoneNumber, + bankAccountList: {}, + groupBy: CONST.SEARCH.GROUP_BY.TAG, + queryJSON: { + type: CONST.SEARCH.DATA_TYPES.EXPENSE, + status: '', + sortBy: CONST.SEARCH.TABLE_COLUMNS.DATE, + sortOrder: CONST.SEARCH.SORT_ORDER.DESC, + view: CONST.SEARCH.VIEW.TABLE, + hash: 12345, + flatFilters: [], + inputQuery: 'type:expense groupBy:tag', + recentSearchHash: 12345, + similarSearchHash: 12345, + filters: { + operator: CONST.SEARCH.SYNTAX_OPERATORS.AND, + left: CONST.SEARCH.SYNTAX_FILTER_KEYS.TYPE, + right: CONST.SEARCH.DATA_TYPES.EXPENSE, + }, + }, + }) as [TransactionTagGroupListItemType[], number]; + + // Each tag section should have a transactionsQueryJSON with a hash + for (const item of result) { + expect(item.transactionsQueryJSON).toBeDefined(); + expect(item.transactionsQueryJSON?.hash).toBeDefined(); + expect(typeof item.transactionsQueryJSON?.hash).toBe('number'); + } + }); }); describe('Test getSortedSections', () => { @@ -3331,6 +3531,134 @@ describe('SearchUIUtils', () => { expect(result.at(0)?.count).toBe(7); expect(result.at(1)?.count).toBe(4); }); + + // Tag sorting tests + it('should return getSortedTagData result when type is EXPENSE and groupBy is tag', () => { + expect( + SearchUIUtils.getSortedSections( + CONST.SEARCH.DATA_TYPES.EXPENSE, + '', + transactionTagGroupListItems, + localeCompare, + translateLocal, + CONST.SEARCH.TABLE_COLUMNS.DATE, + CONST.SEARCH.SORT_ORDER.ASC, + CONST.SEARCH.GROUP_BY.TAG, + ), + ).toStrictEqual(transactionTagGroupListItems); + }); + + it('should sort tag data by tag name in ascending order', () => { + const result = SearchUIUtils.getSortedSections( + CONST.SEARCH.DATA_TYPES.EXPENSE, + '', + transactionTagGroupListItems, + localeCompare, + translateLocal, + CONST.SEARCH.TABLE_COLUMNS.GROUP_TAG, + CONST.SEARCH.SORT_ORDER.ASC, + CONST.SEARCH.GROUP_BY.TAG, + ) as TransactionTagGroupListItemType[]; + + // "Project A" should come before "Project B" in ascending alphabetical order + expect(result.at(0)?.tag).toBe(tagName1); + expect(result.at(1)?.tag).toBe(tagName2); + }); + + it('should sort tag data by tag name in descending order', () => { + const result = SearchUIUtils.getSortedSections( + CONST.SEARCH.DATA_TYPES.EXPENSE, + '', + transactionTagGroupListItems, + localeCompare, + translateLocal, + CONST.SEARCH.TABLE_COLUMNS.GROUP_TAG, + CONST.SEARCH.SORT_ORDER.DESC, + CONST.SEARCH.GROUP_BY.TAG, + ) as TransactionTagGroupListItemType[]; + + // "Project B" should come before "Project A" in descending alphabetical order + expect(result.at(0)?.tag).toBe(tagName2); + expect(result.at(1)?.tag).toBe(tagName1); + }); + + it('should sort tag data by total amount', () => { + const result = SearchUIUtils.getSortedSections( + CONST.SEARCH.DATA_TYPES.EXPENSE, + '', + transactionTagGroupListItems, + localeCompare, + translateLocal, + CONST.SEARCH.TABLE_COLUMNS.GROUP_TOTAL, + CONST.SEARCH.SORT_ORDER.DESC, + CONST.SEARCH.GROUP_BY.TAG, + ) as TransactionTagGroupListItemType[]; + + // Project A (250) should come before Project B (75) when sorted by total descending + expect(result.at(0)?.total).toBe(250); + expect(result.at(1)?.total).toBe(75); + }); + + it('should sort "No tag" alphabetically with other tags (not at the top)', () => { + // Create raw search results data WITHOUT formattedTag - + // this is what comes from the backend. getSections will call getTagSections + // which populates formattedTag with the translated "No tag" text for empty tags. + const dataWithEmptyTag: OnyxTypes.SearchResults['data'] = { + personalDetailsList: {}, + [`${CONST.SEARCH.GROUP_PREFIX}123456` as const]: { + tag: 'Zulu', + count: 2, + currency: 'USD', + total: 100, + }, + [`${CONST.SEARCH.GROUP_PREFIX}789012` as const]: { + // Empty tag - should become "No tag" in formattedTag + tag: '', + count: 1, + currency: 'USD', + total: 50, + }, + [`${CONST.SEARCH.GROUP_PREFIX}345678` as const]: { + tag: 'Alpha', + count: 3, + currency: 'USD', + total: 150, + }, + }; + + // First, call getSections to process raw data through getTagSections. + // This is where formattedTag gets populated + const [sections] = SearchUIUtils.getSections({ + type: CONST.SEARCH.DATA_TYPES.EXPENSE, + data: dataWithEmptyTag, + currentAccountID: 2074551, + currentUserEmail: '', + translate: translateLocal, + formatPhoneNumber, + bankAccountList: {}, + groupBy: CONST.SEARCH.GROUP_BY.TAG, + }) as [TransactionTagGroupListItemType[], number]; + + // Then sort the sections + const result = SearchUIUtils.getSortedSections( + CONST.SEARCH.DATA_TYPES.EXPENSE, + '', + sections, + localeCompare, + translateLocal, + CONST.SEARCH.TABLE_COLUMNS.GROUP_TAG, + CONST.SEARCH.SORT_ORDER.ASC, + CONST.SEARCH.GROUP_BY.TAG, + ) as TransactionTagGroupListItemType[]; + + const emptyTagDisplayText = translateLocal('search.noTag'); + + // In ascending alphabetical order: Alpha < No tag < Zulu + // "No tag" should NOT be at the top (that was the bug with empty string sorting) + expect(result.at(0)?.formattedTag).toBe('Alpha'); + expect(result.at(1)?.formattedTag).toBe(emptyTagDisplayText); + expect(result.at(2)?.formattedTag).toBe('Zulu'); + }); }); describe('Test createTypeMenuItems', () => { @@ -4459,4 +4787,216 @@ describe('SearchUIUtils', () => { expect(transactionThread).toBeTruthy(); }); }); + + describe('getToFieldValueForTransaction', () => { + const mockTransaction: OnyxTypes.Transaction = { + transactionID: '1', + amount: 1000, + currency: 'USD', + reportID, + accountID: adminAccountID, + created: '2024-12-21 13:05:20', + merchant: 'Test Merchant', + } as OnyxTypes.Transaction; + + const mockPersonalDetails: OnyxTypes.PersonalDetailsList = { + [adminAccountID]: { + accountID: adminAccountID, + displayName: 'Admin User', + login: adminEmail, + avatar: 'https://example.com/avatar.png', + }, + [receiverAccountID]: { + accountID: receiverAccountID, + displayName: 'Receiver User', + login: receiverEmail, + avatar: 'https://example.com/avatar2.png', + }, + }; + + test('Should return emptyPersonalDetails when report is undefined', () => { + const result = SearchUIUtils.getToFieldValueForTransaction(mockTransaction, undefined, mockPersonalDetails, undefined); + expect(result).toEqual(emptyPersonalDetails); + }); + + test('Should return emptyPersonalDetails when report is an open expense report', () => { + const openExpenseReport: OnyxTypes.Report = { + ...report1, + stateNum: CONST.REPORT.STATE_NUM.OPEN, + statusNum: CONST.REPORT.STATUS_NUM.OPEN, + } as OnyxTypes.Report; + + const result = SearchUIUtils.getToFieldValueForTransaction(mockTransaction, openExpenseReport, mockPersonalDetails, undefined); + expect(result).toEqual(emptyPersonalDetails); + }); + + test('Should return ownerAccountID personal details when reportAction is PAY type and report has ownerAccountID', () => { + const payReportAction: OnyxTypes.ReportAction = { + ...reportAction1, + originalMessage: { + type: CONST.IOU.REPORT_ACTION_TYPE.PAY, + IOUTransactionID: mockTransaction.transactionID, + IOUReportID: report1.reportID, + }, + } as OnyxTypes.ReportAction; + + const nonOpenReport: OnyxTypes.Report = { + ...report1, + stateNum: CONST.REPORT.STATE_NUM.SUBMITTED, + statusNum: CONST.REPORT.STATUS_NUM.SUBMITTED, + ownerAccountID: adminAccountID, + } as OnyxTypes.Report; + + const result = SearchUIUtils.getToFieldValueForTransaction(mockTransaction, nonOpenReport, mockPersonalDetails, payReportAction); + expect(result).toEqual(mockPersonalDetails[adminAccountID]); + }); + + test('Should return managerID personal details when reportAction is not a money request action', () => { + const nonMoneyRequestAction: OnyxTypes.ReportAction = { + ...reportAction1, + actionName: CONST.REPORT.ACTIONS.TYPE.CREATED, + originalMessage: undefined, + } as OnyxTypes.ReportAction; + + const nonOpenReport: OnyxTypes.Report = { + ...report1, + stateNum: CONST.REPORT.STATE_NUM.SUBMITTED, + statusNum: CONST.REPORT.STATUS_NUM.SUBMITTED, + managerID: receiverAccountID, + } as OnyxTypes.Report; + + const result = SearchUIUtils.getToFieldValueForTransaction(mockTransaction, nonOpenReport, mockPersonalDetails, nonMoneyRequestAction); + expect(result).toEqual(mockPersonalDetails[receiverAccountID]); + }); + + test('Should return getIOUPayerAndReceiver result for IOU report with managerID', () => { + const iouReport: OnyxTypes.Report = { + ...report3, + managerID: receiverAccountID, + ownerAccountID: adminAccountID, + type: CONST.REPORT.TYPE.IOU, + } as OnyxTypes.Report; + + const transactionWithNegativeAmount: OnyxTypes.Transaction = { + ...mockTransaction, + amount: -1000, + modifiedAmount: 1000, + } as OnyxTypes.Transaction; + + const result = SearchUIUtils.getToFieldValueForTransaction(transactionWithNegativeAmount, iouReport, mockPersonalDetails, undefined); + expect(result).toEqual(mockPersonalDetails[receiverAccountID]); + }); + + test('Should return getIOUPayerAndReceiver result for IOU report with positive amount', () => { + const iouReport: OnyxTypes.Report = { + ...report3, + managerID: receiverAccountID, + ownerAccountID: adminAccountID, + type: CONST.REPORT.TYPE.IOU, + } as OnyxTypes.Report; + + const transactionWithPositiveAmount: OnyxTypes.Transaction = { + ...mockTransaction, + amount: 1000, + } as OnyxTypes.Transaction; + + const result = SearchUIUtils.getToFieldValueForTransaction(transactionWithPositiveAmount, iouReport, mockPersonalDetails, undefined); + expect(result).toEqual(mockPersonalDetails[receiverAccountID]); + }); + + test('Should use modifiedAmount when available for IOU report', () => { + const iouReport: OnyxTypes.Report = { + ...report3, + managerID: receiverAccountID, + ownerAccountID: adminAccountID, + type: CONST.REPORT.TYPE.IOU, + } as OnyxTypes.Report; + + const transactionWithModifiedAmount: OnyxTypes.Transaction = { + ...mockTransaction, + amount: 1000, + modifiedAmount: -2000, + } as OnyxTypes.Transaction; + + const result = SearchUIUtils.getToFieldValueForTransaction(transactionWithModifiedAmount, iouReport, mockPersonalDetails, undefined); + expect(result).toEqual(mockPersonalDetails[adminAccountID]); + }); + + test('Should return managerID personal details for non-IOU report with managerID', () => { + const nonIOUReport: OnyxTypes.Report = { + ...report1, + stateNum: CONST.REPORT.STATE_NUM.SUBMITTED, + statusNum: CONST.REPORT.STATUS_NUM.SUBMITTED, + managerID: receiverAccountID, + type: CONST.REPORT.TYPE.EXPENSE, + } as OnyxTypes.Report; + + const result = SearchUIUtils.getToFieldValueForTransaction(mockTransaction, nonIOUReport, mockPersonalDetails, undefined); + expect(result).toEqual(mockPersonalDetails[receiverAccountID]); + }); + + test('Should return emptyPersonalDetails when managerID personal details are not found', () => { + const nonIOUReport: OnyxTypes.Report = { + ...report1, + stateNum: CONST.REPORT.STATE_NUM.SUBMITTED, + statusNum: CONST.REPORT.STATUS_NUM.SUBMITTED, + managerID: 999999, + type: CONST.REPORT.TYPE.EXPENSE, + } as OnyxTypes.Report; + + const result = SearchUIUtils.getToFieldValueForTransaction(mockTransaction, nonIOUReport, mockPersonalDetails, undefined); + expect(result).toEqual(emptyPersonalDetails); + }); + + test('Should return emptyPersonalDetails when report has no managerID', () => { + const reportWithoutManager: OnyxTypes.Report = { + ...report1, + stateNum: CONST.REPORT.STATE_NUM.SUBMITTED, + statusNum: CONST.REPORT.STATUS_NUM.SUBMITTED, + managerID: undefined, + type: CONST.REPORT.TYPE.EXPENSE, + } as OnyxTypes.Report; + + const result = SearchUIUtils.getToFieldValueForTransaction(mockTransaction, reportWithoutManager, mockPersonalDetails, undefined); + expect(result).toEqual(emptyPersonalDetails); + }); + + test('Should return emptyPersonalDetails when getIOUPayerAndReceiver returns undefined for IOU report', () => { + const iouReport: OnyxTypes.Report = { + ...report3, + managerID: receiverAccountID, + ownerAccountID: adminAccountID, + type: CONST.REPORT.TYPE.IOU, + } as OnyxTypes.Report; + + const emptyPersonalDetailsList: OnyxTypes.PersonalDetailsList = {}; + + const result = SearchUIUtils.getToFieldValueForTransaction(mockTransaction, iouReport, emptyPersonalDetailsList, undefined); + expect(result).toEqual(emptyPersonalDetails); + }); + + test('Should handle IOU report with DEFAULT_NUMBER_ID for managerID', () => { + const iouReport: OnyxTypes.Report = { + ...report3, + managerID: CONST.DEFAULT_NUMBER_ID, + ownerAccountID: adminAccountID, + type: CONST.REPORT.TYPE.IOU, + } as OnyxTypes.Report; + + const result = SearchUIUtils.getToFieldValueForTransaction(mockTransaction, iouReport, mockPersonalDetails, undefined); + expect(result).toBeDefined(); + }); + + test('Should handle IOU report with DEFAULT_NUMBER_ID for ownerAccountID', () => { + const iouReport: OnyxTypes.Report = { + ...report3, + managerID: receiverAccountID, + ownerAccountID: CONST.DEFAULT_NUMBER_ID, + type: CONST.REPORT.TYPE.IOU, + } as OnyxTypes.Report; + + const result = SearchUIUtils.getToFieldValueForTransaction(mockTransaction, iouReport, mockPersonalDetails, undefined); + expect(result).toBeDefined(); + }); + }); }); From 6f1357d62e338c3753bf51b6c79c491ffdd9377a Mon Sep 17 00:00:00 2001 From: TaduJR Date: Wed, 28 Jan 2026 03:05:16 +0300 Subject: [PATCH 05/24] fix: Revert unintended Mobile-Expensify submodule change --- Mobile-Expensify | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Mobile-Expensify b/Mobile-Expensify index e753eabb8cc03..0961934361353 160000 --- a/Mobile-Expensify +++ b/Mobile-Expensify @@ -1 +1 @@ -Subproject commit e753eabb8cc0351156a223a7a9a91a8b2b15f289 +Subproject commit 0961934361353ab8d4b10b7b45d509da523713b9 From 66c795307952efd052763f0377454a017c0e3634 Mon Sep 17 00:00:00 2001 From: TaduJR Date: Wed, 28 Jan 2026 03:23:47 +0300 Subject: [PATCH 06/24] refactor: Address PR review feedback for list item headers - Export BaseListItemHeaderProps from BaseListItemHeader - Extend base props in CategoryListItemHeader, MerchantListItemHeader - Refactor TagListItemHeader to use BaseListItemHeader - Refactor MonthListItemHeader to use BaseListItemHeader - Add support for GROUP_TAG and GROUP_MONTH columns in BaseListItemHeader --- .../Search/BaseListItemHeader.tsx | 19 ++- .../Search/CategoryListItemHeader.tsx | 29 +--- .../Search/MerchantListItemHeader.tsx | 29 +--- .../Search/MonthListItemHeader.tsx | 132 +++-------------- .../Search/TagListItemHeader.tsx | 133 +++--------------- 5 files changed, 53 insertions(+), 289 deletions(-) diff --git a/src/components/SelectionListWithSections/Search/BaseListItemHeader.tsx b/src/components/SelectionListWithSections/Search/BaseListItemHeader.tsx index a8bf835fe4fa4..576f06511391a 100644 --- a/src/components/SelectionListWithSections/Search/BaseListItemHeader.tsx +++ b/src/components/SelectionListWithSections/Search/BaseListItemHeader.tsx @@ -25,6 +25,20 @@ type BaseGroupListItemType = TransactionGroupListItemType & { currency: string; }; +/** Supported group column keys for the base header */ +type GroupColumnKey = + | typeof CONST.SEARCH.TABLE_COLUMNS.GROUP_CATEGORY + | typeof CONST.SEARCH.TABLE_COLUMNS.GROUP_MERCHANT + | typeof CONST.SEARCH.TABLE_COLUMNS.GROUP_TAG + | typeof CONST.SEARCH.TABLE_COLUMNS.GROUP_MONTH; + +/** Supported column style keys for sizing */ +type ColumnStyleKey = + | typeof CONST.SEARCH.TABLE_COLUMNS.CATEGORY + | typeof CONST.SEARCH.TABLE_COLUMNS.MERCHANT + | typeof CONST.SEARCH.TABLE_COLUMNS.TAG + | typeof CONST.SEARCH.TABLE_COLUMNS.GROUP_MONTH; + type BaseListItemHeaderProps = { /** The group item being rendered */ item: BaseGroupListItemType; @@ -33,10 +47,10 @@ type BaseListItemHeaderProps = { displayName: string; /** The column key for the group name column (e.g., GROUP_CATEGORY, GROUP_MERCHANT) */ - groupColumnKey: typeof CONST.SEARCH.TABLE_COLUMNS.GROUP_CATEGORY | typeof CONST.SEARCH.TABLE_COLUMNS.GROUP_MERCHANT; + groupColumnKey: GroupColumnKey; /** The column style key for sizing (e.g., CATEGORY, MERCHANT) */ - columnStyleKey: typeof CONST.SEARCH.TABLE_COLUMNS.CATEGORY | typeof CONST.SEARCH.TABLE_COLUMNS.MERCHANT; + columnStyleKey: ColumnStyleKey; /** Callback to fire when a checkbox is pressed */ onCheckboxPress?: (item: TItem) => void; @@ -163,3 +177,4 @@ function BaseListItemHeader({ } export default BaseListItemHeader; +export type {BaseListItemHeaderProps, BaseGroupListItemType}; diff --git a/src/components/SelectionListWithSections/Search/CategoryListItemHeader.tsx b/src/components/SelectionListWithSections/Search/CategoryListItemHeader.tsx index 1e4d94b87f292..c0f26f9f34652 100644 --- a/src/components/SelectionListWithSections/Search/CategoryListItemHeader.tsx +++ b/src/components/SelectionListWithSections/Search/CategoryListItemHeader.tsx @@ -1,37 +1,12 @@ import React from 'react'; -import type {SearchColumnType} from '@components/Search/types'; import type {ListItem, TransactionCategoryGroupListItemType} from '@components/SelectionListWithSections/types'; import useLocalize from '@hooks/useLocalize'; import CONST from '@src/CONST'; -import BaseListItemHeader from './BaseListItemHeader'; +import BaseListItemHeader, {type BaseListItemHeaderProps} from './BaseListItemHeader'; -type CategoryListItemHeaderProps = { +type CategoryListItemHeaderProps = Omit, 'item' | 'displayName' | 'groupColumnKey' | 'columnStyleKey'> & { /** The category currently being looked at */ category: TransactionCategoryGroupListItemType; - - /** Callback to fire when a checkbox is pressed */ - onCheckboxPress?: (item: TItem) => void; - - /** Whether this section items disabled for selection */ - isDisabled?: boolean | null; - - /** Whether selecting multiple transactions at once is allowed */ - canSelectMultiple: boolean | undefined; - - /** Whether all transactions are selected */ - isSelectAllChecked?: boolean; - - /** Whether only some transactions are selected */ - isIndeterminate?: boolean; - - /** Callback for when the down arrow is clicked */ - onDownArrowClick?: () => void; - - /** Whether the down arrow is expanded */ - isExpanded?: boolean; - - /** The visible columns for the header */ - columns?: SearchColumnType[]; }; function CategoryListItemHeader({ diff --git a/src/components/SelectionListWithSections/Search/MerchantListItemHeader.tsx b/src/components/SelectionListWithSections/Search/MerchantListItemHeader.tsx index 2a5db71bb1bbf..433148347f49d 100644 --- a/src/components/SelectionListWithSections/Search/MerchantListItemHeader.tsx +++ b/src/components/SelectionListWithSections/Search/MerchantListItemHeader.tsx @@ -1,37 +1,12 @@ import React from 'react'; -import type {SearchColumnType} from '@components/Search/types'; import type {ListItem, TransactionMerchantGroupListItemType} from '@components/SelectionListWithSections/types'; import useLocalize from '@hooks/useLocalize'; import CONST from '@src/CONST'; -import BaseListItemHeader from './BaseListItemHeader'; +import BaseListItemHeader, {type BaseListItemHeaderProps} from './BaseListItemHeader'; -type MerchantListItemHeaderProps = { +type MerchantListItemHeaderProps = Omit, 'item' | 'displayName' | 'groupColumnKey' | 'columnStyleKey'> & { /** The merchant currently being looked at */ merchant: TransactionMerchantGroupListItemType; - - /** Callback to fire when a checkbox is pressed */ - onCheckboxPress?: (item: TItem) => void; - - /** Whether this section items disabled for selection */ - isDisabled?: boolean | null; - - /** Whether selecting multiple transactions at once is allowed */ - canSelectMultiple: boolean | undefined; - - /** Whether all transactions are selected */ - isSelectAllChecked?: boolean; - - /** Whether only some transactions are selected */ - isIndeterminate?: boolean; - - /** Callback for when the down arrow is clicked */ - onDownArrowClick?: () => void; - - /** Whether the down arrow is expanded */ - isExpanded?: boolean; - - /** The visible columns for the header */ - columns?: SearchColumnType[]; }; function MerchantListItemHeader({ diff --git a/src/components/SelectionListWithSections/Search/MonthListItemHeader.tsx b/src/components/SelectionListWithSections/Search/MonthListItemHeader.tsx index 8b0a2aa9f1170..067d92108d6e5 100644 --- a/src/components/SelectionListWithSections/Search/MonthListItemHeader.tsx +++ b/src/components/SelectionListWithSections/Search/MonthListItemHeader.tsx @@ -1,45 +1,11 @@ import React from 'react'; -import {View} from 'react-native'; -import Checkbox from '@components/Checkbox'; -import type {SearchColumnType} from '@components/Search/types'; import type {ListItem, TransactionMonthGroupListItemType} from '@components/SelectionListWithSections/types'; -import TextWithTooltip from '@components/TextWithTooltip'; -import useLocalize from '@hooks/useLocalize'; -import useResponsiveLayout from '@hooks/useResponsiveLayout'; -import useStyleUtils from '@hooks/useStyleUtils'; -import useThemeStyles from '@hooks/useThemeStyles'; import CONST from '@src/CONST'; -import ExpandCollapseArrowButton from './ExpandCollapseArrowButton'; -import TextCell from './TextCell'; -import TotalCell from './TotalCell'; +import BaseListItemHeader, {type BaseListItemHeaderProps} from './BaseListItemHeader'; -type MonthListItemHeaderProps = { +type MonthListItemHeaderProps = Omit, 'item' | 'displayName' | 'groupColumnKey' | 'columnStyleKey'> & { /** The month group currently being looked at */ month: TransactionMonthGroupListItemType; - - /** Callback to fire when a checkbox is pressed */ - onCheckboxPress?: (item: TItem) => void; - - /** Whether this section items disabled for selection */ - isDisabled?: boolean | null; - - /** Whether selecting multiple transactions at once is allowed */ - canSelectMultiple: boolean | undefined; - - /** Whether all transactions are selected */ - isSelectAllChecked?: boolean; - - /** Whether only some transactions are selected */ - isIndeterminate?: boolean; - - /** Callback for when the down arrow is clicked */ - onDownArrowClick?: () => void; - - /** Whether the down arrow is expanded */ - isExpanded?: boolean; - - /** The visible columns for the header */ - columns?: SearchColumnType[]; }; function MonthListItemHeader({ @@ -53,89 +19,23 @@ function MonthListItemHeader({ onDownArrowClick, columns, }: MonthListItemHeaderProps) { - const styles = useThemeStyles(); - const StyleUtils = useStyleUtils(); - const {isLargeScreenWidth} = useResponsiveLayout(); - const {translate} = useLocalize(); const monthName = monthItem.formattedMonth; - const columnComponents = { - [CONST.SEARCH.TABLE_COLUMNS.GROUP_MONTH]: ( - - - - - - ), - [CONST.SEARCH.TABLE_COLUMNS.GROUP_EXPENSES]: ( - - - - ), - [CONST.SEARCH.TABLE_COLUMNS.GROUP_TOTAL]: ( - - - - ), - }; - return ( - - - - {!!canSelectMultiple && ( - onCheckboxPress?.(monthItem as unknown as TItem)} - isChecked={isSelectAllChecked} - isIndeterminate={isIndeterminate} - disabled={!!isDisabled || monthItem.isDisabledCheckbox} - accessibilityLabel={translate('common.select')} - style={isLargeScreenWidth && styles.mr1} - /> - )} - {!isLargeScreenWidth && ( - - - - - - )} - {isLargeScreenWidth && columns?.map((column) => columnComponents[column as keyof typeof columnComponents])} - - {!isLargeScreenWidth && ( - - - {!!onDownArrowClick && ( - - )} - - )} - - + ); } diff --git a/src/components/SelectionListWithSections/Search/TagListItemHeader.tsx b/src/components/SelectionListWithSections/Search/TagListItemHeader.tsx index cdd6bf743c2af..eca72ad4628a9 100644 --- a/src/components/SelectionListWithSections/Search/TagListItemHeader.tsx +++ b/src/components/SelectionListWithSections/Search/TagListItemHeader.tsx @@ -1,45 +1,11 @@ import React from 'react'; -import {View} from 'react-native'; -import Checkbox from '@components/Checkbox'; -import type {SearchColumnType} from '@components/Search/types'; import type {ListItem, TransactionTagGroupListItemType} from '@components/SelectionListWithSections/types'; -import TextWithTooltip from '@components/TextWithTooltip'; -import useLocalize from '@hooks/useLocalize'; -import useResponsiveLayout from '@hooks/useResponsiveLayout'; -import useStyleUtils from '@hooks/useStyleUtils'; -import useThemeStyles from '@hooks/useThemeStyles'; import CONST from '@src/CONST'; -import ExpandCollapseArrowButton from './ExpandCollapseArrowButton'; -import TextCell from './TextCell'; -import TotalCell from './TotalCell'; +import BaseListItemHeader, {type BaseListItemHeaderProps} from './BaseListItemHeader'; -type TagListItemHeaderProps = { +type TagListItemHeaderProps = Omit, 'item' | 'displayName' | 'groupColumnKey' | 'columnStyleKey'> & { /** The tag currently being looked at */ tag: TransactionTagGroupListItemType; - - /** Callback to fire when a checkbox is pressed */ - onCheckboxPress?: (item: TItem) => void; - - /** Whether this section items disabled for selection */ - isDisabled?: boolean | null; - - /** Whether selecting multiple transactions at once is allowed */ - canSelectMultiple: boolean | undefined; - - /** Whether all transactions are selected */ - isSelectAllChecked?: boolean; - - /** Whether only some transactions are selected */ - isIndeterminate?: boolean; - - /** Callback for when the down arrow is clicked */ - onDownArrowClick?: () => void; - - /** Whether the down arrow is expanded */ - isExpanded?: boolean; - - /** The visible columns for the header */ - columns?: SearchColumnType[]; }; function TagListItemHeader({ @@ -53,91 +19,24 @@ function TagListItemHeader({ onDownArrowClick, columns, }: TagListItemHeaderProps) { - const styles = useThemeStyles(); - const StyleUtils = useStyleUtils(); - const {isLargeScreenWidth} = useResponsiveLayout(); - const {translate} = useLocalize(); - // formattedTag is already translated to "No tag" for empty values in SearchUIUtils const tagName = tagItem.formattedTag ?? tagItem.tag ?? ''; - const columnComponents = { - [CONST.SEARCH.TABLE_COLUMNS.GROUP_TAG]: ( - - - - - - ), - [CONST.SEARCH.TABLE_COLUMNS.GROUP_EXPENSES]: ( - - - - ), - [CONST.SEARCH.TABLE_COLUMNS.GROUP_TOTAL]: ( - - - - ), - }; - return ( - - - - {!!canSelectMultiple && ( - onCheckboxPress?.(tagItem as unknown as TItem)} - isChecked={isSelectAllChecked} - isIndeterminate={isIndeterminate} - disabled={!!isDisabled || tagItem.isDisabledCheckbox} - accessibilityLabel={translate('common.select')} - style={isLargeScreenWidth && styles.mr1} - /> - )} - {!isLargeScreenWidth && ( - - - - - - )} - {isLargeScreenWidth && columns?.map((column) => columnComponents[column as keyof typeof columnComponents])} - - {!isLargeScreenWidth && ( - - - {!!onDownArrowClick && ( - - )} - - )} - - + ); } From bc745e570303e83338727a836d5a8a84e0506850 Mon Sep 17 00:00:00 2001 From: TaduJR Date: Wed, 28 Jan 2026 03:37:12 +0300 Subject: [PATCH 07/24] chore: run prettier --- src/types/onyx/SearchResults.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/types/onyx/SearchResults.ts b/src/types/onyx/SearchResults.ts index f09bb3fa35d7d..1a7da00fcb4bc 100644 --- a/src/types/onyx/SearchResults.ts +++ b/src/types/onyx/SearchResults.ts @@ -249,7 +249,10 @@ type SearchResults = { PrefixedRecord & PrefixedRecord & PrefixedRecord & - PrefixedRecord; + PrefixedRecord< + typeof CONST.SEARCH.GROUP_PREFIX, + SearchMemberGroup | SearchCardGroup | SearchWithdrawalIDGroup | SearchCategoryGroup | SearchMerchantGroup | SearchTagGroup | SearchMonthGroup + >; /** Whether search data is being fetched from server */ isLoading?: boolean; From 9eec09cb304150e301b642b5fe000b4f7da966da Mon Sep 17 00:00:00 2001 From: TaduJR Date: Wed, 28 Jan 2026 04:00:24 +0300 Subject: [PATCH 08/24] refactor: Sort 'No merchant' alphabetically like 'No tag' --- .../Search/MerchantListItemHeader.tsx | 6 +-- src/libs/SearchUIUtils.ts | 24 ++++----- tests/ui/MerchantListItemHeaderTest.tsx | 9 ++-- tests/unit/Search/SearchUIUtilsTest.ts | 52 +++++++++++++++++++ 4 files changed, 69 insertions(+), 22 deletions(-) diff --git a/src/components/SelectionListWithSections/Search/MerchantListItemHeader.tsx b/src/components/SelectionListWithSections/Search/MerchantListItemHeader.tsx index 433148347f49d..e42749c02fb8f 100644 --- a/src/components/SelectionListWithSections/Search/MerchantListItemHeader.tsx +++ b/src/components/SelectionListWithSections/Search/MerchantListItemHeader.tsx @@ -1,6 +1,5 @@ import React from 'react'; import type {ListItem, TransactionMerchantGroupListItemType} from '@components/SelectionListWithSections/types'; -import useLocalize from '@hooks/useLocalize'; import CONST from '@src/CONST'; import BaseListItemHeader, {type BaseListItemHeaderProps} from './BaseListItemHeader'; @@ -20,9 +19,8 @@ function MerchantListItemHeader({ onDownArrowClick, columns, }: MerchantListItemHeaderProps) { - const {translate} = useLocalize(); - const rawMerchant = merchantItem.formattedMerchant ?? merchantItem.merchant; - const merchantName = rawMerchant || translate('search.noMerchant'); + // formattedMerchant is already translated to "No merchant" for empty values in SearchUIUtils + const merchantName = merchantItem.formattedMerchant ?? merchantItem.merchant ?? ''; return ( = {}; for (const key in data) { @@ -2274,12 +2274,17 @@ function getMerchantSections(data: OnyxTypes.SearchResults['data'], queryJSON: S transactionsQueryJSON = buildSearchQueryJSON(newQuery); } + // Format the merchant name - use translated "No merchant" for empty values so it sorts alphabetically + const rawMerchant = merchantGroup.merchant; + const isEmptyMerchant = !rawMerchant || rawMerchant === CONST.SEARCH.MERCHANT_EMPTY_VALUE; + const formattedMerchant = isEmptyMerchant ? translate('search.noMerchant') : rawMerchant; + merchantSections[key] = { groupedBy: CONST.SEARCH.GROUP_BY.MERCHANT, transactions: [], transactionsQueryJSON, ...merchantGroup, - formattedMerchant: merchantGroup.merchant, + formattedMerchant, }; } } @@ -2462,7 +2467,7 @@ function getSections({ case CONST.SEARCH.GROUP_BY.CATEGORY: return getCategorySections(data, queryJSON); case CONST.SEARCH.GROUP_BY.MERCHANT: - return getMerchantSections(data, queryJSON); + return getMerchantSections(data, queryJSON, translate); case CONST.SEARCH.GROUP_BY.TAG: return getTagSections(data, queryJSON, translate); case CONST.SEARCH.GROUP_BY.MONTH: @@ -2894,18 +2899,7 @@ function getSortedMerchantData(data: TransactionMerchantGroupListItemType[], loc data, localeCompare, transactionMerchantGroupColumnNamesToSortingProperty, - (a, b) => { - const merchantA = a.formattedMerchant ?? ''; - const merchantB = b.formattedMerchant ?? ''; - // Empty merchants should sort to the bottom - if (!merchantA && merchantB) { - return 1; - } - if (merchantA && !merchantB) { - return -1; - } - return localeCompare(merchantA, merchantB); - }, + (a, b) => localeCompare(a.formattedMerchant ?? '', b.formattedMerchant ?? ''), sortBy, sortOrder, ); diff --git a/tests/ui/MerchantListItemHeaderTest.tsx b/tests/ui/MerchantListItemHeaderTest.tsx index 7c706ec288b4f..a026788513d2a 100644 --- a/tests/ui/MerchantListItemHeaderTest.tsx +++ b/tests/ui/MerchantListItemHeaderTest.tsx @@ -147,7 +147,8 @@ describe('MerchantListItemHeader', () => { }); it('should display "No merchant" for empty merchant string', async () => { - const merchantItem = createMerchantListItem('', {formattedMerchant: ''}); + // formattedMerchant is set to "No merchant" by getMerchantSections for empty merchants + const merchantItem = createMerchantListItem('', {formattedMerchant: 'No merchant'}); renderMerchantListItemHeader(merchantItem); await waitForBatchedUpdatesWithAct(); @@ -155,7 +156,8 @@ describe('MerchantListItemHeader', () => { }); it('should display "No merchant" when merchant is undefined', async () => { - const merchantItem = createMerchantListItem('', {formattedMerchant: undefined}); + // formattedMerchant is set to "No merchant" by getMerchantSections for empty merchants + const merchantItem = createMerchantListItem('', {formattedMerchant: 'No merchant'}); renderMerchantListItemHeader(merchantItem); await waitForBatchedUpdatesWithAct(); @@ -163,7 +165,8 @@ describe('MerchantListItemHeader', () => { }); it('should display "No merchant" when both merchant and formattedMerchant are empty', async () => { - const merchantItem = createMerchantListItem('', {merchant: '', formattedMerchant: ''}); + // formattedMerchant is set to "No merchant" by getMerchantSections for empty merchants + const merchantItem = createMerchantListItem('', {merchant: '', formattedMerchant: 'No merchant'}); renderMerchantListItemHeader(merchantItem); await waitForBatchedUpdatesWithAct(); diff --git a/tests/unit/Search/SearchUIUtilsTest.ts b/tests/unit/Search/SearchUIUtilsTest.ts index 0c6ec66a626cc..a682e349f8775 100644 --- a/tests/unit/Search/SearchUIUtilsTest.ts +++ b/tests/unit/Search/SearchUIUtilsTest.ts @@ -3532,6 +3532,58 @@ describe('SearchUIUtils', () => { expect(result.at(1)?.count).toBe(4); }); + it('should sort "No merchant" alphabetically like other merchant names', () => { + // "No merchant" should sort alphabetically, not at the bottom + const merchantDataWithEmpty: TransactionMerchantGroupListItemType[] = [ + { + merchant: '', + count: 2, + currency: 'USD', + total: 50, + groupedBy: CONST.SEARCH.GROUP_BY.MERCHANT, + formattedMerchant: 'No merchant', // Translated by getMerchantSections + transactions: [], + transactionsQueryJSON: undefined, + }, + { + merchant: 'Apple Store', + count: 3, + currency: 'USD', + total: 100, + groupedBy: CONST.SEARCH.GROUP_BY.MERCHANT, + formattedMerchant: 'Apple Store', + transactions: [], + transactionsQueryJSON: undefined, + }, + { + merchant: 'Zebra Coffee', + count: 1, + currency: 'USD', + total: 25, + groupedBy: CONST.SEARCH.GROUP_BY.MERCHANT, + formattedMerchant: 'Zebra Coffee', + transactions: [], + transactionsQueryJSON: undefined, + }, + ]; + + const result = SearchUIUtils.getSortedSections( + CONST.SEARCH.DATA_TYPES.EXPENSE, + '', + merchantDataWithEmpty, + localeCompare, + translateLocal, + CONST.SEARCH.TABLE_COLUMNS.GROUP_MERCHANT, + CONST.SEARCH.SORT_ORDER.ASC, + CONST.SEARCH.GROUP_BY.MERCHANT, + ) as TransactionMerchantGroupListItemType[]; + + // Should sort alphabetically: "Apple Store", "No merchant", "Zebra Coffee" + expect(result.at(0)?.formattedMerchant).toBe('Apple Store'); + expect(result.at(1)?.formattedMerchant).toBe('No merchant'); + expect(result.at(2)?.formattedMerchant).toBe('Zebra Coffee'); + }); + // Tag sorting tests it('should return getSortedTagData result when type is EXPENSE and groupBy is tag', () => { expect( From b11181e596904476a162ce0dcb3aaf7e0301f6fd Mon Sep 17 00:00:00 2001 From: TaduJR Date: Wed, 28 Jan 2026 04:13:42 +0300 Subject: [PATCH 09/24] fix: Use top-level type imports instead of inline type specifiers --- .../Search/CategoryListItemHeader.tsx | 3 ++- .../Search/MerchantListItemHeader.tsx | 3 ++- .../SelectionListWithSections/Search/MonthListItemHeader.tsx | 3 ++- .../SelectionListWithSections/Search/TagListItemHeader.tsx | 3 ++- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/components/SelectionListWithSections/Search/CategoryListItemHeader.tsx b/src/components/SelectionListWithSections/Search/CategoryListItemHeader.tsx index c0f26f9f34652..b0903fb26d85c 100644 --- a/src/components/SelectionListWithSections/Search/CategoryListItemHeader.tsx +++ b/src/components/SelectionListWithSections/Search/CategoryListItemHeader.tsx @@ -2,7 +2,8 @@ import React from 'react'; import type {ListItem, TransactionCategoryGroupListItemType} from '@components/SelectionListWithSections/types'; import useLocalize from '@hooks/useLocalize'; import CONST from '@src/CONST'; -import BaseListItemHeader, {type BaseListItemHeaderProps} from './BaseListItemHeader'; +import type {BaseListItemHeaderProps} from './BaseListItemHeader'; +import BaseListItemHeader from './BaseListItemHeader'; type CategoryListItemHeaderProps = Omit, 'item' | 'displayName' | 'groupColumnKey' | 'columnStyleKey'> & { /** The category currently being looked at */ diff --git a/src/components/SelectionListWithSections/Search/MerchantListItemHeader.tsx b/src/components/SelectionListWithSections/Search/MerchantListItemHeader.tsx index e42749c02fb8f..dcb239f7d7195 100644 --- a/src/components/SelectionListWithSections/Search/MerchantListItemHeader.tsx +++ b/src/components/SelectionListWithSections/Search/MerchantListItemHeader.tsx @@ -1,7 +1,8 @@ import React from 'react'; import type {ListItem, TransactionMerchantGroupListItemType} from '@components/SelectionListWithSections/types'; import CONST from '@src/CONST'; -import BaseListItemHeader, {type BaseListItemHeaderProps} from './BaseListItemHeader'; +import type {BaseListItemHeaderProps} from './BaseListItemHeader'; +import BaseListItemHeader from './BaseListItemHeader'; type MerchantListItemHeaderProps = Omit, 'item' | 'displayName' | 'groupColumnKey' | 'columnStyleKey'> & { /** The merchant currently being looked at */ diff --git a/src/components/SelectionListWithSections/Search/MonthListItemHeader.tsx b/src/components/SelectionListWithSections/Search/MonthListItemHeader.tsx index 067d92108d6e5..aab0f9f65f8a3 100644 --- a/src/components/SelectionListWithSections/Search/MonthListItemHeader.tsx +++ b/src/components/SelectionListWithSections/Search/MonthListItemHeader.tsx @@ -1,7 +1,8 @@ import React from 'react'; import type {ListItem, TransactionMonthGroupListItemType} from '@components/SelectionListWithSections/types'; import CONST from '@src/CONST'; -import BaseListItemHeader, {type BaseListItemHeaderProps} from './BaseListItemHeader'; +import type {BaseListItemHeaderProps} from './BaseListItemHeader'; +import BaseListItemHeader from './BaseListItemHeader'; type MonthListItemHeaderProps = Omit, 'item' | 'displayName' | 'groupColumnKey' | 'columnStyleKey'> & { /** The month group currently being looked at */ diff --git a/src/components/SelectionListWithSections/Search/TagListItemHeader.tsx b/src/components/SelectionListWithSections/Search/TagListItemHeader.tsx index eca72ad4628a9..64840b9cf6174 100644 --- a/src/components/SelectionListWithSections/Search/TagListItemHeader.tsx +++ b/src/components/SelectionListWithSections/Search/TagListItemHeader.tsx @@ -1,7 +1,8 @@ import React from 'react'; import type {ListItem, TransactionTagGroupListItemType} from '@components/SelectionListWithSections/types'; import CONST from '@src/CONST'; -import BaseListItemHeader, {type BaseListItemHeaderProps} from './BaseListItemHeader'; +import type {BaseListItemHeaderProps} from './BaseListItemHeader'; +import BaseListItemHeader from './BaseListItemHeader'; type TagListItemHeaderProps = Omit, 'item' | 'displayName' | 'groupColumnKey' | 'columnStyleKey'> & { /** The tag currently being looked at */ From d6b0e835d9d352f3267c818594485d6d16c4b6c9 Mon Sep 17 00:00:00 2001 From: TaduJR Date: Wed, 28 Jan 2026 04:15:41 +0300 Subject: [PATCH 10/24] chore: Temporarily disable max-lines rule for SearchUIUtils.ts --- src/libs/SearchUIUtils.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/libs/SearchUIUtils.ts b/src/libs/SearchUIUtils.ts index 145f1448fc447..637b945d80078 100644 --- a/src/libs/SearchUIUtils.ts +++ b/src/libs/SearchUIUtils.ts @@ -1,3 +1,5 @@ +/* eslint-disable max-lines */ +// TODO: Remove this disable once SearchUIUtils is refactored (see dedicated refactor issue) import {format} from 'date-fns'; import type {TextStyle, ViewStyle} from 'react-native'; import type {OnyxCollection, OnyxEntry} from 'react-native-onyx'; From e800c9283db979d8f9468835b39d64c22ca3d929 Mon Sep 17 00:00:00 2001 From: TaduJR Date: Wed, 28 Jan 2026 05:07:06 +0300 Subject: [PATCH 11/24] fix: treat DEFAULT_MERCHANT 'Expense' as empty merchant in Top Merchants --- src/libs/SearchUIUtils.ts | 3 +- tests/unit/Search/SearchUIUtilsTest.ts | 46 ++++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 1 deletion(-) diff --git a/src/libs/SearchUIUtils.ts b/src/libs/SearchUIUtils.ts index 637b945d80078..ad979abe1a000 100644 --- a/src/libs/SearchUIUtils.ts +++ b/src/libs/SearchUIUtils.ts @@ -2277,8 +2277,9 @@ function getMerchantSections(data: OnyxTypes.SearchResults['data'], queryJSON: S } // Format the merchant name - use translated "No merchant" for empty values so it sorts alphabetically + // Also treat TRANSACTION.DEFAULT_MERCHANT ('Expense') as empty since it's a system default const rawMerchant = merchantGroup.merchant; - const isEmptyMerchant = !rawMerchant || rawMerchant === CONST.SEARCH.MERCHANT_EMPTY_VALUE; + const isEmptyMerchant = !rawMerchant || rawMerchant === CONST.SEARCH.MERCHANT_EMPTY_VALUE || rawMerchant === CONST.TRANSACTION.DEFAULT_MERCHANT; const formattedMerchant = isEmptyMerchant ? translate('search.noMerchant') : rawMerchant; merchantSections[key] = { diff --git a/tests/unit/Search/SearchUIUtilsTest.ts b/tests/unit/Search/SearchUIUtilsTest.ts index a682e349f8775..17faa36c33814 100644 --- a/tests/unit/Search/SearchUIUtilsTest.ts +++ b/tests/unit/Search/SearchUIUtilsTest.ts @@ -2962,6 +2962,52 @@ describe('SearchUIUtils', () => { expect(emptyMerchantItem?.transactionsQueryJSON?.inputQuery).toContain(CONST.SEARCH.MERCHANT_EMPTY_VALUE); }); + it('should treat DEFAULT_MERCHANT "Expense" as empty merchant and display "No merchant"', () => { + const dataWithDefaultMerchant: OnyxTypes.SearchResults['data'] = { + personalDetailsList: {}, + [`${CONST.SEARCH.GROUP_PREFIX}default` as const]: { + merchant: CONST.TRANSACTION.DEFAULT_MERCHANT, // 'Expense' + count: 1, + currency: 'USD', + total: 25, + }, + }; + + const [result] = SearchUIUtils.getSections({ + type: CONST.SEARCH.DATA_TYPES.EXPENSE, + data: dataWithDefaultMerchant, + currentAccountID: 2074551, + currentUserEmail: '', + translate: translateLocal, + formatPhoneNumber, + bankAccountList: {}, + groupBy: CONST.SEARCH.GROUP_BY.MERCHANT, + queryJSON: { + type: CONST.SEARCH.DATA_TYPES.EXPENSE, + status: '', + sortBy: CONST.SEARCH.TABLE_COLUMNS.DATE, + sortOrder: CONST.SEARCH.SORT_ORDER.DESC, + view: CONST.SEARCH.VIEW.TABLE, + hash: 12345, + flatFilters: [], + inputQuery: 'type:expense groupBy:merchant', + recentSearchHash: 12345, + similarSearchHash: 12345, + filters: { + operator: CONST.SEARCH.SYNTAX_OPERATORS.AND, + left: CONST.SEARCH.SYNTAX_FILTER_KEYS.TYPE, + right: CONST.SEARCH.DATA_TYPES.EXPENSE, + }, + }, + }) as [TransactionMerchantGroupListItemType[], number]; + + expect(result).toHaveLength(1); + // The merchant field keeps the original value for query purposes + expect(result.at(0)?.merchant).toBe(CONST.TRANSACTION.DEFAULT_MERCHANT); + // But formattedMerchant should be "No merchant" for display + expect(result.at(0)?.formattedMerchant).toBe('No merchant'); + }); + it('should return isTransactionMerchantGroupListItemType true for merchant group items', () => { const merchantItem: TransactionMerchantGroupListItemType = { merchant: 'Starbucks', From 3ecc56e4e50ac0ab243e6a717cf864412d373ad8 Mon Sep 17 00:00:00 2001 From: TaduJR Date: Wed, 28 Jan 2026 05:23:47 +0300 Subject: [PATCH 12/24] feat: add Basket icon for Top Merchants suggested search --- assets/images/basket.svg | 5 +++++ src/components/Icon/Expensicons.ts | 4 +++- src/libs/SearchUIUtils.ts | 6 +++--- 3 files changed, 11 insertions(+), 4 deletions(-) create mode 100644 assets/images/basket.svg diff --git a/assets/images/basket.svg b/assets/images/basket.svg new file mode 100644 index 0000000000000..2d3d9f64fc277 --- /dev/null +++ b/assets/images/basket.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/src/components/Icon/Expensicons.ts b/src/components/Icon/Expensicons.ts index f41804d1e3acf..e302fbb3d07b9 100644 --- a/src/components/Icon/Expensicons.ts +++ b/src/components/Icon/Expensicons.ts @@ -3,6 +3,7 @@ import Apple from '@assets/images/apple.svg'; import AttachmentNotFound from '@assets/images/attachment-not-found.svg'; import FallbackAvatar from '@assets/images/avatars/fallback-avatar.svg'; import Bank from '@assets/images/bank.svg'; +import Basket from '@assets/images/basket.svg'; import Bell from '@assets/images/bell.svg'; import Bill from '@assets/images/bill.svg'; import boltSlash from '@assets/images/bolt-slash.svg'; @@ -166,8 +167,9 @@ export { Apple, AttachmentNotFound, Bank, - Bill, + Basket, Bell, + Bill, Bolt, Bug, Building, diff --git a/src/libs/SearchUIUtils.ts b/src/libs/SearchUIUtils.ts index ad979abe1a000..e282e9b58b3c2 100644 --- a/src/libs/SearchUIUtils.ts +++ b/src/libs/SearchUIUtils.ts @@ -377,7 +377,7 @@ type SearchTypeMenuItem = { key: SearchKey; translationPath: TranslationPaths; type: SearchDataTypes; - icon?: IconAsset | Extract; + icon?: IconAsset | Extract; searchQuery: string; searchQueryJSON: SearchQueryJSON | undefined; hash: number; @@ -427,7 +427,7 @@ type GetSectionsParams = { function createTopSearchMenuItem( key: SearchKey, translationPath: TranslationPaths, - icon: IconAsset | Extract, + icon: IconAsset | Extract, groupBy: ValueOf, limit?: number, ): SearchTypeMenuItem { @@ -707,7 +707,7 @@ function getSuggestedSearches( [CONST.SEARCH.SEARCH_KEYS.TOP_MERCHANTS]: createTopSearchMenuItem( CONST.SEARCH.SEARCH_KEYS.TOP_MERCHANTS, 'search.topMerchants', - 'Building', + 'Basket', CONST.SEARCH.GROUP_BY.MERCHANT, CONST.SEARCH.TOP_SEARCH_LIMIT, ), From 1ffd4cd91bc6ac3360c426caf41527fa1e619637 Mon Sep 17 00:00:00 2001 From: TaduJR Date: Wed, 28 Jan 2026 05:43:34 +0300 Subject: [PATCH 13/24] feat: add basket icon for Top Merchants suggested search --- assets/images/basket.svg | 6 +----- src/components/Icon/chunks/expensify-icons.chunk.ts | 2 ++ src/hooks/useSearchTypeMenu.tsx | 1 + src/pages/Search/SearchTypeMenu.tsx | 1 + 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/assets/images/basket.svg b/assets/images/basket.svg index 2d3d9f64fc277..117f2d97b0b73 100644 --- a/assets/images/basket.svg +++ b/assets/images/basket.svg @@ -1,5 +1 @@ - - - - - + diff --git a/src/components/Icon/chunks/expensify-icons.chunk.ts b/src/components/Icon/chunks/expensify-icons.chunk.ts index e51dac50bbc55..c14487ce667b3 100644 --- a/src/components/Icon/chunks/expensify-icons.chunk.ts +++ b/src/components/Icon/chunks/expensify-icons.chunk.ts @@ -20,6 +20,7 @@ import NotificationsAvatar from '@assets/images/avatars/notifications-avatar.svg import ActiveRoomAvatar from '@assets/images/avatars/room.svg'; import BackArrow from '@assets/images/back-left.svg'; import Bank from '@assets/images/bank.svg'; +import Basket from '@assets/images/basket.svg'; import Bed from '@assets/images/bed.svg'; import Bell from '@assets/images/bell.svg'; import Bill from '@assets/images/bill.svg'; @@ -256,6 +257,7 @@ const Expensicons = { AttachmentNotFound, BackArrow, Bank, + Basket, CircularArrowBackwards, Bill, BillComSquare, diff --git a/src/hooks/useSearchTypeMenu.tsx b/src/hooks/useSearchTypeMenu.tsx index 498d0bd037292..5d7e8ea56abe1 100644 --- a/src/hooks/useSearchTypeMenu.tsx +++ b/src/hooks/useSearchTypeMenu.tsx @@ -49,6 +49,7 @@ export default function useSearchTypeMenu(queryJSON: SearchQueryJSON) { const [savedSearches] = useOnyx(ONYXKEYS.SAVED_SEARCHES, {canBeMissing: true}); const [currentUserAccountID = -1] = useOnyx(ONYXKEYS.SESSION, {selector: accountIDSelector, canBeMissing: false}); const expensifyIcons = useMemoizedLazyExpensifyIcons([ + 'Basket', 'Bookmark', 'Checkmark', 'Pencil', diff --git a/src/pages/Search/SearchTypeMenu.tsx b/src/pages/Search/SearchTypeMenu.tsx index 55dbaecdc9171..c4cb6e5616b6c 100644 --- a/src/pages/Search/SearchTypeMenu.tsx +++ b/src/pages/Search/SearchTypeMenu.tsx @@ -59,6 +59,7 @@ function SearchTypeMenu({queryJSON}: SearchTypeMenuProps) { !!typeMenuSections.find((section) => section.translationPath === 'search.savedSearchesMenuItemTitle') && isFocused, ); const expensifyIcons = useMemoizedLazyExpensifyIcons([ + 'Basket', 'Bookmark', 'Pencil', 'Receipt', From b97886407fd3d1ebbbf992020ffbae5a728010a7 Mon Sep 17 00:00:00 2001 From: TaduJR Date: Wed, 28 Jan 2026 05:47:22 +0300 Subject: [PATCH 14/24] chore: compress basket.svg --- assets/images/basket.svg | 2 +- src/libs/SearchUIUtils.ts | 8 ++++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/assets/images/basket.svg b/assets/images/basket.svg index 117f2d97b0b73..61eb391683a81 100644 --- a/assets/images/basket.svg +++ b/assets/images/basket.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/src/libs/SearchUIUtils.ts b/src/libs/SearchUIUtils.ts index e282e9b58b3c2..bb7637976ecce 100644 --- a/src/libs/SearchUIUtils.ts +++ b/src/libs/SearchUIUtils.ts @@ -377,7 +377,9 @@ type SearchTypeMenuItem = { key: SearchKey; translationPath: TranslationPaths; type: SearchDataTypes; - icon?: IconAsset | Extract; + icon?: + | IconAsset + | Extract; searchQuery: string; searchQueryJSON: SearchQueryJSON | undefined; hash: number; @@ -427,7 +429,9 @@ type GetSectionsParams = { function createTopSearchMenuItem( key: SearchKey, translationPath: TranslationPaths, - icon: IconAsset | Extract, + icon: + | IconAsset + | Extract, groupBy: ValueOf, limit?: number, ): SearchTypeMenuItem { From f6d4fb3f1f1691496363121ecb5e75b36de48ab9 Mon Sep 17 00:00:00 2001 From: TaduJR Date: Wed, 28 Jan 2026 05:51:33 +0300 Subject: [PATCH 15/24] fix: update merchant test data to use hash-based keys matching backend format --- tests/unit/Search/SearchUIUtilsTest.ts | 33 ++++++++++++++++---------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/tests/unit/Search/SearchUIUtilsTest.ts b/tests/unit/Search/SearchUIUtilsTest.ts index 17faa36c33814..af69b245bb208 100644 --- a/tests/unit/Search/SearchUIUtilsTest.ts +++ b/tests/unit/Search/SearchUIUtilsTest.ts @@ -1726,20 +1726,22 @@ const transactionCategoryGroupListItemsSorted: TransactionCategoryGroupListItemT }, ]; -// Merchant test data +// Merchant test data - backend uses hash-based keys (group_), not merchant names const merchantName1 = 'Starbucks'; const merchantName2 = 'Whole Foods'; +const merchantHash1 = '1234567890'; +const merchantHash2 = '9876543210'; const searchResultsGroupByMerchant: OnyxTypes.SearchResults = { data: { personalDetailsList: {}, - [`${CONST.SEARCH.GROUP_PREFIX}${merchantName1}` as const]: { + [`${CONST.SEARCH.GROUP_PREFIX}${merchantHash1}` as const]: { merchant: merchantName1, count: 7, currency: 'USD', total: 350, }, - [`${CONST.SEARCH.GROUP_PREFIX}${merchantName2}` as const]: { + [`${CONST.SEARCH.GROUP_PREFIX}${merchantHash2}` as const]: { merchant: merchantName2, count: 4, currency: 'USD', @@ -2884,15 +2886,16 @@ describe('SearchUIUtils', () => { }); it('should handle empty merchant values correctly', () => { + // Backend uses hash-based keys (group_), not merchant names const dataWithEmptyMerchant: OnyxTypes.SearchResults['data'] = { personalDetailsList: {}, - [`${CONST.SEARCH.GROUP_PREFIX}empty` as const]: { + [`${CONST.SEARCH.GROUP_PREFIX}111111111` as const]: { merchant: '', count: 2, currency: 'USD', total: 50, }, - [`${CONST.SEARCH.GROUP_PREFIX}valid` as const]: { + [`${CONST.SEARCH.GROUP_PREFIX}222222222` as const]: { merchant: 'Starbucks', count: 1, currency: 'USD', @@ -2917,9 +2920,10 @@ describe('SearchUIUtils', () => { }); it('should normalize empty merchant to MERCHANT_EMPTY_VALUE in transactionsQueryJSON', () => { + // Backend uses hash-based keys (group_), not merchant names const dataWithEmptyMerchant: OnyxTypes.SearchResults['data'] = { personalDetailsList: {}, - [`${CONST.SEARCH.GROUP_PREFIX}empty` as const]: { + [`${CONST.SEARCH.GROUP_PREFIX}333333333` as const]: { merchant: '', count: 2, currency: 'USD', @@ -2963,9 +2967,10 @@ describe('SearchUIUtils', () => { }); it('should treat DEFAULT_MERCHANT "Expense" as empty merchant and display "No merchant"', () => { + // Backend uses hash-based keys (group_), not merchant names const dataWithDefaultMerchant: OnyxTypes.SearchResults['data'] = { personalDetailsList: {}, - [`${CONST.SEARCH.GROUP_PREFIX}default` as const]: { + [`${CONST.SEARCH.GROUP_PREFIX}444444444` as const]: { merchant: CONST.TRANSACTION.DEFAULT_MERCHANT, // 'Expense' count: 1, currency: 'USD', @@ -3076,21 +3081,22 @@ describe('SearchUIUtils', () => { }); it('should handle Unicode characters in merchant names', () => { + // Backend uses hash-based keys (group_), not merchant names const dataWithUnicode: OnyxTypes.SearchResults['data'] = { personalDetailsList: {}, - [`${CONST.SEARCH.GROUP_PREFIX}japanese` as const]: { + [`${CONST.SEARCH.GROUP_PREFIX}555555555` as const]: { merchant: 'カフェ東京', count: 3, currency: 'JPY', total: 50000, }, - [`${CONST.SEARCH.GROUP_PREFIX}chinese` as const]: { + [`${CONST.SEARCH.GROUP_PREFIX}666666666` as const]: { merchant: '北京饭店', count: 2, currency: 'CNY', total: 1000, }, - [`${CONST.SEARCH.GROUP_PREFIX}emoji` as const]: { + [`${CONST.SEARCH.GROUP_PREFIX}777777777` as const]: { merchant: 'Coffee ☕', count: 1, currency: 'USD', @@ -3116,21 +3122,22 @@ describe('SearchUIUtils', () => { }); it('should handle special characters in merchant names', () => { + // Backend uses hash-based keys (group_), not merchant names const dataWithSpecialChars: OnyxTypes.SearchResults['data'] = { personalDetailsList: {}, - [`${CONST.SEARCH.GROUP_PREFIX}ampersand` as const]: { + [`${CONST.SEARCH.GROUP_PREFIX}888888888` as const]: { merchant: "McDonald's & Co.", count: 5, currency: 'USD', total: 2500, }, - [`${CONST.SEARCH.GROUP_PREFIX}parentheses` as const]: { + [`${CONST.SEARCH.GROUP_PREFIX}999999999` as const]: { merchant: 'Walmart (Express)', count: 2, currency: 'USD', total: 1000, }, - [`${CONST.SEARCH.GROUP_PREFIX}quotes` as const]: { + [`${CONST.SEARCH.GROUP_PREFIX}101010101` as const]: { merchant: '"Best" Coffee', count: 1, currency: 'USD', From d28b13c3a610bc79820ccb95651da88c417cb888 Mon Sep 17 00:00:00 2001 From: TaduJR Date: Wed, 28 Jan 2026 10:46:35 +0300 Subject: [PATCH 16/24] refactor: remove unused Building icon from search menu lazy icons --- src/hooks/useSearchTypeMenu.tsx | 1 - src/libs/SearchUIUtils.ts | 4 ++-- src/pages/Search/SearchTypeMenu.tsx | 1 - 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/hooks/useSearchTypeMenu.tsx b/src/hooks/useSearchTypeMenu.tsx index 5d7e8ea56abe1..9c3d582367e59 100644 --- a/src/hooks/useSearchTypeMenu.tsx +++ b/src/hooks/useSearchTypeMenu.tsx @@ -62,7 +62,6 @@ export default function useSearchTypeMenu(queryJSON: SearchQueryJSON) { 'Bank', 'User', 'Folder', - 'Building', ] as const); const [isPopoverVisible, setIsPopoverVisible] = useState(false); diff --git a/src/libs/SearchUIUtils.ts b/src/libs/SearchUIUtils.ts index bb7637976ecce..a1f9eeb723d91 100644 --- a/src/libs/SearchUIUtils.ts +++ b/src/libs/SearchUIUtils.ts @@ -379,7 +379,7 @@ type SearchTypeMenuItem = { type: SearchDataTypes; icon?: | IconAsset - | Extract; + | Extract; searchQuery: string; searchQueryJSON: SearchQueryJSON | undefined; hash: number; @@ -431,7 +431,7 @@ function createTopSearchMenuItem( translationPath: TranslationPaths, icon: | IconAsset - | Extract, + | Extract, groupBy: ValueOf, limit?: number, ): SearchTypeMenuItem { diff --git a/src/pages/Search/SearchTypeMenu.tsx b/src/pages/Search/SearchTypeMenu.tsx index c4cb6e5616b6c..102a347013216 100644 --- a/src/pages/Search/SearchTypeMenu.tsx +++ b/src/pages/Search/SearchTypeMenu.tsx @@ -71,7 +71,6 @@ function SearchTypeMenu({queryJSON}: SearchTypeMenuProps) { 'Bank', 'User', 'Folder', - 'Building', ] as const); const {showDeleteModal} = useDeleteSavedSearch(); const [allPolicies] = useOnyx(ONYXKEYS.COLLECTION.POLICY, {canBeMissing: true}); From 37e2c1f65c8561cf55d70e67b500318d17e5b402 Mon Sep 17 00:00:00 2001 From: TaduJR Date: Wed, 28 Jan 2026 11:13:42 +0300 Subject: [PATCH 17/24] fix: handle all empty merchant values (none, Expense, (none), Unknown Merchant) --- src/libs/SearchUIUtils.ts | 41 ++++++++--- tests/unit/Search/SearchUIUtilsTest.ts | 94 ++++++++++++++++++++++++++ 2 files changed, 127 insertions(+), 8 deletions(-) diff --git a/src/libs/SearchUIUtils.ts b/src/libs/SearchUIUtils.ts index a1f9eeb723d91..9a05dcbd55672 100644 --- a/src/libs/SearchUIUtils.ts +++ b/src/libs/SearchUIUtils.ts @@ -377,9 +377,7 @@ type SearchTypeMenuItem = { key: SearchKey; translationPath: TranslationPaths; type: SearchDataTypes; - icon?: - | IconAsset - | Extract; + icon?: IconAsset | Extract; searchQuery: string; searchQueryJSON: SearchQueryJSON | undefined; hash: number; @@ -429,9 +427,7 @@ type GetSectionsParams = { function createTopSearchMenuItem( key: SearchKey, translationPath: TranslationPaths, - icon: - | IconAsset - | Extract, + icon: IconAsset | Extract, groupBy: ValueOf, limit?: number, ): SearchTypeMenuItem { @@ -2281,11 +2277,40 @@ function getMerchantSections(data: OnyxTypes.SearchResults['data'], queryJSON: S } // Format the merchant name - use translated "No merchant" for empty values so it sorts alphabetically - // Also treat TRANSACTION.DEFAULT_MERCHANT ('Expense') as empty since it's a system default + // Handle all known empty merchant values: + // - Empty string or falsy + // - MERCHANT_EMPTY_VALUE ('none') - used in search queries + // - DEFAULT_MERCHANT ('Expense') - system default for expenses without merchant + // - PARTIAL_TRANSACTION_MERCHANT ('(none)') - used for partial/incomplete transactions + // - UNKNOWN_MERCHANT ('Unknown Merchant') - used when merchant cannot be determined const rawMerchant = merchantGroup.merchant; - const isEmptyMerchant = !rawMerchant || rawMerchant === CONST.SEARCH.MERCHANT_EMPTY_VALUE || rawMerchant === CONST.TRANSACTION.DEFAULT_MERCHANT; + const isEmptyMerchant = + !rawMerchant || + rawMerchant === CONST.SEARCH.MERCHANT_EMPTY_VALUE || + rawMerchant === CONST.TRANSACTION.DEFAULT_MERCHANT || + rawMerchant === CONST.TRANSACTION.PARTIAL_TRANSACTION_MERCHANT || + rawMerchant === CONST.TRANSACTION.UNKNOWN_MERCHANT; const formattedMerchant = isEmptyMerchant ? translate('search.noMerchant') : rawMerchant; + // DEBUG: Log merchant processing to identify edge cases + // eslint-disable-next-line no-console + console.log( + '[getMerchantSections] DEBUG:', + JSON.stringify({ + key, + rawMerchant, + rawMerchantType: typeof rawMerchant, + rawMerchantLength: rawMerchant?.length, + rawMerchantCharCodes: rawMerchant ? Array.from(rawMerchant).map((c) => c.charCodeAt(0)) : [], + MERCHANT_EMPTY_VALUE: CONST.SEARCH.MERCHANT_EMPTY_VALUE, + DEFAULT_MERCHANT: CONST.TRANSACTION.DEFAULT_MERCHANT, + PARTIAL_TRANSACTION_MERCHANT: CONST.TRANSACTION.PARTIAL_TRANSACTION_MERCHANT, + UNKNOWN_MERCHANT: CONST.TRANSACTION.UNKNOWN_MERCHANT, + isEmptyMerchant, + formattedMerchant, + }), + ); + merchantSections[key] = { groupedBy: CONST.SEARCH.GROUP_BY.MERCHANT, transactions: [], diff --git a/tests/unit/Search/SearchUIUtilsTest.ts b/tests/unit/Search/SearchUIUtilsTest.ts index af69b245bb208..b75ef222f9750 100644 --- a/tests/unit/Search/SearchUIUtilsTest.ts +++ b/tests/unit/Search/SearchUIUtilsTest.ts @@ -3013,6 +3013,100 @@ describe('SearchUIUtils', () => { expect(result.at(0)?.formattedMerchant).toBe('No merchant'); }); + it('should treat PARTIAL_TRANSACTION_MERCHANT "(none)" as empty merchant and display "No merchant"', () => { + // Backend uses hash-based keys (group_), not merchant names + const dataWithPartialMerchant: OnyxTypes.SearchResults['data'] = { + personalDetailsList: {}, + [`${CONST.SEARCH.GROUP_PREFIX}555555550` as const]: { + merchant: CONST.TRANSACTION.PARTIAL_TRANSACTION_MERCHANT, // '(none)' + count: 1, + currency: 'USD', + total: 25, + }, + }; + + const [result] = SearchUIUtils.getSections({ + type: CONST.SEARCH.DATA_TYPES.EXPENSE, + data: dataWithPartialMerchant, + currentAccountID: 2074551, + currentUserEmail: '', + translate: translateLocal, + formatPhoneNumber, + bankAccountList: {}, + groupBy: CONST.SEARCH.GROUP_BY.MERCHANT, + queryJSON: { + type: CONST.SEARCH.DATA_TYPES.EXPENSE, + status: '', + sortBy: CONST.SEARCH.TABLE_COLUMNS.DATE, + sortOrder: CONST.SEARCH.SORT_ORDER.DESC, + view: CONST.SEARCH.VIEW.TABLE, + hash: 12345, + flatFilters: [], + inputQuery: 'type:expense groupBy:merchant', + recentSearchHash: 12345, + similarSearchHash: 12345, + filters: { + operator: CONST.SEARCH.SYNTAX_OPERATORS.AND, + left: CONST.SEARCH.SYNTAX_FILTER_KEYS.TYPE, + right: CONST.SEARCH.DATA_TYPES.EXPENSE, + }, + }, + }) as [TransactionMerchantGroupListItemType[], number]; + + expect(result).toHaveLength(1); + // The merchant field keeps the original value for query purposes + expect(result.at(0)?.merchant).toBe(CONST.TRANSACTION.PARTIAL_TRANSACTION_MERCHANT); + // But formattedMerchant should be "No merchant" for display + expect(result.at(0)?.formattedMerchant).toBe('No merchant'); + }); + + it('should treat UNKNOWN_MERCHANT "Unknown Merchant" as empty merchant and display "No merchant"', () => { + // Backend uses hash-based keys (group_), not merchant names + const dataWithUnknownMerchant: OnyxTypes.SearchResults['data'] = { + personalDetailsList: {}, + [`${CONST.SEARCH.GROUP_PREFIX}666666660` as const]: { + merchant: CONST.TRANSACTION.UNKNOWN_MERCHANT, // 'Unknown Merchant' + count: 1, + currency: 'USD', + total: 25, + }, + }; + + const [result] = SearchUIUtils.getSections({ + type: CONST.SEARCH.DATA_TYPES.EXPENSE, + data: dataWithUnknownMerchant, + currentAccountID: 2074551, + currentUserEmail: '', + translate: translateLocal, + formatPhoneNumber, + bankAccountList: {}, + groupBy: CONST.SEARCH.GROUP_BY.MERCHANT, + queryJSON: { + type: CONST.SEARCH.DATA_TYPES.EXPENSE, + status: '', + sortBy: CONST.SEARCH.TABLE_COLUMNS.DATE, + sortOrder: CONST.SEARCH.SORT_ORDER.DESC, + view: CONST.SEARCH.VIEW.TABLE, + hash: 12345, + flatFilters: [], + inputQuery: 'type:expense groupBy:merchant', + recentSearchHash: 12345, + similarSearchHash: 12345, + filters: { + operator: CONST.SEARCH.SYNTAX_OPERATORS.AND, + left: CONST.SEARCH.SYNTAX_FILTER_KEYS.TYPE, + right: CONST.SEARCH.DATA_TYPES.EXPENSE, + }, + }, + }) as [TransactionMerchantGroupListItemType[], number]; + + expect(result).toHaveLength(1); + // The merchant field keeps the original value for query purposes + expect(result.at(0)?.merchant).toBe(CONST.TRANSACTION.UNKNOWN_MERCHANT); + // But formattedMerchant should be "No merchant" for display + expect(result.at(0)?.formattedMerchant).toBe('No merchant'); + }); + it('should return isTransactionMerchantGroupListItemType true for merchant group items', () => { const merchantItem: TransactionMerchantGroupListItemType = { merchant: 'Starbucks', From 3ba084e2f678035ce2c2a509fc01aebed17960f5 Mon Sep 17 00:00:00 2001 From: TaduJR Date: Wed, 28 Jan 2026 13:36:30 +0300 Subject: [PATCH 18/24] chore: remove debug logging from getMerchantSections --- src/libs/SearchUIUtils.ts | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/src/libs/SearchUIUtils.ts b/src/libs/SearchUIUtils.ts index 9a05dcbd55672..d2cdf50f8753c 100644 --- a/src/libs/SearchUIUtils.ts +++ b/src/libs/SearchUIUtils.ts @@ -2292,25 +2292,6 @@ function getMerchantSections(data: OnyxTypes.SearchResults['data'], queryJSON: S rawMerchant === CONST.TRANSACTION.UNKNOWN_MERCHANT; const formattedMerchant = isEmptyMerchant ? translate('search.noMerchant') : rawMerchant; - // DEBUG: Log merchant processing to identify edge cases - // eslint-disable-next-line no-console - console.log( - '[getMerchantSections] DEBUG:', - JSON.stringify({ - key, - rawMerchant, - rawMerchantType: typeof rawMerchant, - rawMerchantLength: rawMerchant?.length, - rawMerchantCharCodes: rawMerchant ? Array.from(rawMerchant).map((c) => c.charCodeAt(0)) : [], - MERCHANT_EMPTY_VALUE: CONST.SEARCH.MERCHANT_EMPTY_VALUE, - DEFAULT_MERCHANT: CONST.TRANSACTION.DEFAULT_MERCHANT, - PARTIAL_TRANSACTION_MERCHANT: CONST.TRANSACTION.PARTIAL_TRANSACTION_MERCHANT, - UNKNOWN_MERCHANT: CONST.TRANSACTION.UNKNOWN_MERCHANT, - isEmptyMerchant, - formattedMerchant, - }), - ); - merchantSections[key] = { groupedBy: CONST.SEARCH.GROUP_BY.MERCHANT, transactions: [], From 5cd7fe38032cd9e5297deea41c7504e7190d1e81 Mon Sep 17 00:00:00 2001 From: TaduJR Date: Wed, 28 Jan 2026 13:38:14 +0300 Subject: [PATCH 19/24] refactor: use transactionGroupBaseSortingProperties spread in merchant and month groups --- src/libs/SearchUIUtils.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/libs/SearchUIUtils.ts b/src/libs/SearchUIUtils.ts index d2cdf50f8753c..2c29ae4c4e6e7 100644 --- a/src/libs/SearchUIUtils.ts +++ b/src/libs/SearchUIUtils.ts @@ -265,14 +265,12 @@ const transactionTagGroupColumnNamesToSortingProperty: TransactionTagGroupSortin const transactionMerchantGroupColumnNamesToSortingProperty: TransactionMerchantGroupSorting = { [CONST.SEARCH.TABLE_COLUMNS.GROUP_MERCHANT]: 'formattedMerchant' as const, [CONST.SEARCH.TABLE_COLUMNS.MERCHANT]: 'formattedMerchant' as const, - [CONST.SEARCH.TABLE_COLUMNS.GROUP_EXPENSES]: 'count' as const, - [CONST.SEARCH.TABLE_COLUMNS.GROUP_TOTAL]: 'total' as const, + ...transactionGroupBaseSortingProperties, }; const transactionMonthGroupColumnNamesToSortingProperty: TransactionMonthGroupSorting = { [CONST.SEARCH.TABLE_COLUMNS.GROUP_MONTH]: 'sortKey' as const, - [CONST.SEARCH.TABLE_COLUMNS.GROUP_EXPENSES]: 'count' as const, - [CONST.SEARCH.TABLE_COLUMNS.GROUP_TOTAL]: 'total' as const, + ...transactionGroupBaseSortingProperties, }; const expenseStatusActionMapping = { From c9ca3b730abcca1992c46a5e7dbd1c0c988d15c5 Mon Sep 17 00:00:00 2001 From: TaduJR Date: Wed, 28 Jan 2026 13:55:09 +0300 Subject: [PATCH 20/24] feat: add groupMerchant to search parser peggy rules --- src/libs/SearchParser/autocompleteParser.js | 305 +++++++++++--------- src/libs/SearchParser/baseRules.peggy | 2 + src/libs/SearchParser/searchParser.js | 305 +++++++++++--------- 3 files changed, 350 insertions(+), 262 deletions(-) diff --git a/src/libs/SearchParser/autocompleteParser.js b/src/libs/SearchParser/autocompleteParser.js index 95b3aea65ccd9..6155382cf255d 100644 --- a/src/libs/SearchParser/autocompleteParser.js +++ b/src/libs/SearchParser/autocompleteParser.js @@ -270,15 +270,16 @@ function peg$parse(input, options) { var peg$c84 = "group-withdrawn"; var peg$c85 = "group-withdrawal-id"; var peg$c86 = "group-category"; - var peg$c87 = "group-month"; - var peg$c88 = "!="; - var peg$c89 = ">="; - var peg$c90 = ">"; - var peg$c91 = "<="; - var peg$c92 = "<"; - var peg$c93 = "\u201C"; - var peg$c94 = "\u201D"; - var peg$c95 = "\""; + var peg$c87 = "group-merchant"; + var peg$c88 = "group-month"; + var peg$c89 = "!="; + var peg$c90 = ">="; + var peg$c91 = ">"; + var peg$c92 = "<="; + var peg$c93 = "<"; + var peg$c94 = "\u201C"; + var peg$c95 = "\u201D"; + var peg$c96 = "\""; var peg$r0 = /^[ \t\r\n\xA0,:=<>!]/; var peg$r1 = /^[:=]/; @@ -384,31 +385,32 @@ function peg$parse(input, options) { var peg$e87 = peg$literalExpectation("group-withdrawn", true); var peg$e88 = peg$literalExpectation("group-withdrawal-id", true); var peg$e89 = peg$literalExpectation("group-category", true); - var peg$e90 = peg$literalExpectation("group-month", true); - var peg$e91 = peg$otherExpectation("operator"); - var peg$e92 = peg$classExpectation([":", "="], false, false); - var peg$e93 = peg$literalExpectation("!=", false); - var peg$e94 = peg$literalExpectation(">=", false); - var peg$e95 = peg$literalExpectation(">", false); - var peg$e96 = peg$literalExpectation("<=", false); - var peg$e97 = peg$literalExpectation("<", false); - var peg$e98 = peg$otherExpectation("word"); - var peg$e99 = peg$classExpectation([" ", ",", "\t", "\n", "\r", "\xA0"], true, false); - var peg$e100 = peg$otherExpectation("whitespace"); - var peg$e101 = peg$classExpectation([" ", "\t", "\r", "\n", "\xA0"], false, false); - var peg$e102 = peg$otherExpectation("quote"); - var peg$e103 = peg$classExpectation([" ", ",", "\"", "\u201D", "\u201C", "\t", "\n", "\r", "\xA0"], true, false); - var peg$e104 = peg$classExpectation(["\"", ["\u201C", "\u201D"]], false, false); - var peg$e105 = peg$classExpectation(["\"", "\u201D", "\u201C", "\r", "\n"], true, false); - var peg$e106 = peg$literalExpectation("\u201C", false); - var peg$e107 = peg$literalExpectation("\u201D", false); - var peg$e108 = peg$literalExpectation("\"", false); - var peg$e109 = peg$classExpectation([" ", "\t", "\n", "\r", "\xA0", ["a", "z"], ["A", "Z"], ["0", "9"]], false, false); - var peg$e110 = peg$classExpectation([["a", "z"], ["A", "Z"], ["0", "9"]], false, false); - var peg$e111 = peg$classExpectation([" ", "\t", "\n", "\r", "\xA0"], false, false); - var peg$e112 = peg$classExpectation([" ", "\t", "\n", "\r", "\xA0", ["a", "z"], ["A", "Z"]], false, false); - var peg$e113 = peg$classExpectation([","], false, false); - var peg$e114 = peg$classExpectation([" ", "\t", "\n", "\r", "\xA0", ","], false, false); + var peg$e90 = peg$literalExpectation("group-merchant", true); + var peg$e91 = peg$literalExpectation("group-month", true); + var peg$e92 = peg$otherExpectation("operator"); + var peg$e93 = peg$classExpectation([":", "="], false, false); + var peg$e94 = peg$literalExpectation("!=", false); + var peg$e95 = peg$literalExpectation(">=", false); + var peg$e96 = peg$literalExpectation(">", false); + var peg$e97 = peg$literalExpectation("<=", false); + var peg$e98 = peg$literalExpectation("<", false); + var peg$e99 = peg$otherExpectation("word"); + var peg$e100 = peg$classExpectation([" ", ",", "\t", "\n", "\r", "\xA0"], true, false); + var peg$e101 = peg$otherExpectation("whitespace"); + var peg$e102 = peg$classExpectation([" ", "\t", "\r", "\n", "\xA0"], false, false); + var peg$e103 = peg$otherExpectation("quote"); + var peg$e104 = peg$classExpectation([" ", ",", "\"", "\u201D", "\u201C", "\t", "\n", "\r", "\xA0"], true, false); + var peg$e105 = peg$classExpectation(["\"", ["\u201C", "\u201D"]], false, false); + var peg$e106 = peg$classExpectation(["\"", "\u201D", "\u201C", "\r", "\n"], true, false); + var peg$e107 = peg$literalExpectation("\u201C", false); + var peg$e108 = peg$literalExpectation("\u201D", false); + var peg$e109 = peg$literalExpectation("\"", false); + var peg$e110 = peg$classExpectation([" ", "\t", "\n", "\r", "\xA0", ["a", "z"], ["A", "Z"], ["0", "9"]], false, false); + var peg$e111 = peg$classExpectation([["a", "z"], ["A", "Z"], ["0", "9"]], false, false); + var peg$e112 = peg$classExpectation([" ", "\t", "\n", "\r", "\xA0"], false, false); + var peg$e113 = peg$classExpectation([" ", "\t", "\n", "\r", "\xA0", ["a", "z"], ["A", "Z"]], false, false); + var peg$e114 = peg$classExpectation([","], false, false); + var peg$e115 = 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(); }; @@ -547,33 +549,34 @@ function peg$parse(input, options) { var peg$f76 = function() { return "groupWithdrawn"; }; var peg$f77 = function() { return "groupWithdrawalID"; }; var peg$f78 = function() { return "groupCategory"; }; - var peg$f79 = function() { return "groupMonth"; }; - var peg$f80 = function() { return "eq"; }; - var peg$f81 = function() { return "neq"; }; - var peg$f82 = function() { return "gte"; }; - var peg$f83 = function() { return "gt"; }; - var peg$f84 = function() { return "lte"; }; - var peg$f85 = function() { return "lt"; }; - var peg$f86 = function(o) { + var peg$f79 = function() { return "groupMerchant"; }; + var peg$f80 = function() { return "groupMonth"; }; + var peg$f81 = function() { return "eq"; }; + var peg$f82 = function() { return "neq"; }; + var peg$f83 = function() { return "gte"; }; + var peg$f84 = function() { return "gt"; }; + var peg$f85 = function() { return "lte"; }; + var peg$f86 = function() { return "lt"; }; + var peg$f87 = function(o) { if (nameOperator) { expectingNestedQuote = (o === "eq"); // Use simple parser if no valid operator is found } isColumnsContext = false; return o; }; - var peg$f87 = function(chars) { return chars.join("").trim(); }; - var peg$f88 = function() { + var peg$f88 = function(chars) { return chars.join("").trim(); }; + var peg$f89 = function() { isColumnsContext = false; return "and"; }; - var peg$f89 = function() { return expectingNestedQuote; }; - var peg$f90 = function(start, inner, end) { //handle no-breaking space + var peg$f90 = function() { return expectingNestedQuote; }; + var peg$f91 = function(start, inner, end) { //handle no-breaking space return [...start, '"', ...inner, '"', ...end].join(""); }; - var peg$f91 = function(start) {return "“"}; - var peg$f92 = function(start) {return "”"}; - var peg$f93 = function(start) {return "\""}; - var peg$f94 = function(start, inner, end) { + var peg$f92 = function(start) {return "“"}; + var peg$f93 = function(start) {return "”"}; + var peg$f94 = function(start) {return "\""}; + var peg$f95 = function(start, inner, end) { return [...start, '"', ...inner, '"'].join(""); }; var peg$currPos = options.peg$currPos | 0; @@ -2375,7 +2378,10 @@ function peg$parse(input, options) { if (s0 === peg$FAILED) { s0 = peg$parsegroupCategory(); if (s0 === peg$FAILED) { - s0 = peg$parsegroupMonth(); + s0 = peg$parsegroupMerchant(); + if (s0 === peg$FAILED) { + s0 = peg$parsegroupMonth(); + } } } } @@ -3261,13 +3267,13 @@ function peg$parse(input, options) { return s0; } - function peg$parsegroupMonth() { + function peg$parsegroupMerchant() { var s0, s1, s2, s3; s0 = peg$currPos; - s1 = input.substr(peg$currPos, 11); + s1 = input.substr(peg$currPos, 14); if (s1.toLowerCase() === peg$c87) { - peg$currPos += 11; + peg$currPos += 14; } else { s1 = peg$FAILED; if (peg$silentFails === 0) { peg$fail(peg$e90); } @@ -3298,6 +3304,43 @@ function peg$parse(input, options) { return s0; } + function peg$parsegroupMonth() { + var s0, s1, s2, s3; + + s0 = peg$currPos; + s1 = input.substr(peg$currPos, 11); + if (s1.toLowerCase() === peg$c88) { + peg$currPos += 11; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e91); } + } + if (s1 !== peg$FAILED) { + s2 = peg$currPos; + peg$silentFails++; + s3 = peg$parsewordBoundary(); + peg$silentFails--; + if (s3 !== peg$FAILED) { + peg$currPos = s2; + s2 = undefined; + } else { + s2 = peg$FAILED; + } + if (s2 !== peg$FAILED) { + peg$savedPos = s0; + s0 = peg$f80(); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + function peg$parseoperator() { var s0, s1; @@ -3308,81 +3351,81 @@ function peg$parse(input, options) { peg$currPos++; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e92); } + if (peg$silentFails === 0) { peg$fail(peg$e93); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f80(); + s1 = peg$f81(); } s0 = s1; if (s0 === peg$FAILED) { s0 = peg$currPos; - if (input.substr(peg$currPos, 2) === peg$c88) { - s1 = peg$c88; + if (input.substr(peg$currPos, 2) === peg$c89) { + s1 = peg$c89; peg$currPos += 2; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e93); } + if (peg$silentFails === 0) { peg$fail(peg$e94); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f81(); + s1 = peg$f82(); } s0 = s1; if (s0 === peg$FAILED) { s0 = peg$currPos; - if (input.substr(peg$currPos, 2) === peg$c89) { - s1 = peg$c89; + if (input.substr(peg$currPos, 2) === peg$c90) { + s1 = peg$c90; peg$currPos += 2; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e94); } + if (peg$silentFails === 0) { peg$fail(peg$e95); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f82(); + s1 = peg$f83(); } s0 = s1; if (s0 === peg$FAILED) { s0 = peg$currPos; if (input.charCodeAt(peg$currPos) === 62) { - s1 = peg$c90; + s1 = peg$c91; peg$currPos++; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e95); } + if (peg$silentFails === 0) { peg$fail(peg$e96); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f83(); + s1 = peg$f84(); } s0 = s1; if (s0 === peg$FAILED) { s0 = peg$currPos; - if (input.substr(peg$currPos, 2) === peg$c91) { - s1 = peg$c91; + if (input.substr(peg$currPos, 2) === peg$c92) { + s1 = peg$c92; peg$currPos += 2; } 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$f84(); + s1 = peg$f85(); } s0 = s1; if (s0 === peg$FAILED) { s0 = peg$currPos; if (input.charCodeAt(peg$currPos) === 60) { - s1 = peg$c92; + s1 = peg$c93; peg$currPos++; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e97); } + if (peg$silentFails === 0) { peg$fail(peg$e98); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f85(); + s1 = peg$f86(); } s0 = s1; } @@ -3393,7 +3436,7 @@ function peg$parse(input, options) { peg$silentFails--; if (s0 === peg$FAILED) { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e91); } + if (peg$silentFails === 0) { peg$fail(peg$e92); } } return s0; @@ -3406,7 +3449,7 @@ function peg$parse(input, options) { s1 = peg$parseoperator(); if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f86(s1); + s1 = peg$f87(s1); } s0 = s1; @@ -3424,7 +3467,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e99); } + if (peg$silentFails === 0) { peg$fail(peg$e100); } } if (s2 !== peg$FAILED) { while (s2 !== peg$FAILED) { @@ -3434,7 +3477,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e99); } + if (peg$silentFails === 0) { peg$fail(peg$e100); } } } } else { @@ -3442,13 +3485,13 @@ function peg$parse(input, options) { } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f87(s1); + s1 = peg$f88(s1); } s0 = s1; peg$silentFails--; if (s0 === peg$FAILED) { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e98); } + if (peg$silentFails === 0) { peg$fail(peg$e99); } } return s0; @@ -3460,7 +3503,7 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = peg$parse_(); peg$savedPos = s0; - s1 = peg$f88(); + s1 = peg$f89(); s0 = s1; return s0; @@ -3476,7 +3519,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e101); } + if (peg$silentFails === 0) { peg$fail(peg$e102); } } while (s1 !== peg$FAILED) { s0.push(s1); @@ -3485,12 +3528,12 @@ function peg$parse(input, options) { peg$currPos++; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e101); } + if (peg$silentFails === 0) { peg$fail(peg$e102); } } } peg$silentFails--; s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e100); } + if (peg$silentFails === 0) { peg$fail(peg$e101); } return s0; } @@ -3500,7 +3543,7 @@ function peg$parse(input, options) { s0 = peg$currPos; peg$savedPos = peg$currPos; - s1 = peg$f89(); + s1 = peg$f90(); if (s1) { s1 = undefined; } else { @@ -3537,7 +3580,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e103); } + if (peg$silentFails === 0) { peg$fail(peg$e104); } } while (s2 !== peg$FAILED) { s1.push(s2); @@ -3546,7 +3589,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e103); } + if (peg$silentFails === 0) { peg$fail(peg$e104); } } } s2 = input.charAt(peg$currPos); @@ -3554,7 +3597,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e104); } + if (peg$silentFails === 0) { peg$fail(peg$e105); } } if (s2 !== peg$FAILED) { s3 = []; @@ -3563,7 +3606,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s4 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e105); } + if (peg$silentFails === 0) { peg$fail(peg$e106); } } while (s4 !== peg$FAILED) { s3.push(s4); @@ -3572,7 +3615,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s4 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e105); } + if (peg$silentFails === 0) { peg$fail(peg$e106); } } } s4 = input.charAt(peg$currPos); @@ -3580,7 +3623,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s4 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e104); } + if (peg$silentFails === 0) { peg$fail(peg$e105); } } if (s4 !== peg$FAILED) { s5 = []; @@ -3589,7 +3632,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s6 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e99); } + if (peg$silentFails === 0) { peg$fail(peg$e100); } } while (s6 !== peg$FAILED) { s5.push(s6); @@ -3598,11 +3641,11 @@ function peg$parse(input, options) { peg$currPos++; } else { s6 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e99); } + if (peg$silentFails === 0) { peg$fail(peg$e100); } } } peg$savedPos = s0; - s0 = peg$f90(s1, s3, s5); + s0 = peg$f91(s1, s3, s5); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -3614,7 +3657,7 @@ function peg$parse(input, options) { peg$silentFails--; if (s0 === peg$FAILED) { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e102); } + if (peg$silentFails === 0) { peg$fail(peg$e103); } } return s0; @@ -3631,7 +3674,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e103); } + if (peg$silentFails === 0) { peg$fail(peg$e104); } } while (s2 !== peg$FAILED) { s1.push(s2); @@ -3640,7 +3683,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e103); } + if (peg$silentFails === 0) { peg$fail(peg$e104); } } } s2 = input.charAt(peg$currPos); @@ -3648,7 +3691,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e104); } + if (peg$silentFails === 0) { peg$fail(peg$e105); } } if (s2 !== peg$FAILED) { s3 = []; @@ -3657,7 +3700,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s4 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e105); } + if (peg$silentFails === 0) { peg$fail(peg$e106); } } if (s4 === peg$FAILED) { s4 = peg$currPos; @@ -3673,15 +3716,15 @@ function peg$parse(input, options) { } if (s5 !== peg$FAILED) { if (input.charCodeAt(peg$currPos) === 8220) { - s6 = peg$c93; + s6 = peg$c94; peg$currPos++; } else { s6 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e106); } + if (peg$silentFails === 0) { peg$fail(peg$e107); } } if (s6 !== peg$FAILED) { peg$savedPos = s4; - s4 = peg$f91(s1); + s4 = peg$f92(s1); } else { peg$currPos = s4; s4 = peg$FAILED; @@ -3704,15 +3747,15 @@ function peg$parse(input, options) { } if (s5 !== peg$FAILED) { if (input.charCodeAt(peg$currPos) === 8221) { - s6 = peg$c94; + s6 = peg$c95; peg$currPos++; } else { s6 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e107); } + if (peg$silentFails === 0) { peg$fail(peg$e108); } } if (s6 !== peg$FAILED) { peg$savedPos = s4; - s4 = peg$f92(s1); + s4 = peg$f93(s1); } else { peg$currPos = s4; s4 = peg$FAILED; @@ -3735,15 +3778,15 @@ function peg$parse(input, options) { } if (s5 !== peg$FAILED) { if (input.charCodeAt(peg$currPos) === 34) { - s6 = peg$c95; + s6 = peg$c96; peg$currPos++; } else { s6 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e108); } + if (peg$silentFails === 0) { peg$fail(peg$e109); } } if (s6 !== peg$FAILED) { peg$savedPos = s4; - s4 = peg$f93(s1); + s4 = peg$f94(s1); } else { peg$currPos = s4; s4 = peg$FAILED; @@ -3762,7 +3805,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s4 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e105); } + if (peg$silentFails === 0) { peg$fail(peg$e106); } } if (s4 === peg$FAILED) { s4 = peg$currPos; @@ -3778,15 +3821,15 @@ function peg$parse(input, options) { } if (s5 !== peg$FAILED) { if (input.charCodeAt(peg$currPos) === 8220) { - s6 = peg$c93; + s6 = peg$c94; peg$currPos++; } else { s6 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e106); } + if (peg$silentFails === 0) { peg$fail(peg$e107); } } if (s6 !== peg$FAILED) { peg$savedPos = s4; - s4 = peg$f91(s1); + s4 = peg$f92(s1); } else { peg$currPos = s4; s4 = peg$FAILED; @@ -3809,15 +3852,15 @@ function peg$parse(input, options) { } if (s5 !== peg$FAILED) { if (input.charCodeAt(peg$currPos) === 8221) { - s6 = peg$c94; + s6 = peg$c95; peg$currPos++; } else { s6 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e107); } + if (peg$silentFails === 0) { peg$fail(peg$e108); } } if (s6 !== peg$FAILED) { peg$savedPos = s4; - s4 = peg$f92(s1); + s4 = peg$f93(s1); } else { peg$currPos = s4; s4 = peg$FAILED; @@ -3840,15 +3883,15 @@ function peg$parse(input, options) { } if (s5 !== peg$FAILED) { if (input.charCodeAt(peg$currPos) === 34) { - s6 = peg$c95; + s6 = peg$c96; peg$currPos++; } else { s6 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e108); } + if (peg$silentFails === 0) { peg$fail(peg$e109); } } if (s6 !== peg$FAILED) { peg$savedPos = s4; - s4 = peg$f93(s1); + s4 = peg$f94(s1); } else { peg$currPos = s4; s4 = peg$FAILED; @@ -3864,7 +3907,7 @@ function peg$parse(input, options) { s4 = peg$parseclosingQuote(); if (s4 !== peg$FAILED) { peg$savedPos = s0; - s0 = peg$f94(s1, s3, s4); + s0 = peg$f95(s1, s3, s4); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -3876,7 +3919,7 @@ function peg$parse(input, options) { peg$silentFails--; if (s0 === peg$FAILED) { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e102); } + if (peg$silentFails === 0) { peg$fail(peg$e103); } } return s0; @@ -3891,7 +3934,7 @@ function peg$parse(input, options) { peg$currPos++; } 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; @@ -3929,7 +3972,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e109); } + if (peg$silentFails === 0) { peg$fail(peg$e110); } } while (s2 !== peg$FAILED) { s1.push(s2); @@ -3938,7 +3981,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e109); } + if (peg$silentFails === 0) { peg$fail(peg$e110); } } } s2 = []; @@ -3947,7 +3990,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s3 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e110); } + if (peg$silentFails === 0) { peg$fail(peg$e111); } } while (s3 !== peg$FAILED) { s2.push(s3); @@ -3956,7 +3999,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s3 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e110); } + if (peg$silentFails === 0) { peg$fail(peg$e111); } } } s3 = []; @@ -3965,7 +4008,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s4 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e111); } + if (peg$silentFails === 0) { peg$fail(peg$e112); } } while (s4 !== peg$FAILED) { s3.push(s4); @@ -3974,7 +4017,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s4 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e111); } + if (peg$silentFails === 0) { peg$fail(peg$e112); } } } s4 = peg$parseoperator(); @@ -3993,7 +4036,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e112); } + if (peg$silentFails === 0) { peg$fail(peg$e113); } } while (s2 !== peg$FAILED) { s1.push(s2); @@ -4002,7 +4045,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e112); } + if (peg$silentFails === 0) { peg$fail(peg$e113); } } } s2 = peg$currPos; @@ -4049,7 +4092,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s0 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e113); } + if (peg$silentFails === 0) { peg$fail(peg$e114); } } } } @@ -4065,7 +4108,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s0 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e114); } + if (peg$silentFails === 0) { peg$fail(peg$e115); } } if (s0 === peg$FAILED) { s0 = peg$currPos; diff --git a/src/libs/SearchParser/baseRules.peggy b/src/libs/SearchParser/baseRules.peggy index 1a8c6d48e905a..3faa65fa027ef 100644 --- a/src/libs/SearchParser/baseRules.peggy +++ b/src/libs/SearchParser/baseRules.peggy @@ -114,6 +114,7 @@ columnsValues / groupWithdrawn / groupWithdrawalId / groupCategory + / groupMerchant / groupMonth perDiem = "per-diem"i &wordBoundary { return "perDiem"; } @@ -139,6 +140,7 @@ groupBankAccount = "group-bank-account"i &wordBoundary { return "gr groupWithdrawn = "group-withdrawn"i &wordBoundary { return "groupWithdrawn"; } groupWithdrawalId = "group-withdrawal-id"i &wordBoundary { return "groupWithdrawalID"; } groupCategory = "group-category"i &wordBoundary { return "groupCategory"; } +groupMerchant = "group-merchant"i &wordBoundary { return "groupMerchant"; } groupMonth = "group-month"i &wordBoundary { return "groupMonth"; } diff --git a/src/libs/SearchParser/searchParser.js b/src/libs/SearchParser/searchParser.js index dd66d002472e6..6a1c703157990 100644 --- a/src/libs/SearchParser/searchParser.js +++ b/src/libs/SearchParser/searchParser.js @@ -271,15 +271,16 @@ function peg$parse(input, options) { var peg$c84 = "group-withdrawn"; var peg$c85 = "group-withdrawal-id"; var peg$c86 = "group-category"; - var peg$c87 = "group-month"; - var peg$c88 = "!="; - var peg$c89 = ">="; - var peg$c90 = ">"; - var peg$c91 = "<="; - var peg$c92 = "<"; - var peg$c93 = "\u201C"; - var peg$c94 = "\u201D"; - var peg$c95 = "\""; + var peg$c87 = "group-merchant"; + var peg$c88 = "group-month"; + var peg$c89 = "!="; + var peg$c90 = ">="; + var peg$c91 = ">"; + var peg$c92 = "<="; + var peg$c93 = "<"; + var peg$c94 = "\u201C"; + var peg$c95 = "\u201D"; + var peg$c96 = "\""; var peg$r0 = /^[^ \t\r\n\xA0]/; var peg$r1 = /^[ \t\r\n\xA0,:=<>!]/; @@ -388,31 +389,32 @@ function peg$parse(input, options) { var peg$e89 = peg$literalExpectation("group-withdrawn", true); var peg$e90 = peg$literalExpectation("group-withdrawal-id", true); var peg$e91 = peg$literalExpectation("group-category", true); - var peg$e92 = peg$literalExpectation("group-month", true); - var peg$e93 = peg$otherExpectation("operator"); - var peg$e94 = peg$classExpectation([":", "="], false, false); - var peg$e95 = peg$literalExpectation("!=", false); - var peg$e96 = peg$literalExpectation(">=", false); - var peg$e97 = peg$literalExpectation(">", false); - var peg$e98 = peg$literalExpectation("<=", false); - var peg$e99 = peg$literalExpectation("<", false); - var peg$e100 = peg$otherExpectation("word"); - var peg$e101 = peg$classExpectation([" ", ",", "\t", "\n", "\r", "\xA0"], true, false); - var peg$e102 = peg$otherExpectation("whitespace"); - var peg$e103 = peg$classExpectation([" ", "\t", "\r", "\n", "\xA0"], false, false); - var peg$e104 = peg$otherExpectation("quote"); - var peg$e105 = peg$classExpectation([" ", ",", "\"", "\u201D", "\u201C", "\t", "\n", "\r", "\xA0"], true, false); - var peg$e106 = peg$classExpectation(["\"", ["\u201C", "\u201D"]], false, false); - var peg$e107 = peg$classExpectation(["\"", "\u201D", "\u201C", "\r", "\n"], true, false); - var peg$e108 = peg$literalExpectation("\u201C", false); - var peg$e109 = peg$literalExpectation("\u201D", false); - var peg$e110 = peg$literalExpectation("\"", false); - var peg$e111 = peg$classExpectation([" ", "\t", "\n", "\r", "\xA0", ["a", "z"], ["A", "Z"], ["0", "9"]], false, false); - var peg$e112 = peg$classExpectation([["a", "z"], ["A", "Z"], ["0", "9"]], false, false); - var peg$e113 = peg$classExpectation([" ", "\t", "\n", "\r", "\xA0"], false, false); - var peg$e114 = peg$classExpectation([" ", "\t", "\n", "\r", "\xA0", ["a", "z"], ["A", "Z"]], false, false); - var peg$e115 = peg$classExpectation([","], false, false); - var peg$e116 = peg$classExpectation([" ", "\t", "\n", "\r", "\xA0", ","], false, false); + var peg$e92 = peg$literalExpectation("group-merchant", true); + var peg$e93 = peg$literalExpectation("group-month", true); + var peg$e94 = peg$otherExpectation("operator"); + var peg$e95 = peg$classExpectation([":", "="], false, false); + var peg$e96 = peg$literalExpectation("!=", false); + var peg$e97 = peg$literalExpectation(">=", false); + var peg$e98 = peg$literalExpectation(">", false); + var peg$e99 = peg$literalExpectation("<=", false); + var peg$e100 = peg$literalExpectation("<", false); + var peg$e101 = peg$otherExpectation("word"); + var peg$e102 = peg$classExpectation([" ", ",", "\t", "\n", "\r", "\xA0"], true, false); + var peg$e103 = peg$otherExpectation("whitespace"); + var peg$e104 = peg$classExpectation([" ", "\t", "\r", "\n", "\xA0"], false, false); + var peg$e105 = peg$otherExpectation("quote"); + var peg$e106 = peg$classExpectation([" ", ",", "\"", "\u201D", "\u201C", "\t", "\n", "\r", "\xA0"], true, false); + var peg$e107 = peg$classExpectation(["\"", ["\u201C", "\u201D"]], false, false); + var peg$e108 = peg$classExpectation(["\"", "\u201D", "\u201C", "\r", "\n"], true, false); + var peg$e109 = peg$literalExpectation("\u201C", false); + var peg$e110 = peg$literalExpectation("\u201D", false); + var peg$e111 = peg$literalExpectation("\"", false); + var peg$e112 = peg$classExpectation([" ", "\t", "\n", "\r", "\xA0", ["a", "z"], ["A", "Z"], ["0", "9"]], false, false); + var peg$e113 = peg$classExpectation([["a", "z"], ["A", "Z"], ["0", "9"]], false, false); + var peg$e114 = peg$classExpectation([" ", "\t", "\n", "\r", "\xA0"], false, false); + var peg$e115 = peg$classExpectation([" ", "\t", "\n", "\r", "\xA0", ["a", "z"], ["A", "Z"]], false, false); + var peg$e116 = peg$classExpectation([","], false, false); + var peg$e117 = peg$classExpectation([" ", "\t", "\n", "\r", "\xA0", ","], false, false); var peg$f0 = function(filters) { return applyDefaults(filters); }; var peg$f1 = function(head, tail) { @@ -574,33 +576,34 @@ function peg$parse(input, options) { var peg$f77 = function() { return "groupWithdrawn"; }; var peg$f78 = function() { return "groupWithdrawalID"; }; var peg$f79 = function() { return "groupCategory"; }; - var peg$f80 = function() { return "groupMonth"; }; - var peg$f81 = function() { return "eq"; }; - var peg$f82 = function() { return "neq"; }; - var peg$f83 = function() { return "gte"; }; - var peg$f84 = function() { return "gt"; }; - var peg$f85 = function() { return "lte"; }; - var peg$f86 = function() { return "lt"; }; - var peg$f87 = function(o) { + var peg$f80 = function() { return "groupMerchant"; }; + var peg$f81 = function() { return "groupMonth"; }; + var peg$f82 = function() { return "eq"; }; + var peg$f83 = function() { return "neq"; }; + var peg$f84 = function() { return "gte"; }; + var peg$f85 = function() { return "gt"; }; + var peg$f86 = function() { return "lte"; }; + var peg$f87 = function() { return "lt"; }; + var peg$f88 = function(o) { if (nameOperator) { expectingNestedQuote = (o === "eq"); // Use simple parser if no valid operator is found } isColumnsContext = false; return o; }; - var peg$f88 = function(chars) { return chars.join("").trim(); }; - var peg$f89 = function() { + var peg$f89 = function(chars) { return chars.join("").trim(); }; + var peg$f90 = function() { isColumnsContext = false; return "and"; }; - var peg$f90 = function() { return expectingNestedQuote; }; - var peg$f91 = function(start, inner, end) { //handle no-breaking space + var peg$f91 = function() { return expectingNestedQuote; }; + var peg$f92 = function(start, inner, end) { //handle no-breaking space return [...start, '"', ...inner, '"', ...end].join(""); }; - var peg$f92 = function(start) {return "“"}; - var peg$f93 = function(start) {return "”"}; - var peg$f94 = function(start) {return "\""}; - var peg$f95 = function(start, inner, end) { + var peg$f93 = function(start) {return "“"}; + var peg$f94 = function(start) {return "”"}; + var peg$f95 = function(start) {return "\""}; + var peg$f96 = function(start, inner, end) { return [...start, '"', ...inner, '"'].join(""); }; var peg$currPos = options.peg$currPos | 0; @@ -2562,7 +2565,10 @@ function peg$parse(input, options) { if (s0 === peg$FAILED) { s0 = peg$parsegroupCategory(); if (s0 === peg$FAILED) { - s0 = peg$parsegroupMonth(); + s0 = peg$parsegroupMerchant(); + if (s0 === peg$FAILED) { + s0 = peg$parsegroupMonth(); + } } } } @@ -3448,13 +3454,13 @@ function peg$parse(input, options) { return s0; } - function peg$parsegroupMonth() { + function peg$parsegroupMerchant() { var s0, s1, s2, s3; s0 = peg$currPos; - s1 = input.substr(peg$currPos, 11); + s1 = input.substr(peg$currPos, 14); if (s1.toLowerCase() === peg$c87) { - peg$currPos += 11; + peg$currPos += 14; } else { s1 = peg$FAILED; if (peg$silentFails === 0) { peg$fail(peg$e92); } @@ -3485,6 +3491,43 @@ function peg$parse(input, options) { return s0; } + function peg$parsegroupMonth() { + var s0, s1, s2, s3; + + s0 = peg$currPos; + s1 = input.substr(peg$currPos, 11); + if (s1.toLowerCase() === peg$c88) { + peg$currPos += 11; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e93); } + } + if (s1 !== peg$FAILED) { + s2 = peg$currPos; + peg$silentFails++; + s3 = peg$parsewordBoundary(); + peg$silentFails--; + if (s3 !== peg$FAILED) { + peg$currPos = s2; + s2 = undefined; + } else { + s2 = peg$FAILED; + } + if (s2 !== peg$FAILED) { + peg$savedPos = s0; + s0 = peg$f81(); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + function peg$parseoperator() { var s0, s1; @@ -3495,81 +3538,81 @@ function peg$parse(input, options) { peg$currPos++; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e94); } + if (peg$silentFails === 0) { peg$fail(peg$e95); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f81(); + s1 = peg$f82(); } s0 = s1; if (s0 === peg$FAILED) { s0 = peg$currPos; - if (input.substr(peg$currPos, 2) === peg$c88) { - s1 = peg$c88; + if (input.substr(peg$currPos, 2) === peg$c89) { + s1 = peg$c89; peg$currPos += 2; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e95); } + if (peg$silentFails === 0) { peg$fail(peg$e96); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f82(); + s1 = peg$f83(); } s0 = s1; if (s0 === peg$FAILED) { s0 = peg$currPos; - if (input.substr(peg$currPos, 2) === peg$c89) { - s1 = peg$c89; + if (input.substr(peg$currPos, 2) === peg$c90) { + s1 = peg$c90; peg$currPos += 2; } 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$f83(); + s1 = peg$f84(); } s0 = s1; if (s0 === peg$FAILED) { s0 = peg$currPos; if (input.charCodeAt(peg$currPos) === 62) { - s1 = peg$c90; + s1 = peg$c91; peg$currPos++; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e97); } + if (peg$silentFails === 0) { peg$fail(peg$e98); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f84(); + s1 = peg$f85(); } s0 = s1; if (s0 === peg$FAILED) { s0 = peg$currPos; - if (input.substr(peg$currPos, 2) === peg$c91) { - s1 = peg$c91; + if (input.substr(peg$currPos, 2) === peg$c92) { + s1 = peg$c92; peg$currPos += 2; } 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$f85(); + s1 = peg$f86(); } s0 = s1; if (s0 === peg$FAILED) { s0 = peg$currPos; if (input.charCodeAt(peg$currPos) === 60) { - s1 = peg$c92; + s1 = peg$c93; peg$currPos++; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e99); } + if (peg$silentFails === 0) { peg$fail(peg$e100); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f86(); + s1 = peg$f87(); } s0 = s1; } @@ -3580,7 +3623,7 @@ function peg$parse(input, options) { peg$silentFails--; if (s0 === peg$FAILED) { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e93); } + if (peg$silentFails === 0) { peg$fail(peg$e94); } } return s0; @@ -3593,7 +3636,7 @@ function peg$parse(input, options) { s1 = peg$parseoperator(); if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f87(s1); + s1 = peg$f88(s1); } s0 = s1; @@ -3611,7 +3654,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e101); } + if (peg$silentFails === 0) { peg$fail(peg$e102); } } if (s2 !== peg$FAILED) { while (s2 !== peg$FAILED) { @@ -3621,7 +3664,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e101); } + if (peg$silentFails === 0) { peg$fail(peg$e102); } } } } else { @@ -3629,13 +3672,13 @@ function peg$parse(input, options) { } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f88(s1); + s1 = peg$f89(s1); } s0 = s1; peg$silentFails--; if (s0 === peg$FAILED) { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e100); } + if (peg$silentFails === 0) { peg$fail(peg$e101); } } return s0; @@ -3647,7 +3690,7 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = peg$parse_(); peg$savedPos = s0; - s1 = peg$f89(); + s1 = peg$f90(); s0 = s1; return s0; @@ -3663,7 +3706,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e103); } + if (peg$silentFails === 0) { peg$fail(peg$e104); } } while (s1 !== peg$FAILED) { s0.push(s1); @@ -3672,12 +3715,12 @@ function peg$parse(input, options) { peg$currPos++; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e103); } + if (peg$silentFails === 0) { peg$fail(peg$e104); } } } peg$silentFails--; s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e102); } + if (peg$silentFails === 0) { peg$fail(peg$e103); } return s0; } @@ -3687,7 +3730,7 @@ function peg$parse(input, options) { s0 = peg$currPos; peg$savedPos = peg$currPos; - s1 = peg$f90(); + s1 = peg$f91(); if (s1) { s1 = undefined; } else { @@ -3724,7 +3767,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e105); } + if (peg$silentFails === 0) { peg$fail(peg$e106); } } while (s2 !== peg$FAILED) { s1.push(s2); @@ -3733,7 +3776,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e105); } + if (peg$silentFails === 0) { peg$fail(peg$e106); } } } s2 = input.charAt(peg$currPos); @@ -3741,7 +3784,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e106); } + if (peg$silentFails === 0) { peg$fail(peg$e107); } } if (s2 !== peg$FAILED) { s3 = []; @@ -3750,7 +3793,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s4 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e107); } + if (peg$silentFails === 0) { peg$fail(peg$e108); } } while (s4 !== peg$FAILED) { s3.push(s4); @@ -3759,7 +3802,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s4 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e107); } + if (peg$silentFails === 0) { peg$fail(peg$e108); } } } s4 = input.charAt(peg$currPos); @@ -3767,7 +3810,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s4 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e106); } + if (peg$silentFails === 0) { peg$fail(peg$e107); } } if (s4 !== peg$FAILED) { s5 = []; @@ -3776,7 +3819,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s6 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e101); } + if (peg$silentFails === 0) { peg$fail(peg$e102); } } while (s6 !== peg$FAILED) { s5.push(s6); @@ -3785,11 +3828,11 @@ function peg$parse(input, options) { peg$currPos++; } else { s6 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e101); } + if (peg$silentFails === 0) { peg$fail(peg$e102); } } } peg$savedPos = s0; - s0 = peg$f91(s1, s3, s5); + s0 = peg$f92(s1, s3, s5); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -3801,7 +3844,7 @@ function peg$parse(input, options) { peg$silentFails--; if (s0 === peg$FAILED) { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e104); } + if (peg$silentFails === 0) { peg$fail(peg$e105); } } return s0; @@ -3818,7 +3861,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e105); } + if (peg$silentFails === 0) { peg$fail(peg$e106); } } while (s2 !== peg$FAILED) { s1.push(s2); @@ -3827,7 +3870,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e105); } + if (peg$silentFails === 0) { peg$fail(peg$e106); } } } s2 = input.charAt(peg$currPos); @@ -3835,7 +3878,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e106); } + if (peg$silentFails === 0) { peg$fail(peg$e107); } } if (s2 !== peg$FAILED) { s3 = []; @@ -3844,7 +3887,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s4 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e107); } + if (peg$silentFails === 0) { peg$fail(peg$e108); } } if (s4 === peg$FAILED) { s4 = peg$currPos; @@ -3860,15 +3903,15 @@ function peg$parse(input, options) { } if (s5 !== peg$FAILED) { if (input.charCodeAt(peg$currPos) === 8220) { - s6 = peg$c93; + s6 = peg$c94; peg$currPos++; } else { s6 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e108); } + if (peg$silentFails === 0) { peg$fail(peg$e109); } } if (s6 !== peg$FAILED) { peg$savedPos = s4; - s4 = peg$f92(s1); + s4 = peg$f93(s1); } else { peg$currPos = s4; s4 = peg$FAILED; @@ -3891,15 +3934,15 @@ function peg$parse(input, options) { } if (s5 !== peg$FAILED) { if (input.charCodeAt(peg$currPos) === 8221) { - s6 = peg$c94; + s6 = peg$c95; peg$currPos++; } else { s6 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e109); } + if (peg$silentFails === 0) { peg$fail(peg$e110); } } if (s6 !== peg$FAILED) { peg$savedPos = s4; - s4 = peg$f93(s1); + s4 = peg$f94(s1); } else { peg$currPos = s4; s4 = peg$FAILED; @@ -3922,15 +3965,15 @@ function peg$parse(input, options) { } if (s5 !== peg$FAILED) { if (input.charCodeAt(peg$currPos) === 34) { - s6 = peg$c95; + s6 = peg$c96; peg$currPos++; } else { s6 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e110); } + if (peg$silentFails === 0) { peg$fail(peg$e111); } } if (s6 !== peg$FAILED) { peg$savedPos = s4; - s4 = peg$f94(s1); + s4 = peg$f95(s1); } else { peg$currPos = s4; s4 = peg$FAILED; @@ -3949,7 +3992,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s4 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e107); } + if (peg$silentFails === 0) { peg$fail(peg$e108); } } if (s4 === peg$FAILED) { s4 = peg$currPos; @@ -3965,15 +4008,15 @@ function peg$parse(input, options) { } if (s5 !== peg$FAILED) { if (input.charCodeAt(peg$currPos) === 8220) { - s6 = peg$c93; + s6 = peg$c94; peg$currPos++; } else { s6 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e108); } + if (peg$silentFails === 0) { peg$fail(peg$e109); } } if (s6 !== peg$FAILED) { peg$savedPos = s4; - s4 = peg$f92(s1); + s4 = peg$f93(s1); } else { peg$currPos = s4; s4 = peg$FAILED; @@ -3996,15 +4039,15 @@ function peg$parse(input, options) { } if (s5 !== peg$FAILED) { if (input.charCodeAt(peg$currPos) === 8221) { - s6 = peg$c94; + s6 = peg$c95; peg$currPos++; } else { s6 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e109); } + if (peg$silentFails === 0) { peg$fail(peg$e110); } } if (s6 !== peg$FAILED) { peg$savedPos = s4; - s4 = peg$f93(s1); + s4 = peg$f94(s1); } else { peg$currPos = s4; s4 = peg$FAILED; @@ -4027,15 +4070,15 @@ function peg$parse(input, options) { } if (s5 !== peg$FAILED) { if (input.charCodeAt(peg$currPos) === 34) { - s6 = peg$c95; + s6 = peg$c96; peg$currPos++; } else { s6 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e110); } + if (peg$silentFails === 0) { peg$fail(peg$e111); } } if (s6 !== peg$FAILED) { peg$savedPos = s4; - s4 = peg$f94(s1); + s4 = peg$f95(s1); } else { peg$currPos = s4; s4 = peg$FAILED; @@ -4051,7 +4094,7 @@ function peg$parse(input, options) { s4 = peg$parseclosingQuote(); if (s4 !== peg$FAILED) { peg$savedPos = s0; - s0 = peg$f95(s1, s3, s4); + s0 = peg$f96(s1, s3, s4); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -4063,7 +4106,7 @@ function peg$parse(input, options) { peg$silentFails--; if (s0 === peg$FAILED) { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e104); } + if (peg$silentFails === 0) { peg$fail(peg$e105); } } return s0; @@ -4078,7 +4121,7 @@ function peg$parse(input, options) { peg$currPos++; } 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; @@ -4116,7 +4159,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e111); } + if (peg$silentFails === 0) { peg$fail(peg$e112); } } while (s2 !== peg$FAILED) { s1.push(s2); @@ -4125,7 +4168,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e111); } + if (peg$silentFails === 0) { peg$fail(peg$e112); } } } s2 = []; @@ -4134,7 +4177,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s3 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e112); } + if (peg$silentFails === 0) { peg$fail(peg$e113); } } while (s3 !== peg$FAILED) { s2.push(s3); @@ -4143,7 +4186,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s3 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e112); } + if (peg$silentFails === 0) { peg$fail(peg$e113); } } } s3 = []; @@ -4152,7 +4195,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s4 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e113); } + if (peg$silentFails === 0) { peg$fail(peg$e114); } } while (s4 !== peg$FAILED) { s3.push(s4); @@ -4161,7 +4204,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s4 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e113); } + if (peg$silentFails === 0) { peg$fail(peg$e114); } } } s4 = peg$parseoperator(); @@ -4180,7 +4223,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e114); } + if (peg$silentFails === 0) { peg$fail(peg$e115); } } while (s2 !== peg$FAILED) { s1.push(s2); @@ -4189,7 +4232,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e114); } + if (peg$silentFails === 0) { peg$fail(peg$e115); } } } s2 = peg$currPos; @@ -4236,7 +4279,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s0 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e115); } + if (peg$silentFails === 0) { peg$fail(peg$e116); } } } } @@ -4252,7 +4295,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s0 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e116); } + if (peg$silentFails === 0) { peg$fail(peg$e117); } } if (s0 === peg$FAILED) { s0 = peg$currPos; From 4382a14935e5ccd07f50fb575d675800c4ed1a88 Mon Sep 17 00:00:00 2001 From: TaduJR Date: Wed, 28 Jan 2026 14:06:40 +0300 Subject: [PATCH 21/24] fix: add MERCHANT case to isTransactionMatchWithGroupItem function --- src/components/Search/SearchList/index.tsx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/components/Search/SearchList/index.tsx b/src/components/Search/SearchList/index.tsx index 3cecb2cdab92a..0bb6e50b0a5c7 100644 --- a/src/components/Search/SearchList/index.tsx +++ b/src/components/Search/SearchList/index.tsx @@ -29,6 +29,7 @@ import type { TransactionCategoryGroupListItemType, TransactionGroupListItemType, TransactionListItemType, + TransactionMerchantGroupListItemType, TransactionMonthGroupListItemType, } from '@components/SelectionListWithSections/types'; import Text from '@components/Text'; @@ -159,6 +160,9 @@ function isTransactionMatchWithGroupItem(transaction: Transaction, groupItem: Se if (groupBy === CONST.SEARCH.GROUP_BY.CATEGORY) { return (transaction.category ?? '') === ((groupItem as TransactionCategoryGroupListItemType).category ?? ''); } + if (groupBy === CONST.SEARCH.GROUP_BY.MERCHANT) { + return (transaction.merchant ?? '') === ((groupItem as TransactionMerchantGroupListItemType).merchant ?? ''); + } if (groupBy === CONST.SEARCH.GROUP_BY.MONTH) { const monthGroup = groupItem as TransactionMonthGroupListItemType; const transactionDateString = transaction.modifiedCreated ?? transaction.created ?? ''; From f6bd38639c16b2f469682d76fab392316e1d3fc1 Mon Sep 17 00:00:00 2001 From: TaduJR Date: Wed, 28 Jan 2026 14:37:58 +0300 Subject: [PATCH 22/24] fix: add merchant entries to searchParser.peggy GROUP_BY_DEFAULT_SORT --- src/libs/SearchParser/searchParser.js | 2 ++ src/libs/SearchParser/searchParser.peggy | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/libs/SearchParser/searchParser.js b/src/libs/SearchParser/searchParser.js index 6a1c703157990..3532644b8b0f0 100644 --- a/src/libs/SearchParser/searchParser.js +++ b/src/libs/SearchParser/searchParser.js @@ -4325,6 +4325,7 @@ function peg$parse(input, options) { card: "card", "withdrawal-id": "withdrawn", category: "category", + merchant: "groupmerchant", month: "groupmonth", }; @@ -4333,6 +4334,7 @@ function peg$parse(input, options) { card: "asc", "withdrawal-id": "desc", category: "asc", + merchant: "desc", month: "desc" }; diff --git a/src/libs/SearchParser/searchParser.peggy b/src/libs/SearchParser/searchParser.peggy index 9dc46092f4cff..9b3fefb2b3d65 100644 --- a/src/libs/SearchParser/searchParser.peggy +++ b/src/libs/SearchParser/searchParser.peggy @@ -33,6 +33,7 @@ card: "card", "withdrawal-id": "withdrawn", category: "category", + merchant: "groupmerchant", month: "groupmonth", }; @@ -41,6 +42,7 @@ card: "asc", "withdrawal-id": "desc", category: "asc", + merchant: "desc", month: "desc" }; From bceb5c32a6cc3272d4040e569a38488eca003e79 Mon Sep 17 00:00:00 2001 From: TaduJR Date: Wed, 28 Jan 2026 14:46:13 +0300 Subject: [PATCH 23/24] fix: use asc sort order for merchant grouping --- src/libs/SearchParser/searchParser.js | 2 +- src/libs/SearchParser/searchParser.peggy | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libs/SearchParser/searchParser.js b/src/libs/SearchParser/searchParser.js index 3532644b8b0f0..96ad50bda9549 100644 --- a/src/libs/SearchParser/searchParser.js +++ b/src/libs/SearchParser/searchParser.js @@ -4334,7 +4334,7 @@ function peg$parse(input, options) { card: "asc", "withdrawal-id": "desc", category: "asc", - merchant: "desc", + merchant: "asc", month: "desc" }; diff --git a/src/libs/SearchParser/searchParser.peggy b/src/libs/SearchParser/searchParser.peggy index 9b3fefb2b3d65..988ac22a13a47 100644 --- a/src/libs/SearchParser/searchParser.peggy +++ b/src/libs/SearchParser/searchParser.peggy @@ -42,7 +42,7 @@ card: "asc", "withdrawal-id": "desc", category: "asc", - merchant: "desc", + merchant: "asc", month: "desc" }; From c1de48c2463c0dd8364884b01e874d828ede928c Mon Sep 17 00:00:00 2001 From: TaduJR Date: Wed, 28 Jan 2026 14:54:00 +0300 Subject: [PATCH 24/24] fix: use camelCase groupMerchant and asc sort order in searchParser --- src/libs/SearchParser/searchParser.js | 2 +- src/libs/SearchParser/searchParser.peggy | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libs/SearchParser/searchParser.js b/src/libs/SearchParser/searchParser.js index 96ad50bda9549..ecdc1984eca9b 100644 --- a/src/libs/SearchParser/searchParser.js +++ b/src/libs/SearchParser/searchParser.js @@ -4325,7 +4325,7 @@ function peg$parse(input, options) { card: "card", "withdrawal-id": "withdrawn", category: "category", - merchant: "groupmerchant", + merchant: "groupMerchant", month: "groupmonth", }; diff --git a/src/libs/SearchParser/searchParser.peggy b/src/libs/SearchParser/searchParser.peggy index 988ac22a13a47..b6f264ebf8af9 100644 --- a/src/libs/SearchParser/searchParser.peggy +++ b/src/libs/SearchParser/searchParser.peggy @@ -33,7 +33,7 @@ card: "card", "withdrawal-id": "withdrawn", category: "category", - merchant: "groupmerchant", + merchant: "groupMerchant", month: "groupmonth", };