@dhyasama/totem-models 7.57.0 → 8.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.
@@ -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,26 @@ 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
+ return cb(null, helpers.cleanOrg(result, options.CUSTOMER_ID));
1698
1381
 
1699
1382
  });
1700
1383
 
1701
1384
  };
1702
1385
 
1703
- Organization.statics.getChairsOfPerson = function getChairsOfPerson(personId, cb) {
1386
+ Organization.statics.getChairsOfPerson = function getChairsOfPerson(personId, options, cb) {
1704
1387
 
1705
- var self = this;
1388
+ const self = this;
1389
+
1390
+ if (!cb) { throw new Error('cb is required'); }
1391
+ if (!personId) { return cb(new Error('personId is required'), null); }
1392
+ if (!mongoose.Types.ObjectId.isValid(personId)) { return cb(new Error('personId is not a valid ObjectId'), null); }
1393
+ if (!options) { return cb(new Error('options is required'), null); }
1394
+ if (!options.CUSTOMER_ID) { return cb(new Error('options.CUSTOMER_ID is required'), null); }
1395
+ if (!mongoose.Types.ObjectId.isValid(options.CUSTOMER_ID)) { return cb(new Error('options.CUSTOMER_ID is not a valid ObjectId'), null); }
1706
1396
 
1707
1397
  self
1708
1398
  .find({ $or:
@@ -1712,57 +1402,63 @@ module.exports = function(mongoose, config) {
1712
1402
  ],
1713
1403
  'deleted': { $ne: true }
1714
1404
  })
1715
- .exec(cb);
1405
+ .exec(function(err, orgs) {
1406
+
1407
+ if (err) { return cb(err, null); }
1408
+
1409
+ orgs = _.map(orgs, function(org) {
1410
+ return helpers.cleanOrg(org, options.CUSTOMER_ID);
1411
+ });
1412
+
1413
+ return cb(null, orgs);
1414
+
1415
+ });
1716
1416
 
1717
1417
  };
1718
1418
 
1719
- Organization.statics.getFlags = function getFlags(orgid, cb) {
1419
+ Organization.statics.getFlags = function getFlags(orgid, options, cb) {
1720
1420
 
1721
- var self = this;
1722
- var query = self.findById(orgid)
1421
+ const self = this;
1422
+
1423
+ if (!cb) { throw new Error('cb is required'); }
1424
+ if (!orgid) { return cb(new Error('orgid is required'), null); }
1425
+ if (!mongoose.Types.ObjectId.isValid(orgid)) { return cb(new Error('orgid is not a valid ObjectId'), null); }
1426
+ if (!options) { return cb(new Error('options is required'), null); }
1427
+ if (!options.CUSTOMER_ID) { return cb(new Error('options.CUSTOMER_ID is required'), null); }
1428
+ if (!mongoose.Types.ObjectId.isValid(options.CUSTOMER_ID)) { return cb(new Error('options.CUSTOMER_ID is not a valid ObjectId'), null); }
1723
1429
 
1724
- query.select('flags')
1430
+ let query = self.findById(orgid);
1431
+
1432
+ query.select('flags');
1725
1433
  query.populate({
1726
1434
  path: 'flags',
1727
- match: { customer: config.CUSTOMER_ID }
1728
- })
1435
+ match: { customer: options.CUSTOMER_ID }
1436
+ });
1729
1437
  query.deepPopulate([
1730
1438
  'flags.createdBy'
1731
1439
  ], {
1732
1440
  populate: {
1733
1441
  'flags.createdBy': { select: 'name avatarUrl title' }
1734
1442
  }
1735
- })
1736
- query.sort({'createdOn':-1})
1737
- query.exec(cb);
1443
+ });
1444
+ query.sort({'createdOn':-1});
1738
1445
 
1739
- };
1446
+ query.exec(function(err, org) {
1740
1447
 
1741
- Organization.statics.getInteractions = function getInteractions(orgid, cb) {
1448
+ if (err) { return cb(err, null); }
1449
+ else if (!org) { return cb(null, []); }
1742
1450
 
1743
- var self = this;
1451
+ org = helpers.cleanOrg(org, options.CUSTOMER_ID);
1744
1452
 
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);
1453
+ return cb(null, org);
1454
+
1455
+ });
1760
1456
 
1761
1457
  };
1762
1458
 
