@zeniai/client-epic-state 5.0.87 → 5.0.88-beta0ND
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/commonStateTypes/animations.d.ts +1 -1
- package/lib/commonStateTypes/animations.js +1 -0
- package/lib/entity/company/companyPayload.d.ts +4 -0
- package/lib/entity/company/companyPayload.js +4 -0
- package/lib/entity/company/companyStateTypes.d.ts +4 -0
- package/lib/entity/paymentAccount/paymentAccountSelector.d.ts +1 -0
- package/lib/entity/paymentAccount/paymentAccountSelector.js +4 -0
- package/lib/entity/tenant/epic/deleteConnectionEpic.d.ts +1 -1
- package/lib/entity/tenant/epic/initEmailConnectOAuthEpic.d.ts +21 -0
- package/lib/entity/tenant/epic/initEmailConnectOAuthEpic.js +54 -0
- package/lib/entity/tenant/epic/saveAPIKeyConnectionEpic.d.ts +1 -1
- package/lib/entity/tenant/epic/saveConnectorCredentialsEpic.d.ts +3 -3
- package/lib/entity/tenant/epic/saveOAuthConnectionEpic.d.ts +1 -1
- package/lib/entity/tenant/tenantPayload.d.ts +4 -0
- package/lib/entity/tenant/tenantReducer.d.ts +40 -27
- package/lib/entity/tenant/tenantReducer.js +117 -20
- package/lib/entity/tenant/tenantState.d.ts +5 -1
- package/lib/epic.d.ts +10 -3
- package/lib/epic.js +11 -3
- package/lib/esm/commonStateTypes/animations.js +1 -0
- package/lib/esm/entity/company/companyPayload.js +4 -0
- package/lib/esm/entity/paymentAccount/paymentAccountSelector.js +3 -0
- package/lib/esm/entity/tenant/epic/initEmailConnectOAuthEpic.js +50 -0
- package/lib/esm/entity/tenant/tenantReducer.js +115 -18
- package/lib/esm/epic.js +11 -3
- package/lib/esm/index.js +13 -10
- package/lib/esm/view/dashboard/dashboardReducer.js +11 -1
- package/lib/esm/view/fileView/epic/deleteFileEpic.js +2 -2
- package/lib/esm/view/fileView/epic/deleteFileListEpic.js +2 -2
- package/lib/esm/view/fileView/epic/updateFileNameEpic.js +2 -2
- package/lib/esm/view/onboardingView/customerView/epic/aiAgentsActivation/fetchAiAgentsActivationStatusEpic.js +42 -0
- package/lib/esm/view/onboardingView/customerView/epic/customerDetails/acknowledgeOnboardingAiActivationViewedEpic.js +29 -0
- package/lib/esm/view/onboardingView/customerView/epic/customerDetails/acknowledgeOnboardingAiFinanceTeamEpic.js +40 -0
- package/lib/esm/view/onboardingView/customerView/onboardingCustomerViewReducer.js +217 -50
- package/lib/esm/view/onboardingView/customerView/onboardingCustomerViewSelector.js +7 -1
- package/lib/esm/view/onboardingView/customerView/onboardingCustomerViewState.js +12 -0
- package/lib/esm/view/spendManagement/commonSetup/epic/setup/parseUploadedKybDocumentEpic.js +52 -0
- package/lib/esm/view/spendManagement/commonSetup/epic/setup/parseUploadedKycDocumentEpic.js +59 -0
- package/lib/esm/view/spendManagement/commonSetup/kycKybAutofillActions.js +14 -0
- package/lib/esm/view/spendManagement/commonSetup/kycKybParseMapper.js +205 -0
- package/lib/esm/view/spendManagement/commonSetup/setupViewReducer.js +105 -52
- package/lib/esm/view/spendManagement/commonSetup/setupViewSelector.js +6 -1
- package/lib/esm/view/spendManagement/commonSetup/types/kycKybAutofill.js +28 -0
- package/lib/esm/view/spendManagement/treasury/treasurySetUp/epic/updateTreasuryPromoIntroClosedByOutsideClickEpic.js +18 -0
- package/lib/esm/view/spendManagement/treasury/treasurySetUp/epic/updateTreasuryPromoRemindMeLaterClickedEpic.js +18 -0
- package/lib/esm/view/spendManagement/treasury/treasurySetUp/epic/updateTreasuryVideoViewedEpic.js +1 -1
- package/lib/esm/view/spendManagement/treasury/treasurySetUp/treasurySetupViewReducer.js +45 -1
- package/lib/index.d.ts +15 -11
- package/lib/index.js +57 -35
- package/lib/view/dashboard/dashboardReducer.js +11 -1
- package/lib/view/fileView/epic/deleteFileEpic.js +1 -1
- package/lib/view/fileView/epic/deleteFileListEpic.js +1 -1
- package/lib/view/fileView/epic/updateFileNameEpic.js +1 -1
- package/lib/view/onboardingView/customerView/epic/aiAgentsActivation/fetchAiAgentsActivationStatusEpic.d.ts +7 -0
- package/lib/view/onboardingView/customerView/epic/aiAgentsActivation/fetchAiAgentsActivationStatusEpic.js +46 -0
- package/lib/view/onboardingView/customerView/epic/customerDetails/acknowledgeOnboardingAiActivationViewedEpic.d.ts +8 -0
- package/lib/view/onboardingView/customerView/epic/customerDetails/acknowledgeOnboardingAiActivationViewedEpic.js +33 -0
- package/lib/view/onboardingView/customerView/epic/customerDetails/acknowledgeOnboardingAiFinanceTeamEpic.d.ts +9 -0
- package/lib/view/onboardingView/customerView/epic/customerDetails/acknowledgeOnboardingAiFinanceTeamEpic.js +44 -0
- package/lib/view/onboardingView/customerView/onboardingCustomerViewPayload.d.ts +3 -0
- package/lib/view/onboardingView/customerView/onboardingCustomerViewReducer.d.ts +41 -4
- package/lib/view/onboardingView/customerView/onboardingCustomerViewReducer.js +219 -51
- package/lib/view/onboardingView/customerView/onboardingCustomerViewSelector.d.ts +5 -1
- package/lib/view/onboardingView/customerView/onboardingCustomerViewSelector.js +11 -2
- package/lib/view/onboardingView/customerView/onboardingCustomerViewState.d.ts +40 -0
- package/lib/view/onboardingView/customerView/onboardingCustomerViewState.js +13 -1
- package/lib/view/spendManagement/commonSetup/epic/setup/parseUploadedKybDocumentEpic.d.ts +28 -0
- package/lib/view/spendManagement/commonSetup/epic/setup/parseUploadedKybDocumentEpic.js +56 -0
- package/lib/view/spendManagement/commonSetup/epic/setup/parseUploadedKycDocumentEpic.d.ts +30 -0
- package/lib/view/spendManagement/commonSetup/epic/setup/parseUploadedKycDocumentEpic.js +63 -0
- package/lib/view/spendManagement/commonSetup/kycKybAutofillActions.d.ts +33 -0
- package/lib/view/spendManagement/commonSetup/kycKybAutofillActions.js +17 -0
- package/lib/view/spendManagement/commonSetup/kycKybParseMapper.d.ts +24 -0
- package/lib/view/spendManagement/commonSetup/kycKybParseMapper.js +213 -0
- package/lib/view/spendManagement/commonSetup/setupViewReducer.d.ts +28 -2
- package/lib/view/spendManagement/commonSetup/setupViewReducer.js +106 -53
- package/lib/view/spendManagement/commonSetup/setupViewSelector.d.ts +7 -2
- package/lib/view/spendManagement/commonSetup/setupViewSelector.js +6 -1
- package/lib/view/spendManagement/commonSetup/setupViewState.d.ts +19 -0
- package/lib/view/spendManagement/commonSetup/types/kycKybAutofill.d.ts +125 -0
- package/lib/view/spendManagement/commonSetup/types/kycKybAutofill.js +32 -0
- package/lib/view/spendManagement/treasury/treasurySetUp/epic/updateTreasuryPromoIntroClosedByOutsideClickEpic.d.ts +8 -0
- package/lib/view/spendManagement/treasury/treasurySetUp/epic/updateTreasuryPromoIntroClosedByOutsideClickEpic.js +22 -0
- package/lib/view/spendManagement/treasury/treasurySetUp/epic/updateTreasuryPromoRemindMeLaterClickedEpic.d.ts +8 -0
- package/lib/view/spendManagement/treasury/treasurySetUp/epic/updateTreasuryPromoRemindMeLaterClickedEpic.js +22 -0
- package/lib/view/spendManagement/treasury/treasurySetUp/epic/updateTreasuryVideoViewedEpic.js +1 -1
- package/lib/view/spendManagement/treasury/treasurySetUp/treasurySetupViewReducer.d.ts +1 -1
- package/lib/view/spendManagement/treasury/treasurySetUp/treasurySetupViewReducer.js +46 -2
- package/lib/view/spendManagement/treasury/treasurySetUp/treasurySetupViewState.d.ts +2 -0
- package/package.json +1 -1
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure mappers from ExtendAI parser payloads to our form-side local-data shapes.
|
|
3
|
+
*
|
|
4
|
+
* Each mapper filters out fields below KYC_KYB_AUTOFILL_MIN_CONFIDENCE and returns
|
|
5
|
+
* both the merged values and the list of field names that were autofilled so the
|
|
6
|
+
* UI can show the ✦ AI badge next to each.
|
|
7
|
+
*/
|
|
8
|
+
import { date } from '../../../zeniDayJS';
|
|
9
|
+
import { toZeniUrl } from '../../../zeniUrl';
|
|
10
|
+
import { KYC_KYB_AUTOFILL_MIN_CONFIDENCE, } from './types/kycKybAutofill';
|
|
11
|
+
const emptyResult = () => ({
|
|
12
|
+
values: {},
|
|
13
|
+
autoFilledFieldNames: [],
|
|
14
|
+
});
|
|
15
|
+
const isConfident = (field) => {
|
|
16
|
+
if (field == null) {
|
|
17
|
+
return false;
|
|
18
|
+
}
|
|
19
|
+
if (field.value == null) {
|
|
20
|
+
return false;
|
|
21
|
+
}
|
|
22
|
+
return field.confidence >= KYC_KYB_AUTOFILL_MIN_CONFIDENCE;
|
|
23
|
+
};
|
|
24
|
+
const assignAutofilledValue = (result, key, value) => {
|
|
25
|
+
if (value == null) {
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
if (typeof value === 'string' && value.trim() === '') {
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
result.values[key] = value;
|
|
32
|
+
result.autoFilledFieldNames.push(key);
|
|
33
|
+
};
|
|
34
|
+
const tryParseDate = (rawDate) => {
|
|
35
|
+
const parsedDate = date(rawDate);
|
|
36
|
+
if (parsedDate.isValid()) {
|
|
37
|
+
return parsedDate;
|
|
38
|
+
}
|
|
39
|
+
return undefined;
|
|
40
|
+
};
|
|
41
|
+
const normalizeNationality = (rawNationality, countries) => {
|
|
42
|
+
const needle = rawNationality.trim().toLowerCase();
|
|
43
|
+
if (needle === '') {
|
|
44
|
+
return undefined;
|
|
45
|
+
}
|
|
46
|
+
// Exact ISO-2 / ISO-3 match.
|
|
47
|
+
const isoMatch = countries.find((country) => country.countryCode.toLowerCase() === needle);
|
|
48
|
+
if (isoMatch != null) {
|
|
49
|
+
return isoMatch.countryCode;
|
|
50
|
+
}
|
|
51
|
+
// Common nationality adjectives map to country names (e.g. "American" → "United States").
|
|
52
|
+
const adjectiveToCountry = {
|
|
53
|
+
american: 'united states',
|
|
54
|
+
british: 'united kingdom',
|
|
55
|
+
indian: 'india',
|
|
56
|
+
canadian: 'canada',
|
|
57
|
+
australian: 'australia',
|
|
58
|
+
german: 'germany',
|
|
59
|
+
french: 'france',
|
|
60
|
+
chinese: 'china',
|
|
61
|
+
japanese: 'japan',
|
|
62
|
+
mexican: 'mexico',
|
|
63
|
+
brazilian: 'brazil',
|
|
64
|
+
};
|
|
65
|
+
const resolvedName = adjectiveToCountry[needle] ?? needle;
|
|
66
|
+
const nameMatch = countries.find((country) => country.countryName.toLowerCase() === resolvedName);
|
|
67
|
+
return nameMatch?.countryCode;
|
|
68
|
+
};
|
|
69
|
+
const splitFullName = (fullName) => {
|
|
70
|
+
const parts = fullName.trim().split(/\s+/);
|
|
71
|
+
if (parts.length === 1) {
|
|
72
|
+
return { firstName: parts[0], lastName: '' };
|
|
73
|
+
}
|
|
74
|
+
const lastName = parts[parts.length - 1];
|
|
75
|
+
const firstName = parts.slice(0, -1).join(' ');
|
|
76
|
+
return { firstName, lastName };
|
|
77
|
+
};
|
|
78
|
+
/** Passport → Company Officer. */
|
|
79
|
+
export const mapPassportToOfficer = (parsed, allNationalityCountries) => {
|
|
80
|
+
const result = emptyResult();
|
|
81
|
+
if (isConfident(parsed.first_name)) {
|
|
82
|
+
assignAutofilledValue(result, 'firstName', parsed.first_name.value);
|
|
83
|
+
}
|
|
84
|
+
if (isConfident(parsed.last_name)) {
|
|
85
|
+
assignAutofilledValue(result, 'lastName', parsed.last_name.value);
|
|
86
|
+
}
|
|
87
|
+
if (isConfident(parsed.date_of_birth)) {
|
|
88
|
+
const parsedDate = tryParseDate(parsed.date_of_birth.value);
|
|
89
|
+
if (parsedDate != null) {
|
|
90
|
+
assignAutofilledValue(result, 'birthday', parsedDate);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
if (isConfident(parsed.nationality)) {
|
|
94
|
+
const isoCode = normalizeNationality(parsed.nationality.value, allNationalityCountries);
|
|
95
|
+
if (isoCode != null) {
|
|
96
|
+
assignAutofilledValue(result, 'nationalityCountryCode', isoCode);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
return result;
|
|
100
|
+
};
|
|
101
|
+
/** Driving License → Company Officer. */
|
|
102
|
+
export const mapDrivingLicenseToOfficer = (parsed) => {
|
|
103
|
+
const result = emptyResult();
|
|
104
|
+
if (isConfident(parsed.first_name)) {
|
|
105
|
+
assignAutofilledValue(result, 'firstName', parsed.first_name.value);
|
|
106
|
+
}
|
|
107
|
+
if (isConfident(parsed.last_name)) {
|
|
108
|
+
assignAutofilledValue(result, 'lastName', parsed.last_name.value);
|
|
109
|
+
}
|
|
110
|
+
if (isConfident(parsed.date_of_birth)) {
|
|
111
|
+
const parsedDate = tryParseDate(parsed.date_of_birth.value);
|
|
112
|
+
if (parsedDate != null) {
|
|
113
|
+
assignAutofilledValue(result, 'birthday', parsedDate);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
// address_* fields are mapped at a higher layer (addressView reducer) — kept here as values
|
|
117
|
+
// only, the consuming epic dispatches the address payload separately.
|
|
118
|
+
return result;
|
|
119
|
+
};
|
|
120
|
+
/** SSN Card → Company Officer (name only — SSN value not yet returned by parser). */
|
|
121
|
+
export const mapSsnCardToOfficer = (parsed) => {
|
|
122
|
+
const result = emptyResult();
|
|
123
|
+
if (isConfident(parsed.full_name)) {
|
|
124
|
+
const { firstName, lastName } = splitFullName(parsed.full_name.value);
|
|
125
|
+
if (firstName !== '') {
|
|
126
|
+
assignAutofilledValue(result, 'firstName', firstName);
|
|
127
|
+
}
|
|
128
|
+
if (lastName !== '') {
|
|
129
|
+
assignAutofilledValue(result, 'lastName', lastName);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
return result;
|
|
133
|
+
};
|
|
134
|
+
/** Certificate of Incorporation → Company Details. */
|
|
135
|
+
export const mapCoiToCompanyDetails = (parsed) => {
|
|
136
|
+
const result = emptyResult();
|
|
137
|
+
if (isConfident(parsed.company_legal_name)) {
|
|
138
|
+
assignAutofilledValue(result, 'companyLegalName', parsed.company_legal_name.value);
|
|
139
|
+
}
|
|
140
|
+
if (isConfident(parsed.ein)) {
|
|
141
|
+
assignAutofilledValue(result, 'taxIdOrEIN', parsed.ein.value);
|
|
142
|
+
}
|
|
143
|
+
if (isConfident(parsed.phone_number)) {
|
|
144
|
+
assignAutofilledValue(result, 'phone', parsed.phone_number.value);
|
|
145
|
+
}
|
|
146
|
+
if (isConfident(parsed.product_description)) {
|
|
147
|
+
assignAutofilledValue(result, 'companyDescription', parsed.product_description.value);
|
|
148
|
+
}
|
|
149
|
+
if (isConfident(parsed.website)) {
|
|
150
|
+
try {
|
|
151
|
+
assignAutofilledValue(result, 'website', toZeniUrl(parsed.website.value));
|
|
152
|
+
}
|
|
153
|
+
catch {
|
|
154
|
+
// ignore — malformed URL string from OCR
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
if (isConfident(parsed.industry)) {
|
|
158
|
+
assignAutofilledValue(result, 'companyIndustryType', parsed.industry.value);
|
|
159
|
+
}
|
|
160
|
+
if (isConfident(parsed.sub_industry)) {
|
|
161
|
+
assignAutofilledValue(result, 'companySubIndustry', parsed.sub_industry.value);
|
|
162
|
+
}
|
|
163
|
+
if (isConfident(parsed.type_of_incorporation)) {
|
|
164
|
+
assignAutofilledValue(result, 'typeOfIncorporation', parsed.type_of_incorporation.value);
|
|
165
|
+
}
|
|
166
|
+
if (isConfident(parsed.date_of_incorporation)) {
|
|
167
|
+
const parsedDate = tryParseDate(parsed.date_of_incorporation.value);
|
|
168
|
+
if (parsedDate != null) {
|
|
169
|
+
assignAutofilledValue(result, 'incDate', parsedDate);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
if (isConfident(parsed.state_of_incorporation)) {
|
|
173
|
+
assignAutofilledValue(result, 'stateOfIncorporation', parsed.state_of_incorporation.value);
|
|
174
|
+
}
|
|
175
|
+
if (isConfident(parsed.countries_of_operations)) {
|
|
176
|
+
assignAutofilledValue(result, 'countriesOfOperations', parsed.countries_of_operations.value);
|
|
177
|
+
}
|
|
178
|
+
if (isConfident(parsed.source_of_funds)) {
|
|
179
|
+
assignAutofilledValue(result, 'sourceOfFunds', parsed.source_of_funds.value);
|
|
180
|
+
}
|
|
181
|
+
if (isConfident(parsed.transaction_volume_expectations)) {
|
|
182
|
+
assignAutofilledValue(result, 'transactionVolume', parsed.transaction_volume_expectations.value);
|
|
183
|
+
}
|
|
184
|
+
if (isConfident(parsed.purpose_of_account)) {
|
|
185
|
+
assignAutofilledValue(result, 'purposeOfAccount', parsed.purpose_of_account.value);
|
|
186
|
+
}
|
|
187
|
+
if (isConfident(parsed.regulated_status)) {
|
|
188
|
+
assignAutofilledValue(result, 'regulatedStatus', parsed.regulated_status.value);
|
|
189
|
+
}
|
|
190
|
+
if (isConfident(parsed.us_nexus)) {
|
|
191
|
+
assignAutofilledValue(result, 'usNexus', parsed.us_nexus.value);
|
|
192
|
+
}
|
|
193
|
+
return result;
|
|
194
|
+
};
|
|
195
|
+
/** Tax EIN letter → Company Details. */
|
|
196
|
+
export const mapTaxEinToCompanyDetails = (parsed) => {
|
|
197
|
+
const result = emptyResult();
|
|
198
|
+
if (isConfident(parsed.legal_business_name)) {
|
|
199
|
+
assignAutofilledValue(result, 'companyLegalName', parsed.legal_business_name.value);
|
|
200
|
+
}
|
|
201
|
+
if (isConfident(parsed.ein)) {
|
|
202
|
+
assignAutofilledValue(result, 'taxIdOrEIN', parsed.ein.value);
|
|
203
|
+
}
|
|
204
|
+
return result;
|
|
205
|
+
};
|
|
@@ -1,62 +1,30 @@
|
|
|
1
1
|
import { createSlice } from '@reduxjs/toolkit';
|
|
2
|
+
import { parseUploadedKybDocument, parseUploadedKybDocumentFailure, parseUploadedKycDocument, parseUploadedKycDocumentFailure, } from './kycKybAutofillActions';
|
|
2
3
|
const initialFetchStatus = {
|
|
3
4
|
fetchState: 'Not-Started',
|
|
4
5
|
error: undefined,
|
|
5
6
|
};
|
|
7
|
+
const emptyOfficerSlot = {
|
|
8
|
+
autoFilledFields: [],
|
|
9
|
+
localData: undefined,
|
|
10
|
+
sendOtpStatus: initialFetchStatus,
|
|
11
|
+
otpverificationStatus: initialFetchStatus,
|
|
12
|
+
};
|
|
6
13
|
export const initialState = {
|
|
7
14
|
updateStatus: { fetchState: 'Not-Started', error: undefined },
|
|
8
|
-
|
|
15
|
+
parsingDocumentFileIds: [],
|
|
16
|
+
companyDetails: { autoFilledFields: [] },
|
|
9
17
|
companyOfficerUpdateStatus: {
|
|
10
|
-
Officer_1: {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
},
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
},
|
|
20
|
-
Officer_3: {
|
|
21
|
-
localData: undefined,
|
|
22
|
-
sendOtpStatus: initialFetchStatus,
|
|
23
|
-
otpverificationStatus: initialFetchStatus,
|
|
24
|
-
},
|
|
25
|
-
Officer_4: {
|
|
26
|
-
localData: undefined,
|
|
27
|
-
sendOtpStatus: initialFetchStatus,
|
|
28
|
-
otpverificationStatus: initialFetchStatus,
|
|
29
|
-
},
|
|
30
|
-
Officer_5: {
|
|
31
|
-
localData: undefined,
|
|
32
|
-
sendOtpStatus: initialFetchStatus,
|
|
33
|
-
otpverificationStatus: initialFetchStatus,
|
|
34
|
-
},
|
|
35
|
-
Officer_6: {
|
|
36
|
-
localData: undefined,
|
|
37
|
-
sendOtpStatus: initialFetchStatus,
|
|
38
|
-
otpverificationStatus: initialFetchStatus,
|
|
39
|
-
},
|
|
40
|
-
Officer_7: {
|
|
41
|
-
localData: undefined,
|
|
42
|
-
sendOtpStatus: initialFetchStatus,
|
|
43
|
-
otpverificationStatus: initialFetchStatus,
|
|
44
|
-
},
|
|
45
|
-
Officer_8: {
|
|
46
|
-
localData: undefined,
|
|
47
|
-
sendOtpStatus: initialFetchStatus,
|
|
48
|
-
otpverificationStatus: initialFetchStatus,
|
|
49
|
-
},
|
|
50
|
-
Officer_9: {
|
|
51
|
-
localData: undefined,
|
|
52
|
-
sendOtpStatus: initialFetchStatus,
|
|
53
|
-
otpverificationStatus: initialFetchStatus,
|
|
54
|
-
},
|
|
55
|
-
Officer_10: {
|
|
56
|
-
localData: undefined,
|
|
57
|
-
sendOtpStatus: initialFetchStatus,
|
|
58
|
-
otpverificationStatus: initialFetchStatus,
|
|
59
|
-
},
|
|
18
|
+
Officer_1: { ...emptyOfficerSlot },
|
|
19
|
+
Officer_2: { ...emptyOfficerSlot },
|
|
20
|
+
Officer_3: { ...emptyOfficerSlot },
|
|
21
|
+
Officer_4: { ...emptyOfficerSlot },
|
|
22
|
+
Officer_5: { ...emptyOfficerSlot },
|
|
23
|
+
Officer_6: { ...emptyOfficerSlot },
|
|
24
|
+
Officer_7: { ...emptyOfficerSlot },
|
|
25
|
+
Officer_8: { ...emptyOfficerSlot },
|
|
26
|
+
Officer_9: { ...emptyOfficerSlot },
|
|
27
|
+
Officer_10: { ...emptyOfficerSlot },
|
|
60
28
|
},
|
|
61
29
|
primaryContactDetails: {},
|
|
62
30
|
};
|
|
@@ -297,7 +265,92 @@ const setupView = createSlice({
|
|
|
297
265
|
clearSetupView(draft) {
|
|
298
266
|
Object.assign(draft, initialState);
|
|
299
267
|
},
|
|
268
|
+
/**
|
|
269
|
+
* Merge AI-parsed officer fields into the selected officer's localData and
|
|
270
|
+
* track which field names were autofilled so the form can show the ✦ badge.
|
|
271
|
+
*/
|
|
272
|
+
applyKycDocumentAutofillForSetup: {
|
|
273
|
+
reducer(draft, action) {
|
|
274
|
+
const { officerType, values, autoFilledFieldNames, fileId } = action.payload;
|
|
275
|
+
const slot = draft.companyOfficerUpdateStatus[officerType];
|
|
276
|
+
slot.localData = Object.assign({}, slot.localData, values);
|
|
277
|
+
slot.autoFilledFields = Array.from(new Set([...slot.autoFilledFields, ...autoFilledFieldNames]));
|
|
278
|
+
draft.parsingDocumentFileIds = draft.parsingDocumentFileIds.filter((id) => id !== fileId);
|
|
279
|
+
},
|
|
280
|
+
prepare(payload) {
|
|
281
|
+
return { payload };
|
|
282
|
+
},
|
|
283
|
+
},
|
|
284
|
+
/**
|
|
285
|
+
* Merge AI-parsed company fields into companyDetails.localData and track
|
|
286
|
+
* which field names were autofilled.
|
|
287
|
+
*/
|
|
288
|
+
applyKybDocumentAutofillForSetup: {
|
|
289
|
+
reducer(draft, action) {
|
|
290
|
+
const { values, autoFilledFieldNames, fileId } = action.payload;
|
|
291
|
+
draft.companyDetails.localData = Object.assign({}, draft.companyDetails.localData, values);
|
|
292
|
+
draft.companyDetails.autoFilledFields = Array.from(new Set([
|
|
293
|
+
...draft.companyDetails.autoFilledFields,
|
|
294
|
+
...autoFilledFieldNames,
|
|
295
|
+
]));
|
|
296
|
+
draft.parsingDocumentFileIds = draft.parsingDocumentFileIds.filter((id) => id !== fileId);
|
|
297
|
+
},
|
|
298
|
+
prepare(payload) {
|
|
299
|
+
return { payload };
|
|
300
|
+
},
|
|
301
|
+
},
|
|
302
|
+
/**
|
|
303
|
+
* Wipe AI-autofill badges. If `officerType` is provided, clears only that
|
|
304
|
+
* officer; otherwise clears company details too.
|
|
305
|
+
*/
|
|
306
|
+
clearKycKybAutofillForSetup: {
|
|
307
|
+
reducer(draft, action) {
|
|
308
|
+
const { officerType } = action.payload;
|
|
309
|
+
if (officerType != null) {
|
|
310
|
+
draft.companyOfficerUpdateStatus[officerType].autoFilledFields = [];
|
|
311
|
+
}
|
|
312
|
+
else {
|
|
313
|
+
draft.companyDetails.autoFilledFields = [];
|
|
314
|
+
Object.keys(draft.companyOfficerUpdateStatus).forEach((key) => {
|
|
315
|
+
draft.companyOfficerUpdateStatus[key].autoFilledFields = [];
|
|
316
|
+
});
|
|
317
|
+
}
|
|
318
|
+
},
|
|
319
|
+
prepare(payload = {}) {
|
|
320
|
+
return { payload };
|
|
321
|
+
},
|
|
322
|
+
},
|
|
323
|
+
},
|
|
324
|
+
extraReducers: (builder) => {
|
|
325
|
+
const addParsingFileId = (draft, fileId) => {
|
|
326
|
+
if (!draft.parsingDocumentFileIds.includes(fileId)) {
|
|
327
|
+
draft.parsingDocumentFileIds.push(fileId);
|
|
328
|
+
}
|
|
329
|
+
};
|
|
330
|
+
const removeParsingFileId = (draft, fileId) => {
|
|
331
|
+
draft.parsingDocumentFileIds = draft.parsingDocumentFileIds.filter((id) => id !== fileId);
|
|
332
|
+
};
|
|
333
|
+
builder.addCase(parseUploadedKycDocument, (draft, action) => {
|
|
334
|
+
if (action.payload.target === 'setup') {
|
|
335
|
+
addParsingFileId(draft, action.payload.fileId);
|
|
336
|
+
}
|
|
337
|
+
});
|
|
338
|
+
builder.addCase(parseUploadedKybDocument, (draft, action) => {
|
|
339
|
+
if (action.payload.target === 'setup') {
|
|
340
|
+
addParsingFileId(draft, action.payload.fileId);
|
|
341
|
+
}
|
|
342
|
+
});
|
|
343
|
+
builder.addCase(parseUploadedKycDocumentFailure, (draft, action) => {
|
|
344
|
+
if (action.payload.target === 'setup') {
|
|
345
|
+
removeParsingFileId(draft, action.payload.fileId);
|
|
346
|
+
}
|
|
347
|
+
});
|
|
348
|
+
builder.addCase(parseUploadedKybDocumentFailure, (draft, action) => {
|
|
349
|
+
if (action.payload.target === 'setup') {
|
|
350
|
+
removeParsingFileId(draft, action.payload.fileId);
|
|
351
|
+
}
|
|
352
|
+
});
|
|
300
353
|
},
|
|
301
354
|
});
|
|
302
|
-
export const { enableSetup, enableSetupSuccess, enableSetupFailure, updateBusinessVerificationDetails, updateBusinessVerificationDetailsSuccess, updateBusinessVerificationDetailsFailure, updateSelectedCompanyOfficer, updateSetupViewLocalStoreData, saveSetupViewDataInLocalStore, saveCompnayOfficerPhoneInLocalStore, saveCompnayOfficerAdditionalDocumentsInLocalStore, saveTreasuryAdditionalDocumentsInLocalStore, sendOtp: sendOtpSpendManagementSetUp, resendOtp: resendOtpSpendManagementSetUp, sendOtpSuccess: sendOtpSuccessSpendManagementSetUp, sendOtpFailure: sendOtpFailureSpendManagementSetUp, verifyOtp: verifyOtpSpendManagementSetUp, verifyOtpSuccess: verifyOtpSuccessSpendManagementSetUp, verifyOtpFailure: verifyOtpFailureSpendManagementSetUp, saveIndustryAndIncDateInLocalStore, clearSetupViewDataInLocalStore, clearSetupView, } = setupView.actions;
|
|
355
|
+
export const { enableSetup, enableSetupSuccess, enableSetupFailure, updateBusinessVerificationDetails, updateBusinessVerificationDetailsSuccess, updateBusinessVerificationDetailsFailure, updateSelectedCompanyOfficer, updateSetupViewLocalStoreData, saveSetupViewDataInLocalStore, saveCompnayOfficerPhoneInLocalStore, saveCompnayOfficerAdditionalDocumentsInLocalStore, saveTreasuryAdditionalDocumentsInLocalStore, sendOtp: sendOtpSpendManagementSetUp, resendOtp: resendOtpSpendManagementSetUp, sendOtpSuccess: sendOtpSuccessSpendManagementSetUp, sendOtpFailure: sendOtpFailureSpendManagementSetUp, verifyOtp: verifyOtpSpendManagementSetUp, verifyOtpSuccess: verifyOtpSuccessSpendManagementSetUp, verifyOtpFailure: verifyOtpFailureSpendManagementSetUp, saveIndustryAndIncDateInLocalStore, clearSetupViewDataInLocalStore, clearSetupView, applyKycDocumentAutofillForSetup, applyKybDocumentAutofillForSetup, clearKycKybAutofillForSetup, } = setupView.actions;
|
|
303
356
|
export default setupView.reducer;
|
|
@@ -87,15 +87,17 @@ export function getBusinessVerificationDetails(state, companyId) {
|
|
|
87
87
|
const { setupViewState, countryListState } = state;
|
|
88
88
|
const { companyDetails, companyOfficerUpdateStatus, primaryContactDetails, updateStatus, } = setupViewState;
|
|
89
89
|
const companyView = getCompanyView(state, companyId, []);
|
|
90
|
-
const { companyDetailsLocalData, companyOfficerLocalData } = getCompanyAndIdentityDetails(state, companyId, {
|
|
90
|
+
const { companyDetailsLocalData, companyOfficerLocalData, parsingDocumentFileIds } = getCompanyAndIdentityDetails(state, companyId, {
|
|
91
91
|
companyDetails,
|
|
92
92
|
companyOfficerUpdateStatus,
|
|
93
93
|
primaryContactDetails,
|
|
94
|
+
parsingDocumentFileIds: setupViewState.parsingDocumentFileIds,
|
|
94
95
|
});
|
|
95
96
|
const allNationalityCountries = countryListState.byCountryListCode.nationalityCountryList.countries;
|
|
96
97
|
return {
|
|
97
98
|
companyDetailsLocalData,
|
|
98
99
|
companyOfficerLocalData,
|
|
100
|
+
parsingDocumentFileIds,
|
|
99
101
|
companyView,
|
|
100
102
|
updateStatus,
|
|
101
103
|
allNationalityCountries,
|
|
@@ -119,6 +121,7 @@ export const getCompanyAndIdentityDetails = (state, companyId, companyAndIdentit
|
|
|
119
121
|
const companyAddress = addressViewState.newAddressState?.company_address;
|
|
120
122
|
const registeredCompanyAddress = addressViewState.newAddressState?.company_registered_address;
|
|
121
123
|
companyDetailsLocalData = {
|
|
124
|
+
autoFilledFields: companyDetails.autoFilledFields,
|
|
122
125
|
companyId,
|
|
123
126
|
companyDescription,
|
|
124
127
|
companyLegalName,
|
|
@@ -191,6 +194,7 @@ export const getCompanyAndIdentityDetails = (state, companyId, companyAndIdentit
|
|
|
191
194
|
const companyOfficerAddress = addressViewState.newAddressState?.[addressType];
|
|
192
195
|
companyOfficerLocalData[officerType] = {
|
|
193
196
|
...companyOfficer.localData,
|
|
197
|
+
autoFilledFields: companyOfficer.autoFilledFields,
|
|
194
198
|
userFiles: getFilesByFileIds(fileState, fileIds),
|
|
195
199
|
additionalFiles: getFilesByFileIds(fileState, additionalSubmittedDocumentsForVerificationFileIds),
|
|
196
200
|
deleteFileStatusById,
|
|
@@ -204,6 +208,7 @@ export const getCompanyAndIdentityDetails = (state, companyId, companyAndIdentit
|
|
|
204
208
|
return {
|
|
205
209
|
companyDetailsLocalData,
|
|
206
210
|
companyOfficerLocalData,
|
|
211
|
+
parsingDocumentFileIds: companyAndIdentityDetails.parsingDocumentFileIds,
|
|
207
212
|
};
|
|
208
213
|
};
|
|
209
214
|
/* This helper function takes deposit accounts and payment accounts
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared types for the KYC / KYB document autofill flow that lives inside the
|
|
3
|
+
* commonSetup feature (Setup pages + Onboarding both consume it via the same
|
|
4
|
+
* selector view; there is no separate state slice).
|
|
5
|
+
*
|
|
6
|
+
* Backed by document-communication-agent `POST /1.0/documents/process/sync`,
|
|
7
|
+
* which proxies document-service ExtendAI parsers and returns one of the
|
|
8
|
+
* parser payloads below — each value shaped as `{value, confidence}` per field.
|
|
9
|
+
*/
|
|
10
|
+
/** Confidence floor below which we drop an autofill candidate. */
|
|
11
|
+
export const KYC_KYB_AUTOFILL_MIN_CONFIDENCE = 0.5;
|
|
12
|
+
/**
|
|
13
|
+
* Maps the form-side {@link KycSelectDocumentType} (camelCase) to the
|
|
14
|
+
* parser-side {@link KycProvidedDocumentType} (snake_case). Returns `null` for
|
|
15
|
+
* `stateId`, which has no parser today.
|
|
16
|
+
*/
|
|
17
|
+
export const toKycProvidedDocumentType = (selectType) => {
|
|
18
|
+
switch (selectType) {
|
|
19
|
+
case 'driverLicense':
|
|
20
|
+
return 'driving_license';
|
|
21
|
+
case 'passport':
|
|
22
|
+
return 'passport';
|
|
23
|
+
case 'ssnCard':
|
|
24
|
+
return 'social_security_card';
|
|
25
|
+
case 'stateId':
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { of } from 'rxjs';
|
|
2
|
+
import { catchError, filter, mergeMap, switchMap } from 'rxjs/operators';
|
|
3
|
+
import { updateTreasuryPromoIntroClosedByOutsideClickForLoggedInUser } from '../../../../../entity/tenant/tenantReducer';
|
|
4
|
+
import { createZeniAPIStatus, isSuccessStatus, } from '../../../../../responsePayload';
|
|
5
|
+
import { updateTreasuryPromoIntroClosedByOutsideClick, updateTreasuryPromoIntroClosedByOutsideClickFailure, updateTreasuryPromoIntroClosedByOutsideClickSuccess, } from '../treasurySetupViewReducer';
|
|
6
|
+
export const updateTreasuryPromoIntroClosedByOutsideClickEpic = (actions$, _state$, zeniAPI) => actions$.pipe(filter(updateTreasuryPromoIntroClosedByOutsideClick.match), switchMap(() => {
|
|
7
|
+
return zeniAPI
|
|
8
|
+
.putAndGetJSON(`${zeniAPI.apiEndPoints.tenantMicroServiceBaseUrl}/1.0/user/self`, { is_treasury_promo_intro_closed_by_outside_click: true })
|
|
9
|
+
.pipe(mergeMap((response) => {
|
|
10
|
+
if (isSuccessStatus(response)) {
|
|
11
|
+
return of(updateTreasuryPromoIntroClosedByOutsideClickForLoggedInUser(), updateTreasuryPromoIntroClosedByOutsideClickSuccess());
|
|
12
|
+
}
|
|
13
|
+
else {
|
|
14
|
+
return of(updateTreasuryPromoIntroClosedByOutsideClickFailure(response.status));
|
|
15
|
+
}
|
|
16
|
+
}), catchError((error) => of(updateTreasuryPromoIntroClosedByOutsideClickFailure(createZeniAPIStatus('Unexpected error', 'Update treasury promo intro closed by outside click REST API call errored out' +
|
|
17
|
+
(error?.message ?? JSON.stringify(error)))))));
|
|
18
|
+
}));
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { of } from 'rxjs';
|
|
2
|
+
import { catchError, filter, mergeMap, switchMap } from 'rxjs/operators';
|
|
3
|
+
import { updateTreasuryPromoRemindMeLaterClickedForLoggedInUser } from '../../../../../entity/tenant/tenantReducer';
|
|
4
|
+
import { createZeniAPIStatus, isSuccessStatus, } from '../../../../../responsePayload';
|
|
5
|
+
import { updateTreasuryPromoRemindMeLaterClicked, updateTreasuryPromoRemindMeLaterClickedFailure, updateTreasuryPromoRemindMeLaterClickedSuccess, } from '../treasurySetupViewReducer';
|
|
6
|
+
export const updateTreasuryPromoRemindMeLaterClickedEpic = (actions$, _state$, zeniAPI) => actions$.pipe(filter(updateTreasuryPromoRemindMeLaterClicked.match), switchMap(() => {
|
|
7
|
+
return zeniAPI
|
|
8
|
+
.putAndGetJSON(`${zeniAPI.apiEndPoints.tenantMicroServiceBaseUrl}/1.0/user/self`, { is_treasury_promo_video_remind_me_later_clicked: true })
|
|
9
|
+
.pipe(mergeMap((response) => {
|
|
10
|
+
if (isSuccessStatus(response)) {
|
|
11
|
+
return of(updateTreasuryPromoRemindMeLaterClickedForLoggedInUser(), updateTreasuryPromoRemindMeLaterClickedSuccess());
|
|
12
|
+
}
|
|
13
|
+
else {
|
|
14
|
+
return of(updateTreasuryPromoRemindMeLaterClickedFailure(response.status));
|
|
15
|
+
}
|
|
16
|
+
}), catchError((error) => of(updateTreasuryPromoRemindMeLaterClickedFailure(createZeniAPIStatus('Unexpected error', 'Update treasury promo remind me later REST API call errored out' +
|
|
17
|
+
(error?.message ?? JSON.stringify(error)))))));
|
|
18
|
+
}));
|
package/lib/esm/view/spendManagement/treasury/treasurySetUp/epic/updateTreasuryVideoViewedEpic.js
CHANGED
|
@@ -14,5 +14,5 @@ export const updateTreasuryVideoViewedEpic = (actions$, _state$, zeniAPI) => act
|
|
|
14
14
|
return of(updateTreasuryVideoViewedFailure(response.status));
|
|
15
15
|
}
|
|
16
16
|
}), catchError((error) => of(updateTreasuryVideoViewedFailure(createZeniAPIStatus('Unexpected error', 'Update treasury video viewed REST API call errored out' +
|
|
17
|
-
JSON.stringify(error))))));
|
|
17
|
+
(error?.message ?? JSON.stringify(error)))))));
|
|
18
18
|
}));
|
|
@@ -33,6 +33,14 @@ export const initialState = {
|
|
|
33
33
|
fetchState: 'Not-Started',
|
|
34
34
|
error: undefined,
|
|
35
35
|
},
|
|
36
|
+
updateTreasuryPromoIntroClosedByOutsideClickStatus: {
|
|
37
|
+
fetchState: 'Not-Started',
|
|
38
|
+
error: undefined,
|
|
39
|
+
},
|
|
40
|
+
updateTreasuryPromoRemindMeLaterClickedStatus: {
|
|
41
|
+
fetchState: 'Not-Started',
|
|
42
|
+
error: undefined,
|
|
43
|
+
},
|
|
36
44
|
updateTreasuryVideoViewedStatus: {
|
|
37
45
|
fetchState: 'Not-Started',
|
|
38
46
|
error: undefined,
|
|
@@ -290,12 +298,48 @@ const treasurySetupView = createSlice({
|
|
|
290
298
|
error: action.payload,
|
|
291
299
|
};
|
|
292
300
|
},
|
|
301
|
+
updateTreasuryPromoRemindMeLaterClicked(draft) {
|
|
302
|
+
draft.updateTreasuryPromoRemindMeLaterClickedStatus = {
|
|
303
|
+
fetchState: 'In-Progress',
|
|
304
|
+
error: undefined,
|
|
305
|
+
};
|
|
306
|
+
},
|
|
307
|
+
updateTreasuryPromoRemindMeLaterClickedSuccess(draft) {
|
|
308
|
+
draft.updateTreasuryPromoRemindMeLaterClickedStatus = {
|
|
309
|
+
fetchState: 'Completed',
|
|
310
|
+
error: undefined,
|
|
311
|
+
};
|
|
312
|
+
},
|
|
313
|
+
updateTreasuryPromoRemindMeLaterClickedFailure(draft, action) {
|
|
314
|
+
draft.updateTreasuryPromoRemindMeLaterClickedStatus = {
|
|
315
|
+
fetchState: 'Error',
|
|
316
|
+
error: action.payload,
|
|
317
|
+
};
|
|
318
|
+
},
|
|
319
|
+
updateTreasuryPromoIntroClosedByOutsideClick(draft) {
|
|
320
|
+
draft.updateTreasuryPromoIntroClosedByOutsideClickStatus = {
|
|
321
|
+
fetchState: 'In-Progress',
|
|
322
|
+
error: undefined,
|
|
323
|
+
};
|
|
324
|
+
},
|
|
325
|
+
updateTreasuryPromoIntroClosedByOutsideClickSuccess(draft) {
|
|
326
|
+
draft.updateTreasuryPromoIntroClosedByOutsideClickStatus = {
|
|
327
|
+
fetchState: 'Completed',
|
|
328
|
+
error: undefined,
|
|
329
|
+
};
|
|
330
|
+
},
|
|
331
|
+
updateTreasuryPromoIntroClosedByOutsideClickFailure(draft, action) {
|
|
332
|
+
draft.updateTreasuryPromoIntroClosedByOutsideClickStatus = {
|
|
333
|
+
fetchState: 'Error',
|
|
334
|
+
error: action.payload,
|
|
335
|
+
};
|
|
336
|
+
},
|
|
293
337
|
clearTreasurySetupView(draft) {
|
|
294
338
|
Object.assign(draft, initialState);
|
|
295
339
|
},
|
|
296
340
|
},
|
|
297
341
|
});
|
|
298
|
-
export const { fetchTreasuryFunds, fetchTreasurySetupView, fetchTreasurySetupViewSuccess, fetchTreasurySetupViewFailure, acceptTreasuryTerms, acceptTreasuryTermsSuccess, acceptTreasuryTermsFailure, clearTreasurySetupView, updateTreasuryFundsSuccess, updateTreasuryFundsFailure, updatePortfolioAllocation, updatePortfolioAllocationSuccess, updatePortfolioAllocationFailure, fetchPortfolioAllocation, fetchPortfolioAllocationSuccess, fetchPortfolioAllocationFailure, updateFundAllocationLocalData,
|
|
342
|
+
export const { fetchTreasuryFunds, fetchTreasurySetupView, fetchTreasurySetupViewSuccess, fetchTreasurySetupViewFailure, acceptTreasuryTerms, acceptTreasuryTermsSuccess, acceptTreasuryTermsFailure, clearTreasurySetupView, updateTreasuryFundsSuccess, updateTreasuryFundsFailure, updatePortfolioAllocation, updatePortfolioAllocationSuccess, updatePortfolioAllocationFailure, fetchPortfolioAllocation, fetchPortfolioAllocationSuccess, fetchPortfolioAllocationFailure, updateFundAllocationLocalData, updateTreasuryPromoIntroClosedByOutsideClick, updateTreasuryPromoIntroClosedByOutsideClickFailure, updateTreasuryPromoIntroClosedByOutsideClickSuccess, updateTreasuryPromoRemindMeLaterClicked, updateTreasuryPromoRemindMeLaterClickedFailure, updateTreasuryPromoRemindMeLaterClickedSuccess, updateTreasuryVideoViewed, updateTreasuryVideoViewedFailure, updateTreasuryVideoViewedSuccess, } = treasurySetupView.actions;
|
|
299
343
|
export default treasurySetupView.reducer;
|
|
300
344
|
function mapTreasuryFundsPayloadToFundData(fundsPayload) {
|
|
301
345
|
return fundsPayload.funds.map((fund) => ({
|