@zeniai/client-epic-state 5.2.22-betaAM4 → 5.2.22-betaAM5
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/actualMatching/actualMatchingPayload.d.ts +25 -0
- package/lib/entity/actualMatching/actualMatchingPayload.js +42 -0
- package/lib/entity/actualMatching/actualMatchingReducer.d.ts +8 -0
- package/lib/entity/actualMatching/actualMatchingReducer.js +33 -0
- package/lib/entity/actualMatching/actualMatchingSelector.d.ts +3 -0
- package/lib/entity/actualMatching/actualMatchingSelector.js +6 -0
- package/lib/entity/actualMatching/actualMatchingState.d.ts +22 -0
- package/lib/entity/actualMatching/actualMatchingState.js +2 -0
- package/lib/entity/actualMatching/actualMatchingTypes.d.ts +1 -0
- package/lib/entity/actualMatching/actualMatchingTypes.js +2 -0
- package/lib/epic.d.ts +2 -1
- package/lib/epic.js +2 -0
- package/lib/esm/entity/actualMatching/actualMatchingPayload.js +39 -0
- package/lib/esm/entity/actualMatching/actualMatchingReducer.js +30 -0
- package/lib/esm/entity/actualMatching/actualMatchingSelector.js +3 -0
- package/lib/esm/entity/actualMatching/actualMatchingState.js +1 -0
- package/lib/esm/entity/actualMatching/actualMatchingTypes.js +1 -0
- package/lib/esm/epic.js +2 -0
- package/lib/esm/index.js +3 -3
- package/lib/esm/reducer.js +3 -0
- package/lib/esm/view/expenseAutomationView/epics/actualMatching/fetchActualMatchingEpic.js +6 -6
- package/lib/esm/view/expenseAutomationView/epics/actualMatching/fetchActualMatchingMatchEpic.js +35 -0
- package/lib/esm/view/expenseAutomationView/epics/actualMatching/searchMatchTransactionsEpic.js +35 -6
- package/lib/esm/view/expenseAutomationView/epics/common/fetchAllExpenseAutomationTabsEpic.js +1 -1
- package/lib/esm/view/expenseAutomationView/reducers/actualMatchingViewReducer.js +87 -8
- package/lib/esm/view/expenseAutomationView/selectors/actualMatchingViewSelector.js +143 -98
- package/lib/esm/view/expenseAutomationView/types/actualMatchingViewState.js +4 -0
- package/lib/index.d.ts +6 -3
- package/lib/index.js +21 -18
- package/lib/reducer.d.ts +1 -0
- package/lib/reducer.js +3 -0
- package/lib/rootStateTypes.d.ts +2 -0
- package/lib/view/expenseAutomationView/epics/actualMatching/fetchActualMatchingEpic.d.ts +2 -2
- package/lib/view/expenseAutomationView/epics/actualMatching/fetchActualMatchingEpic.js +6 -6
- package/lib/view/expenseAutomationView/epics/actualMatching/fetchActualMatchingMatchEpic.d.ts +12 -0
- package/lib/view/expenseAutomationView/epics/actualMatching/fetchActualMatchingMatchEpic.js +39 -0
- package/lib/view/expenseAutomationView/epics/actualMatching/searchMatchTransactionsEpic.d.ts +1 -1
- package/lib/view/expenseAutomationView/epics/actualMatching/searchMatchTransactionsEpic.js +35 -6
- package/lib/view/expenseAutomationView/epics/common/fetchAllExpenseAutomationTabsEpic.js +1 -1
- package/lib/view/expenseAutomationView/payload/actualMatchingPayload.d.ts +3 -6
- package/lib/view/expenseAutomationView/reducers/actualMatchingViewReducer.d.ts +20 -3
- package/lib/view/expenseAutomationView/reducers/actualMatchingViewReducer.js +88 -9
- package/lib/view/expenseAutomationView/selectorTypes/actualMatchingViewSelectorTypes.d.ts +15 -2
- package/lib/view/expenseAutomationView/selectors/actualMatchingViewSelector.d.ts +16 -2
- package/lib/view/expenseAutomationView/selectors/actualMatchingViewSelector.js +146 -98
- package/lib/view/expenseAutomationView/types/actualMatchingViewState.d.ts +7 -2
- package/lib/view/expenseAutomationView/types/actualMatchingViewState.js +4 -0
- package/package.json +1 -1
|
@@ -20,18 +20,22 @@ export const initialAccrualSearchState = {
|
|
|
20
20
|
};
|
|
21
21
|
export const initialMatchModalState = {
|
|
22
22
|
isOpen: false,
|
|
23
|
+
openedFromMatchId: undefined,
|
|
24
|
+
pinnedTransactionResults: [],
|
|
23
25
|
transactionSearch: initialTransactionSearchState,
|
|
24
26
|
accrualSearch: initialAccrualSearchState,
|
|
25
27
|
confirmStatus: { fetchState: 'Not-Started', error: undefined },
|
|
26
28
|
};
|
|
27
29
|
export const initialState = {
|
|
28
|
-
|
|
30
|
+
matchIdsByPeriod: {},
|
|
29
31
|
fetchState: 'Not-Started',
|
|
30
32
|
error: undefined,
|
|
31
33
|
refreshStatus: {
|
|
32
34
|
fetchState: 'Not-Started',
|
|
33
35
|
error: undefined,
|
|
34
36
|
},
|
|
37
|
+
detailFetchStateByMatchId: {},
|
|
38
|
+
detailRefreshStatusByMatchId: {},
|
|
35
39
|
uiState: {
|
|
36
40
|
sortKey: 'date',
|
|
37
41
|
sortOrder: 'descending',
|
|
@@ -51,6 +55,8 @@ function resetMatchModalSearches(draft) {
|
|
|
51
55
|
error: undefined,
|
|
52
56
|
};
|
|
53
57
|
draft.matchModal.lastBatchResults = undefined;
|
|
58
|
+
draft.matchModal.openedFromMatchId = undefined;
|
|
59
|
+
draft.matchModal.pinnedTransactionResults = [];
|
|
54
60
|
}
|
|
55
61
|
const expenseAutomationActualMatchingView = createSlice({
|
|
56
62
|
name: 'expenseAutomationActualMatchingView',
|
|
@@ -90,9 +96,9 @@ const expenseAutomationActualMatchingView = createSlice({
|
|
|
90
96
|
},
|
|
91
97
|
},
|
|
92
98
|
fetchActualMatchingSuccess(draft, action) {
|
|
93
|
-
const {
|
|
99
|
+
const { matchIds, selectedPeriod, refreshViewInBackground } = action.payload;
|
|
94
100
|
const periodId = toMonthYearPeriodId(selectedPeriod);
|
|
95
|
-
draft.
|
|
101
|
+
draft.matchIdsByPeriod[periodId] = matchIds;
|
|
96
102
|
if (refreshViewInBackground) {
|
|
97
103
|
draft.refreshStatus = { fetchState: 'Completed', error: undefined };
|
|
98
104
|
}
|
|
@@ -111,6 +117,56 @@ const expenseAutomationActualMatchingView = createSlice({
|
|
|
111
117
|
draft.error = status;
|
|
112
118
|
}
|
|
113
119
|
},
|
|
120
|
+
fetchActualMatchingMatch: {
|
|
121
|
+
prepare(matchId, refreshViewInBackground = false) {
|
|
122
|
+
return { payload: { matchId, refreshViewInBackground } };
|
|
123
|
+
},
|
|
124
|
+
reducer(draft, action) {
|
|
125
|
+
const { matchId, refreshViewInBackground } = action.payload;
|
|
126
|
+
if (refreshViewInBackground) {
|
|
127
|
+
draft.detailRefreshStatusByMatchId[matchId] = {
|
|
128
|
+
fetchState: 'In-Progress',
|
|
129
|
+
error: undefined,
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
else {
|
|
133
|
+
draft.detailFetchStateByMatchId[matchId] = {
|
|
134
|
+
fetchState: 'In-Progress',
|
|
135
|
+
error: undefined,
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
},
|
|
139
|
+
},
|
|
140
|
+
fetchActualMatchingMatchSuccess(draft, action) {
|
|
141
|
+
const { matchId, refreshViewInBackground } = action.payload;
|
|
142
|
+
if (refreshViewInBackground) {
|
|
143
|
+
draft.detailRefreshStatusByMatchId[matchId] = {
|
|
144
|
+
fetchState: 'Completed',
|
|
145
|
+
error: undefined,
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
else {
|
|
149
|
+
draft.detailFetchStateByMatchId[matchId] = {
|
|
150
|
+
fetchState: 'Completed',
|
|
151
|
+
error: undefined,
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
},
|
|
155
|
+
fetchActualMatchingMatchFailure(draft, action) {
|
|
156
|
+
const { matchId, refreshViewInBackground, status } = action.payload;
|
|
157
|
+
if (refreshViewInBackground) {
|
|
158
|
+
draft.detailRefreshStatusByMatchId[matchId] = {
|
|
159
|
+
fetchState: 'Error',
|
|
160
|
+
error: status,
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
else {
|
|
164
|
+
draft.detailFetchStateByMatchId[matchId] = {
|
|
165
|
+
fetchState: 'Error',
|
|
166
|
+
error: status,
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
},
|
|
114
170
|
updateActualMatchingUIState(draft, action) {
|
|
115
171
|
if (action.payload.sortKey != null) {
|
|
116
172
|
draft.uiState.sortKey = action.payload.sortKey;
|
|
@@ -125,8 +181,20 @@ const expenseAutomationActualMatchingView = createSlice({
|
|
|
125
181
|
draft.uiState.scrollPosition = action.payload.scrollPosition;
|
|
126
182
|
}
|
|
127
183
|
},
|
|
128
|
-
openMatchNewModal
|
|
129
|
-
|
|
184
|
+
openMatchNewModal: {
|
|
185
|
+
prepare(matchId) {
|
|
186
|
+
return { payload: { matchId } };
|
|
187
|
+
},
|
|
188
|
+
reducer(draft, action) {
|
|
189
|
+
resetMatchModalSearches(draft);
|
|
190
|
+
draft.matchModal.isOpen = true;
|
|
191
|
+
const matchId = action.payload.matchId;
|
|
192
|
+
draft.matchModal.openedFromMatchId =
|
|
193
|
+
matchId != null && matchId !== '' ? matchId : undefined;
|
|
194
|
+
if (draft.matchModal.openedFromMatchId != null) {
|
|
195
|
+
draft.matchModal.accrualSearch.fetchState = 'Completed';
|
|
196
|
+
}
|
|
197
|
+
},
|
|
130
198
|
},
|
|
131
199
|
closeMatchNewModal(draft) {
|
|
132
200
|
draft.matchModal.isOpen = false;
|
|
@@ -152,8 +220,15 @@ const expenseAutomationActualMatchingView = createSlice({
|
|
|
152
220
|
draft.matchModal.transactionSearch.error = undefined;
|
|
153
221
|
}
|
|
154
222
|
},
|
|
155
|
-
prepare({ query, pageToken }) {
|
|
156
|
-
return {
|
|
223
|
+
prepare({ query, pageToken, transactionType, transactionIntegrationId, }) {
|
|
224
|
+
return {
|
|
225
|
+
payload: {
|
|
226
|
+
query,
|
|
227
|
+
pageToken: pageToken ?? undefined,
|
|
228
|
+
transactionType,
|
|
229
|
+
transactionIntegrationId,
|
|
230
|
+
},
|
|
231
|
+
};
|
|
157
232
|
},
|
|
158
233
|
},
|
|
159
234
|
searchMatchTransactionsSuccess(draft, action) {
|
|
@@ -171,6 +246,10 @@ const expenseAutomationActualMatchingView = createSlice({
|
|
|
171
246
|
}
|
|
172
247
|
else {
|
|
173
248
|
draft.matchModal.transactionSearch.results = results;
|
|
249
|
+
if (draft.matchModal.openedFromMatchId != null &&
|
|
250
|
+
draft.matchModal.pinnedTransactionResults.length === 0) {
|
|
251
|
+
draft.matchModal.pinnedTransactionResults = results;
|
|
252
|
+
}
|
|
174
253
|
}
|
|
175
254
|
draft.matchModal.transactionSearch.nextPageToken = nextPageToken;
|
|
176
255
|
draft.matchModal.transactionSearch.isLoadingMore = false;
|
|
@@ -256,5 +335,5 @@ const expenseAutomationActualMatchingView = createSlice({
|
|
|
256
335
|
});
|
|
257
336
|
},
|
|
258
337
|
});
|
|
259
|
-
export const { clearActualMatchingView, clearMatchNewModal, closeMatchNewModal, fetchActualMatching, fetchActualMatchingFailure, fetchActualMatchingPage, fetchActualMatchingSuccess, matchAndReverseAccruals, matchAndReverseAccrualsFailure, matchAndReverseAccrualsSuccess, openMatchNewModal, searchMatchAccruals, searchMatchAccrualsFailure, searchMatchAccrualsSuccess, searchMatchTransactions, searchMatchTransactionsFailure, searchMatchTransactionsSuccess, updateActualMatchingUIState, } = expenseAutomationActualMatchingView.actions;
|
|
338
|
+
export const { clearActualMatchingView, clearMatchNewModal, closeMatchNewModal, fetchActualMatching, fetchActualMatchingFailure, fetchActualMatchingMatch, fetchActualMatchingMatchFailure, fetchActualMatchingMatchSuccess, fetchActualMatchingPage, fetchActualMatchingSuccess, matchAndReverseAccruals, matchAndReverseAccrualsFailure, matchAndReverseAccrualsSuccess, openMatchNewModal, searchMatchAccruals, searchMatchAccrualsFailure, searchMatchAccrualsSuccess, searchMatchTransactions, searchMatchTransactionsFailure, searchMatchTransactionsSuccess, updateActualMatchingUIState, } = expenseAutomationActualMatchingView.actions;
|
|
260
339
|
export default expenseAutomationActualMatchingView.reducer;
|
|
@@ -1,7 +1,53 @@
|
|
|
1
1
|
import orderBy from 'lodash/orderBy';
|
|
2
2
|
import { toMonthYearPeriodId } from '../../../commonStateTypes/timePeriod';
|
|
3
|
+
import { getActualMatchingMatchById } from '../../../entity/actualMatching/actualMatchingSelector';
|
|
4
|
+
import { generateJEOneTimeAccrualKey } from '../../../entity/jeSchedules/jeScheduleHelper';
|
|
3
5
|
import { getJEOneTimeAccrualByKey, } from '../../../entity/jeSchedules/jeSchedulesSelector';
|
|
4
6
|
import { getCurrentTenant } from '../../../entity/tenant/tenantSelector';
|
|
7
|
+
function toMatchModalAccrual(member) {
|
|
8
|
+
if ('jeOneTimeAccrualKey' in member && member.jeOneTimeAccrualKey != null) {
|
|
9
|
+
return member;
|
|
10
|
+
}
|
|
11
|
+
return {
|
|
12
|
+
...member,
|
|
13
|
+
jeOneTimeAccrualKey: generateJEOneTimeAccrualKey(member.accrualId),
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
function uniqueMatchModalAccruals(pinned, searched) {
|
|
17
|
+
const byId = new Map();
|
|
18
|
+
pinned.forEach((row) => byId.set(row.accrualId, row));
|
|
19
|
+
searched.forEach((row) => {
|
|
20
|
+
if (!byId.has(row.accrualId)) {
|
|
21
|
+
byId.set(row.accrualId, row);
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
return Array.from(byId.values());
|
|
25
|
+
}
|
|
26
|
+
function uniqueTransactionSearchResults(pinned, searched) {
|
|
27
|
+
const byKey = new Map();
|
|
28
|
+
pinned.forEach((row) => byKey.set(`${row.transactionId}:${row.lineId}`, row));
|
|
29
|
+
searched.forEach((row) => {
|
|
30
|
+
const key = `${row.transactionId}:${row.lineId}`;
|
|
31
|
+
if (!byKey.has(key)) {
|
|
32
|
+
byKey.set(key, row);
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
return Array.from(byKey.values());
|
|
36
|
+
}
|
|
37
|
+
export function parseActualMatchingMatchId(matchId) {
|
|
38
|
+
const separator = matchId.indexOf(':');
|
|
39
|
+
if (separator <= 0 || separator === matchId.length - 1) {
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
return {
|
|
43
|
+
transactionType: matchId.slice(0, separator).toLowerCase(),
|
|
44
|
+
transactionIntegrationId: matchId.slice(separator + 1),
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
const NOT_STARTED = {
|
|
48
|
+
fetchState: 'Not-Started',
|
|
49
|
+
error: undefined,
|
|
50
|
+
};
|
|
5
51
|
export function isAutoReversedAccrual(accrual) {
|
|
6
52
|
return (accrual.accrualStatus === 'reversed' &&
|
|
7
53
|
accrual.reversalTrigger === 'bill_match');
|
|
@@ -17,18 +63,14 @@ export function isPendingReviewAccrual(accrual) {
|
|
|
17
63
|
const resolution = accrual.matchSuggestion.resolution;
|
|
18
64
|
return resolution == null || resolution.length === 0;
|
|
19
65
|
}
|
|
66
|
+
export function isReversedMatchKind(kind) {
|
|
67
|
+
return kind === 'auto_reversed' || kind === 'manually_reversed';
|
|
68
|
+
}
|
|
20
69
|
export function getClearedMatchedAmount(accrual) {
|
|
21
70
|
return accrual.cleared?.matchedAmount?.amount;
|
|
22
71
|
}
|
|
23
|
-
export function getActualMatchingAmount(
|
|
24
|
-
|
|
25
|
-
return (accrual.matchSuggestion?.matchedAmount?.amount ??
|
|
26
|
-
accrual.estimatedAmount.amount);
|
|
27
|
-
}
|
|
28
|
-
if (isAutoReversedAccrual(accrual) || isManuallyReversedAccrual(accrual)) {
|
|
29
|
-
return getClearedMatchedAmount(accrual) ?? accrual.estimatedAmount.amount;
|
|
30
|
-
}
|
|
31
|
-
return accrual.estimatedAmount.amount;
|
|
72
|
+
export function getActualMatchingAmount(row) {
|
|
73
|
+
return row.actualAmount?.amount ?? row.estimatedAmount.amount;
|
|
32
74
|
}
|
|
33
75
|
export function getActualMatchingReversalDate(accrual) {
|
|
34
76
|
if (isPendingReviewAccrual(accrual)) {
|
|
@@ -36,40 +78,6 @@ export function getActualMatchingReversalDate(accrual) {
|
|
|
36
78
|
}
|
|
37
79
|
return accrual.cleared?.matchedTransactionDate;
|
|
38
80
|
}
|
|
39
|
-
function getActualMatchingBillCollapseKey(accrual) {
|
|
40
|
-
const stamp = isPendingReviewAccrual(accrual)
|
|
41
|
-
? accrual.matchSuggestion
|
|
42
|
-
: accrual.cleared;
|
|
43
|
-
const txnId = stamp?.matchedTransactionId;
|
|
44
|
-
if (txnId != null && txnId !== '') {
|
|
45
|
-
return `txn:${txnId}`;
|
|
46
|
-
}
|
|
47
|
-
const integrationId = stamp?.matchedTransactionIntegrationId;
|
|
48
|
-
if (integrationId != null && integrationId !== '') {
|
|
49
|
-
return `int:${integrationId}`;
|
|
50
|
-
}
|
|
51
|
-
const ids = accrual.cleared?.accrualIds;
|
|
52
|
-
if (ids != null && ids.length > 1) {
|
|
53
|
-
return `cleared:${[...ids].sort().join(',')}`;
|
|
54
|
-
}
|
|
55
|
-
return `accrual:${accrual.accrualId}`;
|
|
56
|
-
}
|
|
57
|
-
function collectGroupedAccrualIds(members) {
|
|
58
|
-
const stampIds = members[0]?.cleared?.accrualIds;
|
|
59
|
-
const memberIds = members.map((member) => member.accrualId);
|
|
60
|
-
if (stampIds != null && stampIds.length >= memberIds.length) {
|
|
61
|
-
return stampIds;
|
|
62
|
-
}
|
|
63
|
-
const seen = new Set();
|
|
64
|
-
const grouped = [];
|
|
65
|
-
for (const id of [...(stampIds ?? []), ...memberIds]) {
|
|
66
|
-
if (!seen.has(id)) {
|
|
67
|
-
seen.add(id);
|
|
68
|
-
grouped.push(id);
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
return grouped;
|
|
72
|
-
}
|
|
73
81
|
function collectGroupedMembers(members) {
|
|
74
82
|
if (members.length <= 1) {
|
|
75
83
|
return undefined;
|
|
@@ -82,51 +90,48 @@ function collectGroupedMembers(members) {
|
|
|
82
90
|
serviceMonth: member.serviceMonth,
|
|
83
91
|
}));
|
|
84
92
|
}
|
|
85
|
-
function toActualMatchingRow(
|
|
86
|
-
const
|
|
93
|
+
function toActualMatchingRow(match) {
|
|
94
|
+
const firstMember = match.members[0];
|
|
95
|
+
if (firstMember == null) {
|
|
96
|
+
throw new Error('Actual matching row requires at least one member');
|
|
97
|
+
}
|
|
98
|
+
const first = toMatchModalAccrual(firstMember);
|
|
87
99
|
return {
|
|
88
|
-
...
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
100
|
+
...first,
|
|
101
|
+
matchId: match.matchId,
|
|
102
|
+
kind: match.kind,
|
|
103
|
+
accruedAmount: match.accruedAmount,
|
|
104
|
+
actualAmount: match.actualAmount,
|
|
105
|
+
matchTier: match.matchTier,
|
|
106
|
+
matchShape: match.matchShape,
|
|
107
|
+
transactionType: match.transactionType,
|
|
108
|
+
transactionDate: match.transactionDate,
|
|
109
|
+
groupedAccrualIds: match.members.map((member) => member.accrualId),
|
|
110
|
+
groupedMembers: collectGroupedMembers(match.members),
|
|
111
|
+
reversalDate: getActualMatchingReversalDate(first),
|
|
112
|
+
vendorName: match.vendorName !== '' ? match.vendorName : first.vendorName,
|
|
113
|
+
estimatedAmount: match.accruedAmount,
|
|
93
114
|
};
|
|
94
115
|
}
|
|
95
|
-
function
|
|
96
|
-
const groups = new Map();
|
|
97
|
-
for (const accrual of accruals) {
|
|
98
|
-
const key = getActualMatchingBillCollapseKey(accrual);
|
|
99
|
-
const members = groups.get(key);
|
|
100
|
-
if (members != null) {
|
|
101
|
-
members.push(accrual);
|
|
102
|
-
}
|
|
103
|
-
else {
|
|
104
|
-
groups.set(key, [accrual]);
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
const rows = [];
|
|
108
|
-
for (const members of groups.values()) {
|
|
109
|
-
rows.push(toActualMatchingRow(members, kind));
|
|
110
|
-
}
|
|
111
|
-
return rows;
|
|
112
|
-
}
|
|
113
|
-
function sumCollapsedActualMatchingAmounts(rows) {
|
|
114
|
-
return rows.reduce((sum, row) => sum + getActualMatchingAmount(row), 0);
|
|
115
|
-
}
|
|
116
|
-
function matchesSearch(accrual, searchString) {
|
|
116
|
+
function matchesSearch(row, searchString) {
|
|
117
117
|
const trimmed = searchString.trim().toLowerCase();
|
|
118
118
|
if (trimmed.length === 0) {
|
|
119
119
|
return true;
|
|
120
120
|
}
|
|
121
|
-
|
|
122
|
-
|
|
121
|
+
if (row.vendorName.toLowerCase().includes(trimmed)) {
|
|
122
|
+
return true;
|
|
123
|
+
}
|
|
124
|
+
if (row.memo.toLowerCase().includes(trimmed)) {
|
|
125
|
+
return true;
|
|
126
|
+
}
|
|
127
|
+
return (row.groupedMembers ?? []).some((member) => (member.memo ?? '').toLowerCase().includes(trimmed));
|
|
123
128
|
}
|
|
124
129
|
function getActualMatchingSortValue(row, sortKey) {
|
|
125
130
|
switch (sortKey) {
|
|
126
131
|
case 'vendor':
|
|
127
132
|
return row.vendorName.toLowerCase();
|
|
128
133
|
case 'date':
|
|
129
|
-
return row.reversalDate?.valueOf();
|
|
134
|
+
return row.reversalDate?.valueOf() ?? row.transactionDate;
|
|
130
135
|
case 'amount':
|
|
131
136
|
return getActualMatchingAmount(row);
|
|
132
137
|
case 'category':
|
|
@@ -134,10 +139,23 @@ function getActualMatchingSortValue(row, sortKey) {
|
|
|
134
139
|
case 'class':
|
|
135
140
|
return row.jeDebitAccountingClassName?.toLowerCase();
|
|
136
141
|
case 'type':
|
|
137
|
-
return
|
|
138
|
-
row.matchSuggestion?.matchedTransactionType)?.toLowerCase();
|
|
142
|
+
return row.transactionType?.toLowerCase();
|
|
139
143
|
case 'lifecycle':
|
|
140
144
|
return row.kind;
|
|
145
|
+
case 'service':
|
|
146
|
+
return row.serviceMonth;
|
|
147
|
+
case 'accrued':
|
|
148
|
+
return row.accruedAmount?.amount ?? row.estimatedAmount.amount;
|
|
149
|
+
case 'actual':
|
|
150
|
+
return row.actualAmount?.amount;
|
|
151
|
+
case 'variance': {
|
|
152
|
+
const accrued = row.accruedAmount?.amount ?? row.estimatedAmount.amount;
|
|
153
|
+
const actual = row.actualAmount?.amount;
|
|
154
|
+
if (actual == null || accrued === 0) {
|
|
155
|
+
return undefined;
|
|
156
|
+
}
|
|
157
|
+
return ((actual - accrued) / Math.abs(accrued)) * 100;
|
|
158
|
+
}
|
|
141
159
|
default:
|
|
142
160
|
return undefined;
|
|
143
161
|
}
|
|
@@ -155,37 +173,50 @@ function emptyKpiSummary() {
|
|
|
155
173
|
manual: { count: 0 },
|
|
156
174
|
};
|
|
157
175
|
}
|
|
176
|
+
function sumRowAmounts(rows) {
|
|
177
|
+
return rows.reduce((sum, row) => sum + getActualMatchingAmount(row), 0);
|
|
178
|
+
}
|
|
179
|
+
export function getExpenseAutomationActualMatchingMatchView(state, matchId) {
|
|
180
|
+
const view = state.expenseAutomationActualMatchingViewState;
|
|
181
|
+
return {
|
|
182
|
+
match: getActualMatchingMatchById(matchId, state.actualMatchingState),
|
|
183
|
+
detailFetchState: view.detailFetchStateByMatchId[matchId] ?? NOT_STARTED,
|
|
184
|
+
refreshStatus: view.detailRefreshStatusByMatchId[matchId] ?? NOT_STARTED,
|
|
185
|
+
};
|
|
186
|
+
}
|
|
158
187
|
export function getExpenseAutomationActualMatchingView(state) {
|
|
159
188
|
const { expenseAutomationActualMatchingViewState, expenseAutomationViewState } = state;
|
|
160
|
-
const {
|
|
189
|
+
const { matchIdsByPeriod, fetchState, error, refreshStatus, uiState, matchModal, } = expenseAutomationActualMatchingViewState;
|
|
161
190
|
const currentTenant = getCurrentTenant(state);
|
|
162
191
|
const selectedPeriod = expenseAutomationViewState.selectedPeriodByTenantId[currentTenant.tenantId];
|
|
163
192
|
const monthYearPeriodId = selectedPeriod != null ? toMonthYearPeriodId(selectedPeriod) : undefined;
|
|
164
|
-
const
|
|
165
|
-
?
|
|
193
|
+
const matchIds = monthYearPeriodId != null
|
|
194
|
+
? matchIdsByPeriod[monthYearPeriodId]
|
|
166
195
|
: undefined;
|
|
167
|
-
const
|
|
168
|
-
.map((
|
|
169
|
-
.filter((
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
const
|
|
174
|
-
const
|
|
196
|
+
const rows = (matchIds ?? [])
|
|
197
|
+
.map((matchId) => getActualMatchingMatchById(matchId, state.actualMatchingState))
|
|
198
|
+
.filter((match) => match != null)
|
|
199
|
+
.filter((match) => match.members.length > 0)
|
|
200
|
+
.map(toActualMatchingRow)
|
|
201
|
+
.filter((row) => matchesSearch(row, uiState.searchString));
|
|
202
|
+
const reversed = sortActualMatchingRows(rows.filter((row) => isReversedMatchKind(row.kind)), uiState);
|
|
203
|
+
const pendingReview = sortActualMatchingRows(rows.filter((row) => row.kind === 'pending_review'), uiState);
|
|
204
|
+
const autoReversedForKpi = reversed.filter((row) => row.kind === 'auto_reversed');
|
|
205
|
+
const listedRows = [...reversed, ...pendingReview];
|
|
175
206
|
const kpiSummary = listedRows.length === 0
|
|
176
207
|
? emptyKpiSummary()
|
|
177
208
|
: {
|
|
178
209
|
autoReversed: {
|
|
179
|
-
count:
|
|
180
|
-
amount:
|
|
210
|
+
count: autoReversedForKpi.length,
|
|
211
|
+
amount: sumRowAmounts(autoReversedForKpi),
|
|
181
212
|
},
|
|
182
213
|
pendingReview: {
|
|
183
214
|
count: pendingReview.length,
|
|
184
|
-
amount:
|
|
215
|
+
amount: sumRowAmounts(pendingReview),
|
|
185
216
|
},
|
|
186
217
|
totalThisClose: {
|
|
187
218
|
count: listedRows.length,
|
|
188
|
-
amount:
|
|
219
|
+
amount: sumRowAmounts(listedRows),
|
|
189
220
|
},
|
|
190
221
|
ai: {
|
|
191
222
|
count: listedRows.filter((row) => row.origin === 'agent').length,
|
|
@@ -194,26 +225,40 @@ export function getExpenseAutomationActualMatchingView(state) {
|
|
|
194
225
|
count: listedRows.filter((row) => row.origin === 'human').length,
|
|
195
226
|
},
|
|
196
227
|
};
|
|
197
|
-
const
|
|
228
|
+
const searchedAccruals = matchModal.accrualSearch.results
|
|
198
229
|
.map((key) => getJEOneTimeAccrualByKey(key, state.jeSchedulesState))
|
|
199
230
|
.filter((accrual) => accrual != null);
|
|
231
|
+
const openedMatch = matchModal.openedFromMatchId != null
|
|
232
|
+
? getActualMatchingMatchById(matchModal.openedFromMatchId, state.actualMatchingState)
|
|
233
|
+
: undefined;
|
|
234
|
+
const pinnedAccruals = (openedMatch?.members ?? []).map(toMatchModalAccrual);
|
|
235
|
+
const firstSuggestion = openedMatch?.members[0]?.matchSuggestion;
|
|
236
|
+
const prefill = openedMatch == null
|
|
237
|
+
? undefined
|
|
238
|
+
: {
|
|
239
|
+
selectedAccrualIds: openedMatch.members.map((member) => member.accrualId),
|
|
240
|
+
actualAmount: openedMatch.actualAmount.amount,
|
|
241
|
+
matchedLineId: firstSuggestion?.matchedLineId,
|
|
242
|
+
matchedTransactionId: firstSuggestion?.matchedTransactionId,
|
|
243
|
+
};
|
|
200
244
|
return {
|
|
201
245
|
fetchState,
|
|
202
246
|
error,
|
|
203
|
-
|
|
247
|
+
reversed,
|
|
204
248
|
pendingReview,
|
|
205
|
-
manuallyReversed,
|
|
206
249
|
kpiSummary,
|
|
207
250
|
uiState,
|
|
208
251
|
refreshStatus,
|
|
209
|
-
hasLoadedForSelectedPeriod:
|
|
252
|
+
hasLoadedForSelectedPeriod: matchIds != null,
|
|
210
253
|
matchModal: {
|
|
211
254
|
isOpen: matchModal.isOpen,
|
|
255
|
+
openedFromMatchId: matchModal.openedFromMatchId,
|
|
256
|
+
prefill,
|
|
212
257
|
confirmStatus: matchModal.confirmStatus,
|
|
213
258
|
lastBatchResults: matchModal.lastBatchResults,
|
|
214
259
|
transactionSearch: {
|
|
215
260
|
query: matchModal.transactionSearch.query,
|
|
216
|
-
results: matchModal.transactionSearch.results,
|
|
261
|
+
results: uniqueTransactionSearchResults(matchModal.pinnedTransactionResults, matchModal.transactionSearch.results),
|
|
217
262
|
fetchState: {
|
|
218
263
|
fetchState: matchModal.transactionSearch.fetchState,
|
|
219
264
|
error: matchModal.transactionSearch.error,
|
|
@@ -223,7 +268,7 @@ export function getExpenseAutomationActualMatchingView(state) {
|
|
|
223
268
|
},
|
|
224
269
|
accrualSearch: {
|
|
225
270
|
query: matchModal.accrualSearch.query,
|
|
226
|
-
results:
|
|
271
|
+
results: uniqueMatchModalAccruals(pinnedAccruals, searchedAccruals),
|
|
227
272
|
fetchState: {
|
|
228
273
|
fetchState: matchModal.accrualSearch.fetchState,
|
|
229
274
|
error: matchModal.accrualSearch.error,
|
|
@@ -7,6 +7,10 @@ const ACTUAL_MATCHING_SORT_KEYS = [
|
|
|
7
7
|
'class',
|
|
8
8
|
'type',
|
|
9
9
|
'lifecycle',
|
|
10
|
+
'service',
|
|
11
|
+
'accrued',
|
|
12
|
+
'actual',
|
|
13
|
+
'variance',
|
|
10
14
|
];
|
|
11
15
|
export const toActualMatchingSortKey = (v) => stringToUnion(v, ACTUAL_MATCHING_SORT_KEYS);
|
|
12
16
|
export const MATCH_TRANSACTION_SEARCH_PAGE_SIZE = 50;
|
package/lib/index.d.ts
CHANGED
|
@@ -302,7 +302,7 @@ import { computeNewScheduleJeDetails } from './view/expenseAutomationView/helper
|
|
|
302
302
|
import { isReviewTransactionBankTransferType, isReviewTransactionBillPaymentType, isReviewTransactionCreditCardCreditType, isReviewTransactionCreditCardPaymentType, isReviewTransactionDepositType, isReviewTransactionExpenseType } from './view/expenseAutomationView/helpers/reconciliationHelpers';
|
|
303
303
|
import { MAX_SELECTION_LIMIT, checkIfAllLineItemsAreCategoryClassFilled, getLineItemsByTransactionIdsFromLocalData, isAnyItemWithUncategorizedExpenseAccount } from './view/expenseAutomationView/helpers/transactionCategorizationLocalDataHelper';
|
|
304
304
|
import { UploadStatementDocumentAIPayload, UploadStatementDocumentAIResponse } from './view/expenseAutomationView/payload/reconciliationPayload';
|
|
305
|
-
import { clearActualMatchingView as clearExpenseAutomationActualMatchingView, clearMatchNewModal, closeMatchNewModal, fetchActualMatching as fetchExpenseAutomationActualMatching, fetchActualMatchingPage as fetchExpenseAutomationActualMatchingPage, matchAndReverseAccruals, openMatchNewModal, searchMatchAccruals, searchMatchTransactions, updateActualMatchingUIState as updateExpenseAutomationActualMatchingUIState } from './view/expenseAutomationView/reducers/actualMatchingViewReducer';
|
|
305
|
+
import { clearActualMatchingView as clearExpenseAutomationActualMatchingView, clearMatchNewModal, closeMatchNewModal, fetchActualMatching as fetchExpenseAutomationActualMatching, fetchActualMatchingMatch, fetchActualMatchingPage as fetchExpenseAutomationActualMatchingPage, matchAndReverseAccruals, openMatchNewModal, searchMatchAccruals, searchMatchTransactions, updateActualMatchingUIState as updateExpenseAutomationActualMatchingUIState } from './view/expenseAutomationView/reducers/actualMatchingViewReducer';
|
|
306
306
|
import { clearExpenseAutomationFluxAnalysisView, fetchFluxAnalysisView, reviewFluxAnalysisView, updateFluxAnalysisViewPageMetaData, updateFluxAnalysisViewUIState, updateOperatingExpensesIdsForReview, updateSelectedSectionIdsForReview } from './view/expenseAutomationView/reducers/fluxAnalysisViewReducer';
|
|
307
307
|
import { clearJeScheduleLocalData as clearExpenseAutomationJEScheduleLocalData, clearExpenseAutomationJESchedulesView, clearSearchTransactionsForNewSchedule as clearJeSearchTransactionsForNewSchedule, createOneTimeAccrual, createOneTimeAccrualFailure, createOneTimeAccrualSuccess, fetchJeSchedulesPage as fetchExpenseAutomationJESchedulesPage, fetchOneTimeAccrual, ignoreRecommendedJeSchedule as ignoreExpenseAutomationJESchedule, ignoreOneTimeAccrual, initializeAccountSettingsView as initializeJeAccountSettingsView, initializeNewSchedule as initializeJeNewSchedule, initializeJeScheduleLocalData, promoteOneTimeAccrual, removeJeScheduleTransactionKey, resetNewScheduleLocalData as resetJeNewScheduleLocalData, retryJeSchedule as retryExpenseAutomationJESchedule, revertJeSchedule, revertOneTimeAccrual, saveAccountSettings as saveJeAccountSettings, saveAccountSettingsLocalData as saveJeAccountSettingsLocalData, saveNewSchedule as saveJeNewSchedule, saveNewScheduleFailure as saveJeNewScheduleFailure, saveNewScheduleSuccess as saveJeNewScheduleSuccess, searchTransactionsForNewSchedule as searchJeTransactionsForNewSchedule, searchTransactionsForNewScheduleFailure as searchJeTransactionsForNewScheduleFailure, searchTransactionsForNewScheduleSuccess as searchJeTransactionsForNewScheduleSuccess, toggleJECreatedGroupCollapsed, toggleJEPendingGroupCollapsed, updateJESchedulesUIState as updateExpenseAutomationJESchedulesUIState, updateJEScheduleTypeFilter, updateNewScheduleLocalData as updateJeNewScheduleLocalData, updateJeScheduleLocalDataById, updateJeScheduleTransactionKeys } from './view/expenseAutomationView/reducers/jeSchedulesViewReducer';
|
|
308
308
|
import { acknowledgeBulkUploadConfirmMatchComplete, bulkUploadAutomatchingTimedOut, bulkUploadReceipts, bulkUploadReceiptsFailure, bulkUploadReceiptsSuccess, clearBulkUpload, clearBulkUploadBatchDetailsForScopeChange, clearManualSearchResults, clearMissingReceiptsTabNavigation, confirmBulkUploadMatch, confirmBulkUploadMatchFailure, confirmBulkUploadMatchSuccess, fetchBulkUploadBatchDetails, fetchBulkUploadBatchDetailsFailure, fetchBulkUploadBatchDetailsSuccess, fetchBulkUploadBatches, fetchBulkUploadBatchesFailure, fetchBulkUploadBatchesSuccess, fetchCompletedTransactions, fetchCompletedTransactionsFailure, fetchCompletedTransactionsSuccess, fetchMissingReceipts as fetchExpenseAutomationMissingReceipts, fetchMoreBatchDetails, fetchMoreBatchDetailsComplete, fetchMoreBatchDetailsFailure, markBatchDetailRefreshAttempted, markMissingReceiptAsDone as markExpenseAutomationMissingReceiptAsDone, pusherBatchStatusUpdate, refreshBatchDetailsForBatchId, requestMissingReceiptsTabNavigation, restoreBulkUploadAutomatchingOnMount, restoreBulkUploadMatchingState, searchTransactionsForManualMatch, searchTransactionsForManualMatchFailure, searchTransactionsForManualMatchSuccess, setBulkUploadCompletedSubTab, setBulkUploadResultsTab, setBulkUploadSortConfig, setBulkUploadUploadedFileCount, storeBatchDetails, updateBulkUploadProgress, updateMissingReceiptUploadState as updateExpenseAutomationMissingReceiptUploadState, updateMissingReceiptsUIState as updateExpenseAutomationMissingReceiptsUIState, uploadMissingReceiptSuccess as uploadExpenseAutomationMissingReceiptSuccess } from './view/expenseAutomationView/reducers/missingReceiptsViewReducer';
|
|
@@ -943,7 +943,7 @@ export { fetchApAging, getApAgingReport, updateApAgingUIState, AgingReportId, Ap
|
|
|
943
943
|
export { fetchApAgingDetail, AgingReportInvoice, ApAgingDetail, getApAgingDetailForVendor, updateApAgingDetailUIState, };
|
|
944
944
|
export { LinkBillExpenseKey };
|
|
945
945
|
export { clearExpenseAutomationJEScheduleLocalData, clearExpenseAutomationJESchedulesView, clearJeSearchTransactionsForNewSchedule, fetchExpenseAutomationJESchedulesPage, ignoreExpenseAutomationJESchedule, initializeJeAccountSettingsView, initializeJeNewSchedule, initializeJeScheduleLocalData, removeJeScheduleTransactionKey, resetJeNewScheduleLocalData, retryExpenseAutomationJESchedule, saveJeNewSchedule, saveJeNewScheduleFailure, saveJeNewScheduleSuccess, searchJeTransactionsForNewSchedule, searchJeTransactionsForNewScheduleFailure, searchJeTransactionsForNewScheduleSuccess, updateExpenseAutomationJESchedulesUIState, updateJeNewScheduleLocalData, updateJeScheduleLocalDataById, updateJeScheduleTransactionKeys, };
|
|
946
|
-
export { clearExpenseAutomationActualMatchingView, closeMatchNewModal, clearMatchNewModal, fetchExpenseAutomationActualMatching, fetchExpenseAutomationActualMatchingPage, matchAndReverseAccruals, openMatchNewModal, searchMatchAccruals, searchMatchTransactions, updateExpenseAutomationActualMatchingUIState, };
|
|
946
|
+
export { clearExpenseAutomationActualMatchingView, closeMatchNewModal, clearMatchNewModal, fetchExpenseAutomationActualMatching, fetchActualMatchingMatch, fetchExpenseAutomationActualMatchingPage, matchAndReverseAccruals, openMatchNewModal, searchMatchAccruals, searchMatchTransactions, updateExpenseAutomationActualMatchingUIState, };
|
|
947
947
|
export { createNewSchedulesAccrued, deleteScheduleAccruedDetail, cancelScheduleAccruedJournalEntry, fetchScheduleAccruedDetails, fetchScheduleAccruedDetailsPage, resetJEAccruedLinkInLocalData, saveScheduleAccruedDetails, updateAmountsInScheduleAccruedDetail, updatedJEAccruedLinkWithRecommendedLocalData, updatedJELinkInLocalDataAccruedExpenses, fetchRecommendedTransactionRowIndex, clearSelectedJELinkRowIndex, updateLinkBillExpenseLocalData, updateScheduleAccruedDetailsLocalData, updateSelectedJEAccruedScheduleKey, resetSelectedJEAccruedScheduleKey, resetAccruedDetailNewScheduleState, };
|
|
948
948
|
export { JEScheduleKey, JEScheduleTransactionKey, ScheduleTransactionID, getJEScheduleTransactionKey, ALL_JE_SCHEDULE_IGNORE_REASONS, ALL_JE_SCHEDULE_REVERT_REASONS, ALL_ONE_TIME_ACCRUAL_IGNORE_REASONS, ALL_ONE_TIME_ACCRUAL_REVERT_REASONS, ALL_SCHEDULES_TYPES, JEScheduledTransaction, JEAccruedSchedule, JEOneTimeAccrual, OneTimeAccrualEdits, JEOneTimeAccrualAiSuggestion, JEOneTimeAccrualBillingPattern, JEOneTimeAccrualCleared, JEOneTimeAccrualMatchSuggestion, JEOneTimeAccrualMonthlyTotal, JEOneTimeAccrualProfileSnapshot, JEOneTimeAccrualKey, JEScheduleAISummaries, JEScheduleFieldRecommendation, JEScheduleSummary, ScheduleTypes, ScheduleJournalEntryStatusCodeType, ScheduleListReport, ScheduleAccruedListReport, getScheduleListReport, getAccruedScheduleListReport, ScheduleSubTabType, ScheduleListSortKey, fetchScheduleList, fetchAccruedScheduleList, fetchDownloadSchedules, fetchSchedulesAccount, updateScheduleListLocalData, getFetchStateForScheduleAccountList, toScheduleTypesType, toScheduleTypesTypeStrict, toScheduleListTabsFileTypeStrict, ScheduleListLocalData, ScheduleDetailsLocalDataFixedAssets, ScheduleDetailsLocalDataAccruedExpenses, ScheduleDetailsView, ScheduleAccruedDetailsView, LinkBillExpenseView, LinkBillExpenseLocalData, JEScheduleDetailsLocalData, ScheduleDetailsLocalData, toScheduleSubTabType, ScheduleStatusCodeType, JEScheduleIgnoreReasonType, JEScheduleRevertReasonType, JournalEntryErrorCodeType, OneTimeAccrualIgnoreReasonType, OneTimeAccrualRevertReasonType, ScheduleTransaction, updateScheduleListSubTab, updateScheduleListSearchText, updateScheduleListScrollState, updateScheduleListSortState, ScheduleDetailSortKey, ScheduledJournalEntry, updateSelectedJEScheduleKey, fetchScheduleDetails, getScheduleDetailsView, getAccruedScheduleDetailsView, fetchScheduleDetailsPage, saveScheduleDetails, deleteScheduleDetail, createNewSchedules, updateScheduleDetailsLocalData, JETransactionLink, updateScheduleListDownloadState, updateAccruedJEScheduleAccruedByListKey, DownloadJEScheduleTabOptions, updatedSelectedJELinkRowIndex, ScheduleListTabsFileType, getQBOUrlForLink, getThirdPartyIDFromQBOURL, updatedJELinkInLocalData, updateAmountsInScheduleDetail, ScheduleDetailUIState, resetJELinkInLocalData, JEScheduledTransactionWithBalance, JEScheduleWithBalance, JELinkType, updatedJELinkWithRecommendedLocalData, getFetchStateForScheduleListByType, getDefaultSelectedTimeframeForScheduleType, markAsCompleteScheduleDetail, resetMarkAsCompleteStatus, fetchVendorTabView, updateVendorTabViewTab, VendorTabViewTabType, getVendorTabView, VendorTabViewSelectorView, };
|
|
949
949
|
export { GlobalMerchant, GlobalMerchantBase, TenantMerchant };
|
|
@@ -1269,4 +1269,7 @@ export type { InvoicingOnboardingGateView } from './view/invoicing/invoicingConf
|
|
|
1269
1269
|
export type { InvoicingConfigView } from './view/invoicing/invoicingConfigView/invoicingConfigViewSelector';
|
|
1270
1270
|
export type { InvoicingOnboardingStatus } from './view/invoicing/invoicingConfigView/invoicingConfigViewPayload';
|
|
1271
1271
|
export { getExpenseAutomationJEOneTimeAccrualDetailView, getJEScheduleRowType, isAccruedScheduleRow, isAiAccountantSchedule, isExistingTabRow, isOneTimeAccrualRow, isRenderableOneTimeAccrual, isPendingReviewRow, } from './view/expenseAutomationView/selectors/jeSchedulesViewSelector';
|
|
1272
|
-
export { getActualMatchingAmount, getActualMatchingReversalDate, getExpenseAutomationActualMatchingView, isAutoReversedAccrual, isManuallyReversedAccrual, isPendingReviewAccrual, } from './view/expenseAutomationView/selectors/actualMatchingViewSelector';
|
|
1272
|
+
export { getActualMatchingAmount, getActualMatchingReversalDate, parseActualMatchingMatchId, getExpenseAutomationActualMatchingMatchView, getExpenseAutomationActualMatchingView, isAutoReversedAccrual, isManuallyReversedAccrual, isPendingReviewAccrual, } from './view/expenseAutomationView/selectors/actualMatchingViewSelector';
|
|
1273
|
+
export type { ExpenseAutomationActualMatchingMatchView } from './view/expenseAutomationView/selectors/actualMatchingViewSelector';
|
|
1274
|
+
export type { ActualMatchingMatch, ActualMatchingMatchKind, } from './entity/actualMatching/actualMatchingState';
|
|
1275
|
+
export type { ActualMatchingMatchId } from './entity/actualMatching/actualMatchingTypes';
|