@zeniai/client-epic-state 4.19.46 → 4.19.47

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.
@@ -30,6 +30,34 @@ export const removeTransactionFromTabView = (tabView, transactionId) => {
30
30
  tabView.transactionIdsWithUnsavedData =
31
31
  tabView.transactionIdsWithUnsavedData.filter((id) => id !== transactionId);
32
32
  };
33
+ /**
34
+ * Filters the autoCategorized tab's line items for a transaction, retaining only
35
+ * lines whose categorizationStatus is still `auto_reviewed` or `auto_categorized`.
36
+ * If no lines are retained, removes the transaction from the tab entirely.
37
+ * Intended for use within Immer reducer drafts (mutates in place).
38
+ */
39
+ export const filterAutoTabLineItems = (tabView, transactionId, updatedTransaction) => {
40
+ const localData = tabView.transactionReviewLocalDataById[transactionId];
41
+ if (localData == null) {
42
+ return;
43
+ }
44
+ const currentAutoLineIds = localData.transactionReviewLocalData.tabSpecificLineItems
45
+ .autoCategorized ?? [];
46
+ const linesById = new Map(updatedTransaction.lines?.map((l) => [l.id, l]));
47
+ const retainedLineIds = currentAutoLineIds.filter((lineId) => {
48
+ const line = linesById.get(lineId);
49
+ return (line?.categorizationStatus === 'auto_reviewed' ||
50
+ line?.categorizationStatus === 'auto_categorized');
51
+ });
52
+ if (retainedLineIds.length === 0) {
53
+ removeTransactionFromTabView(tabView, transactionId);
54
+ }
55
+ else {
56
+ localData.transactionReviewLocalData.tabSpecificLineItems = {
57
+ autoCategorized: retainedLineIds,
58
+ };
59
+ }
60
+ };
33
61
  export const MAX_SELECTION_LIMIT = 5;
