@zeniai/client-epic-state 5.0.2-betaRD2 → 5.0.2-betaRR01
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/billPay/billTransaction/billTransactionState.d.ts +2 -2
- package/lib/entity/chargeCard/chargeCard.d.ts +1 -1
- package/lib/entity/depositAccountTransaction/depositAccountTransaction.d.ts +1 -1
- package/lib/entity/entityApprovalStatus/entityApprovalStatusState.d.ts +2 -2
- package/lib/entity/jeSchedules/jeSchedulesTypes.d.ts +1 -1
- package/lib/entity/snackbar/snackbarTypes.d.ts +1 -1
- package/lib/entity/tenant/clearAllEpic.d.ts +1 -3
- package/lib/entity/tenant/clearAllEpic.js +0 -4
- package/lib/entity/transaction/payloadTypes/transactionPayload.js +21 -0
- package/lib/entity/userRole/userRoleType.d.ts +2 -2
- package/lib/epic.d.ts +1 -5
- package/lib/epic.js +1 -5
- package/lib/esm/entity/tenant/clearAllEpic.js +0 -4
- package/lib/esm/entity/transaction/payloadTypes/transactionPayload.js +21 -0
- package/lib/esm/epic.js +1 -5
- package/lib/esm/index.js +0 -7
- package/lib/esm/reducer.js +0 -6
- package/lib/index.d.ts +0 -9
- package/lib/index.js +3 -30
- package/lib/reducer.d.ts +0 -6
- package/lib/reducer.js +0 -6
- package/lib/tsconfig.typecheck.tsbuildinfo +1 -1
- package/lib/view/companyView/types/cockpitTypes.d.ts +5 -6
- package/lib/view/expenseAutomationView/helpers/transactionCategorizationLocalDataHelper.d.ts +1 -1
- package/lib/view/expenseAutomationView/types/missingReceiptsViewState.d.ts +1 -1
- package/lib/view/onboardingView/cockpitView/types/onboardingCockpitViewTypes.d.ts +1 -1
- package/lib/view/reviewCompanyView/reviewCompanyViewState.d.ts +1 -1
- package/lib/view/spendManagement/billPay/billList/billListReducer.d.ts +1 -1
- package/lib/view/spendManagement/billPay/billList/billListState.d.ts +1 -1
- package/lib/view/spendManagement/chargeCards/chargeCardDetail/chargeCardDetail.d.ts +1 -1
- package/lib/view/spendManagement/chargeCards/chargeCardDetail/chargeCardDetailReducer.d.ts +4 -4
- package/lib/view/spendManagement/reimbursement/remiListView/remiListReducer.d.ts +1 -1
- package/lib/view/spendManagement/reimbursement/remiListView/remiListState.d.ts +3 -3
- package/lib/view/subscriptionView/types/subscriptionTypes.d.ts +1 -1
- package/package.json +1 -1
- package/lib/entity/aiAccountantCustomer/aiAccountantCustomerPayload.d.ts +0 -44
- package/lib/entity/aiAccountantCustomer/aiAccountantCustomerPayload.js +0 -55
- package/lib/entity/aiAccountantCustomer/aiAccountantCustomerReducer.d.ts +0 -10
- package/lib/entity/aiAccountantCustomer/aiAccountantCustomerReducer.js +0 -51
- package/lib/entity/aiAccountantCustomer/aiAccountantCustomerSelector.d.ts +0 -48
- package/lib/entity/aiAccountantCustomer/aiAccountantCustomerSelector.js +0 -66
- package/lib/entity/aiAccountantCustomer/aiAccountantCustomerState.d.ts +0 -52
- package/lib/entity/aiAccountantCustomer/aiAccountantCustomerState.js +0 -37
- package/lib/esm/entity/aiAccountantCustomer/aiAccountantCustomerPayload.js +0 -49
- package/lib/esm/entity/aiAccountantCustomer/aiAccountantCustomerReducer.js +0 -47
- package/lib/esm/entity/aiAccountantCustomer/aiAccountantCustomerSelector.js +0 -62
- package/lib/esm/entity/aiAccountantCustomer/aiAccountantCustomerState.js +0 -31
- package/lib/esm/view/aiAccountantView/aiAccountantViewPayload.js +0 -2
- package/lib/esm/view/aiAccountantView/aiAccountantViewReducer.js +0 -149
- package/lib/esm/view/aiAccountantView/aiAccountantViewSelector.js +0 -72
- package/lib/esm/view/aiAccountantView/aiAccountantViewState.js +0 -11
- package/lib/esm/view/aiAccountantView/epics/cancelAiAccountantOnboardingEpic.js +0 -46
- package/lib/esm/view/aiAccountantView/epics/fetchAiAccountantCustomersEpic.js +0 -27
- package/lib/esm/view/aiAccountantView/epics/fetchAiAccountantJobsEpic.js +0 -47
- package/lib/esm/view/aiAccountantView/epics/triggerAiAccountantJobEpic.js +0 -52
- package/lib/view/aiAccountantView/aiAccountantViewPayload.d.ts +0 -31
- package/lib/view/aiAccountantView/aiAccountantViewPayload.js +0 -8
- package/lib/view/aiAccountantView/aiAccountantViewReducer.d.ts +0 -29
- package/lib/view/aiAccountantView/aiAccountantViewReducer.js +0 -153
- package/lib/view/aiAccountantView/aiAccountantViewSelector.d.ts +0 -14
- package/lib/view/aiAccountantView/aiAccountantViewSelector.js +0 -78
- package/lib/view/aiAccountantView/aiAccountantViewState.d.ts +0 -26
- package/lib/view/aiAccountantView/aiAccountantViewState.js +0 -13
- package/lib/view/aiAccountantView/epics/cancelAiAccountantOnboardingEpic.d.ts +0 -33
- package/lib/view/aiAccountantView/epics/cancelAiAccountantOnboardingEpic.js +0 -50
- package/lib/view/aiAccountantView/epics/fetchAiAccountantCustomersEpic.d.ts +0 -23
- package/lib/view/aiAccountantView/epics/fetchAiAccountantCustomersEpic.js +0 -31
- package/lib/view/aiAccountantView/epics/fetchAiAccountantJobsEpic.d.ts +0 -33
- package/lib/view/aiAccountantView/epics/fetchAiAccountantJobsEpic.js +0 -51
- package/lib/view/aiAccountantView/epics/triggerAiAccountantJobEpic.d.ts +0 -28
- package/lib/view/aiAccountantView/epics/triggerAiAccountantJobEpic.js +0 -56
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
import { createSlice } from '@reduxjs/toolkit';
|
|
2
|
-
import { toAiAccountantCustomer, toAiAccountantJob, } from './aiAccountantCustomerPayload';
|
|
3
|
-
export const initialAiAccountantCustomerState = {
|
|
4
|
-
customerByTenantId: {},
|
|
5
|
-
jobsByTenantId: {},
|
|
6
|
-
};
|
|
7
|
-
const aiAccountantCustomer = createSlice({
|
|
8
|
-
name: 'aiAccountantCustomer',
|
|
9
|
-
initialState: initialAiAccountantCustomerState,
|
|
10
|
-
reducers: {
|
|
11
|
-
updateAiAccountantCustomers(draft, action) {
|
|
12
|
-
const newCustomerByTenantId = {};
|
|
13
|
-
action.payload.forEach((payload) => {
|
|
14
|
-
const customer = toAiAccountantCustomer(payload);
|
|
15
|
-
newCustomerByTenantId[customer.tenantId] = customer;
|
|
16
|
-
});
|
|
17
|
-
draft.customerByTenantId = newCustomerByTenantId;
|
|
18
|
-
},
|
|
19
|
-
updateAiAccountantCustomer(draft, action) {
|
|
20
|
-
const customer = toAiAccountantCustomer(action.payload);
|
|
21
|
-
draft.customerByTenantId[customer.tenantId] = customer;
|
|
22
|
-
},
|
|
23
|
-
updateAiAccountantJobs: {
|
|
24
|
-
reducer(draft, action) {
|
|
25
|
-
const mappedJobs = action.payload.jobs.map(toAiAccountantJob);
|
|
26
|
-
if (action.payload.append) {
|
|
27
|
-
const existing = draft.jobsByTenantId[action.payload.tenantId] ?? [];
|
|
28
|
-
const jobMap = new Map(existing.map((job) => [job.jobId, job]));
|
|
29
|
-
mappedJobs.forEach((job) => jobMap.set(job.jobId, job));
|
|
30
|
-
draft.jobsByTenantId[action.payload.tenantId] =
|
|
31
|
-
Array.from(jobMap.values());
|
|
32
|
-
}
|
|
33
|
-
else {
|
|
34
|
-
draft.jobsByTenantId[action.payload.tenantId] = mappedJobs;
|
|
35
|
-
}
|
|
36
|
-
},
|
|
37
|
-
prepare(tenantId, jobs, append = false) {
|
|
38
|
-
return { payload: { tenantId, jobs, append } };
|
|
39
|
-
},
|
|
40
|
-
},
|
|
41
|
-
clearAllAiAccountantCustomers(draft) {
|
|
42
|
-
Object.assign(draft, initialAiAccountantCustomerState);
|
|
43
|
-
},
|
|
44
|
-
},
|
|
45
|
-
});
|
|
46
|
-
export const { clearAllAiAccountantCustomers, updateAiAccountantCustomers, updateAiAccountantCustomer, updateAiAccountantJobs, } = aiAccountantCustomer.actions;
|
|
47
|
-
export default aiAccountantCustomer.reducer;
|
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
import { getUserByUserId } from '../user/userSelector';
|
|
2
|
-
// ── Selectors ──
|
|
3
|
-
export function getAiAccountantCustomers(customerState, userState) {
|
|
4
|
-
return Object.values(customerState.customerByTenantId).map((customer) => toCustomerView(customer, userState));
|
|
5
|
-
}
|
|
6
|
-
export function getAiAccountantJobsByTenantId(customerState, userState, tenantId) {
|
|
7
|
-
const jobs = customerState.jobsByTenantId[tenantId] ?? [];
|
|
8
|
-
return jobs.map((job) => toJobView(job, userState));
|
|
9
|
-
}
|
|
10
|
-
// ── Helpers ──
|
|
11
|
-
function toCustomerView(customer, userState) {
|
|
12
|
-
return {
|
|
13
|
-
averageAccuracy: calcAverageAccuracy(customer),
|
|
14
|
-
companyId: customer.companyId,
|
|
15
|
-
companyName: customer.companyName,
|
|
16
|
-
tenantId: customer.tenantId,
|
|
17
|
-
bookcloseDate: customer.bookcloseDate,
|
|
18
|
-
enrollment: customer.enrollment != null
|
|
19
|
-
? {
|
|
20
|
-
...customer.enrollment,
|
|
21
|
-
offboardedBy: customer.enrollment.offboardedBy != null
|
|
22
|
-
? getUserByUserId(userState, customer.enrollment.offboardedBy)
|
|
23
|
-
: undefined,
|
|
24
|
-
onboardedBy: customer.enrollment.onboardedBy != null
|
|
25
|
-
? getUserByUserId(userState, customer.enrollment.onboardedBy)
|
|
26
|
-
: undefined,
|
|
27
|
-
}
|
|
28
|
-
: undefined,
|
|
29
|
-
};
|
|
30
|
-
}
|
|
31
|
-
function toJobView(job, userState) {
|
|
32
|
-
return {
|
|
33
|
-
companyId: job.companyId,
|
|
34
|
-
createdAt: job.createdAt,
|
|
35
|
-
jobId: job.jobId,
|
|
36
|
-
operationType: job.operationType,
|
|
37
|
-
status: job.status,
|
|
38
|
-
tenantId: job.tenantId,
|
|
39
|
-
triggeredBy: job.triggeredBy != null
|
|
40
|
-
? getUserByUserId(userState, job.triggeredBy)
|
|
41
|
-
: undefined,
|
|
42
|
-
companyNamespace: job.companyNamespace,
|
|
43
|
-
completedAt: job.completedAt,
|
|
44
|
-
errorMessage: job.errorMessage,
|
|
45
|
-
parameters: job.parameters,
|
|
46
|
-
retryCount: job.retryCount,
|
|
47
|
-
startedAt: job.startedAt,
|
|
48
|
-
steps: job.steps,
|
|
49
|
-
validationResults: job.validationResults,
|
|
50
|
-
};
|
|
51
|
-
}
|
|
52
|
-
function calcAverageAccuracy(customer) {
|
|
53
|
-
const accuracy = customer.enrollment?.accuracy;
|
|
54
|
-
if (accuracy == null) {
|
|
55
|
-
return 0;
|
|
56
|
-
}
|
|
57
|
-
const values = Object.values(accuracy);
|
|
58
|
-
if (values.length === 0) {
|
|
59
|
-
return 0;
|
|
60
|
-
}
|
|
61
|
-
return values.reduce((sum, value) => sum + value, 0) / values.length;
|
|
62
|
-
}
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import { stringToUnion } from '../../commonStateTypes/stringToUnion';
|
|
2
|
-
// ── Operation Type ──
|
|
3
|
-
const ALL_OPERATION_TYPES = [
|
|
4
|
-
'onboard',
|
|
5
|
-
'offboard',
|
|
6
|
-
'retrain',
|
|
7
|
-
'full_pipeline',
|
|
8
|
-
'cancel_onboarding',
|
|
9
|
-
];
|
|
10
|
-
export const toAiAccountantOperationType = (v) => stringToUnion(v, ALL_OPERATION_TYPES);
|
|
11
|
-
// ── Enrollment Status ──
|
|
12
|
-
const ALL_ENROLLMENT_STATUSES = [
|
|
13
|
-
'active',
|
|
14
|
-
'pending',
|
|
15
|
-
'onboarding',
|
|
16
|
-
'offboarding',
|
|
17
|
-
'offboarded',
|
|
18
|
-
'failed',
|
|
19
|
-
'error',
|
|
20
|
-
];
|
|
21
|
-
export const toAiAccountantEnrollmentStatus = (v) => stringToUnion(v, ALL_ENROLLMENT_STATUSES);
|
|
22
|
-
// ── Job Status ──
|
|
23
|
-
const ALL_JOB_STATUSES = [
|
|
24
|
-
'queued',
|
|
25
|
-
'running',
|
|
26
|
-
'completed',
|
|
27
|
-
'failed',
|
|
28
|
-
'cancelled',
|
|
29
|
-
'retried',
|
|
30
|
-
];
|
|
31
|
-
export const toAiAccountantJobStatus = (v) => stringToUnion(v, ALL_JOB_STATUSES);
|
|
@@ -1,149 +0,0 @@
|
|
|
1
|
-
import { createSlice } from '@reduxjs/toolkit';
|
|
2
|
-
export const initialAiAccountantViewState = {
|
|
3
|
-
customersByTenantId: {},
|
|
4
|
-
customersFetchStatus: { fetchState: 'Not-Started' },
|
|
5
|
-
selectedTenantIdsForJobTrigger: [],
|
|
6
|
-
triggerJobStatus: { fetchState: 'Not-Started' },
|
|
7
|
-
uiState: {
|
|
8
|
-
filterText: '',
|
|
9
|
-
filters: {},
|
|
10
|
-
selectedCustomerTenantId: '',
|
|
11
|
-
sortKey: 'companyName',
|
|
12
|
-
sortOrder: 'ascending',
|
|
13
|
-
},
|
|
14
|
-
};
|
|
15
|
-
const aiAccountantView = createSlice({
|
|
16
|
-
name: 'aiAccountantView',
|
|
17
|
-
initialState: initialAiAccountantViewState,
|
|
18
|
-
reducers: {
|
|
19
|
-
// ── Customers ──
|
|
20
|
-
fetchAiAccountantCustomers(draft) {
|
|
21
|
-
draft.customersFetchStatus = { fetchState: 'In-Progress' };
|
|
22
|
-
},
|
|
23
|
-
updateAiAccountantCustomers(draft, action) {
|
|
24
|
-
draft.customersByTenantId = toCustomersByTenantId(action.payload, draft.customersByTenantId);
|
|
25
|
-
draft.customersFetchStatus = { fetchState: 'Completed' };
|
|
26
|
-
},
|
|
27
|
-
updateAiAccountantCustomersFailure(draft, action) {
|
|
28
|
-
draft.customersFetchStatus = {
|
|
29
|
-
fetchState: 'Error',
|
|
30
|
-
error: action.payload,
|
|
31
|
-
};
|
|
32
|
-
},
|
|
33
|
-
// ── Jobs ──
|
|
34
|
-
fetchAiAccountantJobs: {
|
|
35
|
-
reducer(draft, action) {
|
|
36
|
-
const customerView = draft.customersByTenantId[action.payload.tenantId];
|
|
37
|
-
if (customerView != null) {
|
|
38
|
-
customerView.jobsFetchStatus = { fetchState: 'In-Progress' };
|
|
39
|
-
}
|
|
40
|
-
},
|
|
41
|
-
prepare(tenantId, fetchNextPage) {
|
|
42
|
-
return { payload: { tenantId, fetchNextPage: fetchNextPage ?? false } };
|
|
43
|
-
},
|
|
44
|
-
},
|
|
45
|
-
updateAiAccountantJobs: {
|
|
46
|
-
reducer(draft, action) {
|
|
47
|
-
const customerView = draft.customersByTenantId[action.payload.tenantId];
|
|
48
|
-
if (customerView != null) {
|
|
49
|
-
customerView.jobsFetchStatus = { fetchState: 'Completed' };
|
|
50
|
-
customerView.jobsPageToken = action.payload.nextPageToken;
|
|
51
|
-
}
|
|
52
|
-
},
|
|
53
|
-
prepare(tenantId, nextPageToken) {
|
|
54
|
-
return { payload: { tenantId, nextPageToken: nextPageToken ?? null } };
|
|
55
|
-
},
|
|
56
|
-
},
|
|
57
|
-
updateAiAccountantJobsFailure(draft, action) {
|
|
58
|
-
const customerView = draft.customersByTenantId[action.payload.tenantId];
|
|
59
|
-
if (customerView != null) {
|
|
60
|
-
customerView.jobsFetchStatus = {
|
|
61
|
-
fetchState: 'Error',
|
|
62
|
-
error: action.payload.error,
|
|
63
|
-
};
|
|
64
|
-
}
|
|
65
|
-
},
|
|
66
|
-
setSelectedTenantIdsForJobTrigger(draft, action) {
|
|
67
|
-
draft.selectedTenantIdsForJobTrigger = action.payload;
|
|
68
|
-
},
|
|
69
|
-
// ── Trigger Job ──
|
|
70
|
-
triggerAiAccountantJob: {
|
|
71
|
-
reducer(draft,
|
|
72
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
73
|
-
_action) {
|
|
74
|
-
draft.triggerJobStatus = { fetchState: 'In-Progress' };
|
|
75
|
-
},
|
|
76
|
-
prepare(operationType, startDate, endDate) {
|
|
77
|
-
return { payload: { operationType, startDate, endDate } };
|
|
78
|
-
},
|
|
79
|
-
},
|
|
80
|
-
triggerAiAccountantJobSuccess(draft) {
|
|
81
|
-
draft.triggerJobStatus = { fetchState: 'Completed' };
|
|
82
|
-
},
|
|
83
|
-
triggerAiAccountantJobFailure(draft, action) {
|
|
84
|
-
draft.triggerJobStatus = { fetchState: 'Error', error: action.payload };
|
|
85
|
-
},
|
|
86
|
-
// ── Cancel Onboarding ──
|
|
87
|
-
cancelAiAccountantOnboarding: {
|
|
88
|
-
reducer(draft, action) {
|
|
89
|
-
const customerView = draft.customersByTenantId[action.payload.tenantId];
|
|
90
|
-
if (customerView != null) {
|
|
91
|
-
customerView.cancelOnboardingStatus = { fetchState: 'In-Progress' };
|
|
92
|
-
}
|
|
93
|
-
},
|
|
94
|
-
prepare(companyId, tenantId) {
|
|
95
|
-
return { payload: { companyId, tenantId } };
|
|
96
|
-
},
|
|
97
|
-
},
|
|
98
|
-
cancelAiAccountantOnboardingSuccess: {
|
|
99
|
-
reducer(draft, action) {
|
|
100
|
-
const customerView = draft.customersByTenantId[action.payload.tenantId];
|
|
101
|
-
if (customerView != null) {
|
|
102
|
-
customerView.cancelOnboardingStatus = { fetchState: 'Completed' };
|
|
103
|
-
}
|
|
104
|
-
},
|
|
105
|
-
prepare(tenantId) {
|
|
106
|
-
return { payload: { tenantId } };
|
|
107
|
-
},
|
|
108
|
-
},
|
|
109
|
-
cancelAiAccountantOnboardingFailure: {
|
|
110
|
-
reducer(draft, action) {
|
|
111
|
-
const customerView = draft.customersByTenantId[action.payload.tenantId];
|
|
112
|
-
if (customerView != null) {
|
|
113
|
-
customerView.cancelOnboardingStatus = {
|
|
114
|
-
fetchState: 'Error',
|
|
115
|
-
error: action.payload.error,
|
|
116
|
-
};
|
|
117
|
-
}
|
|
118
|
-
},
|
|
119
|
-
prepare(tenantId, error) {
|
|
120
|
-
return { payload: { tenantId, error } };
|
|
121
|
-
},
|
|
122
|
-
},
|
|
123
|
-
// ── UI State ──
|
|
124
|
-
updateAiAccountantUIState(draft, action) {
|
|
125
|
-
Object.assign(draft.uiState, action.payload);
|
|
126
|
-
},
|
|
127
|
-
// ── Clear ──
|
|
128
|
-
clearAiAccountantView() {
|
|
129
|
-
return initialAiAccountantViewState;
|
|
130
|
-
},
|
|
131
|
-
},
|
|
132
|
-
});
|
|
133
|
-
export const { cancelAiAccountantOnboarding, cancelAiAccountantOnboardingFailure, cancelAiAccountantOnboardingSuccess, clearAiAccountantView, fetchAiAccountantCustomers, fetchAiAccountantJobs, setSelectedTenantIdsForJobTrigger, triggerAiAccountantJob, triggerAiAccountantJobFailure, triggerAiAccountantJobSuccess, updateAiAccountantCustomers, updateAiAccountantCustomersFailure, updateAiAccountantJobs, updateAiAccountantJobsFailure, updateAiAccountantUIState, } = aiAccountantView.actions;
|
|
134
|
-
export default aiAccountantView.reducer;
|
|
135
|
-
// ── Helpers ──
|
|
136
|
-
const toCustomersByTenantId = (customers, existing) => {
|
|
137
|
-
const result = {};
|
|
138
|
-
for (const payload of customers) {
|
|
139
|
-
const tenantId = payload.tenant_id;
|
|
140
|
-
const existingState = existing[tenantId];
|
|
141
|
-
result[tenantId] = existingState ?? {
|
|
142
|
-
cancelOnboardingStatus: { fetchState: 'Not-Started' },
|
|
143
|
-
jobsFetchStatus: { fetchState: 'Not-Started' },
|
|
144
|
-
jobsPageToken: null,
|
|
145
|
-
tenantId,
|
|
146
|
-
};
|
|
147
|
-
}
|
|
148
|
-
return result;
|
|
149
|
-
};
|
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
import { createSelector } from '@reduxjs/toolkit';
|
|
2
|
-
import orderBy from 'lodash/orderBy';
|
|
3
|
-
import { getAiAccountantCustomers, } from '../../entity/aiAccountantCustomer/aiAccountantCustomerSelector';
|
|
4
|
-
export const getAiAccountantCockpitView = createSelector((state) => state.aiAccountantViewState, (state) => state.aiAccountantCustomerState, (state) => state.userState, (viewState, customerEntityState, userState) => {
|
|
5
|
-
const { customersByTenantId, customersFetchStatus, selectedTenantIdsForJobTrigger, triggerJobStatus, uiState, } = viewState;
|
|
6
|
-
const allCustomers = getAiAccountantCustomers(customerEntityState, userState);
|
|
7
|
-
let filteredCustomers = allCustomers;
|
|
8
|
-
// Text filter
|
|
9
|
-
const trimmedFilterText = uiState.filterText.trim();
|
|
10
|
-
if (trimmedFilterText.length > 0) {
|
|
11
|
-
const query = trimmedFilterText.toLowerCase();
|
|
12
|
-
filteredCustomers = filteredCustomers.filter((customer) => customer.companyName.toLowerCase().includes(query) ||
|
|
13
|
-
customer.tenantId.toLowerCase().includes(query));
|
|
14
|
-
}
|
|
15
|
-
// Cockpit filters (e.g. enrollmentStatus)
|
|
16
|
-
const enrollmentStatusFilter = uiState.filters.categories?.find((category) => category.field === 'enrollmentStatus');
|
|
17
|
-
if (enrollmentStatusFilter != null &&
|
|
18
|
-
enrollmentStatusFilter.values.length > 0) {
|
|
19
|
-
const selectedStatuses = enrollmentStatusFilter.values.map(String);
|
|
20
|
-
const isEqual = enrollmentStatusFilter.matchingOperator === 'equal';
|
|
21
|
-
filteredCustomers = filteredCustomers.filter((customer) => {
|
|
22
|
-
const status = customer.enrollment?.status ?? 'unknown';
|
|
23
|
-
const matches = selectedStatuses.includes(status);
|
|
24
|
-
return isEqual ? matches : !matches;
|
|
25
|
-
});
|
|
26
|
-
}
|
|
27
|
-
// Sorting
|
|
28
|
-
const sortedCustomers = getSortedCustomers(filteredCustomers, uiState.sortKey, uiState.sortOrder);
|
|
29
|
-
const selectedCustomersForJobTrigger = allCustomers.filter((customer) => selectedTenantIdsForJobTrigger.includes(customer.tenantId));
|
|
30
|
-
return {
|
|
31
|
-
averageAccuracy: calcOverallAverageAccuracy(allCustomers),
|
|
32
|
-
fetchState: customersFetchStatus.fetchState,
|
|
33
|
-
error: customersFetchStatus.error,
|
|
34
|
-
customers: sortedCustomers,
|
|
35
|
-
customerViewStateByTenantId: customersByTenantId,
|
|
36
|
-
selectedCustomersForJobTrigger,
|
|
37
|
-
triggerJobStatus,
|
|
38
|
-
uiState,
|
|
39
|
-
};
|
|
40
|
-
});
|
|
41
|
-
// ── Helpers ──
|
|
42
|
-
const getSortedCustomers = (customers, sortKey, sortOrder) => {
|
|
43
|
-
const direction = sortOrder === 'ascending' ? 'asc' : 'desc';
|
|
44
|
-
return orderBy(customers, (customer) => {
|
|
45
|
-
switch (sortKey) {
|
|
46
|
-
case 'companyName':
|
|
47
|
-
return customer.companyName.toLowerCase();
|
|
48
|
-
case 'status':
|
|
49
|
-
return (customer.enrollment?.status ?? 'unknown').toLowerCase();
|
|
50
|
-
case 'bookcloseDate':
|
|
51
|
-
return customer.bookcloseDate?.valueOf() ?? 0;
|
|
52
|
-
case 'latestTraining':
|
|
53
|
-
return customer.enrollment?.latestTraining?.valueOf() ?? 0;
|
|
54
|
-
case 'latestSync':
|
|
55
|
-
return customer.enrollment?.latestTransactionSync?.valueOf() ?? 0;
|
|
56
|
-
case 'accuracy':
|
|
57
|
-
return customer.averageAccuracy;
|
|
58
|
-
default:
|
|
59
|
-
return customer.companyName.toLowerCase();
|
|
60
|
-
}
|
|
61
|
-
}, direction);
|
|
62
|
-
};
|
|
63
|
-
const calcOverallAverageAccuracy = (customers) => {
|
|
64
|
-
const customerAccuracies = customers
|
|
65
|
-
.map((customer) => customer.averageAccuracy)
|
|
66
|
-
.filter((accuracy) => accuracy > 0);
|
|
67
|
-
if (customerAccuracies.length === 0) {
|
|
68
|
-
return 0;
|
|
69
|
-
}
|
|
70
|
-
return (customerAccuracies.reduce((sum, accuracy) => sum + accuracy, 0) /
|
|
71
|
-
customerAccuracies.length);
|
|
72
|
-
};
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import { stringToUnion } from '../../commonStateTypes/stringToUnion';
|
|
2
|
-
const ALL_AI_ACCOUNTANT_SORT_KEYS = [
|
|
3
|
-
'companyName',
|
|
4
|
-
'status',
|
|
5
|
-
'bookcloseDate',
|
|
6
|
-
'latestTraining',
|
|
7
|
-
'latestSync',
|
|
8
|
-
'accuracy',
|
|
9
|
-
];
|
|
10
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
11
|
-
const toAiAccountantSortKeyType = (v) => stringToUnion(v, ALL_AI_ACCOUNTANT_SORT_KEYS);
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
import { from } from 'rxjs';
|
|
2
|
-
import { catchError, filter, mergeMap } from 'rxjs/operators';
|
|
3
|
-
import { openSnackbar } from '../../../entity/snackbar/snackbarReducer';
|
|
4
|
-
import { createZeniAPIStatus, isSuccessResponse } from '../../../responsePayload';
|
|
5
|
-
import { cancelAiAccountantOnboarding, cancelAiAccountantOnboardingFailure, cancelAiAccountantOnboardingSuccess, fetchAiAccountantCustomers, } from '../aiAccountantViewReducer';
|
|
6
|
-
export const cancelAiAccountantOnboardingEpic = (actions$, _, zeniAPI) => actions$.pipe(filter(cancelAiAccountantOnboarding.match), mergeMap((action) => {
|
|
7
|
-
const { tenantId, companyId } = action.payload;
|
|
8
|
-
const base = `${zeniAPI.apiEndPoints.tenantMicroServiceBaseUrl}/1.0/cockpit-panels`;
|
|
9
|
-
const url = `${base}/ai-accountant/cancel-onboarding`;
|
|
10
|
-
return zeniAPI
|
|
11
|
-
.postAndGetJSON(url, {
|
|
12
|
-
tenant_id: tenantId,
|
|
13
|
-
company_id: companyId,
|
|
14
|
-
})
|
|
15
|
-
.pipe(mergeMap((response) => {
|
|
16
|
-
if (isSuccessResponse(response)) {
|
|
17
|
-
return from([
|
|
18
|
-
cancelAiAccountantOnboardingSuccess(tenantId),
|
|
19
|
-
fetchAiAccountantCustomers(),
|
|
20
|
-
openSnackbar({
|
|
21
|
-
messageSection: 'common',
|
|
22
|
-
messageText: 'success',
|
|
23
|
-
type: 'success',
|
|
24
|
-
}),
|
|
25
|
-
]);
|
|
26
|
-
}
|
|
27
|
-
else {
|
|
28
|
-
return from([
|
|
29
|
-
cancelAiAccountantOnboardingFailure(tenantId, response.status),
|
|
30
|
-
openSnackbar({
|
|
31
|
-
messageSection: 'common',
|
|
32
|
-
messageText: 'failed',
|
|
33
|
-
type: 'error',
|
|
34
|
-
}),
|
|
35
|
-
]);
|
|
36
|
-
}
|
|
37
|
-
}), catchError((error) => from([
|
|
38
|
-
cancelAiAccountantOnboardingFailure(tenantId, createZeniAPIStatus('Unexpected error', 'AI Accountant cancel onboarding failed: ' +
|
|
39
|
-
JSON.stringify(error))),
|
|
40
|
-
openSnackbar({
|
|
41
|
-
messageSection: 'common',
|
|
42
|
-
messageText: 'failed',
|
|
43
|
-
type: 'error',
|
|
44
|
-
}),
|
|
45
|
-
])));
|
|
46
|
-
}));
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import { from, of } from 'rxjs';
|
|
2
|
-
import { catchError, filter, mergeMap, switchMap } from 'rxjs/operators';
|
|
3
|
-
import { updateAiAccountantCustomers as updateAiAccountantCustomerEntities } from '../../../entity/aiAccountantCustomer/aiAccountantCustomerReducer';
|
|
4
|
-
import { updateAllUsers } from '../../../entity/user/userReducer';
|
|
5
|
-
import { createZeniAPIStatus, isSuccessResponse } from '../../../responsePayload';
|
|
6
|
-
import { fetchAiAccountantCustomers, updateAiAccountantCustomers, updateAiAccountantCustomersFailure, } from '../aiAccountantViewReducer';
|
|
7
|
-
export const fetchAiAccountantCustomersEpic = (actions$, _, zeniAPI) => actions$.pipe(filter(fetchAiAccountantCustomers.match), switchMap(() => {
|
|
8
|
-
const base = `${zeniAPI.apiEndPoints.tenantMicroServiceBaseUrl}/1.0/cockpit-panels`;
|
|
9
|
-
const url = `${base}/ai-accountant/customers`;
|
|
10
|
-
return zeniAPI
|
|
11
|
-
.getJSON(url)
|
|
12
|
-
.pipe(mergeMap((response) => {
|
|
13
|
-
if (isSuccessResponse(response)) {
|
|
14
|
-
const customers = response.data?.customers ?? [];
|
|
15
|
-
const users = response.data?.users ?? [];
|
|
16
|
-
return from([
|
|
17
|
-
updateAiAccountantCustomerEntities(customers),
|
|
18
|
-
updateAllUsers({ users }),
|
|
19
|
-
updateAiAccountantCustomers(customers),
|
|
20
|
-
]);
|
|
21
|
-
}
|
|
22
|
-
else {
|
|
23
|
-
return of(updateAiAccountantCustomersFailure(response.status));
|
|
24
|
-
}
|
|
25
|
-
}), catchError((error) => of(updateAiAccountantCustomersFailure(createZeniAPIStatus('Unexpected error', 'AI Accountant customers fetch failed: ' +
|
|
26
|
-
JSON.stringify(error))))));
|
|
27
|
-
}));
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
import { from, of } from 'rxjs';
|
|
2
|
-
import { catchError, filter, mergeMap, switchMap } from 'rxjs/operators';
|
|
3
|
-
import { updateAiAccountantJobs as updateAiAccountantJobEntities } from '../../../entity/aiAccountantCustomer/aiAccountantCustomerReducer';
|
|
4
|
-
import { updateAllUsers } from '../../../entity/user/userReducer';
|
|
5
|
-
import { createZeniAPIStatus, isSuccessResponse } from '../../../responsePayload';
|
|
6
|
-
import { fetchAiAccountantJobs, updateAiAccountantJobs, updateAiAccountantJobsFailure, } from '../aiAccountantViewReducer';
|
|
7
|
-
export const fetchAiAccountantJobsEpic = (actions$, state$, zeniAPI) => actions$.pipe(filter(fetchAiAccountantJobs.match), switchMap((action) => {
|
|
8
|
-
const { tenantId, fetchNextPage } = action.payload;
|
|
9
|
-
const rootState = state$.value;
|
|
10
|
-
const customerView = rootState.aiAccountantViewState.customersByTenantId[tenantId];
|
|
11
|
-
const pageToken = fetchNextPage && customerView?.jobsPageToken != null
|
|
12
|
-
? customerView.jobsPageToken
|
|
13
|
-
: null;
|
|
14
|
-
const params = new URLSearchParams({
|
|
15
|
-
page_size: '50',
|
|
16
|
-
tenant_id: tenantId,
|
|
17
|
-
});
|
|
18
|
-
if (pageToken != null) {
|
|
19
|
-
params.set('page_token', pageToken);
|
|
20
|
-
}
|
|
21
|
-
const base = `${zeniAPI.apiEndPoints.tenantMicroServiceBaseUrl}/1.0/cockpit-panels`;
|
|
22
|
-
const url = `${base}/ai-accountant/jobs?${params.toString()}`;
|
|
23
|
-
return zeniAPI
|
|
24
|
-
.getJSON(url)
|
|
25
|
-
.pipe(mergeMap((response) => {
|
|
26
|
-
if (isSuccessResponse(response)) {
|
|
27
|
-
const jobs = response.data?.jobs ?? [];
|
|
28
|
-
const users = response.data?.users ?? [];
|
|
29
|
-
const nextPageToken = response.data?.next_page_token ?? null;
|
|
30
|
-
return from([
|
|
31
|
-
updateAllUsers({ users }),
|
|
32
|
-
updateAiAccountantJobEntities(tenantId, jobs, fetchNextPage),
|
|
33
|
-
updateAiAccountantJobs(tenantId, nextPageToken),
|
|
34
|
-
]);
|
|
35
|
-
}
|
|
36
|
-
else {
|
|
37
|
-
return of(updateAiAccountantJobsFailure({
|
|
38
|
-
tenantId,
|
|
39
|
-
error: response.status,
|
|
40
|
-
}));
|
|
41
|
-
}
|
|
42
|
-
}), catchError((error) => of(updateAiAccountantJobsFailure({
|
|
43
|
-
tenantId,
|
|
44
|
-
error: createZeniAPIStatus('Unexpected error', 'AI Accountant jobs fetch failed: ' +
|
|
45
|
-
JSON.stringify(error)),
|
|
46
|
-
}))));
|
|
47
|
-
}));
|
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
import { from } from 'rxjs';
|
|
2
|
-
import { catchError, filter, mergeMap } from 'rxjs/operators';
|
|
3
|
-
import { openSnackbar } from '../../../entity/snackbar/snackbarReducer';
|
|
4
|
-
import { createZeniAPIStatus, isSuccessResponse } from '../../../responsePayload';
|
|
5
|
-
import { fetchAiAccountantCustomers, triggerAiAccountantJob, triggerAiAccountantJobFailure, triggerAiAccountantJobSuccess, } from '../aiAccountantViewReducer';
|
|
6
|
-
export const triggerAiAccountantJobEpic = (actions$, state$, zeniAPI) => actions$.pipe(filter(triggerAiAccountantJob.match), mergeMap((action) => {
|
|
7
|
-
const { operationType, startDate, endDate } = action.payload;
|
|
8
|
-
const rootState = state$.value;
|
|
9
|
-
const selectedTenantIds = rootState.aiAccountantViewState.selectedTenantIdsForJobTrigger;
|
|
10
|
-
const base = `${zeniAPI.apiEndPoints.tenantMicroServiceBaseUrl}/1.0/cockpit-panels`;
|
|
11
|
-
const url = `${base}/ai-accountant/jobs`;
|
|
12
|
-
const params = operationType === 'offboard'
|
|
13
|
-
? {}
|
|
14
|
-
: { start_date: startDate, end_date: endDate };
|
|
15
|
-
return zeniAPI
|
|
16
|
-
.postAndGetJSON(url, {
|
|
17
|
-
tenant_ids: selectedTenantIds,
|
|
18
|
-
operation_type: operationType,
|
|
19
|
-
params,
|
|
20
|
-
})
|
|
21
|
-
.pipe(mergeMap((response) => {
|
|
22
|
-
if (isSuccessResponse(response)) {
|
|
23
|
-
return from([
|
|
24
|
-
triggerAiAccountantJobSuccess(),
|
|
25
|
-
fetchAiAccountantCustomers(),
|
|
26
|
-
openSnackbar({
|
|
27
|
-
messageSection: 'common',
|
|
28
|
-
messageText: 'success',
|
|
29
|
-
type: 'success',
|
|
30
|
-
}),
|
|
31
|
-
]);
|
|
32
|
-
}
|
|
33
|
-
else {
|
|
34
|
-
return from([
|
|
35
|
-
triggerAiAccountantJobFailure(response.status),
|
|
36
|
-
openSnackbar({
|
|
37
|
-
messageSection: 'common',
|
|
38
|
-
messageText: 'failed',
|
|
39
|
-
type: 'error',
|
|
40
|
-
}),
|
|
41
|
-
]);
|
|
42
|
-
}
|
|
43
|
-
}), catchError((error) => from([
|
|
44
|
-
triggerAiAccountantJobFailure(createZeniAPIStatus('Unexpected error', 'AI Accountant trigger job failed: ' +
|
|
45
|
-
JSON.stringify(error))),
|
|
46
|
-
openSnackbar({
|
|
47
|
-
messageSection: 'common',
|
|
48
|
-
messageText: 'failed',
|
|
49
|
-
type: 'error',
|
|
50
|
-
}),
|
|
51
|
-
])));
|
|
52
|
-
}));
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import { ZeniAPIResponse } from '../../responsePayload';
|
|
2
|
-
export { AiAccountantCustomerPayload, AiAccountantEnrollmentPayload, AiAccountantJobPayload, toAiAccountantCustomer, toAiAccountantEnrollment, toAiAccountantJob, } from '../../entity/aiAccountantCustomer/aiAccountantCustomerPayload';
|
|
3
|
-
import type { AiAccountantCustomerPayload, AiAccountantJobPayload } from '../../entity/aiAccountantCustomer/aiAccountantCustomerPayload';
|
|
4
|
-
import { UserPayload } from '../../entity/user/userPayload';
|
|
5
|
-
export interface AiAccountantCustomersResponseData {
|
|
6
|
-
customers: AiAccountantCustomerPayload[];
|
|
7
|
-
users: UserPayload[];
|
|
8
|
-
}
|
|
9
|
-
export interface AiAccountantJobsResponseData {
|
|
10
|
-
jobs: AiAccountantJobPayload[];
|
|
11
|
-
page_size: number;
|
|
12
|
-
users: UserPayload[];
|
|
13
|
-
next_page_token?: string | null;
|
|
14
|
-
}
|
|
15
|
-
export interface AiAccountantTriggerJobResponseData {
|
|
16
|
-
job_ids: string[];
|
|
17
|
-
queued_count: number;
|
|
18
|
-
skipped?: Array<{
|
|
19
|
-
reason: string;
|
|
20
|
-
tenant_id: string;
|
|
21
|
-
}>;
|
|
22
|
-
}
|
|
23
|
-
export interface AiAccountantCancelOnboardingResponseData {
|
|
24
|
-
cancelled_jobs: string[];
|
|
25
|
-
ok: boolean;
|
|
26
|
-
workflow_cancelled: boolean;
|
|
27
|
-
}
|
|
28
|
-
export type AiAccountantCustomersResponse = ZeniAPIResponse<AiAccountantCustomersResponseData>;
|
|
29
|
-
export type AiAccountantJobsResponse = ZeniAPIResponse<AiAccountantJobsResponseData>;
|
|
30
|
-
export type AiAccountantTriggerJobResponse = ZeniAPIResponse<AiAccountantTriggerJobResponseData>;
|
|
31
|
-
export type AiAccountantCancelOnboardingResponse = ZeniAPIResponse<AiAccountantCancelOnboardingResponseData>;
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.toAiAccountantJob = exports.toAiAccountantEnrollment = exports.toAiAccountantCustomer = void 0;
|
|
4
|
-
// Re-export entity payload types and mapping functions.
|
|
5
|
-
var aiAccountantCustomerPayload_1 = require("../../entity/aiAccountantCustomer/aiAccountantCustomerPayload");
|
|
6
|
-
Object.defineProperty(exports, "toAiAccountantCustomer", { enumerable: true, get: function () { return aiAccountantCustomerPayload_1.toAiAccountantCustomer; } });
|
|
7
|
-
Object.defineProperty(exports, "toAiAccountantEnrollment", { enumerable: true, get: function () { return aiAccountantCustomerPayload_1.toAiAccountantEnrollment; } });
|
|
8
|
-
Object.defineProperty(exports, "toAiAccountantJob", { enumerable: true, get: function () { return aiAccountantCustomerPayload_1.toAiAccountantJob; } });
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import { AiAccountantCustomerPayload } from '../../entity/aiAccountantCustomer/aiAccountantCustomerPayload';
|
|
2
|
-
import { ID } from '../../commonStateTypes/common';
|
|
3
|
-
import { ZeniAPIStatus } from '../../responsePayload';
|
|
4
|
-
import { AiAccountantUIState, AiAccountantViewState } from './aiAccountantViewState';
|
|
5
|
-
export declare const initialAiAccountantViewState: AiAccountantViewState;
|
|
6
|
-
export declare const cancelAiAccountantOnboarding: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[companyId: string, tenantId: string], {
|
|
7
|
-
companyId: string;
|
|
8
|
-
tenantId: string;
|
|
9
|
-
}, "aiAccountantView/cancelAiAccountantOnboarding", never, never>, cancelAiAccountantOnboardingFailure: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[tenantId: string, error: ZeniAPIStatus<Record<string, unknown>>], {
|
|
10
|
-
tenantId: string;
|
|
11
|
-
error: ZeniAPIStatus<Record<string, unknown>>;
|
|
12
|
-
}, "aiAccountantView/cancelAiAccountantOnboardingFailure", never, never>, cancelAiAccountantOnboardingSuccess: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[tenantId: string], {
|
|
13
|
-
tenantId: string;
|
|
14
|
-
}, "aiAccountantView/cancelAiAccountantOnboardingSuccess", never, never>, clearAiAccountantView: import("@reduxjs/toolkit").ActionCreatorWithoutPayload<"aiAccountantView/clearAiAccountantView">, fetchAiAccountantCustomers: import("@reduxjs/toolkit").ActionCreatorWithoutPayload<"aiAccountantView/fetchAiAccountantCustomers">, fetchAiAccountantJobs: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[tenantId: string, fetchNextPage?: boolean | undefined], {
|
|
15
|
-
tenantId: string;
|
|
16
|
-
fetchNextPage: boolean;
|
|
17
|
-
}, "aiAccountantView/fetchAiAccountantJobs", never, never>, setSelectedTenantIdsForJobTrigger: import("@reduxjs/toolkit").ActionCreatorWithPayload<string[], "aiAccountantView/setSelectedTenantIdsForJobTrigger">, triggerAiAccountantJob: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[operationType: "onboard" | "offboard" | "retrain" | "full_pipeline" | "cancel_onboarding", startDate: string, endDate: string], {
|
|
18
|
-
operationType: "onboard" | "offboard" | "retrain" | "full_pipeline" | "cancel_onboarding";
|
|
19
|
-
startDate: string;
|
|
20
|
-
endDate: string;
|
|
21
|
-
}, "aiAccountantView/triggerAiAccountantJob", never, never>, triggerAiAccountantJobFailure: import("@reduxjs/toolkit").ActionCreatorWithPayload<ZeniAPIStatus<Record<string, unknown>>, "aiAccountantView/triggerAiAccountantJobFailure">, triggerAiAccountantJobSuccess: import("@reduxjs/toolkit").ActionCreatorWithoutPayload<"aiAccountantView/triggerAiAccountantJobSuccess">, updateAiAccountantCustomers: import("@reduxjs/toolkit").ActionCreatorWithPayload<AiAccountantCustomerPayload[], "aiAccountantView/updateAiAccountantCustomers">, updateAiAccountantCustomersFailure: import("@reduxjs/toolkit").ActionCreatorWithPayload<ZeniAPIStatus<Record<string, unknown>>, "aiAccountantView/updateAiAccountantCustomersFailure">, updateAiAccountantJobs: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[tenantId: string, nextPageToken?: string | null | undefined], {
|
|
22
|
-
tenantId: string;
|
|
23
|
-
nextPageToken: string | null;
|
|
24
|
-
}, "aiAccountantView/updateAiAccountantJobs", never, never>, updateAiAccountantJobsFailure: import("@reduxjs/toolkit").ActionCreatorWithPayload<{
|
|
25
|
-
error: ZeniAPIStatus;
|
|
26
|
-
tenantId: ID;
|
|
27
|
-
}, "aiAccountantView/updateAiAccountantJobsFailure">, updateAiAccountantUIState: import("@reduxjs/toolkit").ActionCreatorWithPayload<Partial<AiAccountantUIState>, "aiAccountantView/updateAiAccountantUIState">;
|
|
28
|
-
declare const _default: import("redux").Reducer<AiAccountantViewState>;
|
|
29
|
-
export default _default;
|