@dhyasama/totem-models 3.1.0 → 3.2.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/.npmignore +14 -0
- package/index.js +2 -0
- package/lib/Document.js +65 -285
- package/lib/Interaction.js +2 -1
- package/lib/LimitedPartner.js +1 -0
- package/lib/Message.js +209 -0
- package/lib/Organization.js +3 -6
- package/lib/Person.js +2 -0
- package/package-lock.json +1168 -0
- package/package.json +1 -1
- package/test/Document.js +236 -0
- package/test/Message.js +144 -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,126 @@ 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
|
-
history: [{
|
|
70
|
-
timestamp: { type: Date, required: true },
|
|
71
|
-
username: { type: String, required: true },
|
|
72
|
-
action: { type: String, required: true, enum: ['created', 'published', 'unpublished', 'replaced'] }
|
|
73
|
-
}]
|
|
28
|
+
s3key: { type: String, required: true }
|
|
74
29
|
|
|
75
30
|
});
|
|
76
31
|
|
|
77
32
|
|
|
78
33
|
|
|
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
|
-
};
|
|
34
|
+
///////////////////////////////////////////////////////////////////////////////////////
|
|
35
|
+
// METHODS
|
|
36
|
+
// Methods operate on a single document that has already been returned
|
|
37
|
+
// Note that running a method on a document does not save it
|
|
38
|
+
///////////////////////////////////////////////////////////////////////////////////////
|
|
102
39
|
|
|
103
40
|
Document.methods.friendlyFilesize = function() {
|
|
104
|
-
return utils.humanizeFilesize(this.
|
|
105
|
-
};
|
|
106
|
-
|
|
107
|
-
Document.methods.encryptId = function() {
|
|
108
|
-
return crypto.encrypt(this.id);
|
|
41
|
+
return utils.humanizeFilesize(this.contentLength);
|
|
109
42
|
};
|
|
110
43
|
|
|
111
44
|
|
|
112
45
|
|
|
113
|
-
|
|
46
|
+
//////////////////////////////////////////////////////
|
|
114
47
|
// 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
|
-
};
|
|
48
|
+
// Statics operate on the entire collection
|
|
49
|
+
//////////////////////////////////////////////////////
|
|
167
50
|
|
|
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
|
-
});
|
|
51
|
+
Document.statics.createForModel = function(doc, Model, modelId, cb) {
|
|
183
52
|
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
.populate('fundInvolved')
|
|
191
|
-
.sort({ year: -1, quarter: -1, fund: 1 })
|
|
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;
|
|
53
|
+
var addToModel = function(err, createdDoc) {
|
|
54
|
+
if (err) return cb(err, null);
|
|
55
|
+
Model.findByIdAndUpdate(modelId, { $push: { documents: createdDoc }}, { new: true, upsert: false }, function(err, addedTo) {
|
|
56
|
+
return cb(err, {
|
|
57
|
+
document: createdDoc,
|
|
58
|
+
addedTo: addedTo
|
|
238
59
|
});
|
|
239
|
-
encryptDocumentIds(docs);
|
|
240
|
-
cb(err, docs);
|
|
241
60
|
});
|
|
61
|
+
};
|
|
242
62
|
|
|
243
|
-
|
|
63
|
+
doc.createdOn = new Date();
|
|
64
|
+
doc.customer = config.CUSTOMER_ID;
|
|
244
65
|
|
|
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
|
-
});
|
|
66
|
+
this.create(doc, addToModel);
|
|
263
67
|
|
|
264
68
|
};
|
|
265
69
|
|
|
266
|
-
Document.statics.
|
|
267
|
-
return save(doc, cb);
|
|
268
|
-
};
|
|
70
|
+
Document.statics.delete = function(id, cb) {
|
|
269
71
|
|
|
72
|
+
var self = this;
|
|
270
73
|
|
|
74
|
+
// Not strictly necessary but provides verification that the document being deleted belongs to the customer doing the deleting
|
|
75
|
+
self.findOne({
|
|
76
|
+
'_id': id,
|
|
77
|
+
'customer': config.CUSTOMER_ID
|
|
78
|
+
}, function(err, doc) {
|
|
271
79
|
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
////////////////////////
|
|
80
|
+
if (err) return cb(err, null);
|
|
81
|
+
else if (!doc) return cb(null, null);
|
|
275
82
|
|
|
276
|
-
|
|
83
|
+
doc.remove(cb);
|
|
277
84
|
|
|
278
|
-
var result = _.map(documents, function(doc) {
|
|
279
|
-
doc.secureid = crypto.encrypt(doc.id);
|
|
280
|
-
return doc;
|
|
281
85
|
});
|
|
282
86
|
|
|
283
|
-
|
|
87
|
+
};
|
|
284
88
|
|
|
285
|
-
|
|
89
|
+
Document.statics.getById = function (id, cb) {
|
|
90
|
+
this.findOne({
|
|
91
|
+
'_id': id,
|
|
92
|
+
'customer': config.CUSTOMER_ID
|
|
93
|
+
}).exec(cb);
|
|
94
|
+
};
|
|
286
95
|
|
|
287
|
-
|
|
96
|
+
Document.plugin(postFind, {
|
|
288
97
|
|
|
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
|
-
});
|
|
98
|
+
find: function(results, done) {
|
|
296
99
|
|
|
297
|
-
|
|
100
|
+
var CUSTOMER_ID = config.CUSTOMER_ID;
|
|
298
101
|
|
|
299
|
-
|
|
102
|
+
if (CUSTOMER_ID == 'GLOBAL_PROCESS') return done(null, results);
|
|
300
103
|
|
|
301
|
-
|
|
302
|
-
.
|
|
303
|
-
|
|
304
|
-
.exec(function (err, documents) {
|
|
305
|
-
encryptDocumentIds(documents);
|
|
306
|
-
cb(err, documents);
|
|
104
|
+
// Reject any item that is for a different customer
|
|
105
|
+
results = _.reject(results, function(item) {
|
|
106
|
+
return item.customer.toString() != CUSTOMER_ID;
|
|
307
107
|
});
|
|
308
108
|
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
function listK1s(model, fundId, year, cb) {
|
|
109
|
+
return done(null, results);
|
|
312
110
|
|
|
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
|
-
});
|
|
111
|
+
},
|
|
320
112
|
|
|
321
|
-
|
|
113
|
+
findOne: function(result, done) {
|
|
322
114
|
|
|
323
|
-
|
|
115
|
+
var CUSTOMER_ID = config.CUSTOMER_ID;
|
|
324
116
|
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
.
|
|
328
|
-
|
|
329
|
-
return cb(err, encryptDocumentIds(documents));
|
|
330
|
-
});
|
|
117
|
+
if (!result) return done(null, null);
|
|
118
|
+
else if (CUSTOMER_ID == 'GLOBAL_PROCESS') return done(null, result);
|
|
119
|
+
else if (result.customer.toString() == CUSTOMER_ID) return done(null, result);
|
|
120
|
+
else return done(null, null);
|
|
331
121
|
|
|
332
|
-
|
|
122
|
+
}
|
|
333
123
|
|
|
334
|
-
|
|
124
|
+
});
|
|
335
125
|
|
|
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
126
|
|
|
344
|
-
};
|
|
345
127
|
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
});
|
|
350
|
-
}
|
|
128
|
+
///////////////////////////////////////////////////////////////////////////////////////
|
|
129
|
+
// CONFIG
|
|
130
|
+
///////////////////////////////////////////////////////////////////////////////////////
|
|
351
131
|
|
|
352
132
|
Document.set('autoIndex', false);
|
|
353
133
|
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
|
|
package/lib/LimitedPartner.js
CHANGED
package/lib/Message.js
ADDED
|
@@ -0,0 +1,209 @@
|
|
|
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
|
+
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
///////////////////////////////////////
|
|
33
|
+
|
|
34
|
+
Message.statics.addDocument = function(messageId, doc, cb) {
|
|
35
|
+
|
|
36
|
+
Document.createForModel(doc, this, messageId, cb);
|
|
37
|
+
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
Message.statics.addNote = function(messageId, creatorPersonId, text, cb) {
|
|
41
|
+
|
|
42
|
+
Note.createForModel({
|
|
43
|
+
createdBy: creatorPersonId,
|
|
44
|
+
text: text
|
|
45
|
+
}, this, messageId, cb);
|
|
46
|
+
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
Message.statics.delete = function(messageId, customerId, cb) {
|
|
50
|
+
|
|
51
|
+
var self = this;
|
|
52
|
+
|
|
53
|
+
self.findOneAndRemove({
|
|
54
|
+
'_id': messageId,
|
|
55
|
+
'customer': customerId
|
|
56
|
+
}, cb);
|
|
57
|
+
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
Message.statics.deleteDocument = function(docId, cb) {
|
|
61
|
+
|
|
62
|
+
// Delete the doc itself along with any references
|
|
63
|
+
|
|
64
|
+
var self = this;
|
|
65
|
+
|
|
66
|
+
var removeReferences = function removeReferences(callback) {
|
|
67
|
+
self.update({}, {
|
|
68
|
+
$pull: { 'documents' : [docId] }
|
|
69
|
+
}, callback);
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
async.series([
|
|
73
|
+
Document.delete.bind(Document, docId),
|
|
74
|
+
removeReferences
|
|
75
|
+
], function(err, results) {
|
|
76
|
+
return cb(err, null);
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
Message.statics.deleteNote = function(noteId, cb) {
|
|
82
|
+
|
|
83
|
+
// Delete the note itself along with any references
|
|
84
|
+
|
|
85
|
+
var self = this;
|
|
86
|
+
|
|
87
|
+
var removeReferences = function removeReferences(callback) {
|
|
88
|
+
self.update({}, {
|
|
89
|
+
$pull: { 'notes' : [noteId] }
|
|
90
|
+
}, callback);
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
async.series([
|
|
94
|
+
Note.delete.bind(Note, noteId),
|
|
95
|
+
removeReferences
|
|
96
|
+
], function(err, results) {
|
|
97
|
+
return cb(err, null);
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
Message.statics.getDocuments = function getDocuments(personIds, options, cb) {
|
|
103
|
+
|
|
104
|
+
var self = this;
|
|
105
|
+
var query = self.find({ customer: config.CUSTOMER_ID });
|
|
106
|
+
|
|
107
|
+
query.where({'attendees.external': { $in : personIds }});
|
|
108
|
+
query.populate({
|
|
109
|
+
path: 'documents',
|
|
110
|
+
match: { customer: config.CUSTOMER_ID }
|
|
111
|
+
});
|
|
112
|
+
query.deepPopulate([
|
|
113
|
+
'documents.createdBy'
|
|
114
|
+
], {
|
|
115
|
+
populate: {
|
|
116
|
+
'documents.createdBy': { select: 'name avatarUrl title' }
|
|
117
|
+
}
|
|
118
|
+
});
|
|
119
|
+
query.exec(cb);
|
|
120
|
+
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
Message.statics.getForCustomer = function getForCustomer(customerId, cb) {
|
|
124
|
+
|
|
125
|
+
var self = this;
|
|
126
|
+
var query = self.find({ customer: customerId });
|
|
127
|
+
query.exec(cb);
|
|
128
|
+
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
Message.statics.getForPeople = function getForPeople(personIds, options, cb) {
|
|
132
|
+
|
|
133
|
+
// This filters by customer so is NOT usable by admin tools
|
|
134
|
+
if (config.CUSTOMER_ID == 'GLOBAL_PROCESS') return cb(new Error('Access denied. Use getForPeopleLite.'), null);
|
|
135
|
+
|
|
136
|
+
var self = this;
|
|
137
|
+
var query = self.find({ customer: config.CUSTOMER_ID });
|
|
138
|
+
|
|
139
|
+
query.where({'recipients.external': { $in : personIds }});
|
|
140
|
+
query.populate('recipients.internal', 'name title avatarUrl doNotDisplay');
|
|
141
|
+
query.populate('recipients.external', 'name title avatarUrl doNotDisplay');
|
|
142
|
+
query.populate({
|
|
143
|
+
path: 'notes',
|
|
144
|
+
match: { customer: config.CUSTOMER_ID }
|
|
145
|
+
});
|
|
146
|
+
query.populate({
|
|
147
|
+
path: 'documents',
|
|
148
|
+
match: { customer: config.CUSTOMER_ID }
|
|
149
|
+
});
|
|
150
|
+
query.deepPopulate([
|
|
151
|
+
'notes.createdBy',
|
|
152
|
+
'documents.createdBy'
|
|
153
|
+
], {
|
|
154
|
+
populate: {
|
|
155
|
+
'notes.createdBy': { select: 'name avatarUrl title' },
|
|
156
|
+
'documents.createdBy': { select: 'name avatarUrl title' }
|
|
157
|
+
}
|
|
158
|
+
});
|
|
159
|
+
query.exec(cb);
|
|
160
|
+
|
|
161
|
+
};
|
|
162
|
+
|
|
163
|
+
Message.statics.getForPeopleLite = function getForPeopleLite(personIds, cb) {
|
|
164
|
+
|
|
165
|
+
// This doesn't filter by customer so is only usable by admin tools
|
|
166
|
+
if (config.CUSTOMER_ID != 'GLOBAL_PROCESS') return cb(new Error('Access denied'), null);
|
|
167
|
+
|
|
168
|
+
var self = this;
|
|
169
|
+
var query = self.find({'recipients.external': { $in : personIds }});
|
|
170
|
+
query.exec(cb);
|
|
171
|
+
|
|
172
|
+
};
|
|
173
|
+
|
|
174
|
+
Message.statics.getNotes = function getNotes(personIds, options, cb) {
|
|
175
|
+
|
|
176
|
+
var self = this;
|
|
177
|
+
var query = self.find({ customer: config.CUSTOMER_ID });
|
|
178
|
+
|
|
179
|
+
query.where({'attendees.external': { $in : personIds }});
|
|
180
|
+
query.populate({
|
|
181
|
+
path: 'notes',
|
|
182
|
+
match: { customer: config.CUSTOMER_ID }
|
|
183
|
+
});
|
|
184
|
+
query.deepPopulate([
|
|
185
|
+
'notes.createdBy'
|
|
186
|
+
], {
|
|
187
|
+
populate: {
|
|
188
|
+
'notes.createdBy': { select: 'name avatarUrl title' }
|
|
189
|
+
}
|
|
190
|
+
});
|
|
191
|
+
query.exec(cb);
|
|
192
|
+
|
|
193
|
+
};
|
|
194
|
+
|
|
195
|
+
Message.statics.upsert = function(message, cb) {
|
|
196
|
+
message.createdOn = new Date();
|
|
197
|
+
message.save(cb);
|
|
198
|
+
};
|
|
199
|
+
|
|
200
|
+
///////////////////////////////////////
|
|
201
|
+
|
|
202
|
+
Message.set('autoIndex', false);
|
|
203
|
+
|
|
204
|
+
var deepPopulate = require('mongoose-deep-populate')(mongoose);
|
|
205
|
+
Message.plugin(deepPopulate);
|
|
206
|
+
|
|
207
|
+
mongoose.model('Message', Message);
|
|
208
|
+
|
|
209
|
+
};
|