@zeniai/client-epic-state 5.1.27 → 5.1.29-beta0ND

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 (49) hide show
  1. package/lib/commonPayloadTypes/payloadIdentifier.d.ts +6 -0
  2. package/lib/commonPayloadTypes/payloadIdentifier.js +18 -0
  3. package/lib/entity/customer/customerPayload.js +2 -11
  4. package/lib/entity/transaction/payloadTypes/vendorTransactionPayload.js +1 -1
  5. package/lib/entity/vendor/vendorPayload.d.ts +4 -2
  6. package/lib/entity/vendor/vendorPayload.js +12 -3
  7. package/lib/entity/vendor/vendorReducer.js +3 -0
  8. package/lib/esm/commonPayloadTypes/payloadIdentifier.js +14 -0
  9. package/lib/esm/entity/customer/customerPayload.js +2 -11
  10. package/lib/esm/entity/transaction/payloadTypes/vendorTransactionPayload.js +2 -2
  11. package/lib/esm/entity/vendor/vendorPayload.js +10 -2
  12. package/lib/esm/entity/vendor/vendorReducer.js +4 -1
  13. package/lib/esm/view/commonVendorView/transactionVendorView/transactionVendorViewReducer.js +2 -0
  14. package/lib/esm/view/onboardingView/cockpitView/epic/initializeOnboardingCustomerViewUpdateDataEpic.js +4 -16
  15. package/lib/esm/view/onboardingView/cockpitView/onboardingCockpitViewPayload.js +2 -2
  16. package/lib/esm/view/referralView/epics/sendReferralInviteEpic.js +9 -1
  17. package/lib/esm/view/transactionDetail/epics/markTransactionAsNotMiscategorizedEpic.js +28 -2
  18. package/lib/esm/view/transactionDetail/epics/transactionDetailEpic.js +10 -9
  19. package/lib/view/commonVendorView/transactionVendorView/transactionVendorViewReducer.js +2 -0
  20. package/lib/view/onboardingView/cockpitView/epic/initializeOnboardingCustomerViewUpdateDataEpic.js +3 -15
  21. package/lib/view/onboardingView/cockpitView/onboardingCockpitViewPayload.js +2 -2
  22. package/lib/view/referralView/epics/sendReferralInviteEpic.js +9 -1
  23. package/lib/view/transactionDetail/epics/markTransactionAsNotMiscategorizedEpic.js +28 -2
  24. package/lib/view/transactionDetail/epics/transactionDetailEpic.js +9 -8
  25. package/package.json +1 -1
  26. package/lib/__testHelpers__/apiFailure.json +0 -6
  27. package/lib/entity/vendor/__mocks__/vendorMock.d.ts +0 -7
  28. package/lib/entity/vendor/__mocks__/vendorMock.js +0 -311
  29. package/lib/entity/vendor/__mocks__/vendorStateMocks.d.ts +0 -8
  30. package/lib/entity/vendor/__mocks__/vendorStateMocks.js +0 -415
  31. package/lib/esm/__testHelpers__/apiFailure.json +0 -6
  32. package/lib/esm/entity/vendor/__mocks__/vendorMock.js +0 -308
  33. package/lib/esm/entity/vendor/__mocks__/vendorStateMocks.js +0 -412
  34. package/lib/esm/view/accountMappingView/__mocks__/accountMappingSelectorMock.js +0 -4650
  35. package/lib/esm/view/addressView/__mocks__/addressViewMocks.js +0 -203
  36. package/lib/esm/view/addressView/__mocks__/json/createAddressResponse.json +0 -23
  37. package/lib/esm/view/addressView/__mocks__/json/createCompanyAddressSuccess.json +0 -258
  38. package/lib/esm/view/addressView/__mocks__/json/createCompanyUserAddressSuccess.json +0 -418
  39. package/lib/esm/view/addressView/__mocks__/json/fetchAddressResponse.json +0 -24
  40. package/lib/esm/view/addressView/__mocks__/json/updateAddressResponse.json +0 -24
  41. package/lib/view/accountMappingView/__mocks__/accountMappingSelectorMock.d.ts +0 -11
  42. package/lib/view/accountMappingView/__mocks__/accountMappingSelectorMock.js +0 -4659
  43. package/lib/view/addressView/__mocks__/addressViewMocks.d.ts +0 -35
  44. package/lib/view/addressView/__mocks__/addressViewMocks.js +0 -239
  45. package/lib/view/addressView/__mocks__/json/createAddressResponse.json +0 -23
  46. package/lib/view/addressView/__mocks__/json/createCompanyAddressSuccess.json +0 -258
  47. package/lib/view/addressView/__mocks__/json/createCompanyUserAddressSuccess.json +0 -418
  48. package/lib/view/addressView/__mocks__/json/fetchAddressResponse.json +0 -24
  49. package/lib/view/addressView/__mocks__/json/updateAddressResponse.json +0 -24
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Resolves an entity identifier from a primary id and optional fallback id.
3
+ * Treats null and empty string as absent so JE/Deposit payloads can fall back
4
+ * to qbo_id uniformly across customer and vendor mappers.
5
+ */
6
+ export declare const resolvePayloadIdentifier: (primaryId: string | null | undefined, fallbackId: string | null | undefined) => string | null;
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.resolvePayloadIdentifier = void 0;
4
+ /**
5
+ * Resolves an entity identifier from a primary id and optional fallback id.
6
+ * Treats null and empty string as absent so JE/Deposit payloads can fall back
7
+ * to qbo_id uniformly across customer and vendor mappers.
8
+ */
9
+ const resolvePayloadIdentifier = (primaryId, fallbackId) => {
10
+ if (primaryId != null && primaryId !== '') {
11
+ return primaryId;
12
+ }
13
+ if (fallbackId != null && fallbackId !== '') {
14
+ return fallbackId;
15
+ }
16
+ return null;
17
+ };
18
+ exports.resolvePayloadIdentifier = resolvePayloadIdentifier;
@@ -2,23 +2,14 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.toCustomer = exports.toCustomerBasePayload = exports.toCustomerBase = exports.getCustomerPayloadIdentifier = void 0;
4
4
  const urlPayload_1 = require("../../commonPayloadTypes/urlPayload");
