@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.
- package/lib/commonStateTypes/filterPrimitives.d.ts +23 -0
- package/lib/commonStateTypes/filterPrimitives.js +21 -0
- package/lib/esm/commonStateTypes/filterPrimitives.js +20 -0
- package/lib/esm/view/expenseAutomationView/reducers/transactionsViewReducer.js +3 -3
- package/lib/esm/view/expenseAutomationView/transactionFilterHelpers.js +18 -1
- package/lib/view/expenseAutomationView/reducers/transactionsViewReducer.js +3 -3
- package/lib/view/expenseAutomationView/transactionFilterHelpers.d.ts +10 -9
- package/lib/view/expenseAutomationView/transactionFilterHelpers.js +18 -1
- package/lib/view/spendManagement/spendManagementFilterHelpers.d.ts +11 -2
- package/package.json +1 -1
|
@@ -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
|
-
|
|
309
|
-
|
|
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
|
|
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
|
-
|
|
316
|
-
|
|
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.
|
|
6
|
-
* `FilterCategoryType`)
|
|
7
|
-
*
|
|
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
|
-
/**
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
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
|
|
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
|
-
|
|
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-
|
|
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",
|