@zeniai/client-epic-state 5.0.83-betaRR3 → 5.0.83-betaRR5
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/entity/aiCfo/aiCfoPayload.d.ts +1 -4
- package/lib/entity/aiCfo/aiCfoReducer.js +3 -11
- package/lib/entity/aiCfo/aiCfoState.d.ts +0 -19
- package/lib/entity/aiCfo/aiCfoState.js +1 -8
- package/lib/entity/cardPolicy/policyRecommendationFromUploadEpic.d.ts +3 -2
- package/lib/entity/cardPolicy/policyRecommendationFromUploadEpic.js +3 -2
- package/lib/epic.d.ts +14 -12
- package/lib/epic.js +14 -12
- package/lib/esm/entity/aiCfo/aiCfoReducer.js +4 -12
- package/lib/esm/entity/aiCfo/aiCfoState.js +0 -7
- package/lib/esm/entity/cardPolicy/policyRecommendationFromUploadEpic.js +4 -3
- package/lib/esm/epic.js +14 -12
- package/lib/esm/index.js +14 -3
- package/lib/esm/view/spendManagement/chargeCards/cardPolicy/createCardPolicy/applyAiCardPolicyFormDraftUpdate.js +328 -0
- package/lib/esm/view/spendManagement/chargeCards/cardPolicy/createCardPolicy/applyExtractedPolicyToAiCardPolicyDraft.js +120 -0
- package/lib/esm/view/spendManagement/chargeCards/cardPolicy/createCardPolicy/applyExtractedPolicyToDraftEpic.js +60 -0
- package/lib/esm/view/spendManagement/chargeCards/cardPolicy/createCardPolicy/applyExtractedPolicyToManualCardPolicyDraft.js +118 -0
- package/lib/esm/view/spendManagement/chargeCards/cardPolicy/createCardPolicy/applyUploadPlanToAiCardPolicyDraft.js +33 -0
- package/lib/esm/view/spendManagement/chargeCards/cardPolicy/createCardPolicy/buildAiCardPolicyFormDraftSeed.js +385 -0
- package/lib/esm/view/spendManagement/chargeCards/cardPolicy/createCardPolicy/buildManualCardPolicyFormDraftSeed.js +34 -0
- package/lib/esm/view/spendManagement/chargeCards/cardPolicy/createCardPolicy/cardPolicyChipIds.js +33 -0
- package/lib/esm/view/spendManagement/chargeCards/cardPolicy/createCardPolicy/cardPolicyFormDraftTypes.js +17 -0
- package/lib/esm/view/spendManagement/chargeCards/cardPolicy/createCardPolicy/cardPolicyRequestParts.js +144 -0
- package/lib/esm/view/spendManagement/chargeCards/cardPolicy/createCardPolicy/createCardPolicyReducer.js +137 -1
- package/lib/esm/view/spendManagement/chargeCards/cardPolicy/createCardPolicy/createCardPolicySelector.js +18 -0
- package/lib/esm/view/spendManagement/chargeCards/cardPolicy/createCardPolicy/deriveAiPolicyReviewRowsFromInputs.js +148 -0
- package/lib/esm/view/spendManagement/chargeCards/cardPolicy/createCardPolicy/seedAiCardPolicyFormDraftEpic.js +112 -0
- package/lib/esm/view/spendManagement/chargeCards/cardPolicy/createCardPolicy/toBulkCardPolicyTemplateRequestsFromDraft.js +101 -0
- package/lib/esm/view/spendManagement/chargeCards/cardPolicy/createCardPolicy/toCardPolicyTemplateRequestFromDraft.js +71 -0
- package/lib/esm/view/spendManagement/chargeCards/cardPolicy/createCardPolicy/toManualCardPolicyTemplateRequestFromDraft.js +34 -0
- package/lib/esm/view/spendManagement/chargeCards/issueChargeCard/applyAiCardCreationFormDraftUpdate.js +0 -1
- package/lib/esm/view/spendManagement/chargeCards/issueChargeCard/buildAiCardCreationFormDraftSeed.js +13 -6
- package/lib/esm/view/spendManagement/chargeCards/issueChargeCard/deriveAiCardRowsFromTeams.js +1 -3
- package/lib/esm/view/spendManagement/chargeCards/issueChargeCard/toIssueChargeCardLocalDataFromDraft.js +0 -5
- package/lib/index.d.ts +20 -4
- package/lib/index.js +45 -4
- package/lib/view/spendManagement/chargeCards/cardPolicy/createCardPolicy/applyAiCardPolicyFormDraftUpdate.d.ts +38 -0
- package/lib/view/spendManagement/chargeCards/cardPolicy/createCardPolicy/applyAiCardPolicyFormDraftUpdate.js +333 -0
- package/lib/view/spendManagement/chargeCards/cardPolicy/createCardPolicy/applyExtractedPolicyToAiCardPolicyDraft.d.ts +25 -0
- package/lib/view/spendManagement/chargeCards/cardPolicy/createCardPolicy/applyExtractedPolicyToAiCardPolicyDraft.js +124 -0
- package/lib/view/spendManagement/chargeCards/cardPolicy/createCardPolicy/applyExtractedPolicyToDraftEpic.d.ts +28 -0
- package/lib/view/spendManagement/chargeCards/cardPolicy/createCardPolicy/applyExtractedPolicyToDraftEpic.js +64 -0
- package/lib/view/spendManagement/chargeCards/cardPolicy/createCardPolicy/applyExtractedPolicyToManualCardPolicyDraft.d.ts +17 -0
- package/lib/view/spendManagement/chargeCards/cardPolicy/createCardPolicy/applyExtractedPolicyToManualCardPolicyDraft.js +122 -0
- package/lib/view/spendManagement/chargeCards/cardPolicy/createCardPolicy/applyUploadPlanToAiCardPolicyDraft.d.ts +23 -0
- package/lib/view/spendManagement/chargeCards/cardPolicy/createCardPolicy/applyUploadPlanToAiCardPolicyDraft.js +37 -0
- package/lib/view/spendManagement/chargeCards/cardPolicy/createCardPolicy/buildAiCardPolicyFormDraftSeed.d.ts +38 -0
- package/lib/view/spendManagement/chargeCards/cardPolicy/createCardPolicy/buildAiCardPolicyFormDraftSeed.js +391 -0
- package/lib/view/spendManagement/chargeCards/cardPolicy/createCardPolicy/buildManualCardPolicyFormDraftSeed.d.ts +11 -0
- package/lib/view/spendManagement/chargeCards/cardPolicy/createCardPolicy/buildManualCardPolicyFormDraftSeed.js +38 -0
- package/lib/view/spendManagement/chargeCards/cardPolicy/createCardPolicy/cardPolicyChipIds.d.ts +24 -0
- package/lib/view/spendManagement/chargeCards/cardPolicy/createCardPolicy/cardPolicyChipIds.js +40 -0
- package/lib/view/spendManagement/chargeCards/cardPolicy/createCardPolicy/cardPolicyFormDraftTypes.d.ts +253 -0
- package/lib/view/spendManagement/chargeCards/cardPolicy/createCardPolicy/cardPolicyFormDraftTypes.js +21 -0
- package/lib/view/spendManagement/chargeCards/cardPolicy/createCardPolicy/cardPolicyRequestParts.d.ts +66 -0
- package/lib/view/spendManagement/chargeCards/cardPolicy/createCardPolicy/cardPolicyRequestParts.js +151 -0
- package/lib/view/spendManagement/chargeCards/cardPolicy/createCardPolicy/createCardPolicyReducer.d.ts +40 -1
- package/lib/view/spendManagement/chargeCards/cardPolicy/createCardPolicy/createCardPolicyReducer.js +138 -2
- package/lib/view/spendManagement/chargeCards/cardPolicy/createCardPolicy/createCardPolicySelector.d.ts +15 -0
- package/lib/view/spendManagement/chargeCards/cardPolicy/createCardPolicy/createCardPolicySelector.js +20 -0
- package/lib/view/spendManagement/chargeCards/cardPolicy/createCardPolicy/createCardPolicyState.d.ts +28 -0
- package/lib/view/spendManagement/chargeCards/cardPolicy/createCardPolicy/deriveAiPolicyReviewRowsFromInputs.d.ts +30 -0
- package/lib/view/spendManagement/chargeCards/cardPolicy/createCardPolicy/deriveAiPolicyReviewRowsFromInputs.js +152 -0
- package/lib/view/spendManagement/chargeCards/cardPolicy/createCardPolicy/seedAiCardPolicyFormDraftEpic.d.ts +26 -0
- package/lib/view/spendManagement/chargeCards/cardPolicy/createCardPolicy/seedAiCardPolicyFormDraftEpic.js +116 -0
- package/lib/view/spendManagement/chargeCards/cardPolicy/createCardPolicy/toBulkCardPolicyTemplateRequestsFromDraft.d.ts +35 -0
- package/lib/view/spendManagement/chargeCards/cardPolicy/createCardPolicy/toBulkCardPolicyTemplateRequestsFromDraft.js +105 -0
- package/lib/view/spendManagement/chargeCards/cardPolicy/createCardPolicy/toCardPolicyTemplateRequestFromDraft.d.ts +23 -0
- package/lib/view/spendManagement/chargeCards/cardPolicy/createCardPolicy/toCardPolicyTemplateRequestFromDraft.js +75 -0
- package/lib/view/spendManagement/chargeCards/cardPolicy/createCardPolicy/toManualCardPolicyTemplateRequestFromDraft.d.ts +15 -0
- package/lib/view/spendManagement/chargeCards/cardPolicy/createCardPolicy/toManualCardPolicyTemplateRequestFromDraft.js +38 -0
- package/lib/view/spendManagement/chargeCards/issueChargeCard/aiCardCreationFormDraftTypes.d.ts +3 -6
- package/lib/view/spendManagement/chargeCards/issueChargeCard/applyAiCardCreationFormDraftUpdate.js +0 -1
- package/lib/view/spendManagement/chargeCards/issueChargeCard/buildAiCardCreationFormDraftSeed.d.ts +6 -3
- package/lib/view/spendManagement/chargeCards/issueChargeCard/buildAiCardCreationFormDraftSeed.js +13 -6
- package/lib/view/spendManagement/chargeCards/issueChargeCard/deriveAiCardRowsFromTeams.d.ts +1 -4
- package/lib/view/spendManagement/chargeCards/issueChargeCard/deriveAiCardRowsFromTeams.js +1 -3
- package/lib/view/spendManagement/chargeCards/issueChargeCard/toIssueChargeCardLocalDataFromDraft.js +0 -5
- package/package.json +1 -1
package/lib/view/spendManagement/chargeCards/cardPolicy/createCardPolicy/createCardPolicyReducer.js
CHANGED
|
@@ -1,8 +1,15 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
var _a;
|
|
3
3
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
-
exports.clearCreateCardPolicy = exports.updateCreateCardPolicyTemplateRequestState = exports.createCardPolicyTemplates = exports.initialState = void 0;
|
|
4
|
+
exports.clearCreateCardPolicy = exports.clearManualCardPolicyFormDraft = exports.applyExtractedPolicyToManualCardPolicyDraft = exports.updateManualCardPolicyFormDraft = exports.seedManualCardPolicyFormDraft = exports.clearAiCardPolicyFormDraft = exports.applyExtractedPolicyToAiCardPolicyDraft = exports.updateAiCardPolicyFormDraftFromUploadPlan = exports.updateAiCardPolicyFormDraft = exports.seedAiCardPolicyFormDraft = exports.updateCreateCardPolicyTemplateRequestState = exports.createCardPolicyTemplates = exports.initialState = void 0;
|
|
5
5
|
const toolkit_1 = require("@reduxjs/toolkit");
|
|
6
|
+
const applyAiCardPolicyFormDraftUpdate_1 = require("./applyAiCardPolicyFormDraftUpdate");
|
|
7
|
+
const applyExtractedPolicyToAiCardPolicyDraft_1 = require("./applyExtractedPolicyToAiCardPolicyDraft");
|
|
8
|
+
const applyExtractedPolicyToManualCardPolicyDraft_1 = require("./applyExtractedPolicyToManualCardPolicyDraft");
|
|
9
|
+
const applyUploadPlanToAiCardPolicyDraft_1 = require("./applyUploadPlanToAiCardPolicyDraft");
|
|
10
|
+
const buildAiCardPolicyFormDraftSeed_1 = require("./buildAiCardPolicyFormDraftSeed");
|
|
11
|
+
const buildManualCardPolicyFormDraftSeed_1 = require("./buildManualCardPolicyFormDraftSeed");
|
|
12
|
+
const cardPolicyFormDraftTypes_1 = require("./cardPolicyFormDraftTypes");
|
|
6
13
|
exports.initialState = {
|
|
7
14
|
createCardPolicyTemplateRequestState: {
|
|
8
15
|
fetchState: 'Not-Started',
|
|
@@ -40,10 +47,139 @@ const createCardPolicy = (0, toolkit_1.createSlice)({
|
|
|
40
47
|
draft.lastCreateCardPolicyTemplateErrors = action.payload.perItemErrors;
|
|
41
48
|
}
|
|
42
49
|
},
|
|
50
|
+
/**
|
|
51
|
+
* Seed the AI CFO card-policy form draft + companion context from
|
|
52
|
+
* the AI's `interactive_form` payload. Dispatched by
|
|
53
|
+
* `seedAiCardPolicyFormDraftEpic` when the AI answer lands.
|
|
54
|
+
*/
|
|
55
|
+
seedAiCardPolicyFormDraft: {
|
|
56
|
+
reducer(draft, action) {
|
|
57
|
+
const { draft: nextDraft, context } = (0, buildAiCardPolicyFormDraftSeed_1.buildAiCardPolicyFormDraftSeed)({
|
|
58
|
+
initialData: action.payload.initialData,
|
|
59
|
+
cardsMasterList: action.payload.cardsMasterList,
|
|
60
|
+
categorySearchOptions: action.payload.mccCategories.map(cardPolicyFormDraftTypes_1.toMccCategoryLike),
|
|
61
|
+
suggestedAllowMerchants: action.payload.suggestedAllowMerchants,
|
|
62
|
+
suggestedBlockMerchants: action.payload.suggestedBlockMerchants,
|
|
63
|
+
suggestedAllowCategories: (action.payload.suggestedAllowCategories ?? []).map(cardPolicyFormDraftTypes_1.toMccCategoryLike),
|
|
64
|
+
suggestedBlockCategories: (action.payload.suggestedBlockCategories ?? []).map(cardPolicyFormDraftTypes_1.toMccCategoryLike),
|
|
65
|
+
});
|
|
66
|
+
draft.aiCardPolicyFormDraft = nextDraft;
|
|
67
|
+
draft.aiCardPolicyFormDraftContext = context;
|
|
68
|
+
},
|
|
69
|
+
prepare(payload) {
|
|
70
|
+
return { payload };
|
|
71
|
+
},
|
|
72
|
+
},
|
|
73
|
+
/**
|
|
74
|
+
* Replace the AI card-policy form draft from the component's
|
|
75
|
+
* `watchHandler`. Delegates to `applyAiCardPolicyFormDraftUpdate`
|
|
76
|
+
* which:
|
|
77
|
+
* - guided: mirrors review-chip diffs into source slices then
|
|
78
|
+
* re-derives `policiesReview` from those slices,
|
|
79
|
+
* - upload: patches "Applied to Cards" chip group from
|
|
80
|
+
* `cardSelections`,
|
|
81
|
+
* - auto: pass-through.
|
|
82
|
+
*/
|
|
83
|
+
updateAiCardPolicyFormDraft(draft, action) {
|
|
84
|
+
draft.aiCardPolicyFormDraft = (0, applyAiCardPolicyFormDraftUpdate_1.applyAiCardPolicyFormDraftUpdate)({
|
|
85
|
+
prev: draft.aiCardPolicyFormDraft,
|
|
86
|
+
next: action.payload,
|
|
87
|
+
context: draft.aiCardPolicyFormDraftContext,
|
|
88
|
+
});
|
|
89
|
+
},
|
|
90
|
+
/**
|
|
91
|
+
* Apply a fresh `wizardPlan` returned by the upload-mode
|
|
92
|
+
* recommendation API to the AI draft. No-op when the draft isn't
|
|
93
|
+
* in `upload` mode.
|
|
94
|
+
*/
|
|
95
|
+
updateAiCardPolicyFormDraftFromUploadPlan: {
|
|
96
|
+
reducer(draft, action) {
|
|
97
|
+
if (draft.aiCardPolicyFormDraft == null ||
|
|
98
|
+
draft.aiCardPolicyFormDraftContext == null) {
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
const { draft: nextDraft, context } = (0, applyUploadPlanToAiCardPolicyDraft_1.applyUploadPlanToAiCardPolicyDraft)({
|
|
102
|
+
current: draft.aiCardPolicyFormDraft,
|
|
103
|
+
context: draft.aiCardPolicyFormDraftContext,
|
|
104
|
+
wizardPlan: action.payload.wizardPlan,
|
|
105
|
+
source: action.payload.source,
|
|
106
|
+
});
|
|
107
|
+
draft.aiCardPolicyFormDraft = nextDraft;
|
|
108
|
+
draft.aiCardPolicyFormDraftContext = context;
|
|
109
|
+
},
|
|
110
|
+
prepare(wizardPlan, source) {
|
|
111
|
+
return { payload: { wizardPlan, source } };
|
|
112
|
+
},
|
|
113
|
+
},
|
|
114
|
+
/**
|
|
115
|
+
* Apply an extracted policy document response to the AI draft.
|
|
116
|
+
* Dispatched by the extract-success bridge epic when the upload
|
|
117
|
+
* was kicked off from inside an AI CFO card-policy form.
|
|
118
|
+
*/
|
|
119
|
+
applyExtractedPolicyToAiCardPolicyDraft: {
|
|
120
|
+
reducer(draft, action) {
|
|
121
|
+
if (draft.aiCardPolicyFormDraft == null) {
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
draft.aiCardPolicyFormDraft = (0, applyExtractedPolicyToAiCardPolicyDraft_1.applyExtractedPolicyToAiCardPolicyDraft)({
|
|
125
|
+
current: draft.aiCardPolicyFormDraft,
|
|
126
|
+
extracted: action.payload.extracted,
|
|
127
|
+
vendorSearchOptions: action.payload.vendorSearchOptions,
|
|
128
|
+
categorySearchOptions: action.payload.categorySearchOptions,
|
|
129
|
+
});
|
|
130
|
+
},
|
|
131
|
+
prepare(payload) {
|
|
132
|
+
return { payload };
|
|
133
|
+
},
|
|
134
|
+
},
|
|
135
|
+
clearAiCardPolicyFormDraft(draft) {
|
|
136
|
+
draft.aiCardPolicyFormDraft = undefined;
|
|
137
|
+
draft.aiCardPolicyFormDraftContext = undefined;
|
|
138
|
+
},
|
|
139
|
+
/**
|
|
140
|
+
* Seed the manual `CardPolicyCreatePage` form draft from the BE
|
|
141
|
+
* suggested merchant/category seeds + the cards master list.
|
|
142
|
+
* Dispatched on the create-page mount.
|
|
143
|
+
*/
|
|
144
|
+
seedManualCardPolicyFormDraft: {
|
|
145
|
+
reducer(draft, action) {
|
|
146
|
+
draft.manualCardPolicyFormDraft = (0, buildManualCardPolicyFormDraftSeed_1.buildManualCardPolicyFormDraftSeed)(action.payload);
|
|
147
|
+
},
|
|
148
|
+
prepare(payload) {
|
|
149
|
+
return { payload };
|
|
150
|
+
},
|
|
151
|
+
},
|
|
152
|
+
updateManualCardPolicyFormDraft(draft, action) {
|
|
153
|
+
draft.manualCardPolicyFormDraft = action.payload;
|
|
154
|
+
},
|
|
155
|
+
/**
|
|
156
|
+
* Apply an extracted policy document response to the manual draft.
|
|
157
|
+
* Dispatched by the extract-success bridge epic when the upload was
|
|
158
|
+
* kicked off from the manual `CardPolicyCreatePage`.
|
|
159
|
+
*/
|
|
160
|
+
applyExtractedPolicyToManualCardPolicyDraft: {
|
|
161
|
+
reducer(draft, action) {
|
|
162
|
+
if (draft.manualCardPolicyFormDraft == null) {
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
draft.manualCardPolicyFormDraft = (0, applyExtractedPolicyToManualCardPolicyDraft_1.applyExtractedPolicyToManualCardPolicyDraft)({
|
|
166
|
+
current: draft.manualCardPolicyFormDraft,
|
|
167
|
+
extracted: action.payload.extracted,
|
|
168
|
+
vendorSearchOptions: action.payload.vendorSearchOptions,
|
|
169
|
+
categorySearchOptions: action.payload.categorySearchOptions,
|
|
170
|
+
});
|
|
171
|
+
},
|
|
172
|
+
prepare(payload) {
|
|
173
|
+
return { payload };
|
|
174
|
+
},
|
|
175
|
+
},
|
|
176
|
+
clearManualCardPolicyFormDraft(draft) {
|
|
177
|
+
draft.manualCardPolicyFormDraft = undefined;
|
|
178
|
+
},
|
|
43
179
|
clearCreateCardPolicy(draft) {
|
|
44
180
|
Object.assign(draft, exports.initialState);
|
|
45
181
|
},
|
|
46
182
|
},
|
|
47
183
|
});
|
|
48
|
-
_a = createCardPolicy.actions, exports.createCardPolicyTemplates = _a.createCardPolicyTemplates, exports.updateCreateCardPolicyTemplateRequestState = _a.updateCreateCardPolicyTemplateRequestState, exports.clearCreateCardPolicy = _a.clearCreateCardPolicy;
|
|
184
|
+
_a = createCardPolicy.actions, exports.createCardPolicyTemplates = _a.createCardPolicyTemplates, exports.updateCreateCardPolicyTemplateRequestState = _a.updateCreateCardPolicyTemplateRequestState, exports.seedAiCardPolicyFormDraft = _a.seedAiCardPolicyFormDraft, exports.updateAiCardPolicyFormDraft = _a.updateAiCardPolicyFormDraft, exports.updateAiCardPolicyFormDraftFromUploadPlan = _a.updateAiCardPolicyFormDraftFromUploadPlan, exports.applyExtractedPolicyToAiCardPolicyDraft = _a.applyExtractedPolicyToAiCardPolicyDraft, exports.clearAiCardPolicyFormDraft = _a.clearAiCardPolicyFormDraft, exports.seedManualCardPolicyFormDraft = _a.seedManualCardPolicyFormDraft, exports.updateManualCardPolicyFormDraft = _a.updateManualCardPolicyFormDraft, exports.applyExtractedPolicyToManualCardPolicyDraft = _a.applyExtractedPolicyToManualCardPolicyDraft, exports.clearManualCardPolicyFormDraft = _a.clearManualCardPolicyFormDraft, exports.clearCreateCardPolicy = _a.clearCreateCardPolicy;
|
|
49
185
|
exports.default = createCardPolicy.reducer;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { FetchStateAndError, ID } from '../../../../../commonStateTypes/common';
|
|
2
2
|
import { BulkCreateCardPolicyTemplateError } from '../../../../../entity/cardPolicy/cardPolicyPayload';
|
|
3
|
+
import { CardPolicyCreateFormDraft, CardPolicyFormDraft } from './cardPolicyFormDraftTypes';
|
|
3
4
|
import { CreateCardPolicyState } from './createCardPolicyState';
|
|
4
5
|
export declare function getCreateCardPolicyTemplateRequestState(state: CreateCardPolicyState): FetchStateAndError;
|
|
5
6
|
/**
|
|
@@ -30,3 +31,17 @@ export declare function getLastCreateCardPolicyTemplateErrors(state: CreateCardP
|
|
|
30
31
|
* "created" placeholders to the active conversation.
|
|
31
32
|
*/
|
|
32
33
|
export declare function getLastCreateCardPolicySourceChatSessionId(state: CreateCardPolicyState): ID | undefined;
|
|
34
|
+
/**
|
|
35
|
+
* Returns the AI CFO card-policy form draft, or `undefined` before
|
|
36
|
+
* `seedAiCardPolicyFormDraft` runs / after `clearAiCardPolicyFormDraft`.
|
|
37
|
+
* Connected screens use this to hydrate the
|
|
38
|
+
* `CardPolicyInteractiveForm`'s RHF.
|
|
39
|
+
*/
|
|
40
|
+
export declare function getAiCardPolicyFormDraft(state: CreateCardPolicyState): CardPolicyFormDraft | undefined;
|
|
41
|
+
/**
|
|
42
|
+
* Returns the manual `CardPolicyCreatePage` form draft, or `undefined`
|
|
43
|
+
* before `seedManualCardPolicyFormDraft` runs / after
|
|
44
|
+
* `clearManualCardPolicyFormDraft`. The connected screen uses this to
|
|
45
|
+
* hydrate `CardPolicyFormSections`.
|
|
46
|
+
*/
|
|
47
|
+
export declare function getManualCardPolicyFormDraft(state: CreateCardPolicyState): CardPolicyCreateFormDraft | undefined;
|
package/lib/view/spendManagement/chargeCards/cardPolicy/createCardPolicy/createCardPolicySelector.js
CHANGED
|
@@ -5,6 +5,8 @@ exports.getLastCreatedCardPolicyTemplateIds = getLastCreatedCardPolicyTemplateId
|
|
|
5
5
|
exports.getLastCreatedCardPolicyTemplateId = getLastCreatedCardPolicyTemplateId;
|
|
6
6
|
exports.getLastCreateCardPolicyTemplateErrors = getLastCreateCardPolicyTemplateErrors;
|
|
7
7
|
exports.getLastCreateCardPolicySourceChatSessionId = getLastCreateCardPolicySourceChatSessionId;
|
|
8
|
+
exports.getAiCardPolicyFormDraft = getAiCardPolicyFormDraft;
|
|
9
|
+
exports.getManualCardPolicyFormDraft = getManualCardPolicyFormDraft;
|
|
8
10
|
function getCreateCardPolicyTemplateRequestState(state) {
|
|
9
11
|
return state.createCardPolicyTemplateRequestState;
|
|
10
12
|
}
|
|
@@ -44,3 +46,21 @@ function getLastCreateCardPolicyTemplateErrors(state) {
|
|
|
44
46
|
function getLastCreateCardPolicySourceChatSessionId(state) {
|
|
45
47
|
return state.lastCreateCardPolicySourceChatSessionId;
|
|
46
48
|
}
|
|
49
|
+
/**
|
|
50
|
+
* Returns the AI CFO card-policy form draft, or `undefined` before
|
|
51
|
+
* `seedAiCardPolicyFormDraft` runs / after `clearAiCardPolicyFormDraft`.
|
|
52
|
+
* Connected screens use this to hydrate the
|
|
53
|
+
* `CardPolicyInteractiveForm`'s RHF.
|
|
54
|
+
*/
|
|
55
|
+
function getAiCardPolicyFormDraft(state) {
|
|
56
|
+
return state.aiCardPolicyFormDraft;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Returns the manual `CardPolicyCreatePage` form draft, or `undefined`
|
|
60
|
+
* before `seedManualCardPolicyFormDraft` runs / after
|
|
61
|
+
* `clearManualCardPolicyFormDraft`. The connected screen uses this to
|
|
62
|
+
* hydrate `CardPolicyFormSections`.
|
|
63
|
+
*/
|
|
64
|
+
function getManualCardPolicyFormDraft(state) {
|
|
65
|
+
return state.manualCardPolicyFormDraft;
|
|
66
|
+
}
|
package/lib/view/spendManagement/chargeCards/cardPolicy/createCardPolicy/createCardPolicyState.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { FetchStateAndError, ID } from '../../../../../commonStateTypes/common';
|
|
2
2
|
import { BulkCreateCardPolicyTemplateError } from '../../../../../entity/cardPolicy/cardPolicyPayload';
|
|
3
|
+
import { AiCardPolicyFormDraftSeedContext, CardPolicyCreateFormDraft, CardPolicyFormDraft } from './cardPolicyFormDraftTypes';
|
|
3
4
|
/**
|
|
4
5
|
* View-side scaffolding for the Card Policy "create" flow.
|
|
5
6
|
*
|
|
@@ -33,6 +34,25 @@ export interface CreateCardPolicyState {
|
|
|
33
34
|
* ergonomic single-create routing.
|
|
34
35
|
*/
|
|
35
36
|
lastCreatedCardPolicyTemplateIds: ID[];
|
|
37
|
+
/**
|
|
38
|
+
* AI CFO card-policy interactive form draft. Hydrates the
|
|
39
|
+
* `CardPolicyInteractiveForm` and is replaced wholesale on every
|
|
40
|
+
* `watchHandler` tick via `updateAiCardPolicyFormDraft`. `undefined`
|
|
41
|
+
* before `seedAiCardPolicyFormDraft` runs and after
|
|
42
|
+
* `clearAiCardPolicyFormDraft`.
|
|
43
|
+
*/
|
|
44
|
+
aiCardPolicyFormDraft?: CardPolicyFormDraft;
|
|
45
|
+
/**
|
|
46
|
+
* Companion seed context for `aiCardPolicyFormDraft`. Keeps the seed
|
|
47
|
+
* universes (cards master list, MCC categories, suggested seed
|
|
48
|
+
* chips, suggested policies seed) so subsequent
|
|
49
|
+
* `updateAiCardPolicyFormDraft` dispatches can re-derive the review
|
|
50
|
+
* rows / "Applied to Cards" group without the component re-passing
|
|
51
|
+
* the universe each tick. Also stores the latest `wizardPlan` so
|
|
52
|
+
* `applyUploadPlanToAiCardPolicyDraft` can re-seed the review when
|
|
53
|
+
* a late `policy-recommendation-from-upload` response lands.
|
|
54
|
+
*/
|
|
55
|
+
aiCardPolicyFormDraftContext?: AiCardPolicyFormDraftSeedContext;
|
|
36
56
|
/**
|
|
37
57
|
* Chat session id from `sourceChatSessionId` on the most recent
|
|
38
58
|
* `createCardPolicyTemplates` dispatch — i.e. the AI CFO conversation
|
|
@@ -42,4 +62,12 @@ export interface CreateCardPolicyState {
|
|
|
42
62
|
* screen (which omits `sourceChatSessionId`).
|
|
43
63
|
*/
|
|
44
64
|
lastCreateCardPolicySourceChatSessionId?: ID;
|
|
65
|
+
/**
|
|
66
|
+
* Manual `CardPolicyCreatePage` form draft. Hydrates the create
|
|
67
|
+
* page's `CardPolicyFormSections` and is replaced wholesale on every
|
|
68
|
+
* `watchHandler` tick via `updateManualCardPolicyFormDraft`.
|
|
69
|
+
* `undefined` before `seedManualCardPolicyFormDraft` runs and after
|
|
70
|
+
* `clearManualCardPolicyFormDraft`.
|
|
71
|
+
*/
|
|
72
|
+
manualCardPolicyFormDraft?: CardPolicyCreateFormDraft;
|
|
45
73
|
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { CardPolicyAllowBlockFieldValue, CardPolicyCardSelectionRow, CardPolicyLimitFieldValue, CardPolicyReviewRow, CardPolicySuggestedPolicySeed } from './cardPolicyFormDraftTypes';
|
|
2
|
+
export interface DeriveAiPolicyReviewRowsFromInputsArgs {
|
|
3
|
+
cardSelections: CardPolicyCardSelectionRow[];
|
|
4
|
+
categoryPolicy: CardPolicyAllowBlockFieldValue;
|
|
5
|
+
limits: CardPolicyLimitFieldValue[];
|
|
6
|
+
/**
|
|
7
|
+
* Existing review rows from the prior draft. User edits to
|
|
8
|
+
* checked-state are preserved when the source row still exists;
|
|
9
|
+
* chip-level `isSelected` flags are preserved across rebuilds.
|
|
10
|
+
*/
|
|
11
|
+
prevPoliciesReview: CardPolicyReviewRow[];
|
|
12
|
+
/**
|
|
13
|
+
* Identity-only seed (id + name + isChecked). One output row per
|
|
14
|
+
* seed entry, in the same order.
|
|
15
|
+
*/
|
|
16
|
+
suggestedPoliciesSeed: CardPolicySuggestedPolicySeed[];
|
|
17
|
+
vendorPolicy: CardPolicyAllowBlockFieldValue;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Compose the Step 5 review rows from the live Step 1–4 form state.
|
|
21
|
+
*
|
|
22
|
+
* - One row per `suggestedPoliciesSeed` entry, in the same order.
|
|
23
|
+
* - Per-row `isChecked` preserved from `prevPoliciesReview`; otherwise
|
|
24
|
+
* falls back to the seed value.
|
|
25
|
+
* - Chip groups rebuilt from the live vendor / category / card / limit
|
|
26
|
+
* slices, with per-chip `isSelected` merged from the previous build
|
|
27
|
+
* so user-removed (`+ name`) chips don't snap back when an upstream
|
|
28
|
+
* slice changes.
|
|
29
|
+
*/
|
|
30
|
+
export declare const deriveAiPolicyReviewRowsFromInputs: ({ vendorPolicy, categoryPolicy, cardSelections, limits, suggestedPoliciesSeed, prevPoliciesReview, }: DeriveAiPolicyReviewRowsFromInputsArgs) => CardPolicyReviewRow[];
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.deriveAiPolicyReviewRowsFromInputs = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Compose the Step 5 review rows from the live Step 1–4 form state.
|
|
6
|
+
*
|
|
7
|
+
* - One row per `suggestedPoliciesSeed` entry, in the same order.
|
|
8
|
+
* - Per-row `isChecked` preserved from `prevPoliciesReview`; otherwise
|
|
9
|
+
* falls back to the seed value.
|
|
10
|
+
* - Chip groups rebuilt from the live vendor / category / card / limit
|
|
11
|
+
* slices, with per-chip `isSelected` merged from the previous build
|
|
12
|
+
* so user-removed (`+ name`) chips don't snap back when an upstream
|
|
13
|
+
* slice changes.
|
|
14
|
+
*/
|
|
15
|
+
const deriveAiPolicyReviewRowsFromInputs = ({ vendorPolicy, categoryPolicy, cardSelections, limits, suggestedPoliciesSeed, prevPoliciesReview, }) => {
|
|
16
|
+
const prevById = new Map(prevPoliciesReview.map((row) => [row.id, row]));
|
|
17
|
+
const groups = deriveSharedChipGroups({
|
|
18
|
+
vendorPolicy,
|
|
19
|
+
categoryPolicy,
|
|
20
|
+
cardSelections,
|
|
21
|
+
limits,
|
|
22
|
+
});
|
|
23
|
+
return suggestedPoliciesSeed.map((seed) => {
|
|
24
|
+
const previous = prevById.get(seed.id);
|
|
25
|
+
return {
|
|
26
|
+
id: seed.id,
|
|
27
|
+
name: seed.name,
|
|
28
|
+
isChecked: previous?.isChecked ?? seed.isChecked,
|
|
29
|
+
chipGroups: previous != null
|
|
30
|
+
? mergeChipSelections(groups, previous.chipGroups)
|
|
31
|
+
: groups,
|
|
32
|
+
};
|
|
33
|
+
});
|
|
34
|
+
};
|
|
35
|
+
exports.deriveAiPolicyReviewRowsFromInputs = deriveAiPolicyReviewRowsFromInputs;
|
|
36
|
+
const mergeChipSelections = (next, prev) => {
|
|
37
|
+
const prevByGroupId = new Map(prev.map((group) => [group.id, group]));
|
|
38
|
+
return next.map((group) => {
|
|
39
|
+
const prevGroup = prevByGroupId.get(group.id);
|
|
40
|
+
if (prevGroup == null) {
|
|
41
|
+
return group;
|
|
42
|
+
}
|
|
43
|
+
const prevSelectedById = new Map(prevGroup.chips.map((chip) => [chip.id, chip.isSelected]));
|
|
44
|
+
return {
|
|
45
|
+
...group,
|
|
46
|
+
chips: group.chips.map((chip) => {
|
|
47
|
+
const prevSelected = prevSelectedById.get(chip.id);
|
|
48
|
+
return prevSelected === undefined
|
|
49
|
+
? chip
|
|
50
|
+
: { ...chip, isSelected: prevSelected };
|
|
51
|
+
}),
|
|
52
|
+
};
|
|
53
|
+
});
|
|
54
|
+
};
|
|
55
|
+
const deriveSharedChipGroups = ({ vendorPolicy, categoryPolicy, cardSelections, limits, }) => {
|
|
56
|
+
const groups = [];
|
|
57
|
+
const vendorChips = chipsFromAllowBlock(vendorPolicy);
|
|
58
|
+
if (vendorChips.length > 0) {
|
|
59
|
+
groups.push({
|
|
60
|
+
id: 'vendors',
|
|
61
|
+
label: vendorPolicy.mode === 'allow' ? 'Allowed vendors' : 'Blocked vendors',
|
|
62
|
+
chips: vendorChips,
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
const categoryChips = chipsFromAllowBlock(categoryPolicy);
|
|
66
|
+
if (categoryChips.length > 0) {
|
|
67
|
+
groups.push({
|
|
68
|
+
id: 'categories',
|
|
69
|
+
label: categoryPolicy.mode === 'allow'
|
|
70
|
+
? 'Allowed categories'
|
|
71
|
+
: 'Blocked categories',
|
|
72
|
+
chips: categoryChips,
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
const cardChips = cardSelections
|
|
76
|
+
.filter((row) => row.isChecked)
|
|
77
|
+
.map((row) => ({
|
|
78
|
+
id: row.id,
|
|
79
|
+
label: row.owner.displayName,
|
|
80
|
+
chipKind: 'avatar',
|
|
81
|
+
}));
|
|
82
|
+
if (cardChips.length > 0) {
|
|
83
|
+
groups.push({ id: 'cardholders', label: 'Cardholders', chips: cardChips });
|
|
84
|
+
}
|
|
85
|
+
const limitChips = limits.map((row) => ({
|
|
86
|
+
id: limitChipIdForRowId(row.id),
|
|
87
|
+
label: limitDisplayLabelForRowId(row.id),
|
|
88
|
+
helperText: limitHelperTextForRowId(row.id),
|
|
89
|
+
placeholder: '$0',
|
|
90
|
+
chipKind: 'positive',
|
|
91
|
+
isSelected: row.isEnabled,
|
|
92
|
+
optionalCode: row.isEnabled && row.amount != null ? String(row.amount) : undefined,
|
|
93
|
+
}));
|
|
94
|
+
if (limitChips.length > 0) {
|
|
95
|
+
groups.push({
|
|
96
|
+
id: 'limits',
|
|
97
|
+
label: 'Limits',
|
|
98
|
+
kind: 'limits',
|
|
99
|
+
chips: limitChips,
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
return groups;
|
|
103
|
+
};
|
|
104
|
+
const chipsFromAllowBlock = (field) => {
|
|
105
|
+
const items = field.mode === 'allow' ? field.allowItems : field.blockItems;
|
|
106
|
+
return items
|
|
107
|
+
.filter((item) => item.isSelected)
|
|
108
|
+
.map((item) => ({
|
|
109
|
+
id: item.id,
|
|
110
|
+
label: item.optionalCode != null
|
|
111
|
+
? `${item.label} (${item.optionalCode})`
|
|
112
|
+
: item.label,
|
|
113
|
+
chipKind: field.mode === 'allow' ? 'positive' : 'negative',
|
|
114
|
+
}));
|
|
115
|
+
};
|
|
116
|
+
const limitChipIdForRowId = (rowId) => {
|
|
117
|
+
if (rowId === 'transactionLimit') {
|
|
118
|
+
return 'limit-transaction';
|
|
119
|
+
}
|
|
120
|
+
if (rowId === 'requireReceipt') {
|
|
121
|
+
return 'limit-receipt';
|
|
122
|
+
}
|
|
123
|
+
return rowId;
|
|
124
|
+
};
|
|
125
|
+
const limitDisplayLabelForRowId = (rowId) => {
|
|
126
|
+
if (rowId === 'transactionLimit') {
|
|
127
|
+
return 'Transaction Limit';
|
|
128
|
+
}
|
|
129
|
+
if (rowId === 'requireReceipt') {
|
|
130
|
+
return 'Require Receipt';
|
|
131
|
+
}
|
|
132
|
+
return humanizeLimitId(rowId);
|
|
133
|
+
};
|
|
134
|
+
const limitHelperTextForRowId = (rowId) => {
|
|
135
|
+
if (rowId === 'transactionLimit') {
|
|
136
|
+
return 'Maximum amount per single transaction';
|
|
137
|
+
}
|
|
138
|
+
if (rowId === 'requireReceipt') {
|
|
139
|
+
return 'Require a receipt above this amount';
|
|
140
|
+
}
|
|
141
|
+
return undefined;
|
|
142
|
+
};
|
|
143
|
+
const humanizeLimitId = (id) => {
|
|
144
|
+
const spaced = id
|
|
145
|
+
.replace(/([A-Z])/g, ' $1')
|
|
146
|
+
.replace(/[_-]+/g, ' ')
|
|
147
|
+
.trim();
|
|
148
|
+
if (spaced.length === 0) {
|
|
149
|
+
return id;
|
|
150
|
+
}
|
|
151
|
+
return spaced.charAt(0).toUpperCase() + spaced.slice(1).toLowerCase();
|
|
152
|
+
};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { ActionsObservable, StateObservable } from 'redux-observable';
|
|
2
|
+
import { Observable } from 'rxjs';
|
|
3
|
+
import { upsertAnswerPayload, upsertOrAddQuestionAnswerPayload } from '../../../../../entity/aiCfo/aiCfoReducer';
|
|
4
|
+
import { fetchCardPolicyMccCategories } from '../../../../../entity/cardPolicy/cardPolicyReducer';
|
|
5
|
+
import { RootState } from '../../../../../reducer';
|
|
6
|
+
import { clearAiCardPolicyFormDraft, createCardPolicyTemplates, seedAiCardPolicyFormDraft, updateCreateCardPolicyTemplateRequestState } from './createCardPolicyReducer';
|
|
7
|
+
export type ActionType = ReturnType<typeof fetchCardPolicyMccCategories> | ReturnType<typeof seedAiCardPolicyFormDraft> | ReturnType<typeof clearAiCardPolicyFormDraft>;
|
|
8
|
+
type SeedTriggerAction = ReturnType<typeof upsertAnswerPayload> | ReturnType<typeof upsertOrAddQuestionAnswerPayload>;
|
|
9
|
+
type InboundAction = SeedTriggerAction | ReturnType<typeof createCardPolicyTemplates> | ReturnType<typeof updateCreateCardPolicyTemplateRequestState>;
|
|
10
|
+
/**
|
|
11
|
+
* Listens for AI CFO `interactive_form` answers with
|
|
12
|
+
* `formType === "card_policy"` and seeds the AI card-policy form
|
|
13
|
+
* draft + companion context onto `createCardPolicy` state. Mirrors
|
|
14
|
+
* `seedAiCardCreationFormDraftEpic` for the cards form.
|
|
15
|
+
*
|
|
16
|
+
* Also clears the draft on a successful bulk create so a stale draft
|
|
17
|
+
* doesn't leak into the next AI session.
|
|
18
|
+
*
|
|
19
|
+
* MCC categories drive category chip labels in the seed. When the
|
|
20
|
+
* categories slice isn't loaded yet, the epic kicks off
|
|
21
|
+
* `fetchCardPolicyMccCategories` and waits for `Completed` before
|
|
22
|
+
* dispatching the seed (mirrors `fetchUserListByType` in the cards
|
|
23
|
+
* variant).
|
|
24
|
+
*/
|
|
25
|
+
export declare const seedAiCardPolicyFormDraftEpic: (actions$: ActionsObservable<InboundAction>, state$: StateObservable<RootState>) => Observable<ActionType>;
|
|
26
|
+
export {};
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.seedAiCardPolicyFormDraftEpic = void 0;
|
|
4
|
+
const rxjs_1 = require("rxjs");
|
|
5
|
+
const operators_1 = require("rxjs/operators");
|
|
6
|
+
const aiCfoReducer_1 = require("../../../../../entity/aiCfo/aiCfoReducer");
|
|
7
|
+
const aiCfoSelector_1 = require("../../../../../entity/aiCfo/aiCfoSelector");
|
|
8
|
+
const cardPolicyReducer_1 = require("../../../../../entity/cardPolicy/cardPolicyReducer");
|
|
9
|
+
const chargeCardListSelector_1 = require("../../chargeCardList/chargeCardListSelector");
|
|
10
|
+
const createCardPolicyReducer_1 = require("./createCardPolicyReducer");
|
|
11
|
+
const isClosedChargeCardStatusCode = (code) => code === 'closed' || code === 'closed_by_customer';
|
|
12
|
+
const toCardPolicyCardSelectionRow = (card) => {
|
|
13
|
+
const user = card.cardHolderUser;
|
|
14
|
+
const displayName = `${user.firstName ?? ''} ${user.lastName ?? ''}`.trim() ||
|
|
15
|
+
user.email ||
|
|
16
|
+
user.userId;
|
|
17
|
+
return {
|
|
18
|
+
id: card.id,
|
|
19
|
+
isChecked: false,
|
|
20
|
+
cardName: card.cardName,
|
|
21
|
+
last4: card.accountLast4,
|
|
22
|
+
limitAmount: card.limit?.amount ?? 0,
|
|
23
|
+
limitCadence: card.creditLimitFrequency?.code,
|
|
24
|
+
owner: {
|
|
25
|
+
userId: user.userId,
|
|
26
|
+
displayName,
|
|
27
|
+
roleLabel: card.cardHolderRoles?.titleAtCompany,
|
|
28
|
+
},
|
|
29
|
+
utilizationAmount: (card.limit?.amount ?? 0) - (card.available?.amount ?? 0),
|
|
30
|
+
};
|
|
31
|
+
};
|
|
32
|
+
const readCardsMasterList = (state) => {
|
|
33
|
+
const view = (0, chargeCardListSelector_1.getAllChargeCardsWithUser)(state);
|
|
34
|
+
return view.cards
|
|
35
|
+
.filter((card) => !isClosedChargeCardStatusCode(card.status?.code))
|
|
36
|
+
.map(toCardPolicyCardSelectionRow);
|
|
37
|
+
};
|
|
38
|
+
const readMccCategoriesAvailable = (state) => state.cardPolicyState.mccCategoriesFetchState === 'Completed';
|
|
39
|
+
const readCardPolicyPayload = (state, chatSessionId, questionAnswerId) => {
|
|
40
|
+
const qa = (0, aiCfoSelector_1.getQuestionAnswerByIdForChatSession)(state.aiCfoState, chatSessionId, questionAnswerId);
|
|
41
|
+
const visualization = qa?.responses.answer?.content.visualization;
|
|
42
|
+
if (visualization?.type !== 'interactive_form') {
|
|
43
|
+
return undefined;
|
|
44
|
+
}
|
|
45
|
+
const data = visualization.data;
|
|
46
|
+
if (!('formType' in data) || data.formType !== 'card_policy') {
|
|
47
|
+
return undefined;
|
|
48
|
+
}
|
|
49
|
+
return data.payload;
|
|
50
|
+
};
|
|
51
|
+
const resolveQuestionAnswerId = (state, action) => {
|
|
52
|
+
if (action.payload.questionAnswerId != null) {
|
|
53
|
+
return action.payload.questionAnswerId;
|
|
54
|
+
}
|
|
55
|
+
const session = state.aiCfoState.aiCfoByChatSessionId[action.payload.chatSessionId];
|
|
56
|
+
return session?.questionAnswers.slice(-1)[0]?.questionAnswerId;
|
|
57
|
+
};
|
|
58
|
+
const isSeedTrigger = (action) => aiCfoReducer_1.upsertAnswerPayload.match(action) ||
|
|
59
|
+
aiCfoReducer_1.upsertOrAddQuestionAnswerPayload.match(action);
|
|
60
|
+
const isCreateSuccess = (action) => createCardPolicyReducer_1.updateCreateCardPolicyTemplateRequestState.match(action) &&
|
|
61
|
+
action.payload.fetchState === 'Completed';
|
|
62
|
+
const buildSeedAction = (state, payload) => {
|
|
63
|
+
const cardsMasterList = readCardsMasterList(state);
|
|
64
|
+
const mccCategories = state.cardPolicyState.mccCategories;
|
|
65
|
+
return (0, createCardPolicyReducer_1.seedAiCardPolicyFormDraft)({
|
|
66
|
+
initialData: payload,
|
|
67
|
+
cardsMasterList,
|
|
68
|
+
mccCategories,
|
|
69
|
+
suggestedAllowMerchants: state.cardPolicyState.suggestedAllowMerchants,
|
|
70
|
+
suggestedBlockMerchants: state.cardPolicyState.suggestedBlockMerchants,
|
|
71
|
+
suggestedAllowCategories: state.cardPolicyState.suggestedAllowCategories,
|
|
72
|
+
suggestedBlockCategories: state.cardPolicyState.suggestedBlockCategories,
|
|
73
|
+
});
|
|
74
|
+
};
|
|
75
|
+
/**
|
|
76
|
+
* Listens for AI CFO `interactive_form` answers with
|
|
77
|
+
* `formType === "card_policy"` and seeds the AI card-policy form
|
|
78
|
+
* draft + companion context onto `createCardPolicy` state. Mirrors
|
|
79
|
+
* `seedAiCardCreationFormDraftEpic` for the cards form.
|
|
80
|
+
*
|
|
81
|
+
* Also clears the draft on a successful bulk create so a stale draft
|
|
82
|
+
* doesn't leak into the next AI session.
|
|
83
|
+
*
|
|
84
|
+
* MCC categories drive category chip labels in the seed. When the
|
|
85
|
+
* categories slice isn't loaded yet, the epic kicks off
|
|
86
|
+
* `fetchCardPolicyMccCategories` and waits for `Completed` before
|
|
87
|
+
* dispatching the seed (mirrors `fetchUserListByType` in the cards
|
|
88
|
+
* variant).
|
|
89
|
+
*/
|
|
90
|
+
const seedAiCardPolicyFormDraftEpic = (actions$, state$) => actions$.pipe((0, operators_1.mergeMap)((action) => {
|
|
91
|
+
if (isCreateSuccess(action)) {
|
|
92
|
+
return (0, rxjs_1.of)((0, createCardPolicyReducer_1.clearAiCardPolicyFormDraft)());
|
|
93
|
+
}
|
|
94
|
+
if (!isSeedTrigger(action)) {
|
|
95
|
+
return rxjs_1.EMPTY;
|
|
96
|
+
}
|
|
97
|
+
const state = state$.value;
|
|
98
|
+
const questionAnswerId = resolveQuestionAnswerId(state, action);
|
|
99
|
+
if (questionAnswerId == null) {
|
|
100
|
+
return rxjs_1.EMPTY;
|
|
101
|
+
}
|
|
102
|
+
const payload = readCardPolicyPayload(state, action.payload.chatSessionId, questionAnswerId);
|
|
103
|
+
if (payload == null) {
|
|
104
|
+
return rxjs_1.EMPTY;
|
|
105
|
+
}
|
|
106
|
+
if (readMccCategoriesAvailable(state)) {
|
|
107
|
+
return (0, rxjs_1.of)(buildSeedAction(state, payload));
|
|
108
|
+
}
|
|
109
|
+
const seedWhenMccLoaded$ = state$.pipe((0, operators_1.map)((rs) => readMccCategoriesAvailable(rs)), (0, operators_1.distinctUntilChanged)(), (0, operators_1.filter)((available) => available), (0, operators_1.take)(1), (0, operators_1.map)(() => buildSeedAction(state$.value, payload)));
|
|
110
|
+
const mccFetchState = state.cardPolicyState.mccCategoriesFetchState;
|
|
111
|
+
if (mccFetchState === 'In-Progress') {
|
|
112
|
+
return seedWhenMccLoaded$;
|
|
113
|
+
}
|
|
114
|
+
return (0, rxjs_1.concat)((0, rxjs_1.of)((0, cardPolicyReducer_1.fetchCardPolicyMccCategories)()), seedWhenMccLoaded$);
|
|
115
|
+
}));
|
|
116
|
+
exports.seedAiCardPolicyFormDraftEpic = seedAiCardPolicyFormDraftEpic;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { ID } from '../../../../../commonStateTypes/common';
|
|
2
|
+
import { CardPolicyTemplateEntityList } from '../../../../../entity/cardPolicy/cardPolicyState';
|
|
3
|
+
import { CardPolicyFormDraft, CardPolicyModeValue } from './cardPolicyFormDraftTypes';
|
|
4
|
+
export type CardPolicyBulkSubmitKind = 'auto' | 'guided' | 'upload';
|
|
5
|
+
/**
|
|
6
|
+
* Per-row wire entry produced by the bulk builder. Structural superset
|
|
7
|
+
* of `CreateCardPolicyTemplateRequest` with `mode`, `spendLimits`, and
|
|
8
|
+
* `requiredReceiptThreshold` widened to optional so the `auto` /
|
|
9
|
+
* `upload` modes can drop them entirely.
|
|
10
|
+
*/
|
|
11
|
+
export interface BulkCreateCardPolicyTemplateEntry {
|
|
12
|
+
allowedEntity: CardPolicyTemplateEntityList;
|
|
13
|
+
applyToCards: ID[];
|
|
14
|
+
blockedEntity: CardPolicyTemplateEntityList;
|
|
15
|
+
description: string;
|
|
16
|
+
name: string;
|
|
17
|
+
mode?: CardPolicyModeValue;
|
|
18
|
+
requiredReceiptThreshold?: number | null;
|
|
19
|
+
spendLimits?: {
|
|
20
|
+
transaction: number | null;
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
export interface ToBulkCardPolicyTemplateRequestsFromDraftArgs {
|
|
24
|
+
draft: CardPolicyFormDraft;
|
|
25
|
+
description?: string;
|
|
26
|
+
/** Defaults to `"strict"`; only consumed by guided submit. */
|
|
27
|
+
guidedMode?: CardPolicyModeValue;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Build the array of per-row entries for the bulk
|
|
31
|
+
* `createCardPolicyTemplates` action from the AI CFO form draft.
|
|
32
|
+
* Iterates checked review rows and emits one entry per row, with the
|
|
33
|
+
* per-mode key contract enforced internally.
|
|
34
|
+
*/
|
|
35
|
+
export declare const toBulkCardPolicyTemplateRequestsFromDraft: ({ draft, description, guidedMode, }: ToBulkCardPolicyTemplateRequestsFromDraftArgs) => BulkCreateCardPolicyTemplateEntry[];
|