@zeniai/client-epic-state 5.0.65-betaRR1 → 5.0.65-betaRR3
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/common/aiCfo/aiCfoSuggestedQuestionsPageContext.d.ts +1 -1
- package/lib/entity/aiCfo/aiCfoPayload.d.ts +37 -4
- package/lib/entity/aiCfo/aiCfoReducer.js +80 -5
- package/lib/entity/aiCfo/aiCfoState.d.ts +25 -2
- package/lib/entity/cardPolicy/cardPolicyPayload.d.ts +4 -4
- package/lib/entity/cardPolicy/cardPolicyPayload.js +1 -1
- package/lib/entity/cardPolicy/cardPolicyReducer.js +24 -5
- package/lib/entity/jeSchedules/jeSchedulesTypes.d.ts +1 -1
- package/lib/entity/monthEndCloseChecks/monthEndCloseChecksState.d.ts +1 -1
- package/lib/esm/entity/aiCfo/aiCfoReducer.js +80 -5
- package/lib/esm/entity/cardPolicy/cardPolicyPayload.js +1 -1
- package/lib/esm/entity/cardPolicy/cardPolicyReducer.js +24 -5
- package/lib/esm/view/aiCfoView/epics/fetchSuggestedQuestionsEpic.js +12 -2
- package/lib/index.d.ts +1 -1
- package/lib/view/aiCfoView/aiCfoViewReducer.d.ts +7 -0
- package/lib/view/aiCfoView/epics/fetchSuggestedQuestionsEpic.d.ts +8 -1
- package/lib/view/aiCfoView/epics/fetchSuggestedQuestionsEpic.js +12 -2
- package/lib/view/expenseAutomationView/types/jeSchedulesViewState.d.ts +1 -1
- package/lib/view/expenseAutomationView/types/missingReceiptsViewState.d.ts +2 -2
- package/lib/view/expenseAutomationView/types/transactionsViewState.d.ts +1 -1
- package/lib/view/people/peopleTypes.d.ts +1 -1
- package/lib/view/scheduleView/scheduleListView/scheduleListTypes.d.ts +1 -1
- package/lib/view/spendManagement/chargeCards/chargeCardList/chargeCardList.d.ts +1 -1
- package/package.json +1 -1
|
@@ -16,4 +16,4 @@
|
|
|
16
16
|
*
|
|
17
17
|
* @see README.md in this directory for maintenance expectations.
|
|
18
18
|
*/
|
|
19
|
-
export type AiCfoSuggestedQuestionsPageContext = 'balance_sheet' | 'profit_loss' | 'vendors' | 'transactions' | 'cash_flow' | 'accounts_receivable' | 'accounts_payable' | 'transaction_details' | 'dashboard' | 'cash_balance' | 'card_balance' | 'cash_in_cash_out' | 'net_burn_or_income' | 'cash_position' | 'top_expenses' | 'revenue' | 'operating_expenses' | 'command_centre' | 'je_schedules' | 'reconciliation' | 'flux_analysis' | 'receipts' | 'mei' | 'task_checklist' | 'performance' | 'bills_list' | 'bills_details' | 'reimbursement_list' | 'reimbursement_details' | 'vendors_summary' | 'opex_by_vendor' | 'prepaid_expenses' | 'fixed_assets' | 'form_1099' | 'accrued_expenses' | 'forecast' | 'checking' | 'checking_details' | 'treasury' | 'cards' | 'cards_detail' | 'people' | 'rewards' | 'notifications';
|
|
19
|
+
export type AiCfoSuggestedQuestionsPageContext = 'balance_sheet' | 'profit_loss' | 'vendors' | 'transactions' | 'cash_flow' | 'accounts_receivable' | 'accounts_payable' | 'transaction_details' | 'dashboard' | 'cash_balance' | 'card_balance' | 'cash_in_cash_out' | 'net_burn_or_income' | 'cash_position' | 'top_expenses' | 'revenue' | 'operating_expenses' | 'command_centre' | 'je_schedules' | 'reconciliation' | 'flux_analysis' | 'receipts' | 'mei' | 'task_checklist' | 'performance' | 'bills_list' | 'bills_details' | 'reimbursement_list' | 'reimbursement_details' | 'vendors_summary' | 'opex_by_vendor' | 'prepaid_expenses' | 'fixed_assets' | 'form_1099' | 'accrued_expenses' | 'forecast' | 'checking' | 'checking_details' | 'treasury' | 'cards' | 'cards_detail' | 'card_policy' | 'card_policy_detail' | 'people' | 'rewards' | 'notifications';
|
|
@@ -25,25 +25,58 @@ export interface CardsCardOptionPayload {
|
|
|
25
25
|
label: string;
|
|
26
26
|
description?: string | null;
|
|
27
27
|
}
|
|
28
|
+
/**
|
|
29
|
+
* Single AI-suggested card on the wire. The controller ships an array of
|
|
30
|
+
* these mixing vendor and department entries; entries with
|
|
31
|
+
* `is_suggested: true` seed step 1 of the form pre-checked, while entries
|
|
32
|
+
* with `is_suggested: false` are available in the step-2 Card dropdown and
|
|
33
|
+
* step-1 search but don't appear as initial rows.
|
|
34
|
+
*/
|
|
35
|
+
export interface SuggestedCardPayload {
|
|
36
|
+
avg_spend: number;
|
|
37
|
+
card_name: string;
|
|
38
|
+
card_name_id: string;
|
|
39
|
+
card_type: 'vendor' | 'department';
|
|
40
|
+
credit_limit: number;
|
|
41
|
+
is_suggested: boolean;
|
|
42
|
+
owner_id: string;
|
|
43
|
+
}
|
|
28
44
|
/**
|
|
29
45
|
* Discriminated payload for the AI Card Creation interactive form. The wire
|
|
30
46
|
* format mirrors the FE-side `CardsCreationInitialData` field-for-field
|
|
31
47
|
* (with snake_case field names converted to camelCase by the reducer).
|
|
32
48
|
*
|
|
33
|
-
* - `team-then-cards` (
|
|
34
|
-
* step 1, then configures cards in step 2.
|
|
49
|
+
* - `team-then-cards` (default): the AI suggests rows (vendors + departments);
|
|
50
|
+
* user reviews them in step 1, then configures cards in step 2. The wire
|
|
51
|
+
* format ships a flat `suggested_cards` array. Both suggested and
|
|
52
|
+
* not-suggested entries are included; the reducer splits them into seed
|
|
53
|
+
* rows vs. dropdown options. The legacy `team_rows` /
|
|
54
|
+
* `suggested_owner_user_id_by_team_id` shape is also accepted for
|
|
55
|
+
* backward compatibility with mocks and tests.
|
|
35
56
|
* - `cards-only` (1-step): the AI has already chosen cards; user lands
|
|
36
57
|
* directly on the editable card table for confirmation.
|
|
37
58
|
*/
|
|
38
59
|
export type CardsCreationInitialDataPayload = {
|
|
39
60
|
card_options: CardsCardOptionPayload[];
|
|
40
61
|
mode: 'team-then-cards';
|
|
41
|
-
|
|
42
|
-
|
|
62
|
+
/**
|
|
63
|
+
* Preferred wire format: flat list of vendor/department cards with an
|
|
64
|
+
* `is_suggested` discriminator. The reducer derives `team_rows`,
|
|
65
|
+
* `suggested_owner_user_id_by_team_id`, and the full `cardNameOptions`
|
|
66
|
+
* universe from this single array.
|
|
67
|
+
*/
|
|
68
|
+
suggested_cards?: SuggestedCardPayload[];
|
|
69
|
+
/**
|
|
70
|
+
* Legacy/test shape — pre-shaped seed rows. Mutually exclusive with
|
|
71
|
+
* `suggested_cards`; when both are present, `suggested_cards` wins.
|
|
72
|
+
*/
|
|
73
|
+
suggested_owner_user_id_by_team_id?: Record<string, string | null>;
|
|
74
|
+
team_rows?: Array<{
|
|
43
75
|
avg_monthly_spend: string;
|
|
44
76
|
id: string;
|
|
45
77
|
label: string;
|
|
46
78
|
recommended_limit: string;
|
|
79
|
+
card_kind?: 'vendor' | 'class' | null;
|
|
47
80
|
recommended_limit_cadence?: string | null;
|
|
48
81
|
}>;
|
|
49
82
|
} | {
|
|
@@ -180,19 +180,94 @@ const toCardsCreationInitialData = (payload) => {
|
|
|
180
180
|
})),
|
|
181
181
|
};
|
|
182
182
|
}
|
|
183
|
+
// Preferred wire format: a flat `suggested_cards` array with an
|
|
184
|
+
// `is_suggested` discriminator. The adapter splits it into seed rows,
|
|
185
|
+
// owner map, and the full dropdown universe.
|
|
186
|
+
if (payload.suggested_cards != null) {
|
|
187
|
+
return fromSuggestedCards(payload.suggested_cards, cardOptions);
|
|
188
|
+
}
|
|
189
|
+
// Legacy / test shape: backend already pre-shapes seeds. Synthesize an
|
|
190
|
+
// empty `cardNameOptions` (step 2 dropdown still works via row-self ids).
|
|
191
|
+
const teamRows = (payload.team_rows ?? []).map((row) => ({
|
|
192
|
+
avgMonthlySpend: row.avg_monthly_spend,
|
|
193
|
+
cardKind: (row.card_kind ?? 'vendor'),
|
|
194
|
+
id: row.id,
|
|
195
|
+
label: row.label,
|
|
196
|
+
recommendedLimit: row.recommended_limit,
|
|
197
|
+
recommendedLimitCadence: row.recommended_limit_cadence ?? undefined,
|
|
198
|
+
}));
|
|
183
199
|
return {
|
|
184
200
|
mode: 'team-then-cards',
|
|
185
201
|
cardOptions,
|
|
186
|
-
|
|
187
|
-
teamRows: (payload.team_rows ?? []).map((row) => ({
|
|
188
|
-
avgMonthlySpend: row.avg_monthly_spend,
|
|
202
|
+
cardNameOptions: teamRows.map((row) => ({
|
|
189
203
|
id: row.id,
|
|
204
|
+
kind: row.cardKind,
|
|
190
205
|
label: row.label,
|
|
191
|
-
recommendedLimit: row.recommended_limit,
|
|
192
|
-
recommendedLimitCadence: row.recommended_limit_cadence ?? undefined,
|
|
193
206
|
})),
|
|
207
|
+
suggestedOwnerUserIdByTeamId: Object.fromEntries(Object.entries(payload.suggested_owner_user_id_by_team_id ?? {}).map(([teamId, userId]) => [teamId, userId ?? undefined])),
|
|
208
|
+
teamRows,
|
|
194
209
|
};
|
|
195
210
|
};
|
|
211
|
+
const CURRENCY_FORMATTER = new Intl.NumberFormat('en-US', {
|
|
212
|
+
style: 'currency',
|
|
213
|
+
currency: 'USD',
|
|
214
|
+
maximumFractionDigits: 0,
|
|
215
|
+
});
|
|
216
|
+
const fromSuggestedCards = (suggestedCards, cardOptions) => {
|
|
217
|
+
const ordered = [...suggestedCards].sort((a, b) => {
|
|
218
|
+
if (a.card_type === b.card_type) {
|
|
219
|
+
return 0;
|
|
220
|
+
}
|
|
221
|
+
return a.card_type === 'vendor' ? -1 : 1;
|
|
222
|
+
});
|
|
223
|
+
const withUniqueIds = withSynthesizedIds(ordered);
|
|
224
|
+
const teamRows = withUniqueIds
|
|
225
|
+
.filter(({ card }) => card.is_suggested)
|
|
226
|
+
.map(({ card, uniqueId }) => ({
|
|
227
|
+
avgMonthlySpend: CURRENCY_FORMATTER.format(card.avg_spend),
|
|
228
|
+
cardKind: card.card_type === 'department' ? 'class' : 'vendor',
|
|
229
|
+
id: uniqueId,
|
|
230
|
+
label: card.card_name,
|
|
231
|
+
recommendedLimit: CURRENCY_FORMATTER.format(card.credit_limit),
|
|
232
|
+
recommendedLimitCadence: 'Monthly',
|
|
233
|
+
}));
|
|
234
|
+
const suggestedOwnerUserIdByTeamId = Object.fromEntries(withUniqueIds
|
|
235
|
+
.filter(({ card }) => card.is_suggested)
|
|
236
|
+
.map(({ card, uniqueId }) => [uniqueId, card.owner_id]));
|
|
237
|
+
const cardNameOptions = withUniqueIds.map(({ card, uniqueId }) => ({
|
|
238
|
+
id: uniqueId,
|
|
239
|
+
kind: card.card_type === 'department' ? 'class' : 'vendor',
|
|
240
|
+
label: card.card_name,
|
|
241
|
+
}));
|
|
242
|
+
return {
|
|
243
|
+
mode: 'team-then-cards',
|
|
244
|
+
cardOptions,
|
|
245
|
+
cardNameOptions,
|
|
246
|
+
suggestedOwnerUserIdByTeamId,
|
|
247
|
+
teamRows,
|
|
248
|
+
};
|
|
249
|
+
};
|
|
250
|
+
/**
|
|
251
|
+
* Stamp each suggested card with a stable unique id derived from its
|
|
252
|
+
* `card_name_id`. If two cards in the same payload share the same
|
|
253
|
+
* `card_name_id` (which happens in the current sample payload where
|
|
254
|
+
* `card_name_id` is the literal `"vendor_uuid"`), fall back to a
|
|
255
|
+
* synthesized id `${kind}__${card_name_id}__${index}` so RHF row keying
|
|
256
|
+
* stays unique.
|
|
257
|
+
*/
|
|
258
|
+
const withSynthesizedIds = (cards) => {
|
|
259
|
+
const seen = new Set();
|
|
260
|
+
return cards.map((card, index) => {
|
|
261
|
+
const preferred = card.card_name_id;
|
|
262
|
+
if (preferred != null && preferred !== '' && !seen.has(preferred)) {
|
|
263
|
+
seen.add(preferred);
|
|
264
|
+
return { card, uniqueId: preferred };
|
|
265
|
+
}
|
|
266
|
+
const synthesized = `${card.card_type}__${preferred ?? 'unknown'}__${index}`;
|
|
267
|
+
seen.add(synthesized);
|
|
268
|
+
return { card, uniqueId: synthesized };
|
|
269
|
+
});
|
|
270
|
+
};
|
|
196
271
|
const toCardPolicyInitialData = (payload) => {
|
|
197
272
|
const suggestedPolicies = (payload.suggested_policies ?? []).map((policy) => ({
|
|
198
273
|
id: policy.id,
|
|
@@ -62,16 +62,38 @@ export interface CardsCardOption {
|
|
|
62
62
|
label: string;
|
|
63
63
|
description?: string;
|
|
64
64
|
}
|
|
65
|
+
/**
|
|
66
|
+
* Card kind for AI Card Creation rows. `vendor` = vendor-bound card,
|
|
67
|
+
* `class` = department-scoped card. The wire format ships `department`;
|
|
68
|
+
* the reducer maps it to `class` (the FE-side term for accounting class /
|
|
69
|
+
* department) so it lines up with the rest of the codebase.
|
|
70
|
+
*/
|
|
71
|
+
export type CardsCardKind = 'vendor' | 'class';
|
|
72
|
+
/**
|
|
73
|
+
* Single entry in the unified vendor + department dropdown universe shipped
|
|
74
|
+
* by the AI controller for the `team-then-cards` flow. Powers both the
|
|
75
|
+
* step-2 Card cell dropdown (filtered to entries with matching `kind`) and
|
|
76
|
+
* the step-1 "Add something else" search (no kind filter — user can add
|
|
77
|
+
* either).
|
|
78
|
+
*/
|
|
79
|
+
export interface CardNameOption {
|
|
80
|
+
id: string;
|
|
81
|
+
kind: CardsCardKind;
|
|
82
|
+
label: string;
|
|
83
|
+
}
|
|
65
84
|
/**
|
|
66
85
|
* Initial data for the AI Card Creation interactive form. Discriminated on
|
|
67
86
|
* `mode`:
|
|
68
87
|
*
|
|
69
|
-
* - `team-then-cards` (default): AI suggests
|
|
70
|
-
* step 1, then configures one card per
|
|
88
|
+
* - `team-then-cards` (default): AI suggests rows (mix of vendors +
|
|
89
|
+
* departments); user reviews them in step 1, then configures one card per
|
|
90
|
+
* row in step 2. `cardNameOptions` is the full universe (suggested +
|
|
91
|
+
* not-suggested) used to populate the dropdown / search.
|
|
71
92
|
* - `cards-only` (1-step): AI has already chosen cards; user lands directly
|
|
72
93
|
* on the editable card table for confirmation.
|
|
73
94
|
*/
|
|
74
95
|
export type CardsCreationInitialData = {
|
|
96
|
+
cardNameOptions: CardNameOption[];
|
|
75
97
|
cardOptions: CardsCardOption[];
|
|
76
98
|
mode: 'team-then-cards';
|
|
77
99
|
/**
|
|
@@ -81,6 +103,7 @@ export type CardsCreationInitialData = {
|
|
|
81
103
|
suggestedOwnerUserIdByTeamId: Record<string, ID | undefined>;
|
|
82
104
|
teamRows: Array<{
|
|
83
105
|
avgMonthlySpend: string;
|
|
106
|
+
cardKind: CardsCardKind;
|
|
84
107
|
id: string;
|
|
85
108
|
label: string;
|
|
86
109
|
recommendedLimit: string;
|
|
@@ -27,13 +27,13 @@ export type CardPolicyMccCategoriesResponse = ZeniAPIResponse<CardPolicyMccCateg
|
|
|
27
27
|
export declare const toMccCategory: (payload: MccCategoryPayload) => MccCategory;
|
|
28
28
|
/**
|
|
29
29
|
* Vendor row returned by `/accounting/1.0/vendors`. The card-policy
|
|
30
|
-
* vendor search dropdown only needs `vendor_id` + `
|
|
31
|
-
* ignore the rest of the payload to keep this slice
|
|
32
|
-
* heavy `vendor` entity store.
|
|
30
|
+
* vendor search dropdown only needs `vendor_id` + `vendor_name`; we
|
|
31
|
+
* deliberately ignore the rest of the payload to keep this slice
|
|
32
|
+
* independent of the heavy `vendor` entity store.
|
|
33
33
|
*/
|
|
34
34
|
export interface CardPolicyVendorSearchVendorPayload {
|
|
35
|
-
name: string;
|
|
36
35
|
vendor_id: string;
|
|
36
|
+
vendor_name: string;
|
|
37
37
|
}
|
|
38
38
|
export interface CardPolicyVendorSearchData {
|
|
39
39
|
vendors: CardPolicyVendorSearchVendorPayload[];
|
|
@@ -11,7 +11,7 @@ const toMccCategory = (payload) => ({
|
|
|
11
11
|
exports.toMccCategory = toMccCategory;
|
|
12
12
|
const toCardPolicyVendorSearchOption = (payload) => ({
|
|
13
13
|
vendorId: payload.vendor_id,
|
|
14
|
-
name: payload.
|
|
14
|
+
name: payload.vendor_name,
|
|
15
15
|
});
|
|
16
16
|
exports.toCardPolicyVendorSearchOption = toCardPolicyVendorSearchOption;
|
|
17
17
|
const toCardPolicyStats = (payload) => ({
|
|
@@ -4,6 +4,16 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
4
4
|
exports.clearCardPolicy = exports.clearPolicyDocumentExtraction = exports.updatePolicyDocumentExtractionFailure = exports.updatePolicyDocumentExtractionSuccess = exports.extractPolicyDocument = exports.updateCardPolicyStats = exports.removeCardPolicyTemplate = exports.updateCardPolicyTemplates = exports.updateCreatedCardPolicyTemplate = exports.updateCardPolicyVendorOptionsFailure = exports.updateCardPolicyVendorOptions = exports.updateCardPolicyMccCategoriesFailure = exports.updateCardPolicyMccCategories = exports.fetchCardPolicyVendorOptions = exports.fetchCardPolicyMccCategories = exports.initialState = void 0;
|
|
5
5
|
const toolkit_1 = require("@reduxjs/toolkit");
|
|
6
6
|
const cardPolicyPayload_1 = require("./cardPolicyPayload");
|
|
7
|
+
/**
|
|
8
|
+
* Defensive predicate for vendor / merchant names that flow into
|
|
9
|
+
* `buildVendorChipId(name)` (in `@zeniai/web-components`). That helper
|
|
10
|
+
* calls `name.trim().toLowerCase()`, so a null / undefined / whitespace-
|
|
11
|
+
* only value would throw at render time, and an empty string would
|
|
12
|
+
* collapse every nameless row into a single colliding `vendor-` chip-id.
|
|
13
|
+
* Used at the redux ingestion boundary for both the vendor-search results
|
|
14
|
+
* and the BE-suggested merchant seed arrays.
|
|
15
|
+
*/
|
|
16
|
+
const isUsableMerchantName = (name) => typeof name === 'string' && name.trim() !== '';
|
|
7
17
|
const initialPolicyDocumentExtractionState = {
|
|
8
18
|
fetchState: 'Not-Started',
|
|
9
19
|
error: undefined,
|
|
@@ -42,10 +52,12 @@ const cardPolicy = (0, toolkit_1.createSlice)({
|
|
|
42
52
|
// Persist BE-suggested allow / block seeds alongside the universe.
|
|
43
53
|
// Both flows (manual create page + AI CFO interactive form) read
|
|
44
54
|
// these to pre-populate the chip cloud body before the user edits.
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
55
|
+
// Drop empty / nullish merchant names defensively — they feed
|
|
56
|
+
// `buildVendorChipId(name)` (in @zeniai/web-components) which calls
|
|
57
|
+
// `.trim().toLowerCase()` and would crash the chip-picker render
|
|
58
|
+
// path if any entry slipped through as undefined / "".
|
|
59
|
+
draft.suggestedAllowMerchants = (action.payload.suggested_allow_merchants ?? []).filter(isUsableMerchantName);
|
|
60
|
+
draft.suggestedBlockMerchants = (action.payload.suggested_block_merchants ?? []).filter(isUsableMerchantName);
|
|
49
61
|
draft.suggestedAllowCategories = (action.payload.suggested_allow_catagories ?? []).map(cardPolicyPayload_1.toMccCategory);
|
|
50
62
|
draft.suggestedBlockCategories = (action.payload.suggested_block_catagories ?? []).map(cardPolicyPayload_1.toMccCategory);
|
|
51
63
|
draft.mccCategoriesFetchState = 'Completed';
|
|
@@ -167,7 +179,14 @@ const cardPolicy = (0, toolkit_1.createSlice)({
|
|
|
167
179
|
},
|
|
168
180
|
},
|
|
169
181
|
updateCardPolicyVendorOptions(draft, action) {
|
|
170
|
-
|
|
182
|
+
// Drop rows with no usable name. The chip-picker keys vendors by
|
|
183
|
+
// `buildVendorChipId(name)` (in @zeniai/web-components), which calls
|
|
184
|
+
// `name.trim().toLowerCase()`. A null / undefined / whitespace-only
|
|
185
|
+
// name would either throw at render time or collapse every nameless
|
|
186
|
+
// row into a single colliding `vendor-` chip-id.
|
|
187
|
+
draft.vendorSearch.vendors = (action.payload.vendors ?? [])
|
|
188
|
+
.map(cardPolicyPayload_1.toCardPolicyVendorSearchOption)
|
|
189
|
+
.filter((vendor) => isUsableMerchantName(vendor.name));
|
|
171
190
|
draft.vendorSearch.fetchState = 'Completed';
|
|
172
191
|
draft.vendorSearch.error = undefined;
|
|
173
192
|
},
|
|
@@ -10,7 +10,7 @@ export declare const ALL_SCHEDULES_TYPES: readonly ["prepaid_expenses", "fixed_a
|
|
|
10
10
|
export declare const toScheduleTypesType: (v: string) => "prepaid_expenses" | "fixed_assets" | "accrued_expenses" | "deferred_revenue";
|
|
11
11
|
export type ScheduleTypes = ReturnType<typeof toScheduleTypesType>;
|
|
12
12
|
export declare const toScheduleTypesTypeStrict: (v?: string) => "prepaid_expenses" | "fixed_assets" | "accrued_expenses" | "deferred_revenue" | undefined;
|
|
13
|
-
export declare const toScheduleJournalEntryStatusCodeType: (v: string) => "pending" | "
|
|
13
|
+
export declare const toScheduleJournalEntryStatusCodeType: (v: string) => "pending" | "unknown" | "posted" | "canceled" | "recorded";
|
|
14
14
|
export type ScheduleJournalEntryStatusCodeType = ReturnType<typeof toScheduleJournalEntryStatusCodeType>;
|
|
15
15
|
export declare const toScheduleStatusCodeType: (v: string) => "completed" | "draft" | "new" | "ongoing" | "marked_as_completed";
|
|
16
16
|
export type ScheduleStatusCodeType = ReturnType<typeof toScheduleStatusCodeType>;
|
|
@@ -3,7 +3,7 @@ import { MonthYearPeriod, MonthYearPeriodId } from '../../commonStateTypes/timeP
|
|
|
3
3
|
import { ExpenseAutomationViewType } from '../../view/expenseAutomationView/expenseAutomationViewState';
|
|
4
4
|
import { ZeniDate } from '../../zeniDayJS';
|
|
5
5
|
export declare const ALL_MONTH_END_CLOSE_CHECKS_FREQUENCY: readonly ["Weekly", "Monthly"];
|
|
6
|
-
export declare const toMonthEndCloseCheckFrequency: (v?: string) => "
|
|
6
|
+
export declare const toMonthEndCloseCheckFrequency: (v?: string) => "Monthly" | "Weekly";
|
|
7
7
|
export type MonthEndCloseCheckFrequency = NonNullable<ReturnType<typeof toMonthEndCloseCheckFrequency>>;
|
|
8
8
|
export interface MonthCloseCheckMetrics {
|
|
9
9
|
columnIndex: number;
|
|
@@ -175,19 +175,94 @@ const toCardsCreationInitialData = (payload) => {
|
|
|
175
175
|
})),
|
|
176
176
|
};
|
|
177
177
|
}
|
|
178
|
+
// Preferred wire format: a flat `suggested_cards` array with an
|
|
179
|
+
// `is_suggested` discriminator. The adapter splits it into seed rows,
|
|
180
|
+
// owner map, and the full dropdown universe.
|
|
181
|
+
if (payload.suggested_cards != null) {
|
|
182
|
+
return fromSuggestedCards(payload.suggested_cards, cardOptions);
|
|
183
|
+
}
|
|
184
|
+
// Legacy / test shape: backend already pre-shapes seeds. Synthesize an
|
|
185
|
+
// empty `cardNameOptions` (step 2 dropdown still works via row-self ids).
|
|
186
|
+
const teamRows = (payload.team_rows ?? []).map((row) => ({
|
|
187
|
+
avgMonthlySpend: row.avg_monthly_spend,
|
|
188
|
+
cardKind: (row.card_kind ?? 'vendor'),
|
|
189
|
+
id: row.id,
|
|
190
|
+
label: row.label,
|
|
191
|
+
recommendedLimit: row.recommended_limit,
|
|
192
|
+
recommendedLimitCadence: row.recommended_limit_cadence ?? undefined,
|
|
193
|
+
}));
|
|
178
194
|
return {
|
|
179
195
|
mode: 'team-then-cards',
|
|
180
196
|
cardOptions,
|
|
181
|
-
|
|
182
|
-
teamRows: (payload.team_rows ?? []).map((row) => ({
|
|
183
|
-
avgMonthlySpend: row.avg_monthly_spend,
|
|
197
|
+
cardNameOptions: teamRows.map((row) => ({
|
|
184
198
|
id: row.id,
|
|
199
|
+
kind: row.cardKind,
|
|
185
200
|
label: row.label,
|
|
186
|
-
recommendedLimit: row.recommended_limit,
|
|
187
|
-
recommendedLimitCadence: row.recommended_limit_cadence ?? undefined,
|
|
188
201
|
})),
|
|
202
|
+
suggestedOwnerUserIdByTeamId: Object.fromEntries(Object.entries(payload.suggested_owner_user_id_by_team_id ?? {}).map(([teamId, userId]) => [teamId, userId ?? undefined])),
|
|
203
|
+
teamRows,
|
|
189
204
|
};
|
|
190
205
|
};
|
|
206
|
+
const CURRENCY_FORMATTER = new Intl.NumberFormat('en-US', {
|
|
207
|
+
style: 'currency',
|
|
208
|
+
currency: 'USD',
|
|
209
|
+
maximumFractionDigits: 0,
|
|
210
|
+
});
|
|
211
|
+
const fromSuggestedCards = (suggestedCards, cardOptions) => {
|
|
212
|
+
const ordered = [...suggestedCards].sort((a, b) => {
|
|
213
|
+
if (a.card_type === b.card_type) {
|
|
214
|
+
return 0;
|
|
215
|
+
}
|
|
216
|
+
return a.card_type === 'vendor' ? -1 : 1;
|
|
217
|
+
});
|
|
218
|
+
const withUniqueIds = withSynthesizedIds(ordered);
|
|
219
|
+
const teamRows = withUniqueIds
|
|
220
|
+
.filter(({ card }) => card.is_suggested)
|
|
221
|
+
.map(({ card, uniqueId }) => ({
|
|
222
|
+
avgMonthlySpend: CURRENCY_FORMATTER.format(card.avg_spend),
|
|
223
|
+
cardKind: card.card_type === 'department' ? 'class' : 'vendor',
|
|
224
|
+
id: uniqueId,
|
|
225
|
+
label: card.card_name,
|
|
226
|
+
recommendedLimit: CURRENCY_FORMATTER.format(card.credit_limit),
|
|
227
|
+
recommendedLimitCadence: 'Monthly',
|
|
228
|
+
}));
|
|
229
|
+
const suggestedOwnerUserIdByTeamId = Object.fromEntries(withUniqueIds
|
|
230
|
+
.filter(({ card }) => card.is_suggested)
|
|
231
|
+
.map(({ card, uniqueId }) => [uniqueId, card.owner_id]));
|
|
232
|
+
const cardNameOptions = withUniqueIds.map(({ card, uniqueId }) => ({
|
|
233
|
+
id: uniqueId,
|
|
234
|
+
kind: card.card_type === 'department' ? 'class' : 'vendor',
|
|
235
|
+
label: card.card_name,
|
|
236
|
+
}));
|
|
237
|
+
return {
|
|
238
|
+
mode: 'team-then-cards',
|
|
239
|
+
cardOptions,
|
|
240
|
+
cardNameOptions,
|
|
241
|
+
suggestedOwnerUserIdByTeamId,
|
|
242
|
+
teamRows,
|
|
243
|
+
};
|
|
244
|
+
};
|
|
245
|
+
/**
|
|
246
|
+
* Stamp each suggested card with a stable unique id derived from its
|
|
247
|
+
* `card_name_id`. If two cards in the same payload share the same
|
|
248
|
+
* `card_name_id` (which happens in the current sample payload where
|
|
249
|
+
* `card_name_id` is the literal `"vendor_uuid"`), fall back to a
|
|
250
|
+
* synthesized id `${kind}__${card_name_id}__${index}` so RHF row keying
|
|
251
|
+
* stays unique.
|
|
252
|
+
*/
|
|
253
|
+
const withSynthesizedIds = (cards) => {
|
|
254
|
+
const seen = new Set();
|
|
255
|
+
return cards.map((card, index) => {
|
|
256
|
+
const preferred = card.card_name_id;
|
|
257
|
+
if (preferred != null && preferred !== '' && !seen.has(preferred)) {
|
|
258
|
+
seen.add(preferred);
|
|
259
|
+
return { card, uniqueId: preferred };
|
|
260
|
+
}
|
|
261
|
+
const synthesized = `${card.card_type}__${preferred ?? 'unknown'}__${index}`;
|
|
262
|
+
seen.add(synthesized);
|
|
263
|
+
return { card, uniqueId: synthesized };
|
|
264
|
+
});
|
|
265
|
+
};
|
|
191
266
|
const toCardPolicyInitialData = (payload) => {
|
|
192
267
|
const suggestedPolicies = (payload.suggested_policies ?? []).map((policy) => ({
|
|
193
268
|
id: policy.id,
|
|
@@ -7,7 +7,7 @@ export const toMccCategory = (payload) => ({
|
|
|
7
7
|
});
|
|
8
8
|
export const toCardPolicyVendorSearchOption = (payload) => ({
|
|
9
9
|
vendorId: payload.vendor_id,
|
|
10
|
-
name: payload.
|
|
10
|
+
name: payload.vendor_name,
|
|
11
11
|
});
|
|
12
12
|
export const toCardPolicyStats = (payload) => ({
|
|
13
13
|
activePolicies: payload.active_policies,
|
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
import { createSlice } from '@reduxjs/toolkit';
|
|
2
2
|
import { toCardPolicyTemplate, toCardPolicyVendorSearchOption, toExtractedCardPolicyRules, toMccCategory, } from './cardPolicyPayload';
|
|
3
|
+
/**
|
|
4
|
+
* Defensive predicate for vendor / merchant names that flow into
|
|
5
|
+
* `buildVendorChipId(name)` (in `@zeniai/web-components`). That helper
|
|
6
|
+
* calls `name.trim().toLowerCase()`, so a null / undefined / whitespace-
|
|
7
|
+
* only value would throw at render time, and an empty string would
|
|
8
|
+
* collapse every nameless row into a single colliding `vendor-` chip-id.
|
|
9
|
+
* Used at the redux ingestion boundary for both the vendor-search results
|
|
10
|
+
* and the BE-suggested merchant seed arrays.
|
|
11
|
+
*/
|
|
12
|
+
const isUsableMerchantName = (name) => typeof name === 'string' && name.trim() !== '';
|
|
3
13
|
const initialPolicyDocumentExtractionState = {
|
|
4
14
|
fetchState: 'Not-Started',
|
|
5
15
|
error: undefined,
|
|
@@ -38,10 +48,12 @@ const cardPolicy = createSlice({
|
|
|
38
48
|
// Persist BE-suggested allow / block seeds alongside the universe.
|
|
39
49
|
// Both flows (manual create page + AI CFO interactive form) read
|
|
40
50
|
// these to pre-populate the chip cloud body before the user edits.
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
51
|
+
// Drop empty / nullish merchant names defensively — they feed
|
|
52
|
+
// `buildVendorChipId(name)` (in @zeniai/web-components) which calls
|
|
53
|
+
// `.trim().toLowerCase()` and would crash the chip-picker render
|
|
54
|
+
// path if any entry slipped through as undefined / "".
|
|
55
|
+
draft.suggestedAllowMerchants = (action.payload.suggested_allow_merchants ?? []).filter(isUsableMerchantName);
|
|
56
|
+
draft.suggestedBlockMerchants = (action.payload.suggested_block_merchants ?? []).filter(isUsableMerchantName);
|
|
45
57
|
draft.suggestedAllowCategories = (action.payload.suggested_allow_catagories ?? []).map(toMccCategory);
|
|
46
58
|
draft.suggestedBlockCategories = (action.payload.suggested_block_catagories ?? []).map(toMccCategory);
|
|
47
59
|
draft.mccCategoriesFetchState = 'Completed';
|
|
@@ -163,7 +175,14 @@ const cardPolicy = createSlice({
|
|
|
163
175
|
},
|
|
164
176
|
},
|
|
165
177
|
updateCardPolicyVendorOptions(draft, action) {
|
|
166
|
-
|
|
178
|
+
// Drop rows with no usable name. The chip-picker keys vendors by
|
|
179
|
+
// `buildVendorChipId(name)` (in @zeniai/web-components), which calls
|
|
180
|
+
// `name.trim().toLowerCase()`. A null / undefined / whitespace-only
|
|
181
|
+
// name would either throw at render time or collapse every nameless
|
|
182
|
+
// row into a single colliding `vendor-` chip-id.
|
|
183
|
+
draft.vendorSearch.vendors = (action.payload.vendors ?? [])
|
|
184
|
+
.map(toCardPolicyVendorSearchOption)
|
|
185
|
+
.filter((vendor) => isUsableMerchantName(vendor.name));
|
|
167
186
|
draft.vendorSearch.fetchState = 'Completed';
|
|
168
187
|
draft.vendorSearch.error = undefined;
|
|
169
188
|
},
|
|
@@ -2,13 +2,23 @@ import { of } from 'rxjs';
|
|
|
2
2
|
import { catchError, filter, mergeMap } from 'rxjs/operators';
|
|
3
3
|
import { createZeniAPIStatus, isSuccessResponse } from '../../../responsePayload';
|
|
4
4
|
import { fetchSuggestedQuestions, fetchSuggestedQuestionsFailure, fetchSuggestedQuestionsSuccess, } from '../aiCfoViewReducer';
|
|
5
|
-
/**
|
|
5
|
+
/**
|
|
6
|
+
* GET {aiCfoMicroServiceBaseUrl}/1.0/suggested-questions?page_context=...
|
|
7
|
+
*
|
|
8
|
+
* Appends `&no_card_created=true` when the action payload sets
|
|
9
|
+
* `noCardCreated: true` (AI Card Creation flow on the cards list — the tenant
|
|
10
|
+
* has not yet created any card). Any other value omits the flag entirely so
|
|
11
|
+
* the existing call sites continue to issue the unchanged request.
|
|
12
|
+
*/
|
|
6
13
|
export const fetchSuggestedQuestionsEpic = (actions$, _state$, zeniAPI) => actions$.pipe(filter(fetchSuggestedQuestions.match),
|
|
7
14
|
// mergeMap (not switchMap): each page_context is keyed separately in Redux; switchMap
|
|
8
15
|
// would cancel in-flight HTTP for context A when B is requested, leaving A stuck In-Progress.
|
|
9
16
|
mergeMap((action) => {
|
|
10
|
-
const { pageContext } = action.payload;
|
|
17
|
+
const { pageContext, noCardCreated } = action.payload;
|
|
11
18
|
const query = new URLSearchParams({ page_context: pageContext });
|
|
19
|
+
if (noCardCreated === true) {
|
|
20
|
+
query.set('no_card_created', 'true');
|
|
21
|
+
}
|
|
12
22
|
const url = `${zeniAPI.apiEndPoints.aiCfoMicroServiceBaseUrl}/1.0/suggested-questions?${query.toString()}`;
|
|
13
23
|
return zeniAPI.getJSON(url).pipe(mergeMap((response) => {
|
|
14
24
|
if (isSuccessResponse(response) && response.data != null) {
|
package/lib/index.d.ts
CHANGED
|
@@ -906,7 +906,7 @@ export { AiCfoViewSelector, getAiCfoView, getSuggestedQuestionsForPageContext, }
|
|
|
906
906
|
export { MessagePayload, ChatSessionPayload, AiCfoAnswerPayload, } from './entity/aiCfo/aiCfoPayload';
|
|
907
907
|
export { setNewSession, setSessions, upsertAnswerPayload, upsertOrAddQuestionAnswerPayload, addQuestionPayload, clearSession, clearAiCfo, toAiCfoVisualization, } from './entity/aiCfo/aiCfoReducer';
|
|
908
908
|
export { AiCfoSelectorView, getAllQuestionAnswersForChatSession, getQuestionAnswerByIdForChatSession, getAllQuestionsForChatSession, getAiCfoSelectorView, ChatSessionWithOrderedQuestionAnswers, } from './entity/aiCfo/aiCfoSelector';
|
|
909
|
-
export { AiCfoQuestionWithAnswer, AiCfoAnswerParagraph, AiCfoAnswerStateType, AiCfoChartType, AiCfoAnswerResponseType, TableVisualization, ChartVisualization, CardsCardOption, CardsCreationInitialData, CardPolicyCardRowSeed, CardPolicyInitialData, CardPolicyLimitRowSeed, CardPolicyOwnerSeed, CardPolicySuggestedPolicy, CardPolicySuggestedPolicyChip, CardPolicySuggestedPolicyChipGroup, CardPolicyTagSeed, InteractiveFormType, InteractiveFormVisualization, AiCfoVisualization, AiCfoVisualizationType, AiCfoState, ChatSession, ALL_AI_CFO_CHARTS_TYPES, ALL_AI_CFO_VISUALIZATION_TYPES, ALL_AI_CFO_ANSWER_STATE_TYPES, ALL_AI_CFO_ANSWER_RESPONSE_TYPES, ALL_INTERACTIVE_FORM_TYPES, toAiCfoVisualizationType, toAiCfoVisualizationTypeStrict, toAiCfoChartType, toAiCfoChartTypeStrict, toAiCfoAnswerStateType, toAiCfoAnswerStateTypeStrict, toAiCfoAnswerResponseType, toAiCfoAnswerResponseTypeStrict, toInteractiveFormType, toInteractiveFormTypeStrict, ChatSessionWithMessages, ResponseBlockBase, AnswerContentBlockBase, FileAttachmentMetadata, QuestionContentBlockBase, ResponseBlockType, toMessageSender, toMessageType, MessageSender, MessageType, } from './entity/aiCfo/aiCfoState';
|
|
909
|
+
export { AiCfoQuestionWithAnswer, AiCfoAnswerParagraph, AiCfoAnswerStateType, AiCfoChartType, AiCfoAnswerResponseType, TableVisualization, ChartVisualization, CardNameOption, CardsCardKind, CardsCardOption, CardsCreationInitialData, CardPolicyCardRowSeed, CardPolicyInitialData, CardPolicyLimitRowSeed, CardPolicyOwnerSeed, CardPolicySuggestedPolicy, CardPolicySuggestedPolicyChip, CardPolicySuggestedPolicyChipGroup, CardPolicyTagSeed, InteractiveFormType, InteractiveFormVisualization, AiCfoVisualization, AiCfoVisualizationType, AiCfoState, ChatSession, ALL_AI_CFO_CHARTS_TYPES, ALL_AI_CFO_VISUALIZATION_TYPES, ALL_AI_CFO_ANSWER_STATE_TYPES, ALL_AI_CFO_ANSWER_RESPONSE_TYPES, ALL_INTERACTIVE_FORM_TYPES, toAiCfoVisualizationType, toAiCfoVisualizationTypeStrict, toAiCfoChartType, toAiCfoChartTypeStrict, toAiCfoAnswerStateType, toAiCfoAnswerStateTypeStrict, toAiCfoAnswerResponseType, toAiCfoAnswerResponseTypeStrict, toInteractiveFormType, toInteractiveFormTypeStrict, ChatSessionWithMessages, ResponseBlockBase, AnswerContentBlockBase, FileAttachmentMetadata, QuestionContentBlockBase, ResponseBlockType, toMessageSender, toMessageType, MessageSender, MessageType, } from './entity/aiCfo/aiCfoState';
|
|
910
910
|
export { clearPolicyDocumentExtraction, extractPolicyDocument, fetchCardPolicyMccCategories, fetchCardPolicyVendorOptions, removeCardPolicyTemplate, updateCardPolicyMccCategories, updateCardPolicyMccCategoriesFailure, updateCardPolicyStats, updateCardPolicyTemplates, updateCardPolicyVendorOptions, updateCardPolicyVendorOptionsFailure, updateCreatedCardPolicyTemplate, updatePolicyDocumentExtractionFailure, updatePolicyDocumentExtractionSuccess, clearCardPolicy, } from './entity/cardPolicy/cardPolicyReducer';
|
|
911
911
|
export { getAllCardPolicyTemplates, getCardPolicyMccCategories, getCardPolicyMccCategoriesError, getCardPolicyMccCategoriesFetchState, getCardPolicyStats, getCardPolicySuggestedAllowCategories, getCardPolicySuggestedAllowMerchants, getCardPolicySuggestedBlockCategories, getCardPolicySuggestedBlockMerchants, getCardPolicyTemplateById, getCardPolicyTemplatesByIds, getCardPolicyVendorSearchFetchState, getCardPolicyVendorSearchOptions, getCardPolicyVendorSearchString, getExtractedCardPolicyRules, getPolicyDocumentExtractionError, getPolicyDocumentExtractionFetchState, getUploadedPolicyDocumentFileName, } from './entity/cardPolicy/cardPolicySelector';
|
|
912
912
|
export { ALL_CARD_POLICY_TEMPLATE_MODES, ALL_CARD_POLICY_TEMPLATE_STATUSES, CardPolicyState, CardPolicyStats, CardPolicyTemplate, CardPolicyTemplateEntityList, CardPolicyTemplateMode, CardPolicyTemplateSpendLimits, CardPolicyTemplateStatus, CardPolicyVendorSearchEntry, CardPolicyVendorSearchState, ExtractedCardPolicyRules, MccCategory, PolicyDocumentExtractionState, toCardPolicyTemplateMode, toCardPolicyTemplateStatus, } from './entity/cardPolicy/cardPolicyState';
|
|
@@ -92,6 +92,13 @@ export declare const submitQuestion: import("@reduxjs/toolkit").ActionCreatorWit
|
|
|
92
92
|
questionAnswerId: ID;
|
|
93
93
|
}, "aiCfoView/updateCotCollapsedState">, fetchSuggestedQuestions: import("@reduxjs/toolkit").ActionCreatorWithPayload<{
|
|
94
94
|
pageContext: AiCfoSuggestedQuestionsPageContext;
|
|
95
|
+
/**
|
|
96
|
+
* AI Card Creation flow: when true, the epic appends `&no_card_created=true`
|
|
97
|
+
* so the backend tailors prompts for a tenant that has not yet created a
|
|
98
|
+
* card. The bucket key is unchanged (`pageContext`); see
|
|
99
|
+
* `useFetchSuggestedQuestionsWhenReady` for the refetch-on-flag-flip rule.
|
|
100
|
+
*/
|
|
101
|
+
noCardCreated?: boolean;
|
|
95
102
|
}, "aiCfoView/fetchSuggestedQuestions">, fetchSuggestedQuestionsSuccess: import("@reduxjs/toolkit").ActionCreatorWithPayload<{
|
|
96
103
|
generatedAt: string;
|
|
97
104
|
pageContext: AiCfoSuggestedQuestionsPageContext;
|
|
@@ -4,5 +4,12 @@ import { RootState } from '../../../reducer';
|
|
|
4
4
|
import { ZeniAPI } from '../../../zeniAPI';
|
|
5
5
|
import { fetchSuggestedQuestions, fetchSuggestedQuestionsFailure, fetchSuggestedQuestionsSuccess } from '../aiCfoViewReducer';
|
|
6
6
|
export type ActionType = ReturnType<typeof fetchSuggestedQuestions> | ReturnType<typeof fetchSuggestedQuestionsSuccess> | ReturnType<typeof fetchSuggestedQuestionsFailure>;
|
|
7
|
-
/**
|
|
7
|
+
/**
|
|
8
|
+
* GET {aiCfoMicroServiceBaseUrl}/1.0/suggested-questions?page_context=...
|
|
9
|
+
*
|
|
10
|
+
* Appends `&no_card_created=true` when the action payload sets
|
|
11
|
+
* `noCardCreated: true` (AI Card Creation flow on the cards list — the tenant
|
|
12
|
+
* has not yet created any card). Any other value omits the flag entirely so
|
|
13
|
+
* the existing call sites continue to issue the unchanged request.
|
|
14
|
+
*/
|
|
8
15
|
export declare const fetchSuggestedQuestionsEpic: (actions$: ActionsObservable<ActionType>, _state$: StateObservable<RootState>, zeniAPI: ZeniAPI) => Observable<ActionType>;
|
|
@@ -5,13 +5,23 @@ const rxjs_1 = require("rxjs");
|
|
|
5
5
|
const operators_1 = require("rxjs/operators");
|
|
6
6
|
const responsePayload_1 = require("../../../responsePayload");
|
|
7
7
|
const aiCfoViewReducer_1 = require("../aiCfoViewReducer");
|
|
8
|
-
/**
|
|
8
|
+
/**
|
|
9
|
+
* GET {aiCfoMicroServiceBaseUrl}/1.0/suggested-questions?page_context=...
|
|
10
|
+
*
|
|
11
|
+
* Appends `&no_card_created=true` when the action payload sets
|
|
12
|
+
* `noCardCreated: true` (AI Card Creation flow on the cards list — the tenant
|
|
13
|
+
* has not yet created any card). Any other value omits the flag entirely so
|
|
14
|
+
* the existing call sites continue to issue the unchanged request.
|
|
15
|
+
*/
|
|
9
16
|
const fetchSuggestedQuestionsEpic = (actions$, _state$, zeniAPI) => actions$.pipe((0, operators_1.filter)(aiCfoViewReducer_1.fetchSuggestedQuestions.match),
|
|
10
17
|
// mergeMap (not switchMap): each page_context is keyed separately in Redux; switchMap
|
|
11
18
|
// would cancel in-flight HTTP for context A when B is requested, leaving A stuck In-Progress.
|
|
12
19
|
(0, operators_1.mergeMap)((action) => {
|
|
13
|
-
const { pageContext } = action.payload;
|
|
20
|
+
const { pageContext, noCardCreated } = action.payload;
|
|
14
21
|
const query = new URLSearchParams({ page_context: pageContext });
|
|
22
|
+
if (noCardCreated === true) {
|
|
23
|
+
query.set('no_card_created', 'true');
|
|
24
|
+
}
|
|
15
25
|
const url = `${zeniAPI.apiEndPoints.aiCfoMicroServiceBaseUrl}/1.0/suggested-questions?${query.toString()}`;
|
|
16
26
|
return zeniAPI.getJSON(url).pipe((0, operators_1.mergeMap)((response) => {
|
|
17
27
|
if ((0, responsePayload_1.isSuccessResponse)(response) && response.data != null) {
|
|
@@ -6,7 +6,7 @@ import { MonthYearPeriodId } from '../../../commonStateTypes/timePeriod';
|
|
|
6
6
|
import { AccountBase } from '../../../entity/account/accountState';
|
|
7
7
|
import { JEScheduleTransactionKey, ScheduleTypes } from '../../../entity/jeSchedules/jeSchedulesTypes';
|
|
8
8
|
import { VendorBase } from '../../../entity/vendor/vendorState';
|
|
9
|
-
export declare const toJEScheduleSortKey: (v: string) => "vendor" | "type" | "
|
|
9
|
+
export declare const toJEScheduleSortKey: (v: string) => "vendor" | "type" | "class" | "category" | "memo" | "transactionDate" | "totalAmount" | "runningBalance" | "depCategory" | "scheduleCategory" | "startMonth" | "amortizationPeriod" | "jePostingDate" | "remainingMonths";
|
|
10
10
|
export type JEScheduleSortKey = ReturnType<typeof toJEScheduleSortKey>;
|
|
11
11
|
export declare const toJEScheduleMainTab: (v: string) => "completed" | "pending_review" | "ongoing";
|
|
12
12
|
export type JEScheduleMainTab = ReturnType<typeof toJEScheduleMainTab>;
|
|
@@ -2,7 +2,7 @@ import { FetchStateAndError, FetchedState, ID } from '../../../commonStateTypes/
|
|
|
2
2
|
import { SortOrder } from '../../../commonStateTypes/selectorTypes/sortOrderTypes';
|
|
3
3
|
import { MonthYearPeriodId } from '../../../commonStateTypes/timePeriod';
|
|
4
4
|
import { CompletedSubTab } from './completedSubTab';
|
|
5
|
-
export declare const toMissingReceiptsSortKey: (v: string) => "date" | "amount" | "vendor" | "
|
|
5
|
+
export declare const toMissingReceiptsSortKey: (v: string) => "date" | "amount" | "vendor" | "class" | "category";
|
|
6
6
|
export type MissingReceiptsSortKey = ReturnType<typeof toMissingReceiptsSortKey>;
|
|
7
7
|
export interface MissingReceiptsViewUIState {
|
|
8
8
|
scrollPosition: {
|
|
@@ -34,7 +34,7 @@ export declare const toMissingReceiptsTab: (v: string) => "completed" | "unmatch
|
|
|
34
34
|
export type MissingReceiptsTab = ReturnType<typeof toMissingReceiptsTab>;
|
|
35
35
|
export declare const toMatchSource: (v: string) => "manual" | "ai";
|
|
36
36
|
export type MatchSource = ReturnType<typeof toMatchSource>;
|
|
37
|
-
export declare const toBulkUploadSortKey: (v: string) => "date" | "amount" | "vendor" | "
|
|
37
|
+
export declare const toBulkUploadSortKey: (v: string) => "date" | "amount" | "vendor" | "class" | "category";
|
|
38
38
|
export type BulkUploadSortKey = ReturnType<typeof toBulkUploadSortKey>;
|
|
39
39
|
export interface CandidateRef {
|
|
40
40
|
matchScore: number;
|
|
@@ -18,7 +18,7 @@ import { ZeniDate } from '../../../zeniDayJS';
|
|
|
18
18
|
import { EntityRecommendationKey } from '../../recommendation/recommendationState';
|
|
19
19
|
import { TransactionDetailKey } from '../../transactionDetail/transactionDetailState';
|
|
20
20
|
import { CompletedSubTab } from './completedSubTab';
|
|
21
|
-
export declare const toTransactionsSortKey: (v: string) => "date" | "amount" | "vendor" | "project" | "
|
|
21
|
+
export declare const toTransactionsSortKey: (v: string) => "date" | "amount" | "vendor" | "project" | "class" | "category" | "payment_account" | "transaction_type" | "memo_and_receipt";
|
|
22
22
|
export type TransactionsSortKey = ReturnType<typeof toTransactionsSortKey>;
|
|
23
23
|
export declare const TRANSACTIONS_TABS: readonly ["review", "autoCategorized"];
|
|
24
24
|
export declare const toTransactionsTabKey: (v: string) => "review" | "autoCategorized";
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
declare const toPeopleSortKeyType: (v: string) => "
|
|
1
|
+
declare const toPeopleSortKeyType: (v: string) => "department" | "name" | "role" | "manager" | "lastSeen";
|
|
2
2
|
export type PeopleViewSortKey = ReturnType<typeof toPeopleSortKeyType>;
|
|
3
3
|
export {};
|
|
@@ -7,7 +7,7 @@ export declare const getScheduleListKey: (selectedCategory: ID, selectedTimefram
|
|
|
7
7
|
export type ScheduleListKey = ReturnType<typeof getScheduleListKey>;
|
|
8
8
|
export declare const toScheduleSubTabType: (v: string) => "completed" | "new" | "ongoing" | "all";
|
|
9
9
|
export type ScheduleSubTabType = ReturnType<typeof toScheduleSubTabType>;
|
|
10
|
-
declare const toScheduleSortKeyType: (v: string) => "months" | "amount" | "vendor" | "status" | "
|
|
10
|
+
declare const toScheduleSortKeyType: (v: string) => "months" | "amount" | "vendor" | "status" | "class" | "user" | "createTime" | "memo" | "balanceAsOfToday" | "transactionDate" | "transactionType" | "assetId" | "scheduleCategory" | "startMonth" | "accruedExpenseCategory" | "expenseCategory" | "accumulatedDepreciationCategory" | "endMonth";
|
|
11
11
|
export declare type ScheduleListSortKey = ReturnType<typeof toScheduleSortKeyType>;
|
|
12
12
|
export interface DownloadJEScheduleTabOptions {
|
|
13
13
|
categoryId: ID;
|
|
@@ -61,7 +61,7 @@ export declare const initialCreditAcc: CreditAccount;
|
|
|
61
61
|
export declare const initialDebitCardSummaries: DebitCardSummaries;
|
|
62
62
|
export declare const initialResendRevokeCardInvite: ResendRevokeCardInvite;
|
|
63
63
|
export declare const initialCreditAccountRepayment: CreditAccountRepayment;
|
|
64
|
-
export declare const toChargeCardSortKeyType: (v: string) => "status" | "
|
|
64
|
+
export declare const toChargeCardSortKeyType: (v: string) => "status" | "department" | "cardName" | "owner" | "accountType" | "limit" | "cardType" | "utilisation";
|
|
65
65
|
export declare type ChargeCardViewSortKey = ReturnType<typeof toChargeCardSortKeyType>;
|
|
66
66
|
export declare const ALL_CASHBACK_SORT_KEYS: readonly ["month", "cashback"];
|
|
67
67
|
export declare const toCashbackSortKeyType: (v: string) => "month" | "cashback";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zeniai/client-epic-state",
|
|
3
|
-
"version": "5.0.65-
|
|
3
|
+
"version": "5.0.65-betaRR3",
|
|
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",
|