@zeniai/client-epic-state 5.2.22-betaAM2 → 5.2.22-betaAM3

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.
@@ -135,6 +135,7 @@ export interface JEOneTimeAccrualClearedPayload {
135
135
  match_tier?: string | null;
136
136
  matched_amount?: number | null;
137
137
  matched_line_id?: string | null;
138
+ matched_transaction_date?: string | null;
138
139
  matched_transaction_id?: string | null;
139
140
  matched_transaction_integration_id?: string | null;
140
141
  matched_transaction_type?: string | null;
@@ -144,6 +145,7 @@ export interface JEOneTimeAccrualMatchSuggestionPayload {
144
145
  match_tier?: string | null;
145
146
  matched_amount?: number | null;
146
147
  matched_line_id?: string | null;
148
+ matched_transaction_date?: string | null;
147
149
  matched_transaction_id?: string | null;
148
150
  matched_transaction_integration_id?: string | null;
149
151
  matched_transaction_type?: string | null;
@@ -473,6 +473,9 @@ function toJEOneTimeAccrualCleared(payload, currencyCode) {
473
473
  : undefined,
474
474
  accrualIds: payload.accrual_ids ?? undefined,
475
475
  reversedAt: payload.reversed_at != null ? (0, zeniDayJS_1.date)(payload.reversed_at) : undefined,
476
+ matchedTransactionDate: payload.matched_transaction_date != null
477
+ ? (0, zeniDayJS_1.date)(payload.matched_transaction_date)
478
+ : undefined,
476
479
  matchTier: payload.match_tier ?? undefined,
477
480
  matchShape: payload.match_shape ?? undefined,
478
481
  };
@@ -491,6 +494,9 @@ function toJEOneTimeAccrualMatchSuggestion(payload, currencyCode) {
491
494
  matchedAmount: payload.matched_amount != null
492
495
  ? toOneTimeAccrualAmount(payload.matched_amount, currencyCode)
493
496
  : undefined,
497
+ matchedTransactionDate: payload.matched_transaction_date != null
498
+ ? (0, zeniDayJS_1.date)(payload.matched_transaction_date)
499
+ : undefined,
494
500
  };
495
501
  }
496
502
  function toJEOneTimeAccrual(payload) {
@@ -204,6 +204,7 @@ export interface JEOneTimeAccrualCleared {
204
204
  groupSum?: Amount;
205
205
  matchedAmount?: Amount;
206
206
  matchedLineId?: string;
207
+ matchedTransactionDate?: ZeniDate;
207
208
  matchedTransactionId?: string;
208
209
  matchedTransactionIntegrationId?: string;
209
210
  matchedTransactionType?: string;
@@ -215,6 +216,7 @@ export interface JEOneTimeAccrualCleared {
215
216
  export interface JEOneTimeAccrualMatchSuggestion {
216
217
  matchedAmount?: Amount;
217
218
  matchedLineId?: string;
219
+ matchedTransactionDate?: ZeniDate;
218
220
  matchedTransactionId?: string;
219
221
  matchedTransactionIntegrationId?: string;
220
222
  matchedTransactionType?: string;
@@ -462,6 +462,9 @@ function toJEOneTimeAccrualCleared(payload, currencyCode) {
462
462
  : undefined,
463
463
  accrualIds: payload.accrual_ids ?? undefined,
464
464
  reversedAt: payload.reversed_at != null ? date(payload.reversed_at) : undefined,
465
+ matchedTransactionDate: payload.matched_transaction_date != null
466
+ ? date(payload.matched_transaction_date)
467
+ : undefined,
465
468
  matchTier: payload.match_tier ?? undefined,
466
469
  matchShape: payload.match_shape ?? undefined,
467
470
  };
@@ -480,6 +483,9 @@ function toJEOneTimeAccrualMatchSuggestion(payload, currencyCode) {
480
483
  matchedAmount: payload.matched_amount != null
481
484
  ? toOneTimeAccrualAmount(payload.matched_amount, currencyCode)
482
485
  : undefined,
486
+ matchedTransactionDate: payload.matched_transaction_date != null
487
+ ? date(payload.matched_transaction_date)
488
+ : undefined,
483
489
  };
484
490
  }
485
491
  export function toJEOneTimeAccrual(payload) {
@@ -20,26 +20,6 @@ export function isPendingReviewAccrual(accrual) {
20
20
  export function getClearedMatchedAmount(accrual) {
21
21
  return accrual.cleared?.matchedAmount?.amount;
22
22
  }
23
- function getActualMatchingGroupKey(accrual) {
24
- const ids = accrual.cleared?.accrualIds;
25
- if (ids != null && ids.length > 1) {
26
- return `cleared:${[...ids].sort().join(',')}`;
27
- }
28
- return accrual.accrualId;
29
- }
30
- function sumUniqueActualMatchingAmounts(accruals) {
31
- const seen = new Set();
32
- let sum = 0;
33
- for (const accrual of accruals) {
34
- const key = getActualMatchingGroupKey(accrual);
35
- if (seen.has(key)) {
36
- continue;
37
- }
38
- seen.add(key);
39
- sum += getActualMatchingAmount(accrual);
40
- }
41
- return sum;
42
- }
43
23
  export function getActualMatchingAmount(accrual) {
44
24
  if (isPendingReviewAccrual(accrual)) {
45
25
  return (accrual.matchSuggestion?.matchedAmount?.amount ??
@@ -51,20 +31,74 @@ export function getActualMatchingAmount(accrual) {
51
31
  return accrual.estimatedAmount.amount;
52
32
  }
53
33
  export function getActualMatchingReversalDate(accrual) {
54
- if (!isAutoReversedAccrual(accrual) && !isManuallyReversedAccrual(accrual)) {
55
- return undefined;
34
+ if (isPendingReviewAccrual(accrual)) {
35
+ return accrual.matchSuggestion?.matchedTransactionDate;
36
+ }
37
+ return accrual.cleared?.matchedTransactionDate;
38
+ }
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
+ }
56
70
  }
57
- return accrual.actualReversalPostDate ?? accrual.cleared?.reversedAt;
71
+ return grouped;
58
72
  }
59
- function toActualMatchingRow(accrual, kind) {
73
+ function toActualMatchingRow(accrual, kind, groupedAccrualIds) {
60
74
  return {
61
75
  ...accrual,
62
76
  kind,
63
- reversalDate: kind === 'pending_review'
64
- ? undefined
65
- : getActualMatchingReversalDate(accrual),
77
+ groupedAccrualIds,
78
+ reversalDate: getActualMatchingReversalDate(accrual),
66
79
  };
67
80
  }
81
+ function collapseActualMatchingRows(accruals, kind) {
82
+ const groups = new Map();
83
+ for (const accrual of accruals) {
84
+ const key = getActualMatchingBillCollapseKey(accrual);
85
+ const members = groups.get(key);
86
+ if (members != null) {
87
+ members.push(accrual);
88
+ }
89
+ else {
90
+ groups.set(key, [accrual]);
91
+ }
92
+ }
93
+ const rows = [];
94
+ for (const members of groups.values()) {
95
+ rows.push(toActualMatchingRow(members[0], kind, collectGroupedAccrualIds(members)));
96
+ }
97
+ return rows;
98
+ }
99
+ function sumCollapsedActualMatchingAmounts(rows) {
100
+ return rows.reduce((sum, row) => sum + getActualMatchingAmount(row), 0);
101
+ }
68
102
  function matchesSearch(accrual, searchString) {
69
103
  const trimmed = searchString.trim().toLowerCase();
70
104
  if (trimmed.length === 0) {
@@ -120,38 +154,30 @@ export function getExpenseAutomationActualMatchingView(state) {
120
154
  .map((key) => getJEOneTimeAccrualByKey(key, state.jeSchedulesState))
121
155
  .filter((accrual) => accrual != null);
122
156
  const filtered = accruals.filter((accrual) => matchesSearch(accrual, uiState.searchString));
123
- const autoReversed = sortActualMatchingRows(filtered
124
- .filter(isAutoReversedAccrual)
125
- .map((accrual) => toActualMatchingRow(accrual, 'auto_reversed')), uiState);
126
- const pendingReview = sortActualMatchingRows(filtered
127
- .filter(isPendingReviewAccrual)
128
- .map((accrual) => toActualMatchingRow(accrual, 'pending_review')), uiState);
129
- const manuallyReversed = sortActualMatchingRows(filtered
130
- .filter(isManuallyReversedAccrual)
131
- .map((accrual) => toActualMatchingRow(accrual, 'manually_reversed')), uiState);
132
- const listedAccruals = accruals.filter((accrual) => isAutoReversedAccrual(accrual) ||
133
- isPendingReviewAccrual(accrual) ||
134
- isManuallyReversedAccrual(accrual));
135
- const kpiSummary = listedAccruals.length === 0
157
+ const autoReversed = sortActualMatchingRows(collapseActualMatchingRows(filtered.filter(isAutoReversedAccrual), 'auto_reversed'), uiState);
158
+ const pendingReview = sortActualMatchingRows(collapseActualMatchingRows(filtered.filter(isPendingReviewAccrual), 'pending_review'), uiState);
159
+ const manuallyReversed = sortActualMatchingRows(collapseActualMatchingRows(filtered.filter(isManuallyReversedAccrual), 'manually_reversed'), uiState);
160
+ const listedRows = [...autoReversed, ...pendingReview, ...manuallyReversed];
161
+ const kpiSummary = listedRows.length === 0
136
162
  ? emptyKpiSummary()
137
163
  : {
138
164
  autoReversed: {
139
- count: listedAccruals.filter(isAutoReversedAccrual).length,
140
- amount: sumUniqueActualMatchingAmounts(listedAccruals.filter(isAutoReversedAccrual)),
165
+ count: autoReversed.length,
166
+ amount: sumCollapsedActualMatchingAmounts(autoReversed),
141
167
  },
142
168
  pendingReview: {
143
- count: listedAccruals.filter(isPendingReviewAccrual).length,
144
- amount: sumUniqueActualMatchingAmounts(listedAccruals.filter(isPendingReviewAccrual)),
169
+ count: pendingReview.length,
170
+ amount: sumCollapsedActualMatchingAmounts(pendingReview),
145
171
  },
146
172
  totalThisClose: {
147
- count: listedAccruals.length,
148
- amount: sumUniqueActualMatchingAmounts(listedAccruals),
173
+ count: listedRows.length,
174
+ amount: sumCollapsedActualMatchingAmounts(listedRows),
149
175
  },
150
176
  ai: {
151
- count: listedAccruals.filter((accrual) => accrual.origin === 'agent').length,
177
+ count: listedRows.filter((row) => row.origin === 'agent').length,
152
178
  },
153
179
  manual: {
154
- count: listedAccruals.filter((accrual) => accrual.origin === 'human').length,
180
+ count: listedRows.filter((row) => row.origin === 'human').length,
155
181
  },
156
182
  };
157
183
  const accrualSearchResults = matchModal.accrualSearch.results
@@ -1,4 +1,4 @@
1
- import { FetchStateAndError } from '../../../commonStateTypes/common';
1
+ import { FetchStateAndError, ID } from '../../../commonStateTypes/common';
2
2
  import { SelectorView } from '../../../commonStateTypes/viewAndReport/viewAndReport';
3
3
  import { JEOneTimeAccrual } from '../../../entity/jeSchedules/jeSchedulesSelector';
4
4
  import { ZeniDate } from '../../../zeniDayJS';
@@ -6,6 +6,7 @@ import { ActualMatchingTransactionSearchResult, ActualMatchingViewUIState, Match
6
6
  export type ActualMatchingRowKind = 'auto_reversed' | 'pending_review' | 'manually_reversed';
7
7
  export interface ActualMatchingRow extends JEOneTimeAccrual {
8
8
  kind: ActualMatchingRowKind;
9
+ groupedAccrualIds?: ID[];
9
10
  reversalDate?: ZeniDate;
10
11
  }
11
12
  export interface ActualMatchingKpiSummary {
@@ -32,26 +32,6 @@ function isPendingReviewAccrual(accrual) {
32
32
  function getClearedMatchedAmount(accrual) {
33
33
  return accrual.cleared?.matchedAmount?.amount;
34
34
  }
35
- function getActualMatchingGroupKey(accrual) {
36
- const ids = accrual.cleared?.accrualIds;
37
- if (ids != null && ids.length > 1) {
38
- return `cleared:${[...ids].sort().join(',')}`;
39
- }
40
- return accrual.accrualId;
41
- }
42
- function sumUniqueActualMatchingAmounts(accruals) {
43
- const seen = new Set();
44
- let sum = 0;
45
- for (const accrual of accruals) {
46
- const key = getActualMatchingGroupKey(accrual);
47
- if (seen.has(key)) {
48
- continue;
49
- }
50
- seen.add(key);
51
- sum += getActualMatchingAmount(accrual);
52
- }
53
- return sum;
54
- }
55
35
  function getActualMatchingAmount(accrual) {
56
36
  if (isPendingReviewAccrual(accrual)) {
57
37
  return (accrual.matchSuggestion?.matchedAmount?.amount ??
@@ -63,20 +43,74 @@ function getActualMatchingAmount(accrual) {
63
43
  return accrual.estimatedAmount.amount;
64
44
  }
65
45
  function getActualMatchingReversalDate(accrual) {
66
- if (!isAutoReversedAccrual(accrual) && !isManuallyReversedAccrual(accrual)) {
67
- return undefined;
46
+ if (isPendingReviewAccrual(accrual)) {
47
+ return accrual.matchSuggestion?.matchedTransactionDate;
48
+ }
49
+ return accrual.cleared?.matchedTransactionDate;
50
+ }
51
+ function getActualMatchingBillCollapseKey(accrual) {
52
+ const stamp = isPendingReviewAccrual(accrual)
53
+ ? accrual.matchSuggestion
54
+ : accrual.cleared;
55
+ const txnId = stamp?.matchedTransactionId;
56
+ if (txnId != null && txnId !== '') {
57
+ return `txn:${txnId}`;
58
+ }
59
+ const integrationId = stamp?.matchedTransactionIntegrationId;
60
+ if (integrationId != null && integrationId !== '') {
61
+ return `int:${integrationId}`;
62
+ }
63
+ const ids = accrual.cleared?.accrualIds;
64
+ if (ids != null && ids.length > 1) {
65
+ return `cleared:${[...ids].sort().join(',')}`;
66
+ }
67
+ return `accrual:${accrual.accrualId}`;
68
+ }
69
+ function collectGroupedAccrualIds(members) {
70
+ const stampIds = members[0]?.cleared?.accrualIds;
71
+ const memberIds = members.map((member) => member.accrualId);
72
+ if (stampIds != null && stampIds.length >= memberIds.length) {
73
+ return stampIds;
74
+ }
75
+ const seen = new Set();
76
+ const grouped = [];
77
+ for (const id of [...(stampIds ?? []), ...memberIds]) {
78
+ if (!seen.has(id)) {
79
+ seen.add(id);
80
+ grouped.push(id);
81
+ }
68
82
  }
69
- return accrual.actualReversalPostDate ?? accrual.cleared?.reversedAt;
83
+ return grouped;
70
84
  }
71
- function toActualMatchingRow(accrual, kind) {
85
+ function toActualMatchingRow(accrual, kind, groupedAccrualIds) {
72
86
  return {
73
87
  ...accrual,
74
88
  kind,
75
- reversalDate: kind === 'pending_review'
76
- ? undefined
77
- : getActualMatchingReversalDate(accrual),
89
+ groupedAccrualIds,
90
+ reversalDate: getActualMatchingReversalDate(accrual),
78
91
  };
79
92
  }
93
+ function collapseActualMatchingRows(accruals, kind) {
94
+ const groups = new Map();
95
+ for (const accrual of accruals) {
96
+ const key = getActualMatchingBillCollapseKey(accrual);
97
+ const members = groups.get(key);
98
+ if (members != null) {
99
+ members.push(accrual);
100
+ }
101
+ else {
102
+ groups.set(key, [accrual]);
103
+ }
104
+ }
105
+ const rows = [];
106
+ for (const members of groups.values()) {
107
+ rows.push(toActualMatchingRow(members[0], kind, collectGroupedAccrualIds(members)));
108
+ }
109
+ return rows;
110
+ }
111
+ function sumCollapsedActualMatchingAmounts(rows) {
112
+ return rows.reduce((sum, row) => sum + getActualMatchingAmount(row), 0);
113
+ }
80
114
  function matchesSearch(accrual, searchString) {
81
115
  const trimmed = searchString.trim().toLowerCase();
82
116
  if (trimmed.length === 0) {
@@ -132,38 +166,30 @@ function getExpenseAutomationActualMatchingView(state) {
132
166
  .map((key) => (0, jeSchedulesSelector_1.getJEOneTimeAccrualByKey)(key, state.jeSchedulesState))
133
167
  .filter((accrual) => accrual != null);
134
168
  const filtered = accruals.filter((accrual) => matchesSearch(accrual, uiState.searchString));
135
- const autoReversed = sortActualMatchingRows(filtered
136
- .filter(isAutoReversedAccrual)
137
- .map((accrual) => toActualMatchingRow(accrual, 'auto_reversed')), uiState);
138
- const pendingReview = sortActualMatchingRows(filtered
139
- .filter(isPendingReviewAccrual)
140
- .map((accrual) => toActualMatchingRow(accrual, 'pending_review')), uiState);
141
- const manuallyReversed = sortActualMatchingRows(filtered
142
- .filter(isManuallyReversedAccrual)
143
- .map((accrual) => toActualMatchingRow(accrual, 'manually_reversed')), uiState);
144
- const listedAccruals = accruals.filter((accrual) => isAutoReversedAccrual(accrual) ||
145
- isPendingReviewAccrual(accrual) ||
146
- isManuallyReversedAccrual(accrual));
147
- const kpiSummary = listedAccruals.length === 0
169
+ const autoReversed = sortActualMatchingRows(collapseActualMatchingRows(filtered.filter(isAutoReversedAccrual), 'auto_reversed'), uiState);
170
+ const pendingReview = sortActualMatchingRows(collapseActualMatchingRows(filtered.filter(isPendingReviewAccrual), 'pending_review'), uiState);
171
+ const manuallyReversed = sortActualMatchingRows(collapseActualMatchingRows(filtered.filter(isManuallyReversedAccrual), 'manually_reversed'), uiState);
172
+ const listedRows = [...autoReversed, ...pendingReview, ...manuallyReversed];
173
+ const kpiSummary = listedRows.length === 0
148
174
  ? emptyKpiSummary()
149
175
  : {
150
176
  autoReversed: {
151
- count: listedAccruals.filter(isAutoReversedAccrual).length,
152
- amount: sumUniqueActualMatchingAmounts(listedAccruals.filter(isAutoReversedAccrual)),
177
+ count: autoReversed.length,
178
+ amount: sumCollapsedActualMatchingAmounts(autoReversed),
153
179
  },
154
180
  pendingReview: {
155
- count: listedAccruals.filter(isPendingReviewAccrual).length,
156
- amount: sumUniqueActualMatchingAmounts(listedAccruals.filter(isPendingReviewAccrual)),
181
+ count: pendingReview.length,
182
+ amount: sumCollapsedActualMatchingAmounts(pendingReview),
157
183
  },
158
184
  totalThisClose: {
159
- count: listedAccruals.length,
160
- amount: sumUniqueActualMatchingAmounts(listedAccruals),
185
+ count: listedRows.length,
186
+ amount: sumCollapsedActualMatchingAmounts(listedRows),
161
187
  },
162
188
  ai: {
163
- count: listedAccruals.filter((accrual) => accrual.origin === 'agent').length,
189
+ count: listedRows.filter((row) => row.origin === 'agent').length,
164
190
  },
165
191
  manual: {
166
- count: listedAccruals.filter((accrual) => accrual.origin === 'human').length,
192
+ count: listedRows.filter((row) => row.origin === 'human').length,
167
193
  },
168
194
  };
169
195
  const accrualSearchResults = matchModal.accrualSearch.results
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zeniai/client-epic-state",
3
- "version": "5.2.22-betaAM2",
3
+ "version": "5.2.22-betaAM3",
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",