import { Amount } from '../../../commonStateTypes/amount'; import { FetchState, FetchStateAndError, FetchedState, ID } from '../../../commonStateTypes/common'; import { Recommendation, RecommendationWithCOT } from '../../../commonStateTypes/recommendationBase'; import { SortOrder } from '../../../commonStateTypes/selectorTypes/sortOrderTypes'; import { MonthYearPeriodId } from '../../../commonStateTypes/timePeriod'; import { PageToken } from '../../../commonStateTypes/viewAndReport/viewAndReport'; import { AccountBase } from '../../../entity/account/accountState'; import { ClassBase } from '../../../entity/class/classState'; import { CustomerBase } from '../../../entity/customer/customerState'; import { Entity, EntityType } from '../../../entity/genericEntity/entity'; import { ProjectBase } from '../../../entity/project/projectState'; import { TransactionID } from '../../../entity/transaction/stateTypes/transactionID'; import { BillableStatus, CategorizationStatusType, PlatformLineDetailType, ProductOrService, TransactionLineBase } from '../../../entity/transaction/stateTypes/transactionLine'; import { TransactionCategory, TransactionType } from '../../../entity/transaction/stateTypes/transactionType'; import { VendorBase } from '../../../entity/vendor/vendorState'; import { ZeniAPIStatus } from '../../../responsePayload'; import { ZeniDate } from '../../../zeniDayJS'; import { EntityRecommendationKey } from '../../recommendation/recommendationState'; import { TransactionDetailKey } from '../../transactionDetail/transactionDetailState'; import { TransactionFilters } from '../transactionFilterTypes'; import { CompletedSubTab } from './completedSubTab'; import { TransactionGroup } from './transactionGroup'; export declare const toTransactionsSortKey: (v: string) => "date" | "project" | "vendor" | "category" | "class" | "amount" | "payment_account" | "transaction_type" | "memo_and_receipt"; export type TransactionsSortKey = ReturnType; export declare const TRANSACTIONS_TABS: readonly ["review", "autoCategorized"]; export declare const toTransactionsTabKey: (v: string) => "review" | "autoCategorized"; export type TransactionsTab = ReturnType; export declare const getTransactionCategorizationKey: (transactionId: TransactionID, lineId: ID) => `${string}_expense_${string}` | `${string}_check_${string}` | `${string}_invoice_${string}` | `${string}_payment_${string}` | `${string}_credit_memo_${string}` | `${string}_sales_receipt_${string}` | `${string}_delayed_credit_${string}` | `${string}_delayed_charge_${string}` | `${string}_refund_${string}` | `${string}_bill_${string}` | `${string}_bill_payment_${string}` | `${string}_bill_payment_check_${string}` | `${string}_bill_payment_credit_card_${string}` | `${string}_vendor_credit_${string}` | `${string}_credit_card_credit_${string}` | `${string}_transfer_${string}` | `${string}_credit_card_payment_${string}` | `${string}_deposit_${string}` | `${string}_journal_entry_${string}`; export type TransactionCategorizationKey = ReturnType; export interface TransactionsViewUIState { nodeCollapseState: Record; pageToken: PageToken; scrollPosition: { scrollTop: number; scrollLeft?: number; } | undefined; searchString: string; sortKey: TransactionsSortKey; sortOrder: SortOrder; totalCount: Record; limit?: number; } export interface TransactionCategorizationLineItemData extends TransactionLineBase { amount: Amount; billable: BillableStatus; isCategoryMiscategorized: boolean; isClassMiscategorized: boolean; lineId: ID; transactionDate: ZeniDate; transactionId: ID; account?: AccountBase; categorizationStatus?: CategorizationStatusType; categoryClassRecommendationsFetchState?: FetchStateAndError; class?: ClassBase; customer?: CustomerBase; item?: ProductOrService; lineDetailType?: PlatformLineDetailType; lineEntity?: Entity; lineTransactionType?: TransactionType; postingType?: TransactionCategory; postingTypeName?: string; project?: ProjectBase; recommendationsWithCOT?: RecommendationWithCOT[]; reviewPendingReasons?: string[]; selectedEntityLine?: Entity; vendor?: VendorBase; } export interface TransactionReviewLocalData { lineItemById: Record; sortedLineItems: ID[]; tabSpecificLineItems: TabSpecificLineItems; customer?: CustomerBase; customerDetails?: { id: ID; name: string; qboId: string; }; customerUpdates?: TransactionVendorUpdates; description?: string; memo?: string; selectedEntity?: Entity; transactionDate?: ZeniDate; transactionType?: TransactionType; transactionTypeName?: string; vendor?: VendorBase; vendorDetails?: { id: ID; name: string; qboId: string; }; vendorUpdates?: TransactionVendorUpdates; } export interface SupportedTransactionCategorization { transactionReviewLocalData: TransactionReviewLocalData; transactionId?: ID; } export declare const initialSupportedTransactionCategorization: SupportedTransactionCategorization; export interface TransactionsTabViewState extends FetchedState { filters: TransactionFilters; markAsNotMiscategorizedStatus: FetchStateAndError; refreshStatus: FetchStateAndError; saveStatus: FetchStateAndError; selectedCheckBoxTransactionIds: ID[]; transactionIdsBySelectedPeriod: Record; transactionIdsWithUnsavedData: ID[]; transactionReviewLocalDataById: Record; uiState: TransactionsViewUIState; uploadReceiptStatusById: Record; selectedTransactionId?: ID; selectedTransactionLineId?: ID; } /** * Snapshot of the autoCategorized tab's paginated dataset for a single * Completed sub-tab. Stored in {@link TransactionsViewState.autoCategorizedSubTabCache} * so revisiting an already-loaded sub-tab can short-circuit the fetch epic * (mirrors parent-tab caching). The snapshot is period-spanning — both the * `totalCount` map and `transactionIdsBySelectedPeriod` map preserve every * period the user has paged through under that sub-tab. * * `scrollPosition` is captured per sub-tab so revisiting a sub-tab restores * the user's last scroll offset; switching to a fresh / never-visited sub-tab * starts at the top instead of inheriting the previous sub-tab's offset. */ export interface AutoCategorizedSubTabSnapshot { error: ZeniAPIStatus | undefined; fetchState: FetchState; pageToken: PageToken; scrollPosition: TransactionsViewUIState['scrollPosition']; totalCount: Record; transactionIdsBySelectedPeriod: Record; } export type TransactionsViewState = { /** * Per-sub-tab snapshot cache for the Completed (autoCategorized) tab. Keyed * by {@link CompletedSubTab}. Populated as the user navigates between * sub-tabs and consulted on every switch — the active autoCategorized slot * is restored from here when a snapshot exists, otherwise it is reset and * the fetch epic loads page 1 fresh. */ autoCategorizedSubTabCache: Partial>; /** * Period-keyed parent tab counts, scoped per {@link TransactionsTab}. * Sourced from the listing response's `parent_tab_total_count` and used * exclusively to drive the parent tab badges on the UI — every other * count consumer (pagination, sub-tab chips, in-tab "showing X of Y") * keeps reading from {@link TransactionsViewUIState.totalCount}. */ parentTotalCountByTab: Record>; selectedTransactionCategorizationCompletedSubTab: CompletedSubTab; selectedTransactionCategorizationTab: TransactionsTab; /** * Statement-level scope (`'expense' | 'income' | 'all'`) forwarded to the * listing API as `transaction_group`. Unlike the in-memory {@link * TransactionsTabViewState.filters}, a change here invalidates every tab / * sub-tab / count and drives a server refetch (the backend re-scopes the * whole dataset by account_type). Only surfaced in the UI when the * `is_revenue_automation_enabled` gate is on; the backend gate is * authoritative regardless of what is sent. */ selectedTransactionGroup: TransactionGroup; transactionCategorizationView: Record; }; export interface TransactionLineUpdates { account?: AccountBase; class?: ClassBase; customer?: CustomerBase; lineDescription?: string; project?: ProjectBase; recommendation?: Recommendation[]; vendor?: VendorBase; } export interface TransactionUpdates { updatesByLineId: Record; customerId?: ID; memo?: string; vendorId?: ID; } export interface EntityRelatedRecommendationUpdates { entityId: ID | null; entityType: EntityType; isBulkUpdate: boolean; recommendations: Recommendation; updatedEntityId: ID | undefined; vendorName?: string; } export interface TransactionSaveUpdates { anyBulkUpdates: boolean; entityRelatedUpdates: Record; markAsMiscatUpdates: boolean; transactionId: ID; updates: TransactionUpdates; } export interface TransactionVendorUpdates { name: string; id?: ID; qboId?: ID; } export type TabSpecificLineItems = Partial>;