@dhyasama/totem-models 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/List.js ADDED
@@ -0,0 +1,217 @@
1
+ "use strict";
2
+
3
+ module.exports = function(mongoose, config) {
4
+
5
+ var
6
+
7
+ Schema = mongoose.Schema,
8
+ env = process.env.NODE_ENV || 'development',
9
+ utils = require('@dhyasama/ffvc-utilities'),
10
+ _ = require('underscore'),
11
+ postFind = require('mongoose-post-find');
12
+
13
+ var List = new Schema({
14
+
15
+ customer: { type: Schema.ObjectId, ref: 'Organization', index: true, required: true },
16
+
17
+ name: { type: String, index: true, required: true },
18
+
19
+ key: { type: String, required: true, unique: true },
20
+
21
+ createdOn: { type: Date, index: false, required: true },
22
+
23
+ createdBy: { type: Schema.ObjectId, ref: 'Person', index: false, required: true },
24
+
25
+ // Keeping these separate to facilitate population
26
+
27
+ // todo - how to update these with company consolidation?
28
+
29
+ limitedPartners: [{ type: Schema.ObjectId, ref: 'LimitedPartner', index: false, required: false }],
30
+
31
+ organizations: [{ type: Schema.ObjectId, ref: 'Organization', index: false, required: false }],
32
+
33
+ people: [{ type: Schema.ObjectId, ref: 'Person', index: false, required: false }]
34
+ });
35
+
36
+ // Items are kept separate to facilitate population
37
+ // This is a convenience function to get the full list of items
38
+ List.virtual('items').get(function () {
39
+
40
+ var self = this;
41
+ var allItems = [];
42
+
43
+ var addItems = function(type, items) {
44
+ _.each(self[type], function(item) {
45
+ items.push({
46
+ type: type,
47
+ item: item
48
+ });
49
+ });
50
+ };
51
+
52
+ addItems('limitedPartners', allItems);
53
+ addItems('organizations', allItems);
54
+ addItems('people', allItems);
55
+
56
+ allItems = _.sortBy(allItems, function(item) {
57
+ if (!item.item || !item.item.name) return null;
58
+ else return item.type == 'people' ? item.item.name.first + ' ' + item.item.name.last : item.item.name;
59
+ });
60
+
61
+ allItems = _.compact(allItems);
62
+
63
+ return allItems;
64
+
65
+ });
66
+
67
+ List.statics.addItem = function(listId, itemId, collection, cb) {
68
+
69
+ var self = this;
70
+
71
+ self.findOne({
72
+ '_id': listId,
73
+ 'customer': config.CUSTOMER_ID
74
+ }, function(err, result) {
75
+
76
+ if (err) return cb(err, null);
77
+ if (!result) return cb(null, null);
78
+
79
+ result[collection].push(itemId);
80
+
81
+ result.save(cb);
82
+
83
+ });
84
+
85
+ };
86
+
87
+ List.statics.createList = function(name, items, creator, cb) {
88
+
89
+ var self = this;
90
+ var CUSTOMER_ID = config.CUSTOMER_ID;
91
+
92
+ if (CUSTOMER_ID == 'GLOBAL_PROCESS') throw new Error('Cannot create lists in a global process');
93
+ if (!name) throw new Error('Name is required');
94
+ if (!items) items = {};
95
+ if (!cb) throw new Error('cb is required');
96
+
97
+ var list = new self();
98
+ list.customer = config.CUSTOMER_ID;
99
+ list.name = name;
100
+ list.createdOn = new Date();
101
+ list.createdBy = creator;
102
+ list.limitedPartners = items.limitedPartners || [];
103
+ list.organizations = items.organizations || [];
104
+ list.people = items.people || [];
105
+
106
+ // enforce unique customer/name tuple
107
+ list.key = list.customer + '-' + list.name.split(' ').join('-');
108
+
109
+ list.save(cb);
110
+
111
+ };
112
+
113
+ List.statics.getById = function (id, cb) {
114
+ this
115
+ .findOne({
116
+ '_id': id,
117
+ 'customer': config.CUSTOMER_ID
118
+ })
119
+ .populate('createdBy', 'name avatarUrl')
120
+ .populate('limitedPartners', 'name logoUrl')
121
+ .populate('organizations', 'name logoUrl')
122
+ .populate('people', 'name title avatarUrl')
123
+ .exec(cb);
124
+ };
125
+
126
+ List.statics.getLists = function(cb) {
127
+
128
+ var self = this;
129
+
130
+ self
131
+ .find({ 'customer': config.CUSTOMER_ID })
132
+ .populate('limitedPartners', 'name logoUrl')
133
+ .populate('organizations', 'name logoUrl')
134
+ .populate('people', 'name title avatarUrl')
135
+ .exec(cb);
136
+
137
+ };
138
+
139
+ List.statics.remove = function(id, cb) {
140
+ this.findOneAndRemove({
141
+ '_id': id,
142
+ 'customer': config.CUSTOMER_ID
143
+ }, cb);
144
+ };
145
+
146
+ List.statics.removeItem = function(listId, itemId, collection, cb) {
147
+
148
+ var self = this;
149
+
150
+ var update = {};
151
+ update[collection] = itemId;
152
+
153
+ self.findOneAndUpdate({
154
+ '_id': listId,
155
+ 'customer': config.CUSTOMER_ID
156
+ }, { $pull: update }, { new: true }, cb);
157
+
158
+ };
159
+
160
+ List.pre('save', function(next) {
161
+
162
+ var self = this;
163
+
164
+ var dedupeArray = function dedupeArray(arr) {
165
+ return _.uniq(arr, function(item) {
166
+ return (utils.isValidObjectId(item) ? item : item._id).toString();
167
+ });
168
+ };
169
+
170
+ // enforce unique items in arrays
171
+ self.limitedPartners = dedupeArray(self.limitedPartners);
172
+ self.organizations = dedupeArray(self.organizations);
173
+ self.people = dedupeArray(self.people);
174
+
175
+ next();
176
+
177
+ });
178
+
179
+ List.set('autoIndex', (env == 'development'));
180
+ List.set('toJSON', { virtuals: true });
181
+
182
+ List.plugin(postFind, {
183
+
184
+ find: function(results, done) {
185
+
186
+ var CUSTOMER_ID = config.CUSTOMER_ID;
187
+
188
+ if (CUSTOMER_ID == 'GLOBAL_PROCESS') return done(null, results);
189
+
190
+ // Reject any item that is for a different customer
191
+ results = _.reject(results, function(item) {
192
+ return item.customer.toString() != CUSTOMER_ID;
193
+ });
194
+
195
+ return done(null, results);
196
+
197
+ },
198
+
199
+ findOne: function(result, done) {
200
+
201
+ var CUSTOMER_ID = config.CUSTOMER_ID;
202
+
203
+ if (!result) return done(null, null);
204
+ else if (CUSTOMER_ID == 'GLOBAL_PROCESS') return done(null, result);
205
+ else if (result.customer.toString() == CUSTOMER_ID) return done(null, result);
206
+ else return done(null, null);
207
+
208
+ }
209
+
210
+ });
211
+
212
+ List.set('autoIndex', true);
213
+ List.on('index', function(err) { console.log('error building list indexes: ' + err); });
214
+
215
+ mongoose.model('List', List);
216
+
217
+ };
package/lib/News.js ADDED
@@ -0,0 +1,161 @@
1
+ "use strict";
2
+
3
+ module.exports = function(mongoose, config) {
4
+
5
+ var
6
+
7
+ Schema = mongoose.Schema,
8
+ env = process.env.NODE_ENV || 'development',
9
+ _ = require('underscore'),
10
+
11
+ News = new Schema({
12
+
13
+ title: { type: String, required: true },
14
+
15
+ createdOn: { type: Date, required: true },
16
+
17
+ createdBy: { type: String, required: true },
18
+
19
+ excerpt: { type: String, required: false, default: null },
20
+
21
+ link: { type: String, required: true },
22
+
23
+ publication: { type: String },
24
+
25
+ fundsInvolved: [{
26
+ type: Schema.ObjectId,
27
+ ref: 'Fund'
28
+ }],
29
+
30
+ // TODO - make all news about port cos
31
+ // required: true
32
+ // remove internal
33
+ // update admin to reflect these changes
34
+
35
+ // todo - put new org id in org field
36
+ portfolioCompany: {
37
+ type: Schema.ObjectId,
38
+ ref: 'PortfolioCompany',
39
+ required: false,
40
+ default: null
41
+ },
42
+
43
+ org: {
44
+ type: Schema.ObjectId,
45
+ ref: 'Organization',
46
+ required: false,
47
+ default: null
48
+ },
49
+
50
+ internal: { type: Boolean, default: false },
51
+
52
+ // TODO - this will be going away
53
+ discourse: {
54
+ id: { type: String },
55
+ firstPostId: { type: String },
56
+ slug: { type: String }
57
+ },
58
+
59
+ extracted: { type: Schema.Types.Mixed }
60
+
61
+ });
62
+
63
+ News.statics.getById = function (id, cb) {
64
+
65
+ this
66
+ .findById(id)
67
+ .populate('org fundsInvolved')
68
+ .exec(cb);
69
+
70
+ };
71
+
72
+ News.statics.list = function (cb) {
73
+
74
+ this
75
+ .find()
76
+ .populate('org fundsInvolved')
77
+ .sort('-createdOn')
78
+ .exec(cb);
79
+
80
+ };
81
+
82
+ News.statics.listForCompany = function (id, cb) {
83
+
84
+ this
85
+ .find({ org: id })
86
+ .populate('org fundsInvolved')
87
+ .sort('-createdOn')
88
+ .exec(cb);
89
+
90
+ };
91
+
92
+ News.statics.listForCompanyBySlug = function (slug, cb) {
93
+
94
+ this
95
+ .find()
96
+ .populate('org fundsInvolved')
97
+ .sort('-createdOn')
98
+ .exec(function (err, news) {
99
+
100
+ if (err) { return cb(err, null); }
101
+
102
+ var filtered = _.filter(news, function(item) {
103
+ return item.org && item.org.slug == slug;
104
+ });
105
+
106
+ return cb(null, filtered);
107
+
108
+ });
109
+
110
+ };
111
+
112
+ News.statics.listInternal = function (cb) {
113
+
114
+ this
115
+ .find({ internal: true })
116
+ .populate('org fundsInvolved')
117
+ .sort('-createdOn')
118
+ .exec(cb);
119
+
120
+ };
121
+
122
+ News.statics.listForFunds = function (fundIds, cb) {
123
+
124
+ if (!fundIds || fundIds.length == 0) return cb(null, null);
125
+
126
+ this
127
+ .find({ fundsInvolved: { $in : fundIds } })
128
+ .populate('org fundsInvolved')
129
+ .sort('-createdOn')
130
+ .exec(function(err, result) {
131
+
132
+ if (err) return cb(err, null);
133
+
134
+ _.each(result, function(newsItem) {
135
+ newsItem.fundsInvolved = _.filter(newsItem.fundsInvolved, function(fund) { return fundIds.indexOf(fund._id.toString()) >= 0; });
136
+ });
137
+
138
+ return cb(null, result);
139
+
140
+ });
141
+
142
+ };
143
+
144
+ News.statics.upsert = function (news, cb) {
145
+ news.markModified('extracted');
146
+ news.save(cb);
147
+ };
148
+
149
+ News.statics.delete = function(id, cb) {
150
+ this.getById(id, function(err, item) {
151
+ if (err) return cb(err, null);
152
+ item.remove(cb);
153
+ });
154
+ };
155
+
156
+ News.set('autoIndex', true);
157
+ News.on('index', function(err) { console.log('error building news indexes: ' + err); });
158
+
159
+ mongoose.model('News', News);
160
+
161
+ };
package/lib/Note.js ADDED
@@ -0,0 +1,170 @@
1
+ "use strict";
2
+
3
+ module.exports = function(mongoose, config) {
4
+
5
+ var
6
+
7
+ Schema = mongoose.Schema,
8
+ env = process.env.NODE_ENV || 'development',
9
+ async = require('async'),
10
+ _ = require('underscore'),
11
+ postFind = require('mongoose-post-find'),
12
+ querystring = require('querystring');
13
+
14
+ var Note = new Schema({
15
+
16
+ customer: { type: Schema.ObjectId, ref: 'Organization', index: true, required: true },
17
+
18
+ createdOn: { type: Date, index: false, required: true },
19
+
20
+ createdBy: { type: Schema.ObjectId, ref: 'Person', index: false, required: true },
21
+
22
+ text: { type: String, index: false, required: true, trim: true }
23
+
24
+ });
25
+
26
+ Note.statics.createForCalendarEvent = function(providerEventId, creatorPersonId, text, cb) {
27
+
28
+ var self = this;
29
+ var Person = mongoose.model('Person');
30
+
31
+ var queue = async.queue(function(task, callback) {
32
+ Person.update(
33
+ { '_id': task.personId, 'calendarEventSummaries.providerEventId': providerEventId },
34
+ { "$push": { "calendarEventSummaries.$.notes": task.note } },
35
+ callback);
36
+ }, 8);
37
+
38
+ // get all people with cal event summary with providerEventId
39
+ Person
40
+ .find({ 'calendarEventSummaries.providerEventId': providerEventId })
41
+ .exec(function(err, externalAttendees) {
42
+
43
+ if (err) return cb(err, null);
44
+
45
+ var note = {
46
+ createdBy: creatorPersonId,
47
+ text: text,
48
+ createdOn: new Date(),
49
+ customer: config.CUSTOMER_ID
50
+ };
51
+
52
+ // create the note once
53
+ self.create(note, function(err, result) {
54
+
55
+ if (err) return cb(err, null);
56
+
57
+ queue.drain = function() { return cb(null, result); };
58
+
59
+ // add it to each person that attended the event
60
+ _.each(externalAttendees, function(person) {
61
+
62
+ // find the event summary
63
+ var eventSummary = _.find(person.calendarEventSummaries, function(ces) {
64
+ return ces.providerEventId == providerEventId;
65
+ });
66
+
67
+ // attach note reference to event summary
68
+ if (eventSummary) {
69
+ queue.push({
70
+ personId: person._id,
71
+ note: result
72
+ }, function(err, result) {
73
+ if (err) console.log('ERR:', err);
74
+ });
75
+ }
76
+
77
+ });
78
+
79
+ });
80
+
81
+ });
82
+
83
+ };
84
+
85
+ Note.statics.createForModel = function(note, Model, modelId, cb) {
86
+
87
+ var addToModel = function(err, createdNote) {
88
+ if (err) return cb(err, null);
89
+ Model.findByIdAndUpdate(modelId, { $push: { notes: createdNote }}, { new: true, upsert: false }, function(err, addedTo) {
90
+ return cb(err, {
91
+ note: createdNote,
92
+ addedTo: addedTo
93
+ });
94
+ });
95
+ };
96
+
97
+ note.createdOn = new Date();
98
+ note.customer = config.CUSTOMER_ID;
99
+
100
+ this.create(note, addToModel);
101
+
102
+ };
103
+
104
+ Note.statics.getById = function(id, cb) {
105
+ this.findOne({
106
+ '_id': id,
107
+ 'customer': config.CUSTOMER_ID
108
+ }).exec(cb);
109
+ };
110
+
111
+ Note.statics.delete = function(noteId, cb) {
112
+
113
+ var self = this;
114
+
115
+ // Not strictly necessary but provides verification that the note being deleted belongs to the customer doing the deleting
116
+ self.findOne({
117
+ '_id': noteId,
118
+ 'customer': config.CUSTOMER_ID
119
+ }, function(err, note) {
120
+
121
+ if (err) return cb(err, null);
122
+ else if (!note) return cb(null, null);
123
+
124
+ note.remove(cb);
125
+
126
+ });
127
+
128
+ };
129
+
130
+ Note.post('init', function() {
131
+ var self = this;
132
+ self.text = querystring.unescape(self.text);
133
+ });
134
+
135
+ Note.plugin(postFind, {
136
+
137
+ find: function(results, done) {
138
+
139
+ var CUSTOMER_ID = config.CUSTOMER_ID;
140
+
141
+ if (CUSTOMER_ID == 'GLOBAL_PROCESS') return done(null, results);
142
+
143
+ // Reject any item that is for a different customer
144
+ results = _.reject(results, function(item) {
145
+ return item.customer.toString() != CUSTOMER_ID;
146
+ });
147
+
148
+ return done(null, results);
149
+
150
+ },
151
+
152
+ findOne: function(result, done) {
153
+
154
+ var CUSTOMER_ID = config.CUSTOMER_ID;
155
+
156
+ if (!result) return done(null, null);
157
+ else if (CUSTOMER_ID == 'GLOBAL_PROCESS') return done(null, result);
158
+ else if (result.customer.toString() == CUSTOMER_ID) return done(null, result);
159
+ else return done(null, null);
160
+
161
+ }
162
+
163
+ });
164
+
165
+ Note.set('autoIndex', true);
166
+ Note.on('index', function(err) { console.log('error building note indexes: ' + err); });
167
+
168
+ mongoose.model('Note', Note);
169
+
170
+ };