@dhyasama/totem-models 1.0.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.
@@ -0,0 +1,780 @@
1
+ "use strict";
2
+
3
+ module.exports = function(mongoose, config) {
4
+
5
+ var
6
+
7
+ CUSTOMER_ID = config.CUSTOMER_ID,
8
+ LPS_ENABLED = config.LPS_ENABLED,
9
+ Schema = mongoose.Schema,
10
+ Fund = mongoose.model('Fund'),
11
+ Note = mongoose.model('Note'),
12
+ Organization = mongoose.model('Organization'),
13
+ env = process.env.NODE_ENV || 'development',
14
+ Crypto = require('@dhyasama/ffvc-crypto'),
15
+ crypto = new Crypto({'key': config.crypto.key}),
16
+ filter = require('mongoose-filter-denormalize').filter,
17
+ _ = require('underscore'),
18
+ async = require('async'),
19
+ utils = require('@dhyasama/ffvc-utilities');
20
+
21
+ var getFundIdsForCustomer = function(cb) {
22
+ Organization.getById(CUSTOMER_ID, function(err, org) {
23
+ if (err) return cb(err, null);
24
+ else if (!org) return cb(null, null);
25
+ var fundIds = _.map(org.funds, function(fund) {
26
+ return mongoose.Types.ObjectId.isValid(fund) || fund._id;
27
+ });
28
+ return cb(null, fundIds);
29
+ });
30
+ };
31
+
32
+ var LimitedPartner = new Schema({
33
+
34
+ name: { type: String, index: true, required: true },
35
+
36
+ shortName: { type: String, default: '' },
37
+
38
+ start: { type: String, default: '' },
39
+
40
+ people: [{
41
+ type: Schema.ObjectId,
42
+ ref: 'Person'
43
+ }],
44
+
45
+ documentSlugs: {
46
+ annualAudit: { type: String, default: '' },
47
+ capitalCall: { type: String, default: '' },
48
+ portfolioHolding: { type: String, default: '' },
49
+ k1: { type: String, default: '' },
50
+ distribution: { type: String, default: '' },
51
+ quarterlyAccountStatement: { type: String, default: '' }
52
+ },
53
+
54
+ fundsInvested: [{
55
+ fund: {type: Schema.ObjectId, ref: 'Fund'},
56
+ committed: {type: Number, default: 0},
57
+ called: {type: Number, default: 0}
58
+ }],
59
+
60
+ contact: {
61
+
62
+ phone: [{
63
+ type: { type: String, enum: ['home', 'work', 'assistant', 'mobile', 'other'] },
64
+ number: { type: String, default: '' },
65
+ primary: { type: Boolean, default: false }
66
+ }],
67
+
68
+ email: [{
69
+ type: { type: String, enum: ['personal', 'work', 'assistant', 'other'] },
70
+ email: { type: String, default: '' },
71
+ primary: { type: Boolean, default: false }
72
+ }],
73
+
74
+ address: [{
75
+ type: { type: String, default: '' },
76
+ street: { type: String, default: '' },
77
+ suite: { type: String, default: '' },
78
+ city: { type: String, default: '' },
79
+ state: { type: String, default: '' },
80
+ country: { type: String, default: '' },
81
+ postalCode: { type: String, default: '' },
82
+ primary: { type: Boolean, default: false }
83
+ }]
84
+
85
+ },
86
+
87
+ distributions: {
88
+
89
+ typeOf: { type: String, required: false, enum: [null, '', 'ACH', 'Check'] },
90
+
91
+ ach: {
92
+
93
+ stripeRecipientId: { type: String, default: ''},
94
+ legalName: { type: String, default: ''},
95
+ accountType: { type: String, required: false, enum: [null, '', 'Checking', 'Savings']},
96
+ taxId: { type: String, default: ''},
97
+ verified: { type: Boolean, default: false },
98
+
99
+ challengeDeposits: [{
100
+ id: { type: String },
101
+ created: { type: Date },
102
+ amount: { type: Number },
103
+ status: { type: String }
104
+ }],
105
+
106
+ bankAccount: {
107
+ name: { type: String, default: '' },
108
+ country: { type: String, default: '' },
109
+ routingNumber: { type: String, default: '' },
110
+ accountNumber: { type: String, default: '' }
111
+ }
112
+
113
+ },
114
+
115
+ check: {
116
+ address: {
117
+ addressOne: { type: String, default: '' },
118
+ addressTwo: { type: String, default: '' },
119
+ city: { type: String, default: '' },
120
+ state: { type: String, default: '' },
121
+ country: { type: String, default: '' },
122
+ postalCode: { type: String, default: '' }
123
+ }
124
+ }
125
+
126
+ },
127
+
128
+ k1: {
129
+ nameOfInvestor: { type: String, default: '' },
130
+ legalAddress: {
131
+ addressOne: { type: String, default: '' },
132
+ addressTwo: { type: String, default: '' },
133
+ city: { type: String, default: '' },
134
+ state: { type: String, default: '' },
135
+ country: { type: String, default: '' },
136
+ postalCode: { type: String, default: '' }
137
+ },
138
+ EIN: { type: String, default: null },
139
+ entityType: { type: String, enum: [null, 'Individual', 'Trust', 'Partnership', 'Corporation', 'LLC-Partnership', 'LLC-Corporation'] },
140
+ taxExempt: { type: Boolean, default: false },
141
+ USBased: { type: Boolean, default: true },
142
+ fundOrFundOfFunds: { type: Boolean, default: false },
143
+ deliverTo: [{type: String }],
144
+ consented: { type: Boolean, default: false },
145
+ changedBy: { type: String, default: null },
146
+ changedOn: { type: Date, default: null },
147
+ complete: { type: Boolean, default: false }
148
+ },
149
+
150
+ entered: {
151
+ by: { type: String, default: '' },
152
+ on: { type: Date, default: Date.now }
153
+ },
154
+
155
+ status: {
156
+ verified: { type: Boolean, default: false },
157
+ verifiedBy: { type: String, default: '' },
158
+ verifiedOn: { type: Date, default: Date.now }
159
+ },
160
+
161
+ flagged: {
162
+ by: { type: String, default: '' },
163
+ on: { type: Date, default: Date.now },
164
+ text: { type: String, default: '' },
165
+ resolved: { type: Boolean, default: false }
166
+ },
167
+
168
+ notes: [ { type: Schema.ObjectId, ref: 'Note' } ]
169
+
170
+ });
171
+
172
+ /////////////////////
173
+
174
+ LimitedPartner.virtual('email.primary').get(function () {
175
+ var primary = _.find(this.contact.email, function(email) {
176
+ return email.primary;
177
+ });
178
+ return primary ? primary.email : '';
179
+ });
180
+
181
+ LimitedPartner.virtual('phone.primary').get(function () {
182
+ var primary = _.find(this.contact.phone, function(phone) {
183
+ return phone.primary;
184
+ });
185
+ return primary ? primary.number : '';
186
+ });
187
+
188
+ LimitedPartner.virtual('address.primary').get(function () {
189
+
190
+ var primary = _.find(this.contact.address, function(address) {
191
+ return address.primary;
192
+ });
193
+
194
+ if (!primary) {
195
+ primary = {
196
+ street: '',
197
+ suite: '',
198
+ city: '',
199
+ state: '',
200
+ country: '',
201
+ postalCode: '',
202
+ primary: true
203
+ };
204
+ }
205
+
206
+ return primary;
207
+
208
+ });
209
+
210
+ LimitedPartner.virtual('sources').get(function () {
211
+
212
+ // Aggregate sources from all people
213
+ // Sort by interactions descending, full name ascending
214
+
215
+ var self = this;
216
+ var result = self.people || [];
217
+
218
+ if (result.length == 0) return [];
219
+ if (mongoose.Types.ObjectId.isValid(result[0])) return []; // not populated
220
+
221
+ result = _.pluck(result, 'sources');
222
+ result = _.flatten(result);
223
+ result = _.compact(result);
224
+ result = _.uniq(result, function(item) {
225
+ if (!item.person) return null;
226
+ var personId = utils.isValidObjectId(item.person) ? item.person : item.person._id;
227
+ return personId.toString();
228
+ });
229
+ result = _.compact(result);
230
+ result = _.sortBy(result, 'interactions.count');
231
+ result.reverse();
232
+ result = _.sortBy(result, 'name.full');
233
+
234
+ return result;
235
+
236
+ });
237
+
238
+ /////////////////////
239
+
240
+ /************* BASIC FIELDS **********************/
241
+
242
+ LimitedPartner.methods.newBasic = function(field, value) {
243
+
244
+ var compoundField = false;
245
+ if(field.split(".").length > 1) {
246
+ compoundField = true;
247
+ }
248
+
249
+ if(!compoundField) {
250
+ this[field] = value;
251
+ } else {
252
+ var parentField = field.split('.')[0];
253
+ var childField = field.split('.')[1];
254
+
255
+ this[parentField][childField] = value;
256
+ }
257
+
258
+ };
259
+
260
+ LimitedPartner.methods.updateBasic = function(field, value) {
261
+
262
+ var compoundField = false;
263
+ if(field.split(".").length > 1) {
264
+ compoundField = true;
265
+ }
266
+
267
+ if(!compoundField) {
268
+ var currentVal = this[field];
269
+ this[field] = value;
270
+ } else {
271
+ var parentField = field.split('.')[0];
272
+ var childField = field.split('.')[1];
273
+
274
+ var currentVal = this[parentField][childField];
275
+ this[parentField][childField] = value;
276
+ }
277
+
278
+ };
279
+
280
+ /************* CONTACT FIELDS **********************/
281
+
282
+ LimitedPartner.methods.updateContact = function(field, value) {
283
+
284
+ var parentField = field.split('.')[0];
285
+ var childField = field.split('.')[1];
286
+
287
+ this[parentField][childField] = value;
288
+
289
+ };
290
+
291
+ /********** PERSON RELATIONSHIPS ********************/
292
+
293
+ LimitedPartner.methods.addPerson = function(idOfPersonToAdd) {
294
+
295
+ var match = _.find(this.people, function(person) {
296
+ var personId = utils.isValidObjectId(person) ? person : person.id;
297
+ return personId.toString() == idOfPersonToAdd.toString();
298
+ });
299
+
300
+ if (!match) this.people.push(idOfPersonToAdd);
301
+
302
+ };
303
+
304
+ LimitedPartner.methods.removePerson = function(id) {
305
+
306
+ this.people = _.filter(this.people, function(person) {
307
+ return person.id != id;
308
+ });
309
+
310
+ };
311
+
312
+ LimitedPartner.methods.fundPercentCalled = function(fundId) {
313
+
314
+ if (!fundId) return 0;
315
+
316
+ var match = _.find(this.fundsInvested, function(inv) {
317
+ return inv.fund == fundId || inv.fund.id == fundId;
318
+ });
319
+
320
+ if (!match) return 0;
321
+
322
+ return (match.called / match.committed) * 100;
323
+
324
+ };
325
+
326
+ LimitedPartner.methods.listActiveFunds = function(cb) {
327
+
328
+ var lp = this;
329
+ var funds = [];
330
+
331
+ lp.populate('fundsInvested.fund', function(err) {
332
+
333
+ if (err) return cb(err, null);
334
+
335
+ _.each(lp.fundsInvested, function(investment) {
336
+ if (investment.committed > 0) { funds.push(investment); }
337
+ });
338
+
339
+ return cb(null, funds);
340
+
341
+ });
342
+
343
+ };
344
+
345
+ LimitedPartner.methods.docSlugs = function() {
346
+
347
+ var slugs = this.documentSlugs;
348
+ var fullName = this.name;
349
+
350
+ slugs.annualAudit = slugs.annualAudit || fullName;
351
+ slugs.capitalCall = slugs.capitalCall || fullName;
352
+ slugs.portfolioHolding = slugs.portfolioHolding || fullName;
353
+ slugs.k1 = slugs.k1 || fullName;
354
+ slugs.distribution = slugs.distribution || fullName;
355
+ slugs.quarterlyAccountStatement = slugs.quarterlyAccountStatement || fullName;
356
+
357
+ return slugs;
358
+
359
+ };
360
+
361
+ ////////////////////////
362
+
363
+ LimitedPartner.statics.findByTransaction = function (id, role, cb) {
364
+ this
365
+ .find({ 'distributions.ach.challengeDeposits.id': id }, this.getReadFilterKeys(role))
366
+ .exec(cb);
367
+ };
368
+
369
+ LimitedPartner.statics.getById = function(id, role, cb) {
370
+
371
+ var self = this;
372
+ var query;
373
+ var getLp = function() {
374
+ query.populate('fundsInvested.fund');
375
+ query.populate('people');
376
+ query.populate('notes');
377
+ query.deepPopulate([
378
+ 'people.sources.person',
379
+ 'people.calendarEventSummaries.attendees.internal',
380
+ 'people.calendarEventSummaries.attendees.external',
381
+ 'notes.createdBy',
382
+ 'people.calendarEventSummaries.notes.createdBy'
383
+ ], {
384
+ populate: {
385
+ 'people.sources.person': { select: 'name avatarUrl title' },
386
+ 'people.calendarEventSummaries.attendees.internal': { select: 'name avatarUrl title' },
387
+ 'people.calendarEventSummaries.attendees.external': { select: 'name avatarUrl title' },
388
+ 'notes.createdBy': { select: 'name avatarUrl' },
389
+ 'people.calendarEventSummaries.notes.createdBy': {select: ' avatarUrl name' }
390
+ }
391
+ });
392
+ query.exec(cb);
393
+ };
394
+
395
+ if (CUSTOMER_ID == 'GLOBAL_PROCESS') {
396
+ query = self.findById(id, self.getReadFilterKeys(role))
397
+ getLp();
398
+ }
399
+ else {
400
+ getFundIdsForCustomer(function(err, fundIds) {
401
+ if (err) return cb(err, null);
402
+ query = self.findOne({ '_id': id, 'fundsInvested.fund': { $in : fundIds }}, self.getReadFilterKeys(role));
403
+ getLp();
404
+ });
405
+ }
406
+
407
+ };
408
+
409
+ LimitedPartner.statics.getByPersonId = function(personId, role, cb) {
410
+
411
+ var self = this;
412
+
413
+ self
414
+ .find({'people': personId}, this.getReadFilterKeys(role))
415
+ .populate('fundsInvested.fund')
416
+ .populate('people', 'name')
417
+ .exec(cb);
418
+
419
+ };
420
+
421
+ LimitedPartner.statics.list = function (role, cb) {
422
+
423
+ // sorted by name ascending
424
+ // sort is done post retrieval because query sort is done pre-decryption
425
+ // filter by customer
426
+
427
+ var self = this;
428
+ var query;
429
+ var getLps = function() {
430
+ query.populate('fundsInvested.fund')
431
+ query.exec(function (err, lps) {
432
+
433
+ if (err) return cb(err, null);
434
+
435
+ lps = _.sortBy(lps, function(lp) {
436
+ return lp.name ? lp.name.toLowerCase() : '';
437
+ });
438
+
439
+ return cb(null, lps);
440
+ });
441
+ };
442
+
443
+ if (CUSTOMER_ID == 'GLOBAL_PROCESS') {
444
+ query = self.find({}, self.getReadFilterKeys(role));
445
+ getLps();
446
+ }
447
+ else {
448
+ getFundIdsForCustomer(function(err, fundIds) {
449
+ if (err) return cb(err, null);
450
+ query = self.find({ 'fundsInvested.fund': { $in : fundIds }}, self.getReadFilterKeys(role));
451
+ getLps();
452
+ });
453
+ }
454
+
455
+ };
456
+
457
+ LimitedPartner.statics.listAllUnverifiedLps = function (role, cb) {
458
+
459
+ if (role != 'admin') return cb(new Error('Unauthorized'), []);
460
+
461
+ this
462
+ .find({'status.verified': false}, this.getReadFilterKeys(role))
463
+ .populate('fundsInvested.fund')
464
+ .exec(function (err, lps) {
465
+ cb(err, _.sortBy(lps, function(lp) { return lp.name; }));
466
+ });
467
+
468
+ };
469
+
470
+ LimitedPartner.statics.listAllFlaggedLps = function (role, cb) {
471
+
472
+ if (role != 'admin') return cb(new Error('Unauthorized'), []);
473
+
474
+ this
475
+ .find({'flagged.resolved': false, 'flagged.text': { $ne: '' }}, this.getReadFilterKeys(role))
476
+ .populate('fundsInvested.fund')
477
+ .exec(function (err, lps) {
478
+ cb(err, _.sortBy(lps, function(lp) { return lp.name; }));
479
+ });
480
+
481
+ };
482
+
483
+ LimitedPartner.statics.listByFund = function (fundId, role, cb) {
484
+
485
+ // all lps in a fund, sorted by name ascending
486
+ // sort is done post retrieval because query sort is done pre-decryption
487
+
488
+ var self = this;
489
+
490
+ self
491
+ .find({ 'fundsInvested.fund': fundId }, self.getReadFilterKeys(role))
492
+ .populate('fundsInvested.fund')
493
+ .exec(function(err, lps) {
494
+
495
+ if (err) return cb(err, null);
496
+
497
+ lps = _.filter(lps, function(lp) {
498
+ if (CUSTOMER_ID == 'GLOBAL_PROCESS') { return lp; }
499
+ else {
500
+ var match = _.find(lp.fundsInvested, function(fund) {
501
+ return fund.fund.investor.toString() == CUSTOMER_ID.toString();
502
+ });
503
+ return typeof match != 'undefined';
504
+ }
505
+ });
506
+
507
+ lps = _.sortBy(lps, function(lp) {
508
+ return lp.name ? lp.name.toLowerCase() : '';
509
+ });
510
+
511
+ return cb(null, lps);
512
+
513
+ });
514
+
515
+ };
516
+
517
+ LimitedPartner.statics.listPeople = function(lpid, role, cb) {
518
+
519
+ var self = this;
520
+
521
+ self.getById(lpid, role, function(err, lp) {
522
+
523
+ if (err) return cb(err, null);
524
+
525
+ var people = _.map(lp.people, function(person) {
526
+ return {
527
+ _id: person._id,
528
+ name: person.name
529
+ }
530
+ });
531
+
532
+ return cb(null, people);
533
+
534
+ });
535
+
536
+ };
537
+
538
+ LimitedPartner.statics.search = function (terms, role, cb) {
539
+
540
+ var self = this;
541
+ var query;
542
+ var getLps = function() {
543
+ //query.select('name');
544
+ query.exec(function (err, lps) {
545
+
546
+ if (err) return cb(err, null);
547
+
548
+ lps = _.sortBy(lps, function(lp) {
549
+ return lp.name.toLowerCase();
550
+ });
551
+
552
+ return cb(null, lps);
553
+ });
554
+ };
555
+
556
+ if (CUSTOMER_ID == 'GLOBAL_PROCESS') {
557
+ query = self.find({'name': new RegExp(terms, "i")}, self.getReadFilterKeys(role));
558
+ getLps();
559
+ }
560
+ else {
561
+ getFundIdsForCustomer(function(err, fundIds) {
562
+ if (err) return cb(err, null);
563
+ query = self.find({ 'name': new RegExp(terms, "i"), 'fundsInvested.fund': { $in : fundIds }}, self.getReadFilterKeys(role));
564
+ getLps();
565
+ });
566
+ }
567
+
568
+ };
569
+
570
+ LimitedPartner.statics.upsert = function(lp, username, role, cb) {
571
+
572
+ if (!lp) { return cb(new Error('lp is required'), null); }
573
+ if (!username) { return cb(new Error('username is required'), null); }
574
+
575
+ lp.entered.by = username;
576
+ lp.entered.on = new Date();
577
+
578
+ lp.extendWithWriteFilter(lp, role);
579
+ lp.save(function(err, result) {
580
+ if (err) return cb(err, null);
581
+ result.applyReadFilter(role);
582
+ return cb(null, result);
583
+ });
584
+
585
+ };
586
+
587
+ //TODO: this is same as Person & Portfolio Company Function
588
+ //Helper function that multiple models can use...
589
+ LimitedPartner.statics.verify = function(lpId, verified, username, role, cb) {
590
+
591
+ this
592
+ .findById(lpId, this.getReadFilterKeys(role))
593
+ .exec(function(err, lp) {
594
+
595
+ lp.status.verified = verified;
596
+ lp.status.verifiedBy = username;
597
+ lp.status.verifiedOn = Date.now();
598
+
599
+ if(verified) {
600
+ lp.flagged.resolved = true;
601
+ }
602
+
603
+ return this.upsert(lp, username, role, cb);
604
+
605
+ });
606
+
607
+ };
608
+
609
+ LimitedPartner.statics.flag = function(lpId, resolved, text, username, role, cb) {
610
+
611
+ var context = this;
612
+
613
+ context
614
+ .findById(lpId, this.getReadFilterKeys(role))
615
+ .exec(function(err, lp) {
616
+
617
+ lp.flagged.resolved = resolved;
618
+ lp.flagged.text = text;
619
+ lp.flagged.by = username;
620
+ lp.flagged.on = Date.now();
621
+
622
+ if(!resolved) {
623
+ lp.status.verified = false;
624
+ }
625
+
626
+ return context.upsert(lp, username, role, cb);
627
+
628
+ });
629
+
630
+ };
631
+
632
+ LimitedPartner.statics.addNote = function(lpid, creatorPersonId, text, cb) {
633
+
634
+ Note.createForModel({
635
+ createdBy: creatorPersonId,
636
+ text: text
637
+ }, this, lpid, cb);
638
+
639
+ };
640
+
641
+ LimitedPartner.statics.deleteNote = function(noteId, cb) {
642
+
643
+ // Delete the note itself along with any references
644
+
645
+ var self = this;
646
+
647
+ var removeReferences = function removeReferences(callback) {
648
+ self.update({}, {
649
+ $pull: { 'notes' : [noteId] }
650
+ }, callback);
651
+ };
652
+
653
+ async.series([
654
+ Note.delete.bind(Note, noteId),
655
+ removeReferences
656
+ ], function(err, results) {
657
+ return cb(err, null);
658
+ });
659
+
660
+ };
661
+
662
+ //////////////////////////////
663
+
664
+ LimitedPartner.pre('save', function(next) {
665
+
666
+ var self = this;
667
+
668
+ var encryptSensitiveData = function(cb) {
669
+
670
+ if (self.distributions.ach.accountType) { self.distributions.ach.accountType = crypto.encrypt(self.distributions.ach.accountType); }
671
+ if (self.distributions.ach.stripeRecipientId) { self.distributions.ach.stripeRecipientId = crypto.encrypt(self.distributions.ach.stripeRecipientId); }
672
+ if (self.distributions.ach.legalName) { self.distributions.ach.legalName = crypto.encrypt(self.distributions.ach.legalName); }
673
+ if (self.distributions.ach.taxId) { self.distributions.ach.taxId = crypto.encrypt(self.distributions.ach.taxId); }
674
+ if (self.distributions.ach.bankAccount.name) { self.distributions.ach.bankAccount.name = crypto.encrypt(self.distributions.ach.bankAccount.name); }
675
+ if (self.distributions.ach.bankAccount.country) { self.distributions.ach.bankAccount.country = crypto.encrypt(self.distributions.ach.bankAccount.country); }
676
+ if (self.distributions.ach.bankAccount.routingNumber) { self.distributions.ach.bankAccount.routingNumber = crypto.encrypt(self.distributions.ach.bankAccount.routingNumber); }
677
+ if (self.distributions.ach.bankAccount.accountNumber) { self.distributions.ach.bankAccount.accountNumber = crypto.encrypt(self.distributions.ach.bankAccount.accountNumber); }
678
+ if (self.k1.EIN) { self.k1.EIN = crypto.encrypt(self.k1.EIN); }
679
+
680
+ return cb();
681
+
682
+ };
683
+
684
+ encryptSensitiveData(function() {
685
+ return next();
686
+ });
687
+
688
+ // var takeSnapshot = function(cb) {
689
+ //
690
+ // var LimitedPartnerHistory = mongoose.model('LimitedPartnerHistory');
691
+ // var snapshot = new LimitedPartnerHistory();
692
+ // snapshot.create(self, 'jason', function(err, result) {
693
+ // if (err) {} // todo: alert admin to fix; ok to proceed;
694
+ // return cb();
695
+ // });
696
+ //
697
+ // };
698
+ //
699
+ // encryptSensitiveData(function() {
700
+ // takeSnapshot(function() {
701
+ // return next();
702
+ // })
703
+ // });
704
+
705
+
706
+ });
707
+
708
+ LimitedPartner.pre('init', function(next) {
709
+ if (!LPS_ENABLED) throw new Error('LPS_ENABLED is false');
710
+ else next();
711
+ });
712
+
713
+ LimitedPartner.post('init', function() {
714
+
715
+ // Decrypt sensitive data
716
+
717
+ if (this.distributions && this.distributions.ach) {
718
+ if (this.distributions.ach.accountType) {
719
+ this.distributions.ach.accountType = crypto.decrypt(this.distributions.ach.accountType);
720
+ }
721
+ if (this.distributions.ach.stripeRecipientId) {
722
+ this.distributions.ach.stripeRecipientId = crypto.decrypt(this.distributions.ach.stripeRecipientId);
723
+ }
724
+ if (this.distributions.ach.legalName) {
725
+ this.distributions.ach.legalName = crypto.decrypt(this.distributions.ach.legalName);
726
+ }
727
+ if (this.distributions.ach.taxId) {
728
+ this.distributions.ach.taxId = crypto.decrypt(this.distributions.ach.taxId);
729
+ }
730
+ if (this.distributions.ach.bankAccount.name) {
731
+ this.distributions.ach.bankAccount.name = crypto.decrypt(this.distributions.ach.bankAccount.name);
732
+ }
733
+ if (this.distributions.ach.bankAccount.country) {
734
+ this.distributions.ach.bankAccount.country = crypto.decrypt(this.distributions.ach.bankAccount.country);
735
+ }
736
+ if (this.distributions.ach.bankAccount.routingNumber) {
737
+ this.distributions.ach.bankAccount.routingNumber = crypto.decrypt(this.distributions.ach.bankAccount.routingNumber);
738
+ }
739
+ if (this.distributions.ach.bankAccount.accountNumber) {
740
+ this.distributions.ach.bankAccount.accountNumber = crypto.decrypt(this.distributions.ach.bankAccount.accountNumber);
741
+ }
742
+ }
743
+
744
+ if (this.k1 && this.k1.EIN) { this.k1.EIN = crypto.decrypt(this.k1.EIN); }
745
+
746
+ });
747
+
748
+ //////////////////////////////
749
+
750
+ LimitedPartner.plugin(filter, {
751
+ readFilter: {
752
+ 'admin': ['name', 'shortName', 'start', 'people', 'documentSlugs', 'fundsInvested', 'contact', 'distributions', 'k1', 'entered', 'status', 'flagged', 'notes'],
753
+ 'lp-full': ['name', 'shortName', 'start', 'people', 'documentSlugs', 'fundsInvested', 'contact', 'distributions', 'k1', 'entered', 'status', 'flagged', 'notes'],
754
+ 'lp-names': ['name', 'shortName', 'flagged'],
755
+ 'none': []
756
+ },
757
+ writeFilter: {
758
+ 'admin': ['name', 'shortName', 'start', 'people', 'documentSlugs', 'fundsInvested', 'contact', 'distributions', 'k1', 'entered', 'status', 'flagged', 'notes'],
759
+ 'lp-full': ['name', 'shortName', 'start', 'people', 'documentSlugs', 'fundsInvested', 'contact', 'distributions', 'k1', 'entered', 'status', 'flagged', 'notes'],
760
+ 'lp-names': ['flagged'],
761
+ 'none': []
762
+ },
763
+ defaultFilterRole: 'none', // default to no read or write
764
+ sanitize: false, // Escape HTML in strings
765
+ compat: false // Enable compatibility for Mongoose versions prior to 3.6
766
+ });
767
+
768
+ //////////////////////////////
769
+
770
+ LimitedPartner.set('autoIndex', true);
771
+ LimitedPartner.on('index', function(err) { console.log('error building limited partner indexes: ' + err); });
772
+
773
+ LimitedPartner.set('toJSON', { virtuals: true });
774
+
775
+ var deepPopulate = require('mongoose-deep-populate')(mongoose);
776
+ LimitedPartner.plugin(deepPopulate);
777
+
778
+ mongoose.model('LimitedPartner', LimitedPartner);
779
+
780
+ };