5
+ const payloadIdentifier_1 = require("../../commonPayloadTypes/payloadIdentifier");
5
6
  const zeniDayJS_1 = require("../../zeniDayJS");
6
7
  /**
7
8
  * Resolves the effective customer identifier from a payload.
8
9
  * For JE/Deposit transactions, customer_id is null at runtime — qbo_id is the
9
10
  * actual identity.
10
11
  */
11
- const getCustomerPayloadIdentifier = (customer) => {
12
- const cid = customer.customer_id;
13
- if (cid != null && cid !== '') {
14
- return cid;
15
- }
16
- const qid = customer.qbo_id;
17
- if (qid != null && qid !== '') {
18
- return qid;
19
- }
20
- return null;
21
- };
12
+ const getCustomerPayloadIdentifier = (customer) => (0, payloadIdentifier_1.resolvePayloadIdentifier)(customer.customer_id, customer.qbo_id);
22
13
  exports.getCustomerPayloadIdentifier = getCustomerPayloadIdentifier;
23
14
  const toCustomerBase = (payload, parseOutParentName) => {
24
15
  const id = (0, exports.getCustomerPayloadIdentifier)(payload);
@@ -15,7 +15,7 @@ function buildVendorTransactionBase(payload) {
15
15
  return {
16
16
  ...transaction,
17
17
  documentId: payload.document_id,
18
- vendor: payload.vendor_id != null
18
+ vendor: (0, vendorPayload_1.getVendorPayloadIdentifier)(payload) != null
19
19
  ? (0, vendorPayload_1.mapVendorBasePayloadToVendorBase)(payload)
20
20
  : undefined,
21
21
  paymentType: (0, paymentType_1.toPaymentTypeStrict)(payload.payment_type),
@@ -12,7 +12,7 @@ import { AttachmentPayload } from '../transaction/payloadTypes/attachmentPayload
12
12
  import { UserPayload } from '../user/userPayload';
13
13
  import { Vendor, VendorBase } from './vendorState';
14
14
  export interface VendorBasePayload {
15
- vendor_id: string;
15
+ vendor_id: string | null;
16
16
  vendor_name: string;
17
17
  logo?: URLPayload;
18
18
  qbo_id?: string;
@@ -20,9 +20,11 @@ export interface VendorBasePayload {
20
20
  /**
21
21
  * Resolves the effective vendor identifier from a payload.
22
22
  * For JE/Deposit transactions, vendor_id is null at runtime — qbo_id is the
23
- * actual identity. Using nullish-coalescing (`??`) handles both cases uniformly.
23
+ * actual identity.
24
24
  */
25
25
  export declare const getVendorPayloadIdentifier: (vendor: VendorBasePayload) => string | null;
26
+ /** Normalizes vendor_id to the resolved identifier when one exists. */
27
+ export declare const normalizeVendorBasePayload: (vendor: VendorBasePayload) => VendorBasePayload;
26
28
  export declare const mapVendorBasePayloadToVendorBase: (payload: VendorBasePayload) => VendorBase;
27
29
  export declare const toVendorBasePayload: (tranVendor: VendorBase | undefined, vendorUpdates?: VendorBase) => VendorBasePayload;
28
30
  interface MatchScorePayload {
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.mapVendorPayloadToVendor = exports.toVendorBasePayload = exports.mapVendorBasePayloadToVendorBase = exports.getVendorPayloadIdentifier = void 0;
3
+ exports.mapVendorPayloadToVendor = exports.toVendorBasePayload = exports.mapVendorBasePayloadToVendorBase = exports.normalizeVendorBasePayload = exports.getVendorPayloadIdentifier = void 0;
4
+ const payloadIdentifier_1 = require("../../commonPayloadTypes/payloadIdentifier");
4
5
  const urlPayload_1 = require("../../commonPayloadTypes/urlPayload");
5
6
  const common_1 = require("../../commonStateTypes/common");
6
7
  const zeniDayJS_1 = require("../../zeniDayJS");
@@ -11,10 +12,18 @@ const vendorType_1 = require("./vendorType");
11
12
  /**
12
13
  * Resolves the effective vendor identifier from a payload.
13
14
  * For JE/Deposit transactions, vendor_id is null at runtime — qbo_id is the
14
- * actual identity. Using nullish-coalescing (`??`) handles both cases uniformly.
15
+ * actual identity.
15
16
  */
16
- const getVendorPayloadIdentifier = (vendor) => vendor.vendor_id ?? vendor.qbo_id ?? null;
17
+ const getVendorPayloadIdentifier = (vendor) => (0, payloadIdentifier_1.resolvePayloadIdentifier)(vendor.vendor_id, vendor.qbo_id);
17
18
  exports.getVendorPayloadIdentifier = getVendorPayloadIdentifier;
19
+ /** Normalizes vendor_id to the resolved identifier when one exists. */
20
+ const normalizeVendorBasePayload = (vendor) => {
21
+ const resolvedVendorId = (0, exports.getVendorPayloadIdentifier)(vendor);
22
+ return resolvedVendorId != null
23
+ ? { ...vendor, vendor_id: resolvedVendorId }
24
+ : vendor;
25
+ };
26
+ exports.normalizeVendorBasePayload = normalizeVendorBasePayload;
18
27
  const mapVendorBasePayloadToVendorBase = (payload) => {
19
28
  const id = (0, exports.getVendorPayloadIdentifier)(payload);
20
29
  if (id == null) {
@@ -62,6 +62,9 @@ _a = vendor.actions, exports.updateVendors = _a.updateVendors, exports.removeVen
62
62
  exports.default = vendor.reducer;
63
63
  const doUpdateVendors = (draft, vendors, updateType) => {
64
64
  vendors.forEach((vendorPayload) => {
65
+ if ((0, vendorPayload_1.getVendorPayloadIdentifier)(vendorPayload) == null) {
66
+ return;
67
+ }
65
68
  const latestVendor = (0, vendorPayload_1.mapVendorPayloadToVendor)(vendorPayload);
66
69
  if (latestVendor.id in draft && updateType === 'merge') {
67
70
  (0, assignWith_1.default)(draft[latestVendor.id], latestVendor, (objValue, srcValue) => Boolean(srcValue) === false ? objValue : srcValue); // IMPORTANT: replace the value only when source has valid value. Otherwise keep the existing value!);
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Resolves an entity identifier from a primary id and optional fallback id.
3
+ * Treats null and empty string as absent so JE/Deposit payloads can fall back
4
+ * to qbo_id uniformly across customer and vendor mappers.
5
+ */
6
+ export const resolvePayloadIdentifier = (primaryId, fallbackId) => {
7
+ if (primaryId != null && primaryId !== '') {
8
+ return primaryId;
9
+ }
10
+ if (fallbackId != null && fallbackId !== '') {
11
+ return fallbackId;
12
+ }
13
+ return null;
14
+ };
@@ -1,21 +1,12 @@
1
1
  import { toURL } from '../../commonPayloadTypes/urlPayload';
2
+ import { resolvePayloadIdentifier } from '../../commonPayloadTypes/payloadIdentifier';
2
3
  import { date } from '../../zeniDayJS';
3
4
  /**
4
5
  * Resolves the effective customer identifier from a payload.
5
6
  * For JE/Deposit transactions, customer_id is null at runtime — qbo_id is the
6
7
  * actual identity.
7
8
  */
8
- export const getCustomerPayloadIdentifier = (customer) => {
9
- const cid = customer.customer_id;
10
- if (cid != null && cid !== '') {
11
- return cid;
12
- }
13
- const qid = customer.qbo_id;
14
- if (qid != null && qid !== '') {
15
- return qid;
16
- }
17
- return null;
18
- };
9
+ export const getCustomerPayloadIdentifier = (customer) => resolvePayloadIdentifier(customer.customer_id, customer.qbo_id);
19
10
  export const toCustomerBase = (payload, parseOutParentName) => {
20
11
  const id = getCustomerPayloadIdentifier(payload);
21
12
  if (id == null) {
@@ -1,7 +1,7 @@
1
1
  import { toAmountWC } from '../../../commonStateTypes/amount';
2
2
  import { date as zeniDate } from '../../../zeniDayJS';
3
3
  import { toCustomerBase, toCustomerBasePayload, } from '../../customer/customerPayload';
4
- import { mapVendorBasePayloadToVendorBase, toVendorBasePayload, } from '../../vendor/vendorPayload';
4
+ import { getVendorPayloadIdentifier, mapVendorBasePayloadToVendorBase, toVendorBasePayload, } from '../../vendor/vendorPayload';
5
5
  import { toPaymentTypeStrict } from '../stateTypes/paymentType';
6
6
  import { toVendorTransactionTypeStrict } from '../stateTypes/transactionType';
7
7
  import { toTransaction, toTransactionPayload, } from './transactionPayload';
@@ -11,7 +11,7 @@ function buildVendorTransactionBase(payload) {
11
11
  return {
12
12
  ...transaction,
13
13
  documentId: payload.document_id,
14
- vendor: payload.vendor_id != null
14
+ vendor: getVendorPayloadIdentifier(payload) != null
15
15
  ? mapVendorBasePayloadToVendorBase(payload)
16
16
  : undefined,
17
17
  paymentType: toPaymentTypeStrict(payload.payment_type),
@@ -1,3 +1,4 @@
1
+ import { resolvePayloadIdentifier } from '../../commonPayloadTypes/payloadIdentifier';
1
2
  import { toURL } from '../../commonPayloadTypes/urlPayload';
2
3
  import { toCompletionStatusType } from '../../commonStateTypes/common';
3
4
  import { date, dateNow } from '../../zeniDayJS';
@@ -8,9 +9,16 @@ import { toTinType } from './vendorType';
8
9
  /**
9
10
  * Resolves the effective vendor identifier from a payload.
10
11
  * For JE/Deposit transactions, vendor_id is null at runtime — qbo_id is the
11
- * actual identity. Using nullish-coalescing (`??`) handles both cases uniformly.
12
+ * actual identity.
12
13
  */
13
- export const getVendorPayloadIdentifier = (vendor) => vendor.vendor_id ?? vendor.qbo_id ?? null;
14
+ export const getVendorPayloadIdentifier = (vendor) => resolvePayloadIdentifier(vendor.vendor_id, vendor.qbo_id);
15
+ /** Normalizes vendor_id to the resolved identifier when one exists. */
16
+ export const normalizeVendorBasePayload = (vendor) => {
17
+ const resolvedVendorId = getVendorPayloadIdentifier(vendor);
18
+ return resolvedVendorId != null
19
+ ? { ...vendor, vendor_id: resolvedVendorId }
20
+ : vendor;
21
+ };
14
22
  export const mapVendorBasePayloadToVendorBase = (payload) => {
15
23
  const id = getVendorPayloadIdentifier(payload);
16
24
  if (id == null) {
@@ -1,6 +1,6 @@
1
1
  import { createSlice } from '@reduxjs/toolkit';
2
2
  import assignWith from 'lodash/assignWith';
3
- import { mapVendorPayloadToVendor, } from './vendorPayload';
3
+ import { getVendorPayloadIdentifier, mapVendorPayloadToVendor, } from './vendorPayload';
4
4
  export const initialState = {
5
5
  vendorByID: {},
6
6
  };
@@ -55,6 +55,9 @@ export const { updateVendors, removeVendor, updateVendorSpendTrend, clearAllVend
55
55
  export default vendor.reducer;
56
56
  const doUpdateVendors = (draft, vendors, updateType) => {
57
57
  vendors.forEach((vendorPayload) => {
58
+ if (getVendorPayloadIdentifier(vendorPayload) == null) {
59
+ return;
60
+ }
58
61
  const latestVendor = mapVendorPayloadToVendor(vendorPayload);
59
62
  if (latestVendor.id in draft && updateType === 'merge') {
60
63
  assignWith(draft[latestVendor.id], latestVendor, (objValue, srcValue) => Boolean(srcValue) === false ? objValue : srcValue); // IMPORTANT: replace the value only when source has valid value. Otherwise keep the existing value!);
@@ -90,6 +90,8 @@ const transactionVendorView = createSlice({
90
90
  };
91
91
  }
92
92
  else {
93
+ // Legacy empty-string key from pre-resolution vendor id writes.
94
+ delete draft.editVendorStateById[''];
93
95
  if (draft.editVendorStateById[vendorId] != null) {
94
96
  draft.editVendorStateById[vendorId].vendorDetailLocalData = {
95
97
  ...initialVendorDetailLocalData,
@@ -4,7 +4,7 @@ import { getAddressByAddressId } from '../../../../entity/address/addressSelecto
4
4
  import { getOnboardingCompanyByCompanyId } from '../../../../entity/company/companySelector';
5
5
  import { toAccountingConnectionCreationModeStrict } from '../../../../entity/company/companyStateTypes';
6
6
  import { getOnboardingCustomersByCompanyId } from '../../../../entity/onboardingCustomer/onboardingCustomerSelector';
7
- import { getOnboardingTenantByTenantId, isOtherProductsEnabledForTenant, isTenantBankingOnly, isTenantBookkeepingEnabled, isTenantCardsOnly, isTenantTreasuryEnabled, } from '../../../../entity/tenant/tenantSelector';
7
+ import { getOnboardingTenantByTenantId, isOtherProductsEnabledForTenant, isTenantBankingOnly, isTenantBookkeepingEnabled, isTenantCardsOnly, } from '../../../../entity/tenant/tenantSelector';
8
8
  import { getUserByUserId } from '../../../../entity/user/userSelector';
9
9
  import { newAddressInLocalStore, resetNewAddressesInLocalStore, } from '../../../addressView/addressViewReducer';
10
10
  import { clearOnboardingCustomerViewUpdateData, initializeOnboardingCustomerViewUpdateData, saveOnboardingCustomerDataInLocalStore, saveOnboardingCustomerViewUpdateData, updateCustomerLocalStoreInitStateOnFailure, } from '../onboardingCockpitViewReducer';
@@ -112,32 +112,20 @@ const getSelectedProducts = (isDebitCardFlagEnabled, tenant) => {
112
112
  const isBookkeepingEnabled = isTenantBookkeepingEnabled(tenant);
113
113
  const isOtherProductsEnabled = isOtherProductsEnabledForTenant(tenant);
114
114
  const isCardsEnabled = isTenantCardsOnly(tenant);
115
- const isTreasuryEnabled = isTenantTreasuryEnabled(tenant);
116
115
  if (isCardsEnabled && isBankingOnly) {
117
- const selectedProducts = ['zeni_cards', 'zeni_checking'];
118
- if (isTreasuryEnabled) {
119
- selectedProducts.push('zeni_treasury');
120
- }
121
- return selectedProducts;
116
+ return [];
122
117
  }
123
118
  else if (isBankingOnly) {
124
- const selectedProducts = ['zeni_checking'];
125
- if (isTreasuryEnabled) {
126
- selectedProducts.push('zeni_treasury');
127
- }
128
- return selectedProducts;
119
+ return [];
129
120
  }
130
121
  else if (isCardsEnabled) {
131
- return ['zeni_cards'];
122
+ return [];
132
123
  }
133
124
  else if (isBookkeepingEnabled) {
134
125
  return [
135
126
  'bookkeeping',
136
127
  'zeni_bill_pay',
137
- 'zeni_checking',
138
128
  'zeni_reimbursements',
139
- 'zeni_treasury',
140
- 'zeni_cards',
141
129
  ];
142
130
  }
143
131
  else if (isOtherProductsEnabled) {
@@ -48,9 +48,9 @@ export const toOnboardingCustomerPayload = (onboardingCustomer, sendInvite, comp
48
48
  const isTreasury = selectedProducts.includes('zeni_treasury');
49
49
  if (isBookkeeping) {
50
50
  onboardingCustomerPayload.is_book_keeping_enabled = true;
51
- onboardingCustomerPayload.is_banking_enabled = true;
51
+ onboardingCustomerPayload.is_banking_enabled = isChecking;
52
52
  onboardingCustomerPayload.is_spend_management_enabled = true;
53
- onboardingCustomerPayload.is_card_enabled = true;
53
+ onboardingCustomerPayload.is_card_enabled = isCards;
54
54
  onboardingCustomerPayload.is_treasury_enabled = isTreasury;
55
55
  }
56
56
  else if (isChecking && isCards) {
@@ -1,5 +1,6 @@
1
1
  import { of } from 'rxjs';
2
2
  import { catchError, filter, mergeMap, switchMap } from 'rxjs/operators';
3
+ import { openSnackbar } from '../../../entity/snackbar/snackbarReducer';
3
4
  import { createZeniAPIStatus, isSuccessStatus } from '../../../responsePayload';
4
5
  import { sendReferralInvite, sendReferralInviteFailure, sendReferralInviteSuccess, } from '../referralReducer';
5
6
  export const sendReferralInviteEpic = (actions$, state$, zeniAPI) => actions$.pipe(filter(sendReferralInvite.match), switchMap(() => {
@@ -13,7 +14,14 @@ export const sendReferralInviteEpic = (actions$, state$, zeniAPI) => actions$.pi
13
14
  .postAndGetJSON(`${zeniAPI.apiEndPoints.tenantMicroServiceBaseUrl}/1.0/company-referrals`, invitePayload)
14
15
  .pipe(mergeMap((response) => {
15
16
  if (isSuccessStatus(response)) {
16
- const actions = [sendReferralInviteSuccess()];
17
+ const actions = [
18
+ sendReferralInviteSuccess(),
19
+ openSnackbar({
20
+ messageSection: 'referral_invite_sent',
21
+ messageText: 'success',
22
+ type: 'success',
23
+ }),
24
+ ];
17
25
  return actions;
18
26
  }
19
27
  else {
@@ -9,10 +9,36 @@ import { updateStatusForTransactionNotMiscategorizedUpdateForCategorization, upd
9
9
  import { markTransactionAsNotMiscategorized, updateStatusConsolidatedSaveTransactionDetail, updateStatusForTransactionNotMiscategorizedUpdate, } from '../transactionDetailReducer';
10
10
  import { getTransactionDetailKey } from '../transactionDetailState';
11
11
  export const markTransactionAsNotMiscategorizedEpic = (actions$, state$, zeniAPI) => actions$.pipe(filter(markTransactionAsNotMiscategorized.match), mergeMap((action) => {
12
+ // Expense-automation customers must be marked review-complete through the
13
+ // same endpoint the categorization list uses; mark-miscategorized-as-correct
14
+ // does not move their lines out of review. Mirror the list flow by reviewing
15
+ // the transaction's categorizable line ids (updatesByLineId).
16
+ const { url, body } = action.payload.isExpenseAutomationEnabled === true
17
+ ? {
18
+ url: `${zeniAPI.apiEndPoints.accountMicroServiceBaseUrl}/1.0/expense-automation/mark-as-reviewed`,
19
+ body: {
20
+ transactions_reviewed: [
21
+ {
22
+ transaction_id: action.payload.transactionId.id,
23
+ line_ids: Object.keys(action.payload.transactionSaveUpdates.updates
24
+ ?.updatesByLineId ?? {}),
25
+ },
26
+ ],
27
+ },
28
+ }
29
+ : {
30
+ url: `${zeniAPI.apiEndPoints.accountMicroServiceBaseUrl}/1.0/transactions/${action.payload.transactionId.id}/mark-miscategorized-as-correct`,
31
+ body: preparePayload(action.payload.transactionId),
32
+ };
12
33
  return zeniAPI
13
- .putAndGetJSON(`${zeniAPI.apiEndPoints.accountMicroServiceBaseUrl}/1.0/transactions/${action.payload.transactionId.id}/mark-miscategorized-as-correct`, preparePayload(action.payload.transactionId))
34
+ .putAndGetJSON(url, body)
14
35
  .pipe(mergeMap((response) => {
15
- if (isSuccessStatus(response)) {
36
+ // mark-as-reviewed can return 200 while still listing this
37
+ // transaction under transactions_reviewed_failed; don't clear it then.
38
+ const reviewedFailedForExpenseAutomation = action.payload.isExpenseAutomationEnabled === true &&
39
+ (response.data?.transactions_reviewed_failed ?? []).some((reviewed) => reviewed.transaction_id === action.payload.transactionId.id);
40
+ if (isSuccessStatus(response) &&
41
+ !reviewedFailedForExpenseAutomation) {
16
42
  const actions = [];
17
43
  actions.push(updateStatusForTransactionNotMiscategorizedUpdate(action.payload.transactionId, 'Completed', undefined));
18
44
  const transactionKey = getTransactionDetailKey(action.payload.transactionId);
@@ -6,7 +6,7 @@ import { toTransaction, } from '../../../entity/transaction/payloadTypes/transac
6
6
  import { toVendorTransactionTypeStrict } from '../../../entity/transaction/stateTypes/transactionType';
7
7
  import { removeTransaction, updateTransaction, } from '../../../entity/transaction/transactionReducer';
8
8
  import { getSupportedTransactionById } from '../../../entity/transaction/transactionSelector';
9
- import { mapVendorPayloadToVendor } from '../../../entity/vendor/vendorPayload';
9
+ import { mapVendorPayloadToVendor, getVendorPayloadIdentifier, normalizeVendorBasePayload } from '../../../entity/vendor/vendorPayload';
10
10
  import { updateVendors } from '../../../entity/vendor/vendorReducer';
11
11
  import { createZeniAPIStatus, isSuccessResponse } from '../../../responsePayload';
12
12
  import { fetchAccountList } from '../../accountList/accountListReducer';
@@ -56,11 +56,11 @@ export const fetchTransactionDetailEpic = (actions$, state$, zeniAPI) => actions
56
56
  const transcationId = toTransactionID(response.data.transaction);
57
57
  const responseData = {
58
58
  ...response.data,
59
- vendors: response.data.vendors?.map((vendor) => ({
60
- ...vendor,
61
- vendor_id: vendor.qbo_id ?? vendor.vendor_id,
62
- })) ?? [],
59
+ vendors: response.data.vendors?.map((vendor) => normalizeVendorBasePayload(vendor)) ?? [],
63
60
  };
61
+ const resolvedVendorId = responseData.vendors.length > 0
62
+ ? getVendorPayloadIdentifier(responseData.vendors[0])
63
+ : null;
64
64
  if (responseData.vendors.length > 0) {
65
65
  updateActions.push(updateVendors(responseData.vendors, 'merge'));
66
66
  }
@@ -68,15 +68,16 @@ export const fetchTransactionDetailEpic = (actions$, state$, zeniAPI) => actions
68
68
  updateActions.push(updateTransaction(transactionDetailKeyForResponse, responseData.transaction));
69
69
  updateActions.push(initializeTransactionDetailLocalData({
70
70
  transactionId: transcationId,
71
- vendorId: responseData.vendors[0]?.vendor_id,
71
+ vendorId: resolvedVendorId ?? undefined,
72
72
  }));
73
73
  updateActions.push(updateTransactionDetailFetchState(transcationId, 'Completed'));
74
74
  // IMPORTANT: Fetch linked transactions..
75
75
  updateActions.push(...getAllFetchLinkedTransactionDetailActions(responseData.transaction, state$.value));
76
- if (responseData.vendors.length > 0) {
76
+ if (resolvedVendorId != null) {
77
+ const vendorPayload = responseData.vendors[0];
77
78
  updateActions.push(updateTransactionVendorLocalData({
78
- vendorId: responseData.vendors[0].vendor_id,
79
- localData: getInitializedTransactionVendorLocalData(mapVendorPayloadToVendor(responseData.vendors[0])),
79
+ vendorId: resolvedVendorId,
80
+ localData: getInitializedTransactionVendorLocalData(mapVendorPayloadToVendor(vendorPayload)),
80
81
  }));
81
82
  }
82
83
  // If vendor transaction, fetch owners list
@@ -94,6 +94,8 @@ const transactionVendorView = (0, toolkit_1.createSlice)({
94
94
  };
95
95
  }
96
96
  else {
97
+ // Legacy empty-string key from pre-resolution vendor id writes.
98
+ delete draft.editVendorStateById[''];
97
99
  if (draft.editVendorStateById[vendorId] != null) {
98
100
  draft.editVendorStateById[vendorId].vendorDetailLocalData = {
99
101
  ...exports.initialVendorDetailLocalData,
@@ -116,32 +116,20 @@ const getSelectedProducts = (isDebitCardFlagEnabled, tenant) => {
116
116
  const isBookkeepingEnabled = (0, tenantSelector_1.isTenantBookkeepingEnabled)(tenant);
117
117
  const isOtherProductsEnabled = (0, tenantSelector_1.isOtherProductsEnabledForTenant)(tenant);
118
118
  const isCardsEnabled = (0, tenantSelector_1.isTenantCardsOnly)(tenant);
119
- const isTreasuryEnabled = (0, tenantSelector_1.isTenantTreasuryEnabled)(tenant);
120
119
  if (isCardsEnabled && isBankingOnly) {
121
- const selectedProducts = ['zeni_cards', 'zeni_checking'];
122
- if (isTreasuryEnabled) {
123
- selectedProducts.push('zeni_treasury');
124
- }
125
- return selectedProducts;
120
+ return [];
126
121
  }
127
122
  else if (isBankingOnly) {
128
- const selectedProducts = ['zeni_checking'];
129
- if (isTreasuryEnabled) {
130
- selectedProducts.push('zeni_treasury');
131
- }
132
- return selectedProducts;
123
+ return [];
133
124
  }
134
125
  else if (isCardsEnabled) {
135
- return ['zeni_cards'];
126
+ return [];
136
127
  }
137
128
  else if (isBookkeepingEnabled) {
138
129
  return [
139
130
  'bookkeeping',
140
131
  'zeni_bill_pay',
141
- 'zeni_checking',
142
132
  'zeni_reimbursements',
143
- 'zeni_treasury',
144
- 'zeni_cards',
145
133
  ];
146
134
  }
147
135
  else if (isOtherProductsEnabled) {
@@ -51,9 +51,9 @@ const toOnboardingCustomerPayload = (onboardingCustomer, sendInvite, company, te
51
51
  const isTreasury = selectedProducts.includes('zeni_treasury');
52
52
  if (isBookkeeping) {
53
53
  onboardingCustomerPayload.is_book_keeping_enabled = true;
54
- onboardingCustomerPayload.is_banking_enabled = true;
54
+ onboardingCustomerPayload.is_banking_enabled = isChecking;
55
55
  onboardingCustomerPayload.is_spend_management_enabled = true;
56
- onboardingCustomerPayload.is_card_enabled = true;
56
+ onboardingCustomerPayload.is_card_enabled = isCards;
57
57
  onboardingCustomerPayload.is_treasury_enabled = isTreasury;
58
58
  }
59
59
  else if (isChecking && isCards) {
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.sendReferralInviteEpic = void 0;
4
4
  const rxjs_1 = require("rxjs");
5
5
  const operators_1 = require("rxjs/operators");
6
+ const snackbarReducer_1 = require("../../../entity/snackbar/snackbarReducer");
6
7
  const responsePayload_1 = require("../../../responsePayload");
7
8
  const referralReducer_1 = require("../referralReducer");
8
9
  const sendReferralInviteEpic = (actions$, state$, zeniAPI) => actions$.pipe((0, operators_1.filter)(referralReducer_1.sendReferralInvite.match), (0, operators_1.switchMap)(() => {
@@ -16,7 +17,14 @@ const sendReferralInviteEpic = (actions$, state$, zeniAPI) => actions$.pipe((0,
16
17
  .postAndGetJSON(`${zeniAPI.apiEndPoints.tenantMicroServiceBaseUrl}/1.0/company-referrals`, invitePayload)
17
18
  .pipe((0, operators_1.mergeMap)((response) => {
18
19
  if ((0, responsePayload_1.isSuccessStatus)(response)) {
19
- const actions = [(0, referralReducer_1.sendReferralInviteSuccess)()];
20
+ const actions = [
21
+ (0, referralReducer_1.sendReferralInviteSuccess)(),
22
+ (0, snackbarReducer_1.openSnackbar)({
23
+ messageSection: 'referral_invite_sent',
24
+ messageText: 'success',
25
+ type: 'success',
26
+ }),
27
+ ];
20
28
  return actions;
21
29
  }
22
30
  else {
@@ -12,10 +12,36 @@ const transactionsViewReducer_1 = require("../../expenseAutomationView/reducers/
12
12
  const transactionDetailReducer_1 = require("../transactionDetailReducer");
13
13
  const transactionDetailState_1 = require("../transactionDetailState");
14
14
  const markTransactionAsNotMiscategorizedEpic = (actions$, state$, zeniAPI) => actions$.pipe((0, operators_1.filter)(transactionDetailReducer_1.markTransactionAsNotMiscategorized.match), (0, operators_1.mergeMap)((action) => {
15
+ // Expense-automation customers must be marked review-complete through the
16
+ // same endpoint the categorization list uses; mark-miscategorized-as-correct
17
+ // does not move their lines out of review. Mirror the list flow by reviewing
18
+ // the transaction's categorizable line ids (updatesByLineId).
19
+ const { url, body } = action.payload.isExpenseAutomationEnabled === true
20
+ ? {
21
+ url: `${zeniAPI.apiEndPoints.accountMicroServiceBaseUrl}/1.0/expense-automation/mark-as-reviewed`,
22
+ body: {
23
+ transactions_reviewed: [
24
+ {
25
+ transaction_id: action.payload.transactionId.id,
26
+ line_ids: Object.keys(action.payload.transactionSaveUpdates.updates
27
+ ?.updatesByLineId ?? {}),
28
+ },
29
+ ],
30
+ },
31
+ }
32
+ : {
33
+ url: `${zeniAPI.apiEndPoints.accountMicroServiceBaseUrl}/1.0/transactions/${action.payload.transactionId.id}/mark-miscategorized-as-correct`,
34
+ body: preparePayload(action.payload.transactionId),
35
+ };
15
36
  return zeniAPI
16
- .putAndGetJSON(`${zeniAPI.apiEndPoints.accountMicroServiceBaseUrl}/1.0/transactions/${action.payload.transactionId.id}/mark-miscategorized-as-correct`, preparePayload(action.payload.transactionId))
37
+ .putAndGetJSON(url, body)
17
38
  .pipe((0, operators_1.mergeMap)((response) => {
18
- if ((0, responsePayload_1.isSuccessStatus)(response)) {
39
+ // mark-as-reviewed can return 200 while still listing this
40
+ // transaction under transactions_reviewed_failed; don't clear it then.
41
+ const reviewedFailedForExpenseAutomation = action.payload.isExpenseAutomationEnabled === true &&
42
+ (response.data?.transactions_reviewed_failed ?? []).some((reviewed) => reviewed.transaction_id === action.payload.transactionId.id);
43
+ if ((0, responsePayload_1.isSuccessStatus)(response) &&
44
+ !reviewedFailedForExpenseAutomation) {
19
45
  const actions = [];
20
46
  actions.push((0, transactionDetailReducer_1.updateStatusForTransactionNotMiscategorizedUpdate)(action.payload.transactionId, 'Completed', undefined));
21
47
  const transactionKey = (0, transactionDetailState_1.getTransactionDetailKey)(action.payload.transactionId);
@@ -62,11 +62,11 @@ const fetchTransactionDetailEpic = (actions$, state$, zeniAPI) => actions$.pipe(
62
62
  const transcationId = (0, transactionIDPayload_1.toTransactionID)(response.data.transaction);
63
63
  const responseData = {
64
64
  ...response.data,
65
- vendors: response.data.vendors?.map((vendor) => ({
66
- ...vendor,
67
- vendor_id: vendor.qbo_id ?? vendor.vendor_id,
68
- })) ?? [],
65
+ vendors: response.data.vendors?.map((vendor) => (0, vendorPayload_1.normalizeVendorBasePayload)(vendor)) ?? [],
69
66
  };
67
+ const resolvedVendorId = responseData.vendors.length > 0
68
+ ? (0, vendorPayload_1.getVendorPayloadIdentifier)(responseData.vendors[0])
69
+ : null;
70
70
  if (responseData.vendors.length > 0) {
71
71
  updateActions.push((0, vendorReducer_1.updateVendors)(responseData.vendors, 'merge'));
72
72
  }
@@ -74,15 +74,16 @@ const fetchTransactionDetailEpic = (actions$, state$, zeniAPI) => actions$.pipe(
74
74
  updateActions.push((0, transactionReducer_1.updateTransaction)(transactionDetailKeyForResponse, responseData.transaction));
75
75
  updateActions.push((0, transactionDetailReducer_1.initializeTransactionDetailLocalData)({
76
76
  transactionId: transcationId,
77
- vendorId: responseData.vendors[0]?.vendor_id,
77
+ vendorId: resolvedVendorId ?? undefined,
78
78
  }));
79
79
  updateActions.push((0, transactionDetailReducer_1.updateTransactionDetailFetchState)(transcationId, 'Completed'));
80
80
  // IMPORTANT: Fetch linked transactions..
81
81
  updateActions.push(...getAllFetchLinkedTransactionDetailActions(responseData.transaction, state$.value));
82
- if (responseData.vendors.length > 0) {
82
+ if (resolvedVendorId != null) {
83
+ const vendorPayload = responseData.vendors[0];
83
84
  updateActions.push((0, transactionVendorViewReducer_1.updateTransactionVendorLocalData)({
84
- vendorId: responseData.vendors[0].vendor_id,
85
- localData: (0, transactionVendorLocalDataHelper_1.getInitializedTransactionVendorLocalData)((0, vendorPayload_1.mapVendorPayloadToVendor)(responseData.vendors[0])),
85
+ vendorId: resolvedVendorId,
86
+ localData: (0, transactionVendorLocalDataHelper_1.getInitializedTransactionVendorLocalData)((0, vendorPayload_1.mapVendorPayloadToVendor)(vendorPayload)),
86
87
  }));
87
88
  }
88
89
  // If vendor transaction, fetch owners list
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zeniai/client-epic-state",
3
- "version": "5.1.27",
3
+ "version": "5.1.29-beta0ND",
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,6 +0,0 @@
1
- {
2
- "status": {
3
- "message": "Internal server error",
4
- "code": 500
5
- }
6
- }
@@ -1,7 +0,0 @@
1
- import { ID } from '../../../commonStateTypes/common';
2
- import { VendorPayload } from '../vendorPayload';
3
- import { VendorState } from '../vendorState';
4
- export declare const vendorPaylod: VendorPayload[];
5
- export declare const vendorStateWithVendors: VendorState;
6
- export declare const vendorIdToBeRemoved: ID;
7
- export declare const vendorStateAfterRemoval: VendorState;