@zeniai/client-epic-state 5.2.35-beta2MM → 5.2.35-beta4MM
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 +6 -1
- package/lib/entity/actualMatching/actualMatchingPayload.js +8 -13
- package/lib/entity/actualMatching/actualMatchingReducer.d.ts +3 -2
- package/lib/entity/actualMatching/actualMatchingReducer.js +3 -3
- package/lib/entity/actualMatching/actualMatchingState.d.ts +3 -2
- package/lib/esm/entity/actualMatching/actualMatchingPayload.js +9 -14
- package/lib/esm/entity/actualMatching/actualMatchingReducer.js +3 -3
- package/lib/esm/index.js +2 -2
- package/lib/esm/view/expenseAutomationView/epics/actualMatching/fetchActualMatchingEpic.js +2 -2
- package/lib/esm/view/expenseAutomationView/epics/actualMatching/fetchActualMatchingMatchEpic.js +3 -2
- package/lib/esm/view/expenseAutomationView/epics/actualMatching/matchAndReverseAccrualsEpic.js +21 -24
- package/lib/esm/view/expenseAutomationView/epics/actualMatching/refreshActualMatchingList.js +16 -0
- package/lib/esm/view/expenseAutomationView/epics/actualMatching/searchMatchTransactionsEpic.js +6 -9
- package/lib/esm/view/expenseAutomationView/epics/actualMatching/undoReversalAccrualsEpic.js +15 -28
- package/lib/esm/view/expenseAutomationView/payload/actualMatchingPayload.js +9 -9
- package/lib/esm/view/expenseAutomationView/reducers/actualMatchingViewReducer.js +34 -16
- package/lib/esm/view/expenseAutomationView/selectors/actualMatchingViewSelector.js +65 -21
- package/lib/esm/view/expenseAutomationView/types/actualMatchingViewState.js +3 -0
- package/lib/index.d.ts +3 -2
- package/lib/index.js +49 -48
- package/lib/view/expenseAutomationView/epics/actualMatching/fetchActualMatchingEpic.js +1 -1
- package/lib/view/expenseAutomationView/epics/actualMatching/fetchActualMatchingMatchEpic.d.ts +1 -1
- package/lib/view/expenseAutomationView/epics/actualMatching/fetchActualMatchingMatchEpic.js +3 -2
- package/lib/view/expenseAutomationView/epics/actualMatching/matchAndReverseAccrualsEpic.js +17 -20
- package/lib/view/expenseAutomationView/epics/actualMatching/refreshActualMatchingList.d.ts +3 -0
- package/lib/view/expenseAutomationView/epics/actualMatching/refreshActualMatchingList.js +19 -0
- package/lib/view/expenseAutomationView/epics/actualMatching/searchMatchTransactionsEpic.js +5 -8
- package/lib/view/expenseAutomationView/epics/actualMatching/undoReversalAccrualsEpic.js +13 -26
- package/lib/view/expenseAutomationView/payload/actualMatchingPayload.d.ts +2 -2
- package/lib/view/expenseAutomationView/payload/actualMatchingPayload.js +9 -9
- package/lib/view/expenseAutomationView/reducers/actualMatchingViewReducer.d.ts +19 -16
- package/lib/view/expenseAutomationView/reducers/actualMatchingViewReducer.js +33 -15
- package/lib/view/expenseAutomationView/selectorTypes/actualMatchingViewSelectorTypes.d.ts +0 -1
- package/lib/view/expenseAutomationView/selectors/actualMatchingViewSelector.d.ts +6 -1
- package/lib/view/expenseAutomationView/selectors/actualMatchingViewSelector.js +66 -21
- package/lib/view/expenseAutomationView/types/actualMatchingViewState.d.ts +5 -1
- package/lib/view/expenseAutomationView/types/actualMatchingViewState.js +4 -0
- package/package.json +1 -1
|
@@ -4,6 +4,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.getSelectedMonthYearForCurrentTenant = getSelectedMonthYearForCurrentTenant;
|
|
7
|
+
exports.getTenantDisplayCurrency = getTenantDisplayCurrency;
|
|
7
8
|
exports.parseActualMatchingMatchId = parseActualMatchingMatchId;
|
|
8
9
|
exports.isAutoReversedAccrual = isAutoReversedAccrual;
|
|
9
10
|
exports.isManuallyReversedAccrual = isManuallyReversedAccrual;
|
|
@@ -21,6 +22,7 @@ const actualMatchingSelector_1 = require("../../../entity/actualMatching/actualM
|
|
|
21
22
|
const jeScheduleHelper_1 = require("../../../entity/jeSchedules/jeScheduleHelper");
|
|
22
23
|
const jeSchedulesSelector_1 = require("../../../entity/jeSchedules/jeSchedulesSelector");
|
|
23
24
|
const tenantSelector_1 = require("../../../entity/tenant/tenantSelector");
|
|
25
|
+
const actualMatchingViewState_1 = require("../types/actualMatchingViewState");
|
|
24
26
|
function getSelectedMonthYearForCurrentTenant(state) {
|
|
25
27
|
const tenantId = (0, tenantSelector_1.getCurrentTenant)(state)?.tenantId;
|
|
26
28
|
if (tenantId == null) {
|
|
@@ -28,6 +30,18 @@ function getSelectedMonthYearForCurrentTenant(state) {
|
|
|
28
30
|
}
|
|
29
31
|
return state.expenseAutomationViewState.selectedPeriodByTenantId[tenantId];
|
|
30
32
|
}
|
|
33
|
+
function getTenantDisplayCurrency(state) {
|
|
34
|
+
const locale = (0, tenantSelector_1.getCurrentTenant)(state)?.company?.companyLocaleInfo;
|
|
35
|
+
if (locale?.currencyCode == null || locale.currencyCode === '') {
|
|
36
|
+
return undefined;
|
|
37
|
+
}
|
|
38
|
+
return {
|
|
39
|
+
currencyCode: locale.currencyCode,
|
|
40
|
+
currencySymbol: locale.currencySymbol != null && locale.currencySymbol !== ''
|
|
41
|
+
? locale.currencySymbol
|
|
42
|
+
: locale.currencyCode,
|
|
43
|
+
};
|
|
44
|
+
}
|
|
31
45
|
function toMatchModalAccrual(member) {
|
|
32
46
|
if ('jeOneTimeAccrualKey' in member && member.jeOneTimeAccrualKey != null) {
|
|
33
47
|
return member;
|
|
@@ -49,9 +63,9 @@ function uniqueMatchModalAccruals(pinned, searched) {
|
|
|
49
63
|
}
|
|
50
64
|
function uniqueTransactionSearchResults(pinned, searched) {
|
|
51
65
|
const byKey = new Map();
|
|
52
|
-
pinned.forEach((row) => byKey.set(
|
|
66
|
+
pinned.forEach((row) => byKey.set((0, actualMatchingViewState_1.actualMatchingTransactionLineKey)(row.transactionType, row.transactionIntegrationId, row.lineId), row));
|
|
53
67
|
searched.forEach((row) => {
|
|
54
|
-
const key =
|
|
68
|
+
const key = (0, actualMatchingViewState_1.actualMatchingTransactionLineKey)(row.transactionType, row.transactionIntegrationId, row.lineId);
|
|
55
69
|
if (!byKey.has(key)) {
|
|
56
70
|
byKey.set(key, row);
|
|
57
71
|
}
|
|
@@ -133,7 +147,9 @@ function toActualMatchingRow(match) {
|
|
|
133
147
|
groupedAccrualIds: match.members.map((member) => member.accrualId),
|
|
134
148
|
groupedMembers: collectGroupedMembers(match.members),
|
|
135
149
|
reversalDate: getActualMatchingReversalDate(first),
|
|
136
|
-
vendorName: match.vendorName
|
|
150
|
+
vendorName: match.vendorName != null && match.vendorName !== ''
|
|
151
|
+
? match.vendorName
|
|
152
|
+
: first.vendorName,
|
|
137
153
|
estimatedAmount: match.accruedAmount,
|
|
138
154
|
};
|
|
139
155
|
}
|
|
@@ -142,10 +158,10 @@ function matchesSearch(row, searchString) {
|
|
|
142
158
|
if (trimmed.length === 0) {
|
|
143
159
|
return true;
|
|
144
160
|
}
|
|
145
|
-
if (row.vendorName.toLowerCase().includes(trimmed)) {
|
|
161
|
+
if ((row.vendorName ?? '').toLowerCase().includes(trimmed)) {
|
|
146
162
|
return true;
|
|
147
163
|
}
|
|
148
|
-
if (row.memo.toLowerCase().includes(trimmed)) {
|
|
164
|
+
if ((row.memo ?? '').toLowerCase().includes(trimmed)) {
|
|
149
165
|
return true;
|
|
150
166
|
}
|
|
151
167
|
return (row.groupedMembers ?? []).some((member) => (member.memo ?? '').toLowerCase().includes(trimmed));
|
|
@@ -153,7 +169,7 @@ function matchesSearch(row, searchString) {
|
|
|
153
169
|
function getActualMatchingSortValue(row, sortKey) {
|
|
154
170
|
switch (sortKey) {
|
|
155
171
|
case 'vendor':
|
|
156
|
-
return row.vendorName.toLowerCase();
|
|
172
|
+
return (row.vendorName ?? '').toLowerCase();
|
|
157
173
|
case 'date':
|
|
158
174
|
return row.reversalDate?.valueOf() ?? row.transactionDate;
|
|
159
175
|
case 'amount':
|
|
@@ -197,8 +213,14 @@ function emptyKpiSummary() {
|
|
|
197
213
|
variance: { percent: 0, averagePercentPerMatch: 0, netAmount: 0 },
|
|
198
214
|
};
|
|
199
215
|
}
|
|
200
|
-
function sumRowAmounts(rows) {
|
|
201
|
-
return rows.reduce((sum, row) =>
|
|
216
|
+
function sumRowAmounts(rows, displayCurrencyCode) {
|
|
217
|
+
return rows.reduce((sum, row) => {
|
|
218
|
+
if (displayCurrencyCode != null &&
|
|
219
|
+
row.accruedAmount.currencyCode !== displayCurrencyCode) {
|
|
220
|
+
return sum;
|
|
221
|
+
}
|
|
222
|
+
return sum + getActualMatchingAmount(row);
|
|
223
|
+
}, 0);
|
|
202
224
|
}
|
|
203
225
|
function uniqueVendorCount(rows) {
|
|
204
226
|
const ids = new Set();
|
|
@@ -207,7 +229,7 @@ function uniqueVendorCount(rows) {
|
|
|
207
229
|
ids.add(row.vendorId);
|
|
208
230
|
return;
|
|
209
231
|
}
|
|
210
|
-
if (row.vendorName !== '') {
|
|
232
|
+
if (row.vendorName != null && row.vendorName !== '') {
|
|
211
233
|
ids.add(row.vendorName);
|
|
212
234
|
}
|
|
213
235
|
});
|
|
@@ -219,19 +241,35 @@ function rowVariancePercent(row) {
|
|
|
219
241
|
if (actual == null || accrued === 0) {
|
|
220
242
|
return undefined;
|
|
221
243
|
}
|
|
222
|
-
return ((actual - accrued) / accrued) * 100;
|
|
244
|
+
return ((actual - accrued) / Math.abs(accrued)) * 100;
|
|
223
245
|
}
|
|
224
|
-
function buildActualMatchingKpiSummary(rows) {
|
|
246
|
+
function buildActualMatchingKpiSummary(rows, displayCurrencyCode) {
|
|
225
247
|
if (rows.length === 0) {
|
|
226
248
|
return emptyKpiSummary();
|
|
227
249
|
}
|
|
228
250
|
const autoReversed = rows.filter((row) => row.kind === 'auto_reversed');
|
|
229
251
|
const pendingReview = rows.filter((row) => row.kind === 'pending_review');
|
|
230
252
|
const receivedCount = rows.length;
|
|
231
|
-
const rowsWithActual = rows.filter((row) =>
|
|
253
|
+
const rowsWithActual = rows.filter((row) => {
|
|
254
|
+
if (row.actualAmount?.amount == null) {
|
|
255
|
+
return false;
|
|
256
|
+
}
|
|
257
|
+
if (displayCurrencyCode == null) {
|
|
258
|
+
return true;
|
|
259
|
+
}
|
|
260
|
+
const rowCurrency = row.accruedAmount?.currencyCode ?? row.estimatedAmount.currencyCode;
|
|
261
|
+
return rowCurrency === displayCurrencyCode;
|
|
262
|
+
});
|
|
232
263
|
const accruedTotal = rowsWithActual.reduce((sum, row) => sum + (row.accruedAmount?.amount ?? row.estimatedAmount.amount), 0);
|
|
233
264
|
const actualTotal = rowsWithActual.reduce((sum, row) => sum + (row.actualAmount?.amount ?? 0), 0);
|
|
234
265
|
const variancePercents = rows
|
|
266
|
+
.filter((row) => {
|
|
267
|
+
if (displayCurrencyCode == null) {
|
|
268
|
+
return true;
|
|
269
|
+
}
|
|
270
|
+
const rowCurrency = row.accruedAmount?.currencyCode ?? row.estimatedAmount.currencyCode;
|
|
271
|
+
return rowCurrency === displayCurrencyCode;
|
|
272
|
+
})
|
|
235
273
|
.map(rowVariancePercent)
|
|
236
274
|
.filter((percent) => percent != null);
|
|
237
275
|
return {
|
|
@@ -245,17 +283,17 @@ function buildActualMatchingKpiSummary(rows) {
|
|
|
245
283
|
autoReversed: {
|
|
246
284
|
count: autoReversed.length,
|
|
247
285
|
percent: Math.round((autoReversed.length / receivedCount) * 100),
|
|
248
|
-
clearedAmount: sumRowAmounts(autoReversed),
|
|
286
|
+
clearedAmount: sumRowAmounts(autoReversed, displayCurrencyCode),
|
|
249
287
|
},
|
|
250
288
|
pendingReview: {
|
|
251
289
|
count: pendingReview.length,
|
|
252
|
-
amount: sumRowAmounts(pendingReview),
|
|
290
|
+
amount: sumRowAmounts(pendingReview, displayCurrencyCode),
|
|
253
291
|
estimatedMinutesToClear: pendingReview.length * ESTIMATED_MINUTES_PER_PENDING_MATCH,
|
|
254
292
|
},
|
|
255
293
|
variance: {
|
|
256
294
|
percent: accruedTotal === 0
|
|
257
295
|
? 0
|
|
258
|
-
: ((actualTotal - accruedTotal) / accruedTotal) * 100,
|
|
296
|
+
: ((actualTotal - accruedTotal) / Math.abs(accruedTotal)) * 100,
|
|
259
297
|
averagePercentPerMatch: variancePercents.length === 0
|
|
260
298
|
? 0
|
|
261
299
|
: variancePercents.reduce((sum, percent) => sum + percent, 0) /
|
|
@@ -270,12 +308,14 @@ function getExpenseAutomationActualMatchingMatchView(state, matchId) {
|
|
|
270
308
|
match: (0, actualMatchingSelector_1.getActualMatchingMatchById)(state.actualMatchingState, matchId),
|
|
271
309
|
detailFetchState: view.detailFetchStateByMatchId[matchId] ?? NOT_STARTED,
|
|
272
310
|
refreshStatus: view.detailRefreshStatusByMatchId[matchId] ?? NOT_STARTED,
|
|
273
|
-
undoReversalStatus: view.
|
|
311
|
+
undoReversalStatus: view.undoReversalStatusByMatchId[matchId] ?? NOT_STARTED,
|
|
312
|
+
lastUndoResults: view.lastUndoResultsByMatchId[matchId],
|
|
313
|
+
lastMatchResults: view.lastMatchResultsByMatchId?.[matchId],
|
|
274
314
|
};
|
|
275
315
|
}
|
|
276
316
|
function getExpenseAutomationActualMatchingView(state) {
|
|
277
317
|
const { expenseAutomationActualMatchingViewState } = state;
|
|
278
|
-
const { matchIdsByPeriod, fetchState, error, refreshStatus, uiState, matchModal,
|
|
318
|
+
const { matchIdsByPeriod, fetchState, error, refreshStatus, uiState, matchModal, } = expenseAutomationActualMatchingViewState;
|
|
279
319
|
const selectedPeriod = getSelectedMonthYearForCurrentTenant(state);
|
|
280
320
|
const monthYearPeriodId = selectedPeriod != null ? (0, timePeriod_1.toMonthYearPeriodId)(selectedPeriod) : undefined;
|
|
281
321
|
const matchIds = monthYearPeriodId != null ? matchIdsByPeriod[monthYearPeriodId] : undefined;
|
|
@@ -287,19 +327,25 @@ function getExpenseAutomationActualMatchingView(state) {
|
|
|
287
327
|
const rows = allRows.filter((row) => matchesSearch(row, uiState.searchString));
|
|
288
328
|
const reversed = sortActualMatchingRows(rows.filter((row) => isReversedMatchKind(row.kind)), uiState);
|
|
289
329
|
const pendingReview = sortActualMatchingRows(rows.filter((row) => row.kind === 'pending_review'), uiState);
|
|
290
|
-
const kpiSummary = buildActualMatchingKpiSummary(allRows);
|
|
330
|
+
const kpiSummary = buildActualMatchingKpiSummary(allRows, getTenantDisplayCurrency(state)?.currencyCode);
|
|
291
331
|
const searchedAccruals = matchModal.accrualSearch.results
|
|
292
332
|
.map((key) => (0, jeSchedulesSelector_1.getJEOneTimeAccrualByKey)(key, state.jeSchedulesState))
|
|
293
333
|
.filter((accrual) => accrual != null);
|
|
294
334
|
const openedMatch = matchModal.openedFromMatchId != null
|
|
295
335
|
? (0, actualMatchingSelector_1.getActualMatchingMatchById)(state.actualMatchingState, matchModal.openedFromMatchId)
|
|
296
336
|
: undefined;
|
|
297
|
-
const pinnedAccruals =
|
|
337
|
+
const pinnedAccruals = [
|
|
338
|
+
...(openedMatch?.members ?? []),
|
|
339
|
+
...(openedMatch?.leftovers ?? []),
|
|
340
|
+
].map(toMatchModalAccrual);
|
|
298
341
|
const firstSuggestion = openedMatch?.members[0]?.matchSuggestion;
|
|
299
342
|
const prefill = openedMatch == null
|
|
300
343
|
? undefined
|
|
301
344
|
: {
|
|
302
|
-
selectedAccrualIds:
|
|
345
|
+
selectedAccrualIds: [
|
|
346
|
+
...openedMatch.members.map((member) => member.accrualId),
|
|
347
|
+
...(openedMatch.leftovers ?? []).map((leftover) => leftover.accrualId),
|
|
348
|
+
],
|
|
303
349
|
actualAmount: openedMatch.actualAmount.amount,
|
|
304
350
|
matchedLineId: firstSuggestion?.matchedLineId,
|
|
305
351
|
matchedTransactionId: firstSuggestion?.matchedTransactionId,
|
|
@@ -313,7 +359,6 @@ function getExpenseAutomationActualMatchingView(state) {
|
|
|
313
359
|
uiState,
|
|
314
360
|
refreshStatus,
|
|
315
361
|
hasLoadedForSelectedPeriod: matchIds != null,
|
|
316
|
-
undoReversalStatus,
|
|
317
362
|
matchModal: {
|
|
318
363
|
isOpen: matchModal.isOpen,
|
|
319
364
|
openedFromMatchId: matchModal.openedFromMatchId,
|
|
@@ -66,6 +66,7 @@ export interface UndoReversalResult {
|
|
|
66
66
|
}
|
|
67
67
|
export interface UndoReversalAccrualsParams {
|
|
68
68
|
accrualIds: ID[];
|
|
69
|
+
matchId: ActualMatchingMatchId;
|
|
69
70
|
}
|
|
70
71
|
export interface ActualMatchingTransactionSearchState extends FetchStateAndError {
|
|
71
72
|
isLoadingMore: boolean;
|
|
@@ -88,12 +89,15 @@ export interface ActualMatchingMatchModalState {
|
|
|
88
89
|
lastBatchResults?: MatchAndReverseResult[];
|
|
89
90
|
openedFromMatchId?: ActualMatchingMatchId;
|
|
90
91
|
}
|
|
92
|
+
export declare function actualMatchingTransactionLineKey(transactionType: string, transactionIntegrationId: string, lineId: string): string;
|
|
91
93
|
export interface ActualMatchingViewState extends FetchedState {
|
|
92
94
|
detailFetchStateByMatchId: Record<ActualMatchingMatchId, FetchStateAndError>;
|
|
93
95
|
detailRefreshStatusByMatchId: Record<ActualMatchingMatchId, FetchStateAndError>;
|
|
96
|
+
lastMatchResultsByMatchId: Record<ActualMatchingMatchId, MatchAndReverseResult[]>;
|
|
97
|
+
lastUndoResultsByMatchId: Record<ActualMatchingMatchId, UndoReversalResult[]>;
|
|
94
98
|
matchIdsByPeriod: Record<MonthYearPeriodId, ActualMatchingMatchId[]>;
|
|
95
99
|
matchModal: ActualMatchingMatchModalState;
|
|
96
100
|
refreshStatus: FetchStateAndError;
|
|
97
101
|
uiState: ActualMatchingViewUIState;
|
|
98
|
-
|
|
102
|
+
undoReversalStatusByMatchId: Record<ActualMatchingMatchId, FetchStateAndError>;
|
|
99
103
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.toUndoReversalResultStatus = exports.toMatchAndReverseResultStatus = exports.MATCH_SEARCH_DEBOUNCE_MS = exports.MATCH_ACCRUAL_SEARCH_LIMIT = exports.MATCH_TRANSACTION_SEARCH_PAGE_SIZE = exports.toActualMatchingSortKey = void 0;
|
|
4
|
+
exports.actualMatchingTransactionLineKey = actualMatchingTransactionLineKey;
|
|
4
5
|
const stringToUnion_1 = require("../../../commonStateTypes/stringToUnion");
|
|
5
6
|
const ACTUAL_MATCHING_SORT_KEYS = [
|
|
6
7
|
'vendor',
|
|
@@ -36,3 +37,6 @@ const UNDO_REVERSAL_RESULT_STATUSES = [
|
|
|
36
37
|
];
|
|
37
38
|
const toUndoReversalResultStatus = (v) => (0, stringToUnion_1.stringToUnion)(v, UNDO_REVERSAL_RESULT_STATUSES);
|
|
38
39
|
exports.toUndoReversalResultStatus = toUndoReversalResultStatus;
|
|
40
|
+
function actualMatchingTransactionLineKey(transactionType, transactionIntegrationId, lineId) {
|
|
41
|
+
return `${transactionType}:${transactionIntegrationId}:${lineId}`;
|
|
42
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zeniai/client-epic-state",
|
|
3
|
-
"version": "5.2.35-
|
|
3
|
+
"version": "5.2.35-beta4MM",
|
|
4
4
|
"description": "Shared module between Web & Mobile containing required abstractions for state management, async network communication. ",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"module": "lib/esm/index.js",
|