@dhyasama/totem-models 3.1.0 → 3.2.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.
- package/.npmignore +14 -0
- package/index.js +2 -0
- package/lib/Document.js +67 -285
- package/lib/Interaction.js +3 -2
- package/lib/LimitedPartner.js +1 -0
- package/lib/Message.js +210 -0
- package/lib/Organization.js +4 -7
- package/lib/Person.js +2 -0
- package/package-lock.json +1168 -0
- package/package.json +1 -1
- package/test/Document.js +253 -0
- package/test/Message.js +147 -0
- package/test/Organization.js +1 -1
package/.npmignore
ADDED
package/index.js
CHANGED
|
@@ -53,10 +53,12 @@ var bootstrap = function(mongoose, config) {
|
|
|
53
53
|
require('./lib/Activity.js')(mongoose, config);
|
|
54
54
|
require('./lib/CalendarEvent.js')(mongoose, config);
|
|
55
55
|
require('./lib/CapTable.js')(mongoose, config);
|
|
56
|
+
require('./lib/Document.js')(mongoose, config);
|
|
56
57
|
require('./lib/Financials.js')(mongoose, config);
|
|
57
58
|
require('./lib/Interaction.js')(mongoose, config);
|
|
58
59
|
require('./lib/Investment.js')(mongoose, config);
|
|
59
60
|
require('./lib/List.js')(mongoose, config);
|
|
61
|
+
require('./lib/Message.js')(mongoose, config);
|
|
60
62
|
require('./lib/News.js')(mongoose, config);
|
|
61
63
|
require('./lib/Webhook.js')(mongoose, config);
|
|
62
64
|
|
package/lib/Document.js
CHANGED
|
@@ -8,346 +8,128 @@ module.exports = function(mongoose, config) {
|
|
|
8
8
|
env = process.env.NODE_ENV || 'development',
|
|
9
9
|
s3 = require('@dhyasama/ffvc-s3'),
|
|
10
10
|
utils = require('@dhyasama/ffvc-utilities'),
|
|
11
|
-
|
|
12
|
-
crypto = new Crypto({'key': config.crypto.key}),
|
|
11
|
+
postFind = require('mongoose-post-find'),
|
|
13
12
|
_ = require('underscore');
|
|
14
13
|
|
|
15
14
|
var Document = new Schema({
|
|
16
15
|
|
|
17
|
-
|
|
16
|
+
customer: { type: Schema.ObjectId, ref: 'Organization', required: true },
|
|
18
17
|
|
|
19
|
-
|
|
20
|
-
type: Schema.ObjectId,
|
|
21
|
-
ref: 'Fund'
|
|
22
|
-
},
|
|
23
|
-
|
|
24
|
-
published: { type: Boolean, required: true },
|
|
25
|
-
|
|
26
|
-
filename: { type: String, required: true },
|
|
27
|
-
|
|
28
|
-
filetype: { type: String, required: true },
|
|
29
|
-
|
|
30
|
-
filesize: { type: String, required: true },
|
|
18
|
+
createdOn: { type: Date, required: true },
|
|
31
19
|
|
|
32
|
-
|
|
20
|
+
createdBy: { type: Schema.ObjectId, ref: 'Person', index: false, required: true },
|
|
33
21
|
|
|
34
|
-
|
|
35
|
-
type: String,
|
|
36
|
-
required: true,
|
|
37
|
-
enum: ['annual-audit', 'portfolio-holding', 'capital-call', 'k1', 'distribution', 'quarterly-account-statement'] },
|
|
22
|
+
name: { type: String, required: true },
|
|
38
23
|
|
|
39
|
-
|
|
40
|
-
type: String,
|
|
41
|
-
required: true,
|
|
42
|
-
enum: ['lp', 'fund'] },
|
|
24
|
+
contentType: { type: String, required: true },
|
|
43
25
|
|
|
44
|
-
|
|
45
|
-
// upload one doc to s3 with this id in the key
|
|
46
|
-
// e.g., an annual audit for ff Rose would be stored at documents/[scopeid] and shared by all lps in ff Rose
|
|
47
|
-
// for lp-level docs:
|
|
48
|
-
// used to get a batch of docs that were uploaded together
|
|
49
|
-
// e.g., a capital call for ff Sapphire requires a separate document to be uploaded for each lp in the fund
|
|
50
|
-
// scopeid allows retrieving all of the doc records at once for admin purposes
|
|
51
|
-
// unlike fund level docs, these are stored at documents/[_id] so they can be retrieved on an individual basis
|
|
52
|
-
scopeid: { type: String, required: true },
|
|
53
|
-
|
|
54
|
-
year: { type: Number, required: false },
|
|
55
|
-
|
|
56
|
-
quarter: {
|
|
57
|
-
type: String,
|
|
58
|
-
required: false,
|
|
59
|
-
enum: [null, '', 'Q1', 'Q2', 'Q3', 'Q4'] },
|
|
60
|
-
|
|
61
|
-
capitalCall: {
|
|
62
|
-
noticeNumber: { type: Number, required: false },
|
|
63
|
-
noticeDate: { type: Date, required: false },
|
|
64
|
-
dueDate: { type: Date, required: false }
|
|
65
|
-
},
|
|
26
|
+
contentLength: { type: String, required: true },
|
|
66
27
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
username: { type: String, required: true },
|
|
72
|
-
action: { type: String, required: true, enum: ['created', 'published', 'unpublished', 'replaced'] }
|
|
73
|
-
}]
|
|
28
|
+
s3: {
|
|
29
|
+
bucket: { type: String, required: true, trim: true },
|
|
30
|
+
key: { type: String, required: true, trim: true }
|
|
31
|
+
}
|
|
74
32
|
|
|
75
33
|
});
|
|
76
34
|
|
|
77
35
|
|
|
78
36
|
|
|
79
|
-
|
|
80
|
-
//
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
var fund = this.fundInvolved.name;
|
|
85
|
-
return fund;
|
|
86
|
-
};
|
|
87
|
-
|
|
88
|
-
Document.methods.friendlyDocType = function() {
|
|
89
|
-
var doctype = this.doctype ? utils.capitalizeFirstLetters(this.doctype.toLowerCase().split('-').join(' ')) : '';
|
|
90
|
-
return doctype;
|
|
91
|
-
};
|
|
92
|
-
|
|
93
|
-
Document.methods.friendlyDocumentName = function() {
|
|
94
|
-
var year = this.year ? this.year + ' ' : '';
|
|
95
|
-
var quarter = this.quarter ? this.quarter + ' ' : '';
|
|
96
|
-
var callNum = this.doctype == 'capital-call' && utils.isNumeric(this.capitalCall.noticeNumber) ? ' #' + this.capitalCall.noticeNumber : '';
|
|
97
|
-
var desc = this.doctype == 'distribution' ? ' - ' + this.description : '';
|
|
98
|
-
|
|
99
|
-
return year + quarter + this.friendlyDocType() + callNum + desc;
|
|
100
|
-
|
|
101
|
-
};
|
|
37
|
+
///////////////////////////////////////////////////////////////////////////////////////
|
|
38
|
+
// METHODS
|
|
39
|
+
// Methods operate on a single document that has already been returned
|
|
40
|
+
// Note that running a method on a document does not save it
|
|
41
|
+
///////////////////////////////////////////////////////////////////////////////////////
|
|
102
42
|
|
|
103
43
|
Document.methods.friendlyFilesize = function() {
|
|
104
|
-
return utils.humanizeFilesize(this.
|
|
105
|
-
};
|
|
106
|
-
|
|
107
|
-
Document.methods.encryptId = function() {
|
|
108
|
-
return crypto.encrypt(this.id);
|
|
44
|
+
return utils.humanizeFilesize(this.contentLength);
|
|
109
45
|
};
|
|
110
46
|
|
|
111
47
|
|
|
112
48
|
|
|
113
|
-
|
|
49
|
+
//////////////////////////////////////////////////////
|
|
114
50
|
// STATICS
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
Document.statics.exists = function(meta, cb) {
|
|
118
|
-
|
|
119
|
-
var model = this;
|
|
120
|
-
|
|
121
|
-
var done = function(err, docs) {
|
|
122
|
-
return cb(!err && docs.length >= 1, docs[0]);
|
|
123
|
-
};
|
|
124
|
-
|
|
125
|
-
switch(meta.doctype.toLowerCase()) {
|
|
126
|
-
case 'annual-audit':
|
|
127
|
-
listAnnualAudits(model, meta.fundId, meta.year, done);
|
|
128
|
-
break;
|
|
129
|
-
case 'capital-call':
|
|
130
|
-
listCapitalCalls(model, meta.fundId, meta.callNumber, done);
|
|
131
|
-
break;
|
|
132
|
-
case 'portfolio-holding':
|
|
133
|
-
listPortfolioHoldings(model, meta.fundId, meta.year, meta.quarter, done);
|
|
134
|
-
break;
|
|
135
|
-
case 'k1':
|
|
136
|
-
listK1s(model, meta.fundId, meta.year, done);
|
|
137
|
-
break;
|
|
138
|
-
case 'quarterly-account-statement':
|
|
139
|
-
listQuarterlyAccountStatements(model, meta.fundId, meta.year, meta.quarter, done);
|
|
140
|
-
break;
|
|
141
|
-
default:
|
|
142
|
-
return cb(false, null);
|
|
143
|
-
break;
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
};
|
|
147
|
-
|
|
148
|
-
Document.statics.getById = function (cipher, cb) {
|
|
149
|
-
|
|
150
|
-
var id = crypto.decrypt(cipher);
|
|
151
|
-
|
|
152
|
-
this
|
|
153
|
-
.findById(id)
|
|
154
|
-
.populate({
|
|
155
|
-
path: 'lpid',
|
|
156
|
-
model: 'LimitedPartner',
|
|
157
|
-
select: 'name shortName id'
|
|
158
|
-
})
|
|
159
|
-
.populate('fundInvolved')
|
|
160
|
-
.exec(function (err, document) {
|
|
161
|
-
if (document) { document.secureid = cipher; }
|
|
162
|
-
document.secureid = cipher;
|
|
163
|
-
cb(err, document);
|
|
164
|
-
});
|
|
165
|
-
|
|
166
|
-
};
|
|
51
|
+
// Statics operate on the entire collection
|
|
52
|
+
//////////////////////////////////////////////////////
|
|
167
53
|
|
|
168
|
-
Document.statics.
|
|
169
|
-
|
|
170
|
-
this
|
|
171
|
-
.find()
|
|
172
|
-
.populate({
|
|
173
|
-
path: 'lpid',
|
|
174
|
-
model: 'LimitedPartner',
|
|
175
|
-
select: 'name shortName id'
|
|
176
|
-
})
|
|
177
|
-
.populate('fundInvolved')
|
|
178
|
-
.sort({ year: -1, quarter: -1 })
|
|
179
|
-
.exec(function (err, documents) {
|
|
180
|
-
encryptDocumentIds(documents);
|
|
181
|
-
cb(err, documents);
|
|
182
|
-
});
|
|
183
|
-
|
|
184
|
-
};
|
|
54
|
+
Document.statics.createForModel = function(doc, Model, modelId, cb) {
|
|
185
55
|
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
.exec(function (err, documents) {
|
|
193
|
-
encryptDocumentIds(documents);
|
|
194
|
-
return cb(err, documents);
|
|
195
|
-
});
|
|
196
|
-
|
|
197
|
-
};
|
|
198
|
-
|
|
199
|
-
Document.statics.listForScopeId = function (cipher, cb) {
|
|
200
|
-
|
|
201
|
-
// lp-level docs are grouped to scope id to faciliate pulling a batch all at once
|
|
202
|
-
|
|
203
|
-
var id = crypto.decrypt(cipher);
|
|
204
|
-
|
|
205
|
-
this
|
|
206
|
-
.find({ 'scopeid': id })
|
|
207
|
-
.populate({
|
|
208
|
-
path: 'lpid',
|
|
209
|
-
model: 'LimitedPartner',
|
|
210
|
-
select: 'name shortName id'
|
|
211
|
-
})
|
|
212
|
-
.populate('fundInvolved')
|
|
213
|
-
.exec(function (err, documents) {
|
|
214
|
-
console.log(documents.length);
|
|
215
|
-
encryptDocumentIds(documents);
|
|
216
|
-
return cb(err, _.sortBy(documents, function(doc) {
|
|
217
|
-
var lowered = doc.lpid && doc.lpid.name ? doc.lpid.name.toLowerCase() : 'Unknown';
|
|
218
|
-
return lowered;
|
|
219
|
-
}));
|
|
220
|
-
});
|
|
221
|
-
|
|
222
|
-
};
|
|
223
|
-
|
|
224
|
-
Document.statics.listFundLevel = function (cb) {
|
|
225
|
-
|
|
226
|
-
this
|
|
227
|
-
.find({ 'scope': 'fund' })
|
|
228
|
-
.populate({
|
|
229
|
-
path: 'lpid',
|
|
230
|
-
model: 'LimitedPartner',
|
|
231
|
-
select: 'name shortName id'
|
|
232
|
-
})
|
|
233
|
-
.populate('fundInvolved')
|
|
234
|
-
.sort({ year: -1, quarter: -1 })
|
|
235
|
-
.exec(function (err, documents) {
|
|
236
|
-
var docs = _.uniq(documents, false, function(doc) {
|
|
237
|
-
return doc.scopeid;
|
|
56
|
+
var addToModel = function(err, createdDoc) {
|
|
57
|
+
if (err) return cb(err, null);
|
|
58
|
+
Model.findByIdAndUpdate(modelId, { $push: { documents: createdDoc }}, { new: true, upsert: false }, function(err, addedTo) {
|
|
59
|
+
return cb(err, {
|
|
60
|
+
document: createdDoc,
|
|
61
|
+
addedTo: addedTo
|
|
238
62
|
});
|
|
239
|
-
encryptDocumentIds(docs);
|
|
240
|
-
cb(err, docs);
|
|
241
63
|
});
|
|
64
|
+
};
|
|
242
65
|
|
|
243
|
-
|
|
66
|
+
doc.createdOn = new Date();
|
|
244
67
|
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
this
|
|
248
|
-
.find({ 'scope': 'lp' })
|
|
249
|
-
.populate({
|
|
250
|
-
path: 'lpid',
|
|
251
|
-
model: 'LimitedPartner',
|
|
252
|
-
select: 'name shortName id'
|
|
253
|
-
})
|
|
254
|
-
.populate('fundInvolved')
|
|
255
|
-
.sort({ year: -1 })
|
|
256
|
-
.exec(function (err, documents) {
|
|
257
|
-
var docs = _.uniq(documents, false, function(doc) {
|
|
258
|
-
return doc.scopeid;
|
|
259
|
-
});
|
|
260
|
-
encryptDocumentIds(docs);
|
|
261
|
-
cb(err, docs);
|
|
262
|
-
});
|
|
68
|
+
this.create(doc, addToModel);
|
|
263
69
|
|
|
264
70
|
};
|
|
265
71
|
|
|
266
|
-
Document.statics.
|
|
267
|
-
return save(doc, cb);
|
|
268
|
-
};
|
|
72
|
+
Document.statics.delete = function(id, cb) {
|
|
269
73
|
|
|
74
|
+
var self = this;
|
|
270
75
|
|
|
76
|
+
// Not strictly necessary but provides verification that the document being deleted belongs to the customer doing the deleting
|
|
77
|
+
self.findOne({
|
|
78
|
+
'_id': id,
|
|
79
|
+
'customer': config.CUSTOMER_ID
|
|
80
|
+
}, function(err, doc) {
|
|
271
81
|
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
////////////////////////
|
|
82
|
+
if (err) return cb(err, null);
|
|
83
|
+
else if (!doc) return cb(null, null);
|
|
275
84
|
|
|
276
|
-
|
|
85
|
+
doc.remove(cb);
|
|
277
86
|
|
|
278
|
-
var result = _.map(documents, function(doc) {
|
|
279
|
-
doc.secureid = crypto.encrypt(doc.id);
|
|
280
|
-
return doc;
|
|
281
87
|
});
|
|
282
88
|
|
|
283
|
-
|
|
89
|
+
};
|
|
284
90
|
|
|
285
|
-
|
|
91
|
+
Document.statics.getById = function (id, cb) {
|
|
92
|
+
this.findOne({
|
|
93
|
+
'_id': id,
|
|
94
|
+
'customer': config.CUSTOMER_ID
|
|
95
|
+
}).exec(cb);
|
|
96
|
+
};
|
|
286
97
|
|
|
287
|
-
|
|
98
|
+
Document.plugin(postFind, {
|
|
288
99
|
|
|
289
|
-
|
|
290
|
-
.find({ doctype: 'annual-audit', fundInvolved: fundId, year: year })
|
|
291
|
-
.sort({ year: -1 })
|
|
292
|
-
.exec(function (err, documents) {
|
|
293
|
-
encryptDocumentIds(documents);
|
|
294
|
-
cb(err, documents);
|
|
295
|
-
});
|
|
100
|
+
find: function(results, done) {
|
|
296
101
|
|
|
297
|
-
|
|
102
|
+
var CUSTOMER_ID = config.CUSTOMER_ID;
|
|
298
103
|
|
|
299
|
-
|
|
104
|
+
if (CUSTOMER_ID == 'GLOBAL_PROCESS') return done(null, results);
|
|
300
105
|
|
|
301
|
-
|
|
302
|
-
.
|
|
303
|
-
|
|
304
|
-
.exec(function (err, documents) {
|
|
305
|
-
encryptDocumentIds(documents);
|
|
306
|
-
cb(err, documents);
|
|
106
|
+
// Reject any item that is for a different customer
|
|
107
|
+
results = _.reject(results, function(item) {
|
|
108
|
+
return item.customer.toString() != CUSTOMER_ID;
|
|
307
109
|
});
|
|
308
110
|
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
function listK1s(model, fundId, year, cb) {
|
|
111
|
+
return done(null, results);
|
|
312
112
|
|
|
313
|
-
|
|
314
|
-
.find({ doctype: 'k1', fundInvolved: fundId, year: year })
|
|
315
|
-
.sort({ 'year': -1 })
|
|
316
|
-
.exec(function (err, documents) {
|
|
317
|
-
encryptDocumentIds(documents);
|
|
318
|
-
cb(err, documents);
|
|
319
|
-
});
|
|
113
|
+
},
|
|
320
114
|
|
|
321
|
-
|
|
115
|
+
findOne: function(result, done) {
|
|
322
116
|
|
|
323
|
-
|
|
117
|
+
var CUSTOMER_ID = config.CUSTOMER_ID;
|
|
324
118
|
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
.
|
|
328
|
-
|
|
329
|
-
return cb(err, encryptDocumentIds(documents));
|
|
330
|
-
});
|
|
119
|
+
if (!result) return done(null, null);
|
|
120
|
+
else if (CUSTOMER_ID == 'GLOBAL_PROCESS') return done(null, result);
|
|
121
|
+
else if (result.customer.toString() == CUSTOMER_ID) return done(null, result);
|
|
122
|
+
else return done(null, null);
|
|
331
123
|
|
|
332
|
-
|
|
124
|
+
}
|
|
333
125
|
|
|
334
|
-
|
|
126
|
+
});
|
|
335
127
|
|
|
336
|
-
model
|
|
337
|
-
.find({ doctype: 'quarterly-account-statement', fundInvolved: fundId, year: year, quarter: quarter })
|
|
338
|
-
.sort({ year: -1, quarter: -1 })
|
|
339
|
-
.exec(function (err, documents) {
|
|
340
|
-
encryptDocumentIds(documents);
|
|
341
|
-
cb(err, documents);
|
|
342
|
-
});
|
|
343
128
|
|
|
344
|
-
};
|
|
345
129
|
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
});
|
|
350
|
-
}
|
|
130
|
+
///////////////////////////////////////////////////////////////////////////////////////
|
|
131
|
+
// CONFIG
|
|
132
|
+
///////////////////////////////////////////////////////////////////////////////////////
|
|
351
133
|
|
|
352
134
|
Document.set('autoIndex', false);
|
|
353
135
|
Document.on('index', function(err) { console.log('error building document indexes: ' + err); });
|
package/lib/Interaction.js
CHANGED
|
@@ -23,7 +23,8 @@ module.exports = function(mongoose, config) {
|
|
|
23
23
|
internal: [{ type: Schema.ObjectId, ref: 'Person', index: true }], // people from customer
|
|
24
24
|
external: [{ type: Schema.ObjectId, ref: 'Person', index: true }] // everyone else
|
|
25
25
|
},
|
|
26
|
-
notes: [ { type: Schema.ObjectId, ref: 'Note' } ]
|
|
26
|
+
notes: [ { type: Schema.ObjectId, ref: 'Note' } ],
|
|
27
|
+
documents: [ { type: Schema.ObjectId, ref: 'Document' } ]
|
|
27
28
|
|
|
28
29
|
});
|
|
29
30
|
|
|
@@ -77,7 +78,7 @@ module.exports = function(mongoose, config) {
|
|
|
77
78
|
|
|
78
79
|
var self = this;
|
|
79
80
|
var query = self.find({ totemCustomerId: customerId, _id: { $gt: sinceObjectId } });
|
|
80
|
-
|
|
81
|
+
query.populate('attendees.external');
|
|
81
82
|
query.exec(cb);
|
|
82
83
|
|
|
83
84
|
};
|
package/lib/LimitedPartner.js
CHANGED
package/lib/Message.js
ADDED
|
@@ -0,0 +1,210 @@
|
|
|
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
|
+
async = require('async'),
|
|
11
|
+
moment = require('moment'),
|
|
12
|
+
Document = mongoose.model('Document'),
|
|
13
|
+
Note = mongoose.model('Note');
|
|
14
|
+
|
|
15
|
+
var Message = new Schema({
|
|
16
|
+
|
|
17
|
+
createdOn: { type: Date, required: true },
|
|
18
|
+
webhook: { type: Schema.ObjectId, ref: 'Webhook', required: true },
|
|
19
|
+
type: { type: String, required: true, enum: ['email'], default: 'email' }, // for future options
|
|
20
|
+
customer: { type: Schema.ObjectId, ref: 'Organization', required: true },
|
|
21
|
+
subject: { type: String, required: false, default: null, trim: true },
|
|
22
|
+
body: { type: String, required: false, default: null, trim: true },
|
|
23
|
+
recipients: {
|
|
24
|
+
internal: [{ type: Schema.ObjectId, ref: 'Person', index: true }], // people from customer
|
|
25
|
+
external: [{ type: Schema.ObjectId, ref: 'Person', index: true }] // everyone else
|
|
26
|
+
},
|
|
27
|
+
notes: [ { type: Schema.ObjectId, ref: 'Note' } ],
|
|
28
|
+
documents: [ { type: Schema.ObjectId, ref: 'Document' } ],
|
|
29
|
+
raw: { type: Schema.Types.Mixed, required: true }
|
|
30
|
+
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
///////////////////////////////////////
|
|
34
|
+
|
|
35
|
+
Message.statics.addDocument = function(messageId, doc, cb) {
|
|
36
|
+
|
|
37
|
+
Document.createForModel(doc, this, messageId, cb);
|
|
38
|
+
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
Message.statics.addNote = function(messageId, creatorPersonId, text, cb) {
|
|
42
|
+
|
|
43
|
+
Note.createForModel({
|
|
44
|
+
createdBy: creatorPersonId,
|
|
45
|
+
text: text
|
|
46
|
+
}, this, messageId, cb);
|
|
47
|
+
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
Message.statics.delete = function(messageId, customerId, cb) {
|
|
51
|
+
|
|
52
|
+
var self = this;
|
|
53
|
+
|
|
54
|
+
self.findOneAndRemove({
|
|
55
|
+
'_id': messageId,
|
|
56
|
+
'customer': customerId
|
|
57
|
+
}, cb);
|
|
58
|
+
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
Message.statics.deleteDocument = function(docId, cb) {
|
|
62
|
+
|
|
63
|
+
// Delete the doc itself along with any references
|
|
64
|
+
|
|
65
|
+
var self = this;
|
|
66
|
+
|
|
67
|
+
var removeReferences = function removeReferences(callback) {
|
|
68
|
+
self.update({}, {
|
|
69
|
+
$pull: { 'documents' : [docId] }
|
|
70
|
+
}, callback);
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
async.series([
|
|
74
|
+
Document.delete.bind(Document, docId),
|
|
75
|
+
removeReferences
|
|
76
|
+
], function(err, results) {
|
|
77
|
+
return cb(err, null);
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
Message.statics.deleteNote = function(noteId, cb) {
|
|
83
|
+
|
|
84
|
+
// Delete the note itself along with any references
|
|
85
|
+
|
|
86
|
+
var self = this;
|
|
87
|
+
|
|
88
|
+
var removeReferences = function removeReferences(callback) {
|
|
89
|
+
self.update({}, {
|
|
90
|
+
$pull: { 'notes' : [noteId] }
|
|
91
|
+
}, callback);
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
async.series([
|
|
95
|
+
Note.delete.bind(Note, noteId),
|
|
96
|
+
removeReferences
|
|
97
|
+
], function(err, results) {
|
|
98
|
+
return cb(err, null);
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
Message.statics.getDocuments = function getDocuments(personIds, options, cb) {
|
|
104
|
+
|
|
105
|
+
var self = this;
|
|
106
|
+
var query = self.find({ customer: config.CUSTOMER_ID });
|
|
107
|
+
|
|
108
|
+
query.where({'attendees.external': { $in : personIds }});
|
|
109
|
+
query.populate({
|
|
110
|
+
path: 'documents',
|
|
111
|
+
match: { customer: config.CUSTOMER_ID }
|
|
112
|
+
});
|
|
113
|
+
query.deepPopulate([
|
|
114
|
+
'documents.createdBy'
|
|
115
|
+
], {
|
|
116
|
+
populate: {
|
|
117
|
+
'documents.createdBy': { select: 'name avatarUrl title' }
|
|
118
|
+
}
|
|
119
|
+
});
|
|
120
|
+
query.exec(cb);
|
|
121
|
+
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
Message.statics.getForCustomer = function getForCustomer(customerId, cb) {
|
|
125
|
+
|
|
126
|
+
var self = this;
|
|
127
|
+
var query = self.find({ customer: customerId });
|
|
128
|
+
query.exec(cb);
|
|
129
|
+
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
Message.statics.getForPeople = function getForPeople(personIds, options, cb) {
|
|
133
|
+
|
|
134
|
+
// This filters by customer so is NOT usable by admin tools
|
|
135
|
+
if (config.CUSTOMER_ID == 'GLOBAL_PROCESS') return cb(new Error('Access denied. Use getForPeopleLite.'), null);
|
|
136
|
+
|
|
137
|
+
var self = this;
|
|
138
|
+
var query = self.find({ customer: config.CUSTOMER_ID });
|
|
139
|
+
|
|
140
|
+
query.where({'recipients.external': { $in : personIds }});
|
|
141
|
+
query.populate('recipients.internal', 'name title avatarUrl doNotDisplay');
|
|
142
|
+
query.populate('recipients.external', 'name title avatarUrl doNotDisplay');
|
|
143
|
+
query.populate({
|
|
144
|
+
path: 'notes',
|
|
145
|
+
match: { customer: config.CUSTOMER_ID }
|
|
146
|
+
});
|
|
147
|
+
query.populate({
|
|
148
|
+
path: 'documents',
|
|
149
|
+
match: { customer: config.CUSTOMER_ID }
|
|
150
|
+
});
|
|
151
|
+
query.deepPopulate([
|
|
152
|
+
'notes.createdBy',
|
|
153
|
+
'documents.createdBy'
|
|
154
|
+
], {
|
|
155
|
+
populate: {
|
|
156
|
+
'notes.createdBy': { select: 'name avatarUrl title' },
|
|
157
|
+
'documents.createdBy': { select: 'name avatarUrl title' }
|
|
158
|
+
}
|
|
159
|
+
});
|
|
160
|
+
query.exec(cb);
|
|
161
|
+
|
|
162
|
+
};
|
|
163
|
+
|
|
164
|
+
Message.statics.getForPeopleLite = function getForPeopleLite(personIds, cb) {
|
|
165
|
+
|
|
166
|
+
// This doesn't filter by customer so is only usable by admin tools
|
|
167
|
+
if (config.CUSTOMER_ID != 'GLOBAL_PROCESS') return cb(new Error('Access denied'), null);
|
|
168
|
+
|
|
169
|
+
var self = this;
|
|
170
|
+
var query = self.find({'recipients.external': { $in : personIds }});
|
|
171
|
+
query.exec(cb);
|
|
172
|
+
|
|
173
|
+
};
|
|
174
|
+
|
|
175
|
+
Message.statics.getNotes = function getNotes(personIds, options, cb) {
|
|
176
|
+
|
|
177
|
+
var self = this;
|
|
178
|
+
var query = self.find({ customer: config.CUSTOMER_ID });
|
|
179
|
+
|
|
180
|
+
query.where({'attendees.external': { $in : personIds }});
|
|
181
|
+
query.populate({
|
|
182
|
+
path: 'notes',
|
|
183
|
+
match: { customer: config.CUSTOMER_ID }
|
|
184
|
+
});
|
|
185
|
+
query.deepPopulate([
|
|
186
|
+
'notes.createdBy'
|
|
187
|
+
], {
|
|
188
|
+
populate: {
|
|
189
|
+
'notes.createdBy': { select: 'name avatarUrl title' }
|
|
190
|
+
}
|
|
191
|
+
});
|
|
192
|
+
query.exec(cb);
|
|
193
|
+
|
|
194
|
+
};
|
|
195
|
+
|
|
196
|
+
Message.statics.upsert = function(message, cb) {
|
|
197
|
+
message.createdOn = new Date();
|
|
198
|
+
message.save(cb);
|
|
199
|
+
};
|
|
200
|
+
|
|
201
|
+
///////////////////////////////////////
|
|
202
|
+
|
|
203
|
+
Message.set('autoIndex', false);
|
|
204
|
+
|
|
205
|
+
var deepPopulate = require('mongoose-deep-populate')(mongoose);
|
|
206
|
+
Message.plugin(deepPopulate);
|
|
207
|
+
|
|
208
|
+
mongoose.model('Message', Message);
|
|
209
|
+
|
|
210
|
+
};
|