dt-common-device 1.3.0 → 2.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.
- package/TROUBLESHOOTING.md +184 -0
- package/dist/config/config.d.ts +9 -2
- package/dist/config/config.js +97 -14
- package/dist/constants/Event.d.ts +75 -0
- package/dist/constants/Event.js +78 -0
- package/dist/db/db.d.ts +1 -0
- package/dist/db/db.js +18 -2
- package/dist/device/local/entities/AlertBuilder.d.ts +87 -0
- package/dist/device/local/entities/AlertBuilder.example.d.ts +11 -0
- package/dist/device/local/entities/AlertBuilder.example.js +117 -0
- package/dist/device/local/entities/AlertBuilder.js +179 -0
- package/dist/device/local/entities/IssueBuilder.d.ts +109 -0
- package/dist/device/local/entities/IssueBuilder.example.d.ts +16 -0
- package/dist/device/local/entities/IssueBuilder.example.js +196 -0
- package/dist/device/local/entities/IssueBuilder.js +237 -0
- package/dist/device/local/entities/index.d.ts +2 -0
- package/dist/device/local/entities/index.js +7 -0
- package/dist/device/local/interfaces/IDevice.d.ts +10 -9
- package/dist/device/local/interfaces/IDevice.js +7 -0
- package/dist/device/local/models/Alert.model.d.ts +28 -0
- package/dist/device/local/models/Alert.model.js +222 -0
- package/dist/device/local/models/Issue.model.d.ts +28 -0
- package/dist/device/local/models/Issue.model.js +260 -0
- package/dist/device/local/repository/Alert.repository.d.ts +106 -0
- package/dist/device/local/repository/Alert.repository.js +374 -0
- package/dist/device/local/repository/Device.repository.d.ts +10 -2
- package/dist/device/local/repository/Device.repository.js +153 -30
- package/dist/device/local/repository/Hub.repository.d.ts +1 -1
- package/dist/device/local/repository/Hub.repository.js +60 -18
- package/dist/device/local/repository/Issue.repository.d.ts +113 -0
- package/dist/device/local/repository/Issue.repository.js +401 -0
- package/dist/device/local/repository/Schedule.repository.d.ts +1 -1
- package/dist/device/local/repository/Schedule.repository.js +14 -18
- package/dist/device/local/services/Alert.service.d.ts +135 -5
- package/dist/device/local/services/Alert.service.js +471 -7
- package/dist/device/local/services/AlertService.example.d.ts +55 -0
- package/dist/device/local/services/AlertService.example.js +148 -0
- package/dist/device/local/services/Device.service.d.ts +8 -5
- package/dist/device/local/services/Device.service.js +58 -40
- package/dist/device/local/services/Issue.service.d.ts +168 -0
- package/dist/device/local/services/Issue.service.js +642 -0
- package/dist/device/local/services/IssueService.example.d.ts +68 -0
- package/dist/device/local/services/IssueService.example.js +177 -0
- package/dist/device/local/services/index.d.ts +7 -5
- package/dist/device/local/services/index.js +21 -11
- package/dist/events/BaseEventHandler.d.ts +43 -0
- package/dist/events/BaseEventHandler.js +111 -0
- package/dist/events/BaseEventTransformer.d.ts +26 -0
- package/dist/events/BaseEventTransformer.js +72 -0
- package/dist/events/DeviceEventHandler.d.ts +15 -0
- package/dist/events/DeviceEventHandler.js +152 -0
- package/dist/events/DeviceEventTransformerFactory.d.ts +27 -0
- package/dist/events/DeviceEventTransformerFactory.js +116 -0
- package/dist/events/EventHandler.d.ts +11 -0
- package/dist/events/EventHandler.js +106 -0
- package/dist/events/EventHandlerOrchestrator.d.ts +35 -0
- package/dist/events/EventHandlerOrchestrator.js +141 -0
- package/dist/events/EventProcessingService.d.ts +43 -0
- package/dist/events/EventProcessingService.js +243 -0
- package/dist/events/InternalEventSubscription.d.ts +44 -0
- package/dist/events/InternalEventSubscription.js +152 -0
- package/dist/events/index.d.ts +9 -0
- package/dist/events/index.js +21 -0
- package/dist/events/interfaces/DeviceEvent.d.ts +48 -0
- package/dist/events/interfaces/DeviceEvent.js +2 -0
- package/dist/events/interfaces/IEventHandler.d.ts +23 -0
- package/dist/events/interfaces/IEventHandler.js +2 -0
- package/dist/events/interfaces/IEventTransformer.d.ts +7 -0
- package/dist/events/interfaces/IEventTransformer.js +2 -0
- package/dist/events/interfaces/IInternalEvent.d.ts +42 -0
- package/dist/events/interfaces/IInternalEvent.js +2 -0
- package/dist/events/interfaces/index.d.ts +4 -0
- package/dist/events/interfaces/index.js +20 -0
- package/dist/index.d.ts +6 -2
- package/dist/index.js +9 -2
- package/dist/types/alert.types.d.ts +57 -0
- package/dist/types/alert.types.js +22 -0
- package/dist/types/config.types.d.ts +15 -4
- package/dist/types/index.d.ts +2 -0
- package/dist/types/index.js +2 -0
- package/dist/types/issue.types.d.ts +90 -0
- package/dist/types/issue.types.js +40 -0
- package/dist/utils/http-utils.d.ts +13 -0
- package/dist/utils/http-utils.js +117 -0
- package/package.json +2 -1
- package/src/config/config.ts +117 -14
- package/src/{device/local/events/Events.ts → constants/Event.ts} +34 -13
- package/src/db/db.ts +14 -5
- package/src/device/local/entities/AlertBuilder.example.ts +126 -0
- package/src/device/local/entities/AlertBuilder.ts +202 -0
- package/src/device/local/entities/IssueBuilder.example.ts +210 -0
- package/src/device/local/entities/IssueBuilder.ts +263 -0
- package/src/device/local/entities/README.md +173 -0
- package/src/device/local/entities/index.ts +2 -0
- package/src/device/local/interfaces/IDevice.ts +11 -9
- package/src/device/local/models/Alert.model.md +319 -0
- package/src/device/local/models/Alert.model.ts +283 -0
- package/src/device/local/models/Issue.model.md +386 -0
- package/src/device/local/models/Issue.model.ts +350 -0
- package/src/device/local/models/README.md +312 -0
- package/src/device/local/repository/Alert.repository.ts +465 -0
- package/src/device/local/repository/Device.repository.ts +241 -32
- package/src/device/local/repository/Hub.repository.ts +74 -18
- package/src/device/local/repository/Issue.repository.ts +517 -0
- package/src/device/local/repository/Schedule.repository.ts +28 -22
- package/src/device/local/services/Alert.service.ts +617 -5
- package/src/device/local/services/AlertService.example.ts +229 -0
- package/src/device/local/services/Device.service.ts +70 -50
- package/src/device/local/services/Issue.service.ts +872 -0
- package/src/device/local/services/IssueService.example.ts +307 -0
- package/src/device/local/services/index.ts +7 -5
- package/src/events/BaseEventHandler.ts +145 -0
- package/src/events/BaseEventTransformer.ts +97 -0
- package/src/events/DeviceEventHandler.ts +211 -0
- package/src/events/DeviceEventTransformerFactory.ts +77 -0
- package/src/{device/local/events → events}/EventHandler.ts +19 -15
- package/src/events/EventHandlerOrchestrator.ts +119 -0
- package/src/events/EventProcessingService.ts +248 -0
- package/src/events/InternalEventSubscription.ts +219 -0
- package/src/events/index.ts +9 -0
- package/src/events/interfaces/DeviceEvent.ts +56 -0
- package/src/events/interfaces/IEventHandler.ts +28 -0
- package/src/events/interfaces/IEventTransformer.ts +8 -0
- package/src/events/interfaces/IInternalEvent.ts +47 -0
- package/src/events/interfaces/index.ts +4 -0
- package/src/index.ts +9 -2
- package/src/types/alert.types.ts +64 -0
- package/src/types/config.types.ts +17 -4
- package/src/types/index.ts +2 -0
- package/src/types/issue.types.ts +98 -0
- package/src/utils/http-utils.ts +143 -0
- package/src/device/local/events/index.ts +0 -2
|
@@ -0,0 +1,386 @@
|
|
|
1
|
+
# Issue Model Documentation
|
|
2
|
+
|
|
3
|
+
This document describes the Mongoose implementation of the Issue model, which was converted from a Prisma schema to provide comprehensive issue tracking functionality.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
The Issue model provides a complete issue tracking system with the following features:
|
|
8
|
+
|
|
9
|
+
- **Issue Management**: Create, read, update, and delete issues
|
|
10
|
+
- **Status Tracking**: Track issue status from OPEN to CLOSED
|
|
11
|
+
- **Priority Levels**: Assign priority levels (LOW, MEDIUM, HIGH, CRITICAL)
|
|
12
|
+
- **Categories**: Categorize issues (TECHNICAL, OPERATIONAL, etc.)
|
|
13
|
+
- **Entity References**: Link issues to various entities (DEVICE, HUB, etc.)
|
|
14
|
+
- **Assignment**: Assign issues to users for resolution
|
|
15
|
+
- **Comments**: Add, update, and remove comments on issues
|
|
16
|
+
- **Due Dates**: Set and track due dates for issues
|
|
17
|
+
- **Soft Deletion**: Support for soft deletion with recovery capability
|
|
18
|
+
- **Search**: Full-text search across issue titles and descriptions
|
|
19
|
+
- **Statistics**: Comprehensive issue statistics and reporting
|
|
20
|
+
|
|
21
|
+
## Model Structure
|
|
22
|
+
|
|
23
|
+
### Core Fields
|
|
24
|
+
|
|
25
|
+
| Field | Type | Required | Description |
|
|
26
|
+
| ------------- | -------------- | -------- | --------------------------------------------- |
|
|
27
|
+
| `_id` | String | Yes | MongoDB ObjectId (auto-generated) |
|
|
28
|
+
| `category` | IssueCategory | Yes | Issue category (TECHNICAL, OPERATIONAL, etc.) |
|
|
29
|
+
| `propertyId` | String | Yes | Property UUID reference |
|
|
30
|
+
| `title` | String | Yes | Issue title |
|
|
31
|
+
| `description` | String | Yes | Issue description |
|
|
32
|
+
| `entityId` | String | No | Generic entity reference UUID |
|
|
33
|
+
| `entityType` | EntityType | Yes | Entity type (DEVICE, HUB, etc.) |
|
|
34
|
+
| `priority` | IssuePriority | Yes | Issue priority (default: MEDIUM) |
|
|
35
|
+
| `status` | IssueStatus | Yes | Issue status (default: OPEN) |
|
|
36
|
+
| `assignedTo` | String | No | User UUID assigned to resolve |
|
|
37
|
+
| `resolvedBy` | String | No | User UUID who resolved the issue |
|
|
38
|
+
| `resolvedAt` | Date | No | Resolution timestamp |
|
|
39
|
+
| `dueDate` | Date | No | Due date for resolution |
|
|
40
|
+
| `isDeleted` | Boolean | Yes | Soft deletion flag (default: false) |
|
|
41
|
+
| `createdBy` | String | Yes | User UUID who created the issue |
|
|
42
|
+
| `updatedBy` | String | No | User UUID who last updated |
|
|
43
|
+
| `createdAt` | Date | Yes | Creation timestamp |
|
|
44
|
+
| `updatedAt` | Date | Yes | Last update timestamp |
|
|
45
|
+
| `comments` | IssueComment[] | No | Array of comments |
|
|
46
|
+
|
|
47
|
+
### Enums
|
|
48
|
+
|
|
49
|
+
#### IssueCategory
|
|
50
|
+
|
|
51
|
+
```typescript
|
|
52
|
+
enum IssueCategory {
|
|
53
|
+
READINESS = "READINESS",
|
|
54
|
+
OPERATIONS = "OPERATIONS",
|
|
55
|
+
SECURITY = "SECURITY",
|
|
56
|
+
ENERGY = "ENERGY",
|
|
57
|
+
OTHER = "OTHER",
|
|
58
|
+
}
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
#### IssuePriority
|
|
62
|
+
|
|
63
|
+
```typescript
|
|
64
|
+
enum IssuePriority {
|
|
65
|
+
LOW = "LOW",
|
|
66
|
+
MEDIUM = "MEDIUM",
|
|
67
|
+
HIGH = "HIGH",
|
|
68
|
+
CRITICAL = "CRITICAL",
|
|
69
|
+
}
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
#### IssueStatus
|
|
73
|
+
|
|
74
|
+
```typescript
|
|
75
|
+
enum IssueStatus {
|
|
76
|
+
OPEN = "OPEN",
|
|
77
|
+
IN_PROGRESS = "IN_PROGRESS",
|
|
78
|
+
RESOLVED = "RESOLVED",
|
|
79
|
+
CLOSED = "CLOSED",
|
|
80
|
+
}
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
#### EntityType
|
|
84
|
+
|
|
85
|
+
```typescript
|
|
86
|
+
enum EntityType {
|
|
87
|
+
DEVICE = "DEVICE",
|
|
88
|
+
COLLECTION = "COLLECTION",
|
|
89
|
+
USER = "USER",
|
|
90
|
+
INTEGRATION = "INTEGRATION",
|
|
91
|
+
PROPERTY = "PROPERTY",
|
|
92
|
+
HUB = "HUB",
|
|
93
|
+
SCHEDULE = "SCHEDULE",
|
|
94
|
+
ALERT = "ALERT",
|
|
95
|
+
OTHER = "OTHER",
|
|
96
|
+
}
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
### Comment Structure
|
|
100
|
+
|
|
101
|
+
```typescript
|
|
102
|
+
interface IssueComment {
|
|
103
|
+
id: string;
|
|
104
|
+
userId: string;
|
|
105
|
+
content: string;
|
|
106
|
+
createdAt: Date;
|
|
107
|
+
updatedAt?: Date;
|
|
108
|
+
}
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
## Usage Examples
|
|
112
|
+
|
|
113
|
+
### Basic CRUD Operations
|
|
114
|
+
|
|
115
|
+
#### Creating an Issue
|
|
116
|
+
|
|
117
|
+
```typescript
|
|
118
|
+
import { IssueService } from "../services/Issue.service";
|
|
119
|
+
import {
|
|
120
|
+
IssueCategory,
|
|
121
|
+
EntityType,
|
|
122
|
+
IssuePriority,
|
|
123
|
+
} from "../../../types/issue.types";
|
|
124
|
+
|
|
125
|
+
const issueService = new IssueService();
|
|
126
|
+
|
|
127
|
+
const newIssue = await issueService.createIssue({
|
|
128
|
+
category: IssueCategory.READINESS,
|
|
129
|
+
propertyId: "property-uuid",
|
|
130
|
+
title: "Device connectivity issue",
|
|
131
|
+
description: "Device is not responding to commands",
|
|
132
|
+
entityId: "device-uuid",
|
|
133
|
+
entityType: EntityType.DEVICE,
|
|
134
|
+
priority: IssuePriority.HIGH,
|
|
135
|
+
createdBy: "user-uuid",
|
|
136
|
+
dueDate: new Date("2024-01-15"),
|
|
137
|
+
});
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
#### Getting Issues
|
|
141
|
+
|
|
142
|
+
```typescript
|
|
143
|
+
// Get all issues for a property
|
|
144
|
+
const propertyIssues = await issueService.getIssuesByProperty("property-uuid");
|
|
145
|
+
|
|
146
|
+
// Get issues assigned to a user
|
|
147
|
+
const assignedIssues = await issueService.getIssuesByAssignee("user-uuid");
|
|
148
|
+
|
|
149
|
+
// Get issues by status
|
|
150
|
+
const openIssues = await issueService.getIssuesByStatus(IssueStatus.OPEN);
|
|
151
|
+
|
|
152
|
+
// Get issues with filters
|
|
153
|
+
const filteredIssues = await issueService.getIssues({
|
|
154
|
+
propertyId: "property-uuid",
|
|
155
|
+
status: IssueStatus.IN_PROGRESS,
|
|
156
|
+
priority: IssuePriority.HIGH,
|
|
157
|
+
limit: 10,
|
|
158
|
+
skip: 0,
|
|
159
|
+
});
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
#### Updating an Issue
|
|
163
|
+
|
|
164
|
+
```typescript
|
|
165
|
+
// Update issue status
|
|
166
|
+
await issueService.updateIssue(issueId, {
|
|
167
|
+
status: IssueStatus.IN_PROGRESS,
|
|
168
|
+
updatedBy: "user-uuid",
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
// Assign issue to user
|
|
172
|
+
await issueService.assignIssue(issueId, "assignee-uuid", "assigned-by-uuid");
|
|
173
|
+
|
|
174
|
+
// Resolve issue
|
|
175
|
+
await issueService.resolveIssue(
|
|
176
|
+
issueId,
|
|
177
|
+
"resolved-by-uuid",
|
|
178
|
+
"Issue resolved successfully"
|
|
179
|
+
);
|
|
180
|
+
|
|
181
|
+
// Close issue
|
|
182
|
+
await issueService.closeIssue(issueId, "closed-by-uuid");
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
#### Adding Comments
|
|
186
|
+
|
|
187
|
+
```typescript
|
|
188
|
+
// Add a comment
|
|
189
|
+
await issueService.addComment(issueId, {
|
|
190
|
+
userId: "user-uuid",
|
|
191
|
+
content: "Investigation in progress",
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
// Update a comment
|
|
195
|
+
await issueService.updateComment(
|
|
196
|
+
issueId,
|
|
197
|
+
commentId,
|
|
198
|
+
"Updated content",
|
|
199
|
+
"user-uuid"
|
|
200
|
+
);
|
|
201
|
+
|
|
202
|
+
// Remove a comment
|
|
203
|
+
await issueService.removeComment(issueId, commentId);
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
### Advanced Operations
|
|
207
|
+
|
|
208
|
+
#### Search Issues
|
|
209
|
+
|
|
210
|
+
```typescript
|
|
211
|
+
// Search by text
|
|
212
|
+
const searchResults = await issueService.searchIssues("connectivity", {
|
|
213
|
+
propertyId: "property-uuid",
|
|
214
|
+
limit: 20,
|
|
215
|
+
});
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
#### Get Statistics
|
|
219
|
+
|
|
220
|
+
```typescript
|
|
221
|
+
// Get overall statistics
|
|
222
|
+
const stats = await issueService.getIssueStatistics();
|
|
223
|
+
|
|
224
|
+
// Get property-specific statistics
|
|
225
|
+
const propertyStats = await issueService.getIssueStatistics("property-uuid");
|
|
226
|
+
|
|
227
|
+
console.log(`Total issues: ${stats.total}`);
|
|
228
|
+
console.log(`Open issues: ${stats.open}`);
|
|
229
|
+
console.log(`Overdue issues: ${stats.overdue}`);
|
|
230
|
+
console.log(`High priority: ${stats.byPriority.HIGH}`);
|
|
231
|
+
console.log(`Readiness issues: ${stats.byCategory.READINESS}`);
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
#### Find Overdue Issues
|
|
235
|
+
|
|
236
|
+
```typescript
|
|
237
|
+
// Get all overdue issues
|
|
238
|
+
const overdueIssues = await issueService.getOverdueIssues();
|
|
239
|
+
|
|
240
|
+
// Get upcoming issues (due within 7 days)
|
|
241
|
+
const upcomingIssues = await issueService.getUpcomingIssues(7);
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
#### Repository Pattern Usage
|
|
245
|
+
|
|
246
|
+
For more advanced data access patterns, use the repository:
|
|
247
|
+
|
|
248
|
+
```typescript
|
|
249
|
+
import { IssueRepository } from "../repository/Issue.repository";
|
|
250
|
+
|
|
251
|
+
const issueRepo = new IssueRepository();
|
|
252
|
+
|
|
253
|
+
// Bulk operations
|
|
254
|
+
await issueRepo.bulkUpdate(["issue1", "issue2"], {
|
|
255
|
+
status: IssueStatus.CLOSED,
|
|
256
|
+
updatedBy: "user-uuid",
|
|
257
|
+
});
|
|
258
|
+
|
|
259
|
+
// Count issues
|
|
260
|
+
const count = await issueRepo.count({
|
|
261
|
+
propertyId: "property-uuid",
|
|
262
|
+
status: IssueStatus.OPEN,
|
|
263
|
+
});
|
|
264
|
+
|
|
265
|
+
// Advanced filtering with sorting
|
|
266
|
+
const issues = await issueRepo.findAll({
|
|
267
|
+
propertyId: "property-uuid",
|
|
268
|
+
sort: { priority: -1, createdAt: -1 },
|
|
269
|
+
limit: 50,
|
|
270
|
+
});
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
## Business Rules
|
|
274
|
+
|
|
275
|
+
### Status Transitions
|
|
276
|
+
|
|
277
|
+
Issues follow a specific status flow:
|
|
278
|
+
|
|
279
|
+
1. **OPEN** → **IN_PROGRESS** (requires assignment)
|
|
280
|
+
2. **IN_PROGRESS** → **RESOLVED** (requires resolution note)
|
|
281
|
+
3. **RESOLVED** → **CLOSED** (final state)
|
|
282
|
+
4. **RESOLVED** → **OPEN** (reopen allowed)
|
|
283
|
+
5. **CLOSED** → **OPEN** (reopen allowed)
|
|
284
|
+
|
|
285
|
+
### Assignment Requirements
|
|
286
|
+
|
|
287
|
+
- Issues must be assigned before moving to IN_PROGRESS status
|
|
288
|
+
- Only assigned issues can be moved to IN_PROGRESS
|
|
289
|
+
- Unassigned issues remain in OPEN status
|
|
290
|
+
|
|
291
|
+
### Resolution Requirements
|
|
292
|
+
|
|
293
|
+
- Issues must have a resolution note when moved to RESOLVED status
|
|
294
|
+
- Resolution automatically sets the `resolvedAt` timestamp
|
|
295
|
+
- Resolution automatically sets the `resolvedBy` user
|
|
296
|
+
|
|
297
|
+
### Overdue Calculation
|
|
298
|
+
|
|
299
|
+
Issues are considered overdue based on priority:
|
|
300
|
+
|
|
301
|
+
| Priority | Overdue After |
|
|
302
|
+
| -------- | ------------- |
|
|
303
|
+
| LOW | 14 days |
|
|
304
|
+
| MEDIUM | 7 days |
|
|
305
|
+
| HIGH | 3 days |
|
|
306
|
+
| CRITICAL | 1 day |
|
|
307
|
+
|
|
308
|
+
### Priority Management
|
|
309
|
+
|
|
310
|
+
- Priority can be changed at any time
|
|
311
|
+
- Priority changes are logged for audit purposes
|
|
312
|
+
- Critical priority issues get special handling
|
|
313
|
+
|
|
314
|
+
## Indexes
|
|
315
|
+
|
|
316
|
+
The model includes the following indexes for optimal performance:
|
|
317
|
+
|
|
318
|
+
- `propertyId` (single field)
|
|
319
|
+
- `assignedTo` (single field)
|
|
320
|
+
- `entityId` (single field)
|
|
321
|
+
- `entityType` (single field)
|
|
322
|
+
- `status` (single field)
|
|
323
|
+
- `priority` (single field)
|
|
324
|
+
- `createdAt` (single field)
|
|
325
|
+
- `{ propertyId: 1, status: 1, priority: 1 }` (compound)
|
|
326
|
+
- `{ assignedTo: 1, status: 1 }` (compound)
|
|
327
|
+
- `{ entityId: 1, entityType: 1 }` (compound)
|
|
328
|
+
|
|
329
|
+
## Middleware
|
|
330
|
+
|
|
331
|
+
The model includes pre-save and pre-update middleware that automatically:
|
|
332
|
+
|
|
333
|
+
- Updates the `updatedAt` timestamp on save
|
|
334
|
+
- Updates the `updatedAt` timestamp on update operations
|
|
335
|
+
- Validates status transitions
|
|
336
|
+
- Validates assignment requirements
|
|
337
|
+
|
|
338
|
+
## Virtual Fields
|
|
339
|
+
|
|
340
|
+
- `isOverdue`: Returns `true` if the issue is overdue
|
|
341
|
+
- `timeToResolution`: Calculates time to resolution (if resolved)
|
|
342
|
+
- `isAssigned`: Returns `true` if the issue is assigned
|
|
343
|
+
|
|
344
|
+
## Error Handling
|
|
345
|
+
|
|
346
|
+
All operations include comprehensive error handling with descriptive error messages. The service and repository layers wrap database operations in try-catch blocks and provide meaningful error messages.
|
|
347
|
+
|
|
348
|
+
Common error scenarios:
|
|
349
|
+
|
|
350
|
+
- **Invalid status transition**: "Cannot transition from OPEN to RESOLVED"
|
|
351
|
+
- **Missing assignment**: "Issue must be assigned before moving to IN_PROGRESS"
|
|
352
|
+
- **Missing resolution**: "Resolution note is required when resolving an issue"
|
|
353
|
+
- **Invalid due date**: "Due date must be in the future"
|
|
354
|
+
- **Missing required fields**: "Issue title must be at least 3 characters long"
|
|
355
|
+
|
|
356
|
+
## Best Practices
|
|
357
|
+
|
|
358
|
+
1. **Set Realistic Due Dates**: Set achievable due dates for better tracking
|
|
359
|
+
2. **Use Appropriate Categories**: Properly categorize issues for better organization
|
|
360
|
+
3. **Assign Issues Promptly**: Assign issues to appropriate users quickly
|
|
361
|
+
4. **Add Meaningful Comments**: Use comments to track progress and communication
|
|
362
|
+
5. **Monitor Overdue Issues**: Regularly check for overdue issues
|
|
363
|
+
6. **Use Priority Wisely**: Don't overuse high/critical priority
|
|
364
|
+
7. **Provide Resolution Notes**: Always include detailed resolution notes
|
|
365
|
+
8. **Use Soft Deletion**: Always use soft deletion for audit trails
|
|
366
|
+
9. **Validate Input**: Always validate issue data before creation
|
|
367
|
+
10. **Monitor Statistics**: Regularly check issue statistics for insights
|
|
368
|
+
|
|
369
|
+
## Migration from Prisma
|
|
370
|
+
|
|
371
|
+
This Mongoose model maintains full compatibility with the original Prisma schema:
|
|
372
|
+
|
|
373
|
+
- All fields and types are preserved
|
|
374
|
+
- Indexes match the Prisma schema
|
|
375
|
+
- Relationships are maintained through foreign key references
|
|
376
|
+
- Collection name matches Prisma (`dt_issues`)
|
|
377
|
+
|
|
378
|
+
The model provides additional features beyond the Prisma schema:
|
|
379
|
+
|
|
380
|
+
- Instance methods for common operations
|
|
381
|
+
- Static methods for complex queries
|
|
382
|
+
- Virtual fields for computed properties
|
|
383
|
+
- Comprehensive business logic validation
|
|
384
|
+
- Built-in monitoring and logging
|
|
385
|
+
- Comment management system
|
|
386
|
+
- Overdue calculation logic
|