dt-common-device 7.2.0 → 7.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,35 +1,31 @@
1
1
  import { IAlertDocument } from "./Alert.model";
2
- import { CreateAlertData, UpdateAlertData, AlertCategory, AlertSeverity, EntityType, IAlertQuery } from "./alert.types";
2
+ import { CreateAlertData, UpdateAlertData, AlertCategory, AlertSeverity, IAlertQuery } from "./alert.types";
3
3
  import { Source } from "../constants/Service";
4
4
  import { AlertBuilder } from "./AlertBuilder";
5
5
  import { IDevice } from "../entities/device/local/interfaces";
6
6
  export declare class AlertService {
7
7
  private readonly alertRepository;
8
8
  constructor();
9
- /**
10
- * Create a readiness alert using AlertBuilder
11
- */
12
- raiseReadinessAlert(propertyId: string, zoneId: string, title: string, description: string, entityId?: string, entityType?: EntityType, createdBy?: string): Promise<IAlertDocument>;
13
9
  /**
14
10
  * Create an operations alert using AlertBuilder
15
11
  */
16
- raiseOperationsAlert(propertyId: string, zoneId: string, title: string, description: string, entityId?: string, entityType?: EntityType, createdBy?: string): Promise<IAlertDocument>;
12
+ raiseOperationsAlert(data: CreateAlertData): Promise<IAlertDocument>;
17
13
  /**
18
14
  * Create a security alert using AlertBuilder
19
15
  */
20
- raiseSecurityAlert(propertyId: string, zoneId: string, title: string, description: string, entityId?: string, entityType?: EntityType, createdBy?: string): Promise<IAlertDocument>;
16
+ raiseSecurityAlert(data: CreateAlertData): Promise<IAlertDocument>;
21
17
  /**
22
18
  * Create an energy alert using AlertBuilder
23
19
  */
24
- raiseEnergyAlert(propertyId: string, zoneId: string, title: string, description: string, entityId?: string, entityType?: EntityType, createdBy?: string): Promise<IAlertDocument>;
20
+ raiseEnergyAlert(data: CreateAlertData): Promise<IAlertDocument>;
25
21
  /**
26
22
  * Create a device-specific alert using AlertBuilder
27
23
  */
28
- raiseDeviceAlert(deviceId: string, propertyId: string, zoneId: string, title: string, description: string, category?: AlertCategory, severity?: AlertSeverity, source?: Source): Promise<IAlertDocument>;
24
+ raiseDeviceAlert(data: CreateAlertData): Promise<IAlertDocument>;
29
25
  /**
30
26
  * Create a hub-specific alert using AlertBuilder
31
27
  */
32
- raiseHubAlert(hubId: string, propertyId: string, zoneId: string, title: string, description: string, category?: AlertCategory, severity?: AlertSeverity, createdBy?: string): Promise<IAlertDocument>;
28
+ raiseHubAlert(data: CreateAlertData): Promise<IAlertDocument>;
33
29
  /**
34
30
  * Raise alert for device going offline (OPERATIONAL only)
35
31
  */
@@ -86,127 +86,150 @@ let AlertService = (() => {
86
86
  constructor() {
87
87
  this.alertRepository = typedi_1.default.get(Alert_repository_1.AlertRepository);
88
88
  }
89
- /**
90
- * Create a readiness alert using AlertBuilder
91
- */
92
- async raiseReadinessAlert(propertyId, zoneId, title, description, entityId, entityType, createdBy) {
93
- const alertBuilder = AlertBuilder_1.AlertBuilder.createReadinessAlert()
94
- .setPropertyId(propertyId)
95
- .setZoneId(zoneId)
96
- .setTitle(title)
97
- .setDescription(description);
98
- if (entityId)
99
- alertBuilder.setEntityId(entityId);
100
- if (entityType)
101
- alertBuilder.setEntityType(entityType);
102
- if (createdBy)
103
- alertBuilder.setCreatedBy(createdBy);
104
- return await this.createAlert(alertBuilder);
105
- }
106
89
  /**
107
90
  * Create an operations alert using AlertBuilder
108
91
  */
109
- async raiseOperationsAlert(propertyId, zoneId, title, description, entityId, entityType, createdBy) {
92
+ async raiseOperationsAlert(data) {
110
93
  const alertBuilder = AlertBuilder_1.AlertBuilder.createOperationsAlert()
111
- .setPropertyId(propertyId)
112
- .setZoneId(zoneId)
113
- .setTitle(title)
114
- .setDescription(description);
115
- if (entityId)
116
- alertBuilder.setEntityId(entityId);
117
- if (entityType)
118
- alertBuilder.setEntityType(entityType);
119
- if (createdBy)
120
- alertBuilder.setCreatedBy(createdBy);
94
+ .setPropertyId(data.propertyId)
95
+ .setZoneId(data.zoneId)
96
+ .setTitle(data.title)
97
+ .setDescription(data.description);
98
+ if (data.entityId)
99
+ alertBuilder.setEntityId(data.entityId);
100
+ if (data.entityType)
101
+ alertBuilder.setEntityType(data.entityType);
102
+ if (data.createdBy)
103
+ alertBuilder.setCreatedBy(data.createdBy);
121
104
  return await this.createAlert(alertBuilder);
122
105
  }
123
106
  /**
124
107
  * Create a security alert using AlertBuilder
125
108
  */
126
- async raiseSecurityAlert(propertyId, zoneId, title, description, entityId, entityType, createdBy) {
109
+ async raiseSecurityAlert(data) {
127
110
  const alertBuilder = AlertBuilder_1.AlertBuilder.createSecurityAlert()
128
- .setPropertyId(propertyId)
129
- .setZoneId(zoneId)
130
- .setTitle(title)
131
- .setDescription(description);
132
- if (entityId)
133
- alertBuilder.setEntityId(entityId);
134
- if (entityType)
135
- alertBuilder.setEntityType(entityType);
136
- if (createdBy)
137
- alertBuilder.setCreatedBy(createdBy);
111
+ .setPropertyId(data.propertyId)
112
+ .setZoneId(data.zoneId)
113
+ .setTitle(data.title)
114
+ .setDescription(data.description);
115
+ if (data.entityId)
116
+ alertBuilder.setEntityId(data.entityId);
117
+ if (data.entityType)
118
+ alertBuilder.setEntityType(data.entityType);
119
+ if (data.createdBy)
120
+ alertBuilder.setCreatedBy(data.createdBy);
138
121
  return await this.createAlert(alertBuilder);
139
122
  }
140
123
  /**
141
124
  * Create an energy alert using AlertBuilder
142
125
  */
143
- async raiseEnergyAlert(propertyId, zoneId, title, description, entityId, entityType, createdBy) {
126
+ async raiseEnergyAlert(data) {
144
127
  const alertBuilder = AlertBuilder_1.AlertBuilder.createEnergyAlert()
145
- .setPropertyId(propertyId)
146
- .setZoneId(zoneId)
147
- .setTitle(title)
148
- .setDescription(description);
149
- if (entityId)
150
- alertBuilder.setEntityId(entityId);
151
- if (entityType)
152
- alertBuilder.setEntityType(entityType);
153
- if (createdBy)
154
- alertBuilder.setCreatedBy(createdBy);
128
+ .setPropertyId(data.propertyId)
129
+ .setZoneId(data.zoneId)
130
+ .setTitle(data.title)
131
+ .setDescription(data.description);
132
+ if (data.entityId)
133
+ alertBuilder.setEntityId(data.entityId);
134
+ if (data.entityType)
135
+ alertBuilder.setEntityType(data.entityType);
136
+ if (data.createdBy)
137
+ alertBuilder.setCreatedBy(data.createdBy);
155
138
  return await this.createAlert(alertBuilder);
156
139
  }
157
140
  /**
158
141
  * Create a device-specific alert using AlertBuilder
159
142
  */
160
- async raiseDeviceAlert(deviceId, propertyId, zoneId, title, description, category, severity, source) {
161
- const alertBuilder = AlertBuilder_1.AlertBuilder.createDeviceAlert(deviceId, propertyId, zoneId)
162
- .setTitle(title)
163
- .setDescription(description);
164
- if (category)
165
- alertBuilder.setCategory(category);
166
- if (severity)
167
- alertBuilder.setSeverity(severity);
168
- if (source)
169
- alertBuilder.setCreatedBy(source);
143
+ async raiseDeviceAlert(data) {
144
+ const alertBuilder = AlertBuilder_1.AlertBuilder.createDeviceAlert(data.entityId || "", data.propertyId, data.zoneId)
145
+ .setTitle(data.title)
146
+ .setDescription(data.description);
147
+ if (data.category)
148
+ alertBuilder.setCategory(data.category);
149
+ if (data.severity)
150
+ alertBuilder.setSeverity(data.severity);
151
+ if (data.createdBy)
152
+ alertBuilder.setCreatedBy(data.createdBy);
170
153
  return await this.createAlert(alertBuilder);
171
154
  }
172
155
  /**
173
156
  * Create a hub-specific alert using AlertBuilder
174
157
  */
175
- async raiseHubAlert(hubId, propertyId, zoneId, title, description, category, severity, createdBy) {
176
- const alertBuilder = AlertBuilder_1.AlertBuilder.createHubAlert(hubId, propertyId, zoneId)
177
- .setTitle(title)
178
- .setDescription(description);
179
- if (category)
180
- alertBuilder.setCategory(category);
181
- if (severity)
182
- alertBuilder.setSeverity(severity);
183
- if (createdBy)
184
- alertBuilder.setCreatedBy(createdBy);
158
+ async raiseHubAlert(data) {
159
+ const alertBuilder = AlertBuilder_1.AlertBuilder.createHubAlert(data.entityId || "", data.propertyId, data.zoneId)
160
+ .setTitle(data.title)
161
+ .setDescription(data.description);
162
+ if (data.category)
163
+ alertBuilder.setCategory(data.category);
164
+ if (data.severity)
165
+ alertBuilder.setSeverity(data.severity);
166
+ if (data.createdBy)
167
+ alertBuilder.setCreatedBy(data.createdBy);
185
168
  return await this.createAlert(alertBuilder);
186
169
  }
187
170
  /**
188
171
  * Raise alert for device going offline (OPERATIONAL only)
189
172
  */
190
173
  async raiseDeviceOfflineAlert(device, source, reason) {
191
- return await this.raiseDeviceAlert(device.deviceId, device.propertyId, device.zoneId, "Device Offline", `Device ${device.name} (${device.deviceId}) has gone offline. ${reason ? `Reason: ${reason}` : ""}`, alert_types_1.AlertCategory.OPERATIONS, alert_types_1.AlertSeverity.HIGH, source);
174
+ return await this.raiseDeviceAlert({
175
+ entityId: device.deviceId,
176
+ propertyId: device.propertyId,
177
+ zoneId: device.zoneId,
178
+ title: "Device Offline",
179
+ description: `Device ${device.name} has gone offline. ${reason ? `Reason: ${reason}` : ""}`,
180
+ category: alert_types_1.AlertCategory.OPERATIONS,
181
+ severity: alert_types_1.AlertSeverity.HIGH,
182
+ createdBy: source,
183
+ entityType: alert_types_1.EntityType.DEVICE,
184
+ });
192
185
  }
193
186
  /**
194
187
  * Raise alert for device coming online (OPERATIONAL only)
195
188
  */
196
189
  async raiseDeviceOnlineAlert(device, source, reason) {
197
- return await this.raiseDeviceAlert(device.deviceId, device.propertyId, device.zoneId, "Device Online", `Device ${device.name} (${device.deviceId}) is now online. ${reason ? `Reason: ${reason}` : ""}`, alert_types_1.AlertCategory.OPERATIONS, alert_types_1.AlertSeverity.INFO, source);
190
+ return await this.raiseDeviceAlert({
191
+ entityId: device.deviceId,
192
+ propertyId: device.propertyId,
193
+ zoneId: device.zoneId,
194
+ title: "Device Online",
195
+ description: `Device ${device.name} is now online. ${reason ? `Reason: ${reason}` : ""}`,
196
+ category: alert_types_1.AlertCategory.OPERATIONS,
197
+ severity: alert_types_1.AlertSeverity.INFO,
198
+ createdBy: source,
199
+ entityType: alert_types_1.EntityType.DEVICE,
200
+ });
198
201
  }
199
202
  /**
200
203
  * Raise alert for device battery level below threshold (READINESS + OPERATIONAL + ENERGY)
201
204
  */
202
205
  async raiseDeviceBatteryAlert(device, batteryLevel, threshold, source) {
203
- return await this.raiseDeviceAlert(device.deviceId, device.propertyId, device.zoneId, "Device Battery Low", `Device ${device.name} (${device.deviceId}) battery level is ${batteryLevel}%, which is below the property threshold of ${threshold}%.`, alert_types_1.AlertCategory.ENERGY, alert_types_1.AlertSeverity.HIGH, source);
206
+ return await this.raiseDeviceAlert({
207
+ entityId: device.deviceId,
208
+ propertyId: device.propertyId,
209
+ zoneId: device.zoneId,
210
+ title: "Device Battery Low",
211
+ description: `Device ${device.name} (${device.deviceId}) battery level is ${batteryLevel}%, which is below the property threshold of ${threshold}%.`,
212
+ category: alert_types_1.AlertCategory.ENERGY,
213
+ severity: alert_types_1.AlertSeverity.HIGH,
214
+ createdBy: source,
215
+ entityType: alert_types_1.EntityType.DEVICE,
216
+ });
204
217
  }
205
218
  /**
206
219
  * Raise alert for device issue (jammed or malfunctioned) (READINESS + OPERATIONAL)
207
220
  */
208
221
  async raiseDeviceIssueAlert(device, issueType, source, reason) {
209
- return await this.raiseDeviceAlert(device.deviceId, device.propertyId, device.zoneId, `Device Issue - ${issueType}`, `Device ${device.name} (${device.deviceId}) has an issue: ${issueType}. ${reason ? `Reason: ${reason}` : ""}`, alert_types_1.AlertCategory.READINESS, alert_types_1.AlertSeverity.HIGH, source);
222
+ return await this.raiseDeviceAlert({
223
+ entityId: device.deviceId,
224
+ propertyId: device.propertyId,
225
+ zoneId: device.zoneId,
226
+ title: `Device Issue - ${issueType}`,
227
+ description: `Device ${device.name} has an issue: ${issueType}. ${reason ? `Reason: ${reason}` : ""}`,
228
+ category: alert_types_1.AlertCategory.OPERATIONS,
229
+ severity: alert_types_1.AlertSeverity.HIGH,
230
+ createdBy: source,
231
+ entityType: alert_types_1.EntityType.DEVICE,
232
+ });
210
233
  }
211
234
  /**
212
235
  * Create a new alert with business logic validation
@@ -538,7 +561,6 @@ let AlertService = (() => {
538
561
  determineDefaultSeverity(category) {
539
562
  // Business logic: Determine default severity based on category
540
563
  const categorySeverities = {
541
- [alert_types_1.AlertCategory.READINESS]: alert_types_1.AlertSeverity.LOW,
542
564
  [alert_types_1.AlertCategory.OPERATIONS]: alert_types_1.AlertSeverity.HIGH,
543
565
  [alert_types_1.AlertCategory.SECURITY]: alert_types_1.AlertSeverity.CRITICAL,
544
566
  [alert_types_1.AlertCategory.ENERGY]: alert_types_1.AlertSeverity.LOW,
@@ -73,10 +73,6 @@ export declare class AlertBuilder {
73
73
  * Resets the builder to its initial state
74
74
  */
75
75
  reset(): this;
76
- /**
77
- * Creates a new builder instance with predefined values for common alert types
78
- */
79
- static createReadinessAlert(): AlertBuilder;
80
76
  static createOperationsAlert(): AlertBuilder;
81
77
  static createSecurityAlert(): AlertBuilder;
82
78
  static createEnergyAlert(): AlertBuilder;
@@ -152,14 +152,6 @@ class AlertBuilder {
152
152
  this.data = {};
153
153
  return this;
154
154
  }
155
- /**
156
- * Creates a new builder instance with predefined values for common alert types
157
- */
158
- static createReadinessAlert() {
159
- return new AlertBuilder()
160
- .setCategory(alert_types_1.AlertCategory.READINESS)
161
- .setSeverity(alert_types_1.AlertSeverity.LOW);
162
- }
163
155
  static createOperationsAlert() {
164
156
  return new AlertBuilder()
165
157
  .setCategory(alert_types_1.AlertCategory.OPERATIONS)
@@ -1,6 +1,5 @@
1
1
  import { EntityType } from "../issues/issue.types";
2
2
  export declare enum AlertCategory {
3
- READINESS = "READINESS",
4
3
  OPERATIONS = "OPERATIONS",
5
4
  SECURITY = "SECURITY",
6
5
  ENERGY = "ENERGY",
@@ -3,7 +3,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.EntityType = exports.AlertSeverity = exports.AlertCategory = void 0;
4
4
  var AlertCategory;
5
5
  (function (AlertCategory) {
6
- AlertCategory["READINESS"] = "READINESS";
7
6
  AlertCategory["OPERATIONS"] = "OPERATIONS";
8
7
  AlertCategory["SECURITY"] = "SECURITY";
9
8
  AlertCategory["ENERGY"] = "ENERGY";
@@ -172,27 +172,26 @@ export declare const DT_EVENT_TYPES: {
172
172
  };
173
173
  UPDATE: {
174
174
  SUCCESS: string;
175
+ FAILED: string;
175
176
  };
176
177
  DELETE: {
177
178
  SUCCESS: string;
178
- };
179
- CANCEL: {
180
- SUCCESS: string;
181
- };
182
- RESOLVE: {
183
- SUCCESS: string;
179
+ FAILED: string;
184
180
  };
185
181
  };
186
182
  ALERT: {
187
183
  CREATE: {
188
184
  SUCCESS: string;
185
+ FAILED: string;
189
186
  SKIPPED: string;
190
187
  };
191
188
  UPDATE: {
192
189
  SUCCESS: string;
190
+ FAILED: string;
193
191
  };
194
192
  DELETE: {
195
193
  SUCCESS: string;
194
+ FAILED: string;
196
195
  };
197
196
  };
198
197
  };
@@ -175,27 +175,26 @@ exports.DT_EVENT_TYPES = {
175
175
  },
176
176
  UPDATE: {
177
177
  SUCCESS: "issue.update.success",
178
+ FAILED: "issue.update.failed",
178
179
  },
179
180
  DELETE: {
180
181
  SUCCESS: "issue.delete.success",
182
+ FAILED: "issue.delete.failed",
181
183
  },
182
- CANCEL: {
183
- SUCCESS: "issue.cancel.success",
184
- },
185
- RESOLVE: {
186
- SUCCESS: "issue.resolve.success",
187
- }
188
184
  },
189
185
  ALERT: {
190
186
  CREATE: {
191
187
  SUCCESS: "alert.create.success",
188
+ FAILED: "alert.create.failed",
192
189
  SKIPPED: "alert.create.skipped",
193
190
  },
194
191
  UPDATE: {
195
192
  SUCCESS: "alert.update.success",
193
+ FAILED: "alert.update.failed",
196
194
  },
197
195
  DELETE: {
198
196
  SUCCESS: "alert.delete.success",
197
+ FAILED: "alert.delete.failed",
199
198
  },
200
199
  },
201
200
  };
package/dist/db/db.js CHANGED
@@ -44,10 +44,10 @@ const connectDatabase = async () => {
44
44
  try {
45
45
  const URI = (0, config_1.getMongoUri)();
46
46
  await mongoose_1.default.connect(URI);
47
- console.log(`Connected to MongoDB at ${URI.split("/").at(-1)}`);
47
+ (0, config_1.getLogger)().info(`Connected to MongoDB at ${URI.split("/").at(-1)}`);
48
48
  }
49
49
  catch (error) {
50
- console.error("Error connecting to MongoDB:", error);
50
+ (0, config_1.getLogger)().error("Error connecting to MongoDB:", error);
51
51
  }
52
52
  };
53
53
  exports.connectDatabase = connectDatabase;
@@ -1,6 +1,7 @@
1
1
  import { IAccessGroup, IUser, IZone } from "./IAdmin";
2
2
  export declare class AdminService {
3
3
  private readonly adminRepository;
4
+ private readonly redisUtils;
4
5
  constructor();
5
6
  getZonesByAccessGroupIds(accessGroupIds: string[]): Promise<any[] | undefined>;
6
7
  getZonesByAccessGroups(accessGroupIds: string[]): Promise<any[] | undefined>;
@@ -74,6 +74,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
74
74
  exports.AdminService = void 0;
75
75
  const typedi_1 = __importStar(require("typedi"));
76
76
  const Admin_repository_1 = require("./Admin.repository");
77
+ const redis_utils_1 = require("../../utils/redis.utils");
77
78
  let AdminService = (() => {
78
79
  let _classDecorators = [(0, typedi_1.Service)()];
79
80
  let _classDescriptor;
@@ -82,6 +83,7 @@ let AdminService = (() => {
82
83
  var AdminService = _classThis = class {
83
84
  constructor() {
84
85
  this.adminRepository = typedi_1.default.get(Admin_repository_1.AdminRepository);
86
+ this.redisUtils = typedi_1.default.get(redis_utils_1.RedisUtils);
85
87
  }
86
88
  async getZonesByAccessGroupIds(accessGroupIds) {
87
89
  try {
@@ -124,6 +126,10 @@ let AdminService = (() => {
124
126
  if (!zoneId) {
125
127
  throw new Error("Zone ID is required");
126
128
  }
129
+ const cachedZone = await this.redisUtils.get(`zone:${zoneId}`);
130
+ if (cachedZone)
131
+ return JSON.parse(cachedZone);
132
+ // Do Not Cache Zone if not found in Redis Here! Its being cached in Smart-Cloud
127
133
  const zone = await this.adminRepository.getZone(zoneId);
128
134
  if (!zone)
129
135
  return null;
@@ -61,6 +61,10 @@ const IssueSchema = new mongoose_1.Schema({
61
61
  required: false,
62
62
  index: true,
63
63
  },
64
+ zoneName: {
65
+ type: String,
66
+ required: false,
67
+ },
64
68
  title: {
65
69
  type: String,
66
70
  required: true,
@@ -6,10 +6,6 @@ import { IDevice } from "../entities/device/local/interfaces";
6
6
  export declare class IssueService {
7
7
  private readonly issueRepository;
8
8
  constructor();
9
- /**
10
- * Create a readiness issue using IssueBuilder
11
- */
12
- createReadinessIssue(data: CreateIssueData): Promise<IIssueDocument | null>;
13
9
  /**
14
10
  * Create an operations issue using IssueBuilder
15
11
  */
@@ -117,6 +113,11 @@ export declare class IssueService {
117
113
  * Unassign an issue
118
114
  */
119
115
  unassignIssue(id: string, unassignedBy: string): Promise<IIssueDocument | null>;
116
+ /**
117
+ * Cancel/Close/Resolve an issue based on query
118
+ * This method will find an issue matching the query and update its status
119
+ */
120
+ performIssueAction(query: IIssueQuery, action: "cancel" | "close" | "resolve" | "ignore" | "in_progress" | "on_hold", updatedBy: string): Promise<IIssueDocument | null>;
120
121
  /**
121
122
  * Get issues assigned to a user with business logic
122
123
  */
@@ -77,6 +77,7 @@ const Issue_repository_1 = require("./Issue.repository");
77
77
  const Issue_model_1 = require("./Issue.model");
78
78
  const issue_types_1 = require("./issue.types");
79
79
  const IssueBuilder_1 = require("./IssueBuilder");
80
+ const Service_1 = require("../constants/Service");
80
81
  const Admin_service_1 = require("../entities/admin/Admin.service");
81
82
  const audit_1 = require("../audit");
82
83
  const constants_1 = require("../constants");
@@ -90,29 +91,6 @@ let IssueService = (() => {
90
91
  constructor() {
91
92
  this.issueRepository = typedi_1.default.get(Issue_repository_1.IssueRepository);
92
93
  }
93
- /**
94
- * Create a readiness issue using IssueBuilder
95
- */
96
- async createReadinessIssue(data) {
97
- const issueBuilder = IssueBuilder_1.IssueBuilder.createReadinessIssue()
98
- .setPropertyId(data.propertyId)
99
- .setTitle(data.title)
100
- .setDescription(data.description)
101
- .setCreatedBy(data.createdBy);
102
- if (data.entityId)
103
- issueBuilder.setEntityId(data.entityId);
104
- if (data.entityType)
105
- issueBuilder.setEntityType(data.entityType);
106
- if (data.assignedTo)
107
- issueBuilder.setAssignedTo(data.assignedTo);
108
- if (data.dueDate)
109
- issueBuilder.setDueDate(data.dueDate);
110
- if (data.zoneId)
111
- issueBuilder.setZoneId(data.zoneId);
112
- if (data.type)
113
- issueBuilder.setType(data.type);
114
- return await this.createIssue(issueBuilder);
115
- }
116
94
  /**
117
95
  * Create an operations issue using IssueBuilder
118
96
  */
@@ -356,51 +334,88 @@ let IssueService = (() => {
356
334
  * Accepts either a CreateIssueData object or an IssueBuilder instance
357
335
  */
358
336
  async createIssue(issueData) {
359
- let processedIssueData;
360
- // Handle IssueBuilder instance
361
- if (issueData instanceof IssueBuilder_1.IssueBuilder) {
362
- processedIssueData = issueData.build();
363
- }
364
- else {
365
- processedIssueData = issueData;
366
- }
367
- // Business logic: Validate issue data
368
- this.validateIssueData(processedIssueData);
369
- // Business logic: Set default priority if not provided
370
- if (!processedIssueData.priority) {
371
- processedIssueData.priority = this.determineDefaultPriority(processedIssueData.category);
372
- }
373
- // Business logic: Validate due date is in the future
374
- if (processedIssueData.dueDate &&
375
- processedIssueData.dueDate <= new Date()) {
376
- throw new Error("Due date must be in the future");
377
- }
378
- const existingIssue = await this.issueRepository.query({
379
- propertyId: processedIssueData.propertyId,
380
- entityId: processedIssueData.entityId,
381
- entityType: processedIssueData.entityType,
382
- entitySubType: processedIssueData.entitySubType,
383
- type: processedIssueData.type,
384
- });
385
- if (existingIssue.length > 0) {
337
+ try {
338
+ let processedIssueData;
339
+ // Handle IssueBuilder instance
340
+ if (issueData instanceof IssueBuilder_1.IssueBuilder) {
341
+ processedIssueData = issueData.build();
342
+ }
343
+ else {
344
+ processedIssueData = issueData;
345
+ }
346
+ // Business logic: Validate issue data
347
+ this.validateIssueData(processedIssueData);
348
+ // Business logic: Set default priority if not provided
349
+ if (!processedIssueData.priority) {
350
+ processedIssueData.priority = this.determineDefaultPriority(processedIssueData.category);
351
+ }
352
+ // Business logic: Validate due date is in the future
353
+ if (processedIssueData.dueDate &&
354
+ processedIssueData.dueDate <= new Date()) {
355
+ throw new Error("Due date must be in the future");
356
+ }
357
+ if (processedIssueData?.zoneId && !processedIssueData?.zoneName) {
358
+ const zone = await typedi_1.default.get(Admin_service_1.AdminService).getZone(processedIssueData.zoneId);
359
+ processedIssueData.zoneName = zone?.name || "";
360
+ }
361
+ const existingIssue = await this.query({
362
+ propertyId: processedIssueData.propertyId,
363
+ zoneId: processedIssueData.zoneId,
364
+ entityId: processedIssueData.entityId,
365
+ entityType: processedIssueData.entityType,
366
+ entitySubType: processedIssueData.entitySubType,
367
+ type: processedIssueData.type,
368
+ });
369
+ if (existingIssue.length > 0) {
370
+ await (0, audit_1.pushAudit)({
371
+ auditType: constants_1.DT_EVENT_TYPES.ISSUE.CREATE.SKIPPED,
372
+ auditData: {
373
+ reason: "Issue already exists",
374
+ propertyId: processedIssueData.propertyId,
375
+ entityId: processedIssueData.entityId,
376
+ entityType: processedIssueData.entityType,
377
+ entitySubType: processedIssueData.entitySubType,
378
+ type: processedIssueData.type,
379
+ resource: audit_1.Resource.ISSUE,
380
+ source: processedIssueData.createdBy,
381
+ },
382
+ });
383
+ return null;
384
+ }
385
+ const issue = await this.issueRepository.create(processedIssueData);
386
386
  await (0, audit_1.pushAudit)({
387
- auditType: constants_1.DT_EVENT_TYPES.ISSUE.CREATE.SKIPPED,
387
+ auditType: constants_1.DT_EVENT_TYPES.ISSUE.CREATE.SUCCESS,
388
388
  auditData: {
389
- reason: "Issue already exists",
389
+ resource: audit_1.Resource.ISSUE,
390
+ source: Service_1.Source.USER,
390
391
  propertyId: processedIssueData.propertyId,
392
+ zoneId: processedIssueData.zoneId,
391
393
  entityId: processedIssueData.entityId,
392
394
  entityType: processedIssueData.entityType,
393
395
  entitySubType: processedIssueData.entitySubType,
394
396
  type: processedIssueData.type,
397
+ createdBy: processedIssueData.createdBy,
398
+ createdAt: new Date(),
399
+ },
400
+ });
401
+ await dt_pub_sub_1.eventDispatcher.publishEvent(constants_1.DT_EVENT_TYPES.ISSUE.CREATE.SUCCESS, issue, "dt-common-device");
402
+ return issue;
403
+ }
404
+ catch (error) {
405
+ await (0, audit_1.pushAudit)({
406
+ auditType: constants_1.DT_EVENT_TYPES.ISSUE.CREATE.FAILED,
407
+ auditData: {
395
408
  resource: audit_1.Resource.ISSUE,
396
- source: processedIssueData.createdBy,
409
+ source: Service_1.Source.USER,
410
+ propertyId: issueData?.propertyId || "",
411
+ zoneId: issueData?.zoneId || "",
412
+ errorMessage: error.message,
413
+ error: error,
414
+ createdBy: issueData?.createdBy || "",
397
415
  },
398
416
  });
399
- return null;
417
+ throw error;
400
418
  }
401
- const issue = await this.issueRepository.create(processedIssueData);
402
- await dt_pub_sub_1.eventDispatcher.publishEvent(constants_1.DT_EVENT_TYPES.ISSUE.CREATE.SUCCESS, issue, "dt-common-device");
403
- return issue;
404
419
  }
405
420
  /**
406
421
  * Get issue by ID with business logic
@@ -613,6 +628,106 @@ let IssueService = (() => {
613
628
  issueModel.unassign(unassignedBy);
614
629
  return await issueModel.save();
615
630
  }
631
+ /**
632
+ * Cancel/Close/Resolve an issue based on query
633
+ * This method will find an issue matching the query and update its status
634
+ */
635
+ async performIssueAction(query, action, updatedBy) {
636
+ try {
637
+ if (!updatedBy) {
638
+ throw new Error("Updated by user is required");
639
+ }
640
+ // Find the issue based on the query
641
+ const issues = await this.query(query);
642
+ if (issues.length === 0) {
643
+ return null; // No issue found matching the query
644
+ }
645
+ if (issues.length > 1) {
646
+ throw new Error(`Multiple issues found matching the query. Please provide more specific criteria.`);
647
+ }
648
+ const issue = issues[0];
649
+ // Check if issue can be cancelled/closed/resolved
650
+ if (issue.status === issue_types_1.IssueStatus.CANCELLED) {
651
+ throw new Error("Issue is already cancelled");
652
+ }
653
+ if (issue.status === issue_types_1.IssueStatus.CLOSED) {
654
+ throw new Error("Issue is already closed");
655
+ }
656
+ if (issue.status === issue_types_1.IssueStatus.RESOLVED) {
657
+ throw new Error("Issue is already resolved");
658
+ }
659
+ if (issue.status === issue_types_1.IssueStatus.IGNORED) {
660
+ throw new Error("Issue is already ignored");
661
+ }
662
+ // Determine the new status based on the action
663
+ let newStatus;
664
+ let updateData = {
665
+ updatedBy,
666
+ updatedAt: new Date(),
667
+ };
668
+ switch (action) {
669
+ case "in_progress":
670
+ newStatus = issue_types_1.IssueStatus.IN_PROGRESS;
671
+ break;
672
+ case "resolve":
673
+ newStatus = issue_types_1.IssueStatus.RESOLVED;
674
+ updateData.resolvedAt = new Date();
675
+ break;
676
+ case "close":
677
+ newStatus = issue_types_1.IssueStatus.CLOSED;
678
+ break;
679
+ case "cancel":
680
+ newStatus = issue_types_1.IssueStatus.CANCELLED;
681
+ break;
682
+ case "on_hold":
683
+ newStatus = issue_types_1.IssueStatus.ON_HOLD;
684
+ break;
685
+ case "ignore":
686
+ newStatus = issue_types_1.IssueStatus.IGNORED;
687
+ break;
688
+ default:
689
+ throw new Error("Invalid action. Must be 'cancel', 'close', or 'resolve'");
690
+ }
691
+ updateData.status = newStatus;
692
+ // Update the issue
693
+ const updatedIssue = await this.updateIssue(issue._id, updateData);
694
+ if (updatedIssue) {
695
+ // Log the action for audit purposes
696
+ console.log(`Issue ${issue._id} has been ${action}ed by ${updatedBy}`);
697
+ await (0, audit_1.pushAudit)({
698
+ auditType: constants_1.DT_EVENT_TYPES.ISSUE.UPDATE.SUCCESS,
699
+ auditData: {
700
+ resource: audit_1.Resource.ISSUE,
701
+ source: Service_1.Source.USER,
702
+ propertyId: issue.propertyId,
703
+ zoneId: issue.zoneId,
704
+ oldStatus: issue.status,
705
+ newStatus,
706
+ action,
707
+ updatedBy,
708
+ updatedAt: new Date(),
709
+ },
710
+ });
711
+ }
712
+ return updatedIssue;
713
+ }
714
+ catch (error) {
715
+ await (0, audit_1.pushAudit)({
716
+ auditType: constants_1.DT_EVENT_TYPES.ISSUE.UPDATE.FAILED,
717
+ auditData: {
718
+ resource: audit_1.Resource.ISSUE,
719
+ source: Service_1.Source.USER,
720
+ propertyId: query.propertyId || "",
721
+ zoneId: query.zoneId || "",
722
+ errorMessage: error.message,
723
+ error: error,
724
+ updatedBy,
725
+ updatedAt: new Date(),
726
+ },
727
+ });
728
+ throw error;
729
+ }
730
+ }
616
731
  /**
617
732
  * Get issues assigned to a user with business logic
618
733
  */
@@ -764,7 +879,6 @@ let IssueService = (() => {
764
879
  determineDefaultPriority(category) {
765
880
  // Business logic: Determine default priority based on category
766
881
  const categoryPriorities = {
767
- [issue_types_1.IssuesCategory.READINESS]: issue_types_1.IssuePriority.LOW,
768
882
  [issue_types_1.IssuesCategory.OPERATIONS]: issue_types_1.IssuePriority.HIGH,
769
883
  [issue_types_1.IssuesCategory.SECURITY]: issue_types_1.IssuePriority.CRITICAL,
770
884
  [issue_types_1.IssuesCategory.ENERGY]: issue_types_1.IssuePriority.HIGH,
@@ -87,10 +87,6 @@ export declare class IssueBuilder {
87
87
  * Resets the builder to its initial state
88
88
  */
89
89
  reset(): this;
90
- /**
91
- * Creates a new builder instance with predefined values for common issue types
92
- */
93
- static createReadinessIssue(): IssueBuilder;
94
90
  static createOperationsIssue(): IssueBuilder;
95
91
  static createSecurityIssue(): IssueBuilder;
96
92
  static createEnergyIssue(): IssueBuilder;
@@ -182,14 +182,6 @@ class IssueBuilder {
182
182
  this.data = {};
183
183
  return this;
184
184
  }
185
- /**
186
- * Creates a new builder instance with predefined values for common issue types
187
- */
188
- static createReadinessIssue() {
189
- return new IssueBuilder()
190
- .setCategory(issue_types_1.IssuesCategory.READINESS)
191
- .setPriority(issue_types_1.IssuePriority.LOW);
192
- }
193
185
  static createOperationsIssue() {
194
186
  return new IssueBuilder()
195
187
  .setCategory(issue_types_1.IssuesCategory.OPERATIONS)
@@ -255,7 +247,7 @@ class IssueBuilder {
255
247
  */
256
248
  static createMaintenanceIssue(propertyId, type, entityId, entityType) {
257
249
  const builder = new IssueBuilder()
258
- .setCategory(issue_types_1.IssuesCategory.READINESS)
250
+ .setCategory(issue_types_1.IssuesCategory.OPERATIONS)
259
251
  .setPropertyId(propertyId)
260
252
  .setType(type)
261
253
  .setPriority(issue_types_1.IssuePriority.LOW);
@@ -1,5 +1,4 @@
1
1
  export declare enum IssuesCategory {
2
- READINESS = "READINESS",
3
2
  OPERATIONS = "OPERATIONS",
4
3
  SECURITY = "SECURITY",
5
4
  ENERGY = "ENERGY",
@@ -71,6 +70,7 @@ export interface IssueDocument {
71
70
  category: IssuesCategory;
72
71
  propertyId: string;
73
72
  zoneId?: string;
73
+ zoneName?: string;
74
74
  title: string;
75
75
  description: string;
76
76
  entityId?: string;
@@ -93,6 +93,7 @@ export interface CreateIssueData {
93
93
  category: IssuesCategory;
94
94
  propertyId: string;
95
95
  zoneId?: string;
96
+ zoneName?: string;
96
97
  title: string;
97
98
  description: string;
98
99
  entityId: string;
@@ -116,6 +117,7 @@ export interface UpdateIssueData {
116
117
  priority?: IssuePriority;
117
118
  assignedTo?: string;
118
119
  updatedBy?: string;
120
+ updatedAt?: Date;
119
121
  resolvedAt?: Date;
120
122
  dueDate?: Date;
121
123
  isDeleted?: boolean;
@@ -127,6 +129,7 @@ export interface AddCommentData {
127
129
  export interface IIssueQuery {
128
130
  propertyId?: string;
129
131
  zoneId?: string;
132
+ zoneName?: string;
130
133
  assignedTo?: string;
131
134
  status?: IssueStatus;
132
135
  priority?: IssuePriority;
@@ -3,7 +3,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.IssueType = exports.IssuePriority = exports.IssueStatus = exports.EntitySubType = exports.EntityType = exports.IssuesCategory = void 0;
4
4
  var IssuesCategory;
5
5
  (function (IssuesCategory) {
6
- IssuesCategory["READINESS"] = "READINESS";
7
6
  IssuesCategory["OPERATIONS"] = "OPERATIONS";
8
7
  IssuesCategory["SECURITY"] = "SECURITY";
9
8
  IssuesCategory["ENERGY"] = "ENERGY";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dt-common-device",
3
- "version": "7.2.0",
3
+ "version": "7.2.1",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "files": [