@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.
- package/lib/CapTable.js +39 -115
- 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
|
-
//
|
|
35
|
-
|
|
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
|
-
|
|
38
|
+
unissued: { type: Number, default: 0 },
|
|
39
39
|
|
|
40
40
|
// computed on save (via pre-save hook); don't set directly;
|
|
41
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
193
|
-
var participants = [];
|
|
150
|
+
var roundMatch = _.find(stakeholdersByRound, function(r) { return r.round == round.round });
|
|
194
151
|
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
370
|
+
// Sum each stakeholders shares
|
|
433
371
|
_.each(self.stakeholders, function(stakeholder) {
|
|
434
372
|
|
|
435
|
-
var
|
|
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
|
-
|
|
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
|
|
456
|
-
self.
|
|
457
|
-
return memo + stakeholder.
|
|
381
|
+
// Sum total shares
|
|
382
|
+
self.shares = _.reduce(self.stakeholders, function(memo, stakeholder) {
|
|
383
|
+
return memo + stakeholder.shares;
|
|
458
384
|
}, 0);
|
|
459
|
-
self.
|
|
385
|
+
self.shares = self.shares + self.unissued;
|
|
460
386
|
|
|
461
|
-
// Calculate each stakeholders
|
|
387
|
+
// Calculate each stakeholders ownership
|
|
462
388
|
_.each(self.stakeholders, function(stakeholder) {
|
|
463
|
-
if (self.
|
|
464
|
-
else
|
|
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, '
|
|
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
|
///////////////////////////////////////////////////////////////////////////////////////
|