@dhyasama/totem-models 7.58.0 → 8.0.1

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.
@@ -1,18 +1,16 @@
1
- "use strict";
1
+ 'use strict';
2
2
 
3
3
  module.exports = function(mongoose, config) {
4
4
 
5
- var
5
+ let
6
6
 
7
7
  _ = require('underscore'),
8
8
  async = require('async'),
9
9
  utils = require('@dhyasama/ffvc-utilities'),
10
+ helpers = require('../helpers'),
10
11
  Schema = mongoose.Schema,
11
- Deal = mongoose.model('Deal'),
12
12
  Flag = mongoose.model('Flag'),
13
13
  Note = mongoose.model('Note'),
14
- customerFunds = [],
15
- customerPortfolio = [],
16
14
 
17
15
  Organization = new Schema({
18
16
 
@@ -173,7 +171,13 @@ module.exports = function(mongoose, config) {
173
171
 
174
172
  totemUrl: { type: String, trim: true, unique: true, partialFilterExpression : { type :"string" } },
175
173
 
176
- locale: { type: String, default: 'en-us', trim: true },
174
+ auth: {
175
+
176
+ google: { type: Boolean, default: false },
177
+
178
+ microsoft: { type: Boolean, default: false }
179
+
180
+ },
177
181
 
178
182
  beanstalk: {
179
183
  environmentName: { type: String, trim: true },
@@ -251,6 +255,12 @@ module.exports = function(mongoose, config) {
251
255
 
252
256
  },
253
257
 
258
+ lps: {
259
+
260
+ active: {type: Boolean, default: false},
261
+
262
+ },
263
+
254
264
  deals: {
255
265
 
256
266
  active: { type: Boolean, default: false },
@@ -430,163 +440,6 @@ module.exports = function(mongoose, config) {
430
440
 
431
441
 
432
442
 
433
- ///////////////////////////////////////////////////////////////////////////////////////
434
- // HELPERS
435
- ///////////////////////////////////////////////////////////////////////////////////////
436
-
437
- var getSources = function getSources(people) {
438
-
439
- var result = _.compact(_.pluck(people, 'person'));
440
- if (result.length == 0) return [];
441
-
442
- result = _.compact(_.pluck(result, 'sources'));
443
- if (result.length == 0) return [];
444
-
445
- result = _.flatten(result);
446
- result = _.compact(result);
447
-
448
- if (result.length == 0) return [];
449
- if (mongoose.Types.ObjectId.isValid(result[0].person)) return []; // not populated
450
-
451
- result = _.uniq(result, function(item) {
452
- if (!item || !item.person) return '';
453
- else return item.person._id ? item.person._id.toString() : '';
454
- });
455
- result = _.compact(result);
456
- result = _.reject(result, function(item) { return !item.person; });
457
- result = _.sortBy(result, 'interactions.count');
458
- result.reverse();
459
- result = _.sortBy(result, 'name.full');
460
-
461
- return result;
462
-
463
- };
464
-
465
- var prepForSave = function prepForSave(doc) {
466
-
467
- var cleanContactInfo = function cleanContactInfo(obj) {
468
-
469
- var thereCanOnlyBeOne = function thereCanOnlyBeOne(items) {
470
-
471
- var primaryItems = _.filter(items, function(item) { return item.primary; });
472
-
473
- if (primaryItems.length > 1) {
474
-
475
- _.each(primaryItems, function(item, index) {
476
- // skip the first one (leave it primary) and mark the rest as not primary
477
- if (index >= 1) item.primary = false;
478
- });
479
-
480
- }
481
-
482
- return items;
483
-
484
- };
485
-
486
- if (!obj || !obj.contact) return;
487
-
488
- if (obj.contact.address) {
489
-
490
- // must have something meaningful
491
- obj.contact.address = _.map(obj.contact.address, function(address) {
492
- if (!address.city && !address.state && !address.country) return null;
493
- else return address;
494
- });
495
-
496
- // remove emptiness and dedupe
497
- obj.contact.address = _.uniq(_.compact(obj.contact.address), function(item) { return item.city + item.state + item.country; });
498
-
499
- // only one primary
500
- obj.contact.address = thereCanOnlyBeOne(obj.contact.address);
501
-
502
- }
503
-
504
- if (obj.contact.email) {
505
-
506
- // must have something meaningful
507
- obj.contact.email = _.map(doc.contact.email, function(item) {
508
- if (!item.email) return null;
509
- else return item;
510
- });
511
-
512
- // remove emptiness and dedupe
513
- obj.contact.email = _.uniq(_.compact(obj.contact.email), function(item) { return item.email; });
514
-
515
- // only one primary
516
- obj.contact.email = thereCanOnlyBeOne(obj.contact.email);
517
-
518
- }
519
-
520
- if (obj.contact.phone) {
521
-
522
- // must have something meaningful
523
- obj.contact.phone = _.map(doc.contact.phone, function(item) {
524
- if (!item.number) return null;
525
- else return item;
526
- });
527
-
528
- // remove emptiness and dedupe
529
- obj.contact.phone = _.uniq(_.compact(obj.contact.phone), function(item) { return item.number; });
530
-
531
- // only one primary
532
- obj.contact.phone = thereCanOnlyBeOne(obj.contact.phone);
533
-
534
- }
535
-
536
- };
537
-
538
- var cleanPeople = function cleanPeople(obj) {
539
-
540
- if (!obj || !obj.people) return;
541
-
542
- // remove junk
543
- obj.people = _.reject(obj.people, function(p) { return p.person == null; });
544
-
545
- // dedupe
546
- obj.people = _.uniq(obj.people, function(p) { return p.person._id ? p.person._id.toString() : p.person.toString(); });
547
-
548
- };
549
-
550
- var cleanWebsites = function cleanWebsites(obj) {
551
-
552
- if (!obj) return;
553
-
554
- // Format website
555
- if (obj.website) {
556
- obj.website = String(obj.website);
557
- obj.website = obj.website.replace('http://', '').replace('https://', '').replace(/\/+$/, '');
558
- obj.website = utils.getDomain(obj.website);
559
- }
560
-
561
- // Format website aliases
562
- if (obj.websiteAliases && obj.websiteAliases.length >= 1) {
563
- obj.websiteAliases = _.map(obj.websiteAliases, function(alias) {
564
- alias = String(alias);
565
- alias = alias.replace('http://', '').replace('https://', '').replace(/\/+$/, '');
566
- return utils.getDomain(alias);
567
- });
568
- }
569
-
570
- // Add website to website aliases
571
- // There are unique constraints on website and website aliases
572
- // This enables us to enforce uniqueness across both and across documents
573
- if (obj.website && obj.websiteAliases) obj.websiteAliases.push(obj.website);
574
-
575
- if (obj.websiteAliases) {
576
- obj.websiteAliases = _.uniq(obj.websiteAliases);
577
- obj.websiteAliases = _.compact(obj.websiteAliases);
578
- }
579
-
580
- };
581
-
582
- cleanContactInfo(doc);
583
- cleanPeople(doc);
584
- cleanWebsites(doc);
585
-
586
- };
587
-
588
-
589
-
590
443
  ///////////////////////////////////////////////////////////////////////////////////////
591
444
  // VIRTUALS
592
445
  // Properties that are not persisted to the database
@@ -594,12 +447,12 @@ module.exports = function(mongoose, config) {
594
447
 
595
448
  Organization.virtual('acquired.amount').get(function () {
596
449
 
597
- var self = this;
598
- var publicData = self.operating.acquired.public || {};
599
- var privateData = self.operating.acquired.private || [];
450
+ const self = this;
451
+ const publicData = self.operating.acquired.public || {};
452
+ const privateData = self.operating.acquired.private || [];
600
453
 
601
454
  if (publicData.amount) return publicData.amount;
602
- else if (privateData.length == 1) {
455
+ else if (privateData.length >= 1) {
603
456
  if (privateData[0].amount) return privateData[0].amount;
604
457
  else return 0;
605
458
  }
@@ -609,12 +462,12 @@ module.exports = function(mongoose, config) {
609
462
 
610
463
  Organization.virtual('acquired.by').get(function () {
611
464
 
612
- var self = this;
613
- var publicData = self.operating.acquired.public || {};
614
- var privateData = self.operating.acquired.private || [];
465
+ const self = this;
466
+ const publicData = self.operating.acquired.public || {};
467
+ const privateData = self.operating.acquired.private || [];
615
468
 
616
469
  if (publicData.by) return publicData.by;
617
- else if (privateData.length == 1) {
470
+ else if (privateData.length >= 1) {
618
471
  if (privateData[0].by) return privateData[0].by;
619
472
  else return null;
620
473
  }
@@ -624,12 +477,12 @@ module.exports = function(mongoose, config) {
624
477
 
625
478
  Organization.virtual('acquired.on').get(function () {
626
479
 
627
- var self = this;
628
- var publicData = self.operating.acquired.public || {};
629
- var privateData = self.operating.acquired.private || [];
480
+ const self = this;
481
+ const publicData = self.operating.acquired.public || {};
482
+ const privateData = self.operating.acquired.private || [];
630
483
 
631
484
  if (publicData.acquiredOn) return publicData.acquiredOn;
632
- else if (privateData.length == 1) {
485
+ else if (privateData.length >= 1) {
633
486
  if (privateData[0].acquiredOn) return privateData[0].acquiredOn;
634
487
  else return null;
635
488
  }
@@ -1021,7 +874,7 @@ module.exports = function(mongoose, config) {
1021
874
 
1022
875
  Organization.virtual('status').get(function () {
1023
876
 
1024
- var self = this;
877
+ const self = this;
1025
878
 
1026
879
  if (self.ipo.ticker) return 'IPO';
1027
880
  else if (self.acquired.by || self.acquired.on) return 'Acquired';
@@ -1099,7 +952,7 @@ module.exports = function(mongoose, config) {
1099
952
  };
1100
953
 
1101
954
  Organization.methods.merge = function(id) {
1102
- if (this.merged.indexOf(id) == -1) {
955
+ if (this.merged.indexOf(id) === -1) {
1103
956
  this.merged = this.merged.concat([id]);
1104
957
  return true;
1105
958
  }
@@ -1114,7 +967,7 @@ module.exports = function(mongoose, config) {
1114
967
 
1115
968
  var match = _.find(self.related, function(org) {
1116
969
  var orgId = utils.isValidObjectId(org) ? org : org.id;
1117
- return orgId.toString() == id.toString();
970
+ return orgId.toString() === id.toString();
1118
971
  });
1119
972
 
1120
973
  if (!match) { self.related.push(id); }
@@ -1135,158 +988,34 @@ module.exports = function(mongoose, config) {
1135
988
  // Statics query the entire collection
1136
989
  //////////////////////////////////////////////////////
1137
990
 
1138
- Organization.statics.addDeal = function(deal, user, cb) {
1139
-
1140
- var self = this;
1141
-
1142
- var checkForDuplicates = function checkForDuplicates(previous, callback) {
1143
-
1144
- // get org and make sure not already a deal for current customer
1145
-
1146
- self.getById(utils.getIdAsString(previous.deal, 'organization'), {}, function(err, org) {
1147
-
1148
- if (err) return callback(err, null);
1149
- else if (!org) return callback(new Error('Org not found'), null);
1150
- else if (org.deleted) return callback(new Error('Org deleted'), null);
1151
-
1152
- var match = _.find(org.deals, function(d) {
1153
- return utils.getIdAsString(d, 'customer') == deal.customer._id.toString();
1154
- });
1155
-
1156
- if (match) return callback(new Error('This org already has a deal for this customer'), null);
1157
-
1158
- previous.org = org;
1159
-
1160
- return callback(null, previous);
1161
-
1162
- });
1163
-
1164
- };
1165
-
1166
- var validateStage = function validateStage(previous, callback) {
1167
-
1168
- // check allowable deal stages against the new deal
1169
-
1170
- self.findById(deal.customer, function(err, org) {
1171
-
1172
- if (err) return callback(err, null);
1173
- else if (!org) return callback(new Error('Customer not found'), null);
1174
-
1175
- var statuses = org.customer.deals.activeStatuses;
1176
-
1177
- var match = _.find(statuses, function(status) {
1178
- return status == previous.deal.stage;
1179
- });
1180
-
1181
- if (!match) return callback(new Error('This stage is not valid for this customer'), null);
1182
-
1183
- return callback(null, previous);
1184
-
1185
- });
1186
-
1187
- };
1188
-
1189
- var createDeal = function createDeal(previous, callback) {
1190
-
1191
- Deal.upsert(previous.deal, previous.user, function(err, result) {
1192
-
1193
- if (err) return callback(err, null);
1194
-
1195
- previous.deal = result;
1196
-
1197
- return callback(null, previous);
1198
-
1199
- });
1200
-
1201
- };
1202
-
1203
- var addDealToOrg = function addDealToOrg(previous, callback) {
1204
-
1205
- previous.org.deals.push(previous.deal);
1206
-
1207
- self.upsert(previous.org, previous.user.username, function(err, result) {
1208
-
1209
- if (err) return callback(err, null);
1210
-
1211
- previous.org = result;
1212
-
1213
- return callback(null, previous);
1214
-
1215
- });
1216
-
1217
- };
1218
-
1219
- var previous = {
1220
- deal: deal,
1221
- user: user,
1222
- org: null
1223
- };
1224
-
1225
- async.waterfall([
1226
- checkForDuplicates.bind(null, previous),
1227
- validateStage,
1228
- createDeal,
1229
- addDealToOrg
1230
- ], function(err, results) {
1231
-
1232
- if (err) return cb(err, null);
1233
-
1234
- return cb(null, {
1235
- org: results.org,
1236
- deal: results.deal
1237
- });
1238
-
1239
- });
1240
-
1241
- };
1242
-
1243
- Organization.statics.addFlag = function(organizationId, creatorPersonId, text, cb) {
991
+ Organization.statics.addFlag = function(orgId, creatorPersonId, text, customerId, cb) {
1244
992
 
1245
993
  Flag.createForModel({
1246
994
  createdBy: creatorPersonId,
1247
- text: text
1248
- }, this, organizationId, cb);
995
+ text: text,
996
+ customer: customerId
997
+ }, this, orgId, cb);
1249
998
 
1250
999
  };
1251
1000
 
1252
- Organization.statics.addNote = function(organizationId, creatorPersonId, text, isPrivate, cb) {
1001
+ Organization.statics.addNote = function(organizationId, creatorPersonId, text, isPrivate, customerId, cb) {
1253
1002
 
1254
1003
  Note.createForModel({
1255
1004
  createdBy: creatorPersonId,
1256
1005
  text: text,
1257
- isPrivate: isPrivate
1006
+ isPrivate: isPrivate,
1007
+ customer: customerId
1258
1008
  }, this, organizationId, cb);
1259
1009
 
1260
1010
  };
1261
1011
 
1262
- Organization.statics.deleteDeal = function(dealId, cb) {
1263
-
1264
- // Delete the deal itself along with any references
1265
-
1266
- var self = this;
1267
-
1268
- var removeReferences = function removeReferences(callback) {
1269
- self.update({}, {
1270
- $pull: { 'deals' : [dealId] }
1271
- }, callback);
1272
- };
1273
-
1274
- async.series([
1275
- Deal.delete.bind(Deal, dealId),
1276
- removeReferences
1277
- ], function(err, results) {
1278
- return cb(err, null);
1279
- });
1280
-
1281
- };
1282
-
1283
1012
  Organization.statics.deleteFlag = function(flagId, cb) {
1284
1013
 
1285
1014
  // Delete the flag itself along with reference
1286
1015
 
1287
- var self = this;
1016
+ const self = this;
1288
1017
 
1289
- var removeReferences = function removeReferences(callback) {
1018
+ let removeReferences = function removeReferences(callback) {
1290
1019
  self.update({}, {
1291
1020
  $pull: { 'flags' : [flagId] }
1292
1021
  }, callback);
@@ -1305,9 +1034,9 @@ module.exports = function(mongoose, config) {
1305
1034
 
1306
1035
  // Delete the note itself along with any references
1307
1036
 
1308
- var self = this;
1037
+ const self = this;
1309
1038
 
1310
- var removeReferences = function removeReferences(callback) {
1039
+ let removeReferences = function removeReferences(callback) {
1311
1040
  self.update({}, {
1312
1041
  $pull: { 'notes' : [noteId] }
1313
1042
  }, callback);
@@ -1322,21 +1051,15 @@ module.exports = function(mongoose, config) {
1322
1051
 
1323
1052
  };
1324
1053
 
1325
- Organization.statics.removeCustomerFilters = function(customerId, cb) {
1054
+ Organization.statics.findByDomains = function findByDomains(domains, options, cb) {
1326
1055
 
1327
- var self = this;
1056
+ const self = this;
1328
1057
 
1329
- self
1330
- .update(
1331
- { 'filters.customer': customerId },
1332
- { $pull : { 'filters': { 'customer': customerId } } },
1333
- { multi : true }
1334
- )
1335
- .exec(cb);
1336
-
1337
- };
1338
-
1339
- Organization.statics.findByDomains = function findByDomains(domains, cb) {
1058
+ if (!cb) { throw new Error('cb is required'); }
1059
+ if (!domains) { return cb(new Error('domains is required'), null); }
1060
+ if (!options) { return cb(new Error('options is required'), null); }
1061
+ if (!options.CUSTOMER_ID) { return cb(new Error('options.CUSTOMER_ID is required'), null); }
1062
+ if (!mongoose.Types.ObjectId.isValid(options.CUSTOMER_ID)) { return cb(new Error('options.CUSTOMER_ID is not a valid ObjectId'), null); }
1340
1063
 
1341
1064
  // we haven't been able to avoid some domains having a protocol prefix in the database
1342
1065
  // until we can, use protocol as part of searching by domain
@@ -1353,7 +1076,7 @@ module.exports = function(mongoose, config) {
1353
1076
  });
1354
1077
 
1355
1078
  // add http and https alternatives for each domain
1356
- var alternativeDomains = [];
1079
+ let alternativeDomains = [];
1357
1080
  _.each(domains, function(d) {
1358
1081
  alternativeDomains.push('http://' + d);
1359
1082
  alternativeDomains.push('https://' + d);
@@ -1361,32 +1084,67 @@ module.exports = function(mongoose, config) {
1361
1084
 
1362
1085
  domains = domains.concat(alternativeDomains);
1363
1086
 
1364
- var query = this.find({ $or: [ {'website': { $in : domains }}, {'websiteAliases': { $in : domains }} ], 'deleted': {$ne: true} });
1365
- query.exec(cb);
1087
+ let query = self.find({ $or: [ {'website': { $in : domains }}, {'websiteAliases': { $in : domains }} ], 'deleted': {$ne: true} });
1088
+
1089
+ query.exec(function(err, orgs) {
1090
+
1091
+ if (err) { return cb(err, null); }
1092
+ else if (!orgs) { return cb(null, []); }
1093
+
1094
+ orgs = _.map(orgs, function(org) {
1095
+ return helpers.cleanOrg(org, options.CUSTOMER_ID);
1096
+ });
1097
+
1098
+ return cb(null, orgs);
1099
+
1100
+ });
1366
1101
 
1367
1102
  };
1368
1103
 
1369
1104
  Organization.statics.findByFunds = function findByFunds(fundids, cb) {
1370
- var self = this;
1105
+ const self = this;
1371
1106
  self
1372
1107
  .find({ 'funds': { $in : fundids }, 'deleted': {$ne: true} })
1373
1108
  .select('name logoUrl funds contact')
1374
1109
  .exec(cb);
1375
1110
  };
1376
1111
 
1377
- Organization.statics.findByIdsUnpopulated = function findByIdsUnpopulated(ids, cb) {
1112
+ Organization.statics.findByIdsUnpopulated = function findByIdsUnpopulated(ids, options, cb) {
1378
1113
 
1379
- var self = this;
1114
+ const self = this;
1115
+
1116
+ if (!cb) { throw new Error('cb is required'); }
1117
+ if (!ids) { return cb(new Error('ids is required'), null); }
1118
+ if (!options) { return cb(new Error('options is required'), null); }
1119
+ if (!options.CUSTOMER_ID) { return cb(new Error('options.CUSTOMER_ID is required'), null); }
1120
+ if (!mongoose.Types.ObjectId.isValid(options.CUSTOMER_ID)) { return cb(new Error('options.CUSTOMER_ID is not a valid ObjectId'), null); }
1380
1121
 
1381
1122
  self
1382
1123
  .find({ '_id': { $in : ids }})
1383
- .exec(cb);
1124
+ .exec(function(err, orgs) {
1125
+
1126
+ if (err) { return cb(err, null); }
1127
+ else if (!orgs) { return cb(null, []); }
1128
+
1129
+ orgs = _.map(orgs, function(org) {
1130
+ return helpers.cleanOrg(org, options.CUSTOMER_ID);
1131
+ });
1132
+
1133
+ return cb(null, orgs);
1134
+
1135
+ });
1384
1136
 
1385
1137
  };
1386
1138
 
1387
- Organization.statics.findByIds = function findByIds(ids, cb) {
1139
+ Organization.statics.findByIds = function findByIds(ids, options, cb) {
1388
1140
 
1389
- var self = this;
1141
+ const self = this;
1142
+
1143
+ if (!cb) { throw new Error('cb is required'); }
1144
+ if (!ids) { return cb(new Error('ids is required'), null); }
1145
+ if (!options) { return cb(new Error('options is required'), null); }
1146
+ if (!options.CUSTOMER_ID) { return cb(new Error('options.CUSTOMER_ID is required'), null); }
1147
+ if (!mongoose.Types.ObjectId.isValid(options.CUSTOMER_ID)) { return cb(new Error('options.CUSTOMER_ID is not a valid ObjectId'), null); }
1390
1148
 
1391
1149
  self
1392
1150
  .find({ '_id': { $in : ids }})
@@ -1408,18 +1166,28 @@ module.exports = function(mongoose, config) {
1408
1166
  'people.person.calendarEventSummaries.notes.createdBy': { select: 'name avatarUrl title doNotDisplay' }
1409
1167
  }
1410
1168
  })
1411
- .exec(cb);
1169
+ .exec(function(err, orgs) {
1170
+
1171
+ if (err) { return cb(err, null); }
1172
+ else if (!orgs) { return cb(null, []); }
1173
+
1174
+ orgs = _.map(orgs, function(org) {
1175
+ return helpers.cleanOrg(org, options.CUSTOMER_ID);
1176
+ });
1177
+
1178
+ return cb(null, orgs);
1179
+
1180
+ });
1412
1181
 
1413
1182
  };
1414
1183
 
1415
1184
  Organization.statics.findByLimitedPartner = function findByLimitedPartner(lpid, options, cb) {
1416
1185
 
1417
- var self = this;
1186
+ const self = this;
1418
1187
 
1419
- options = options || {};
1420
- options.role = options.role || 'none';
1188
+ options = helpers.getDefaultOptions(options);
1421
1189
 
1422
- if (options.role == 'none') return cb(new Error('Access denied'), null);
1190
+ if (options.role === 'none') { return cb(new Error('Access denied'), null); }
1423
1191
 
1424
1192
  self
1425
1193
  .find({ 'lps': lpid, 'deleted': {$ne: true} })
@@ -1432,7 +1200,11 @@ module.exports = function(mongoose, config) {
1432
1200
 
1433
1201
  // Given a person id, get all organizations with that person
1434
1202
 
1435
- var self = this;
1203
+ const self = this;
1204
+
1205
+ if (!cb) { throw new Error('cb is required'); }
1206
+ if (!personId) { return cb(new Error('ids is required'), null); }
1207
+ if (!mongoose.Types.ObjectId.isValid(personId)) { return cb(new Error('personId is not a valid ObjectId'), null); }
1436
1208
 
1437
1209
  self
1438
1210
  .find({ $or:
@@ -1443,28 +1215,11 @@ module.exports = function(mongoose, config) {
1443
1215
  ],
1444
1216
  'deleted': { $ne: true }
1445
1217
  })
1218
+ .select('-sources -customer')
1446
1219
  .exec(cb);
1447
1220
 
1448
1221
  };
1449
1222
 
1450
- Organization.statics.findByPersonRaw = function findByPersonRaw(personId, cb) {
1451
-
1452
- // Given a person id, get all organizations with that person
1453
- // directly from mongo driver to avoid mongoose middlewares
1454
-
1455
- var self = this;
1456
-
1457
- self.collection.find({ $or:
1458
- [
1459
- { 'people.person': personId },
1460
- { 'chairs.first': personId },
1461
- { 'chairs.second': personId }
1462
- ],
1463
- 'deleted': { $ne: true }
1464
- }).toArray(cb);
1465
-
1466
- };
1467
-
1468
1223
  Organization.statics.findBySlug = function findBySlug(slug, cb) {
1469
1224
  this.findOne({ slug: slug, 'deleted': {$ne: true} }).exec(cb);
1470
1225
  };
@@ -1473,15 +1228,19 @@ module.exports = function(mongoose, config) {
1473
1228
  this.find({ 'slug': { $in : slugs } }).exec(cb);
1474
1229
  };
1475
1230
 
1476
- Organization.statics.findBySocial = function findBySocial(value, cb) {
1231
+ Organization.statics.findBySocial = function findBySocial(value, options, cb) {
1477
1232
 
1478
1233
  // Extract stand-alone username and append it to our standardized domains
1479
1234
 
1480
- var self = this;
1235
+ const self = this;
1481
1236
 
1482
- if (!value) { return cb(new Error('value must be provided'), null); }
1237
+ if (!cb) { throw new Error('cb is required'); }
1238
+ if (!value) { return cb(new Error('value is required'), null); }
1239
+ if (!options) { return cb(new Error('options is required'), null); }
1240
+ if (!options.CUSTOMER_ID) { return cb(new Error('options.CUSTOMER_ID is required'), null); }
1241
+ if (!mongoose.Types.ObjectId.isValid(options.CUSTOMER_ID)) { return cb(new Error('options.CUSTOMER_ID is not a valid ObjectId'), null); }
1483
1242
 
1484
- var username = utils.getUsernameFromUrl(value);
1243
+ let username = utils.getUsernameFromUrl(value);
1485
1244
 
1486
1245
  if (!username) { return cb(null, []); }
1487
1246
 
@@ -1495,57 +1254,40 @@ module.exports = function(mongoose, config) {
1495
1254
  ],
1496
1255
  'deleted': { $ne: true }
1497
1256
  })
1498
- .exec(cb);
1499
-
1500
- };
1501
-
1502
- Organization.statics.findDupes = function findDupes(org, options, cb) {
1257
+ .exec(function(err, orgs) {
1503
1258
 
1504
- if (!cb) throw new Error('cb is required');
1505
- if (!org || (!org.name && !org.website)) return cb(null, []);
1259
+ if (err) { return cb(err, null); }
1506
1260
 
1507
- this.search({
1508
- name: org.name,
1509
- domain: utils.getDomain(org.website)
1510
- }, options, function(err, orgs) {
1261
+ orgs = _.map(orgs, function(org) {
1262
+ return helpers.cleanOrg(org, options.CUSTOMER_ID);
1263
+ });
1511
1264
 
1512
- if (err) return cb(err, null);
1513
- if (!orgs) return cb(null, null);
1265
+ return cb(null, orgs);
1514
1266
 
1515
- // exclude passed in org from results
1516
- orgs = _.reject(orgs, function(o) {
1517
- return o.id == org.id;
1518
1267
  });
1519
1268
 
1520
- return cb(null, orgs);
1521
-
1522
- });
1523
-
1524
1269
  };
1525
1270
 
1526
- Organization.statics.flag = function(orgId, resolved, text, username, cb) {
1527
-
1528
- this.findById(orgId).exec(function(err, org) {
1529
-
1530
- org.flagged.resolved = resolved;
1531
- org.flagged.text = text;
1532
- org.flagged.by = username;
1533
- org.flagged.on = Date.now();
1271
+ Organization.statics.findByTotemUrl = function findBySlug(url, cb) {
1272
+ this.findOne({ 'customer.totemUrl': url }).exec(cb);
1273
+ };
1534
1274
 
1535
- org.save(cb);
1275
+ Organization.statics.getAcquisitions = function getAcquisitions(orgid, options, cb) {
1536
1276
 
1537
- });
1277
+ const self = this;
1538
1278
 
1539
- };
1279
+ if (!cb) { throw new Error('cb is required'); }
1280
+ if (!orgid) { return cb(new Error('orgid is required'), null); }
1281
+ if (!mongoose.Types.ObjectId.isValid(orgid)) { return cb(new Error('orgid is not a valid ObjectId'), null); }
1282
+ if (!options) { return cb(new Error('options is required'), null); }
1283
+ if (!options.CUSTOMER_ID) { return cb(new Error('options.CUSTOMER_ID is required'), null); }
1284
+ if (!mongoose.Types.ObjectId.isValid(options.CUSTOMER_ID)) { return cb(new Error('options.CUSTOMER_ID is not a valid ObjectId'), null); }
1540
1285
 
1541
- Organization.statics.getAcquisitions = function getAcquisitions(orgid, cb) {
1542
- // todo - logic to check public and private
1543
- var self = this;
1544
1286
  self
1545
1287
  .find(
1546
1288
  { $or: [
1547
- {'operating.acquired.private.by': orgid, 'deleted': {$ne: true} },
1548
- {'operating.acquired.public.by': orgid, 'deleted': {$ne: true} },
1289
+ { 'operating.acquired.private.by': orgid, 'operating.acquired.private.customer': options.CUSTOMER_ID, 'deleted': { $ne: true } },
1290
+ { 'operating.acquired.public.by': orgid, 'deleted': { $ne: true } },
1549
1291
  ]}
1550
1292
  )
1551
1293
  .select('name logoUrl')
@@ -1582,18 +1324,24 @@ module.exports = function(mongoose, config) {
1582
1324
 
1583
1325
  Organization.statics.getById = function getById(id, options, cb) {
1584
1326
 
1585
- var self = this;
1327
+ const self = this;
1328
+
1329
+ if (!cb) { throw new Error('cb is required'); }
1330
+ if (!id) { return cb(new Error('id is required'), null); }
1331
+ if (!mongoose.Types.ObjectId.isValid(id)) { return cb(new Error('id is not a valid ObjectId'), null); }
1332
+ if (!options) { return cb(new Error('options is required'), null); }
1333
+ if (!options.CUSTOMER_ID) { return cb(new Error('options.CUSTOMER_ID is required'), null); }
1334
+ if (!mongoose.Types.ObjectId.isValid(options.CUSTOMER_ID)) { return cb(new Error('options.CUSTOMER_ID is not a valid ObjectId'), null); }
1586
1335
 
1587
- options = options || {};
1588
- options.role = options.role || 'none';
1336
+ options = helpers.getDefaultOptions(options);
1589
1337
 
1590
- var lpPopulateOptions = { path: 'lps' };
1591
- if (config.CUSTOMER_ID != 'GLOBAL_PROCESS') lpPopulateOptions.match = { customer: config.CUSTOMER_ID };
1338
+ let lpPopulateOptions = { path: 'lps' };
1339
+ if (!options.isWorkerProcess) { lpPopulateOptions.match = { customer: options.CUSTOMER_ID }; }
1592
1340
 
1593
1341
  var dealPopulateOptions = { path: 'deals' };
1594
- if (config.CUSTOMER_ID != 'GLOBAL_PROCESS') dealPopulateOptions.match = { customer: config.CUSTOMER_ID };
1342
+ if (!options.isWorkerProcess) { dealPopulateOptions.match = { customer: options.CUSTOMER_ID }; }
1595
1343
 
1596
- var query = self.findById(id);
1344
+ let query = self.findById(id);
1597
1345
 
1598
1346
  query.populate('people.person', 'name avatarUrl title contact doNotDisplay');
1599
1347
  query.populate('related', 'name logoUrl');
@@ -1604,7 +1352,7 @@ module.exports = function(mongoose, config) {
1604
1352
  query.populate('operating.acquired.private.by', 'name logoUrl');
1605
1353
  query.populate(dealPopulateOptions);
1606
1354
 
1607
- if (options.role != 'none') {
1355
+ if (options.role !== 'none') {
1608
1356
  query.populate(lpPopulateOptions);
1609
1357
  query.deepPopulate([
1610
1358
  'deals.sources.person',
@@ -1625,84 +1373,27 @@ module.exports = function(mongoose, config) {
1625
1373
  ]);
1626
1374
  }
1627
1375
 
1628
- query.exec(cb);
1376
+ query.exec(function(err, result) {
1629
1377
 
1630
- };
1631
-
1632
- Organization.statics.getByIdAsGlobal = function getByIdAsGlobal(id, options, cb) {
1633
-
1634
- var self = this;
1635
-
1636
- // Save original id so we can put it back when we're done
1637
- var orginalCustomerId = config.CUSTOMER_ID;
1638
-
1639
- // Switch to global
1640
- config.CUSTOMER_ID = "GLOBAL_PROCESS";
1641
- console.log('config.CUSTOMER_ID pre query', config.CUSTOMER_ID);
1642
-
1643
- try {
1644
-
1645
- self.findById(id, function(err, result) {
1646
-
1647
- // Put original id back
1648
- config.CUSTOMER_ID = orginalCustomerId;
1649
- console.log('config.CUSTOMER_ID post query', config.CUSTOMER_ID);
1650
-
1651
- if (err) { return cb(err, null); }
1652
-
1653
- return cb(null, result);
1654
-
1655
- });
1656
-
1657
-
1658
- }
1659
- catch(err) {
1660
-
1661
- // Put original id back
1662
- config.CUSTOMER_ID = orginalCustomerId;
1663
- console.log('config.CUSTOMER_ID post query', config.CUSTOMER_ID);
1664
-
1665
- console.log('ERROR WITH ORGANIZATION.GETBYIDGLOBAL');
1666
- console.log('config.CUSTOMER_ID', config.CUSTOMER_ID);
1667
- console.log(err);
1668
-
1669
- return cb(err, null);
1670
-
1671
- }
1672
-
1673
- };
1674
-
1675
- Organization.statics.getByIdRaw = function getByIdRaw(id, options, cb) {
1676
-
1677
- // directly from mongo driver to avoid mongoose middlewares
1678
-
1679
- var self = this;
1680
-
1681
- //self.collection.findOne({ "_id": id }, cb);
1378
+ if (err) { return cb(err, null); }
1682
1379
 
1683
- self.collection.findOne({ "_id": id }, function(err, result) {
1684
-
1685
- if (err) return cb(err, null);
1686
- else if (!result) return cb(null, null);
1687
-
1688
- // hydrate so we can use the populate method to get people
1689
- // note the hydrated version is not returned
1690
- var hydrated = self.hydrate(result);
1691
- hydrated.populate({
1692
- path: 'people.person',
1693
- select: 'name avatarUrl title contact doNotDisplay'
1694
- }, function (err, populated) {
1695
- result.people = populated.people;
1696
- return cb(null, result);
1697
- });
1380
+ if (options.isWorkerProcess) { return cb(null, result); }
1381
+ else { return cb(null, helpers.cleanOrg(result, options.CUSTOMER_ID)); }
1698
1382
 
1699
1383
  });
1700
1384
 
1701
1385
  };
1702
1386
 
1703
- Organization.statics.getChairsOfPerson = function getChairsOfPerson(personId, cb) {
1387
+ Organization.statics.getChairsOfPerson = function getChairsOfPerson(personId, options, cb) {
1704
1388
 
1705
- var self = this;
1389
+ const self = this;
1390
+
1391
+ if (!cb) { throw new Error('cb is required'); }
1392
+ if (!personId) { return cb(new Error('personId is required'), null); }
1393
+ if (!mongoose.Types.ObjectId.isValid(personId)) { return cb(new Error('personId is not a valid ObjectId'), null); }
1394
+ if (!options) { return cb(new Error('options is required'), null); }
1395
+ if (!options.CUSTOMER_ID) { return cb(new Error('options.CUSTOMER_ID is required'), null); }
1396
+ if (!mongoose.Types.ObjectId.isValid(options.CUSTOMER_ID)) { return cb(new Error('options.CUSTOMER_ID is not a valid ObjectId'), null); }
1706
1397
 
1707
1398
  self
1708
1399
  .find({ $or:
@@ -1712,57 +1403,63 @@ module.exports = function(mongoose, config) {
1712
1403
  ],
1713
1404
  'deleted': { $ne: true }
1714
1405
  })
1715
- .exec(cb);
1406
+ .exec(function(err, orgs) {
1407
+
1408
+ if (err) { return cb(err, null); }
1409
+
1410
+ orgs = _.map(orgs, function(org) {
1411
+ return helpers.cleanOrg(org, options.CUSTOMER_ID);
1412
+ });
1413
+
1414
+ return cb(null, orgs);
1415
+
1416
+ });
1716
1417
 
1717
1418
  };
1718
1419
 
1719
- Organization.statics.getFlags = function getFlags(orgid, cb) {
1420
+ Organization.statics.getFlags = function getFlags(orgid, options, cb) {
1720
1421
 
1721
- var self = this;
1722
- var query = self.findById(orgid)
1422
+ const self = this;
1423
+
1424
+ if (!cb) { throw new Error('cb is required'); }
1425
+ if (!orgid) { return cb(new Error('orgid is required'), null); }
1426
+ if (!mongoose.Types.ObjectId.isValid(orgid)) { return cb(new Error('orgid is not a valid ObjectId'), null); }
1427
+ if (!options) { return cb(new Error('options is required'), null); }
1428
+ if (!options.CUSTOMER_ID) { return cb(new Error('options.CUSTOMER_ID is required'), null); }
1429
+ if (!mongoose.Types.ObjectId.isValid(options.CUSTOMER_ID)) { return cb(new Error('options.CUSTOMER_ID is not a valid ObjectId'), null); }
1723
1430
 
1724
- query.select('flags')
1431
+ let query = self.findById(orgid);
1432
+
1433
+ query.select('flags');
1725
1434
  query.populate({
1726
1435
  path: 'flags',
1727
- match: { customer: config.CUSTOMER_ID }
1728
- })
1436
+ match: { customer: options.CUSTOMER_ID }
1437
+ });
1729
1438
  query.deepPopulate([
1730
1439
  'flags.createdBy'
1731
1440
  ], {
1732
1441
  populate: {
1733
1442
  'flags.createdBy': { select: 'name avatarUrl title' }
1734
1443
  }
1735
- })
1736
- query.sort({'createdOn':-1})
1737
- query.exec(cb);
1444
+ });
1445
+ query.sort({'createdOn':-1});
1738
1446
 
1739
- };
1447
+ query.exec(function(err, org) {
1740
1448
 
1741
- Organization.statics.getInteractions = function getInteractions(orgid, cb) {
1449
+ if (err) { return cb(err, null); }
1450
+ else if (!org) { return cb(null, []); }
1742
1451
 
1743
- var self = this;
1452
+ org = helpers.cleanOrg(org, options.CUSTOMER_ID);
1744
1453
 
1745
- self
1746
- .findById(orgid)
1747
- .populate('people.person', 'name avatarUrl title doNotDisplay calendarEventSummaries')
1748
- .deepPopulate([
1749
- 'people.person.calendarEventSummaries.attendees.internal',
1750
- 'people.person.calendarEventSummaries.attendees.external',
1751
- 'people.person.calendarEventSummaries.notes.createdBy'
1752
- ], {
1753
- populate: {
1754
- 'people.person.calendarEventSummaries.attendees.internal': { select: 'name avatarUrl title doNotDisplay' },
1755
- 'people.person.calendarEventSummaries.attendees.external': { select: 'name avatarUrl title doNotDisplay' },
1756
- 'people.person.calendarEventSummaries.notes.createdBy': { select: 'name avatarUrl title doNotDisplay' }
1757
- }
1758
- })
1759
- .exec(cb);
1454
+ return cb(null, org);
1455
+
1456
+ });
1760
1457
 
1761
1458
  };
1762
1459
 
1763
1460
  Organization.statics.getList = function getList(cb) {
1764
1461
 
1765
- var self = this;
1462
+ const self = this;
1766
1463
 
1767
1464
  self
1768
1465
  .find({'deleted': {$ne: true}})
@@ -1772,26 +1469,55 @@ module.exports = function(mongoose, config) {
1772
1469
 
1773
1470
  };
1774
1471
 
1775
- Organization.statics.getLpOrgs = function getLpOrgs(lpids, cb) {
1776
- var self = this;
1777
- self
1778
- .find({ 'lps': { $in : lpids }, 'deleted': {$ne: true} })
1779
- .select('name logoUrl lps')
1780
- .populate('lps', 'name customer')
1781
- .exec(cb);
1472
+ Organization.statics.getLpOrgs = function getLpOrgs(lpids, options, cb) {
1473
+
1474
+ const self = this;
1475
+
1476
+ if (!cb) { throw new Error('cb is required'); }
1477
+ if (!lpids) { return cb(new Error('lpids is required'), null); }
1478
+ if (!options) { return cb(new Error('options is required'), null); }
1479
+ if (!options.CUSTOMER_ID) { return cb(new Error('options.CUSTOMER_ID is required'), null); }
1480
+ if (!mongoose.Types.ObjectId.isValid(options.CUSTOMER_ID)) { return cb(new Error('options.CUSTOMER_ID is not a valid ObjectId'), null); }
1481
+
1482
+ let query = self.find({ 'lps': { $in : lpids }, 'deleted': {$ne: true} });
1483
+
1484
+ query.select('name logoUrl lps');
1485
+ query.populate('lps', 'name customer');
1486
+
1487
+ query.exec(function(err, orgs) {
1488
+
1489
+ if (err) { return cb(err, null); }
1490
+ else if (!orgs) { return cb(null, []); }
1491
+
1492
+ orgs = _.map(orgs, function(org) {
1493
+ return helpers.cleanOrg(org, options.CUSTOMER_ID);
1494
+ });
1495
+
1496
+ return cb(null, orgs);
1497
+
1498
+ });
1499
+
1782
1500
  };
1783
1501
 
1784
- Organization.statics.getNotes = function getNotes(orgid, cb) {
1502
+ Organization.statics.getNotes = function getNotes(orgid, options, cb) {
1785
1503
 
1786
- var self = this;
1787
- var query = self.findById(orgid)
1504
+ const self = this;
1788
1505
 
1789
- query.select('notes people.person')
1790
- query.populate('people.person', 'name avatarUrl title calendarEventSummaries')
1506
+ if (!cb) { throw new Error('cb is required'); }
1507
+ if (!orgid) { return cb(new Error('orgid is required'), null); }
1508
+ if (!mongoose.Types.ObjectId.isValid(orgid)) { return cb(new Error('orgid is not a valid ObjectId'), null); }
1509
+ if (!options) { return cb(new Error('options is required'), null); }
1510
+ if (!options.CUSTOMER_ID) { return cb(new Error('options.CUSTOMER_ID is required'), null); }
1511
+ if (!mongoose.Types.ObjectId.isValid(options.CUSTOMER_ID)) { return cb(new Error('options.CUSTOMER_ID is not a valid ObjectId'), null); }
1512
+
1513
+ let query = self.findById(orgid);
1514
+
1515
+ query.select('notes people.person');
1516
+ query.populate('people.person', 'name avatarUrl title calendarEventSummaries');
1791
1517
  query.populate({
1792
1518
  path: 'notes',
1793
- match: { customer: config.CUSTOMER_ID }
1794
- })
1519
+ match: { customer: options.CUSTOMER_ID }
1520
+ });
1795
1521
  query.deepPopulate([
1796
1522
  'notes.createdBy',
1797
1523
  'people.person.calendarEventSummaries.notes.createdBy'
@@ -1800,47 +1526,69 @@ module.exports = function(mongoose, config) {
1800
1526
  'notes.createdBy': { select: 'name avatarUrl title' },
1801
1527
  'people.person.calendarEventSummaries.notes.createdBy': { select: 'name avatarUrl title' }
1802
1528
  }
1803
- })
1804
- query.sort({'createdOn':-1})
1805
- query.exec(cb);
1529
+ });
1530
+ query.sort({'createdOn':-1});
1531
+
1532
+ query.exec(function(err, org) {
1533
+
1534
+ if (err) { return cb(err, null); }
1535
+ else if (!org) { return cb(null, []); }
1536
+
1537
+ org = helpers.cleanOrg(org, options.CUSTOMER_ID);
1538
+
1539
+ return cb(null, org);
1540
+
1541
+ });
1806
1542
 
1807
1543
  };
1808
1544
 
1809
- Organization.statics.getSources = function(id, cb) {
1545
+ Organization.statics.getSources = function(id, options, cb) {
1810
1546
 
1811
- var self = this;
1547
+ const self = this;
1812
1548
 
1813
- self
1814
- .findById(id)
1815
- .select('people')
1816
- .populate('people.person', 'name avatarUrl title doNotDisplay sources')
1817
- .deepPopulate([
1818
- 'people.person.sources.person'
1819
- ], {
1820
- populate: {
1821
- 'people.person.sources.person': { select: 'name avatarUrl title doNotDisplay' }
1822
- }
1823
- })
1824
- .exec(function(err, org) {
1549
+ if (!cb) { throw new Error('cb is required'); }
1550
+ if (!id) { return cb(new Error('id is required'), null); }
1551
+ if (!mongoose.Types.ObjectId.isValid(id)) { return cb(new Error('id is not a valid ObjectId'), null); }
1552
+ if (!options) { return cb(new Error('options is required'), null); }
1553
+ if (!options.CUSTOMER_ID) { return cb(new Error('options.CUSTOMER_ID is required'), null); }
1554
+ if (!mongoose.Types.ObjectId.isValid(options.CUSTOMER_ID)) { return cb(new Error('options.CUSTOMER_ID is not a valid ObjectId'), null); }
1555
+
1556
+ let query = self.findById(id);
1557
+ query.select('people');
1558
+ query.populate('people.person', 'name avatarUrl title doNotDisplay sources');
1559
+ query.deepPopulate([
1560
+ 'people.person.sources.person'
1561
+ ], {
1562
+ populate: {
1563
+ 'people.person.sources.person': { select: 'name avatarUrl title doNotDisplay' }
1564
+ }
1565
+ });
1825
1566
 
1826
- if (err) return cb(err, null);
1827
- if (!org) return cb(null, null);
1567
+ // get the org requested
1568
+ query.exec(function(err, org) {
1569
+
1570
+ if (err) { return cb(err, null); }
1571
+ if (!org) { return cb(null, null); }
1828
1572
 
1829
- self.findById(config.CUSTOMER_ID, function(err, customer) {
1573
+ // get the customer requesting org
1574
+ self.findById(options.CUSTOMER_ID, function(err, customer) {
1830
1575
 
1831
- if (err) return cb(err, null);
1832
- if (!customer) return cb(null, null);
1576
+ if (err) { return cb(err, null); }
1577
+ if (!customer) { return cb(null, null); }
1833
1578
 
1834
- var current = [];
1835
- var past = [];
1836
- var all = [];
1837
- var orgSources = getSources(org.people);
1579
+ let current = [];
1580
+ let past = [];
1581
+ let all = [];
1838
1582
 
1583
+ // combined list of sources from each person at org
1584
+ let orgSources = helpers.getPeopleSources(_.pluck(org.people, 'person'));
1585
+
1586
+ // loop through customer's people and categorize sources
1839
1587
  _.each(customer.people, function(p) {
1840
1588
 
1841
1589
  var source = _.find(orgSources, function(os) {
1842
1590
  if (!os || !os.person || !os.person._id) return false;
1843
- return os.person._id.toString() == p.person.toString();
1591
+ return os.person._id.toString() === p.person.toString();
1844
1592
  });
1845
1593
 
1846
1594
  if (!source) return;
@@ -1851,10 +1599,11 @@ module.exports = function(mongoose, config) {
1851
1599
 
1852
1600
  });
1853
1601
 
1602
+ // return categorized sources
1854
1603
  return cb(null, {
1855
- all: all,
1856
- current: current,
1857
- past: past
1604
+ all: helpers.sortPeopleSources(all, options.CUSTOMER_ID),
1605
+ current: helpers.sortPeopleSources(current, options.CUSTOMER_ID),
1606
+ past: helpers.sortPeopleSources(past, options.CUSTOMER_ID)
1858
1607
  });
1859
1608
 
1860
1609
  });
@@ -1863,53 +1612,57 @@ module.exports = function(mongoose, config) {
1863
1612
 
1864
1613
  };
1865
1614
 
1866
- Organization.statics.listAllFlagged = function (cb) {
1615
+ Organization.statics.modify = function(filter, update, cb) {
1867
1616
 
1868
- var query = this.find({'flagged.resolved': false, 'flagged.text': { $ne: '' }, 'deleted': {$ne: true}});
1869
- query.exec(function (err, orgs) {
1617
+ // VERY IMPORTANT NOTE
1618
+ // findByIdAndUpdate and findOneAndUpdate do not trigger pre-save hook so that code will not run here
1619
+ // at this time, the only known and approved use of this method is for adding and removing roles in totem web
1870
1620
 
1871
- if (err) return cb(err, null);
1621
+ if (!cb) throw new Error('cb is required');
1622
+ if (!filter) { return cb(new Error('filter is required'), null); }
1623
+ if (!update) { return cb(new Error('update is required'), null); }
1872
1624
 
1873
- orgs = _.sortBy(orgs, function(org){
1874
- var timestamp = new Date(org.flagged.on);
1875
- timestamp = timestamp.getTime();
1876
- return timestamp;
1877
- });
1878
- orgs = orgs.reverse();
1625
+ var self = this;
1879
1626
 
1880
- return cb(null, orgs);
1627
+ // https://mongoosejs.com/docs/api.html#model_Model.findOneAndUpdate
1628
+ // options runValidators defaults false which is ok since we have upsert false
1629
+ // new returns the updated document
1881
1630
 
1882
- });
1631
+ self.findOneAndUpdate(filter, update, { upsert: false, new: true }, cb);
1883
1632
 
1884
1633
  };
1885
1634
 
1886
- Organization.statics.listCustomers = function listCustomers(cb) {
1635
+ Organization.statics.modifyById = function(id, update, cb) {
1887
1636
 
1888
- var self = this;
1637
+ // VERY IMPORTANT NOTE
1638
+ // findByIdAndUpdate and findOneAndUpdate do not trigger pre-save hook so that code will not run here
1639
+ // at this time, the only known and approved use of this method is for the org edit form in totem web
1889
1640
 
1890
- self
1891
- .find({$where:'this.customer && this.customer.totemUrl && this.customer.totemUrl.length >=1'})
1892
- .exec(cb);
1641
+ if (!cb) throw new Error('cb is required');
1642
+ if (!id) { return cb(new Error('id is required'), null); }
1643
+ if (!update) { return cb(new Error('update is required'), null); }
1893
1644
 
1894
- };
1645
+ var self = this;
1895
1646
 
1896
- Organization.statics.listPage = function (skip, cb) {
1647
+ // https://mongoosejs.com/docs/api.html#model_Model.findOneAndUpdate
1648
+ // options runValidators defaults false which is ok since we have upsert false
1649
+ // new returns the updated document
1897
1650
 
1898
- this
1899
- .find({'deleted': {$ne: true}})
1900
- .sort('name')
1901
- .skip(skip)
1902
- .limit(100)
1903
- .exec(cb)
1651
+ self.findByIdAndUpdate(id, update, { upsert: false, new: true }, cb);
1904
1652
 
1905
1653
  };
1906
1654
 
1907
- Organization.statics.removeById = function(id, cb) {
1655
+ Organization.statics.removeCustomerFilters = function(customerId, cb) {
1908
1656
 
1909
- if (!id) { return cb(new Error('id is required'), null); }
1910
- if (!cb) { throw new Error('cb is required'); }
1657
+ var self = this;
1911
1658
 
1912
- this.remove({_id: id}, cb);
1659
+ self
1660
+ .update(
1661
+ { 'filters.customer': customerId },
1662
+ { $pull : { 'filters': { 'customer': customerId } } },
1663
+ { multi : true }
1664
+ )
1665
+ .exec(cb);
1913
1666
 
1914
1667
  };
1915
1668
 
@@ -2070,22 +1823,6 @@ module.exports = function(mongoose, config) {
2070
1823
 
2071
1824
  };
2072
1825
 
2073
- Organization.statics.setCustomerFunds = function setCustomerFunds(fundids) {
2074
- var self = this;
2075
- self.customerFunds = fundids;
2076
- return self.customerFunds;
2077
- };
2078
-
2079
- Organization.statics.setCustomerPortfolio = function setCustomerPortfolio(portfolio) {
2080
- var self = this;
2081
- self.customerPortfolio = portfolio;
2082
- return self.customerPortfolio;
2083
- };
2084
-
2085
- Organization.statics.stats = function stats(cb) {
2086
- this.collection.stats(cb);
2087
- };
2088
-
2089
1826
  Organization.statics.upsert = function(org, username, cb) {
2090
1827
 
2091
1828
  if (!org) { return cb(new Error('Organization is required'), null); }
@@ -2101,56 +1838,138 @@ module.exports = function(mongoose, config) {
2101
1838
 
2102
1839
  };
2103
1840
 
2104
- Organization.statics.modify = function(filter, update, cb) {
2105
1841
 
2106
- // VERY IMPORTANT NOTE
2107
- // findByIdAndUpdate and findOneAndUpdate do not trigger pre-save hook so that code will not run here
2108
- // at this time, the only known and approved use of this method is for adding and removing roles in totem web
2109
1842
 
2110
- if (!cb) throw new Error('cb is required');
2111
- if (!filter) { return cb(new Error('filter is required'), null); }
2112
- if (!update) { return cb(new Error('update is required'), null); }
1843
+ ///////////////////////////////////////////////////////////////////////////////////////
1844
+ // HOOKS
1845
+ // Pre-save: fired on every document before it is saved
1846
+ // Post-init: fired on every document when it's returned from a query
1847
+ ///////////////////////////////////////////////////////////////////////////////////////
2113
1848
 
2114
- var self = this;
1849
+ Organization.pre('save', function(next) {
2115
1850
 
2116
- // https://mongoosejs.com/docs/api.html#model_Model.findOneAndUpdate
2117
- // options runValidators defaults false which is ok since we have upsert false
2118
- // new returns the updated document
1851
+ let prepForSave = function prepForSave(doc) {
2119
1852
 
2120
- self.findOneAndUpdate(filter, update, { upsert: false, new: true }, cb);
1853
+ var cleanContactInfo = function cleanContactInfo(obj) {
2121
1854
 
2122
- };
1855
+ var thereCanOnlyBeOne = function thereCanOnlyBeOne(items) {
2123
1856
 
2124
- Organization.statics.modifyById = function(id, update, cb) {
1857
+ var primaryItems = _.filter(items, function(item) { return item.primary; });
2125
1858
 
2126
- // VERY IMPORTANT NOTE
2127
- // findByIdAndUpdate and findOneAndUpdate do not trigger pre-save hook so that code will not run here
2128
- // at this time, the only known and approved use of this method is for the org edit form in totem web
1859
+ if (primaryItems.length > 1) {
2129
1860
 
2130
- if (!cb) throw new Error('cb is required');
2131
- if (!id) { return cb(new Error('id is required'), null); }
2132
- if (!update) { return cb(new Error('update is required'), null); }
1861
+ _.each(primaryItems, function(item, index) {
1862
+ // skip the first one (leave it primary) and mark the rest as not primary
1863
+ if (index >= 1) item.primary = false;
1864
+ });
2133
1865
 
2134
- var self = this;
1866
+ }
2135
1867
 
2136
- // https://mongoosejs.com/docs/api.html#model_Model.findOneAndUpdate
2137
- // options runValidators defaults false which is ok since we have upsert false
2138
- // new returns the updated document
1868
+ return items;
2139
1869
 
2140
- self.findByIdAndUpdate(id, update, { upsert: false, new: true }, cb);
1870
+ };
2141
1871
 
2142
- };
1872
+ if (!obj || !obj.contact) return;
2143
1873
 
1874
+ if (obj.contact.address) {
2144
1875
 
1876
+ // must have something meaningful
1877
+ obj.contact.address = _.map(obj.contact.address, function(address) {
1878
+ if (!address.city && !address.state && !address.country) return null;
1879
+ else return address;
1880
+ });
2145
1881
 
2146
- ///////////////////////////////////////////////////////////////////////////////////////
2147
- // HOOKS
2148
- // Pre-save: fired on every document before it is saved
2149
- // Post-init: fired on every document when it's returned from a query
2150
- ///////////////////////////////////////////////////////////////////////////////////////
1882
+ // remove emptiness and dedupe
1883
+ obj.contact.address = _.uniq(_.compact(obj.contact.address), function(item) { return item.city + item.state + item.country; });
2151
1884
 
1885
+ // only one primary
1886
+ obj.contact.address = thereCanOnlyBeOne(obj.contact.address);
2152
1887
 
2153
- Organization.pre('save', function(next) {
1888
+ }
1889
+
1890
+ if (obj.contact.email) {
1891
+
1892
+ // must have something meaningful
1893
+ obj.contact.email = _.map(doc.contact.email, function(item) {
1894
+ if (!item.email) return null;
1895
+ else return item;
1896
+ });
1897
+
1898
+ // remove emptiness and dedupe
1899
+ obj.contact.email = _.uniq(_.compact(obj.contact.email), function(item) { return item.email; });
1900
+
1901
+ // only one primary
1902
+ obj.contact.email = thereCanOnlyBeOne(obj.contact.email);
1903
+
1904
+ }
1905
+
1906
+ if (obj.contact.phone) {
1907
+
1908
+ // must have something meaningful
1909
+ obj.contact.phone = _.map(doc.contact.phone, function(item) {
1910
+ if (!item.number) return null;
1911
+ else return item;
1912
+ });
1913
+
1914
+ // remove emptiness and dedupe
1915
+ obj.contact.phone = _.uniq(_.compact(obj.contact.phone), function(item) { return item.number; });
1916
+
1917
+ // only one primary
1918
+ obj.contact.phone = thereCanOnlyBeOne(obj.contact.phone);
1919
+
1920
+ }
1921
+
1922
+ };
1923
+
1924
+ var cleanPeople = function cleanPeople(obj) {
1925
+
1926
+ if (!obj || !obj.people) return;
1927
+
1928
+ // remove junk
1929
+ obj.people = _.reject(obj.people, function(p) { return p.person == null; });
1930
+
1931
+ // dedupe
1932
+ obj.people = _.uniq(obj.people, function(p) { return p.person._id ? p.person._id.toString() : p.person.toString(); });
1933
+
1934
+ };
1935
+
1936
+ var cleanWebsites = function cleanWebsites(obj) {
1937
+
1938
+ if (!obj) return;
1939
+
1940
+ // Format website
1941
+ if (obj.website) {
1942
+ obj.website = String(obj.website);
1943
+ obj.website = obj.website.replace('http://', '').replace('https://', '').replace(/\/+$/, '');
1944
+ obj.website = utils.getDomain(obj.website);
1945
+ }
1946
+
1947
+ // Format website aliases
1948
+ if (obj.websiteAliases && obj.websiteAliases.length >= 1) {
1949
+ obj.websiteAliases = _.map(obj.websiteAliases, function(alias) {
1950
+ alias = String(alias);
1951
+ alias = alias.replace('http://', '').replace('https://', '').replace(/\/+$/, '');
1952
+ return utils.getDomain(alias);
1953
+ });
1954
+ }
1955
+
1956
+ // Add website to website aliases
1957
+ // There are unique constraints on website and website aliases
1958
+ // This enables us to enforce uniqueness across both and across documents
1959
+ if (obj.website && obj.websiteAliases) obj.websiteAliases.push(obj.website);
1960
+
1961
+ if (obj.websiteAliases) {
1962
+ obj.websiteAliases = _.uniq(obj.websiteAliases);
1963
+ obj.websiteAliases = _.compact(obj.websiteAliases);
1964
+ }
1965
+
1966
+ };
1967
+
1968
+ cleanContactInfo(doc);
1969
+ cleanPeople(doc);
1970
+ cleanWebsites(doc);
1971
+
1972
+ };
2154
1973
 
2155
1974
  prepForSave(this);
2156
1975
 
@@ -2163,27 +1982,40 @@ module.exports = function(mongoose, config) {
2163
1982
  // Protect private data
2164
1983
  // Merge public and private data
2165
1984
 
2166
- var CUSTOMER_ID = config.CUSTOMER_ID;
2167
-
2168
- if (CUSTOMER_ID == 'GLOBAL_PROCESS' && next) return next();
1985
+ // const CUSTOMER_ID = this[CUSTOMER_ID];
1986
+ // let err;
1987
+ //
1988
+ // if (!CUSTOMER_ID) {
1989
+ // err = new Error('Missing CUSTOMER_ID');
1990
+ // if (next) { return next(err); }
1991
+ // else { throw err; }
1992
+ // }
1993
+ //
1994
+ // else if (CUSTOMER_ID === 'GLOBAL_PROCESS' && next) { return next(); }
1995
+ //
1996
+ // else if (!mongoose.Types.ObjectId.isValid(CUSTOMER_ID)) {
1997
+ // err = new Error('CUSTOMER_ID is not a valid ObjectId');
1998
+ // if (next) { return next(err); }
1999
+ // else { throw err; }
2000
+ // }
2169
2001
 
2170
2002
  // remove customer details if not viewing self
2171
- if (doc._id.toString() != CUSTOMER_ID) doc.customer = {};
2003
+ //if (doc._id.toString() !== CUSTOMER_ID) { doc.customer = {}; }
2172
2004
 
2173
2005
  // Website is stored in aliases to facilitate enforcing uniqueness
2174
2006
  // Remove it here to make it easier for consumers to provide a good ux
2175
2007
  // It will get added back in during pre save hook
2176
2008
  if (doc.website && doc.websiteAliases && doc.websiteAliases.length >= 1) {
2177
- doc.websiteAliases = _.reject(doc.websiteAliases, function(alias) { return alias == doc.website; });
2009
+ doc.websiteAliases = _.reject(doc.websiteAliases, function(alias) { return alias === doc.website; });
2178
2010
  }
2179
2011
 
2180
- doc.lps = _.reject(doc.lps, function(item) { return !item.customer || item.customer.toString() != CUSTOMER_ID; });
2181
- doc.filters = _.reject(doc.filters, function(item) { return !item.customer || item.customer.toString() != CUSTOMER_ID; });
2182
- doc.valuations = _.reject(doc.valuations, function(item) { return !item.customer || item.customer.toString() != CUSTOMER_ID; });
2183
- doc.iLevel = _.reject(doc.iLevel, function(item) { return !item.customer || item.customer.toString() != CUSTOMER_ID; });
2184
- doc.chairs = _.reject(doc.chairs, function(item) { return !item.customer || item.customer.toString() != CUSTOMER_ID; });
2185
- doc.operating.acquired.private = _.find(doc.operating.acquired.private, function(item) { return !item.customer || item.customer.toString() == CUSTOMER_ID; });
2186
- doc.operating.closed.private = _.find(doc.operating.closed.private, function(item) { return !item.customer || item.customer.toString() == CUSTOMER_ID; });
2012
+ // doc.lps = _.reject(doc.lps, function(item) { return !item.customer || item.customer.toString() !== CUSTOMER_ID; });
2013
+ // doc.filters = _.reject(doc.filters, function(item) { return !item.customer || item.customer.toString() !== CUSTOMER_ID; });
2014
+ // doc.valuations = _.reject(doc.valuations, function(item) { return !item.customer || item.customer.toString() !== CUSTOMER_ID; });
2015
+ // doc.iLevel = _.reject(doc.iLevel, function(item) { return !item.customer || item.customer.toString() !== CUSTOMER_ID; });
2016
+ // doc.chairs = _.reject(doc.chairs, function(item) { return !item.customer || item.customer.toString() !== CUSTOMER_ID; });
2017
+ // doc.operating.acquired.private = _.find(doc.operating.acquired.private, function(item) { return !item.customer || item.customer.toString() === CUSTOMER_ID; });
2018
+ // doc.operating.closed.private = _.find(doc.operating.closed.private, function(item) { return !item.customer || item.customer.toString() === CUSTOMER_ID; });
2187
2019
 
2188
2020
  // people
2189
2021
  _.each(doc.people, function(person) {
@@ -2191,10 +2023,6 @@ module.exports = function(mongoose, config) {
2191
2023
  // always include if explicitly public
2192
2024
  if (person.public) return;
2193
2025
 
2194
- // if not public, keep it in if org is in the current customer's portfolio. otherwise remove it.
2195
- // todo
2196
- //console.log(customerPortfolio);
2197
-
2198
2026
  });
2199
2027
 
2200
2028
  if (next) return next();
@@ -2207,9 +2035,7 @@ module.exports = function(mongoose, config) {
2207
2035
  ///////////////////////////////////////////////////////////////////////////////////////
2208
2036
 
2209
2037
  Organization.set('toJSON', { virtuals: true });
2210
- Organization.set('usePushEach', true);
2211
2038
  Organization.set('autoIndex', false);
2212
- Organization.set('usePushEach', true);
2213
2039
 
2214
2040
  Organization.index({ website: 1, websiteAliases: 1 }, { unique: true, partialFilterExpression : { type :"string" } });
2215
2041
  Organization.on('index', function(err) { console.log('error building organization_new indexes: ' + err); });