@dhyasama/totem-models 12.3.0 → 12.4.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/lib/Deal.js CHANGED
@@ -79,7 +79,7 @@ module.exports = function(mongoose, config) {
79
79
 
80
80
  const self = this;
81
81
  return _.find(self.documents, function(document) { return document.type == 'deck'; })
82
-
82
+
83
83
  });
84
84
 
85
85
  Deal.virtual('added').get(function () {
@@ -113,9 +113,7 @@ module.exports = function(mongoose, config) {
113
113
  // Statics operate on the entire collection
114
114
  //////////////////////////////////////////////////////
115
115
 
116
- Deal.statics.delete = function(id, options, cb) {
117
-
118
- let self = this;
116
+ Deal.statics.delete = async function(id, options, cb) {
119
117
 
120
118
  if (!cb) { throw new Error('cb is required'); }
121
119
  if (!id) { return cb(new Error('id is required'), null); }
@@ -124,26 +122,27 @@ module.exports = function(mongoose, config) {
124
122
  if (!options.CUSTOMER_ID) { return cb(new Error('options.CUSTOMER_ID is required'), null); }
125
123
  if (!mongoose.Types.ObjectId.isValid(options.CUSTOMER_ID)) { return cb(new Error('options.CUSTOMER_ID is not a valid ObjectId'), null); }
126
124
 
127
- // Not strictly necessary but provides verification that the document being deleted belongs to the customer doing the deleting
128
- let query = self.findOne({
129
- '_id': id,
130
- 'customer': options.CUSTOMER_ID
131
- });
125
+ try {
126
+ // Not strictly necessary but provides verification that the document being deleted belongs to the customer doing the deleting
127
+ let query = this.findOne({
128
+ '_id': id,
129
+ 'customer': options.CUSTOMER_ID
130
+ });
132
131
 
133
- query.exec().then(function(deal) {
132
+ const deal = await query;
134
133
  if (!deal) return cb(null, null);
135
134
 
136
135
  // No population so no need to scrub
137
136
 
138
- deal.deleteOne().then(function() { cb(null, deal); }).catch(function(err) { cb(err); });
139
-
140
- }).catch(function(err) { cb(err); });
137
+ await deal.deleteOne();
138
+ return cb(null, deal);
139
+ } catch(err) {
140
+ return cb(err);
141
+ }
141
142
 
142
143
  };
143
144
 
144
- Deal.statics.getById = function (id, options, cb) {
145
-
146
- let self = this;
145
+ Deal.statics.getById = async function (id, options, cb) {
147
146
 
148
147
  if (!cb) { throw new Error('cb is required'); }
149
148
  if (!id) { return cb(new Error('id is required'), null); }
@@ -152,22 +151,25 @@ module.exports = function(mongoose, config) {
152
151
  if (!options.CUSTOMER_ID) { return cb(new Error('options.CUSTOMER_ID is required'), null); }
153
152
  if (!mongoose.Types.ObjectId.isValid(options.CUSTOMER_ID)) { return cb(new Error('options.CUSTOMER_ID is not a valid ObjectId'), null); }
154
153
 
155
- let query = self.findOne({
156
- '_id': id,
157
- 'customer': options.CUSTOMER_ID
158
- });
154
+ try {
155
+ let query = this.findOne({
156
+ '_id': id,
157
+ 'customer': options.CUSTOMER_ID
158
+ });
159
159
 
160
- query.populate({ path: 'documents', match: { customer: options.CUSTOMER_ID } });
161
- query.populate({ path: 'messages', match: { customer: options.CUSTOMER_ID } });
162
- query.populate('organization', 'name aliases description logoUrl website websiteAliases chairs contact social crunchbase pitchbook foundedOn operating shutdown');
163
- query.populate('referrer.person', 'name avatarUrl title');
164
- query.exec().then(function(result) { cb(null, result); }).catch(function(err) { cb(err); });
160
+ query.populate({ path: 'documents', match: { customer: options.CUSTOMER_ID } });
161
+ query.populate({ path: 'messages', match: { customer: options.CUSTOMER_ID } });
162
+ query.populate('organization', 'name aliases description logoUrl website websiteAliases chairs contact social crunchbase pitchbook foundedOn operating shutdown');
163
+ query.populate('referrer.person', 'name avatarUrl title');
164
+ const result = await query;
165
+ return cb(null, result);
166
+ } catch(err) {
167
+ return cb(err);
168
+ }
165
169
 
166
170
  };
167
171
 
168
- Deal.statics.getByIds = function (ids, options, cb) {
169
-
170
- let self = this;
172
+ Deal.statics.getByIds = async function (ids, options, cb) {
171
173
 
172
174
  if (!cb) { throw new Error('cb is required'); }
173
175
  if (!ids) { return cb(new Error('ids is required'), null); }
@@ -175,290 +177,295 @@ module.exports = function(mongoose, config) {
175
177
  if (!options.CUSTOMER_ID) { return cb(new Error('options.CUSTOMER_ID is required'), null); }
176
178
  if (!mongoose.Types.ObjectId.isValid(options.CUSTOMER_ID)) { return cb(new Error('options.CUSTOMER_ID is not a valid ObjectId'), null); }
177
179
 
178
- let query = self.find({
179
- customer: options.CUSTOMER_ID,
180
- '_id': { $in : ids }
181
- });
180
+ try {
181
+ let query = this.find({
182
+ customer: options.CUSTOMER_ID,
183
+ '_id': { $in : ids }
184
+ });
182
185
 
183
- query.populate({ path: 'documents', match: { customer: options.CUSTOMER_ID } });
184
- query.populate({ path: 'messages', match: { customer: options.CUSTOMER_ID } });
185
- query.populate('organization', 'name aliases description logoUrl website websiteAliases chairs contact');
186
- query.populate('referrer.person', 'name avatarUrl title');
187
- query.exec().then(function(result) { cb(null, result); }).catch(function(err) { cb(err); });
186
+ query.populate({ path: 'documents', match: { customer: options.CUSTOMER_ID } });
187
+ query.populate({ path: 'messages', match: { customer: options.CUSTOMER_ID } });
188
+ query.populate('organization', 'name aliases description logoUrl website websiteAliases chairs contact');
189
+ query.populate('referrer.person', 'name avatarUrl title');
190
+ const result = await query;
191
+ return cb(null, result);
192
+ } catch(err) {
193
+ return cb(err);
194
+ }
188
195
 
189
196
  };
190
197
 
191
198
  // Get all deals belonging to a customer
192
- Deal.statics.getForCustomer = function (customerId, options, cb) {
193
-
194
- let self = this;
199
+ Deal.statics.getForCustomer = async function (customerId, options, cb) {
195
200
 
196
201
  if (!cb) { throw new Error('cb is required'); }
197
202
  if (!customerId) { return cb(new Error('customerId is required'), null); }
198
203
  if (!mongoose.Types.ObjectId.isValid(customerId)) { return cb(new Error('customerId is not a valid ObjectId'), null); }
199
204
 
200
- options = options || {};
205
+ try {
206
+ options = options || {};
201
207
 
202
- let terms = { 'customer': customerId };
203
- if (options.stages) { terms['stage'] = { $in: options.stages }; }
204
- if (options.added) {
205
- if(options.added.lte && options.added.gte) terms['history.0.timestamp'] = { $lte: options.added.lte, $gte: options.added.gte };
206
- else if(options.added.lte) terms['history.0.timestamp'] = { $lte: options.added.lte };
207
- else if(options.added.gte) terms['history.0.timestamp'] = { $gte: options.added.gte };
208
- }
209
- if (options.updated) {
210
- if(options.updated.lte && options.updated.gte) terms['history'] = { $elemMatch: { timestamp: { $lte: options.updated.lte, $gte: options.updated.gte } } };
211
- else if(options.updated.lte) terms['history'] = { $elemMatch: { timestamp: { $lte: options.updated.lte } } };
212
- else if(options.updated.gte) terms['history'] = { $elemMatch: { timestamp: { $gte: options.updated.gte } } };
213
- };
208
+ let terms = { 'customer': customerId };
209
+ if (options.stages) { terms['stage'] = { $in: options.stages }; }
210
+ if (options.added) {
211
+ if(options.added.lte && options.added.gte) terms['history.0.timestamp'] = { $lte: options.added.lte, $gte: options.added.gte };
212
+ else if(options.added.lte) terms['history.0.timestamp'] = { $lte: options.added.lte };
213
+ else if(options.added.gte) terms['history.0.timestamp'] = { $gte: options.added.gte };
214
+ }
215
+ if (options.updated) {
216
+ if(options.updated.lte && options.updated.gte) terms['history'] = { $elemMatch: { timestamp: { $lte: options.updated.lte, $gte: options.updated.gte } } };
217
+ else if(options.updated.lte) terms['history'] = { $elemMatch: { timestamp: { $lte: options.updated.lte } } };
218
+ else if(options.updated.gte) terms['history'] = { $elemMatch: { timestamp: { $gte: options.updated.gte } } };
219
+ };
214
220
 
215
- let query = self.find(terms);
221
+ let query = this.find(terms);
216
222
 
217
- if (options.populate) {
218
- query.populate({ path: 'documents', match: { customer: options.CUSTOMER_ID } });
219
- query.populate({ path: 'messages', match: { customer: options.CUSTOMER_ID }, select: '-raw' });
220
- query.populate('organization', 'name aliases description logoUrl website websiteAliases chairs contact people');
221
- query.populate('referrer.person', 'name avatarUrl title');
222
- query.populate('latestInteraction');
223
- query.populate('latestMessage');
224
- }
223
+ if (options.populate) {
224
+ query.populate({ path: 'documents', match: { customer: options.CUSTOMER_ID } });
225
+ query.populate({ path: 'messages', match: { customer: options.CUSTOMER_ID }, select: '-raw' });
226
+ query.populate('organization', 'name aliases description logoUrl website websiteAliases chairs contact people');
227
+ query.populate('referrer.person', 'name avatarUrl title');
228
+ query.populate('latestInteraction');
229
+ query.populate('latestMessage');
230
+ }
225
231
 
226
- query.exec().then(function(result) { cb(null, result); }).catch(function(err) { cb(err); });
232
+ const result = await query;
233
+ return cb(null, result);
234
+ } catch(err) {
235
+ return cb(err);
236
+ }
227
237
 
228
238
  };
229
239
 
230
- Deal.statics.getForCustomer2 = function (customerId, updatedSince, cb) {
231
-
232
- const self = this;
240
+ Deal.statics.getForCustomer2 = async function (customerId, updatedSince, cb) {
233
241
 
234
242
  if (!cb) { throw new Error('cb is required'); }
235
243
  if (!customerId) { return cb(new Error('customerId is required'), null); }
236
244
  if (!mongoose.Types.ObjectId.isValid(customerId)) { return cb(new Error('customerId is not a valid ObjectId'), null); }
237
245
 
238
- let query = self.find({
239
- customer: customerId,
240
- lastUpdated: { $gte: updatedSince }
241
- });
246
+ try {
247
+ let query = this.find({
248
+ customer: customerId,
249
+ lastUpdated: { $gte: updatedSince }
250
+ });
242
251
 
243
- query.populate({ path: 'documents', match: { customer: customerId } });
244
- query.populate({ path: 'messages', match: { customer: customerId }, select: '-raw' });
245
- query.populate('organization', 'name aliases description logoUrl website websiteAliases chairs contact people');
246
- query.populate('referrer.person', 'name avatarUrl title');
247
- query.populate('latestInteraction');
248
- query.populate('latestMessage');
252
+ query.populate({ path: 'documents', match: { customer: customerId } });
253
+ query.populate({ path: 'messages', match: { customer: customerId }, select: '-raw' });
254
+ query.populate('organization', 'name aliases description logoUrl website websiteAliases chairs contact people');
255
+ query.populate('referrer.person', 'name avatarUrl title');
256
+ query.populate('latestInteraction');
257
+ query.populate('latestMessage');
249
258
 
250
- query.exec().then(function(result) { cb(null, result); }).catch(function(err) { cb(err); });
259
+ const result = await query;
260
+ return cb(null, result);
261
+ } catch(err) {
262
+ return cb(err);
263
+ }
251
264
 
252
265
  };
253
266
 
254
- Deal.statics.getForCustomer3 = function (customerId, options, cb) {
255
-
256
- let self = this;
267
+ Deal.statics.getForCustomer3 = async function (customerId, options, cb) {
257
268
 
258
269
  if (!cb) { throw new Error('cb is required'); }
259
270
  if (!customerId) { return cb(new Error('customerId is required'), null); }
260
271
  if (!mongoose.Types.ObjectId.isValid(customerId)) { return cb(new Error('customerId is not a valid ObjectId'), null); }
261
272
 
262
- options = options || {};
263
-
264
- //let terms = { 'customer': customerId };
265
- //if (options.stages) { terms['stage'] = { $in: options.stages }; }
266
- // if (options.added) {
267
- // if(options.added.lte && options.added.gte) terms['history.0.timestamp'] = { $lte: options.added.lte, $gte: options.added.gte };
268
- // else if(options.added.lte) terms['history.0.timestamp'] = { $lte: options.added.lte };
269
- // else if(options.added.gte) terms['history.0.timestamp'] = { $gte: options.added.gte };
270
- // }
271
- // if (options.updated) {
272
- // if(options.updated.lte && options.updated.gte) terms['history'] = { $elemMatch: { timestamp: { $lte: options.updated.lte, $gte: options.updated.gte } } };
273
- // else if(options.updated.lte) terms['history'] = { $elemMatch: { timestamp: { $lte: options.updated.lte } } };
274
- // else if(options.updated.gte) terms['history'] = { $elemMatch: { timestamp: { $gte: options.updated.gte } } };
275
- // };
276
-
277
- let matchTerms = { 'customer': new mongoose.Types.ObjectId(customerId) };
278
- if (options.stages) { matchTerms['stage'] = { $in: options.stages }; }
279
- if (options.added) {
280
- if(options.added.lte && options.added.gte) matchTerms['lastUpdated'] = { $lte: new Date(options.added.lte), $gte: new Date(options.added.gte) };
281
- else if(options.added.lte) matchTerms['lastUpdated'] = { $lte: new Date(options.added.lte) };
282
- else if(options.added.gte) matchTerms['lastUpdated'] = { $gte: new Date(options.added.gte) };
283
- }
284
- if (options.updated) {
285
- if(options.updated.lte && options.updated.gte) matchTerms['lastUpdated'] = { $lte: new Date(options.updated.lte), $gte: new Date(options.updated.gte) };
286
- else if(options.updated.lte) matchTerms['lastUpdated'] = { $lte: new Date(options.updated.lte) };
287
- else if(options.updated.gte) matchTerms['lastUpdated'] = { $gte: new Date(options.updated.gte) };
288
- };
273
+ try {
274
+ options = options || {};
275
+
276
+ //let terms = { 'customer': customerId };
277
+ //if (options.stages) { terms['stage'] = { $in: options.stages }; }
278
+ // if (options.added) {
279
+ // if(options.added.lte && options.added.gte) terms['history.0.timestamp'] = { $lte: options.added.lte, $gte: options.added.gte };
280
+ // else if(options.added.lte) terms['history.0.timestamp'] = { $lte: options.added.lte };
281
+ // else if(options.added.gte) terms['history.0.timestamp'] = { $gte: options.added.gte };
282
+ // }
283
+ // if (options.updated) {
284
+ // if(options.updated.lte && options.updated.gte) terms['history'] = { $elemMatch: { timestamp: { $lte: options.updated.lte, $gte: options.updated.gte } } };
285
+ // else if(options.updated.lte) terms['history'] = { $elemMatch: { timestamp: { $lte: options.updated.lte } } };
286
+ // else if(options.updated.gte) terms['history'] = { $elemMatch: { timestamp: { $gte: options.updated.gte } } };
287
+ // };
288
+
289
+ let matchTerms = { 'customer': new mongoose.Types.ObjectId(customerId) };
290
+ if (options.stages) { matchTerms['stage'] = { $in: options.stages }; }
291
+ if (options.added) {
292
+ if(options.added.lte && options.added.gte) matchTerms['lastUpdated'] = { $lte: new Date(options.added.lte), $gte: new Date(options.added.gte) };
293
+ else if(options.added.lte) matchTerms['lastUpdated'] = { $lte: new Date(options.added.lte) };
294
+ else if(options.added.gte) matchTerms['lastUpdated'] = { $gte: new Date(options.added.gte) };
295
+ }
296
+ if (options.updated) {
297
+ if(options.updated.lte && options.updated.gte) matchTerms['lastUpdated'] = { $lte: new Date(options.updated.lte), $gte: new Date(options.updated.gte) };
298
+ else if(options.updated.lte) matchTerms['lastUpdated'] = { $lte: new Date(options.updated.lte) };
299
+ else if(options.updated.gte) matchTerms['lastUpdated'] = { $gte: new Date(options.updated.gte) };
300
+ };
289
301
 
290
- let pipeline = [
302
+ let pipeline = [
291
303
 
292
- // start by getting deals for the requested customer
293
- {
294
- $match: matchTerms
304
+ // start by getting deals for the requested customer
305
+ {
306
+ $match: matchTerms
307
+ // {
308
+ // customer: mongoose.Types.ObjectId(customerId),
309
+ // stage: {
310
+ // $in: options.stages
311
+ // },
312
+ // lastUpdated: { $gte: new Date(options.updated.gte) }
313
+ // //history: { $elemMatch: { timestamp: { $gte: ISODate('2023-02-14T00:00:00.000Z') } } }
314
+ // }
315
+ },
316
+
317
+ // get the orgs the deals are for
318
+ {
319
+ $lookup:
320
+ {
321
+ from: "organizations",
322
+ localField: "organization",
323
+ foreignField: "_id",
324
+ as: "organization"
325
+ }
326
+ },
295
327
  // {
296
- // customer: mongoose.Types.ObjectId(customerId),
297
- // stage: {
298
- // $in: options.stages
299
- // },
300
- // lastUpdated: { $gte: new Date(options.updated.gte) }
301
- // //history: { $elemMatch: { timestamp: { $gte: ISODate('2023-02-14T00:00:00.000Z') } } }
302
- // }
303
- },
304
-
305
- // get the orgs the deals are for
306
- {
307
- $lookup:
308
- {
309
- from: "organizations",
310
- localField: "organization",
311
- foreignField: "_id",
312
- as: "organization"
313
- }
314
- },
315
- // {
316
- // $unwind: {
317
- // path: "$organization",
318
- // preserveNullAndEmptyArrays: true
319
- // }
320
- // },
321
-
322
- // get the referrer
323
- {
324
- $lookup:
325
- {
326
- from: "people",
327
- let: { referrerPersonId: "$referrer.person" },
328
- pipeline: [
329
- {
330
- $match: {
331
- $expr: {
332
- $eq: ["$_id", "$$referrerPersonId"]
328
+ // $unwind: {
329
+ // path: "$organization",
330
+ // preserveNullAndEmptyArrays: true
331
+ // }
332
+ // },
333
+
334
+ // get the referrer
335
+ {
336
+ $lookup:
337
+ {
338
+ from: "people",
339
+ let: { referrerPersonId: "$referrer.person" },
340
+ pipeline: [
341
+ {
342
+ $match: {
343
+ $expr: {
344
+ $eq: ["$_id", "$$referrerPersonId"]
345
+ }
346
+ }
347
+ },
348
+ {
349
+ $project: {
350
+ name: 1,
351
+ avatarUrl: 1,
352
+ title: 1
333
353
  }
334
354
  }
335
- },
336
- {
337
- $project: {
338
- name: 1,
339
- avatarUrl: 1,
340
- title: 1
341
- }
342
- }
343
- ],
344
- as: "referrerPerson"
345
- }
346
- },
355
+ ],
356
+ as: "referrerPerson"
357
+ }
358
+ },
347
359
 
348
- // get documents
349
- {
350
- $lookup:
351
- {
352
- from: "documents",
353
- let: { docIds: { $ifNull: ["$documents", []] } },
354
- pipeline: [
355
- {
356
- $match: {
357
- $expr: {
358
- $in: ["$_id", "$$docIds"]
360
+ // get documents
361
+ {
362
+ $lookup:
363
+ {
364
+ from: "documents",
365
+ let: { docIds: { $ifNull: ["$documents", []] } },
366
+ pipeline: [
367
+ {
368
+ $match: {
369
+ $expr: {
370
+ $in: ["$_id", "$$docIds"]
371
+ }
372
+ }
373
+ },
374
+ {
375
+ $project: {
376
+ name: 1,
377
+ type: 1,
378
+ contentType: 1,
379
+ s3: 1,
380
+ createdOn: 1,
381
+ createdBy: 1,
382
+ customer: 1
359
383
  }
360
384
  }
361
- },
362
- {
363
- $project: {
364
- name: 1,
365
- type: 1,
366
- contentType: 1,
367
- s3: 1,
368
- createdOn: 1,
369
- createdBy: 1,
370
- customer: 1
371
- }
372
- }
373
- ],
374
- as: "documents"
375
- }
376
- },
385
+ ],
386
+ as: "documents"
387
+ }
388
+ },
377
389
 
378
- // get messages
379
- {
380
- $lookup:
381
- {
382
- from: "messages",
383
- let: { messageIds: { $ifNull: ["$messages", []] } },
384
- pipeline: [
385
- {
386
- $match: {
387
- $expr: {
388
- $in: ["$_id", "$$messageIds"]
390
+ // get messages
391
+ {
392
+ $lookup:
393
+ {
394
+ from: "messages",
395
+ let: { messageIds: { $ifNull: ["$messages", []] } },
396
+ pipeline: [
397
+ {
398
+ $match: {
399
+ $expr: {
400
+ $in: ["$_id", "$$messageIds"]
401
+ }
389
402
  }
390
403
  }
391
- }
392
- ],
393
- as: "messages"
394
- }
395
- },
404
+ ],
405
+ as: "messages"
406
+ }
407
+ },
396
408
 
397
- // keep the lightweight latest-message payload for callers that use it
398
- {
399
- $lookup:
400
- {
401
- from: "messages",
402
- let: { latestMessageId: "$latestMessage" },
403
- pipeline: [
404
- {
405
- $match: {
406
- $expr: {
407
- $eq: ["$_id", "$$latestMessageId"]
409
+ // keep the lightweight latest-message payload for callers that use it
410
+ {
411
+ $lookup:
412
+ {
413
+ from: "messages",
414
+ let: { latestMessageId: "$latestMessage" },
415
+ pipeline: [
416
+ {
417
+ $match: {
418
+ $expr: {
419
+ $eq: ["$_id", "$$latestMessageId"]
420
+ }
421
+ }
422
+ },
423
+ {
424
+ $project: {
425
+ subject: 1,
426
+ originalMessageDate: 1,
427
+ createdOn: 1,
428
+ messageDate: 1
408
429
  }
409
430
  }
410
- },
411
- {
412
- $project: {
413
- subject: 1,
414
- originalMessageDate: 1,
415
- createdOn: 1,
416
- messageDate: 1
417
- }
418
- }
419
- ],
420
- as: "latestMessage"
421
- }
422
- }
423
-
424
- ];
425
-
426
- mongoose.connection.db.collection('deals').aggregate(pipeline, { allowDiskUse: true }).toArray()
427
- .then(function(results) {
431
+ ],
432
+ as: "latestMessage"
433
+ }
434
+ }
428
435
 
429
- results = Array.isArray(results) ? results : [];
436
+ ];
430
437
 
431
- _.each(results, function(result) {
438
+ let results = await mongoose.connection.db.collection('deals').aggregate(pipeline, { allowDiskUse: true }).toArray();
432
439
 
433
- if (!result) { return; }
440
+ results = Array.isArray(results) ? results : [];
434
441
 
435
- result.organization = Array.isArray(result.organization) && result.organization.length ? result.organization[0] : null;
436
- result.documents = Array.isArray(result.documents) ? result.documents : [];
437
- result.messages = Array.isArray(result.messages) ? result.messages : [];
438
- result.latestMessage = Array.isArray(result.latestMessage) && result.latestMessage.length ? result.latestMessage[0] : null;
439
- result.referrer = result.referrer || {};
440
- result.referrer.person = Array.isArray(result.referrerPerson) && result.referrerPerson.length ? result.referrerPerson[0] : null;
442
+ _.each(results, function(result) {
441
443
 
442
- if (result.referrer.person && result.referrer.person.name) {
443
- result.referrer.person.name.full = ((result.referrer.person.name.first || '') + ' ' + (result.referrer.person.name.last || '')).trim();
444
- }
444
+ if (!result) { return; }
445
445
 
446
- delete result.referrerPerson;
446
+ result.organization = Array.isArray(result.organization) && result.organization.length ? result.organization[0] : null;
447
+ result.documents = Array.isArray(result.documents) ? result.documents : [];
448
+ result.messages = Array.isArray(result.messages) ? result.messages : [];
449
+ result.latestMessage = Array.isArray(result.latestMessage) && result.latestMessage.length ? result.latestMessage[0] : null;
450
+ result.referrer = result.referrer || {};
451
+ result.referrer.person = Array.isArray(result.referrerPerson) && result.referrerPerson.length ? result.referrerPerson[0] : null;
447
452
 
448
- });
453
+ if (result.referrer.person && result.referrer.person.name) {
454
+ result.referrer.person.name.full = ((result.referrer.person.name.first || '') + ' ' + (result.referrer.person.name.last || '')).trim();
455
+ }
449
456
 
450
- return cb(null, results);
457
+ delete result.referrerPerson;
451
458
 
452
- })
453
- .catch(function(err) {
454
- return cb(err, null);
455
459
  });
456
460
 
457
- }
461
+ return cb(null, results);
462
+ } catch(err) {
463
+ return cb(err, null);
464
+ }
458
465
 
459
- Deal.statics.getByReferrer = function (personId, options, cb) {
466
+ }
460
467
 
461
- let self = this;
468
+ Deal.statics.getByReferrer = async function (personId, options, cb) {
462
469
 
463
470
  if (!cb) { throw new Error('cb is required'); }
464
471
  if (!personId) { return cb(new Error('personId is required'), null); }
@@ -467,21 +474,24 @@ module.exports = function(mongoose, config) {
467
474
  if (!options.CUSTOMER_ID) { return cb(new Error('options.CUSTOMER_ID is required'), null); }
468
475
  if (!mongoose.Types.ObjectId.isValid(options.CUSTOMER_ID)) { return cb(new Error('options.CUSTOMER_ID is not a valid ObjectId'), null); }
469
476
 
470
- let query = self.find({
471
- 'referrer.person': personId,
472
- 'customer': options.CUSTOMER_ID
473
- });
477
+ try {
478
+ let query = this.find({
479
+ 'referrer.person': personId,
480
+ 'customer': options.CUSTOMER_ID
481
+ });
474
482
 
475
- query.populate({ path: 'documents', match: { customer: options.CUSTOMER_ID } });
476
- query.populate({ path: 'messages', match: { customer: options.CUSTOMER_ID } });
477
- query.populate('organization', 'name aliases description logoUrl website websiteAliases');
478
- query.exec().then(function(result) { cb(null, result); }).catch(function(err) { cb(err); });
483
+ query.populate({ path: 'documents', match: { customer: options.CUSTOMER_ID } });
484
+ query.populate({ path: 'messages', match: { customer: options.CUSTOMER_ID } });
485
+ query.populate('organization', 'name aliases description logoUrl website websiteAliases');
486
+ const result = await query;
487
+ return cb(null, result);
488
+ } catch(err) {
489
+ return cb(err);
490
+ }
479
491
 
480
492
  };
481
493
 
482
- Deal.statics.getByApplication = function (application, options, cb) {
483
-
484
- let self = this;
494
+ Deal.statics.getByApplication = async function (application, options, cb) {
485
495
 
486
496
  if (!cb) { throw new Error('cb is required'); }
487
497
  if (!application) { return cb(new Error('application is required'), null); }
@@ -489,20 +499,23 @@ module.exports = function(mongoose, config) {
489
499
  if (!options.CUSTOMER_ID) { return cb(new Error('options.CUSTOMER_ID is required'), null); }
490
500
  if (!mongoose.Types.ObjectId.isValid(options.CUSTOMER_ID)) { return cb(new Error('options.CUSTOMER_ID is not a valid ObjectId'), null); }
491
501
 
492
- let query = self.find({
493
- 'applications.application': application,
494
- 'customer': options.CUSTOMER_ID
495
- });
502
+ try {
503
+ let query = this.find({
504
+ 'applications.application': application,
505
+ 'customer': options.CUSTOMER_ID
506
+ });
496
507
 
497
- query.populate('organization', 'name description');
498
- query.exec().then(function(result) { cb(null, result); }).catch(function(err) { cb(err); });
508
+ query.populate('organization', 'name description');
509
+ const result = await query;
510
+ return cb(null, result);
511
+ } catch(err) {
512
+ return cb(err);
513
+ }
499
514
 
500
515
  };
501
516
 
502
517
  // Get a deal for a org, belonging to current customer
503
- Deal.statics.getForOrg = function (orgId, options, cb) {
504
-
505
- const self = this;
518
+ Deal.statics.getForOrg = async function (orgId, options, cb) {
506
519
 
507
520
  if (!cb) { throw new Error('cb is required'); }
508
521
  if (!orgId) { return cb(new Error('orgId is required'), null); }
@@ -511,42 +524,48 @@ module.exports = function(mongoose, config) {
511
524
  if (!options.CUSTOMER_ID) { return cb(new Error('options.CUSTOMER_ID is required'), null); }
512
525
  if (!mongoose.Types.ObjectId.isValid(options.CUSTOMER_ID)) { return cb(new Error('options.CUSTOMER_ID is not a valid ObjectId'), null); }
513
526
 
514
- let query = self.findOne({
515
- 'organization': orgId,
516
- 'customer': options.CUSTOMER_ID
517
- });
527
+ try {
528
+ let query = this.findOne({
529
+ 'organization': orgId,
530
+ 'customer': options.CUSTOMER_ID
531
+ });
518
532
 
519
- query.populate({ path: 'documents', match: { customer: options.CUSTOMER_ID } });
520
- query.populate({ path: 'messages', match: { customer: options.CUSTOMER_ID } });
521
- query.populate('organization', 'name aliases logoUrl website websiteAliases');
522
- query.populate('referrer.person', 'name avatarUrl title');
523
- query.exec().then(function(result) { cb(null, result); }).catch(function(err) { cb(err); });
533
+ query.populate({ path: 'documents', match: { customer: options.CUSTOMER_ID } });
534
+ query.populate({ path: 'messages', match: { customer: options.CUSTOMER_ID } });
535
+ query.populate('organization', 'name aliases logoUrl website websiteAliases');
536
+ query.populate('referrer.person', 'name avatarUrl title');
537
+ const result = await query;
538
+ return cb(null, result);
539
+ } catch(err) {
540
+ return cb(err);
541
+ }
524
542
 
525
543
  };
526
544
 
527
- Deal.statics.getOrgsForCustomer = function (customerId, options, cb) {
528
-
529
- let self = this;
545
+ Deal.statics.getOrgsForCustomer = async function (customerId, options, cb) {
530
546
 
531
547
  if (!cb) { throw new Error('cb is required'); }
532
548
  if (!customerId) { return cb(new Error('customerId is required'), null); }
533
549
  if (!mongoose.Types.ObjectId.isValid(customerId)) { return cb(new Error('customerId is not a valid ObjectId'), null); }
534
550
 
535
- options = options || {};
551
+ try {
552
+ options = options || {};
536
553
 
537
- let query = self.find({ 'customer': customerId });
538
- query.select('organization');
539
- query.exec().then(function(result) { cb(null, result); }).catch(function(err) { cb(err); });
554
+ let query = this.find({ 'customer': customerId });
555
+ query.select('organization');
556
+ const result = await query;
557
+ return cb(null, result);
558
+ } catch(err) {
559
+ return cb(err);
560
+ }
540
561
 
541
562
  };
542
563
 
543
- Deal.statics.modifyById = function(id, update, options, cb) {
564
+ Deal.statics.modifyById = async function(id, update, options, cb) {
544
565
 
545
566
  // VERY IMPORTANT NOTE
546
567
  // findByIdAndUpdate and findOneAndUpdate do not trigger pre-save hook so that code will not run here
547
568
 
548
- let self = this;
549
-
550
569
  if (!cb) { throw new Error('cb is required'); }
551
570
  if (!id) { return cb(new Error('id is required'), null); }
552
571
  if (!mongoose.Types.ObjectId.isValid(id)) { return cb(new Error('id is not a valid ObjectId'), null); }
@@ -555,15 +574,20 @@ module.exports = function(mongoose, config) {
555
574
  if (!options.CUSTOMER_ID) { return cb(new Error('options.CUSTOMER_ID is required'), null); }
556
575
  if (!mongoose.Types.ObjectId.isValid(options.CUSTOMER_ID)) { return cb(new Error('options.CUSTOMER_ID is not a valid ObjectId'), null); }
557
576
 
558
- // https://mongoosejs.com/docs/api.html#model_Model.findOneAndUpdate
559
- // options runValidators defaults false which is ok since we have upsert false
560
- // new returns the updated document
577
+ try {
578
+ // https://mongoosejs.com/docs/api.html#model_Model.findOneAndUpdate
579
+ // options runValidators defaults false which is ok since we have upsert false
580
+ // new returns the updated document
561
581
 
562
- let query = self.findOneAndUpdate({ _id: id, customer: options.CUSTOMER_ID }, update, { upsert: false, new: true });
582
+ let query = this.findOneAndUpdate({ _id: id, customer: options.CUSTOMER_ID }, update, { upsert: false, new: true });
563
583
 
564
- // No population so no need to scrub
584
+ // No population so no need to scrub
565
585
 
566
- query.exec().then(function(result) { cb(null, result); }).catch(function(err) { cb(err); });
586
+ const result = await query;
587
+ return cb(null, result);
588
+ } catch(err) {
589
+ return cb(err);
590
+ }
567
591
 
568
592
  };
569
593
 
@@ -575,30 +599,33 @@ module.exports = function(mongoose, config) {
575
599
 
576
600
  // The upsert piece is unusually complicated for an update query but it is necessary in order to have an atomic transaction
577
601
 
578
- const self = this;
579
-
580
602
  // Remove this user's vote for this deal
581
- const removePollItem = function(id, path, voterid, callback) {
603
+ const removePollItem = async function(id, path, voterid, callback) {
582
604
 
583
605
  // Dynamic custom field name requires building object this way, rather than { 'customField.' + key: value }
584
606
  let pull = {};
585
607
  pull[path] = { voter: voterid };
586
608
 
587
- const query = self.updateOne(
588
- {
589
- '_id': id,
590
- customer: customerId
591
- },
592
- { $pull: pull },
593
- { upsert: false, new: true }
594
- );
595
-
596
- query.exec().then(function(result) { callback(null, result); }).catch(function(err) { callback(err); });
609
+ try {
610
+ const query = this.updateOne(
611
+ {
612
+ '_id': id,
613
+ customer: customerId
614
+ },
615
+ { $pull: pull },
616
+ { upsert: false, new: true }
617
+ );
618
+
619
+ const result = await query;
620
+ return callback(null, result);
621
+ } catch(err) {
622
+ return callback(err);
623
+ }
597
624
 
598
- }
625
+ }.bind(this);
599
626
 
600
627
  // Add or update this user's vote for this deal
601
- const upsertPollItem = function(id, path, voterid, vote, callback) {
628
+ const upsertPollItem = async function(id, path, voterid, vote, callback) {
602
629
 
603
630
  const pollItem = {
604
631
  voter: voterid,
@@ -650,21 +677,26 @@ module.exports = function(mongoose, config) {
650
677
  }
651
678
  };
652
679
 
653
- const query = self.updateOne(
654
- {
655
- '_id': id,
656
- customer: customerId
657
- },
658
- [
659
- { $addFields: addFields },
660
- { $set: set }
661
- ], // must be part of aggregation pipeline for conditions to work
662
- { upsert: false, new: true }
663
- );
664
-
665
- query.exec().then(function(result) { callback(null, result); }).catch(function(err) { callback(err); });
680
+ try {
681
+ const query = this.updateOne(
682
+ {
683
+ '_id': id,
684
+ customer: customerId
685
+ },
686
+ [
687
+ { $addFields: addFields },
688
+ { $set: set }
689
+ ], // must be part of aggregation pipeline for conditions to work
690
+ { upsert: false, new: true }
691
+ );
692
+
693
+ const result = await query;
694
+ return callback(null, result);
695
+ } catch(err) {
696
+ return callback(err);
697
+ }
666
698
 
667
- }
699
+ }.bind(this);
668
700
 
669
701
  // Save the action in the deal's history
670
702
  // todo - I can't figure a way to do it in a single transaction, so bonus points to anyone that can...
@@ -672,7 +704,7 @@ module.exports = function(mongoose, config) {
672
704
  // update requires aggregation pipeline but doesn't recognize $push stage
673
705
  // removing aggregation allows $push to work, but the $cond update doesn't
674
706
  // commence spinning in circles...
675
- const saveHistory = function(err, result) {
707
+ const saveHistory = async function(err, result) {
676
708
 
677
709
  if (err) return cb(err);
678
710
 
@@ -689,18 +721,23 @@ module.exports = function(mongoose, config) {
689
721
  description: 'The deal details were updated'
690
722
  };
691
723
 
692
- const query = self.updateOne(
693
- {
694
- '_id': id,
695
- customer: customerId
696
- },
697
- { $push: { history: historyItem } },
698
- { upsert: false, new: true }
699
- );
700
-
701
- query.exec().then(function(result) { cb(null, result); }).catch(function(err) { cb(err); });
724
+ try {
725
+ const query = this.updateOne(
726
+ {
727
+ '_id': id,
728
+ customer: customerId
729
+ },
730
+ { $push: { history: historyItem } },
731
+ { upsert: false, new: true }
732
+ );
733
+
734
+ const result = await query;
735
+ return cb(null, result);
736
+ } catch(err) {
737
+ return cb(err);
738
+ }
702
739
 
703
- }
740
+ }.bind(this);
704
741
 
705
742
  if (!cb) { throw new Error('cb is required'); }
706
743
  if (!id) { return cb(new Error('id is required'), null); }
@@ -719,9 +756,7 @@ module.exports = function(mongoose, config) {
719
756
 
720
757
  };
721
758
 
722
- Deal.statics.modifyProperty = function modifyProperty(id, key, value, customerId, options, cb) {
723
-
724
- const self = this;
759
+ Deal.statics.modifyProperty = async function modifyProperty(id, key, value, customerId, options, cb) {
725
760
 
726
761
  if (!cb) { throw new Error('cb is required'); }
727
762
  if (!id) { return cb(new Error('id is required'), null); }
@@ -730,33 +765,38 @@ module.exports = function(mongoose, config) {
730
765
  if (!customerId) { return cb(new Error('customerId is required'), null); }
731
766
  if (!mongoose.Types.ObjectId.isValid(customerId)) { return cb(new Error('customerId is not a valid ObjectId'), null); }
732
767
 
733
- let keyValue = {};
734
- keyValue[key] = value;
768
+ try {
769
+ let keyValue = {};
770
+ keyValue[key] = value;
735
771
 
736
- const historyItem = {
737
- timestamp: new Date(),
738
- account: options.account,
739
- stage: null,
740
- description: 'The deal details were updated'
741
- };
772
+ const historyItem = {
773
+ timestamp: new Date(),
774
+ account: options.account,
775
+ stage: null,
776
+ description: 'The deal details were updated'
777
+ };
742
778
 
743
- const update = {
744
- $set: keyValue,
745
- $push: { history: historyItem }
746
- };
779
+ const update = {
780
+ $set: keyValue,
781
+ $push: { history: historyItem }
782
+ };
747
783
 
748
- const match = {
749
- _id: id,
750
- customer: customerId
751
- };
784
+ const match = {
785
+ _id: id,
786
+ customer: customerId
787
+ };
752
788
 
753
- const query = self.updateOne(match, update, { upsert: false, new: true });
789
+ const query = this.updateOne(match, update, { upsert: false, new: true });
754
790
 
755
- query.exec().then(function(result) { cb(null, result); }).catch(function(err) { cb(err); });
791
+ const result = await query;
792
+ return cb(null, result);
793
+ } catch(err) {
794
+ return cb(err);
795
+ }
756
796
 
757
797
  };
758
798
 
759
- Deal.statics.upsert = function upsert(deal, options, cb) {
799
+ Deal.statics.upsert = async function upsert(deal, options, cb) {
760
800
 
761
801
  // Deal is dumb and doesn't validate customer stages or duplicate deals. That responsibility is with the org.
762
802
 
@@ -831,11 +871,16 @@ module.exports = function(mongoose, config) {
831
871
 
832
872
  // Required for mixed types
833
873
  deal.markModified('customFields');
834
-
835
- deal.save().then(function(result) { cb(null, result); }).catch(function(err) { cb(err); });
874
+
875
+ try {
876
+ const result = await deal.save();
877
+ return cb(null, result);
878
+ } catch(err) {
879
+ return cb(err);
880
+ }
836
881
 
837
882
  };
838
-
883
+
839
884
  ///////////////////////////////////////////////////////////////////////////////////////
840
885
  // CONFIG
841
886
  ///////////////////////////////////////////////////////////////////////////////////////