1763
1459
  Organization.statics.getList = function getList(cb) {
1764
1460
 
1765
- var self = this;
1461
+ const self = this;
1766
1462
 
1767
1463
  self
1768
1464
  .find({'deleted': {$ne: true}})
@@ -1772,26 +1468,55 @@ module.exports = function(mongoose, config) {
1772
1468
 
1773
1469
  };
1774
1470
 
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);
1471
+ Organization.statics.getLpOrgs = function getLpOrgs(lpids, options, cb) {
1472
+
1473
+ const self = this;
1474
+
1475
+ if (!cb) { throw new Error('cb is required'); }
1476
+ if (!lpids) { return cb(new Error('lpids is required'), null); }
1477
+ if (!options) { return cb(new Error('options is required'), null); }
1478
+ if (!options.CUSTOMER_ID) { return cb(new Error('options.CUSTOMER_ID is required'), null); }
1479
+ if (!mongoose.Types.ObjectId.isValid(options.CUSTOMER_ID)) { return cb(new Error('options.CUSTOMER_ID is not a valid ObjectId'), null); }
1480
+
1481
+ let query = self.find({ 'lps': { $in : lpids }, 'deleted': {$ne: true} });
1482
+
1483
+ query.select('name logoUrl lps');
1484
+ query.populate('lps', 'name customer');
1485
+
1486
+ query.exec(function(err, orgs) {
1487
+
1488
+ if (err) { return cb(err, null); }
1489
+ else if (!orgs) { return cb(null, []); }
1490
+
1491
+ orgs = _.map(orgs, function(org) {
1492
+ return helpers.cleanOrg(org, options.CUSTOMER_ID);
1493
+ });
1494
+
1495
+ return cb(null, orgs);
1496
+
1497
+ });
1498
+
1782
1499
  };
1783
1500
 
1784
- Organization.statics.getNotes = function getNotes(orgid, cb) {
1501
+ Organization.statics.getNotes = function getNotes(orgid, options, cb) {
1785
1502
 
1786
- var self = this;
1787
- var query = self.findById(orgid)
1503
+ const self = this;
1788
1504
 
1789
- query.select('notes people.person')
1790
- query.populate('people.person', 'name avatarUrl title calendarEventSummaries')
1505
+ if (!cb) { throw new Error('cb is required'); }
1506
+ if (!orgid) { return cb(new Error('orgid is required'), null); }
1507
+ if (!mongoose.Types.ObjectId.isValid(orgid)) { return cb(new Error('orgid is not a valid ObjectId'), null); }
1508
+ if (!options) { return cb(new Error('options is required'), null); }
1509
+ if (!options.CUSTOMER_ID) { return cb(new Error('options.CUSTOMER_ID is required'), null); }
1510
+ if (!mongoose.Types.ObjectId.isValid(options.CUSTOMER_ID)) { return cb(new Error('options.CUSTOMER_ID is not a valid ObjectId'), null); }
1511
+
1512
+ let query = self.findById(orgid);
1513
+
1514
+ query.select('notes people.person');
1515
+ query.populate('people.person', 'name avatarUrl title calendarEventSummaries');
1791
1516
  query.populate({
1792
1517
  path: 'notes',
1793
- match: { customer: config.CUSTOMER_ID }
1794
- })
1518
+ match: { customer: options.CUSTOMER_ID }
1519
+ });
1795
1520
  query.deepPopulate([
1796
1521
  'notes.createdBy',
1797
1522
  'people.person.calendarEventSummaries.notes.createdBy'
@@ -1800,47 +1525,69 @@ module.exports = function(mongoose, config) {
1800
1525
  'notes.createdBy': { select: 'name avatarUrl title' },
1801
1526
  'people.person.calendarEventSummaries.notes.createdBy': { select: 'name avatarUrl title' }
1802
1527
  }
1803
- })
1804
- query.sort({'createdOn':-1})
1805
- query.exec(cb);
1528
+ });
1529
+ query.sort({'createdOn':-1});
1530
+
1531
+ query.exec(function(err, org) {
1532
+
1533
+ if (err) { return cb(err, null); }
1534
+ else if (!org) { return cb(null, []); }
1535
+
1536
+ org = helpers.cleanOrg(org, options.CUSTOMER_ID);
1537
+
1538
+ return cb(null, org);
1539
+
1540
+ });
1806
1541
 
1807
1542
  };
1808
1543
 
