tabletcommand-incident 0.4.16 → 0.5.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/build/domain.js +7 -8
- package/build/domain.js.map +1 -1
- package/build/incidentProcessor.js +15 -12
- package/build/incidentProcessor.js.map +1 -1
- package/build/ruleProcessorLegacy.js +1 -1
- package/build/ruleProcessorLegacy.js.map +1 -1
- package/build/rules/clean-up-comments.js.map +1 -1
- package/build/rules/close-incident-after-hours.js.map +1 -1
- package/build/rules/close-incident-matching-incident-number.js.map +1 -1
- package/build/rules/close-incident-of-certain-type.js.map +1 -1
- package/build/rules/copy-incident-number.js.map +1 -1
- package/build/rules/copy-location-comment.js.map +1 -1
- package/build/rules/index.js +2 -2
- package/build/rules/index.js.map +1 -1
- package/build/rules/map-unit-dates-verdugo.js.map +1 -1
- package/build/rules/remove-person-from-unit.js.map +1 -1
- package/build/rules/set-address.js.map +1 -1
- package/build/rules/set-communication-channels-from-radio-names.js.map +1 -1
- package/build/rules/set-fire-alarm-at-dispatch-from-alarm-level.js.map +1 -1
- package/build/rules/set-fire-map-from-map-pages-southern-marin.js.map +1 -1
- package/build/rules/set-format-units-pulsepoint.js.map +1 -1
- package/build/store.js +10 -4
- package/build/store.js.map +1 -1
- package/build/test/domain.js.map +1 -1
- package/build/test/index.js +20 -21
- package/build/test/index.js.map +1 -1
- package/build/test/mock.js +34 -33
- package/build/test/mock.js.map +1 -1
- package/build/test/rules/map-unit-dates-verdugo.js.map +1 -1
- package/build/test/rules/remove-person-from-unit.js.map +1 -1
- package/build/test/rules/set-format-units-pulsepoint.js.map +1 -1
- package/definitions/domain.d.ts +5 -5
- package/definitions/domain.d.ts.map +1 -1
- package/definitions/incidentProcessor.d.ts.map +1 -1
- package/definitions/rules/clean-up-comments.d.ts +2 -2
- package/definitions/rules/clean-up-comments.d.ts.map +1 -1
- package/definitions/rules/close-incident-matching-incident-number.d.ts.map +1 -1
- package/definitions/rules/copy-incident-number.d.ts.map +1 -1
- package/definitions/rules/copy-location-comment.d.ts.map +1 -1
- package/definitions/rules/index.d.ts.map +1 -1
- package/definitions/rules/map-unit-dates-verdugo.d.ts.map +1 -1
- package/definitions/rules/remove-person-from-unit.d.ts +2 -2
- package/definitions/rules/remove-person-from-unit.d.ts.map +1 -1
- package/definitions/rules/set-address.d.ts.map +1 -1
- package/definitions/rules/set-communication-channels-from-radio-names.d.ts.map +1 -1
- package/definitions/rules/set-format-units-pulsepoint.d.ts.map +1 -1
- package/definitions/store.d.ts +33 -1
- package/definitions/store.d.ts.map +1 -1
- package/definitions/test/mock.d.ts.map +1 -1
- package/definitions/test/rules/map-unit-dates-verdugo.d.ts.map +1 -1
- package/definitions/types.d.ts +0 -40
- package/definitions/types.d.ts.map +1 -1
- package/package.json +2 -5
- package/src/domain.ts +30 -38
- package/src/incidentProcessor.ts +9 -10
- package/src/ruleProcessorLegacy.js +1 -1
- package/src/rules/clean-up-comments.ts +9 -9
- package/src/rules/close-incident-after-hours.ts +1 -1
- package/src/rules/close-incident-matching-incident-number.ts +3 -3
- package/src/rules/close-incident-of-certain-type.ts +1 -1
- package/src/rules/copy-incident-number.ts +2 -2
- package/src/rules/copy-location-comment.ts +3 -3
- package/src/rules/index.ts +1 -2
- package/src/rules/map-unit-dates-verdugo.ts +3 -3
- package/src/rules/remove-person-from-unit.ts +6 -5
- package/src/rules/set-address.ts +4 -4
- package/src/rules/set-communication-channels-from-radio-names.ts +2 -2
- package/src/rules/set-fire-alarm-at-dispatch-from-alarm-level.ts +4 -4
- package/src/rules/set-fire-map-from-map-pages-southern-marin.ts +3 -3
- package/src/rules/set-format-units-pulsepoint.ts +4 -4
- package/src/store.ts +16 -10
- package/src/test/domain.ts +17 -17
- package/src/test/index.ts +23 -26
- package/src/test/mock.ts +34 -33
- package/src/test/rules/map-unit-dates-verdugo.ts +2 -2
- package/src/test/rules/remove-person-from-unit.ts +2 -2
- package/src/test/rules/set-format-units-pulsepoint.ts +3 -3
- package/src/types.ts +0 -51
package/src/domain.ts
CHANGED
|
@@ -8,22 +8,16 @@ import {
|
|
|
8
8
|
PersonnelImport,
|
|
9
9
|
} from "tabletcommand-backend-models";
|
|
10
10
|
|
|
11
|
-
import mongoose from "mongoose";
|
|
12
|
-
|
|
13
11
|
const debug = debug_module("tabletcommand-incident:domain");
|
|
14
12
|
|
|
15
13
|
import { promisify } from "util";
|
|
16
14
|
|
|
17
15
|
const sleep = promisify(setTimeout);
|
|
18
16
|
|
|
19
|
-
import {
|
|
20
|
-
|
|
21
|
-
CADPerson,
|
|
22
|
-
CADRadioChannel,
|
|
23
|
-
CADUnit,
|
|
24
|
-
} from "./types";
|
|
17
|
+
import { CADPersonSchemaType, RadioChannelSchemaType } from "tabletcommand-backend-models/definitions/types/shared-incident";
|
|
18
|
+
import { CADCommentType, CADUnitType } from "tabletcommand-backend-models/definitions/types/cad-incident";
|
|
25
19
|
|
|
26
|
-
function uniquePersonnel(personnel: Partial<
|
|
20
|
+
function uniquePersonnel(personnel: Partial<CADPersonSchemaType>[], person: Partial<CADPersonSchemaType>) {
|
|
27
21
|
if (!_.isArray(personnel)) {
|
|
28
22
|
return personnel;
|
|
29
23
|
}
|
|
@@ -39,11 +33,11 @@ function uniquePersonnel(personnel: Partial<CADPerson>[], person: Partial<CADPer
|
|
|
39
33
|
}
|
|
40
34
|
return shouldAddItem;
|
|
41
35
|
});
|
|
42
|
-
return filtered as
|
|
36
|
+
return filtered as CADPersonSchemaType[]; // Temporarily from Partial<>[]
|
|
43
37
|
}
|
|
44
38
|
|
|
45
|
-
function mergePersonnel(units:
|
|
46
|
-
let mappedUnits:
|
|
39
|
+
function mergePersonnel(units: CADUnitType[], personnel: Partial<PersonnelImport>[], time: number): CADUnitType[] {
|
|
40
|
+
let mappedUnits: CADUnitType[] = [];
|
|
47
41
|
if (_.isArray(units)) {
|
|
48
42
|
mappedUnits = _.map(units, function(item) {
|
|
49
43
|
if (!_.isArray(item.Personnel)) {
|
|
@@ -54,7 +48,7 @@ function mergePersonnel(units: CADUnit[], personnel: Partial<PersonnelImport>[],
|
|
|
54
48
|
});
|
|
55
49
|
}
|
|
56
50
|
|
|
57
|
-
const unitMap: Record<string,
|
|
51
|
+
const unitMap: Record<string, CADUnitType[]> = {};
|
|
58
52
|
const unitIDs: string[] = [];
|
|
59
53
|
const unitUniqueMap = _.keyBy(mappedUnits, (unit) => {
|
|
60
54
|
return unit.UnitID + unit.UnitDispatchNumber;
|
|
@@ -114,7 +108,7 @@ function mergePersonnel(units: CADUnit[], personnel: Partial<PersonnelImport>[],
|
|
|
114
108
|
});
|
|
115
109
|
});
|
|
116
110
|
const unitArrayValues = _.values(unitMap);
|
|
117
|
-
const revisedUnits:
|
|
111
|
+
const revisedUnits: CADUnitType[] = ([] as CADUnitType[]).concat(...unitArrayValues);
|
|
118
112
|
return revisedUnits;
|
|
119
113
|
}
|
|
120
114
|
|
|
@@ -123,7 +117,7 @@ function ignoreCheck(incident: Partial<CADIncident>) {
|
|
|
123
117
|
return result;
|
|
124
118
|
}
|
|
125
119
|
|
|
126
|
-
function radioNames(units: Partial<
|
|
120
|
+
function radioNames(units: Partial<CADUnitType>[]): string[] {
|
|
127
121
|
const radioNames: string[] = [];
|
|
128
122
|
if (!_.isArray(units)) {
|
|
129
123
|
return radioNames;
|
|
@@ -186,15 +180,15 @@ function mergeIncidentsV3(nextUpdates: Partial<CADIncident>[], previous: Partial
|
|
|
186
180
|
}
|
|
187
181
|
|
|
188
182
|
if (key === "units") {
|
|
189
|
-
const subItems = _.flatten([accItems as
|
|
183
|
+
const subItems = _.flatten([accItems as CADUnitType[], valueItems as CADUnitType[]]);
|
|
190
184
|
acc[key] = mergeUnitsV3(subItems);
|
|
191
185
|
} else if (key === "Comment") {
|
|
192
|
-
const unionCommentItems = _.union(accItems as
|
|
186
|
+
const unionCommentItems = _.union(accItems as CADCommentType[], valueItems as CADCommentType[]);
|
|
193
187
|
acc[key] = mergeCommentsV3(unionCommentItems);
|
|
194
188
|
} else if (key === "PriorIncident") { // Handled already
|
|
195
189
|
} else if (key === "radioChannels") {
|
|
196
190
|
// overwrite radioChannels with latest update always
|
|
197
|
-
acc[key] = valueItems as
|
|
191
|
+
acc[key] = valueItems as RadioChannelSchemaType[];
|
|
198
192
|
} else {
|
|
199
193
|
// Handles other array types, like notifications
|
|
200
194
|
const unionItems = _.union(accItems as Record<string, unknown>[], valueItems as Record<string, unknown>[]);
|
|
@@ -223,7 +217,7 @@ function mergeIncidentsV3(nextUpdates: Partial<CADIncident>[], previous: Partial
|
|
|
223
217
|
return itemCopy;
|
|
224
218
|
}
|
|
225
219
|
|
|
226
|
-
function mergeUnitsV3(items:
|
|
220
|
+
function mergeUnitsV3(items: CADUnitType[]): CADUnitType[] {
|
|
227
221
|
if (!_.isArray(items) || _.size(items) === 0) {
|
|
228
222
|
return [];
|
|
229
223
|
}
|
|
@@ -233,7 +227,7 @@ function mergeUnitsV3(items: CADUnit[]): CADUnit[] {
|
|
|
233
227
|
(_.isString(item.UnitID) || _.isNumber(item.UnitID));
|
|
234
228
|
});
|
|
235
229
|
|
|
236
|
-
const mapAcc: Record<string,
|
|
230
|
+
const mapAcc: Record<string, CADUnitType> = {};
|
|
237
231
|
const itemsMap = _.reduce(filteredItems, function(memo, item) {
|
|
238
232
|
const key = `${item.UnitID}-${item.UnitDispatchNumber}`;
|
|
239
233
|
if (!_.has(memo, key)) {
|
|
@@ -252,7 +246,7 @@ function mergeUnitsV3(items: CADUnit[]): CADUnit[] {
|
|
|
252
246
|
return _.values(itemsMap);
|
|
253
247
|
}
|
|
254
248
|
|
|
255
|
-
function mergeCommentsV3(items:
|
|
249
|
+
function mergeCommentsV3(items: CADCommentType[]) {
|
|
256
250
|
// Keys defined in models
|
|
257
251
|
const allowedCommentKeys = [
|
|
258
252
|
"Comment",
|
|
@@ -261,7 +255,7 @@ function mergeCommentsV3(items: CADComment[]) {
|
|
|
261
255
|
"CommentSource",
|
|
262
256
|
];
|
|
263
257
|
debug(`mergeComments: ${JSON.stringify(items)}`);
|
|
264
|
-
function ourComment(c: Partial<
|
|
258
|
+
function ourComment(c: Partial<CADCommentType>) {
|
|
265
259
|
return _.isString(c.CommentSource) && _.trim(c.CommentSource) === "TC";
|
|
266
260
|
}
|
|
267
261
|
|
|
@@ -324,8 +318,9 @@ function enforceMandatoryFields(incidentIn: Partial<CADIncident>): Partial<CADIn
|
|
|
324
318
|
} else if (_.isString(incident.expiration_date) && moment(incident.expiration_date, true).isValid()) {
|
|
325
319
|
resolvedExpirationDate = moment(incident.expiration_date, true).toDate();
|
|
326
320
|
}
|
|
327
|
-
|
|
328
|
-
|
|
321
|
+
if (_.isDate(resolvedExpirationDate)) {
|
|
322
|
+
incident.expiration_date = resolvedExpirationDate;
|
|
323
|
+
}
|
|
329
324
|
// Set default simulation/notify/rts fields
|
|
330
325
|
if (!_.isBoolean(incident.simulation)) {
|
|
331
326
|
incident.simulation = false;
|
|
@@ -364,19 +359,16 @@ function updateWithUUIDAndDepartment(itemIn: Partial<CADIncident>, department: P
|
|
|
364
359
|
}
|
|
365
360
|
|
|
366
361
|
if (!_.isString(item.departmentId) || item.departmentId === "") {
|
|
367
|
-
item.departmentId =
|
|
362
|
+
item.departmentId = department._id?.toString();
|
|
368
363
|
item.sharedSource = {
|
|
369
364
|
name: department.department ?? "",
|
|
370
365
|
isExternal: false,
|
|
371
366
|
reasons: [],
|
|
372
|
-
// Currently unused, present to silence Typescript
|
|
373
|
-
startAt: "",
|
|
374
|
-
expireAt: "",
|
|
375
367
|
};
|
|
376
368
|
}
|
|
377
369
|
|
|
378
370
|
// Always update modified_date
|
|
379
|
-
item.modified = atDate
|
|
371
|
+
item.modified = atDate;
|
|
380
372
|
item.modified_date = moment(atDate).utc().format("YYYY-MM-DDTHH:mm:ss.SSS");
|
|
381
373
|
item.modified_unix_date = atDate.valueOf() / 1000.0;
|
|
382
374
|
|
|
@@ -394,12 +386,12 @@ function mergeIncidentsV1(current: Partial<CADIncident>, previous: Partial<CADIn
|
|
|
394
386
|
const item: Partial<CADIncident> = _.reduce(items, function(acc, other) {
|
|
395
387
|
// Rename "Unit" key to "units"
|
|
396
388
|
if (_.has(acc, "Unit") && _.isArray(acc.Unit)) {
|
|
397
|
-
acc.units = _.clone(acc.Unit) as
|
|
389
|
+
acc.units = _.clone(acc.Unit) as CADUnitType[];
|
|
398
390
|
delete acc.Unit;
|
|
399
391
|
}
|
|
400
392
|
|
|
401
393
|
if (_.has(other, "Unit") && _.isArray(other.Unit)) {
|
|
402
|
-
other.units = _.clone(other.Unit) as
|
|
394
|
+
other.units = _.clone(other.Unit) as CADUnitType[];
|
|
403
395
|
delete other.Unit;
|
|
404
396
|
}
|
|
405
397
|
|
|
@@ -430,15 +422,15 @@ function mergeIncidentsV1(current: Partial<CADIncident>, previous: Partial<CADIn
|
|
|
430
422
|
}
|
|
431
423
|
|
|
432
424
|
if (key === "units") {
|
|
433
|
-
const subItems = _.flatten([accItems as
|
|
425
|
+
const subItems = _.flatten([accItems as CADUnitType[], valueItems as CADUnitType[]]);
|
|
434
426
|
acc[key] = mergeUnitsV1(subItems);
|
|
435
427
|
} else if (key === "Comment") {
|
|
436
|
-
const unionCommentItems = _.union(accItems as
|
|
428
|
+
const unionCommentItems = _.union(accItems as CADCommentType[], valueItems as CADCommentType[]);
|
|
437
429
|
acc[key] = mergeCommentsV1(unionCommentItems);
|
|
438
430
|
} else if (key === "PriorIncident") { // Handled already
|
|
439
431
|
} else if (key === "radioChannels") {
|
|
440
432
|
// overwrite radioChannels with latest update always
|
|
441
|
-
acc[key] = valueItems as
|
|
433
|
+
acc[key] = valueItems as RadioChannelSchemaType[];
|
|
442
434
|
} else if (key === "simulationSequences") {
|
|
443
435
|
// overwrite simulationSequences with latest update always
|
|
444
436
|
acc[key] = valueItems as number[];
|
|
@@ -467,7 +459,7 @@ function mergeIncidentsV1(current: Partial<CADIncident>, previous: Partial<CADIn
|
|
|
467
459
|
return itemCopy;
|
|
468
460
|
}
|
|
469
461
|
|
|
470
|
-
function mergeUnitsV1(items:
|
|
462
|
+
function mergeUnitsV1(items: CADUnitType[]): CADUnitType[] {
|
|
471
463
|
if (!_.isArray(items) || _.size(items) === 0) {
|
|
472
464
|
return [];
|
|
473
465
|
}
|
|
@@ -490,12 +482,12 @@ function mergeUnitsV1(items: CADUnit[]): CADUnit[] {
|
|
|
490
482
|
}
|
|
491
483
|
|
|
492
484
|
return memo;
|
|
493
|
-
}, {} as Record<string,
|
|
485
|
+
}, {} as Record<string, CADUnitType>);
|
|
494
486
|
|
|
495
487
|
return _.values(itemsMap);
|
|
496
488
|
}
|
|
497
489
|
|
|
498
|
-
function mergeCommentsV1(items:
|
|
490
|
+
function mergeCommentsV1(items: CADCommentType[]) {
|
|
499
491
|
// Keys defined in models
|
|
500
492
|
const allowedCommentKeys = [
|
|
501
493
|
"Comment",
|
|
@@ -504,7 +496,7 @@ function mergeCommentsV1(items: CADComment[]) {
|
|
|
504
496
|
"CommentSource",
|
|
505
497
|
];
|
|
506
498
|
debug(`mergeComments: ${JSON.stringify(items)}`);
|
|
507
|
-
function ourComment(c: Partial<
|
|
499
|
+
function ourComment(c: Partial<CADCommentType>) {
|
|
508
500
|
return _.isString(c.CommentSource) && _.trim(c.CommentSource) === "TC";
|
|
509
501
|
}
|
|
510
502
|
|
package/src/incidentProcessor.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import debug_module from "debug";
|
|
2
2
|
import _ from "lodash";
|
|
3
|
-
import mongoose from "mongoose";
|
|
4
3
|
|
|
5
4
|
import * as Sentry from "@sentry/node";
|
|
6
5
|
|
|
@@ -52,7 +51,7 @@ export default function incidentProcessorLib({
|
|
|
52
51
|
}
|
|
53
52
|
|
|
54
53
|
async function handleProcessIncidentRequestLegacy(streamItem: CADIncidentStream, department: Partial<Department>, atDate: Date): Promise<HandleProcessIncidentRequestResult> {
|
|
55
|
-
const departmentId: string =
|
|
54
|
+
const departmentId: string = department._id?.toString() ?? "";
|
|
56
55
|
const incident = _.cloneDeep(streamItem.payload) as Partial<CADIncident>;
|
|
57
56
|
const incidentTypes = department.incidentTypes || [];
|
|
58
57
|
|
|
@@ -111,7 +110,7 @@ export default function incidentProcessorLib({
|
|
|
111
110
|
}
|
|
112
111
|
|
|
113
112
|
async function handleProcessIncidentRequestCorrection(incidentNumber: string, department: Partial<Department>, atDate: Date): Promise<HandleProcessIncidentRequestResult> {
|
|
114
|
-
const departmentId: string =
|
|
113
|
+
const departmentId: string = department._id?.toString() ?? "";
|
|
115
114
|
// Attempt to fix race condition where
|
|
116
115
|
const randomSeconds = Math.random() * 10 * 1000; // Between ~0 and ~9 seconds
|
|
117
116
|
const streamDate = new Date(atDate.valueOf() + randomSeconds);
|
|
@@ -132,13 +131,13 @@ export default function incidentProcessorLib({
|
|
|
132
131
|
}
|
|
133
132
|
|
|
134
133
|
async function processIncidentRequestsV3(streamItems: CADIncidentStream[], department: Partial<Department>, atDate: Date, attemptsLeft = 7): Promise<{ error: Error } | { incident: CADIncident | null }> {
|
|
135
|
-
const departmentId: string =
|
|
134
|
+
const departmentId: string = department._id?.toString() ?? "";
|
|
136
135
|
const incidentTypes = department.incidentTypes || [];
|
|
137
136
|
|
|
138
137
|
let result: { error: Error } | { incident: CADIncident | null } = { incident: null };
|
|
139
138
|
|
|
140
139
|
const streamItemsText = streamItems.map((x: CADIncidentStream) => {
|
|
141
|
-
return `${(x._id
|
|
140
|
+
return `${(x._id).toString()}: ${x.incidentNumber}`;
|
|
142
141
|
}).join(", ");
|
|
143
142
|
|
|
144
143
|
if (attemptsLeft === 0) {
|
|
@@ -185,13 +184,13 @@ export default function incidentProcessorLib({
|
|
|
185
184
|
|
|
186
185
|
// Append Personnel
|
|
187
186
|
const mergedItemWithPersonnel = await applyPersonnel(departmentId, mergedItemWithDept, atDate);
|
|
188
|
-
|
|
187
|
+
const mergedItemWithPersonnelModel = await store.convertItemWithPersonnelToModel(mergedItemWithPersonnel);
|
|
189
188
|
await artificialDelay?.afterApplyPersonnel?.();
|
|
190
189
|
|
|
191
190
|
try {
|
|
192
191
|
// as CADIncident to silence Partial<> messing with .validate()
|
|
193
192
|
debug("CADIncident.validate()");
|
|
194
|
-
await
|
|
193
|
+
await mergedItemWithPersonnelModel.validate();
|
|
195
194
|
} catch (error: unknown) {
|
|
196
195
|
return {
|
|
197
196
|
error: error as Error,
|
|
@@ -201,14 +200,14 @@ export default function incidentProcessorLib({
|
|
|
201
200
|
try {
|
|
202
201
|
debug("CADIncident.save()");
|
|
203
202
|
// as CADIncident to silence Partial<> messing with .save()
|
|
204
|
-
await
|
|
203
|
+
await mergedItemWithPersonnelModel.save();
|
|
205
204
|
result = {
|
|
206
|
-
incident:
|
|
205
|
+
incident: mergedItemWithPersonnelModel,
|
|
207
206
|
};
|
|
208
207
|
} catch (error: unknown) {
|
|
209
208
|
// Sleep between 50 and 800 ms, Necessary mostly for running parallel tests
|
|
210
209
|
const randomSleepMS = Math.random() * (800 - 50) + 50;
|
|
211
|
-
console.log(`retry after w/${randomSleepMS}ms... ${department.department} ${
|
|
210
|
+
console.log(`retry after w/${randomSleepMS}ms... ${department.department} ${mergedItemWithPersonnelModel.departmentId} ${mergedItemWithPersonnelModel.IncidentNumber} v${mergedItemWithPersonnelModel.__v}`);
|
|
212
211
|
await domain.sleep(randomSleepMS);
|
|
213
212
|
|
|
214
213
|
// Most of the times, this happens when trying to insert a document with the same unique key
|
|
@@ -3,11 +3,11 @@ import moment from "moment-timezone";
|
|
|
3
3
|
|
|
4
4
|
import { CADIncident } from "tabletcommand-backend-models";
|
|
5
5
|
import { IncidentRule, IncidentRuleChange } from ".";
|
|
6
|
-
import {
|
|
6
|
+
import { CADCommentType } from "tabletcommand-backend-models/definitions/types/cad-incident";
|
|
7
7
|
|
|
8
8
|
export interface CleanUpFilter {
|
|
9
9
|
name: string;
|
|
10
|
-
clean(items: Partial<
|
|
10
|
+
clean(items: Partial<CADCommentType>[]): Partial<CADCommentType>[];
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
export class IncidentRuleCleanUpComments implements IncidentRule {
|
|
@@ -17,7 +17,7 @@ export class IncidentRuleCleanUpComments implements IncidentRule {
|
|
|
17
17
|
changes: IncidentRuleChange[] = [];
|
|
18
18
|
filter: CleanUpFilter = {
|
|
19
19
|
name: "No Filter",
|
|
20
|
-
clean(items: Partial<
|
|
20
|
+
clean(items: Partial<CADCommentType>[]) {
|
|
21
21
|
return items;
|
|
22
22
|
}
|
|
23
23
|
};
|
|
@@ -32,7 +32,7 @@ export class IncidentRuleCleanUpComments implements IncidentRule {
|
|
|
32
32
|
return item;
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
-
const cleanComments = this.filter.clean(item.Comment as Partial<
|
|
35
|
+
const cleanComments = this.filter.clean(item.Comment as Partial<CADCommentType>[]);
|
|
36
36
|
const ruleMatched = item.Comment?.length > cleanComments.length;
|
|
37
37
|
if (ruleMatched) {
|
|
38
38
|
item.Comment = cleanComments as never; // Mongoose/Typescript mismatch
|
|
@@ -56,7 +56,7 @@ export class IncidentRuleCleanUpComments implements IncidentRule {
|
|
|
56
56
|
|
|
57
57
|
export const cleanUpFilterMissingDates: CleanUpFilter = {
|
|
58
58
|
name: "Clean Up Missing Dates",
|
|
59
|
-
clean: function(items: Partial<
|
|
59
|
+
clean: function(items: Partial<CADCommentType>[]): Partial<CADCommentType>[] {
|
|
60
60
|
if (!_.isArray(items)) {
|
|
61
61
|
return items;
|
|
62
62
|
}
|
|
@@ -64,7 +64,7 @@ export const cleanUpFilterMissingDates: CleanUpFilter = {
|
|
|
64
64
|
const atDate = new Date("2000-01-02T03:04:05.678Z");
|
|
65
65
|
const fallbackDate = moment(atDate).tz("America/Los_Angeles").format("YYYY-MM-DDTHH:mm:ssZZ");
|
|
66
66
|
|
|
67
|
-
const clean: Partial<
|
|
67
|
+
const clean: Partial<CADCommentType>[] = [];
|
|
68
68
|
_.forEach(items, (c) => {
|
|
69
69
|
if (!_.isObject(c)) {
|
|
70
70
|
return;
|
|
@@ -82,7 +82,7 @@ export const cleanUpFilterMissingDates: CleanUpFilter = {
|
|
|
82
82
|
|
|
83
83
|
export const cleanUpTorrance: CleanUpFilter = {
|
|
84
84
|
name: "Clean Up Torrance",
|
|
85
|
-
clean: function(items: Partial<
|
|
85
|
+
clean: function(items: Partial<CADCommentType>[]): Partial<CADCommentType>[] {
|
|
86
86
|
return items.filter((c) => {
|
|
87
87
|
if (_.isObject(c) && _.isString(c.Comment) && c.Comment.match(/^\s*State.Response:/)) {
|
|
88
88
|
return false;
|
|
@@ -94,12 +94,12 @@ export const cleanUpTorrance: CleanUpFilter = {
|
|
|
94
94
|
|
|
95
95
|
export const cleanUpWhitby: CleanUpFilter = {
|
|
96
96
|
name: "Clean Up Whitby",
|
|
97
|
-
clean: function(items: Partial<
|
|
97
|
+
clean: function(items: Partial<CADCommentType>[]): Partial<CADCommentType>[] {
|
|
98
98
|
if (!_.isArray(items)) {
|
|
99
99
|
return items;
|
|
100
100
|
}
|
|
101
101
|
|
|
102
|
-
const clean: Partial<
|
|
102
|
+
const clean: Partial<CADCommentType>[] = [];
|
|
103
103
|
_.forEach(items, (c) => {
|
|
104
104
|
if (!_.isObject(c)) {
|
|
105
105
|
return;
|
|
@@ -26,7 +26,7 @@ export class IncidentRuleCloseIncidentAfterHours implements IncidentRule {
|
|
|
26
26
|
this.changed = true;
|
|
27
27
|
|
|
28
28
|
const closeDate = moment(atDate).utc().add(this.hoursDelay, "hours");
|
|
29
|
-
item.expiration_date = closeDate.toDate()
|
|
29
|
+
item.expiration_date = closeDate.toDate();
|
|
30
30
|
|
|
31
31
|
this.changes.push({
|
|
32
32
|
name: this.name,
|
|
@@ -17,11 +17,11 @@ export class IncidentRuleCloseMatchingIncidentNumber implements IncidentRule {
|
|
|
17
17
|
changed = false;
|
|
18
18
|
changes: IncidentRuleChange[] = [];
|
|
19
19
|
|
|
20
|
-
ignoreMatching: (RegExp|string)[] = [];
|
|
20
|
+
ignoreMatching: (RegExp | string)[] = [];
|
|
21
21
|
skipMatching: AllowMatching[] = [];
|
|
22
22
|
secondsDelay = 0;
|
|
23
23
|
|
|
24
|
-
constructor(ignoreMatching: (RegExp|string)[], skipMatching: AllowMatching[], seconds: number) {
|
|
24
|
+
constructor(ignoreMatching: (RegExp | string)[], skipMatching: AllowMatching[], seconds: number) {
|
|
25
25
|
this.ignoreMatching = ignoreMatching;
|
|
26
26
|
this.skipMatching = skipMatching;
|
|
27
27
|
this.secondsDelay = seconds;
|
|
@@ -60,7 +60,7 @@ export class IncidentRuleCloseMatchingIncidentNumber implements IncidentRule {
|
|
|
60
60
|
item.ClosedDateTime = closeDate.format("YYYY-MM-DDTHH:mm:ssZZ");
|
|
61
61
|
item.closed_unix_date = closeDate.valueOf() / 1000.0;
|
|
62
62
|
}
|
|
63
|
-
item.expiration_date = closeDate.toDate()
|
|
63
|
+
item.expiration_date = closeDate.toDate();
|
|
64
64
|
}
|
|
65
65
|
this.changed = ruleMatched;
|
|
66
66
|
this.matched = ruleMatched;
|
|
@@ -34,7 +34,7 @@ export class IncidentRuleCloseIncidentOfCertainType implements IncidentRule {
|
|
|
34
34
|
this.changed = true;
|
|
35
35
|
|
|
36
36
|
const closeDate = moment(atDate).utc().add(this.secondsDelay, "seconds");
|
|
37
|
-
item.expiration_date = closeDate.toDate()
|
|
37
|
+
item.expiration_date = closeDate.toDate();
|
|
38
38
|
|
|
39
39
|
if (this.secondsDelay <= 0) {
|
|
40
40
|
item.closed_unix_date = atDate.valueOf() / 1000.0;
|
|
@@ -2,8 +2,8 @@ import _ from "lodash";
|
|
|
2
2
|
import moment from "moment-timezone";
|
|
3
3
|
|
|
4
4
|
import { CADIncident } from "tabletcommand-backend-models";
|
|
5
|
-
import { CADComment } from "../types";
|
|
6
5
|
import { IncidentRule, IncidentRuleChange } from ".";
|
|
6
|
+
import { CADCommentType } from "tabletcommand-backend-models/definitions/types/cad-incident";
|
|
7
7
|
|
|
8
8
|
export class IncidentRuleCopyIncidentNumber implements IncidentRule {
|
|
9
9
|
name = "Copy Incident Number";
|
|
@@ -22,7 +22,7 @@ export class IncidentRuleCopyIncidentNumber implements IncidentRule {
|
|
|
22
22
|
|
|
23
23
|
this.matched = true;
|
|
24
24
|
this.changed = true;
|
|
25
|
-
const extraComment: Partial<
|
|
25
|
+
const extraComment: Partial<CADCommentType> = {
|
|
26
26
|
Comment: `TC Incident Number: ${_.trim(item.IncidentNumber)}`,
|
|
27
27
|
CommentDateTime: moment(atDate).format("YYYY-MM-DDTHH:mm:ssZZ"),
|
|
28
28
|
CommentSource: "TC",
|
|
@@ -2,8 +2,8 @@ import _ from "lodash";
|
|
|
2
2
|
import moment from "moment-timezone";
|
|
3
3
|
|
|
4
4
|
import { CADIncident } from "tabletcommand-backend-models";
|
|
5
|
-
import { CADComment } from "../types";
|
|
6
5
|
import { IncidentRule, IncidentRuleChange } from ".";
|
|
6
|
+
import { CADCommentType } from "tabletcommand-backend-models/definitions/types/cad-incident";
|
|
7
7
|
|
|
8
8
|
export class IncidentRuleCopyLocationComment implements IncidentRule {
|
|
9
9
|
name = "Copy Location Comment";
|
|
@@ -22,7 +22,7 @@ export class IncidentRuleCopyLocationComment implements IncidentRule {
|
|
|
22
22
|
|
|
23
23
|
this.matched = true;
|
|
24
24
|
this.changed = true;
|
|
25
|
-
const extraComment: Partial<
|
|
25
|
+
const extraComment: Partial<CADCommentType> = {
|
|
26
26
|
Comment: `Location Comment: ${_.trim(item.LocationComment)}`,
|
|
27
27
|
CommentDateTime: moment(atDate).format("YYYY-MM-DDTHH:mm:ssZZ"),
|
|
28
28
|
CommentSource: "TC",
|
|
@@ -31,7 +31,7 @@ export class IncidentRuleCopyLocationComment implements IncidentRule {
|
|
|
31
31
|
if (!_.isArray(item.Comment)) {
|
|
32
32
|
item.Comment = [];
|
|
33
33
|
}
|
|
34
|
-
item.Comment?.push(extraComment as
|
|
34
|
+
item.Comment?.push(extraComment as CADCommentType); // Silence typescript/mongo mismatch
|
|
35
35
|
|
|
36
36
|
this.changes.push({
|
|
37
37
|
name: this.name,
|
package/src/rules/index.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import mongoose from "mongoose";
|
|
2
1
|
import { CADIncident, Department } from "tabletcommand-backend-models";
|
|
3
2
|
|
|
4
3
|
export interface IncidentRuleChange {
|
|
@@ -59,7 +58,7 @@ import {
|
|
|
59
58
|
|
|
60
59
|
export function rulesForDepartment(department: Partial<Department>): IncidentRule[] {
|
|
61
60
|
const items: IncidentRule[] = [];
|
|
62
|
-
const departmentId: string =
|
|
61
|
+
const departmentId: string = department._id?.toString() ?? "";
|
|
63
62
|
|
|
64
63
|
// City of Ontario, production testing, testing
|
|
65
64
|
if (departmentId === "61573ce72b3395e12228833e" || departmentId === "6573a7ec11c628d37734e39f" || departmentId === "646e81a459fcdd03372b5a2e") {
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { CADUnit } from "../types";
|
|
2
1
|
import _ from "lodash";
|
|
3
2
|
|
|
4
3
|
import { CADIncident } from "tabletcommand-backend-models";
|
|
5
4
|
import { IncidentRule, IncidentRuleChange } from ".";
|
|
5
|
+
import { CADUnitType } from "tabletcommand-backend-models/definitions/types/cad-incident";
|
|
6
6
|
|
|
7
7
|
export class IncidentRuleMapUnitDatesVerdugo implements IncidentRule {
|
|
8
8
|
name = "Map Unit Dates Verdugo";
|
|
@@ -20,8 +20,8 @@ export class IncidentRuleMapUnitDatesVerdugo implements IncidentRule {
|
|
|
20
20
|
return item;
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
-
const tempUnits:
|
|
24
|
-
_.each(item.Unit as
|
|
23
|
+
const tempUnits: CADUnitType[] = [];
|
|
24
|
+
_.each(item.Unit as CADUnitType[], function(value) {
|
|
25
25
|
if (!_.isObject(value)) {
|
|
26
26
|
return;
|
|
27
27
|
}
|
|
@@ -2,7 +2,8 @@ import _ from "lodash";
|
|
|
2
2
|
|
|
3
3
|
import { CADIncident } from "tabletcommand-backend-models";
|
|
4
4
|
import { IncidentRule, IncidentRuleChange } from ".";
|
|
5
|
-
import {
|
|
5
|
+
import { CADUnitType } from "tabletcommand-backend-models/definitions/types/cad-incident";
|
|
6
|
+
import { CADPersonSchemaType } from "tabletcommand-backend-models/definitions/types/shared-incident";
|
|
6
7
|
|
|
7
8
|
export type FieldToClear = keyof CADIncident;
|
|
8
9
|
|
|
@@ -24,7 +25,7 @@ export class IncidentRuleRemovePersonFromUnit implements IncidentRule {
|
|
|
24
25
|
|
|
25
26
|
let ruleMatched = false;
|
|
26
27
|
|
|
27
|
-
_.each(item.Unit as
|
|
28
|
+
_.each(item.Unit as CADUnitType[], function(unit) {
|
|
28
29
|
if (!_.isObject(unit)) {
|
|
29
30
|
return;
|
|
30
31
|
}
|
|
@@ -33,9 +34,9 @@ export class IncidentRuleRemovePersonFromUnit implements IncidentRule {
|
|
|
33
34
|
return;
|
|
34
35
|
}
|
|
35
36
|
|
|
36
|
-
const revisedItems:
|
|
37
|
+
const revisedItems: CADPersonSchemaType[] = [];
|
|
37
38
|
let personnelCount = (_.isNumber(unit.PersonnelCount) && _.isFinite(unit.PersonnelCount) && unit.PersonnelCount > 0) ? unit.PersonnelCount : 0;
|
|
38
|
-
_.each(unit.Personnel, function(person:
|
|
39
|
+
_.each(unit.Personnel, function(person: CADPersonSchemaType) {
|
|
39
40
|
if (!_.isObject(person) || !_.isString(person.PersonnelName)) {
|
|
40
41
|
return;
|
|
41
42
|
}
|
|
@@ -66,7 +67,7 @@ export class IncidentRuleRemovePersonFromUnit implements IncidentRule {
|
|
|
66
67
|
}
|
|
67
68
|
}
|
|
68
69
|
|
|
69
|
-
export function shouldRemovePerson(item: Partial<
|
|
70
|
+
export function shouldRemovePerson(item: Partial<CADPersonSchemaType>): boolean {
|
|
70
71
|
if (!_.isString(item.PersonnelName)) {
|
|
71
72
|
return false;
|
|
72
73
|
}
|
package/src/rules/set-address.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { CADComment } from "../types";
|
|
2
1
|
import _ from "lodash";
|
|
3
2
|
import moment from "moment-timezone";
|
|
4
3
|
|
|
5
4
|
import { CADIncident } from "tabletcommand-backend-models";
|
|
6
5
|
import { IncidentRule, IncidentRuleChange } from ".";
|
|
6
|
+
import { CADCommentType } from "tabletcommand-backend-models/definitions/types/cad-incident";
|
|
7
7
|
|
|
8
8
|
export class IncidentRuleSetAddress implements IncidentRule {
|
|
9
9
|
name = "Set Address";
|
|
@@ -24,15 +24,15 @@ export class IncidentRuleSetAddress implements IncidentRule {
|
|
|
24
24
|
this.changed = this.matched;
|
|
25
25
|
item.full_address = address;
|
|
26
26
|
|
|
27
|
-
const addrComment: Partial<
|
|
27
|
+
const addrComment: Partial<CADCommentType> = {
|
|
28
28
|
Comment: `Address: ${address}`,
|
|
29
29
|
CommentDateTime: moment(atDate).format("YYYY-MM-DDTHH:mm:ssZZ"),
|
|
30
30
|
CommentSource: "TC",
|
|
31
31
|
};
|
|
32
32
|
if (!_.isArray(item.Comment)) {
|
|
33
33
|
item.Comment = [];
|
|
34
|
-
}
|
|
35
|
-
item.Comment?.push(addrComment as
|
|
34
|
+
}
|
|
35
|
+
item.Comment?.push(addrComment as CADCommentType); // Silence typescript/mongo mismatch
|
|
36
36
|
|
|
37
37
|
this.changes.push({
|
|
38
38
|
name: this.name,
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { CADUnit } from "../types";
|
|
2
1
|
import _ from "lodash";
|
|
3
2
|
|
|
4
3
|
import { CADIncident } from "tabletcommand-backend-models";
|
|
5
4
|
import { IncidentRule, IncidentRuleChange } from ".";
|
|
5
|
+
import { CADUnitType } from "tabletcommand-backend-models/definitions/types/cad-incident";
|
|
6
6
|
|
|
7
7
|
export class IncidentRuleSetCommunicationChannelsFromRadioNames implements IncidentRule {
|
|
8
8
|
name = "Set Communication Channels From Radio Names";
|
|
@@ -29,7 +29,7 @@ export class IncidentRuleSetCommunicationChannelsFromRadioNames implements Incid
|
|
|
29
29
|
return item;
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
-
const incomingRadioNames = _.map(item.Unit as Partial<
|
|
32
|
+
const incomingRadioNames = _.map(item.Unit as Partial<CADUnitType>[], (item: Partial<CADUnitType>) => {
|
|
33
33
|
if (!_.isString(item.UnitID)) {
|
|
34
34
|
return "";
|
|
35
35
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import _ from "lodash";
|
|
2
2
|
import { CADIncident } from "tabletcommand-backend-models";
|
|
3
3
|
import { IncidentRule, IncidentRuleChange } from ".";
|
|
4
|
-
import {
|
|
4
|
+
import { CADUnitType } from "tabletcommand-backend-models/definitions/types/cad-incident";
|
|
5
5
|
|
|
6
6
|
export class IncidentRuleSetAlarmAtDispatchFromAlarmLevel implements IncidentRule {
|
|
7
7
|
name = "Set Unit.AlarmAtDispatch from Incident.AlarmLevel";
|
|
@@ -27,8 +27,8 @@ export class IncidentRuleSetAlarmAtDispatchFromAlarmLevel implements IncidentRul
|
|
|
27
27
|
const change: Record<string, string> = {};
|
|
28
28
|
|
|
29
29
|
// Process if unit is from Stream
|
|
30
|
-
if (_.isArray(item.Unit as
|
|
31
|
-
(item.Unit as
|
|
30
|
+
if (_.isArray(item.Unit as CADUnitType[])) {
|
|
31
|
+
(item.Unit as CADUnitType[]).forEach((unit) => {
|
|
32
32
|
if (_.isString(unit.AlarmAtDispatch) && unit.AlarmAtDispatch !== "") {
|
|
33
33
|
return;
|
|
34
34
|
}
|
|
@@ -41,7 +41,7 @@ export class IncidentRuleSetAlarmAtDispatchFromAlarmLevel implements IncidentRul
|
|
|
41
41
|
|
|
42
42
|
// Process if unit is from Incident
|
|
43
43
|
if (_.isArray(item.units)) {
|
|
44
|
-
item.units.forEach((unit:
|
|
44
|
+
item.units.forEach((unit: CADUnitType) => {
|
|
45
45
|
if (_.isString(unit.AlarmAtDispatch) && unit.AlarmAtDispatch !== "") {
|
|
46
46
|
return;
|
|
47
47
|
}
|
|
@@ -3,7 +3,7 @@ import moment from "moment-timezone";
|
|
|
3
3
|
|
|
4
4
|
import { CADIncident } from "tabletcommand-backend-models";
|
|
5
5
|
import { IncidentRule, IncidentRuleChange } from ".";
|
|
6
|
-
import {
|
|
6
|
+
import { CADCommentType } from "tabletcommand-backend-models/definitions/types/cad-incident";
|
|
7
7
|
|
|
8
8
|
export class IncidentRuleSetFireMapFromMapPagesSouthernMarin implements IncidentRule {
|
|
9
9
|
name = "Set Fire Map From Map Pages Southern Marin";
|
|
@@ -30,7 +30,7 @@ export class IncidentRuleSetFireMapFromMapPagesSouthernMarin implements Incident
|
|
|
30
30
|
item.FireMap = fireMap;
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
-
const extraComment: Partial<
|
|
33
|
+
const extraComment: Partial<CADCommentType> = {
|
|
34
34
|
Comment: `MapGrid: ${_.trim(previousMapPage)}`,
|
|
35
35
|
CommentDateTime: moment(atDate).format("YYYY-MM-DDTHH:mm:ssZZ"),
|
|
36
36
|
CommentSource: "TC",
|
|
@@ -39,7 +39,7 @@ export class IncidentRuleSetFireMapFromMapPagesSouthernMarin implements Incident
|
|
|
39
39
|
if (!_.isArray(item.Comment)) {
|
|
40
40
|
item.Comment = [];
|
|
41
41
|
}
|
|
42
|
-
item.Comment?.push(extraComment as
|
|
42
|
+
item.Comment?.push(extraComment as CADCommentType); // Silence typescript/mongo mismatch
|
|
43
43
|
|
|
44
44
|
this.changes.push({
|
|
45
45
|
name: this.name,
|