Merge pull request #1 from shackbarth/keith1
[xtuple] / enyo-client / application / source / models / incident.js
1 /*jshint indent:2, curly:true, eqeqeq:true, immed:true, latedef:true,
2 newcap:true, noarg:true, regexp:true, undef:true, strict:true, trailing:true,
3 white:true*/
4 /*global Globalize:true, XT:true, XM:true, Backbone:true, _:true, console:true */
5
6 (function () {
7   "use strict";
8
9   /**
10     @class
11
12     @extends XM.Document
13   */
14   XM.IncidentCategory = XM.Document.extend({
15     /** @scope XM.IncidentCategory.prototype */
16
17     recordType: 'XM.IncidentCategory',
18
19     documentKey: 'name',
20
21     enforceUpperKey: false,
22
23     defaults: {
24       order: 0
25     },
26
27     orderAttribute: {
28       orderBy: [{
29         attribute: "order"
30       }]
31     }
32
33   });
34
35   /**
36     @class
37
38     @extends XM.Document
39   */
40   XM.IncidentSeverity = XM.Document.extend({
41     /** @scope XM.IncidentSeverity.prototype */
42
43     recordType: 'XM.IncidentSeverity',
44
45     documentKey: 'name',
46
47     enforceUpperKey: false,
48
49     defaults: {
50       order: 0
51     },
52
53     orderAttribute: {
54       orderBy: [{
55         attribute: "order"
56       }]
57     }
58   });
59
60   /**
61     @class
62
63     @extends XM.Model
64   */
65   XM.IncidentResolution = XM.Document.extend({
66     /** @scope XM.IncidentResolution.prototype */
67
68     recordType: 'XM.IncidentResolution',
69
70     documentKey: 'name',
71
72     enforceUpperKey: false,
73
74     defaults: {
75       order: 0
76     },
77
78     orderAttribute: {
79       orderBy: [{
80         attribute: "order"
81       }]
82     }
83
84   });
85
86   /**
87     @namespace
88
89     A mixin shared by incident models that share common incident status
90     functionality.
91   */
92   XM.IncidentStatus = {
93     /** @scope XM.IncidentStatus */
94
95     /**
96     Returns incident status as a localized string.
97
98     @returns {String}
99     */
100     getIncidentStatusString: function () {
101       var K = XM.Incident,
102         status = this.get('status');
103       if (status === K.NEW) {
104         return '_new'.loc();
105       }
106       if (status === K.FEEDBACK) {
107         return '_feedback'.loc();
108       }
109       if (status === K.CONFIRMED) {
110         return '_confirmed'.loc();
111       }
112       if (status === K.ASSIGNED) {
113         return '_assigned'.loc();
114       }
115       if (status === K.RESOLVED) {
116         return '_resolved'.loc();
117       }
118       if (status === K.CLOSED) {
119         return '_closed'.loc();
120       }
121     },
122
123     isActive: function () {
124       var K = XM.Incident,
125         status = this.get('status');
126       return (status !== K.CLOSED);
127     }
128
129   };
130
131   /**
132     @class
133
134     @extends XM.Document
135   */
136   XM.Incident = XM.Document.extend({
137     /** @scope XM.Incident.prototype */
138
139     recordType: 'XM.Incident',
140
141     nameAttribute: "number",
142
143     numberPolicy: XM.Document.AUTO_NUMBER,
144
145     defaults: function () {
146       return {
147         owner: XM.currentUser,
148         status: XM.Incident.NEW,
149         isPublic: XT.session.getSettings().get("IncidentPublicDefault"),
150         created: new Date()
151       };
152     },
153
154     // ..........................................................
155     // METHODS
156     //
157
158     bindEvents: function () {
159       XM.Document.prototype.bindEvents.apply(this, arguments);
160       this.on('change:assignedTo', this.assignedToDidChange);
161     },
162
163     assignedToDidChange: function (model, value, options) {
164       if (value && this.get("status") !== XM.Incident.RESOLVED && this.get("status") !== XM.Incident.CLOSED) {
165         this.set('status', XM.Incident.ASSIGNED);
166       }
167     },
168
169     validate: function () {
170       var K = XM.Incident;
171       if (this.get('status') === K.ASSIGNED && !this.get('assignedTo')) {
172         return XT.Error.clone('xt2001');
173       }
174       return XM.Document.prototype.validate.apply(this, arguments);
175     }
176
177   });
178
179   // Add support for sending email
180   XM.Incident = XM.Incident.extend(XM.EmailSendMixin);
181   XM.Incident = XM.Incident.extend({
182     emailDocumentName: "_incident".loc(),
183     emailProfileAttribute: "category.emailProfile",
184     emailStatusMethod: "getIncidentStatusString"
185   });
186
187   _.extend(XM.Incident, {
188     /** @scope XM.Incident */
189
190     /**
191       New status.
192
193       @static
194       @constant
195       @type String
196       @default N
197     */
198     NEW: 'N',
199
200     /**
201       Feedback status.
202
203       @static
204       @constant
205       @type String
206       @default F
207     */
208     FEEDBACK: 'F',
209
210     /**
211       Confirmed Status.
212
213       @static
214       @constant
215       @type String
216       @default I
217     */
218     CONFIRMED: 'C',
219
220     /**
221       Assigned status.
222
223       @static
224       @constant
225       @type String
226       @default A
227     */
228     ASSIGNED: 'A',
229
230     /**
231       Resolved status.
232
233       @static
234       @constant
235       @type String
236       @default R
237     */
238     RESOLVED: 'R',
239
240     /**
241       Closed status.
242
243       @static
244       @constant
245       @type String
246       @default L
247     */
248     CLOSED: 'L'
249
250   });
251
252   // Incident status mixin
253   XM.Incident = XM.Incident.extend(XM.IncidentStatus);
254
255   // email-relevant mixin
256   XM.Incident = XM.Incident.extend({
257
258     getHistoryString: function () {
259       var history = this.get('history'),
260         ret = "",
261         isFirst = true;
262       if (history.length) {
263         // Sort by date ascending
264         history.comparator = function (a, b) {
265           var aval = a.get('created'),
266             bval = b.get('created');
267           return XT.date.compare(aval, bval);
268         };
269         history.sort();
270         _.each(history.models, function (model) {
271           var offset = (new Date()).getTimezoneOffset(), // hack: the data should include timezone
272             created = new Date(model.get('created').getTime() + offset * 60 * 1000),
273             fdate = Globalize.format(created, "d"),
274             ftime = Globalize.format(created, "t");
275           if (!isFirst) { ret += "\n"; }
276           isFirst = false;
277           ret += (fdate + ' ' + ftime).rightPad(' ', 24);
278           ret += model.get('createdBy').slice(0, 17).rightPad(' ', 18);
279           ret += model.get('description');
280         });
281       }
282       return ret;
283     }
284   });
285
286   /**
287     @class
288
289     @extends XM.Comment
290   */
291   XM.IncidentComment = XM.Comment.extend({
292     /** @scope XM.IncidentComment.prototype */
293
294     recordType: 'XM.IncidentComment',
295
296     sourceName: 'INCDT',
297
298     defaults: function () {
299       var result = XM.Comment.prototype.defaults.apply(this, arguments),
300         publicDefault = XT.session.getSettings().get('IncidentPublicDefault');
301
302       result.isPublic = publicDefault || false;
303       return result;
304     }
305
306   });
307
308   /**
309     @class
310
311     @extends XM.Characteristic
312   */
313   XM.IncidentCharacteristic = XM.CharacteristicAssignment.extend({
314     /** @scope XM.IncidentCharacteristic.prototype */
315
316     recordType: 'XM.IncidentCharacteristic',
317
318     which: 'isIncidents'
319
320   });
321
322   /**
323     @class
324
325     @extends XM.Alarm
326   */
327   XM.IncidentAlarm = XM.Alarm.extend({
328     /** @scope XM.IncidentAlarm.prototype */
329
330     recordType: 'XM.IncidentAlarm'
331
332   });
333
334   /**
335     @class
336
337     @extends XM.Model
338   */
339   XM.IncidentHistory = XM.Model.extend({
340     /** @scope XM.IncidentAccount.prototype */
341
342     recordType: 'XM.IncidentHistory'
343
344   });
345
346   /**
347     @class
348
349     @extends XM.Model
350   */
351   XM.IncidentAccount = XM.Model.extend({
352     /** @scope XM.IncidentAccount.prototype */
353
354     recordType: 'XM.IncidentAccount',
355
356     isDocumentAssignment: true
357
358   });
359
360   /**
361     @class
362
363     @extends XM.Model
364   */
365   XM.IncidentContact = XM.Model.extend({
366     /** @scope XM.IncidentContact.prototype */
367
368     recordType: 'XM.IncidentContact',
369
370     isDocumentAssignment: true
371
372   });
373
374   /**
375     @class
376
377     @extends XM.Model
378   */
379   XM.IncidentItem = XM.Model.extend({
380     /** @scope XM.IncidentItem.prototype */
381
382     recordType: 'XM.IncidentItem',
383
384     isDocumentAssignment: true
385
386   });
387
388   /**
389     @class
390
391     @extends XM.Model
392   */
393   XM.IncidentFile = XM.Model.extend({
394     /** @scope XM.IncidentFile.prototype */
395
396     recordType: 'XM.IncidentFile',
397
398     isDocumentAssignment: true
399
400   });
401
402   /**
403     @class
404
405     @extends XM.Model
406   */
407   XM.IncidentUrl = XM.Model.extend({
408     /** @scope XM.IncidentUrl.prototype */
409
410     recordType: 'XM.IncidentUrl',
411
412     isDocumentAssignment: true
413
414   });
415
416   /**
417     @class
418
419     @extends XM.Model
420   */
421   XM.IncidentIncident = XM.Model.extend({
422     /** @scope XM.IncidentIncident.prototype */
423
424     recordType: 'XM.IncidentIncident',
425
426     isDocumentAssignment: true
427
428   });
429
430   /**
431     @class
432
433     @extends XM.Model
434   */
435   XM.IncidentRecurrence = XM.Model.extend({
436     /** @scope XM.IncidentRecurrence.prototype */
437
438     recordType: 'XM.IncidentRecurrence'
439
440   });
441
442   /**
443     @class
444
445     @extends XM.Info
446   */
447   XM.IncidentRelation = XM.Info.extend({
448     /** @scope XM.IncidentRelation.prototype */
449
450     recordType: 'XM.IncidentRelation',
451
452     editableModel: 'XM.Incident'
453
454   });
455
456   // Incident status mixin
457   XM.IncidentRelation = XM.IncidentRelation.extend(XM.IncidentStatus);
458
459   /**
460     @class
461
462     @extends XM.Info
463   */
464   XM.IncidentListItem = XM.Info.extend({
465     /** @scope XM.IncidentListItem.prototype */
466
467     recordType: 'XM.IncidentListItem',
468
469     editableModel: 'XM.Incident'
470
471   });
472
473   /**
474     @class
475
476     @extends XM.Model
477   */
478   XM.IncidentListItemCharacteristic = XM.Model.extend({
479     /** @scope XM.IncidentListItemCharacteristic.prototype */
480
481     recordType: 'XM.IncidentListItemCharacteristic'
482
483   });
484
485   // Incident status mixin
486   XM.IncidentListItem = XM.IncidentListItem.extend(XM.IncidentStatus);
487
488   /**
489     @class
490
491     @extends XM.Document
492   */
493   XM.IncidentEmailProfile = XM.Document.extend(
494     /** @scope XM.IncidentEmailProfile.prototype */ {
495
496     recordType: 'XM.IncidentEmailProfile',
497
498     documentKey: 'name'
499
500   });
501
502   // ..........................................................
503   // COLLECTIONS
504   //
505
506   /**
507     @class
508
509     @extends XM.Collection
510   */
511   XM.IncidentCategoryCollection = XM.Collection.extend({
512     /** @scope XM.IncidentCategoryCollection.prototype */
513
514     model: XM.IncidentCategory
515
516   });
517
518   /**
519     @class
520
521     @extends XM.Collection
522   */
523   XM.IncidentSeverityCollection = XM.Collection.extend({
524     /** @scope XM.IncidentSeverityCollection.prototype */
525
526     model: XM.IncidentSeverity
527
528   });
529
530   /**
531     @class
532
533     @extends XM.Collection
534   */
535   XM.IncidentResolutionCollection = XM.Collection.extend({
536     /** @scope XM.IncidentResolutionCollection.prototype */
537
538     model: XM.IncidentResolution
539
540   });
541
542   /**
543     @class
544
545     @extends XM.Collection
546   */
547   XM.IncidentListItemCollection = XM.Collection.extend({
548     /** @scope XM.IncidentListItemCollection.prototype */
549
550     model: XM.IncidentListItem
551
552   });
553
554   /**
555     @class
556
557     @extends XM.Collection
558   */
559   XM.IncidentRelationCollection = XM.Collection.extend({
560     /** @scope XM.IncidentRelationCollection.prototype */
561
562     model: XM.IncidentRelation
563
564   });
565
566   /**
567     @class
568
569     @extends XM.Collection
570   */
571   XM.IncidentEmailProfileCollection = XM.Collection.extend({
572     /** @scope XM.IncidentEmailProfileCollection.prototype */
573
574     model: XM.IncidentEmailProfile
575
576   });
577 }());
578