@zeniai/client-epic-state 5.0.95-beta1ND → 5.0.95-betaML1

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.
Files changed (95) hide show
  1. package/lib/commonStateTypes/animations.d.ts +1 -1
  2. package/lib/commonStateTypes/animations.js +0 -1
  3. package/lib/entity/company/companyPayload.d.ts +0 -4
  4. package/lib/entity/company/companyPayload.js +0 -4
  5. package/lib/entity/company/companyStateTypes.d.ts +0 -4
  6. package/lib/entity/paymentAccount/paymentAccountSelector.d.ts +0 -1
  7. package/lib/entity/paymentAccount/paymentAccountSelector.js +0 -4
  8. package/lib/entity/tenant/epic/deleteConnectionEpic.d.ts +1 -1
  9. package/lib/entity/tenant/epic/saveAPIKeyConnectionEpic.d.ts +1 -1
  10. package/lib/entity/tenant/epic/saveConnectorCredentialsEpic.d.ts +3 -3
  11. package/lib/entity/tenant/epic/saveOAuthConnectionEpic.d.ts +1 -1
  12. package/lib/entity/tenant/tenantPayload.d.ts +0 -1
  13. package/lib/entity/tenant/tenantReducer.d.ts +25 -38
  14. package/lib/entity/tenant/tenantReducer.js +5 -65
  15. package/lib/entity/tenant/tenantState.d.ts +0 -1
  16. package/lib/epic.d.ts +1 -6
  17. package/lib/epic.js +1 -7
  18. package/lib/esm/commonStateTypes/animations.js +0 -1
  19. package/lib/esm/entity/company/companyPayload.js +0 -4
  20. package/lib/esm/entity/paymentAccount/paymentAccountSelector.js +0 -3
  21. package/lib/esm/entity/tenant/tenantReducer.js +3 -63
  22. package/lib/esm/epic.js +1 -7
  23. package/lib/esm/index.js +8 -11
  24. package/lib/esm/view/expenseAutomationView/epics/transactionCategorization/initializeTransactionCategorizationLocalDataEpic.js +15 -0
  25. package/lib/esm/view/expenseAutomationView/reducers/transactionsViewReducer.js +63 -5
  26. package/lib/esm/view/fileView/epic/deleteFileEpic.js +2 -2
  27. package/lib/esm/view/fileView/epic/deleteFileListEpic.js +2 -2
  28. package/lib/esm/view/fileView/epic/updateFileNameEpic.js +2 -2
  29. package/lib/esm/view/onboardingView/customerView/onboardingCustomerViewReducer.js +50 -217
  30. package/lib/esm/view/onboardingView/customerView/onboardingCustomerViewSelector.js +1 -7
  31. package/lib/esm/view/onboardingView/customerView/onboardingCustomerViewState.js +0 -12
  32. package/lib/esm/view/recommendation/fetchEntityRecommendationsForLineUpdateEpic.js +12 -3
  33. package/lib/esm/view/recommendation/recommendationReducer.js +18 -1
  34. package/lib/esm/view/recommendation/recommendationStaleResponseHelper.js +26 -0
  35. package/lib/esm/view/spendManagement/commonSetup/setupViewReducer.js +52 -105
  36. package/lib/esm/view/spendManagement/commonSetup/setupViewSelector.js +1 -6
  37. package/lib/esm/view/transactionDetail/epics/initializeTransactionDetailLocalDataEpic.js +7 -0
  38. package/lib/esm/view/transactionDetail/transactionDetailReducer.js +44 -3
  39. package/lib/index.d.ts +9 -13
  40. package/lib/index.js +35 -54
  41. package/lib/view/expenseAutomationView/epics/transactionCategorization/initializeTransactionCategorizationLocalDataEpic.d.ts +2 -1
  42. package/lib/view/expenseAutomationView/epics/transactionCategorization/initializeTransactionCategorizationLocalDataEpic.js +15 -0
  43. package/lib/view/expenseAutomationView/reducers/transactionsViewReducer.js +63 -5
  44. package/lib/view/fileView/epic/deleteFileEpic.js +1 -1
  45. package/lib/view/fileView/epic/deleteFileListEpic.js +1 -1
  46. package/lib/view/fileView/epic/updateFileNameEpic.js +1 -1
  47. package/lib/view/onboardingView/customerView/onboardingCustomerViewPayload.d.ts +0 -3
  48. package/lib/view/onboardingView/customerView/onboardingCustomerViewReducer.d.ts +4 -41
  49. package/lib/view/onboardingView/customerView/onboardingCustomerViewReducer.js +51 -219
  50. package/lib/view/onboardingView/customerView/onboardingCustomerViewSelector.d.ts +1 -5
  51. package/lib/view/onboardingView/customerView/onboardingCustomerViewSelector.js +2 -11
  52. package/lib/view/onboardingView/customerView/onboardingCustomerViewState.d.ts +0 -40
  53. package/lib/view/onboardingView/customerView/onboardingCustomerViewState.js +1 -13
  54. package/lib/view/recommendation/fetchEntityRecommendationsForLineUpdateEpic.d.ts +2 -2
  55. package/lib/view/recommendation/fetchEntityRecommendationsForLineUpdateEpic.js +10 -1
  56. package/lib/view/recommendation/recommendationReducer.d.ts +3 -1
  57. package/lib/view/recommendation/recommendationReducer.js +19 -2
  58. package/lib/view/recommendation/recommendationStaleResponseHelper.d.ts +7 -0
  59. package/lib/view/recommendation/recommendationStaleResponseHelper.js +30 -0
  60. package/lib/view/spendManagement/commonSetup/setupViewReducer.d.ts +2 -28
  61. package/lib/view/spendManagement/commonSetup/setupViewReducer.js +53 -106
  62. package/lib/view/spendManagement/commonSetup/setupViewSelector.d.ts +2 -7
  63. package/lib/view/spendManagement/commonSetup/setupViewSelector.js +1 -6
  64. package/lib/view/spendManagement/commonSetup/setupViewState.d.ts +0 -19
  65. package/lib/view/transactionDetail/epics/initializeTransactionDetailLocalDataEpic.d.ts +2 -1
  66. package/lib/view/transactionDetail/epics/initializeTransactionDetailLocalDataEpic.js +7 -0
  67. package/lib/view/transactionDetail/transactionDetailReducer.js +44 -3
  68. package/package.json +1 -1
  69. package/lib/entity/tenant/epic/initEmailConnectOAuthEpic.d.ts +0 -21
  70. package/lib/entity/tenant/epic/initEmailConnectOAuthEpic.js +0 -54
  71. package/lib/esm/entity/tenant/epic/initEmailConnectOAuthEpic.js +0 -50
  72. package/lib/esm/view/onboardingView/customerView/epic/aiAgentsActivation/fetchAiAgentsActivationStatusEpic.js +0 -42
  73. package/lib/esm/view/onboardingView/customerView/epic/customerDetails/acknowledgeOnboardingAiActivationViewedEpic.js +0 -29
  74. package/lib/esm/view/onboardingView/customerView/epic/customerDetails/acknowledgeOnboardingAiFinanceTeamEpic.js +0 -40
  75. package/lib/esm/view/spendManagement/commonSetup/epic/setup/parseUploadedKybDocumentEpic.js +0 -58
  76. package/lib/esm/view/spendManagement/commonSetup/epic/setup/parseUploadedKycDocumentEpic.js +0 -77
  77. package/lib/esm/view/spendManagement/commonSetup/kycKybAutofillActions.js +0 -14
  78. package/lib/esm/view/spendManagement/commonSetup/kycKybParseMapper.js +0 -210
  79. package/lib/esm/view/spendManagement/commonSetup/types/kycKybAutofill.js +0 -50
  80. package/lib/view/onboardingView/customerView/epic/aiAgentsActivation/fetchAiAgentsActivationStatusEpic.d.ts +0 -7
  81. package/lib/view/onboardingView/customerView/epic/aiAgentsActivation/fetchAiAgentsActivationStatusEpic.js +0 -46
  82. package/lib/view/onboardingView/customerView/epic/customerDetails/acknowledgeOnboardingAiActivationViewedEpic.d.ts +0 -8
  83. package/lib/view/onboardingView/customerView/epic/customerDetails/acknowledgeOnboardingAiActivationViewedEpic.js +0 -33
  84. package/lib/view/onboardingView/customerView/epic/customerDetails/acknowledgeOnboardingAiFinanceTeamEpic.d.ts +0 -9
  85. package/lib/view/onboardingView/customerView/epic/customerDetails/acknowledgeOnboardingAiFinanceTeamEpic.js +0 -44
  86. package/lib/view/spendManagement/commonSetup/epic/setup/parseUploadedKybDocumentEpic.d.ts +0 -28
  87. package/lib/view/spendManagement/commonSetup/epic/setup/parseUploadedKybDocumentEpic.js +0 -62
  88. package/lib/view/spendManagement/commonSetup/epic/setup/parseUploadedKycDocumentEpic.d.ts +0 -9
  89. package/lib/view/spendManagement/commonSetup/epic/setup/parseUploadedKycDocumentEpic.js +0 -81
  90. package/lib/view/spendManagement/commonSetup/kycKybAutofillActions.d.ts +0 -33
  91. package/lib/view/spendManagement/commonSetup/kycKybAutofillActions.js +0 -17
  92. package/lib/view/spendManagement/commonSetup/kycKybParseMapper.d.ts +0 -36
  93. package/lib/view/spendManagement/commonSetup/kycKybParseMapper.js +0 -218
  94. package/lib/view/spendManagement/commonSetup/types/kycKybAutofill.d.ts +0 -154
  95. package/lib/view/spendManagement/commonSetup/types/kycKybAutofill.js +0 -55
