@zeniai/client-epic-state 5.2.62-beta0MM → 5.2.62-beta1MM

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.
@@ -1,6 +1,6 @@
1
1
  import { from } from 'rxjs';
2
2
  import { catchError, filter, mergeMap, takeUntil } from 'rxjs/operators';
3
- import { updateActualMatchingMatches } from '../../../../../entity/actualMatching/actualMatchingReducer';
3
+ import { removeActualMatchingMatch, updateActualMatchingMatches, } from '../../../../../entity/actualMatching/actualMatchingReducer';
4
4
  import { createZeniAPIStatus, isSuccessResponse, } from '../../../../../responsePayload';
5
5
  import { clearAll } from '../../../../../rootActions';
6
6
  import { fetchActualMatchingMatch, fetchActualMatchingMatchFailure, fetchActualMatchingMatchSuccess, } from '../../../reducers/actualMatchingViewReducer';
@@ -32,5 +32,7 @@ export const fetchActualMatchingMatchEpic = (actions$, state$, zeniAPI) => actio
32
32
  refreshViewInBackground,
33
33
  status: createZeniAPIStatus('Unexpected Error', `Fetch actual matching match REST API call errored out ${JSON.stringify(error)}`),
34
34
  }),
35
- ])), takeUntil(actions$.pipe(filter(clearAll.match))));
35
+ ])), takeUntil(actions$.pipe(filter((action) => clearAll.match(action) ||
36
+ (removeActualMatchingMatch.match(action) &&
37
+ action.payload.matchId === matchId)))));
36
38
  }));
@@ -1,15 +1,15 @@
1
1
  import { from, of } from 'rxjs';
2
- import { catchError, exhaustMap, filter, mergeMap, takeUntil } from 'rxjs/operators';
2
+ import { catchError, exhaustMap, filter, groupBy, mergeMap, takeUntil, } from 'rxjs/operators';
3
3
  import { getActualMatchingMatchById } from '../../../../../entity/actualMatching/actualMatchingSelector';
4
4
  import { openSnackbar } from '../../../../../entity/snackbar/snackbarReducer';
5
- import { createZeniAPIStatus, isSuccessResponse } from '../../../../../responsePayload';
5
+ import { createZeniAPIStatus, isSuccessResponse, } from '../../../../../responsePayload';
6
6
  import { clearAll } from '../../../../../rootActions';
7
7
  import { toMatchAndReverseResult, } from '../../../payload/actualMatchingPayload';
8
8
  import { clearMatchNewModal, fetchActualMatchingMatch, matchAndReverseAccruals, matchAndReverseAccrualsFailure, matchAndReverseAccrualsSuccess, } from '../../../reducers/actualMatchingViewReducer';
9
9
  import { isMatchAndReverseCompleteStatus, } from '../../../types/actualMatchingViewState';
10
10
  import { refreshActualMatchingList } from './refreshActualMatchingList';
11
11
  function isMatchFailedStatus(status) {
12
- return (status === 'conflict' || status === 'claim_lost' || status === 'error');
12
+ return status === 'conflict' || status === 'claim_lost' || status === 'error';
13
13
  }
14
14
  function matchAndReverseSnackbar(results, vendorName) {
15
15
  const reversedCount = results.filter((result) => result.status === 'reversed').length;
@@ -56,12 +56,15 @@ function matchAndReverseHttpFailSnackbar(vendorName) {
56
56
  });
57
57
  }
58
58
  function matchVendorName(state, matchId) {
59
- return getActualMatchingMatchById(state.actualMatchingState, matchId)?.vendorName ?? '';
59
+ return (getActualMatchingMatchById(state.actualMatchingState, matchId)
60
+ ?.vendorName ?? '');
60
61
  }
