@dhyasama/totem-models 1.22.2 → 1.23.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.
@@ -19,8 +19,8 @@ module.exports = function(mongoose, config) {
19
19
  async = require('async'),
20
20
  utils = require('@dhyasama/ffvc-utilities');
21
21
 
22
- var getFundIdsForCustomer = function(cb) {
23
- Organization.getById(CUSTOMER_ID, function(err, org) {
22
+ var getFundIdsForOrg = function(id, cb) {
23
+ Organization.getById(id, function(err, org) {
24
24
  if (err) return cb(err, null);
25
25
  else if (!org) return cb(null, null);
26
26
  var fundIds = _.map(org.funds, function(fund) {
@@ -36,6 +36,8 @@ module.exports = function(mongoose, config) {
36
36
 
37
37
  shortName: { type: String, default: '' },
38
38
 
39
+ customer: { type: Schema.ObjectId, ref: 'Organization' },
40
+
39
41
  start: { type: String, default: '' },
40
42
 
41
43
  people: [{
@@ -400,7 +402,7 @@ module.exports = function(mongoose, config) {
400
402
  getLp();
401
403
  }
402
404
  else {
403
- getFundIdsForCustomer(function(err, fundIds) {
405
+ getFundIdsForOrg(CUSTOMER_ID, function(err, fundIds) {
404
406
  if (err) return cb(err, null);
405
407
  query = self.findOne({ '_id': id, 'fundsInvested.fund': { $in : fundIds }}, self.getReadFilterKeys(role));
406
408
  getLp();
@@ -429,19 +431,13 @@ module.exports = function(mongoose, config) {
429
431
  getLps(query);
430
432
  }
431
433
  else {
432
- getFundIdsForCustomer(function(err, fundIds) {
434
+ getFundIdsForOrg(CUSTOMER_ID, function(err, fundIds) {
433
435
  if (err) return cb(err, null);
434
436
  query = self.find({'people': personId, 'fundsInvested.fund': { $in : fundIds }}, self.getReadFilterKeys(role));
435
437
  getLps(query);
436
438
  });
437
439
  }
438
440
 
439
- // self
440
- // .find({'people': personId}, this.getReadFilterKeys(role))
441
- // .populate('fundsInvested.fund')
442
- // .populate('people', 'name')
443
- // .exec(cb);
444
-
445
441
  };
446
442
 
447
443
  LimitedPartner.statics.getFlags = function getFlags(lpid, cb) {
@@ -514,7 +510,7 @@ module.exports = function(mongoose, config) {
514
510
  getLps(query);
515
511
  }
516
512
  else {
517
- getFundIdsForCustomer(function(err, fundIds) {
513
+ getFundIdsForOrg(CUSTOMER_ID, function(err, fundIds) {
518
514
  if (err) return cb(err, null);
519
515
  query = self.find({ 'fundsInvested.fund': { $in : fundIds }}, self.getReadFilterKeys(role));
520
516
  getLps(query);
@@ -523,6 +519,31 @@ module.exports = function(mongoose, config) {
523
519
 
524
520
  };
525
521
 
522
+ LimitedPartner.statics.listForOrganization = function (orgid, role, cb) {
523
+
524
+ // sorted by name ascending
525
+ // sort is done post retrieval because query sort is done pre-decryption
526
+
527
+ var self = this;
528
+ var query;
529
+
530
+ var getLps = function(q) {
531
+ q.populate('fundsInvested.fund')
532
+ q.exec(function (err, lps) {
533
+ if (err) return cb(err, null);
534
+ lps = _.sortBy(lps, function(lp) { return lp.name ? lp.name.toLowerCase() : ''; });
535
+ return cb(null, lps);
536
+ });
537
+ };
538
+
539
+ getFundIdsForOrg(orgid, function(err, fundIds) {
540
+ if (err) return cb(err, null);
541
+ query = self.find({ 'fundsInvested.fund': { $in : fundIds }}, self.getReadFilterKeys(role));
542
+ getLps(query);
543
+ });
544
+
545
+ };
546
+
526
547
  LimitedPartner.statics.listAllUnverifiedLps = function (role, cb) {
527
548
 
528
549
  if (role != 'admin') return cb(new Error('Unauthorized'), []);
@@ -617,7 +638,7 @@ module.exports = function(mongoose, config) {
617
638
  getLps();
618
639
  }
619
640
  else {
620
- getFundIdsForCustomer(function(err, fundIds) {
641
+ getFundIdsForOrg(CUSTOMER_ID, function(err, fundIds) {
621
642
  if (err) return cb(err, null);
622
643
  query = self.find({ 'name': new RegExp(terms, "i"), 'fundsInvested.fund': { $in : fundIds }}, self.getReadFilterKeys(role));
623
644
  getLps();
@@ -643,6 +664,7 @@ module.exports = function(mongoose, config) {
643
664
 
644
665
  };
645
666
 
667
+ // Deprecated
646
668
  LimitedPartner.statics.flag = function(lpId, resolved, text, username, role, cb) {
647
669
 
648
670
  var context = this;
@@ -762,12 +784,16 @@ module.exports = function(mongoose, config) {
762
784
  LimitedPartner.post('init', function(doc, next) {
763
785
 
764
786
  if (CUSTOMER_ID != 'GLOBAL_PROCESS' && !LPS_ENABLED) {
765
- doc = null;
766
- return next();
787
+
788
+ // Don't return doc if lps aren't enabled or lp doesn't belong to current customer
789
+ if (!LPS_ENABLED || doc.customer != CUSTOMER_ID) {
790
+ doc = null;
791
+ return next();
792
+ }
793
+
767
794
  }
768
795
 
769
796
  // Decrypt sensitive data
770
-
771
797
  if (this.distributions && this.distributions.ach) {
772
798
  if (this.distributions.ach.accountType) {
773
799
  this.distributions.ach.accountType = crypto.decrypt(this.distributions.ach.accountType);
@@ -794,7 +820,6 @@ module.exports = function(mongoose, config) {
794
820
  this.distributions.ach.bankAccount.accountNumber = crypto.decrypt(this.distributions.ach.bankAccount.accountNumber);
795
821
  }
796
822
  }
797
-
798
823
  if (this.k1 && this.k1.EIN) { this.k1.EIN = crypto.decrypt(this.k1.EIN); }
799
824
 
800
825
  next();
@@ -785,7 +785,10 @@ module.exports = function(mongoose, config) {
785
785
  .populate('funds', 'name hexColorCode closeDate')
786
786
  .populate('operating.acquired.public.by', 'name logoUrl')
787
787
  .populate('operating.acquired.private.by', 'name logoUrl')
788
- .populate('lps')
788
+ .populate({
789
+ path: 'lps',
790
+ match: { customer: config.CUSTOMER_ID }
791
+ })
789
792
  .deepPopulate([
790
793
  'people.person.sources.person',
791
794
  'people.person.calendarEventSummaries.attendees.internal',
@@ -941,6 +944,16 @@ module.exports = function(mongoose, config) {
941
944
 
942
945
  };
943
946
 
947
+ Organization.statics.listCustomers = function listCustomers(cb) {
948
+
949
+ var self = this;
950
+
951
+ self
952
+ .find({$where:'this.customer && this.customer.totemUrl && this.customer.totemUrl.length >=1'})
953
+ .exec(cb);
954
+
955
+ };
956
+
944
957
  Organization.statics.listPage = function (skip, cb) {
945
958
 
946
959
  this
@@ -1152,15 +1165,80 @@ module.exports = function(mongoose, config) {
1152
1165
 
1153
1166
  var self = this;
1154
1167
 
1155
- // Format website
1156
- if (self.website) self.website = utils.getDomain(self.website);
1168
+ var cleanContactInfo = function cleanContactInfo() {
1169
+
1170
+ var thereCanOnlyBeOne = function thereCanOnlyBeOne(items) {
1171
+
1172
+ var primaryItems = _.filter(items, function(item) { return item.primary; });
1157
1173
 
1158
- // Format website aliases
1159
- if (self.websiteAliases && self.websiteAliases.length >= 1) {
1160
- self.websiteAliases = _.map(self.websiteAliases, function(alias) {
1161
- return utils.getDomain(alias);
1174
+ if (primaryItems.length > 1) {
1175
+
1176
+ _.each(primaryItems, function(item, index) {
1177
+ // skip the first one (leave it primary) and mark the rest as not primary
1178
+ if (index >= 1) item.primary = false;
1179
+ });
1180
+
1181
+ }
1182
+
1183
+ return items;
1184
+
1185
+ };
1186
+
1187
+ // must have something meaningful
1188
+ self.contact.address = _.map(self.contact.address, function(address) {
1189
+ if (!address.city && !address.state && !address.country) return null;
1190
+ else return address;
1191
+ });
1192
+
1193
+ self.contact.email = _.map(self.contact.email, function(item) {
1194
+ if (!item.email) return null;
1195
+ else return item;
1196
+ });
1197
+
1198
+ self.contact.phone = _.map(self.contact.phone, function(item) {
1199
+ if (!item.number) return null;
1200
+ else return item;
1162
1201
  });
1163
- }
1202
+
1203
+ // remove emptiness and dedupe
1204
+ self.contact.address = _.uniq(_.compact(self.contact.address), function(item) { return item.city + item.state + item.country; });
1205
+ self.contact.email = _.uniq(_.compact(self.contact.email), function(item) { return item.email; });
1206
+ self.contact.phone = _.uniq(_.compact(self.contact.phone), function(item) { return item.number; });
1207
+
1208
+ // only one primary
1209
+ self.contact.address = thereCanOnlyBeOne(self.contact.address);
1210
+ self.contact.email = thereCanOnlyBeOne(self.contact.email);
1211
+ self.contact.phone = thereCanOnlyBeOne(self.contact.phone);
1212
+
1213
+ };
1214
+
1215
+ var cleanPeople = function cleanPeople() {
1216
+
1217
+ // remove junk
1218
+ self.people = _.reject(self.people, function(p) { return p.person == null; });
1219
+
1220
+ // dedupe
1221
+ self.people = _.uniq(self.people, function(p) { return p.person._id ? p.person._id : p.person; });
1222
+
1223
+ };
1224
+
1225
+ var cleanWebsites = function cleanWebsites() {
1226
+
1227
+ // Format website
1228
+ if (self.website) self.website = utils.getDomain(self.website);
1229
+
1230
+ // Format website aliases
1231
+ if (self.websiteAliases && self.websiteAliases.length >= 1) {
1232
+ self.websiteAliases = _.map(self.websiteAliases, function(alias) {
1233
+ return utils.getDomain(alias);
1234
+ });
1235
+ }
1236
+
1237
+ };
1238
+
1239
+ cleanContactInfo();
1240
+ cleanPeople();
1241
+ cleanWebsites();
1164
1242
 
1165
1243
  return next();
1166
1244
 
@@ -1178,6 +1256,7 @@ module.exports = function(mongoose, config) {
1178
1256
  // remove customer details if not viewing self
1179
1257
  if (doc._id.toString() != CUSTOMER_ID) doc.customer = {};
1180
1258
 
1259
+ doc.lps = _.reject(doc.lps, function(item) { return !item.customer || item.customer.toString() != CUSTOMER_ID; });
1181
1260
  doc.filters = _.reject(doc.filters, function(item) { return !item.customer || item.customer.toString() != CUSTOMER_ID; });
1182
1261
  doc.docs = _.reject(doc.docs, function(item) { return !item.customer || item.customer.toString() != CUSTOMER_ID; });
1183
1262
  doc.iLevel = _.reject(doc.iLevel, function(item) { return !item.customer || item.customer.toString() != CUSTOMER_ID; });
@@ -1197,20 +1276,6 @@ module.exports = function(mongoose, config) {
1197
1276
 
1198
1277
  });
1199
1278
 
1200
- // var customerFunds = doc.constructor.customerFunds;
1201
- // //console.log('customerFunds', customerFunds);
1202
- // doc.lps = _.filter(doc.lps, function(lp) {
1203
- // var lpFunds = _.pluck(lp.fundsInvested, 'fund');
1204
- // var intersection = _.intersection(lpFunds, customerFunds);
1205
- // return intersection.length >= 1;
1206
- // });
1207
-
1208
- // will there ever be a reason to show an org's lps?
1209
- // a customer should only be able to see their own lps, which are queried and viewable on /lps
1210
- // and if it's not used, why is it here?
1211
- // todo - research flipping ref onto lp model
1212
- doc.lps = [];
1213
-
1214
1279
  return next();
1215
1280
 
1216
1281
  });
package/lib/Person.js CHANGED
@@ -1112,9 +1112,52 @@ module.exports = function(mongoose, config) {
1112
1112
 
1113
1113
  var self = this;
1114
1114
 
1115
+ var thereCanOnlyBeOne = function thereCanOnlyBeOne(items) {
1116
+
1117
+ var primaryItems = _.filter(items, function(item) { return item.primary; });
1118
+
1119
+ if (primaryItems.length > 1) {
1120
+
1121
+ _.each(primaryItems, function(item, index) {
1122
+ // skip the first one (leave it primary) and mark the rest as not primary
1123
+ if (index >= 1) item.primary = false;
1124
+ });
1125
+
1126
+ }
1127
+
1128
+ return items;
1129
+
1130
+ };
1131
+
1115
1132
  // set full name for ease of searching
1116
1133
  self.fullName = self.name.first + ' ' + self.name.last;
1117
1134
 
1135
+ // must have something meaningful
1136
+ self.contact.address = _.map(self.contact.address, function(address) {
1137
+ if (!address.city && !address.state && !address.country) return null;
1138
+ else return address;
1139
+ });
1140
+
1141
+ self.contact.email = _.map(self.contact.email, function(item) {
1142
+ if (!item.email) return null;
1143
+ else return item;
1144
+ });
1145
+
1146
+ self.contact.phone = _.map(self.contact.phone, function(item) {
1147
+ if (!item.number) return null;
1148
+ else return item;
1149
+ });
1150
+
1151
+ // remove emptiness and dedupe
1152
+ self.contact.address = _.uniq(_.compact(self.contact.address), function(item) { return item.city + item.state + item.country; });
1153
+ self.contact.email = _.uniq(_.compact(self.contact.email), function(item) { return item.email; });
1154
+ self.contact.phone = _.uniq(_.compact(self.contact.phone), function(item) { return item.number; });
1155
+
1156
+ // only one primary
1157
+ self.contact.address = thereCanOnlyBeOne(self.contact.address);
1158
+ self.contact.email = thereCanOnlyBeOne(self.contact.email);
1159
+ self.contact.phone = thereCanOnlyBeOne(self.contact.phone);
1160
+
1118
1161
  // Reset counters so we can calc from scratch
1119
1162
  _.each(self.sources, function(source) {
1120
1163
  source.interactions.calendar = 0;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dhyasama/totem-models",
3
- "version": "1.22.2",
3
+ "version": "1.23.0",
4
4
  "author": "Jason Reynolds",
5
5
  "license": "UNLICENSED",
6
6
  "description": "Models for Totem platform",
@@ -3,17 +3,22 @@
3
3
  var
4
4
 
5
5
  should = require("should"),
6
+ _ = require('underscore'),
6
7
  config = require('./config')['test'],
7
8
  mongoose = require('mongoose'),
8
9
  clearDB = require('mocha-mongoose')(config.db.uri, {noClear: true}),
9
10
  Organization = mongoose.model('Organization'),
10
11
  Person = mongoose.model('Person'),
12
+ LimitedPartner = mongoose.model('LimitedPartner'),
13
+ Fund = mongoose.model('Fund'),
11
14
  Note = mongoose.model('Note');
12
15
 
13
16
  var person, person1, person2;
14
17
  var noteId;
15
18
  var eventNote;
16
19
  var flagId;
20
+ var someOtherFund;
21
+ var someOtherLp;
17
22
 
18
23
  describe('Organization', function() {
19
24
 
@@ -47,6 +52,15 @@ describe('Organization', function() {
47
52
  });
48
53
  });
49
54
 
55
+ before(function (done) {
56
+ Fund.collection.dropIndexes(function (err, result) {
57
+ should.not.exist(err);
58
+ should.exist(result);
59
+ result.should.equal(true);
60
+ return done();
61
+ });
62
+ });
63
+
50
64
  before(function (done) {
51
65
 
52
66
  org2 = new Organization();
@@ -208,6 +222,45 @@ describe('Organization', function() {
208
222
 
209
223
  });
210
224
 
225
+ before(function(done) {
226
+
227
+ var f = new Fund();
228
+ f.name = 'FUND XYZ';
229
+ f.shortName = 'xyz';
230
+ f.slug = 'fund-xyz';
231
+
232
+ Fund.upsert(f, 'test', function(err, fundResult) {
233
+
234
+ should.not.exist(err);
235
+ should.exist(fundResult);
236
+
237
+ someOtherFund = fundResult;
238
+
239
+ done();
240
+
241
+ });
242
+
243
+ });
244
+
245
+ before(function(done) {
246
+
247
+ var lp = new LimitedPartner();
248
+ lp.name = 'SOME OTHER LP';
249
+ lp.fundsInvested.push({fund:someOtherFund});
250
+
251
+ LimitedPartner.upsert(lp, 'test', 'lp-full', function(err, lpResult) {
252
+
253
+ should.not.exist(err);
254
+ should.exist(lpResult);
255
+
256
+ someOtherLp = lpResult;
257
+
258
+ done();
259
+
260
+ });
261
+
262
+ });
263
+
211
264
  before(function(done) {
212
265
 
213
266
  var providerEventId = 'some_other_random_data';
@@ -800,6 +853,172 @@ describe('Organization', function() {
800
853
 
801
854
  });
802
855
 
856
+ it('gets lps', function(done) {
857
+
858
+ var lp = new LimitedPartner();
859
+ lp.name = 'LP';
860
+ lp.customer = config.CUSTOMER_ID;
861
+
862
+ LimitedPartner.upsert(lp, 'test', 'lp-full', function(err, lpResult) {
863
+
864
+ should.not.exist(err);
865
+ should.exist(lpResult);
866
+
867
+ var o = new Organization();
868
+ o.name = 'ORG';
869
+ o.slug = 'org';
870
+ o.website = 'org.org';
871
+ o.lps.push(lpResult);
872
+ o.lps.push(someOtherLp);
873
+
874
+ Organization.upsert(o, 'test-user', function(err, orgResult) {
875
+
876
+ should.not.exist(err);
877
+ should.exist(orgResult);
878
+
879
+ Organization.getById(orgResult._id, function(err, result) {
880
+
881
+ should.not.exist(err);
882
+ should.exist(result);
883
+ result.lps.length.should.equal(1);
884
+ result.lps[0]._id.toString().should.equal(lpResult._id.toString());
885
+
886
+ done();
887
+
888
+ });
889
+
890
+ });
891
+
892
+ });
893
+
894
+ });
895
+
896
+ it('cleans contact info', function(done) {
897
+
898
+ var o = new Organization();
899
+ o.name = 'ORG';
900
+ o.slug = 'org';
901
+ o.website = 'org.org';
902
+
903
+ o.contact.address = [];
904
+ o.contact.address.push({
905
+ city: 'Testville',
906
+ state: 'Test',
907
+ country: 'TSA',
908
+ type: 'work',
909
+ primary: true
910
+ });
911
+ o.contact.address.push({
912
+ city: 'Testville',
913
+ state: 'Test',
914
+ country: 'TSA',
915
+ type: 'other',
916
+ primary: true
917
+ });
918
+ o.contact.address.push({
919
+ city: 'Bangor',
920
+ state: 'ME',
921
+ country: 'USA',
922
+ type: 'other',
923
+ primary: true
924
+ });
925
+ o.contact.address.push({
926
+ city: '',
927
+ state: '',
928
+ country: '',
929
+ type: 'other',
930
+ primary: true
931
+ });
932
+
933
+ o.contact.email = [];
934
+ o.contact.email.push({
935
+ email: 'test@org.org',
936
+ type: 'work',
937
+ primary: true
938
+ });
939
+ o.contact.email.push({
940
+ email: 'test@org.org',
941
+ type: 'other',
942
+ primary: true
943
+ });
944
+ o.contact.email.push({
945
+ email: 'admin@org.org',
946
+ type: 'other',
947
+ primary: true
948
+ });
949
+ o.contact.email.push({
950
+ email: '',
951
+ type: 'test',
952
+ primary: false
953
+ });
954
+
955
+ o.contact.phone = [];
956
+ o.contact.phone.push({
957
+ number: '2075551212',
958
+ type: 'work',
959
+ primary: true
960
+ });
961
+ o.contact.phone.push({
962
+ number: '2075551212',
963
+ type: 'other',
964
+ primary: true
965
+ });
966
+ o.contact.phone.push({
967
+ number: null,
968
+ type: null,
969
+ primary: null
970
+ });
971
+ o.contact.phone.push({
972
+ number: '3455551212',
973
+ type: 'other',
974
+ primary: true
975
+ });
976
+
977
+ Organization.upsert(o, 'test-user', function(err, org) {
978
+
979
+ should.not.exist(err);
980
+ should.exist(org);
981
+
982
+ org.contact.address.length.should.equal(2);
983
+ org.contact.email.length.should.equal(2);
984
+ org.contact.phone.length.should.equal(2);
985
+
986
+ var primaryAddresses = _.filter(org.contact.address, function(item) { return item.primary; });
987
+ primaryAddresses.length.should.be.lessThan(2);
988
+
989
+ var primaryEmails = _.filter(org.contact.email, function(item) { return item.primary; });
990
+ primaryEmails.length.should.be.lessThan(2);
991
+
992
+ var primaryPhones = _.filter(org.contact.phone, function(item) { return item.primary; });
993
+ primaryPhones.length.should.be.lessThan(2);
994
+
995
+ done();
996
+
997
+ });
998
+ });
999
+
1000
+ it('cleans people', function(done) {
1001
+
1002
+ var littleDirtyOrg = new Organization();
1003
+ littleDirtyOrg.name = 'N00b';
1004
+ littleDirtyOrg.slug = 'n00b';
1005
+
1006
+ var temp = new mongoose.Types.ObjectId();
1007
+
1008
+ littleDirtyOrg.addPerson({person: temp});
1009
+ littleDirtyOrg.addPerson({person: temp});
1010
+ littleDirtyOrg.addPerson({person: new mongoose.Types.ObjectId()});
1011
+ littleDirtyOrg.addPerson({person: new mongoose.Types.ObjectId()});
1012
+
1013
+ Organization.upsert(littleDirtyOrg, 'test-user', function(err, result) {
1014
+ should.not.exist(err);
1015
+ should.exist(result);
1016
+ result.people.length.should.equal(3);
1017
+ return done();
1018
+ });
1019
+
1020
+ });
1021
+
803
1022
  describe('State', function() {
804
1023
 
805
1024
  it('gets ipo info', function(done) {
package/test/Person.js CHANGED
@@ -854,6 +854,109 @@ describe('Person', function() {
854
854
 
855
855
  });
856
856
 
857
+ it('cleans contact info', function(done) {
858
+
859
+ var p = new Person();
860
+ p.name = { first: 'Testy', last: 'Tester' };
861
+ p.slug = 'testy-tester';
862
+
863
+ p.contact.address = [];
864
+ p.contact.address.push({
865
+ city: 'Testville',
866
+ state: 'Test',
867
+ country: 'TSA',
868
+ type: 'work',
869
+ primary: true
870
+ });
871
+ p.contact.address.push({
872
+ city: 'Testville',
873
+ state: 'Test',
874
+ country: 'TSA',
875
+ type: 'other',
876
+ primary: true
877
+ });
878
+ p.contact.address.push({
879
+ city: 'Bangor',
880
+ state: 'ME',
881
+ country: 'USA',
882
+ type: 'other',
883
+ primary: true
884
+ });
885
+ p.contact.address.push({
886
+ city: '',
887
+ state: '',
888
+ country: '',
889
+ type: 'other',
890
+ primary: true
891
+ });
892
+
893
+ p.contact.email = [];
894
+ p.contact.email.push({
895
+ email: 'test@org.org',
896
+ type: 'work',
897
+ primary: true
898
+ });
899
+ p.contact.email.push({
900
+ email: 'test@org.org',
901
+ type: 'other',
902
+ primary: true
903
+ });
904
+ p.contact.email.push({
905
+ email: 'admin@org.org',
906
+ type: 'other',
907
+ primary: true
908
+ });
909
+ p.contact.email.push({
910
+ email: '',
911
+ type: 'other',
912
+ primary: false
913
+ });
914
+
915
+ p.contact.phone = [];
916
+ p.contact.phone.push({
917
+ number: '2075551212',
918
+ type: 'work',
919
+ primary: true
920
+ });
921
+ p.contact.phone.push({
922
+ number: '2075551212',
923
+ type: 'other',
924
+ primary: true
925
+ });
926
+ p.contact.phone.push({
927
+ number: null,
928
+ type: 'other',
929
+ primary: null
930
+ });
931
+ p.contact.phone.push({
932
+ number: '3455551212',
933
+ type: 'other',
934
+ primary: true
935
+ });
936
+
937
+ Person.upsert(p, 'test-user', function(err, person) {
938
+
939
+ should.not.exist(err);
940
+ should.exist(person);
941
+
942
+ person.contact.address.length.should.equal(2);
943
+ person.contact.email.length.should.equal(2);
944
+ person.contact.phone.length.should.equal(2);
945
+
946
+ var primaryAddresses = _.filter(person.contact.address, function(item) { return item.primary; });
947
+ primaryAddresses.length.should.be.lessThan(2);
948
+
949
+ var primaryEmails = _.filter(person.contact.email, function(item) { return item.primary; });
950
+ primaryEmails.length.should.be.lessThan(2);
951
+
952
+ var primaryPhones = _.filter(person.contact.phone, function(item) { return item.primary; });
953
+ primaryPhones.length.should.be.lessThan(2);
954
+
955
+ done();
956
+
957
+ });
958
+ });
959
+
857
960
  // describe('sources', function() {
858
961
  //
859
962
  // // can only add source if global process