@@ -86,6 +86,15 @@ const fetchEntityRecommendationsForLineUpdateEpic = (actions$, state$, zeniAPI)
86
86
  ? (0, transactionsViewReducer_1.markCategoryClassRecommendationsFailureForCategorization)(payload.selectedTab, transactionId, lineIds, status)
87
87
  : (0, transactionDetailReducer_1.markCategoryClassRecommendationsFailureForTransactionDetail)(transactionId, lineIds, status));
88
88
  }));
89
- return (0, rxjs_1.concat)((0, rxjs_1.of)(startAction), httpStream$);
89
+ // takeUntil kills the in-flight HTTP and suppresses every
90
+ // downstream success/failure/markCompleted emission once a
91
+ // cancel action lands for the same transactionId. groupBy +
92
+ // switchMap already handle re-fetch-on-same-target; takeUntil
93
+ // covers the user-initiated Cancel (detail footer + list
94
+ // footer) and the silent backgroundRefetchReviewTab path,
95
+ // which both wipe local data without dispatching another
96
+ // fetch on the same target.
97
+ const cancel$ = actions$.pipe((0, operators_1.filter)(recommendationReducer_1.cancelEntityRecommendationsForLineUpdate.match), (0, operators_1.filter)((a) => a.payload.transactionId.id === transactionId.id));
98
+ return (0, rxjs_1.concat)((0, rxjs_1.of)(startAction), httpStream$.pipe((0, operators_1.takeUntil)(cancel$)));
90
99
  }))));
91
100
  exports.fetchEntityRecommendationsForLineUpdateEpic = fetchEntityRecommendationsForLineUpdateEpic;
