@zeniai/web-components 4.4.1-beta0MM → 4.4.1-beta0ND

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/dist/{SessionTimeoutPopup-Bf7n3N95.cjs → SessionTimeoutPopup-BC3xgHC7.cjs} +804 -943
  2. package/dist/SessionTimeoutPopup-BC3xgHC7.cjs.map +4 -0
  3. package/dist/{SessionTimeoutPopup-DRlXjiB_.js → SessionTimeoutPopup-DEw_zv_G.js} +1318 -1448
  4. package/dist/SessionTimeoutPopup-DEw_zv_G.js.map +4 -0
  5. package/dist/appLocale.d.ts +2 -68
  6. package/dist/cockpit.cjs.js +151 -151
  7. package/dist/cockpit.cjs.js.map +1 -1
  8. package/dist/cockpit.esm.js +2096 -2096
  9. package/dist/cockpit.esm.js.map +1 -1
  10. package/dist/components/common/Footer.d.ts +0 -1
  11. package/dist/components/expenseAutomation/ExpenseAutomationPage.d.ts +7 -1
  12. package/dist/components/expenseAutomation/components/navbarHeaderData.d.ts +4 -3
  13. package/dist/components/expenseAutomation/sections/actualMatching/ActualMatchingKpiStrip.d.ts +3 -2
  14. package/dist/components/expenseAutomation/sections/actualMatching/ActualMatchingList.d.ts +3 -6
  15. package/dist/components/expenseAutomation/sections/actualMatching/ActualMatchingListRow.d.ts +2 -5
  16. package/dist/components/expenseAutomation/sections/actualMatching/ActualMatchingMatchDetailPage.d.ts +4 -18
  17. package/dist/components/expenseAutomation/sections/actualMatching/ActualMatchingPage.d.ts +3 -2
  18. package/dist/components/expenseAutomation/sections/actualMatching/actualMatchingHelpers.d.ts +23 -12
  19. package/dist/components/expenseAutomation/sections/actualMatching/actualMatchingListConfig.d.ts +1 -1
  20. package/dist/components/expenseAutomation/sections/actualMatching/actualMatchingMatchDetailHelpers.d.ts +1 -6
  21. package/dist/components/expenseAutomation/sections/actualMatching/actualMatchingTypes.d.ts +22 -15
  22. package/dist/components/expenseAutomation/sections/actualMatching/matchNewPreviewHelpers.d.ts +0 -9
  23. package/dist/components/expenseAutomation/sections/jeSchedules/JESchedulePage.d.ts +1 -1
  24. package/dist/components/expenseAutomation/sections/jeSchedules/accrualDetail/JEAccrualFeedbackDialog.d.ts +2 -3
  25. package/dist/components/expenseAutomation/sections/jeSchedules/common/JEScheduleNewEntryButton.d.ts +1 -7
  26. package/dist/components/expenseAutomation/sections/jeSchedules/list/JEScheduleGroupList.d.ts +2 -2
  27. package/dist/components/expenseAutomation/sections/jeSchedules/list/jeScheduleListItems.d.ts +36 -14
  28. package/dist/context/featureProvider/DynamicConfigNameConstants.d.ts +3 -1
  29. package/dist/context/featureProvider/isActualMatchingEnabledInAgentJeConfig.d.ts +18 -0
  30. package/dist/context/featureProvider/isActualMatchingEnabledInAgentJeConfig.test.d.ts +1 -0
  31. package/dist/context/featureProvider/useActualMatchingEnabled.d.ts +6 -0
  32. package/dist/{index-DSE5Jeq7.cjs → index-BEgjuI-O.cjs} +2 -2
  33. package/dist/{index-DSE5Jeq7.cjs.map → index-BEgjuI-O.cjs.map} +1 -1
  34. package/dist/{index-BuvE_Eyo.js → index-CMHWaaKm.js} +2 -2
  35. package/dist/{index-BuvE_Eyo.js.map → index-CMHWaaKm.js.map} +1 -1
  36. package/dist/index.cjs.js +1 -1
  37. package/dist/index.d.ts +2 -0
  38. package/dist/index.esm.js +1 -1
  39. package/dist/strings/strings.d.ts +2 -68
  40. package/package.json +1 -64
  41. package/dist/SessionTimeoutPopup-Bf7n3N95.cjs.map +0 -4
  42. package/dist/SessionTimeoutPopup-DRlXjiB_.js.map +0 -4
  43. package/dist/components/expenseAutomation/sections/actualMatching/ActualMatchingStatusFilterBar.d.ts +0 -9
  44. package/dist/components/expenseAutomation/sections/actualMatching/matchNewPreviewJeColumns.d.ts +0 -9
