@zeniai/client-epic-state 5.0.69-betaAR3 → 5.0.69-betaAR5

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.
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Shared filter primitives — used by both Transaction Categorization and
3
+ * Spend Management filter pipelines.
4
+ *
5
+ * These types are deliberately decoupled from any specific feature group:
6
+ *
7
+ * - `CategoryCombinationOperator` is how a `categories[]` array combines
8
+ * (`AND` ⇒ every category must match; `OR` ⇒ any category matches).
9
+ * - `FilterCategoryType` is the input-type tag a filter category uses to
10
+ * pick its value-picker UI (text autocomplete, user picker, date range,
11
+ * number range, plain dropdown).
12
+ *
13
+ * They used to be redeclared locally in both `transactionFilterHelpers.ts`
14
+ * and `spendManagementFilterHelpers.ts` to keep the feature groups
15
+ * independent. Centralising them here is consistent with Route B (which
16
+ * separated the *matching pipelines*, not the *shared primitive types*) and
17
+ * removes the maintenance trap of two identical type definitions drifting
18
+ * apart over time.
19
+ */
20
+ /** How `categories[]` combines: AND requires every category to match, OR requires any. */
21
+ export type CategoryCombinationOperator = 'AND' | 'OR';
22
+ /** Input-type tag a filter category uses to pick its value-picker UI. */
23
+ export type FilterCategoryType = 'searchAutocomplete' | 'user' | 'dateRange' | 'numberRange' | 'dropdown';
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+ /**
3
+ * Shared filter primitives — used by both Transaction Categorization and
4
+ * Spend Management filter pipelines.
5
+ *
6
+ * These types are deliberately decoupled from any specific feature group:
7
+ *
8
+ * - `CategoryCombinationOperator` is how a `categories[]` array combines
9
+ * (`AND` ⇒ every category must match; `OR` ⇒ any category matches).
10
+ * - `FilterCategoryType` is the input-type tag a filter category uses to
11
+ * pick its value-picker UI (text autocomplete, user picker, date range,
12
+ * number range, plain dropdown).
13
+ *
14
+ * They used to be redeclared locally in both `transactionFilterHelpers.ts`
15
+ * and `spendManagementFilterHelpers.ts` to keep the feature groups
16
+ * independent. Centralising them here is consistent with Route B (which
17
+ * separated the *matching pipelines*, not the *shared primitive types*) and
18
+ * removes the maintenance trap of two identical type definitions drifting
19
+ * apart over time.
20
+ */
21
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Shared filter primitives — used by both Transaction Categorization and
3
+ * Spend Management filter pipelines.
4
+ *
5
+ * These types are deliberately decoupled from any specific feature group:
6
+ *
7
+ * - `CategoryCombinationOperator` is how a `categories[]` array combines
8
+ * (`AND` ⇒ every category must match; `OR` ⇒ any category matches).
9
+ * - `FilterCategoryType` is the input-type tag a filter category uses to
10
+ * pick its value-picker UI (text autocomplete, user picker, date range,
11
+ * number range, plain dropdown).
12
+ *
13
+ * They used to be redeclared locally in both `transactionFilterHelpers.ts`
14
+ * and `spendManagementFilterHelpers.ts` to keep the feature groups
15
+ * independent. Centralising them here is consistent with Route B (which
16
+ * separated the *matching pipelines*, not the *shared primitive types*) and
17
+ * removes the maintenance trap of two identical type definitions drifting
18
+ * apart over time.
19
+ */
20
+ export {};
@@ -305,9 +305,9 @@ const expenseAutomationTransactionsView = createSlice({
305
305
  },
306
306
  updateTransactionFilters(draft, action) {
307
307
  const { selectedTab, filters } = action.payload;
308
- if (filters != null) {
309
- draft.transactionCategorizationView[selectedTab].filters = filters;
310
- }
308
+ // `filters` is non-nullable per the payload type, so no runtime
309
+ // null-check is needed — dropping it removes a dead defensive branch.
310
+ draft.transactionCategorizationView[selectedTab].filters = filters;
311
311
  },
312
312
  saveTransactionCategorization: {
313
313
  prepare(selectedTab, transactionIds, cotTrackingByTransactionId, isUncategorizedExpenseCategoryEnabled) {
@@ -176,7 +176,24 @@ const matchAmount = (amount, category) => {
176
176
  const transactionMatchesCategory = (transaction, category) => {
177
177
  const value = getCategoryValueForTransaction(category.field, transaction);
178
178
  if (value == null) {
179
- // Absent values count as a match only under 'not_equal'.
179
+ // Absent-value semantics pinning these down explicitly so the
180
+ // asymmetry isn't surprising:
181
+ //
182
+ // not_equal: a missing value IS NOT EQUAL to any candidate, so the
183
+ // transaction matches the filter (passes through).
184
+ // equal: a missing value is not equal to any candidate, so the
185
+ // transaction does NOT match (filtered out).
186
+ // less_than / greater_than: SQL-style three-valued logic — comparing
187
+ // against a missing value is "unknown", which we treat as
188
+ // "does not match" (filtered out). A user setting
189
+ // "amount < $1000" probably wants transactions with a
190
+ // concrete amount that satisfies the bound, not rows
191
+ // where the amount can't be determined.
192
+ // in_between: same as the single-sided comparators — missing values
193
+ // are filtered out.
194
+ //
195
+ // Only the `not_equal` branch returns `true` here; everything else
196
+ // falls through to the `false` below.
180
197
  return category.matchingOperator === 'not_equal';
181
198
  }
182
199
  if (category.field === 'amount') {
@@ -312,9 +312,9 @@ const expenseAutomationTransactionsView = (0, toolkit_1.createSlice)({
312
312
  },
313
313
  updateTransactionFilters(draft, action) {
314
314
  const { selectedTab, filters } = action.payload;
315
- if (filters != null) {
316
- draft.transactionCategorizationView[selectedTab].filters = filters;
317
- }
315
+ // `filters` is non-nullable per the payload type, so no runtime
316
+ // null-check is needed — dropping it removes a dead defensive branch.
317
+ draft.transactionCategorizationView[selectedTab].filters = filters;
318
318
  },
319
319
  saveTransactionCategorization: {
320
320
  prepare(selectedTab, transactionIds, cotTrackingByTransactionId, isUncategorizedExpenseCategoryEnabled) {
@@ -2,22 +2,23 @@
2
2
  * Filter machinery for the Transaction Categorization feature inside
3
3
  * Expense Automation. Intentionally self-contained — does NOT import anything
4
4
  * from `view/spendManagement/*`, because Transaction Categorization is not a
5
- * Spend Management product. Generic primitives (`CategoryCombinationOperator`,
6
- * `FilterCategoryType`) are redeclared locally rather than imported across the
7
- * feature boundary; their definitions happen to coincide with the
8
- * spend-management equivalents, which is fine — they're the same primitive
9
- * concept used independently by both feature groups.
5
+ * Spend Management product. Shared primitives
6
+ * (`CategoryCombinationOperator`, `FilterCategoryType`) come from
7
+ * `commonStateTypes/filterPrimitives`, which both feature groups consume.
10
8
  */
11
9
  import { Amount } from '../../commonStateTypes/amount';
12
10
  import { ID } from '../../commonStateTypes/common';
11
+ import { CategoryCombinationOperator, FilterCategoryType } from '../../commonStateTypes/filterPrimitives';
13
12
  import { TransactionType } from '../../entity/transaction/stateTypes/transactionType';
14
13
  import { SupportedTransactionWithCOT } from '../../entity/transaction/transactionState';
15
14
  import { ZeniDate } from '../../zeniDayJS';
16
15
  import { TransactionReviewLocalDataSelectorView } from './selectorTypes/transactionsViewSelectorTypes';
17
- /** Local copy of the generic combination operator — independent of SM. */
18
- export type CategoryCombinationOperator = 'AND' | 'OR';
19
- /** Local copy of the generic filter category-input type — independent of SM. */
20
- export type FilterCategoryType = 'searchAutocomplete' | 'user' | 'dateRange' | 'numberRange' | 'dropdown';
16
+ /**
17
+ * Re-exported here so the CES barrel can pull TC's primitives from the
18
+ * Expense Automation surface without reaching into `commonStateTypes`
19
+ * directly keeps the barrel's existing import topology stable.
20
+ */
21
+ export type { CategoryCombinationOperator, FilterCategoryType };
21
22
  export type TransactionFilterEntityType = 'transaction_categorization' | 'customer' | 'vendor' | 'merchant';
22
23
  export type TransactionFilterCategoryField = 'payment_account_name' | 'payment_account_type' | 'payee' | 'category' | 'class' | 'amount';
23
24
  export interface TransactionFilterCategoryDropdownOption {
@@ -179,7 +179,24 @@ const matchAmount = (amount, category) => {
179
179
  const transactionMatchesCategory = (transaction, category) => {
180
180
  const value = getCategoryValueForTransaction(category.field, transaction);
181
181
  if (value == null) {
182
- // Absent values count as a match only under 'not_equal'.
182
+ // Absent-value semantics pinning these down explicitly so the
183
+ // asymmetry isn't surprising:
184
+ //
185
+ // not_equal: a missing value IS NOT EQUAL to any candidate, so the
186
+ // transaction matches the filter (passes through).
187
+ // equal: a missing value is not equal to any candidate, so the
188
+ // transaction does NOT match (filtered out).
189
+ // less_than / greater_than: SQL-style three-valued logic — comparing
190
+ // against a missing value is "unknown", which we treat as
191
+ // "does not match" (filtered out). A user setting
192
+ // "amount < $1000" probably wants transactions with a
193
+ // concrete amount that satisfies the bound, not rows
194
+ // where the amount can't be determined.
195
+ // in_between: same as the single-sided comparators — missing values
196
+ // are filtered out.
197
+ //
198
+ // Only the `not_equal` branch returns `true` here; everything else
199
+ // falls through to the `false` below.
183
200
  return category.matchingOperator === 'not_equal';
184
201
  }
185
202
  if (category.field === 'amount') {
@@ -1,3 +1,4 @@
1
+ import { CategoryCombinationOperator, FilterCategoryType } from '../../commonStateTypes/filterPrimitives';
1
2
  import { TimePeriod } from '../../commonStateTypes/timePeriod';
2
3
  import { UserRoleType } from '../../entity/userRole/userRoleType';
3
4
  import { RootState } from '../../reducer';
@@ -12,12 +13,20 @@ import { ReimbursementView } from './reimbursement/remiListView/remiListSelector
12
13
  import { ReimbursementFilters, RemiListViewFilterCategoryField } from './reimbursement/remiListView/remiListState';
13
14
  export type SpendManagementFiltersType = BillPayFilters | ReimbursementFilters | TaskListFilters | PaymentHistoryFilters;
14
15
  export type SpendManagementFilterEntityType = 'bill_pay' | 'reimbursement' | 'task_management' | 'charge_card_payment_history';
15
- export type FilterCategoryType = 'searchAutocomplete' | 'user' | 'dateRange' | 'numberRange' | 'dropdown';
16
+ /**
17
+ * Re-exported here so consumers of `spendManagementFilterHelpers` keep
18
+ * their existing import path stable after the primitives moved to
19
+ * `commonStateTypes/filterPrimitives`. Downstream files (`taskList`,
20
+ * `remiListState`, `chargeCardPaymentHistory`, `billListState`) and the
21
+ * CES barrel still pull `CategoryCombinationOperator` / `FilterCategoryType`
22
+ * from this module — the source of truth is upstream but the surface is
23
+ * unchanged.
24
+ */
25
+ export type { CategoryCombinationOperator, FilterCategoryType };
16
26
  export interface MatchingOperatorDropdownOption {
17
27
  label: 'is' | 'is not';
18
28
  value: 'equal' | 'not_equal';
19
29
  }
20
- export type CategoryCombinationOperator = 'AND' | 'OR';
21
30
  export interface BillPayFilterCategoryDropdownOption {
22
31
  value: BillListViewFilterCategoryField;
23
32
  multiple?: boolean;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zeniai/client-epic-state",
3
- "version": "5.0.69-betaAR3",
3
+ "version": "5.0.69-betaAR5",
4
4
  "description": "Shared module between Web & Mobile containing required abstractions for state management, async network communication. ",
5
5
  "main": "lib/index.js",
6
6
  "module": "lib/esm/index.js",