@leaddreamer/inventorylogic 0.0.3-beta.29 → 0.0.3-beta.30

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/README.md CHANGED
@@ -19,6 +19,10 @@ services.</p>
19
19
  <dd><p>A collection of Business logic and database functions. Shared between ReactJS
20
20
  frontEnd and NodeJS BackEnd</p>
21
21
  </dd>
22
+ <dt><a href="#module_BusinessData">BusinessData</a></dt>
23
+ <dd><p>Functions for managing (potentially)private data for an organization.
24
+ Unified structure as a sub-record of organization, or CityManager accounts</p>
25
+ </dd>
22
26
  <dt><a href="#module_Commodities">Commodities</a></dt>
23
27
  <dd><p>Typedefs, constants, support functions and database operations related to Commodity Matrials
24
28
  users</p>
@@ -178,6 +182,208 @@ called from a cloud environment
178
182
  | measurementId: | <code>string</code> | (optional) Analytics/Measurement ID from Firebase Console |
179
183
  | mapsAPIKey | <code>string</code> | (optional) App ID for Google Maps API, from Google |
180
184
 
185
+ <a name="module_BusinessData"></a>
186
+
187
+ ## BusinessData
188
+ Functions for managing (potentially)private data for an organization.
189
+ Unified structure as a sub-record of organization, or CityManager accounts
190
+
191
+
192
+ * [BusinessData](#module_BusinessData)
193
+ * _static_
194
+ * [.fetchFullAccount(account)](#module_BusinessData.fetchFullAccount) ⇒ <code>Promise.AccountType</code>
195
+ * [.fetchBusinessData(account)](#module_BusinessData.fetchBusinessData) ⇒ <code>Promise.BusinessData</code>
196
+ * [.accountPage(account, origin)](#module_BusinessData.accountPage) ⇒ <code>string</code>
197
+ * [.createBusinessData(account, batch)](#module_BusinessData.createBusinessData) ⇒ <code>Promise.&lt;ChainType&gt;</code>
198
+ * [.saveBusinessData(businessData)](#module_BusinessData.saveBusinessData) ⇒ <code>Promise.&lt;BusinessData&gt;</code>
199
+ * [.deleteBusinessData(businessData)](#module_BusinessData.deleteBusinessData) ⇒ <code>Promise.&lt;void&gt;</code>
200
+ * [.businessDataPath(account)](#module_BusinessData.businessDataPath) ⇒ <code>string</code>
201
+ * [.profileComplete(account, businessData)](#module_BusinessData.profileComplete) ⇒ <code>Boolean</code>
202
+ * [.profileIncomplete(account, businessData)](#module_BusinessData.profileIncomplete) ⇒ <code>string</code> \| <code>null</code>
203
+ * [.setOpenIssues(businessData)](#module_BusinessData.setOpenIssues) ⇒ <code>Promise.boolean</code>
204
+ * [.clearOpenIssues(businessData)](#module_BusinessData.clearOpenIssues) ⇒ <code>Promise.boolean</code>
205
+ * _inner_
206
+ * [~BusinessDefault](#module_BusinessData..BusinessDefault) : <code>BusinessData</code>
207
+ * [~BusinessAccountForm](#module_BusinessData..BusinessAccountForm) : <code>BusinessData</code>
208
+ * [~contact](#module_BusinessData..contact) : <code>object</code>
209
+ * [~BusinessData](#module_BusinessData..BusinessData) : <code>object</code>
210
+ * [~ChainType](#module_BusinessData..ChainType) : <code>WriteBatch</code> \| <code>Transaction</code> \| <code>void</code>
211
+
212
+ <a name="module_BusinessData.fetchFullAccount"></a>
213
+
214
+ ### BusinessData.fetchFullAccount(account) ⇒ <code>Promise.AccountType</code>
215
+ Fetches a fulll object representation of an account, including BusinessData
216
+
217
+ **Kind**: static method of [<code>BusinessData</code>](#module_BusinessData)
218
+
219
+ | Param | Type |
220
+ | --- | --- |
221
+ | account | <code>AccountType</code> |
222
+
223
+ <a name="module_BusinessData.fetchBusinessData"></a>
224
+
225
+ ### BusinessData.fetchBusinessData(account) ⇒ <code>Promise.BusinessData</code>
226
+ Fetches the BusinessData (corporate, addresses, etc) for an account
227
+
228
+ **Kind**: static method of [<code>BusinessData</code>](#module_BusinessData)
229
+
230
+ | Param | Type |
231
+ | --- | --- |
232
+ | account | <code>AccountType</code> |
233
+
234
+ <a name="module_BusinessData.accountPage"></a>
235
+
236
+ ### BusinessData.accountPage(account, origin) ⇒ <code>string</code>
237
+ Composes a URL for an "account page" from the account, and passed base URL
238
+
239
+ **Kind**: static method of [<code>BusinessData</code>](#module_BusinessData)
240
+ **Returns**: <code>string</code> - full URL for business accouont
241
+
242
+ | Param | Type | Description |
243
+ | --- | --- | --- |
244
+ | account | <code>AccountType</code> | |
245
+ | origin | <code>string</code> | base URL for the application |
246
+
247
+ <a name="module_BusinessData.createBusinessData"></a>
248
+
249
+ ### BusinessData.createBusinessData(account, batch) ⇒ <code>Promise.&lt;ChainType&gt;</code>
250
+ **Kind**: static method of [<code>BusinessData</code>](#module_BusinessData)
251
+ **Returns**: <code>Promise.&lt;ChainType&gt;</code> - WriteBatch, Transaction or Void
252
+
253
+ | Param | Type | Description |
254
+ | --- | --- | --- |
255
+ | account | <code>AccountType</code> | |
256
+ | batch | <code>ChainType</code> | batching object. Transaction will be added to the batch |
257
+
258
+ <a name="module_BusinessData.saveBusinessData"></a>
259
+
260
+ ### BusinessData.saveBusinessData(businessData) ⇒ <code>Promise.&lt;BusinessData&gt;</code>
261
+ Writes the "Business" data to the database
262
+
263
+ **Kind**: static method of [<code>BusinessData</code>](#module_BusinessData)
264
+
265
+ | Param | Type |
266
+ | --- | --- |
267
+ | businessData | <code>BusinessData</code> |
268
+
269
+ <a name="module_BusinessData.deleteBusinessData"></a>
270
+
271
+ ### BusinessData.deleteBusinessData(businessData) ⇒ <code>Promise.&lt;void&gt;</code>
272
+ Deletes a BusinessData record (rarely used if ever)
273
+
274
+ **Kind**: static method of [<code>BusinessData</code>](#module_BusinessData)
275
+
276
+ | Param | Type |
277
+ | --- | --- |
278
+ | businessData | <code>BusinessData</code> |
279
+ | businessData.refPath | <code>string</code> |
280
+
281
+ <a name="module_BusinessData.businessDataPath"></a>
282
+
283
+ ### BusinessData.businessDataPath(account) ⇒ <code>string</code>
284
+ creates the "base path" (refPath) to store addresses based on an account (refPath)
285
+
286
+ **Kind**: static method of [<code>BusinessData</code>](#module_BusinessData)
287
+
288
+ | Param | Type |
289
+ | --- | --- |
290
+ | account | <code>Record</code> |
291
+ | account.refPath | <code>string</code> |
292
+
293
+ <a name="module_BusinessData.profileComplete"></a>
294
+
295
+ ### BusinessData.profileComplete(account, businessData) ⇒ <code>Boolean</code>
296
+ verifies that all needed information has been filled in
297
+
298
+ **Kind**: static method of [<code>BusinessData</code>](#module_BusinessData)
299
+
300
+ | Param | Type | Description |
301
+ | --- | --- | --- |
302
+ | account | <code>AccountType</code> | |
303
+ | businessData | <code>BusinessData</code> | record |
304
+
305
+ <a name="module_BusinessData.profileIncomplete"></a>
306
+
307
+ ### BusinessData.profileIncomplete(account, businessData) ⇒ <code>string</code> \| <code>null</code>
308
+ verifies that all needed information has been filled in
309
+
310
+ **Kind**: static method of [<code>BusinessData</code>](#module_BusinessData)
311
+
312
+ | Param | Type | Description |
313
+ | --- | --- | --- |
314
+ | account | <code>AccountType</code> | |
315
+ | businessData | <code>BusinessData</code> | record |
316
+
317
+ <a name="module_BusinessData.setOpenIssues"></a>
318
+
319
+ ### BusinessData.setOpenIssues(businessData) ⇒ <code>Promise.boolean</code>
320
+ Sets the "openIssues" flag in an account's BUSINESSDATA record
321
+ The account's refPath is attached to the Payment system's record, and
322
+ used here to find the Payment Account
323
+
324
+ **Kind**: static method of [<code>BusinessData</code>](#module_BusinessData)
325
+
326
+ | Param | Type |
327
+ | --- | --- |
328
+ | businessData | <code>BusinessData</code> |
329
+
330
+ <a name="module_BusinessData.clearOpenIssues"></a>
331
+
332
+ ### BusinessData.clearOpenIssues(businessData) ⇒ <code>Promise.boolean</code>
333
+ Clears the "openIssues" flag in an account's BUSINESSDATA record
334
+ The account's refPath is attached to the Payment system's record, and
335
+ used here to find the Payment Account
336
+
337
+ **Kind**: static method of [<code>BusinessData</code>](#module_BusinessData)
338
+
339
+ | Param | Type |
340
+ | --- | --- |
341
+ | businessData | <code>BusinessData</code> |
342
+
343
+ <a name="module_BusinessData..BusinessDefault"></a>
344
+
345
+ ### BusinessData~BusinessDefault : <code>BusinessData</code>
346
+ **Kind**: inner constant of [<code>BusinessData</code>](#module_BusinessData)
347
+ **Default**: <code>{&quot;Id&quot;:null,&quot;email&quot;:null,&quot;business_type&quot;:null,&quot;contact&quot;:null,&quot;business_address&quot;:null,&quot;mailing_address&quot;:null,&quot;billing_address&quot;:null,&quot;tel&quot;:null,&quot;mcc&quot;:null,&quot;tax_rate&quot;:null,&quot;openIssues&quot;:false}</code>
348
+ <a name="module_BusinessData..BusinessAccountForm"></a>
349
+
350
+ ### BusinessData~BusinessAccountForm : <code>BusinessData</code>
351
+ **Kind**: inner constant of [<code>BusinessData</code>](#module_BusinessData)
352
+ **Default**: <code>{&quot;refPath&quot;:&quot;hidden:text&quot;,&quot;email&quot;:&quot;email&quot;,&quot;business_type&quot;:&quot;&quot;,&quot;contact&quot;:&quot;&quot;,&quot;business_address&quot;:&quot;&quot;,&quot;mailing_address&quot;:&quot;&quot;,&quot;billing_address&quot;:&quot;&quot;,&quot;tel&quot;:&quot;tel&quot;,&quot;mcc&quot;:&quot;&quot;}</code>
353
+ <a name="module_BusinessData..contact"></a>
354
+
355
+ ### BusinessData~contact : <code>object</code>
356
+ **Kind**: inner typedef of [<code>BusinessData</code>](#module_BusinessData)
357
+ **Properties**
358
+
359
+ | Name | Type | Description |
360
+ | --- | --- | --- |
361
+ | contact.Id | <code>string</code> | |
362
+ | contact.first_name | <code>string</code> | |
363
+ | contact.last_name | <code>string</code> | |
364
+ | contact.tel | <code>string</code> | |
365
+ | contact.email | <code>string</code> | must be filled in to make profile public |
366
+
367
+ <a name="module_BusinessData..BusinessData"></a>
368
+
369
+ ### BusinessData~BusinessData : <code>object</code>
370
+ **Kind**: inner typedef of [<code>BusinessData</code>](#module_BusinessData)
371
+ **Properties**
372
+
373
+ | Name | Type | Description |
374
+ | --- | --- | --- |
375
+ | email | <code>string</code> | must be filled in to make profile public |
376
+ | contact | <code>contact</code> | |
377
+ | tel | <code>string</code> | |
378
+ | business_type | <code>string</code> | |
379
+ | business_address | <code>AddressType</code> | |
380
+ | mailing_address | <code>AddressType</code> | |
381
+ | billing_address | <code>AddressType</code> | |
382
+
383
+ <a name="module_BusinessData..ChainType"></a>
384
+
385
+ ### BusinessData~ChainType : <code>WriteBatch</code> \| <code>Transaction</code> \| <code>void</code>
386
+ **Kind**: inner typedef of [<code>BusinessData</code>](#module_BusinessData)
181
387
  <a name="module_Commodities"></a>
182
388
 
183
389
  ## Commodities
@@ -0,0 +1,301 @@
1
+ /**
2
+ * Functions for managing (potentially)private data for an organization.
3
+ * Unified structure as a sub-record of organization, or CityManager accounts
4
+ * @module BusinessData
5
+ */
6
+ import {
7
+ fetchRecord,
8
+ writeRecord,
9
+ typedWrite,
10
+ writeBack,
11
+ deleteRecordByRefPath,
12
+ } from "@leaddreamer/firebase-wrapper";
13
+ import {
14
+ BUSINESS,
15
+ BUSINESSDATA,
16
+ BUSINESS_TYPE,
17
+ ADDRESSES,
18
+ PERSON,
19
+ MCC,
20
+ } from "../boilerplate";
21
+ import { Forms, fillForm } from "../../formModule";
22
+ import { fetchAddresses } from "../Addresses";
23
+
24
+ //////////////////////////////////////////////////////////////////////
25
+ // definitions
26
+
27
+ /**
28
+ * @external AddressType
29
+ */
30
+ /**
31
+ * @typedef {object} contact
32
+ * @property {?string} contact.Id
33
+ * @property {!string} contact.first_name
34
+ * @property {!string} contact.last_name
35
+ * @property {!string} contact.tel
36
+ * @property {?string} contact.email - must be filled in to make profile public
37
+ */
38
+ /**
39
+ * @typedef {object} BusinessData
40
+ * @property {?string} email - must be filled in to make profile public
41
+ * @property {contact} contact
42
+ * @property {!string} tel
43
+ * @property {string} business_type
44
+ * @property {AddressType} business_address
45
+ * @property {AddressType} mailing_address
46
+ * @property {AddressType} billing_address
47
+ */
48
+ /**
49
+ * @constant
50
+ * @type {BusinessData}
51
+ * @default
52
+ */
53
+ const BusinessDefault = {
54
+ Id: null,
55
+ email: null,
56
+ business_type: null,
57
+ contact: null,
58
+ business_address: null,
59
+ mailing_address: null,
60
+ billing_address: null,
61
+ tel: null,
62
+ mcc: null,
63
+ tax_rate: null,
64
+ //tax_id: null,
65
+ openIssues: false,
66
+ };
67
+
68
+ /**
69
+ * @constant
70
+ * @type {BusinessData}
71
+ * @default
72
+ */
73
+ const BusinessAccountForm = {
74
+ refPath: "hidden:text",
75
+ email: "email",
76
+ business_type: `lookup:${BUSINESS_TYPE}`,
77
+ contact: `object:${PERSON}`,
78
+ business_address: `lookupLink:${ADDRESSES}`,
79
+ mailing_address: `lookupLink:${ADDRESSES}`,
80
+ billing_address: `lookupLink:${ADDRESSES}`,
81
+ tel: "tel",
82
+ mcc: `lookup:${MCC}`,
83
+ };
84
+
85
+ Forms.Base[BUSINESSDATA] = BusinessDefault;
86
+ Forms.BaseForm[BUSINESSDATA] = BusinessAccountForm;
87
+ Forms.AccountForm[BUSINESSDATA] = BusinessAccountForm;
88
+
89
+ //////////////////////////////////////////////////////////////////////
90
+ // Utilities
91
+
92
+ /**
93
+ * Fetches a fulll object representation of an account, including BusinessData
94
+ * @param {AccountType} account
95
+ * @returns {Promise.AccountType}
96
+ */
97
+ export async function fetchFullAccount(account) {
98
+ const BusinessData = await fetchBusinessData(account);
99
+
100
+ account.business = BusinessData;
101
+
102
+ return account;
103
+ }
104
+
105
+ /**
106
+ * Fetches the BusinessData (corporate, addresses, etc) for an account
107
+ * @param {AccountType} account
108
+ * @returns {Promise.BusinessData}
109
+ */
110
+ export async function fetchBusinessData(account) {
111
+ let addresses = [];
112
+ try {
113
+ addresses = await fetchAddresses(account);
114
+ } catch (err) {}
115
+ const addressMap = new Map();
116
+ if (addresses.length) {
117
+ addresses.forEach((address) => {
118
+ addressMap.set(address.Id, address);
119
+ });
120
+ }
121
+
122
+ const BusinessData = await fetchRecord(
123
+ BUSINESSDATA,
124
+ account.Id,
125
+ account.refPath,
126
+ );
127
+
128
+ let addressEntries = {};
129
+ ["business_address", "billing_address", "mailing_address"].forEach(
130
+ (entry) => {
131
+ const isLink =
132
+ entry && BusinessData[entry] && !BusinessData[entry]?.address_line_1;
133
+ if (isLink) {
134
+ addressEntries[entry] = {
135
+ ...addressMap.get(BusinessData[entry]),
136
+ };
137
+ }
138
+ },
139
+ ); //hacky way to repeat same effort
140
+
141
+ return {
142
+ ...BusinessData,
143
+ ...addressEntries,
144
+ };
145
+ }
146
+
147
+ /**
148
+ * Composes a URL for an "account page" from the account, and passed base URL
149
+ * @param {!AccountType} account
150
+ * @param {!string} origin base URL for the application
151
+ * @returns {string} full URL for business accouont
152
+ */
153
+ export function accountPage(account, origin) {
154
+ return `${origin}/${BUSINESS}/Account`; //Leads to LOGGED IN organization account page
155
+ }
156
+
157
+ /**
158
+ * @external WriteBatch
159
+ * @typedef {WriteBatch|Transaction|void} ChainType
160
+ */
161
+
162
+ /**
163
+ * @async
164
+ * @function
165
+ * @static
166
+ * Creates the Business information document
167
+ * @param {AccountType} account
168
+ * @param {?ChainType} batch - batching object. Transaction will be added to the batch
169
+ * @returns {Promise<ChainType>} WriteBatch, Transaction or Void
170
+ */
171
+ export async function createBusinessData(account, batch = null) {
172
+ return typedWrite(
173
+ {
174
+ ...Forms.Base[BUSINESSDATA], //base fields with defaults
175
+ ...fillForm(account, BUSINESSDATA), //sanitize passed data
176
+ }, //data
177
+ account, //parent
178
+ BUSINESSDATA, //type
179
+ batch,
180
+ );
181
+ }
182
+
183
+ /**
184
+ * Writes the "Business" data to the database
185
+ * @param {BusinessData} businessData
186
+ * @returns {Promise<BusinessData>}
187
+ */
188
+ export async function saveBusinessData(businessData, batch = null) {
189
+ return writeBack(businessData, batch);
190
+ }
191
+
192
+ /**
193
+ * Deletes a BusinessData record (rarely used if ever)
194
+ * @param {BusinessData} businessData
195
+ * @param {!string} businessData.refPath
196
+ * @returns {Promise<void>}
197
+ */
198
+ export async function deleteBusinessData(businessData, batch = null) {
199
+ return deleteRecordByRefPath(businessData.refPath, batch);
200
+ }
201
+
202
+ /**
203
+ * creates the "base path" (refPath) to store addresses based on an account (refPath)
204
+ * @param {Record} account
205
+ * @param {!string} account.refPath
206
+ * @returns {string}
207
+ */
208
+ export function businessDataPath(account) {
209
+ return `${account.refPath}/${BUSINESSDATA}/${account.Id}`;
210
+ }
211
+
212
+ /**
213
+ * verifies that all needed information has been filled in
214
+ * @param {AccountType} account
215
+ * @param {BusinessData} businessData record
216
+ * @returns {Boolean}
217
+ */
218
+ export function profileComplete(account, businessData) {
219
+ if (!businessData?.business_address) return false;
220
+ if (!businessData?.billing_address) return false;
221
+ if (!businessData?.mailing_address) return false;
222
+ if (!businessData?.email) return false;
223
+ if (!businessData?.tel) return false;
224
+ if (!account?.website) return false;
225
+ if (!(account?.name || account?.corporate)) return false;
226
+ return true;
227
+ }
228
+
229
+ /**
230
+ * verifies that all needed information has been filled in
231
+ * @param {AccountType} account
232
+ * @param {BusinessData} businessData record
233
+ * @returns {string|null}
234
+ */
235
+ export function profileIncomplete(account, businessData) {
236
+ let problem_string = "";
237
+ if (!businessData?.business_address) {
238
+ problem_string = problem_string.concat(`=> Business Address Missing\n`);
239
+ }
240
+ if (!businessData?.billing_address) {
241
+ problem_string = problem_string.concat(`=> Billing Address Missing\n`);
242
+ }
243
+ if (!businessData?.mailing_address) {
244
+ problem_string = problem_string.concat(`=> Mailing Address Missing\n`);
245
+ }
246
+ if (!businessData?.email) {
247
+ problem_string = problem_string.concat(`=> Business Email Missing\n`);
248
+ }
249
+ if (!businessData?.tel) {
250
+ problem_string = problem_string.concat(`=> Business Telephone Missing\n`);
251
+ }
252
+ if (!account?.website) {
253
+ problem_string = problem_string.concat(`=> Business Website Missing\n`);
254
+ }
255
+ if (!(account?.name || account?.corporate)) {
256
+ problem_string = problem_string.concat(
257
+ `=> Business and/or Corporate Name Missing\n`,
258
+ );
259
+ }
260
+ return problem_string.length ? problem_string : null;
261
+ }
262
+
263
+ /**
264
+ * Sets the "openIssues" flag in an account's BUSINESSDATA record
265
+ * The account's refPath is attached to the Payment system's record, and
266
+ * used here to find the Payment Account
267
+ * @param {BusinessData} businessData
268
+ * @returns {Promise.boolean}
269
+ */
270
+ export async function setOpenIssues(businessData) {
271
+ return writeRecord(
272
+ BUSINESSDATA,
273
+ {
274
+ ...businessData,
275
+ openIssues: true,
276
+ },
277
+ businessData.refPath,
278
+ null,
279
+ true,
280
+ );
281
+ }
282
+
283
+ /**
284
+ * Clears the "openIssues" flag in an account's BUSINESSDATA record
285
+ * The account's refPath is attached to the Payment system's record, and
286
+ * used here to find the Payment Account
287
+ * @param {BusinessData} businessData
288
+ * @returns {Promise.boolean}
289
+ */
290
+ export async function clearOpenIssues(businessData) {
291
+ return writeRecord(
292
+ BUSINESSDATA,
293
+ {
294
+ ...businessData,
295
+ openIssues: false,
296
+ },
297
+ businessData.refPath,
298
+ null,
299
+ true,
300
+ );
301
+ }
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "engines": {
4
4
  "node": ">=22"
5
5
  },
6
- "version": "0.0.3-beta.29",
6
+ "version": "0.0.3-beta.30",
7
7
  "description": "Business & Database Logic for Inventory Services",
8
8
  "repository": {
9
9
  "type": "git",