dt-common-device 3.0.1 → 3.0.3

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.
Files changed (87) hide show
  1. package/README.md +7 -2
  2. package/dist/alerts/Alert.model.js +8 -2
  3. package/dist/alerts/Alert.repository.d.ts +3 -3
  4. package/dist/alerts/Alert.repository.js +28 -5
  5. package/dist/alerts/Alert.service.d.ts +18 -4
  6. package/dist/alerts/Alert.service.js +34 -3
  7. package/dist/alerts/AlertBuilder.d.ts +1 -1
  8. package/dist/alerts/AlertBuilder.js +1 -1
  9. package/dist/alerts/AlertService.example.js +5 -3
  10. package/dist/alerts/alert.types.d.ts +3 -3
  11. package/dist/config/config.d.ts +1 -1
  12. package/dist/config/config.js +3 -3
  13. package/dist/connection/Connection.repository.js +1 -1
  14. package/dist/constants/ConnectionProviders.d.ts +11 -0
  15. package/dist/constants/ConnectionProviders.js +14 -0
  16. package/dist/constants/Event.d.ts +14 -0
  17. package/dist/constants/Event.js +14 -0
  18. package/dist/constants/Service.d.ts +15 -0
  19. package/dist/constants/Service.js +19 -0
  20. package/dist/constants/index.d.ts +3 -0
  21. package/dist/constants/index.js +19 -0
  22. package/dist/device/cloud/entities/CloudDevice.d.ts +2 -2
  23. package/dist/device/cloud/entities/CloudDeviceService.d.ts +1 -1
  24. package/dist/device/cloud/entities/DeviceFactory.d.ts +1 -1
  25. package/dist/device/cloud/entities/DeviceFactory.js +1 -1
  26. package/dist/device/local/interfaces/IDevice.d.ts +3 -2
  27. package/dist/device/local/repository/Device.repository.js +3 -3
  28. package/dist/device/local/repository/Hub.repository.js +3 -3
  29. package/dist/device/local/repository/Schedule.repository.js +2 -2
  30. package/dist/device/local/services/Device.service.d.ts +11 -2
  31. package/dist/device/local/services/Device.service.js +145 -25
  32. package/dist/events/BaseEventHandler.d.ts +2 -2
  33. package/dist/events/BaseEventHandler.js +2 -2
  34. package/dist/events/BaseEventTransformer.d.ts +1 -1
  35. package/dist/events/BaseEventTransformer.js +1 -1
  36. package/dist/events/DeviceEventHandler.d.ts +1 -1
  37. package/dist/events/DeviceEventHandler.js +4 -3
  38. package/dist/events/EventHandler.js +1 -1
  39. package/dist/events/EventHandlerOrchestrator.js +1 -1
  40. package/dist/events/EventProcessingService.js +1 -1
  41. package/dist/events/InternalEventSubscription.js +1 -1
  42. package/dist/index.d.ts +1 -0
  43. package/dist/index.js +2 -0
  44. package/dist/issues/Issue.service.d.ts +11 -1
  45. package/dist/issues/Issue.service.js +16 -3
  46. package/dist/issues/IssueService.example.js +4 -2
  47. package/dist/queue/entities/HybridHttpQueue.d.ts +1 -0
  48. package/dist/queue/entities/HybridHttpQueue.js +2 -1
  49. package/dist/queue/interfaces/IHybridHttpQueue.d.ts +1 -0
  50. package/dist/queue/services/QueueService.d.ts +1 -0
  51. package/dist/queue/types/http.types.d.ts +1 -0
  52. package/package.json +1 -1
  53. package/src/alerts/Alert.model.ts +8 -2
  54. package/src/alerts/Alert.repository.ts +28 -6
  55. package/src/alerts/Alert.service.ts +91 -7
  56. package/src/alerts/AlertBuilder.ts +2 -2
  57. package/src/alerts/AlertService.example.ts +5 -3
  58. package/src/alerts/alert.types.ts +3 -3
  59. package/src/config/config.ts +3 -3
  60. package/src/connection/Connection.repository.ts +1 -1
  61. package/src/constants/ConnectionProviders.ts +11 -0
  62. package/src/constants/Event.ts +14 -0
  63. package/src/constants/Service.ts +17 -0
  64. package/src/constants/index.ts +3 -0
  65. package/src/device/cloud/entities/CloudDevice.ts +2 -2
  66. package/src/device/cloud/entities/CloudDeviceService.ts +1 -1
  67. package/src/device/cloud/entities/DeviceFactory.ts +2 -2
  68. package/src/device/local/interfaces/IDevice.ts +3 -2
  69. package/src/device/local/repository/Device.repository.ts +3 -3
  70. package/src/device/local/repository/Hub.repository.ts +3 -3
  71. package/src/device/local/repository/Schedule.repository.ts +2 -2
  72. package/src/device/local/services/Device.service.ts +231 -29
  73. package/src/events/BaseEventHandler.ts +3 -3
  74. package/src/events/BaseEventTransformer.ts +2 -2
  75. package/src/events/DeviceEventHandler.ts +6 -4
  76. package/src/events/EventHandler.ts +1 -1
  77. package/src/events/EventHandlerOrchestrator.ts +2 -2
  78. package/src/events/EventProcessingService.ts +2 -2
  79. package/src/events/InternalEventSubscription.ts +2 -2
  80. package/src/index.ts +3 -0
  81. package/src/issues/Issue.service.ts +67 -7
  82. package/src/issues/IssueService.example.ts +4 -2
  83. package/src/queue/entities/HybridHttpQueue.ts +3 -1
  84. package/src/queue/interfaces/IHybridHttpQueue.ts +1 -0
  85. package/src/queue/services/QueueService.ts +1 -0
  86. package/src/queue/types/http.types.ts +1 -0
  87. package/tsconfig.json +0 -4
