@zeniai/client-epic-state 5.2.5 → 5.2.6
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.
- package/lib/epic.js +2 -4
- package/lib/esm/epic.js +2 -4
- package/lib/esm/index.js +2 -1
- package/lib/esm/view/accountList/accountListReducer.js +1 -0
- package/lib/esm/view/invoicing/editInvoicingCatalogItemDetailView/editInvoicingCatalogItemDetailViewSelector.js +8 -0
- package/lib/esm/view/invoicing/invoicingQboView/epics/fetchInvoicingAccountingPickersEpic.js +29 -0
- package/lib/esm/view/invoicing/invoicingQboView/invoicingQboViewPayload.js +0 -23
- package/lib/esm/view/invoicing/invoicingQboView/invoicingQboViewReducer.js +3 -40
- package/lib/esm/view/invoicing/invoicingQboView/invoicingQboViewSelector.js +124 -6
- package/lib/index.d.ts +4 -2
- package/lib/index.js +6 -4
- package/lib/view/accountList/accountListReducer.js +1 -0
- package/lib/view/accountList/accountListState.d.ts +1 -1
- package/lib/view/invoicing/editInvoicingCatalogItemDetailView/editInvoicingCatalogItemDetailViewSelector.d.ts +9 -0
- package/lib/view/invoicing/editInvoicingCatalogItemDetailView/editInvoicingCatalogItemDetailViewSelector.js +8 -0
- package/lib/view/invoicing/invoicingQboView/epics/fetchInvoicingAccountingPickersEpic.d.ts +5 -0
- package/lib/view/invoicing/invoicingQboView/epics/fetchInvoicingAccountingPickersEpic.js +33 -0
- package/lib/view/invoicing/invoicingQboView/epics/invoicingQboViewActionType.d.ts +4 -2
- package/lib/view/invoicing/invoicingQboView/invoicingQboViewPayload.d.ts +0 -26
- package/lib/view/invoicing/invoicingQboView/invoicingQboViewPayload.js +0 -24
- package/lib/view/invoicing/invoicingQboView/invoicingQboViewReducer.d.ts +2 -10
- package/lib/view/invoicing/invoicingQboView/invoicingQboViewReducer.js +4 -41
- package/lib/view/invoicing/invoicingQboView/invoicingQboViewSelector.d.ts +43 -6
- package/lib/view/invoicing/invoicingQboView/invoicingQboViewSelector.js +128 -7
- package/lib/view/invoicing/invoicingQboView/invoicingQboViewState.d.ts +1 -5
- package/package.json +1 -1
- package/lib/esm/view/invoicing/invoicingQboView/epics/fetchInvoicingQboAccountsEpic.js +0 -25
- package/lib/esm/view/invoicing/invoicingQboView/epics/fetchInvoicingQboClassesEpic.js +0 -15
- package/lib/view/invoicing/invoicingQboView/epics/fetchInvoicingQboAccountsEpic.d.ts +0 -6
- package/lib/view/invoicing/invoicingQboView/epics/fetchInvoicingQboAccountsEpic.js +0 -29
- package/lib/view/invoicing/invoicingQboView/epics/fetchInvoicingQboClassesEpic.d.ts +0 -6
- package/lib/view/invoicing/invoicingQboView/epics/fetchInvoicingQboClassesEpic.js +0 -19
package/lib/epic.js
CHANGED
|
@@ -297,8 +297,7 @@ const fetchInvoicingOverviewKPIsEpic_1 = require("./view/invoicing/invoicingOver
|
|
|
297
297
|
const fetchInvoicingOverviewMRREpic_1 = require("./view/invoicing/invoicingOverview/epics/fetchInvoicingOverviewMRREpic");
|
|
298
298
|
const fetchInvoicingOverviewPlanRevenueEpic_1 = require("./view/invoicing/invoicingOverview/epics/fetchInvoicingOverviewPlanRevenueEpic");
|
|
299
299
|
const fetchInvoicingOverviewRevenueEpic_1 = require("./view/invoicing/invoicingOverview/epics/fetchInvoicingOverviewRevenueEpic");
|
|
300
|
-
const
|
|
301
|
-
const fetchInvoicingQboClassesEpic_1 = require("./view/invoicing/invoicingQboView/epics/fetchInvoicingQboClassesEpic");
|
|
300
|
+
const fetchInvoicingAccountingPickersEpic_1 = require("./view/invoicing/invoicingQboView/epics/fetchInvoicingAccountingPickersEpic");
|
|
302
301
|
const fetchInvoicingQboConnectionEpic_1 = require("./view/invoicing/invoicingQboView/epics/fetchInvoicingQboConnectionEpic");
|
|
303
302
|
const fetchInvoicingQboSyncHealthEpic_1 = require("./view/invoicing/invoicingQboView/epics/fetchInvoicingQboSyncHealthEpic");
|
|
304
303
|
const retryInvoicingQboSyncTaskEpic_1 = require("./view/invoicing/invoicingQboView/epics/retryInvoicingQboSyncTaskEpic");
|
|
@@ -983,6 +982,7 @@ const ALL_EPICS = [
|
|
|
983
982
|
fetchInvoiceKPIsEpic_1.fetchInvoiceKPIsEpic,
|
|
984
983
|
fetchInvoiceListEpic_1.fetchInvoiceListEpic,
|
|
985
984
|
fetchInvoiceListPageEpic_1.fetchInvoiceListPageEpic,
|
|
985
|
+
fetchInvoicingAccountingPickersEpic_1.fetchInvoicingAccountingPickersEpic,
|
|
986
986
|
auditViewEpics_1.fetchInvoicingAuditLogEpic,
|
|
987
987
|
fetchInvoicingCatalogCountsEpic_1.fetchInvoicingCatalogCountsEpic,
|
|
988
988
|
invoicingCatalogItemDetailViewEpics_1.fetchInvoicingCatalogItemDetailEpic,
|
|
@@ -1021,8 +1021,6 @@ const ALL_EPICS = [
|
|
|
1021
1021
|
fetchInvoicingOverviewPlanRevenueEpic_1.fetchInvoicingOverviewPlanRevenueEpic,
|
|
1022
1022
|
fetchInvoicingOverviewRevenueEpic_1.fetchInvoicingOverviewRevenueEpic,
|
|
1023
1023
|
customerPaymentMethodEpic_1.fetchInvoicingPlaidLinkTokenEpic,
|
|
1024
|
-
fetchInvoicingQboAccountsEpic_1.fetchInvoicingQboAccountsEpic,
|
|
1025
|
-
fetchInvoicingQboClassesEpic_1.fetchInvoicingQboClassesEpic,
|
|
1026
1024
|
fetchInvoicingQboConnectionEpic_1.fetchInvoicingQboConnectionEpic,
|
|
1027
1025
|
fetchInvoicingQboSyncHealthEpic_1.fetchInvoicingQboSyncHealthEpic,
|
|
1028
1026
|
settingsViewEpics_1.fetchInvoicingSettingsEpic,
|
package/lib/esm/epic.js
CHANGED
|
@@ -294,8 +294,7 @@ import { fetchInvoicingOverviewKPIsEpic } from './view/invoicing/invoicingOvervi
|
|
|
294
294
|
import { fetchInvoicingOverviewMRREpic } from './view/invoicing/invoicingOverview/epics/fetchInvoicingOverviewMRREpic';
|
|
295
295
|
import { fetchInvoicingOverviewPlanRevenueEpic } from './view/invoicing/invoicingOverview/epics/fetchInvoicingOverviewPlanRevenueEpic';
|
|
296
296
|
import { fetchInvoicingOverviewRevenueEpic } from './view/invoicing/invoicingOverview/epics/fetchInvoicingOverviewRevenueEpic';
|
|
297
|
-
import {
|
|
298
|
-
import { fetchInvoicingQboClassesEpic } from './view/invoicing/invoicingQboView/epics/fetchInvoicingQboClassesEpic';
|
|
297
|
+
import { fetchInvoicingAccountingPickersEpic } from './view/invoicing/invoicingQboView/epics/fetchInvoicingAccountingPickersEpic';
|
|
299
298
|
import { fetchInvoicingQboConnectionEpic } from './view/invoicing/invoicingQboView/epics/fetchInvoicingQboConnectionEpic';
|
|
300
299
|
import { fetchInvoicingQboSyncHealthEpic } from './view/invoicing/invoicingQboView/epics/fetchInvoicingQboSyncHealthEpic';
|
|
301
300
|
import { retryInvoicingQboSyncTaskEpic } from './view/invoicing/invoicingQboView/epics/retryInvoicingQboSyncTaskEpic';
|
|
@@ -980,6 +979,7 @@ const ALL_EPICS = [
|
|
|
980
979
|
fetchInvoiceKPIsEpic,
|
|
981
980
|
fetchInvoiceListEpic,
|
|
982
981
|
fetchInvoiceListPageEpic,
|
|
982
|
+
fetchInvoicingAccountingPickersEpic,
|
|
983
983
|
fetchInvoicingAuditLogEpic,
|
|
984
984
|
fetchInvoicingCatalogCountsEpic,
|
|
985
985
|
fetchInvoicingCatalogItemDetailEpic,
|
|
@@ -1018,8 +1018,6 @@ const ALL_EPICS = [
|
|
|
1018
1018
|
fetchInvoicingOverviewPlanRevenueEpic,
|
|
1019
1019
|
fetchInvoicingOverviewRevenueEpic,
|
|
1020
1020
|
fetchInvoicingPlaidLinkTokenEpic,
|
|
1021
|
-
fetchInvoicingQboAccountsEpic,
|
|
1022
|
-
fetchInvoicingQboClassesEpic,
|
|
1023
1021
|
fetchInvoicingQboConnectionEpic,
|
|
1024
1022
|
fetchInvoicingQboSyncHealthEpic,
|
|
1025
1023
|
fetchInvoicingSettingsEpic,
|
package/lib/esm/index.js
CHANGED
|
@@ -853,7 +853,8 @@ export { getInvoicingBrandingFormView, getInvoicingSettings, getInvoicingSetting
|
|
|
853
853
|
export { INVOICING_BUSINESS_ADDRESS_TYPE, entityToInvoicingBrandingFormLocalData, initialInvoicingBrandingFormLocalData, } from './view/invoicing/settingsView/invoicingBrandingFormConfig';
|
|
854
854
|
export { isStripeConnectedFromSettings } from './view/invoicing/settingsView/invoicingSettingsHelpers';
|
|
855
855
|
// ── Invoicing: QBO integration ────────────────────────────────────────────────
|
|
856
|
-
export {
|
|
856
|
+
export { fetchInvoicingAccountingPickers, fetchInvoicingQboConnection, fetchInvoicingQboSyncHealth, retryInvoicingQboSyncTask, startInvoicingQboBackfill, } from './view/invoicing/invoicingQboView/invoicingQboViewReducer';
|
|
857
|
+
export { INVOICING_INCOME_ACCOUNT_TYPES, invoicingAccountsForQboAccountTypes, } from './view/invoicing/invoicingQboView/invoicingQboViewSelector';
|
|
857
858
|
export { getInvoicingQboView } from './view/invoicing/invoicingQboView/invoicingQboViewSelector';
|
|
858
859
|
export { INVOICING_QBO_CUSTOMER_MATCHING_MODES, getInvoicingQboAccountMappingId, toInvoicingNamedOptionsByKey, toInvoicingQboCustomerMatchingMode, withInvoicingQboAccountMappingId, } from './entity/invoicing/invoicingCommonPayload';
|
|
859
860
|
// ── Invoicing: config ─────────────────────────────────────────────────────────
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { createSelector } from '@reduxjs/toolkit';
|
|
2
2
|
import { getInvoicingPlanById, getInvoicingPlansByIds, } from '../../../entity/invoicing/plan/planSelector';
|
|
3
3
|
import { getInvoicingConfigView, invoicingFieldHelpForGroup, } from '../invoicingConfigView/invoicingConfigViewSelector';
|
|
4
|
+
import { INVOICING_INCOME_ACCOUNT_TYPES, getInvoicingQboView, invoicingAccountHierarchyForTypes, isInvoicingQboConnected, } from '../invoicingQboView/invoicingQboViewSelector';
|
|
4
5
|
import { INVOICING_CATALOG_APPLICABILITY_VALUES, INVOICING_CATALOG_PRICING_MODEL_VALUES, INVOICING_CATALOG_PRORATION_VALUES, INVOICING_CATALOG_TIER_TYPE_VALUES, entityToInvoicingCatalogItemFormLocalData, } from './invoicingCatalogItemFormConfig';
|
|
5
6
|
export const getEditInvoicingCatalogItemDetailViewState = (state) => ({
|
|
6
7
|
fetchState: state.editInvoicingCatalogItemDetailViewState.fetchState,
|
|
@@ -48,9 +49,16 @@ export const getInvoicingCatalogItemFormView = (state, id) => {
|
|
|
48
49
|
const applicableItemOptions = id != null
|
|
49
50
|
? allApplicableItemOptions.filter((option) => option.id !== id)
|
|
50
51
|
: allApplicableItemOptions;
|
|
52
|
+
const isQboConnected = isInvoicingQboConnected(state);
|
|
51
53
|
const { billingPeriodUnitOptions, catalogItemTypeOptions, catalogTierTypeOptionsByPricingModel, catalogTrialEndActionOptions, catalogTrialUnitOptions, } = getInvoicingConfigView(state);
|
|
52
54
|
return {
|
|
53
55
|
fieldHelp: invoicingFieldHelpForGroup(state, 'catalog'),
|
|
56
|
+
qboClassHierarchy: isQboConnected
|
|
57
|
+
? getInvoicingQboView(state).nestedClassHierarchy
|
|
58
|
+
: [],
|
|
59
|
+
qboIncomeAccountHierarchy: isQboConnected
|
|
60
|
+
? invoicingAccountHierarchyForTypes(state, INVOICING_INCOME_ACCOUNT_TYPES)
|
|
61
|
+
: [],
|
|
54
62
|
applicabilityValues: INVOICING_CATALOG_APPLICABILITY_VALUES,
|
|
55
63
|
applicableItemOptions,
|
|
56
64
|
localData,
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { EMPTY, from } from 'rxjs';
|
|
2
|
+
import { filter, mergeMap, withLatestFrom } from 'rxjs/operators';
|
|
3
|
+
import { fetchAccountList } from '../../../accountList/accountListReducer';
|
|
4
|
+
import { fetchClassList } from '../../../classList/classListReducer';
|
|
5
|
+
import { fetchInvoicingAccountingPickers } from '../invoicingQboViewReducer';
|
|
6
|
+
import { INVOICING_ACCOUNT_LIST_KEY } from '../invoicingQboViewSelector';
|
|
7
|
+
// Tops up the shared account and class lists, skipping either when the store
|
|
8
|
+
// already holds it or has it in flight.
|
|
9
|
+
export const fetchInvoicingAccountingPickersEpic = (actions$, state$) => actions$.pipe(filter(fetchInvoicingAccountingPickers.match), withLatestFrom(state$), mergeMap(([, state]) => {
|
|
10
|
+
const actions = [];
|
|
11
|
+
const accountList = state.accountListState.byReportId[INVOICING_ACCOUNT_LIST_KEY];
|
|
12
|
+
if (accountList.hasValidState() === false &&
|
|
13
|
+
accountList.fetchState !== 'In-Progress') {
|
|
14
|
+
// AP/AR accounts cannot back an invoicing mapping, so they are excluded
|
|
15
|
+
// here — which is why this uses invoicing's own bucket rather than the
|
|
16
|
+
// general `accountList` other screens fill without those exclusions.
|
|
17
|
+
actions.push(fetchAccountList(INVOICING_ACCOUNT_LIST_KEY, true, true, true));
|
|
18
|
+
}
|
|
19
|
+
const classList = state.classListState;
|
|
20
|
+
if (classList.hasValidState() === false &&
|
|
21
|
+
classList.fetchState !== 'In-Progress') {
|
|
22
|
+
// Without deleted classes, matching almost every other caller of this
|
|
23
|
+
// single global slice. Asking for deleted rows here would have handed
|
|
24
|
+
// them to the vendor and transaction screens too — and the picker
|
|
25
|
+
// filters deleted classes out anyway, so there is nothing to gain.
|
|
26
|
+
actions.push(fetchClassList());
|
|
27
|
+
}
|
|
28
|
+
return actions.length > 0 ? from(actions) : EMPTY;
|
|
29
|
+
}));
|
|
@@ -6,29 +6,6 @@ export function mapInvoicingQboConnection(payload) {
|
|
|
6
6
|
realmId: payload.realm_id ?? undefined,
|
|
7
7
|
};
|
|
8
8
|
}
|
|
9
|
-
export function mapInvoicingQboAccountOptions(rows) {
|
|
10
|
-
return rows.flatMap((row) => {
|
|
11
|
-
// Only qbo_id is a valid QBO AccountRef/ClassRef value — platform-internal
|
|
12
|
-
// ids (account_id / id) are display metadata and must never be submitted.
|
|
13
|
-
const accountId = row.qbo_id ?? row.id ?? row.account_id ?? '';
|
|
14
|
-
if (accountId === '') {
|
|
15
|
-
return [];
|
|
16
|
-
}
|
|
17
|
-
const accountName = row.name ??
|
|
18
|
-
row.account_name ??
|
|
19
|
-
row.accounting_class_name ??
|
|
20
|
-
row.qbo_accounting_class_name ??
|
|
21
|
-
row.fully_qualified_name ??
|
|
22
|
-
accountId;
|
|
23
|
-
return [
|
|
24
|
-
{
|
|
25
|
-
id: accountId,
|
|
26
|
-
name: accountName,
|
|
27
|
-
accountType: row.account_type ?? undefined,
|
|
28
|
-
},
|
|
29
|
-
];
|
|
30
|
-
});
|
|
31
|
-
}
|
|
32
9
|
export function mapInvoicingQboSyncHealth(payload) {
|
|
33
10
|
return {
|
|
34
11
|
connection: payload.connection != null
|
|
@@ -1,11 +1,7 @@
|
|
|
1
1
|
import { createSlice } from '@reduxjs/toolkit';
|
|
2
2
|
import { clearAll } from '../../../rootActions';
|
|
3
3
|
export const initialState = {
|
|
4
|
-
accountsByAccountTypes: {},
|
|
5
|
-
accountsFetchStateByAccountTypes: {},
|
|
6
4
|
backfillFetchState: { fetchState: 'Not-Started', error: undefined },
|
|
7
|
-
classes: [],
|
|
8
|
-
classesFetchState: { fetchState: 'Not-Started', error: undefined },
|
|
9
5
|
connection: undefined,
|
|
10
6
|
connectionFetchState: { fetchState: 'Not-Started', error: undefined },
|
|
11
7
|
retryFetchStateByTaskId: {},
|
|
@@ -29,41 +25,8 @@ const invoicingQboView = createSlice({
|
|
|
29
25
|
updateInvoicingQboConnectionFailure(draft, action) {
|
|
30
26
|
draft.connectionFetchState = { fetchState: 'Error', error: action.payload };
|
|
31
27
|
},
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
draft.accountsFetchStateByAccountTypes[action.payload.accountTypes] = {
|
|
35
|
-
fetchState: 'In-Progress',
|
|
36
|
-
error: undefined,
|
|
37
|
-
};
|
|
38
|
-
},
|
|
39
|
-
prepare(accountTypes) {
|
|
40
|
-
return { payload: { accountTypes } };
|
|
41
|
-
},
|
|
42
|
-
},
|
|
43
|
-
updateInvoicingQboAccounts(draft, action) {
|
|
44
|
-
draft.accountsByAccountTypes[action.payload.accountTypes] =
|
|
45
|
-
action.payload.accounts;
|
|
46
|
-
draft.accountsFetchStateByAccountTypes[action.payload.accountTypes] = {
|
|
47
|
-
fetchState: 'Completed',
|
|
48
|
-
error: undefined,
|
|
49
|
-
};
|
|
50
|
-
},
|
|
51
|
-
updateInvoicingQboAccountsFailure(draft, action) {
|
|
52
|
-
draft.accountsFetchStateByAccountTypes[action.payload.accountTypes] = {
|
|
53
|
-
fetchState: 'Error',
|
|
54
|
-
error: action.payload.status,
|
|
55
|
-
};
|
|
56
|
-
},
|
|
57
|
-
fetchInvoicingQboClasses(draft) {
|
|
58
|
-
draft.classesFetchState = { fetchState: 'In-Progress', error: undefined };
|
|
59
|
-
},
|
|
60
|
-
updateInvoicingQboClasses(draft, action) {
|
|
61
|
-
draft.classes = action.payload;
|
|
62
|
-
draft.classesFetchState = { fetchState: 'Completed', error: undefined };
|
|
63
|
-
},
|
|
64
|
-
updateInvoicingQboClassesFailure(draft, action) {
|
|
65
|
-
draft.classesFetchState = { fetchState: 'Error', error: action.payload };
|
|
66
|
-
},
|
|
28
|
+
// No state of its own: the epic decides which shared lists to load.
|
|
29
|
+
fetchInvoicingAccountingPickers() { },
|
|
67
30
|
fetchInvoicingQboSyncHealth(draft) {
|
|
68
31
|
draft.syncHealthFetchState = {
|
|
69
32
|
fetchState: 'In-Progress',
|
|
@@ -127,5 +90,5 @@ const invoicingQboView = createSlice({
|
|
|
127
90
|
});
|
|
128
91
|
},
|
|
129
92
|
});
|
|
130
|
-
export const { fetchInvoicingQboConnection, updateInvoicingQboConnection, updateInvoicingQboConnectionFailure,
|
|
93
|
+
export const { fetchInvoicingQboConnection, updateInvoicingQboConnection, updateInvoicingQboConnectionFailure, fetchInvoicingAccountingPickers, fetchInvoicingQboSyncHealth, updateInvoicingQboSyncHealth, updateInvoicingQboSyncHealthFailure, retryInvoicingQboSyncTask, retryInvoicingQboSyncTaskSuccess, retryInvoicingQboSyncTaskFailure, startInvoicingQboBackfill, startInvoicingQboBackfillSuccess, startInvoicingQboBackfillFailure, } = invoicingQboView.actions;
|
|
131
94
|
export default invoicingQboView.reducer;
|
|
@@ -1,16 +1,134 @@
|
|
|
1
|
+
import { getAccountList, getNestedAccountListHierarchy, } from '../../accountList/accountListSelector';
|
|
2
|
+
import { getClassList, getNestedClassListHierarchy, } from '../../classList/classListSelector';
|
|
3
|
+
// Its own bucket: invoicing needs the AP/AR exclusions that the vendor and
|
|
4
|
+
// transaction screens sharing `accountList` do not pass.
|
|
5
|
+
export const INVOICING_ACCOUNT_LIST_KEY = 'invoicingAccountList';
|
|
6
|
+
/** Whether QBO is connected, without building the option lists to find out. */
|
|
7
|
+
export const isInvoicingQboConnected = (state) => state.invoicingQboViewState.connection?.connected === true;
|
|
8
|
+
/**
|
|
9
|
+
* Account types that can back invoicing revenue. Named here so screens ask for
|
|
10
|
+
* "income accounts" rather than repeating the accounting service's vocabulary.
|
|
11
|
+
*/
|
|
12
|
+
export const INVOICING_INCOME_ACCOUNT_TYPES = [
|
|
13
|
+
'income',
|
|
14
|
+
'other_income',
|
|
15
|
+
];
|
|
16
|
+
/**
|
|
17
|
+
* Accounts and classes as the invoicing pickers need them. Both come from the
|
|
18
|
+
* shared accounting-service lists, so whatever another screen already loaded
|
|
19
|
+
* is reused. `qboId` is the submitted value because that is what the invoicing
|
|
20
|
+
* API stores; an account without one cannot be posted, so it is dropped rather
|
|
21
|
+
* than offered.
|
|
22
|
+
*/
|
|
23
|
+
const invoicingAccountingOptions = (state, accountTypes) => {
|
|
24
|
+
const { accounts } = getAccountList(state.accountState, state.accountListState, INVOICING_ACCOUNT_LIST_KEY);
|
|
25
|
+
return accounts.flatMap((account) => {
|
|
26
|
+
if (account.qboId == null || account.isDeleted === true) {
|
|
27
|
+
return [];
|
|
28
|
+
}
|
|
29
|
+
if (accountTypes != null &&
|
|
30
|
+
(account.accountType == null ||
|
|
31
|
+
!accountTypes.includes(account.accountType))) {
|
|
32
|
+
return [];
|
|
33
|
+
}
|
|
34
|
+
return [
|
|
35
|
+
{
|
|
36
|
+
id: String(account.qboId),
|
|
37
|
+
name: account.accountName,
|
|
38
|
+
accountType: account.accountType,
|
|
39
|
+
},
|
|
40
|
+
];
|
|
41
|
+
});
|
|
42
|
+
};
|
|
43
|
+
/**
|
|
44
|
+
* Normalises an account-type name for comparison. The config's mapping kinds
|
|
45
|
+
* name QuickBooks types the way QuickBooks displays them ("Other Current
|
|
46
|
+
* Asset", "Expense"), while the accounting service uses snake_case and
|
|
47
|
+
* sometimes pluralises ("other_current_assets", "expenses"). Comparing the
|
|
48
|
+
* normalised, de-pluralised forms keeps a picker from silently emptying because
|
|
49
|
+
* of a trailing "s".
|
|
50
|
+
*/
|
|
51
|
+
const normalizeAccountTypeName = (value) => {
|
|
52
|
+
const normalized = value
|
|
53
|
+
.trim()
|
|
54
|
+
.toLowerCase()
|
|
55
|
+
.replace(/[^a-z0-9]+/g, '_');
|
|
56
|
+
// Singularise so "Other Current Liability" meets `other_current_liabilities`
|
|
57
|
+
// and "Expense" meets `expenses`. `-ies` needs its own case: stripping the
|
|
58
|
+
// trailing "s" alone would leave "liabilitie", matching nothing.
|
|
59
|
+
return normalized.replace(/ies$/, 'y').replace(/([^s])s$/, '$1');
|
|
60
|
+
};
|
|
61
|
+
/**
|
|
62
|
+
* The accounts valid for one QBO mapping kind, whose `accountTypes` is a
|
|
63
|
+
* comma-separated list of QuickBooks type names. An unrecognised list yields no
|
|
64
|
+
* accounts rather than every account: offering a bank account where income is
|
|
65
|
+
* required would post a mapping QuickBooks rejects.
|
|
66
|
+
*/
|
|
67
|
+
export const invoicingAccountsForQboAccountTypes = (accounts, accountTypes) => {
|
|
68
|
+
const wanted = new Set(accountTypes
|
|
69
|
+
.split(',')
|
|
70
|
+
.map(normalizeAccountTypeName)
|
|
71
|
+
.filter((accountType) => accountType !== ''));
|
|
72
|
+
if (wanted.size === 0) {
|
|
73
|
+
return accounts;
|
|
74
|
+
}
|
|
75
|
+
return accounts.filter((account) => account.accountType != null &&
|
|
76
|
+
wanted.has(normalizeAccountTypeName(account.accountType)));
|
|
77
|
+
};
|
|
78
|
+
/** Classes as the invoicing pickers need them, from the shared class list. */
|
|
79
|
+
const invoicingAccountingClassOptions = (state) => {
|
|
80
|
+
const { classes } = getClassList(state.classState, state.classListState);
|
|
81
|
+
return classes.flatMap((accountingClass) => accountingClass.qboId == null || accountingClass.isDeleted === true
|
|
82
|
+
? []
|
|
83
|
+
: [
|
|
84
|
+
{
|
|
85
|
+
id: String(accountingClass.qboId),
|
|
86
|
+
name: accountingClass.className,
|
|
87
|
+
},
|
|
88
|
+
]);
|
|
89
|
+
};
|
|
90
|
+
/**
|
|
91
|
+
* The account tree narrowed to the given account types. The tree itself carries
|
|
92
|
+
* no account type, so the flat account list supplies that and the matching
|
|
93
|
+
* `qboId`s are kept — which is why callers that only need "income accounts, as a
|
|
94
|
+
* tree" do not have to hold a second flat list to filter with.
|
|
95
|
+
*/
|
|
96
|
+
export const invoicingAccountHierarchyForTypes = (state, accountTypes) => {
|
|
97
|
+
const allowedQboIds = new Set(invoicingAccountingOptions(state, accountTypes).map((account) => account.id));
|
|
98
|
+
const keepMatching = (nodes) => nodes.flatMap((node) => {
|
|
99
|
+
const children = keepMatching(node.children);
|
|
100
|
+
const isMatch = node.qboId != null && allowedQboIds.has(String(node.qboId));
|
|
101
|
+
// A parent that is not itself a match is still kept when it holds one, so
|
|
102
|
+
// the tree's shape survives the filter.
|
|
103
|
+
if (!isMatch && children.length === 0) {
|
|
104
|
+
return [];
|
|
105
|
+
}
|
|
106
|
+
return [{ ...node, children }];
|
|
107
|
+
});
|
|
108
|
+
return keepMatching(getNestedAccountListHierarchy(state.accountListState, INVOICING_ACCOUNT_LIST_KEY));
|
|
109
|
+
};
|
|
1
110
|
/**
|
|
2
111
|
* Single bundled view for the QBO integration settings screen — the
|
|
3
|
-
* connection,
|
|
4
|
-
*
|
|
112
|
+
* connection, the account and class options, sync health, and the fetch/action
|
|
113
|
+
* states for each of them.
|
|
5
114
|
*/
|
|
6
115
|
export const getInvoicingQboView = (state) => {
|
|
7
116
|
const qboState = state.invoicingQboViewState;
|
|
117
|
+
const accountList = state.accountListState.byReportId[INVOICING_ACCOUNT_LIST_KEY];
|
|
8
118
|
return {
|
|
9
|
-
|
|
10
|
-
|
|
119
|
+
accounts: invoicingAccountingOptions(state),
|
|
120
|
+
accountsFetchState: {
|
|
121
|
+
fetchState: accountList.fetchState,
|
|
122
|
+
error: accountList.error,
|
|
123
|
+
},
|
|
124
|
+
nestedAccountHierarchy: getNestedAccountListHierarchy(state.accountListState, INVOICING_ACCOUNT_LIST_KEY),
|
|
125
|
+
nestedClassHierarchy: getNestedClassListHierarchy(state.classListState),
|
|
11
126
|
backfillState: qboState.backfillFetchState,
|
|
12
|
-
classes:
|
|
13
|
-
classesFetchState:
|
|
127
|
+
classes: invoicingAccountingClassOptions(state),
|
|
128
|
+
classesFetchState: {
|
|
129
|
+
fetchState: state.classListState.fetchState,
|
|
130
|
+
error: state.classListState.error,
|
|
131
|
+
},
|
|
14
132
|
connection: qboState.connection,
|
|
15
133
|
connectionFetchState: qboState.connectionFetchState,
|
|
16
134
|
retryFetchStateByTaskId: qboState.retryFetchStateByTaskId,
|
package/lib/index.d.ts
CHANGED
|
@@ -1240,10 +1240,12 @@ export type { InvoicingBrandingFormView, InvoicingSettingsHubView, InvoicingSett
|
|
|
1240
1240
|
export type { InvoicingBrandingFormLocalData } from './view/invoicing/settingsView/invoicingBrandingFormConfig';
|
|
1241
1241
|
export { INVOICING_BUSINESS_ADDRESS_TYPE, entityToInvoicingBrandingFormLocalData, initialInvoicingBrandingFormLocalData, } from './view/invoicing/settingsView/invoicingBrandingFormConfig';
|
|
1242
1242
|
export { isStripeConnectedFromSettings } from './view/invoicing/settingsView/invoicingSettingsHelpers';
|
|
1243
|
-
export {
|
|
1243
|
+
export { fetchInvoicingAccountingPickers, fetchInvoicingQboConnection, fetchInvoicingQboSyncHealth, retryInvoicingQboSyncTask, startInvoicingQboBackfill, } from './view/invoicing/invoicingQboView/invoicingQboViewReducer';
|
|
1244
|
+
export { INVOICING_INCOME_ACCOUNT_TYPES, invoicingAccountsForQboAccountTypes, } from './view/invoicing/invoicingQboView/invoicingQboViewSelector';
|
|
1245
|
+
export type { InvoicingAccountingOption } from './view/invoicing/invoicingQboView/invoicingQboViewSelector';
|
|
1244
1246
|
export { getInvoicingQboView } from './view/invoicing/invoicingQboView/invoicingQboViewSelector';
|
|
1245
1247
|
export type { InvoicingQboView } from './view/invoicing/invoicingQboView/invoicingQboViewSelector';
|
|
1246
|
-
export type {
|
|
1248
|
+
export type { InvoicingQboConnection, InvoicingQboFailedTask, InvoicingQboSyncHealth, } from './view/invoicing/invoicingQboView/invoicingQboViewPayload';
|
|
1247
1249
|
export { INVOICING_QBO_CUSTOMER_MATCHING_MODES, getInvoicingQboAccountMappingId, toInvoicingNamedOptionsByKey, toInvoicingQboCustomerMatchingMode, withInvoicingQboAccountMappingId, } from './entity/invoicing/invoicingCommonPayload';
|
|
1248
1250
|
export type { InvoicingNamedOption, InvoicingFieldHelp, InvoicingFieldHelpByCode, InvoicingFieldHelpGroup, InvoicingNamedOptionsByKey, InvoicingQboAccountMappingKindOption, InvoicingQboAccountMappingsPayload, InvoicingQboCustomerMatchingMode, InvoicingQboSettingsPayload, } from './entity/invoicing/invoicingCommonPayload';
|
|
1249
1251
|
export { acceptInvoicingTerms, enableInvoicing, fetchInvoicingConfig, resetInvoicingConfigActionStates, updateInvoicingConfig, } from './view/invoicing/invoicingConfigView/invoicingConfigViewReducer';
|
package/lib/index.js
CHANGED
|
@@ -83,7 +83,7 @@ exports.getInvoicingDiscountActionState = exports.runInvoicingDiscountAction = e
|
|
|
83
83
|
exports.updateInvoicingSubscriptions = exports.removeInvoicingSubscription = exports.resetPromotionalCreditAction = exports.submitAddPromotionalCredits = exports.getInvoicingSetupIntentFetchState = exports.getInvoicingSetupIntent = exports.getInvoicingSentPaymentLinkMagicUrl = exports.getInvoicingSentPaymentLinkEmail = exports.getInvoicingPlaidLinkTokenFetchState = exports.getInvoicingPlaidLinkToken = exports.getInvoicingPaymentMethodSaveState = exports.getInvoicingPaymentLinkSendState = exports.sendInvoicingPaymentLink = exports.saveInvoicingPaymentMethod = exports.resetInvoicingCustomerPaymentMethod = exports.fetchInvoicingPlaidLinkToken = exports.createInvoicingSetupIntent = exports.getInvoicingCustomerDetail = exports.fetchInvoicingCustomerDetailPage = exports.fetchInvoicingCustomerDetail = exports.getInvoicingCustomerListView = exports.INVOICING_CUSTOMER_COLUMNS = exports.ALL_INVOICING_CUSTOMER_TAB_IDS = exports.ALL_INVOICING_CUSTOMER_SORT_KEYS = exports.updateInvoicingCustomerFilters = exports.setInvoicingCustomerActiveTab = exports.fetchInvoicingCustomerListPage = exports.fetchInvoicingCustomerList = exports.fetchInvoicingCustomerCounts = exports.updateInvoicingCustomers = exports.removeInvoicingCustomer = exports.INVOICING_LIST_PAGE_SIZE = exports.getInvoicingDataImportActionState = exports.uploadInvoicingMigrationFiles = exports.startInvoicingMigration = exports.rollbackInvoicingMigration = exports.retryInvoicingMigration = exports.connectInvoicingChargebee = exports.getInvoicingDataImportView = exports.setInvoicingActiveMigrationSessionId = exports.fetchInvoicingMigrationSessions = exports.fetchInvoicingMigrationSession = exports.fetchInvoicingMigrationDiagnostics = exports.fetchInvoicingDataImportStatus = exports.getInvoicingPaymentActionState = exports.runInvoicingPaymentAction = exports.getInvoicingDunningActionState = exports.runInvoicingDunningAction = exports.getInvoicingSubscriptionActionState = exports.runInvoicingSubscriptionAction = void 0;
|
|
84
84
|
exports.getInvoicingCouponCounts = exports.INVOICING_COUPON_COLUMNS = exports.ALL_INVOICING_COUPON_TAB_IDS = exports.ALL_INVOICING_COUPON_SORT_KEYS = exports.updateInvoicingCouponFilters = exports.setInvoicingCouponActiveTab = exports.fetchInvoicingCouponListPage = exports.fetchInvoicingCouponList = exports.fetchInvoicingCouponCounts = exports.updateInvoicingCoupons = exports.removeInvoicingCoupon = exports.getInvoicingCreditNoteDetail = exports.getInvoicingCreditNoteById = exports.fetchInvoicingCreditNoteDetail = exports.getInvoicingCreditNoteListView = exports.INVOICING_CREDIT_NOTE_COLUMNS = exports.ALL_INVOICING_CREDIT_NOTE_TAB_IDS = exports.ALL_INVOICING_CREDIT_NOTE_SORT_KEYS = exports.updateInvoicingCreditNoteFilters = exports.setInvoicingCreditNoteActiveTab = exports.fetchInvoicingCreditNoteListPage = exports.fetchInvoicingCreditNoteList = exports.fetchInvoicingCreditNoteCounts = exports.updateInvoicingCreditNotes = exports.removeInvoicingCreditNote = exports.getInvoicingTransactionDetail = exports.getInvoicingTransactionById = exports.fetchInvoicingTransactionDetail = exports.getInvoicingTransactionListView = exports.INVOICING_TRANSACTION_COLUMNS = exports.ALL_INVOICING_TRANSACTION_TAB_IDS = exports.ALL_INVOICING_TRANSACTION_SORT_KEYS = exports.updateInvoicingTransactionFilters = exports.setInvoicingTransactionActiveTab = exports.fetchInvoicingTransactionListPage = exports.fetchInvoicingTransactionList = exports.updateInvoicingTransactions = exports.removeInvoicingTransaction = exports.getInvoicingSubscriptionDetail = exports.getInvoicingSubscriptionById = exports.fetchInvoicingSubscriptionDetail = exports.getInvoicingSubscriptionListView = exports.INVOICING_SUBSCRIPTION_COLUMNS = exports.ALL_INVOICING_SUBSCRIPTION_TAB_IDS = exports.ALL_INVOICING_SUBSCRIPTION_SORT_KEYS = exports.updateInvoicingSubscriptionFilters = exports.setInvoicingSubscriptionActiveTab = exports.fetchInvoicingSubscriptionListPage = exports.fetchInvoicingSubscriptionList = exports.fetchInvoicingSubscriptionCounts = void 0;
|
|
85
85
|
exports.resetSaveInvoicingSettings = exports.resetInvoicingBrandingFormDraft = exports.fetchInvoicingSettings = exports.disconnectInvoicingStripe = exports.connectInvoicingStripe = exports.getInvoicingProductById = exports.getInvoicingPlanById = exports.getInvoicingCatalogItemDetail = exports.fetchInvoicingCatalogItemDetail = exports.getInvoicingCatalogListView = exports.INVOICING_PRODUCT_COLUMNS = exports.ALL_INVOICING_PRODUCT_SORT_KEYS = exports.updateInvoicingCatalogProductFilters = exports.updateInvoicingCatalogPlanFilters = exports.fetchInvoicingCatalogProductList = exports.fetchInvoicingCatalogPlanList = exports.fetchInvoicingCatalogListPage = exports.fetchInvoicingCatalogCounts = exports.updateInvoicingProducts = exports.removeInvoicingProduct = exports.updateInvoicingPlans = exports.removeInvoicingPlan = exports.mergeInvoicingPlanSubFamily = exports.getInvoicingDunningEmailPreview = exports.getInvoicingDunningCaseDetail = exports.getInvoicingDunningCaseById = exports.invalidateInvoicingDunningEmailPreview = exports.fetchInvoicingDunningEmailPreviewPage = exports.fetchInvoicingDunningCaseDetail = exports.clearInvoicingDunningCaseDetailView = exports.getInvoicingDunningCaseListView = exports.INVOICING_DUNNING_CASE_COLUMNS = exports.ALL_INVOICING_DUNNING_CASE_TAB_IDS = exports.ALL_INVOICING_DUNNING_CASE_SORT_KEYS = exports.updateInvoicingDunningCaseFilters = exports.setInvoicingDunningCaseActiveTab = exports.fetchInvoicingDunningCaseListPage = exports.fetchInvoicingDunningCaseList = exports.fetchInvoicingDunningCaseCounts = exports.updateInvoicingDunningCases = exports.removeInvoicingDunningCase = exports.getInvoicingCouponDetail = exports.fetchInvoicingCouponDetail = exports.getInvoicingCouponById = exports.getInvoicingCouponListView = exports.getInvoicingCouponListNextCursor = exports.getInvoicingCouponListItems = exports.getInvoicingCouponListHasMore = exports.getInvoicingCouponListFilters = exports.getInvoicingCouponListFetchState = void 0;
|
|
86
|
-
exports.getInvoicingOnboardingGateView = exports.getInvoicingConfigView = exports.updateInvoicingConfig = exports.resetInvoicingConfigActionStates = exports.fetchInvoicingConfig = exports.enableInvoicing = exports.acceptInvoicingTerms = exports.withInvoicingQboAccountMappingId = exports.toInvoicingQboCustomerMatchingMode = exports.toInvoicingNamedOptionsByKey = exports.getInvoicingQboAccountMappingId = exports.INVOICING_QBO_CUSTOMER_MATCHING_MODES = exports.getInvoicingQboView = exports.
|
|
86
|
+
exports.getInvoicingOnboardingGateView = exports.getInvoicingConfigView = exports.updateInvoicingConfig = exports.resetInvoicingConfigActionStates = exports.fetchInvoicingConfig = exports.enableInvoicing = exports.acceptInvoicingTerms = exports.withInvoicingQboAccountMappingId = exports.toInvoicingQboCustomerMatchingMode = exports.toInvoicingNamedOptionsByKey = exports.getInvoicingQboAccountMappingId = exports.INVOICING_QBO_CUSTOMER_MATCHING_MODES = exports.getInvoicingQboView = exports.invoicingAccountsForQboAccountTypes = exports.INVOICING_INCOME_ACCOUNT_TYPES = exports.startInvoicingQboBackfill = exports.retryInvoicingQboSyncTask = exports.fetchInvoicingQboSyncHealth = exports.fetchInvoicingQboConnection = exports.fetchInvoicingAccountingPickers = exports.isStripeConnectedFromSettings = exports.initialInvoicingBrandingFormLocalData = exports.entityToInvoicingBrandingFormLocalData = exports.INVOICING_BUSINESS_ADDRESS_TYPE = exports.getInvoicingSettingsView = exports.getInvoicingSettingsHubView = exports.getInvoicingSettingsFetchState = exports.getInvoicingSettings = exports.getInvoicingBrandingFormView = exports.updateInvoicingSettings = exports.updateInvoicingBrandingFormDraft = exports.submitInvoicingBrandingForm = exports.saveInvoicingSettings = void 0;
|
|
87
87
|
const allowedValue_1 = require("./commonStateTypes/allowedValue");
|
|
88
88
|
Object.defineProperty(exports, "isAllowedValueWithCode", { enumerable: true, get: function () { return allowedValue_1.isAllowedValueWithCode; } });
|
|
89
89
|
Object.defineProperty(exports, "isAllowedValueWithID", { enumerable: true, get: function () { return allowedValue_1.isAllowedValueWithID; } });
|
|
@@ -3105,14 +3105,16 @@ var invoicingSettingsHelpers_1 = require("./view/invoicing/settingsView/invoicin
|
|
|
3105
3105
|
Object.defineProperty(exports, "isStripeConnectedFromSettings", { enumerable: true, get: function () { return invoicingSettingsHelpers_1.isStripeConnectedFromSettings; } });
|
|
3106
3106
|
// ── Invoicing: QBO integration ────────────────────────────────────────────────
|
|
3107
3107
|
var invoicingQboViewReducer_1 = require("./view/invoicing/invoicingQboView/invoicingQboViewReducer");
|
|
3108
|
-
Object.defineProperty(exports, "
|
|
3109
|
-
Object.defineProperty(exports, "fetchInvoicingQboClasses", { enumerable: true, get: function () { return invoicingQboViewReducer_1.fetchInvoicingQboClasses; } });
|
|
3108
|
+
Object.defineProperty(exports, "fetchInvoicingAccountingPickers", { enumerable: true, get: function () { return invoicingQboViewReducer_1.fetchInvoicingAccountingPickers; } });
|
|
3110
3109
|
Object.defineProperty(exports, "fetchInvoicingQboConnection", { enumerable: true, get: function () { return invoicingQboViewReducer_1.fetchInvoicingQboConnection; } });
|
|
3111
3110
|
Object.defineProperty(exports, "fetchInvoicingQboSyncHealth", { enumerable: true, get: function () { return invoicingQboViewReducer_1.fetchInvoicingQboSyncHealth; } });
|
|
3112
3111
|
Object.defineProperty(exports, "retryInvoicingQboSyncTask", { enumerable: true, get: function () { return invoicingQboViewReducer_1.retryInvoicingQboSyncTask; } });
|
|
3113
3112
|
Object.defineProperty(exports, "startInvoicingQboBackfill", { enumerable: true, get: function () { return invoicingQboViewReducer_1.startInvoicingQboBackfill; } });
|
|
3114
3113
|
var invoicingQboViewSelector_1 = require("./view/invoicing/invoicingQboView/invoicingQboViewSelector");
|
|
3115
|
-
Object.defineProperty(exports, "
|
|
3114
|
+
Object.defineProperty(exports, "INVOICING_INCOME_ACCOUNT_TYPES", { enumerable: true, get: function () { return invoicingQboViewSelector_1.INVOICING_INCOME_ACCOUNT_TYPES; } });
|
|
3115
|
+
Object.defineProperty(exports, "invoicingAccountsForQboAccountTypes", { enumerable: true, get: function () { return invoicingQboViewSelector_1.invoicingAccountsForQboAccountTypes; } });
|
|
3116
|
+
var invoicingQboViewSelector_2 = require("./view/invoicing/invoicingQboView/invoicingQboViewSelector");
|
|
3117
|
+
Object.defineProperty(exports, "getInvoicingQboView", { enumerable: true, get: function () { return invoicingQboViewSelector_2.getInvoicingQboView; } });
|
|
3116
3118
|
var invoicingCommonPayload_2 = require("./entity/invoicing/invoicingCommonPayload");
|
|
3117
3119
|
Object.defineProperty(exports, "INVOICING_QBO_CUSTOMER_MATCHING_MODES", { enumerable: true, get: function () { return invoicingCommonPayload_2.INVOICING_QBO_CUSTOMER_MATCHING_MODES; } });
|
|
3118
3120
|
Object.defineProperty(exports, "getInvoicingQboAccountMappingId", { enumerable: true, get: function () { return invoicingCommonPayload_2.getInvoicingQboAccountMappingId; } });
|
|
@@ -35,6 +35,7 @@ exports.initialState = {
|
|
|
35
35
|
reimbursementAccountList: exports.initialAccountList,
|
|
36
36
|
schedulesAccountList: exports.initialAccountList,
|
|
37
37
|
billPayAccountList: exports.initialAccountList,
|
|
38
|
+
invoicingAccountList: exports.initialAccountList,
|
|
38
39
|
},
|
|
39
40
|
};
|
|
40
41
|
const accountList = (0, toolkit_1.createSlice)({
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { NestedAccountHierarchyForReport } from '../../commonStateTypes/accountView/nestedAccountID';
|
|
2
2
|
import { FetchedState, ID } from '../../commonStateTypes/common';
|
|
3
3
|
import { AccountLabel } from '../../entity/account/accountState';
|
|
4
|
-
export type AccountListKeyType = 'accountList' | 'reimbursementAccountList' | 'schedulesAccountList' | 'billPayAccountList';
|
|
4
|
+
export type AccountListKeyType = 'accountList' | 'reimbursementAccountList' | 'schedulesAccountList' | 'billPayAccountList' | 'invoicingAccountList';
|
|
5
5
|
export interface AccountList extends FetchedState {
|
|
6
6
|
accountIds: ID[];
|
|
7
7
|
accountIdsByLabel: Record<AccountLabel, ID[]>;
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { NestedAccountHierarchyForReport } from '../../../commonStateTypes/accountView/nestedAccountID';
|
|
2
|
+
import { NestedClassHierarchyForReport } from '../../../commonStateTypes/classesView/nestedClassID';
|
|
1
3
|
import { FetchStateAndError, ID } from '../../../commonStateTypes/common';
|
|
2
4
|
import { SelectorView } from '../../../commonStateTypes/viewAndReport/viewAndReport';
|
|
3
5
|
import { InvoicingFieldHelpByCode, InvoicingNamedOption, InvoicingNamedOptionsByKey } from '../../../entity/invoicing/invoicingCommonPayload';
|
|
@@ -40,6 +42,13 @@ export interface InvoicingCatalogItemFormView extends SelectorView {
|
|
|
40
42
|
periodUnitOptions: InvoicingNamedOption[];
|
|
41
43
|
pricingModelValues: readonly string[];
|
|
42
44
|
prorationValues: readonly string[];
|
|
45
|
+
/**
|
|
46
|
+
* Account and class trees for the price-point pickers, already narrowed to the
|
|
47
|
+
* income accounts a price may post to. Empty until QBO is connected — the form
|
|
48
|
+
* must not offer a mapping that cannot be pushed.
|
|
49
|
+
*/
|
|
50
|
+
qboClassHierarchy: NestedClassHierarchyForReport[];
|
|
51
|
+
qboIncomeAccountHierarchy: NestedAccountHierarchyForReport[];
|
|
43
52
|
tierTypeValues: readonly string[];
|
|
44
53
|
trialEndActionOptions: InvoicingNamedOption[];
|
|
45
54
|
trialUnitOptions: InvoicingNamedOption[];
|
|
@@ -4,6 +4,7 @@ exports.getInvoicingCatalogItemFormView = exports.getInvoicingApplicableCatalogI
|
|
|
4
4
|
const toolkit_1 = require("@reduxjs/toolkit");
|
|
5
5
|
const planSelector_1 = require("../../../entity/invoicing/plan/planSelector");
|
|
6
6
|
const invoicingConfigViewSelector_1 = require("../invoicingConfigView/invoicingConfigViewSelector");
|
|
7
|
+
const invoicingQboViewSelector_1 = require("../invoicingQboView/invoicingQboViewSelector");
|
|
7
8
|
const invoicingCatalogItemFormConfig_1 = require("./invoicingCatalogItemFormConfig");
|
|
8
9
|
const getEditInvoicingCatalogItemDetailViewState = (state) => ({
|
|
9
10
|
fetchState: state.editInvoicingCatalogItemDetailViewState.fetchState,
|
|
@@ -54,9 +55,16 @@ const getInvoicingCatalogItemFormView = (state, id) => {
|
|
|
54
55
|
const applicableItemOptions = id != null
|
|
55
56
|
? allApplicableItemOptions.filter((option) => option.id !== id)
|
|
56
57
|
: allApplicableItemOptions;
|
|
58
|
+
const isQboConnected = (0, invoicingQboViewSelector_1.isInvoicingQboConnected)(state);
|
|
57
59
|
const { billingPeriodUnitOptions, catalogItemTypeOptions, catalogTierTypeOptionsByPricingModel, catalogTrialEndActionOptions, catalogTrialUnitOptions, } = (0, invoicingConfigViewSelector_1.getInvoicingConfigView)(state);
|
|
58
60
|
return {
|
|
59
61
|
fieldHelp: (0, invoicingConfigViewSelector_1.invoicingFieldHelpForGroup)(state, 'catalog'),
|
|
62
|
+
qboClassHierarchy: isQboConnected
|
|
63
|
+
? (0, invoicingQboViewSelector_1.getInvoicingQboView)(state).nestedClassHierarchy
|
|
64
|
+
: [],
|
|
65
|
+
qboIncomeAccountHierarchy: isQboConnected
|
|
66
|
+
? (0, invoicingQboViewSelector_1.invoicingAccountHierarchyForTypes)(state, invoicingQboViewSelector_1.INVOICING_INCOME_ACCOUNT_TYPES)
|
|
67
|
+
: [],
|
|
60
68
|
applicabilityValues: invoicingCatalogItemFormConfig_1.INVOICING_CATALOG_APPLICABILITY_VALUES,
|
|
61
69
|
applicableItemOptions,
|
|
62
70
|
localData,
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { ActionsObservable, StateObservable } from 'redux-observable';
|
|
2
|
+
import { Observable } from 'rxjs';
|
|
3
|
+
import { RootState } from '../../../../rootStateTypes';
|
|
4
|
+
import { InvoicingQboViewActionType } from './invoicingQboViewActionType';
|
|
5
|
+
export declare const fetchInvoicingAccountingPickersEpic: (actions$: ActionsObservable<InvoicingQboViewActionType>, state$: StateObservable<RootState>) => Observable<InvoicingQboViewActionType>;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.fetchInvoicingAccountingPickersEpic = void 0;
|
|
4
|
+
const rxjs_1 = require("rxjs");
|
|
5
|
+
const operators_1 = require("rxjs/operators");
|
|
6
|
+
const accountListReducer_1 = require("../../../accountList/accountListReducer");
|
|
7
|
+
const classListReducer_1 = require("../../../classList/classListReducer");
|
|
8
|
+
const invoicingQboViewReducer_1 = require("../invoicingQboViewReducer");
|
|
9
|
+
const invoicingQboViewSelector_1 = require("../invoicingQboViewSelector");
|
|
10
|
+
// Tops up the shared account and class lists, skipping either when the store
|
|
11
|
+
// already holds it or has it in flight.
|
|
12
|
+
const fetchInvoicingAccountingPickersEpic = (actions$, state$) => actions$.pipe((0, operators_1.filter)(invoicingQboViewReducer_1.fetchInvoicingAccountingPickers.match), (0, operators_1.withLatestFrom)(state$), (0, operators_1.mergeMap)(([, state]) => {
|
|
13
|
+
const actions = [];
|
|
14
|
+
const accountList = state.accountListState.byReportId[invoicingQboViewSelector_1.INVOICING_ACCOUNT_LIST_KEY];
|
|
15
|
+
if (accountList.hasValidState() === false &&
|
|
16
|
+
accountList.fetchState !== 'In-Progress') {
|
|
17
|
+
// AP/AR accounts cannot back an invoicing mapping, so they are excluded
|
|
18
|
+
// here — which is why this uses invoicing's own bucket rather than the
|
|
19
|
+
// general `accountList` other screens fill without those exclusions.
|
|
20
|
+
actions.push((0, accountListReducer_1.fetchAccountList)(invoicingQboViewSelector_1.INVOICING_ACCOUNT_LIST_KEY, true, true, true));
|
|
21
|
+
}
|
|
22
|
+
const classList = state.classListState;
|
|
23
|
+
if (classList.hasValidState() === false &&
|
|
24
|
+
classList.fetchState !== 'In-Progress') {
|
|
25
|
+
// Without deleted classes, matching almost every other caller of this
|
|
26
|
+
// single global slice. Asking for deleted rows here would have handed
|
|
27
|
+
// them to the vendor and transaction screens too — and the picker
|
|
28
|
+
// filters deleted classes out anyway, so there is nothing to gain.
|
|
29
|
+
actions.push((0, classListReducer_1.fetchClassList)());
|
|
30
|
+
}
|
|
31
|
+
return actions.length > 0 ? (0, rxjs_1.from)(actions) : rxjs_1.EMPTY;
|
|
32
|
+
}));
|
|
33
|
+
exports.fetchInvoicingAccountingPickersEpic = fetchInvoicingAccountingPickersEpic;
|
|
@@ -1,3 +1,5 @@
|
|
|
1
1
|
import { openSnackbar } from '../../../../entity/snackbar/snackbarReducer';
|
|
2
|
-
import {
|
|
3
|
-
|
|
2
|
+
import { fetchAccountList } from '../../../accountList/accountListReducer';
|
|
3
|
+
import { fetchClassList } from '../../../classList/classListReducer';
|
|
4
|
+
import { fetchInvoicingAccountingPickers, fetchInvoicingQboConnection, fetchInvoicingQboSyncHealth, retryInvoicingQboSyncTask, retryInvoicingQboSyncTaskFailure, retryInvoicingQboSyncTaskSuccess, startInvoicingQboBackfill, startInvoicingQboBackfillFailure, startInvoicingQboBackfillSuccess, updateInvoicingQboConnection, updateInvoicingQboConnectionFailure, updateInvoicingQboSyncHealth, updateInvoicingQboSyncHealthFailure } from '../invoicingQboViewReducer';
|
|
5
|
+
export type InvoicingQboViewActionType = ReturnType<typeof openSnackbar> | ReturnType<typeof fetchInvoicingQboConnection> | ReturnType<typeof updateInvoicingQboConnection> | ReturnType<typeof updateInvoicingQboConnectionFailure> | ReturnType<typeof fetchInvoicingAccountingPickers> | ReturnType<typeof fetchAccountList> | ReturnType<typeof fetchClassList> | ReturnType<typeof fetchInvoicingQboSyncHealth> | ReturnType<typeof updateInvoicingQboSyncHealth> | ReturnType<typeof updateInvoicingQboSyncHealthFailure> | ReturnType<typeof retryInvoicingQboSyncTask> | ReturnType<typeof retryInvoicingQboSyncTaskSuccess> | ReturnType<typeof retryInvoicingQboSyncTaskFailure> | ReturnType<typeof startInvoicingQboBackfill> | ReturnType<typeof startInvoicingQboBackfillSuccess> | ReturnType<typeof startInvoicingQboBackfillFailure>;
|
|
@@ -12,31 +12,6 @@ export interface InvoicingQboConnection {
|
|
|
12
12
|
realmId?: string;
|
|
13
13
|
}
|
|
14
14
|
export declare function mapInvoicingQboConnection(payload: InvoicingQboConnectionPayload): InvoicingQboConnection;
|
|
15
|
-
/**
|
|
16
|
-
* A single row from the QBO accounts / classes endpoints. The rows carry the
|
|
17
|
-
* QBO id plus one or more name fields depending on the entity — inspect
|
|
18
|
-
* loosely, render the name, submit the id.
|
|
19
|
-
*/
|
|
20
|
-
export interface InvoicingQboAccountRowPayload {
|
|
21
|
-
account_id?: string | null;
|
|
22
|
-
account_name?: string | null;
|
|
23
|
-
account_type?: string | null;
|
|
24
|
-
accounting_class_name?: string | null;
|
|
25
|
-
fully_qualified_name?: string | null;
|
|
26
|
-
id?: string | null;
|
|
27
|
-
name?: string | null;
|
|
28
|
-
qbo_accounting_class_name?: string | null;
|
|
29
|
-
qbo_id?: string | null;
|
|
30
|
-
}
|
|
31
|
-
export interface InvoicingQboAccountOption {
|
|
32
|
-
id: string;
|
|
33
|
-
name: string;
|
|
34
|
-
accountType?: string;
|
|
35
|
-
}
|
|
36
|
-
export declare function mapInvoicingQboAccountOptions(rows: InvoicingQboAccountRowPayload[]): InvoicingQboAccountOption[];
|
|
37
|
-
export interface InvoicingQboAccountsPayload {
|
|
38
|
-
accounts: InvoicingQboAccountRowPayload[];
|
|
39
|
-
}
|
|
40
15
|
export interface InvoicingQboFailedTaskPayload {
|
|
41
16
|
attempts: number;
|
|
42
17
|
entity_id: string;
|
|
@@ -73,7 +48,6 @@ export interface InvoicingQboBackfillPayload {
|
|
|
73
48
|
start_date?: string | null;
|
|
74
49
|
}
|
|
75
50
|
export type InvoicingQboConnectionResponse = ZeniAPIResponse<InvoicingQboConnectionPayload>;
|
|
76
|
-
export type InvoicingQboAccountsResponse = ZeniAPIResponse<InvoicingQboAccountsPayload>;
|
|
77
51
|
export type InvoicingQboSyncHealthResponse = ZeniAPIResponse<InvoicingQboSyncHealthPayload>;
|
|
78
52
|
export type InvoicingQboRetryTaskResponse = ZeniAPIResponse<InvoicingQboRetryTaskPayload>;
|
|
79
53
|
export type InvoicingQboBackfillResponse = ZeniAPIResponse<InvoicingQboBackfillPayload>;
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.mapInvoicingQboConnection = mapInvoicingQboConnection;
|
|
4
|
-
exports.mapInvoicingQboAccountOptions = mapInvoicingQboAccountOptions;
|
|
5
4
|
exports.mapInvoicingQboSyncHealth = mapInvoicingQboSyncHealth;
|
|
6
5
|
function mapInvoicingQboConnection(payload) {
|
|
7
6
|
return {
|
|
@@ -11,29 +10,6 @@ function mapInvoicingQboConnection(payload) {
|
|
|
11
10
|
realmId: payload.realm_id ?? undefined,
|
|
12
11
|
};
|
|
13
12
|
}
|
|
14
|
-
function mapInvoicingQboAccountOptions(rows) {
|
|
15
|
-
return rows.flatMap((row) => {
|
|
16
|
-
// Only qbo_id is a valid QBO AccountRef/ClassRef value — platform-internal
|
|
17
|
-
// ids (account_id / id) are display metadata and must never be submitted.
|
|
18
|
-
const accountId = row.qbo_id ?? row.id ?? row.account_id ?? '';
|
|
19
|
-
if (accountId === '') {
|
|
20
|
-
return [];
|
|
21
|
-
}
|
|
22
|
-
const accountName = row.name ??
|
|
23
|
-
row.account_name ??
|
|
24
|
-
row.accounting_class_name ??
|
|
25
|
-
row.qbo_accounting_class_name ??
|
|
26
|
-
row.fully_qualified_name ??
|
|
27
|
-
accountId;
|
|
28
|
-
return [
|
|
29
|
-
{
|
|
30
|
-
id: accountId,
|
|
31
|
-
name: accountName,
|
|
32
|
-
accountType: row.account_type ?? undefined,
|
|
33
|
-
},
|
|
34
|
-
];
|
|
35
|
-
});
|
|
36
|
-
}
|
|
37
13
|
function mapInvoicingQboSyncHealth(payload) {
|
|
38
14
|
return {
|
|
39
15
|
connection: payload.connection != null
|
|
@@ -1,16 +1,8 @@
|
|
|
1
1
|
import { ZeniAPIStatus } from '../../../responsePayload';
|
|
2
|
-
import {
|
|
2
|
+
import { InvoicingQboConnection, InvoicingQboSyncHealth } from './invoicingQboViewPayload';
|
|
3
3
|
import { InvoicingQboViewState } from './invoicingQboViewState';
|
|
4
4
|
export declare const initialState: InvoicingQboViewState;
|
|
5
|
-
export declare const fetchInvoicingQboConnection: import("@reduxjs/toolkit").ActionCreatorWithoutPayload<"invoicingQboView/fetchInvoicingQboConnection">, updateInvoicingQboConnection: import("@reduxjs/toolkit").ActionCreatorWithPayload<InvoicingQboConnection, "invoicingQboView/updateInvoicingQboConnection">, updateInvoicingQboConnectionFailure: import("@reduxjs/toolkit").ActionCreatorWithPayload<ZeniAPIStatus<Record<string, unknown>>, "invoicingQboView/updateInvoicingQboConnectionFailure">,
|
|
6
|
-
accountTypes: string;
|
|
7
|
-
}, "invoicingQboView/fetchInvoicingQboAccounts", never, never>, updateInvoicingQboAccounts: import("@reduxjs/toolkit").ActionCreatorWithPayload<{
|
|
8
|
-
accounts: InvoicingQboAccountOption[];
|
|
9
|
-
accountTypes: string;
|
|
10
|
-
}, "invoicingQboView/updateInvoicingQboAccounts">, updateInvoicingQboAccountsFailure: import("@reduxjs/toolkit").ActionCreatorWithPayload<{
|
|
11
|
-
accountTypes: string;
|
|
12
|
-
status: ZeniAPIStatus;
|
|
13
|
-
}, "invoicingQboView/updateInvoicingQboAccountsFailure">, fetchInvoicingQboClasses: import("@reduxjs/toolkit").ActionCreatorWithoutPayload<"invoicingQboView/fetchInvoicingQboClasses">, updateInvoicingQboClasses: import("@reduxjs/toolkit").ActionCreatorWithPayload<InvoicingQboAccountOption[], "invoicingQboView/updateInvoicingQboClasses">, updateInvoicingQboClassesFailure: import("@reduxjs/toolkit").ActionCreatorWithPayload<ZeniAPIStatus<Record<string, unknown>>, "invoicingQboView/updateInvoicingQboClassesFailure">, fetchInvoicingQboSyncHealth: import("@reduxjs/toolkit").ActionCreatorWithoutPayload<"invoicingQboView/fetchInvoicingQboSyncHealth">, updateInvoicingQboSyncHealth: import("@reduxjs/toolkit").ActionCreatorWithPayload<InvoicingQboSyncHealth, "invoicingQboView/updateInvoicingQboSyncHealth">, updateInvoicingQboSyncHealthFailure: import("@reduxjs/toolkit").ActionCreatorWithPayload<ZeniAPIStatus<Record<string, unknown>>, "invoicingQboView/updateInvoicingQboSyncHealthFailure">, retryInvoicingQboSyncTask: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[taskId: string], {
|
|
5
|
+
export declare const fetchInvoicingQboConnection: import("@reduxjs/toolkit").ActionCreatorWithoutPayload<"invoicingQboView/fetchInvoicingQboConnection">, updateInvoicingQboConnection: import("@reduxjs/toolkit").ActionCreatorWithPayload<InvoicingQboConnection, "invoicingQboView/updateInvoicingQboConnection">, updateInvoicingQboConnectionFailure: import("@reduxjs/toolkit").ActionCreatorWithPayload<ZeniAPIStatus<Record<string, unknown>>, "invoicingQboView/updateInvoicingQboConnectionFailure">, fetchInvoicingAccountingPickers: import("@reduxjs/toolkit").ActionCreatorWithoutPayload<"invoicingQboView/fetchInvoicingAccountingPickers">, fetchInvoicingQboSyncHealth: import("@reduxjs/toolkit").ActionCreatorWithoutPayload<"invoicingQboView/fetchInvoicingQboSyncHealth">, updateInvoicingQboSyncHealth: import("@reduxjs/toolkit").ActionCreatorWithPayload<InvoicingQboSyncHealth, "invoicingQboView/updateInvoicingQboSyncHealth">, updateInvoicingQboSyncHealthFailure: import("@reduxjs/toolkit").ActionCreatorWithPayload<ZeniAPIStatus<Record<string, unknown>>, "invoicingQboView/updateInvoicingQboSyncHealthFailure">, retryInvoicingQboSyncTask: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[taskId: string], {
|
|
14
6
|
taskId: string;
|
|
15
7
|
}, "invoicingQboView/retryInvoicingQboSyncTask", never, never>, retryInvoicingQboSyncTaskSuccess: import("@reduxjs/toolkit").ActionCreatorWithPayload<{
|
|
16
8
|
status: string;
|
|
@@ -1,15 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
var _a;
|
|
3
3
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
-
exports.startInvoicingQboBackfillFailure = exports.startInvoicingQboBackfillSuccess = exports.startInvoicingQboBackfill = exports.retryInvoicingQboSyncTaskFailure = exports.retryInvoicingQboSyncTaskSuccess = exports.retryInvoicingQboSyncTask = exports.updateInvoicingQboSyncHealthFailure = exports.updateInvoicingQboSyncHealth = exports.fetchInvoicingQboSyncHealth = exports.
|
|
4
|
+
exports.startInvoicingQboBackfillFailure = exports.startInvoicingQboBackfillSuccess = exports.startInvoicingQboBackfill = exports.retryInvoicingQboSyncTaskFailure = exports.retryInvoicingQboSyncTaskSuccess = exports.retryInvoicingQboSyncTask = exports.updateInvoicingQboSyncHealthFailure = exports.updateInvoicingQboSyncHealth = exports.fetchInvoicingQboSyncHealth = exports.fetchInvoicingAccountingPickers = exports.updateInvoicingQboConnectionFailure = exports.updateInvoicingQboConnection = exports.fetchInvoicingQboConnection = exports.initialState = void 0;
|
|
5
5
|
const toolkit_1 = require("@reduxjs/toolkit");
|
|
6
6
|
const rootActions_1 = require("../../../rootActions");
|
|
7
7
|
exports.initialState = {
|
|
8
|
-
accountsByAccountTypes: {},
|
|
9
|
-
accountsFetchStateByAccountTypes: {},
|
|
10
8
|
backfillFetchState: { fetchState: 'Not-Started', error: undefined },
|
|
11
|
-
classes: [],
|
|
12
|
-
classesFetchState: { fetchState: 'Not-Started', error: undefined },
|
|
13
9
|
connection: undefined,
|
|
14
10
|
connectionFetchState: { fetchState: 'Not-Started', error: undefined },
|
|
15
11
|
retryFetchStateByTaskId: {},
|
|
@@ -33,41 +29,8 @@ const invoicingQboView = (0, toolkit_1.createSlice)({
|
|
|
33
29
|
updateInvoicingQboConnectionFailure(draft, action) {
|
|
34
30
|
draft.connectionFetchState = { fetchState: 'Error', error: action.payload };
|
|
35
31
|
},
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
draft.accountsFetchStateByAccountTypes[action.payload.accountTypes] = {
|
|
39
|
-
fetchState: 'In-Progress',
|
|
40
|
-
error: undefined,
|
|
41
|
-
};
|
|
42
|
-
},
|
|
43
|
-
prepare(accountTypes) {
|
|
44
|
-
return { payload: { accountTypes } };
|
|
45
|
-
},
|
|
46
|
-
},
|
|
47
|
-
updateInvoicingQboAccounts(draft, action) {
|
|
48
|
-
draft.accountsByAccountTypes[action.payload.accountTypes] =
|
|
49
|
-
action.payload.accounts;
|
|
50
|
-
draft.accountsFetchStateByAccountTypes[action.payload.accountTypes] = {
|
|
51
|
-
fetchState: 'Completed',
|
|
52
|
-
error: undefined,
|
|
53
|
-
};
|
|
54
|
-
},
|
|
55
|
-
updateInvoicingQboAccountsFailure(draft, action) {
|
|
56
|
-
draft.accountsFetchStateByAccountTypes[action.payload.accountTypes] = {
|
|
57
|
-
fetchState: 'Error',
|
|
58
|
-
error: action.payload.status,
|
|
59
|
-
};
|
|
60
|
-
},
|
|
61
|
-
fetchInvoicingQboClasses(draft) {
|
|
62
|
-
draft.classesFetchState = { fetchState: 'In-Progress', error: undefined };
|
|
63
|
-
},
|
|
64
|
-
updateInvoicingQboClasses(draft, action) {
|
|
65
|
-
draft.classes = action.payload;
|
|
66
|
-
draft.classesFetchState = { fetchState: 'Completed', error: undefined };
|
|
67
|
-
},
|
|
68
|
-
updateInvoicingQboClassesFailure(draft, action) {
|
|
69
|
-
draft.classesFetchState = { fetchState: 'Error', error: action.payload };
|
|
70
|
-
},
|
|
32
|
+
// No state of its own: the epic decides which shared lists to load.
|
|
33
|
+
fetchInvoicingAccountingPickers() { },
|
|
71
34
|
fetchInvoicingQboSyncHealth(draft) {
|
|
72
35
|
draft.syncHealthFetchState = {
|
|
73
36
|
fetchState: 'In-Progress',
|
|
@@ -131,5 +94,5 @@ const invoicingQboView = (0, toolkit_1.createSlice)({
|
|
|
131
94
|
});
|
|
132
95
|
},
|
|
133
96
|
});
|
|
134
|
-
_a = invoicingQboView.actions, exports.fetchInvoicingQboConnection = _a.fetchInvoicingQboConnection, exports.updateInvoicingQboConnection = _a.updateInvoicingQboConnection, exports.updateInvoicingQboConnectionFailure = _a.updateInvoicingQboConnectionFailure, exports.
|
|
97
|
+
_a = invoicingQboView.actions, exports.fetchInvoicingQboConnection = _a.fetchInvoicingQboConnection, exports.updateInvoicingQboConnection = _a.updateInvoicingQboConnection, exports.updateInvoicingQboConnectionFailure = _a.updateInvoicingQboConnectionFailure, exports.fetchInvoicingAccountingPickers = _a.fetchInvoicingAccountingPickers, exports.fetchInvoicingQboSyncHealth = _a.fetchInvoicingQboSyncHealth, exports.updateInvoicingQboSyncHealth = _a.updateInvoicingQboSyncHealth, exports.updateInvoicingQboSyncHealthFailure = _a.updateInvoicingQboSyncHealthFailure, exports.retryInvoicingQboSyncTask = _a.retryInvoicingQboSyncTask, exports.retryInvoicingQboSyncTaskSuccess = _a.retryInvoicingQboSyncTaskSuccess, exports.retryInvoicingQboSyncTaskFailure = _a.retryInvoicingQboSyncTaskFailure, exports.startInvoicingQboBackfill = _a.startInvoicingQboBackfill, exports.startInvoicingQboBackfillSuccess = _a.startInvoicingQboBackfillSuccess, exports.startInvoicingQboBackfillFailure = _a.startInvoicingQboBackfillFailure;
|
|
135
98
|
exports.default = invoicingQboView.reducer;
|
|
@@ -1,21 +1,58 @@
|
|
|
1
|
+
import { NestedAccountHierarchyForReport } from '../../../commonStateTypes/accountView/nestedAccountID';
|
|
2
|
+
import { NestedClassHierarchyForReport } from '../../../commonStateTypes/classesView/nestedClassID';
|
|
1
3
|
import { FetchStateAndError } from '../../../commonStateTypes/common';
|
|
4
|
+
import { AccountType } from '../../../entity/account/accountState';
|
|
2
5
|
import { RootState } from '../../../rootStateTypes';
|
|
3
|
-
import {
|
|
6
|
+
import { InvoicingQboConnection, InvoicingQboSyncHealth } from './invoicingQboViewPayload';
|
|
7
|
+
export declare const INVOICING_ACCOUNT_LIST_KEY: "invoicingAccountList";
|
|
8
|
+
/** Whether QBO is connected, without building the option lists to find out. */
|
|
9
|
+
export declare const isInvoicingQboConnected: (state: RootState) => boolean;
|
|
10
|
+
/**
|
|
11
|
+
* Account types that can back invoicing revenue. Named here so screens ask for
|
|
12
|
+
* "income accounts" rather than repeating the accounting service's vocabulary.
|
|
13
|
+
*/
|
|
14
|
+
export declare const INVOICING_INCOME_ACCOUNT_TYPES: readonly AccountType[];
|
|
15
|
+
/** An account or class as the invoicing pickers render and submit it. */
|
|
16
|
+
export interface InvoicingAccountingOption {
|
|
17
|
+
id: string;
|
|
18
|
+
name: string;
|
|
19
|
+
accountType?: string;
|
|
20
|
+
}
|
|
4
21
|
export interface InvoicingQboView {
|
|
5
|
-
|
|
6
|
-
|
|
22
|
+
accounts: InvoicingAccountingOption[];
|
|
23
|
+
accountsFetchState: FetchStateAndError;
|
|
7
24
|
backfillState: FetchStateAndError;
|
|
8
|
-
classes:
|
|
25
|
+
classes: InvoicingAccountingOption[];
|
|
9
26
|
classesFetchState: FetchStateAndError;
|
|
10
27
|
connectionFetchState: FetchStateAndError;
|
|
28
|
+
/**
|
|
29
|
+
* The account and class trees the grouped pickers render. The flat option
|
|
30
|
+
* lists above stay for callers that only need id and name.
|
|
31
|
+
*/
|
|
32
|
+
nestedAccountHierarchy: NestedAccountHierarchyForReport[];
|
|
33
|
+
nestedClassHierarchy: NestedClassHierarchyForReport[];
|
|
11
34
|
retryFetchStateByTaskId: Record<string, FetchStateAndError>;
|
|
12
35
|
syncHealthFetchState: FetchStateAndError;
|
|
13
36
|
connection?: InvoicingQboConnection;
|
|
14
37
|
syncHealth?: InvoicingQboSyncHealth;
|
|
15
38
|
}
|
|
39
|
+
/**
|
|
40
|
+
* The accounts valid for one QBO mapping kind, whose `accountTypes` is a
|
|
41
|
+
* comma-separated list of QuickBooks type names. An unrecognised list yields no
|
|
42
|
+
* accounts rather than every account: offering a bank account where income is
|
|
43
|
+
* required would post a mapping QuickBooks rejects.
|
|
44
|
+
*/
|
|
45
|
+
export declare const invoicingAccountsForQboAccountTypes: (accounts: InvoicingAccountingOption[], accountTypes: string) => InvoicingAccountingOption[];
|
|
46
|
+
/**
|
|
47
|
+
* The account tree narrowed to the given account types. The tree itself carries
|
|
48
|
+
* no account type, so the flat account list supplies that and the matching
|
|
49
|
+
* `qboId`s are kept — which is why callers that only need "income accounts, as a
|
|
50
|
+
* tree" do not have to hold a second flat list to filter with.
|
|
51
|
+
*/
|
|
52
|
+
export declare const invoicingAccountHierarchyForTypes: (state: RootState, accountTypes: readonly AccountType[]) => NestedAccountHierarchyForReport[];
|
|
16
53
|
/**
|
|
17
54
|
* Single bundled view for the QBO integration settings screen — the
|
|
18
|
-
* connection,
|
|
19
|
-
*
|
|
55
|
+
* connection, the account and class options, sync health, and the fetch/action
|
|
56
|
+
* states for each of them.
|
|
20
57
|
*/
|
|
21
58
|
export declare const getInvoicingQboView: (state: RootState) => InvoicingQboView;
|
|
@@ -1,19 +1,140 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.getInvoicingQboView = void 0;
|
|
3
|
+
exports.getInvoicingQboView = exports.invoicingAccountHierarchyForTypes = exports.invoicingAccountsForQboAccountTypes = exports.INVOICING_INCOME_ACCOUNT_TYPES = exports.isInvoicingQboConnected = exports.INVOICING_ACCOUNT_LIST_KEY = void 0;
|
|
4
|
+
const accountListSelector_1 = require("../../accountList/accountListSelector");
|
|
5
|
+
const classListSelector_1 = require("../../classList/classListSelector");
|
|
6
|
+
// Its own bucket: invoicing needs the AP/AR exclusions that the vendor and
|
|
7
|
+
// transaction screens sharing `accountList` do not pass.
|
|
8
|
+
exports.INVOICING_ACCOUNT_LIST_KEY = 'invoicingAccountList';
|
|
9
|
+
/** Whether QBO is connected, without building the option lists to find out. */
|
|
10
|
+
const isInvoicingQboConnected = (state) => state.invoicingQboViewState.connection?.connected === true;
|
|
11
|
+
exports.isInvoicingQboConnected = isInvoicingQboConnected;
|
|
12
|
+
/**
|
|
13
|
+
* Account types that can back invoicing revenue. Named here so screens ask for
|
|
14
|
+
* "income accounts" rather than repeating the accounting service's vocabulary.
|
|
15
|
+
*/
|
|
16
|
+
exports.INVOICING_INCOME_ACCOUNT_TYPES = [
|
|
17
|
+
'income',
|
|
18
|
+
'other_income',
|
|
19
|
+
];
|
|
20
|
+
/**
|
|
21
|
+
* Accounts and classes as the invoicing pickers need them. Both come from the
|
|
22
|
+
* shared accounting-service lists, so whatever another screen already loaded
|
|
23
|
+
* is reused. `qboId` is the submitted value because that is what the invoicing
|
|
24
|
+
* API stores; an account without one cannot be posted, so it is dropped rather
|
|
25
|
+
* than offered.
|
|
26
|
+
*/
|
|
27
|
+
const invoicingAccountingOptions = (state, accountTypes) => {
|
|
28
|
+
const { accounts } = (0, accountListSelector_1.getAccountList)(state.accountState, state.accountListState, exports.INVOICING_ACCOUNT_LIST_KEY);
|
|
29
|
+
return accounts.flatMap((account) => {
|
|
30
|
+
if (account.qboId == null || account.isDeleted === true) {
|
|
31
|
+
return [];
|
|
32
|
+
}
|
|
33
|
+
if (accountTypes != null &&
|
|
34
|
+
(account.accountType == null ||
|
|
35
|
+
!accountTypes.includes(account.accountType))) {
|
|
36
|
+
return [];
|
|
37
|
+
}
|
|
38
|
+
return [
|
|
39
|
+
{
|
|
40
|
+
id: String(account.qboId),
|
|
41
|
+
name: account.accountName,
|
|
42
|
+
accountType: account.accountType,
|
|
43
|
+
},
|
|
44
|
+
];
|
|
45
|
+
});
|
|
46
|
+
};
|
|
47
|
+
/**
|
|
48
|
+
* Normalises an account-type name for comparison. The config's mapping kinds
|
|
49
|
+
* name QuickBooks types the way QuickBooks displays them ("Other Current
|
|
50
|
+
* Asset", "Expense"), while the accounting service uses snake_case and
|
|
51
|
+
* sometimes pluralises ("other_current_assets", "expenses"). Comparing the
|
|
52
|
+
* normalised, de-pluralised forms keeps a picker from silently emptying because
|
|
53
|
+
* of a trailing "s".
|
|
54
|
+
*/
|
|
55
|
+
const normalizeAccountTypeName = (value) => {
|
|
56
|
+
const normalized = value
|
|
57
|
+
.trim()
|
|
58
|
+
.toLowerCase()
|
|
59
|
+
.replace(/[^a-z0-9]+/g, '_');
|
|
60
|
+
// Singularise so "Other Current Liability" meets `other_current_liabilities`
|
|
61
|
+
// and "Expense" meets `expenses`. `-ies` needs its own case: stripping the
|
|
62
|
+
// trailing "s" alone would leave "liabilitie", matching nothing.
|
|
63
|
+
return normalized.replace(/ies$/, 'y').replace(/([^s])s$/, '$1');
|
|
64
|
+
};
|
|
65
|
+
/**
|
|
66
|
+
* The accounts valid for one QBO mapping kind, whose `accountTypes` is a
|
|
67
|
+
* comma-separated list of QuickBooks type names. An unrecognised list yields no
|
|
68
|
+
* accounts rather than every account: offering a bank account where income is
|
|
69
|
+
* required would post a mapping QuickBooks rejects.
|
|
70
|
+
*/
|
|
71
|
+
const invoicingAccountsForQboAccountTypes = (accounts, accountTypes) => {
|
|
72
|
+
const wanted = new Set(accountTypes
|
|
73
|
+
.split(',')
|
|
74
|
+
.map(normalizeAccountTypeName)
|
|
75
|
+
.filter((accountType) => accountType !== ''));
|
|
76
|
+
if (wanted.size === 0) {
|
|
77
|
+
return accounts;
|
|
78
|
+
}
|
|
79
|
+
return accounts.filter((account) => account.accountType != null &&
|
|
80
|
+
wanted.has(normalizeAccountTypeName(account.accountType)));
|
|
81
|
+
};
|
|
82
|
+
exports.invoicingAccountsForQboAccountTypes = invoicingAccountsForQboAccountTypes;
|
|
83
|
+
/** Classes as the invoicing pickers need them, from the shared class list. */
|
|
84
|
+
const invoicingAccountingClassOptions = (state) => {
|
|
85
|
+
const { classes } = (0, classListSelector_1.getClassList)(state.classState, state.classListState);
|
|
86
|
+
return classes.flatMap((accountingClass) => accountingClass.qboId == null || accountingClass.isDeleted === true
|
|
87
|
+
? []
|
|
88
|
+
: [
|
|
89
|
+
{
|
|
90
|
+
id: String(accountingClass.qboId),
|
|
91
|
+
name: accountingClass.className,
|
|
92
|
+
},
|
|
93
|
+
]);
|
|
94
|
+
};
|
|
95
|
+
/**
|
|
96
|
+
* The account tree narrowed to the given account types. The tree itself carries
|
|
97
|
+
* no account type, so the flat account list supplies that and the matching
|
|
98
|
+
* `qboId`s are kept — which is why callers that only need "income accounts, as a
|
|
99
|
+
* tree" do not have to hold a second flat list to filter with.
|
|
100
|
+
*/
|
|
101
|
+
const invoicingAccountHierarchyForTypes = (state, accountTypes) => {
|
|
102
|
+
const allowedQboIds = new Set(invoicingAccountingOptions(state, accountTypes).map((account) => account.id));
|
|
103
|
+
const keepMatching = (nodes) => nodes.flatMap((node) => {
|
|
104
|
+
const children = keepMatching(node.children);
|
|
105
|
+
const isMatch = node.qboId != null && allowedQboIds.has(String(node.qboId));
|
|
106
|
+
// A parent that is not itself a match is still kept when it holds one, so
|
|
107
|
+
// the tree's shape survives the filter.
|
|
108
|
+
if (!isMatch && children.length === 0) {
|
|
109
|
+
return [];
|
|
110
|
+
}
|
|
111
|
+
return [{ ...node, children }];
|
|
112
|
+
});
|
|
113
|
+
return keepMatching((0, accountListSelector_1.getNestedAccountListHierarchy)(state.accountListState, exports.INVOICING_ACCOUNT_LIST_KEY));
|
|
114
|
+
};
|
|
115
|
+
exports.invoicingAccountHierarchyForTypes = invoicingAccountHierarchyForTypes;
|
|
4
116
|
/**
|
|
5
117
|
* Single bundled view for the QBO integration settings screen — the
|
|
6
|
-
* connection,
|
|
7
|
-
*
|
|
118
|
+
* connection, the account and class options, sync health, and the fetch/action
|
|
119
|
+
* states for each of them.
|
|
8
120
|
*/
|
|
9
121
|
const getInvoicingQboView = (state) => {
|
|
10
122
|
const qboState = state.invoicingQboViewState;
|
|
123
|
+
const accountList = state.accountListState.byReportId[exports.INVOICING_ACCOUNT_LIST_KEY];
|
|
11
124
|
return {
|
|
12
|
-
|
|
13
|
-
|
|
125
|
+
accounts: invoicingAccountingOptions(state),
|
|
126
|
+
accountsFetchState: {
|
|
127
|
+
fetchState: accountList.fetchState,
|
|
128
|
+
error: accountList.error,
|
|
129
|
+
},
|
|
130
|
+
nestedAccountHierarchy: (0, accountListSelector_1.getNestedAccountListHierarchy)(state.accountListState, exports.INVOICING_ACCOUNT_LIST_KEY),
|
|
131
|
+
nestedClassHierarchy: (0, classListSelector_1.getNestedClassListHierarchy)(state.classListState),
|
|
14
132
|
backfillState: qboState.backfillFetchState,
|
|
15
|
-
classes:
|
|
16
|
-
classesFetchState:
|
|
133
|
+
classes: invoicingAccountingClassOptions(state),
|
|
134
|
+
classesFetchState: {
|
|
135
|
+
fetchState: state.classListState.fetchState,
|
|
136
|
+
error: state.classListState.error,
|
|
137
|
+
},
|
|
17
138
|
connection: qboState.connection,
|
|
18
139
|
connectionFetchState: qboState.connectionFetchState,
|
|
19
140
|
retryFetchStateByTaskId: qboState.retryFetchStateByTaskId,
|
|
@@ -1,11 +1,7 @@
|
|
|
1
1
|
import { FetchStateAndError } from '../../../commonStateTypes/common';
|
|
2
|
-
import {
|
|
2
|
+
import { InvoicingQboConnection, InvoicingQboSyncHealth } from './invoicingQboViewPayload';
|
|
3
3
|
export interface InvoicingQboViewState {
|
|
4
|
-
accountsByAccountTypes: Record<string, InvoicingQboAccountOption[]>;
|
|
5
|
-
accountsFetchStateByAccountTypes: Record<string, FetchStateAndError>;
|
|
6
4
|
backfillFetchState: FetchStateAndError;
|
|
7
|
-
classes: InvoicingQboAccountOption[];
|
|
8
|
-
classesFetchState: FetchStateAndError;
|
|
9
5
|
connectionFetchState: FetchStateAndError;
|
|
10
6
|
retryFetchStateByTaskId: Record<string, FetchStateAndError>;
|
|
11
7
|
syncHealthFetchState: FetchStateAndError;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zeniai/client-epic-state",
|
|
3
|
-
"version": "5.2.
|
|
3
|
+
"version": "5.2.6",
|
|
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,25 +0,0 @@
|
|
|
1
|
-
import { of } from 'rxjs';
|
|
2
|
-
import { catchError, filter, map, mergeMap } from 'rxjs/operators';
|
|
3
|
-
import { createZeniAPIStatus, isSuccessResponse, } from '../../../../responsePayload';
|
|
4
|
-
import { mapInvoicingQboAccountOptions, } from '../invoicingQboViewPayload';
|
|
5
|
-
import { fetchInvoicingQboAccounts, updateInvoicingQboAccounts, updateInvoicingQboAccountsFailure, } from '../invoicingQboViewReducer';
|
|
6
|
-
export const fetchInvoicingQboAccountsEpic = (actions$, _state$, zeniAPI) => actions$.pipe(filter(fetchInvoicingQboAccounts.match), mergeMap((action) => {
|
|
7
|
-
const { accountTypes } = action.payload;
|
|
8
|
-
const apiUrl = `${zeniAPI.apiEndPoints.invoicingMicroServiceBaseUrl}/1.0/qbo/accounts?account_types=${encodeURIComponent(accountTypes)}`;
|
|
9
|
-
return zeniAPI.getJSON(apiUrl).pipe(map((response) => {
|
|
10
|
-
if (isSuccessResponse(response)) {
|
|
11
|
-
return updateInvoicingQboAccounts({
|
|
12
|
-
accountTypes,
|
|
13
|
-
accounts: mapInvoicingQboAccountOptions(response.data?.accounts ?? []),
|
|
14
|
-
});
|
|
15
|
-
}
|
|
16
|
-
return updateInvoicingQboAccountsFailure({
|
|
17
|
-
accountTypes,
|
|
18
|
-
status: response.status,
|
|
19
|
-
});
|
|
20
|
-
}), catchError((error) => of(updateInvoicingQboAccountsFailure({
|
|
21
|
-
accountTypes,
|
|
22
|
-
status: createZeniAPIStatus('Unexpected Error', 'Fetch QBO accounts REST API call errored out ' +
|
|
23
|
-
JSON.stringify(error)),
|
|
24
|
-
}))));
|
|
25
|
-
}));
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import { of } from 'rxjs';
|
|
2
|
-
import { catchError, filter, map, switchMap } from 'rxjs/operators';
|
|
3
|
-
import { createZeniAPIStatus, isSuccessResponse, } from '../../../../responsePayload';
|
|
4
|
-
import { mapInvoicingQboAccountOptions, } from '../invoicingQboViewPayload';
|
|
5
|
-
import { fetchInvoicingQboClasses, updateInvoicingQboClasses, updateInvoicingQboClassesFailure, } from '../invoicingQboViewReducer';
|
|
6
|
-
export const fetchInvoicingQboClassesEpic = (actions$, _state$, zeniAPI) => actions$.pipe(filter(fetchInvoicingQboClasses.match), switchMap(() => {
|
|
7
|
-
const apiUrl = `${zeniAPI.apiEndPoints.invoicingMicroServiceBaseUrl}/1.0/qbo/classes`;
|
|
8
|
-
return zeniAPI.getJSON(apiUrl).pipe(map((response) => {
|
|
9
|
-
if (isSuccessResponse(response)) {
|
|
10
|
-
return updateInvoicingQboClasses(mapInvoicingQboAccountOptions(response.data?.accounts ?? []));
|
|
11
|
-
}
|
|
12
|
-
return updateInvoicingQboClassesFailure(response.status);
|
|
13
|
-
}), catchError((error) => of(updateInvoicingQboClassesFailure(createZeniAPIStatus('Unexpected Error', 'Fetch QBO classes REST API call errored out ' +
|
|
14
|
-
JSON.stringify(error))))));
|
|
15
|
-
}));
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
import { ActionsObservable, StateObservable } from 'redux-observable';
|
|
2
|
-
import { Observable } from 'rxjs';
|
|
3
|
-
import { RootState } from '../../../../rootStateTypes';
|
|
4
|
-
import { ZeniAPI } from '../../../../zeniAPI';
|
|
5
|
-
import { InvoicingQboViewActionType } from './invoicingQboViewActionType';
|
|
6
|
-
export declare const fetchInvoicingQboAccountsEpic: (actions$: ActionsObservable<InvoicingQboViewActionType>, _state$: StateObservable<RootState>, zeniAPI: ZeniAPI) => Observable<InvoicingQboViewActionType>;
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.fetchInvoicingQboAccountsEpic = void 0;
|
|
4
|
-
const rxjs_1 = require("rxjs");
|
|
5
|
-
const operators_1 = require("rxjs/operators");
|
|
6
|
-
const responsePayload_1 = require("../../../../responsePayload");
|
|
7
|
-
const invoicingQboViewPayload_1 = require("../invoicingQboViewPayload");
|
|
8
|
-
const invoicingQboViewReducer_1 = require("../invoicingQboViewReducer");
|
|
9
|
-
const fetchInvoicingQboAccountsEpic = (actions$, _state$, zeniAPI) => actions$.pipe((0, operators_1.filter)(invoicingQboViewReducer_1.fetchInvoicingQboAccounts.match), (0, operators_1.mergeMap)((action) => {
|
|
10
|
-
const { accountTypes } = action.payload;
|
|
11
|
-
const apiUrl = `${zeniAPI.apiEndPoints.invoicingMicroServiceBaseUrl}/1.0/qbo/accounts?account_types=${encodeURIComponent(accountTypes)}`;
|
|
12
|
-
return zeniAPI.getJSON(apiUrl).pipe((0, operators_1.map)((response) => {
|
|
13
|
-
if ((0, responsePayload_1.isSuccessResponse)(response)) {
|
|
14
|
-
return (0, invoicingQboViewReducer_1.updateInvoicingQboAccounts)({
|
|
15
|
-
accountTypes,
|
|
16
|
-
accounts: (0, invoicingQboViewPayload_1.mapInvoicingQboAccountOptions)(response.data?.accounts ?? []),
|
|
17
|
-
});
|
|
18
|
-
}
|
|
19
|
-
return (0, invoicingQboViewReducer_1.updateInvoicingQboAccountsFailure)({
|
|
20
|
-
accountTypes,
|
|
21
|
-
status: response.status,
|
|
22
|
-
});
|
|
23
|
-
}), (0, operators_1.catchError)((error) => (0, rxjs_1.of)((0, invoicingQboViewReducer_1.updateInvoicingQboAccountsFailure)({
|
|
24
|
-
accountTypes,
|
|
25
|
-
status: (0, responsePayload_1.createZeniAPIStatus)('Unexpected Error', 'Fetch QBO accounts REST API call errored out ' +
|
|
26
|
-
JSON.stringify(error)),
|
|
27
|
-
}))));
|
|
28
|
-
}));
|
|
29
|
-
exports.fetchInvoicingQboAccountsEpic = fetchInvoicingQboAccountsEpic;
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
import { ActionsObservable, StateObservable } from 'redux-observable';
|
|
2
|
-
import { Observable } from 'rxjs';
|
|
3
|
-
import { RootState } from '../../../../rootStateTypes';
|
|
4
|
-
import { ZeniAPI } from '../../../../zeniAPI';
|
|
5
|
-
import { InvoicingQboViewActionType } from './invoicingQboViewActionType';
|
|
6
|
-
export declare const fetchInvoicingQboClassesEpic: (actions$: ActionsObservable<InvoicingQboViewActionType>, _state$: StateObservable<RootState>, zeniAPI: ZeniAPI) => Observable<InvoicingQboViewActionType>;
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.fetchInvoicingQboClassesEpic = void 0;
|
|
4
|
-
const rxjs_1 = require("rxjs");
|
|
5
|
-
const operators_1 = require("rxjs/operators");
|
|
6
|
-
const responsePayload_1 = require("../../../../responsePayload");
|
|
7
|
-
const invoicingQboViewPayload_1 = require("../invoicingQboViewPayload");
|
|
8
|
-
const invoicingQboViewReducer_1 = require("../invoicingQboViewReducer");
|
|
9
|
-
const fetchInvoicingQboClassesEpic = (actions$, _state$, zeniAPI) => actions$.pipe((0, operators_1.filter)(invoicingQboViewReducer_1.fetchInvoicingQboClasses.match), (0, operators_1.switchMap)(() => {
|
|
10
|
-
const apiUrl = `${zeniAPI.apiEndPoints.invoicingMicroServiceBaseUrl}/1.0/qbo/classes`;
|
|
11
|
-
return zeniAPI.getJSON(apiUrl).pipe((0, operators_1.map)((response) => {
|
|
12
|
-
if ((0, responsePayload_1.isSuccessResponse)(response)) {
|
|
13
|
-
return (0, invoicingQboViewReducer_1.updateInvoicingQboClasses)((0, invoicingQboViewPayload_1.mapInvoicingQboAccountOptions)(response.data?.accounts ?? []));
|
|
14
|
-
}
|
|
15
|
-
return (0, invoicingQboViewReducer_1.updateInvoicingQboClassesFailure)(response.status);
|
|
16
|
-
}), (0, operators_1.catchError)((error) => (0, rxjs_1.of)((0, invoicingQboViewReducer_1.updateInvoicingQboClassesFailure)((0, responsePayload_1.createZeniAPIStatus)('Unexpected Error', 'Fetch QBO classes REST API call errored out ' +
|
|
17
|
-
JSON.stringify(error))))));
|
|
18
|
-
}));
|
|
19
|
-
exports.fetchInvoicingQboClassesEpic = fetchInvoicingQboClassesEpic;
|