@dhyasama/totem-models 9.4.2 → 9.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.
Files changed (2) hide show
  1. package/lib/CapTable.js +82 -133
  2. package/package.json +1 -1
package/lib/CapTable.js CHANGED
@@ -34,41 +34,21 @@ module.exports = function(mongoose, config) {
34
34
  // optional reference to download the cap table file
35
35
  document: { type: Schema.ObjectId, ref: 'Document', required: false },
36
36
 
37
- // computed on save (via pre-save hook); don't set directly;
38
- shares: { type: Number, default: 0 },
39
-
40
37
  stakeholders: [{
38
+
39
+ _id: false,
41
40
 
42
- // verbatim text from the cap table
41
+ // the raw stakeholder name on the cap table
43
42
  name: { type: String, trim: true, required: true },
44
43
 
44
+ // the stakeholders shares broken down by round
45
45
  rounds: [{
46
- round: { type: String, trim: true, required: true },
46
+ _id: false,
47
+ name: { type: String, trim: true, required: true },
47
48
  shares: { type: Number, default: 0 },
48
49
  }],
49
50
 
50
- // computed on save (via pre-save hook); don't set directly;
51
- shares: { type: Number, default: 0 },
52
-
53
- // computed on save (via pre-save hook); don't set directly;
54
- ownership: { type: Number, default: 0 },
55
-
56
- // link stakeholder to a fund in our system
57
- fund: {
58
- type: Schema.ObjectId,
59
- ref: 'Fund',
60
- default: null,
61
- required: false,
62
- validate: {
63
- validator: function(v) {
64
- if (v && (this.lp || this.org || this.person)) return false;
65
- else return true;
66
- },
67
- message: 'A stakeholder can only be linked to one of the following: fund, lp, org, person'
68
- }
69
- },
70
-
71
- // link stakeholder to a lp in our system
51
+ // stakeholder reference to an lp
72
52
  lp: {
73
53
  type: Schema.ObjectId,
74
54
  ref: 'LimitedPartner',
@@ -76,14 +56,14 @@ module.exports = function(mongoose, config) {
76
56
  required: false,
77
57
  validate: {
78
58
  validator: function(v) {
79
- if (v && (this.fund || this.org || this.person)) return false;
59
+ if (v && (this.org || this.person)) return false;
80
60
  else return true;
81
61
  },
82
- message: 'A stakeholder can only be linked to one of the following: fund, lp, org, person'
62
+ message: 'A stakeholder can only be linked to one of the following: lp, org, person'
83
63
  }
84
64
  },
85
65
 
86
- // link stakeholder to a person in our system
66
+ // stakeholder reference to an org
87
67
  org: {
88
68
  type: Schema.ObjectId,
89
69
  ref: 'Organization',
@@ -91,14 +71,14 @@ module.exports = function(mongoose, config) {
91
71
  required: false,
92
72
  validate: {
93
73
  validator: function(v) {
94
- if (v && (this.fund || this.lp || this.person)) return false;
74
+ if (v && (this.lp || this.person)) return false;
95
75
  else return true;
96
76
  },
97
- message: 'A stakeholder can only be linked to one of the following: fund, lp, org, person'
77
+ message: 'A stakeholder can only be linked to one of the following: lp, org, person'
98
78
  }
99
79
  },
100
80
 
101
- // link stakeholder to a person in our system
81
+ // stakeholder reference to an person
102
82
  person: {
103
83
  type: Schema.ObjectId,
104
84
  ref: 'Person',
@@ -106,12 +86,12 @@ module.exports = function(mongoose, config) {
106
86
  required: false,
107
87
  validate: {
108
88
  validator: function(v) {
109
- if (v && (this.fund || this.lp || this.org)) return false;
89
+ if (v && (this.lp || this.org)) return false;
110
90
  else return true;
111
91
  },
112
- message: 'A stakeholder can only be linked to one of the following: fund, lp, org, person'
92
+ message: 'A stakeholder can only be linked to one of the following: lp, org, person'
113
93
  }
114
- },
94
+ }
115
95
 
116
96
  }],
117
97
 
@@ -127,30 +107,19 @@ module.exports = function(mongoose, config) {
127
107
  // Properties that are not persisted to the database
128
108
  ///////////////////////////////////////////////////////////////////////////////////////
129
109
 
130
- CapTable.virtual('stakeholdersByRound').get(function () {
110
+ CapTable.virtual('shares').get(function() {
131
111
 
132
112
  var self = this;
133
113
 
134
- var stakeholdersByRound = [];
114
+ var shares = 0;
135
115
 
136
116
  _.each(self.stakeholders, function(stakeholder) {
137
117
  _.each(stakeholder.rounds, function(round) {
138
-
139
- var roundMatch = _.find(stakeholdersByRound, function(r) { return r.round == round.round });
140
-
141
- if(roundMatch) {
142
- roundMatch.stakeholders.push(stakeholder);
143
- }
144
-
145
- else {
146
- stakeholdersByRound.push({round: round.round, stakeholders: []});
147
- _.last(stakeholdersByRound).stakeholders.push(stakeholder);
148
- }
149
-
118
+ shares += round.shares;
150
119
  });
151
120
  });
152
121
 
153
- return stakeholdersByRound;
122
+ return shares;
154
123
 
155
124
  });
156
125
 
@@ -165,21 +134,7 @@ module.exports = function(mongoose, config) {
165
134
  // Statics operate on the entire collection
166
135
  //////////////////////////////////////////////////////
167
136
 
168
- CapTable.statics.getForCustomer = function getForCustomer(orgId, customerId, cb) {
169
-
170
- var self = this;
171
-
172
- self
173
- .findOne({customer: customerId, organization: orgId })
174
- .populate('stakeholders.fund', 'name shortName')
175
- .populate('stakeholders.lp', 'name')
176
- .populate('stakeholders.org', 'name logoUrl')
177
- .populate('stakeholders.person', 'name avatarUrl title')
178
- .exec(cb);
179
-
180
- };
181
-
182
- CapTable.statics.getAllForCustomer = function getAllForCustomer(options, cb) {
137
+ CapTable.statics.getForCustomer = function getForCustomer(options, cb) {
183
138
 
184
139
  var self = this;
185
140
 
@@ -197,7 +152,6 @@ module.exports = function(mongoose, config) {
197
152
  query.populate('organization', 'name logoUrl');
198
153
 
199
154
  if(options.populateStakeholders) {
200
- query.populate('stakeholders.fund', 'name shortName')
201
155
  query.populate('stakeholders.lp', 'name')
202
156
  query.populate('stakeholders.org', 'name logoUrl')
203
157
  query.populate('stakeholders.person', 'name avatarUrl title')
@@ -207,61 +161,100 @@ module.exports = function(mongoose, config) {
207
161
 
208
162
  };
209
163
 
210
- CapTable.statics.deleteAllForCustomer = function deleteAllForCustomer(customerId, cb) {
164
+ CapTable.statics.deleteForCustomer = function deleteForCustomer(options, cb) {
165
+
211
166
  var self = this;
212
- self.remove({ customer: customerId, 'entered.by': { $ne: 'carta-parser' } }, cb);
167
+
168
+ if (!cb) { throw new Error('cb is required'); }
169
+ if (!options) { return cb(new Error('options is required'), null); }
170
+ if (!options.CUSTOMER_ID) { return cb(new Error('options.CUSTOMER_ID is required'), null); }
171
+ if (!mongoose.Types.ObjectId.isValid(options.CUSTOMER_ID)) { return cb(new Error('options.CUSTOMER_ID is not a valid ObjectId'), null); }
172
+
173
+ self.remove({ customer: options.CUSTOMER_ID, 'entered.by': { $ne: 'carta-parser' } }, cb);
174
+
213
175
  };
214
176
 
215
- CapTable.statics.getByFunds = function getByFunds(fundIds, cb) {
177
+ CapTable.statics.getForOrg = function getForOrg(options, cb) {
216
178
 
217
179
  var self = this;
218
180
 
219
- self
220
- .find({ 'stakeholders.fund': { $in: fundIds } })
221
- .populate('organization', 'name logoUrl')
222
- .exec(cb);
181
+ if (!cb) { throw new Error('cb is required'); }
182
+ if (!options) { return cb(new Error('options is required'), null); }
183
+ if (!options.CUSTOMER_ID) { return cb(new Error('options.CUSTOMER_ID is required'), null); }
184
+ if (!mongoose.Types.ObjectId.isValid(options.CUSTOMER_ID)) { return cb(new Error('options.CUSTOMER_ID is not a valid ObjectId'), null); }
223
185
 
224
- };
186
+ var query;
225
187
 
226
- CapTable.statics.getByFund = function getByFund(fundId, cb) {
188
+ query = self.find({
189
+ customer: options.CUSTOMER_ID,
190
+ organization: options.orgId
191
+ });
227
192
 
228
- var self = this;
193
+ query.populate('organization', 'name logoUrl');
229
194
 
230
- self
231
- .find({ 'stakeholders.fund': fundId })
232
- .populate('organization', 'name logoUrl')
233
- .exec(cb);
195
+ if(options.populateStakeholders) {
196
+ query.populate('stakeholders.lp', 'name')
197
+ query.populate('stakeholders.org', 'name logoUrl')
198
+ query.populate('stakeholders.person', 'name avatarUrl title')
199
+ }
234
200
 
235
201
  };
236
202
 
237
- CapTable.statics.getByLP = function getByLP(lpId, cb) {
203
+ CapTable.statics.getByLP = function getByLP(options, cb) {
238
204
 
239
205
  var self = this;
240
206
 
207
+ if (!cb) { throw new Error('cb is required'); }
208
+ if (!options) { return cb(new Error('options is required'), null); }
209
+ if (!options.CUSTOMER_ID) { return cb(new Error('options.CUSTOMER_ID is required'), null); }
210
+ if (!mongoose.Types.ObjectId.isValid(options.CUSTOMER_ID)) { return cb(new Error('options.CUSTOMER_ID is not a valid ObjectId'), null); }
211
+
212
+ query = self.find({
213
+ customer: options.CUSTOMER_ID,
214
+ 'stakeholders.lp': options.lpId
215
+ });
216
+
241
217
  self
242
- .find({ 'stakeholders.lp': lpId })
243
218
  .populate('organization', 'name logoUrl')
244
219
  .exec(cb);
245
220
 
246
221
  };
247
222
 
248
- CapTable.statics.getByOrg = function getByOrg(orgId, cb) {
223
+ CapTable.statics.getByOrg = function getByOrg(options, cb) {
249
224
 
250
225
  var self = this;
251
226
 
227
+ if (!cb) { throw new Error('cb is required'); }
228
+ if (!options) { return cb(new Error('options is required'), null); }
229
+ if (!options.CUSTOMER_ID) { return cb(new Error('options.CUSTOMER_ID is required'), null); }
230
+ if (!mongoose.Types.ObjectId.isValid(options.CUSTOMER_ID)) { return cb(new Error('options.CUSTOMER_ID is not a valid ObjectId'), null); }
231
+
232
+ query = self.find({
233
+ customer: options.CUSTOMER_ID,
234
+ 'stakeholders.org': options.orgId
235
+ });
236
+
252
237
  self
253
- .find({ 'stakeholders.org': orgId })
254
238
  .populate('organization', 'name logoUrl')
255
239
  .exec(cb);
256
240
 
257
241
  };
258
242
 
259
- CapTable.statics.getByPerson = function getByPerson(personId, cb) {
243
+ CapTable.statics.getByPerson = function getByPerson(options, cb) {
260
244
 
261
245
  var self = this;
262
246
 
247
+ if (!cb) { throw new Error('cb is required'); }
248
+ if (!options) { return cb(new Error('options is required'), null); }
249
+ if (!options.CUSTOMER_ID) { return cb(new Error('options.CUSTOMER_ID is required'), null); }
250
+ if (!mongoose.Types.ObjectId.isValid(options.CUSTOMER_ID)) { return cb(new Error('options.CUSTOMER_ID is not a valid ObjectId'), null); }
251
+
252
+ query = self.find({
253
+ customer: options.CUSTOMER_ID,
254
+ 'stakeholders.person': options.personId
255
+ });
256
+
263
257
  self
264
- .find({ 'stakeholders.person': personId })
265
258
  .populate('organization', 'name logoUrl')
266
259
  .exec(cb);
267
260
 
@@ -298,12 +291,7 @@ module.exports = function(mongoose, config) {
298
291
  capTable.entered.by = username;
299
292
  capTable.entered.on = new Date();
300
293
 
301
- self.update(
302
- { '_id': capTable._id },
303
- capTable,
304
- { upsert: false, multi: false, overwrite: true },
305
- cb
306
- );
294
+ self.update({ '_id': capTable._id }, capTable, { upsert: false, multi: false, overwrite: true }, cb);
307
295
 
308
296
  };
309
297
 
@@ -324,8 +312,7 @@ module.exports = function(mongoose, config) {
324
312
  query = self.find({
325
313
  customer: options.CUSTOMER_ID,
326
314
  'stakeholders.name': new RegExp(terms, 'i'),
327
- 'stakeholders.person': null,
328
- 'stakeholders.fund': null
315
+ 'stakeholders.person': null
329
316
  });
330
317
 
331
318
  query.populate('organization', 'name logoUrl');
@@ -352,44 +339,6 @@ module.exports = function(mongoose, config) {
352
339
  // Pre-save: fired on every document before it is saved
353
340
  ///////////////////////////////////////////////////////////////////////////////////////
354
341
 
355
- CapTable.pre('save', function(next) {
356
-
357
- var self = this;
358
-
359
- // Sum each stakeholders shares
360
- _.each(self.stakeholders, function(stakeholder) {
361
-
362
- var shares = _.reduce(stakeholder.rounds, function(memo, i) {
363
- return memo + i.shares;
364
- }, 0);
365
-
366
- stakeholder.shares = shares;
367
-
368
- });
369
-
370
- // Sum total shares
371
- self.shares = _.reduce(self.stakeholders, function(memo, stakeholder) {
372
- return memo + stakeholder.shares;
373
- }, 0);
374
-
375
- // Calculate each stakeholders ownership
376
- _.each(self.stakeholders, function(stakeholder) {
377
- if (self.shares == 0) stakeholder.shares = 0;
378
- else stakeholder.ownership = ((stakeholder.shares / self.shares) * 100).toFixed(2);
379
- });
380
-
381
- return next();
382
-
383
- });
384
-
385
- CapTable.post('init', function(doc, next) {
386
-
387
- doc.stakeholders = _.sortBy(doc.stakeholders, 'ownership').reverse();
388
-
389
- return next();
390
-
391
- });
392
-
393
342
  ///////////////////////////////////////////////////////////////////////////////////////
394
343
  // CONFIG
395
344
  ///////////////////////////////////////////////////////////////////////////////////////
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dhyasama/totem-models",
3
- "version": "9.4.2",
3
+ "version": "9.6.0",
4
4
  "author": "Jason Reynolds",
5
5
  "license": "UNLICENSED",
6
6
  "description": "Models for Totem platform",