1809
- Organization.statics.getSources = function(id, cb) {
1544
+ Organization.statics.getSources = function(id, options, cb) {
1810
1545
 
1811
- var self = this;
1546
+ const self = this;
1812
1547
 
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) {
1548
+ if (!cb) { throw new Error('cb is required'); }
1549
+ if (!id) { return cb(new Error('id is required'), null); }
1550
+ if (!mongoose.Types.ObjectId.isValid(id)) { return cb(new Error('id is not a valid ObjectId'), null); }
1551
+ if (!options) { return cb(new Error('options is required'), null); }
1552
+ if (!options.CUSTOMER_ID) { return cb(new Error('options.CUSTOMER_ID is required'), null); }
1553
+ if (!mongoose.Types.ObjectId.isValid(options.CUSTOMER_ID)) { return cb(new Error('options.CUSTOMER_ID is not a valid ObjectId'), null); }
1554
+
1555
+ let query = self.findById(id);
1556
+ query.select('people');
1557
+ query.populate('people.person', 'name avatarUrl title doNotDisplay sources');
1558
+ query.deepPopulate([
1559
+ 'people.person.sources.person'
1560
+ ], {
1561
+ populate: {
1562
+ 'people.person.sources.person': { select: 'name avatarUrl title doNotDisplay' }
1563
+ }
1564
+ });
1825
1565
 
1826
- if (err) return cb(err, null);
1827
- if (!org) return cb(null, null);
1566
+ // get the org requested
1567
+ query.exec(function(err, org) {
1568
+
1569
+ if (err) { return cb(err, null); }
1570
+ if (!org) { return cb(null, null); }
1828
1571
 
1829
- self.findById(config.CUSTOMER_ID, function(err, customer) {
1572
+ // get the customer requesting org
1573
+ self.findById(options.CUSTOMER_ID, function(err, customer) {
1830
1574
 
1831
- if (err) return cb(err, null);
1832
- if (!customer) return cb(null, null);
1575
+ if (err) { return cb(err, null); }
1576
+ if (!customer) { return cb(null, null); }
1833
1577
 
1834
- var current = [];
1835
- var past = [];
1836
- var all = [];
1837
- var orgSources = getSources(org.people);
1578
+ let current = [];
1579
+ let past = [];
1580
+ let all = [];
1838
1581
 
1582
+ // combined list of sources from each person at org
1583
+ let orgSources = helpers.getPeopleSources(_.pluck(org.people, 'person'));
1584
+
1585
+ // loop through customer's people and categorize sources
1839
1586
  _.each(customer.people, function(p) {
1840
1587
 
1841
1588
  var source = _.find(orgSources, function(os) {
1842
1589
  if (!os || !os.person || !os.person._id) return false;
1843
- return os.person._id.toString() == p.person.toString();
1590
+ return os.person._id.toString() === p.person.toString();
1844
1591
  });
1845
1592
 
1846
1593
  if (!source) return;
@@ -1851,10 +1598,11 @@ module.exports = function(mongoose, config) {
1851
1598
 
1852
1599
  });
1853
1600
 
1601
+ // return categorized sources
1854
1602
  return cb(null, {
1855
- all: all,
1856
- current: current,
1857
- past: past
1603
+ all: helpers.sortPeopleSources(all, options.CUSTOMER_ID),
1604
+ current: helpers.sortPeopleSources(current, options.CUSTOMER_ID),
1605
+ past: helpers.sortPeopleSources(past, options.CUSTOMER_ID)
1858
1606
  });
1859
1607
 
1860
1608
  });
@@ -1863,53 +1611,57 @@ module.exports = function(mongoose, config) {
1863
1611
 
1864
1612
  };
1865
1613
 
1866
- Organization.statics.listAllFlagged = function (cb) {
1614
+ Organization.statics.modify = function(filter, update, cb) {
1867
1615
 
1868
- var query = this.find({'flagged.resolved': false, 'flagged.text': { $ne: '' }, 'deleted': {$ne: true}});
1869
- query.exec(function (err, orgs) {
1616
+ // VERY IMPORTANT NOTE
1617
+ // findByIdAndUpdate and findOneAndUpdate do not trigger pre-save hook so that code will not run here
1618
+ // at this time, the only known and approved use of this method is for adding and removing roles in totem web
1870
1619
 
1871
- if (err) return cb(err, null);
1620
+ if (!cb) throw new Error('cb is required');
1621
+ if (!filter) { return cb(new Error('filter is required'), null); }
1622
+ if (!update) { return cb(new Error('update is required'), null); }
1872
1623
 
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();
1624
+ var self = this;
1879
1625
 
1880
- return cb(null, orgs);
1626
+ // https://mongoosejs.com/docs/api.html#model_Model.findOneAndUpdate
1627
+ // options runValidators defaults false which is ok since we have upsert false
1628
+ // new returns the updated document
1881
1629
 
1882
- });
1630
+ self.findOneAndUpdate(filter, update, { upsert: false, new: true }, cb);
1883
1631
 
1884
1632
  };
1885
1633
 
1886
- Organization.statics.listCustomers = function listCustomers(cb) {
1634
+ Organization.statics.modifyById = function(id, update, cb) {
1887
1635
 
1888
- var self = this;
1636
+ // VERY IMPORTANT NOTE
1637
+ // findByIdAndUpdate and findOneAndUpdate do not trigger pre-save hook so that code will not run here
1638
+ // at this time, the only known and approved use of this method is for the org edit form in totem web
1889
1639
 
1890
- self
1891
- .find({$where:'this.customer && this.customer.totemUrl && this.customer.totemUrl.length >=1'})
1892
- .exec(cb);
1640
+ if (!cb) throw new Error('cb is required');
1641
+ if (!id) { return cb(new Error('id is required'), null); }
1642
+ if (!update) { return cb(new Error('update is required'), null); }
1893
1643
 
1894
- };
1644
+ var self = this;
1895
1645
 
1896
- Organization.statics.listPage = function (skip, cb) {
1646
+ // https://mongoosejs.com/docs/api.html#model_Model.findOneAndUpdate
1647
+ // options runValidators defaults false which is ok since we have upsert false
1648
+ // new returns the updated document
1897
1649
 
1898
- this
1899
- .find({'deleted': {$ne: true}})
1900
- .sort('name')
1901
- .skip(skip)
1902
- .limit(100)
1903
- .exec(cb)
1650
+ self.findByIdAndUpdate(id, update, { upsert: false, new: true }, cb);
1904
1651
 
1905
1652
  };
1906
1653
 
1907
- Organization.statics.removeById = function(id, cb) {
1654
+ Organization.statics.removeCustomerFilters = function(customerId, cb) {
1908
1655
 
1909
- if (!id) { return cb(new Error('id is required'), null); }
1910
- if (!cb) { throw new Error('cb is required'); }
1656
+ var self = this;
1911
1657
 
1912
- this.remove({_id: id}, cb);
1658
+ self
1659
+ .update(
1660
+ { 'filters.customer': customerId },
1661
+ { $pull : { 'filters': { 'customer': customerId } } },
1662
+ { multi : true }
1663
+ )
1664
+ .exec(cb);
1913
1665
 
1914
1666
  };
1915
1667
 
@@ -2070,22 +1822,6 @@ module.exports = function(mongoose, config) {
2070
1822
 
2071
1823
  };
2072
1824
 
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
1825
  Organization.statics.upsert = function(org, username, cb) {
2090
1826
 
2091
1827
  if (!org) { return cb(new Error('Organization is required'), null); }
@@ -2101,56 +1837,138 @@ module.exports = function(mongoose, config) {
2101
1837
 
2102
1838
  };
2103
1839
 
2104
- Organization.statics.modify = function(filter, update, cb) {
2105
1840
 
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
1841
 
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); }
1842
+ ///////////////////////////////////////////////////////////////////////////////////////
1843
+ // HOOKS
1844
+ // Pre-save: fired on every document before it is saved
1845
+ // Post-init: fired on every document when it's returned from a query
1846
+ ///////////////////////////////////////////////////////////////////////////////////////
2113
1847
 
2114
- var self = this;
1848
+ Organization.pre('save', function(next) {
2115
1849
 
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
1850
+ let prepForSave = function prepForSave(doc) {
2119
1851
 
2120
- self.findOneAndUpdate(filter, update, { upsert: false, new: true }, cb);
1852
+ var cleanContactInfo = function cleanContactInfo(obj) {
2121
1853
 
2122
- };
1854
+ var thereCanOnlyBeOne = function thereCanOnlyBeOne(items) {
2123
1855
 
2124
- Organization.statics.modifyById = function(id, update, cb) {
1856
+ var primaryItems = _.filter(items, function(item) { return item.primary; });
2125
1857
 
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
1858
+ if (primaryItems.length > 1) {
2129
1859
 
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); }
1860
+ _.each(primaryItems, function(item, index) {
1861
+ // skip the first one (leave it primary) and mark the rest as not primary
1862
+ if (index >= 1) item.primary = false;
1863
+ });
2133
1864
 
2134
- var self = this;
1865
+ }
2135
1866
 
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
1867
+ return items;
2139
1868
 
2140
- self.findByIdAndUpdate(id, update, { upsert: false, new: true }, cb);
1869
+ };
2141
1870
 
2142
- };
1871
+ if (!obj || !obj.contact) return;
2143
1872
 
1873
+ if (obj.contact.address) {
2144
1874
 
1875
+ // must have something meaningful
1876
+ obj.contact.address = _.map(obj.contact.address, function(address) {
1877
+ if (!address.city && !address.state && !address.country) return null;
1878
+ else return address;
1879
+ });
2145
1880
 
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
- ///////////////////////////////////////////////////////////////////////////////////////
1881
+ // remove emptiness and dedupe
1882
+ obj.contact.address = _.uniq(_.compact(obj.contact.address), function(item) { return item.city + item.state + item.country; });
2151
1883
 
1884
+ // only one primary
1885
+ obj.contact.address = thereCanOnlyBeOne(obj.contact.address);
2152
1886
 
2153
- Organization.pre('save', function(next) {
1887
+ }
1888
+
1889
+ if (obj.contact.email) {
1890
+
1891
+ // must have something meaningful
1892
+ obj.contact.email = _.map(doc.contact.email, function(item) {
1893
+ if (!item.email) return null;
1894
+ else return item;
1895
+ });
1896
+
1897
+ // remove emptiness and dedupe
1898
+ obj.contact.email = _.uniq(_.compact(obj.contact.email), function(item) { return item.email; });
1899
+
1900
+ // only one primary
1901
+ obj.contact.email = thereCanOnlyBeOne(obj.contact.email);
1902
+
1903
+ }
1904
+
1905
+ if (obj.contact.phone) {
1906
+
1907
+ // must have something meaningful
1908
+ obj.contact.phone = _.map(doc.contact.phone, function(item) {
1909
+ if (!item.number) return null;
1910
+ else return item;
1911
+ });
1912
+
1913
+ // remove emptiness and dedupe
1914
+ obj.contact.phone = _.uniq(_.compact(obj.contact.phone), function(item) { return item.number; });
1915
+
1916
+ // only one primary
1917
+ obj.contact.phone = thereCanOnlyBeOne(obj.contact.phone);
1918
+
1919
+ }
1920
+
1921
+ };
1922
+
1923
+ var cleanPeople = function cleanPeople(obj) {
1924
+
1925
+ if (!obj || !obj.people) return;
1926
+
1927
+ // remove junk
1928
+ obj.people = _.reject(obj.people, function(p) { return p.person == null; });
1929
+
1930
+ // dedupe
1931
+ obj.people = _.uniq(obj.people, function(p) { return p.person._id ? p.person._id.toString() : p.person.toString(); });
1932
+
1933
+ };
1934
+
1935
+ var cleanWebsites = function cleanWebsites(obj) {
1936
+
1937
+ if (!obj) return;
1938
+
1939
+ // Format website
1940
+ if (obj.website) {
1941
+ obj.website = String(obj.website);
1942
+ obj.website = obj.website.replace('http://', '').replace('https://', '').replace(/\/+$/, '');
1943
+ obj.website = utils.getDomain(obj.website);
1944
+ }
1945
+
1946
+ // Format website aliases
1947
+ if (obj.websiteAliases && obj.websiteAliases.length >= 1) {
1948
+ obj.websiteAliases = _.map(obj.websiteAliases, function(alias) {
1949
+ alias = String(alias);
1950
+ alias = alias.replace('http://', '').replace('https://', '').replace(/\/+$/, '');
1951
+ return utils.getDomain(alias);
1952
+ });
1953
+ }
1954
+
1955
+ // Add website to website aliases
1956
+ // There are unique constraints on website and website aliases
1957
+ // This enables us to enforce uniqueness across both and across documents
1958
+ if (obj.website && obj.websiteAliases) obj.websiteAliases.push(obj.website);
1959
+
1960
+ if (obj.websiteAliases) {
1961
+ obj.websiteAliases = _.uniq(obj.websiteAliases);
1962
+ obj.websiteAliases = _.compact(obj.websiteAliases);
1963
+ }
1964
+
1965
+ };
1966
+
1967
+ cleanContactInfo(doc);
1968
+ cleanPeople(doc);
1969
+ cleanWebsites(doc);
1970
+
1971
+ };
2154
1972
 
2155
1973
  prepForSave(this);
2156
1974
 
@@ -2163,27 +1981,40 @@ module.exports = function(mongoose, config) {
2163
1981
  // Protect private data
2164
1982
  // Merge public and private data
2165
1983
 
2166
- var CUSTOMER_ID = config.CUSTOMER_ID;
2167
-
2168
- if (CUSTOMER_ID == 'GLOBAL_PROCESS' && next) return next();
1984
+ // const CUSTOMER_ID = this[CUSTOMER_ID];
1985
+ // let err;
1986
+ //
1987
+ // if (!CUSTOMER_ID) {
1988
+ // err = new Error('Missing CUSTOMER_ID');
1989
+ // if (next) { return next(err); }
1990
+ // else { throw err; }
1991
+ // }
1992
+ //
1993
+ // else if (CUSTOMER_ID === 'GLOBAL_PROCESS' && next) { return next(); }
1994
+ //
1995
+ // else if (!mongoose.Types.ObjectId.isValid(CUSTOMER_ID)) {
1996
+ // err = new Error('CUSTOMER_ID is not a valid ObjectId');
1997
+ // if (next) { return next(err); }
1998
+ // else { throw err; }
1999
+ // }
2169
2000
 
2170
2001
  // remove customer details if not viewing self
2171
- if (doc._id.toString() != CUSTOMER_ID) doc.customer = {};
2002
+ //if (doc._id.toString() !== CUSTOMER_ID) { doc.customer = {}; }
2172
2003
 
2173
2004
  // Website is stored in aliases to facilitate enforcing uniqueness
2174
2005
  // Remove it here to make it easier for consumers to provide a good ux
2175
2006
  // It will get added back in during pre save hook
2176
2007
  if (doc.website && doc.websiteAliases && doc.websiteAliases.length >= 1) {
2177
- doc.websiteAliases = _.reject(doc.websiteAliases, function(alias) { return alias == doc.website; });
2008
+ doc.websiteAliases = _.reject(doc.websiteAliases, function(alias) { return alias === doc.website; });
2178
2009
  }
2179
2010
 
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; });
2011
+ // doc.lps = _.reject(doc.lps, function(item) { return !item.customer || item.customer.toString() !== CUSTOMER_ID; });
2012
+ // doc.filters = _.reject(doc.filters, function(item) { return !item.customer || item.customer.toString() !== CUSTOMER_ID; });
2013
+ // doc.valuations = _.reject(doc.valuations, function(item) { return !item.customer || item.customer.toString() !== CUSTOMER_ID; });
2014
+ // doc.iLevel = _.reject(doc.iLevel, function(item) { return !item.customer || item.customer.toString() !== CUSTOMER_ID; });
2015
+ // doc.chairs = _.reject(doc.chairs, function(item) { return !item.customer || item.customer.toString() !== CUSTOMER_ID; });
2016
+ // doc.operating.acquired.private = _.find(doc.operating.acquired.private, function(item) { return !item.customer || item.customer.toString() === CUSTOMER_ID; });
2017
+ // doc.operating.closed.private = _.find(doc.operating.closed.private, function(item) { return !item.customer || item.customer.toString() === CUSTOMER_ID; });
2187
2018
 
2188
2019
  // people
2189
2020
  _.each(doc.people, function(person) {
@@ -2191,10 +2022,6 @@ module.exports = function(mongoose, config) {
2191
2022
  // always include if explicitly public
2192
2023
  if (person.public) return;
2193
2024
 
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
2025
  });
2199
2026
 
2200
2027
  if (next) return next();
@@ -2207,9 +2034,7 @@ module.exports = function(mongoose, config) {
2207
2034
  ///////////////////////////////////////////////////////////////////////////////////////
2208
2035
 
2209
2036
  Organization.set('toJSON', { virtuals: true });
2210
- Organization.set('usePushEach', true);
2211
2037
  Organization.set('autoIndex', false);
2212
- Organization.set('usePushEach', true);
2213
2038
 
2214
2039
  Organization.index({ website: 1, websiteAliases: 1 }, { unique: true, partialFilterExpression : { type :"string" } });
2215
2040
  Organization.on('index', function(err) { console.log('error building organization_new indexes: ' + err); });