@zeniai/client-epic-state 5.1.4 → 5.1.5-betaJK1
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/company/companyPayload.d.ts +4 -0
- package/lib/entity/company/companyPayload.js +6 -0
- package/lib/entity/company/companyStateTypes.d.ts +7 -0
- package/lib/entity/paymentAccount/paymentAccountSelector.d.ts +1 -0
- package/lib/entity/paymentAccount/paymentAccountSelector.js +9 -0
- package/lib/entity/snackbar/snackbarTypes.d.ts +1 -1
- package/lib/entity/snackbar/snackbarTypes.js +1 -0
- package/lib/entity/task/taskPayload.d.ts +1 -0
- package/lib/entity/task/taskPayload.js +1 -0
- package/lib/entity/task/taskReducer.d.ts +5 -1
- package/lib/entity/task/taskReducer.js +8 -2
- package/lib/entity/task/taskState.d.ts +1 -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 +59 -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 +1 -0
- package/lib/entity/tenant/tenantReducer.d.ts +38 -25
- package/lib/entity/tenant/tenantReducer.js +65 -5
- package/lib/entity/tenant/tenantState.d.ts +1 -0
- package/lib/epic.d.ts +8 -1
- package/lib/epic.js +9 -1
- package/lib/esm/entity/company/companyPayload.js +6 -0
- package/lib/esm/entity/paymentAccount/paymentAccountSelector.js +8 -0
- package/lib/esm/entity/snackbar/snackbarTypes.js +1 -0
- package/lib/esm/entity/task/taskPayload.js +1 -0
- package/lib/esm/entity/task/taskReducer.js +7 -1
- package/lib/esm/entity/tenant/epic/initEmailConnectOAuthEpic.js +55 -0
- package/lib/esm/entity/tenant/tenantReducer.js +63 -3
- package/lib/esm/epic.js +9 -1
- package/lib/esm/index.js +13 -9
- package/lib/esm/view/fileView/epic/deleteFileEpic.js +2 -2
- package/lib/esm/view/fileView/epic/deleteFileListEpic.js +2 -2
- package/lib/esm/view/onboardingView/customerView/epic/aiAgentsActivation/fetchAiAgentsActivationStatusEpic.js +40 -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/epic/customerDetails/updateOnboardingCustomerViewEpic.js +24 -18
- package/lib/esm/view/onboardingView/customerView/epic/customerDetails/updateOnboardingCustomerViewLocalStoreDataEpic.js +29 -17
- package/lib/esm/view/onboardingView/customerView/onboardingCustomerViewReducer.js +223 -51
- package/lib/esm/view/onboardingView/customerView/onboardingCustomerViewSelector.js +24 -12
- package/lib/esm/view/onboardingView/customerView/onboardingCustomerViewState.js +37 -6
- package/lib/esm/view/spendManagement/commonSetup/epic/setup/parseUploadedKybDocumentEpic.js +58 -0
- package/lib/esm/view/spendManagement/commonSetup/epic/setup/parseUploadedKycDocumentEpic.js +77 -0
- package/lib/esm/view/spendManagement/commonSetup/kycKybAutofillActions.js +14 -0
- package/lib/esm/view/spendManagement/commonSetup/kycKybParseMapper.js +207 -0
- package/lib/esm/view/spendManagement/commonSetup/setupViewReducer.js +106 -52
- package/lib/esm/view/spendManagement/commonSetup/setupViewSelector.js +6 -1
- package/lib/esm/view/spendManagement/commonSetup/types/kycKybAutofill.js +41 -0
- package/lib/esm/view/taskManager/taskDetailView/epics/createSubTaskEpic.js +80 -0
- package/lib/esm/view/taskManager/taskDetailView/epics/fetchSubTasksEpic.js +36 -0
- package/lib/esm/view/taskManager/taskDetailView/epics/fetchTaskDetailEpic.js +13 -0
- package/lib/esm/view/taskManager/taskDetailView/taskDetailReducer.js +56 -2
- package/lib/esm/view/taskManager/taskDetailView/taskDetailSelector.js +19 -8
- package/lib/index.d.ts +17 -13
- package/lib/index.js +67 -35
- package/lib/view/expenseAutomationView/helpers/transactionCategorizationLocalDataHelper.d.ts +1 -1
- package/lib/view/fileView/epic/deleteFileEpic.js +1 -1
- package/lib/view/fileView/epic/deleteFileListEpic.js +1 -1
- package/lib/view/onboardingView/customerView/epic/aiAgentsActivation/fetchAiAgentsActivationStatusEpic.d.ts +7 -0
- package/lib/view/onboardingView/customerView/epic/aiAgentsActivation/fetchAiAgentsActivationStatusEpic.js +44 -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/epic/customerDetails/updateOnboardingCustomerViewEpic.js +24 -18
- package/lib/view/onboardingView/customerView/epic/customerDetails/updateOnboardingCustomerViewLocalStoreDataEpic.d.ts +2 -2
- package/lib/view/onboardingView/customerView/epic/customerDetails/updateOnboardingCustomerViewLocalStoreDataEpic.js +27 -15
- package/lib/view/onboardingView/customerView/onboardingCustomerViewPayload.d.ts +3 -0
- package/lib/view/onboardingView/customerView/onboardingCustomerViewReducer.d.ts +44 -5
- package/lib/view/onboardingView/customerView/onboardingCustomerViewReducer.js +225 -52
- package/lib/view/onboardingView/customerView/onboardingCustomerViewSelector.d.ts +6 -1
- package/lib/view/onboardingView/customerView/onboardingCustomerViewSelector.js +27 -12
- package/lib/view/onboardingView/customerView/onboardingCustomerViewState.d.ts +52 -8
- package/lib/view/onboardingView/customerView/onboardingCustomerViewState.js +39 -7
- package/lib/view/spendManagement/commonSetup/epic/setup/parseUploadedKybDocumentEpic.d.ts +28 -0
- package/lib/view/spendManagement/commonSetup/epic/setup/parseUploadedKybDocumentEpic.js +62 -0
- package/lib/view/spendManagement/commonSetup/epic/setup/parseUploadedKycDocumentEpic.d.ts +9 -0
- package/lib/view/spendManagement/commonSetup/epic/setup/parseUploadedKycDocumentEpic.js +81 -0
- package/lib/view/spendManagement/commonSetup/kycKybAutofillActions.d.ts +24 -0
- package/lib/view/spendManagement/commonSetup/kycKybAutofillActions.js +17 -0
- package/lib/view/spendManagement/commonSetup/kycKybParseMapper.d.ts +29 -0
- package/lib/view/spendManagement/commonSetup/kycKybParseMapper.js +215 -0
- package/lib/view/spendManagement/commonSetup/setupViewReducer.d.ts +28 -2
- package/lib/view/spendManagement/commonSetup/setupViewReducer.js +107 -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 +154 -0
- package/lib/view/spendManagement/commonSetup/types/kycKybAutofill.js +46 -0
- package/lib/view/taskManager/taskDetailView/epics/createSubTaskEpic.d.ts +9 -0
- package/lib/view/taskManager/taskDetailView/epics/createSubTaskEpic.js +84 -0
- package/lib/view/taskManager/taskDetailView/epics/fetchSubTasksEpic.d.ts +8 -0
- package/lib/view/taskManager/taskDetailView/epics/fetchSubTasksEpic.js +40 -0
- package/lib/view/taskManager/taskDetailView/epics/fetchTaskDetailEpic.d.ts +2 -1
- package/lib/view/taskManager/taskDetailView/epics/fetchTaskDetailEpic.js +13 -0
- package/lib/view/taskManager/taskDetailView/taskDetail.d.ts +13 -0
- package/lib/view/taskManager/taskDetailView/taskDetailReducer.d.ts +14 -2
- package/lib/view/taskManager/taskDetailView/taskDetailReducer.js +57 -3
- package/lib/view/taskManager/taskDetailView/taskDetailSelector.d.ts +2 -1
- package/lib/view/taskManager/taskDetailView/taskDetailSelector.js +17 -6
- package/package.json +1 -1
|
@@ -18,7 +18,7 @@ import { getOnboardingCustomerView } from '../../onboardingCustomerViewSelector'
|
|
|
18
18
|
export const updateOnboardingCustomerViewEpic = (actions$, state$, zeniAPI) => actions$.pipe(filter(updateOnboardingCustomerView.match), mergeMap((action) => {
|
|
19
19
|
const { companyId, officerType, sendForVerification, reCalculateCurrentStep = false, isBillingAddressUpdate, } = action.payload;
|
|
20
20
|
const { onboardingCustomerViewState } = state$.value;
|
|
21
|
-
const { companyDetails, primaryContactDetails, companyOfficerUpdateStatus, currentStep, } = onboardingCustomerViewState;
|
|
21
|
+
const { companyDetails, primaryContactDetails, companyOfficerUpdateStatus, currentStep, currentSubStep, } = onboardingCustomerViewState;
|
|
22
22
|
const companyLocalData = companyDetails.localData;
|
|
23
23
|
const primaryContactLocalData = primaryContactDetails.localData;
|
|
24
24
|
let companyOfficerLocalData;
|
|
@@ -52,8 +52,12 @@ export const updateOnboardingCustomerViewEpic = (actions$, state$, zeniAPI) => a
|
|
|
52
52
|
Boolean(companyOfficerLocalData.email) === true // Don't save Empty Company Officer details
|
|
53
53
|
? toBusinessVerificationOfficerDataPayload(companyOfficerLocalData, false, companyOfficerAddressToCreate)
|
|
54
54
|
: {};
|
|
55
|
+
// Verification step has two sub-steps that share currentStep but save
|
|
56
|
+
// different payloads — currentSubStep is the source of truth here.
|
|
57
|
+
const isOfficerSave = currentStep === 'verification' &&
|
|
58
|
+
currentSubStep === 'company_officer';
|
|
55
59
|
if (isBillingAddressUpdate === false) {
|
|
56
|
-
if (
|
|
60
|
+
if (isOfficerSave) {
|
|
57
61
|
payload = {
|
|
58
62
|
company: toBusinessVerificationMinimalCompanyDataPayload(companyLocalData),
|
|
59
63
|
company_officer,
|
|
@@ -66,6 +70,11 @@ export const updateOnboardingCustomerViewEpic = (actions$, state$, zeniAPI) => a
|
|
|
66
70
|
};
|
|
67
71
|
}
|
|
68
72
|
}
|
|
73
|
+
const section = isBillingAddressUpdate === true
|
|
74
|
+
? 'setup_billing'
|
|
75
|
+
: isOfficerSave
|
|
76
|
+
? 'company_officer'
|
|
77
|
+
: 'company_details';
|
|
69
78
|
const messageSectionMapper = {
|
|
70
79
|
company_officer: {
|
|
71
80
|
sendForVerification: 'onboarding_customer_identity_verification_submit',
|
|
@@ -75,23 +84,20 @@ export const updateOnboardingCustomerViewEpic = (actions$, state$, zeniAPI) => a
|
|
|
75
84
|
sendForVerification: 'onboarding_customer_business_verification_submit',
|
|
76
85
|
save: 'onboarding_customer_business_verification_save',
|
|
77
86
|
},
|
|
78
|
-
|
|
87
|
+
setup_billing: {
|
|
79
88
|
save: 'billing_address_view',
|
|
80
89
|
sendForVerification: 'billing_address_view',
|
|
81
90
|
},
|
|
82
91
|
};
|
|
83
92
|
let messageSection;
|
|
84
93
|
if (isBillingAddressUpdate === true) {
|
|
85
|
-
messageSection = messageSectionMapper[
|
|
94
|
+
messageSection = messageSectionMapper[section].save;
|
|
95
|
+
}
|
|
96
|
+
else if (sendForVerification === true) {
|
|
97
|
+
messageSection = messageSectionMapper[section].sendForVerification;
|
|
86
98
|
}
|
|
87
99
|
else {
|
|
88
|
-
|
|
89
|
-
messageSection =
|
|
90
|
-
messageSectionMapper[currentStep].sendForVerification;
|
|
91
|
-
}
|
|
92
|
-
else {
|
|
93
|
-
messageSection = messageSectionMapper[currentStep].save;
|
|
94
|
-
}
|
|
100
|
+
messageSection = messageSectionMapper[section].save;
|
|
95
101
|
}
|
|
96
102
|
return zeniAPI
|
|
97
103
|
.putAndGetJSON(`${zeniAPI.apiEndPoints.tenantMicroServiceBaseUrl}/1.0/companies/${companyId}`, payload)
|
|
@@ -114,18 +120,18 @@ export const updateOnboardingCustomerViewEpic = (actions$, state$, zeniAPI) => a
|
|
|
114
120
|
const externalConnections = currentTenant.externalConnections;
|
|
115
121
|
const isQBOConnection = externalConnections?.accounting?.some((connection) => connection.connectionName.match(/quickbooks/i)) ?? false;
|
|
116
122
|
const { allSteps } = getOnboardingCustomerView(state$.value, companyId);
|
|
117
|
-
if (currentStep === '
|
|
123
|
+
if (currentStep === 'setup_billing') {
|
|
118
124
|
if (isQBOConnection === true &&
|
|
119
|
-
allSteps.includes('
|
|
120
|
-
actions.push(updateCurrentStep({ step: '
|
|
125
|
+
allSteps.includes('connect_ledger')) {
|
|
126
|
+
actions.push(updateCurrentStep({ step: 'connect_ledger' }));
|
|
121
127
|
}
|
|
122
128
|
else {
|
|
123
|
-
actions.push(updateCurrentStep({ step: '
|
|
129
|
+
actions.push(updateCurrentStep({ step: 'verification' }));
|
|
124
130
|
}
|
|
125
131
|
}
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
132
|
+
// The officer→details transition is now a sub-step change
|
|
133
|
+
// handled by the page (currentSubStep dispatch). No
|
|
134
|
+
// currentStep update needed for that traversal anymore.
|
|
129
135
|
actions.push(updateOnboardingCustomerViewLocalStoreData({
|
|
130
136
|
companyId: response.data.companies[0].company_id,
|
|
131
137
|
currentStep,
|
|
@@ -12,11 +12,11 @@ import { newAddressInLocalStore, resetNewAddressesInLocalStore, } from '../../..
|
|
|
12
12
|
import { toAddressViewLocalData } from '../../../../addressView/toAddressViewLocalData';
|
|
13
13
|
import { getCompanyView } from '../../../../companyView/selectorHelpers/getCompanyView';
|
|
14
14
|
import { toSetupViewLocalData } from '../../../../spendManagement/commonSetup/epic/setup/updateSetupViewLocalStoreDataEpic';
|
|
15
|
-
import { clearOnboardingCustomerViewDataInLocalStore, saveOnboardingCustomerViewDataInLocalStore, updateCurrentStep, updateOnboardingCustomerViewLocalStoreData, } from '../../onboardingCustomerViewReducer';
|
|
16
|
-
import {
|
|
15
|
+
import { clearOnboardingCustomerViewDataInLocalStore, saveOnboardingCustomerViewDataInLocalStore, updateCurrentStep, updateCurrentSubStep, updateOnboardingCustomerViewLocalStoreData, } from '../../onboardingCustomerViewReducer';
|
|
16
|
+
import { onboardingStepsData } from '../../onboardingCustomerViewSelector';
|
|
17
17
|
export const updateOnboardingCustomerViewLocalStoreDataEpic = (actions$, state$) => actions$.pipe(filter(updateOnboardingCustomerViewLocalStoreData.match), mergeMap((action) => {
|
|
18
18
|
const { companyId, currentStep, reCalculateCurrentStep } = action.payload;
|
|
19
|
-
const { companyState, companyViewState,
|
|
19
|
+
const { companyState, companyViewState, userState, userRoleState, onboardingCustomerViewState, subscriptionPaymentAccountState, paymentAccountState, addressState, } = state$.value;
|
|
20
20
|
const { subscriptionPaymentAccountIds } = onboardingCustomerViewState;
|
|
21
21
|
const subscriptionIDs = recordGet(companyViewState.passportView.subscriptionIDsByCompanyID, companyId, undefined);
|
|
22
22
|
const companyView = getCompanyView(state$.value, companyId, subscriptionIDs ?? []);
|
|
@@ -36,7 +36,12 @@ export const updateOnboardingCustomerViewLocalStoreDataEpic = (actions$, state$)
|
|
|
36
36
|
const onboardingCustomerViewLocalData = toOnboardingCustomerViewLocalData(company, companyOfficers, companyOfficerRoles, primaryContact);
|
|
37
37
|
const { companyDetails, officers, primaryContactDetails } = onboardingCustomerViewLocalData;
|
|
38
38
|
let updatedCompanyDetails = companyDetails;
|
|
39
|
-
|
|
39
|
+
// After an officer sub-step save inside the verification step, propagate
|
|
40
|
+
// the latest syncToken into the cached company-details local data so the
|
|
41
|
+
// user's next details-save doesn't 409.
|
|
42
|
+
const isOfficerSave = currentStep === 'verification' &&
|
|
43
|
+
onboardingCustomerViewState.currentSubStep === 'company_officer';
|
|
44
|
+
if (isOfficerSave &&
|
|
40
45
|
onboardingCustomerViewState.companyDetails.localData != null) {
|
|
41
46
|
const { companyInfo } = company;
|
|
42
47
|
const { syncToken } = companyInfo;
|
|
@@ -45,7 +50,7 @@ export const updateOnboardingCustomerViewLocalStoreDataEpic = (actions$, state$)
|
|
|
45
50
|
syncToken,
|
|
46
51
|
};
|
|
47
52
|
}
|
|
48
|
-
let updatedCurrentStep = '
|
|
53
|
+
let updatedCurrentStep = 'setup_billing';
|
|
49
54
|
let subscriptionPaymentAccount;
|
|
50
55
|
const { companyOnboardingInfo } = company;
|
|
51
56
|
const accountingConnectionCreationMode = companyOnboardingInfo?.onboardingInfo
|
|
@@ -72,18 +77,17 @@ export const updateOnboardingCustomerViewLocalStoreDataEpic = (actions$, state$)
|
|
|
72
77
|
cardPaymentViewState.cardPaymentsIds.length > 0) &&
|
|
73
78
|
companyView?.company.company.companyOnboardingInfo
|
|
74
79
|
.subscriptionBillingAddressId != null) {
|
|
75
|
-
updatedCurrentStep = '
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
}
|
|
80
|
+
updatedCurrentStep = 'connect_ledger';
|
|
81
|
+
const isOnboardingAiActivationViewed = companyOnboardingInfo?.onboardingInfo
|
|
82
|
+
?.onboardingAiActivationInfo?.isOnboardingAiActivationViewed ??
|
|
83
|
+
false;
|
|
84
|
+
// Past the ledger step we always sit on connect_data_source —
|
|
85
|
+
// it has many integrations, so we treat it as never auto-complete
|
|
86
|
+
// and only advance to verification on an explicit user dispatch.
|
|
87
|
+
// While the AI activation interstitial hasn't been viewed yet,
|
|
88
|
+
// stay on connect_ledger so the interstitial gets its chance.
|
|
89
|
+
if (isValidConnection && isOnboardingAiActivationViewed) {
|
|
90
|
+
updatedCurrentStep = 'connect_data_source';
|
|
87
91
|
}
|
|
88
92
|
}
|
|
89
93
|
}
|
|
@@ -105,6 +109,14 @@ export const updateOnboardingCustomerViewLocalStoreDataEpic = (actions$, state$)
|
|
|
105
109
|
}
|
|
106
110
|
if (reCalculateCurrentStep === true) {
|
|
107
111
|
fetchActions.push(updateCurrentStep({ step: updatedCurrentStep }));
|
|
112
|
+
// Whenever the recalc lands the user on a different step, reset
|
|
113
|
+
// the sub-step to the step's landing sub-state — otherwise a
|
|
114
|
+
// stale subStep (e.g. 'default' carried over from another step)
|
|
115
|
+
// leaves verification rendering an empty form.
|
|
116
|
+
if (updatedCurrentStep !== onboardingCustomerViewState.currentStep) {
|
|
117
|
+
const targetSubStep = updatedCurrentStep === 'verification' ? 'unlock-stack' : 'default';
|
|
118
|
+
fetchActions.push(updateCurrentSubStep({ subStep: targetSubStep }));
|
|
119
|
+
}
|
|
108
120
|
}
|
|
109
121
|
}
|
|
110
122
|
if (companyView != null) {
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { createSlice } from '@reduxjs/toolkit';
|
|
2
2
|
import { date } from '../../../zeniDayJS';
|
|
3
|
+
import { parseUploadedKybDocument, parseUploadedKybDocumentFailure, parseUploadedKycDocument, parseUploadedKycDocumentFailure, } from '../../spendManagement/commonSetup/kycKybAutofillActions';
|
|
4
|
+
import { emptyAiAgentsActivationSubview, } from './onboardingCustomerViewState';
|
|
3
5
|
const initialStatus = {
|
|
4
6
|
fetchState: 'Not-Started',
|
|
5
7
|
error: undefined,
|
|
@@ -8,62 +10,33 @@ export const initialState = {
|
|
|
8
10
|
updateStatus: initialStatus,
|
|
9
11
|
saveStatus: initialStatus,
|
|
10
12
|
dashboardLoadedStatus: initialStatus,
|
|
11
|
-
currentStep: '
|
|
13
|
+
currentStep: 'setup_billing',
|
|
14
|
+
currentSubStep: 'default',
|
|
15
|
+
parsingDocumentFileIds: [],
|
|
12
16
|
companyDetails: {
|
|
17
|
+
autoFilledFields: [],
|
|
13
18
|
localData: undefined,
|
|
14
19
|
},
|
|
15
|
-
companyOfficerUpdateStatus: {
|
|
16
|
-
|
|
20
|
+
companyOfficerUpdateStatus: (() => {
|
|
21
|
+
const emptyOfficerSlot = {
|
|
22
|
+
autoFilledFields: [],
|
|
17
23
|
localData: undefined,
|
|
18
24
|
sendOtpStatus: initialStatus,
|
|
19
25
|
otpverificationStatus: initialStatus,
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
otpverificationStatus: initialStatus,
|
|
35
|
-
},
|
|
36
|
-
Officer_5: {
|
|
37
|
-
localData: undefined,
|
|
38
|
-
sendOtpStatus: initialStatus,
|
|
39
|
-
otpverificationStatus: initialStatus,
|
|
40
|
-
},
|
|
41
|
-
Officer_6: {
|
|
42
|
-
localData: undefined,
|
|
43
|
-
sendOtpStatus: initialStatus,
|
|
44
|
-
otpverificationStatus: initialStatus,
|
|
45
|
-
},
|
|
46
|
-
Officer_7: {
|
|
47
|
-
localData: undefined,
|
|
48
|
-
sendOtpStatus: initialStatus,
|
|
49
|
-
otpverificationStatus: initialStatus,
|
|
50
|
-
},
|
|
51
|
-
Officer_8: {
|
|
52
|
-
localData: undefined,
|
|
53
|
-
sendOtpStatus: initialStatus,
|
|
54
|
-
otpverificationStatus: initialStatus,
|
|
55
|
-
},
|
|
56
|
-
Officer_9: {
|
|
57
|
-
localData: undefined,
|
|
58
|
-
sendOtpStatus: initialStatus,
|
|
59
|
-
otpverificationStatus: initialStatus,
|
|
60
|
-
},
|
|
61
|
-
Officer_10: {
|
|
62
|
-
localData: undefined,
|
|
63
|
-
sendOtpStatus: initialStatus,
|
|
64
|
-
otpverificationStatus: initialStatus,
|
|
65
|
-
},
|
|
66
|
-
},
|
|
26
|
+
};
|
|
27
|
+
return {
|
|
28
|
+
Officer_1: { ...emptyOfficerSlot },
|
|
29
|
+
Officer_2: { ...emptyOfficerSlot },
|
|
30
|
+
Officer_3: { ...emptyOfficerSlot },
|
|
31
|
+
Officer_4: { ...emptyOfficerSlot },
|
|
32
|
+
Officer_5: { ...emptyOfficerSlot },
|
|
33
|
+
Officer_6: { ...emptyOfficerSlot },
|
|
34
|
+
Officer_7: { ...emptyOfficerSlot },
|
|
35
|
+
Officer_8: { ...emptyOfficerSlot },
|
|
36
|
+
Officer_9: { ...emptyOfficerSlot },
|
|
37
|
+
Officer_10: { ...emptyOfficerSlot },
|
|
38
|
+
};
|
|
39
|
+
})(),
|
|
67
40
|
primaryContactDetails: {},
|
|
68
41
|
paymentAccountDetails: {
|
|
69
42
|
fetchStatus: initialStatus,
|
|
@@ -91,6 +64,7 @@ export const initialState = {
|
|
|
91
64
|
},
|
|
92
65
|
fetchState: 'Not-Started',
|
|
93
66
|
error: undefined,
|
|
67
|
+
aiAgentsActivation: { ...emptyAiAgentsActivationSubview },
|
|
94
68
|
uiState: {
|
|
95
69
|
isQBOPopupOpen: false,
|
|
96
70
|
isCardPaymentPopupOpen: false,
|
|
@@ -143,6 +117,9 @@ const onboardingCustomerView = createSlice({
|
|
|
143
117
|
updateCurrentStep(draft, action) {
|
|
144
118
|
draft.currentStep = action.payload.step;
|
|
145
119
|
},
|
|
120
|
+
updateCurrentSubStep(draft, action) {
|
|
121
|
+
draft.currentSubStep = action.payload.subStep;
|
|
122
|
+
},
|
|
146
123
|
updateOnboardingCustomerViewAccountDetails: {
|
|
147
124
|
prepare(paymentAccountIds, subscriptionPaymentAccountIds) {
|
|
148
125
|
return { payload: { paymentAccountIds, subscriptionPaymentAccountIds } };
|
|
@@ -180,6 +157,126 @@ const onboardingCustomerView = createSlice({
|
|
|
180
157
|
};
|
|
181
158
|
},
|
|
182
159
|
},
|
|
160
|
+
acknowledgeOnboardingAiFinanceTeam: {
|
|
161
|
+
reducer(draft) {
|
|
162
|
+
draft.aiFinanceTeamAcknowledgementStatus = {
|
|
163
|
+
fetchState: 'In-Progress',
|
|
164
|
+
error: undefined,
|
|
165
|
+
};
|
|
166
|
+
},
|
|
167
|
+
prepare(companyId) {
|
|
168
|
+
return {
|
|
169
|
+
payload: { companyId },
|
|
170
|
+
};
|
|
171
|
+
},
|
|
172
|
+
},
|
|
173
|
+
acknowledgeOnboardingAiFinanceTeamSuccess(draft) {
|
|
174
|
+
draft.aiFinanceTeamAcknowledgementStatus = {
|
|
175
|
+
fetchState: 'Completed',
|
|
176
|
+
error: undefined,
|
|
177
|
+
};
|
|
178
|
+
},
|
|
179
|
+
acknowledgeOnboardingAiFinanceTeamFailure: {
|
|
180
|
+
reducer(draft, action) {
|
|
181
|
+
draft.aiFinanceTeamAcknowledgementStatus = {
|
|
182
|
+
fetchState: 'Error',
|
|
183
|
+
error: action.payload,
|
|
184
|
+
};
|
|
185
|
+
},
|
|
186
|
+
prepare(error) {
|
|
187
|
+
return {
|
|
188
|
+
payload: error,
|
|
189
|
+
};
|
|
190
|
+
},
|
|
191
|
+
},
|
|
192
|
+
acknowledgeOnboardingAiActivationViewed: {
|
|
193
|
+
reducer(draft) {
|
|
194
|
+
draft.aiActivationViewedAcknowledgementStatus = {
|
|
195
|
+
fetchState: 'In-Progress',
|
|
196
|
+
error: undefined,
|
|
197
|
+
};
|
|
198
|
+
},
|
|
199
|
+
prepare(companyId) {
|
|
200
|
+
return {
|
|
201
|
+
payload: { companyId },
|
|
202
|
+
};
|
|
203
|
+
},
|
|
204
|
+
},
|
|
205
|
+
acknowledgeOnboardingAiActivationViewedSuccess(draft) {
|
|
206
|
+
draft.aiActivationViewedAcknowledgementStatus = {
|
|
207
|
+
fetchState: 'Completed',
|
|
208
|
+
error: undefined,
|
|
209
|
+
};
|
|
210
|
+
},
|
|
211
|
+
acknowledgeOnboardingAiActivationViewedFailure: {
|
|
212
|
+
reducer(draft, action) {
|
|
213
|
+
draft.aiActivationViewedAcknowledgementStatus = {
|
|
214
|
+
fetchState: 'Error',
|
|
215
|
+
error: action.payload,
|
|
216
|
+
};
|
|
217
|
+
},
|
|
218
|
+
prepare(error) {
|
|
219
|
+
return {
|
|
220
|
+
payload: error,
|
|
221
|
+
};
|
|
222
|
+
},
|
|
223
|
+
},
|
|
224
|
+
fetchAiAgentsActivationStatus(draft) {
|
|
225
|
+
draft.aiAgentsActivation.fetchStatus = {
|
|
226
|
+
fetchState: 'In-Progress',
|
|
227
|
+
error: undefined,
|
|
228
|
+
};
|
|
229
|
+
},
|
|
230
|
+
fetchAiAgentsActivationStatusSuccess: {
|
|
231
|
+
reducer(draft, action) {
|
|
232
|
+
draft.aiAgentsActivation.fetchStatus = {
|
|
233
|
+
fetchState: 'Completed',
|
|
234
|
+
error: undefined,
|
|
235
|
+
};
|
|
236
|
+
draft.aiAgentsActivation.phases = action.payload.phases;
|
|
237
|
+
draft.aiAgentsActivation.counts = action.payload.counts;
|
|
238
|
+
},
|
|
239
|
+
prepare(payload) {
|
|
240
|
+
return { payload };
|
|
241
|
+
},
|
|
242
|
+
},
|
|
243
|
+
fetchAiAgentsActivationStatusFailure: {
|
|
244
|
+
reducer(draft, action) {
|
|
245
|
+
draft.aiAgentsActivation.fetchStatus = {
|
|
246
|
+
fetchState: 'Error',
|
|
247
|
+
error: action.payload,
|
|
248
|
+
};
|
|
249
|
+
},
|
|
250
|
+
prepare(error) {
|
|
251
|
+
return { payload: error };
|
|
252
|
+
},
|
|
253
|
+
},
|
|
254
|
+
aiAgentsActivationCountsUpdated: {
|
|
255
|
+
reducer(draft, action) {
|
|
256
|
+
draft.aiAgentsActivation.counts = {
|
|
257
|
+
...draft.aiAgentsActivation.counts,
|
|
258
|
+
...action.payload,
|
|
259
|
+
};
|
|
260
|
+
},
|
|
261
|
+
prepare(payload) {
|
|
262
|
+
return { payload };
|
|
263
|
+
},
|
|
264
|
+
},
|
|
265
|
+
aiAgentsActivationPhaseChanged: {
|
|
266
|
+
reducer(draft, action) {
|
|
267
|
+
const target = draft.aiAgentsActivation.phases;
|
|
268
|
+
const index = target.findIndex((phase) => phase.key === action.payload.key);
|
|
269
|
+
if (index === -1) {
|
|
270
|
+
target.push(action.payload);
|
|
271
|
+
}
|
|
272
|
+
else {
|
|
273
|
+
target[index] = { ...target[index], ...action.payload };
|
|
274
|
+
}
|
|
275
|
+
},
|
|
276
|
+
prepare(payload) {
|
|
277
|
+
return { payload };
|
|
278
|
+
},
|
|
279
|
+
},
|
|
183
280
|
updateOnboardingCustomerViewDashboardLoaded: {
|
|
184
281
|
reducer(draft) {
|
|
185
282
|
draft.dashboardLoadedStatus = {
|
|
@@ -592,7 +689,82 @@ const onboardingCustomerView = createSlice({
|
|
|
592
689
|
clearOnboardingCustomerView(draft) {
|
|
593
690
|
Object.assign(draft, initialState);
|
|
594
691
|
},
|
|
692
|
+
/** Merge AI-parsed officer fields into the officer's onboarding localData. */
|
|
693
|
+
applyKycDocumentAutofillForOnboarding: {
|
|
694
|
+
reducer(draft, action) {
|
|
695
|
+
const { officerType, values, autoFilledFieldNames, fileId } = action.payload;
|
|
696
|
+
const slot = draft.companyOfficerUpdateStatus[officerType];
|
|
697
|
+
slot.localData = Object.assign({}, slot.localData, values);
|
|
698
|
+
slot.autoFilledFields = Array.from(new Set([...(slot.autoFilledFields ?? []), ...autoFilledFieldNames]));
|
|
699
|
+
draft.parsingDocumentFileIds = (draft.parsingDocumentFileIds ?? []).filter((id) => id !== fileId);
|
|
700
|
+
},
|
|
701
|
+
prepare(payload) {
|
|
702
|
+
return { payload };
|
|
703
|
+
},
|
|
704
|
+
},
|
|
705
|
+
/** Merge AI-parsed company fields into companyDetails onboarding localData. */
|
|
706
|
+
applyKybDocumentAutofillForOnboarding: {
|
|
707
|
+
reducer(draft, action) {
|
|
708
|
+
const { values, autoFilledFieldNames, fileId } = action.payload;
|
|
709
|
+
draft.companyDetails.localData = Object.assign({}, draft.companyDetails.localData, values);
|
|
710
|
+
const prev = draft.companyDetails.autoFilledFields ?? [];
|
|
711
|
+
draft.companyDetails.autoFilledFields = Array.from(new Set([...prev, ...autoFilledFieldNames]));
|
|
712
|
+
draft.parsingDocumentFileIds = (draft.parsingDocumentFileIds ?? []).filter((id) => id !== fileId);
|
|
713
|
+
},
|
|
714
|
+
prepare(payload) {
|
|
715
|
+
return { payload };
|
|
716
|
+
},
|
|
717
|
+
},
|
|
718
|
+
/** Wipe AI-autofill badges during onboarding. */
|
|
719
|
+
clearKycKybAutofillForOnboarding: {
|
|
720
|
+
reducer(draft, action) {
|
|
721
|
+
const { officerType } = action.payload;
|
|
722
|
+
if (officerType != null) {
|
|
723
|
+
draft.companyOfficerUpdateStatus[officerType].autoFilledFields = [];
|
|
724
|
+
}
|
|
725
|
+
else {
|
|
726
|
+
draft.companyDetails.autoFilledFields = [];
|
|
727
|
+
Object.keys(draft.companyOfficerUpdateStatus).forEach((key) => {
|
|
728
|
+
draft.companyOfficerUpdateStatus[key].autoFilledFields = [];
|
|
729
|
+
});
|
|
730
|
+
}
|
|
731
|
+
},
|
|
732
|
+
prepare(payload = {}) {
|
|
733
|
+
return { payload };
|
|
734
|
+
},
|
|
735
|
+
},
|
|
736
|
+
},
|
|
737
|
+
extraReducers: (builder) => {
|
|
738
|
+
const addParsingFileId = (draft, fileId) => {
|
|
739
|
+
draft.parsingDocumentFileIds = draft.parsingDocumentFileIds ?? [];
|
|
740
|
+
if (!draft.parsingDocumentFileIds.includes(fileId)) {
|
|
741
|
+
draft.parsingDocumentFileIds.push(fileId);
|
|
742
|
+
}
|
|
743
|
+
};
|
|
744
|
+
const removeParsingFileId = (draft, fileId) => {
|
|
745
|
+
draft.parsingDocumentFileIds = (draft.parsingDocumentFileIds ?? []).filter((id) => id !== fileId);
|
|
746
|
+
};
|
|
747
|
+
builder.addCase(parseUploadedKycDocument, (draft, action) => {
|
|
748
|
+
if (action.payload.target === 'onboarding') {
|
|
749
|
+
addParsingFileId(draft, action.payload.fileId);
|
|
750
|
+
}
|
|
751
|
+
});
|
|
752
|
+
builder.addCase(parseUploadedKybDocument, (draft, action) => {
|
|
753
|
+
if (action.payload.target === 'onboarding') {
|
|
754
|
+
addParsingFileId(draft, action.payload.fileId);
|
|
755
|
+
}
|
|
756
|
+
});
|
|
757
|
+
builder.addCase(parseUploadedKycDocumentFailure, (draft, action) => {
|
|
758
|
+
if (action.payload.target === 'onboarding') {
|
|
759
|
+
removeParsingFileId(draft, action.payload.fileId);
|
|
760
|
+
}
|
|
761
|
+
});
|
|
762
|
+
builder.addCase(parseUploadedKybDocumentFailure, (draft, action) => {
|
|
763
|
+
if (action.payload.target === 'onboarding') {
|
|
764
|
+
removeParsingFileId(draft, action.payload.fileId);
|
|
765
|
+
}
|
|
766
|
+
});
|
|
595
767
|
},
|
|
596
768
|
});
|
|
597
|
-
export const { fetchOnboardingCustomerView, fetchOnboardingCustomerSetupView, fetchOnboardingCustomerSetupViewSuccess, fetchOnboardingCustomerSetupViewFailure, updateOnboardingCustomerViewCompleteStatus, updateOnboardingCustomerViewCompleteStatusSuccess, updateOnboardingCustomerViewCompleteStatusFailure, updateOnboardingCustomerViewDashboardLoaded, updateOnboardingCustomerViewDashboardLoadedSuccess, updateOnboardingCustomerViewDashboardLoadedFailure, updateOnboardingCustomerView, updateOnboardingCustomerViewSuccess, updateOnboardingCustomerViewFailure, updateOnboardingPaymentAccountStatus, updateOnboardingPaymentAccountStatusSuccess, updateOnboardingPaymentAccountStatusFailure, updateOnboardingPaymentAccountLoginStatus, updateOnboardingPaymentAccountLoginStatusSuccess, updateOnboardingPaymentAccountLoginStatusFailure, establishOnboardingPlaidConnection, establishOnboardingPlaidConnectionSuccess, establishOnboardingPlaidConnectionFailure, getOnboardingPlaidLinkToken, getOnboardingPlaidLinkTokenSuccess, getOnboardingPlaidLinkTokenFailure, updateCurrentStep, updateOnboardingCustomerViewAccountDetails, updateOnboardingCustomerViewLocalStoreData, saveOnboardingCustomerViewDataInLocalStore, saveOnboardingCompnayOfficerPhoneInLocalStore, updateOnboardingCustomerViewUIState, sendOnboardingOfficerOtp, sendOnboardingOfficerOtpSuccess, sendOnboardingOfficerOtpFailure, resendOnboardingOfficerOtp, verifyOnboardingOfficerOtp, verifyOnboardingOfficerOtpSuccess, verifyOnboardingOfficerOtpFailure, clearOnboardingCustomerViewDataInLocalStore, clearOnboardingCustomerView, } = onboardingCustomerView.actions;
|
|
769
|
+
export const { fetchOnboardingCustomerView, fetchOnboardingCustomerSetupView, fetchOnboardingCustomerSetupViewSuccess, fetchOnboardingCustomerSetupViewFailure, updateOnboardingCustomerViewCompleteStatus, updateOnboardingCustomerViewCompleteStatusSuccess, updateOnboardingCustomerViewCompleteStatusFailure, acknowledgeOnboardingAiFinanceTeam, acknowledgeOnboardingAiFinanceTeamSuccess, acknowledgeOnboardingAiFinanceTeamFailure, acknowledgeOnboardingAiActivationViewed, acknowledgeOnboardingAiActivationViewedSuccess, acknowledgeOnboardingAiActivationViewedFailure, fetchAiAgentsActivationStatus, fetchAiAgentsActivationStatusSuccess, fetchAiAgentsActivationStatusFailure, aiAgentsActivationCountsUpdated, aiAgentsActivationPhaseChanged, updateOnboardingCustomerViewDashboardLoaded, updateOnboardingCustomerViewDashboardLoadedSuccess, updateOnboardingCustomerViewDashboardLoadedFailure, updateOnboardingCustomerView, updateOnboardingCustomerViewSuccess, updateOnboardingCustomerViewFailure, updateOnboardingPaymentAccountStatus, updateOnboardingPaymentAccountStatusSuccess, updateOnboardingPaymentAccountStatusFailure, updateOnboardingPaymentAccountLoginStatus, updateOnboardingPaymentAccountLoginStatusSuccess, updateOnboardingPaymentAccountLoginStatusFailure, establishOnboardingPlaidConnection, establishOnboardingPlaidConnectionSuccess, establishOnboardingPlaidConnectionFailure, getOnboardingPlaidLinkToken, getOnboardingPlaidLinkTokenSuccess, getOnboardingPlaidLinkTokenFailure, updateCurrentStep, updateCurrentSubStep, updateOnboardingCustomerViewAccountDetails, updateOnboardingCustomerViewLocalStoreData, saveOnboardingCustomerViewDataInLocalStore, saveOnboardingCompnayOfficerPhoneInLocalStore, updateOnboardingCustomerViewUIState, sendOnboardingOfficerOtp, sendOnboardingOfficerOtpSuccess, sendOnboardingOfficerOtpFailure, resendOnboardingOfficerOtp, verifyOnboardingOfficerOtp, verifyOnboardingOfficerOtpSuccess, verifyOnboardingOfficerOtpFailure, clearOnboardingCustomerViewDataInLocalStore, clearOnboardingCustomerView, applyKycDocumentAutofillForOnboarding, applyKybDocumentAutofillForOnboarding, clearKycKybAutofillForOnboarding, } = onboardingCustomerView.actions;
|
|
598
770
|
export default onboardingCustomerView.reducer;
|
|
@@ -8,10 +8,10 @@ import { getUserRoleByUserIds } from '../../../entity/userRole/userRoleSelector'
|
|
|
8
8
|
import { getCompanyConfig } from '../../companyConfigView/companyConfigSelector';
|
|
9
9
|
import { getCompanyView } from '../../companyView/selectorHelpers/getCompanyView';
|
|
10
10
|
import { getCompanyAndIdentityDetails, } from '../../spendManagement/commonSetup/setupViewSelector';
|
|
11
|
-
import { ALL_ONBOARDING_STEPS, ALL_ZENI_USER_ONBOARDING_STEPS, REQUIRED_ONBOARDING_STEPS, ZENI_USER_REQUIRED_ONBOARDING_STEPS, toOnboardingStepType, } from './onboardingCustomerViewState';
|
|
11
|
+
import { ALL_ONBOARDING_STEPS, ALL_ZENI_USER_ONBOARDING_STEPS, REQUIRED_ONBOARDING_STEPS, ZENI_USER_REQUIRED_ONBOARDING_STEPS, emptyAiAgentsActivationSubview, toOnboardingStepType, } from './onboardingCustomerViewState';
|
|
12
12
|
export function getOnboardingCustomerView(state, companyId) {
|
|
13
13
|
const { fileState, paymentAccountState, onboardingCustomerViewState, userState, userRoleState, subscriptionPaymentAccountState, companyConfigState, cardPaymentViewState, countryListState, addressViewState, } = state;
|
|
14
|
-
const { companyDetails, companyOfficerUpdateStatus, primaryContactDetails, subscriptionPaymentAccountIds, paymentAccountDetails, plaidConnectionDetails, updateStatus, saveStatus, currentStep, uiState, fetchState, error, } = onboardingCustomerViewState;
|
|
14
|
+
const { companyDetails, companyOfficerUpdateStatus, primaryContactDetails, subscriptionPaymentAccountIds, paymentAccountDetails, plaidConnectionDetails, parsingDocumentFileIds, updateStatus, saveStatus, currentStep, currentSubStep, uiState, fetchState, error, } = onboardingCustomerViewState;
|
|
15
15
|
const { paymentAccountIds } = paymentAccountDetails;
|
|
16
16
|
let subscriptionPaymentAccount;
|
|
17
17
|
let paymentAccount;
|
|
@@ -54,6 +54,7 @@ export function getOnboardingCustomerView(state, companyId) {
|
|
|
54
54
|
companyDetails,
|
|
55
55
|
companyOfficerUpdateStatus,
|
|
56
56
|
primaryContactDetails,
|
|
57
|
+
parsingDocumentFileIds,
|
|
57
58
|
});
|
|
58
59
|
const companyAddress = addressViewState.newAddressState?.company_address;
|
|
59
60
|
if (companyAddress == null &&
|
|
@@ -73,7 +74,7 @@ export function getOnboardingCustomerView(state, companyId) {
|
|
|
73
74
|
cardPaymentViewState.cardPaymentsIds.length > 0) &&
|
|
74
75
|
companyView?.company.company.companyOnboardingInfo
|
|
75
76
|
.subscriptionBillingAddressId != null) {
|
|
76
|
-
completedSteps.push('
|
|
77
|
+
completedSteps.push('setup_billing');
|
|
77
78
|
}
|
|
78
79
|
const isPaymentVerified = (paymentAccount?.providerVerificationStatus?.code?.includes('verified') ===
|
|
79
80
|
true &&
|
|
@@ -84,24 +85,25 @@ export function getOnboardingCustomerView(state, companyId) {
|
|
|
84
85
|
.subscriptionBillingAddressId != null;
|
|
85
86
|
if ((isPaymentVerified || hasSubscriptionBillingAddress) &&
|
|
86
87
|
!(isPaymentVerified && hasSubscriptionBillingAddress)) {
|
|
87
|
-
halfCompletedSteps.push('
|
|
88
|
+
halfCompletedSteps.push('setup_billing');
|
|
88
89
|
}
|
|
89
90
|
const isValidConnection = externalConnections?.accounting[0]?.isValid ?? false;
|
|
90
91
|
if (isValidConnection) {
|
|
91
|
-
completedSteps.push('
|
|
92
|
+
completedSteps.push('connect_ledger');
|
|
92
93
|
}
|
|
93
|
-
|
|
94
|
+
const isCompanyDetailsDone = companyDetails.localData != null &&
|
|
94
95
|
primaryContactDetails.localData != null &&
|
|
95
|
-
isCompanyDetailsCompleted(fileState, companyView, primaryContact)
|
|
96
|
-
completedSteps.push('company_details');
|
|
97
|
-
}
|
|
96
|
+
isCompanyDetailsCompleted(fileState, companyView, primaryContact);
|
|
98
97
|
const officerIndex = companyOfficers.length > 0
|
|
99
98
|
? Object.values(companyOfficerLocalData).findIndex((officer) => officer?.isSelectedForVerification === true)
|
|
100
99
|
: 0;
|
|
101
100
|
const selectedOfficerType = `Officer_${officerIndex < 0 ? 1 : officerIndex + 1}`;
|
|
102
|
-
|
|
103
|
-
isOfficerDetailsCompleted(companyOfficers, companyOfficerRoles, companyOfficerLocalData[selectedOfficerType], fileState)
|
|
104
|
-
|
|
101
|
+
const isOfficerDone = companyOfficerLocalData[selectedOfficerType] != null &&
|
|
102
|
+
isOfficerDetailsCompleted(companyOfficers, companyOfficerRoles, companyOfficerLocalData[selectedOfficerType], fileState);
|
|
103
|
+
// The verification step (single sidebar step) is only "complete" once both
|
|
104
|
+
// the company-officer and company-details sub-steps are fully filled in.
|
|
105
|
+
if (isCompanyDetailsDone && isOfficerDone) {
|
|
106
|
+
completedSteps.push('verification');
|
|
105
107
|
}
|
|
106
108
|
const { allStepsData, requiredStepsData } = onboardingStepsData(isValidConnection, currentTenant?.productSettings ?? [], accountingConnectionCreationMode);
|
|
107
109
|
const allRequiredStepsCompleted = requiredStepsData.every((step) => {
|
|
@@ -119,6 +121,7 @@ export function getOnboardingCustomerView(state, companyId) {
|
|
|
119
121
|
return {
|
|
120
122
|
companyDetailsLocalData,
|
|
121
123
|
companyOfficerLocalData,
|
|
124
|
+
parsingDocumentFileIds,
|
|
122
125
|
subscriptionBillingAddress: subscriptionBillingAddress?.addressToCreate,
|
|
123
126
|
companyView,
|
|
124
127
|
allNationalityCountries,
|
|
@@ -127,6 +130,7 @@ export function getOnboardingCustomerView(state, companyId) {
|
|
|
127
130
|
officer: isOfficerDetailsSavePending(companyOfficers, companyOfficerRoles, fileState, companyOfficerLocalData[selectedOfficerType]),
|
|
128
131
|
},
|
|
129
132
|
currentStep,
|
|
133
|
+
currentSubStep,
|
|
130
134
|
completedSteps,
|
|
131
135
|
halfCompletedSteps,
|
|
132
136
|
allRequiredStepsCompleted,
|
|
@@ -323,3 +327,11 @@ export const getProductSettingsString = (productSettings) => {
|
|
|
323
327
|
.map((key) => productKeyMap[key])
|
|
324
328
|
.join(',');
|
|
325
329
|
};
|
|
330
|
+
const fromActivationView = (state) =>
|
|
331
|
+
// Fall back to the empty subview so state hydrated from an older persisted
|
|
332
|
+
// version (before aiAgentsActivation existed) doesn't crash on .phases/.counts.
|
|
333
|
+
state.onboardingCustomerViewState.aiAgentsActivation ??
|
|
334
|
+
emptyAiAgentsActivationSubview;
|
|
335
|
+
export const getAiAgentsActivationSubview = (state) => fromActivationView(state);
|
|
336
|
+
export const getAiAgentsActivationPhases = (state) => fromActivationView(state).phases;
|
|
337
|
+
export const getAiAgentsActivationCounts = (state) => fromActivationView(state).counts;
|
|
@@ -1,17 +1,18 @@
|
|
|
1
1
|
import { stringToUnion } from '../../../commonStateTypes/stringToUnion';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
2
|
+
// Onboarding steps are the 4 top-level surfaces. Officer + details verification
|
|
3
|
+
// live as sub-steps under `verification` (state machine in CustomerOnboardingPage).
|
|
4
|
+
// The optional data-source step is its own surface; the legacy connect-data-source
|
|
5
|
+
// sub-step under the old `qbo_connection` no longer exists.
|
|
6
|
+
export const ZENI_USER_REQUIRED_ONBOARDING_STEPS = ['setup_billing'];
|
|
5
7
|
export const CUSTOMER_REQUIRED_ONBOARDING_STEPS_WITH_QBO = [
|
|
6
|
-
'
|
|
8
|
+
'connect_ledger',
|
|
7
9
|
];
|
|
8
10
|
export const REQUIRED_ONBOARDING_STEPS = [
|
|
9
11
|
...ZENI_USER_REQUIRED_ONBOARDING_STEPS,
|
|
10
12
|
...CUSTOMER_REQUIRED_ONBOARDING_STEPS_WITH_QBO,
|
|
11
13
|
];
|
|
12
14
|
export const ALL_ZENI_USER_ONBOARDING_STEPS_WITHOUT_ACCOUNT = [
|
|
13
|
-
'
|
|
14
|
-
'company_details',
|
|
15
|
+
'verification',
|
|
15
16
|
];
|
|
16
17
|
export const ALL_ZENI_USER_ONBOARDING_STEPS = [
|
|
17
18
|
...ZENI_USER_REQUIRED_ONBOARDING_STEPS,
|
|
@@ -19,10 +20,40 @@ export const ALL_ZENI_USER_ONBOARDING_STEPS = [
|
|
|
19
20
|
];
|
|
20
21
|
export const ALL_CUSTOMER_ONBOARDING_STEPS_WITH_QBO = [
|
|
21
22
|
...CUSTOMER_REQUIRED_ONBOARDING_STEPS_WITH_QBO,
|
|
23
|
+
'connect_data_source',
|
|
22
24
|
...ALL_ZENI_USER_ONBOARDING_STEPS_WITHOUT_ACCOUNT,
|
|
23
25
|
];
|
|
24
26
|
export const ALL_ONBOARDING_STEPS = [
|
|
25
27
|
...REQUIRED_ONBOARDING_STEPS,
|
|
28
|
+
'connect_data_source',
|
|
26
29
|
...ALL_ZENI_USER_ONBOARDING_STEPS_WITHOUT_ACCOUNT,
|
|
27
30
|
];
|
|
28
31
|
export const toOnboardingStepType = (v) => stringToUnion(v, ALL_ONBOARDING_STEPS);
|
|
32
|
+
// Per-step sub-state. Lives in Redux so the save epic can tell, for example,
|
|
33
|
+
// an officer-form save from a company-details save while both share
|
|
34
|
+
// currentStep = 'verification'.
|
|
35
|
+
// - 'default' generic landing sub-state.
|
|
36
|
+
// - 'ai-activating' connect_ledger interstitial during AI activation.
|
|
37
|
+
// - 'unlock-stack' verification landing — VerifyUnlockFinancialStackPage.
|
|
38
|
+
// - 'company_officer' verification → officer form.
|
|
39
|
+
// - 'company_details' verification → company details form.
|
|
40
|
+
export const ALL_ONBOARDING_SUB_STEPS = [
|
|
41
|
+
'default',
|
|
42
|
+
'ai-activating',
|
|
43
|
+
'unlock-stack',
|
|
44
|
+
'company_officer',
|
|
45
|
+
'company_details',
|
|
46
|
+
];
|
|
47
|
+
export const toOnboardingSubStepType = (v) => stringToUnion(v, ALL_ONBOARDING_SUB_STEPS);
|
|
48
|
+
export const emptyAiAgentsActivationCounts = {
|
|
49
|
+
customerCount: 0,
|
|
50
|
+
glAccountCount: 0,
|
|
51
|
+
targetTransactionCount: 0,
|
|
52
|
+
transactionCount: 0,
|
|
53
|
+
vendorCount: 0,
|
|
54
|
+
};
|
|
55
|
+
export const emptyAiAgentsActivationSubview = {
|
|
56
|
+
counts: emptyAiAgentsActivationCounts,
|
|
57
|
+
fetchStatus: { fetchState: 'Not-Started', error: undefined },
|
|
58
|
+
phases: [],
|
|
59
|
+
};
|