@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/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "@dhyasama/totem-models",
3
- "version": "1.0.0",
3
+ "version": "1.6.0",
4
4
  "author": "Jason Reynolds",
5
- "license": "none",
5
+ "license": "UNLICENSED",
6
6
  "description": "Models for Totem platform",
7
7
  "main": "index.js",
8
8
  "scripts": {
@@ -16,7 +16,7 @@
16
16
  "@dhyasama/ffvc-geoip": "^1.0.0",
17
17
  "@dhyasama/ffvc-s3": "^1.0.0",
18
18
  "@dhyasama/ffvc-utilities": "^2.0.0",
19
- "async": "^0.9.0",
19
+ "async": "^2.6.0",
20
20
  "awesome-phonenumber": "^1.0.14",
21
21
  "bcrypt": "^0.8.0",
22
22
  "bluebird": "^3.5.0",
@@ -32,6 +32,7 @@
32
32
  "mocha-mongoose": "^1.2.0",
33
33
  "mongoose": "~4.5.7",
34
34
  "nock": "^7.2.2",
35
+ "rewire": "^3.0.2",
35
36
  "should": "^11.1.1"
36
37
  }
37
38
  }
@@ -0,0 +1,359 @@
1
+ "use strict";
2
+
3
+ var
4
+
5
+ should = require("should"),
6
+ config = require('./config')['test'],
7
+ mongoose = require('mongoose'),
8
+ clearDB = require('mocha-mongoose')(config.db.uri, {noClear: true}),
9
+ CapTable = mongoose.model('CapTable'),
10
+ Fund = mongoose.model('Fund'),
11
+ Organization = mongoose.model('Organization');
12
+
13
+ var customerid = new mongoose.Types.ObjectId();
14
+ var orgid = new mongoose.Types.ObjectId();
15
+ var org = new Organization();
16
+ var fund = new Fund();
17
+
18
+
19
+ describe('Cap Tables', function() {
20
+
21
+ before(function(done) {
22
+ if (mongoose.connection.db) return done();
23
+ mongoose.connect(config.db.uri, done);
24
+ });
25
+
26
+ before(function(done) {
27
+ clearDB(done);
28
+ });
29
+
30
+ before(function(done) {
31
+ CapTable.collection.dropIndexes(function (err, result) {
32
+ should.not.exist(err);
33
+ should.exist(result);
34
+ result.should.equal(true);
35
+ return done();
36
+ });
37
+ });
38
+
39
+ before(function(done) {
40
+
41
+ fund.name = 'My Huge Fund';
42
+ fund.slug = 'my-huge-fund';
43
+ fund.shortName = 'Huge';
44
+
45
+ Fund.upsert(fund, 'test-user', function(err, result) {
46
+ should.not.exist(err);
47
+ should.exist(result);
48
+ done();
49
+ });
50
+
51
+ });
52
+
53
+ before(function(done) {
54
+
55
+ org.name = 'No Thanks 2';
56
+ org.slug = 'org2-slug';
57
+ org.website = 'nothanks2.org';
58
+ org.funds.push(fund);
59
+
60
+ Organization.upsert(org, 'test', function(err, result) {
61
+ should.not.exist(err);
62
+ should.exist(result);
63
+ org = result;
64
+ done();
65
+ });
66
+
67
+ });
68
+
69
+ it('creates a cap table', function(done) {
70
+
71
+ var ct = new CapTable({
72
+ customer: customerid,
73
+ organization: orgid
74
+ });
75
+
76
+ ct.stakeholders.push({
77
+ name: 'Test Fund IV, LLC',
78
+ common:[{
79
+ round: 'Series A',
80
+ shares: 100
81
+ }, {
82
+ round: 'Series Seed',
83
+ shares: 200
84
+ }],
85
+ warrants:[{
86
+ round: 'Series A',
87
+ shares: 15
88
+ }],
89
+ fund: fund
90
+ });
91
+
92
+ ct.stakeholders.push({
93
+ name: 'My Little Trust',
94
+ common:[{
95
+ round: 'Series Seed',
96
+ shares: 50
97
+ }]
98
+ });
99
+
100
+ ct.stakeholders.push({
101
+ name: 'John Appleseed',
102
+ options:[{
103
+ round: 'Series Seed',
104
+ shares: 5
105
+ }]
106
+ });
107
+
108
+ CapTable.insert(ct, 'test', function(err, result) {
109
+ should.not.exist(err);
110
+ should.exist(result);
111
+ done();
112
+ });
113
+
114
+ });
115
+
116
+ it('prevents cap table from being created with both a person and a fund link', function(done) {
117
+
118
+ var ct = new CapTable({
119
+ customer: customerid,
120
+ organization: orgid
121
+ });
122
+
123
+ ct.stakeholders.push({
124
+ name: 'Test Fund IV, LLC',
125
+ person: new mongoose.Types.ObjectId(),
126
+ fund: new mongoose.Types.ObjectId()
127
+ });
128
+
129
+ CapTable.insert(ct, 'test', function(err, result) {
130
+ should.exist(err);
131
+ return done();
132
+ });
133
+
134
+ });
135
+
136
+ it('prevents cap table from being created with duplicate org/customer combo', function(done) {
137
+
138
+ var ct = new CapTable({
139
+ customer: customerid,
140
+ organization: orgid
141
+ });
142
+
143
+ CapTable.insert(ct, 'test', function(err, result) {
144
+ should.exist(err);
145
+ return done();
146
+ });
147
+
148
+ });
149
+
150
+ it('finds a cap table', function(done) {
151
+
152
+ CapTable.getForCustomer(orgid, customerid, function(err, result) {
153
+ should.not.exist(err);
154
+ should.exist(result);
155
+ done();
156
+ });
157
+
158
+ });
159
+
160
+ it('get a fund to org map', function(done) {
161
+
162
+ CapTable.getForCustomer(orgid, customerid, function(err, result) {
163
+
164
+ should.not.exist(err);
165
+ should.exist(result);
166
+
167
+ result.mapFundsToOrgs(function(err, result) {
168
+ should.not.exist(err);
169
+ should.exist(result);
170
+ result.length.should.equal(1);
171
+ result[0].fund.toString().should.equal(fund._id.toString());
172
+ result[0].org._id.toString().should.equal(org._id.toString());
173
+ return done();
174
+ });
175
+
176
+ });
177
+
178
+ });
179
+
180
+ it('auto-calculates dilution', function(done) {
181
+
182
+ CapTable.getForCustomer(orgid, customerid, function(err, result) {
183
+
184
+ should.not.exist(err);
185
+ should.exist(result);
186
+
187
+ result.fullyDiluted.should.be.above(0);
188
+
189
+ result.stakeholders.forEach(function(s) {
190
+ s.fullyDiluted.should.be.above(0);
191
+ s.fullyDilutedPercentage.should.be.above(0);
192
+ });
193
+
194
+ return done();
195
+
196
+ });
197
+
198
+ });
199
+
200
+ it('gets stakeholders by round', function(done) {
201
+
202
+ CapTable.getForCustomer(orgid, customerid, function(err, result) {
203
+
204
+ should.not.exist(err);
205
+ should.exist(result);
206
+
207
+ var stakeholders = result.stakeholdersByRound;
208
+ should.exist(stakeholders);
209
+ stakeholders.length.should.equal(2);
210
+ should.exist(stakeholders[0].round);
211
+ should.exist(stakeholders[0].participants);
212
+ stakeholders[0].participants.length.should.be.above(0);
213
+ should.exist(stakeholders[1].round);
214
+ should.exist(stakeholders[1].participants);
215
+ stakeholders[1].participants.length.should.be.above(0);
216
+
217
+ return done();
218
+
219
+ });
220
+
221
+ });
222
+
223
+ it('gets stakeholders by percentage', function(done) {
224
+
225
+ CapTable.getForCustomer(orgid, customerid, function(err, result) {
226
+
227
+ should.not.exist(err);
228
+ should.exist(result);
229
+
230
+ var stakeholders = result.stakeholders;
231
+ should.exist(stakeholders);
232
+
233
+ return done();
234
+
235
+ });
236
+
237
+ });
238
+
239
+ it('updates a document url', function(done) {
240
+
241
+ var url = 'https://s3.aws.amazon.com/bucket/key';
242
+
243
+ // get a table
244
+ CapTable.find({}, function (err, result1) {
245
+
246
+ should.not.exist(err);
247
+ should.exist(result1);
248
+ result1.length.should.be.above(0);
249
+
250
+ // update url
251
+ CapTable.updateOriginalDocumentUrl(result1[0]._id, url, function(err, result2) {
252
+
253
+ should.not.exist(err);
254
+ should.exist(result2);
255
+ result2.originalDocumentUrl.should.equal(url);
256
+
257
+ return done();
258
+
259
+ });
260
+
261
+ });
262
+
263
+ });
264
+
265
+ it('replaces a cap table', function(done) {
266
+
267
+ // get a table
268
+ CapTable.find({}, function (err, result1) {
269
+
270
+ should.not.exist(err);
271
+ should.exist(result1);
272
+ result1.length.should.be.above(0);
273
+
274
+ CapTable.replace(result1[0], 'test', function(err, result2) {
275
+
276
+ should.not.exist(err);
277
+ should.exist(result2);
278
+
279
+ return done();
280
+
281
+ });
282
+
283
+ });
284
+
285
+ });
286
+
287
+ it('deletes all cap tables for a customer', function(done) {
288
+
289
+ var cid = new mongoose.Types.ObjectId();
290
+ var ct1 = new CapTable({ customer: cid, organization: new mongoose.Types.ObjectId() });
291
+ var ct2 = new CapTable({ customer: cid, organization: new mongoose.Types.ObjectId() });
292
+ var ct3 = new CapTable({ customer: new mongoose.Types.ObjectId(), organization: new mongoose.Types.ObjectId() });
293
+
294
+ CapTable.find({}, function(err, result) {
295
+
296
+ should.not.exist(err);
297
+ should.exist(result);
298
+
299
+ var count = result.length;
300
+
301
+ CapTable.insert(ct1, 'test', function (err, result) {
302
+ should.not.exist(err);
303
+ should.exist(result);
304
+ CapTable.insert(ct2, 'test', function (err, result) {
305
+ should.not.exist(err);
306
+ should.exist(result);
307
+ CapTable.insert(ct3, 'test', function (err, result) {
308
+ should.not.exist(err);
309
+ should.exist(result);
310
+ CapTable.deleteAllForCustomer(cid, function (err, result) {
311
+
312
+ should.not.exist(err);
313
+ should.exist(result);
314
+
315
+ CapTable.find({}, function (err, result) {
316
+ should.not.exist(err);
317
+ should.exist(result);
318
+ result.length.should.equal(count + 1);
319
+ done();
320
+ });
321
+
322
+ });
323
+ });
324
+ });
325
+ });
326
+
327
+ });
328
+
329
+ });
330
+
331
+ it('deletes a specific cap table', function(done) {
332
+
333
+ // Get a table to delete
334
+ CapTable.find({}, function (err, result1) {
335
+
336
+ should.not.exist(err);
337
+ should.exist(result1);
338
+ result1.length.should.be.above(0);
339
+
340
+ // Delete it
341
+ CapTable.delete(result1[0]._id, function(err, result2) {
342
+
343
+ should.not.exist(err);
344
+ should.exist(result2);
345
+
346
+ // Make sure it's really gone
347
+ CapTable.findById(result2._id, function(err, result3) {
348
+ should.not.exist(err);
349
+ should.not.exist(result3);
350
+ return done();
351
+ });
352
+
353
+ });
354
+
355
+ });
356
+
357
+ });
358
+
359
+ });
@@ -0,0 +1,180 @@
1
+ "use strict";
2
+
3
+ var
4
+
5
+ should = require("should"),
6
+ config = require('./config')['test'],
7
+ mongoose = require('mongoose'),
8
+ clearDB = require('mocha-mongoose')(config.db.uri, {noClear: true}),
9
+ Investment = mongoose.model('Investment'),
10
+ Round = mongoose.model('Round');
11
+
12
+ var customerid = new mongoose.Types.ObjectId();
13
+
14
+ describe('Investments', function() {
15
+
16
+ before(function(done) {
17
+ if (mongoose.connection.db) return done();
18
+ mongoose.connect(config.db.uri, done);
19
+ });
20
+
21
+ before(function(done) {
22
+ clearDB(done);
23
+ });
24
+
25
+ before(function (done) {
26
+ Investment.collection.dropIndexes(function (err, result) {
27
+ should.not.exist(err);
28
+ should.exist(result);
29
+ result.should.equal(true);
30
+ return done();
31
+ });
32
+ });
33
+
34
+ it('creates an investment', function(done) {
35
+
36
+ var inv = new Investment({
37
+ customer: customerid,
38
+ cost: 200000,
39
+ costPlusInterest: 200000,
40
+ investmentDate: Date.now(),
41
+ pricePerShare: 0.002,
42
+ preMoneyValuation: 1000000,
43
+ dollarsRaised: 200000,
44
+ closingDate: Date.now()
45
+ });
46
+
47
+ Investment.upsert(inv, function(err, result) {
48
+ should.not.exist(err);
49
+ should.exist(result);
50
+ result.customer.should.equal(customerid);
51
+ result.cost.should.equal(200000);
52
+ done();
53
+ });
54
+
55
+ });
56
+
57
+ it('removes customer investments', function(done) {
58
+
59
+ var inv1 = new Investment({
60
+ customer: customerid,
61
+ amount: 1,
62
+ investmentDate: Date.now()
63
+ });
64
+
65
+ var inv2 = new Investment({
66
+ customer: new mongoose.Types.ObjectId(),
67
+ amount: 2,
68
+ investmentDate: Date.now()
69
+ });
70
+
71
+ Investment.upsert(inv1, function(err, result) {
72
+
73
+ should.not.exist(err);
74
+ should.exist(result);
75
+
76
+ Investment.upsert(inv2, function(err, result) {
77
+
78
+ should.not.exist(err);
79
+ should.exist(result);
80
+
81
+ Investment.removeCustomerInvestments(customerid, function(err) {
82
+
83
+ should.not.exist(err);
84
+
85
+ Investment.find({}, function(err, result) {
86
+ should.not.exist(err);
87
+ should.exist(result);
88
+ result.length.should.equal(1);
89
+ done();
90
+ });
91
+
92
+ });
93
+
94
+ });
95
+ });
96
+
97
+ });
98
+
99
+ it('removes investment reference from round when deleted', function(done) {
100
+
101
+ var inv1 = new Investment({
102
+ customer: customerid,
103
+ amount: 1,
104
+ investmentDate: Date.now()
105
+ });
106
+
107
+ var round1 = new Round({
108
+ organization: new mongoose.Types.ObjectId(),
109
+ roundName: 'Series Test'
110
+ });
111
+
112
+ Investment.upsert(inv1, function(err, result) {
113
+
114
+ should.not.exist(err);
115
+ should.exist(result);
116
+ inv1 = result;
117
+
118
+ Round.upsert(round1, function(err, result) {
119
+
120
+ should.not.exist(err);
121
+ should.exist(result);
122
+ round1 = result;
123
+
124
+ round1.addInvestment(inv1, new mongoose.Types.ObjectId());
125
+ Round.upsert(round1, function(err, result) {
126
+
127
+ should.not.exist(err);
128
+ should.exist(result);
129
+ round1.vehicles[0].investments.length.should.equal(1);
130
+
131
+ Investment.removeCustomerInvestments(customerid, function(err, results) {
132
+
133
+ should.not.exist(err);
134
+
135
+ setTimeout(function() {
136
+ Round.findById(round1._id, function(err, toot) {
137
+
138
+ should.not.exist(err);
139
+ should.exist(toot);
140
+
141
+ toot.vehicles[0].investments.length.should.equal(0);
142
+
143
+ done();
144
+
145
+ })
146
+ }, 1000);
147
+
148
+ });
149
+
150
+ });
151
+
152
+ });
153
+
154
+ });
155
+
156
+ });
157
+
158
+ it('cannot create a non-debt investment with a debt type', function(done) {
159
+
160
+ var inv = new Investment({
161
+ customer: customerid,
162
+ cost: 200000,
163
+ costPlusInterest: 200000,
164
+ investmentDate: Date.now(),
165
+ pricePerShare: 0.002,
166
+ preMoneyValuation: 1000000,
167
+ dollarsRaised: 200000,
168
+ closingDate: Date.now(),
169
+ debt: false,
170
+ debtType: 'SAFE'
171
+ });
172
+
173
+ Investment.upsert(inv, function(err, result) {
174
+ should.exist(err);
175
+ done();
176
+ });
177
+
178
+ });
179
+
180
+ });
package/test/News.js CHANGED
@@ -31,16 +31,11 @@ describe('News', function() {
31
31
  news.createdOn = Date.now();
32
32
  news.title = 'Google';
33
33
  news.link = 'http://google.com';
34
- news.fundsInvolved.push(fund._id);
35
34
  news.internal = false;
36
- news.discourse.id = '1';
37
- news.discourse.slug = 'google';
38
- news.discourse.firstPostId = '1';
39
35
 
40
36
  News.upsert(news, function(err, item) {
41
37
  should.not.exist(err);
42
38
  should.exist(item);
43
- item.fundsInvolved.length.should.equal(1);
44
39
  news = item;
45
40
  done();
46
41
  });
@@ -60,50 +55,29 @@ describe('News', function() {
60
55
 
61
56
  });
62
57
 
63
- it('gets a news item by id', function(done) {
64
- News.getById(news.id, function(err, item) {
65
- should.not.exist(err);
66
- should.exist(item);
67
- item.id.should.equal(news.id);
68
- done();
69
- });
70
- });
71
-
72
- it('lists all news items', function(done) {
73
- News.list(function(err, items) {
74
- should.not.exist(err);
75
- should.exist(items);
76
- items.length.should.equal(1);
77
- done();
78
- });
79
- });
80
-
81
- it('lists news items for a fund', function(done) {
82
- News.listForFunds([fund._id], function(err, items) {
83
- should.not.exist(err);
84
- should.exist(items);
85
- items.length.should.equal(1);
86
- done();
87
- });
58
+ it('gets a news item by id', function(done) {
59
+ News.getById(news.id, function(err, item) {
60
+ should.not.exist(err);
61
+ should.exist(item);
62
+ item.id.should.equal(news.id);
63
+ done();
64
+ });
88
65
  });
89
66
 
90
-
91
- it('lists news items for funds', function(done) {
92
- News.listForFunds([fund._id, new mongoose.Types.ObjectId()], function(err, items) {
93
- should.not.exist(err);
94
- should.exist(items);
95
- items.length.should.equal(1);
96
- done();
97
- });
67
+ it('lists all news items', function(done) {
68
+ News.list(function(err, items) {
69
+ should.not.exist(err);
70
+ should.exist(items);
71
+ items.length.should.equal(1);
72
+ done();
73
+ });
98
74
  });
99
75
 
100
- it('deletes a news item', function(done) {
101
- News.delete(news.id, function(err, item) {
102
- should.not.exist(err);
103
- done();
104
- });
105
- });
106
-
107
- // todo - listforcompany
76
+ it('deletes a news item', function(done) {
77
+ News.delete(news.id, function(err, item) {
78
+ should.not.exist(err);
79
+ done();
80
+ });
81
+ });
108
82
 
109
83
  });