@@ -17,7 +17,6 @@ export interface PrimaryBtnProps {
17
17
  isDisabled?: boolean;
18
18
  isLoading?: boolean;
19
19
  prefixIcon?: JSX.Element;
20
- reverseSpinnerColor?: boolean;
21
20
  size?: ButtonSize;
22
21
  style?: React.CSSProperties;
23
22
  suffixIcon?: JSX.Element;
@@ -59,8 +59,14 @@ export interface ExpenseAutomationPageProps extends MonthEndReportPageProps, Act
59
59
  initialMissingReceiptsTab?: MissingReceiptsTab;
60
60
  /** The base transaction that draft names, resolved by the host. */
61
61
  initialSelectedBaseTransaction?: ScheduleTransaction;
62
- /** Cron-2's live gate for this company, per Statsig. Off hides one-time accrual creation and Actual Matching. */
62
+ /** Cron-2's live gate for this company, per Statsig. Off hides one-time accrual creation. */
63
63
  isAccrualEnabled?: boolean;
64
+ /**
65
+ * Actual Matching JE subtab + match-detail bounce. Independent of
66
+ * `isAccrualEnabled` so one-time accrual create can stay live while AM
67
+ * stays hidden. Host reads `agent_je_config` (`ACTUAL_MATCHING_ENABLED`).
68
+ */
69
+ isActualMatchingEnabled?: boolean;
64
70
  isAiCfoAccessEnabled?: boolean;
65
71
  /**
66
72
  * Statsig `is_create_transfer_entry_from_expense_enabled`. When false the TC list
@@ -42,8 +42,9 @@ missingReceiptsOptions?: {
42
42
  navTitle?: string;
43
43
  }, receiptsEmail?: string,
44
44
  /**
45
- * Cron-2 live gate (`is_accrual_enabled`). Off hides the Actual Matching JE
46
- * subtab — there are no one-time accruals to match.
45
+ * Actual Matching JE subtab. Host ANDs `is_accrual_enabled` with
46
+ * `agent_je_config.global.accrual_config.ACTUAL_MATCHING_ENABLED`. Off
47
+ * hides the tab — code stays; this is the master-release UI gate.
47
48
  */
48
- isAccrualEnabled?: boolean) => ExpenseAutomationNavbarHeaderData;
49
+ isActualMatchingEnabled?: boolean) => ExpenseAutomationNavbarHeaderData;
49
50
  export {};
@@ -1,8 +1,9 @@
1
- import { Amount } from '@zeniai/client-epic-state';
1
+ import { Amount, MonthYearPeriod } from '@zeniai/client-epic-state';
2
2
  import { ActualMatchingKpiSummary } from './actualMatchingTypes';
3
3
  export interface ActualMatchingKpiStripProps {
4
4
  displayCurrency: Amount;
5
5
  kpiSummary: ActualMatchingKpiSummary;
6
+ selectedPeriod: MonthYearPeriod;
6
7
  }
7
- declare function ActualMatchingKpiStrip({ displayCurrency, kpiSummary, }: Readonly<ActualMatchingKpiStripProps>): import("react/jsx-runtime").JSX.Element;
8
+ declare function ActualMatchingKpiStrip({ displayCurrency, kpiSummary, selectedPeriod, }: Readonly<ActualMatchingKpiStripProps>): import("react/jsx-runtime").JSX.Element;
8
9
  export default ActualMatchingKpiStrip;
@@ -1,16 +1,13 @@
1
- import { FetchStateAndError, SortOrder } from '@zeniai/client-epic-state';
1
+ import { SortOrder } from '@zeniai/client-epic-state';
2
2
  import { ActualMatchingRow, ActualMatchingSortKey, ActualMatchingViewUIState } from './actualMatchingTypes';
3
3
  export interface ActualMatchingListProps {
4
4
  pendingReview: ActualMatchingRow[];
5
5
  reversed: ActualMatchingRow[];
6
- ignoreStatusByMatchId?: Record<string, FetchStateAndError>;
7
6
  sortKey?: ActualMatchingSortKey;
8
7
  sortOrder?: SortOrder;
9
- undoStatusByMatchId?: Record<string, FetchStateAndError>;
10
8
  onOpenMatch: (matchId: string) => void;
11
- onIgnoreMatchSuggestion?: (matchId: string) => void;
12
- onUndoReversal?: (matchId: string, accrualIds: string[]) => void;
9
+ onOpenMatchNewModal?: (matchId: string) => void;
13
10
  onUpdateActualMatchingUIState?: (uiState: Partial<ActualMatchingViewUIState>) => void;
14
11
  }
15
- declare function ActualMatchingList({ ignoreStatusByMatchId, pendingReview, reversed, onIgnoreMatchSuggestion, onOpenMatch, onUndoReversal, onUpdateActualMatchingUIState, sortKey, sortOrder, undoStatusByMatchId, }: Readonly<ActualMatchingListProps>): import("react/jsx-runtime").JSX.Element;
12
+ declare function ActualMatchingList({ pendingReview, reversed, onOpenMatch, onOpenMatchNewModal, onUpdateActualMatchingUIState, sortKey, sortOrder, }: Readonly<ActualMatchingListProps>): import("react/jsx-runtime").JSX.Element;
16
13
  export default ActualMatchingList;
@@ -4,11 +4,8 @@ export interface ActualMatchingListRowProps {
4
4
  columns: ActualMatchingColumnKey[];
5
5
  gridTemplateColumns: string;
6
6
  row: ActualMatchingRow;
7
- isIgnoring?: boolean;
8
- isUndoing?: boolean;
9
7
  onOpenMatch: (matchId: string) => void;
10
- onIgnoreMatchSuggestion?: (matchId: string) => void;
11
- onUndoReversal?: (matchId: string, accrualIds: string[]) => void;
8
+ onOpenMatchNewModal?: (matchId: string) => void;
12
9
  }
13
- declare function ActualMatchingListRow({ columns, gridTemplateColumns, isIgnoring, isUndoing, row, onIgnoreMatchSuggestion, onOpenMatch, onUndoReversal, }: Readonly<ActualMatchingListRowProps>): import("react/jsx-runtime").JSX.Element;
10
+ declare function ActualMatchingListRow({ columns, gridTemplateColumns, row, onOpenMatch, onOpenMatchNewModal, }: Readonly<ActualMatchingListRowProps>): import("react/jsx-runtime").JSX.Element;
14
11
  export default ActualMatchingListRow;
