@dhyasama/totem-models 11.86.0 → 11.88.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/Financials.js CHANGED
@@ -19,6 +19,9 @@ module.exports = function(mongoose, config) {
19
19
 
20
20
  customer: { type: Schema.ObjectId, ref: 'Organization', required: true, index: true },
21
21
 
22
+ // the date the financial is as of (not the date added to our system)
23
+ asOfDate: { type: Date },
24
+
22
25
  fiscal: {
23
26
  month: { type: Number, default: 1 },
24
27
  day: { type: Number, default: 1 },
package/lib/Round.js CHANGED
@@ -258,16 +258,6 @@ module.exports = function(mongoose, config) {
258
258
  // Statics operate on the entire collection
259
259
  //////////////////////////////////////////////////////\
260
260
 
261
- Round.statics.getAllOrgs = function getAllOrgs(cb) {
262
-
263
- const self = this;
264
-
265
- if (!cb) { throw new Error('cb is required'); }
266
-
267
- self.distinct('organization', cb);
268
-
269
- };
270
-
271
261
  Round.statics.getByOrg = function getByOrg(orgId, options, cb) {
272
262
 
273
263
  // Gets all the rounds an org has raised
@@ -351,7 +341,7 @@ module.exports = function(mongoose, config) {
351
341
  'organization': { $in: orgIds }
352
342
  });
353
343
 
354
- query.populate('organization', 'name logoUrl website websiteAliases');
344
+ query.populate('organization', 'name logoUrl website websiteAliases operating');
355
345
  query.populate('vehicles.fund');
356
346
 
357
347
  if (options.isWorkerProcess) {
@@ -487,6 +477,74 @@ module.exports = function(mongoose, config) {
487
477
  });
488
478
 
489
479
  };
480
+
481
+ Round.statics.getPortfolioInvestments = function getPortfolioInvestments(options, cb) {
482
+
483
+ const self = this;
484
+
485
+ if (!cb) { throw new Error('cb is required'); }
486
+ if (!options) { return cb(new Error('options is required'), null); }
487
+
488
+ options = helpers.getDefaultOptions(options);
489
+
490
+ if (!options.isWorkerProcess) {
491
+ if (!options.CUSTOMER_ID) { return cb(new Error('options.CUSTOMER_ID is required'), null); }
492
+ if (!mongoose.Types.ObjectId.isValid(options.CUSTOMER_ID)) { return cb(new Error('options.CUSTOMER_ID is not a valid ObjectId'), null); }
493
+ }
494
+
495
+ // First get the customer's fund IDs
496
+ Organization.getById(options.CUSTOMER_ID, { CUSTOMER_ID: options.CUSTOMER_ID }, function(err, customer) {
497
+
498
+ if (err) return cb(err, null);
499
+ if (!customer) return cb(new Error('Customer not found'), null);
500
+ if (!customer.funds || customer.funds.length === 0) return cb(null, []);
501
+
502
+ const fundIds = _.pluck(customer.funds, '_id');
503
+
504
+ let query = self.find({ 'vehicles.fund': { $in: fundIds } });
505
+ query.select('organization roundName vehicles');
506
+ query.populate('organization', 'name description logoUrl website websiteAliases filters status ipo closed acquired operating');
507
+
508
+ if (options.isWorkerProcess) {
509
+ query.populate('vehicles.investments');
510
+ }
511
+ else {
512
+ query.populate({
513
+ path: 'vehicles.investments',
514
+ match: { customer: options.CUSTOMER_ID }
515
+ });
516
+ }
517
+
518
+ query.exec(function(err, rounds) {
519
+
520
+ if (err) return cb(err, null);
521
+ if (!rounds) return cb(null, []);
522
+
523
+ if (!options.isWorkerProcess) {
524
+ _.each(rounds, function(round) {
525
+ round = helpers.cleanRound(round, fundIds, options.CUSTOMER_ID);
526
+ round.organization = helpers.cleanOrg(round.organization, options.CUSTOMER_ID);
527
+ });
528
+ }
529
+
530
+ let portfolioInvestments = [];
531
+ _.each(rounds, function(round) {
532
+ _.each(round.vehicles, function(vehicle) {
533
+ _.each(vehicle.investments, function(investment) {
534
+ investment.organization = round.organization;
535
+ investment.roundName = round.roundName;
536
+ portfolioInvestments.push(investment);
537
+ });
538
+ });
539
+ });
540
+
541
+ return cb(null, portfolioInvestments);
542
+
543
+ });
544
+
545
+ });
546
+
547
+ };
490
548
 
491
549
  Round.statics.getFundPerformance = function getFundPerformance(fundId, options, cb) {
492
550
 
@@ -696,6 +754,7 @@ module.exports = function(mongoose, config) {
696
754
  website: rounds[0].organization.website,
697
755
  status: rounds[0].organization.status,
698
756
  people: rounds[0].organization.people,
757
+ operating: rounds[0].organization.operating,
699
758
  funds: fundList
700
759
  });
701
760
 
@@ -757,6 +816,175 @@ module.exports = function(mongoose, config) {
757
816
 
758
817
  };
759
818
 
819
+ Round.statics.getRelated = function getRelated(orgid, options, cb) {
820
+
821
+ const self = this;
822
+ const async = require('async');
823
+ const Organization = mongoose.model('Organization');
824
+
825
+ if (!cb) { throw new Error('cb is required'); }
826
+ if (!orgid) { return cb(new Error('orgid is required'), null); }
827
+ if (!mongoose.Types.ObjectId.isValid(orgid)) { return cb(new Error('orgid is not a valid ObjectId'), null); }
828
+ if (!options) { return cb(new Error('options is required'), null); }
829
+ if (!options.CUSTOMER_ID) { return cb(new Error('options.CUSTOMER_ID is required'), null); }
830
+ if (!mongoose.Types.ObjectId.isValid(options.CUSTOMER_ID)) { return cb(new Error('options.CUSTOMER_ID is not a valid ObjectId'), null); }
831
+
832
+ // We need customerFunds to filter rounds - extract from options or get all customer funds
833
+ var customerFunds = options.customerFunds;
834
+ if (!customerFunds) {
835
+ const Fund = mongoose.model('Fund');
836
+ return Fund.findByCustomer(options.CUSTOMER_ID, function(err, funds) {
837
+ if (err) return cb(err);
838
+ options.customerFunds = funds;
839
+ return self.getRelated(orgid, options, cb);
840
+ });
841
+ }
842
+
843
+ async.parallel([
844
+
845
+ // Find organizations acquired by this org (acquirees)
846
+ function(callback) {
847
+ Organization
848
+ .find({
849
+ $or: [
850
+ { 'operating.acquired.private.by': orgid, 'operating.acquired.private.customer': options.CUSTOMER_ID, 'deleted': { $ne: true } },
851
+ { 'operating.acquired.public.by': orgid, 'deleted': { $ne: true } }
852
+ ]
853
+ })
854
+ .select('name logoUrl')
855
+ .exec(callback);
856
+ },
857
+
858
+ // Find organizations merged with this org
859
+ function(callback) {
860
+ Organization
861
+ .find({
862
+ $or: [
863
+ { 'operating.merged.private.with': orgid, 'operating.merged.private.customer': options.CUSTOMER_ID, 'deleted': { $ne: true } },
864
+ { 'operating.merged.public.with': orgid, 'deleted': { $ne: true } }
865
+ ]
866
+ })
867
+ .select('name logoUrl')
868
+ .exec(callback);
869
+ },
870
+
871
+ // Find organizations that acquired this org (acquirers) or merged with this org
872
+ function(callback) {
873
+ Organization
874
+ .findById(orgid)
875
+ .select('operating')
876
+ .exec(function(err, mainOrg) {
877
+ if (err) return callback(err);
878
+ if (!mainOrg) return callback(null, []);
879
+
880
+ var relatedIds = [];
881
+
882
+ // Check for acquirer
883
+ if (mainOrg.operating && mainOrg.operating.acquired) {
884
+ // acquired.private is an array, iterate through it
885
+ if (mainOrg.operating.acquired.private && Array.isArray(mainOrg.operating.acquired.private)) {
886
+ mainOrg.operating.acquired.private.forEach(function(acquiredEntry) {
887
+ if (acquiredEntry && acquiredEntry.by) {
888
+ relatedIds.push(acquiredEntry.by);
889
+ }
890
+ });
891
+ }
892
+
893
+ if (mainOrg.operating.acquired.public && mainOrg.operating.acquired.public.by) {
894
+ relatedIds.push(mainOrg.operating.acquired.public.by);
895
+ }
896
+ }
897
+
898
+ // Check for merger partner
899
+ if (mainOrg.operating && mainOrg.operating.merged) {
900
+ // merged.private is an array, iterate through it
901
+ if (mainOrg.operating.merged.private && Array.isArray(mainOrg.operating.merged.private)) {
902
+ mainOrg.operating.merged.private.forEach(function(mergedEntry) {
903
+ if (mergedEntry && mergedEntry.with) {
904
+ relatedIds.push(mergedEntry.with);
905
+ }
906
+ });
907
+ }
908
+
909
+ if (mainOrg.operating.merged.public && mainOrg.operating.merged.public.with) {
910
+ relatedIds.push(mainOrg.operating.merged.public.with);
911
+ }
912
+ }
913
+
914
+ if (relatedIds.length === 0) return callback(null, []);
915
+
916
+ Organization
917
+ .find({
918
+ '_id': { $in: relatedIds },
919
+ 'deleted': { $ne: true }
920
+ })
921
+ .select('name logoUrl')
922
+ .exec(callback);
923
+ });
924
+ }
925
+
926
+ ], function(err, results) {
927
+ if (err) return cb(err);
928
+
929
+ // Flatten and combine all results
930
+ var allResults = [];
931
+ results.forEach(function(resultSet) {
932
+ if (Array.isArray(resultSet)) {
933
+ allResults = allResults.concat(resultSet);
934
+ }
935
+ });
936
+
937
+ // Remove duplicates and the org itself
938
+ var uniqueResults = [];
939
+ var seenIds = new Set();
940
+
941
+ allResults.forEach(function(org) {
942
+ if (!seenIds.has(org._id.toString()) && org._id.toString() !== orgid.toString()) {
943
+ seenIds.add(org._id.toString());
944
+ uniqueResults.push(org);
945
+ }
946
+ });
947
+
948
+ // Now get rounds for each related organization
949
+ async.map(uniqueResults, function(org, mapCallback) {
950
+
951
+ var fundIds = customerFunds.map(function(fund) { return fund._id; });
952
+
953
+ self
954
+ .find({
955
+ 'organization': org._id,
956
+ 'vehicles.fund': { $in: fundIds },
957
+ 'deleted': { $ne: true }
958
+ })
959
+ .populate('vehicles.fund', 'name shortName hexColorCode abbreviation closeDate')
960
+ .populate('organization', 'name logoUrl')
961
+ .populate({
962
+ path: 'vehicles.investments',
963
+ match: { customer: options.CUSTOMER_ID }
964
+ })
965
+ .exec(function(err, rounds) {
966
+ if (err) return mapCallback(err);
967
+
968
+ // Clean rounds to only show vehicles for customer funds
969
+ if (rounds && !options.isWorkerProcess) {
970
+ rounds = rounds.map(function(round) {
971
+ return helpers.cleanRound(round, fundIds, options.CUSTOMER_ID);
972
+ });
973
+ }
974
+
975
+ mapCallback(null, {
976
+ org: org,
977
+ rounds: rounds || []
978
+ });
979
+ });
980
+
981
+ }, function(err, relatedWithRounds) {
982
+ if (err) return cb(err);
983
+ cb(null, relatedWithRounds);
984
+ });
985
+ });
986
+ };
987
+
760
988
  Round.statics.upsert = function(round, cb) {
761
989
 
762
990
  if (!round) { return cb(new Error('round is required'), null); }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dhyasama/totem-models",
3
- "version": "11.86.0",
3
+ "version": "11.88.0",
4
4
  "author": "Jason Reynolds",
5
5
  "license": "UNLICENSED",
6
6
  "description": "Models for Totem platform",