@dhyasama/totem-models 8.45.0 → 8.47.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 CHANGED
@@ -19,6 +19,14 @@ module.exports = function(mongoose, config) {
19
19
  // Enable this and iLevel links will show on portfolio pages
20
20
  iLevelUser: { type: Boolean },
21
21
 
22
+ totemLive: {
23
+
24
+ excelUser: { type: Boolean, default: false },
25
+
26
+ sheetsUser: { type: Boolean, default: false },
27
+
28
+ },
29
+
22
30
  person: {
23
31
  type: Schema.ObjectId,
24
32
  ref: 'Person',
@@ -71,6 +79,20 @@ module.exports = function(mongoose, config) {
71
79
 
72
80
  });
73
81
 
82
+
83
+
84
+ Account.virtual('live.excelUser').get(function () {
85
+ const self = this;
86
+ return self.totemLive && self.totemLive.excelUser;
87
+ });
88
+
89
+ Account.virtual('live.sheetsUser').get(function () {
90
+ const self = this;
91
+ return self.totemLive && self.totemLive.sheetsUser;
92
+ });
93
+
94
+
95
+
74
96
  Account.statics.findByEmail = function(email, cb) {
75
97
 
76
98
  let self = this;
package/lib/Investment.js CHANGED
@@ -25,40 +25,14 @@ module.exports = function(mongoose, config) {
25
25
  // Used by Round to selectively populate
26
26
  customer: { type: Schema.ObjectId, ref: 'Organization', required: true, index: true },
27
27
 
28
- investmentDate: { type: Date, required: true },
29
- cost: { type: Number, default: 0 },
30
- costPlusInterest: { type: Number, default: 0 },
31
- pricePerShare: { type: Number, default: 0 },
32
-
33
- debt: { type: Boolean, default: false },
34
- debtType: {
35
- type: String,
36
- enum: [ 'Convertible Note', 'Convertible Promissory Note', 'Demand Note', 'Demand Promissory Note', 'SAFE', 'SAFT', 'SAFTE', 'KISS', null ],
37
- default: null,
38
- required: false,
39
- validate: {
40
- validator: function(v) {
41
- var self = this;
42
- if (v && v.length && self.debt == false) return false;
43
- else return true;
44
- },
45
- message: 'There is a debt type ({VALUE}) but debt is set to false! Either set debt to true or remove the debt type.'
46
- }
47
- },
48
-
49
- converted: { type: Boolean, default: false },
50
- convertedInto: {
51
- type: String,
52
- trim: true,
53
- validate: {
54
- validator: function(v) {
55
- var self = this;
56
- if (self.converted && (!v || v.length == 0)) return false;
57
- else return true;
58
- },
59
- message: 'The investments is marked as converted but a converted into value was not provided! Either set converted to false or provide a value for converted into.'
60
- }
61
- },
28
+ date: { type: Date, required: true },
29
+ investment: { type: Number, default: 0 },
30
+ unrealized: { type: Number, default: 0 },
31
+ realized: { type: Number, default: 0 },
32
+ raised: { type: Number, required: false },
33
+ premoney: { type: Number, required: false },
34
+ postmoney: { type: Number, required: false },
35
+ pricePerShare: { type: Number, required: false },
62
36
 
63
37
  // Catch-all for customer specific key-value pairs from sheet that aren't supported by our schema
64
38
  details: [{
@@ -66,38 +40,15 @@ module.exports = function(mongoose, config) {
66
40
  value: { type: Schema.Types.Mixed, required: true },
67
41
  format: { type: String, enum: [null, 'number', 'decimal', 'money', 'percentage', 'date']},
68
42
  _id: false
69
- }],
70
-
71
- // note these fields are duplicative at the round level
72
- // this is private data and will override the round level numbers where appropriate
73
- preMoneyValuation: { type: Number, default: 0 },
74
- postMoneyValuation: { type: Number, default: 0 },
75
- dollarsRaised: { type: Number, default: 0 },
76
- closingDate: { type: Date, default: null }
43
+ }]
77
44
 
78
45
  });
79
46
 
80
-
81
-
82
47
  ///////////////////////////////////////////////////////////////////////////////////////
