@dhyasama/totem-models 8.110.1 → 9.1.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.
Files changed (2) hide show
  1. package/lib/CapTable.js +39 -115
  2. package/package.json +1 -1
package/lib/CapTable.js CHANGED
@@ -31,14 +31,14 @@ module.exports = function(mongoose, config) {
31
31
  // preferably the date in the cap table document, not the date added to our system
32
32
  asOfDate: { type: Date, required: true, default: Date.now },
33
33
 
34
- // so customers can download full file
35
- originalDocumentUrl: { type: String, trim: true },
34
+ // optional reference to download the cap table file
35
+ document: { type: Schema.ObjectId, ref: 'Document', required: false },
36
36
 
37
37
  // single pool of unissued options for the org
38
- unissuedOptions: { type: Number, default: 0 },
38
+ unissued: { type: Number, default: 0 },
39
39
 
40
40
  // computed on save (via pre-save hook); don't set directly;
41
- fullyDiluted: { type: Number, default: 0 },
41
+ shares: { type: Number, default: 0 },
42
42
 
43
43
  stakeholders: [{
44
44
 
@@ -50,6 +50,18 @@ module.exports = function(mongoose, config) {
50
50
  // verbatim text from the cap table
51
51
  name: { type: String, trim: true, required: true },
52
52
 
53
+ rounds: [{
54
+ round: { type: String, trim: true, required: true },
55
+ shares: { type: Number, default: 0 },
56
+ ownership: { type: Number, default: 0 }
57
+ }],
58
+
59
+ // computed on save (via pre-save hook); don't set directly;
60
+ shares: { type: Number, default: 0 },
61
+
62
+ // computed on save (via pre-save hook); don't set directly;
63
+ ownership: { type: Number, default: 0 }
64
+
53
65
  // link stakeholder to a fund in our system
54
66
  fund: {
55
67
  type: Schema.ObjectId,
@@ -110,35 +122,6 @@ module.exports = function(mongoose, config) {
110
122
  }
111
123
  },
112
124
 
113
- // Put stakes in a bucket for their type.
114
- // Note we are grouping all stakes for the current stakeholder.
115
-
116
- common: [{
117
- round: { type: String, trim: true, required: true },
118
- shares: { type: Number, default: 0 }
119
- }],
120
-
121
- options: [{
122
- round: { type: String, trim: true, required: true },
123
- shares: { type: Number, default: 0 }
124
- }],
125
-
126
- preferred: [{
127
- round: { type: String, trim: true, required: true },
128
- shares: { type: Number, default: 0 }
129
- }],
130
-
131
- warrants: [{
132
- round: { type: String, trim: true, required: true },
133
- shares: { type: Number, default: 0 }
134
- }],
135
-
136
- // computed on save (via pre-save hook); don't set directly;
137
- fullyDiluted: { type: Number, default: 0 },
138
-
139
- // computed on save (via pre-save hook); don't set directly;
140
- fullyDilutedPercentage: { type: Number, default: 0 }
141
-
142
125
  }],
143
126
 
144
127
  entered: {
@@ -157,59 +140,28 @@ module.exports = function(mongoose, config) {
157
140
 
158
141
  CapTable.virtual('stakeholdersByRound').get(function () {
159
142
 
160
- // Returns list of tuples, one for each round on this cap table along with participants in each round
161
-
162
143
  var self = this;
163
144
 
164
- var buildRoundList = function buildRoundList(stakeholders) {
165
-
166
- var roundList = [];
167
-
168
- _.each(stakeholders, function(stakeholder) {
169
- roundList = roundList.concat(_.pluck(stakeholder.common, 'round'));
170
- roundList = roundList.concat(_.pluck(stakeholder.options, 'round'));
171
- roundList = roundList.concat(_.pluck(stakeholder.preferred, 'round'));
172
- roundList = roundList.concat(_.pluck(stakeholder.warrants, 'round'));
173
- });
174
-
175
- roundList = _.uniq(roundList);
145
+ var stakeholdersByRound = [];
176
146
 
177
- return roundList;
178
-
179
- };
180
-
181
- var matchStakeholderToRound = function matchStakeholderToRound(arr, participants, name, round) {
182
- var match = _.find(arr, function(i) { return round == i.round; });
183
- if (match) { participants.push(name); }
184
- };
185
-
186
- var roundList = buildRoundList(self.stakeholders);
187
-
188
- var stakeholders = [];
189
-
190
- _.each(roundList, function(round) {
147
+ _.each(self.stakeholders, function(stakeholder) {
148
+ _.each(stakeholder.rounds, function(round) {
191
149
 
192
- // List of each participant in this round
193
- var participants = [];
150
+ var roundMatch = _.find(stakeholdersByRound, function(r) { return r.round == round.round });
194
151
 
195
- _.each(self.stakeholders, function(stakeholder) {
196
- matchStakeholderToRound(stakeholder.common, participants, stakeholder.name, round);
197
- matchStakeholderToRound(stakeholder.options, participants, stakeholder.name, round);
198
- matchStakeholderToRound(stakeholder.preferred, participants, stakeholder.name, round);
199
- matchStakeholderToRound(stakeholder.warrants, participants, stakeholder.name, round);
200
- });
152
+ if(roundMatch) {
153
+ roundMatch.stakeholders.push(stakeholder);
154
+ }
201
155
 
202
- participants = _.uniq(participants);
156
+ else {
157
+ stakeholdersByRound.push({round: round.round, stakeholders: []});
158
+ _.last(stakeholdersByRound).stakeholders.push(stakeholder);
159
+ }
203
160
 
204
- // return tuple of round name and participants in the round
205
- stakeholders.push({
206
- round: round,
207
- participants: participants
208
161
  });
209
-
210
162
  });
211
163
 
212
- return stakeholders;
164
+ return stakeholdersByRound;
213
165
 
214
166
  });
215
167
 
@@ -393,20 +345,6 @@ module.exports = function(mongoose, config) {
393
345
 
394
346
  };
395
347
 
396
- CapTable.statics.updateOriginalDocumentUrl = function updateOriginalDocumentUrl(id, originalDocumentUrl, cb) {
397
-
398
- var self = this;
399
-
400
- self
401
- .findByIdAndUpdate(
402
- id,
403
- { $set: { originalDocumentUrl: originalDocumentUrl } },
404
- { new: true, upsert: false },
405
- cb
406
- );
407
-
408
- };
409
-
410
348
  CapTable.statics.upsert = function upsert(capTable, cb) {
411
349
 
412
350
  if (!capTable) { return cb(new Error('cap table is required'), null); }
@@ -429,39 +367,27 @@ module.exports = function(mongoose, config) {
429
367
 
430
368
  var self = this;
431
369
 
432
- // Sum each stakeholders fully diluted shares
370
+ // Sum each stakeholders shares
433
371
  _.each(self.stakeholders, function(stakeholder) {
434
372
 
435
- var common = _.reduce(stakeholder.common, function(memo, i) {
436
- return memo + i.shares;
437
- }, 0);
438
-
439
- var options = _.reduce(stakeholder.options, function(memo, i) {
440
- return memo + i.shares;
441
- }, 0);
442
-
443
- var preferred = _.reduce(stakeholder.preferred, function(memo, i) {
373
+ var shares = _.reduce(stakeholder.rounds, function(rounds, i) {
444
374
  return memo + i.shares;
445
375
  }, 0);
446
376
 
447
- var warrants = _.reduce(stakeholder.warrants, function(memo, i) {
448
- return memo + i.shares;
449
- }, 0);
450
-
451
- stakeholder.fullyDiluted = common + options + preferred + warrants;
377
+ stakeholder.shares = shares;
452
378
 
453
379
  });
454
380
 
455
- // Sum total fully diluted
456
- self.fullyDiluted = _.reduce(self.stakeholders, function(memo, stakeholder) {
457
- return memo + stakeholder.fullyDiluted;
381
+ // Sum total shares
382
+ self.shares = _.reduce(self.stakeholders, function(memo, stakeholder) {
383
+ return memo + stakeholder.shares;
458
384
  }, 0);
459
- self.fullyDiluted = self.fullyDiluted + self.unissuedOptions;
385
+ self.shares = self.shares + self.unissued;
460
386
 
461
- // Calculate each stakeholders fully diluted percentage
387
+ // Calculate each stakeholders ownership
462
388
  _.each(self.stakeholders, function(stakeholder) {
463
- if (self.fullyDiluted == 0) { stakeholder.fullyDiluted = 0; }
464
- else { stakeholder.fullyDilutedPercentage = ((stakeholder.fullyDiluted / self.fullyDiluted) * 100).toFixed(2); }
389
+ if (self.shares == 0) stakeholder.shares = 0;
390
+ else stakeholder.ownership = ((stakeholder.shares / self.shares) * 100).toFixed(2);
465
391
  });
466
392
 
467
393
  return next();
@@ -470,14 +396,12 @@ module.exports = function(mongoose, config) {
470
396
 
471
397
  CapTable.post('init', function(doc, next) {
472
398
 
473
- doc.stakeholders = _.sortBy(doc.stakeholders, 'fullyDilutedPercentage').reverse();
399
+ doc.stakeholders = _.sortBy(doc.stakeholders, 'ownership').reverse();
474
400
 
475
401
  return next();
476
402
 
477
403
  });
478
404
 
479
-
480
-
481
405
  ///////////////////////////////////////////////////////////////////////////////////////
482
406
  // CONFIG
483
407
  ///////////////////////////////////////////////////////////////////////////////////////
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dhyasama/totem-models",
3
- "version": "8.110.1",
3
+ "version": "9.1.0",
4
4
  "author": "Jason Reynolds",
5
5
  "license": "UNLICENSED",
6
6
  "description": "Models for Totem platform",