61
62
  export const matchAndReverseAccrualsEpic = (actions$, state$, zeniAPI) => actions$.pipe(filter(matchAndReverseAccruals.match),
62
- // Posts reversing JEs; drop duplicate clicks while a request is in flight.
63
- exhaustMap((action) => {
64
- const { transactionId, transactionIntegrationId, transactionType, lineIds, accrualIds, transactionSyncToken, } = action.payload;
63
+ // Per-match exhaust: a second click on the same match drops while HTTP is in
64
+ // flight. A different match must still run — a global exhaustMap left the
65
+ // other match's reducer In-Progress with no request.
66
+ groupBy((action) => `${action.payload.transactionType.toLowerCase()}:${action.payload.transactionIntegrationId}`), mergeMap((perMatch$) => perMatch$.pipe(exhaustMap((action) => {
67
+ const { transactionId, transactionIntegrationId, transactionType, lineIds, accrualIds, transactionSyncToken, forMatchModal, } = action.payload;
65
68
  const body = {
66
69
  transaction_id: transactionId,
67
70
  transaction_integration_id: transactionIntegrationId,
@@ -80,7 +83,11 @@ exhaustMap((action) => {
80
83
  if (isSuccessResponse(response) && response.data != null) {
81
84
  const results = response.data.results.map(toMatchAndReverseResult);
82
85
  const successActions = [
83
- matchAndReverseAccrualsSuccess({ matchId, results }),
86
+ matchAndReverseAccrualsSuccess({
87
+ matchId,
88
+ results,
89
+ ...(forMatchModal === true ? { forMatchModal: true } : {}),
90
+ }),
84
91
  ];
85
92
  const occupancyChanged = results.some((result) => isMatchAndReverseCompleteStatus(result.status));
86
93
  const allComplete = results.length > 0 &&
@@ -95,7 +102,7 @@ exhaustMap((action) => {
95
102
  if (snackbar != null) {
96
103
  successActions.push(snackbar);
97
104
  }
98
- if (allComplete) {
105
+ if (allComplete && forMatchModal === true) {
99
106
  successActions.push(clearMatchNewModal());
100
107
  }
101
108
  return from(successActions);
@@ -103,10 +110,12 @@ exhaustMap((action) => {
103
110
  return of(matchAndReverseAccrualsFailure({
104
111
  status: response.status,
105
112
  matchId,
113
+ ...(forMatchModal === true ? { forMatchModal: true } : {}),
106
114
  }), matchAndReverseHttpFailSnackbar(vendorName));
107
115
  }), catchError((error) => of(matchAndReverseAccrualsFailure({
108
116
  matchId,
117
+ ...(forMatchModal === true ? { forMatchModal: true } : {}),
109
118
  status: createZeniAPIStatus('Unexpected Error', 'Match and reverse accruals REST API call errored out' +
110
119
  JSON.stringify(error)),
111
120
  }), matchAndReverseHttpFailSnackbar(vendorName))), takeUntil(actions$.pipe(filter(clearAll.match))));
112
- }));
121
+ }))));
@@ -47,14 +47,22 @@ export const initialState = {
47
47
  undoReversalStatusByMatchId: {},
48
48
  ignoreStatusByMatchId: {},
49
49
  confirmStatusByMatchId: {},
50
- closeMatchAfterUndoMatchId: undefined,
51
- closeMatchAfterIgnoreMatchId: undefined,
50
+ closeMatchAfterUndoMatchIds: [],
51
+ closeMatchAfterIgnoreMatchIds: [],
52
52
  lastMatchResultsByMatchId: {},
53
53
  lastUndoResultsByMatchId: {},
54
54
  hasValidState() {
55
55
  return this.fetchState == 'Completed';
56
56
  },
57
57
  };
58
+ function enqueueCloseMatchId(ids, matchId) {
59
+ if (!ids.includes(matchId)) {
60
+ ids.push(matchId);
61
+ }
62
+ }
63
+ function dropCloseMatchId(ids, matchId) {
64
+ return ids.filter((id) => id !== matchId);
65
+ }
58
66
  function pruneLastMatchResultsForUndone(draft, matchId, results) {
59
67
  const undoneIds = new Set(results
60
68
  .filter((result) => result.status === 'undone')
@@ -355,11 +363,13 @@ const expenseAutomationActualMatchingView = createSlice({
355
363
  fetchState: 'In-Progress',
356
364
  error: undefined,
357
365
  };
358
- draft.matchModal.confirmStatus = inProgress;
366
+ if (action.payload.forMatchModal === true) {
367
+ draft.matchModal.confirmStatus = inProgress;
368
+ }
359
369
  const matchId = `${action.payload.transactionType.toLowerCase()}:${action.payload.transactionIntegrationId}`;
360
370
  draft.confirmStatusByMatchId[matchId] = inProgress;
361
371
  },
362
- prepare(transactionId, transactionIntegrationId, transactionType, lineIds, transactionSyncToken, accrualIds) {
372
+ prepare(transactionId, transactionIntegrationId, transactionType, lineIds, transactionSyncToken, accrualIds, forMatchModal) {
363
373
  return {
364
374
  payload: {
365
375
  accrualIds,
@@ -368,6 +378,7 @@ const expenseAutomationActualMatchingView = createSlice({
368
378
  transactionIntegrationId,
369
379
  transactionSyncToken,
370
380
  transactionType,
381
+ forMatchModal,
371
382
  },
372
383
  };
373
384
  },
@@ -376,16 +387,18 @@ const expenseAutomationActualMatchingView = createSlice({
376
387
  const { results } = action.payload;
377
388
  const allComplete = results.length > 0 &&
378
389
  results.every((result) => isMatchAndReverseCompleteStatus(result.status));
379
- draft.matchModal.confirmStatus = allComplete
390
+ const confirmStatus = allComplete
380
391
  ? { fetchState: 'Completed', error: undefined }
381
392
  : {
382
393
  fetchState: 'Error',
383
394
  error: createZeniAPIStatus('Partial match-and-reverse', 'Some accruals were not reversed'),
384
395
  };
385
- draft.matchModal.lastBatchResults = results;
396
+ if (action.payload.forMatchModal === true) {
397
+ draft.matchModal.confirmStatus = confirmStatus;
398
+ draft.matchModal.lastBatchResults = results;
399
+ }
386
400
  if (action.payload.matchId != null) {
387
- draft.confirmStatusByMatchId[action.payload.matchId] =
388
- draft.matchModal.confirmStatus;
401
+ draft.confirmStatusByMatchId[action.payload.matchId] = confirmStatus;
389
402
  draft.lastMatchResultsByMatchId[action.payload.matchId] = results;
390
403
  pruneLastUndoResultsForMatched(draft, action.payload.matchId, action.payload.results);
391
404
  }
@@ -395,7 +408,9 @@ const expenseAutomationActualMatchingView = createSlice({
395
408
  fetchState: 'Error',
396
409
  error: action.payload.status,
397
410
  };
398
- draft.matchModal.confirmStatus = failed;
411
+ if (action.payload.forMatchModal === true) {
412
+ draft.matchModal.confirmStatus = failed;
413
+ }
399
414
  if (action.payload.matchId != null) {
400
415
  draft.confirmStatusByMatchId[action.payload.matchId] = failed;
401
416
  }
@@ -420,7 +435,12 @@ const expenseAutomationActualMatchingView = createSlice({
420
435
  };
421
436
  const allUndone = results.length > 0 &&
422
437
  results.every((result) => result.status === 'undone');
423
- draft.closeMatchAfterUndoMatchId = allUndone ? matchId : undefined;
438
+ if (allUndone) {
439
+ enqueueCloseMatchId(draft.closeMatchAfterUndoMatchIds, matchId);
440
+ }
441
+ else {
442
+ draft.closeMatchAfterUndoMatchIds = dropCloseMatchId(draft.closeMatchAfterUndoMatchIds, matchId);
443
+ }
424
444
  pruneLastMatchResultsForUndone(draft, matchId, results);
425
445
  if (allUndone) {
426
446
  delete draft.lastUndoResultsByMatchId[matchId];
@@ -434,7 +454,7 @@ const expenseAutomationActualMatchingView = createSlice({
434
454
  },
435
455
  },
436
456
  ackCloseMatchAfterUndo(draft) {
437
- draft.closeMatchAfterUndoMatchId = undefined;
457
+ draft.closeMatchAfterUndoMatchIds.shift();
438
458
  },
439
459
  ignoreActualMatchingSuggestion: {
440
460
  prepare(matchId, reason, note) {
@@ -453,7 +473,7 @@ const expenseAutomationActualMatchingView = createSlice({
453
473
  fetchState: 'Completed',
454
474
  error: undefined,
455
475
  };
456
- draft.closeMatchAfterIgnoreMatchId = matchId;
476
+ enqueueCloseMatchId(draft.closeMatchAfterIgnoreMatchIds, matchId);
457
477
  delete draft.lastMatchResultsByMatchId[matchId];
458
478
  delete draft.lastUndoResultsByMatchId[matchId];
459
479
  delete draft.detailFetchStateByMatchId[matchId];
@@ -471,7 +491,7 @@ const expenseAutomationActualMatchingView = createSlice({
471
491
  };
472
492
  },
473
493
  ackCloseMatchAfterIgnore(draft) {
474
- draft.closeMatchAfterIgnoreMatchId = undefined;
494
+ draft.closeMatchAfterIgnoreMatchIds.shift();
475
495
  },
476
496
  undoReversalAccrualsFailure(draft, action) {
477
497
  draft.undoReversalStatusByMatchId[action.payload.matchId] = {
@@ -334,14 +334,15 @@ export function getExpenseAutomationActualMatchingMatchView(state, matchId) {
334
334
  return selector(state);
335
335
  }
336
336
  export function getCloseMatchAfterUndo(state) {
337
- return state.expenseAutomationActualMatchingViewState.closeMatchAfterUndoMatchId;
337
+ return state.expenseAutomationActualMatchingViewState
338
+ .closeMatchAfterUndoMatchIds[0];
338
339
  }
339
340
  export function getCloseMatchAfterUndoMatchId(state) {
340
341
  return getCloseMatchAfterUndo(state);
341
342
  }
342
343
  export function getCloseMatchAfterIgnoreMatchId(state) {
343
344
  return state.expenseAutomationActualMatchingViewState
344
- .closeMatchAfterIgnoreMatchId;
345
+ .closeMatchAfterIgnoreMatchIds[0];
345
346
  }
346
347
  export function getActualMatchingMatchModalConfirmStatus(state, matchId) {
347
348
  if (matchId != null && matchId !== '') {
@@ -625,7 +625,7 @@ export const getDueDate = (billStageCode, dueDate, invoiceDate, bookCloseDate) =
625
625
  }
626
626
  };
627
627
  export const getWithdrawFrom = (state, fromAccountId, fromAccountType, companyId, lastSelectedFromAccount) => {
628
- const { paymentAccountState, depositAccountState, depositAccountListState, paymentAccountListState, } = state;
628
+ const { paymentAccountState, depositAccountState, paymentAccountListState } = state;
629
629
  if (fromAccountId != null) {
630
630
  const withdrawFromAsDepositAcc = getDepositAccountByDepositAccountId(depositAccountState, fromAccountId);
631
631
  const withdrawFromAsPaymentAcc = getPaymentAccountByPaymentAccountId(paymentAccountState, fromAccountId);
@@ -639,41 +639,15 @@ export const getWithdrawFrom = (state, fromAccountId, fromAccountType, companyId
639
639
  }
640
640
  }
641
641
  else {
642
- return getDefaultWithdrawFromAccount(state, depositAccountListState.accountIds, companyId ?? '', lastSelectedFromAccount);
642
+ return getDefaultWithdrawFromAccount(state, companyId ?? '', lastSelectedFromAccount);
643
643
  }
644
644
  return undefined;
645
645
  };
646
- export const getDefaultWithdrawFromAccount = (state, depositAccounts, companyId, lastSelectedFromAccount) => {
646
+ export const getDefaultWithdrawFromAccount = (state, companyId, lastSelectedFromAccount) => {
647
647
  const { depositAccountState, paymentAccountState, paymentAccountListState } = state;
648
648
  const companyView = getCompanyView(state, companyId, []);
649
649
  const primaryAccount = companyView?.company.company.companyBillPayInfo.primaryFundingAccount;
650
- let defaultAccount = undefined;
651
- // User paying bill for first time or previously paid with external account
652
- if (lastSelectedFromAccount == null ||
653
- lastSelectedFromAccount?.accountType === 'paymentAccount') {
654
- if (depositAccounts.length === 0) {
655
- defaultAccount = primaryAccount;
656
- }
657
- else {
658
- if (primaryAccount?.accountType === 'depositAccount') {
659
- defaultAccount = primaryAccount;
660
- }
661
- }
662
- }
663
- else {
664
- // User paid with Zeni account previously
665
- if (depositAccounts.length === 1) {
666
- defaultAccount = lastSelectedFromAccount;
667
- }
668
- else {
669
- if (primaryAccount?.accountType === 'depositAccount') {
670
- defaultAccount = primaryAccount;
671
- }
672
- else {
673
- defaultAccount = lastSelectedFromAccount;
674
- }
675
- }
676
- }
650
+ const defaultAccount = primaryAccount ?? lastSelectedFromAccount;
677
651
  if (defaultAccount != null) {
678
652
  const defaultAccAsDepositAcc = getDepositAccountByDepositAccountId(depositAccountState, defaultAccount?.accountId);
679
653
  const defaultAccAsPaymentAcc = getPaymentAccountByPaymentAccountId(paymentAccountState, defaultAccount?.accountId);
@@ -1,12 +1,12 @@
1
1
  import { ActionsObservable, StateObservable } from 'redux-observable';
2
2
  import { Observable } from 'rxjs';
3
3
  import { ActualMatchingMatchPayload } from '../../../../../entity/actualMatching/actualMatchingPayload';
4
- import { updateActualMatchingMatches } from '../../../../../entity/actualMatching/actualMatchingReducer';
4
+ import { removeActualMatchingMatch, updateActualMatchingMatches } from '../../../../../entity/actualMatching/actualMatchingReducer';
5
5
  import { ZeniAPIResponse } from '../../../../../responsePayload';
6
6
  import { clearAll } from '../../../../../rootActions';
7
7
  import { RootState } from '../../../../../rootStateTypes';
8
8
  import { ZeniAPI } from '../../../../../zeniAPI';
9
9
  import { fetchActualMatchingMatch, fetchActualMatchingMatchFailure, fetchActualMatchingMatchSuccess } from '../../../reducers/actualMatchingViewReducer';
10
10
  export type ActualMatchingMatchResponse = ZeniAPIResponse<ActualMatchingMatchPayload>;
11
- export type ActionType = ReturnType<typeof clearAll> | ReturnType<typeof fetchActualMatchingMatch> | ReturnType<typeof fetchActualMatchingMatchFailure> | ReturnType<typeof fetchActualMatchingMatchSuccess> | ReturnType<typeof updateActualMatchingMatches>;
11
+ export type ActionType = ReturnType<typeof clearAll> | ReturnType<typeof fetchActualMatchingMatch> | ReturnType<typeof fetchActualMatchingMatchFailure> | ReturnType<typeof fetchActualMatchingMatchSuccess> | ReturnType<typeof removeActualMatchingMatch> | ReturnType<typeof updateActualMatchingMatches>;
12
12
  export declare const fetchActualMatchingMatchEpic: (actions$: ActionsObservable<ActionType>, state$: StateObservable<RootState>, zeniAPI: ZeniAPI) => Observable<ActionType>;
@@ -35,6 +35,8 @@ const fetchActualMatchingMatchEpic = (actions$, state$, zeniAPI) => actions$.pip
35
35
  refreshViewInBackground,
36
36
  status: (0, responsePayload_1.createZeniAPIStatus)('Unexpected Error', `Fetch actual matching match REST API call errored out ${JSON.stringify(error)}`),
37
37
  }),
38
- ])), (0, operators_1.takeUntil)(actions$.pipe((0, operators_1.filter)(rootActions_1.clearAll.match))));
38
+ ])), (0, operators_1.takeUntil)(actions$.pipe((0, operators_1.filter)((action) => rootActions_1.clearAll.match(action) ||
39
+ (actualMatchingReducer_1.removeActualMatchingMatch.match(action) &&
40
+ action.payload.matchId === matchId)))));
39
41
  }));
40
42
  exports.fetchActualMatchingMatchEpic = fetchActualMatchingMatchEpic;
@@ -12,7 +12,7 @@ const actualMatchingViewReducer_1 = require("../../../reducers/actualMatchingVie
12
12
  const actualMatchingViewState_1 = require("../../../types/actualMatchingViewState");
13
13
  const refreshActualMatchingList_1 = require("./refreshActualMatchingList");
14
14
  function isMatchFailedStatus(status) {
15
- return (status === 'conflict' || status === 'claim_lost' || status === 'error');
15
+ return status === 'conflict' || status === 'claim_lost' || status === 'error';
16
16
  }
17
17
  function matchAndReverseSnackbar(results, vendorName) {
18
18
  const reversedCount = results.filter((result) => result.status === 'reversed').length;
@@ -59,12 +59,15 @@ function matchAndReverseHttpFailSnackbar(vendorName) {
59
59
  });
60
60
  }
61
61
  function matchVendorName(state, matchId) {
62
- return (0, actualMatchingSelector_1.getActualMatchingMatchById)(state.actualMatchingState, matchId)?.vendorName ?? '';
62
+ return ((0, actualMatchingSelector_1.getActualMatchingMatchById)(state.actualMatchingState, matchId)
63
+ ?.vendorName ?? '');
63
64
  }
64
65
  const matchAndReverseAccrualsEpic = (actions$, state$, zeniAPI) => actions$.pipe((0, operators_1.filter)(actualMatchingViewReducer_1.matchAndReverseAccruals.match),
65
- // Posts reversing JEs; drop duplicate clicks while a request is in flight.
66
- (0, operators_1.exhaustMap)((action) => {
67
- const { transactionId, transactionIntegrationId, transactionType, lineIds, accrualIds, transactionSyncToken, } = action.payload;
66
+ // Per-match exhaust: a second click on the same match drops while HTTP is in
67
+ // flight. A different match must still run — a global exhaustMap left the
68
+ // other match's reducer In-Progress with no request.
69
+ (0, operators_1.groupBy)((action) => `${action.payload.transactionType.toLowerCase()}:${action.payload.transactionIntegrationId}`), (0, operators_1.mergeMap)((perMatch$) => perMatch$.pipe((0, operators_1.exhaustMap)((action) => {
70
+ const { transactionId, transactionIntegrationId, transactionType, lineIds, accrualIds, transactionSyncToken, forMatchModal, } = action.payload;
68
71
  const body = {
69
72
  transaction_id: transactionId,
70
73
  transaction_integration_id: transactionIntegrationId,
@@ -83,7 +86,11 @@ const matchAndReverseAccrualsEpic = (actions$, state$, zeniAPI) => actions$.pipe
83
86
  if ((0, responsePayload_1.isSuccessResponse)(response) && response.data != null) {
84
87
  const results = response.data.results.map(actualMatchingPayload_1.toMatchAndReverseResult);
85
88
  const successActions = [
86
- (0, actualMatchingViewReducer_1.matchAndReverseAccrualsSuccess)({ matchId, results }),
89
+ (0, actualMatchingViewReducer_1.matchAndReverseAccrualsSuccess)({
90
+ matchId,
91
+ results,
92
+ ...(forMatchModal === true ? { forMatchModal: true } : {}),
93
+ }),
87
94
  ];
88
95
  const occupancyChanged = results.some((result) => (0, actualMatchingViewState_1.isMatchAndReverseCompleteStatus)(result.status));
89
96
  const allComplete = results.length > 0 &&
@@ -98,7 +105,7 @@ const matchAndReverseAccrualsEpic = (actions$, state$, zeniAPI) => actions$.pipe
98
105
  if (snackbar != null) {
99
106
  successActions.push(snackbar);
100
107
  }
101
- if (allComplete) {
108
+ if (allComplete && forMatchModal === true) {
102
109
  successActions.push((0, actualMatchingViewReducer_1.clearMatchNewModal)());
103
110
  }
104
111
  return (0, rxjs_1.from)(successActions);
@@ -106,11 +113,13 @@ const matchAndReverseAccrualsEpic = (actions$, state$, zeniAPI) => actions$.pipe
106
113
  return (0, rxjs_1.of)((0, actualMatchingViewReducer_1.matchAndReverseAccrualsFailure)({
107
114
  status: response.status,
108
115
  matchId,
116
+ ...(forMatchModal === true ? { forMatchModal: true } : {}),
109
117
  }), matchAndReverseHttpFailSnackbar(vendorName));
110
118
  }), (0, operators_1.catchError)((error) => (0, rxjs_1.of)((0, actualMatchingViewReducer_1.matchAndReverseAccrualsFailure)({
111
119
  matchId,
120
+ ...(forMatchModal === true ? { forMatchModal: true } : {}),
112
121
  status: (0, responsePayload_1.createZeniAPIStatus)('Unexpected Error', 'Match and reverse accruals REST API call errored out' +
113
122
  JSON.stringify(error)),
114
123
  }), matchAndReverseHttpFailSnackbar(vendorName))), (0, operators_1.takeUntil)(actions$.pipe((0, operators_1.filter)(rootActions_1.clearAll.match))));
115
- }));
124
+ }))));
116
125
  exports.matchAndReverseAccrualsEpic = matchAndReverseAccrualsEpic;
@@ -40,18 +40,21 @@ export declare const ackCloseMatchAfterIgnore: import("@reduxjs/toolkit").Action
40
40
  status: ZeniAPIStatus;
41
41
  }, "expenseAutomationActualMatchingView/ignoreActualMatchingSuggestionFailure">, ignoreActualMatchingSuggestionSuccess: import("@reduxjs/toolkit").ActionCreatorWithPayload<{
42
42
  matchId: ActualMatchingMatchId;
43
- }, "expenseAutomationActualMatchingView/ignoreActualMatchingSuggestionSuccess">, matchAndReverseAccruals: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[transactionId: string, transactionIntegrationId: string, transactionType: string, lineIds: string[], transactionSyncToken: string, accrualIds: string[]], {
43
+ }, "expenseAutomationActualMatchingView/ignoreActualMatchingSuggestionSuccess">, matchAndReverseAccruals: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[transactionId: string, transactionIntegrationId: string, transactionType: string, lineIds: string[], transactionSyncToken: string, accrualIds: string[], forMatchModal?: boolean | undefined], {
44
44
  accrualIds: string[];
45
45
  lineIds: string[];
46
46
  transactionId: string;
47
47
  transactionIntegrationId: string;
48
48
  transactionSyncToken: string;
49
49
  transactionType: string;
50
+ forMatchModal: boolean | undefined;
50
51
  }, "expenseAutomationActualMatchingView/matchAndReverseAccruals", never, never>, matchAndReverseAccrualsFailure: import("@reduxjs/toolkit").ActionCreatorWithPayload<{
51
52
  status: ZeniAPIStatus;
53
+ forMatchModal?: boolean;
52
54
  matchId?: ActualMatchingMatchId;
53
55
  }, "expenseAutomationActualMatchingView/matchAndReverseAccrualsFailure">, matchAndReverseAccrualsSuccess: import("@reduxjs/toolkit").ActionCreatorWithPayload<{
54
56
  results: MatchAndReverseResult[];
57
+ forMatchModal?: boolean;
55
58
  matchId?: ActualMatchingMatchId;
56
59
  }, "expenseAutomationActualMatchingView/matchAndReverseAccrualsSuccess">, openMatchNewModal: import("@reduxjs/toolkit").ActionCreatorWithoutPayload<"expenseAutomationActualMatchingView/openMatchNewModal">, searchMatchAccruals: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[query: string, pageToken?: string | null | undefined], {
57
60
  query: string;
@@ -51,14 +51,22 @@ exports.initialState = {
51
51
  undoReversalStatusByMatchId: {},
52
52
  ignoreStatusByMatchId: {},
53
53
  confirmStatusByMatchId: {},
54
- closeMatchAfterUndoMatchId: undefined,
55
- closeMatchAfterIgnoreMatchId: undefined,
54
+ closeMatchAfterUndoMatchIds: [],
55
+ closeMatchAfterIgnoreMatchIds: [],
56
56
  lastMatchResultsByMatchId: {},
57
57
  lastUndoResultsByMatchId: {},
58
58
  hasValidState() {
59
59
  return this.fetchState == 'Completed';
60
60
  },
61
61
  };
62
+ function enqueueCloseMatchId(ids, matchId) {
63
+ if (!ids.includes(matchId)) {
64
+ ids.push(matchId);
65
+ }
66
+ }
67
+ function dropCloseMatchId(ids, matchId) {
68
+ return ids.filter((id) => id !== matchId);
69
+ }
62
70
  function pruneLastMatchResultsForUndone(draft, matchId, results) {
63
71
  const undoneIds = new Set(results
64
72
  .filter((result) => result.status === 'undone')
@@ -359,11 +367,13 @@ const expenseAutomationActualMatchingView = (0, toolkit_1.createSlice)({
359
367
  fetchState: 'In-Progress',
360
368
  error: undefined,
361
369
  };
362
- draft.matchModal.confirmStatus = inProgress;
370
+ if (action.payload.forMatchModal === true) {
371
+ draft.matchModal.confirmStatus = inProgress;
372
+ }
363
373
  const matchId = `${action.payload.transactionType.toLowerCase()}:${action.payload.transactionIntegrationId}`;
364
374
  draft.confirmStatusByMatchId[matchId] = inProgress;
365
375
  },
366
- prepare(transactionId, transactionIntegrationId, transactionType, lineIds, transactionSyncToken, accrualIds) {
376
+ prepare(transactionId, transactionIntegrationId, transactionType, lineIds, transactionSyncToken, accrualIds, forMatchModal) {
367
377
  return {
368
378
  payload: {
369
379
  accrualIds,
@@ -372,6 +382,7 @@ const expenseAutomationActualMatchingView = (0, toolkit_1.createSlice)({
372
382
  transactionIntegrationId,
373
383
  transactionSyncToken,
374
384
  transactionType,
385
+ forMatchModal,
375
386
  },
376
387
  };
377
388
  },
@@ -380,16 +391,18 @@ const expenseAutomationActualMatchingView = (0, toolkit_1.createSlice)({
380
391
  const { results } = action.payload;
381
392
  const allComplete = results.length > 0 &&
382
393
  results.every((result) => (0, actualMatchingViewState_1.isMatchAndReverseCompleteStatus)(result.status));
383
- draft.matchModal.confirmStatus = allComplete
394
+ const confirmStatus = allComplete
384
395
  ? { fetchState: 'Completed', error: undefined }
385
396
  : {
386
397
  fetchState: 'Error',
387
398
  error: (0, responsePayload_1.createZeniAPIStatus)('Partial match-and-reverse', 'Some accruals were not reversed'),
388
399
  };
389
- draft.matchModal.lastBatchResults = results;
400
+ if (action.payload.forMatchModal === true) {
401
+ draft.matchModal.confirmStatus = confirmStatus;
402
+ draft.matchModal.lastBatchResults = results;
403
+ }
390
404
  if (action.payload.matchId != null) {
391
- draft.confirmStatusByMatchId[action.payload.matchId] =
392
- draft.matchModal.confirmStatus;
405
+ draft.confirmStatusByMatchId[action.payload.matchId] = confirmStatus;
393
406
  draft.lastMatchResultsByMatchId[action.payload.matchId] = results;
394
407
  pruneLastUndoResultsForMatched(draft, action.payload.matchId, action.payload.results);
395
408
  }
@@ -399,7 +412,9 @@ const expenseAutomationActualMatchingView = (0, toolkit_1.createSlice)({
399
412
  fetchState: 'Error',
400
413
  error: action.payload.status,
401
414
  };
402
- draft.matchModal.confirmStatus = failed;
415
+ if (action.payload.forMatchModal === true) {
416
+ draft.matchModal.confirmStatus = failed;
417
+ }
403
418
  if (action.payload.matchId != null) {
404
419
  draft.confirmStatusByMatchId[action.payload.matchId] = failed;
405
420
  }
@@ -424,7 +439,12 @@ const expenseAutomationActualMatchingView = (0, toolkit_1.createSlice)({
424
439
  };
425
440
  const allUndone = results.length > 0 &&
426
441
  results.every((result) => result.status === 'undone');
427
- draft.closeMatchAfterUndoMatchId = allUndone ? matchId : undefined;
442
+ if (allUndone) {
443
+ enqueueCloseMatchId(draft.closeMatchAfterUndoMatchIds, matchId);
444
+ }
445
+ else {
446
+ draft.closeMatchAfterUndoMatchIds = dropCloseMatchId(draft.closeMatchAfterUndoMatchIds, matchId);
447
+ }
428
448
  pruneLastMatchResultsForUndone(draft, matchId, results);
429
449
  if (allUndone) {
430
450
  delete draft.lastUndoResultsByMatchId[matchId];
@@ -438,7 +458,7 @@ const expenseAutomationActualMatchingView = (0, toolkit_1.createSlice)({
438
458
  },
439
459
  },
440
460
  ackCloseMatchAfterUndo(draft) {
441
- draft.closeMatchAfterUndoMatchId = undefined;
461
+ draft.closeMatchAfterUndoMatchIds.shift();
442
462
  },
443
463
  ignoreActualMatchingSuggestion: {
444
464
  prepare(matchId, reason, note) {
@@ -457,7 +477,7 @@ const expenseAutomationActualMatchingView = (0, toolkit_1.createSlice)({
457
477
  fetchState: 'Completed',
458
478
  error: undefined,
459
479
  };
460
- draft.closeMatchAfterIgnoreMatchId = matchId;
480
+ enqueueCloseMatchId(draft.closeMatchAfterIgnoreMatchIds, matchId);
461
481
  delete draft.lastMatchResultsByMatchId[matchId];
462
482
  delete draft.lastUndoResultsByMatchId[matchId];
463
483
  delete draft.detailFetchStateByMatchId[matchId];
@@ -475,7 +495,7 @@ const expenseAutomationActualMatchingView = (0, toolkit_1.createSlice)({
475
495
  };
476
496
  },
477
497
  ackCloseMatchAfterIgnore(draft) {
478
- draft.closeMatchAfterIgnoreMatchId = undefined;
498
+ draft.closeMatchAfterIgnoreMatchIds.shift();
479
499
  },
480
500
  undoReversalAccrualsFailure(draft, action) {
481
501
  draft.undoReversalStatusByMatchId[action.payload.matchId] = {
@@ -356,14 +356,15 @@ function getExpenseAutomationActualMatchingMatchView(state, matchId) {
356
356
  return selector(state);
357
357
  }
358
358
  function getCloseMatchAfterUndo(state) {
359
- return state.expenseAutomationActualMatchingViewState.closeMatchAfterUndoMatchId;
359
+ return state.expenseAutomationActualMatchingViewState
360
+ .closeMatchAfterUndoMatchIds[0];
360
361
  }
361
362
  function getCloseMatchAfterUndoMatchId(state) {
362
363
  return getCloseMatchAfterUndo(state);
363
364
  }
364
365
  function getCloseMatchAfterIgnoreMatchId(state) {
365
366
  return state.expenseAutomationActualMatchingViewState
366
- .closeMatchAfterIgnoreMatchId;
367
+ .closeMatchAfterIgnoreMatchIds[0];
367
368
  }
368
369
  function getActualMatchingMatchModalConfirmStatus(state, matchId) {
369
370
  if (matchId != null && matchId !== '') {
@@ -106,6 +106,8 @@ export interface ActualMatchingMatchModalState {
106
106
  }
107
107
  export declare function actualMatchingTransactionLineKey(transactionType: string, transactionIntegrationId: string, lineId: string): string;
108
108
  export interface ActualMatchingViewState extends FetchedState {
109
+ closeMatchAfterIgnoreMatchIds: ActualMatchingMatchId[];
110
+ closeMatchAfterUndoMatchIds: ActualMatchingMatchId[];
109
111
  confirmStatusByMatchId: Record<ActualMatchingMatchId, FetchStateAndError>;
110
112
  detailFetchStateByMatchId: Record<ActualMatchingMatchId, FetchStateAndError>;
111
113
  detailRefreshStatusByMatchId: Record<ActualMatchingMatchId, FetchStateAndError>;
@@ -117,6 +119,4 @@ export interface ActualMatchingViewState extends FetchedState {
117
119
  refreshStatus: FetchStateAndError;
118
120
  uiState: ActualMatchingViewUIState;
119
121
  undoReversalStatusByMatchId: Record<ActualMatchingMatchId, FetchStateAndError>;
120
- closeMatchAfterIgnoreMatchId?: ActualMatchingMatchId;
121
- closeMatchAfterUndoMatchId?: ActualMatchingMatchId;
122
122
  }
@@ -141,7 +141,7 @@ export declare const getWithdrawFrom: (state: RootState, fromAccountId?: ID, fro
141
141
  accountId: ID;
142
142
  accountType: AccountTypeSubConfigCodeKeyType;
143
143
  }) => FundingAccount | undefined;
144
- export declare const getDefaultWithdrawFromAccount: (state: RootState, depositAccounts: ID[], companyId: ID, lastSelectedFromAccount?: {
144
+ export declare const getDefaultWithdrawFromAccount: (state: RootState, companyId: ID, lastSelectedFromAccount?: {
145
145
  accountId: ID;
146
146
  accountType: AccountTypeSubConfigCodeKeyType;
147
147
  }) => FundingAccount | undefined;
@@ -640,7 +640,7 @@ const getDueDate = (billStageCode, dueDate, invoiceDate, bookCloseDate) => {
640
640
  };
641
641
  exports.getDueDate = getDueDate;
642
642
  const getWithdrawFrom = (state, fromAccountId, fromAccountType, companyId, lastSelectedFromAccount) => {
643
- const { paymentAccountState, depositAccountState, depositAccountListState, paymentAccountListState, } = state;
643
+ const { paymentAccountState, depositAccountState, paymentAccountListState } = state;
644
644
  if (fromAccountId != null) {
645
645
  const withdrawFromAsDepositAcc = (0, depositAccountSelector_1.getDepositAccountByDepositAccountId)(depositAccountState, fromAccountId);
646
646
  const withdrawFromAsPaymentAcc = (0, paymentAccountSelector_1.getPaymentAccountByPaymentAccountId)(paymentAccountState, fromAccountId);
@@ -654,42 +654,16 @@ const getWithdrawFrom = (state, fromAccountId, fromAccountType, companyId, lastS
654
654
  }
655
655
  }
656
656
  else {
657
- return (0, exports.getDefaultWithdrawFromAccount)(state, depositAccountListState.accountIds, companyId ?? '', lastSelectedFromAccount);
657
+ return (0, exports.getDefaultWithdrawFromAccount)(state, companyId ?? '', lastSelectedFromAccount);
658
658
  }
659
659
  return undefined;
660
660
  };
661
661
  exports.getWithdrawFrom = getWithdrawFrom;
662
- const getDefaultWithdrawFromAccount = (state, depositAccounts, companyId, lastSelectedFromAccount) => {
662
+ const getDefaultWithdrawFromAccount = (state, companyId, lastSelectedFromAccount) => {
663
663
  const { depositAccountState, paymentAccountState, paymentAccountListState } = state;
664
664
  const companyView = (0, getCompanyView_1.getCompanyView)(state, companyId, []);
665
665
  const primaryAccount = companyView?.company.company.companyBillPayInfo.primaryFundingAccount;
666
- let defaultAccount = undefined;
667
- // User paying bill for first time or previously paid with external account
668
- if (lastSelectedFromAccount == null ||
669
- lastSelectedFromAccount?.accountType === 'paymentAccount') {
670
- if (depositAccounts.length === 0) {
671
- defaultAccount = primaryAccount;
672
- }
673
- else {
674
- if (primaryAccount?.accountType === 'depositAccount') {
675
- defaultAccount = primaryAccount;
676
- }
677
- }
678
- }
679
- else {
680
- // User paid with Zeni account previously
681
- if (depositAccounts.length === 1) {
682
- defaultAccount = lastSelectedFromAccount;
683
- }
684
- else {
685
- if (primaryAccount?.accountType === 'depositAccount') {
686
- defaultAccount = primaryAccount;
687
- }
688
- else {
689
- defaultAccount = lastSelectedFromAccount;
690
- }
691
- }
692
- }
666
+ const defaultAccount = primaryAccount ?? lastSelectedFromAccount;
693
667
  if (defaultAccount != null) {
694
668
  const defaultAccAsDepositAcc = (0, depositAccountSelector_1.getDepositAccountByDepositAccountId)(depositAccountState, defaultAccount?.accountId);
695
669
  const defaultAccAsPaymentAcc = (0, paymentAccountSelector_1.getPaymentAccountByPaymentAccountId)(paymentAccountState, defaultAccount?.accountId);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zeniai/client-epic-state",
3
- "version": "5.2.62-beta0MM",
3
+ "version": "5.2.62-beta1MM",
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",