83
48
  // VIRTUALS
84
49
  // Properties that are not persisted to the database
85
50
  ///////////////////////////////////////////////////////////////////////////////////////
86
51
 
87
- Investment.virtual('month').get(function () {
88
- var self = this;
89
- var monthNames = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
90
- if (!self.investmentDate) return 'Unknown';
91
- else return monthNames[self.investmentDate.getMonth()];
92
- });
93
-
94
- Investment.virtual('year').get(function () {
95
- var self = this;
96
- if (!self.investmentDate) return 'Unknown';
97
- else return self.investmentDate.getFullYear();
98
- });
99
-
100
-
101
52
 
102
53
  //////////////////////////////////////////////////////
103
54
  // STATICS
@@ -179,6 +130,4 @@ module.exports = function(mongoose, config) {
179
130
 
180
131
  mongoose.model('Investment', Investment);
181
132
 
182
- };
183
-
184
-
133
+ };
package/lib/Round.js CHANGED
@@ -29,16 +29,6 @@ module.exports = function(mongoose, config) {
29
29
 
30
30
  roundName: { type: String, trim: true, required: true },
31
31
 
32
- // used when cap table round names are changed and need to be matched to investment data
33
- oldRoundName: { type: String, trim: true, default: null },
34
-
35
- // these three values are public and will be used in the absence of overriding private data
36
- // if private data exists (in the form of investments), the most recent investment data will be used
37
- preMoneyValuation: { type: Number, default: 0 },
38
- postMoneyValuation: { type: Number, default: 0 },
39
- dollarsRaised: { type: Number, default: 0 },
40
- closingDate: { type: Date, default: null },
41
-
42
32
  // People that participated in this round
43
33
  // This is a public list of people that invested
44
34
  // Use the addPerson method and removePerson static
@@ -65,11 +55,7 @@ module.exports = function(mongoose, config) {
65
55
  investments: [{ type: Schema.ObjectId, ref: 'Investment', required: false }],
66
56
 
67
57
  // computed from investments
68
- cost: { type: Number, default: 0 },
69
-
70
- // set at the vehicle level during investment pull
71
- fairValue: { type: Number, default: 0 },
72
- valuationDate: { type: Date, default: null },
58
+ investment: { type: Number, default: 0 },
73
59
  unrealized: { type: Number, default: 0 },
74
60
  realized: { type: Number, default: 0 },
75
61
 
@@ -79,8 +65,6 @@ module.exports = function(mongoose, config) {
79
65
 
80
66
  });
81
67
 
82
-
83
-
84
68
  ///////////////////////////////////////////////////////////////////////////////////////
85
69
  // HELPERS
86
70
  ///////////////////////////////////////////////////////////////////////////////////////
@@ -93,15 +77,15 @@ module.exports = function(mongoose, config) {
93
77
 
94
78
  var calculateOrgPerformance = function calculateOrgPerformance(org, rounds) {
95
79
 
96
- // sum the cost of each vehicle
97
- org.cost = _.reduce(rounds, function(memo, round) {
98
- var sum = _.reduce(round.vehicles, function(memo, vehicle) { return memo + vehicle.cost; }, 0);
80
+ // sum the investment of each vehicle
81
+ org.investment = _.reduce(rounds, function(memo, round) {
82
+ var sum = _.reduce(round.vehicles, function(memo, vehicle) { return memo + vehicle.investment; }, 0);
99
83
  return memo + sum;
100
84
  }, 0);
101
85
 
102
- // sum the fair value of each vehicle, i.e., the unrealized value
86
+ // sum the unrealized of each vehicle
103
87
  org.unrealized = _.reduce(rounds, function(memo, round) {
104
- var sum = _.reduce(round.vehicles, function(memo, vehicle) { return memo + vehicle.fairValue; }, 0);
88
+ var sum = _.reduce(round.vehicles, function(memo, vehicle) { return memo + vehicle.unrealized; }, 0);
105
89
  return memo + sum;
106
90
  }, 0);
107
91
 
@@ -112,7 +96,7 @@ module.exports = function(mongoose, config) {
112
96
  }, 0);
113
97
 
114
98
  // finally, calc the multiple
115
- org.multiple = org.cost > 0 ? (org.unrealized + org.realized) / org.cost : 0;
99
+ org.multiple = org.investment > 0 ? (org.unrealized + org.realized) / org.investment : 0;
116
100
 
117
101
  return org;
118
102
 
@@ -158,8 +142,6 @@ module.exports = function(mongoose, config) {
158
142
  contact: rounds[0].organization.contact,
159
143
  filters: rounds[0].organization.filters,
160
144
  status: rounds[0].organization.status,
161
- preMoneyValuation: rounds[0].preMoneyValuation,
162
- postMoneyValuation: rounds[0].postMoneyValuation,
163
145
  chairs: rounds[0].organization.chairs,
164
146
  funds: funds
165
147
  };
@@ -220,43 +202,19 @@ module.exports = function(mongoose, config) {
220
202
 
221
203
  };
222
204
 
223
-
224
-
225
205
  ///////////////////////////////////////////////////////////////////////////////////////
226
206
  // VIRTUALS
227
207
  // Properties that are not persisted to the database
228
208
  ///////////////////////////////////////////////////////////////////////////////////////
229
209
 
230
- Round.virtual('cost').get(function () {
231
- // sums the cost of all vehicles in the round
232
- var self = this;
233
- return _.reduce(self.vehicles, function(memo, vehicle) { return memo + vehicle.cost; }, 0);
234
- });
235
-
236
- Round.virtual('month').get(function () {
237
- var self = this;
238
- var monthNames = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
239
- if (!self.closingDate) return 'Unknown';
240
- else return monthNames[self.closingDate.getMonth()];
241
- });
242
-
243
210
  Round.virtual('value').get(function () {
244
- // sums the value (fair or realized) of all vehicles in the round
211
+ // sums the value (realized and unrealized) of all vehicles in the round
245
212
  var self = this;
246
213
  return _.reduce(self.vehicles, function(memo, vehicle) {
247
- if (self.roundName === 'Proceeds') return memo + vehicle.realized; // proceeds are realized and do not have a fair value
248
- else return memo + vehicle.fairValue;
214
+ return memo + vehicle.unrealized + vehicle.realized;
249
215
  }, 0);
250
216
  });
251
217
 
252
- Round.virtual('year').get(function () {
253
- var self = this;
254
- if (!self.closingDate) return 'Unknown';
255
- else return self.closingDate.getFullYear();
256
- });
257
-
258
-
259
-
260
218
  ///////////////////////////////////////////////////////////////////////////////////////
261
219
  // METHODS
262
220
  //
@@ -315,7 +273,6 @@ module.exports = function(mongoose, config) {
315
273
 
316
274
  // If not, add it
317
275
  if (!match) vehicle.investments.push(investment);
318
- // note there is no need to compute vehicle cost as it is done during upsert
319
276
 
320
277
  };
321
278
 
@@ -366,9 +323,8 @@ module.exports = function(mongoose, config) {
366
323
  }
367
324
 
368
325
  data = data || {};
369
- data.fairValue = data.fairValue || 0;
326
+ data.unrealized = data.unrealized || 0;
370
327
  data.realized = data.realized || 0;
371
- data.valuationDate = data.valuationDate || null;
372
328
 
373
329
  // Check if vehicle is already added
374
330
  let vehicle = _.find(self.vehicles, function(v) {
@@ -378,18 +334,16 @@ module.exports = function(mongoose, config) {
378
334
 
379
335
  // update data on existing vehicle
380
336
  if (vehicle) {
381
- vehicle.fairValue = data.fairValue;
337
+ vehicle.unrealized = data.unrealized;
382
338
  vehicle.realized = data.realized;
383
- vehicle.valuationDate = data.valuationDate;
384
339
  }
385
340
  // create vehicle
386
341
  else {
387
342
  vehicle = {
388
343
  fund: fund,
389
344
  investments: [],
390
- fairValue: data.fairValue,
391
- realized: data.realized,
392
- valuationDate: data.valuationDate
345
+ unrealized: data.unrealized,
346
+ realized: data.realized
393
347
  };
394
348
  self.vehicles.push(vehicle);
395
349
  }
@@ -398,8 +352,6 @@ module.exports = function(mongoose, config) {
398
352
 
399
353
  };
400
354
 
401
-
402
-
403
355
  //////////////////////////////////////////////////////
404
356
  // STATICS
405
357
  // Statics operate on the entire collection
@@ -453,11 +405,9 @@ module.exports = function(mongoose, config) {
453
405
  // reverse chronological
454
406
  rounds = _.sortBy(rounds, function(r) {
455
407
 
456
- let date = r.closingDate;
457
-
458
408
  // use investment date in absence of closing date
459
409
  if (!date && r.vehicles.length && r.vehicles[0].investments.length) {
460
- date = r.vehicles[0].investments[0].investmentDate;
410
+ date = r.vehicles[0].investments[0].date;
461
411
  }
462
412
 
463
413
  return date;
@@ -515,11 +465,9 @@ module.exports = function(mongoose, config) {
515
465
  // reverse chronological
516
466
  rounds = _.sortBy(rounds, function(r) {
517
467
 
518
- let date = r.closingDate;
519
-
520
468
  // use investment date in absence of closing date
521
469
  if (!date && r.vehicles.length && r.vehicles[0].investments.length) {
522
- date = r.vehicles[0].investments[0].investmentDate;
470
+ date = r.vehicles[0].investments[0].date;
523
471
  }
524
472
 
525
473
  return date;
@@ -607,27 +555,27 @@ module.exports = function(mongoose, config) {
607
555
 
608
556
  // we now have all the rounds the fund has participated in with other fund information removed from each round
609
557
 
610
- let totalFundCost = _.reduce(rounds, function(memo, round) {
611
- let roundCost = _.reduce(round.vehicles, function(memo, vehicle) { return memo + vehicle.cost; }, 0);
558
+ let totalInvestment = _.reduce(rounds, function(memo, round) {
559
+ let roundInvestment = _.reduce(round.vehicles, function(memo, vehicle) { return memo + vehicle.investment; }, 0);
612
560
  return memo + roundCost;
613
561
  }, 0);
614
562
 
615
563
  let totalUnrealized = _.reduce(rounds, function(memo, round) {
616
- let roundValue = _.reduce(round.vehicles, function(memo, vehicle) { return memo + vehicle.fairValue; }, 0);
617
- return memo + roundValue;
564
+ let roundUnrealized = _.reduce(round.vehicles, function(memo, vehicle) { return memo + vehicle.unrealized; }, 0);
565
+ return memo + roundUnrealized;
618
566
  }, 0);
619
567
 
620
568
  let totalRealized = _.reduce(rounds, function(memo, round) {
621
- let roundValue = _.reduce(round.vehicles, function(memo, vehicle) { return memo + vehicle.realized; }, 0);
622
- return memo + roundValue;
569
+ let roundRealized = _.reduce(round.vehicles, function(memo, vehicle) { return memo + vehicle.realized; }, 0);
570
+ return memo + roundRealized;
623
571
  }, 0);
624
572
 
625
573
  return cb(null, {
626
- cost: totalFundCost,
574
+ investment: totalInvestment,
627
575
  unrealized: totalUnrealized,
628
576
  realized: totalRealized,
629
577
  value: totalUnrealized + totalRealized,
630
- multiple: totalFundCost > 0 ? (totalUnrealized + totalRealized) / totalFundCost : 0
578
+ multiple: totalInvestment > 0 ? (totalUnrealized + totalRealized) / totalInvestment : 0
631
579
  });
632
580
 
633
581
  });
@@ -652,7 +600,7 @@ module.exports = function(mongoose, config) {
652
600
 
653
601
  let query = self.find({ 'vehicles.fund': fundId });
654
602
 
655
- query.select('organization vehicles preMoneyValuation postMoneyValuation');
603
+ query.select('organization vehicles');
656
604
  query.populate('organization', 'name slug logoUrl description contact filters status ipo closed acquired operating website websiteAliases');
657
605
  query.populate('vehicles.fund');
658
606
 
@@ -706,7 +654,7 @@ module.exports = function(mongoose, config) {
706
654
 
707
655
  let query = self.find({ 'vehicles.fund': { $in: fundIds } });
708
656
 
709
- query.select('organization vehicles preMoneyValuation postMoneyValuation');
657
+ query.select('organization vehicles');
710
658
  query.populate('organization', 'name slug logoUrl description contact chairs filters status ipo closed acquired operating website websiteAliases');
711
659
  query.deepPopulate([
712
660
  'organization.chairs.first',
@@ -879,26 +827,10 @@ module.exports = function(mongoose, config) {
879
827
  var investments = vehicle.investments;
880
828
 
881
829
  if (investments.length >= 1) {
882
- // sum cost of each investment
883
- vehicle.cost = _.reduce(investments, function(memo, investment){ return memo + investment.cost; }, 0);
830
+ vehicle.investment = _.reduce(investments, function(memo, investment) { return memo + investment.investment; }, 0);
884
831
  }
885
832
  else {
886
- // no investments = no cost
887
- vehicle.cost = 0;
888
- }
889
-
890
- // proceeds are special in that the cost is actually a realized gain
891
- if (doc.roundName == 'Proceeds') {
892
- vehicle.realized = vehicle.cost;
893
- vehicle.cost = 0;
894
- vehicle.unrealized = 0;
895
- vehicle.fairValue = 0;
896
- }
897
-
898
- // escrow is also special, except the gains are unrealized
899
- else if (doc.roundName === 'Escrow') {
900
- vehicle.unrealized = vehicle.fairValue - vehicle.cost;
901
- vehicle.realized = 0;
833
+ vehicle.investment = 0;
902
834
  }
903
835
 
904
836
  });
@@ -911,7 +843,7 @@ module.exports = function(mongoose, config) {
911
843
 
912
844
  result.populate({
913
845
  path: 'vehicles.investments',
914
- select: 'cost'
846
+ select: 'investment'
915
847
  }, function(err, doc) {
916
848
 
917
849
  if (err) return cb(err, null);
@@ -940,13 +872,6 @@ module.exports = function(mongoose, config) {
940
872
 
941
873
  // note participating people are public as there is no investment, i.e., private, data attached to them
942
874
 
943
- // note that public versions of the following data exist at this level:
944
- // preMoneyValuation
945
- // postMoneyValuation
946
- // amountRaised
947
- // closingDate
948
- // this data will be overwritten if private data belonging to the current customer is present
949
-
950
875
  // participating vehicles are public
951
876
  // merge private data that was matched for customer
952
877
 
@@ -954,17 +879,6 @@ module.exports = function(mongoose, config) {
954
879
  return vehicle.investments.length > 0;
955
880
  });
956
881
 
957
- let allInvestments = _.flatten(_.pluck(doc.vehicles, 'investments'));
958
- let mostRecentInvestment = _.max(allInvestments, function(investment) { return investment.investmentDate; });
959
-
960
- // if we have private data, use it rather than the public data
961
- if (mostRecentInvestment) {
962
- if (mostRecentInvestment.preMoneyValuation) { doc.preMoneyValuation = mostRecentInvestment.preMoneyValuation; }
963
- if (mostRecentInvestment.postMoneyValuation) { doc.postMoneyValuation = mostRecentInvestment.postMoneyValuation; }
964
- if (mostRecentInvestment.dollarsRaised) { doc.dollarsRaised = mostRecentInvestment.dollarsRaised; }
965
- if (mostRecentInvestment.closingDate) { doc.closingDate = mostRecentInvestment.closingDate; }
966
- }
967
-
968
882
  next();
969
883
 
970
884
  });
@@ -985,6 +899,4 @@ module.exports = function(mongoose, config) {
985
899
 
986
900
  mongoose.model('Round', Round);
987
901
 
988
- };
989
-
990
-
902
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dhyasama/totem-models",
3
- "version": "8.45.0",
3
+ "version": "8.47.0",
4
4
  "author": "Jason Reynolds",
5
5
  "license": "UNLICENSED",
6
6
  "description": "Models for Totem platform",