@leaddreamer/inventorylogic 0.0.3-beta.0
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/LICENSE +21 -0
- package/README.hbs +13 -0
- package/README.md +1948 -0
- package/business/Commodities/index.js +240 -0
- package/business/LineItem/index.js +328 -0
- package/business/Markups/index.js +183 -0
- package/business/Payment/index.js +516 -0
- package/business/Product/index.js +142 -0
- package/business/User/index.js +372 -0
- package/business/Utilities/index.js +336 -0
- package/business/boilerplate/index.js +55 -0
- package/business/index.js +14 -0
- package/business/units/index.js +94 -0
- package/index.js +61 -0
- package/package.json +72 -0
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Typedefs, constants, support functions and database operations related to product creation stages
|
|
3
|
+
* users
|
|
4
|
+
* @module Markups
|
|
5
|
+
*/
|
|
6
|
+
import { updateRecord } from "@leaddreamer/firebase-wrapper";
|
|
7
|
+
import { Forms, fillForm } from "@leaddreamer/staticforms";
|
|
8
|
+
|
|
9
|
+
import { MARKUPS, STAGE, FABRICATION, WHOLESALE, RETAIL, BASE, HIGHVALUE, SERVICE, MATERIAL } from "../boilerplate";
|
|
10
|
+
|
|
11
|
+
//////////////////////////////////////////////////////////////////////
|
|
12
|
+
// Constants
|
|
13
|
+
/**
|
|
14
|
+
* Database Structure
|
|
15
|
+
* Product or User or Fundamentals (document)
|
|
16
|
+
* \-> Markups (collection)
|
|
17
|
+
* \-> [ParentId] (sole document)
|
|
18
|
+
* \-> [Stage Name(s)] (field, object)
|
|
19
|
+
* \-> [Material Name(s)] (field, value [Markup])
|
|
20
|
+
*/
|
|
21
|
+
/**
|
|
22
|
+
* @typedef {number} Markup
|
|
23
|
+
* @typedef {"base"|"highValue"|"service"} MaterialLevels
|
|
24
|
+
* @typedef {"fabrication"|"wholesale"|"retail"} StageLevels
|
|
25
|
+
* @typedef {Object.<MaterialLevels, Markup>} Material
|
|
26
|
+
* @typedef {Object.<StageLevels, Material>} Markups
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* @readonly
|
|
31
|
+
* @constant
|
|
32
|
+
* @type {Material}
|
|
33
|
+
* @default
|
|
34
|
+
*/
|
|
35
|
+
const MaterialDefault = {
|
|
36
|
+
[BASE]: 1.0,
|
|
37
|
+
[HIGHVALUE]: 1.0,
|
|
38
|
+
[SERVICE]: 1.0,
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* @readonly
|
|
43
|
+
* @constant
|
|
44
|
+
* @type {Markups}
|
|
45
|
+
* @default
|
|
46
|
+
*/
|
|
47
|
+
const MarkupsDefault = {
|
|
48
|
+
[FABRICATION]: {
|
|
49
|
+
[BASE]: 1.0,
|
|
50
|
+
[HIGHVALUE]: 1.0,
|
|
51
|
+
[SERVICE]: 1.0,
|
|
52
|
+
},
|
|
53
|
+
[WHOLESALE]: {
|
|
54
|
+
[BASE]: 1.0,
|
|
55
|
+
[HIGHVALUE]: 1.0,
|
|
56
|
+
[SERVICE]: 1.0,
|
|
57
|
+
},
|
|
58
|
+
[RETAIL]: {
|
|
59
|
+
[BASE]: 1.0,
|
|
60
|
+
[HIGHVALUE]: 1.0,
|
|
61
|
+
[SERVICE]: 1.0,
|
|
62
|
+
},
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* @readonly
|
|
67
|
+
* @constant
|
|
68
|
+
* @type {Material}
|
|
69
|
+
* @default
|
|
70
|
+
*/
|
|
71
|
+
const MaterialDefaultForm = {
|
|
72
|
+
[BASE]: "number",
|
|
73
|
+
[HIGHVALUE]: "number",
|
|
74
|
+
[SERVICE]: "number",
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* @readonly
|
|
79
|
+
* @constant
|
|
80
|
+
* @type {Stage}
|
|
81
|
+
* @default
|
|
82
|
+
*/
|
|
83
|
+
const MarkupsDefaultForm = {
|
|
84
|
+
[FABRICATION]: `subrecord:${MATERIAL}`,
|
|
85
|
+
[WHOLESALE]: `subrecord:${MATERIAL}`,
|
|
86
|
+
[RETAIL]: `subrecord:${MATERIAL}`,
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
Forms.Base[MATERIAL] = MaterialDefaultForm;
|
|
90
|
+
Forms.BaseForm[MATERIAL] = MaterialDefaultForm;
|
|
91
|
+
Forms.CreateForm[MATERIAL] = MaterialDefaultForm;
|
|
92
|
+
//Forms.Save[MATERIAL] = updateMaterial;
|
|
93
|
+
Forms.SearchBy[MATERIAL] = MATERIAL;
|
|
94
|
+
|
|
95
|
+
Forms.Base[MARKUPS] = MarkupsDefault;
|
|
96
|
+
Forms.BaseForm[MARKUPS] = MarkupsDefaultForm;
|
|
97
|
+
Forms.CreateForm[MARKUPS] = MarkupsDefaultForm;
|
|
98
|
+
Forms.Save[MARKUPS] = updateMarkups;
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* @readonly
|
|
102
|
+
* @constant
|
|
103
|
+
* @default
|
|
104
|
+
*
|
|
105
|
+
*/
|
|
106
|
+
export const MaterialChoices = {
|
|
107
|
+
[BASE]: {
|
|
108
|
+
Id: BASE,
|
|
109
|
+
label: BASE,
|
|
110
|
+
description: "Base",
|
|
111
|
+
order: 1,
|
|
112
|
+
},
|
|
113
|
+
[HIGHVALUE]: {
|
|
114
|
+
Id: HIGHVALUE,
|
|
115
|
+
label: HIGHVALUE,
|
|
116
|
+
description: "High Value",
|
|
117
|
+
order: 2,
|
|
118
|
+
},
|
|
119
|
+
[SERVICE]: {
|
|
120
|
+
Id: SERVICE,
|
|
121
|
+
label: SERVICE,
|
|
122
|
+
description: "Service",
|
|
123
|
+
order: 3,
|
|
124
|
+
},
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* @readonly
|
|
129
|
+
* @constant
|
|
130
|
+
* @default
|
|
131
|
+
*/
|
|
132
|
+
export const StageChoices = {
|
|
133
|
+
[FABRICATION]: {
|
|
134
|
+
Id: FABRICATION,
|
|
135
|
+
label: FABRICATION,
|
|
136
|
+
description: "Fabrication Stage",
|
|
137
|
+
order: 1,
|
|
138
|
+
},
|
|
139
|
+
[WHOLESALE]: {
|
|
140
|
+
Id: WHOLESALE,
|
|
141
|
+
label: WHOLESALE,
|
|
142
|
+
description: "Wholesale Stage",
|
|
143
|
+
order: 2,
|
|
144
|
+
},
|
|
145
|
+
[RETAIL]: {
|
|
146
|
+
Id: RETAIL,
|
|
147
|
+
label: RETAIL,
|
|
148
|
+
description: "Retail Stage",
|
|
149
|
+
order: 3,
|
|
150
|
+
},
|
|
151
|
+
};
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* @readonly
|
|
155
|
+
* @constant
|
|
156
|
+
* @default
|
|
157
|
+
*/
|
|
158
|
+
Forms.Choices[STAGE] = StageChoices;
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* @readonly
|
|
162
|
+
* @constant
|
|
163
|
+
* @default
|
|
164
|
+
*/
|
|
165
|
+
Forms.Choices[MATERIAL] = MaterialChoices
|
|
166
|
+
|
|
167
|
+
//////////////////////////////////////////////////////////////////////
|
|
168
|
+
// record operations
|
|
169
|
+
/**
|
|
170
|
+
* writes record back to database. Assumes only Id is valid
|
|
171
|
+
* @param {LineItem} stage a partially-populated product record for updates
|
|
172
|
+
* @param {Record} parent minimal record of product, user (or none) this stage belongs to
|
|
173
|
+
* @returns {promise.LineItem} a copy of the data written
|
|
174
|
+
*/
|
|
175
|
+
async function updateMarkups(markups, parent = null) {
|
|
176
|
+
return updateRecord(
|
|
177
|
+
fillForm(markups, MARKUPS), //saves only APPROPRIATE fields -does NOT populate missing fields
|
|
178
|
+
parent,
|
|
179
|
+
MARKUPS
|
|
180
|
+
);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
|
|
@@ -0,0 +1,516 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* "Payment Descriptor" handling operations. These descriptors represent paymentMethods, each tied
|
|
3
|
+
* to an individual user. These do not *particularly* represent a paymentProvider - they are meant
|
|
4
|
+
* as an abstraction above a specific payment processor.
|
|
5
|
+
* @module Payment
|
|
6
|
+
*/
|
|
7
|
+
import {
|
|
8
|
+
typedWrite,
|
|
9
|
+
writeBack,
|
|
10
|
+
fetchRecord,
|
|
11
|
+
collectRecords,
|
|
12
|
+
collectRecordsByFilter,
|
|
13
|
+
deleteRecord,
|
|
14
|
+
ownerByChild,
|
|
15
|
+
ownerByOwnerType,
|
|
16
|
+
serverTimestampFieldValue,
|
|
17
|
+
} from "@leaddreamer/firebase-wrapper";
|
|
18
|
+
|
|
19
|
+
import { Forms, cleanType } from "@leaddreamer/staticforms";
|
|
20
|
+
import { PAYMENT, RECEIPTS, CARDS } from "../boilerplate";
|
|
21
|
+
|
|
22
|
+
//////////////////////////////////////////////////////////////////////
|
|
23
|
+
// definitions
|
|
24
|
+
/**
|
|
25
|
+
* @constant
|
|
26
|
+
* @type {{CARD_ERROR: string, VALIDATION_ERROR: string}}
|
|
27
|
+
* @default
|
|
28
|
+
*/
|
|
29
|
+
export const ERROR_TYPES = {
|
|
30
|
+
CARD_ERROR: `card_error`,
|
|
31
|
+
VALIDATION_ERROR: `validation_error`,
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* @typedef {object} PaymentData
|
|
36
|
+
* @property {string} Id
|
|
37
|
+
* @property {string} payment_gateway
|
|
38
|
+
* @property {string} status
|
|
39
|
+
*/
|
|
40
|
+
/**
|
|
41
|
+
* @constant
|
|
42
|
+
* @type {PaymentData}
|
|
43
|
+
* @default
|
|
44
|
+
*/
|
|
45
|
+
export const PaymentDefault = {
|
|
46
|
+
Id: null,
|
|
47
|
+
payment_gateway: null,
|
|
48
|
+
status: null,
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* @typedef {object} PaymentDescriptorType
|
|
53
|
+
* @property {!string} Id document Id of this Card Descriptor (same as fingerprint)
|
|
54
|
+
* @property {!string} paymentMethod Id of payment system card item
|
|
55
|
+
* @property {!string} fingerprint Unique hash of card info - for checking uniqueness
|
|
56
|
+
* @property {!string} label Brand & last4, or other descriptive
|
|
57
|
+
* @property {!string} expiry expiry date of payment method (if any)
|
|
58
|
+
* @property {timestamp} timestamp last create or modify server time
|
|
59
|
+
*/
|
|
60
|
+
/**
|
|
61
|
+
* @typedef {object} PDSummary
|
|
62
|
+
* @property {!string} Id document Id of this Card Descriptor
|
|
63
|
+
* @property {!string} label Brand & last4, or other descriptive
|
|
64
|
+
*/
|
|
65
|
+
/**
|
|
66
|
+
* @constant
|
|
67
|
+
* @type {PaymentDescriptorType}
|
|
68
|
+
* @default
|
|
69
|
+
*/
|
|
70
|
+
export const paymentDescriptor = {
|
|
71
|
+
Id: null,
|
|
72
|
+
paymentMethod: null,
|
|
73
|
+
fingerprint: null,
|
|
74
|
+
label: null,
|
|
75
|
+
nickname: null,
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* @typedef {object} ReceiptType
|
|
80
|
+
* @property {!string} Id same Id as the associated pledgeTicket
|
|
81
|
+
* @property {!number} amount
|
|
82
|
+
* @property {object} payment
|
|
83
|
+
* @property {!string} link Id of associated payment_intent
|
|
84
|
+
* @property {!string} paidQ string describing status
|
|
85
|
+
* @property {?string} description supplemental information
|
|
86
|
+
*/
|
|
87
|
+
/**
|
|
88
|
+
* @constant
|
|
89
|
+
* @type {ReceiptType}
|
|
90
|
+
* @default
|
|
91
|
+
*/
|
|
92
|
+
export const receiptDefault = {
|
|
93
|
+
Id: null, //pledgeTicketId for user receipts
|
|
94
|
+
amount: 0,
|
|
95
|
+
payment: {
|
|
96
|
+
link: null, //paymentIntentId
|
|
97
|
+
paidQ: null, //current status
|
|
98
|
+
},
|
|
99
|
+
description: null, //supplemental information
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
Forms.Base[PAYMENT] = PaymentDefault;
|
|
103
|
+
|
|
104
|
+
//////////////////////////////////////////////////////////////////////
|
|
105
|
+
// Utilities
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* @typedef {UserObject} AccountObject
|
|
109
|
+
*/
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Creates the Organization Payment information document
|
|
113
|
+
* @async
|
|
114
|
+
* @function
|
|
115
|
+
* @param {AccountObject} account
|
|
116
|
+
* @param {?WriteBatch|Transaction} batch batching object. Transaction will be added to the batch
|
|
117
|
+
* @return {Promise<WriteBatch|Transaction|void>} WriteBatch, Transaction or Void
|
|
118
|
+
*/
|
|
119
|
+
export async function createPaymentRecord(account, batch = null) {
|
|
120
|
+
return typedWrite(
|
|
121
|
+
cleanType(account, PAYMENT), //sanitized data - unused fields added
|
|
122
|
+
account, //parent
|
|
123
|
+
PAYMENT, //type
|
|
124
|
+
batch,
|
|
125
|
+
);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Saves a payment data record to a given account (user)
|
|
130
|
+
* ALL OF fans, artists and venues save the payment data in the same collection
|
|
131
|
+
* name under the parent, with the SAME Id as the parent
|
|
132
|
+
* PaymentData *COMES FROM* payement processor, and should INCLUDE the record Id and
|
|
133
|
+
* refPath
|
|
134
|
+
* @param {PaymentDataRecord} paymentData
|
|
135
|
+
*/
|
|
136
|
+
export async function savePaymentData(paymentData) {
|
|
137
|
+
//ALL OF fans, artists and venues save the payment data in the same collection
|
|
138
|
+
// name under the parent, with the SAME Id as the parent
|
|
139
|
+
return writeBack({
|
|
140
|
+
...paymentData,
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* fetches a paymentData record from the database for an account
|
|
146
|
+
* ALL OF fans, artists and venues, etc save the payment data in the same collection
|
|
147
|
+
* name under the parent, with the SAME Id as the parent
|
|
148
|
+
* @param {AccountType} account
|
|
149
|
+
* @param {Promise.PaymentData} paymentData
|
|
150
|
+
*/
|
|
151
|
+
export async function fetchPayment(account) {
|
|
152
|
+
//payment data is saved under the same collection name for fans, artists
|
|
153
|
+
//and venues, with the parent ID
|
|
154
|
+
let payment_record = null;
|
|
155
|
+
try {
|
|
156
|
+
payment_record = await fetchRecord(PAYMENT, account.Id, account.refPath);
|
|
157
|
+
} catch (err) { }
|
|
158
|
+
return payment_record;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* fetches a paymentData record from the database for an account when only accountID and type are known
|
|
163
|
+
* ALL OF fans, artists and venues save the payment data in the same collection
|
|
164
|
+
* name under the parent, with the SAME Id as the parent
|
|
165
|
+
* @param {!string} accountId
|
|
166
|
+
* @param {!string} type
|
|
167
|
+
* @param {Promise.PaymentData} paymentData
|
|
168
|
+
*/
|
|
169
|
+
export async function fetchPaymentByUser(accountId) {
|
|
170
|
+
return fetchPayment({
|
|
171
|
+
Id: accountId,
|
|
172
|
+
refPath: `${USER}/${accountId}`,
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Adds a specific paymentDescriptor to an account payment data
|
|
178
|
+
* @param {AccountType} account
|
|
179
|
+
* @param {!string} account.Id
|
|
180
|
+
* @param {!string} account.refPath
|
|
181
|
+
* @param {PaymentDescriptorType} descriptor
|
|
182
|
+
* @param {!string} descriptor.paymentMethod
|
|
183
|
+
* @param {!string} descriptor.fingerprint
|
|
184
|
+
* @param {!string} descriptor.label
|
|
185
|
+
* @param {?WriteBatch|Transaction} batch batching object. Transaction will be added to the batch
|
|
186
|
+
* @return {Promise.PaymentDescriptorType}
|
|
187
|
+
*/
|
|
188
|
+
export async function addPaymentDescriptor(account, descriptor, batch = null) {
|
|
189
|
+
return typedWrite(
|
|
190
|
+
{
|
|
191
|
+
...descriptor,
|
|
192
|
+
timestamp: serverTimestampFieldValue,
|
|
193
|
+
},
|
|
194
|
+
{
|
|
195
|
+
//Payment documents BY DEFINITION have the same Id as the parent
|
|
196
|
+
refPath: `${account.refPath}/${PAYMENT}/${account.Id}`,
|
|
197
|
+
},
|
|
198
|
+
CARDS,
|
|
199
|
+
batch,
|
|
200
|
+
);
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* Saves a modified paymentDescriptor back to the database
|
|
205
|
+
* @param {PaymentDescriptorType} descriptor
|
|
206
|
+
* @param {!string} descriptor.Id
|
|
207
|
+
* @param {!string} descriptor.refPath
|
|
208
|
+
* @return {Promise.PaymentDescriptorType}
|
|
209
|
+
*/
|
|
210
|
+
export async function savePaymentDescriptor(descriptor) {
|
|
211
|
+
//BOTH fans, artists and venues save the payment data in the same collection
|
|
212
|
+
// name under the parent, with the SAME Id as the parent
|
|
213
|
+
return writeBack({
|
|
214
|
+
...descriptor,
|
|
215
|
+
timestamp: serverTimestampFieldValue,
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* Removes a paymentDescriptor from an account's paymentData
|
|
221
|
+
* @param {AccountType} account
|
|
222
|
+
* @param {PaymentDescriptorType} descriptor
|
|
223
|
+
* @returns {Promise<void>}
|
|
224
|
+
*/
|
|
225
|
+
export async function removePaymentDescriptor(account, descriptor) {
|
|
226
|
+
//MASSIVE CAVEAT
|
|
227
|
+
//A paymentMethod *might* be removed with e same *fingerprint* as a current descriptor
|
|
228
|
+
//but is still a different *paymentMethod*. PaymentDescriptors are unique on the fingerprint
|
|
229
|
+
//Therefore, we need to *first* confirm that is is the same, so...
|
|
230
|
+
//READ FIRST...
|
|
231
|
+
const existingPD = await fetchPDByFingerprint(
|
|
232
|
+
account,
|
|
233
|
+
descriptor.fingerprint,
|
|
234
|
+
);
|
|
235
|
+
//COMPARE PAYEMNTMETHOD, THEN DELETE IF NEEDED
|
|
236
|
+
return existingPD.paymentMethod === descriptor.paymentMethod
|
|
237
|
+
? deleteRecord(
|
|
238
|
+
descriptor,
|
|
239
|
+
CARDS,
|
|
240
|
+
`/${account.refPath}/${PAYMENT}/${account.Id}`,
|
|
241
|
+
)
|
|
242
|
+
: Promise.resolve(null); //don't delete if not identical
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
/**
|
|
246
|
+
* fetch all customer card records IN OUR DATABASE (not payment database)
|
|
247
|
+
* @param {AccountType} account
|
|
248
|
+
* @param {!string} account.refPath
|
|
249
|
+
* @returns {Promise.Array.PaymentDescriptor}
|
|
250
|
+
*
|
|
251
|
+
*/
|
|
252
|
+
export async function fetchPaymentDescriptors(account) {
|
|
253
|
+
return collectRecords(CARDS, `${account.refPath}/${PAYMENT}/${account.Id}`);
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
/**
|
|
257
|
+
* fetch the front-end list of paymentDescriptors
|
|
258
|
+
* @param {AccountType} account
|
|
259
|
+
* @param {!string} account.Id
|
|
260
|
+
* @param {!string} account.refPath
|
|
261
|
+
* @return {Promise.Array.PDSummary}
|
|
262
|
+
*/
|
|
263
|
+
export async function listPDSummaries(account) {
|
|
264
|
+
const full = await fetchPaymentDescriptors(account);
|
|
265
|
+
return full.map((pd) => ({
|
|
266
|
+
Id: pd.Id,
|
|
267
|
+
label: pd.label,
|
|
268
|
+
nickname: pd.nickname,
|
|
269
|
+
}));
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
/**
|
|
273
|
+
* @param {AccountType} account
|
|
274
|
+
* @param {!string} account.Id
|
|
275
|
+
* @param {!string} account.refPath
|
|
276
|
+
* @returns {Promise.PaymentDescriptorType}
|
|
277
|
+
*/
|
|
278
|
+
export async function fetchLatestPDSummary(account) {
|
|
279
|
+
const sortArray = [
|
|
280
|
+
{
|
|
281
|
+
fieldRef: "timestamp",
|
|
282
|
+
dirStr: "desc",
|
|
283
|
+
},
|
|
284
|
+
];
|
|
285
|
+
|
|
286
|
+
const shortlist = await collectRecordsByFilter(
|
|
287
|
+
CARDS,
|
|
288
|
+
`/${account.refPath}/${PAYMENT}/${account.Id}`,
|
|
289
|
+
null, //filterArray
|
|
290
|
+
sortArray,
|
|
291
|
+
1, //limit
|
|
292
|
+
);
|
|
293
|
+
const latest = shortlist?.[0];
|
|
294
|
+
|
|
295
|
+
return { Id: latest?.Id, label: latest?.label };
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
/**
|
|
299
|
+
* retreives a PD, given the account Id and Type
|
|
300
|
+
* @param {AccountType} account
|
|
301
|
+
* @param {!string} fingerprint
|
|
302
|
+
* @returns {Promise<PDSummary>}
|
|
303
|
+
*/
|
|
304
|
+
export async function fetchPDByFingerprint(account, fingerprint) {
|
|
305
|
+
return fetchRecord(
|
|
306
|
+
CARDS, //tableName
|
|
307
|
+
fingerprint, //Id/DocId
|
|
308
|
+
`/${account.refPath}/${PAYMENT}/${account.Id}`, //refPath
|
|
309
|
+
);
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
/**
|
|
313
|
+
* retreives a PD, given the account Id and Type
|
|
314
|
+
* @param {!string} accountId
|
|
315
|
+
* @param {!string} type
|
|
316
|
+
* @param {!string} fingerprint
|
|
317
|
+
* @returns {Promise<PDSummary>}
|
|
318
|
+
*/
|
|
319
|
+
export async function fetchPDByOwnerType(accountId, type, fingerprint) {
|
|
320
|
+
return fetchRecord(
|
|
321
|
+
CARDS, //tableName
|
|
322
|
+
fingerprint, //Id/DocId
|
|
323
|
+
`/${type}/${accountId}/${PAYMENT}/${accountId}`, //refPath
|
|
324
|
+
);
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
/**
|
|
328
|
+
* Copies a PDSummary tobe the new default (convenience function)
|
|
329
|
+
* @param {AccountType} account
|
|
330
|
+
* @param {?PDSummary} PDSummary
|
|
331
|
+
* @returns {Promise.AccountObject}
|
|
332
|
+
*/
|
|
333
|
+
export async function replaceDefaultPDSummary(account, PDSummary = null) {
|
|
334
|
+
//if not passed a PaymentDescriptorType, use the latest available
|
|
335
|
+
const lastestPayment = await (PDSummary
|
|
336
|
+
? Promise.resolve(PDSummary)
|
|
337
|
+
: fetchLatestPDSummary(account));
|
|
338
|
+
return writeBack({
|
|
339
|
+
...account,
|
|
340
|
+
payment_method: lastestPayment,
|
|
341
|
+
});
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
//////////////////////////////////////////////////////////////////////
|
|
345
|
+
//Receipt support
|
|
346
|
+
|
|
347
|
+
/**
|
|
348
|
+
* Savess a Receipt to an account
|
|
349
|
+
* @param {AccountType} account
|
|
350
|
+
* @param {?ReceiptType} receipt
|
|
351
|
+
* @param {?WriteBatch|Transaction} batch batching object. Transaction will be added to the batch
|
|
352
|
+
* @returns {Promise.ReceiptType}
|
|
353
|
+
*/
|
|
354
|
+
export async function saveReceiptRecord(account, receipt, batch = null) {
|
|
355
|
+
return typedWrite(receipt, account, RECEIPTS, batch);
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
/**
|
|
359
|
+
* Updates a (changed?) Receipt record
|
|
360
|
+
* @param {?ReceiptType} receipt
|
|
361
|
+
* @returns {Promise.ReceiptType}
|
|
362
|
+
*/
|
|
363
|
+
export async function updateReceipt(receipt) {
|
|
364
|
+
return writeBack(receipt);
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
/**
|
|
368
|
+
* Saves a new receipt to an account referrred by ID and type
|
|
369
|
+
* @param {!string} ownerId
|
|
370
|
+
* @param {string} type either ORGANIZATIONS or USER
|
|
371
|
+
* @param {ReceiptType} receipt
|
|
372
|
+
* @param {?WriteBatch|Transaction} batch batching object. Transaction will be added to the batch
|
|
373
|
+
* @returns {Promise.ReceiptType}
|
|
374
|
+
*/
|
|
375
|
+
export async function saveReceiptRecordByOwnerType(
|
|
376
|
+
ownerId,
|
|
377
|
+
ownerType,
|
|
378
|
+
receipt,
|
|
379
|
+
batch = null,
|
|
380
|
+
) {
|
|
381
|
+
return saveReceiptRecord(
|
|
382
|
+
ownerByOwnerType(ownerId, ownerType),
|
|
383
|
+
receipt,
|
|
384
|
+
batch,
|
|
385
|
+
);
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
/**
|
|
389
|
+
* Fetches an array of receipts in any particular month by monthStampt
|
|
390
|
+
* @param {AccountObject} account
|
|
391
|
+
* @param {dateString} monthStamp
|
|
392
|
+
* @returns {Promise.Array.ReceiptType}
|
|
393
|
+
*/
|
|
394
|
+
export async function anyReceiptsByMonthStamp(account, monthStamp) {
|
|
395
|
+
const filterArray = [
|
|
396
|
+
{ fieldRef: "monthStamp", opStr: "==", value: monthStamp },
|
|
397
|
+
];
|
|
398
|
+
try {
|
|
399
|
+
const receipts = await fetchReceiptsFiltered(account, filterArray);
|
|
400
|
+
return !!receipts.length; //true if more than zero
|
|
401
|
+
} catch (err) {
|
|
402
|
+
return false;
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
/**
|
|
407
|
+
* Saves a receipt by a child record reference
|
|
408
|
+
* @param {RecordDocument} child
|
|
409
|
+
* @param {ReceiptType} receipt
|
|
410
|
+
* @param {?WriteBatch|Transaction} batch batching object. Transaction will be added to the batch
|
|
411
|
+
* @returns {Promise.ReceiptType}
|
|
412
|
+
*/
|
|
413
|
+
export async function saveReceiptRecordByChild(child, receipt, batch = null) {
|
|
414
|
+
return saveReceiptRecord(ownerByChild(child), receipt, batch);
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
/**
|
|
418
|
+
* Fetches receipts based on a filter set
|
|
419
|
+
* @param {AccountObject} account
|
|
420
|
+
* @param {!string} account.refPath
|
|
421
|
+
* @param {Array.filterObject} filterArray
|
|
422
|
+
* @param {Array.sortObject} sortArray
|
|
423
|
+
* @param {number} limit
|
|
424
|
+
* @return {Promise.Array.ReceiptType}
|
|
425
|
+
*/
|
|
426
|
+
export async function fetchReceiptsFiltered(
|
|
427
|
+
account,
|
|
428
|
+
filterArray = null,
|
|
429
|
+
sortArray = null,
|
|
430
|
+
limit = null,
|
|
431
|
+
) {
|
|
432
|
+
return collectRecordsByFilter(
|
|
433
|
+
RECEIPTS, //tablePath
|
|
434
|
+
account.refPath, //refPath
|
|
435
|
+
filterArray, //filter array
|
|
436
|
+
sortArray, //sort Array
|
|
437
|
+
limit, //limit
|
|
438
|
+
);
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
/**
|
|
442
|
+
* @param {AccountObject} account
|
|
443
|
+
* @param {!string} account.refPath
|
|
444
|
+
* @param {!string} receiptId
|
|
445
|
+
* @return {Promise.ReceiptType}
|
|
446
|
+
*/
|
|
447
|
+
async function fetchReceipt(account, receiptId) {
|
|
448
|
+
return fetchRecord(RECEIPTS, receiptId, account.refPath);
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
/**
|
|
452
|
+
* @param {AccountObject} account
|
|
453
|
+
* @param {!string} account.refPath
|
|
454
|
+
* @return {Promise.Array.ReceiptType}
|
|
455
|
+
*/
|
|
456
|
+
export async function fetchProblemReceipts(account) {
|
|
457
|
+
//const in_status_array = [
|
|
458
|
+
//`requires_payment_method`,
|
|
459
|
+
//`requires_confirmation`,
|
|
460
|
+
//`requires_action`,
|
|
461
|
+
//`processing`,
|
|
462
|
+
//`requires_capture`,
|
|
463
|
+
//`canceled`,
|
|
464
|
+
//`succeeded`,
|
|
465
|
+
//`none`
|
|
466
|
+
//];
|
|
467
|
+
const not_in_status_array = [`succeeded`, `none`];
|
|
468
|
+
const filterArray = [
|
|
469
|
+
{ fieldRef: "payment.paidQ", opStr: "not-in", value: not_in_status_array },
|
|
470
|
+
];
|
|
471
|
+
return fetchReceiptsFiltered(account, filterArray, null, null);
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
/**
|
|
475
|
+
* Fetches the receipt for a pledgeTicket
|
|
476
|
+
* @param {PledgeTicket} pledgeTicket
|
|
477
|
+
* @returns {Promise.ReceiptType}
|
|
478
|
+
*/
|
|
479
|
+
export async function fetchPledgeTicketReceipt(pledgeTicket) {
|
|
480
|
+
const account = {
|
|
481
|
+
Id: pledgeTicket.fan.Id,
|
|
482
|
+
refPath: `/${USER}/${pledgeTicket.fan.Id}`,
|
|
483
|
+
};
|
|
484
|
+
const receiptId = pledgeTicket.Id;
|
|
485
|
+
return fetchReceipt(account, receiptId);
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
/**
|
|
489
|
+
* Changes the paidQ label on a receipt associated with a pledgeTicket
|
|
490
|
+
* @param {pledgeTicketType} pledgeTicket
|
|
491
|
+
* @param {?string} label
|
|
492
|
+
* @returns {Promise.ReceiptType}
|
|
493
|
+
*/
|
|
494
|
+
export async function markReceiptFromPledgeTicket(pledgeTicket, label) {
|
|
495
|
+
const receipt = await fetchPledgeTicketReceipt(pledgeTicket);
|
|
496
|
+
return markReceipt(receipt, label);
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
/**
|
|
500
|
+
* Changes the paidQ label on a receipt associated with a pledgeTicket
|
|
501
|
+
* @param {receiptType} receipt
|
|
502
|
+
* @param {?string} label
|
|
503
|
+
* @returns {Promise.ReceiptType}
|
|
504
|
+
*/
|
|
505
|
+
export async function markReceipt(receipt, label) {
|
|
506
|
+
return updateReceipt({
|
|
507
|
+
...receipt,
|
|
508
|
+
payment: {
|
|
509
|
+
...receipt.payment,
|
|
510
|
+
paidQ: label,
|
|
511
|
+
},
|
|
512
|
+
});
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
//////////////////////////////////////////////////////////////////////
|
|
516
|
+
// utilities
|