@@ -41,7 +41,9 @@ export declare const fetchEntityRecommendationsByTransactionId: import("@reduxjs
41
41
  isTransactionCategorizationFlow: any;
42
42
  isFetchCOT: any;
43
43
  isUncategorizedExpenseCategoryEnabled: boolean | undefined;
44
- }, "recommendation/fetchEntityRecommendationsByTransactionId", never, never>, fetchEntityRecommendationsForLineUpdate: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[args: FetchEntityRecommendationsForLineUpdatePayload], FetchEntityRecommendationsForLineUpdatePayload, "recommendation/fetchEntityRecommendationsForLineUpdate", never, never>, fetchRecommendationByEntityName: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[entityName: string, entityType: EntityType], {
44
+ }, "recommendation/fetchEntityRecommendationsByTransactionId", never, never>, fetchEntityRecommendationsForLineUpdate: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[args: FetchEntityRecommendationsForLineUpdatePayload], FetchEntityRecommendationsForLineUpdatePayload, "recommendation/fetchEntityRecommendationsForLineUpdate", never, never>, cancelEntityRecommendationsForLineUpdate: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[transactionId: TransactionID], {
45
+ transactionId: TransactionID;
46
+ }, "recommendation/cancelEntityRecommendationsForLineUpdate", never, never>, fetchRecommendationByEntityName: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[entityName: string, entityType: EntityType], {
45
47
  entityName: string;
46
48
  entityType: EntityType;
47
49
  }, "recommendation/fetchRecommendationByEntityName", never, never>, fetchRecommendationByEntityId: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[entityId: string, entityType: EntityType], {
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  var _a;
3
3
  Object.defineProperty(exports, "__esModule", { value: true });
4
- exports.clearRecommendation = exports.indicateReadyToInitializeRecommendation = exports.updateRecommendationForEntityFailure = exports.updateRecommendationForEntity = exports.fetchRecommendationByEntityId = exports.fetchRecommendationByEntityName = exports.fetchEntityRecommendationsForLineUpdate = exports.fetchEntityRecommendationsByTransactionId = exports.initialState = void 0;
4
+ exports.clearRecommendation = exports.indicateReadyToInitializeRecommendation = exports.updateRecommendationForEntityFailure = exports.updateRecommendationForEntity = exports.fetchRecommendationByEntityId = exports.fetchRecommendationByEntityName = exports.cancelEntityRecommendationsForLineUpdate = exports.fetchEntityRecommendationsForLineUpdate = exports.fetchEntityRecommendationsByTransactionId = exports.initialState = void 0;
5
5
  const toolkit_1 = require("@reduxjs/toolkit");
6
6
  const recommendationState_1 = require("./recommendationState");
7
7
  exports.initialState = {
@@ -62,6 +62,23 @@ const recommendation = (0, toolkit_1.createSlice)({
62
62
  return { payload: args };
63
63
  },
64
64
  },
65
+ // No-op reducer; the action exists purely so the line-update epic
66
+ // can observe it via `takeUntil` and kill an in-flight HTTP request
67
+ // when the user (or a background refresh) wipes local data before
68
+ // the response lands. Without this, a stale response races the reset
69
+ // and overwrites the user's intent. Cancel is keyed by
70
+ // `transactionId` only: per-page Cancel buttons cancel everything
71
+ // under that transaction (including JE sibling line sets), which
72
+ // matches the UI semantics on both detail and categorization pages.
73
+ cancelEntityRecommendationsForLineUpdate: {
74
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
75
+ reducer(_draft, _action) {
76
+ // intentionally empty
77
+ },
78
+ prepare(transactionId) {
79
+ return { payload: { transactionId } };
80
+ },
81
+ },
65
82
  fetchRecommendationByEntityName: {
66
83
  reducer(draft, action) {
67
84
  const { entityName, entityType } = action.payload;
@@ -140,7 +157,7 @@ const recommendation = (0, toolkit_1.createSlice)({
140
157
  },
141
158
  },
142
159
  });
143
- _a = recommendation.actions, exports.fetchEntityRecommendationsByTransactionId = _a.fetchEntityRecommendationsByTransactionId, exports.fetchEntityRecommendationsForLineUpdate = _a.fetchEntityRecommendationsForLineUpdate, exports.fetchRecommendationByEntityName = _a.fetchRecommendationByEntityName, exports.fetchRecommendationByEntityId = _a.fetchRecommendationByEntityId, exports.updateRecommendationForEntity = _a.updateRecommendationForEntity, exports.updateRecommendationForEntityFailure = _a.updateRecommendationForEntityFailure, exports.indicateReadyToInitializeRecommendation = _a.indicateReadyToInitializeRecommendation, exports.clearRecommendation = _a.clearRecommendation;
160
+ _a = recommendation.actions, exports.fetchEntityRecommendationsByTransactionId = _a.fetchEntityRecommendationsByTransactionId, exports.fetchEntityRecommendationsForLineUpdate = _a.fetchEntityRecommendationsForLineUpdate, exports.cancelEntityRecommendationsForLineUpdate = _a.cancelEntityRecommendationsForLineUpdate, exports.fetchRecommendationByEntityName = _a.fetchRecommendationByEntityName, exports.fetchRecommendationByEntityId = _a.fetchRecommendationByEntityId, exports.updateRecommendationForEntity = _a.updateRecommendationForEntity, exports.updateRecommendationForEntityFailure = _a.updateRecommendationForEntityFailure, exports.indicateReadyToInitializeRecommendation = _a.indicateReadyToInitializeRecommendation, exports.clearRecommendation = _a.clearRecommendation;
144
161
  exports.default = recommendation.reducer;
145
162
  const doUpdateRecommendationForEntity = (draft, entityId, entityType, payload) => {
146
163
  const key = (0, recommendationState_1.getEntityRecommendationKey)(entityType, entityId);
@@ -0,0 +1,7 @@
1
+ import { ID } from '../../commonStateTypes/common';
2
+ import { Entity } from '../../entity/genericEntity/entity';
3
+ export declare const getLineIdsWhereEntityStillMatches: (args: {
4
+ lineIds: ID[];
5
+ payloadEntity: Entity;
6
+ getCurrentEntityForLine: (lineId: ID) => Entity | undefined;
7
+ }) => ID[];
@@ -0,0 +1,30 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getLineIdsWhereEntityStillMatches = void 0;
4
+ // Two entities refer to the same real-world thing iff they share both
5
+ // type and id. We deliberately compare on these fields only — qboId /
6
+ // zeniId can lag during entity-create flows where the persisted id
7
+ // hasn't been roundtripped yet, while `id` is the local-source-of-truth
8
+ // the line carries.
9
+ const entitiesMatch = (a, b) => a != null && b != null && a.type === b.type && a.id === b.id;
10
+ // Filters `lineIds` down to those whose currently selected entity (as
11
+ // reported by the caller) still matches the payload entity at the
12
+ // moment the success reducer fires. Used by the two
13
+ // `setEntityRecommendationForLineIds…` reducers as a defensive guard
14
+ // against stale responses landing after the user (or a background
15
+ // refresh) has changed or wiped their selection.
16
+ //
17
+ // Each flow decides separately where the "current entity" lives,
18
+ // because the rules diverge:
19
+ // - Detail flow: vendor + customer transactions read from page-level
20
+ // `selectedEntity`; JE / deposit reads per-line `lineEntity`.
21
+ // - List flow: ONLY vendor reads from page-level `selectedEntity`;
22
+ // customer, JE, deposit all read per-line `selectedEntityLine`.
23
+ // Pushing the lookup into the caller keeps this helper a pure
24
+ // comparator and avoids the helper having to know which flow / page-
25
+ // level rule applies.
26
+ const getLineIdsWhereEntityStillMatches = (args) => {
27
+ const { lineIds, payloadEntity, getCurrentEntityForLine } = args;
28
+ return lineIds.filter((lineId) => entitiesMatch(payloadEntity, getCurrentEntityForLine(lineId)));
29
+ };
30
+ exports.getLineIdsWhereEntityStillMatches = getLineIdsWhereEntityStillMatches;
@@ -2,7 +2,7 @@ import { ID } from '../../../commonStateTypes/common';
2
2
  import { ZeniAPIStatus } from '../../../responsePayload';
3
3
  import { ZeniDate } from '../../../zeniDayJS';
4
4
  import { CompanyOfficerType } from '../../companyView/types/companyPassport/companyUsersLocalData';
5
- import { CompanyDetailsLocalData, CompanyOfficerLocalData, SetupViewLocalData, SetupViewState } from './setupViewState';
5
+ import { CompanyDetailsLocalData, SetupViewLocalData, SetupViewState } from './setupViewState';
6
6
  export declare const initialState: SetupViewState;
7
7
  export declare const enableSetup: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[companyId: string, setupViewType: "bill_pay" | "reimbursement" | "zeni_accounts" | "zeni_treasury" | "charge_cards" | "other_connection" | "billing" | "debit_cards" | "charge_cards__debit_cards"], {
8
8
  companyId: string;
@@ -29,32 +29,6 @@ export declare const enableSetup: import("@reduxjs/toolkit").ActionCreatorWithPr
29
29
  }, "setupView/sendOtpSuccess">, sendOtpFailureSpendManagementSetUp: import("@reduxjs/toolkit").ActionCreatorWithPayload<ZeniAPIStatus<Record<string, unknown>>, "setupView/sendOtpFailure">, verifyOtpSpendManagementSetUp: import("@reduxjs/toolkit").ActionCreatorWithoutPayload<"setupView/verifyOtp">, verifyOtpSuccessSpendManagementSetUp: import("@reduxjs/toolkit").ActionCreatorWithoutPayload<"setupView/verifyOtpSuccess">, verifyOtpFailureSpendManagementSetUp: import("@reduxjs/toolkit").ActionCreatorWithPayload<ZeniAPIStatus<Record<string, unknown>>, "setupView/verifyOtpFailure">, saveIndustryAndIncDateInLocalStore: import("@reduxjs/toolkit").ActionCreatorWithPayload<{
30
30
  incDate: ZeniDate;
31
31
  industry: string;
32
- }, "setupView/saveIndustryAndIncDateInLocalStore">, clearSetupViewDataInLocalStore: import("@reduxjs/toolkit").ActionCreatorWithoutPayload<"setupView/clearSetupViewDataInLocalStore">, clearSetupView: import("@reduxjs/toolkit").ActionCreatorWithoutPayload<"setupView/clearSetupView">, applyKycDocumentAutofillForSetup: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[payload: {
33
- autoFilledFieldNames: string[];
34
- companyId: ID;
35
- fileId: ID;
36
- officerType: CompanyOfficerType;
37
- values: Partial<CompanyOfficerLocalData>;
38
- }], {
39
- autoFilledFieldNames: string[];
40
- companyId: ID;
41
- fileId: ID;
42
- officerType: CompanyOfficerType;
43
- values: Partial<CompanyOfficerLocalData>;
44
- }, "setupView/applyKycDocumentAutofillForSetup", never, never>, applyKybDocumentAutofillForSetup: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[payload: {
45
- autoFilledFieldNames: string[];
46
- companyId: ID;
47
- fileId: ID;
48
- values: Partial<CompanyDetailsLocalData>;
49
- }], {
50
- autoFilledFieldNames: string[];
51
- companyId: ID;
52
- fileId: ID;
53
- values: Partial<CompanyDetailsLocalData>;
54
- }, "setupView/applyKybDocumentAutofillForSetup", never, never>, clearKycKybAutofillForSetup: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[payload?: {
55
- officerType?: CompanyOfficerType;
56
- } | undefined], {
57
- officerType?: CompanyOfficerType;
58
- }, "setupView/clearKycKybAutofillForSetup", never, never>;
32
+ }, "setupView/saveIndustryAndIncDateInLocalStore">, clearSetupViewDataInLocalStore: import("@reduxjs/toolkit").ActionCreatorWithoutPayload<"setupView/clearSetupViewDataInLocalStore">, clearSetupView: import("@reduxjs/toolkit").ActionCreatorWithoutPayload<"setupView/clearSetupView">;
59
33
  declare const _default: import("redux").Reducer<SetupViewState>;
60
34
  export default _default;
@@ -1,34 +1,66 @@
1
1
  "use strict";
2
2
  var _a;
3
3
  Object.defineProperty(exports, "__esModule", { value: true });
4
- exports.clearKycKybAutofillForSetup = exports.applyKybDocumentAutofillForSetup = exports.applyKycDocumentAutofillForSetup = exports.clearSetupView = exports.clearSetupViewDataInLocalStore = exports.saveIndustryAndIncDateInLocalStore = exports.verifyOtpFailureSpendManagementSetUp = exports.verifyOtpSuccessSpendManagementSetUp = exports.verifyOtpSpendManagementSetUp = exports.sendOtpFailureSpendManagementSetUp = exports.sendOtpSuccessSpendManagementSetUp = exports.resendOtpSpendManagementSetUp = exports.sendOtpSpendManagementSetUp = exports.saveTreasuryAdditionalDocumentsInLocalStore = exports.saveCompnayOfficerAdditionalDocumentsInLocalStore = exports.saveCompnayOfficerPhoneInLocalStore = exports.saveSetupViewDataInLocalStore = exports.updateSetupViewLocalStoreData = exports.updateSelectedCompanyOfficer = exports.updateBusinessVerificationDetailsFailure = exports.updateBusinessVerificationDetailsSuccess = exports.updateBusinessVerificationDetails = exports.enableSetupFailure = exports.enableSetupSuccess = exports.enableSetup = exports.initialState = void 0;
4
+ exports.clearSetupView = exports.clearSetupViewDataInLocalStore = exports.saveIndustryAndIncDateInLocalStore = exports.verifyOtpFailureSpendManagementSetUp = exports.verifyOtpSuccessSpendManagementSetUp = exports.verifyOtpSpendManagementSetUp = exports.sendOtpFailureSpendManagementSetUp = exports.sendOtpSuccessSpendManagementSetUp = exports.resendOtpSpendManagementSetUp = exports.sendOtpSpendManagementSetUp = exports.saveTreasuryAdditionalDocumentsInLocalStore = exports.saveCompnayOfficerAdditionalDocumentsInLocalStore = exports.saveCompnayOfficerPhoneInLocalStore = exports.saveSetupViewDataInLocalStore = exports.updateSetupViewLocalStoreData = exports.updateSelectedCompanyOfficer = exports.updateBusinessVerificationDetailsFailure = exports.updateBusinessVerificationDetailsSuccess = exports.updateBusinessVerificationDetails = exports.enableSetupFailure = exports.enableSetupSuccess = exports.enableSetup = exports.initialState = void 0;
5
5
  const toolkit_1 = require("@reduxjs/toolkit");
6
- const kycKybAutofillActions_1 = require("./kycKybAutofillActions");
7
6
  const initialFetchStatus = {
8
7
  fetchState: 'Not-Started',
9
8
  error: undefined,
10
9
  };
11
- const emptyOfficerSlot = {
12
- autoFilledFields: [],
13
- localData: undefined,
14
- sendOtpStatus: initialFetchStatus,
15
- otpverificationStatus: initialFetchStatus,
16
- };
17
10
  exports.initialState = {
18
11
  updateStatus: { fetchState: 'Not-Started', error: undefined },
19
- parsingDocumentFileIds: [],
20
- companyDetails: { autoFilledFields: [] },
12
+ companyDetails: {},
21
13
  companyOfficerUpdateStatus: {
22
- Officer_1: { ...emptyOfficerSlot },
23
- Officer_2: { ...emptyOfficerSlot },
24
- Officer_3: { ...emptyOfficerSlot },
25
- Officer_4: { ...emptyOfficerSlot },
26
- Officer_5: { ...emptyOfficerSlot },
27
- Officer_6: { ...emptyOfficerSlot },
28
- Officer_7: { ...emptyOfficerSlot },
29
- Officer_8: { ...emptyOfficerSlot },
30
- Officer_9: { ...emptyOfficerSlot },
31
- Officer_10: { ...emptyOfficerSlot },
14
+ Officer_1: {
15
+ localData: undefined,
16
+ sendOtpStatus: initialFetchStatus,
17
+ otpverificationStatus: initialFetchStatus,
18
+ },
19
+ Officer_2: {
20
+ localData: undefined,
21
+ sendOtpStatus: initialFetchStatus,
22
+ otpverificationStatus: initialFetchStatus,
23
+ },
24
+ Officer_3: {
25
+ localData: undefined,
26
+ sendOtpStatus: initialFetchStatus,
27
+ otpverificationStatus: initialFetchStatus,
28
+ },
29
+ Officer_4: {
30
+ localData: undefined,
31
+ sendOtpStatus: initialFetchStatus,
32
+ otpverificationStatus: initialFetchStatus,
33
+ },
34
+ Officer_5: {
35
+ localData: undefined,
36
+ sendOtpStatus: initialFetchStatus,
37
+ otpverificationStatus: initialFetchStatus,
38
+ },
39
+ Officer_6: {
40
+ localData: undefined,
41
+ sendOtpStatus: initialFetchStatus,
42
+ otpverificationStatus: initialFetchStatus,
43
+ },
44
+ Officer_7: {
45
+ localData: undefined,
46
+ sendOtpStatus: initialFetchStatus,
47
+ otpverificationStatus: initialFetchStatus,
48
+ },
49
+ Officer_8: {
50
+ localData: undefined,
51
+ sendOtpStatus: initialFetchStatus,
52
+ otpverificationStatus: initialFetchStatus,
53
+ },
54
+ Officer_9: {
55
+ localData: undefined,
56
+ sendOtpStatus: initialFetchStatus,
57
+ otpverificationStatus: initialFetchStatus,
58
+ },
59
+ Officer_10: {
60
+ localData: undefined,
61
+ sendOtpStatus: initialFetchStatus,
62
+ otpverificationStatus: initialFetchStatus,
63
+ },
32
64
  },
33
65
  primaryContactDetails: {},
34
66
  };
@@ -269,92 +301,7 @@ const setupView = (0, toolkit_1.createSlice)({
269
301
  clearSetupView(draft) {
270
302
  Object.assign(draft, exports.initialState);
271
303
  },
272
- /**
273
- * Merge AI-parsed officer fields into the selected officer's localData and
274
- * track which field names were autofilled so the form can show the ✦ badge.
275
- */
276
- applyKycDocumentAutofillForSetup: {
277
- reducer(draft, action) {
278
- const { officerType, values, autoFilledFieldNames, fileId } = action.payload;
279
- const slot = draft.companyOfficerUpdateStatus[officerType];
280
- slot.localData = Object.assign({}, slot.localData, values);
281
- slot.autoFilledFields = Array.from(new Set([...slot.autoFilledFields, ...autoFilledFieldNames]));
282
- draft.parsingDocumentFileIds = draft.parsingDocumentFileIds.filter((id) => id !== fileId);
283
- },
284
- prepare(payload) {
285
- return { payload };
286
- },
287
- },
288
- /**
289
- * Merge AI-parsed company fields into companyDetails.localData and track
290
- * which field names were autofilled.
291
- */
292
- applyKybDocumentAutofillForSetup: {
293
- reducer(draft, action) {
294
- const { values, autoFilledFieldNames, fileId } = action.payload;
295
- draft.companyDetails.localData = Object.assign({}, draft.companyDetails.localData, values);
296
- draft.companyDetails.autoFilledFields = Array.from(new Set([
297
- ...draft.companyDetails.autoFilledFields,
298
- ...autoFilledFieldNames,
299
- ]));
300
- draft.parsingDocumentFileIds = draft.parsingDocumentFileIds.filter((id) => id !== fileId);
301
- },
302
- prepare(payload) {
303
- return { payload };
304
- },
305
- },
306
- /**
307
- * Wipe AI-autofill badges. If `officerType` is provided, clears only that
308
- * officer; otherwise clears company details too.
309
- */
310
- clearKycKybAutofillForSetup: {
311
- reducer(draft, action) {
312
- const { officerType } = action.payload;
313
- if (officerType != null) {
314
- draft.companyOfficerUpdateStatus[officerType].autoFilledFields = [];
315
- }
316
- else {
317
- draft.companyDetails.autoFilledFields = [];
318
- Object.keys(draft.companyOfficerUpdateStatus).forEach((key) => {
319
- draft.companyOfficerUpdateStatus[key].autoFilledFields = [];
320
- });
321
- }
322
- },
323
- prepare(payload = {}) {
324
- return { payload };
325
- },
326
- },
327
- },
328
- extraReducers: (builder) => {
329
- const addParsingFileId = (draft, fileId) => {
330
- if (!draft.parsingDocumentFileIds.includes(fileId)) {
331
- draft.parsingDocumentFileIds.push(fileId);
332
- }
333
- };
334
- const removeParsingFileId = (draft, fileId) => {
335
- draft.parsingDocumentFileIds = draft.parsingDocumentFileIds.filter((id) => id !== fileId);
336
- };
337
- builder.addCase(kycKybAutofillActions_1.parseUploadedKycDocument, (draft, action) => {
338
- if (action.payload.target === 'setup') {
339
- addParsingFileId(draft, action.payload.fileId);
340
- }
341
- });
342
- builder.addCase(kycKybAutofillActions_1.parseUploadedKybDocument, (draft, action) => {
343
- if (action.payload.target === 'setup') {
344
- addParsingFileId(draft, action.payload.fileId);
345
- }
346
- });
347
- builder.addCase(kycKybAutofillActions_1.parseUploadedKycDocumentFailure, (draft, action) => {
348
- if (action.payload.target === 'setup') {
349
- removeParsingFileId(draft, action.payload.fileId);
350
- }
351
- });
352
- builder.addCase(kycKybAutofillActions_1.parseUploadedKybDocumentFailure, (draft, action) => {
353
- if (action.payload.target === 'setup') {
354
- removeParsingFileId(draft, action.payload.fileId);
355
- }
356
- });
357
304
  },
358
305
  });
359
- _a = setupView.actions, exports.enableSetup = _a.enableSetup, exports.enableSetupSuccess = _a.enableSetupSuccess, exports.enableSetupFailure = _a.enableSetupFailure, exports.updateBusinessVerificationDetails = _a.updateBusinessVerificationDetails, exports.updateBusinessVerificationDetailsSuccess = _a.updateBusinessVerificationDetailsSuccess, exports.updateBusinessVerificationDetailsFailure = _a.updateBusinessVerificationDetailsFailure, exports.updateSelectedCompanyOfficer = _a.updateSelectedCompanyOfficer, exports.updateSetupViewLocalStoreData = _a.updateSetupViewLocalStoreData, exports.saveSetupViewDataInLocalStore = _a.saveSetupViewDataInLocalStore, exports.saveCompnayOfficerPhoneInLocalStore = _a.saveCompnayOfficerPhoneInLocalStore, exports.saveCompnayOfficerAdditionalDocumentsInLocalStore = _a.saveCompnayOfficerAdditionalDocumentsInLocalStore, exports.saveTreasuryAdditionalDocumentsInLocalStore = _a.saveTreasuryAdditionalDocumentsInLocalStore, exports.sendOtpSpendManagementSetUp = _a.sendOtp, exports.resendOtpSpendManagementSetUp = _a.resendOtp, exports.sendOtpSuccessSpendManagementSetUp = _a.sendOtpSuccess, exports.sendOtpFailureSpendManagementSetUp = _a.sendOtpFailure, exports.verifyOtpSpendManagementSetUp = _a.verifyOtp, exports.verifyOtpSuccessSpendManagementSetUp = _a.verifyOtpSuccess, exports.verifyOtpFailureSpendManagementSetUp = _a.verifyOtpFailure, exports.saveIndustryAndIncDateInLocalStore = _a.saveIndustryAndIncDateInLocalStore, exports.clearSetupViewDataInLocalStore = _a.clearSetupViewDataInLocalStore, exports.clearSetupView = _a.clearSetupView, exports.applyKycDocumentAutofillForSetup = _a.applyKycDocumentAutofillForSetup, exports.applyKybDocumentAutofillForSetup = _a.applyKybDocumentAutofillForSetup, exports.clearKycKybAutofillForSetup = _a.clearKycKybAutofillForSetup;
306
+ _a = setupView.actions, exports.enableSetup = _a.enableSetup, exports.enableSetupSuccess = _a.enableSetupSuccess, exports.enableSetupFailure = _a.enableSetupFailure, exports.updateBusinessVerificationDetails = _a.updateBusinessVerificationDetails, exports.updateBusinessVerificationDetailsSuccess = _a.updateBusinessVerificationDetailsSuccess, exports.updateBusinessVerificationDetailsFailure = _a.updateBusinessVerificationDetailsFailure, exports.updateSelectedCompanyOfficer = _a.updateSelectedCompanyOfficer, exports.updateSetupViewLocalStoreData = _a.updateSetupViewLocalStoreData, exports.saveSetupViewDataInLocalStore = _a.saveSetupViewDataInLocalStore, exports.saveCompnayOfficerPhoneInLocalStore = _a.saveCompnayOfficerPhoneInLocalStore, exports.saveCompnayOfficerAdditionalDocumentsInLocalStore = _a.saveCompnayOfficerAdditionalDocumentsInLocalStore, exports.saveTreasuryAdditionalDocumentsInLocalStore = _a.saveTreasuryAdditionalDocumentsInLocalStore, exports.sendOtpSpendManagementSetUp = _a.sendOtp, exports.resendOtpSpendManagementSetUp = _a.resendOtp, exports.sendOtpSuccessSpendManagementSetUp = _a.sendOtpSuccess, exports.sendOtpFailureSpendManagementSetUp = _a.sendOtpFailure, exports.verifyOtpSpendManagementSetUp = _a.verifyOtp, exports.verifyOtpSuccessSpendManagementSetUp = _a.verifyOtpSuccess, exports.verifyOtpFailureSpendManagementSetUp = _a.verifyOtpFailure, exports.saveIndustryAndIncDateInLocalStore = _a.saveIndustryAndIncDateInLocalStore, exports.clearSetupViewDataInLocalStore = _a.clearSetupViewDataInLocalStore, exports.clearSetupView = _a.clearSetupView;
360
307
  exports.default = setupView.reducer;
@@ -16,7 +16,7 @@ import { CompanyOfficerType } from '../../companyView/types/companyPassport/comp
16
16
  import { CompanyView } from '../../companyView/types/companyView';
17
17
  import { AccountTypeSubConfigCodeKeyType } from '../billPay/billPayConfig/billPayConfigState';
18
18
  import { PlaidAccountKeyType, PlaidConnectionDetails } from '../plaidAccount/plaidAccountViewState';
19
- import { CompanyAndIdentityDetails, CompanyOfficerLocalData, PrimaryContactLocalData, SetupViewState, SetupViewType } from './setupViewState';
19
+ import { CompanyAndIdentityDetails, CompanyOfficerLocalData, PrimaryContactLocalData, SetupViewType } from './setupViewState';
20
20
  export interface SetupView {
21
21
  accountFetchStatus: FetchStateAndError;
22
22
  accountUpdateStatus: FetchStateAndError;
@@ -54,8 +54,6 @@ export interface FundingAccount {
54
54
  }
55
55
  export interface CompanyOfficersDetails extends CompanyOfficerLocalData {
56
56
  additionalFiles: File[];
57
- /** Field names in this officer's localData populated by AI doc autofill. */
58
- autoFilledFields: string[];
59
57
  deleteFileStatusById: Record<ID, FetchStateAndError | undefined>;
60
58
  otpverificationStatus: FetchStateAndError;
61
59
  sendOtpStatus: FetchStateAndError;
@@ -64,8 +62,6 @@ export interface CompanyOfficersDetails extends CompanyOfficerLocalData {
64
62
  addressStatus?: NewAddressData;
65
63
  }
66
64
  export interface CompanyDetails {
67
- /** Field names in companyDetails localData populated by AI doc autofill. */
68
- autoFilledFields: string[];
69
65
  companyFiles: File[];
70
66
  companyId: ID;
71
67
  deleteFileStatusById: Record<ID, FetchStateAndError | undefined>;
@@ -100,7 +96,6 @@ export interface CompanyDetails {
100
96
  }
101
97
  interface CompanyAndOfficerLocalData {
102
98
  companyOfficerLocalData: Record<CompanyOfficerType, CompanyOfficersDetails | undefined>;
103
- parsingDocumentFileIds: ID[];
104
99
  companyDetailsLocalData?: CompanyDetails;
105
100
  }
106
101
  export interface BusinessVerificationDetails extends CompanyAndOfficerLocalData {
@@ -110,7 +105,7 @@ export interface BusinessVerificationDetails extends CompanyAndOfficerLocalData
110
105
  }
111
106
  export declare function getCommonSetupViewDetails(state: RootState, companyId: ID, setupViewType: SetupViewType, plaidAccountKeyType: PlaidAccountKeyType): SetupView;
112
107
  export declare function getBusinessVerificationDetails(state: RootState, companyId: ID): BusinessVerificationDetails;
113
- export declare const getCompanyAndIdentityDetails: (state: RootState, companyId: ID, companyAndIdentityDetails: CompanyAndIdentityDetails & Pick<SetupViewState, "parsingDocumentFileIds">) => CompanyAndOfficerLocalData;
108
+ export declare const getCompanyAndIdentityDetails: (state: RootState, companyId: ID, companyAndIdentityDetails: CompanyAndIdentityDetails) => CompanyAndOfficerLocalData;
114
109
  export declare const getAllFundingAccounts: (depositAccounts: DepositAccount[], paymentAccounts: PaymentAccount[], paymentAccountBalanceFetchStatus: Record<ID, FetchStateAndError>, includeOnlyVerifiedAccounts?: boolean) => FundingAccount[];
115
110
  export declare const mapDepositAccToFundingAccount: (depositAcc: DepositAccount) => FundingAccount;
116
111
  export declare const mapDepositAccountWithLimitToFundingAccount: (depositAcc: DepositAccountWithLimit) => FundingAccount;
@@ -92,17 +92,15 @@ function getBusinessVerificationDetails(state, companyId) {
92
92
  const { setupViewState, countryListState } = state;
93
93
  const { companyDetails, companyOfficerUpdateStatus, primaryContactDetails, updateStatus, } = setupViewState;
94
94
  const companyView = (0, getCompanyView_1.getCompanyView)(state, companyId, []);
95
- const { companyDetailsLocalData, companyOfficerLocalData, parsingDocumentFileIds } = (0, exports.getCompanyAndIdentityDetails)(state, companyId, {
95
+ const { companyDetailsLocalData, companyOfficerLocalData } = (0, exports.getCompanyAndIdentityDetails)(state, companyId, {
96
96
  companyDetails,
97
97
  companyOfficerUpdateStatus,
98
98
  primaryContactDetails,
99
- parsingDocumentFileIds: setupViewState.parsingDocumentFileIds,
100
99
  });
101
100
  const allNationalityCountries = countryListState.byCountryListCode.nationalityCountryList.countries;
102
101
  return {
103
102
  companyDetailsLocalData,
104
103
  companyOfficerLocalData,
105
- parsingDocumentFileIds,
106
104
  companyView,
107
105
  updateStatus,
108
106
  allNationalityCountries,
@@ -126,7 +124,6 @@ const getCompanyAndIdentityDetails = (state, companyId, companyAndIdentityDetail
126
124
  const companyAddress = addressViewState.newAddressState?.company_address;
127
125
  const registeredCompanyAddress = addressViewState.newAddressState?.company_registered_address;
128
126
  companyDetailsLocalData = {
129
- autoFilledFields: companyDetails.autoFilledFields,
130
127
  companyId,
131
128
  companyDescription,
132
129
  companyLegalName,
@@ -199,7 +196,6 @@ const getCompanyAndIdentityDetails = (state, companyId, companyAndIdentityDetail
199
196
  const companyOfficerAddress = addressViewState.newAddressState?.[addressType];
200
197
  companyOfficerLocalData[officerType] = {
201
198
  ...companyOfficer.localData,
202
- autoFilledFields: companyOfficer.autoFilledFields,
203
199
  userFiles: (0, fileSelector_1.getFilesByFileIds)(fileState, fileIds),
204
200
  additionalFiles: (0, fileSelector_1.getFilesByFileIds)(fileState, additionalSubmittedDocumentsForVerificationFileIds),
205
201
  deleteFileStatusById,
@@ -213,7 +209,6 @@ const getCompanyAndIdentityDetails = (state, companyId, companyAndIdentityDetail
213
209
  return {
214
210
  companyDetailsLocalData,
215
211
  companyOfficerLocalData,
216
- parsingDocumentFileIds: companyAndIdentityDetails.parsingDocumentFileIds,
217
212
  };
218
213
  };
219
214
  exports.getCompanyAndIdentityDetails = getCompanyAndIdentityDetails;
@@ -81,21 +81,9 @@ export interface SetupViewLocalData {
81
81
  */
82
82
  export interface CompanyAndIdentityDetails {
83
83
  companyDetails: {
84
- /**
85
- * Field names from {@link CompanyDetailsLocalData} that were populated by AI
86
- * autofill from an uploaded KYB document. Drives the ✦ sparkle in the form.
87
- * Always present (empty when no autofill has run yet).
88
- */
89
- autoFilledFields: string[];
90
84
  localData?: CompanyDetailsLocalData;
91
85
  };
92
86
  companyOfficerUpdateStatus: Record<CompanyOfficerType, {
93
- /**
94
- * Field names from {@link CompanyOfficerLocalData} populated by AI autofill
95
- * from an uploaded KYC identity document. Drives the ✦ sparkle in the form.
96
- * Always present (empty when no autofill has run yet).
97
- */
98
- autoFilledFields: string[];
99
87
  otpverificationStatus: FetchStateAndError;
100
88
  sendOtpStatus: FetchStateAndError;
101
89
  localData?: CompanyOfficerLocalData;
@@ -105,13 +93,6 @@ export interface CompanyAndIdentityDetails {
105
93
  };
106
94
  }
107
95
  export interface SetupViewState extends CompanyAndIdentityDetails {
108
- /**
109
- * File IDs currently being parsed by the AI autofill epic. Populated when
110
- * `parseUploadedKyc/KybDocument` dispatches and cleared when the
111
- * corresponding apply / failure action fires. Drives the "AI is reading
112
- * your document" overlay on the document upload field.
113
- */
114
- parsingDocumentFileIds: ID[];
115
96
  updateStatus: FetchStateAndError;
116
97
  }
117
98
  export {};
@@ -1,5 +1,6 @@
1
1
  import { ActionsObservable, StateObservable } from 'redux-observable';
2
2
  import { RootState } from '../../../reducer';
3
+ import { cancelEntityRecommendationsForLineUpdate } from '../../recommendation/recommendationReducer';
3
4
  import { clearTransactionDetailLocalData, initializeTransactionDetailLocalData, saveTransactionDetailLocalData } from '../transactionDetailReducer';
4
- export type ActionType = ReturnType<typeof initializeTransactionDetailLocalData> | ReturnType<typeof saveTransactionDetailLocalData> | ReturnType<typeof clearTransactionDetailLocalData>;
5
+ export type ActionType = ReturnType<typeof initializeTransactionDetailLocalData> | ReturnType<typeof saveTransactionDetailLocalData> | ReturnType<typeof clearTransactionDetailLocalData> | ReturnType<typeof cancelEntityRecommendationsForLineUpdate>;
5
6
  export declare const initializeTransactionDetailLocalDataEpic: (actions$: ActionsObservable<ActionType>, state$: StateObservable<RootState>) => import("rxjs").Observable<ActionType>;
@@ -5,6 +5,7 @@ const rxjs_1 = require("rxjs");
5
5
  const operators_1 = require("rxjs/operators");
6
6
  const transactionSelector_1 = require("../../../entity/transaction/transactionSelector");
7
7
  const accountListSelector_1 = require("../../accountList/accountListSelector");
8
+ const recommendationReducer_1 = require("../../recommendation/recommendationReducer");
8
9
  const transactionDetailLocalDataHelper_1 = require("../transactionDetailLocalDataHelper");
9
10
  const transactionDetailReducer_1 = require("../transactionDetailReducer");
10
11
  const transactionDetailState_1 = require("../transactionDetailState");
@@ -17,6 +18,12 @@ const initializeTransactionDetailLocalDataEpic = (actions$, state$) => actions$.
17
18
  if (detail != null) {
18
19
  const uncategorizedIncomeExpense = (0, accountListSelector_1.getUncategorizedAccounts)(state$.value.accountState, state$.value.accountListState, 'accountList');
19
20
  const localData = (0, transactionDetailLocalDataHelper_1.toTransactionDetailLocalData)(detail, vendorId, uncategorizedIncomeExpense);
21
+ // Cancel any in-flight line-update recommendations fetch for
22
+ // this transaction BEFORE the clear+restore writes land. The
23
+ // shared epic's takeUntil observes this action and unsubscribes
24
+ // the HTTP stream, preventing a stale response from being
25
+ // applied to the freshly-restored local data.
26
+ fetchActions.push((0, recommendationReducer_1.cancelEntityRecommendationsForLineUpdate)(transactionId));
20
27
  fetchActions.push((0, transactionDetailReducer_1.clearTransactionDetailLocalData)({ transactionId }));
21
28
  fetchActions.push((0, transactionDetailReducer_1.saveTransactionDetailLocalData)({
22
29
  transactionId,
@@ -8,6 +8,9 @@ exports.setIsVendorUpdateAllChecked = exports.updateVendorBulkRecommendationsFet
8
8
  const toolkit_1 = require("@reduxjs/toolkit");
9
9
  const get_1 = __importDefault(require("lodash/get"));
10
10
  const entity_1 = require("../../entity/genericEntity/entity");
11
+ const customerTransaction_1 = require("../../entity/transaction/stateTypes/customerTransaction");
12
+ const vendorTransaction_1 = require("../../entity/transaction/stateTypes/vendorTransaction");
13
+ const recommendationStaleResponseHelper_1 = require("../recommendation/recommendationStaleResponseHelper");
11
14
  const transactionDetailLocalDataHelper_1 = require("./transactionDetailLocalDataHelper");
12
15
  const transactionDetailState_1 = require("./transactionDetailState");
13
16
  exports.initialState = {
@@ -258,6 +261,17 @@ const transactionDetail = (0, toolkit_1.createSlice)({
258
261
  // captures the snapshot before the epic's start arm runs and would
259
262
  // otherwise clobber In-Progress back to undefined). Treat the field as
260
263
  // sticky: only let the caller override it when they explicitly set it.
264
+ //
265
+ // Note on Cancel: the explicit user-Cancel path NO LONGER relies on
266
+ // this stickiness to release In-Progress lines. Cancel dispatches
267
+ // `cancelEntityRecommendationsForLineUpdate` ahead of the
268
+ // clear+save pair (see initializeTransactionDetailLocalDataEpic);
269
+ // the shared line-update epic's `takeUntil` catches that action
270
+ // and unsubscribes the HTTP stream, so no markCompleted /
271
+ // setEntityRecommendation arm fires for the cancelled fetch.
272
+ // Stickiness still matters for the BENIGN snapshot-rebuild paths
273
+ // described above where a fetch is legitimately in flight and
274
+ // must keep its skeleton until the success/failure arm lands.
261
275
  const mergedLineItemById = {};
262
276
  Object.entries(incoming.lineItemById ?? {}).forEach(([lineId, line]) => {
263
277
  mergedLineItemById[lineId] = {
@@ -393,10 +407,37 @@ const transactionDetail = (0, toolkit_1.createSlice)({
393
407
  const key = (0, transactionDetailState_1.getTransactionDetailKey)(action.payload.transactionId);
394
408
  const detail = (0, get_1.default)(draft.transactionDetailById, key, undefined);
395
409
  if (detail != null) {
396
- const newLocalData = (0, transactionDetailLocalDataHelper_1.setEntityRecommendationForLineIdInLocalData)(transaction, detail.transactionDetailLocalData, action.payload.entity, lineIds, uncategorizedIncomeExpense, recommendationWithCOTByLineId);
410
+ // Stale-response guard. If the user has changed their selection
411
+ // (or Cancel restored an earlier vendor) between the fetch
412
+ // starting and the response landing, the payload entity will
413
+ // no longer match what's currently selected on the line(s).
414
+ // Apply recommendations only to the still-matching subset of
415
+ // lines. Lines that fail the guard still flip to Completed
416
+ // below so their inline skeletons resolve. This complements
417
+ // the epic-level `takeUntil`: even if a response slips
418
+ // through, it can't write recommendations onto unrelated
419
+ // selections.
420
+ //
421
+ // Detail flow: vendor + customer use page-level
422
+ // `selectedEntity`; JE / deposit use per-line `lineEntity`.
423
+ // Match the same dichotomy used by
424
+ // `setEntityRecommendationForLineIdInLocalData`'s
425
+ // `checkIfNotJEAndDeposit` test below.
426
+ const usesPageLevelEntity = (0, vendorTransaction_1.isVendorTransaction)(transaction) === true ||
427
+ (0, customerTransaction_1.isCustomerTransaction)(transaction) === true;
428
+ const matchedLineIds = (0, recommendationStaleResponseHelper_1.getLineIdsWhereEntityStillMatches)({
429
+ lineIds,
430
+ payloadEntity: action.payload.entity,
431
+ getCurrentEntityForLine: (lineId) => usesPageLevelEntity
432
+ ? detail.transactionDetailLocalData.selectedEntity
433
+ : detail.transactionDetailLocalData.lineItemById[lineId]
434
+ ?.lineEntity,
435
+ });
436
+ const newLocalData = (0, transactionDetailLocalDataHelper_1.setEntityRecommendationForLineIdInLocalData)(transaction, detail.transactionDetailLocalData, action.payload.entity, matchedLineIds, uncategorizedIncomeExpense, recommendationWithCOTByLineId);
397
437
  // Release the per-line fetch flag for every line this fetch
398
- // covered so the inline skeleton resolves and the page-level
399
- // Save button can re-enable.
438
+ // covered (matched AND unmatched) so the inline skeleton
439
+ // resolves and the page-level Save button can re-enable.
440
+ // Unmatched lines are released without recommendation writes.
400
441
  lineIds.forEach((lineId) => {
401
442
  const lineItem = newLocalData.lineItemById[lineId];
402
443
  if (lineItem != null) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zeniai/client-epic-state",
3
- "version": "5.0.95-beta1ND",
3
+ "version": "5.0.95-betaML1",
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",
@@ -1,21 +0,0 @@
1
- import { ActionsObservable, StateObservable } from 'redux-observable';
2
- import { RootState } from '../../../reducer';
3
- import { ZeniAPI } from '../../../zeniAPI';
4
- import { initEmailConnectOAuth, initEmailConnectOAuthFailure, initEmailConnectOAuthSuccess } from '../tenantReducer';
5
- export type ActionType = ReturnType<typeof initEmailConnectOAuth> | ReturnType<typeof initEmailConnectOAuthSuccess> | ReturnType<typeof initEmailConnectOAuthFailure>;
6
- export type NavigateFn = (url: string) => void;
7
- export declare const initEmailConnectOAuthEpic: (actions$: ActionsObservable<ActionType>, _state$: StateObservable<RootState>, zeniAPI: ZeniAPI, navigate?: NavigateFn) => import("rxjs").Observable<{
8
- payload: {
9
- tenantId: string;
10
- provider: "gmail" | "outlook";
11
- authorizationUrl: string;
12
- };
13
- type: "tenant/initEmailConnectOAuthSuccess";
14
- } | {
15
- payload: {
16
- tenantId: string;
17
- provider: "gmail" | "outlook";
18
- status: import("../../../responsePayload").ZeniAPIStatus<Record<string, unknown>>;
19
- };
20
- type: "tenant/initEmailConnectOAuthFailure";
21
- }>;