@dhyasama/totem-models 1.0.0 → 1.6.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/index.js +18 -6
- package/lib/Account.js +13 -58
- package/lib/CapTable.js +397 -0
- package/lib/Fund.js +56 -12
- package/lib/Investment.js +143 -0
- package/lib/LimitedPartner.js +0 -50
- package/lib/List.js +1 -2
- package/lib/News.js +8 -61
- package/lib/Organization.js +520 -504
- package/lib/Person.js +49 -94
- package/lib/Round.js +805 -0
- package/package.json +4 -3
- package/test/CapTable.js +359 -0
- package/test/Investment.js +180 -0
- package/test/News.js +20 -46
- package/test/Organization.js +100 -30
- package/test/Person.js +0 -48
- package/test/Round.js +684 -0
package/lib/Organization.js
CHANGED
|
@@ -2,8 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
module.exports = function(mongoose, config) {
|
|
4
4
|
|
|
5
|
-
var LPS_ENABLED = config.LPS_ENABLED || false;
|
|
6
|
-
|
|
7
5
|
var
|
|
8
6
|
|
|
9
7
|
_ = require('underscore'),
|
|
@@ -12,6 +10,8 @@ module.exports = function(mongoose, config) {
|
|
|
12
10
|
Schema = mongoose.Schema,
|
|
13
11
|
Note = mongoose.model('Note'),
|
|
14
12
|
|
|
13
|
+
customerPortfolio = [],
|
|
14
|
+
|
|
15
15
|
Organization = new Schema({
|
|
16
16
|
|
|
17
17
|
name: { type: String, required: true, index: true },
|
|
@@ -64,6 +64,7 @@ module.exports = function(mongoose, config) {
|
|
|
64
64
|
title: { type: String, default: null, trim: true },
|
|
65
65
|
current: { type: Boolean, default: false, index: true },
|
|
66
66
|
leader: { type: Boolean, default: false, index: true },
|
|
67
|
+
public: { type: Boolean, default: true },
|
|
67
68
|
board: { type: String, enum: ['chairman', 'director', 'observer', 'none'], default: 'none', index: true }
|
|
68
69
|
}],
|
|
69
70
|
|
|
@@ -114,10 +115,6 @@ module.exports = function(mongoose, config) {
|
|
|
114
115
|
url: { type: String, unique: true, sparse: true, trim: true }
|
|
115
116
|
},
|
|
116
117
|
|
|
117
|
-
eshares: {
|
|
118
|
-
companyid: { type: String, unique: true, sparse: true, trim: true }
|
|
119
|
-
},
|
|
120
|
-
|
|
121
118
|
related: [{ type: Schema.ObjectId, ref: 'Organization' }],
|
|
122
119
|
|
|
123
120
|
// customer specific (customer id is stored on note)
|
|
@@ -172,219 +169,238 @@ module.exports = function(mongoose, config) {
|
|
|
172
169
|
// Funds belonging to this organization (which is typically, but not necessarily, what we'd call an investor)
|
|
173
170
|
// An example of a non-"investor" with funds would be Slack with it's Slack Fund
|
|
174
171
|
// Another way to put it, these are funds from which this organization makes investments
|
|
175
|
-
funds: [{ type: Schema.ObjectId, ref: 'Fund' }]
|
|
172
|
+
funds: [{ type: Schema.ObjectId, ref: 'Fund' }]
|
|
176
173
|
|
|
177
|
-
|
|
178
|
-
capTable: [{
|
|
179
|
-
|
|
180
|
-
customer: { type: Schema.ObjectId, ref: 'Organization', required: true },
|
|
181
|
-
shares: { type: Number, default: 0 },
|
|
182
|
-
fullyDiluted: { type: Number, default: 0 },
|
|
183
|
-
asOfDate: { type: Date },
|
|
174
|
+
});
|
|
184
175
|
|
|
185
|
-
// todo - ???
|
|
186
|
-
optionsAndWarrants: {
|
|
187
|
-
unissued: { type: Number },
|
|
188
|
-
issuedToUnspecified: { type: Number }
|
|
189
|
-
}
|
|
190
176
|
|
|
191
|
-
}],
|
|
192
177
|
|
|
193
|
-
|
|
194
|
-
|
|
178
|
+
///////////////////////////////////////////////////////////////////////////////////////
|
|
179
|
+
// HELPERS
|
|
180
|
+
///////////////////////////////////////////////////////////////////////////////////////
|
|
195
181
|
|
|
196
|
-
|
|
182
|
+
var getSources = function getSources(people) {
|
|
197
183
|
|
|
198
|
-
|
|
199
|
-
|
|
184
|
+
var result = _.compact(_.pluck(people, 'person'));
|
|
185
|
+
if (result.length == 0) return [];
|
|
200
186
|
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
amountRaised: { type: Number, default: 0 },
|
|
204
|
-
closingDate: { type: Date, default: null },
|
|
187
|
+
result = _.compact(_.pluck(result, 'sources'));
|
|
188
|
+
if (result.length == 0) return [];
|
|
205
189
|
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
// This is a public list of funds/orgs that invested
|
|
209
|
-
funds: [{
|
|
190
|
+
result = _.flatten(result);
|
|
191
|
+
result = _.compact(result);
|
|
210
192
|
|
|
211
|
-
|
|
193
|
+
if (result.length == 0) return [];
|
|
194
|
+
if (mongoose.Types.ObjectId.isValid(result[0].person)) return []; // not populated
|
|
212
195
|
|
|
213
|
-
|
|
214
|
-
|
|
196
|
+
result = _.uniq(result, function(item) { return item.person._id.toString(); });
|
|
197
|
+
result = _.sortBy(result, 'interactions.count');
|
|
198
|
+
result.reverse();
|
|
199
|
+
result = _.sortBy(result, 'name.full');
|
|
215
200
|
|
|
216
|
-
|
|
217
|
-
// include because it makes filtering investments data, which is private, much easier
|
|
218
|
-
customer: { type: Schema.ObjectId, ref: 'Organization', required: false },
|
|
201
|
+
return result;
|
|
219
202
|
|
|
220
|
-
|
|
221
|
-
// this is all private data
|
|
222
|
-
investments: [{
|
|
203
|
+
};
|
|
223
204
|
|
|
224
|
-
amount: { type: Number, default: 0 },
|
|
225
|
-
date: { type: Date, default: null },
|
|
226
|
-
lead: { type: Boolean, default: false },
|
|
227
|
-
participatingPreferred: { type: Boolean, default: false },
|
|
228
|
-
pricePerShare: { type: Number, default: 0 },
|
|
229
|
-
fairMarketValue: { type: Number, default: 0 },
|
|
230
|
-
notes: { type: String, trim: true, default: null },
|
|
231
205
|
|
|
232
|
-
// note these fields are duplicative at the round level
|
|
233
|
-
// this is private data and will override the round level numbers where appropriate
|
|
234
|
-
preMoneyValuation: { type: Number, default: 0 },
|
|
235
|
-
amountRaised: { type: Number, default: 0 },
|
|
236
|
-
closingDate: { type: Date, default: null },
|
|
237
206
|
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
maturityDate: { type: Date, default: null },
|
|
243
|
-
fairMarketValue: { type: Number, default: 0 },
|
|
244
|
-
notes: { type: String, trim: true, default: null }
|
|
245
|
-
}]
|
|
207
|
+
///////////////////////////////////////////////////////////////////////////////////////
|
|
208
|
+
// VIRTUALS
|
|
209
|
+
// Properties that are not persisted to the database
|
|
210
|
+
///////////////////////////////////////////////////////////////////////////////////////
|
|
246
211
|
|
|
247
|
-
|
|
212
|
+
Organization.virtual('address.primary').get(function () {
|
|
213
|
+
var primary = _.find(this.contact.address, function(address) {
|
|
214
|
+
return address.primary;
|
|
215
|
+
});
|
|
216
|
+
return primary ? primary.address : null;
|
|
217
|
+
});
|
|
248
218
|
|
|
249
|
-
|
|
219
|
+
Organization.virtual('board.all').get(function () {
|
|
250
220
|
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
people: [{
|
|
254
|
-
person: {type: Schema.ObjectId, ref: 'Person'}
|
|
255
|
-
}]
|
|
221
|
+
var self = this;
|
|
222
|
+
var members = [];
|
|
256
223
|
|
|
257
|
-
|
|
224
|
+
_.each(self.people, function(p) {
|
|
225
|
+
var boardRole = p.board;
|
|
226
|
+
if (boardRole && boardRole != 'none') members.push(p.person);
|
|
227
|
+
});
|
|
258
228
|
|
|
229
|
+
members = _.sortBy(members, function(member) {
|
|
230
|
+
if (!member || !member.name) return null;
|
|
231
|
+
return member.name.last + member.name.first;
|
|
259
232
|
});
|
|
260
233
|
|
|
261
|
-
|
|
234
|
+
return members;
|
|
262
235
|
|
|
263
|
-
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
Organization.virtual('board.current').get(function () {
|
|
264
239
|
|
|
265
240
|
var self = this;
|
|
241
|
+
var members = [];
|
|
266
242
|
|
|
267
|
-
|
|
243
|
+
_.each(self.people, function(p) {
|
|
244
|
+
var boardRole = p.board;
|
|
245
|
+
if (p.current && boardRole && boardRole != 'none') members.push(p.person);
|
|
246
|
+
});
|
|
268
247
|
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
248
|
+
members = _.sortBy(members, function(member) {
|
|
249
|
+
if (!member || !member.name) return null;
|
|
250
|
+
return member.name.last + member.name.first;
|
|
251
|
+
});
|
|
252
|
+
|
|
253
|
+
return members;
|
|
273
254
|
|
|
274
255
|
});
|
|
275
256
|
|
|
276
|
-
Organization.virtual('
|
|
277
|
-
|
|
278
|
-
|
|
257
|
+
Organization.virtual('board.past').get(function () {
|
|
258
|
+
|
|
259
|
+
var self = this;
|
|
260
|
+
var members = [];
|
|
261
|
+
|
|
262
|
+
_.each(self.people, function(p) {
|
|
263
|
+
var boardRole = p.board;
|
|
264
|
+
if (!p.current && boardRole && boardRole != 'none') members.push(p.person);
|
|
279
265
|
});
|
|
280
|
-
|
|
266
|
+
|
|
267
|
+
members = _.sortBy(members, function(member) {
|
|
268
|
+
if (!member || !member.name) return null;
|
|
269
|
+
return member.name.last + member.name.first;
|
|
270
|
+
});
|
|
271
|
+
|
|
272
|
+
return members;
|
|
273
|
+
|
|
281
274
|
});
|
|
282
275
|
|
|
283
|
-
Organization.virtual('
|
|
276
|
+
Organization.virtual('employees.all').get(function () {
|
|
277
|
+
|
|
278
|
+
var self = this;
|
|
279
|
+
var result = [];
|
|
280
|
+
|
|
281
|
+
_.each(self.people, function(p) {
|
|
282
|
+
if (!p.leader && (!p.board || p.board == 'none')) result.push(p);
|
|
283
|
+
});
|
|
284
|
+
|
|
285
|
+
result = _.sortBy(result, function(item) {
|
|
286
|
+
if (!item.person || !item.person.name) return null;
|
|
287
|
+
return item.person.name.last + item.person.name.first;
|
|
288
|
+
});
|
|
289
|
+
|
|
290
|
+
return result;
|
|
291
|
+
|
|
292
|
+
});
|
|
284
293
|
|
|
285
|
-
|
|
286
|
-
// Sort by interactions descending, full name ascending
|
|
294
|
+
Organization.virtual('employees.current').get(function () {
|
|
287
295
|
|
|
288
296
|
var self = this;
|
|
297
|
+
var result = [];
|
|
289
298
|
|
|
290
|
-
|
|
291
|
-
|
|
299
|
+
_.each(self.people, function(p) {
|
|
300
|
+
if (p.current && !p.leader && (!p.board || p.board == 'none')) result.push(p);
|
|
301
|
+
});
|
|
292
302
|
|
|
293
|
-
result = _.
|
|
294
|
-
|
|
303
|
+
result = _.sortBy(result, function(item) {
|
|
304
|
+
if (!item.person || !item.person.name) return null;
|
|
305
|
+
return item.person.name.last + item.person.name.first;
|
|
306
|
+
});
|
|
295
307
|
|
|
296
|
-
|
|
297
|
-
result = _.compact(result);
|
|
308
|
+
return result;
|
|
298
309
|
|
|
299
|
-
|
|
300
|
-
if (mongoose.Types.ObjectId.isValid(result[0].person)) return []; // not populated
|
|
310
|
+
});
|
|
301
311
|
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
result =
|
|
312
|
+
Organization.virtual('employees.past').get(function () {
|
|
313
|
+
|
|
314
|
+
var self = this;
|
|
315
|
+
var result = [];
|
|
316
|
+
|
|
317
|
+
_.each(self.people, function(p) {
|
|
318
|
+
if (!p.current && !p.leader && (!p.board || p.board == 'none')) result.push(p);
|
|
319
|
+
});
|
|
320
|
+
|
|
321
|
+
result = _.sortBy(result, function(item) {
|
|
322
|
+
if (!item.person || !item.person.name) return null;
|
|
323
|
+
return item.person.name.last + item.person.name.first;
|
|
324
|
+
});
|
|
306
325
|
|
|
307
326
|
return result;
|
|
308
327
|
|
|
309
328
|
});
|
|
310
329
|
|
|
311
|
-
|
|
330
|
+
Organization.virtual('leaders.all').get(function () {
|
|
312
331
|
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
this.merged.push(id);
|
|
316
|
-
return true;
|
|
317
|
-
}
|
|
318
|
-
else {
|
|
319
|
-
return false;
|
|
320
|
-
}
|
|
321
|
-
};
|
|
332
|
+
var self = this;
|
|
333
|
+
var result = [];
|
|
322
334
|
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
};
|
|
335
|
+
_.each(self.people, function(p) {
|
|
336
|
+
if (p.leader) result.push(p);
|
|
337
|
+
});
|
|
327
338
|
|
|
328
|
-
|
|
339
|
+
result = _.sortBy(result, function(item) {
|
|
340
|
+
if (!item.person || !item.person.name) return null;
|
|
341
|
+
return item.person.name.last + item.person.name.first;
|
|
342
|
+
});
|
|
343
|
+
|
|
344
|
+
return result;
|
|
345
|
+
|
|
346
|
+
});
|
|
347
|
+
|
|
348
|
+
Organization.virtual('leaders.current').get(function () {
|
|
329
349
|
|
|
330
350
|
var self = this;
|
|
351
|
+
var result = [];
|
|
331
352
|
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
return orgId.toString() == id.toString();
|
|
353
|
+
_.each(self.people, function(p) {
|
|
354
|
+
if (p.leader && p.current) result.push(p);
|
|
335
355
|
});
|
|
336
356
|
|
|
337
|
-
|
|
357
|
+
result = _.sortBy(result, function(item) {
|
|
358
|
+
if (!item.person || !item.person.name) return null;
|
|
359
|
+
return item.person.name.last + item.person.name.first;
|
|
360
|
+
});
|
|
338
361
|
|
|
339
|
-
|
|
362
|
+
return result;
|
|
340
363
|
|
|
341
|
-
|
|
342
|
-
Organization.methods.newBasic = function(field, value) {
|
|
364
|
+
});
|
|
343
365
|
|
|
344
|
-
|
|
345
|
-
if(field.split(".").length > 1) {
|
|
346
|
-
compoundField = true;
|
|
347
|
-
}
|
|
366
|
+
Organization.virtual('leaders.past').get(function () {
|
|
348
367
|
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
} else {
|
|
352
|
-
var parentField = field.split('.')[0];
|
|
353
|
-
var childField = field.split('.')[1];
|
|
368
|
+
var self = this;
|
|
369
|
+
var result = [];
|
|
354
370
|
|
|
355
|
-
|
|
356
|
-
|
|
371
|
+
_.each(self.people, function(p) {
|
|
372
|
+
if (p.leader && !p.current) result.push(p);
|
|
373
|
+
});
|
|
357
374
|
|
|
358
|
-
|
|
375
|
+
result = _.sortBy(result, function(item) {
|
|
376
|
+
if (!item.person || !item.person.name) return null;
|
|
377
|
+
return item.person.name.last + item.person.name.first;
|
|
378
|
+
});
|
|
379
|
+
|
|
380
|
+
return result;
|
|
359
381
|
|
|
360
|
-
|
|
382
|
+
});
|
|
361
383
|
|
|
362
|
-
|
|
363
|
-
if(field.split(".").length > 1) {
|
|
364
|
-
compoundField = true;
|
|
365
|
-
}
|
|
384
|
+
Organization.virtual('status').get(function () {
|
|
366
385
|
|
|
367
|
-
|
|
368
|
-
var currentVal = this[field];
|
|
369
|
-
this[field] = value;
|
|
370
|
-
} else {
|
|
371
|
-
var parentField = field.split('.')[0];
|
|
372
|
-
var childField = field.split('.')[1];
|
|
386
|
+
var self = this;
|
|
373
387
|
|
|
374
|
-
|
|
375
|
-
this[parentField][childField] = value;
|
|
376
|
-
}
|
|
388
|
+
// infer from data
|
|
377
389
|
|
|
378
|
-
|
|
390
|
+
if (self.closedOn) return 'Dead';
|
|
391
|
+
else if (self.ipo && self.ipo.year) return 'IPO';
|
|
392
|
+
else if (self.acquisition && self.acquisition.year) return 'Acquired';
|
|
393
|
+
else return 'Active';
|
|
379
394
|
|
|
380
|
-
|
|
395
|
+
});
|
|
381
396
|
|
|
382
|
-
var parentField = field.split('.')[0];
|
|
383
|
-
var childField = field.split('.')[1];
|
|
384
397
|
|
|
385
|
-
this[parentField][childField] = value;
|
|
386
398
|
|
|
387
|
-
|
|
399
|
+
///////////////////////////////////////////////////////////////////////////////////////
|
|
400
|
+
// METHODS
|
|
401
|
+
// Methods operate on a single document that has already been returned
|
|
402
|
+
// Note that running a method on a document does not save it
|
|
403
|
+
///////////////////////////////////////////////////////////////////////////////////////
|
|
388
404
|
|
|
389
405
|
Organization.methods.addPerson = function(personToAdd) {
|
|
390
406
|
|
|
@@ -406,151 +422,375 @@ module.exports = function(mongoose, config) {
|
|
|
406
422
|
|
|
407
423
|
};
|
|
408
424
|
|
|
409
|
-
Organization.methods.
|
|
410
|
-
|
|
411
|
-
this.
|
|
412
|
-
|
|
413
|
-
return id.toString() == personIdToRemove.toString();
|
|
414
|
-
});
|
|
425
|
+
Organization.methods.deleteOrg = function() {
|
|
426
|
+
// Soft delete
|
|
427
|
+
this.deleted = true;
|
|
428
|
+
};
|
|
415
429
|
|
|
430
|
+
Organization.methods.merge = function(id) {
|
|
431
|
+
if (this.merged.indexOf(id) == -1) {
|
|
432
|
+
this.merged.push(id);
|
|
433
|
+
return true;
|
|
434
|
+
}
|
|
435
|
+
else {
|
|
436
|
+
return false;
|
|
437
|
+
}
|
|
416
438
|
};
|
|
417
439
|
|
|
418
|
-
Organization.methods.
|
|
440
|
+
Organization.methods.relateOrg = function(id) {
|
|
419
441
|
|
|
420
442
|
var self = this;
|
|
421
443
|
|
|
422
|
-
|
|
444
|
+
var match = _.find(self.related, function(org) {
|
|
445
|
+
var orgId = utils.isValidObjectId(org) ? org : org.id;
|
|
446
|
+
return orgId.toString() == id.toString();
|
|
447
|
+
});
|
|
423
448
|
|
|
424
|
-
if (!self.
|
|
449
|
+
if (!match) { self.related.push(id); }
|
|
425
450
|
|
|
426
|
-
|
|
427
|
-
self.portfolioCompany.fundsInvested = funds;
|
|
451
|
+
};
|
|
428
452
|
|
|
429
|
-
|
|
430
|
-
// TODO: The alternative is to get a list of funds and verify against that
|
|
431
|
-
// TODO: also would be good to check for dupes
|
|
432
|
-
// This is used internally, in admin, so let's punt for now
|
|
453
|
+
Organization.methods.removePerson = function(personIdToRemove) {
|
|
433
454
|
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
//});
|
|
455
|
+
this.people = _.reject(this.people, function(existingPerson) {
|
|
456
|
+
var id = utils.isValidObjectId(existingPerson.person) ? existingPerson.person : existingPerson.person._id;
|
|
457
|
+
return id.toString() == personIdToRemove.toString();
|
|
458
|
+
});
|
|
439
459
|
|
|
440
460
|
};
|
|
441
461
|
|
|
442
|
-
Organization.methods.updateChair = function(chairObj) {
|
|
443
|
-
|
|
444
|
-
var self = this;
|
|
445
462
|
|
|
446
|
-
if (!self.portfolioCompany) return;
|
|
447
463
|
|
|
448
|
-
|
|
464
|
+
//////////////////////////////////////////////////////
|
|
465
|
+
// STATICS
|
|
466
|
+
// Statics query the entire collection
|
|
467
|
+
//////////////////////////////////////////////////////
|
|
449
468
|
|
|
450
|
-
|
|
451
|
-
case 'chair1':
|
|
452
|
-
if(chairObj.val && chairObj.val != "") {
|
|
453
|
-
self.portfolioCompany.chairs.first = chairObj.val;
|
|
454
|
-
} else {
|
|
455
|
-
self.portfolioCompany.chairs.first = {};
|
|
456
|
-
}
|
|
457
|
-
break;
|
|
469
|
+
Organization.statics.addNote = function(organizationId, creatorPersonId, text, cb) {
|
|
458
470
|
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
self.portfolioCompany.chairs.second = {}
|
|
464
|
-
}
|
|
465
|
-
break;
|
|
466
|
-
}
|
|
471
|
+
Note.createForModel({
|
|
472
|
+
createdBy: creatorPersonId,
|
|
473
|
+
text: text
|
|
474
|
+
}, this, organizationId, cb);
|
|
467
475
|
|
|
468
476
|
};
|
|
469
477
|
|
|
470
|
-
|
|
471
|
-
|
|
478
|
+
Organization.statics.deleteNote = function(noteId, cb) {
|
|
479
|
+
|
|
480
|
+
// Delete the note itself along with any references
|
|
472
481
|
|
|
473
482
|
var self = this;
|
|
474
483
|
|
|
475
|
-
|
|
484
|
+
var removeReferences = function removeReferences(callback) {
|
|
485
|
+
self.update({}, {
|
|
486
|
+
$pull: { 'notes' : [noteId] }
|
|
487
|
+
}, callback);
|
|
488
|
+
};
|
|
476
489
|
|
|
477
|
-
|
|
490
|
+
async.series([
|
|
491
|
+
Note.delete.bind(Note, noteId),
|
|
492
|
+
removeReferences
|
|
493
|
+
], function(err, results) {
|
|
494
|
+
return cb(err, null);
|
|
495
|
+
});
|
|
478
496
|
|
|
479
497
|
};
|
|
480
498
|
|
|
481
|
-
Organization.
|
|
499
|
+
Organization.statics.findByDomains = function findByDomains(domains, cb) {
|
|
500
|
+
var query = this.find({ $or: [ {'website': { $in : domains }}, {'websiteAliases': { $in : domains }} ], 'deleted': {$ne: true} });
|
|
501
|
+
query.exec(cb);
|
|
502
|
+
};
|
|
482
503
|
|
|
504
|
+
Organization.statics.findByFunds = function findByFunds(fundids, cb) {
|
|
483
505
|
var self = this;
|
|
506
|
+
self
|
|
507
|
+
.find({ 'funds': { $in : fundids }, 'deleted': {$ne: true} })
|
|
508
|
+
.select('name logoUrl')
|
|
509
|
+
.exec(cb);
|
|
510
|
+
};
|
|
484
511
|
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
if (!self.portfolioCompany) return;
|
|
488
|
-
|
|
489
|
-
if(self.portfolioCompany.investments.length > 0) {
|
|
490
|
-
self.portfolioCompany.investments = _.reject(self.portfolioCompany.investments, function(i) {
|
|
491
|
-
return String(i.source) == String(investor._id);
|
|
492
|
-
});
|
|
493
|
-
}
|
|
512
|
+
Organization.statics.findByIds = function findByIds(ids, cb) {
|
|
494
513
|
|
|
495
|
-
|
|
496
|
-
self.portfolioCompany.debts = _.reject(self.portfolioCompany.debts, function(d) {
|
|
497
|
-
return String(d.source) == String(investor._id);
|
|
498
|
-
});
|
|
499
|
-
}
|
|
514
|
+
var self = this;
|
|
500
515
|
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
516
|
+
self
|
|
517
|
+
.find({ '_id': { $in : ids }})
|
|
518
|
+
.populate('people.person', 'name avatarUrl title calendarEventSummaries sources')
|
|
519
|
+
.populate('related', 'name logoUrl')
|
|
520
|
+
.populate('notes')
|
|
521
|
+
.populate('chairs.first', 'name avatarUrl title')
|
|
522
|
+
.populate('chairs.second', 'name avatarUrl title')
|
|
523
|
+
.populate('funds', 'name hexColorCode')
|
|
524
|
+
.deepPopulate([
|
|
525
|
+
'people.person.sources.person',
|
|
526
|
+
'people.person.calendarEventSummaries.attendees.internal',
|
|
527
|
+
'people.person.calendarEventSummaries.attendees.external',
|
|
528
|
+
'people.person.calendarEventSummaries.notes.createdBy',
|
|
529
|
+
'notes.createdBy'
|
|
530
|
+
], {
|
|
531
|
+
populate: {
|
|
532
|
+
'people.person.sources.person': { select: 'name avatarUrl title' },
|
|
533
|
+
'people.person.calendarEventSummaries.attendees.internal': { select: 'name avatarUrl title' },
|
|
534
|
+
'people.person.calendarEventSummaries.attendees.external': { select: 'name avatarUrl title' },
|
|
535
|
+
'people.person.calendarEventSummaries.notes.createdBy': { select: 'name avatarUrl title' },
|
|
536
|
+
'notes.createdBy': { select: 'name avatarUrl title' }
|
|
537
|
+
}
|
|
538
|
+
})
|
|
539
|
+
.exec(cb);
|
|
506
540
|
|
|
507
541
|
};
|
|
508
542
|
|
|
509
|
-
Organization.
|
|
543
|
+
Organization.statics.findByPerson = function findByPerson(personId, cb) {
|
|
544
|
+
|
|
545
|
+
// Given a person id, get all organizations with that person
|
|
510
546
|
|
|
511
547
|
var self = this;
|
|
512
|
-
if (!self.investor) return;
|
|
513
548
|
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
549
|
+
self
|
|
550
|
+
.find({ $or:
|
|
551
|
+
[
|
|
552
|
+
{ 'people.person': personId },
|
|
553
|
+
{ 'chairs.first': personId },
|
|
554
|
+
{ 'chairs.second': personId }
|
|
555
|
+
],
|
|
556
|
+
'deleted': { $ne: true }
|
|
557
|
+
})
|
|
558
|
+
.exec(cb);
|
|
518
559
|
|
|
519
|
-
|
|
560
|
+
};
|
|
520
561
|
|
|
562
|
+
Organization.statics.findBySlug = function findBySlug(slug, cb) {
|
|
563
|
+
this.findOne({ slug: slug, 'deleted': {$ne: true} }).exec(cb);
|
|
521
564
|
};
|
|
522
565
|
|
|
523
|
-
Organization.
|
|
566
|
+
Organization.statics.findBySlugs = function findBySlugs(slugs, cb) {
|
|
567
|
+
this.find({ 'slug': { $in : slugs }, 'deleted': {$ne: true} }).exec(cb);
|
|
568
|
+
};
|
|
524
569
|
|
|
525
|
-
|
|
526
|
-
if (!self.investor) return;
|
|
570
|
+
Organization.statics.findDupes = function findDupes(org, options, cb) {
|
|
527
571
|
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
return fundId.toString() == idOfFundToAdd.toString();
|
|
531
|
-
});
|
|
572
|
+
if (!cb) throw new Error('cb is required');
|
|
573
|
+
if (!org || (!org.name && !org.website)) return cb(null, []);
|
|
532
574
|
|
|
533
|
-
|
|
575
|
+
this.search({
|
|
576
|
+
name: org.name,
|
|
577
|
+
domain: utils.getDomain(org.website)
|
|
578
|
+
}, options, function(err, orgs) {
|
|
534
579
|
|
|
535
|
-
|
|
580
|
+
if (err) return cb(err, null);
|
|
581
|
+
if (!orgs) return cb(null, null);
|
|
536
582
|
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
// {
|
|
542
|
-
// domain: ''
|
|
543
|
-
// name: ''
|
|
544
|
-
// }
|
|
545
|
-
// options:
|
|
546
|
-
// fuzzy: searches within strings, e.g., searching for "venture" will match "ff Venture Capital"
|
|
547
|
-
// non-fuzzy does a full-string match, e.g., "ffvc" will match "ffvc" but "ff" will not
|
|
548
|
-
// both fuzzy and non are case-insensitive
|
|
549
|
-
// queryFirstWord: tokenizes first word and searches for it
|
|
550
|
-
// removeRelatedFromTopLevel: related people are removed from top-level results
|
|
551
|
-
Organization.statics.search = function search(data, options, cb) {
|
|
583
|
+
// exclude passed in org from results
|
|
584
|
+
orgs = _.reject(orgs, function(o) {
|
|
585
|
+
return o.id == org.id;
|
|
586
|
+
});
|
|
552
587
|
|
|
553
|
-
|
|
588
|
+
return cb(null, orgs);
|
|
589
|
+
|
|
590
|
+
});
|
|
591
|
+
|
|
592
|
+
};
|
|
593
|
+
|
|
594
|
+
Organization.statics.flag = function(orgId, resolved, text, username, cb) {
|
|
595
|
+
|
|
596
|
+
this.findById(orgId).exec(function(err, org) {
|
|
597
|
+
|
|
598
|
+
org.flagged.resolved = resolved;
|
|
599
|
+
org.flagged.text = text;
|
|
600
|
+
org.flagged.by = username;
|
|
601
|
+
org.flagged.on = Date.now();
|
|
602
|
+
|
|
603
|
+
org.save(cb);
|
|
604
|
+
|
|
605
|
+
});
|
|
606
|
+
|
|
607
|
+
};
|
|
608
|
+
|
|
609
|
+
Organization.statics.getBoardsOfPerson = function getBoardsOfPerson(personId, cb) {
|
|
610
|
+
|
|
611
|
+
var self = this;
|
|
612
|
+
|
|
613
|
+
self
|
|
614
|
+
.find({
|
|
615
|
+
'deleted': { $ne: true },
|
|
616
|
+
'people': {
|
|
617
|
+
$elemMatch: {
|
|
618
|
+
'person': personId,
|
|
619
|
+
'board': { $in: ['chairman', 'director', 'observer'] }
|
|
620
|
+
}
|
|
621
|
+
}
|
|
622
|
+
})
|
|
623
|
+
.select('name avatarUrl')
|
|
624
|
+
.exec(cb);
|
|
625
|
+
|
|
626
|
+
};
|
|
627
|
+
|
|
628
|
+
Organization.statics.getByFund = function getByFund(id, cb) {
|
|
629
|
+
var self = this;
|
|
630
|
+
self
|
|
631
|
+
.findOne({ 'funds': id, 'deleted': {$ne: true} })
|
|
632
|
+
.select('name logoUrl')
|
|
633
|
+
.exec(cb);
|
|
634
|
+
};
|
|
635
|
+
|
|
636
|
+
Organization.statics.getById = function getById(id, cb) {
|
|
637
|
+
|
|
638
|
+
var self = this;
|
|
639
|
+
|
|
640
|
+
self
|
|
641
|
+
.findById(id)
|
|
642
|
+
.populate('people.person', 'name avatarUrl title calendarEventSummaries sources')
|
|
643
|
+
.populate('related', 'name logoUrl')
|
|
644
|
+
.populate('notes')
|
|
645
|
+
.populate('chairs.first', 'name avatarUrl title')
|
|
646
|
+
.populate('chairs.second', 'name avatarUrl title')
|
|
647
|
+
.populate('funds', 'name hexColorCode closeDate')
|
|
648
|
+
.deepPopulate([
|
|
649
|
+
'people.person.sources.person',
|
|
650
|
+
'people.person.calendarEventSummaries.attendees.internal',
|
|
651
|
+
'people.person.calendarEventSummaries.attendees.external',
|
|
652
|
+
'people.person.calendarEventSummaries.notes.createdBy',
|
|
653
|
+
'notes.createdBy'
|
|
654
|
+
], {
|
|
655
|
+
populate: {
|
|
656
|
+
'people.person.sources.person': { select: 'name avatarUrl title' },
|
|
657
|
+
'people.person.calendarEventSummaries.attendees.internal': { select: 'name avatarUrl title' },
|
|
658
|
+
'people.person.calendarEventSummaries.attendees.external': { select: 'name avatarUrl title' },
|
|
659
|
+
'people.person.calendarEventSummaries.notes.createdBy': { select: 'name avatarUrl title' },
|
|
660
|
+
'notes.createdBy': { select: 'name avatarUrl title' }
|
|
661
|
+
}
|
|
662
|
+
})
|
|
663
|
+
.exec(cb);
|
|
664
|
+
|
|
665
|
+
};
|
|
666
|
+
|
|
667
|
+
Organization.statics.getChairsOfPerson = function getChairsOfPerson(personId, cb) {
|
|
668
|
+
|
|
669
|
+
var self = this;
|
|
670
|
+
|
|
671
|
+
self
|
|
672
|
+
.find({ $or:
|
|
673
|
+
[
|
|
674
|
+
{ 'chairs.first': personId },
|
|
675
|
+
{ 'chairs.second': personId }
|
|
676
|
+
],
|
|
677
|
+
'deleted': { $ne: true }
|
|
678
|
+
})
|
|
679
|
+
.exec(cb);
|
|
680
|
+
|
|
681
|
+
};
|
|
682
|
+
|
|
683
|
+
Organization.statics.getSources = function(id, cb) {
|
|
684
|
+
|
|
685
|
+
var self = this;
|
|
686
|
+
|
|
687
|
+
self
|
|
688
|
+
.findById(id)
|
|
689
|
+
.populate('people.person', 'name avatarUrl title calendarEventSummaries sources')
|
|
690
|
+
.deepPopulate([
|
|
691
|
+
'people.person.sources.person'
|
|
692
|
+
], {
|
|
693
|
+
populate: {
|
|
694
|
+
'people.person.sources.person': { select: 'name avatarUrl title' }
|
|
695
|
+
}
|
|
696
|
+
})
|
|
697
|
+
.exec(function(err, org) {
|
|
698
|
+
|
|
699
|
+
if (err) return cb(err, null);
|
|
700
|
+
if (!org) return cb(null, null);
|
|
701
|
+
|
|
702
|
+
self.findById(config.CUSTOMER_ID, function(err, customer) {
|
|
703
|
+
|
|
704
|
+
if (err) return cb(err, null);
|
|
705
|
+
if (!customer) return cb(null, null);
|
|
706
|
+
|
|
707
|
+
var current = [];
|
|
708
|
+
var past = [];
|
|
709
|
+
var all = [];
|
|
710
|
+
var orgSources = getSources(org.people);
|
|
711
|
+
|
|
712
|
+
_.each(customer.people, function(p) {
|
|
713
|
+
|
|
714
|
+
var source = _.find(orgSources, function(os) {
|
|
715
|
+
return os.person._id.toString() == p.person.toString();
|
|
716
|
+
});
|
|
717
|
+
|
|
718
|
+
if (!source) return;
|
|
719
|
+
|
|
720
|
+
if (p.current) current.push(source);
|
|
721
|
+
if (!p.current) past.push(source);
|
|
722
|
+
all.push(source);
|
|
723
|
+
|
|
724
|
+
});
|
|
725
|
+
|
|
726
|
+
return cb(null, {
|
|
727
|
+
all: all,
|
|
728
|
+
current: current,
|
|
729
|
+
past: past
|
|
730
|
+
});
|
|
731
|
+
|
|
732
|
+
});
|
|
733
|
+
|
|
734
|
+
});
|
|
735
|
+
|
|
736
|
+
};
|
|
737
|
+
|
|
738
|
+
Organization.statics.listAllFlagged = function (cb) {
|
|
739
|
+
|
|
740
|
+
var query = this.find({'flagged.resolved': false, 'flagged.text': { $ne: '' }, 'deleted': {$ne: true}});
|
|
741
|
+
query.exec(function (err, orgs) {
|
|
742
|
+
|
|
743
|
+
if (err) return cb(err, null);
|
|
744
|
+
|
|
745
|
+
orgs = _.sortBy(orgs, function(org){
|
|
746
|
+
var timestamp = new Date(org.flagged.on);
|
|
747
|
+
timestamp = timestamp.getTime();
|
|
748
|
+
return timestamp;
|
|
749
|
+
});
|
|
750
|
+
orgs = orgs.reverse();
|
|
751
|
+
|
|
752
|
+
return cb(null, orgs);
|
|
753
|
+
|
|
754
|
+
});
|
|
755
|
+
|
|
756
|
+
};
|
|
757
|
+
|
|
758
|
+
Organization.statics.listPage = function (skip, cb) {
|
|
759
|
+
|
|
760
|
+
this
|
|
761
|
+
.find({'deleted': {$ne: true}})
|
|
762
|
+
.sort('name')
|
|
763
|
+
.skip(skip)
|
|
764
|
+
.limit(100)
|
|
765
|
+
.exec(cb)
|
|
766
|
+
|
|
767
|
+
};
|
|
768
|
+
|
|
769
|
+
Organization.statics.removeById = function(id, cb) {
|
|
770
|
+
|
|
771
|
+
if (!id) { return cb(new Error('id is required'), null); }
|
|
772
|
+
if (!cb) { throw new Error('cb is required'); }
|
|
773
|
+
|
|
774
|
+
this.remove({_id: id}, cb);
|
|
775
|
+
|
|
776
|
+
};
|
|
777
|
+
|
|
778
|
+
Organization.statics.search = function search(data, options, cb) {
|
|
779
|
+
|
|
780
|
+
// search for orgs based on fields provided
|
|
781
|
+
// data format, each field is optional
|
|
782
|
+
// {
|
|
783
|
+
// domain: ''
|
|
784
|
+
// name: ''
|
|
785
|
+
// }
|
|
786
|
+
// options:
|
|
787
|
+
// fuzzy: searches within strings, e.g., searching for "venture" will match "ff Venture Capital"
|
|
788
|
+
// non-fuzzy does a full-string match, e.g., "ffvc" will match "ffvc" but "ff" will not
|
|
789
|
+
// both fuzzy and non are case-insensitive
|
|
790
|
+
// queryFirstWord: tokenizes first word and searches for it
|
|
791
|
+
// removeRelatedFromTopLevel: related people are removed from top-level results
|
|
792
|
+
|
|
793
|
+
// validate input
|
|
554
794
|
if (!cb) throw new Error('cb is required');
|
|
555
795
|
if (!data || (!data.name && !data.domain)) return cb(null, []);
|
|
556
796
|
|
|
@@ -686,162 +926,16 @@ module.exports = function(mongoose, config) {
|
|
|
686
926
|
|
|
687
927
|
};
|
|
688
928
|
|
|
689
|
-
Organization.statics.
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
this.search({
|
|
695
|
-
name: org.name,
|
|
696
|
-
domain: utils.getDomain(org.website)
|
|
697
|
-
}, options, function(err, orgs) {
|
|
698
|
-
|
|
699
|
-
if (err) return cb(err, null);
|
|
700
|
-
if (!orgs) return cb(null, null);
|
|
701
|
-
|
|
702
|
-
// exclude passed in org from results
|
|
703
|
-
orgs = _.reject(orgs, function(o) {
|
|
704
|
-
return o.id == org.id;
|
|
705
|
-
});
|
|
706
|
-
|
|
707
|
-
return cb(null, orgs);
|
|
708
|
-
|
|
709
|
-
});
|
|
710
|
-
|
|
929
|
+
Organization.statics.setCustomerPortfolio = function setCustomerPortfolio(portfolio) {
|
|
930
|
+
var self = this;
|
|
931
|
+
self.customerPortfolio = portfolio;
|
|
932
|
+
return self.customerPortfolio;
|
|
711
933
|
};
|
|
712
934
|
|
|
713
935
|
Organization.statics.stats = function stats(cb) {
|
|
714
936
|
this.collection.stats(cb);
|
|
715
937
|
};
|
|
716
938
|
|
|
717
|
-
Organization.statics.findByPerson = function findByPerson(personId, cb) {
|
|
718
|
-
this.find({ 'people.person': personId, 'deleted': {$ne: true} }).exec(cb);
|
|
719
|
-
};
|
|
720
|
-
|
|
721
|
-
Organization.statics.findBySlug = function findBySlug(slug, cb) {
|
|
722
|
-
this.find({ slug: slug, 'deleted': {$ne: true} }).exec(cb);
|
|
723
|
-
};
|
|
724
|
-
|
|
725
|
-
Organization.statics.findBySlugs = function findBySlugs(slugs, cb) {
|
|
726
|
-
this.find({ 'slug': { $in : slugs }, 'deleted': {$ne: true} }).exec(cb);
|
|
727
|
-
};
|
|
728
|
-
|
|
729
|
-
Organization.statics.findByDomains = function findByDomains(domains, cb) {
|
|
730
|
-
var query = this.find({ $or: [ {'website': { $in : domains }}, {'websiteAliases': { $in : domains }} ], 'deleted': {$ne: true} });
|
|
731
|
-
query.exec(cb);
|
|
732
|
-
};
|
|
733
|
-
|
|
734
|
-
Organization.statics.findByIds = function findByIds(ids, cb) {
|
|
735
|
-
|
|
736
|
-
var self = this;
|
|
737
|
-
|
|
738
|
-
self
|
|
739
|
-
.find({ '_id': { $in : ids }})
|
|
740
|
-
.populate('people.person', 'name avatarUrl title calendarEventSummaries sources')
|
|
741
|
-
.populate('related', 'name logoUrl')
|
|
742
|
-
.populate('notes')
|
|
743
|
-
.populate('chairs.first', 'name avatarUrl title')
|
|
744
|
-
.populate('chairs.second', 'name avatarUrl title')
|
|
745
|
-
.populate('funds', 'name hexColorCode')
|
|
746
|
-
.populate('rounds.funds.fund', 'name hexColorCode')
|
|
747
|
-
.populate('rounds.funds.partner', 'name avatarUrl title')
|
|
748
|
-
.populate('rounds.people.person', 'name avatarUrl title')
|
|
749
|
-
.deepPopulate([
|
|
750
|
-
'people.person.sources.person',
|
|
751
|
-
'people.person.calendarEventSummaries.attendees.internal',
|
|
752
|
-
'people.person.calendarEventSummaries.attendees.external',
|
|
753
|
-
'people.person.calendarEventSummaries.notes.createdBy',
|
|
754
|
-
'notes.createdBy'
|
|
755
|
-
], {
|
|
756
|
-
populate: {
|
|
757
|
-
'people.person.sources.person': { select: 'name avatarUrl title' },
|
|
758
|
-
'people.person.calendarEventSummaries.attendees.internal': { select: 'name avatarUrl title' },
|
|
759
|
-
'people.person.calendarEventSummaries.attendees.external': { select: 'name avatarUrl title' },
|
|
760
|
-
'people.person.calendarEventSummaries.notes.createdBy': { select: 'name avatarUrl title' },
|
|
761
|
-
'notes.createdBy': { select: 'name avatarUrl title' }
|
|
762
|
-
}
|
|
763
|
-
})
|
|
764
|
-
.exec(cb);
|
|
765
|
-
|
|
766
|
-
};
|
|
767
|
-
|
|
768
|
-
Organization.statics.getById = function getById(id, cb) {
|
|
769
|
-
|
|
770
|
-
var self = this;
|
|
771
|
-
|
|
772
|
-
self
|
|
773
|
-
.findById(id)
|
|
774
|
-
.populate('people.person', 'name avatarUrl title calendarEventSummaries sources')
|
|
775
|
-
.populate('related', 'name logoUrl')
|
|
776
|
-
.populate('notes')
|
|
777
|
-
.populate('chairs.first', 'name avatarUrl title')
|
|
778
|
-
.populate('chairs.second', 'name avatarUrl title')
|
|
779
|
-
.populate('funds', 'name hexColorCode')
|
|
780
|
-
.populate('rounds.funds.fund', 'name hexColorCode')
|
|
781
|
-
.populate('rounds.funds.partner', 'name avatarUrl title')
|
|
782
|
-
.populate('rounds.people.person', 'name avatarUrl title')
|
|
783
|
-
.deepPopulate([
|
|
784
|
-
'people.person.sources.person',
|
|
785
|
-
'people.person.calendarEventSummaries.attendees.internal',
|
|
786
|
-
'people.person.calendarEventSummaries.attendees.external',
|
|
787
|
-
'people.person.calendarEventSummaries.notes.createdBy',
|
|
788
|
-
'notes.createdBy'
|
|
789
|
-
], {
|
|
790
|
-
populate: {
|
|
791
|
-
'people.person.sources.person': { select: 'name avatarUrl title' },
|
|
792
|
-
'people.person.calendarEventSummaries.attendees.internal': { select: 'name avatarUrl title' },
|
|
793
|
-
'people.person.calendarEventSummaries.attendees.external': { select: 'name avatarUrl title' },
|
|
794
|
-
'people.person.calendarEventSummaries.notes.createdBy': { select: 'name avatarUrl title' },
|
|
795
|
-
'notes.createdBy': { select: 'name avatarUrl title' }
|
|
796
|
-
}
|
|
797
|
-
})
|
|
798
|
-
.exec(cb);
|
|
799
|
-
|
|
800
|
-
};
|
|
801
|
-
|
|
802
|
-
Organization.statics.getPortfolio = function getPortfolio(orgId, cb) {
|
|
803
|
-
|
|
804
|
-
var self = this;
|
|
805
|
-
|
|
806
|
-
self
|
|
807
|
-
.find({ 'rounds.funds.customer': orgId })
|
|
808
|
-
.select('name logoUrl description exit filters contact.addresses')
|
|
809
|
-
.sort('name')
|
|
810
|
-
.exec(cb);
|
|
811
|
-
|
|
812
|
-
};
|
|
813
|
-
|
|
814
|
-
Organization.statics.listPage = function (skip, cb) {
|
|
815
|
-
|
|
816
|
-
this
|
|
817
|
-
.find({'deleted': {$ne: true}})
|
|
818
|
-
.sort('name')
|
|
819
|
-
.skip(skip)
|
|
820
|
-
.limit(100)
|
|
821
|
-
.exec(cb)
|
|
822
|
-
|
|
823
|
-
};
|
|
824
|
-
|
|
825
|
-
Organization.statics.listAllFlagged = function (cb) {
|
|
826
|
-
|
|
827
|
-
var query = this.find({'flagged.resolved': false, 'flagged.text': { $ne: '' }, 'deleted': {$ne: true}});
|
|
828
|
-
query.exec(function (err, orgs) {
|
|
829
|
-
|
|
830
|
-
if (err) return cb(err, null);
|
|
831
|
-
|
|
832
|
-
orgs = _.sortBy(orgs, function(org){
|
|
833
|
-
var timestamp = new Date(org.flagged.on);
|
|
834
|
-
timestamp = timestamp.getTime();
|
|
835
|
-
return timestamp;
|
|
836
|
-
});
|
|
837
|
-
orgs = orgs.reverse();
|
|
838
|
-
|
|
839
|
-
return cb(null, orgs);
|
|
840
|
-
|
|
841
|
-
});
|
|
842
|
-
|
|
843
|
-
};
|
|
844
|
-
|
|
845
939
|
Organization.statics.upsert = function(org, username, cb) {
|
|
846
940
|
|
|
847
941
|
if (!org) { return cb(new Error('Organization is required'), null); }
|
|
@@ -854,61 +948,13 @@ module.exports = function(mongoose, config) {
|
|
|
854
948
|
|
|
855
949
|
};
|
|
856
950
|
|
|
857
|
-
Organization.statics.removeById = function(id, cb) {
|
|
858
|
-
|
|
859
|
-
if (!id) { return cb(new Error('id is required'), null); }
|
|
860
|
-
if (!cb) { throw new Error('cb is required'); }
|
|
861
|
-
|
|
862
|
-
this.remove({_id: id}, cb);
|
|
863
|
-
|
|
864
|
-
};
|
|
865
|
-
|
|
866
|
-
Organization.statics.flag = function(orgId, resolved, text, username, cb) {
|
|
867
|
-
|
|
868
|
-
this.findById(orgId).exec(function(err, org) {
|
|
869
|
-
|
|
870
|
-
org.flagged.resolved = resolved;
|
|
871
|
-
org.flagged.text = text;
|
|
872
|
-
org.flagged.by = username;
|
|
873
|
-
org.flagged.on = Date.now();
|
|
874
|
-
|
|
875
|
-
org.save(cb);
|
|
876
951
|
|
|
877
|
-
});
|
|
878
952
|
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
createdBy: creatorPersonId,
|
|
885
|
-
text: text
|
|
886
|
-
}, this, organizationId, cb);
|
|
887
|
-
|
|
888
|
-
};
|
|
889
|
-
|
|
890
|
-
Organization.statics.deleteNote = function(noteId, cb) {
|
|
891
|
-
|
|
892
|
-
// Delete the note itself along with any references
|
|
893
|
-
|
|
894
|
-
var self = this;
|
|
895
|
-
|
|
896
|
-
var removeReferences = function removeReferences(callback) {
|
|
897
|
-
self.update({}, {
|
|
898
|
-
$pull: { 'notes' : [noteId] }
|
|
899
|
-
}, callback);
|
|
900
|
-
};
|
|
901
|
-
|
|
902
|
-
async.series([
|
|
903
|
-
Note.delete.bind(Note, noteId),
|
|
904
|
-
removeReferences
|
|
905
|
-
], function(err, results) {
|
|
906
|
-
return cb(err, null);
|
|
907
|
-
});
|
|
908
|
-
|
|
909
|
-
};
|
|
910
|
-
|
|
911
|
-
///////////////////////////////
|
|
953
|
+
///////////////////////////////////////////////////////////////////////////////////////
|
|
954
|
+
// HOOKS
|
|
955
|
+
// Pre-save: fired on every document before it is saved
|
|
956
|
+
// Post-init: fired on every document when it's returned from a query
|
|
957
|
+
///////////////////////////////////////////////////////////////////////////////////////
|
|
912
958
|
|
|
913
959
|
Organization.pre('save', function(next) {
|
|
914
960
|
|
|
@@ -928,74 +974,44 @@ module.exports = function(mongoose, config) {
|
|
|
928
974
|
|
|
929
975
|
});
|
|
930
976
|
|
|
931
|
-
Organization.post('init', function() {
|
|
977
|
+
Organization.post('init', function(doc, next) {
|
|
932
978
|
|
|
933
|
-
// Protect private data
|
|
979
|
+
// Protect private data
|
|
980
|
+
// Merge public and private data
|
|
934
981
|
|
|
935
|
-
var self = this;
|
|
936
982
|
var CUSTOMER_ID = config.CUSTOMER_ID;
|
|
937
983
|
|
|
938
|
-
if (CUSTOMER_ID == 'GLOBAL_PROCESS') return;
|
|
939
|
-
|
|
940
|
-
var protectCustomerData = function protectCustomerData() {
|
|
941
|
-
|
|
942
|
-
// remove customer details if not viewing self
|
|
943
|
-
if (self._id.toString() != CUSTOMER_ID) self.customer = {};
|
|
984
|
+
if (CUSTOMER_ID == 'GLOBAL_PROCESS') return next();
|
|
944
985
|
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
self.iLevel = _.reject(self.iLevel, function(item) { return item.customer != CUSTOMER_ID; });
|
|
948
|
-
self.chairs = _.reject(self.chairs, function(item) { return item.customer != CUSTOMER_ID; });
|
|
949
|
-
self.capTable = _.reject(self.capTable, function(item) { return item.customer != CUSTOMER_ID; });
|
|
950
|
-
|
|
951
|
-
// investment data
|
|
952
|
-
_.each(self.rounds, function(round) {
|
|
953
|
-
_.each(round.funds, function(fund) {
|
|
954
|
-
if (fund.customer != CUSTOMER_ID) fund.investments = [];
|
|
955
|
-
});
|
|
956
|
-
});
|
|
957
|
-
|
|
958
|
-
};
|
|
986
|
+
// remove customer details if not viewing self
|
|
987
|
+
if (doc._id.toString() != CUSTOMER_ID) doc.customer = {};
|
|
959
988
|
|
|
960
|
-
|
|
989
|
+
doc.filters = _.reject(doc.filters, function(item) { return item.customer != CUSTOMER_ID; });
|
|
990
|
+
doc.docs = _.reject(doc.docs, function(item) { return item.customer != CUSTOMER_ID; });
|
|
991
|
+
doc.iLevel = _.reject(doc.iLevel, function(item) { return item.customer != CUSTOMER_ID; });
|
|
992
|
+
doc.chairs = _.reject(doc.chairs, function(item) { return item.customer != CUSTOMER_ID; });
|
|
961
993
|
|
|
962
|
-
|
|
963
|
-
|
|
994
|
+
// people
|
|
995
|
+
_.each(doc.people, function(person) {
|
|
964
996
|
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
// amountRaised
|
|
968
|
-
// closingDate
|
|
969
|
-
// this data will be overwritten if private data belonging to the current customer is present
|
|
997
|
+
// always include if explicitly public
|
|
998
|
+
if (person.public) return;
|
|
970
999
|
|
|
971
|
-
|
|
972
|
-
|
|
1000
|
+
// if not public, keep it in if org is in the current customer's portfolio. otherwise remove it.
|
|
1001
|
+
// todo
|
|
1002
|
+
console.log(customerPortfolio);
|
|
973
1003
|
|
|
974
|
-
|
|
975
|
-
if (!fund.investments || fund.investments.length == 0) return;
|
|
976
|
-
|
|
977
|
-
// there can be multiple investments in a single round from the same fund
|
|
978
|
-
// use the most recent
|
|
979
|
-
var mostRecentInvestment = _.max(fund.investments, function(investment) { return investment.date; });
|
|
980
|
-
|
|
981
|
-
// this fund belongs to the current customer
|
|
982
|
-
// if we have private data, use it rather than the public data
|
|
983
|
-
if (mostRecentInvestment) {
|
|
984
|
-
if (mostRecentInvestment.preMoneyValuation) round.preMoneyValuation = mostRecentInvestment.preMoneyValuation;
|
|
985
|
-
if (mostRecentInvestment.amountRaised) round.amountRaised = mostRecentInvestment.amountRaised;
|
|
986
|
-
if (mostRecentInvestment.closingDate) round.closingDate = mostRecentInvestment.closingDate;
|
|
987
|
-
}
|
|
1004
|
+
});
|
|
988
1005
|
|
|
989
|
-
|
|
1006
|
+
return next();
|
|
990
1007
|
|
|
991
|
-
|
|
1008
|
+
});
|
|
992
1009
|
|
|
993
|
-
};
|
|
994
1010
|
|
|
995
|
-
protectCustomerData();
|
|
996
|
-
mergePublicAndPrivateData();
|
|
997
1011
|
|
|
998
|
-
|
|
1012
|
+
///////////////////////////////////////////////////////////////////////////////////////
|
|
1013
|
+
// CONFIG
|
|
1014
|
+
///////////////////////////////////////////////////////////////////////////////////////
|
|
999
1015
|
|
|
1000
1016
|
Organization.set('toJSON', { virtuals: true });
|
|
1001
1017
|
Organization.set('autoIndex', true);
|
|
@@ -1006,6 +1022,6 @@ module.exports = function(mongoose, config) {
|
|
|
1006
1022
|
var deepPopulate = require('mongoose-deep-populate')(mongoose);
|
|
1007
1023
|
Organization.plugin(deepPopulate);
|
|
1008
1024
|
|
|
1009
|
-
mongoose.model('Organization', Organization, '
|
|
1025
|
+
mongoose.model('Organization', Organization, 'organization_new');
|
|
1010
1026
|
|
|
1011
1027
|
};
|