@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/Account.js +120 -109
- package/lib/Activity.js +23 -13
- package/lib/ApiKey.js +24 -21
- package/lib/CalendarEvent.js +100 -61
- package/lib/CapTable.js +148 -107
- package/lib/Deal.js +409 -364
- package/lib/DiffbotArticle.js +21 -15
- package/lib/DiffbotOrganization.js +21 -15
- package/lib/Document.js +60 -44
- package/lib/Event.js +38 -21
- package/lib/EventAttendee.js +29 -17
- package/lib/Financials.js +400 -367
- package/lib/FinancialsAnalysis.js +49 -38
- package/lib/Flag.js +42 -35
- package/lib/Folder.js +33 -20
- package/lib/Fund.js +103 -74
- package/lib/Interaction.js +182 -141
- package/lib/Investment.js +58 -49
- package/lib/LimitedPartner.js +241 -241
- package/lib/LimitedPartnerCampaign.js +59 -49
- package/lib/LimitedPartnerCommunication.js +91 -77
- package/lib/LimitedPartnerContactGroup.js +31 -33
- package/lib/LimitedPartnerReportGenerator.js +13 -9
- package/lib/List.js +68 -42
- package/lib/Meeting.js +56 -33
- package/lib/Message.js +225 -173
- package/lib/MessageRecipient.js +42 -31
- package/lib/News.js +30 -19
- package/lib/Note.js +40 -33
- package/lib/Organization.js +570 -506
- package/lib/Person.js +281 -246
- package/lib/Rate.js +24 -17
- package/lib/Round.js +309 -311
- package/lib/Snapshot.js +14 -9
- package/lib/Sync.js +19 -11
- package/lib/Webhook.js +8 -3
- package/package.json +1 -1
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
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
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
|
-
|
|
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()
|
|
139
|
-
|
|
140
|
-
}
|
|
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
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
154
|
+
try {
|
|
155
|
+
let query = this.findOne({
|
|
156
|
+
'_id': id,
|
|
157
|
+
'customer': options.CUSTOMER_ID
|
|
158
|
+
});
|
|
159
159
|
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
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
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
180
|
+
try {
|
|
181
|
+
let query = this.find({
|
|
182
|
+
customer: options.CUSTOMER_ID,
|
|
183
|
+
'_id': { $in : ids }
|
|
184
|
+
});
|
|
182
185
|
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
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
|
-
|
|
205
|
+
try {
|
|
206
|
+
options = options || {};
|
|
201
207
|
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
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
|
-
|
|
221
|
+
let query = this.find(terms);
|
|
216
222
|
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
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
|
-
|
|
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
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
246
|
+
try {
|
|
247
|
+
let query = this.find({
|
|
248
|
+
customer: customerId,
|
|
249
|
+
lastUpdated: { $gte: updatedSince }
|
|
250
|
+
});
|
|
242
251
|
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
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
|
-
|
|
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
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
if(options.added
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
if(options.updated
|
|
286
|
-
|
|
287
|
-
|
|
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
|
-
|
|
302
|
+
let pipeline = [
|
|
291
303
|
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
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
|
-
//
|
|
297
|
-
//
|
|
298
|
-
//
|
|
299
|
-
// }
|
|
300
|
-
//
|
|
301
|
-
|
|
302
|
-
//
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
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
|
-
|
|
338
|
-
|
|
339
|
-
avatarUrl: 1,
|
|
340
|
-
title: 1
|
|
341
|
-
}
|
|
342
|
-
}
|
|
343
|
-
],
|
|
344
|
-
as: "referrerPerson"
|
|
345
|
-
}
|
|
346
|
-
},
|
|
355
|
+
],
|
|
356
|
+
as: "referrerPerson"
|
|
357
|
+
}
|
|
358
|
+
},
|
|
347
359
|
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
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
|
-
|
|
364
|
-
|
|
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
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
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
|
-
|
|
394
|
-
|
|
395
|
-
},
|
|
404
|
+
],
|
|
405
|
+
as: "messages"
|
|
406
|
+
}
|
|
407
|
+
},
|
|
396
408
|
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
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
|
-
|
|
413
|
-
|
|
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
|
-
|
|
436
|
+
];
|
|
430
437
|
|
|
431
|
-
|
|
438
|
+
let results = await mongoose.connection.db.collection('deals').aggregate(pipeline, { allowDiskUse: true }).toArray();
|
|
432
439
|
|
|
433
|
-
|
|
440
|
+
results = Array.isArray(results) ? results : [];
|
|
434
441
|
|
|
435
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
466
|
+
}
|
|
460
467
|
|
|
461
|
-
|
|
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
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
477
|
+
try {
|
|
478
|
+
let query = this.find({
|
|
479
|
+
'referrer.person': personId,
|
|
480
|
+
'customer': options.CUSTOMER_ID
|
|
481
|
+
});
|
|
474
482
|
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
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
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
502
|
+
try {
|
|
503
|
+
let query = this.find({
|
|
504
|
+
'applications.application': application,
|
|
505
|
+
'customer': options.CUSTOMER_ID
|
|
506
|
+
});
|
|
496
507
|
|
|
497
|
-
|
|
498
|
-
|
|
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
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
527
|
+
try {
|
|
528
|
+
let query = this.findOne({
|
|
529
|
+
'organization': orgId,
|
|
530
|
+
'customer': options.CUSTOMER_ID
|
|
531
|
+
});
|
|
518
532
|
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
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
|
-
|
|
551
|
+
try {
|
|
552
|
+
options = options || {};
|
|
536
553
|
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
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
|
-
|
|
559
|
-
|
|
560
|
-
|
|
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
|
-
|
|
582
|
+
let query = this.findOneAndUpdate({ _id: id, customer: options.CUSTOMER_ID }, update, { upsert: false, new: true });
|
|
563
583
|
|
|
564
|
-
|
|
584
|
+
// No population so no need to scrub
|
|
565
585
|
|
|
566
|
-
|
|
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
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
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
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
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
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
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
|
-
|
|
734
|
-
|
|
768
|
+
try {
|
|
769
|
+
let keyValue = {};
|
|
770
|
+
keyValue[key] = value;
|
|
735
771
|
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
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
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
779
|
+
const update = {
|
|
780
|
+
$set: keyValue,
|
|
781
|
+
$push: { history: historyItem }
|
|
782
|
+
};
|
|
747
783
|
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
784
|
+
const match = {
|
|
785
|
+
_id: id,
|
|
786
|
+
customer: customerId
|
|
787
|
+
};
|
|
752
788
|
|
|
753
|
-
|
|
789
|
+
const query = this.updateOne(match, update, { upsert: false, new: true });
|
|
754
790
|
|
|
755
|
-
|
|
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
|
-
|
|
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
|
///////////////////////////////////////////////////////////////////////////////////////
|