@zeniai/client-epic-state 5.2.75 → 5.2.76-betaNB1
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/common.d.ts +3 -0
- package/lib/commonStateTypes/common.js +10 -1
- package/lib/entity/reconciliationReport/reconciliationReportPayload.d.ts +124 -0
- package/lib/entity/reconciliationReport/reconciliationReportPayload.js +2 -0
- package/lib/entity/reconciliationReport/reconciliationReportReducer.d.ts +7 -0
- package/lib/entity/reconciliationReport/reconciliationReportReducer.js +173 -0
- package/lib/entity/reconciliationReport/reconciliationReportSelector.d.ts +3 -0
- package/lib/entity/reconciliationReport/reconciliationReportSelector.js +10 -0
- package/lib/entity/reconciliationReport/reconciliationReportState.d.ts +133 -0
- package/lib/entity/reconciliationReport/reconciliationReportState.js +15 -0
- package/lib/epic.d.ts +2 -1
- package/lib/epic.js +2 -0
- package/lib/esm/commonStateTypes/common.js +8 -0
- package/lib/esm/entity/reconciliationReport/reconciliationReportPayload.js +1 -0
- package/lib/esm/entity/reconciliationReport/reconciliationReportReducer.js +168 -0
- package/lib/esm/entity/reconciliationReport/reconciliationReportSelector.js +4 -0
- package/lib/esm/entity/reconciliationReport/reconciliationReportState.js +10 -0
- package/lib/esm/epic.js +2 -0
- package/lib/esm/index.js +5 -2
- package/lib/esm/reducer.js +7 -1
- package/lib/esm/view/companyTaskManagerView/epics/fetchCompanyTaskManagerViewEpic.js +140 -9
- package/lib/esm/view/reconciliationReportView/epic/fetchReconciliationReportEpic.js +29 -0
- package/lib/esm/view/reconciliationReportView/reconciliationReportViewPayload.js +1 -0
- package/lib/esm/view/reconciliationReportView/reconciliationReportViewReducer.js +44 -0
- package/lib/esm/view/reconciliationReportView/reconciliationReportViewSelector.js +10 -0
- package/lib/esm/view/reconciliationReportView/reconciliationReportViewState.js +1 -0
- package/lib/esm/view/taskManager/taskListView/taskListSelector.js +70 -19
- package/lib/index.d.ts +6 -2
- package/lib/index.js +40 -34
- package/lib/reducer.d.ts +2 -0
- package/lib/reducer.js +7 -1
- package/lib/rootStateTypes.d.ts +5 -1
- package/lib/view/companyTaskManagerView/epics/fetchCompanyTaskManagerViewEpic.d.ts +1 -1
- package/lib/view/companyTaskManagerView/epics/fetchCompanyTaskManagerViewEpic.js +140 -9
- package/lib/view/reconciliationReportView/epic/fetchReconciliationReportEpic.d.ts +19 -0
- package/lib/view/reconciliationReportView/epic/fetchReconciliationReportEpic.js +33 -0
- package/lib/view/reconciliationReportView/reconciliationReportViewPayload.d.ts +3 -0
- package/lib/view/reconciliationReportView/reconciliationReportViewPayload.js +2 -0
- package/lib/view/reconciliationReportView/reconciliationReportViewReducer.d.ts +13 -0
- package/lib/view/reconciliationReportView/reconciliationReportViewReducer.js +48 -0
- package/lib/view/reconciliationReportView/reconciliationReportViewSelector.d.ts +9 -0
- package/lib/view/reconciliationReportView/reconciliationReportViewSelector.js +13 -0
- package/lib/view/reconciliationReportView/reconciliationReportViewState.d.ts +4 -0
- package/lib/view/reconciliationReportView/reconciliationReportViewState.js +2 -0
- package/lib/view/taskManager/taskListView/taskListSelector.d.ts +13 -2
- package/lib/view/taskManager/taskListView/taskListSelector.js +70 -19
- package/package.json +1 -1
package/lib/epic.js
CHANGED
|
@@ -445,6 +445,7 @@ const fetchEntityRecommendationsForLineUpdateEpic_1 = require("./view/recommenda
|
|
|
445
445
|
const fetchRecommendationByEntityIdEpic_1 = require("./view/recommendation/fetchRecommendationByEntityIdEpic");
|
|
446
446
|
const fetchRecommendationByEntityNameEpic_1 = require("./view/recommendation/fetchRecommendationByEntityNameEpic");
|
|
447
447
|
const submitRecommendationFeedbackEpic_1 = require("./view/recommendation/submitRecommendationFeedbackEpic");
|
|
448
|
+
const fetchReconciliationReportEpic_1 = require("./view/reconciliationReportView/epic/fetchReconciliationReportEpic");
|
|
448
449
|
const fetchReferralsEpic_1 = require("./view/referralView/epics/fetchReferralsEpic");
|
|
449
450
|
const fetchRewardsPlanEpic_1 = require("./view/referralView/epics/fetchRewardsPlanEpic");
|
|
450
451
|
const resendReferralInviteEpic_1 = require("./view/referralView/epics/resendReferralInviteEpic");
|
|
@@ -1174,6 +1175,7 @@ const ALL_EPICS = [
|
|
|
1174
1175
|
fetchRecommendationForAccountTypeEpic_1.fetchRecommendationForAccountTypeEpic,
|
|
1175
1176
|
fetchRecommendationsAndUpdateMerchantRecommendationsEpic_1.fetchRecommendationsAndUpdateMerchantRecommendationsEpic,
|
|
1176
1177
|
fetchRecommendedTransactionRowIndexEpic_1.fetchRecommendedTransactionRowIndexEpic,
|
|
1178
|
+
fetchReconciliationReportEpic_1.fetchReconciliationReportEpic,
|
|
1177
1179
|
fetchReferralsEpic_1.fetchReferralsEpic,
|
|
1178
1180
|
fetchRegisteredInterestsEpic_1.fetchRegisteredInterestsEpic,
|
|
1179
1181
|
fetchReimbursementCardEpic_1.fetchReimbursementCardEpic,
|
|
@@ -2,3 +2,11 @@ import { stringToUnion } from './stringToUnion';
|
|
|
2
2
|
const COMPLETION_STATUS_TYPES = ['incomplete', 'complete'];
|
|
3
3
|
export const toCompletionStatusType = (v) => stringToUnion(v, COMPLETION_STATUS_TYPES);
|
|
4
4
|
export const getUnderScoreKey = (keys) => keys.join('_');
|
|
5
|
+
/** Early-exit emptiness check: `Object.keys(x).length > 0` allocates an array
|
|
6
|
+
* on every call, and this one runs inside selector inputs. */
|
|
7
|
+
export const hasAnyKey = (record) => {
|
|
8
|
+
for (const _key in record) {
|
|
9
|
+
return true;
|
|
10
|
+
}
|
|
11
|
+
return false;
|
|
12
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
import { createSlice } from '@reduxjs/toolkit';
|
|
2
|
+
import { mapCurrencyPayloadToCurrency } from '../../commonPayloadTypes/v2/viewAndReportPayloadv2';
|
|
3
|
+
import { toAmountWC } from '../../commonStateTypes/amount';
|
|
4
|
+
import { clearAll } from '../../rootActions';
|
|
5
|
+
import { date } from '../../zeniDayJS';
|
|
6
|
+
import { toReconciliationStatusCodeType } from '../accountRecon/accountReconState';
|
|
7
|
+
import { toReconciliationReportDataSource, toReconciliationReportMatchType, } from './reconciliationReportState';
|
|
8
|
+
export const initialState = {
|
|
9
|
+
reportsByReconciliationId: {},
|
|
10
|
+
};
|
|
11
|
+
const reconciliationReport = createSlice({
|
|
12
|
+
name: 'reconciliationReport',
|
|
13
|
+
initialState,
|
|
14
|
+
reducers: {
|
|
15
|
+
updateReconciliationReport(draft, action) {
|
|
16
|
+
const report = mapReconciliationReportPayloadToReconciliationReport(action.payload);
|
|
17
|
+
draft.reportsByReconciliationId[report.reconciliationId] = report;
|
|
18
|
+
},
|
|
19
|
+
removeReconciliationReport(draft, action) {
|
|
20
|
+
delete draft.reportsByReconciliationId[action.payload];
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
extraReducers: (builder) => {
|
|
24
|
+
builder.addCase(clearAll, (draft) => {
|
|
25
|
+
Object.assign(draft, initialState);
|
|
26
|
+
});
|
|
27
|
+
},
|
|
28
|
+
});
|
|
29
|
+
export const { updateReconciliationReport, removeReconciliationReport } = reconciliationReport.actions;
|
|
30
|
+
export default reconciliationReport.reducer;
|
|
31
|
+
function toOptionalAmount(amount, currency) {
|
|
32
|
+
if (amount == null) {
|
|
33
|
+
return undefined;
|
|
34
|
+
}
|
|
35
|
+
return toAmountWC(amount, currency);
|
|
36
|
+
}
|
|
37
|
+
function toOptionalDate(value) {
|
|
38
|
+
if (value == null || value === '') {
|
|
39
|
+
return undefined;
|
|
40
|
+
}
|
|
41
|
+
return date(value);
|
|
42
|
+
}
|
|
43
|
+
function mapCountAmount(payload, currency) {
|
|
44
|
+
return {
|
|
45
|
+
count: payload.count,
|
|
46
|
+
amount: toAmountWC(payload.amount, currency),
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
function mapTransactionRow(payload, currency) {
|
|
50
|
+
return {
|
|
51
|
+
transactionId: payload.transaction_id ?? undefined,
|
|
52
|
+
date: toOptionalDate(payload.date),
|
|
53
|
+
type: payload.type,
|
|
54
|
+
payee: payload.payee,
|
|
55
|
+
match: toReconciliationReportMatchType(payload.match),
|
|
56
|
+
amount: toAmountWC(payload.amount, currency),
|
|
57
|
+
clearedBalance: payload.cleared_balance != null
|
|
58
|
+
? toAmountWC(payload.cleared_balance, currency)
|
|
59
|
+
: undefined,
|
|
60
|
+
glAccount: payload.gl_account ?? undefined,
|
|
61
|
+
referenceNumber: payload.reference_number ?? undefined,
|
|
62
|
+
issueDate: toOptionalDate(payload.issue_date),
|
|
63
|
+
ageDays: payload.age_days ?? undefined,
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
function mapBucket(payload, currency) {
|
|
67
|
+
return {
|
|
68
|
+
count: payload.count,
|
|
69
|
+
amount: toAmountWC(payload.amount, currency),
|
|
70
|
+
transactions: payload.transactions.map((transaction) => mapTransactionRow(transaction, currency)),
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
function mapPaymentsDeposits(payload, currency) {
|
|
74
|
+
return {
|
|
75
|
+
payments: mapBucket(payload.payments, currency),
|
|
76
|
+
deposits: mapBucket(payload.deposits, currency),
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
export function mapReconciliationReportPayloadToReconciliationReport(payload) {
|
|
80
|
+
const currency = mapCurrencyPayloadToCurrency(payload.currency);
|
|
81
|
+
return {
|
|
82
|
+
reconciliationId: payload.reconciliation_id,
|
|
83
|
+
companyName: payload.company_name ?? undefined,
|
|
84
|
+
account: {
|
|
85
|
+
accountId: payload.account.account_id,
|
|
86
|
+
accountName: payload.account.account_name ?? undefined,
|
|
87
|
+
accountType: payload.account.account_type ?? undefined,
|
|
88
|
+
accountSubType: payload.account.account_sub_type ?? undefined,
|
|
89
|
+
last4Digits: payload.account.last_4_digits ?? undefined,
|
|
90
|
+
maskedAccountNumber: payload.account.masked_account_number ?? undefined,
|
|
91
|
+
financialInstitution: payload.account.financial_institution ?? undefined,
|
|
92
|
+
glAccountName: payload.account.gl_account_name ?? undefined,
|
|
93
|
+
coaId: payload.account.coa_id ?? undefined,
|
|
94
|
+
},
|
|
95
|
+
period: {
|
|
96
|
+
startDate: toOptionalDate(payload.period.start_date),
|
|
97
|
+
endDate: toOptionalDate(payload.period.end_date),
|
|
98
|
+
},
|
|
99
|
+
statementDate: toOptionalDate(payload.statement_date),
|
|
100
|
+
dataSource: toReconciliationReportDataSource(payload.data_source),
|
|
101
|
+
currency,
|
|
102
|
+
status: {
|
|
103
|
+
code: toReconciliationStatusCodeType(payload.status.code),
|
|
104
|
+
label: payload.status.label,
|
|
105
|
+
},
|
|
106
|
+
reconciledAt: toOptionalDate(payload.reconciled_at),
|
|
107
|
+
reconciledBy: {
|
|
108
|
+
userId: payload.reconciled_by.user_id ?? undefined,
|
|
109
|
+
name: payload.reconciled_by.name ?? undefined,
|
|
110
|
+
},
|
|
111
|
+
disclaimer: payload.disclaimer,
|
|
112
|
+
reportReference: payload.report_reference ?? undefined,
|
|
113
|
+
locked: payload.locked,
|
|
114
|
+
difference: toOptionalAmount(payload.difference.amount, currency),
|
|
115
|
+
aiMatch: {
|
|
116
|
+
autoMatchedCount: payload.ai_match.auto_matched_count,
|
|
117
|
+
manuallyMatchedCount: payload.ai_match.manually_matched_count,
|
|
118
|
+
clearedCount: payload.ai_match.cleared_count,
|
|
119
|
+
},
|
|
120
|
+
afterPeriodEnd: {
|
|
121
|
+
unclearedAmount: toAmountWC(payload.after_period_end.uncleared_amount, currency),
|
|
122
|
+
clearedAmount: toAmountWC(payload.after_period_end.cleared_amount, currency),
|
|
123
|
+
},
|
|
124
|
+
statement: {
|
|
125
|
+
openingBalance: toOptionalAmount(payload.statement.opening_balance, currency),
|
|
126
|
+
paymentsCleared: mapCountAmount(payload.statement.payments_cleared, currency),
|
|
127
|
+
depositsCleared: mapCountAmount(payload.statement.deposits_cleared, currency),
|
|
128
|
+
closingBalance: toOptionalAmount(payload.statement.closing_balance, currency),
|
|
129
|
+
},
|
|
130
|
+
register: {
|
|
131
|
+
balanceAsOfPeriodEnd: toOptionalAmount(payload.register.balance_as_of_period_end, currency),
|
|
132
|
+
outstandingAsOfPeriodEnd: toAmountWC(payload.register.outstanding_as_of_period_end, currency),
|
|
133
|
+
balanceAsOfReconciledAt: toOptionalAmount(payload.register.balance_as_of_reconciled_at, currency),
|
|
134
|
+
},
|
|
135
|
+
summary: {
|
|
136
|
+
openingBalance: toOptionalAmount(payload.summary.opening_balance, currency),
|
|
137
|
+
clearedPayments: mapCountAmount(payload.summary.cleared_payments, currency),
|
|
138
|
+
clearedDeposits: mapCountAmount(payload.summary.cleared_deposits, currency),
|
|
139
|
+
closingBalance: toOptionalAmount(payload.summary.closing_balance, currency),
|
|
140
|
+
unclearedAsOfStatementDate: {
|
|
141
|
+
payments: mapCountAmount(payload.summary.uncleared_as_of_statement_date.payments, currency),
|
|
142
|
+
deposits: mapCountAmount(payload.summary.uncleared_as_of_statement_date.deposits, currency),
|
|
143
|
+
},
|
|
144
|
+
ledgerClosingAsOfStatementDate: toOptionalAmount(payload.summary.ledger_closing_as_of_statement_date, currency),
|
|
145
|
+
clearedAfterStatementDate: payload.summary.cleared_after_statement_date != null
|
|
146
|
+
? mapCountAmount(payload.summary.cleared_after_statement_date, currency)
|
|
147
|
+
: undefined,
|
|
148
|
+
unclearedAfterStatementDate: payload.summary.uncleared_after_statement_date != null
|
|
149
|
+
? mapCountAmount(payload.summary.uncleared_after_statement_date, currency)
|
|
150
|
+
: undefined,
|
|
151
|
+
ledgerBalanceAsOfReconciledOn: toOptionalAmount(payload.summary.ledger_balance_as_of_reconciled_on, currency),
|
|
152
|
+
bridge: {
|
|
153
|
+
bankClosing: toOptionalAmount(payload.summary.bridge.bank_closing, currency),
|
|
154
|
+
unclearedDeposits: toAmountWC(payload.summary.bridge.uncleared_deposits, currency),
|
|
155
|
+
unclearedPayments: toAmountWC(payload.summary.bridge.uncleared_payments, currency),
|
|
156
|
+
computedLedgerClosing: toOptionalAmount(payload.summary.bridge.computed_ledger_closing, currency),
|
|
157
|
+
ledgerClosing: toOptionalAmount(payload.summary.bridge.ledger_closing, currency),
|
|
158
|
+
variance: toOptionalAmount(payload.summary.bridge.variance, currency),
|
|
159
|
+
},
|
|
160
|
+
variance: toOptionalAmount(payload.summary.variance, currency),
|
|
161
|
+
},
|
|
162
|
+
details: {
|
|
163
|
+
cleared: mapPaymentsDeposits(payload.details.cleared, currency),
|
|
164
|
+
carriedForward: mapPaymentsDeposits(payload.details.carried_forward, currency),
|
|
165
|
+
unclearedAsOfStatementDate: mapPaymentsDeposits(payload.details.uncleared_as_of_statement_date, currency),
|
|
166
|
+
},
|
|
167
|
+
};
|
|
168
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { stringToUnion } from '../../commonStateTypes/stringToUnion';
|
|
2
|
+
const RECONCILIATION_REPORT_MATCH_TYPE = ['automatic', 'manual'];
|
|
3
|
+
export const toReconciliationReportMatchType = (value) => {
|
|
4
|
+
if (value === 'auto') {
|
|
5
|
+
return 'automatic';
|
|
6
|
+
}
|
|
7
|
+
return stringToUnion(value, RECONCILIATION_REPORT_MATCH_TYPE);
|
|
8
|
+
};
|
|
9
|
+
const RECONCILIATION_REPORT_DATA_SOURCE = ['Statement', 'Plaid'];
|
|
10
|
+
export const toReconciliationReportDataSource = (value) => stringToUnion(value, RECONCILIATION_REPORT_DATA_SOURCE);
|
package/lib/esm/epic.js
CHANGED
|
@@ -442,6 +442,7 @@ import { fetchEntityRecommendationsForLineUpdateEpic, } from './view/recommendat
|
|
|
442
442
|
import { fetchRecommendationByEntityIdEpic, } from './view/recommendation/fetchRecommendationByEntityIdEpic';
|
|
443
443
|
import { fetchRecommendationByEntityNameEpic, } from './view/recommendation/fetchRecommendationByEntityNameEpic';
|
|
444
444
|
import { submitRecommendationFeedbackEpic, } from './view/recommendation/submitRecommendationFeedbackEpic';
|
|
445
|
+
import { fetchReconciliationReportEpic, } from './view/reconciliationReportView/epic/fetchReconciliationReportEpic';
|
|
445
446
|
import { fetchReferralsEpic, } from './view/referralView/epics/fetchReferralsEpic';
|
|
446
447
|
import { fetchRewardsPlanEpic, } from './view/referralView/epics/fetchRewardsPlanEpic';
|
|
447
448
|
import { resendReferralInviteEpic, } from './view/referralView/epics/resendReferralInviteEpic';
|
|
@@ -1171,6 +1172,7 @@ const ALL_EPICS = [
|
|
|
1171
1172
|
fetchRecommendationForAccountTypeEpic,
|
|
1172
1173
|
fetchRecommendationsAndUpdateMerchantRecommendationsEpic,
|
|
1173
1174
|
fetchRecommendedTransactionRowIndexEpic,
|
|
1175
|
+
fetchReconciliationReportEpic,
|
|
1174
1176
|
fetchReferralsEpic,
|
|
1175
1177
|
fetchRegisteredInterestsEpic,
|
|
1176
1178
|
fetchReimbursementCardEpic,
|
package/lib/esm/index.js
CHANGED
|
@@ -274,6 +274,8 @@ import { fetchProjectList } from './view/projectList/projectListReducer';
|
|
|
274
274
|
import { getProjectList, } from './view/projectList/projectListSelector';
|
|
275
275
|
import { fetchEntityRecommendationsByTransactionId, fetchEntityRecommendationsForLineUpdate, fetchRecommendationByEntityId, fetchRecommendationByEntityName, submitRecommendationFeedback, } from './view/recommendation/recommendationReducer';
|
|
276
276
|
import { getRecommendationFeedbackSubmitState } from './view/recommendation/recommendationSelector';
|
|
277
|
+
import { fetchReconciliationReport } from './view/reconciliationReportView/reconciliationReportViewReducer';
|
|
278
|
+
import { getReconciliationReport } from './view/reconciliationReportView/reconciliationReportViewSelector';
|
|
277
279
|
import { DEFAULT_REFERRER_AMOUNT, clearReferrals, fetchReferrals, fetchRewardsPlan, resendReferralInvite, saveReferralFormDataInLocalStore, sendReferralInvite, updateReferViewed, updateReferralListSortUiState, } from './view/referralView/referralReducer';
|
|
278
280
|
import { getInviteFormView, getReferralListView, getRewardsPlanCard, } from './view/referralView/referralSelector';
|
|
279
281
|
import { AmountStatusTypes, StatusTypes, toReferralListViewSortKeyType, } from './view/referralView/referralState';
|
|
@@ -416,7 +418,7 @@ import { allTaskPriority, allTaskStatus, getTaskDetail, } from './view/taskManag
|
|
|
416
418
|
import { createTaskFromTaskGroupTemplate } from './view/taskManager/taskGroupTemplateView/taskGroupTemplateViewReducer';
|
|
417
419
|
import { createNewTaskGroup, deleteTaskGroup, fetchAllTaskGroups, updateTaskGroupName, } from './view/taskManager/taskGroupView/taskGroupViewReducer';
|
|
418
420
|
import { ALL_TASK_LIST_TABS, TASK_LIST_FILTER_CATEGORIES, TASK_LIST_GROUP_BY_CATEGORIES, toDueDateGroupKeyType, toTaskListGroupByKeyType, toTaskListGroupByKeyTypeStrict, } from './view/taskManager/taskListView/taskList';
|
|
419
|
-
import { bulkUpdateTaskList, dragNDropTasks, fetchTaskListPage, initiateTaskListLocalData, removeTaskFromList, updateTaskFilters, updateTaskFromListView, updateTaskListLocalData, updateTaskListSearchText, updateTaskListTab, updateTaskListUIState, } from './view/taskManager/taskListView/taskListReducer';
|
|
421
|
+
import { bulkUpdateTaskList, dragNDropTasks, fetchTaskList, fetchTaskListPage, initiateTaskListLocalData, removeTaskFromList, updateTaskFilters, updateTaskFromListView, updateTaskListLocalData, updateTaskListSearchText, updateTaskListTab, updateTaskListUIState, } from './view/taskManager/taskListView/taskListReducer';
|
|
420
422
|
import { getAllTasks, } from './view/taskManager/taskListView/taskListSelector';
|
|
421
423
|
import { getDueDateValueFromDueDateGroupId, getTaskUpdates, sortSubtasks, } from './view/taskManager/taskListView/taskListViewHelpers';
|
|
422
424
|
import { fetchTasksCard } from './view/tasksCard/tasksCardReducer';
|
|
@@ -576,6 +578,7 @@ export { getEntityAutoCompleteResults };
|
|
|
576
578
|
export { updateEntities };
|
|
577
579
|
export { getEntityByEntityIDs };
|
|
578
580
|
export { getAddressByAddressId };
|
|
581
|
+
export { fetchReconciliationReport, getReconciliationReport, };
|
|
579
582
|
export { ALL_ACCOUNTING_CONNECTION_CREATION_MODES, isCompanyEligibleForTreasury, isCardsProductEnabledOnCompany, filterChargeCardRolesWhenProductDisabled, };
|
|
580
583
|
export { getCompanyByCompanyId, getControllersForCompany, getCompanyInfoForAllCockpitCompaniesInState, getFirstControllerEmail, getFirstControllerId, getControllersName, };
|
|
581
584
|
export { getCompanyManagementView, getPlanListZeniSku, getAddonListZeniSku, };
|
|
@@ -671,7 +674,7 @@ export { fetchGlobalMerchantRecommendation, createGlobalMerchant, updateCreateGl
|
|
|
671
674
|
export { approveVendorGlobalReview, rejectVendorGlobalReview, fetchVendorGlobalReviewView, updateSelectedGlobalMerchant, updateVendorGlobalReviewViewUIState, getVendorGlobalReviewView, getTenantMerchantByMerchantId, toVendorGlobalReviewColumnSortKeyType, updateVendorGlobalReviewViewLocalData, };
|
|
672
675
|
export { fetchArAging, updateArAgingUIState, fetchArAgingDetail, updateArAgingDetailUIState, getArAgingReport, getArAgingDetailForCustomer, updateArAgingNodeCollapseState, };
|
|
673
676
|
export { toRecurringBillFrequency, toRecurringBillFrequencyStrict, };
|
|
674
|
-
export { getTaskGroupById, getAllTasks, fetchTaskListPage, getTaskDetail, fetchTaskDetailPage, saveTaskUpdatesToLocalStore, saveTaskDetail, createSubTask, resetSubTaskCreateStatus, fetchSubTasks, archiveTask, fetchCannedResponses, saveCannedResponse, deleteCannedResponse, getCannedResponsesView, updateTaskListSearchText, updateTaskListUIState, allTaskStatus, allTaskPriority, updateTaskFilters, TASK_LIST_FILTER_CATEGORIES, TASK_LIST_GROUP_BY_CATEGORIES, deleteTask, discardTaskUpdatesInLocalStore, bulkUpdateTaskList, createNewTaskGroup, initiateTaskListLocalData, deleteTaskGroup, updateTaskListLocalData, dragNDropTasks, updateTaskGroupName, toTaskListGroupByKeyType, toTaskListGroupByKeyTypeStrict, getTaskUpdates, sortSubtasks, fetchAllTaskGroups, initialTaskDetail, getDueDateValueFromDueDateGroupId, toPriorityCodeType, toTaskStatusCodeType, toDueDateGroupKeyType, updateTaskFromListView, updateTaskListTab, removeTaskFromList, snoozeTask, unsnoozeTask, convertHHMMStrToMinutes, initialTaskDetailLocalData, ALL_TASK_LIST_TABS, };
|
|
677
|
+
export { getTaskGroupById, getAllTasks, fetchTaskList, fetchTaskListPage, getTaskDetail, fetchTaskDetailPage, saveTaskUpdatesToLocalStore, saveTaskDetail, createSubTask, resetSubTaskCreateStatus, fetchSubTasks, archiveTask, fetchCannedResponses, saveCannedResponse, deleteCannedResponse, getCannedResponsesView, updateTaskListSearchText, updateTaskListUIState, allTaskStatus, allTaskPriority, updateTaskFilters, TASK_LIST_FILTER_CATEGORIES, TASK_LIST_GROUP_BY_CATEGORIES, deleteTask, discardTaskUpdatesInLocalStore, bulkUpdateTaskList, createNewTaskGroup, initiateTaskListLocalData, deleteTaskGroup, updateTaskListLocalData, dragNDropTasks, updateTaskGroupName, toTaskListGroupByKeyType, toTaskListGroupByKeyTypeStrict, getTaskUpdates, sortSubtasks, fetchAllTaskGroups, initialTaskDetail, getDueDateValueFromDueDateGroupId, toPriorityCodeType, toTaskStatusCodeType, toDueDateGroupKeyType, updateTaskFromListView, updateTaskListTab, removeTaskFromList, snoozeTask, unsnoozeTask, convertHHMMStrToMinutes, initialTaskDetailLocalData, ALL_TASK_LIST_TABS, };
|
|
675
678
|
export { getAllTags, fetchTagList, createTag, deleteTag, };
|
|
676
679
|
export { getAllCardsAndBankPaymentMethods, createCardSetupIntent, confirmCardSetupIntent, addCardPaymentSource, fetchPaymentSources, resetCardPaymentErrorStatuses, clearCardPaymentView, };
|
|
677
680
|
export { getAuditReportGroupViewSelectorView, getAuditRuleGroupViewSelectorView, getUserFromAllUsers, fetchAuditRuleGroupView, fetchAuditReportGroupView, saveReasonForAuditRule, clearAuditReportGroupViewByCompanyId, };
|
package/lib/esm/reducer.js
CHANGED
|
@@ -38,10 +38,10 @@ import invoicingCoupon, { initialState as initialInvoicingCouponState, } from '.
|
|
|
38
38
|
import invoicingCreditNote, { initialState as initialInvoicingCreditNoteState, } from './entity/invoicing/creditNote/creditNoteReducer';
|
|
39
39
|
import invoicingDunningCase, { initialState as initialInvoicingDunningCaseState, } from './entity/invoicing/dunningCase/dunningCaseReducer';
|
|
40
40
|
import invoicingInvoice, { initialState as initialInvoicingInvoiceState, } from './entity/invoicing/invoice/invoiceReducer';
|
|
41
|
+
import invoicingCatalog, { initialState as initialInvoicingCatalogState, } from './entity/invoicing/invoicingCatalog/invoicingCatalogReducer';
|
|
41
42
|
import invoicingCustomer, { initialState as initialInvoicingCustomerState, } from './entity/invoicing/invoicingCustomer/invoicingCustomerReducer';
|
|
42
43
|
import invoicingSubscription, { initialState as initialInvoicingSubscriptionState, } from './entity/invoicing/invoicingSubscription/invoicingSubscriptionReducer';
|
|
43
44
|
import invoicingTransaction, { initialState as initialInvoicingTransactionState, } from './entity/invoicing/invoicingTransaction/invoicingTransactionReducer';
|
|
44
|
-
import invoicingCatalog, { initialState as initialInvoicingCatalogState, } from './entity/invoicing/invoicingCatalog/invoicingCatalogReducer';
|
|
45
45
|
import jeSchedules, { initialState as initialJESchedulesState, } from './entity/jeSchedules/jeSchedulesReducer';
|
|
46
46
|
import merchant, { initialState as initialMerchantState, } from './entity/merchant/merchantReducer';
|
|
47
47
|
import monthEndCloseChecks, { initialState as initialMonthEndCloseChecksState, } from './entity/monthEndCloseChecks/monthEndCloseChecksReducer';
|
|
@@ -52,6 +52,7 @@ import paymentAccount, { initialState as initialPaymentAccountState, } from './e
|
|
|
52
52
|
import paymentInstrument, { initialState as initialPaymentInstrumentState, } from './entity/paymentInstrument/paymentInstrumentReducer';
|
|
53
53
|
import accountingSummary, { initialState as initialAccountingSummaryState, } from './entity/portfolio/accountingSummary/accountingSummaryReducer';
|
|
54
54
|
import project, { initialState as initialProjectState, } from './entity/project/projectReducer';
|
|
55
|
+
import reconciliationReport, { initialState as initialReconciliationReportState, } from './entity/reconciliationReport/reconciliationReportReducer';
|
|
55
56
|
import reimbursement, { initialState as initialReimbursementState, } from './entity/reimbursement/reimbursementReducer';
|
|
56
57
|
import sectionAccountsView, { initialState as initialSectionAccountsViewState, } from './entity/sectionAccountsView/sectionAccountsViewReducer';
|
|
57
58
|
import sectionClassesViewV2, { initialState as initialSectionClassesViewStateV2, } from './entity/sectionClassesViewV2/sectionClassesViewReducer';
|
|
@@ -179,6 +180,7 @@ import profitAndLossClassesView, { initialState as initialProfitAndLossClassesVi
|
|
|
179
180
|
import profitAndLossProjectView, { initialState as initialProfitAndLossProjectViewState, } from './view/profitAndLossProjectView/profitAndLossProjectViewReducer';
|
|
180
181
|
import projectList, { initialState as initialProjectListState, } from './view/projectList/projectListReducer';
|
|
181
182
|
import recommendation, { initialState as initialEntityRecommendationState, } from './view/recommendation/recommendationReducer';
|
|
183
|
+
import reconciliationReportView, { initialState as initialReconciliationReportViewState, } from './view/reconciliationReportView/reconciliationReportViewReducer';
|
|
182
184
|
import referralView, { initialState as initialReferralViewState, } from './view/referralView/referralReducer';
|
|
183
185
|
import reimbursementCard, { initialState as initialReimbursementCardState, } from './view/reimbursementCard/reimbursementCardReducer';
|
|
184
186
|
import reportUIOptionsReducer, { initialState as initialReportUIOptionsState, } from './view/reportUIOptions/reportUIOptionsReducer';
|
|
@@ -325,6 +327,7 @@ const initialEntitiesState = {
|
|
|
325
327
|
onboardingCustomerState: initialOnboardingCustomerState,
|
|
326
328
|
paymentAccountState: initialPaymentAccountState,
|
|
327
329
|
paymentInstrumentState: initialPaymentInstrumentState,
|
|
330
|
+
reconciliationReportState: initialReconciliationReportState,
|
|
328
331
|
recurringBillState: initialRecurringBillState,
|
|
329
332
|
reimbursementConfigState: initialReimbursementConfigState,
|
|
330
333
|
reimbursementState: initialReimbursementState,
|
|
@@ -493,6 +496,7 @@ const initialViewsState = {
|
|
|
493
496
|
profitAndLossState: initialProfitAndLossState,
|
|
494
497
|
projectListState: initialProjectListState,
|
|
495
498
|
realTimeApprovalState: initialRealTimeApprovalState,
|
|
499
|
+
reconciliationReportViewState: initialReconciliationReportViewState,
|
|
496
500
|
referralViewState: initialReferralViewState,
|
|
497
501
|
reimbursementCardState: initialReimbursementCardState,
|
|
498
502
|
reimbursementConfigState: initialReimbursementConfigState,
|
|
@@ -611,6 +615,7 @@ const entityReducers = {
|
|
|
611
615
|
onboardingCustomerState: onboardingCustomer,
|
|
612
616
|
paymentAccountState: paymentAccount,
|
|
613
617
|
paymentInstrumentState: paymentInstrument,
|
|
618
|
+
reconciliationReportState: reconciliationReport,
|
|
614
619
|
recurringBillState: recurringBill,
|
|
615
620
|
reimbursementConfigState: reimbursementConfig,
|
|
616
621
|
reimbursementState: reimbursement,
|
|
@@ -779,6 +784,7 @@ const viewReducers = {
|
|
|
779
784
|
profitAndLossState: profitAndLoss,
|
|
780
785
|
projectListState: projectList,
|
|
781
786
|
realTimeApprovalState: realTimeApproval,
|
|
787
|
+
reconciliationReportViewState: reconciliationReportView,
|
|
782
788
|
referralViewState: referralView,
|
|
783
789
|
reimbursementCardState: reimbursementCard,
|
|
784
790
|
reimbursementConfigState: reimbursementConfig,
|
|
@@ -4,19 +4,41 @@ import { getSortOrder } from '../../../commonPayloadTypes/sortOrderPayload';
|
|
|
4
4
|
import { updateTags } from '../../../entity/tag/tagReducer';
|
|
5
5
|
import { updateTasks } from '../../../entity/task/taskReducer';
|
|
6
6
|
import { createZeniAPIStatus, isSuccessResponse } from '../../../responsePayload';
|
|
7
|
+
import { date as toZeniDate } from '../../../zeniDayJS';
|
|
7
8
|
import { fetchCompanyTaskManagerView, updateCompanyTaskManagerViewOnFailure, updateCompanyTaskManagerViewOnSuccess, } from '../companyTaskManagerViewReducer';
|
|
8
9
|
const DEFAULT_PAGE_SIZE = 100;
|
|
9
|
-
|
|
10
|
+
// Mutates the accumulator rather than spreading it: spreading rebuilds the whole
|
|
11
|
+
// map on every entry, which is O(n^2) over a tenant's tag list.
|
|
12
|
+
const toTagNameByID = (state) => Object.entries(state.tagState.tagByID).reduce((result, [tagId, tag]) => {
|
|
13
|
+
const name = tag?.name;
|
|
14
|
+
if (name != null && name !== '') {
|
|
15
|
+
result[tagId] = name;
|
|
16
|
+
}
|
|
17
|
+
return result;
|
|
18
|
+
}, {});
|
|
19
|
+
const hasTagCategory = (filters) => (filters?.categories ?? []).some((category) => category.field === 'tag');
|
|
20
|
+
export const fetchCompanyTaskManagerViewEpic = (actions$, state$, zeniAPI) => actions$.pipe(filter(fetchCompanyTaskManagerView.match), switchMap((action) => {
|
|
10
21
|
const { from: fromOffset, searchString, sortKey, sortOrder, filters, } = action.payload;
|
|
11
22
|
const queryValue = {
|
|
12
23
|
size: DEFAULT_PAGE_SIZE,
|
|
13
24
|
from: fromOffset,
|
|
14
25
|
global_search: searchString ?? '',
|
|
26
|
+
// TasksEsSearch defaults this to true, which AND-injects an
|
|
27
|
+
// `assignees = <caller>` filter. Cockpit's task list is a cross-tenant
|
|
28
|
+
// view grouped by company (and offers an Assignee filter), so it must
|
|
29
|
+
// NOT be scoped to the operator — otherwise every category filter
|
|
30
|
+
// AND's down to their own tasks and returns nothing. The metrics panel
|
|
31
|
+
// deliberately passes `true`; this list deliberately passes `false`.
|
|
32
|
+
is_filter_by_logged_in_user: false,
|
|
15
33
|
sort_by: toSortKeyPayload(sortKey),
|
|
16
34
|
sort_order: getSortOrder(sortOrder),
|
|
17
35
|
filter_join: filters?.categoryCombinationOperator === 'AND' ? 'and' : 'or',
|
|
18
36
|
...(filters?.categories != null && filters.categories.length > 0
|
|
19
|
-
? {
|
|
37
|
+
? {
|
|
38
|
+
// Only walk the tag map when a tag filter is actually in play;
|
|
39
|
+
// otherwise every dispatch pays for a map nothing reads.
|
|
40
|
+
filter_by: toFilterByPayload(filters, hasTagCategory(filters) ? toTagNameByID(state$.value) : {}),
|
|
41
|
+
}
|
|
20
42
|
: {}),
|
|
21
43
|
task_group_scopes: filters?.taskGroupScopes != null && filters.taskGroupScopes.length > 0
|
|
22
44
|
? filters.taskGroupScopes
|
|
@@ -63,14 +85,123 @@ const toSortKeyPayload = (sortKey) => {
|
|
|
63
85
|
return sortKey;
|
|
64
86
|
}
|
|
65
87
|
};
|
|
66
|
-
|
|
88
|
+
// Cockpit filter-category keys are UI identifiers; the ES index uses its own
|
|
89
|
+
// field names (see TasksEsSearch.get). Anything not listed here already matches
|
|
90
|
+
// the contract (assignees, priority, status, company_id).
|
|
91
|
+
const ES_FIELD_BY_CATEGORY = {
|
|
92
|
+
creationDate: 'create_time',
|
|
93
|
+
dueDate: 'due_date',
|
|
94
|
+
tag: 'tags',
|
|
95
|
+
};
|
|
96
|
+
// ES rejects `is` / `is_not` on date fields — they only accept `between`, whose
|
|
97
|
+
// values are the [start, end] pair the dateRange picker already emits.
|
|
98
|
+
const ES_DATE_FIELDS = new Set(['create_time', 'due_date']);
|
|
99
|
+
// The cockpit date picker hands over ZeniDate objects; once filters have round-
|
|
100
|
+
// tripped through redux they can arrive as ISO or date-only strings instead.
|
|
101
|
+
// Both have to reach ES as instants: `create_time`/`update_time` carry a real
|
|
102
|
+
// timestamp, so a date-only upper bound lands on midnight and drops everything
|
|
103
|
+
// created later that day — a single-day Created filter would return almost
|
|
104
|
+
// nothing, which is the empty state this epic exists to fix.
|
|
105
|
+
// A real check rather than `value as ZeniDate`: the cast would silently lie
|
|
106
|
+
// about a raw Date, a number, or anything else redux hands back, leaving the
|
|
107
|
+
// runtime guard as the only thing standing between us and a crash.
|
|
108
|
+
const isZeniDateLike = (value) => value != null &&
|
|
109
|
+
typeof value.isValid === 'function' &&
|
|
110
|
+
typeof value.format === 'function';
|
|
111
|
+
const CALENDAR_DATE_ONLY = /^\d{4}-\d{2}-\d{2}$/;
|
|
112
|
+
const toDateBound = (value, edge) => {
|
|
113
|
+
// A bare `YYYY-MM-DD` carries no instant to misread — use it verbatim. This
|
|
114
|
+
// is the only genuinely timezone-proof shape, which is why it is worth a
|
|
115
|
+
// fast path of its own.
|
|
116
|
+
if (typeof value === 'string' && CALENDAR_DATE_ONLY.test(value)) {
|
|
117
|
+
return edge === 'start'
|
|
118
|
+
? `${value}T00:00:00.000Z`
|
|
119
|
+
: `${value}T23:59:59.999Z`;
|
|
120
|
+
}
|
|
121
|
+
// Everything else came from the picker, and the picker emits LOCAL midnight:
|
|
122
|
+
// `ZeniDatePicker` hands react-datepicker's local-midnight Date to
|
|
123
|
+
// `zeniDate(date.toISOString())`. So the instant encodes "midnight on the day
|
|
124
|
+
// the user clicked, in the user's zone" — and the day they clicked is
|
|
125
|
+
// recovered by reading it locally, never in UTC.
|
|
126
|
+
//
|
|
127
|
+
// Reading it in UTC subtracts the offset for every UTC+ operator: clicking
|
|
128
|
+
// "Mar 4" in Asia/Kolkata stores 2026-03-03T18:30:00Z, which is the 3rd in
|
|
129
|
+
// UTC. A single-day filter then returns the wrong day's tasks rather than
|
|
130
|
+
// none, and US-based testing never sees it.
|
|
131
|
+
const parsed = typeof value === 'string' ? toZeniDate(value) : value;
|
|
132
|
+
if (!isZeniDateLike(parsed) || !parsed.isValid()) {
|
|
133
|
+
// Drop the row rather than send garbage: ES rejects the whole request on
|
|
134
|
+
// one bad bound, taking the other filters down with it.
|
|
135
|
+
return '';
|
|
136
|
+
}
|
|
137
|
+
const ymd = parsed.format('YYYY-MM-DD');
|
|
138
|
+
return edge === 'start' ? `${ymd}T00:00:00.000Z` : `${ymd}T23:59:59.999Z`;
|
|
139
|
+
};
|
|
140
|
+
const toFilterByPayload = (filters, tagNameByID) => {
|
|
67
141
|
if (filters.categories == null) {
|
|
68
142
|
return [];
|
|
69
143
|
}
|
|
70
|
-
return filters.categories.
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
144
|
+
return filters.categories.flatMap((category) => {
|
|
145
|
+
const categoryField = category.field ?? '';
|
|
146
|
+
const field = ES_FIELD_BY_CATEGORY[categoryField] ?? categoryField;
|
|
147
|
+
// The dropdown is keyed by tagId, but ES matches `tags` on the tag NAME,
|
|
148
|
+
// so resolve through the tag entity this epic itself populates. Unknown ids
|
|
149
|
+
// fall through unchanged rather than being dropped.
|
|
150
|
+
const isDateField = ES_DATE_FIELDS.has(field);
|
|
151
|
+
// `between` is exactly [from, to]. A half-filled picker (one value) makes ES
|
|
152
|
+
// reject the query outright, and a longer array would quietly bind extras to
|
|
153
|
+
// `end` — both land the user back on an unexplained empty page, which is the
|
|
154
|
+
// failure this epic exists to remove. Drop the row instead.
|
|
155
|
+
if (isDateField && category.values.length !== 2) {
|
|
156
|
+
return [];
|
|
157
|
+
}
|
|
158
|
+
const values = category.values.map((value, index) => {
|
|
159
|
+
if (isDateField) {
|
|
160
|
+
// [from, to] — widen the upper bound to the end of its day.
|
|
161
|
+
return toDateBound(value, index === 0 ? 'start' : 'end');
|
|
162
|
+
}
|
|
163
|
+
const raw = String(value);
|
|
164
|
+
if (field !== 'tags') {
|
|
165
|
+
return raw;
|
|
166
|
+
}
|
|
167
|
+
// An id we cannot resolve would reach ES verbatim and match nothing —
|
|
168
|
+
// another silent empty page. Can happen when a filter is hydrated from the
|
|
169
|
+
// URL before `updateTags` has populated `tagByID`, so keep the value
|
|
170
|
+
// (dropping it would widen the result set) but make it visible in logs.
|
|
171
|
+
const tagName = tagNameByID[raw];
|
|
172
|
+
if (tagName == null) {
|
|
173
|
+
console.debug(`[taskManager] unresolved tagId "${raw}" sent to ES verbatim; expect no matches`);
|
|
174
|
+
}
|
|
175
|
+
return tagName ?? raw;
|
|
176
|
+
});
|
|
177
|
+
// `toDateBound` returns '' for a value it cannot parse. Honour that here:
|
|
178
|
+
// emitting a `between` with an empty bound fails the whole ES query, which
|
|
179
|
+
// takes every OTHER filter in the same request down with it — the silent
|
|
180
|
+
// empty page this epic exists to remove, from one unparseable value that a
|
|
181
|
+
// URL-hydrated filter can supply.
|
|
182
|
+
if (isDateField && values.some((value) => value === '')) {
|
|
183
|
+
return [];
|
|
184
|
+
}
|
|
185
|
+
// ES has no date-exclusion operator: `is`/`is_not` are rejected on date
|
|
186
|
+
// fields, and `between` can only select a range, never exclude one. The
|
|
187
|
+
// operator dropdown still offers "is not" for every category, so an excluded
|
|
188
|
+
// date range would otherwise be sent as a plain `between` — returning exactly
|
|
189
|
+
// the rows the user asked to hide. Drop the row instead: a superset is
|
|
190
|
+
// wrong-but-obvious, an inverted result is wrong-and-invisible.
|
|
191
|
+
if (isDateField && category.matchingOperator !== 'equal') {
|
|
192
|
+
return [];
|
|
193
|
+
}
|
|
194
|
+
return [
|
|
195
|
+
{
|
|
196
|
+
field,
|
|
197
|
+
operator: isDateField
|
|
198
|
+
? 'between'
|
|
199
|
+
: category.matchingOperator === 'equal'
|
|
200
|
+
? 'is'
|
|
201
|
+
: 'is_not',
|
|
202
|
+
values,
|
|
203
|
+
join: category.valuesCombinationOperator === 'ALL' ? 'and' : 'or',
|
|
204
|
+
},
|
|
205
|
+
];
|
|
206
|
+
});
|
|
76
207
|
};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { of } from 'rxjs';
|
|
2
|
+
import { catchError, filter, mergeMap, switchMap } from 'rxjs/operators';
|
|
3
|
+
import { updateReconciliationReport } from '../../../entity/reconciliationReport/reconciliationReportReducer';
|
|
4
|
+
import { getReconciliationReportByReconciliationId } from '../../../entity/reconciliationReport/reconciliationReportSelector';
|
|
5
|
+
import { createZeniAPIStatus, isSuccessResponse } from '../../../responsePayload';
|
|
6
|
+
import { fetchReconciliationReport, fetchReconciliationReportFailure, fetchReconciliationReportSuccess, } from '../reconciliationReportViewReducer';
|
|
7
|
+
export const fetchReconciliationReportEpic = (actions$, state$, zeniAPI) => actions$.pipe(filter(fetchReconciliationReport.match), switchMap((action) => {
|
|
8
|
+
const { reconciliationId, cacheOverride } = action.payload;
|
|
9
|
+
const cachedReport = getReconciliationReportByReconciliationId(state$.value.reconciliationReportState, reconciliationId);
|
|
10
|
+
if (cacheOverride === true || cachedReport == null) {
|
|
11
|
+
return zeniAPI
|
|
12
|
+
.getJSON(`${zeniAPI.apiEndPoints.reconciliationMicroServiceBaseUrl}/2.0/reconciliation/${reconciliationId}/report`)
|
|
13
|
+
.pipe(mergeMap((response) => {
|
|
14
|
+
if (isSuccessResponse(response) === true &&
|
|
15
|
+
response.data != null) {
|
|
16
|
+
return of(updateReconciliationReport(response.data), fetchReconciliationReportSuccess(reconciliationId));
|
|
17
|
+
}
|
|
18
|
+
return of(fetchReconciliationReportFailure({
|
|
19
|
+
reconciliationId,
|
|
20
|
+
status: response.status,
|
|
21
|
+
}));
|
|
22
|
+
}), catchError((error) => of(fetchReconciliationReportFailure({
|
|
23
|
+
reconciliationId,
|
|
24
|
+
status: createZeniAPIStatus('Unexpected Error', 'Fetch Reconciliation Report REST API call errored out' +
|
|
25
|
+
JSON.stringify(error)),
|
|
26
|
+
}))));
|
|
27
|
+
}
|
|
28
|
+
return of(fetchReconciliationReportSuccess(reconciliationId));
|
|
29
|
+
}));
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { createSlice } from '@reduxjs/toolkit';
|
|
2
|
+
import { clearAll } from '../../rootActions';
|
|
3
|
+
export const initialState = {
|
|
4
|
+
fetchReconciliationReportState: {},
|
|
5
|
+
};
|
|
6
|
+
const reconciliationReportView = createSlice({
|
|
7
|
+
name: 'reconciliationReportView',
|
|
8
|
+
initialState,
|
|
9
|
+
reducers: {
|
|
10
|
+
fetchReconciliationReport: {
|
|
11
|
+
prepare(reconciliationId, cacheOverride = false) {
|
|
12
|
+
return { payload: { reconciliationId, cacheOverride } };
|
|
13
|
+
},
|
|
14
|
+
reducer(draft, action) {
|
|
15
|
+
const { reconciliationId } = action.payload;
|
|
16
|
+
draft.fetchReconciliationReportState[reconciliationId] = {
|
|
17
|
+
fetchState: 'In-Progress',
|
|
18
|
+
error: undefined,
|
|
19
|
+
};
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
fetchReconciliationReportSuccess(draft, action) {
|
|
23
|
+
const reconciliationId = action.payload;
|
|
24
|
+
draft.fetchReconciliationReportState[reconciliationId] = {
|
|
25
|
+
fetchState: 'Completed',
|
|
26
|
+
error: undefined,
|
|
27
|
+
};
|
|
28
|
+
},
|
|
29
|
+
fetchReconciliationReportFailure(draft, action) {
|
|
30
|
+
const { reconciliationId, status } = action.payload;
|
|
31
|
+
draft.fetchReconciliationReportState[reconciliationId] = {
|
|
32
|
+
fetchState: 'Error',
|
|
33
|
+
error: status,
|
|
34
|
+
};
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
extraReducers: (builder) => {
|
|
38
|
+
builder.addCase(clearAll, (draft) => {
|
|
39
|
+
Object.assign(draft, initialState);
|
|
40
|
+
});
|
|
41
|
+
},
|
|
42
|
+
});
|
|
43
|
+
export const { fetchReconciliationReport, fetchReconciliationReportSuccess, fetchReconciliationReportFailure, } = reconciliationReportView.actions;
|
|
44
|
+
export default reconciliationReportView.reducer;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { getReconciliationReportByReconciliationId } from '../../entity/reconciliationReport/reconciliationReportSelector';
|
|
2
|
+
export function getReconciliationReport(state, reconciliationId) {
|
|
3
|
+
const fetchReconciliationReportState = state.reconciliationReportViewState.fetchReconciliationReportState[reconciliationId];
|
|
4
|
+
const report = getReconciliationReportByReconciliationId(state.reconciliationReportState, reconciliationId);
|
|
5
|
+
return {
|
|
6
|
+
fetchState: fetchReconciliationReportState?.fetchState ?? 'Not-Started',
|
|
7
|
+
fetchError: fetchReconciliationReportState?.error,
|
|
8
|
+
report,
|
|
9
|
+
};
|
|
10
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|