@zeniai/client-epic-state 5.1.34-betaRD1 → 5.1.35
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/viewAndReport/agingReportStateTypes.d.ts +1 -1
- package/lib/entity/accountRecon/accountReconPayload.d.ts +22 -0
- package/lib/entity/accountRecon/accountReconPayload.js +26 -1
- package/lib/entity/accountRecon/accountReconReducer.d.ts +5 -2
- package/lib/entity/accountRecon/accountReconReducer.js +36 -2
- package/lib/entity/accountRecon/accountReconSelector.d.ts +6 -1
- package/lib/entity/accountRecon/accountReconSelector.js +5 -0
- package/lib/entity/accountRecon/accountReconState.d.ts +22 -0
- package/lib/entity/monthEndCloseChecks/monthEndCloseChecksPayload.d.ts +8 -0
- package/lib/entity/monthEndCloseChecks/monthEndCloseChecksPayload.js +10 -0
- package/lib/entity/monthEndCloseChecks/monthEndCloseChecksState.d.ts +8 -0
- package/lib/epic.d.ts +4 -1
- package/lib/epic.js +4 -1
- package/lib/esm/entity/accountRecon/accountReconPayload.js +26 -1
- package/lib/esm/entity/accountRecon/accountReconReducer.js +35 -1
- package/lib/esm/entity/accountRecon/accountReconSelector.js +5 -0
- package/lib/esm/entity/monthEndCloseChecks/monthEndCloseChecksPayload.js +10 -0
- package/lib/esm/epic.js +4 -1
- package/lib/esm/index.js +3 -3
- package/lib/esm/view/expenseAutomationView/epics/accountRecon/parseStatementEpic.js +34 -0
- package/lib/esm/view/expenseAutomationView/epics/accountRecon/reparseStatementEpic.js +31 -0
- package/lib/esm/view/expenseAutomationView/epics/accountRecon/updateStatementInfoEpic.js +57 -0
- package/lib/esm/view/expenseAutomationView/payload/reconciliationPayload.js +153 -0
- package/lib/esm/view/expenseAutomationView/reducers/reconciliationViewReducer.js +188 -9
- package/lib/esm/view/expenseAutomationView/selectors/reconciliationViewSelector.js +27 -0
- package/lib/esm/view/expenseAutomationView/types/reconciliationViewState.js +29 -0
- package/lib/index.d.ts +6 -6
- package/lib/index.js +51 -37
- package/lib/view/expenseAutomationView/epics/accountRecon/parseStatementEpic.d.ts +6 -0
- package/lib/view/expenseAutomationView/epics/accountRecon/parseStatementEpic.js +38 -0
- package/lib/view/expenseAutomationView/epics/accountRecon/reparseStatementEpic.d.ts +26 -0
- package/lib/view/expenseAutomationView/epics/accountRecon/reparseStatementEpic.js +35 -0
- package/lib/view/expenseAutomationView/epics/accountRecon/updateStatementInfoEpic.d.ts +27 -0
- package/lib/view/expenseAutomationView/epics/accountRecon/updateStatementInfoEpic.js +61 -0
- package/lib/view/expenseAutomationView/payload/reconciliationPayload.d.ts +176 -10
- package/lib/view/expenseAutomationView/payload/reconciliationPayload.js +159 -0
- package/lib/view/expenseAutomationView/reducers/reconciliationViewReducer.d.ts +53 -3
- package/lib/view/expenseAutomationView/reducers/reconciliationViewReducer.js +190 -10
- package/lib/view/expenseAutomationView/selectorTypes/reconciliationViewSelectorTypes.d.ts +7 -1
- package/lib/view/expenseAutomationView/selectors/reconciliationViewSelector.d.ts +2 -0
- package/lib/view/expenseAutomationView/selectors/reconciliationViewSelector.js +29 -1
- package/lib/view/expenseAutomationView/types/reconciliationViewState.d.ts +175 -0
- package/lib/view/expenseAutomationView/types/reconciliationViewState.js +30 -0
- package/lib/view/vendorFiling1099/vendorFiling1099List/vendorFiling1099ListState.d.ts +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { of } from 'rxjs';
|
|
2
|
+
import { catchError, filter, mergeMap, switchMap } from 'rxjs/operators';
|
|
3
|
+
import { toMonthYearPeriodId } from '../../../../commonStateTypes/timePeriod';
|
|
4
|
+
import { createZeniAPIStatus, isSuccessResponse, } from '../../../../responsePayload';
|
|
5
|
+
import { isStatementDateConflictResponse, toStatementUpdateRequestBody, transformStatementDateConflictToState, transformUpdateStatementInfoPayloadToState, } from '../../payload/reconciliationPayload';
|
|
6
|
+
import { submitStatementUpdate, submitStatementUpdateFailure, submitStatementUpdateSuccess, updateParsedStatementData, } from '../../reducers/reconciliationViewReducer';
|
|
7
|
+
export const updateStatementInfoEpic = (actions$, state$, zeniAPI) => actions$.pipe(filter(submitStatementUpdate.match), switchMap((action) => {
|
|
8
|
+
const { accountId, selectedPeriod, statementUploadId } = action.payload;
|
|
9
|
+
const state = state$.value;
|
|
10
|
+
const reconciliationView = state.expenseAutomationReconciliationViewState;
|
|
11
|
+
const accountRecon = reconciliationView.accountReconciliationRecordsBySelectedPeriod[toMonthYearPeriodId(selectedPeriod)]?.reconciliationByAccountID[accountId];
|
|
12
|
+
const localData = accountRecon?.localData?.statementUpdateLocalData;
|
|
13
|
+
if (!localData) {
|
|
14
|
+
return of(submitStatementUpdateFailure({
|
|
15
|
+
accountId,
|
|
16
|
+
selectedPeriod,
|
|
17
|
+
error: createZeniAPIStatus('Missing Data', 'No statement update data found'),
|
|
18
|
+
}));
|
|
19
|
+
}
|
|
20
|
+
const hasInvalidUpdates = localData.statementTransactions.updated.some((txn) => txn.statementTransactionId == null);
|
|
21
|
+
if (hasInvalidUpdates) {
|
|
22
|
+
return of(submitStatementUpdateFailure({
|
|
23
|
+
accountId,
|
|
24
|
+
selectedPeriod,
|
|
25
|
+
error: createZeniAPIStatus('Invalid Data', 'One or more edited transactions are missing statement transaction ids'),
|
|
26
|
+
}));
|
|
27
|
+
}
|
|
28
|
+
const body = toStatementUpdateRequestBody(localData);
|
|
29
|
+
const updateStatementApi$ = zeniAPI.putAndGetJSON(`${zeniAPI.apiEndPoints.reconciliationMicroServiceBaseUrl}/2.0/statement-uploads/${statementUploadId}`, body);
|
|
30
|
+
return updateStatementApi$.pipe(mergeMap((response) => {
|
|
31
|
+
if (isSuccessResponse(response) === true && response.data != null) {
|
|
32
|
+
const parsedStatementData = transformUpdateStatementInfoPayloadToState(response.data);
|
|
33
|
+
return of(updateParsedStatementData({
|
|
34
|
+
accountId,
|
|
35
|
+
selectedPeriod,
|
|
36
|
+
parsedStatementData,
|
|
37
|
+
}), submitStatementUpdateSuccess({
|
|
38
|
+
accountId,
|
|
39
|
+
selectedPeriod,
|
|
40
|
+
}));
|
|
41
|
+
}
|
|
42
|
+
const dateConflict = isStatementDateConflictResponse(response)
|
|
43
|
+
? transformStatementDateConflictToState(response)
|
|
44
|
+
: null;
|
|
45
|
+
return of(submitStatementUpdateFailure({
|
|
46
|
+
accountId,
|
|
47
|
+
selectedPeriod,
|
|
48
|
+
error: response.status,
|
|
49
|
+
dateConflict,
|
|
50
|
+
}));
|
|
51
|
+
}), catchError((error) => of(submitStatementUpdateFailure({
|
|
52
|
+
accountId,
|
|
53
|
+
selectedPeriod,
|
|
54
|
+
error: createZeniAPIStatus('Unexpected Error', 'Update Statement REST API call errored out ' +
|
|
55
|
+
(error instanceof Error ? error.message : String(error))),
|
|
56
|
+
}))));
|
|
57
|
+
}));
|
|
@@ -67,3 +67,156 @@ function createReviewTransactionPayload(accountReconciliationEntity) {
|
|
|
67
67
|
});
|
|
68
68
|
return reviewTransactionsPayload;
|
|
69
69
|
}
|
|
70
|
+
export function isStatementDateConflictResponse(response) {
|
|
71
|
+
return response.status.code === 409 && response.error_code != null;
|
|
72
|
+
}
|
|
73
|
+
function transformStatementUploadPayloadToState(statementUploadPayload) {
|
|
74
|
+
return {
|
|
75
|
+
account: {
|
|
76
|
+
accountId: statementUploadPayload.account.account_id,
|
|
77
|
+
accountName: statementUploadPayload.account.account_name,
|
|
78
|
+
accountType: statementUploadPayload.account.account_type,
|
|
79
|
+
currencyCode: statementUploadPayload.account.currency_code,
|
|
80
|
+
last4Digits: statementUploadPayload.account.last_4_digits,
|
|
81
|
+
},
|
|
82
|
+
file: statementUploadPayload.file != null
|
|
83
|
+
? {
|
|
84
|
+
fileId: statementUploadPayload.file.file_id,
|
|
85
|
+
fileName: statementUploadPayload.file.file_name,
|
|
86
|
+
signedUrl: statementUploadPayload.file.signed_url,
|
|
87
|
+
}
|
|
88
|
+
: null,
|
|
89
|
+
statementMeta: {
|
|
90
|
+
closingBalance: statementUploadPayload.statement_meta.closing_balance,
|
|
91
|
+
openingBalance: statementUploadPayload.statement_meta.opening_balance,
|
|
92
|
+
statementDataStatus: statementUploadPayload.statement_meta.statement_data_status,
|
|
93
|
+
statementEndDate: statementUploadPayload.statement_meta.statement_end_date,
|
|
94
|
+
statementStartDate: statementUploadPayload.statement_meta.statement_start_date,
|
|
95
|
+
statementStatus: statementUploadPayload.statement_meta.statement_status,
|
|
96
|
+
statementUploadId: statementUploadPayload.statement_meta.statement_upload_id,
|
|
97
|
+
totalDeposits: statementUploadPayload.statement_meta.total_deposits,
|
|
98
|
+
totalPayments: statementUploadPayload.statement_meta.total_payments,
|
|
99
|
+
},
|
|
100
|
+
statementTransactions: (statementUploadPayload.statement_transactions ?? []).map((txn) => ({
|
|
101
|
+
amount: txn.amount,
|
|
102
|
+
citations: (txn.citation ?? []).map((c) => ({
|
|
103
|
+
page: c.page,
|
|
104
|
+
pageHeight: c.page_height,
|
|
105
|
+
pageWidth: c.page_width,
|
|
106
|
+
polygon: (c.polygon ?? []).map((point) => ({
|
|
107
|
+
x: point.x,
|
|
108
|
+
y: point.y,
|
|
109
|
+
})),
|
|
110
|
+
referenceText: c.reference_text,
|
|
111
|
+
})),
|
|
112
|
+
isUserAdded: txn.is_user_added,
|
|
113
|
+
isUserEdited: txn.is_user_edited,
|
|
114
|
+
statementTransactionId: txn.statement_transaction_id,
|
|
115
|
+
transactionDate: txn.transaction_date,
|
|
116
|
+
transactionDirection: txn.transaction_direction,
|
|
117
|
+
transactionMemo: txn.transaction_memo,
|
|
118
|
+
})),
|
|
119
|
+
aiSummary: transformAiSummaryPayloadToState(statementUploadPayload.ai_summary),
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
function transformPreviousReconciliationInfoToState(payload) {
|
|
123
|
+
if (payload == null) {
|
|
124
|
+
return null;
|
|
125
|
+
}
|
|
126
|
+
return {
|
|
127
|
+
endDate: payload.end_date,
|
|
128
|
+
reconciledAt: payload.reconciled_at,
|
|
129
|
+
reconciledByUserId: payload.reconciled_by_user_id,
|
|
130
|
+
reconciliationId: payload.reconciliation_id,
|
|
131
|
+
startDate: payload.start_date,
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
function transformAiSummaryPayloadToState(aiSummaryPayload) {
|
|
135
|
+
if (aiSummaryPayload == null) {
|
|
136
|
+
return null;
|
|
137
|
+
}
|
|
138
|
+
const { chain_status: chainStatus } = aiSummaryPayload;
|
|
139
|
+
return {
|
|
140
|
+
accountIdentified: aiSummaryPayload.account_identified,
|
|
141
|
+
transactionsExtracted: aiSummaryPayload.transactions_extracted,
|
|
142
|
+
exceptionsDetected: aiSummaryPayload.exceptions_detected,
|
|
143
|
+
fieldsCaptured: (aiSummaryPayload.fields_captured ?? []).map((field) => ({
|
|
144
|
+
code: field.code,
|
|
145
|
+
label: field.label,
|
|
146
|
+
})),
|
|
147
|
+
chainStatus: {
|
|
148
|
+
code: chainStatus?.code ?? '',
|
|
149
|
+
label: chainStatus?.label ?? '',
|
|
150
|
+
expectedStartDate: chainStatus?.expected_start_date ?? null,
|
|
151
|
+
previousReconciliationInfo: transformPreviousReconciliationInfoToState(chainStatus?.previous_reconciliation_info),
|
|
152
|
+
},
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Builds date-conflict state from a 409 Confirm & Save response.
|
|
157
|
+
* Returns null for non-409 responses or 409s without a recognized error code.
|
|
158
|
+
*/
|
|
159
|
+
export function transformStatementDateConflictToState(response) {
|
|
160
|
+
if (isStatementDateConflictResponse(response) === false) {
|
|
161
|
+
return null;
|
|
162
|
+
}
|
|
163
|
+
const previousReconciliationInfo = transformPreviousReconciliationInfoToState(response.previous_reconciliation_info);
|
|
164
|
+
if (response.error_code === 'STATEMENT_RANGE_ALREADY_RECONCILED' &&
|
|
165
|
+
previousReconciliationInfo == null) {
|
|
166
|
+
return null;
|
|
167
|
+
}
|
|
168
|
+
if (response.error_code === 'STATEMENT_RANGE_HAS_GAP' &&
|
|
169
|
+
response.expected_start_date == null &&
|
|
170
|
+
previousReconciliationInfo == null) {
|
|
171
|
+
return null;
|
|
172
|
+
}
|
|
173
|
+
return {
|
|
174
|
+
errorCode: response.error_code,
|
|
175
|
+
expectedStartDate: response.expected_start_date ?? null,
|
|
176
|
+
...(previousReconciliationInfo != null ? { previousReconciliationInfo } : {}),
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
export function transformParseStatementPayloadToState(payload) {
|
|
180
|
+
return {
|
|
181
|
+
statementUpload: transformStatementUploadPayloadToState(payload.statement_upload),
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
export function transformUpdateStatementInfoPayloadToState(payload) {
|
|
185
|
+
return {
|
|
186
|
+
statementUpload: transformStatementUploadPayloadToState(payload.statement_upload),
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
export function transformStatementUpdateStateToPayload(localData) {
|
|
190
|
+
const { statementMeta, statementTransactions } = localData;
|
|
191
|
+
return {
|
|
192
|
+
statement_meta: {
|
|
193
|
+
opening_balance: statementMeta.openingBalance,
|
|
194
|
+
statement_end_date: statementMeta.statementEndDate,
|
|
195
|
+
statement_start_date: statementMeta.statementStartDate,
|
|
196
|
+
total_deposits: statementMeta.totalDeposits,
|
|
197
|
+
total_payments: statementMeta.totalPayments,
|
|
198
|
+
},
|
|
199
|
+
statement_transactions: {
|
|
200
|
+
added: statementTransactions.added.map((txn) => ({
|
|
201
|
+
amount: txn.amount,
|
|
202
|
+
transaction_date: txn.transactionDate,
|
|
203
|
+
transaction_direction: txn.transactionDirection,
|
|
204
|
+
transaction_memo: txn.transactionMemo,
|
|
205
|
+
})),
|
|
206
|
+
deleted_ids: statementTransactions.deletedIds,
|
|
207
|
+
updated: statementTransactions.updated
|
|
208
|
+
.filter((txn) => txn.statementTransactionId != null)
|
|
209
|
+
.map((txn) => ({
|
|
210
|
+
amount: txn.amount,
|
|
211
|
+
statement_transaction_id: txn.statementTransactionId,
|
|
212
|
+
transaction_date: txn.transactionDate,
|
|
213
|
+
transaction_direction: txn.transactionDirection,
|
|
214
|
+
transaction_memo: txn.transactionMemo,
|
|
215
|
+
})),
|
|
216
|
+
},
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
/** API request body for PUT statement-uploads; cast lives here for putAndGetJSON. */
|
|
220
|
+
export function toStatementUpdateRequestBody(localData) {
|
|
221
|
+
return transformStatementUpdateStateToPayload(localData);
|
|
222
|
+
}
|
|
@@ -2,6 +2,7 @@ import { createSlice } from '@reduxjs/toolkit';
|
|
|
2
2
|
import { toMonthYearPeriodId, } from '../../../commonStateTypes/timePeriod';
|
|
3
3
|
import { toReconciliationAccountSource } from '../../../entity/account/accountState';
|
|
4
4
|
import { toBankStatusCodeType } from '../../../entity/accountRecon/accountReconState';
|
|
5
|
+
import { toReconciliationViewSummary, } from '../types/reconciliationViewState';
|
|
5
6
|
// Initial state
|
|
6
7
|
export const initialReconciliationTabsState = {
|
|
7
8
|
balances: {
|
|
@@ -67,6 +68,7 @@ export const initialState = {
|
|
|
67
68
|
refreshStatus: { fetchState: 'Not-Started', error: undefined },
|
|
68
69
|
actionFetchState: initialActionFetchState,
|
|
69
70
|
selectedAccountId: undefined,
|
|
71
|
+
statementProcessingFailed: false,
|
|
70
72
|
statementUploadChosen: false,
|
|
71
73
|
reconListUIState: {
|
|
72
74
|
nodeCollapseState: {},
|
|
@@ -75,6 +77,7 @@ export const initialState = {
|
|
|
75
77
|
},
|
|
76
78
|
},
|
|
77
79
|
excludedAccountIDs: [],
|
|
80
|
+
summary: undefined,
|
|
78
81
|
};
|
|
79
82
|
// Create slice with reducers
|
|
80
83
|
const expenseAutomationReconciliationView = createSlice({
|
|
@@ -143,7 +146,7 @@ const expenseAutomationReconciliationView = createSlice({
|
|
|
143
146
|
fetchReconciliationSuccess: {
|
|
144
147
|
reducer(draft, action) {
|
|
145
148
|
if (action.payload.accountId == null) {
|
|
146
|
-
updateAllReconciliation(draft, action.payload.reconciliation.accounts, action.payload.selectedPeriod, action.payload.reconciliation.reconciliation, action.payload.refreshViewInBackground, action.payload.reconciliation.excluded_accounts ?? []);
|
|
149
|
+
updateAllReconciliation(draft, action.payload.reconciliation.accounts, action.payload.selectedPeriod, action.payload.reconciliation.reconciliation, action.payload.refreshViewInBackground, action.payload.reconciliation.excluded_accounts ?? [], action.payload.reconciliation.summary);
|
|
147
150
|
}
|
|
148
151
|
else if (action.payload.reconciliation.reconciliation.length > 0 &&
|
|
149
152
|
action.payload.reconciliation.accounts.length > 0) {
|
|
@@ -287,6 +290,10 @@ const expenseAutomationReconciliationView = createSlice({
|
|
|
287
290
|
updateSelectedDrawerAccountId: (draft, action) => {
|
|
288
291
|
draft.selectedDrawerAccountId = action.payload.selectedDrawerAccountId;
|
|
289
292
|
},
|
|
293
|
+
updateStatementProcessingFailed: (draft, action) => {
|
|
294
|
+
draft.statementProcessingFailed =
|
|
295
|
+
action.payload.statementProcessingFailed;
|
|
296
|
+
},
|
|
290
297
|
initialiseLocalDataForSelectedAccountId: () => { },
|
|
291
298
|
updateSelectedTab: (draft, action) => {
|
|
292
299
|
const { selectedTab } = action.payload;
|
|
@@ -378,10 +385,22 @@ const expenseAutomationReconciliationView = createSlice({
|
|
|
378
385
|
},
|
|
379
386
|
uploadAccountStatement: (draft, action) => {
|
|
380
387
|
const { accountId, selectedPeriod } = action.payload;
|
|
381
|
-
draft.accountReconciliationRecordsBySelectedPeriod[toMonthYearPeriodId(selectedPeriod)]
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
388
|
+
const accountRecon = draft.accountReconciliationRecordsBySelectedPeriod[toMonthYearPeriodId(selectedPeriod)]?.reconciliationByAccountID[accountId];
|
|
389
|
+
if (accountRecon != null) {
|
|
390
|
+
accountRecon.statementUploadStatus = {
|
|
391
|
+
fetchState: 'In-Progress',
|
|
392
|
+
error: undefined,
|
|
393
|
+
};
|
|
394
|
+
accountRecon.parsedStatementData = undefined;
|
|
395
|
+
accountRecon.statementParseStatus = {
|
|
396
|
+
fetchState: 'Not-Started',
|
|
397
|
+
error: undefined,
|
|
398
|
+
};
|
|
399
|
+
accountRecon.reparseStatementStatus = {
|
|
400
|
+
fetchState: 'Not-Started',
|
|
401
|
+
error: undefined,
|
|
402
|
+
};
|
|
403
|
+
}
|
|
385
404
|
},
|
|
386
405
|
uploadAccountStatementSuccess: (draft, action) => {
|
|
387
406
|
const { accountId, selectedPeriod } = action.payload;
|
|
@@ -419,6 +438,143 @@ const expenseAutomationReconciliationView = createSlice({
|
|
|
419
438
|
error: action.payload.error,
|
|
420
439
|
};
|
|
421
440
|
},
|
|
441
|
+
parseStatement: (draft, action) => {
|
|
442
|
+
const { accountId, selectedPeriod } = action.payload;
|
|
443
|
+
const accountRecon = draft.accountReconciliationRecordsBySelectedPeriod[toMonthYearPeriodId(selectedPeriod)]?.reconciliationByAccountID[accountId];
|
|
444
|
+
if (accountRecon != null) {
|
|
445
|
+
accountRecon.parsedStatementData = undefined;
|
|
446
|
+
accountRecon.statementParseStatus = {
|
|
447
|
+
fetchState: 'In-Progress',
|
|
448
|
+
error: undefined,
|
|
449
|
+
};
|
|
450
|
+
}
|
|
451
|
+
},
|
|
452
|
+
parseStatementSuccess: (draft, action) => {
|
|
453
|
+
const { accountId, selectedPeriod } = action.payload;
|
|
454
|
+
draft.accountReconciliationRecordsBySelectedPeriod[toMonthYearPeriodId(selectedPeriod)].reconciliationByAccountID[accountId].statementParseStatus = {
|
|
455
|
+
fetchState: 'Completed',
|
|
456
|
+
error: undefined,
|
|
457
|
+
};
|
|
458
|
+
draft.accountReconciliationRecordsBySelectedPeriod[toMonthYearPeriodId(selectedPeriod)].reconciliationByAccountID[accountId].statementParseInProgress = false;
|
|
459
|
+
draft.statementProcessingFailed = false;
|
|
460
|
+
},
|
|
461
|
+
parseStatementFailure: (draft, action) => {
|
|
462
|
+
const { accountId, selectedPeriod } = action.payload;
|
|
463
|
+
draft.accountReconciliationRecordsBySelectedPeriod[toMonthYearPeriodId(selectedPeriod)].reconciliationByAccountID[accountId].statementParseStatus = {
|
|
464
|
+
fetchState: 'Error',
|
|
465
|
+
error: action.payload.error,
|
|
466
|
+
};
|
|
467
|
+
draft.accountReconciliationRecordsBySelectedPeriod[toMonthYearPeriodId(selectedPeriod)].reconciliationByAccountID[accountId].statementParseInProgress = false;
|
|
468
|
+
draft.statementProcessingFailed = true;
|
|
469
|
+
},
|
|
470
|
+
reparseStatement: (draft, action) => {
|
|
471
|
+
const { accountId, selectedPeriod } = action.payload;
|
|
472
|
+
const accountRecon = draft.accountReconciliationRecordsBySelectedPeriod[toMonthYearPeriodId(selectedPeriod)]?.reconciliationByAccountID[accountId];
|
|
473
|
+
if (accountRecon != null) {
|
|
474
|
+
accountRecon.parsedStatementData = undefined;
|
|
475
|
+
accountRecon.reparseStatementStatus = {
|
|
476
|
+
fetchState: 'In-Progress',
|
|
477
|
+
error: undefined,
|
|
478
|
+
};
|
|
479
|
+
accountRecon.statementParseStatus = {
|
|
480
|
+
fetchState: 'Not-Started',
|
|
481
|
+
error: undefined,
|
|
482
|
+
};
|
|
483
|
+
accountRecon.statementParseInProgress = false;
|
|
484
|
+
}
|
|
485
|
+
},
|
|
486
|
+
reparseStatementSuccess: (draft, action) => {
|
|
487
|
+
const { accountId, selectedPeriod } = action.payload;
|
|
488
|
+
draft.accountReconciliationRecordsBySelectedPeriod[toMonthYearPeriodId(selectedPeriod)].reconciliationByAccountID[accountId].reparseStatementStatus = {
|
|
489
|
+
fetchState: 'Completed',
|
|
490
|
+
error: undefined,
|
|
491
|
+
};
|
|
492
|
+
draft.accountReconciliationRecordsBySelectedPeriod[toMonthYearPeriodId(selectedPeriod)].reconciliationByAccountID[accountId].statementParseStatus = {
|
|
493
|
+
fetchState: 'Not-Started',
|
|
494
|
+
error: undefined,
|
|
495
|
+
};
|
|
496
|
+
draft.accountReconciliationRecordsBySelectedPeriod[toMonthYearPeriodId(selectedPeriod)].reconciliationByAccountID[accountId].statementParseInProgress = false;
|
|
497
|
+
draft.statementProcessingFailed = false;
|
|
498
|
+
},
|
|
499
|
+
reparseStatementFailure: (draft, action) => {
|
|
500
|
+
const { accountId, selectedPeriod } = action.payload;
|
|
501
|
+
draft.accountReconciliationRecordsBySelectedPeriod[toMonthYearPeriodId(selectedPeriod)].reconciliationByAccountID[accountId].reparseStatementStatus = {
|
|
502
|
+
fetchState: 'Error',
|
|
503
|
+
error: action.payload.error,
|
|
504
|
+
};
|
|
505
|
+
draft.statementProcessingFailed = true;
|
|
506
|
+
},
|
|
507
|
+
resetReparseStatementStatus: (draft, action) => {
|
|
508
|
+
const { accountId, selectedPeriod } = action.payload;
|
|
509
|
+
draft.accountReconciliationRecordsBySelectedPeriod[toMonthYearPeriodId(selectedPeriod)].reconciliationByAccountID[accountId].reparseStatementStatus = {
|
|
510
|
+
fetchState: 'Not-Started',
|
|
511
|
+
error: undefined,
|
|
512
|
+
};
|
|
513
|
+
},
|
|
514
|
+
updateParsedStatementData: (draft, action) => {
|
|
515
|
+
const { accountId, selectedPeriod, parsedStatementData } = action.payload;
|
|
516
|
+
draft.accountReconciliationRecordsBySelectedPeriod[toMonthYearPeriodId(selectedPeriod)].reconciliationByAccountID[accountId].parsedStatementData =
|
|
517
|
+
parsedStatementData;
|
|
518
|
+
},
|
|
519
|
+
updateStatementUpdateLocalData: (draft, action) => {
|
|
520
|
+
const { accountId, selectedPeriod, statementUpdateLocalData } = action.payload;
|
|
521
|
+
const accountRecon = draft.accountReconciliationRecordsBySelectedPeriod[toMonthYearPeriodId(selectedPeriod)]?.reconciliationByAccountID[accountId];
|
|
522
|
+
if (accountRecon != null) {
|
|
523
|
+
if (accountRecon.localData == null) {
|
|
524
|
+
accountRecon.localData = {
|
|
525
|
+
statementUpdateLocalData,
|
|
526
|
+
};
|
|
527
|
+
}
|
|
528
|
+
else {
|
|
529
|
+
accountRecon.localData.statementUpdateLocalData =
|
|
530
|
+
statementUpdateLocalData;
|
|
531
|
+
}
|
|
532
|
+
}
|
|
533
|
+
},
|
|
534
|
+
submitStatementUpdate: (draft, action) => {
|
|
535
|
+
const { accountId, selectedPeriod } = action.payload;
|
|
536
|
+
const accountRecon = draft.accountReconciliationRecordsBySelectedPeriod[toMonthYearPeriodId(selectedPeriod)]?.reconciliationByAccountID[accountId];
|
|
537
|
+
if (accountRecon != null) {
|
|
538
|
+
accountRecon.statementUpdateStatus = {
|
|
539
|
+
fetchState: 'In-Progress',
|
|
540
|
+
error: undefined,
|
|
541
|
+
};
|
|
542
|
+
// Clear any stale date conflict from a previous attempt.
|
|
543
|
+
accountRecon.statementDateConflict = null;
|
|
544
|
+
}
|
|
545
|
+
},
|
|
546
|
+
submitStatementUpdateSuccess: (draft, action) => {
|
|
547
|
+
const { accountId, selectedPeriod } = action.payload;
|
|
548
|
+
const accountRecon = draft.accountReconciliationRecordsBySelectedPeriod[toMonthYearPeriodId(selectedPeriod)]?.reconciliationByAccountID[accountId];
|
|
549
|
+
if (accountRecon != null) {
|
|
550
|
+
accountRecon.statementUpdateStatus = {
|
|
551
|
+
fetchState: 'Completed',
|
|
552
|
+
error: undefined,
|
|
553
|
+
};
|
|
554
|
+
accountRecon.statementDateConflict = null;
|
|
555
|
+
if (accountRecon.localData != null) {
|
|
556
|
+
accountRecon.localData.statementUpdateLocalData = undefined;
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
},
|
|
560
|
+
submitStatementUpdateFailure: (draft, action) => {
|
|
561
|
+
const { accountId, selectedPeriod, dateConflict } = action.payload;
|
|
562
|
+
const accountRecon = draft.accountReconciliationRecordsBySelectedPeriod[toMonthYearPeriodId(selectedPeriod)]?.reconciliationByAccountID[accountId];
|
|
563
|
+
if (accountRecon != null) {
|
|
564
|
+
accountRecon.statementUpdateStatus = {
|
|
565
|
+
fetchState: 'Error',
|
|
566
|
+
error: action.payload.error,
|
|
567
|
+
};
|
|
568
|
+
accountRecon.statementDateConflict = dateConflict ?? null;
|
|
569
|
+
}
|
|
570
|
+
},
|
|
571
|
+
clearStatementDateConflict: (draft, action) => {
|
|
572
|
+
const { accountId, selectedPeriod } = action.payload;
|
|
573
|
+
const accountRecon = draft.accountReconciliationRecordsBySelectedPeriod[toMonthYearPeriodId(selectedPeriod)]?.reconciliationByAccountID[accountId];
|
|
574
|
+
if (accountRecon != null) {
|
|
575
|
+
accountRecon.statementDateConflict = null;
|
|
576
|
+
}
|
|
577
|
+
},
|
|
422
578
|
updateAccountReconciliationLocalData: (draft, action) => {
|
|
423
579
|
const { accountId, selectedPeriod, localData } = action.payload;
|
|
424
580
|
const oldLocalData = draft.accountReconciliationRecordsBySelectedPeriod[toMonthYearPeriodId(selectedPeriod)].reconciliationByAccountID[accountId].localData;
|
|
@@ -524,10 +680,10 @@ const expenseAutomationReconciliationView = createSlice({
|
|
|
524
680
|
},
|
|
525
681
|
});
|
|
526
682
|
// Export actions
|
|
527
|
-
export const { fetchReconciliation, fetchReconciliationFailure, fetchReconciliationSuccess, saveReconciliationDetail, saveReconciliationDetailFailure, updateSelectedAccountId, setConnectionInProgressForAccount, setStatementParseInProgress, updateReconcileTabLocalData, updateReconcileTabListSortState, updateReconcileTabListScrollState, saveReconciliationDetailSuccess, updateSelectedTab, updateBalancesLocalData, initialiseLocalDataForSelectedAccountId, clearExpenseAutomationReconciliationView, updateSelectedDrawerAccountId, updateReviewTabSortState, initializeReconciliationReviewTabLocalData, updateReviewTabLocalData, saveReconciliationReview, updateSaveReconciliationReviewFetchStatus, updateReconListScrollPosition, updateAccountReconciliationLocalData, deleteAccountStatement, deleteAccountStatementSuccess, deleteAccountStatementFailure, excludeAccountFromReconciliation, excludeAccountFromReconciliationSuccess, excludeAccountFromReconciliationFailure, includeAccountInReconciliation, includeAccountInReconciliationSuccess, includeAccountInReconciliationFailure, uploadAccountStatement, uploadAccountStatementSuccess, uploadAccountStatementFailure, updateStatementUploadChosen, updateNodeCollapseState, } = expenseAutomationReconciliationView.actions;
|
|
683
|
+
export const { fetchReconciliation, fetchReconciliationFailure, fetchReconciliationSuccess, saveReconciliationDetail, saveReconciliationDetailFailure, updateSelectedAccountId, setConnectionInProgressForAccount, setStatementParseInProgress, updateReconcileTabLocalData, updateReconcileTabListSortState, updateReconcileTabListScrollState, saveReconciliationDetailSuccess, updateSelectedTab, updateBalancesLocalData, initialiseLocalDataForSelectedAccountId, clearExpenseAutomationReconciliationView, updateSelectedDrawerAccountId, updateStatementProcessingFailed, updateReviewTabSortState, initializeReconciliationReviewTabLocalData, updateReviewTabLocalData, saveReconciliationReview, updateSaveReconciliationReviewFetchStatus, updateReconListScrollPosition, updateAccountReconciliationLocalData, deleteAccountStatement, deleteAccountStatementSuccess, deleteAccountStatementFailure, excludeAccountFromReconciliation, excludeAccountFromReconciliationSuccess, excludeAccountFromReconciliationFailure, includeAccountInReconciliation, includeAccountInReconciliationSuccess, includeAccountInReconciliationFailure, uploadAccountStatement, uploadAccountStatementSuccess, uploadAccountStatementFailure, parseStatement, parseStatementSuccess, parseStatementFailure, reparseStatement, reparseStatementSuccess, reparseStatementFailure, resetReparseStatementStatus, updateParsedStatementData, updateStatementUpdateLocalData, submitStatementUpdate, submitStatementUpdateSuccess, submitStatementUpdateFailure, clearStatementDateConflict, updateStatementUploadChosen, updateNodeCollapseState, } = expenseAutomationReconciliationView.actions;
|
|
528
684
|
// Export reducer
|
|
529
685
|
export default expenseAutomationReconciliationView.reducer;
|
|
530
|
-
function updateAllReconciliation(draft, accounts, selectedPeriod, reconciliationData, refreshViewInBackground, excludedAccounts) {
|
|
686
|
+
function updateAllReconciliation(draft, accounts, selectedPeriod, reconciliationData, refreshViewInBackground, excludedAccounts, summary) {
|
|
531
687
|
draft.excludedAccountIDs = excludedAccounts.map((ea) => ea.account_id);
|
|
532
688
|
draft.excludedAccountExclusionInfo = {};
|
|
533
689
|
excludedAccounts.forEach((ea) => {
|
|
@@ -556,6 +712,7 @@ function updateAllReconciliation(draft, accounts, selectedPeriod, reconciliation
|
|
|
556
712
|
: undefined,
|
|
557
713
|
};
|
|
558
714
|
});
|
|
715
|
+
const oldReconciliationByAccountID = draft.accountReconciliationRecordsBySelectedPeriod[toMonthYearPeriodId(selectedPeriod)]?.reconciliationByAccountID ?? {};
|
|
559
716
|
draft.accountReconciliationRecordsBySelectedPeriod[toMonthYearPeriodId(selectedPeriod)] = {
|
|
560
717
|
accountIDs: [],
|
|
561
718
|
reconciliationByAccountID: {},
|
|
@@ -579,6 +736,7 @@ function updateAllReconciliation(draft, accounts, selectedPeriod, reconciliation
|
|
|
579
736
|
paymentAccountId: account?.payment_account_id ?? undefined,
|
|
580
737
|
};
|
|
581
738
|
}
|
|
739
|
+
const oldRecord = oldReconciliationByAccountID[reconciliation.account_id];
|
|
582
740
|
accountReconciliationRecords.reconciliationByAccountID[reconciliation.account_id] = {
|
|
583
741
|
accountId: reconciliation.account_id,
|
|
584
742
|
reconciliationId: reconciliation.reconciliation_id ?? undefined,
|
|
@@ -586,16 +744,30 @@ function updateAllReconciliation(draft, accounts, selectedPeriod, reconciliation
|
|
|
586
744
|
refreshStatus: { fetchState: 'Not-Started', error: undefined },
|
|
587
745
|
statementDeleteStatus: { fetchState: 'Not-Started', error: undefined },
|
|
588
746
|
statementUploadStatus: { fetchState: 'Not-Started', error: undefined },
|
|
589
|
-
statementUpdateStatus:
|
|
747
|
+
statementUpdateStatus: oldRecord?.statementUpdateStatus ?? {
|
|
748
|
+
fetchState: 'Not-Started',
|
|
749
|
+
error: undefined,
|
|
750
|
+
},
|
|
590
751
|
statementParseInProgress: reconciliation.bank_status.code === 'parsing',
|
|
752
|
+
statementParseStatus: oldRecord?.statementParseStatus ?? {
|
|
753
|
+
fetchState: 'Not-Started',
|
|
754
|
+
error: undefined,
|
|
755
|
+
},
|
|
756
|
+
reparseStatementStatus: oldRecord?.reparseStatementStatus ?? {
|
|
757
|
+
fetchState: 'Not-Started',
|
|
758
|
+
error: undefined,
|
|
759
|
+
},
|
|
760
|
+
statementDateConflict: oldRecord?.statementDateConflict ?? null,
|
|
591
761
|
localData: {
|
|
762
|
+
...oldRecord?.localData,
|
|
592
763
|
accountSource: account?.reconciliation_source != null
|
|
593
764
|
? toReconciliationAccountSource(account.reconciliation_source)
|
|
594
|
-
:
|
|
765
|
+
: oldRecord?.localData?.accountSource,
|
|
595
766
|
},
|
|
596
767
|
accountDetectionReason: account?.detection_info != null && account.detection_reason != null
|
|
597
768
|
? account.detection_reason
|
|
598
769
|
: undefined,
|
|
770
|
+
parsedStatementData: oldRecord?.parsedStatementData,
|
|
599
771
|
};
|
|
600
772
|
accountReconciliationRecords.accountIDs.push(reconciliation.account_id);
|
|
601
773
|
});
|
|
@@ -609,6 +781,10 @@ function updateAllReconciliation(draft, accounts, selectedPeriod, reconciliation
|
|
|
609
781
|
draft.fetchState = 'Completed';
|
|
610
782
|
draft.error = undefined;
|
|
611
783
|
}
|
|
784
|
+
if (summary !== undefined) {
|
|
785
|
+
draft.summary =
|
|
786
|
+
summary != null ? toReconciliationViewSummary(summary) : undefined;
|
|
787
|
+
}
|
|
612
788
|
}
|
|
613
789
|
function updateReconciliationByAccountID(draft, accounts, selectedPeriod, accountId, reconciliationData, refreshViewInBackground) {
|
|
614
790
|
const oldRecord = draft.accountReconciliationRecordsBySelectedPeriod[toMonthYearPeriodId(selectedPeriod)].reconciliationByAccountID[accountId];
|
|
@@ -676,6 +852,9 @@ const updateReconciliationByAccountIDOnIncludeAccount = (draft, accountId, recon
|
|
|
676
852
|
statementUploadStatus: { fetchState: 'Not-Started', error: undefined },
|
|
677
853
|
statementUpdateStatus: { fetchState: 'Not-Started', error: undefined },
|
|
678
854
|
statementParseInProgress: reconciliation.bank_status.code === 'parsing',
|
|
855
|
+
statementParseStatus: { fetchState: 'Not-Started', error: undefined },
|
|
856
|
+
reparseStatementStatus: { fetchState: 'Not-Started', error: undefined },
|
|
857
|
+
statementDateConflict: null,
|
|
679
858
|
localData: {},
|
|
680
859
|
accountDetectionReason: undefined,
|
|
681
860
|
};
|
|
@@ -43,6 +43,17 @@ export const getExpenseAutomationReconciliationView = createSelector((state) =>
|
|
|
43
43
|
error: undefined,
|
|
44
44
|
})
|
|
45
45
|
: { fetchState: 'Not-Started', error: undefined };
|
|
46
|
+
const monthEndChecksForPeriod = selectedPeriod != null
|
|
47
|
+
? monthEndCloseChecksState.monthEndCloseChecksByTenantId[currentTenant.tenantId]?.[toMonthYearPeriodId(selectedPeriod)]
|
|
48
|
+
: undefined;
|
|
49
|
+
const reconCheckTimeSavedHours = monthEndChecksForPeriod?.monthEndCloseCheckList?.find((check) => check.id === 'reconciliation')?.progressJson?.timeSavedHours;
|
|
50
|
+
const summaryWithTimeSaved = reconciliationViewState.summary != null
|
|
51
|
+
? {
|
|
52
|
+
...reconciliationViewState.summary,
|
|
53
|
+
timeSavedHours: reconCheckTimeSavedHours ??
|
|
54
|
+
reconciliationViewState.summary.timeSavedHours,
|
|
55
|
+
}
|
|
56
|
+
: undefined;
|
|
46
57
|
if (accountReconForMonthYearPeriod == null) {
|
|
47
58
|
return {
|
|
48
59
|
bankAccounts: [],
|
|
@@ -66,6 +77,7 @@ export const getExpenseAutomationReconciliationView = createSelector((state) =>
|
|
|
66
77
|
selectedTab: reconciliationViewState.selectedTab,
|
|
67
78
|
monthYearPeriod: selectedPeriod,
|
|
68
79
|
selectedAccountId: reconciliationViewState.selectedAccountId,
|
|
80
|
+
statementProcessingFailed: reconciliationViewState.statementProcessingFailed,
|
|
69
81
|
statementUploadChosen: reconciliationViewState.statementUploadChosen,
|
|
70
82
|
accountReconciliationsByAccountID: {},
|
|
71
83
|
reconciliationTabsState: initialReconciliationTabsState,
|
|
@@ -115,6 +127,7 @@ export const getExpenseAutomationReconciliationView = createSelector((state) =>
|
|
|
115
127
|
excludeAccountFetchState: reconciliationViewState.actionFetchState.excludeAccountFetch,
|
|
116
128
|
includeAccountFetchState: reconciliationViewState.actionFetchState.includeAccountFetch,
|
|
117
129
|
excludedAccountIDs: reconciliationViewState.excludedAccountIDs,
|
|
130
|
+
summary: summaryWithTimeSaved,
|
|
118
131
|
};
|
|
119
132
|
}
|
|
120
133
|
const allAccountIDs = accountReconForMonthYearPeriod.accountIDs;
|
|
@@ -239,6 +252,12 @@ export const getExpenseAutomationReconciliationView = createSelector((state) =>
|
|
|
239
252
|
.refreshStatus,
|
|
240
253
|
statementDeleteStatus: accountReconForMonthYearPeriod.reconciliationByAccountID[accountID]
|
|
241
254
|
.statementDeleteStatus,
|
|
255
|
+
statementParseStatus: accountReconForMonthYearPeriod.reconciliationByAccountID[accountID]
|
|
256
|
+
.statementParseStatus,
|
|
257
|
+
reparseStatementStatus: accountReconForMonthYearPeriod.reconciliationByAccountID[accountID]
|
|
258
|
+
.reparseStatementStatus,
|
|
259
|
+
statementDateConflict: accountReconForMonthYearPeriod.reconciliationByAccountID[accountID]
|
|
260
|
+
.statementDateConflict,
|
|
242
261
|
statementUpdateStatus: accountReconForMonthYearPeriod.reconciliationByAccountID[accountID]
|
|
243
262
|
.statementUpdateStatus,
|
|
244
263
|
statementUploadStatus: accountReconForMonthYearPeriod.reconciliationByAccountID[accountID]
|
|
@@ -247,6 +266,8 @@ export const getExpenseAutomationReconciliationView = createSelector((state) =>
|
|
|
247
266
|
.localData,
|
|
248
267
|
statementParseInProgress: accountReconForMonthYearPeriod.reconciliationByAccountID[accountID]
|
|
249
268
|
.statementParseInProgress,
|
|
269
|
+
parsedStatementData: accountReconForMonthYearPeriod.reconciliationByAccountID[accountID]
|
|
270
|
+
.parsedStatementData,
|
|
250
271
|
transactionFetchState: reduceAnyFetchState([
|
|
251
272
|
accountReconForMonthYearPeriod.reconciliationByAccountID[accountID]
|
|
252
273
|
.transactionFetchState,
|
|
@@ -315,6 +336,9 @@ export const getExpenseAutomationReconciliationView = createSelector((state) =>
|
|
|
315
336
|
statementUpdateStatus: { fetchState: 'Not-Started' },
|
|
316
337
|
statementUploadStatus: { fetchState: 'Not-Started' },
|
|
317
338
|
statementDeleteStatus: { fetchState: 'Not-Started' },
|
|
339
|
+
statementParseStatus: { fetchState: 'Not-Started' },
|
|
340
|
+
reparseStatementStatus: { fetchState: 'Not-Started' },
|
|
341
|
+
statementDateConflict: null,
|
|
318
342
|
localData: {},
|
|
319
343
|
connectionInProgress: false,
|
|
320
344
|
statementParseInProgress: false,
|
|
@@ -403,6 +427,7 @@ export const getExpenseAutomationReconciliationView = createSelector((state) =>
|
|
|
403
427
|
refreshStatus: reconciliationViewState.refreshStatus,
|
|
404
428
|
selectedTab: reconciliationViewState.selectedTab,
|
|
405
429
|
selectedDrawerAccountId: reconciliationViewState.selectedDrawerAccountId,
|
|
430
|
+
statementProcessingFailed: reconciliationViewState.statementProcessingFailed,
|
|
406
431
|
statementUploadChosen: reconciliationViewState.statementUploadChosen,
|
|
407
432
|
monthYearPeriod: selectedPeriod,
|
|
408
433
|
accountReconciliationBySectionID,
|
|
@@ -423,8 +448,10 @@ export const getExpenseAutomationReconciliationView = createSelector((state) =>
|
|
|
423
448
|
excludeAccountFetchState: reconciliationViewState.actionFetchState.excludeAccountFetch,
|
|
424
449
|
includeAccountFetchState: reconciliationViewState.actionFetchState.includeAccountFetch,
|
|
425
450
|
excludedAccountIDs: reconciliationViewState.excludedAccountIDs,
|
|
451
|
+
summary: summaryWithTimeSaved,
|
|
426
452
|
};
|
|
427
453
|
});
|
|
454
|
+
export const getReparseStatementStatusByAccountId = (state, accountId) => getExpenseAutomationReconciliationView(state).accountReconciliationsByAccountID[accountId]?.reparseStatementStatus;
|
|
428
455
|
export const isAccountReconReport = (reportId) => {
|
|
429
456
|
return reportId.endsWith('reconciliation');
|
|
430
457
|
};
|
|
@@ -1,4 +1,33 @@
|
|
|
1
1
|
import { stringToUnion } from '../../../commonStateTypes/stringToUnion';
|
|
2
|
+
export function toReconciliationViewSummary(payload) {
|
|
3
|
+
return {
|
|
4
|
+
accounts: {
|
|
5
|
+
done: payload.accounts.done,
|
|
6
|
+
failed: payload.accounts.failed,
|
|
7
|
+
inProgress: payload.accounts.in_progress,
|
|
8
|
+
total: payload.accounts.total,
|
|
9
|
+
},
|
|
10
|
+
accountsToConnectCount: payload.accounts_to_connect_count,
|
|
11
|
+
autoMatched: {
|
|
12
|
+
matchedTxns: payload.auto_matched.matched_txns,
|
|
13
|
+
totalTxns: payload.auto_matched.total_txns,
|
|
14
|
+
},
|
|
15
|
+
needsReview: {
|
|
16
|
+
accountCount: payload.needs_review.account_count,
|
|
17
|
+
txnCount: payload.needs_review.txn_count,
|
|
18
|
+
},
|
|
19
|
+
timeSavedHours: 0,
|
|
20
|
+
timeSavedPercentage: payload.time_saved_percentage,
|
|
21
|
+
progressBar: payload.progress_bar != null
|
|
22
|
+
? {
|
|
23
|
+
aiPercentageShare: payload.progress_bar.ai_percentage_share,
|
|
24
|
+
completePercentage: payload.progress_bar.complete_percentage,
|
|
25
|
+
humanPercentageShare: payload.progress_bar.human_percentage_share,
|
|
26
|
+
remainingPercentage: payload.progress_bar.remaining_percentage,
|
|
27
|
+
}
|
|
28
|
+
: undefined,
|
|
29
|
+
};
|
|
30
|
+
}
|
|
2
31
|
export const RECONCILE_ACTIONS = [
|
|
3
32
|
'reconcile',
|
|
4
33
|
'save_reconcile_for_later',
|