@zeniai/client-epic-state 5.0.65-betaRR6 → 5.0.65
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 +1 -168
- package/lib/entity/aiCfo/aiCfoReducer.js +2 -186
- package/lib/entity/aiCfo/aiCfoState.d.ts +4 -164
- package/lib/entity/aiCfo/aiCfoState.js +1 -10
- package/lib/entity/jeSchedules/jeSchedulesTypes.d.ts +1 -1
- package/lib/entity/monthEndCloseChecks/monthEndCloseChecksState.d.ts +1 -1
- package/lib/entity/snackbar/snackbarTypes.d.ts +1 -1
- package/lib/entity/snackbar/snackbarTypes.js +0 -2
- package/lib/entity/tenant/clearAllEpic.d.ts +2 -6
- package/lib/entity/tenant/clearAllEpic.js +0 -8
- package/lib/epic.d.ts +1 -9
- package/lib/epic.js +1 -9
- package/lib/esm/entity/aiCfo/aiCfoReducer.js +3 -187
- package/lib/esm/entity/aiCfo/aiCfoState.js +0 -7
- package/lib/esm/entity/snackbar/snackbarTypes.js +0 -2
- package/lib/esm/entity/tenant/clearAllEpic.js +0 -8
- package/lib/esm/epic.js +1 -9
- package/lib/esm/index.js +3 -17
- package/lib/esm/reducer.js +0 -12
- package/lib/esm/view/aiCfoView/epics/fetchSuggestedQuestionsEpic.js +2 -12
- package/lib/esm/view/spendManagement/chargeCards/chargeCardList/chargeCardListSelector.js +0 -25
- package/lib/index.d.ts +3 -16
- package/lib/index.js +11 -99
- package/lib/reducer.d.ts +0 -12
- package/lib/reducer.js +0 -12
- package/lib/tsconfig.typecheck.tsbuildinfo +1 -0
- package/lib/view/aiCfoView/aiCfoViewReducer.d.ts +0 -7
- package/lib/view/aiCfoView/epics/fetchSuggestedQuestionsEpic.d.ts +1 -8
- package/lib/view/aiCfoView/epics/fetchSuggestedQuestionsEpic.js +2 -12
- package/lib/view/companyHealthMetricView/companyHealthMetricViewSelector.d.ts +1 -1
- package/lib/view/expenseAutomationView/helpers/transactionCategorizationLocalDataHelper.d.ts +1 -1
- 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/onboardingView/cockpitView/types/onboardingCockpitViewTypes.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/lib/view/spendManagement/chargeCards/chargeCardList/chargeCardListSelector.d.ts +0 -14
- package/lib/view/spendManagement/chargeCards/chargeCardList/chargeCardListSelector.js +1 -27
- package/lib/view/taskManager/taskListView/taskListReducer.d.ts +1 -1
- package/package.json +1 -1
- package/lib/entity/cardPolicy/cardPolicyPayload.d.ts +0 -176
- package/lib/entity/cardPolicy/cardPolicyPayload.js +0 -112
- package/lib/entity/cardPolicy/cardPolicyReducer.d.ts +0 -13
- package/lib/entity/cardPolicy/cardPolicyReducer.js +0 -203
- package/lib/entity/cardPolicy/cardPolicySelector.d.ts +0 -28
- package/lib/entity/cardPolicy/cardPolicySelector.js +0 -86
- package/lib/entity/cardPolicy/cardPolicyState.d.ts +0 -172
- package/lib/entity/cardPolicy/cardPolicyState.js +0 -14
- package/lib/entity/cardPolicy/extractPolicyDocumentEpic.d.ts +0 -18
- package/lib/entity/cardPolicy/extractPolicyDocumentEpic.js +0 -54
- package/lib/entity/cardPolicy/fetchCardPolicyVendorOptionsEpic.d.ts +0 -26
- package/lib/entity/cardPolicy/fetchCardPolicyVendorOptionsEpic.js +0 -47
- package/lib/esm/entity/cardPolicy/cardPolicyPayload.js +0 -101
- package/lib/esm/entity/cardPolicy/cardPolicyReducer.js +0 -199
- package/lib/esm/entity/cardPolicy/cardPolicySelector.js +0 -66
- package/lib/esm/entity/cardPolicy/cardPolicyState.js +0 -9
- package/lib/esm/entity/cardPolicy/extractPolicyDocumentEpic.js +0 -50
- package/lib/esm/entity/cardPolicy/fetchCardPolicyVendorOptionsEpic.js +0 -43
- package/lib/esm/view/spendManagement/chargeCards/cardPolicy/cardPolicyDetail/cardPolicyDetailReducer.js +0 -70
- package/lib/esm/view/spendManagement/chargeCards/cardPolicy/cardPolicyDetail/cardPolicyDetailSelector.js +0 -22
- package/lib/esm/view/spendManagement/chargeCards/cardPolicy/cardPolicyDetail/cardPolicyDetailState.js +0 -1
- package/lib/esm/view/spendManagement/chargeCards/cardPolicy/cardPolicyDetail/fetchCardPolicyDetailEpic.js +0 -56
- package/lib/esm/view/spendManagement/chargeCards/cardPolicy/cardPolicyDetail/updateCardPolicyEpic.js +0 -49
- package/lib/esm/view/spendManagement/chargeCards/cardPolicy/cardPolicyList/archiveCardPolicyEpic.js +0 -42
- package/lib/esm/view/spendManagement/chargeCards/cardPolicy/cardPolicyList/cardPolicyListReducer.js +0 -72
- package/lib/esm/view/spendManagement/chargeCards/cardPolicy/cardPolicyList/cardPolicyListSelector.js +0 -21
- package/lib/esm/view/spendManagement/chargeCards/cardPolicy/cardPolicyList/cardPolicyListState.js +0 -1
- package/lib/esm/view/spendManagement/chargeCards/cardPolicy/cardPolicyList/fetchCardPolicyListEpic.js +0 -56
- package/lib/esm/view/spendManagement/chargeCards/cardPolicy/createCardPolicy/createCardPolicyReducer.js +0 -50
- package/lib/esm/view/spendManagement/chargeCards/cardPolicy/createCardPolicy/createCardPolicySelector.js +0 -6
- package/lib/esm/view/spendManagement/chargeCards/cardPolicy/createCardPolicy/createCardPolicyState.js +0 -1
- package/lib/esm/view/spendManagement/chargeCards/cardPolicy/createCardPolicy/createCardPolicyTemplateEpic.js +0 -34
- package/lib/esm/view/spendManagement/chargeCards/cardPolicy/createCardPolicy/fetchCardPolicyMccCategoriesEpic.js +0 -25
- package/lib/view/spendManagement/chargeCards/cardPolicy/cardPolicyDetail/cardPolicyDetailReducer.d.ts +0 -14
- package/lib/view/spendManagement/chargeCards/cardPolicy/cardPolicyDetail/cardPolicyDetailReducer.js +0 -74
- package/lib/view/spendManagement/chargeCards/cardPolicy/cardPolicyDetail/cardPolicyDetailSelector.d.ts +0 -21
- package/lib/view/spendManagement/chargeCards/cardPolicy/cardPolicyDetail/cardPolicyDetailSelector.js +0 -28
- package/lib/view/spendManagement/chargeCards/cardPolicy/cardPolicyDetail/cardPolicyDetailState.d.ts +0 -25
- package/lib/view/spendManagement/chargeCards/cardPolicy/cardPolicyDetail/cardPolicyDetailState.js +0 -2
- package/lib/view/spendManagement/chargeCards/cardPolicy/cardPolicyDetail/fetchCardPolicyDetailEpic.d.ts +0 -19
- package/lib/view/spendManagement/chargeCards/cardPolicy/cardPolicyDetail/fetchCardPolicyDetailEpic.js +0 -60
- package/lib/view/spendManagement/chargeCards/cardPolicy/cardPolicyDetail/updateCardPolicyEpic.d.ts +0 -18
- package/lib/view/spendManagement/chargeCards/cardPolicy/cardPolicyDetail/updateCardPolicyEpic.js +0 -53
- package/lib/view/spendManagement/chargeCards/cardPolicy/cardPolicyList/archiveCardPolicyEpic.d.ts +0 -16
- package/lib/view/spendManagement/chargeCards/cardPolicy/cardPolicyList/archiveCardPolicyEpic.js +0 -46
- package/lib/view/spendManagement/chargeCards/cardPolicy/cardPolicyList/cardPolicyListReducer.d.ts +0 -15
- package/lib/view/spendManagement/chargeCards/cardPolicy/cardPolicyList/cardPolicyListReducer.js +0 -76
- package/lib/view/spendManagement/chargeCards/cardPolicy/cardPolicyList/cardPolicyListSelector.d.ts +0 -21
- package/lib/view/spendManagement/chargeCards/cardPolicy/cardPolicyList/cardPolicyListSelector.js +0 -27
- package/lib/view/spendManagement/chargeCards/cardPolicy/cardPolicyList/cardPolicyListState.d.ts +0 -19
- package/lib/view/spendManagement/chargeCards/cardPolicy/cardPolicyList/cardPolicyListState.js +0 -2
- package/lib/view/spendManagement/chargeCards/cardPolicy/cardPolicyList/fetchCardPolicyListEpic.d.ts +0 -19
- package/lib/view/spendManagement/chargeCards/cardPolicy/cardPolicyList/fetchCardPolicyListEpic.js +0 -60
- package/lib/view/spendManagement/chargeCards/cardPolicy/createCardPolicy/createCardPolicyReducer.d.ts +0 -12
- package/lib/view/spendManagement/chargeCards/cardPolicy/createCardPolicy/createCardPolicyReducer.js +0 -54
- package/lib/view/spendManagement/chargeCards/cardPolicy/createCardPolicy/createCardPolicySelector.d.ts +0 -4
- package/lib/view/spendManagement/chargeCards/cardPolicy/createCardPolicy/createCardPolicySelector.js +0 -10
- package/lib/view/spendManagement/chargeCards/cardPolicy/createCardPolicy/createCardPolicyState.d.ts +0 -15
- package/lib/view/spendManagement/chargeCards/cardPolicy/createCardPolicy/createCardPolicyState.js +0 -2
- package/lib/view/spendManagement/chargeCards/cardPolicy/createCardPolicy/createCardPolicyTemplateEpic.d.ts +0 -8
- package/lib/view/spendManagement/chargeCards/cardPolicy/createCardPolicy/createCardPolicyTemplateEpic.js +0 -38
- package/lib/view/spendManagement/chargeCards/cardPolicy/createCardPolicy/fetchCardPolicyMccCategoriesEpic.d.ts +0 -15
- package/lib/view/spendManagement/chargeCards/cardPolicy/createCardPolicy/fetchCardPolicyMccCategoriesEpic.js +0 -29
|
@@ -1,101 +0,0 @@
|
|
|
1
|
-
import { date } from '../../zeniDayJS';
|
|
2
|
-
import { toCardPolicyTemplateMode, toCardPolicyTemplateStatus, } from './cardPolicyState';
|
|
3
|
-
export const toMccCategory = (payload) => ({
|
|
4
|
-
count: payload.count,
|
|
5
|
-
mccCodes: payload.mcc_codes ?? [],
|
|
6
|
-
name: payload.name,
|
|
7
|
-
});
|
|
8
|
-
export const toCardPolicyVendorSearchOption = (payload) => ({
|
|
9
|
-
vendorId: payload.vendor_id,
|
|
10
|
-
name: payload.vendor_name,
|
|
11
|
-
});
|
|
12
|
-
export const toCardPolicyStats = (payload) => ({
|
|
13
|
-
activePolicies: payload.active_policies,
|
|
14
|
-
totalCards: payload.total_cards,
|
|
15
|
-
totalTemplates: payload.total_templates,
|
|
16
|
-
});
|
|
17
|
-
export const toCardPolicyTemplateList = (data) => (data.templates ?? []).map((row) => toCardPolicyTemplate(row.data.template));
|
|
18
|
-
const toCardPolicyTemplateEntityList = (payload) => ({
|
|
19
|
-
categoryCodes: payload.category_codes ?? [],
|
|
20
|
-
merchantNames: payload.merchant_names ?? [],
|
|
21
|
-
});
|
|
22
|
-
export const toCardPolicyTemplate = (payload) => ({
|
|
23
|
-
allowedEntity: toCardPolicyTemplateEntityList(payload.allowed_entity),
|
|
24
|
-
appliedCards: payload.applied_cards ?? [],
|
|
25
|
-
blockedEntity: toCardPolicyTemplateEntityList(payload.blocked_entity),
|
|
26
|
-
cardsCount: payload.cards_count,
|
|
27
|
-
categoryRestrictions: payload.category_restrictions ?? [],
|
|
28
|
-
createdAt: date(payload.created_at),
|
|
29
|
-
createdBy: payload.created_by,
|
|
30
|
-
description: payload.description,
|
|
31
|
-
mode: toCardPolicyTemplateMode(payload.mode),
|
|
32
|
-
name: payload.name,
|
|
33
|
-
requiredReceiptThreshold: payload.required_receipt_threshold,
|
|
34
|
-
spendLimits: {
|
|
35
|
-
transaction: payload.spend_limits.transaction,
|
|
36
|
-
},
|
|
37
|
-
status: toCardPolicyTemplateStatus(payload.status),
|
|
38
|
-
templateId: payload.template_id,
|
|
39
|
-
tenantId: payload.tenant_id,
|
|
40
|
-
updatedAt: date(payload.updated_at),
|
|
41
|
-
});
|
|
42
|
-
/**
|
|
43
|
-
* Re-shape a camelCase create request into the snake_case wire body.
|
|
44
|
-
* Used by the epic at request time.
|
|
45
|
-
*/
|
|
46
|
-
export const toCreateCardPolicyTemplateRequestBody = (request) => ({
|
|
47
|
-
allowed_entity: {
|
|
48
|
-
category_codes: request.allowedEntity.categoryCodes,
|
|
49
|
-
merchant_names: request.allowedEntity.merchantNames,
|
|
50
|
-
},
|
|
51
|
-
apply_to_cards: request.applyToCards,
|
|
52
|
-
blocked_entity: {
|
|
53
|
-
category_codes: request.blockedEntity.categoryCodes,
|
|
54
|
-
merchant_names: request.blockedEntity.merchantNames,
|
|
55
|
-
},
|
|
56
|
-
description: request.description,
|
|
57
|
-
mode: request.mode ?? 'strict',
|
|
58
|
-
name: request.name,
|
|
59
|
-
required_receipt_threshold: request.requiredReceiptThreshold,
|
|
60
|
-
spend_limits: {
|
|
61
|
-
transaction: request.spendLimits.transaction,
|
|
62
|
-
},
|
|
63
|
-
});
|
|
64
|
-
// Update body uses the exact same wire shape as create — the PUT
|
|
65
|
-
// endpoint is a full replace.
|
|
66
|
-
export const toUpdateCardPolicyTemplateRequestBody = toCreateCardPolicyTemplateRequestBody;
|
|
67
|
-
/**
|
|
68
|
-
* Seed an edit-form draft (`CreateCardPolicyTemplateRequest`) from an
|
|
69
|
-
* existing camelCased `CardPolicyTemplate`. Used by the detail-fetch
|
|
70
|
-
* epic so the edit page can render with the saved values pre-populated.
|
|
71
|
-
*/
|
|
72
|
-
export const toCardPolicyEditFormDraft = (template) => ({
|
|
73
|
-
allowedEntity: {
|
|
74
|
-
categoryCodes: [...template.allowedEntity.categoryCodes],
|
|
75
|
-
merchantNames: [...template.allowedEntity.merchantNames],
|
|
76
|
-
},
|
|
77
|
-
applyToCards: [...template.appliedCards],
|
|
78
|
-
blockedEntity: {
|
|
79
|
-
categoryCodes: [...template.blockedEntity.categoryCodes],
|
|
80
|
-
merchantNames: [...template.blockedEntity.merchantNames],
|
|
81
|
-
},
|
|
82
|
-
description: template.description,
|
|
83
|
-
mode: template.mode,
|
|
84
|
-
name: template.name,
|
|
85
|
-
requiredReceiptThreshold: template.requiredReceiptThreshold,
|
|
86
|
-
spendLimits: { transaction: template.spendLimits.transaction },
|
|
87
|
-
});
|
|
88
|
-
export const toExtractedCardPolicyRules = (payload) => ({
|
|
89
|
-
allowedEntity: {
|
|
90
|
-
categoryCodes: payload.allowed_entity?.category_codes ?? [],
|
|
91
|
-
merchantNames: payload.allowed_entity?.merchant_names ?? [],
|
|
92
|
-
},
|
|
93
|
-
blockedEntity: {
|
|
94
|
-
categoryCodes: payload.blocked_entity?.category_codes ?? [],
|
|
95
|
-
merchantNames: payload.blocked_entity?.merchant_names ?? [],
|
|
96
|
-
},
|
|
97
|
-
confidenceScore: payload.confidence_score,
|
|
98
|
-
policyName: payload.policy_name,
|
|
99
|
-
requiredReceiptThreshold: payload.required_receipt_threshold,
|
|
100
|
-
transactionLimit: payload.transaction_limit,
|
|
101
|
-
});
|
|
@@ -1,199 +0,0 @@
|
|
|
1
|
-
import { createSlice } from '@reduxjs/toolkit';
|
|
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() !== '';
|
|
13
|
-
const initialPolicyDocumentExtractionState = {
|
|
14
|
-
fetchState: 'Not-Started',
|
|
15
|
-
error: undefined,
|
|
16
|
-
extractedRules: undefined,
|
|
17
|
-
uploadedFileName: undefined,
|
|
18
|
-
};
|
|
19
|
-
const initialVendorSearchState = {
|
|
20
|
-
fetchState: 'Not-Started',
|
|
21
|
-
searchString: '',
|
|
22
|
-
vendors: [],
|
|
23
|
-
error: undefined,
|
|
24
|
-
};
|
|
25
|
-
export const initialState = {
|
|
26
|
-
cardPolicyTemplateById: {},
|
|
27
|
-
mccCategories: [],
|
|
28
|
-
mccCategoriesError: undefined,
|
|
29
|
-
mccCategoriesFetchState: 'Not-Started',
|
|
30
|
-
policyDocumentExtraction: initialPolicyDocumentExtractionState,
|
|
31
|
-
suggestedAllowCategories: [],
|
|
32
|
-
suggestedAllowMerchants: [],
|
|
33
|
-
suggestedBlockCategories: [],
|
|
34
|
-
suggestedBlockMerchants: [],
|
|
35
|
-
vendorSearch: initialVendorSearchState,
|
|
36
|
-
cardPolicyStats: undefined,
|
|
37
|
-
};
|
|
38
|
-
const cardPolicy = createSlice({
|
|
39
|
-
name: 'cardPolicy',
|
|
40
|
-
initialState,
|
|
41
|
-
reducers: {
|
|
42
|
-
fetchCardPolicyMccCategories(draft) {
|
|
43
|
-
draft.mccCategoriesFetchState = 'In-Progress';
|
|
44
|
-
draft.mccCategoriesError = undefined;
|
|
45
|
-
},
|
|
46
|
-
updateCardPolicyMccCategories(draft, action) {
|
|
47
|
-
draft.mccCategories = (action.payload.categories ?? []).map(toMccCategory);
|
|
48
|
-
// Persist BE-suggested allow / block seeds alongside the universe.
|
|
49
|
-
// Both flows (manual create page + AI CFO interactive form) read
|
|
50
|
-
// these to pre-populate the chip cloud body before the user edits.
|
|
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);
|
|
57
|
-
draft.suggestedAllowCategories = (action.payload.suggested_allow_catagories ?? []).map(toMccCategory);
|
|
58
|
-
draft.suggestedBlockCategories = (action.payload.suggested_block_catagories ?? []).map(toMccCategory);
|
|
59
|
-
draft.mccCategoriesFetchState = 'Completed';
|
|
60
|
-
draft.mccCategoriesError = undefined;
|
|
61
|
-
},
|
|
62
|
-
updateCardPolicyMccCategoriesFailure(draft, action) {
|
|
63
|
-
draft.mccCategoriesFetchState = 'Error';
|
|
64
|
-
draft.mccCategoriesError = action.payload;
|
|
65
|
-
},
|
|
66
|
-
/**
|
|
67
|
-
* Store a newly-created (or refreshed) card-policy template keyed by
|
|
68
|
-
* `templateId`. Dispatched by the create / list / get epics; consumed
|
|
69
|
-
* by both manual and AI-CFO policy flows via `getCardPolicyTemplateById`.
|
|
70
|
-
*/
|
|
71
|
-
updateCreatedCardPolicyTemplate(draft, action) {
|
|
72
|
-
const template = toCardPolicyTemplate(action.payload);
|
|
73
|
-
draft.cardPolicyTemplateById[template.templateId] = template;
|
|
74
|
-
},
|
|
75
|
-
/**
|
|
76
|
-
* Replace the entity store's `cardPolicyTemplateById` map with the
|
|
77
|
-
* full list returned by the templates-list endpoint. Full replace is
|
|
78
|
-
* intentional — templates that no longer exist on the server should be
|
|
79
|
-
* dropped from local state too. The view slice keeps the server-order
|
|
80
|
-
* ID list separately for stable list rendering.
|
|
81
|
-
*/
|
|
82
|
-
updateCardPolicyTemplates(draft, action) {
|
|
83
|
-
const byId = {};
|
|
84
|
-
for (const template of action.payload) {
|
|
85
|
-
byId[template.templateId] = template;
|
|
86
|
-
}
|
|
87
|
-
draft.cardPolicyTemplateById = byId;
|
|
88
|
-
},
|
|
89
|
-
/**
|
|
90
|
-
* Drop a single template from the entity map. Dispatched by the
|
|
91
|
-
* archive (DELETE) epic on success; also usable by any future flow
|
|
92
|
-
* that needs to evict a template (e.g. AI-CFO rejection).
|
|
93
|
-
*/
|
|
94
|
-
removeCardPolicyTemplate(draft, action) {
|
|
95
|
-
delete draft.cardPolicyTemplateById[action.payload];
|
|
96
|
-
},
|
|
97
|
-
/**
|
|
98
|
-
* Replace the tenant-wide policy stats. Dispatched alongside
|
|
99
|
-
* `updateCardPolicyTemplates` from the list epic, but lives on the
|
|
100
|
-
* entity slice so any consumer can read it without re-fetching the
|
|
101
|
-
* list.
|
|
102
|
-
*/
|
|
103
|
-
updateCardPolicyStats(draft, action) {
|
|
104
|
-
draft.cardPolicyStats = action.payload;
|
|
105
|
-
},
|
|
106
|
-
/**
|
|
107
|
-
* Kick off the `POST /cards/1.0/policy-documents/extract` request.
|
|
108
|
-
*
|
|
109
|
-
* Synchronously flips the sub-slice to `In-Progress` and captures the
|
|
110
|
-
* first uploaded file's name (used by the manual `CardPolicyCreatePage`
|
|
111
|
-
* to render the "Policy.pdf ×" pill once the request completes) so
|
|
112
|
-
* downstream callers don't have to keep their own file refs.
|
|
113
|
-
*
|
|
114
|
-
* The accompanying `extractPolicyDocumentEpic` listens for this action,
|
|
115
|
-
* POSTs multipart form-data to the cards micro-service, and dispatches
|
|
116
|
-
* either `updatePolicyDocumentExtractionSuccess` or
|
|
117
|
-
* `updatePolicyDocumentExtractionFailure`.
|
|
118
|
-
*
|
|
119
|
-
* Designed to be dispatched from both the manual create page and a
|
|
120
|
-
* future AI CFO composer/upload surface — selectors return a single
|
|
121
|
-
* source of truth.
|
|
122
|
-
*/
|
|
123
|
-
extractPolicyDocument: {
|
|
124
|
-
reducer(draft, action) {
|
|
125
|
-
draft.policyDocumentExtraction.fetchState = 'In-Progress';
|
|
126
|
-
draft.policyDocumentExtraction.error = undefined;
|
|
127
|
-
draft.policyDocumentExtraction.extractedRules = undefined;
|
|
128
|
-
draft.policyDocumentExtraction.uploadedFileName =
|
|
129
|
-
action.meta.uploadedFileName;
|
|
130
|
-
},
|
|
131
|
-
prepare(files) {
|
|
132
|
-
return {
|
|
133
|
-
payload: { files },
|
|
134
|
-
meta: { uploadedFileName: files[0]?.name },
|
|
135
|
-
};
|
|
136
|
-
},
|
|
137
|
-
},
|
|
138
|
-
updatePolicyDocumentExtractionSuccess(draft, action) {
|
|
139
|
-
draft.policyDocumentExtraction.fetchState = 'Completed';
|
|
140
|
-
draft.policyDocumentExtraction.error = undefined;
|
|
141
|
-
draft.policyDocumentExtraction.extractedRules =
|
|
142
|
-
toExtractedCardPolicyRules(action.payload);
|
|
143
|
-
},
|
|
144
|
-
updatePolicyDocumentExtractionFailure(draft, action) {
|
|
145
|
-
draft.policyDocumentExtraction.fetchState = 'Error';
|
|
146
|
-
draft.policyDocumentExtraction.error = action.payload;
|
|
147
|
-
draft.policyDocumentExtraction.extractedRules = undefined;
|
|
148
|
-
},
|
|
149
|
-
clearPolicyDocumentExtraction(draft) {
|
|
150
|
-
draft.policyDocumentExtraction = {
|
|
151
|
-
...initialPolicyDocumentExtractionState,
|
|
152
|
-
};
|
|
153
|
-
},
|
|
154
|
-
/**
|
|
155
|
-
* Kick off `GET /accounting/1.0/vendors` (card-policy mode). When
|
|
156
|
-
* `searchString` is empty the BE returns the top vendors sorted by
|
|
157
|
-
* year-to-date spend; with a non-empty value it filters server-side.
|
|
158
|
-
*
|
|
159
|
-
* The accompanying `fetchCardPolicyVendorOptionsEpic` listens for
|
|
160
|
-
* this action, builds the `query` JSON (matching `fetchVendorsList`'s
|
|
161
|
-
* `view: "vendor_list"` shape) and dispatches success / failure.
|
|
162
|
-
*
|
|
163
|
-
* Designed to be dispatched from both the manual `CardPolicyCreate /
|
|
164
|
-
* EditScreen` (on mount + on every chip-picker keystroke, debounced)
|
|
165
|
-
* and the AI CFO interactive form's vendor step.
|
|
166
|
-
*/
|
|
167
|
-
fetchCardPolicyVendorOptions: {
|
|
168
|
-
reducer(draft, action) {
|
|
169
|
-
draft.vendorSearch.fetchState = 'In-Progress';
|
|
170
|
-
draft.vendorSearch.searchString = action.payload.searchString;
|
|
171
|
-
draft.vendorSearch.error = undefined;
|
|
172
|
-
},
|
|
173
|
-
prepare(searchString) {
|
|
174
|
-
return { payload: { searchString: searchString ?? '' } };
|
|
175
|
-
},
|
|
176
|
-
},
|
|
177
|
-
updateCardPolicyVendorOptions(draft, action) {
|
|
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));
|
|
186
|
-
draft.vendorSearch.fetchState = 'Completed';
|
|
187
|
-
draft.vendorSearch.error = undefined;
|
|
188
|
-
},
|
|
189
|
-
updateCardPolicyVendorOptionsFailure(draft, action) {
|
|
190
|
-
draft.vendorSearch.fetchState = 'Error';
|
|
191
|
-
draft.vendorSearch.error = action.payload;
|
|
192
|
-
},
|
|
193
|
-
clearCardPolicy(draft) {
|
|
194
|
-
Object.assign(draft, initialState);
|
|
195
|
-
},
|
|
196
|
-
},
|
|
197
|
-
});
|
|
198
|
-
export const { fetchCardPolicyMccCategories, fetchCardPolicyVendorOptions, updateCardPolicyMccCategories, updateCardPolicyMccCategoriesFailure, updateCardPolicyVendorOptions, updateCardPolicyVendorOptionsFailure, updateCreatedCardPolicyTemplate, updateCardPolicyTemplates, removeCardPolicyTemplate, updateCardPolicyStats, extractPolicyDocument, updatePolicyDocumentExtractionSuccess, updatePolicyDocumentExtractionFailure, clearPolicyDocumentExtraction, clearCardPolicy, } = cardPolicy.actions;
|
|
199
|
-
export default cardPolicy.reducer;
|
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
export function getCardPolicyMccCategories(state) {
|
|
2
|
-
return state.mccCategories;
|
|
3
|
-
}
|
|
4
|
-
export function getCardPolicyMccCategoriesFetchState(state) {
|
|
5
|
-
return state.mccCategoriesFetchState;
|
|
6
|
-
}
|
|
7
|
-
export function getCardPolicyMccCategoriesError(state) {
|
|
8
|
-
return state.mccCategoriesError;
|
|
9
|
-
}
|
|
10
|
-
export function getCardPolicyTemplateById(state, templateId) {
|
|
11
|
-
return state.cardPolicyTemplateById[templateId];
|
|
12
|
-
}
|
|
13
|
-
export function getAllCardPolicyTemplates(state) {
|
|
14
|
-
return Object.values(state.cardPolicyTemplateById);
|
|
15
|
-
}
|
|
16
|
-
/**
|
|
17
|
-
* Resolve an ordered list of `templateId`s against the entity store and
|
|
18
|
-
* return the corresponding `CardPolicyTemplate[]` in the same order.
|
|
19
|
-
* Missing IDs (e.g. stale local state during a refetch) are silently
|
|
20
|
-
* dropped. Pair with `getCardPolicyTemplateIds` from the view slice to
|
|
21
|
-
* render the Policy List page in server order.
|
|
22
|
-
*/
|
|
23
|
-
export function getCardPolicyTemplatesByIds(state, templateIds) {
|
|
24
|
-
return templateIds
|
|
25
|
-
.map((id) => state.cardPolicyTemplateById[id])
|
|
26
|
-
.filter((template) => template != null);
|
|
27
|
-
}
|
|
28
|
-
export function getCardPolicyStats(state) {
|
|
29
|
-
return state.cardPolicyStats;
|
|
30
|
-
}
|
|
31
|
-
// ── Policy document extraction ───────────────────────────────────────
|
|
32
|
-
export function getPolicyDocumentExtractionFetchState(state) {
|
|
33
|
-
return state.policyDocumentExtraction.fetchState;
|
|
34
|
-
}
|
|
35
|
-
export function getPolicyDocumentExtractionError(state) {
|
|
36
|
-
return state.policyDocumentExtraction.error;
|
|
37
|
-
}
|
|
38
|
-
export function getExtractedCardPolicyRules(state) {
|
|
39
|
-
return state.policyDocumentExtraction.extractedRules;
|
|
40
|
-
}
|
|
41
|
-
export function getUploadedPolicyDocumentFileName(state) {
|
|
42
|
-
return state.policyDocumentExtraction.uploadedFileName;
|
|
43
|
-
}
|
|
44
|
-
// ── Suggested allow / block seeds (shipped alongside MCC categories) ─
|
|
45
|
-
export function getCardPolicySuggestedAllowMerchants(state) {
|
|
46
|
-
return state.suggestedAllowMerchants;
|
|
47
|
-
}
|
|
48
|
-
export function getCardPolicySuggestedBlockMerchants(state) {
|
|
49
|
-
return state.suggestedBlockMerchants;
|
|
50
|
-
}
|
|
51
|
-
export function getCardPolicySuggestedAllowCategories(state) {
|
|
52
|
-
return state.suggestedAllowCategories;
|
|
53
|
-
}
|
|
54
|
-
export function getCardPolicySuggestedBlockCategories(state) {
|
|
55
|
-
return state.suggestedBlockCategories;
|
|
56
|
-
}
|
|
57
|
-
// ── Vendor search dropdown ───────────────────────────────────────────
|
|
58
|
-
export function getCardPolicyVendorSearchOptions(state) {
|
|
59
|
-
return state.vendorSearch.vendors;
|
|
60
|
-
}
|
|
61
|
-
export function getCardPolicyVendorSearchFetchState(state) {
|
|
62
|
-
return state.vendorSearch.fetchState;
|
|
63
|
-
}
|
|
64
|
-
export function getCardPolicyVendorSearchString(state) {
|
|
65
|
-
return state.vendorSearch.searchString;
|
|
66
|
-
}
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import { stringToUnion } from '../../commonStateTypes/stringToUnion';
|
|
2
|
-
export const ALL_CARD_POLICY_TEMPLATE_MODES = ['strict', 'flexible'];
|
|
3
|
-
export const toCardPolicyTemplateMode = (v) => stringToUnion(v, ALL_CARD_POLICY_TEMPLATE_MODES);
|
|
4
|
-
export const ALL_CARD_POLICY_TEMPLATE_STATUSES = [
|
|
5
|
-
'active',
|
|
6
|
-
'inactive',
|
|
7
|
-
'archived',
|
|
8
|
-
];
|
|
9
|
-
export const toCardPolicyTemplateStatus = (v) => stringToUnion(v, ALL_CARD_POLICY_TEMPLATE_STATUSES);
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
import { of } from 'rxjs';
|
|
2
|
-
import { catchError, filter, mergeMap } from 'rxjs/operators';
|
|
3
|
-
import { createZeniAPIStatus, isSuccessStatus } from '../../responsePayload';
|
|
4
|
-
import { extractPolicyDocument, updatePolicyDocumentExtractionFailure, updatePolicyDocumentExtractionSuccess, } from './cardPolicyReducer';
|
|
5
|
-
/**
|
|
6
|
-
* Build a multipart `FormData` body for `POST /cards/1.0/policy-documents/extract`.
|
|
7
|
-
*
|
|
8
|
-
* Uses the same `attachment_file_<i>` / `attachment_json_<i>` field-naming
|
|
9
|
-
* convention as the charge-card receipt upload (`uploadReceipts.ts` in
|
|
10
|
-
* `web-components`) so backends that already support that wire shape
|
|
11
|
-
* accept this endpoint without bespoke parsing.
|
|
12
|
-
*/
|
|
13
|
-
const buildPolicyDocumentFormData = (files) => {
|
|
14
|
-
const data = new FormData();
|
|
15
|
-
files.forEach((file, index) => {
|
|
16
|
-
data.append(`attachment_file_${index}`, file);
|
|
17
|
-
const attachmentJson = JSON.stringify({
|
|
18
|
-
file_name: file.name,
|
|
19
|
-
content_type: file.type,
|
|
20
|
-
size: file.size,
|
|
21
|
-
});
|
|
22
|
-
data.append(`attachment_json_${index}`, attachmentJson);
|
|
23
|
-
});
|
|
24
|
-
return data;
|
|
25
|
-
};
|
|
26
|
-
/**
|
|
27
|
-
* Listens for `extractPolicyDocument`, POSTs the file(s) as multipart
|
|
28
|
-
* form-data to the cards micro-service's policy-document extract endpoint,
|
|
29
|
-
* and dispatches success / failure into the entity slice.
|
|
30
|
-
*
|
|
31
|
-
* Consumed by:
|
|
32
|
-
* - Manual `CardPolicyCreatePage` (read result via
|
|
33
|
-
* `getExtractedCardPolicyRules` then pre-fill the RHF form via
|
|
34
|
-
* `applyExtractedPolicyRulesToFormValues` from `@zeniai/web-components`).
|
|
35
|
-
* - (Future) AI CFO upload surface — same action + selector contract.
|
|
36
|
-
*/
|
|
37
|
-
export const extractPolicyDocumentEpic = (actions$, _state$, zeniAPI) => actions$.pipe(filter(extractPolicyDocument.match), mergeMap((action) => {
|
|
38
|
-
const formData = buildPolicyDocumentFormData(action.payload.files);
|
|
39
|
-
return zeniAPI
|
|
40
|
-
.postFormData(`${zeniAPI.apiEndPoints.cardMicroServiceBaseUrl}/1.0/policy-documents/extract`, formData)
|
|
41
|
-
.pipe(mergeMap((response) => {
|
|
42
|
-
if (isSuccessStatus(response) &&
|
|
43
|
-
response.data != null &&
|
|
44
|
-
response.data.extracted_rules != null) {
|
|
45
|
-
return of(updatePolicyDocumentExtractionSuccess(response.data.extracted_rules));
|
|
46
|
-
}
|
|
47
|
-
return of(updatePolicyDocumentExtractionFailure(response.status));
|
|
48
|
-
}), catchError((error) => of(updatePolicyDocumentExtractionFailure(createZeniAPIStatus('Unexpected Error', 'Extract card-policy document REST API call errored out' +
|
|
49
|
-
JSON.stringify(error))))));
|
|
50
|
-
}));
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
import { of } from 'rxjs';
|
|
2
|
-
import { catchError, filter, switchMap } from 'rxjs/operators';
|
|
3
|
-
import { createZeniAPIStatus, isSuccessStatus } from '../../responsePayload';
|
|
4
|
-
import { fetchCardPolicyVendorOptions, updateCardPolicyVendorOptions, updateCardPolicyVendorOptionsFailure, } from './cardPolicyReducer';
|
|
5
|
-
const buildQuery = (searchString) => ({
|
|
6
|
-
view: 'vendor_list',
|
|
7
|
-
page_token: null,
|
|
8
|
-
sort_by: 'year_to_date_spend',
|
|
9
|
-
sort_order: 'desc',
|
|
10
|
-
search_text: searchString,
|
|
11
|
-
vendor_name: searchString,
|
|
12
|
-
});
|
|
13
|
-
/**
|
|
14
|
-
* Card-policy vendor search.
|
|
15
|
-
*
|
|
16
|
-
* Listens for `fetchCardPolicyVendorOptions` and hits the same
|
|
17
|
-
* `/accounting/1.0/vendors` endpoint the Vendors-tab uses, but writes
|
|
18
|
-
* results onto the dedicated `cardPolicyState.vendorSearch` slice — no
|
|
19
|
-
* fan-out to the global `vendor` / `account` / `class` / `vendorList`
|
|
20
|
-
* entities. That isolation is important: the user may be configuring a
|
|
21
|
-
* card policy in parallel with browsing the Vendors tab, and we don't
|
|
22
|
-
* want either flow to clobber the other's list state.
|
|
23
|
-
*
|
|
24
|
-
* Uses `switchMap` so the latest typed search wins — earlier in-flight
|
|
25
|
-
* requests are abandoned, which is the right semantics for a
|
|
26
|
-
* search-as-you-type UX.
|
|
27
|
-
*
|
|
28
|
-
* Consumers:
|
|
29
|
-
* - Manual `CardPolicyCreate / EditScreen`
|
|
30
|
-
* - AI CFO `CardPolicyInteractiveForm` (vendor step)
|
|
31
|
-
*/
|
|
32
|
-
export const fetchCardPolicyVendorOptionsEpic = (actions$, _state$, zeniAPI) => actions$.pipe(filter(fetchCardPolicyVendorOptions.match), switchMap((action) => {
|
|
33
|
-
const query = buildQuery(action.payload.searchString);
|
|
34
|
-
const apiUrl = `${zeniAPI.apiEndPoints.accountMicroServiceBaseUrl}/1.0/vendors` +
|
|
35
|
-
`?query=${encodeURIComponent(JSON.stringify(query))}`;
|
|
36
|
-
return zeniAPI.getJSON(apiUrl).pipe(switchMap((response) => {
|
|
37
|
-
if (isSuccessStatus(response) && response.data != null) {
|
|
38
|
-
return of(updateCardPolicyVendorOptions(response.data));
|
|
39
|
-
}
|
|
40
|
-
return of(updateCardPolicyVendorOptionsFailure(response.status));
|
|
41
|
-
}), catchError((error) => of(updateCardPolicyVendorOptionsFailure(createZeniAPIStatus('Unexpected Error', 'Fetch card policy vendor options REST API call errored out' +
|
|
42
|
-
JSON.stringify(error))))));
|
|
43
|
-
}));
|
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
import { createSlice } from '@reduxjs/toolkit';
|
|
2
|
-
export const initialState = {
|
|
3
|
-
detailTemplateId: undefined,
|
|
4
|
-
detailFetchState: { fetchState: 'Not-Started', error: undefined },
|
|
5
|
-
updateFetchState: { fetchState: 'Not-Started', error: undefined },
|
|
6
|
-
formDraft: undefined,
|
|
7
|
-
};
|
|
8
|
-
const cardPolicyDetail = createSlice({
|
|
9
|
-
name: 'cardPolicyDetail',
|
|
10
|
-
initialState,
|
|
11
|
-
reducers: {
|
|
12
|
-
/**
|
|
13
|
-
* Kick off the `GET /cards/1.0/policy-templates/{id}` request. The
|
|
14
|
-
* accompanying epic dispatches `updateCreatedCardPolicyTemplate` on
|
|
15
|
-
* the entity slice + `updateCardPolicyFormDraft` (seeded from the
|
|
16
|
-
* template) + `updateCardPolicyDetailFetchStatus` here.
|
|
17
|
-
*/
|
|
18
|
-
fetchCardPolicyDetail: {
|
|
19
|
-
reducer(draft, action) {
|
|
20
|
-
draft.detailTemplateId = action.payload;
|
|
21
|
-
draft.detailFetchState.fetchState = 'In-Progress';
|
|
22
|
-
draft.detailFetchState.error = undefined;
|
|
23
|
-
// Reset the draft so a stale form from a previous template
|
|
24
|
-
// doesn't leak into the new edit session.
|
|
25
|
-
draft.formDraft = undefined;
|
|
26
|
-
},
|
|
27
|
-
prepare(templateId) {
|
|
28
|
-
return { payload: templateId };
|
|
29
|
-
},
|
|
30
|
-
},
|
|
31
|
-
updateCardPolicyDetailFetchStatus(draft, action) {
|
|
32
|
-
draft.detailFetchState.fetchState = action.payload.fetchState;
|
|
33
|
-
draft.detailFetchState.error = action.payload.error;
|
|
34
|
-
},
|
|
35
|
-
/**
|
|
36
|
-
* Replace (or seed) the local edit-form draft. Dispatched by the
|
|
37
|
-
* detail-fetch epic with the camelCased values pulled from the
|
|
38
|
-
* fetched template, and by the edit page itself as the user types.
|
|
39
|
-
*/
|
|
40
|
-
updateCardPolicyFormDraft(draft, action) {
|
|
41
|
-
draft.formDraft = action.payload;
|
|
42
|
-
},
|
|
43
|
-
/**
|
|
44
|
-
* Kick off the `PUT /cards/1.0/policy-templates/{id}` save. The
|
|
45
|
-
* epic reads the current `formDraft` from state, posts the wire
|
|
46
|
-
* body, then dispatches `updateCreatedCardPolicyTemplate` (entity)
|
|
47
|
-
* + `updateCardPolicyFetchStatus({fetchState: 'Completed'})` here.
|
|
48
|
-
*/
|
|
49
|
-
updateCardPolicy: {
|
|
50
|
-
reducer(draft,
|
|
51
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
52
|
-
_action) {
|
|
53
|
-
draft.updateFetchState.fetchState = 'In-Progress';
|
|
54
|
-
draft.updateFetchState.error = undefined;
|
|
55
|
-
},
|
|
56
|
-
prepare(templateId) {
|
|
57
|
-
return { payload: templateId };
|
|
58
|
-
},
|
|
59
|
-
},
|
|
60
|
-
updateCardPolicyFetchStatus(draft, action) {
|
|
61
|
-
draft.updateFetchState.fetchState = action.payload.fetchState;
|
|
62
|
-
draft.updateFetchState.error = action.payload.error;
|
|
63
|
-
},
|
|
64
|
-
clearCardPolicyDetail(draft) {
|
|
65
|
-
Object.assign(draft, initialState);
|
|
66
|
-
},
|
|
67
|
-
},
|
|
68
|
-
});
|
|
69
|
-
export const { fetchCardPolicyDetail, updateCardPolicyDetailFetchStatus, updateCardPolicyFormDraft, updateCardPolicy, updateCardPolicyFetchStatus, clearCardPolicyDetail, } = cardPolicyDetail.actions;
|
|
70
|
-
export default cardPolicyDetail.reducer;
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import { getCardPolicyTemplateById } from '../../../../../entity/cardPolicy/cardPolicySelector';
|
|
2
|
-
export function getCardPolicyDetailView(state) {
|
|
3
|
-
const { cardPolicyDetailState, cardPolicyState } = state;
|
|
4
|
-
return {
|
|
5
|
-
templateId: cardPolicyDetailState.detailTemplateId,
|
|
6
|
-
template: cardPolicyDetailState.detailTemplateId != null
|
|
7
|
-
? getCardPolicyTemplateById(cardPolicyState, cardPolicyDetailState.detailTemplateId)
|
|
8
|
-
: undefined,
|
|
9
|
-
formDraft: cardPolicyDetailState.formDraft,
|
|
10
|
-
detailFetchState: cardPolicyDetailState.detailFetchState,
|
|
11
|
-
updateFetchState: cardPolicyDetailState.updateFetchState,
|
|
12
|
-
};
|
|
13
|
-
}
|
|
14
|
-
export function getCardPolicyFormDraft(state) {
|
|
15
|
-
return state.cardPolicyDetailState.formDraft;
|
|
16
|
-
}
|
|
17
|
-
export function getCardPolicyDetailFetchState(state) {
|
|
18
|
-
return state.cardPolicyDetailState.detailFetchState;
|
|
19
|
-
}
|
|
20
|
-
export function getUpdateCardPolicyFetchState(state) {
|
|
21
|
-
return state.cardPolicyDetailState.updateFetchState;
|
|
22
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
import { from, of } from 'rxjs';
|
|
2
|
-
import { catchError, exhaustMap, filter, mergeMap } from 'rxjs/operators';
|
|
3
|
-
import { toCardPolicyEditFormDraft, toCardPolicyTemplate, } from '../../../../../entity/cardPolicy/cardPolicyPayload';
|
|
4
|
-
import { updateCreatedCardPolicyTemplate } from '../../../../../entity/cardPolicy/cardPolicyReducer';
|
|
5
|
-
import { createZeniAPIStatus, isSuccessStatus, } from '../../../../../responsePayload';
|
|
6
|
-
import { fetchCardPolicyDetail, updateCardPolicyDetailFetchStatus, updateCardPolicyFormDraft, } from './cardPolicyDetailReducer';
|
|
7
|
-
/**
|
|
8
|
-
* `GET /cards/1.0/policy-templates/{id}`. Response is the same
|
|
9
|
-
* `{cards_applied, template}` envelope the create endpoint returns.
|
|
10
|
-
* We:
|
|
11
|
-
*
|
|
12
|
-
* 1. Cache the template on the entity slice (so the list page picks
|
|
13
|
-
* up any drift from the server).
|
|
14
|
-
* 2. Seed the local edit-form draft from the camelCased template so
|
|
15
|
-
* the page can render with the existing values pre-populated.
|
|
16
|
-
* 3. Flip the view lifecycle to `Completed` / `Error`.
|
|
17
|
-
*/
|
|
18
|
-
export const fetchCardPolicyDetailEpic = (actions$, _state$, zeniAPI) => actions$.pipe(filter(fetchCardPolicyDetail.match),
|
|
19
|
-
// `exhaustMap` (rather than `mergeMap`) so a duplicate
|
|
20
|
-
// `fetchCardPolicyDetail` dispatched while the previous one is
|
|
21
|
-
// still in flight is dropped instead of producing a second HTTP
|
|
22
|
-
// request. The edit screen dispatches this on mount, and React 18
|
|
23
|
-
// StrictMode invokes its mount effect twice with a stale
|
|
24
|
-
// `detailFetchState` closure — without `exhaustMap` that yields
|
|
25
|
-
// two `/policy-templates/{id}` calls. (The screen also dedupes
|
|
26
|
-
// list→edit navigations via the entity-cached template, so the
|
|
27
|
-
// detail GET is only emitted on direct landings — there's no
|
|
28
|
-
// realistic cross-templateId scenario that needs cancel-and-retry
|
|
29
|
-
// semantics here.)
|
|
30
|
-
exhaustMap((action) => {
|
|
31
|
-
const templateId = action.payload;
|
|
32
|
-
return zeniAPI
|
|
33
|
-
.getJSON(`${zeniAPI.apiEndPoints.cardMicroServiceBaseUrl}/1.0/policy-templates/${templateId}`)
|
|
34
|
-
.pipe(mergeMap((response) => {
|
|
35
|
-
if (isSuccessStatus(response) && response.data != null) {
|
|
36
|
-
const { template } = response.data;
|
|
37
|
-
const formDraft = toCardPolicyEditFormDraft(toCardPolicyTemplate(template));
|
|
38
|
-
const actions = [
|
|
39
|
-
updateCreatedCardPolicyTemplate(template),
|
|
40
|
-
updateCardPolicyFormDraft(formDraft),
|
|
41
|
-
updateCardPolicyDetailFetchStatus({ fetchState: 'Completed' }),
|
|
42
|
-
];
|
|
43
|
-
return from(actions);
|
|
44
|
-
}
|
|
45
|
-
else {
|
|
46
|
-
return of(updateCardPolicyDetailFetchStatus({
|
|
47
|
-
fetchState: 'Error',
|
|
48
|
-
error: response.status,
|
|
49
|
-
}));
|
|
50
|
-
}
|
|
51
|
-
}), catchError((error) => of(updateCardPolicyDetailFetchStatus({
|
|
52
|
-
fetchState: 'Error',
|
|
53
|
-
error: createZeniAPIStatus('Unexpected Error', 'Fetch card-policy detail REST API call errored out' +
|
|
54
|
-
JSON.stringify(error)),
|
|
55
|
-
}))));
|
|
56
|
-
}));
|