34
62
  export const toTransactionDetailLocalData = (transaction, selectedTab, lineItemsByTransactionIds, uncategorizedIncomeExpense, isUncategorizedExpenseCategoryEnabled) => {
35
63
  const transactionLocal = {
@@ -3,7 +3,7 @@ import recordGet from 'lodash/get';
3
3
  import uniq from 'lodash/uniq';
4
4
  import { toMonthYearPeriodId, } from '../../../commonStateTypes/timePeriod';
5
5
  import { isVendorTransaction } from '../../../entity/transaction/stateTypes/vendorTransaction';
6
- import { MAX_SELECTION_LIMIT, checkIfAllLineItemsAreCategoryClassFilled, mergeTabSpecificLineItems, removeTransactionFromTabView, setEntityRecommendationForLineIdInLocalData, toSetAllLineItemsToCategoryClass, toTransactionDetailLocalData, } from '../helpers/transactionCategorizationLocalDataHelper';
6
+ import { MAX_SELECTION_LIMIT, checkIfAllLineItemsAreCategoryClassFilled, filterAutoTabLineItems, mergeTabSpecificLineItems, removeTransactionFromTabView, setEntityRecommendationForLineIdInLocalData, toSetAllLineItemsToCategoryClass, toTransactionDetailLocalData, } from '../helpers/transactionCategorizationLocalDataHelper';
7
7
  export const initialTransactionTabViewState = {
8
8
  saveStatus: {
9
9
  fetchState: 'Not-Started',
@@ -721,24 +721,18 @@ const expenseAutomationTransactionsView = createSlice({
721
721
  if (!existsInReview && !existsInAuto) {
722
722
  return;
723
723
  }
724
+ // Auto tab: retain only lines still auto_reviewed or auto_categorized
725
+ if (existsInAuto) {
726
+ filterAutoTabLineItems(autoTabView, txnId, updatedTransaction);
727
+ }
724
728
  const allReviewed = pendingReviewLineIds.length === 0;
725
729
  if (allReviewed) {
726
730
  if (existsInReview) {
727
731
  removeTransactionFromTabView(reviewTabView, txnId);
728
732
  }
729
- if (existsInAuto) {
730
- removeTransactionFromTabView(autoTabView, txnId);
731
- }
732
733
  return;
733
734
  }
734
- // Partially reviewed auto-only: remove transaction from auto tab entirely
735
- // since pending_review lines don't belong in auto tab and review_complete lines are done
736
- const isAutoOnly = existsInAuto && !existsInReview;
737
- if (isAutoOnly) {
738
- removeTransactionFromTabView(autoTabView, txnId);
739
- return;
740
- }
741
- // Review-only or both-tabs: rebuild review tab local data with pending review lines
735
+ // Partially reviewed: rebuild review tab local data with pending review lines
742
736
  if (existsInReview) {
743
737
  const newLocalData = toTransactionDetailLocalData(updatedTransaction, 'review', pendingReviewLineIds, uncategorizedIncomeExpense, isUncategorizedExpenseCategoryEnabled);
744
738
  reviewTabView.transactionReviewLocalDataById[txnId] = {
@@ -756,10 +750,6 @@ const expenseAutomationTransactionsView = createSlice({
756
750
  reviewTabView.transactionIdsWithUnsavedData =
757
751
  reviewTabView.transactionIdsWithUnsavedData.filter((id) => id !== txnId);
758
752
  }
759
- // If both tabs, remove from auto tab entirely
760
- if (existsInAuto) {
761
- removeTransactionFromTabView(autoTabView, txnId);
762
- }
763
753
  },
764
754
  },
765
755
  backgroundRefetchReviewTab: {
@@ -24,20 +24,35 @@ export const markTransactionAsNotMiscategorizedEpic = (actions$, state$, zeniAPI
24
24
  const currentTenant = getCurrentTenant(state$.value);
25
25
  const { selectedPeriodByTenantId } = expenseAutomationViewState;
26
26
  const selectedPeriod = selectedPeriodByTenantId[currentTenant.tenantId];
27
+ const txnId = action.payload.transactionId.id;
28
+ const autoTabLineItems = transactionCategorizationView.autoCategorized
29
+ .transactionReviewLocalDataById[txnId]
30
+ ?.transactionReviewLocalData.tabSpecificLineItems
31
+ .autoCategorized ?? [];
32
+ const hasAutoLines = autoTabLineItems.length > 0;
27
33
  const { uiState } = transactionCategorizationView[selectedTransactionCategorizationTab];
28
- const totalCountByPeriod = uiState.totalCount[toMonthYearPeriodId(selectedPeriod)];
29
- const updatedTotalCount = totalCountByPeriod === 0
30
- ? totalCountByPeriod
31
- : totalCountByPeriod - 1;
32
- actions.push(updateStatusForTransactionNotMiscategorizedUpdateForCategorization(selectedTransactionCategorizationTab, [action.payload.transactionId.id], [action.payload.transactionId.id], selectedPeriod, 'Completed'));
33
- actions.push(removeTransactionCategorization({
34
- transactionIds: [action.payload.transactionId.id],
35
- }));
36
- actions.push(updateTotalCountForTransactionCategorization({
37
- selectedPeriod,
38
- selectedTab: selectedTransactionCategorizationTab,
39
- totalCount: updatedTotalCount,
40
- }));
34
+ const removeIdsFromPeriod = selectedTransactionCategorizationTab === 'review'
35
+ ? [txnId]
36
+ : hasAutoLines
37
+ ? []
38
+ : [txnId];
39
+ actions.push(updateStatusForTransactionNotMiscategorizedUpdateForCategorization(selectedTransactionCategorizationTab, [txnId], removeIdsFromPeriod, selectedPeriod, 'Completed'));
40
+ if (!hasAutoLines) {
41
+ actions.push(removeTransactionCategorization({
42
+ transactionIds: [txnId],
43
+ }));
44
+ }
45
+ if (removeIdsFromPeriod.length > 0) {
46
+ const totalCountByPeriod = uiState.totalCount[toMonthYearPeriodId(selectedPeriod)];
47
+ const updatedTotalCount = totalCountByPeriod === 0
48
+ ? totalCountByPeriod
49
+ : totalCountByPeriod - 1;
50
+ actions.push(updateTotalCountForTransactionCategorization({
51
+ selectedPeriod,
52
+ selectedTab: selectedTransactionCategorizationTab,
53
+ totalCount: updatedTotalCount,
54
+ }));
55
+ }
41
56
  }
42
57
  actions.push(updateStatusConsolidatedSaveTransactionDetail({
43
58
  transactionId: action.payload.transactionId,