@@ -1,10 +1,8 @@
1
- import { FetchState, MatchAndReverseAccrualsParams, MatchAndReverseResult, UndoReversalResult } from '@zeniai/client-epic-state';
2
- import { ActualMatchingIgnoreReasonType, ActualMatchingMatch } from './actualMatchingTypes';
1
+ import { FetchState, MatchAndReverseResult, UndoReversalResult } from '@zeniai/client-epic-state';
2
+ import { ActualMatchingMatch } from './actualMatchingTypes';
3
3
  export interface ActualMatchingMatchDetailPageProps {
4
4
  detailFetchState: FetchState;
5
5
  refreshStatus: FetchState;
6
- isApproveInFlight?: boolean;
7
- isIgnoreInFlight?: boolean;
8
6
  isRenderedInPanel?: boolean;
9
7
  isUndoInFlight?: boolean;
10
8
  lastMatchResults?: MatchAndReverseResult[];
@@ -12,24 +10,12 @@ export interface ActualMatchingMatchDetailPageProps {
12
10
  match?: ActualMatchingMatch;
13
11
  onNavigateBack: () => void;
14
12
  onRefresh: () => void;
15
- onApproveAndReverse?: (params: MatchAndReverseAccrualsParams) => void;
16
- onIgnoreMatchSuggestion?: (reason: ActualMatchingIgnoreReasonType, note?: string) => void;
13
+ onContinueMatch?: () => void;
17
14
  onOpenBill?: (txn: {
18
15
  id: string;
19
16
  type: string;
20
17
  }) => void;
21
18
  onUndoReversal?: (accrualIds: string[]) => void;
22
19
  }
23
- export declare function ActualMatchingOpenBillActionButton({ match, transaction, onOpenBill, }: Readonly<{
24
- match?: ActualMatchingMatch;
25
- transaction?: {
26
- id: string;
27
- type: string;
28
- };
29
- onOpenBill?: (txn: {
30
- id: string;
31
- type: string;
32
- }) => void;
33
- }>): import("react/jsx-runtime").JSX.Element | null;
34
- declare function ActualMatchingMatchDetailPage({ detailFetchState, isRenderedInPanel, isApproveInFlight, isIgnoreInFlight, isUndoInFlight, match, onNavigateBack, onRefresh, onOpenBill, onApproveAndReverse, onIgnoreMatchSuggestion, onUndoReversal, lastMatchResults, lastUndoResults, refreshStatus, }: Readonly<ActualMatchingMatchDetailPageProps>): import("react/jsx-runtime").JSX.Element;
20
+ declare function ActualMatchingMatchDetailPage({ detailFetchState, isRenderedInPanel, isUndoInFlight, match, onNavigateBack, onRefresh, onOpenBill, onContinueMatch, onUndoReversal, lastMatchResults, lastUndoResults, refreshStatus, }: Readonly<ActualMatchingMatchDetailPageProps>): import("react/jsx-runtime").JSX.Element;
35
21
  export default ActualMatchingMatchDetailPage;
@@ -14,8 +14,9 @@ export interface ActualMatchingPageProps extends ActualMatchingActionProps {
14
14
  isMatchPanelOpen?: boolean;
15
15
  matchPanelContent?: ReactNode;
16
16
  }
17
- export declare function ActualMatchingPageKpis({ actualMatching, }: Readonly<{
17
+ export declare function ActualMatchingPageKpis({ actualMatching, selectedPeriod, }: Readonly<{
18
18
  actualMatching: ExpenseAutomationActualMatchingViewSelector;
19
+ selectedPeriod: MonthYearPeriod;
19
20
  }>): import("react/jsx-runtime").JSX.Element;
20
- declare function ActualMatchingPage({ actualMatching, isMatchPanelOpen, matchPanelContent, onClearMatchNewModal, onCloseMatchNewModal, onIgnoreMatchSuggestion, onMatchAndReverse, onOpenBill, onOpenMatch, onSearchMatchAccruals, onSearchMatchTransactions, onUndoReversal, onUpdateActualMatchingUIState, }: Readonly<ActualMatchingPageProps>): import("react/jsx-runtime").JSX.Element;
21
+ declare function ActualMatchingPage({ actualMatching, isMatchPanelOpen, matchPanelContent, onClearMatchNewModal, onCloseMatchNewModal, onMatchAndReverse, onOpenMatch, onOpenMatchNewModal, onSearchMatchAccruals, onSearchMatchTransactions, onUpdateActualMatchingUIState, selectedPeriod, }: Readonly<ActualMatchingPageProps>): import("react/jsx-runtime").JSX.Element;
21
22
  export default ActualMatchingPage;
@@ -1,7 +1,7 @@
1
- import { Amount, ExpenseAutomationViewSelector, SortOrder } from '@zeniai/client-epic-state';
1
+ import { Amount, ExpenseAutomationViewSelector, MonthYearPeriod, SortOrder } from '@zeniai/client-epic-state';
2
2
  import { StyledCapsuleThemeType } from '../../../common/StyledCapsule';
3
3
  import { ActualMatchingColumnKey } from './actualMatchingListConfig';
4
- import { ActualMatchingGroupedAccrual, ActualMatchingKpiSummary, ActualMatchingMatch, ActualMatchingRow, ActualMatchingSortKey, ActualMatchingStatusFilter, ActualMatchingTransactionSearchResult, ActualMatchingViewUIState, ExpenseAutomationActualMatchingViewSelector, MatchAndReverseAccrualsParams } from './actualMatchingTypes';
4
+ import { ActualMatchingGroupedAccrual, ActualMatchingKpiSummary, ActualMatchingMatch, ActualMatchingRow, ActualMatchingSortKey, ActualMatchingTransactionSearchResult, ExpenseAutomationActualMatchingViewSelector } from './actualMatchingTypes';
5
5
  export declare const EMPTY_ACTUAL_MATCHING_KPI_SUMMARY: ActualMatchingKpiSummary;
6
6
  export declare const EMPTY_ACTUAL_MATCHING_VIEW: ExpenseAutomationActualMatchingViewSelector;
7
7
  export declare function getActualMatchingFromSelector(selector: ExpenseAutomationViewSelector): ExpenseAutomationActualMatchingViewSelector;
@@ -36,8 +36,11 @@ export declare function isSameMatchVendor(transaction: {
36
36
  }): boolean;
37
37
  export declare function getAccruedDisplayAmount(row: ActualMatchingRow): Amount;
38
38
  export declare function getActualDisplayAmount(row: ActualMatchingRow): Amount | undefined;
39
+ export declare function sumRowDisplayAmount(rows: ActualMatchingRow[]): Amount;
39
40
  export declare function getActualMatchingDisplayCurrency(rows: ActualMatchingRow[]): Amount;
40
41
  export declare function formatKpiAmount(amount: number, currency: Amount): string;
42
+ export declare function formatActualMatchingKpiMonth(period: MonthYearPeriod): string;
43
+ export declare function formatGroupAmountSubtitle(template: string, amount: Amount): string;
41
44
  export declare function isAiCreatedAccrual(row: ActualMatchingRow): boolean;
42
45
  export declare function isHumanReversedRow(row: ActualMatchingRow): boolean;
43
46
  export declare function isAiReversedBy(row: ActualMatchingRow): boolean;
@@ -46,20 +49,28 @@ export declare function getColumnKeyForActualMatchingSortKey(sortKey: ActualMatc
46
49
  export declare function getActualMatchingColumnSortValue(row: ActualMatchingRow, columnKey: ActualMatchingColumnKey): string | number | null;
47
50
  export declare function sortActualMatchingRowsByColumn(rows: ActualMatchingRow[], columnKey: ActualMatchingColumnKey, sortOrder: SortOrder): ActualMatchingRow[];
48
51
  export declare function getUndoReversalAccrualIds(row: Pick<ActualMatchingRow, "accrualId" | "groupedMembers">): string[];
49
- export declare function getActualMatchingStatusFilter(uiState: ActualMatchingViewUIState): ActualMatchingStatusFilter;
50
- export declare function getMatchedBillTransaction(match: Pick<ActualMatchingMatch, "members" | "transactionType"> & {
51
- leftovers?: ActualMatchingMatch["leftovers"];
52
- transactionIntegrationId?: string;
53
- }): {
52
+ export declare function getMatchedBillTransaction(match: Pick<ActualMatchingMatch, "members" | "transactionType">): {
54
53
  id: string;
55
54
  type: string;
56
55
  } | null;
57
56
  export declare function getUndoReversalAccrualIdsFromMatch(match: Pick<ActualMatchingMatch, "members">): string[];
58
- /**
59
- * Confirm the AI suggestion in place: same match-and-reverse body Match New
60
- * posts, taken from the pending-review stamp instead of a picker.
61
- */
62
- export declare function getApproveAndReverseParams(match: Pick<ActualMatchingMatch, "members" | "transactionIntegrationId" | "transactionType">): MatchAndReverseAccrualsParams | null;
63
57
  export declare function getLeftoverWarningTooltip(row: ActualMatchingRow): string;
64
58
  export declare function pruneSelectionToVisibleResults(currentKeys: string[], visibleKeys: ReadonlySet<string>, searchFetchState: string): string[];
65
59
  export declare function nextSelectedTransactionLines(currentKeys: string[], clickedKey: string, results: ActualMatchingTransactionSearchResult[]): string[];
60
+ export declare function pickPrefillTransactionLines(results: ActualMatchingTransactionSearchResult[], prefill?: {
61
+ actualAmount?: number;
62
+ consumedLineIds?: string[];
63
+ matchedLineId?: string;
64
+ matchedTransactionId?: string;
65
+ }): string[];
66
+ export declare function pickPrefillTransactionLine(results: ActualMatchingTransactionSearchResult[], prefill?: {
67
+ actualAmount?: number;
68
+ matchedLineId?: string;
69
+ matchedTransactionId?: string;
70
+ }): string | null;
71
+ export declare function shouldPromptSelectMatchLine({ isTxnSearchComplete, lineCount, openedFromMatchId, selectedLineKey, }: {
72
+ isTxnSearchComplete: boolean;
73
+ lineCount: number;
74
+ selectedLineKey: string | null;
75
+ openedFromMatchId?: string;
76
+ }): boolean;
@@ -1,5 +1,5 @@
1
1
  import { ActualMatchingSortKey } from './actualMatchingTypes';
2
- export type ActualMatchingColumnKey = "received" | "vendor" | "type" | "reversedBy" | "service" | "reverses" | "matchTier" | "accrued" | "actual" | "variance" | "action";
2
+ export type ActualMatchingColumnKey = "received" | "vendor" | "type" | "reversedBy" | "service" | "reverses" | "matchTier" | "accrued" | "actual" | "variance";
3
3
  export interface ActualMatchingHeaderItem {
4
4
  key: ActualMatchingColumnKey;
5
5
  sortable: boolean;
@@ -1,12 +1,7 @@
1
1
  import { FetchState, JEOneTimeAccrual } from '@zeniai/client-epic-state';
2
2
  import { ActualMatchingMatch, ActualMatchingRowKind } from './actualMatchingTypes';
3
- export type ActualMatchingMatchMethod = "exact" | "fuzzy" | "manual" | "ai";
4
3
  export declare function getMatchServiceMonthsLabel(members: readonly JEOneTimeAccrual[]): string;
5
- export declare function getMatchMethodKey(match: ActualMatchingMatch): ActualMatchingMatchMethod;
6
- export declare function getMatchSourceLabel(match: ActualMatchingMatch): string;
7
- export declare function getMatchMethodLabel(match: ActualMatchingMatch): string;
8
- export declare function getWhyThisMatchedCopy(match: ActualMatchingMatch): string;
9
- export declare function getMatchJeSectionTitle(kind: ActualMatchingRowKind): string;
4
+ export declare function getMatchSubtitle(match: ActualMatchingMatch): string;
10
5
  export declare function getMatchStatusLabel(kind: ActualMatchingRowKind, labels: {
11
6
  statusAutoReversed: string;
12
7
  statusManuallyReversed: string;
@@ -1,29 +1,36 @@
1
- import { ActualMatchingIgnoreReasonType, ActualMatchingKpiSummary, ActualMatchingMatchModalView, ActualMatchingMatchView, ActualMatchingRow, ActualMatchingRowKind, ExpenseAutomationActualMatchingSortKey as ActualMatchingSortKey, ExpenseAutomationActualMatchingStatusFilter as ActualMatchingStatusFilter, ActualMatchingTransactionSearchResult, ExpenseAutomationActualMatchingViewUIState as ActualMatchingViewUIState, ExpenseAutomationActualMatchingViewSelector, FetchStateAndError, MatchAndReverseAccrualsParams, MatchAndReverseResult, MatchAndReverseResultStatus, UndoReversalAccrualsParams, UndoReversalResult, UndoReversalResultStatus, ALL_ACTUAL_MATCHING_IGNORE_REASONS, parseActualMatchingMatchId, toActualMatchingIgnoreReasonType } from '@zeniai/client-epic-state';
2
- export type { ActualMatchingIgnoreReasonType, ActualMatchingKpiSummary, ActualMatchingMatchModalView, ActualMatchingRow, ActualMatchingRowKind, ActualMatchingSortKey, ActualMatchingStatusFilter, ActualMatchingTransactionSearchResult, ActualMatchingViewUIState, ExpenseAutomationActualMatchingViewSelector, FetchStateAndError, MatchAndReverseAccrualsParams, MatchAndReverseResult, MatchAndReverseResultStatus, UndoReversalAccrualsParams, UndoReversalResult, UndoReversalResultStatus, };
3
- export type ActualMatchingMatch = ActualMatchingMatchView;
4
- export type ActualMatchingGroupedAccrual = NonNullable<ActualMatchingRow["groupedMembers"]>[number];
5
- export { ALL_ACTUAL_MATCHING_IGNORE_REASONS, parseActualMatchingMatchId, toActualMatchingIgnoreReasonType, };
1
+ import { ActualMatchingKpiSummary, ActualMatchingMatchModalView, ActualMatchingRow, ActualMatchingRowKind, ExpenseAutomationActualMatchingSortKey as ActualMatchingSortKey, ActualMatchingTransactionSearchResult, ExpenseAutomationActualMatchingViewUIState as ActualMatchingViewUIState, Amount, ExpenseAutomationActualMatchingViewSelector, ID, JEOneTimeAccrual, MatchAndReverseAccrualsParams, MatchAndReverseResult, MatchAndReverseResultStatus, UndoReversalAccrualsParams, UndoReversalResult, UndoReversalResultStatus } from '@zeniai/client-epic-state';
2
+ export type { ActualMatchingKpiSummary, ActualMatchingMatchModalView, ActualMatchingRow, ActualMatchingRowKind, ActualMatchingSortKey, ActualMatchingTransactionSearchResult, ActualMatchingViewUIState, ExpenseAutomationActualMatchingViewSelector, MatchAndReverseAccrualsParams, MatchAndReverseResult, MatchAndReverseResultStatus, UndoReversalAccrualsParams, UndoReversalResult, UndoReversalResultStatus, };
6
3
  /**
7
- * WC-only Actual Matching types (page tab, form, handlers).
8
- * CES-owned row / KPI / modal / ignore types are re-exported from
9
- * `@zeniai/client-epic-state`.
4
+ * WC-only Actual Matching types (page tab, list row extras, form, handlers).
5
+ * CES owns the view selector, row, KPI, and match-modal shapes — re-exported
6
+ * above so stories/mocks stay assignable to `ExpenseAutomationViewSelector`.
10
7
  */
11
8
  export declare const ACTUAL_MATCHING_PAGE_TAB: "actual_matching";
12
9
  export type ActualMatchingPageTab = typeof ACTUAL_MATCHING_PAGE_TAB;
10
+ export type ActualMatchingGroupedAccrual = NonNullable<ActualMatchingRow["groupedMembers"]>[number];
11
+ export interface ActualMatchingMatch {
12
+ accruedAmount: Amount;
13
+ actualAmount: Amount;
14
+ kind: ActualMatchingRowKind;
15
+ matchId: string;
16
+ members: JEOneTimeAccrual[];
17
+ transactionIntegrationId: ID;
18
+ transactionType: string;
19
+ leftovers?: JEOneTimeAccrual[];
20
+ matchShape?: string;
21
+ matchTier?: string;
22
+ transactionDate?: string;
23
+ vendorId?: ID;
24
+ vendorName?: string;
25
+ }
13
26
  export interface ActualMatchingActionProps {
14
27
  onClearMatchNewModal: () => void;
15
28
  onCloseMatchNewModal: () => void;
16
- onIgnoreMatchSuggestion: (matchId: string, reason: ActualMatchingIgnoreReasonType, note?: string) => void;
17
29
  onMatchAndReverse: (params: MatchAndReverseAccrualsParams) => void;
18
30
  onOpenMatch: (matchId: string) => void;
19
- onOpenMatchNewModal: () => void;
31
+ onOpenMatchNewModal: (matchId?: string) => void;
20
32
  onSearchMatchAccruals: (query: string, pageToken?: string) => void;
21
33
  onSearchMatchTransactions: (query: string, pageToken?: string) => void;
22
- onOpenBill?: (txn: {
23
- id: string;
24
- type: string;
25
- }) => void;
26
- onUndoReversal?: (matchId: string, accrualIds: string[]) => void;
27
34
  onUpdateActualMatchingUIState?: (uiState: Partial<ActualMatchingViewUIState>) => void;
28
35
  }
29
36
  export declare const MATCH_NEW_FORM = "expenseAutomationMatchNew";
@@ -4,18 +4,9 @@ export declare function formatServiceMonthLabel(serviceMonth: string): string;
4
4
  export declare function formatAccrualJeDate(serviceMonth: string, lastDayLabel: string): string;
5
5
  export declare function formatJeShortDate(dateValue: string): string;
6
6
  export declare function formatReversalJeDate(reversalPostingDate?: ZeniDate): string;
7
- /** Intended or posted QBO TxnDate of the reversal JE — not the matched bill date. */
8
- export declare function reversalJeDateFromAccrual(accrual: Pick<JEOneTimeAccrual, "actualReversalPostDate" | "expectedReversalDate" | "reversalPostingDate">): ZeniDate | undefined;
9
7
  export declare function sumAccruedAmount(accruals: readonly JEOneTimeAccrual[]): number;
10
8
  export declare function variancePercent(transactionAmount: number, accruedAmount: number): number | null;
11
9
  export declare function uniqueServiceMonthLabel(accruals: readonly JEOneTimeAccrual[]): string | null;
12
- export declare function transactionListMeta(transaction: Pick<ActualMatchingTransactionSearchResult, "transactionDate" | "transactionMemo">, dateLabel: string): {
13
- dateLabel: string;
14
- memo: string;
15
- monthLabel: string;
16
- };
17
10
  export declare function transactionMatchLabel(transaction: ActualMatchingTransactionSearchResult, accruals: readonly JEOneTimeAccrual[]): string;
18
11
  export declare function creditAccountName(accrual: JEOneTimeAccrual, fallback: string): string;
19
12
  export declare function debitAccountName(accrual: JEOneTimeAccrual, fallback: string): string;
20
- /** Preview-only DocNumber: cron reversal shape without the random NN suffix. */
21
- export declare function reversalJeGroupTitle(accrual: Pick<JEOneTimeAccrual, "vendorName" | "serviceMonth">): string;
@@ -59,5 +59,5 @@ export interface JESchedulePageProps extends Omit<JESchedulesSectionProps, "jeSc
59
59
  setResetJeAccountSettingsForm: (resetFn: () => void) => void;
60
60
  onNewScheduleFormChange?: (scheduleType: string, formValues: NewScheduleSaveFormValues) => void;
61
61
  }
62
- declare function JESchedulePage({ accountListNestedAccountHierarchy, baseTransactionSearchFetchState, baseTransactionSearchResults, classListNestedAccountHierarchy, expenseAutomationViewSelector, currentFooterFormId, isAccountingClassesEnabled, isCreatingNewSchedule, newScheduleSaveStatus, allDepreciationAccountListNestedAccountHierarchy, closeMonth, initialScheduleDetailsMode, initialScheduleType, newAccrualAccountsView, onCreateAccruedSchedule, onCreateOneTimeAccrual, setResetJeAccountSettingsForm, vendorSearchAutoCompleteData, onJESchedulesFormDataChange, onPostJESchedule, handleJeScheduleClick, onOneTimeAccrualClick, onOneTimeAccrualFeedback, onJeAccountSettingsChange, onSaveJeAccountSettingsClick, onSaveSchedule, onScheduleTypeChange, onSearchBaseTransaction, onViewTransaction, newScheduleLocalData, initialSelectedBaseTransaction, isAccrualEnabled, onNewScheduleFormChange, ignoreRecommendedJeSchedule, vendorSearchAutoCompleteActions, isMatchPanelOpen, isSchedulePanelOpen, matchPanelContent, schedulePanelContent, schedulePendingDiscardConfirmation, setCurrentFooterFormId, setIsCreatingNewSchedule, setIsJeAccountSettingsOpened, onRevertJeSchedule, onToggleCreatedGroupCollapsed, onTogglePendingGroupCollapsed, onUpdateJEScheduleTypeFilter, onUpdateJESchedulesUIState, onClearMatchNewModal, onCloseMatchNewModal, onIgnoreMatchSuggestion, onMatchAndReverse, onOpenBill, onOpenMatch, onOpenMatchNewModal, onSearchMatchAccruals, onSearchMatchTransactions, onUndoReversal, onUpdateActualMatchingUIState, }: Readonly<JESchedulePageProps>): import("react/jsx-runtime").JSX.Element;
62
+ declare function JESchedulePage({ accountListNestedAccountHierarchy, baseTransactionSearchFetchState, baseTransactionSearchResults, classListNestedAccountHierarchy, expenseAutomationViewSelector, currentFooterFormId, isAccountingClassesEnabled, isCreatingNewSchedule, newScheduleSaveStatus, allDepreciationAccountListNestedAccountHierarchy, closeMonth, initialScheduleDetailsMode, initialScheduleType, newAccrualAccountsView, onCreateAccruedSchedule, onCreateOneTimeAccrual, setResetJeAccountSettingsForm, vendorSearchAutoCompleteData, onJESchedulesFormDataChange, onPostJESchedule, handleJeScheduleClick, onOneTimeAccrualClick, onOneTimeAccrualFeedback, onJeAccountSettingsChange, onSaveJeAccountSettingsClick, onSaveSchedule, onScheduleTypeChange, onSearchBaseTransaction, onViewTransaction, newScheduleLocalData, initialSelectedBaseTransaction, isAccrualEnabled, onNewScheduleFormChange, ignoreRecommendedJeSchedule, vendorSearchAutoCompleteActions, isMatchPanelOpen, isSchedulePanelOpen, matchPanelContent, schedulePanelContent, schedulePendingDiscardConfirmation, setCurrentFooterFormId, setIsCreatingNewSchedule, setIsJeAccountSettingsOpened, onRevertJeSchedule, onToggleCreatedGroupCollapsed, onTogglePendingGroupCollapsed, onUpdateJEScheduleTypeFilter, onUpdateJESchedulesUIState, onClearMatchNewModal, onCloseMatchNewModal, onMatchAndReverse, onOpenMatch, onOpenMatchNewModal, onSearchMatchAccruals, onSearchMatchTransactions, onUpdateActualMatchingUIState, }: Readonly<JESchedulePageProps>): import("react/jsx-runtime").JSX.Element;
63
63
  export default JESchedulePage;
@@ -1,7 +1,6 @@
1
1
  import { JEScheduleIgnoreReasonType, JEScheduleRevertReasonType, OneTimeAccrualIgnoreReasonType, OneTimeAccrualRevertReasonType } from '@zeniai/client-epic-state';
2
- import { ActualMatchingIgnoreReasonType } from '../../actualMatching/actualMatchingTypes';
3
- export type JEAccrualFeedbackMode = "skip" | "revert" | "ignoreSchedule" | "revertSchedule" | "ignoreMatchSuggestion";
4
- export type JEAccrualFeedbackReason = JEScheduleIgnoreReasonType | JEScheduleRevertReasonType | OneTimeAccrualIgnoreReasonType | OneTimeAccrualRevertReasonType | ActualMatchingIgnoreReasonType;
2
+ export type JEAccrualFeedbackMode = "skip" | "revert" | "ignoreSchedule" | "revertSchedule";
3
+ export type JEAccrualFeedbackReason = JEScheduleIgnoreReasonType | JEScheduleRevertReasonType | OneTimeAccrualIgnoreReasonType | OneTimeAccrualRevertReasonType;
5
4
  export interface JEAccrualFeedbackDialogProps {
6
5
  /** Already formatted — interpolated into the subtitle. */
7
6
  amount: string;
@@ -13,13 +13,7 @@ export interface JEScheduleNewEntryButtonProps {
13
13
  * been typed, and the form now opens in a drawer that leaves this button reachable behind it.
14
14
  */
15
15
  isDisabled?: boolean;
16
- /**
17
- * Actual Matching only: label the primary button Match new, prepend that option in the menu, and
18
- * make the primary click open that workspace instead of a one-time accrual.
19
- */
20
- showMatchNew?: boolean;
21
16
  onSelect: (selection: JEScheduleNewEntrySelection) => void;
22
- onMatchNew?: () => void;
23
17
  }
24
- declare function JEScheduleNewEntryButton({ onSelect, isAccrualEnabled, isDisabled, onMatchNew, showMatchNew, }: Readonly<JEScheduleNewEntryButtonProps>): import("react/jsx-runtime").JSX.Element;
18
+ declare function JEScheduleNewEntryButton({ onSelect, isAccrualEnabled, isDisabled, }: Readonly<JEScheduleNewEntryButtonProps>): import("react/jsx-runtime").JSX.Element;
25
19
  export default JEScheduleNewEntryButton;
@@ -40,8 +40,8 @@ export interface JEScheduleGroupListItemData {
40
40
  export interface JEScheduleGroupListProps {
41
41
  activeHeaderItems: JEScheduleHeaderItemData[];
42
42
  /**
43
- * Rendered in order, one table per non-empty group. Callers must memoize this: an array literal
44
- * changes identity on every render, which would rebuild every group's items and re-render every row.
43
+ * Rendered in order as one table. Callers must memoize this: an array literal changes identity on
44
+ * every render, which would rebuild the item list and re-render every row.
45
45
  */
46
46
  groups: readonly JEScheduleListGroup[];
47
47
  listItemData: JEScheduleGroupListItemData;
@@ -1,7 +1,7 @@
1
1
  import { JEScheduleRow } from '@zeniai/client-epic-state';
2
2
  import { JEScheduleGroupKey } from './jeScheduleConfig';
3
3
  /**
4
- * One group of schedules, rendered as its own table, optionally under a collapsible title bar.
4
+ * One group of schedules, optionally introduced by a collapsible group row.
5
5
  *
6
6
  * `groupRow` is absent for a list that is just a table — the Existing tab — which is what used to be
7
7
  * expressed by a `hideGroupHeader` flag alongside a title and an `onToggle` nobody called.
@@ -17,24 +17,46 @@ export interface JEScheduleListGroup {
17
17
  };
18
18
  }
19
19
  /**
20
- * `isPendingReview` is recorded here, from the group the row arrived in, and must never be
21
- * re-derived from the row: a resolve row lives in the pending group but does not satisfy
22
- * `isPendingReviewRow`, so deriving it would quietly turn every resolve row read-only and strip its
23
- * pickers and Post button.
20
+ * A single flat sequence of group rows and schedule rows, so both render inside one virtualized list
21
+ * and therefore one table with one column header.
22
+ *
23
+ * `isPendingReview` rides on the row rather than the list because a merged list holds both kinds. It
24
+ * is recorded here, from the group the row arrived in, and must never be re-derived from the row: a
25
+ * resolve row lives in the pending group but does not satisfy `isPendingReviewRow`, so deriving it
26
+ * would quietly turn every resolve row read-only and strip its pickers and Post button.
24
27
  */
25
- export interface JEScheduleListItem {
28
+ export type JEScheduleListItem = {
29
+ count: number;
30
+ groupKey: JEScheduleGroupKey;
31
+ isCollapsed: boolean;
32
+ kind: "group";
33
+ title: string;
34
+ onToggle: () => void;
35
+ } | {
26
36
  groupKey: JEScheduleGroupKey;
27
37
  isPendingReview: boolean;
38
+ kind: "row";
28
39
  row: JEScheduleRow;
29
- }
30
- /** A collapsed group yields no rows; its title bar is rendered outside the list. */
31
- export declare function buildJEScheduleListItems(group: JEScheduleListGroup): JEScheduleListItem[];
40
+ };
32
41
  /**
33
- * The row-instance key matters: a schedule that failed to post in two months is two resolve rows
34
- * inside one group sharing a `jeScheduleTransactionKey`. `getJEScheduleRowInstanceKey` appends the
35
- * journal entry id for exactly those rows.
42
+ * Flatten groups into list items.
43
+ *
44
+ * An empty group contributes nothing at all, not even its group row — the two-table version achieved
45
+ * that with `length > 0` guards at the call site.
36
46
  *
37
- * The group prefix is no longer needed for uniqueness — each group is its own list — but it keeps
38
- * keys stable and readable across the groups.
47
+ * A collapsed group keeps its group row and drops its schedule rows, which is what makes the chevron
48
+ * work without unmounting the table.
49
+ */
50
+ export declare function buildJEScheduleListItems(groups: readonly JEScheduleListGroup[]): JEScheduleListItem[];
51
+ /**
52
+ * Two collisions to avoid, and both are real.
53
+ *
54
+ * The group prefix: the same schedule can appear as a resolve row in one group and an ongoing row
55
+ * in another while sharing a `jeScheduleTransactionKey`. Separate tables made that harmless; one
56
+ * list would give react-window two items with the same key.
57
+ *
58
+ * The row-instance key: a schedule that failed to post in two months is two resolve rows *inside
59
+ * one group*, which the group prefix cannot separate. `getJEScheduleRowInstanceKey` appends the
60
+ * journal entry id for exactly those rows.
39
61
  */
40
62
  export declare function getJEScheduleListItemKey(item: JEScheduleListItem): string;
@@ -27,7 +27,8 @@ export declare enum DynamicConfigNamesWebApp {
27
27
  approvalRuleV3Config = "approval_rule_v3_config",
28
28
  transactionCategorizationConfig = "transaction_categorization_config",
29
29
  zeniCardsVisibilityConfig = "zeni_cards_visibility_config",
30
- updateTransactionTypeConfig = "update_transaction_type_config"
30
+ updateTransactionTypeConfig = "update_transaction_type_config",
31
+ agentJeConfig = "agent_je_config"
31
32
  }
32
33
  /** Shared configs used by both web-app-ui and cockpit-ui */
33
34
  export declare enum DynamicConfigNamesShared {
@@ -54,6 +55,7 @@ export declare const DynamicConfigNames: {
54
55
  transactionCategorizationConfig: DynamicConfigNamesWebApp.transactionCategorizationConfig;
55
56
  zeniCardsVisibilityConfig: DynamicConfigNamesWebApp.zeniCardsVisibilityConfig;
56
57
  updateTransactionTypeConfig: DynamicConfigNamesWebApp.updateTransactionTypeConfig;
58
+ agentJeConfig: DynamicConfigNamesWebApp.agentJeConfig;
57
59
  cardsTabCockpitUser: DynamicConfigNamesCockpit.cardsTabCockpitUser;
58
60
  monthEndInsightsEnablement: DynamicConfigNamesCockpit.monthEndInsightsEnablement;
59
61
  expenseAutomationEnablement: DynamicConfigNamesCockpit.expenseAutomationEnablement;
@@ -0,0 +1,18 @@
1
+ /**
2
+ * UI gate for Actual Matching. Reads Statsig dynamic config `agent_je_config`
3
+ * (same object agent-je uses). Fail-closed: missing slice / missing key /
4
+ * any value other than explicit `true` hides the tab.
5
+ *
6
+ * Expected shape:
7
+ * ```
8
+ * {
9
+ * "global": {
10
+ * "accrual_config": {
11
+ * "ACTUAL_MATCHING_ENABLED": true
12
+ * }
13
+ * }
14
+ * }
15
+ * ```
16
+ */
17
+ export declare const ACTUAL_MATCHING_ENABLED_KEY = "ACTUAL_MATCHING_ENABLED";
18
+ export declare function isActualMatchingEnabledInAgentJeConfig(configValue: Record<string, unknown> | null | undefined): boolean;
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Actual Matching JE subtab / match-detail UI gate from Statsig
3
+ * `agent_je_config`. Fail-closed while Statsig is loading or the key is
4
+ * missing — master can ship the code with the tab hidden.
5
+ */
6
+ export declare function useActualMatchingEnabled(): boolean;