@zeniai/client-epic-state 5.2.10-betaAK0 → 5.2.10
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/entity/invoicing/invoicingCommonPayload.d.ts +17 -29
- package/lib/entity/invoicing/invoicingCommonPayload.js +10 -47
- package/lib/entity/invoicing/product/productPayload.d.ts +0 -10
- package/lib/entity/invoicing/product/productPayload.js +2 -14
- package/lib/esm/entity/invoicing/invoicingCommonPayload.js +9 -44
- package/lib/esm/entity/invoicing/product/productPayload.js +2 -14
- package/lib/esm/view/invoicing/editInvoicingCatalogItemDetailView/editInvoicingCatalogItemDetailViewPayload.js +9 -24
- package/lib/esm/view/invoicing/editInvoicingCatalogItemDetailView/saveInvoicingCatalogItemEpic.js +1 -6
- package/lib/esm/view/invoicing/invoicingQboView/invoicingQboViewSelector.js +0 -20
- package/lib/esm/view/invoicing/settingsView/settingsViewEpics.js +2 -17
- package/lib/view/invoicing/editInvoicingCatalogItemDetailView/editInvoicingCatalogItemDetailViewPayload.d.ts +1 -12
- package/lib/view/invoicing/editInvoicingCatalogItemDetailView/editInvoicingCatalogItemDetailViewPayload.js +9 -24
- package/lib/view/invoicing/editInvoicingCatalogItemDetailView/saveInvoicingCatalogItemEpic.js +1 -6
- package/lib/view/invoicing/invoicingQboView/invoicingQboViewSelector.d.ts +1 -10
- package/lib/view/invoicing/invoicingQboView/invoicingQboViewSelector.js +1 -23
- package/lib/view/invoicing/settingsView/settingsViewEpics.d.ts +1 -1
- package/lib/view/invoicing/settingsView/settingsViewEpics.js +2 -17
- package/package.json +1 -1
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import { AccountBasePayload } from '../account/accountPayload';
|
|
2
|
-
import { AccountBase } from '../account/accountState';
|
|
3
1
|
import { AddressPayload } from '../address/addressPayload';
|
|
4
2
|
export type InvoicingPriceType = 'tax_exclusive' | 'tax_inclusive';
|
|
5
3
|
export declare const INVOICING_DUNNING_ACTIONS: readonly ["email_only", "email_and_retry", "do_nothing", "retry_only"];
|
|
@@ -94,51 +92,41 @@ export declare function toInvoicingQboCustomerMatchingMode(value: string): Invoi
|
|
|
94
92
|
* A mapped account as the newer settings payload returns it: the platform id,
|
|
95
93
|
* plus hydrated fields the client only displays.
|
|
96
94
|
*/
|
|
95
|
+
export interface InvoicingQboMappedAccountPayload {
|
|
96
|
+
account_id?: string | null;
|
|
97
|
+
account_name?: string | null;
|
|
98
|
+
fully_qualified_name?: string | null;
|
|
99
|
+
qbo_id?: string | null;
|
|
100
|
+
}
|
|
97
101
|
/**
|
|
98
102
|
* Account mappings arrive in two shapes. The original sends a bare id per slot
|
|
99
|
-
* (`deposit_account_id`); the newer one sends the
|
|
100
|
-
* (`deposit_account`). Both are declared because a tenant can be
|
|
101
|
-
* depending on when its backend rolled, and a page that understands
|
|
102
|
-
* renders an empty picker over data that exists.
|
|
103
|
-
* carry only the ids, while a write sends a whole `AccountBasePayload`.
|
|
103
|
+
* (`deposit_account_id`); the newer one sends an object holding the platform id
|
|
104
|
+
* (`deposit_account: {account_id}`). Both are declared because a tenant can be
|
|
105
|
+
* served either depending on when its backend rolled, and a page that understands
|
|
106
|
+
* only one renders an empty picker over data that exists.
|
|
104
107
|
*/
|
|
105
108
|
export interface InvoicingQboAccountMappingsPayload {
|
|
106
|
-
default_income_account?:
|
|
109
|
+
default_income_account?: InvoicingQboMappedAccountPayload | null;
|
|
107
110
|
default_income_account_id?: string | null;
|
|
108
|
-
deposit_account?:
|
|
111
|
+
deposit_account?: InvoicingQboMappedAccountPayload | null;
|
|
109
112
|
deposit_account_id?: string | null;
|
|
110
113
|
deposit_account_overrides?: Record<string, string> | null;
|
|
111
|
-
discounts_account?:
|
|
114
|
+
discounts_account?: InvoicingQboMappedAccountPayload | null;
|
|
112
115
|
discounts_account_id?: string | null;
|
|
113
|
-
rounding_account?:
|
|
116
|
+
rounding_account?: InvoicingQboMappedAccountPayload | null;
|
|
114
117
|
rounding_account_id?: string | null;
|
|
115
|
-
write_off_account?:
|
|
118
|
+
write_off_account?: InvoicingQboMappedAccountPayload | null;
|
|
116
119
|
write_off_account_id?: string | null;
|
|
117
120
|
}
|
|
118
|
-
/**
|
|
119
|
-
* The id for one mapping slot, from whichever shape the backend sent. The object
|
|
120
|
-
* form wins when present; a blank id in either is treated as unset so the picker
|
|
121
|
-
* shows its placeholder rather than selecting nothing.
|
|
122
|
-
*/
|
|
123
|
-
/**
|
|
124
|
-
* The first id a picker can actually select. Callers list the QuickBooks id
|
|
125
|
-
* first: the options are keyed on it, so an internal id selects nothing even
|
|
126
|
-
* when it names the same record. Blank counts as absent, so a cleared field
|
|
127
|
-
* falls through to the next candidate rather than selecting an empty option.
|
|
128
|
-
*/
|
|
129
|
-
export declare const firstSelectableInvoicingId: (candidates: readonly (string | null | undefined)[]) => string | undefined;
|
|
130
121
|
/**
|
|
131
122
|
* Read one account-mapping dropdown value by its config `code` (the codes in
|
|
132
123
|
* `qbo_account_mapping_kind_options` match the `account_mappings` field names).
|
|
133
124
|
*/
|
|
134
125
|
export declare function getInvoicingQboAccountMappingId(accountMappings: InvoicingQboAccountMappingsPayload | undefined, code: string): string | undefined;
|
|
135
126
|
/**
|
|
136
|
-
*
|
|
137
|
-
*
|
|
138
|
-
* page's draft so the UI keeps working in ids, and an id that no longer resolves
|
|
139
|
-
* is left out — a mapping the service cannot expand is worse than none.
|
|
127
|
+
* Return a copy of the account mappings with the dropdown slot named by
|
|
128
|
+
* `code` set to `accountId`. Unknown codes leave the mappings unchanged.
|
|
140
129
|
*/
|
|
141
|
-
export declare const withInvoicingQboMappedAccounts: (accountMappings: InvoicingQboAccountMappingsPayload | undefined, accountByQboId: (qboId: string) => AccountBase | undefined) => InvoicingQboAccountMappingsPayload | undefined;
|
|
142
130
|
export declare function withInvoicingQboAccountMappingId(accountMappings: InvoicingQboAccountMappingsPayload | undefined, code: string, accountId: string): InvoicingQboAccountMappingsPayload;
|
|
143
131
|
export interface InvoicingQboSettingsPayload {
|
|
144
132
|
account_mappings?: InvoicingQboAccountMappingsPayload | null;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.ALL_INVOICING_FIELD_HELP_GROUPS = exports.
|
|
3
|
+
exports.ALL_INVOICING_FIELD_HELP_GROUPS = exports.INVOICING_QBO_CUSTOMER_MATCHING_MODES = exports.INVOICING_DISCOUNT_LIFECYCLE_ACTIONS = exports.INVOICING_CATALOG_PRODUCT_LIFECYCLE_ACTIONS = exports.INVOICING_CATALOG_ITEM_LIFECYCLE_ACTIONS = exports.INVOICING_SUBSCRIPTION_LIFECYCLE_ACTIONS = exports.INVOICING_DUNNING_ACTIONS = void 0;
|
|
4
4
|
exports.toInvoicingDunningAction = toInvoicingDunningAction;
|
|
5
5
|
exports.toInvoicingSubscriptionLifecycleAction = toInvoicingSubscriptionLifecycleAction;
|
|
6
6
|
exports.toInvoicingSubscriptionLifecycleActionOption = toInvoicingSubscriptionLifecycleActionOption;
|
|
@@ -23,7 +23,6 @@ exports.toInvoicingSubscriptionEditFieldOption = toInvoicingSubscriptionEditFiel
|
|
|
23
23
|
exports.toAuditLogEntityRouteOption = toAuditLogEntityRouteOption;
|
|
24
24
|
exports.buildInvoicingEntityPath = buildInvoicingEntityPath;
|
|
25
25
|
exports.isInvoicingEntityLinkable = isInvoicingEntityLinkable;
|
|
26
|
-
const accountPayload_1 = require("../account/accountPayload");
|
|
27
26
|
exports.INVOICING_DUNNING_ACTIONS = [
|
|
28
27
|
'email_only',
|
|
29
28
|
'email_and_retry',
|
|
@@ -159,22 +158,17 @@ function toInvoicingQboCustomerMatchingMode(value) {
|
|
|
159
158
|
* form wins when present; a blank id in either is treated as unset so the picker
|
|
160
159
|
* shows its placeholder rather than selecting nothing.
|
|
161
160
|
*/
|
|
162
|
-
/**
|
|
163
|
-
* The first id a picker can actually select. Callers list the QuickBooks id
|
|
164
|
-
* first: the options are keyed on it, so an internal id selects nothing even
|
|
165
|
-
* when it names the same record. Blank counts as absent, so a cleared field
|
|
166
|
-
* falls through to the next candidate rather than selecting an empty option.
|
|
167
|
-
*/
|
|
168
|
-
const firstSelectableInvoicingId = (candidates) => candidates.find((candidate) => candidate != null && candidate !== '');
|
|
169
|
-
exports.firstSelectableInvoicingId = firstSelectableInvoicingId;
|
|
170
161
|
function readInvoicingQboMappedAccountId(mappedAccount, legacyAccountId) {
|
|
171
|
-
//
|
|
172
|
-
//
|
|
173
|
-
|
|
162
|
+
// `qbo_id` first: the pickers key their options on the QuickBooks id, so an
|
|
163
|
+
// internal `account_id` would not select anything even when it is the same
|
|
164
|
+
// account. Both are read because the mapping arrives either way depending on
|
|
165
|
+
// how it was saved.
|
|
166
|
+
const candidates = [
|
|
174
167
|
mappedAccount?.qbo_id,
|
|
175
168
|
mappedAccount?.account_id,
|
|
176
169
|
legacyAccountId,
|
|
177
|
-
]
|
|
170
|
+
];
|
|
171
|
+
return candidates.find((candidate) => candidate != null && candidate !== '');
|
|
178
172
|
}
|
|
179
173
|
/**
|
|
180
174
|
* Read one account-mapping dropdown value by its config `code` (the codes in
|
|
@@ -200,42 +194,11 @@ function getInvoicingQboAccountMappingId(accountMappings, code) {
|
|
|
200
194
|
* Return a copy of the account mappings with the dropdown slot named by
|
|
201
195
|
* `code` set to `accountId`. Unknown codes leave the mappings unchanged.
|
|
202
196
|
*/
|
|
203
|
-
/** The object key holding the mapped account for each `*_account_id` code. */
|
|
204
|
-
const INVOICING_QBO_MAPPED_ACCOUNT_KEY = {
|
|
205
|
-
default_income_account_id: 'default_income_account',
|
|
206
|
-
deposit_account_id: 'deposit_account',
|
|
207
|
-
discounts_account_id: 'discounts_account',
|
|
208
|
-
rounding_account_id: 'rounding_account',
|
|
209
|
-
write_off_account_id: 'write_off_account',
|
|
210
|
-
};
|
|
211
|
-
/**
|
|
212
|
-
* Expand each mapping from the id the picker submitted to the whole account, the
|
|
213
|
-
* shape the service stores. Written at the request boundary rather than in the
|
|
214
|
-
* page's draft so the UI keeps working in ids, and an id that no longer resolves
|
|
215
|
-
* is left out — a mapping the service cannot expand is worse than none.
|
|
216
|
-
*/
|
|
217
|
-
const withInvoicingQboMappedAccounts = (accountMappings, accountByQboId) => {
|
|
218
|
-
if (accountMappings == null) {
|
|
219
|
-
return undefined;
|
|
220
|
-
}
|
|
221
|
-
const expanded = { ...accountMappings };
|
|
222
|
-
Object.entries(INVOICING_QBO_MAPPED_ACCOUNT_KEY).forEach(([code, objectKey]) => {
|
|
223
|
-
const accountId = getInvoicingQboAccountMappingId(accountMappings, code);
|
|
224
|
-
if (accountId == null) {
|
|
225
|
-
return;
|
|
226
|
-
}
|
|
227
|
-
const account = accountByQboId(accountId);
|
|
228
|
-
expanded[objectKey] =
|
|
229
|
-
account != null ? (0, accountPayload_1.toAccountPayload)(account) : undefined;
|
|
230
|
-
expanded[code] = undefined;
|
|
231
|
-
});
|
|
232
|
-
return expanded;
|
|
233
|
-
};
|
|
234
|
-
exports.withInvoicingQboMappedAccounts = withInvoicingQboMappedAccounts;
|
|
235
197
|
function withInvoicingQboAccountMappingId(accountMappings, code, accountId) {
|
|
236
198
|
// Both slots are written together. Setting only the bare id would leave the
|
|
237
199
|
// object shape behind, and the reader prefers it — so the selection just made
|
|
238
|
-
// would read back as whatever was mapped before.
|
|
200
|
+
// would read back as whatever was mapped before. The object is dropped rather
|
|
201
|
+
// than rebuilt: only the id is known here, not the name that came with it.
|
|
239
202
|
const base = accountMappings ?? {};
|
|
240
203
|
switch (code) {
|
|
241
204
|
case 'deposit_account_id':
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import { AccountBasePayload } from '../../account/accountPayload';
|
|
2
|
-
import { ClassBasePayload } from '../../class/classPayload';
|
|
3
1
|
import { InvoicingPlanTier, InvoicingProduct } from './productState';
|
|
4
2
|
export interface InvoicingPlanTierPayload {
|
|
5
3
|
price: number;
|
|
@@ -9,18 +7,10 @@ export interface InvoicingPlanTierPayload {
|
|
|
9
7
|
pricing_type?: string;
|
|
10
8
|
}
|
|
11
9
|
export interface InvoicingAccountingDetailPayload {
|
|
12
|
-
/**
|
|
13
|
-
* `account` and `accounting_class` hold whole records — what the service stores
|
|
14
|
-
* and what the catalog payload builder sends. The bare `accounting_code` /
|
|
15
|
-
* `accounting_category_1` are the older shape, still read so a plan saved
|
|
16
|
-
* before the rollover prefills.
|
|
17
|
-
*/
|
|
18
|
-
account?: Partial<AccountBasePayload> | null;
|
|
19
10
|
accounting_category_1?: string;
|
|
20
11
|
accounting_category_2?: string;
|
|
21
12
|
accounting_category_3?: string;
|
|
22
13
|
accounting_category_4?: string;
|
|
23
|
-
accounting_class?: Partial<ClassBasePayload> | null;
|
|
24
14
|
accounting_code?: string;
|
|
25
15
|
sku?: string;
|
|
26
16
|
}
|
|
@@ -4,7 +4,6 @@ exports.mapInvoicingProductPayloadToState = exports.mapInvoicingPlanTierPayloadT
|
|
|
4
4
|
const amount_1 = require("../../../commonStateTypes/amount");
|
|
5
5
|
const currencyHelper_1 = require("../../../commonStateTypes/currencyHelper");
|
|
6
6
|
const zeniDayJS_1 = require("../../../zeniDayJS");
|
|
7
|
-
const invoicingCommonPayload_1 = require("../invoicingCommonPayload");
|
|
8
7
|
// ── Payload → State mappers (snake_case wire shape → camelCase domain shape) ──
|
|
9
8
|
const mapInvoicingPlanTierPayloadToState = (payload, currencyCode, currencySymbol) => ({
|
|
10
9
|
price: (0, amount_1.toAmount)(payload.price, currencyCode, currencySymbol),
|
|
@@ -15,22 +14,11 @@ const mapInvoicingPlanTierPayloadToState = (payload, currencyCode, currencySymbo
|
|
|
15
14
|
});
|
|
16
15
|
exports.mapInvoicingPlanTierPayloadToState = mapInvoicingPlanTierPayloadToState;
|
|
17
16
|
const mapInvoicingAccountingDetailPayloadToState = (payload) => ({
|
|
18
|
-
|
|
19
|
-
// documents: the form's pickers are keyed on it, so reading the internal id
|
|
20
|
-
// would leave the field blank over a mapping that exists.
|
|
21
|
-
accountingCategory1: (0, invoicingCommonPayload_1.firstSelectableInvoicingId)([
|
|
22
|
-
payload.accounting_class?.qbo_id,
|
|
23
|
-
payload.accounting_class?.accounting_class_id,
|
|
24
|
-
payload.accounting_category_1,
|
|
25
|
-
]),
|
|
17
|
+
accountingCategory1: payload.accounting_category_1,
|
|
26
18
|
accountingCategory2: payload.accounting_category_2,
|
|
27
19
|
accountingCategory3: payload.accounting_category_3,
|
|
28
20
|
accountingCategory4: payload.accounting_category_4,
|
|
29
|
-
accountingCode:
|
|
30
|
-
payload.account?.qbo_id,
|
|
31
|
-
payload.account?.account_id,
|
|
32
|
-
payload.accounting_code,
|
|
33
|
-
]),
|
|
21
|
+
accountingCode: payload.accounting_code,
|
|
34
22
|
sku: payload.sku,
|
|
35
23
|
});
|
|
36
24
|
const mapInvoicingProductPayloadToState = (payload) => {
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { toAccountPayload } from '../account/accountPayload';
|
|
2
1
|
export const INVOICING_DUNNING_ACTIONS = [
|
|
3
2
|
'email_only',
|
|
4
3
|
'email_and_retry',
|
|
@@ -134,21 +133,17 @@ export function toInvoicingQboCustomerMatchingMode(value) {
|
|
|
134
133
|
* form wins when present; a blank id in either is treated as unset so the picker
|
|
135
134
|
* shows its placeholder rather than selecting nothing.
|
|
136
135
|
*/
|
|
137
|
-
/**
|
|
138
|
-
* The first id a picker can actually select. Callers list the QuickBooks id
|
|
139
|
-
* first: the options are keyed on it, so an internal id selects nothing even
|
|
140
|
-
* when it names the same record. Blank counts as absent, so a cleared field
|
|
141
|
-
* falls through to the next candidate rather than selecting an empty option.
|
|
142
|
-
*/
|
|
143
|
-
export const firstSelectableInvoicingId = (candidates) => candidates.find((candidate) => candidate != null && candidate !== '');
|
|
144
136
|
function readInvoicingQboMappedAccountId(mappedAccount, legacyAccountId) {
|
|
145
|
-
//
|
|
146
|
-
//
|
|
147
|
-
|
|
137
|
+
// `qbo_id` first: the pickers key their options on the QuickBooks id, so an
|
|
138
|
+
// internal `account_id` would not select anything even when it is the same
|
|
139
|
+
// account. Both are read because the mapping arrives either way depending on
|
|
140
|
+
// how it was saved.
|
|
141
|
+
const candidates = [
|
|
148
142
|
mappedAccount?.qbo_id,
|
|
149
143
|
mappedAccount?.account_id,
|
|
150
144
|
legacyAccountId,
|
|
151
|
-
]
|
|
145
|
+
];
|
|
146
|
+
return candidates.find((candidate) => candidate != null && candidate !== '');
|
|
152
147
|
}
|
|
153
148
|
/**
|
|
154
149
|
* Read one account-mapping dropdown value by its config `code` (the codes in
|
|
@@ -174,41 +169,11 @@ export function getInvoicingQboAccountMappingId(accountMappings, code) {
|
|
|
174
169
|
* Return a copy of the account mappings with the dropdown slot named by
|
|
175
170
|
* `code` set to `accountId`. Unknown codes leave the mappings unchanged.
|
|
176
171
|
*/
|
|
177
|
-
/** The object key holding the mapped account for each `*_account_id` code. */
|
|
178
|
-
const INVOICING_QBO_MAPPED_ACCOUNT_KEY = {
|
|
179
|
-
default_income_account_id: 'default_income_account',
|
|
180
|
-
deposit_account_id: 'deposit_account',
|
|
181
|
-
discounts_account_id: 'discounts_account',
|
|
182
|
-
rounding_account_id: 'rounding_account',
|
|
183
|
-
write_off_account_id: 'write_off_account',
|
|
184
|
-
};
|
|
185
|
-
/**
|
|
186
|
-
* Expand each mapping from the id the picker submitted to the whole account, the
|
|
187
|
-
* shape the service stores. Written at the request boundary rather than in the
|
|
188
|
-
* page's draft so the UI keeps working in ids, and an id that no longer resolves
|
|
189
|
-
* is left out — a mapping the service cannot expand is worse than none.
|
|
190
|
-
*/
|
|
191
|
-
export const withInvoicingQboMappedAccounts = (accountMappings, accountByQboId) => {
|
|
192
|
-
if (accountMappings == null) {
|
|
193
|
-
return undefined;
|
|
194
|
-
}
|
|
195
|
-
const expanded = { ...accountMappings };
|
|
196
|
-
Object.entries(INVOICING_QBO_MAPPED_ACCOUNT_KEY).forEach(([code, objectKey]) => {
|
|
197
|
-
const accountId = getInvoicingQboAccountMappingId(accountMappings, code);
|
|
198
|
-
if (accountId == null) {
|
|
199
|
-
return;
|
|
200
|
-
}
|
|
201
|
-
const account = accountByQboId(accountId);
|
|
202
|
-
expanded[objectKey] =
|
|
203
|
-
account != null ? toAccountPayload(account) : undefined;
|
|
204
|
-
expanded[code] = undefined;
|
|
205
|
-
});
|
|
206
|
-
return expanded;
|
|
207
|
-
};
|
|
208
172
|
export function withInvoicingQboAccountMappingId(accountMappings, code, accountId) {
|
|
209
173
|
// Both slots are written together. Setting only the bare id would leave the
|
|
210
174
|
// object shape behind, and the reader prefers it — so the selection just made
|
|
211
|
-
// would read back as whatever was mapped before.
|
|
175
|
+
// would read back as whatever was mapped before. The object is dropped rather
|
|
176
|
+
// than rebuilt: only the id is known here, not the name that came with it.
|
|
212
177
|
const base = accountMappings ?? {};
|
|
213
178
|
switch (code) {
|
|
214
179
|
case 'deposit_account_id':
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { toAmount } from '../../../commonStateTypes/amount';
|
|
2
2
|
import { defaultCustomerCurrency } from '../../../commonStateTypes/currencyHelper';
|
|
3
3
|
import { date } from '../../../zeniDayJS';
|
|
4
|
-
import { firstSelectableInvoicingId } from '../invoicingCommonPayload';
|
|
5
4
|
// ── Payload → State mappers (snake_case wire shape → camelCase domain shape) ──
|
|
6
5
|
export const mapInvoicingPlanTierPayloadToState = (payload, currencyCode, currencySymbol) => ({
|
|
7
6
|
price: toAmount(payload.price, currencyCode, currencySymbol),
|
|
@@ -11,22 +10,11 @@ export const mapInvoicingPlanTierPayloadToState = (payload, currencyCode, curren
|
|
|
11
10
|
pricingType: payload.pricing_type,
|
|
12
11
|
});
|
|
13
12
|
const mapInvoicingAccountingDetailPayloadToState = (payload) => ({
|
|
14
|
-
|
|
15
|
-
// documents: the form's pickers are keyed on it, so reading the internal id
|
|
16
|
-
// would leave the field blank over a mapping that exists.
|
|
17
|
-
accountingCategory1: firstSelectableInvoicingId([
|
|
18
|
-
payload.accounting_class?.qbo_id,
|
|
19
|
-
payload.accounting_class?.accounting_class_id,
|
|
20
|
-
payload.accounting_category_1,
|
|
21
|
-
]),
|
|
13
|
+
accountingCategory1: payload.accounting_category_1,
|
|
22
14
|
accountingCategory2: payload.accounting_category_2,
|
|
23
15
|
accountingCategory3: payload.accounting_category_3,
|
|
24
16
|
accountingCategory4: payload.accounting_category_4,
|
|
25
|
-
accountingCode:
|
|
26
|
-
payload.account?.qbo_id,
|
|
27
|
-
payload.account?.account_id,
|
|
28
|
-
payload.accounting_code,
|
|
29
|
-
]),
|
|
17
|
+
accountingCode: payload.accounting_code,
|
|
30
18
|
sku: payload.sku,
|
|
31
19
|
});
|
|
32
20
|
export const mapInvoicingProductPayloadToState = (payload) => {
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import { toAccountPayload } from '../../../entity/account/accountPayload';
|
|
2
|
-
import { toClassBasePayload } from '../../../entity/class/classPayload';
|
|
3
1
|
import { blankInvoicingCatalogSubFamily, isTieredCatalogPricingModel, } from './invoicingCatalogItemFormConfig';
|
|
4
2
|
const CURRENCY_CODE = 'USD';
|
|
5
3
|
const trimOrUndefined = (value) => value.trim() !== '' ? value.trim() : undefined;
|
|
@@ -9,26 +7,20 @@ const toProductCode = (value) => value
|
|
|
9
7
|
.toLowerCase()
|
|
10
8
|
.replace(/[^a-z0-9]+/g, '-')
|
|
11
9
|
.replace(/^-|-$/g, '');
|
|
12
|
-
const buildAccountingDetail = (subFamily
|
|
10
|
+
const buildAccountingDetail = (subFamily) => {
|
|
13
11
|
const detail = {};
|
|
14
12
|
if (subFamily.sku.trim() !== '') {
|
|
15
13
|
detail.sku = subFamily.sku.trim();
|
|
16
14
|
}
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
// longer resolves is dropped: sending a code the service cannot expand is how
|
|
20
|
-
// a mapping silently lands on the wrong account.
|
|
21
|
-
const account = lookup.accountByQboId(subFamily.accountingCode.trim());
|
|
22
|
-
if (account != null) {
|
|
23
|
-
detail.account = toAccountPayload(account);
|
|
15
|
+
if (subFamily.accountingCode.trim() !== '') {
|
|
16
|
+
detail.accounting_code = subFamily.accountingCode.trim();
|
|
24
17
|
}
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
detail.accounting_class = toClassBasePayload(accountingClass);
|
|
18
|
+
if (subFamily.accountingCategory.trim() !== '') {
|
|
19
|
+
detail.accounting_category_1 = subFamily.accountingCategory.trim();
|
|
28
20
|
}
|
|
29
21
|
return Object.keys(detail).length > 0 ? detail : undefined;
|
|
30
22
|
};
|
|
31
|
-
const buildSubFamilyPayload = (localData, subFamily, clearEmptyValues
|
|
23
|
+
const buildSubFamilyPayload = (localData, subFamily, clearEmptyValues) => {
|
|
32
24
|
const isAddon = localData.catalogType === 'addon';
|
|
33
25
|
const tiered = isTieredCatalogPricingModel(subFamily.pricingModel);
|
|
34
26
|
const name = subFamily.name.trim();
|
|
@@ -82,7 +74,7 @@ const buildSubFamilyPayload = (localData, subFamily, clearEmptyValues, lookup) =
|
|
|
82
74
|
starting_unit: Number(tier.startingUnit) || 1,
|
|
83
75
|
}));
|
|
84
76
|
}
|
|
85
|
-
const accountingDetail = buildAccountingDetail(subFamily
|
|
77
|
+
const accountingDetail = buildAccountingDetail(subFamily);
|
|
86
78
|
if (accountingDetail != null) {
|
|
87
79
|
payload.accounting_detail = accountingDetail;
|
|
88
80
|
}
|
|
@@ -94,7 +86,7 @@ const DEFAULT_CATALOG_ITEM_UNIT = 'USD';
|
|
|
94
86
|
* Build the parent catalog-item request body from the form draft. Creates omit
|
|
95
87
|
* both parent and sub-family IDs; edits retain returned sub-family IDs.
|
|
96
88
|
*/
|
|
97
|
-
export const localDataToSaveInvoicingCatalogItemPayload = (localData, isCreate
|
|
89
|
+
export const localDataToSaveInvoicingCatalogItemPayload = (localData, isCreate) => {
|
|
98
90
|
const description = trimOrUndefined(localData.description);
|
|
99
91
|
const productCode = trimOrUndefined(localData.productCode) ?? toProductCode(localData.name);
|
|
100
92
|
const itemPayload = {
|
|
@@ -122,7 +114,7 @@ export const localDataToSaveInvoicingCatalogItemPayload = (localData, isCreate,
|
|
|
122
114
|
? localData.subFamilies
|
|
123
115
|
: [blankInvoicingCatalogSubFamily()];
|
|
124
116
|
itemPayload.sub_family_details = isCreate
|
|
125
|
-
? subFamilies.map((subFamily) => buildSubFamilyPayload(localData, subFamily, false
|
|
117
|
+
? subFamilies.map((subFamily) => buildSubFamilyPayload(localData, subFamily, false))
|
|
126
118
|
: subFamilies.map((subFamily) => {
|
|
127
119
|
const priceCode = trimOrUndefined(subFamily.priceCode) ?? toProductCode(subFamily.name);
|
|
128
120
|
const detail = {
|
|
@@ -132,13 +124,6 @@ export const localDataToSaveInvoicingCatalogItemPayload = (localData, isCreate,
|
|
|
132
124
|
price_code: priceCode,
|
|
133
125
|
show_description_in_invoices: subFamily.showDescriptionInInvoices,
|
|
134
126
|
};
|
|
135
|
-
// Edits send a narrower body than creates, but the accounting mapping
|
|
136
|
-
// is editable on this form, so leaving it out dropped the account and
|
|
137
|
-
// class the user had just picked.
|
|
138
|
-
const accountingDetail = buildAccountingDetail(subFamily, lookup);
|
|
139
|
-
if (accountingDetail != null) {
|
|
140
|
-
detail.accounting_detail = accountingDetail;
|
|
141
|
-
}
|
|
142
127
|
const id = trimOrUndefined(subFamily.id);
|
|
143
128
|
return id != null ? { ...detail, id } : detail;
|
|
144
129
|
});
|
package/lib/esm/view/invoicing/editInvoicingCatalogItemDetailView/saveInvoicingCatalogItemEpic.js
CHANGED
|
@@ -6,7 +6,6 @@ import { apiErrorSnackbarVariables } from '../../../entity/snackbar/snackbarApiE
|
|
|
6
6
|
import { openSnackbar } from '../../../entity/snackbar/snackbarReducer';
|
|
7
7
|
import { createZeniAPIStatus, isSuccessResponse } from '../../../responsePayload';
|
|
8
8
|
import { addInvoicingCatalogItem } from '../invoicingCatalogListView/invoicingCatalogListViewReducer';
|
|
9
|
-
import { invoicingQboAccountByQboId, invoicingQboClassByQboId, } from '../invoicingQboView/invoicingQboViewSelector';
|
|
10
9
|
import { localDataToSaveInvoicingCatalogItemPayload, } from './editInvoicingCatalogItemDetailViewPayload';
|
|
11
10
|
import { saveInvoicingCatalogItem, submitInvoicingCatalogItemForm, submitInvoicingCatalogItemFormFailure, submitInvoicingCatalogItemFormSuccess, } from './editInvoicingCatalogItemDetailViewReducer';
|
|
12
11
|
export const saveInvoicingCatalogItemEpic = (actions$, state$, zeniAPI) => actions$.pipe(filter((action) => submitInvoicingCatalogItemForm.match(action) ||
|
|
@@ -21,11 +20,7 @@ export const saveInvoicingCatalogItemEpic = (actions$, state$, zeniAPI) => actio
|
|
|
21
20
|
const viewState = state$.value.editInvoicingCatalogItemDetailViewState;
|
|
22
21
|
const localData = (id != null ? viewState.editDraftById[id] : viewState.newItemDraft) ??
|
|
23
22
|
viewState.newItemDraft;
|
|
24
|
-
|
|
25
|
-
data = localDataToSaveInvoicingCatalogItemPayload(localData, id == null, {
|
|
26
|
-
accountByQboId: (qboId) => invoicingQboAccountByQboId(state, qboId),
|
|
27
|
-
classByQboId: (qboId) => invoicingQboClassByQboId(state, qboId),
|
|
28
|
-
});
|
|
23
|
+
data = localDataToSaveInvoicingCatalogItemPayload(localData, id == null);
|
|
29
24
|
}
|
|
30
25
|
const baseUrl = `${zeniAPI.apiEndPoints.invoicingMicroServiceBaseUrl}/1.0`;
|
|
31
26
|
const path = id != null
|
|
@@ -37,26 +37,6 @@ export const INVOICING_INCOME_ACCOUNT_TYPES = [
|
|
|
37
37
|
'income',
|
|
38
38
|
'other_income',
|
|
39
39
|
];
|
|
40
|
-
/**
|
|
41
|
-
* The account behind a picker value. The pickers submit the QuickBooks id, so
|
|
42
|
-
* that is what callers hold; the payload builders need the whole entity to send
|
|
43
|
-
* `toAccountPayload`, which is why the lookup lives here next to the options.
|
|
44
|
-
*/
|
|
45
|
-
export const invoicingQboAccountByQboId = (state, qboId) => {
|
|
46
|
-
if (qboId == null || qboId === '') {
|
|
47
|
-
return undefined;
|
|
48
|
-
}
|
|
49
|
-
const { accounts } = getAccountList(state.accountState, state.accountListState, INVOICING_ACCOUNT_LIST_KEY);
|
|
50
|
-
return accounts.find((account) => String(account.qboId) === qboId);
|
|
51
|
-
};
|
|
52
|
-
/** The class behind a picker value, for the same reason as the account above. */
|
|
53
|
-
export const invoicingQboClassByQboId = (state, qboId) => {
|
|
54
|
-
if (qboId == null || qboId === '') {
|
|
55
|
-
return undefined;
|
|
56
|
-
}
|
|
57
|
-
const { classes } = getClassList(state.classState, state.classListState);
|
|
58
|
-
return classes.find((accountingClass) => String(accountingClass.qboId) === qboId);
|
|
59
|
-
};
|
|
60
40
|
/**
|
|
61
41
|
* Accounts and classes as the invoicing pickers need them. Both come from the
|
|
62
42
|
* shared accounting-service lists, so whatever another screen already loaded
|
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
import { from, of } from 'rxjs';
|
|
2
2
|
import { catchError, filter, mergeMap, switchMap } from 'rxjs/operators';
|
|
3
3
|
import { updateAddresses } from '../../../entity/address/addressReducer';
|
|
4
|
-
import { withInvoicingQboMappedAccounts, } from '../../../entity/invoicing/invoicingCommonPayload';
|
|
5
4
|
import { apiErrorSnackbarVariables } from '../../../entity/snackbar/snackbarApiError';
|
|
6
5
|
import { openSnackbar } from '../../../entity/snackbar/snackbarReducer';
|
|
7
6
|
import { createZeniAPIStatus, isSuccessResponse, } from '../../../responsePayload';
|
|
8
|
-
import { invoicingQboAccountByQboId } from '../invoicingQboView/invoicingQboViewSelector';
|
|
9
7
|
import { connectInvoicingStripe, disconnectInvoicingStripe, fetchInvoicingSettings, invoicingStripeConnectionFailure, saveInvoicingSettings, saveInvoicingSettingsFailure, saveInvoicingSettingsSuccess, updateInvoicingSettings, updateInvoicingSettingsFailure, updateInvoicingStripeConnection, } from './settingsViewReducer';
|
|
10
8
|
export const fetchInvoicingSettingsEpic = (actions$, _state$, zeniAPI) => actions$.pipe(filter(fetchInvoicingSettings.match), switchMap(() => {
|
|
11
9
|
const apiUrl = `${zeniAPI.apiEndPoints.invoicingMicroServiceBaseUrl}/1.0/settings`;
|
|
@@ -59,22 +57,9 @@ export const disconnectInvoicingStripeEpic = (actions$, _state$, zeniAPI) => act
|
|
|
59
57
|
}), catchError((error) => of(invoicingStripeConnectionFailure(createZeniAPIStatus('Unexpected Error', 'Stripe disconnect REST API call errored out ' +
|
|
60
58
|
JSON.stringify(error))))));
|
|
61
59
|
}));
|
|
62
|
-
export const saveInvoicingSettingsEpic = (actions$,
|
|
60
|
+
export const saveInvoicingSettingsEpic = (actions$, _state$, zeniAPI) => actions$.pipe(filter(saveInvoicingSettings.match), mergeMap((action) => {
|
|
63
61
|
const apiUrl = `${zeniAPI.apiEndPoints.invoicingMicroServiceBaseUrl}/1.0/settings`;
|
|
64
62
|
const { settings, snackbarSection } = action.payload;
|
|
65
|
-
// The QBO page edits mappings as picker ids; the service stores whole
|
|
66
|
-
// accounts. Expanded here, at the request boundary, so the page does not
|
|
67
|
-
// have to hold entities it only needs in order to save.
|
|
68
|
-
const qboSettings = settings.qbo;
|
|
69
|
-
const body = qboSettings?.account_mappings != null
|
|
70
|
-
? {
|
|
71
|
-
...settings,
|
|
72
|
-
qbo: {
|
|
73
|
-
...qboSettings,
|
|
74
|
-
account_mappings: withInvoicingQboMappedAccounts(qboSettings.account_mappings, (qboId) => invoicingQboAccountByQboId(state$.value, qboId)),
|
|
75
|
-
},
|
|
76
|
-
}
|
|
77
|
-
: settings;
|
|
78
63
|
/** `status` surfaces the platform's error text; omit it to keep the generic copy. */
|
|
79
64
|
const snackbar = (messageText, status) => snackbarSection == null
|
|
80
65
|
? []
|
|
@@ -87,7 +72,7 @@ export const saveInvoicingSettingsEpic = (actions$, state$, zeniAPI) => actions$
|
|
|
87
72
|
}),
|
|
88
73
|
];
|
|
89
74
|
return zeniAPI
|
|
90
|
-
.putAndGetJSON(apiUrl, { ...
|
|
75
|
+
.putAndGetJSON(apiUrl, { ...settings })
|
|
91
76
|
.pipe(switchMap((response) => {
|
|
92
77
|
if (isSuccessResponse(response) && response.data != null) {
|
|
93
78
|
return from([
|
|
@@ -1,20 +1,9 @@
|
|
|
1
|
-
import { AccountBase } from '../../../entity/account/accountState';
|
|
2
|
-
import { ClassBase } from '../../../entity/class/classState';
|
|
3
1
|
import { InvoicingPlanPayload } from '../../../entity/invoicing/plan/planPayload';
|
|
4
2
|
import { ZeniAPIResponse } from '../../../responsePayload';
|
|
5
3
|
import { InvoicingCatalogItemFormLocalData } from './editInvoicingCatalogItemDetailViewState';
|
|
6
4
|
export type SaveInvoicingCatalogItemResponse = ZeniAPIResponse<InvoicingPlanPayload>;
|
|
7
|
-
/**
|
|
8
|
-
* Resolves the QuickBooks ids the pickers submit back to the entities they name.
|
|
9
|
-
* The payload carries the whole account and class, so the ids alone are not
|
|
10
|
-
* enough; `saveInvoicingCatalogItemEpic` builds this from the shared lists.
|
|
11
|
-
*/
|
|
12
|
-
export interface InvoicingCatalogAccountingLookup {
|
|
13
|
-
accountByQboId: (qboId: string) => AccountBase | undefined;
|
|
14
|
-
classByQboId: (qboId: string) => ClassBase | undefined;
|
|
15
|
-
}
|
|
16
5
|
/**
|
|
17
6
|
* Build the parent catalog-item request body from the form draft. Creates omit
|
|
18
7
|
* both parent and sub-family IDs; edits retain returned sub-family IDs.
|
|
19
8
|
*/
|
|
20
|
-
export declare const localDataToSaveInvoicingCatalogItemPayload: (localData: InvoicingCatalogItemFormLocalData, isCreate: boolean
|
|
9
|
+
export declare const localDataToSaveInvoicingCatalogItemPayload: (localData: InvoicingCatalogItemFormLocalData, isCreate: boolean) => Record<string, unknown>;
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.localDataToSaveInvoicingCatalogItemPayload = void 0;
|
|
4
|
-
const accountPayload_1 = require("../../../entity/account/accountPayload");
|
|
5
|
-
const classPayload_1 = require("../../../entity/class/classPayload");
|
|
6
4
|
const invoicingCatalogItemFormConfig_1 = require("./invoicingCatalogItemFormConfig");
|
|
7
5
|
const CURRENCY_CODE = 'USD';
|
|
8
6
|
const trimOrUndefined = (value) => value.trim() !== '' ? value.trim() : undefined;
|
|
@@ -12,26 +10,20 @@ const toProductCode = (value) => value
|
|
|
12
10
|
.toLowerCase()
|
|
13
11
|
.replace(/[^a-z0-9]+/g, '-')
|
|
14
12
|
.replace(/^-|-$/g, '');
|
|
15
|
-
const buildAccountingDetail = (subFamily
|
|
13
|
+
const buildAccountingDetail = (subFamily) => {
|
|
16
14
|
const detail = {};
|
|
17
15
|
if (subFamily.sku.trim() !== '') {
|
|
18
16
|
detail.sku = subFamily.sku.trim();
|
|
19
17
|
}
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
// longer resolves is dropped: sending a code the service cannot expand is how
|
|
23
|
-
// a mapping silently lands on the wrong account.
|
|
24
|
-
const account = lookup.accountByQboId(subFamily.accountingCode.trim());
|
|
25
|
-
if (account != null) {
|
|
26
|
-
detail.account = (0, accountPayload_1.toAccountPayload)(account);
|
|
18
|
+
if (subFamily.accountingCode.trim() !== '') {
|
|
19
|
+
detail.accounting_code = subFamily.accountingCode.trim();
|
|
27
20
|
}
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
detail.accounting_class = (0, classPayload_1.toClassBasePayload)(accountingClass);
|
|
21
|
+
if (subFamily.accountingCategory.trim() !== '') {
|
|
22
|
+
detail.accounting_category_1 = subFamily.accountingCategory.trim();
|
|
31
23
|
}
|
|
32
24
|
return Object.keys(detail).length > 0 ? detail : undefined;
|
|
33
25
|
};
|
|
34
|
-
const buildSubFamilyPayload = (localData, subFamily, clearEmptyValues
|
|
26
|
+
const buildSubFamilyPayload = (localData, subFamily, clearEmptyValues) => {
|
|
35
27
|
const isAddon = localData.catalogType === 'addon';
|
|
36
28
|
const tiered = (0, invoicingCatalogItemFormConfig_1.isTieredCatalogPricingModel)(subFamily.pricingModel);
|
|
37
29
|
const name = subFamily.name.trim();
|
|
@@ -85,7 +77,7 @@ const buildSubFamilyPayload = (localData, subFamily, clearEmptyValues, lookup) =
|
|
|
85
77
|
starting_unit: Number(tier.startingUnit) || 1,
|
|
86
78
|
}));
|
|
87
79
|
}
|
|
88
|
-
const accountingDetail = buildAccountingDetail(subFamily
|
|
80
|
+
const accountingDetail = buildAccountingDetail(subFamily);
|
|
89
81
|
if (accountingDetail != null) {
|
|
90
82
|
payload.accounting_detail = accountingDetail;
|
|
91
83
|
}
|
|
@@ -97,7 +89,7 @@ const DEFAULT_CATALOG_ITEM_UNIT = 'USD';
|
|
|
97
89
|
* Build the parent catalog-item request body from the form draft. Creates omit
|
|
98
90
|
* both parent and sub-family IDs; edits retain returned sub-family IDs.
|
|
99
91
|
*/
|
|
100
|
-
const localDataToSaveInvoicingCatalogItemPayload = (localData, isCreate
|
|
92
|
+
const localDataToSaveInvoicingCatalogItemPayload = (localData, isCreate) => {
|
|
101
93
|
const description = trimOrUndefined(localData.description);
|
|
102
94
|
const productCode = trimOrUndefined(localData.productCode) ?? toProductCode(localData.name);
|
|
103
95
|
const itemPayload = {
|
|
@@ -125,7 +117,7 @@ const localDataToSaveInvoicingCatalogItemPayload = (localData, isCreate, lookup)
|
|
|
125
117
|
? localData.subFamilies
|
|
126
118
|
: [(0, invoicingCatalogItemFormConfig_1.blankInvoicingCatalogSubFamily)()];
|
|
127
119
|
itemPayload.sub_family_details = isCreate
|
|
128
|
-
? subFamilies.map((subFamily) => buildSubFamilyPayload(localData, subFamily, false
|
|
120
|
+
? subFamilies.map((subFamily) => buildSubFamilyPayload(localData, subFamily, false))
|
|
129
121
|
: subFamilies.map((subFamily) => {
|
|
130
122
|
const priceCode = trimOrUndefined(subFamily.priceCode) ?? toProductCode(subFamily.name);
|
|
131
123
|
const detail = {
|
|
@@ -135,13 +127,6 @@ const localDataToSaveInvoicingCatalogItemPayload = (localData, isCreate, lookup)
|
|
|
135
127
|
price_code: priceCode,
|
|
136
128
|
show_description_in_invoices: subFamily.showDescriptionInInvoices,
|
|
137
129
|
};
|
|
138
|
-
// Edits send a narrower body than creates, but the accounting mapping
|
|
139
|
-
// is editable on this form, so leaving it out dropped the account and
|
|
140
|
-
// class the user had just picked.
|
|
141
|
-
const accountingDetail = buildAccountingDetail(subFamily, lookup);
|
|
142
|
-
if (accountingDetail != null) {
|
|
143
|
-
detail.accounting_detail = accountingDetail;
|
|
144
|
-
}
|
|
145
130
|
const id = trimOrUndefined(subFamily.id);
|
|
146
131
|
return id != null ? { ...detail, id } : detail;
|
|
147
132
|
});
|
package/lib/view/invoicing/editInvoicingCatalogItemDetailView/saveInvoicingCatalogItemEpic.js
CHANGED
|
@@ -9,7 +9,6 @@ const snackbarApiError_1 = require("../../../entity/snackbar/snackbarApiError");
|
|
|
9
9
|
const snackbarReducer_1 = require("../../../entity/snackbar/snackbarReducer");
|
|
10
10
|
const responsePayload_1 = require("../../../responsePayload");
|
|
11
11
|
const invoicingCatalogListViewReducer_1 = require("../invoicingCatalogListView/invoicingCatalogListViewReducer");
|
|
12
|
-
const invoicingQboViewSelector_1 = require("../invoicingQboView/invoicingQboViewSelector");
|
|
13
12
|
const editInvoicingCatalogItemDetailViewPayload_1 = require("./editInvoicingCatalogItemDetailViewPayload");
|
|
14
13
|
const editInvoicingCatalogItemDetailViewReducer_1 = require("./editInvoicingCatalogItemDetailViewReducer");
|
|
15
14
|
const saveInvoicingCatalogItemEpic = (actions$, state$, zeniAPI) => actions$.pipe((0, operators_1.filter)((action) => editInvoicingCatalogItemDetailViewReducer_1.submitInvoicingCatalogItemForm.match(action) ||
|
|
@@ -24,11 +23,7 @@ const saveInvoicingCatalogItemEpic = (actions$, state$, zeniAPI) => actions$.pip
|
|
|
24
23
|
const viewState = state$.value.editInvoicingCatalogItemDetailViewState;
|
|
25
24
|
const localData = (id != null ? viewState.editDraftById[id] : viewState.newItemDraft) ??
|
|
26
25
|
viewState.newItemDraft;
|
|
27
|
-
|
|
28
|
-
data = (0, editInvoicingCatalogItemDetailViewPayload_1.localDataToSaveInvoicingCatalogItemPayload)(localData, id == null, {
|
|
29
|
-
accountByQboId: (qboId) => (0, invoicingQboViewSelector_1.invoicingQboAccountByQboId)(state, qboId),
|
|
30
|
-
classByQboId: (qboId) => (0, invoicingQboViewSelector_1.invoicingQboClassByQboId)(state, qboId),
|
|
31
|
-
});
|
|
26
|
+
data = (0, editInvoicingCatalogItemDetailViewPayload_1.localDataToSaveInvoicingCatalogItemPayload)(localData, id == null);
|
|
32
27
|
}
|
|
33
28
|
const baseUrl = `${zeniAPI.apiEndPoints.invoicingMicroServiceBaseUrl}/1.0`;
|
|
34
29
|
const path = id != null
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { NestedAccountHierarchyForReport } from '../../../commonStateTypes/accountView/nestedAccountID';
|
|
2
2
|
import { NestedClassHierarchyForReport } from '../../../commonStateTypes/classesView/nestedClassID';
|
|
3
3
|
import { FetchStateAndError } from '../../../commonStateTypes/common';
|
|
4
|
-
import {
|
|
5
|
-
import { ClassBase } from '../../../entity/class/classState';
|
|
4
|
+
import { AccountType } from '../../../entity/account/accountState';
|
|
6
5
|
import { RootState } from '../../../rootStateTypes';
|
|
7
6
|
import { InvoicingQboConnection, InvoicingQboSyncHealth } from './invoicingQboViewPayload';
|
|
8
7
|
export declare const INVOICING_ACCOUNT_LIST_KEY: "accountList";
|
|
@@ -21,14 +20,6 @@ export declare const getInvoicingQboConnectionFetchState: (state: RootState) =>
|
|
|
21
20
|
* "income accounts" rather than repeating the accounting service's vocabulary.
|
|
22
21
|
*/
|
|
23
22
|
export declare const INVOICING_INCOME_ACCOUNT_TYPES: readonly AccountType[];
|
|
24
|
-
/**
|
|
25
|
-
* The account behind a picker value. The pickers submit the QuickBooks id, so
|
|
26
|
-
* that is what callers hold; the payload builders need the whole entity to send
|
|
27
|
-
* `toAccountPayload`, which is why the lookup lives here next to the options.
|
|
28
|
-
*/
|
|
29
|
-
export declare const invoicingQboAccountByQboId: (state: RootState, qboId: string | undefined) => AccountBase | undefined;
|
|
30
|
-
/** The class behind a picker value, for the same reason as the account above. */
|
|
31
|
-
export declare const invoicingQboClassByQboId: (state: RootState, qboId: string | undefined) => ClassBase | undefined;
|
|
32
23
|
/** An account or class as the invoicing pickers render and submit it. */
|
|
33
24
|
export interface InvoicingAccountingOption {
|
|
34
25
|
id: string;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.getInvoicingQboView = exports.invoicingAccountHierarchyForTypes = exports.invoicingAccountsForQboAccountTypes = exports.
|
|
3
|
+
exports.getInvoicingQboView = exports.invoicingAccountHierarchyForTypes = exports.invoicingAccountsForQboAccountTypes = exports.INVOICING_INCOME_ACCOUNT_TYPES = exports.getInvoicingQboConnectionFetchState = exports.isInvoicingAccountingPickerDataLoading = exports.isInvoicingQboConnected = exports.INVOICING_ACCOUNT_LIST_KEY = void 0;
|
|
4
4
|
const accountListSelector_1 = require("../../accountList/accountListSelector");
|
|
5
5
|
const classListSelector_1 = require("../../classList/classListSelector");
|
|
6
6
|
// The shared bucket, fetched with the same arguments as the other consumers so
|
|
@@ -43,28 +43,6 @@ exports.INVOICING_INCOME_ACCOUNT_TYPES = [
|
|
|
43
43
|
'income',
|
|
44
44
|
'other_income',
|
|
45
45
|
];
|
|
46
|
-
/**
|
|
47
|
-
* The account behind a picker value. The pickers submit the QuickBooks id, so
|
|
48
|
-
* that is what callers hold; the payload builders need the whole entity to send
|
|
49
|
-
* `toAccountPayload`, which is why the lookup lives here next to the options.
|
|
50
|
-
*/
|
|
51
|
-
const invoicingQboAccountByQboId = (state, qboId) => {
|
|
52
|
-
if (qboId == null || qboId === '') {
|
|
53
|
-
return undefined;
|
|
54
|
-
}
|
|
55
|
-
const { accounts } = (0, accountListSelector_1.getAccountList)(state.accountState, state.accountListState, exports.INVOICING_ACCOUNT_LIST_KEY);
|
|
56
|
-
return accounts.find((account) => String(account.qboId) === qboId);
|
|
57
|
-
};
|
|
58
|
-
exports.invoicingQboAccountByQboId = invoicingQboAccountByQboId;
|
|
59
|
-
/** The class behind a picker value, for the same reason as the account above. */
|
|
60
|
-
const invoicingQboClassByQboId = (state, qboId) => {
|
|
61
|
-
if (qboId == null || qboId === '') {
|
|
62
|
-
return undefined;
|
|
63
|
-
}
|
|
64
|
-
const { classes } = (0, classListSelector_1.getClassList)(state.classState, state.classListState);
|
|
65
|
-
return classes.find((accountingClass) => String(accountingClass.qboId) === qboId);
|
|
66
|
-
};
|
|
67
|
-
exports.invoicingQboClassByQboId = invoicingQboClassByQboId;
|
|
68
46
|
/**
|
|
69
47
|
* Accounts and classes as the invoicing pickers need them. Both come from the
|
|
70
48
|
* shared accounting-service lists, so whatever another screen already loaded
|
|
@@ -9,4 +9,4 @@ export type ActionType = ReturnType<typeof fetchInvoicingSettings> | ReturnType<
|
|
|
9
9
|
export declare const fetchInvoicingSettingsEpic: (actions$: ActionsObservable<ActionType>, _state$: StateObservable<RootState>, zeniAPI: ZeniAPI) => Observable<ActionType>;
|
|
10
10
|
export declare const connectInvoicingStripeEpic: (actions$: ActionsObservable<ActionType>, _state$: StateObservable<RootState>, zeniAPI: ZeniAPI) => Observable<ActionType>;
|
|
11
11
|
export declare const disconnectInvoicingStripeEpic: (actions$: ActionsObservable<ActionType>, _state$: StateObservable<RootState>, zeniAPI: ZeniAPI) => Observable<ActionType>;
|
|
12
|
-
export declare const saveInvoicingSettingsEpic: (actions$: ActionsObservable<ActionType>,
|
|
12
|
+
export declare const saveInvoicingSettingsEpic: (actions$: ActionsObservable<ActionType>, _state$: StateObservable<RootState>, zeniAPI: ZeniAPI) => Observable<ActionType>;
|
|
@@ -4,11 +4,9 @@ exports.saveInvoicingSettingsEpic = exports.disconnectInvoicingStripeEpic = expo
|
|
|
4
4
|
const rxjs_1 = require("rxjs");
|
|
5
5
|
const operators_1 = require("rxjs/operators");
|
|
6
6
|
const addressReducer_1 = require("../../../entity/address/addressReducer");
|
|
7
|
-
const invoicingCommonPayload_1 = require("../../../entity/invoicing/invoicingCommonPayload");
|
|
8
7
|
const snackbarApiError_1 = require("../../../entity/snackbar/snackbarApiError");
|
|
9
8
|
const snackbarReducer_1 = require("../../../entity/snackbar/snackbarReducer");
|
|
10
9
|
const responsePayload_1 = require("../../../responsePayload");
|
|
11
|
-
const invoicingQboViewSelector_1 = require("../invoicingQboView/invoicingQboViewSelector");
|
|
12
10
|
const settingsViewReducer_1 = require("./settingsViewReducer");
|
|
13
11
|
const fetchInvoicingSettingsEpic = (actions$, _state$, zeniAPI) => actions$.pipe((0, operators_1.filter)(settingsViewReducer_1.fetchInvoicingSettings.match), (0, operators_1.switchMap)(() => {
|
|
14
12
|
const apiUrl = `${zeniAPI.apiEndPoints.invoicingMicroServiceBaseUrl}/1.0/settings`;
|
|
@@ -65,22 +63,9 @@ const disconnectInvoicingStripeEpic = (actions$, _state$, zeniAPI) => actions$.p
|
|
|
65
63
|
JSON.stringify(error))))));
|
|
66
64
|
}));
|
|
67
65
|
exports.disconnectInvoicingStripeEpic = disconnectInvoicingStripeEpic;
|
|
68
|
-
const saveInvoicingSettingsEpic = (actions$,
|
|
66
|
+
const saveInvoicingSettingsEpic = (actions$, _state$, zeniAPI) => actions$.pipe((0, operators_1.filter)(settingsViewReducer_1.saveInvoicingSettings.match), (0, operators_1.mergeMap)((action) => {
|
|
69
67
|
const apiUrl = `${zeniAPI.apiEndPoints.invoicingMicroServiceBaseUrl}/1.0/settings`;
|
|
70
68
|
const { settings, snackbarSection } = action.payload;
|
|
71
|
-
// The QBO page edits mappings as picker ids; the service stores whole
|
|
72
|
-
// accounts. Expanded here, at the request boundary, so the page does not
|
|
73
|
-
// have to hold entities it only needs in order to save.
|
|
74
|
-
const qboSettings = settings.qbo;
|
|
75
|
-
const body = qboSettings?.account_mappings != null
|
|
76
|
-
? {
|
|
77
|
-
...settings,
|
|
78
|
-
qbo: {
|
|
79
|
-
...qboSettings,
|
|
80
|
-
account_mappings: (0, invoicingCommonPayload_1.withInvoicingQboMappedAccounts)(qboSettings.account_mappings, (qboId) => (0, invoicingQboViewSelector_1.invoicingQboAccountByQboId)(state$.value, qboId)),
|
|
81
|
-
},
|
|
82
|
-
}
|
|
83
|
-
: settings;
|
|
84
69
|
/** `status` surfaces the platform's error text; omit it to keep the generic copy. */
|
|
85
70
|
const snackbar = (messageText, status) => snackbarSection == null
|
|
86
71
|
? []
|
|
@@ -93,7 +78,7 @@ const saveInvoicingSettingsEpic = (actions$, state$, zeniAPI) => actions$.pipe((
|
|
|
93
78
|
}),
|
|
94
79
|
];
|
|
95
80
|
return zeniAPI
|
|
96
|
-
.putAndGetJSON(apiUrl, { ...
|
|
81
|
+
.putAndGetJSON(apiUrl, { ...settings })
|
|
97
82
|
.pipe((0, operators_1.switchMap)((response) => {
|
|
98
83
|
if ((0, responsePayload_1.isSuccessResponse)(response) && response.data != null) {
|
|
99
84
|
return (0, rxjs_1.from)([
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zeniai/client-epic-state",
|
|
3
|
-
"version": "5.2.10
|
|
3
|
+
"version": "5.2.10",
|
|
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",
|