dt-common-device 6.2.0 → 7.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -39,21 +39,20 @@ const alert_types_1 = require("./alert.types");
39
39
  // Main Alert schema
40
40
  const AlertSchema = new mongoose_1.Schema({
41
41
  category: {
42
- type: [String],
42
+ type: String,
43
43
  enum: Object.values(alert_types_1.AlertCategory),
44
44
  required: true,
45
- validate: {
46
- validator: function (categories) {
47
- return categories && categories.length > 0;
48
- },
49
- message: "At least one category is required",
50
- },
51
45
  },
52
46
  propertyId: {
53
47
  type: String,
54
48
  required: true,
55
49
  index: true,
56
50
  },
51
+ zoneId: {
52
+ type: String,
53
+ required: true,
54
+ index: true,
55
+ },
57
56
  title: {
58
57
  type: String,
59
58
  required: true,
@@ -102,6 +101,7 @@ const AlertSchema = new mongoose_1.Schema({
102
101
  },
103
102
  updatedBy: {
104
103
  type: String,
104
+ index: true,
105
105
  },
106
106
  createdAt: {
107
107
  type: Date,
@@ -114,10 +114,14 @@ const AlertSchema = new mongoose_1.Schema({
114
114
  }, {
115
115
  timestamps: true,
116
116
  collection: "dt_alerts",
117
+ toJSON: { virtuals: true },
118
+ toObject: { virtuals: true },
119
+ id: false, // Disable the virtual id field since we're handling it manually
117
120
  });
118
121
  exports.AlertSchema = AlertSchema;
119
122
  // Compound indexes to match Prisma schema
120
123
  AlertSchema.index({ propertyId: 1, isActive: 1, isRead: 1 });
124
+ AlertSchema.index({ zoneId: 1, category: 1 });
121
125
  AlertSchema.index({ entityId: 1, entityType: 1 });
122
126
  AlertSchema.index({ createdAt: 1 });
123
127
  // Pre-save middleware to update the updatedAt field
@@ -157,7 +161,7 @@ AlertSchema.methods.unsnooze = function (updatedBy) {
157
161
  };
158
162
  // Static methods
159
163
  AlertSchema.statics.findByCategory = function (category, includeDeleted = false) {
160
- const query = { category: { $in: [category] } };
164
+ const query = { category: category };
161
165
  if (!includeDeleted) {
162
166
  query.isDeleted = false;
163
167
  }
@@ -187,8 +191,57 @@ AlertSchema.virtual("isSnoozed").get(function () {
187
191
  AlertSchema.virtual("isSnoozeExpired").get(function () {
188
192
  return this.snoozeUntil && this.snoozeUntil <= new Date();
189
193
  });
190
- // Ensure virtuals are serialized
191
- AlertSchema.set("toJSON", { virtuals: true });
192
- AlertSchema.set("toObject", { virtuals: true });
194
+ // Virtual for soft delete status (different name to avoid conflict)
195
+ AlertSchema.virtual("isNotDeleted").get(function () {
196
+ return !this.isDeleted;
197
+ });
198
+ // Post middleware to transform all find results to plain objects
199
+ AlertSchema.post(/^find/, function (result) {
200
+ if (!result)
201
+ return;
202
+ // Handle array results (find)
203
+ if (Array.isArray(result)) {
204
+ result.forEach((doc) => {
205
+ if (doc && typeof doc.toObject === "function") {
206
+ const plainDoc = doc.toObject();
207
+ // Transform _id to id and remove __v
208
+ plainDoc.id = plainDoc._id ? plainDoc._id.toString() : plainDoc._id;
209
+ delete plainDoc._id;
210
+ delete plainDoc.__v;
211
+ // Replace the document with plain object
212
+ Object.assign(doc, plainDoc);
213
+ }
214
+ });
215
+ }
216
+ // Handle single document results (findOne, findById, etc.)
217
+ else if (result && typeof result.toObject === "function") {
218
+ const plainDoc = result.toObject();
219
+ // Transform _id to id and remove __v
220
+ plainDoc.id = plainDoc._id ? plainDoc._id.toString() : plainDoc._id;
221
+ delete plainDoc._id;
222
+ delete plainDoc.__v;
223
+ // Replace the document with plain object
224
+ Object.assign(result, plainDoc);
225
+ }
226
+ });
227
+ // Ensure virtuals are serialized and transform to plain objects
228
+ AlertSchema.set("toJSON", {
229
+ virtuals: true,
230
+ transform: function (doc, ret) {
231
+ ret.id = ret._id ? ret._id.toString() : ret._id;
232
+ delete ret._id;
233
+ delete ret.__v;
234
+ return ret;
235
+ },
236
+ });
237
+ AlertSchema.set("toObject", {
238
+ virtuals: true,
239
+ transform: function (doc, ret) {
240
+ ret.id = ret._id ? ret._id.toString() : ret._id;
241
+ delete ret._id;
242
+ delete ret.__v;
243
+ return ret;
244
+ },
245
+ });
193
246
  // Create and export the model
194
247
  exports.AlertModel = mongoose_1.default.model("Alert", AlertSchema);
@@ -33,7 +33,7 @@ export declare class AlertRepository {
33
33
  /**
34
34
  * Find alerts by category
35
35
  */
36
- findByCategory(category: AlertCategory | AlertCategory[], includeDeleted?: boolean): Promise<IAlertDocument[]>;
36
+ findByCategory(category: AlertCategory, includeDeleted?: boolean): Promise<IAlertDocument[]>;
37
37
  /**
38
38
  * Find snoozed alerts
39
39
  */
@@ -45,7 +45,7 @@ export declare class AlertRepository {
45
45
  /**
46
46
  * Get alert statistics
47
47
  */
48
- getStatistics(propertyId?: string): Promise<{
48
+ getStatistics(propertyId?: string, zoneId?: string): Promise<{
49
49
  total: number;
50
50
  active: number;
51
51
  unread: number;
@@ -61,4 +61,38 @@ export declare class AlertRepository {
61
61
  * Bulk soft delete alerts
62
62
  */
63
63
  bulkSoftDelete(ids: string[], deletedBy: string): Promise<number>;
64
+ /**
65
+ * Find alerts by zone ID
66
+ */
67
+ findByZoneId(zoneId: string, includeDeleted?: boolean): Promise<IAlertDocument[]>;
68
+ /**
69
+ * Find alerts by zone ID and category
70
+ */
71
+ findByZoneIdAndCategory(zoneId: string, category: AlertCategory, includeDeleted?: boolean): Promise<IAlertDocument[]>;
72
+ /**
73
+ * Find alerts by zone ID and severity
74
+ */
75
+ findByZoneIdAndSeverity(zoneId: string, severity: AlertSeverity, includeDeleted?: boolean): Promise<IAlertDocument[]>;
76
+ /**
77
+ * Find alerts by zone ID and active status
78
+ */
79
+ findByZoneIdAndActiveStatus(zoneId: string, isActive: boolean, includeDeleted?: boolean): Promise<IAlertDocument[]>;
80
+ /**
81
+ * Find alerts by zone ID and read status
82
+ */
83
+ findByZoneIdAndReadStatus(zoneId: string, isRead: boolean, includeDeleted?: boolean): Promise<IAlertDocument[]>;
84
+ /**
85
+ * Find alerts by multiple zone IDs
86
+ */
87
+ findByZoneIds(zoneIds: string[], includeDeleted?: boolean): Promise<IAlertDocument[]>;
88
+ /**
89
+ * Get alert statistics by zone ID and severity
90
+ */
91
+ getStatisticsByZoneAndSeverity(zoneId: string, severity?: AlertSeverity): Promise<{
92
+ total: number;
93
+ active: number;
94
+ unread: number;
95
+ snoozed: number;
96
+ byCategory: Record<AlertCategory, number>;
97
+ }>;
64
98
  }
@@ -52,14 +52,10 @@ let AlertRepository = (() => {
52
52
  const query = {};
53
53
  if (filters.propertyId)
54
54
  query.propertyId = filters.propertyId;
55
- if (filters.category) {
56
- if (Array.isArray(filters.category)) {
57
- query.category = { $in: filters.category };
58
- }
59
- else {
60
- query.category = { $in: [filters.category] };
61
- }
62
- }
55
+ if (filters.zoneId)
56
+ query.zoneId = filters.zoneId;
57
+ if (filters.category)
58
+ query.category = filters.category;
63
59
  if (filters.severity)
64
60
  query.severity = filters.severity;
65
61
  if (filters.entityType)
@@ -86,7 +82,8 @@ let AlertRepository = (() => {
86
82
  isActive: true,
87
83
  isDeleted: false,
88
84
  });
89
- return await alert.save();
85
+ const savedAlert = await alert.save();
86
+ return savedAlert.toObject();
90
87
  }
91
88
  catch (error) {
92
89
  throw new Error(`Failed to create alert: ${error instanceof Error ? error.message : "Unknown error"}`);
@@ -101,7 +98,8 @@ let AlertRepository = (() => {
101
98
  if (!includeDeleted) {
102
99
  query.isDeleted = false;
103
100
  }
104
- return await Alert_model_1.AlertModel.findOne(query);
101
+ const result = await Alert_model_1.AlertModel.findOne(query);
102
+ return result ? result.toObject() : null;
105
103
  }
106
104
  catch (error) {
107
105
  throw new Error(`Failed to find alert by ID: ${error instanceof Error ? error.message : "Unknown error"}`);
@@ -124,7 +122,8 @@ let AlertRepository = (() => {
124
122
  queryBuilder.skip(filters.skip);
125
123
  if (filters.limit)
126
124
  queryBuilder.limit(filters.limit);
127
- return await queryBuilder.exec();
125
+ const results = await queryBuilder.exec();
126
+ return results.map((result) => result.toObject());
128
127
  }
129
128
  catch (error) {
130
129
  throw new Error(`Failed to find alerts: ${error instanceof Error ? error.message : "Unknown error"}`);
@@ -135,7 +134,8 @@ let AlertRepository = (() => {
135
134
  */
136
135
  async update(id, updateData) {
137
136
  try {
138
- return await Alert_model_1.AlertModel.findByIdAndUpdate(id, { ...updateData, updatedAt: new Date() }, { new: true, runValidators: true });
137
+ const result = await Alert_model_1.AlertModel.findByIdAndUpdate(id, { ...updateData, updatedAt: new Date() }, { new: true, runValidators: true });
138
+ return result ? result.toObject() : null;
139
139
  }
140
140
  catch (error) {
141
141
  throw new Error(`Failed to update alert: ${error instanceof Error ? error.message : "Unknown error"}`);
@@ -186,17 +186,7 @@ let AlertRepository = (() => {
186
186
  */
187
187
  async findByCategory(category, includeDeleted = false) {
188
188
  try {
189
- if (Array.isArray(category)) {
190
- // Use $in operator for array of categories
191
- const query = { category: { $in: category } };
192
- if (!includeDeleted) {
193
- query.isDeleted = false;
194
- }
195
- return await Alert_model_1.AlertModel.find(query).sort({ createdAt: -1 });
196
- }
197
- else {
198
- return await Alert_model_1.AlertModel.findByCategory(category, includeDeleted);
199
- }
189
+ return await Alert_model_1.AlertModel.findByCategory(category, includeDeleted);
200
190
  }
201
191
  catch (error) {
202
192
  throw new Error(`Failed to find alerts by category: ${error instanceof Error ? error.message : "Unknown error"}`);
@@ -227,11 +217,13 @@ let AlertRepository = (() => {
227
217
  /**
228
218
  * Get alert statistics
229
219
  */
230
- async getStatistics(propertyId) {
220
+ async getStatistics(propertyId, zoneId) {
231
221
  try {
232
222
  const query = { isDeleted: false };
233
223
  if (propertyId)
234
224
  query.propertyId = propertyId;
225
+ if (zoneId)
226
+ query.zoneId = zoneId;
235
227
  const [total, active, unread, snoozed, severityStats, categoryStats] = await Promise.all([
236
228
  Alert_model_1.AlertModel.countDocuments(query),
237
229
  Alert_model_1.AlertModel.countDocuments({ ...query, isActive: true }),
@@ -246,7 +238,6 @@ let AlertRepository = (() => {
246
238
  ]),
247
239
  Alert_model_1.AlertModel.aggregate([
248
240
  { $match: query },
249
- { $unwind: "$category" },
250
241
  { $group: { _id: "$category", count: { $sum: 1 } } },
251
242
  ]),
252
243
  ]);
@@ -310,6 +301,147 @@ let AlertRepository = (() => {
310
301
  throw new Error(`Failed to bulk soft delete alerts: ${error instanceof Error ? error.message : "Unknown error"}`);
311
302
  }
312
303
  }
304
+ /**
305
+ * Find alerts by zone ID
306
+ */
307
+ async findByZoneId(zoneId, includeDeleted = false) {
308
+ try {
309
+ const query = { zoneId };
310
+ if (!includeDeleted) {
311
+ query.isDeleted = false;
312
+ }
313
+ const results = await Alert_model_1.AlertModel.find(query).sort({ createdAt: -1 });
314
+ return results.map((result) => result.toObject());
315
+ }
316
+ catch (error) {
317
+ throw new Error(`Failed to find alerts by zone ID: ${error instanceof Error ? error.message : "Unknown error"}`);
318
+ }
319
+ }
320
+ /**
321
+ * Find alerts by zone ID and category
322
+ */
323
+ async findByZoneIdAndCategory(zoneId, category, includeDeleted = false) {
324
+ try {
325
+ const query = { zoneId, category };
326
+ if (!includeDeleted) {
327
+ query.isDeleted = false;
328
+ }
329
+ const results = await Alert_model_1.AlertModel.find(query).sort({ createdAt: -1 });
330
+ return results.map((result) => result.toObject());
331
+ }
332
+ catch (error) {
333
+ throw new Error(`Failed to find alerts by zone ID and category: ${error instanceof Error ? error.message : "Unknown error"}`);
334
+ }
335
+ }
336
+ /**
337
+ * Find alerts by zone ID and severity
338
+ */
339
+ async findByZoneIdAndSeverity(zoneId, severity, includeDeleted = false) {
340
+ try {
341
+ const query = { zoneId, severity };
342
+ if (!includeDeleted) {
343
+ query.isDeleted = false;
344
+ }
345
+ const results = await Alert_model_1.AlertModel.find(query).sort({ createdAt: -1 });
346
+ return results.map((result) => result.toObject());
347
+ }
348
+ catch (error) {
349
+ throw new Error(`Failed to find alerts by zone ID and severity: ${error instanceof Error ? error.message : "Unknown error"}`);
350
+ }
351
+ }
352
+ /**
353
+ * Find alerts by zone ID and active status
354
+ */
355
+ async findByZoneIdAndActiveStatus(zoneId, isActive, includeDeleted = false) {
356
+ try {
357
+ const query = { zoneId, isActive };
358
+ if (!includeDeleted) {
359
+ query.isDeleted = false;
360
+ }
361
+ const results = await Alert_model_1.AlertModel.find(query).sort({ createdAt: -1 });
362
+ return results.map((result) => result.toObject());
363
+ }
364
+ catch (error) {
365
+ throw new Error(`Failed to find alerts by zone ID and active status: ${error instanceof Error ? error.message : "Unknown error"}`);
366
+ }
367
+ }
368
+ /**
369
+ * Find alerts by zone ID and read status
370
+ */
371
+ async findByZoneIdAndReadStatus(zoneId, isRead, includeDeleted = false) {
372
+ try {
373
+ const query = { zoneId, isRead };
374
+ if (!includeDeleted) {
375
+ query.isDeleted = false;
376
+ }
377
+ const results = await Alert_model_1.AlertModel.find(query).sort({ createdAt: -1 });
378
+ return results.map((result) => result.toObject());
379
+ }
380
+ catch (error) {
381
+ throw new Error(`Failed to find alerts by zone ID and read status: ${error instanceof Error ? error.message : "Unknown error"}`);
382
+ }
383
+ }
384
+ /**
385
+ * Find alerts by multiple zone IDs
386
+ */
387
+ async findByZoneIds(zoneIds, includeDeleted = false) {
388
+ try {
389
+ if (!zoneIds || zoneIds.length === 0) {
390
+ throw new Error("Zone IDs array is required and cannot be empty");
391
+ }
392
+ const query = { zoneId: { $in: zoneIds } };
393
+ if (!includeDeleted) {
394
+ query.isDeleted = false;
395
+ }
396
+ const results = await Alert_model_1.AlertModel.find(query).sort({ createdAt: -1 });
397
+ return results.map((result) => result.toObject());
398
+ }
399
+ catch (error) {
400
+ throw new Error(`Failed to find alerts by zone IDs: ${error instanceof Error ? error.message : "Unknown error"}`);
401
+ }
402
+ }
403
+ /**
404
+ * Get alert statistics by zone ID and severity
405
+ */
406
+ async getStatisticsByZoneAndSeverity(zoneId, severity) {
407
+ try {
408
+ const query = { isDeleted: false, zoneId };
409
+ if (severity)
410
+ query.severity = severity;
411
+ const [total, active, unread, snoozed, categoryStats] = await Promise.all([
412
+ Alert_model_1.AlertModel.countDocuments(query),
413
+ Alert_model_1.AlertModel.countDocuments({ ...query, isActive: true }),
414
+ Alert_model_1.AlertModel.countDocuments({ ...query, isRead: false }),
415
+ Alert_model_1.AlertModel.countDocuments({
416
+ ...query,
417
+ snoozeUntil: { $exists: true, $ne: null },
418
+ }),
419
+ Alert_model_1.AlertModel.aggregate([
420
+ { $match: query },
421
+ { $group: { _id: "$category", count: { $sum: 1 } } },
422
+ ]),
423
+ ]);
424
+ const byCategory = Object.values(alert_types_1.AlertCategory).reduce((acc, category) => {
425
+ acc[category] = 0;
426
+ return acc;
427
+ }, {});
428
+ categoryStats.forEach((stat) => {
429
+ if (stat._id in byCategory) {
430
+ byCategory[stat._id] = stat.count;
431
+ }
432
+ });
433
+ return {
434
+ total,
435
+ active,
436
+ unread,
437
+ snoozed,
438
+ byCategory,
439
+ };
440
+ }
441
+ catch (error) {
442
+ throw new Error(`Failed to get alert statistics by zone and severity: ${error instanceof Error ? error.message : "Unknown error"}`);
443
+ }
444
+ }
313
445
  };
314
446
  __setFunctionName(_classThis, "AlertRepository");
315
447
  (() => {
@@ -9,27 +9,27 @@ export declare class AlertService {
9
9
  /**
10
10
  * Create a readiness alert using AlertBuilder
11
11
  */
12
- raiseReadinessAlert(propertyId: string, title: string, description: string, entityId?: string, entityType?: EntityType, createdBy?: string): Promise<IAlertDocument>;
12
+ raiseReadinessAlert(propertyId: string, zoneId: string, title: string, description: string, entityId?: string, entityType?: EntityType, createdBy?: string): Promise<IAlertDocument>;
13
13
  /**
14
14
  * Create an operations alert using AlertBuilder
15
15
  */
16
- raiseOperationsAlert(propertyId: string, title: string, description: string, entityId?: string, entityType?: EntityType, createdBy?: string): Promise<IAlertDocument>;
16
+ raiseOperationsAlert(propertyId: string, zoneId: string, title: string, description: string, entityId?: string, entityType?: EntityType, createdBy?: string): Promise<IAlertDocument>;
17
17
  /**
18
18
  * Create a security alert using AlertBuilder
19
19
  */
20
- raiseSecurityAlert(propertyId: string, title: string, description: string, entityId?: string, entityType?: EntityType, createdBy?: string): Promise<IAlertDocument>;
20
+ raiseSecurityAlert(propertyId: string, zoneId: string, title: string, description: string, entityId?: string, entityType?: EntityType, createdBy?: string): Promise<IAlertDocument>;
21
21
  /**
22
22
  * Create an energy alert using AlertBuilder
23
23
  */
24
- raiseEnergyAlert(propertyId: string, title: string, description: string, entityId?: string, entityType?: EntityType, createdBy?: string): Promise<IAlertDocument>;
24
+ raiseEnergyAlert(propertyId: string, zoneId: string, title: string, description: string, entityId?: string, entityType?: EntityType, createdBy?: string): Promise<IAlertDocument>;
25
25
  /**
26
26
  * Create a device-specific alert using AlertBuilder
27
27
  */
28
- raiseDeviceAlert(deviceId: string, propertyId: string, title: string, description: string, category?: AlertCategory | AlertCategory[], severity?: AlertSeverity, source?: Source): Promise<IAlertDocument>;
28
+ raiseDeviceAlert(deviceId: string, propertyId: string, zoneId: string, title: string, description: string, category?: AlertCategory, severity?: AlertSeverity, source?: Source): Promise<IAlertDocument>;
29
29
  /**
30
30
  * Create a hub-specific alert using AlertBuilder
31
31
  */
32
- raiseHubAlert(hubId: string, propertyId: string, title: string, description: string, category?: AlertCategory | AlertCategory[], severity?: AlertSeverity, createdBy?: string): Promise<IAlertDocument>;
32
+ raiseHubAlert(hubId: string, propertyId: string, zoneId: string, title: string, description: string, category?: AlertCategory, severity?: AlertSeverity, createdBy?: string): Promise<IAlertDocument>;
33
33
  /**
34
34
  * Raise alert for device going offline (OPERATIONAL only)
35
35
  */
@@ -94,7 +94,7 @@ export declare class AlertService {
94
94
  /**
95
95
  * Get alerts by category with business logic
96
96
  */
97
- getAlertsByCategory(category: AlertCategory | AlertCategory[], includeDeleted?: boolean): Promise<IAlertDocument[]>;
97
+ getAlertsByCategory(category: AlertCategory, includeDeleted?: boolean): Promise<IAlertDocument[]>;
98
98
  /**
99
99
  * Get snoozed alerts with business logic
100
100
  */
@@ -106,7 +106,7 @@ export declare class AlertService {
106
106
  /**
107
107
  * Get alert statistics with business logic
108
108
  */
109
- getAlertStatistics(propertyId?: string): Promise<{
109
+ getAlertStatistics(propertyId?: string, zoneId?: string): Promise<{
110
110
  total: number;
111
111
  active: number;
112
112
  unread: number;
@@ -114,6 +114,40 @@ export declare class AlertService {
114
114
  bySeverity: Record<AlertSeverity, number>;
115
115
  byCategory: Record<AlertCategory, number>;
116
116
  }>;
117
+ /**
118
+ * Get alerts by zone ID
119
+ */
120
+ getAlertsByZoneId(zoneId: string, includeDeleted?: boolean): Promise<IAlertDocument[]>;
121
+ /**
122
+ * Get alerts by zone ID and category
123
+ */
124
+ getAlertsByZoneIdAndCategory(zoneId: string, category: AlertCategory, includeDeleted?: boolean): Promise<IAlertDocument[]>;
125
+ /**
126
+ * Get alerts by zone ID and severity
127
+ */
128
+ getAlertsByZoneIdAndSeverity(zoneId: string, severity: AlertSeverity, includeDeleted?: boolean): Promise<IAlertDocument[]>;
129
+ /**
130
+ * Get alerts by multiple zone IDs
131
+ */
132
+ getAlertsByZoneIds(zoneIds: string[], includeDeleted?: boolean): Promise<IAlertDocument[]>;
133
+ /**
134
+ * Get alert statistics by zone ID and severity
135
+ */
136
+ getAlertStatisticsByZoneAndSeverity(zoneId: string, severity?: AlertSeverity): Promise<{
137
+ total: number;
138
+ active: number;
139
+ unread: number;
140
+ snoozed: number;
141
+ byCategory: Record<AlertCategory, number>;
142
+ }>;
143
+ /**
144
+ * Get alerts by zone ID and active status
145
+ */
146
+ getAlertsByZoneIdAndActiveStatus(zoneId: string, isActive: boolean, includeDeleted?: boolean): Promise<IAlertDocument[]>;
147
+ /**
148
+ * Get alerts by zone ID and read status
149
+ */
150
+ getAlertsByZoneIdAndReadStatus(zoneId: string, isRead: boolean, includeDeleted?: boolean): Promise<IAlertDocument[]>;
117
151
  private validateAlertData;
118
152
  private validateFilters;
119
153
  private validateUpdateData;