@@ -1,15 +1,26 @@
1
1
  import { IDevice, IStatus } from "../interfaces";
2
- import { EventHandler } from "src/events/EventHandler";
2
+ import { EventHandler } from "../../../events/EventHandler";
3
3
  import { isEqual } from "lodash";
4
4
  import { DeviceRepository } from "../repository/Device.repository";
5
5
  import Container from "typedi";
6
+ import { AlertService } from "../../../alerts/Alert.service";
7
+ import { IssueService } from "../../../issues/Issue.service";
8
+ import { Source } from "../../../constants/Service";
9
+ import { getConfig } from "../../../config/config";
6
10
 
7
11
  export class LocalDeviceService {
8
12
  private readonly eventHandler: EventHandler;
9
13
  private readonly deviceRepository: DeviceRepository;
14
+ private readonly alertService: AlertService;
15
+ private readonly issueService: IssueService;
16
+ private readonly logger;
17
+
10
18
  constructor() {
11
19
  this.eventHandler = new EventHandler();
12
20
  this.deviceRepository = Container.get(DeviceRepository);
21
+ this.alertService = Container.get(AlertService);
22
+ this.issueService = Container.get(IssueService);
23
+ this.logger = getConfig().LOGGER;
13
24
  }
14
25
 
15
26
  async createDevice(body: IDevice): Promise<IDevice> {
@@ -117,31 +128,168 @@ export class LocalDeviceService {
117
128
  return await this.deviceRepository.getStatus(deviceId);
118
129
  }
119
130
 
120
- async setStatus(deviceId: string, newStatus: IStatus) {
131
+ async setStatus(
132
+ deviceId: string,
133
+ newStatus: IStatus,
134
+ source: Source,
135
+ reason?: string
136
+ ) {
121
137
  if (!deviceId || !newStatus) {
122
138
  throw new Error("Device ID and new status are required");
123
139
  }
124
140
 
125
- const oldStatus = await this.getStatus(deviceId);
126
- const isStatusChanged = !isEqual(oldStatus, newStatus);
141
+ const device = await this.getDevice(deviceId);
142
+ const oldStatus = device.status;
143
+ const currentTime = new Date().toISOString();
144
+
145
+ // Determine if the new status is ONLINE or OFFLINE
146
+ const isNewStatusOnline = newStatus.liveStatus === "ONLINE";
147
+ const isNewStatusOffline = newStatus.liveStatus === "OFFLINE";
148
+
149
+ if (isNewStatusOffline) {
150
+ // New Status = OFFLINE
151
+ await this.handleOfflineStatus(
152
+ deviceId,
153
+ device,
154
+ oldStatus,
155
+ newStatus,
156
+ source,
157
+ reason,
158
+ currentTime
159
+ );
160
+ } else if (isNewStatusOnline) {
161
+ // New Status = ONLINE
162
+ await this.handleOnlineStatus(
163
+ deviceId,
164
+ device,
165
+ oldStatus,
166
+ newStatus,
167
+ source,
168
+ reason,
169
+ currentTime
170
+ );
171
+ } else {
172
+ // For any other status, just update normally
173
+ await this.deviceRepository.setStatus(deviceId, newStatus);
174
+ await this.eventHandler.onStatusChange(deviceId, newStatus);
175
+ }
176
+ }
177
+
178
+ private async handleOfflineStatus(
179
+ deviceId: string,
180
+ device: IDevice,
181
+ oldStatus: any,
182
+ newStatus: IStatus,
183
+ source: Source,
184
+ reason?: string,
185
+ currentTime?: string
186
+ ) {
187
+ const isExistingStatusOnline = oldStatus?.online === true;
188
+ const isExistingStatusOffline = oldStatus?.online === false;
189
+
190
+ if (isExistingStatusOnline) {
191
+ // Existing status is Online
192
+ newStatus.online = true;
193
+ newStatus.liveStatus = "OFFLINE";
194
+ newStatus.lastUpdated = currentTime;
195
+ newStatus.error = {
196
+ type: "offline",
197
+ message: reason || "Device went offline",
198
+ default: {},
199
+ };
127
200
 
128
- if (isStatusChanged) {
129
201
  await this.deviceRepository.setStatus(deviceId, newStatus);
130
202
  await this.eventHandler.onStatusChange(deviceId, newStatus);
203
+ } else if (isExistingStatusOffline) {
204
+ // Existing status is Offline
205
+ const timeLapsed = oldStatus?.lastUpdated
206
+ ? Date.now() - new Date(oldStatus.lastUpdated).getTime()
207
+ : 0;
208
+
209
+ const baselineTime = await this.getDeviceBaseline(deviceId);
210
+
211
+ if (timeLapsed > baselineTime) {
212
+ // When the time lapsed is higher than the baseline time
213
+ newStatus.online = false;
214
+ newStatus.liveStatus = "OFFLINE";
215
+ newStatus.lastUpdated = currentTime;
216
+ newStatus.error = {
217
+ type: "offline",
218
+ message: reason || "Device has been offline for longer than baseline",
219
+ default: {},
220
+ };
221
+
222
+ await this.deviceRepository.setStatus(deviceId, newStatus);
223
+ await this.eventHandler.onStatusChange(deviceId, newStatus);
224
+
225
+ // Raise alert
226
+ await this.alertService.raiseDeviceOfflineAlert(device, source, reason);
227
+
228
+ // Raise issue when the device goes offline if longer than the baseline
229
+ await this.issueService.createDeviceOfflineIssue(
230
+ device,
231
+ source,
232
+ reason
233
+ );
234
+ }
131
235
  }
236
+ }
237
+
238
+ private async handleOnlineStatus(
239
+ deviceId: string,
240
+ device: IDevice,
241
+ oldStatus: any,
242
+ newStatus: IStatus,
243
+ source: Source,
244
+ reason?: string,
245
+ currentTime?: string
246
+ ) {
247
+ const isExistingStatusOnline = oldStatus?.online === true;
248
+ const isExistingStatusOffline = oldStatus?.online === false;
132
249
 
133
- const isBothOffline =
134
- oldStatus?.online === false && newStatus?.online === false;
135
- if (isBothOffline && oldStatus?.lastUpdated) {
136
- const timeDifference =
137
- Date.now() - new Date(oldStatus.lastUpdated).getTime();
138
- if (timeDifference > 86400000) {
139
- //return await this.alertService.raiseOperationsAlert();
250
+ if (isExistingStatusOnline) {
251
+ // Existing status is Online
252
+ if (oldStatus?.liveStatus === "ONLINE") {
253
+ // liveStatus = Online → Do nothing
140
254
  return;
255
+ } else if (oldStatus?.liveStatus === "OFFLINE") {
256
+ // liveStatus = Offline → Follow the step #2 (same as existing status is Offline)
257
+ newStatus.online = true;
258
+ newStatus.liveStatus = "ONLINE";
259
+ newStatus.lastUpdated = currentTime;
260
+ newStatus.error = {}; // Clear the error
261
+
262
+ await this.deviceRepository.setStatus(deviceId, newStatus);
263
+ await this.eventHandler.onStatusChange(deviceId, newStatus);
264
+
265
+ //TODO: ALERT NEEDED?
266
+ // Raise alert
267
+ await this.alertService.raiseDeviceOnlineAlert(device, source, reason);
141
268
  }
269
+ } else if (isExistingStatusOffline) {
270
+ // Existing status is Offline
271
+ newStatus.online = true;
272
+ newStatus.liveStatus = "ONLINE";
273
+ newStatus.lastUpdated = currentTime;
274
+ newStatus.error = undefined; // Clear the error
275
+
276
+ await this.deviceRepository.setStatus(deviceId, newStatus);
277
+ await this.eventHandler.onStatusChange(deviceId, newStatus);
278
+
279
+ //TODO: ALERT NEEDED?
280
+ // Raise alert
281
+ await this.alertService.raiseDeviceOnlineAlert(device, source, reason);
142
282
  }
143
283
  }
144
284
 
285
+ private async getDeviceBaseline(deviceId: string): Promise<number> {
286
+ // TODO: Implement device baseline retrieval
287
+ // This should return the baseline time in milliseconds for the specific device
288
+ // For now, returning a default value of 5 minutes (300000ms)
289
+ // In a real implementation, this would fetch from device configuration or settings
290
+ return 3600000; // 1 hour in milliseconds
291
+ }
292
+
145
293
  async getBatteryLevel(deviceId: string) {
146
294
  if (!deviceId) {
147
295
  throw new Error("Device ID is required");
@@ -149,29 +297,83 @@ export class LocalDeviceService {
149
297
  return await this.deviceRepository.getBatteryLevel(deviceId);
150
298
  }
151
299
 
152
- async setBatteryLevel(deviceId: string, batteryLevel: number) {
300
+ async setBatteryLevel(
301
+ deviceId: string,
302
+ batteryLevel: number,
303
+ source: Source
304
+ ) {
305
+ if (!deviceId || batteryLevel === undefined || batteryLevel === null) {
306
+ throw new Error("Device ID and battery level are required");
307
+ }
308
+
309
+ // Get device information
310
+ const device = await this.getDevice(deviceId);
311
+
153
312
  // Fetch the old battery level state
154
- const oldBatteryLevel = await this.getBatteryLevel(deviceId);
313
+ const oldBatteryLevel = device.state?.batteryPercentage;
155
314
 
315
+ // Check if battery level has changed
156
316
  const isDifferent = !isEqual(oldBatteryLevel?.value, batteryLevel);
157
317
 
158
318
  if (isDifferent) {
159
- await this.deviceRepository.setBatteryLevel(deviceId, batteryLevel);
160
- await this.eventHandler.onBatteryLevelChange(deviceId, batteryLevel);
161
- }
162
-
163
- // Check if battery is low and not updated for 8 hours
164
- if (
165
- batteryLevel < 20 &&
166
- oldBatteryLevel?.value < 20 &&
167
- oldBatteryLevel?.lastUpdated &&
168
- new Date(oldBatteryLevel.lastUpdated).getTime() <
169
- Date.now() - 1000 * 60 * 60 * 8 // 8 hours in ms
170
- ) {
171
- // TODO: Raise an energy alert
172
- // await this.alertService.raiseEnergyAlert();
173
- return;
319
+ // Check if current time is greater than or equal to last updated time (8-hour logic)
320
+ const shouldUpdate = this.shouldUpdateBatteryLevel(
321
+ oldBatteryLevel?.lastUpdated
322
+ );
323
+
324
+ if (shouldUpdate) {
325
+ // Save the battery level in the device
326
+ await this.deviceRepository.setBatteryLevel(deviceId, batteryLevel);
327
+ await this.eventHandler.onBatteryLevelChange(deviceId, batteryLevel);
328
+
329
+ // Get property threshold
330
+ const propertyThreshold = await this.getPropertyBatteryThreshold(
331
+ device.propertyId
332
+ );
333
+
334
+ // Check if battery level is below threshold
335
+ if (batteryLevel < propertyThreshold) {
336
+ // Raise alert
337
+ await this.alertService.raiseDeviceBatteryAlert(
338
+ device,
339
+ batteryLevel,
340
+ propertyThreshold,
341
+ source
342
+ );
343
+
344
+ // Raise issue when the level is below threshold
345
+ await this.issueService.createDeviceBatteryIssue(
346
+ device,
347
+ batteryLevel,
348
+ propertyThreshold,
349
+ source
350
+ );
351
+ }
352
+ }
353
+ }
354
+ }
355
+
356
+ private shouldUpdateBatteryLevel(lastUpdated?: string): boolean {
357
+ if (!lastUpdated) {
358
+ return true; // No previous update, so we should update
174
359
  }
360
+
361
+ const lastUpdateTime = new Date(lastUpdated).getTime();
362
+ const currentTime = Date.now();
363
+ const eightHoursInMs = 8 * 60 * 60 * 1000; // 8 hours in milliseconds
364
+
365
+ // Return true if current time is greater than or equal to last updated time + 8 hours
366
+ return currentTime >= lastUpdateTime + eightHoursInMs;
367
+ }
368
+
369
+ private async getPropertyBatteryThreshold(
370
+ propertyId: string
371
+ ): Promise<number> {
372
+ // TODO: Implement property battery threshold retrieval
373
+ // This should return the battery threshold for the specific property
374
+ // For now, returning a default value of 20%
375
+ // In a real implementation, this would fetch from property configuration or settings
376
+ return 20; // 20% default threshold
175
377
  }
176
378
 
177
379
  async getMetaData(deviceId: string) {
@@ -1,8 +1,8 @@
1
1
  import { DeviceEvent } from "./interfaces/DeviceEvent";
2
2
  import { IEventHandler } from "./interfaces/IEventHandler";
3
- import { getConfig } from "src/config/config";
4
- import { ILogger } from "src/config/config.types";
5
- import { LocalDeviceService } from "src/device/local/services/Device.service";
3
+ import { getConfig } from "../config/config";
4
+ import { ILogger } from "../config/config.types";
5
+ import { LocalDeviceService } from "../device/local/services/Device.service";
6
6
 
7
7
  export abstract class BaseEventHandler implements IEventHandler {
8
8
  protected readonly supportedEventTypes: string[];
@@ -1,5 +1,5 @@
1
- import { getConfig } from "src/config/config";
2
- import { ILogger } from "src/config/config.types";
1
+ import { getConfig } from "../config/config";
2
+ import { ILogger } from "../config/config.types";
3
3
  import { DeviceEvent } from "./interfaces/DeviceEvent";
4
4
  import { IEventTransformer } from "./interfaces/IEventTransformer";
5
5
 
@@ -1,6 +1,7 @@
1
- import { DT_EVENT_TYPES } from "src/constants/Event";
2
- import { IDevice } from "src/device/local/interfaces";
3
- import { LocalHubService } from "src/device/local/services";
1
+ import { Source } from "../constants";
2
+ import { DT_EVENT_TYPES } from "../constants/Event";
3
+ import { IDevice } from "../device/local/interfaces";
4
+ import { LocalHubService } from "../device/local/services";
4
5
  import { BaseEventHandler } from "./BaseEventHandler";
5
6
  import {
6
7
  DeviceEvent,
@@ -82,7 +83,8 @@ export class DeviceEventHandler extends BaseEventHandler {
82
83
  case DT_EVENT_TYPES.DEVICE.BATTERY.CHANGED:
83
84
  await this.localDeviceService.setBatteryLevel(
84
85
  deviceData.deviceId,
85
- event?.data?.batteryLevel ?? 0
86
+ event?.data?.batteryLevel ?? 0,
87
+ Source.CLOUD_EVENT
86
88
  );
87
89
  break;
88
90
  }
@@ -1,6 +1,6 @@
1
1
  import { eventDispatcher } from "dt-pub-sub";
2
2
  import { publishAudit } from "dt-audit-library";
3
- import { DT_EVENT_TYPES } from "src/constants/Event";
3
+ import { DT_EVENT_TYPES } from "../constants/Event";
4
4
 
5
5
  export class EventHandler {
6
6
  private readonly source: string;
@@ -1,8 +1,8 @@
1
1
  import { Service } from "typedi";
2
2
  import { IEventHandler } from "./interfaces/IEventHandler";
3
3
  import { DeviceEvent } from "./interfaces/DeviceEvent";
4
- import { ILogger } from "src/config/config.types";
5
- import { getConfig } from "src/config/config";
4
+ import { ILogger } from "../config/config.types";
5
+ import { getConfig } from "../config/config";
6
6
 
7
7
  @Service()
8
8
  export class EventHandlerOrchestrator {
@@ -1,7 +1,7 @@
1
1
  import { Service } from "typedi";
2
2
  import { DeviceEventHandler } from "./DeviceEventHandler";
3
- import { ILogger } from "src/config/config.types";
4
- import { getConfig } from "src/config/config";
3
+ import { ILogger } from "../config/config.types";
4
+ import { getConfig } from "../config/config";
5
5
  import { DeviceEvent } from "./interfaces/DeviceEvent";
6
6
  import { IEventTransformer } from "./interfaces/IEventTransformer";
7
7
  import { EventHandlerOrchestrator } from "./EventHandlerOrchestrator";
@@ -1,5 +1,5 @@
1
1
  import { eventDispatcher } from "dt-pub-sub";
2
- import { getConfig } from "src/config/config";
2
+ import { getConfig } from "../config/config";
3
3
  import {
4
4
  IInternalEvent,
5
5
  HeartbeatEventData,
@@ -7,7 +7,7 @@ import {
7
7
  ReservationEventData,
8
8
  ServiceEventData,
9
9
  } from "./interfaces/IInternalEvent";
10
- import { ILogger } from "src/config/config.types";
10
+ import { ILogger } from "../config/config.types";
11
11
 
12
12
  // Event types enum for better type safety
13
13
  export enum InternalEventType {
package/src/index.ts CHANGED
@@ -1,5 +1,8 @@
1
1
  // Main entry point for dt-common-device
2
2
 
3
+ // CONSTANTS EXPORTS
4
+ export * from "./constants";
5
+
3
6
  // DEVICE EXPORTS
4
7
  export {
5
8
  CloudDevice,
@@ -11,6 +11,8 @@ import {
11
11
  EntityType,
12
12
  } from "./issue.types";
13
13
  import { IssueBuilder } from "./IssueBuilder";
14
+ import { Source } from "../constants/Service";
15
+ import { IDevice } from "../device/local/interfaces";
14
16
 
15
17
  @Service()
16
18
  export class IssueService {
@@ -132,7 +134,7 @@ export class IssueService {
132
134
  propertyId: string,
133
135
  title: string,
134
136
  description: string,
135
- createdBy: string,
137
+ source: Source,
136
138
  category?: IssuesCategory,
137
139
  priority?: IssuePriority,
138
140
  assignedTo?: string,
@@ -141,7 +143,7 @@ export class IssueService {
141
143
  const issueBuilder = IssueBuilder.createDeviceIssue(deviceId, propertyId)
142
144
  .setTitle(title)
143
145
  .setDescription(description)
144
- .setCreatedBy(createdBy);
146
+ .setCreatedBy(source);
145
147
 
146
148
  if (category) issueBuilder.setCategory(category);
147
149
  if (priority) issueBuilder.setPriority(priority);
@@ -205,6 +207,49 @@ export class IssueService {
205
207
  return await this.createIssue(issueBuilder);
206
208
  }
207
209
 
210
+ /**
211
+ * Create issue for device going offline longer than baseline
212
+ */
213
+ async createDeviceOfflineIssue(
214
+ device: IDevice,
215
+ source: Source,
216
+ reason?: string
217
+ ): Promise<IIssueDocument> {
218
+ return await this.createDeviceIssue(
219
+ device.deviceId,
220
+ device.propertyId,
221
+ "Device Offline - Requires Attention",
222
+ `Device ${device.name} (${
223
+ device.deviceId
224
+ }) has been offline for longer than the baseline time. ${
225
+ reason ? `Reason: ${reason}` : ""
226
+ } This requires immediate attention to restore device functionality.`,
227
+ source,
228
+ IssuesCategory.OPERATIONS,
229
+ IssuePriority.HIGH
230
+ );
231
+ }
232
+
233
+ /**
234
+ * Create issue for device battery level below threshold
235
+ */
236
+ async createDeviceBatteryIssue(
237
+ device: IDevice,
238
+ batteryLevel: number,
239
+ threshold: number,
240
+ source: Source
241
+ ): Promise<IIssueDocument> {
242
+ return await this.createDeviceIssue(
243
+ device.deviceId,
244
+ device.propertyId,
245
+ "Device Battery Low - Requires Attention",
246
+ `Device ${device.name} (${device.deviceId}) battery level is ${batteryLevel}%, which is below the property threshold of ${threshold}%. This requires immediate attention to replace or charge the device battery.`,
247
+ source,
248
+ IssuesCategory.ENERGY,
249
+ IssuePriority.MEDIUM
250
+ );
251
+ }
252
+
208
253
  /**
209
254
  * Create a maintenance issue using IssueBuilder
210
255
  */
@@ -218,7 +263,11 @@ export class IssueService {
218
263
  assignedTo?: string,
219
264
  dueDate?: Date
220
265
  ): Promise<IIssueDocument> {
221
- const issueBuilder = IssueBuilder.createMaintenanceIssue(propertyId, entityId, entityType)
266
+ const issueBuilder = IssueBuilder.createMaintenanceIssue(
267
+ propertyId,
268
+ entityId,
269
+ entityType
270
+ )
222
271
  .setTitle(title)
223
272
  .setDescription(description)
224
273
  .setCreatedBy(createdBy);
@@ -242,7 +291,11 @@ export class IssueService {
242
291
  assignedTo?: string,
243
292
  dueDate?: Date
244
293
  ): Promise<IIssueDocument> {
245
- const issueBuilder = IssueBuilder.createUrgentIssue(propertyId, entityId, entityType)
294
+ const issueBuilder = IssueBuilder.createUrgentIssue(
295
+ propertyId,
296
+ entityId,
297
+ entityType
298
+ )
246
299
  .setTitle(title)
247
300
  .setDescription(description)
248
301
  .setCreatedBy(createdBy);
@@ -257,7 +310,9 @@ export class IssueService {
257
310
  * Create a new issue with business logic validation
258
311
  * Accepts either a CreateIssueData object or an IssueBuilder instance
259
312
  */
260
- async createIssue(issueData: CreateIssueData | IssueBuilder): Promise<IIssueDocument> {
313
+ async createIssue(
314
+ issueData: CreateIssueData | IssueBuilder
315
+ ): Promise<IIssueDocument> {
261
316
  let processedIssueData: CreateIssueData;
262
317
 
263
318
  // Handle IssueBuilder instance
@@ -272,11 +327,16 @@ export class IssueService {
272
327
 
273
328
  // Business logic: Set default priority if not provided
274
329
  if (!processedIssueData.priority) {
275
- processedIssueData.priority = this.determineDefaultPriority(processedIssueData.category);
330
+ processedIssueData.priority = this.determineDefaultPriority(
331
+ processedIssueData.category
332
+ );
276
333
  }
277
334
 
278
335
  // Business logic: Validate due date is in the future
279
- if (processedIssueData.dueDate && processedIssueData.dueDate <= new Date()) {
336
+ if (
337
+ processedIssueData.dueDate &&
338
+ processedIssueData.dueDate <= new Date()
339
+ ) {
280
340
  throw new Error("Due date must be in the future");
281
341
  }
282
342
 
@@ -1,3 +1,4 @@
1
+ import { Source } from "../constants";
1
2
  import { IssueService } from "./Issue.service";
2
3
  import { IssueBuilder } from "./IssueBuilder";
3
4
  import { IssuesCategory, IssuePriority, EntityType } from "./issue.types";
@@ -96,7 +97,7 @@ export class IssueServiceExample {
96
97
  "prop456",
97
98
  "Device Battery Low",
98
99
  "Device battery level is below 20%",
99
- "system",
100
+ Source.CLOUD_EVENT,
100
101
  undefined, // Use default category
101
102
  undefined, // Use default priority
102
103
  "maintenance-team",
@@ -109,7 +110,7 @@ export class IssueServiceExample {
109
110
  "prop456",
110
111
  "Device Firmware Update Available",
111
112
  "New firmware version is available for installation",
112
- "firmware-manager",
113
+ Source.CLOUD_EVENT,
113
114
  IssuesCategory.READINESS,
114
115
  IssuePriority.MEDIUM,
115
116
  "admin",
@@ -299,6 +300,7 @@ export class IssueServiceExample {
299
300
  assignedTo: "tech-support",
300
301
  createdBy: "legacy-system",
301
302
  dueDate: new Date("2024-01-20"),
303
+ source: Source.CLOUD_EVENT,
302
304
  };
303
305
 
304
306
  // This still works with the updated createIssue method
@@ -166,6 +166,7 @@ export class HybridHttpQueue {
166
166
  method: string;
167
167
  url: string;
168
168
  body?: any;
169
+ params?: Record<string, any>;
169
170
  headers?: Record<string, string>;
170
171
  queueOptions?: {
171
172
  connectionId: string;
@@ -173,11 +174,12 @@ export class HybridHttpQueue {
173
174
  microservice: string;
174
175
  };
175
176
  }): Promise<IQueueResponse> {
176
- const { method, url, body, headers, queueOptions } = options;
177
+ const { method, url, body, params, headers, queueOptions } = options;
177
178
  // Create HttpCallOption object
178
179
  const httpCallOption: HttpCallOption = {
179
180
  headers,
180
181
  body,
182
+ params,
181
183
  queueOptions,
182
184
  };
183
185
  // Call handleRequest with the constructed parameters
@@ -6,6 +6,7 @@ export interface IHybridHttpQueue {
6
6
  method: string;
7
7
  url: string;
8
8
  body?: any;
9
+ params?: Record<string, any>;
9
10
  headers?: Record<string, string>;
10
11
  queueOptions?: {
11
12
  connectionId: string;
@@ -15,6 +15,7 @@ export class QueueService implements IHybridHttpQueue {
15
15
  method: string;
16
16
  url: string;
17
17
  body?: any;
18
+ params?: Record<string, any>;
18
19
  headers?: Record<string, string>;
19
20
  queueOptions?: {
20
21
  connectionId: string;
@@ -13,6 +13,7 @@ export interface HttpRequestOptions {
13
13
  method: string;
14
14
  url: string;
15
15
  body?: any;
16
+ params?: Record<string, any>;
16
17
  headers?: Record<string, string>;
17
18
  queueOptions?: {
18
19
  connectionId: string;
package/tsconfig.json CHANGED
@@ -6,10 +6,6 @@
6
6
  "declaration": true,
7
7
  "outDir": "./dist",
8
8
  "rootDir": "./src",
9
- "baseUrl": ".",
10
- "paths": {
11
- "src/*": ["src/*"]
12
- },
13
9
  "strict": true,
14
10
  "esModuleInterop": true,
15
11
  "skipLibCheck": true,