payservedb 6.6.0 → 6.6.2
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/package.json +1 -1
- package/src/models/auditTrail.js +38 -12
- package/src/models/dailyChecklist.js +235 -20
- package/src/models/auditlog.js +0 -83
package/package.json
CHANGED
package/src/models/auditTrail.js
CHANGED
|
@@ -40,7 +40,7 @@ const userDetailsSchema = new mongoose.Schema(
|
|
|
40
40
|
required: false,
|
|
41
41
|
},
|
|
42
42
|
},
|
|
43
|
-
{ _id: false }
|
|
43
|
+
{ _id: false },
|
|
44
44
|
);
|
|
45
45
|
|
|
46
46
|
// Main audit trail schema
|
|
@@ -125,6 +125,14 @@ const auditTrailSchema = new mongoose.Schema(
|
|
|
125
125
|
required: true,
|
|
126
126
|
},
|
|
127
127
|
|
|
128
|
+
// response status
|
|
129
|
+
response_status: {
|
|
130
|
+
type: String,
|
|
131
|
+
required: true,
|
|
132
|
+
enum: ["success", "error", "unknown"],
|
|
133
|
+
default: "unknown",
|
|
134
|
+
},
|
|
135
|
+
|
|
128
136
|
// Method-specific data
|
|
129
137
|
previous_data: {
|
|
130
138
|
type: mongoose.Schema.Types.Mixed,
|
|
@@ -149,7 +157,7 @@ const auditTrailSchema = new mongoose.Schema(
|
|
|
149
157
|
},
|
|
150
158
|
{
|
|
151
159
|
timestamps: true,
|
|
152
|
-
}
|
|
160
|
+
},
|
|
153
161
|
);
|
|
154
162
|
|
|
155
163
|
// Pre-save middleware for data validation and cleanup
|
|
@@ -202,7 +210,11 @@ auditTrailSchema.statics.findByActivity = function (activity, limit = 100) {
|
|
|
202
210
|
.limit(limit);
|
|
203
211
|
};
|
|
204
212
|
|
|
205
|
-
auditTrailSchema.statics.findByFacility = function (
|
|
213
|
+
auditTrailSchema.statics.findByFacility = function (
|
|
214
|
+
facilityId,
|
|
215
|
+
startDate,
|
|
216
|
+
endDate,
|
|
217
|
+
) {
|
|
206
218
|
const query = { "route_params.facilityId": facilityId };
|
|
207
219
|
if (startDate || endDate) {
|
|
208
220
|
query.timestamp = {};
|
|
@@ -252,10 +264,12 @@ auditTrailSchema.methods.getActivityType = function () {
|
|
|
252
264
|
};
|
|
253
265
|
|
|
254
266
|
auditTrailSchema.methods.isSuccessful = function () {
|
|
255
|
-
return
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
267
|
+
return (
|
|
268
|
+
this.activity.includes("Success") ||
|
|
269
|
+
(!this.activity.includes("Failed") &&
|
|
270
|
+
!this.activity.includes("Error") &&
|
|
271
|
+
!this.activity.includes("Not Found"))
|
|
272
|
+
);
|
|
259
273
|
};
|
|
260
274
|
|
|
261
275
|
auditTrailSchema.methods.hasDataChanges = function () {
|
|
@@ -277,9 +291,21 @@ auditTrailSchema.index({ device_type: 1, timestamp: -1 }); // Device type querie
|
|
|
277
291
|
auditTrailSchema.index({ browser: 1, timestamp: -1 }); // Browser-based queries
|
|
278
292
|
|
|
279
293
|
// Compound indexes for common query patterns
|
|
280
|
-
auditTrailSchema.index({
|
|
281
|
-
|
|
282
|
-
|
|
294
|
+
auditTrailSchema.index({
|
|
295
|
+
"user_details.userId": 1,
|
|
296
|
+
activity: 1,
|
|
297
|
+
timestamp: -1,
|
|
298
|
+
}); // User + activity
|
|
299
|
+
auditTrailSchema.index({
|
|
300
|
+
"route_params.facilityId": 1,
|
|
301
|
+
method: 1,
|
|
302
|
+
timestamp: -1,
|
|
303
|
+
}); // Facility + method
|
|
304
|
+
auditTrailSchema.index({
|
|
305
|
+
ip_address: 1,
|
|
306
|
+
"user_details.userId": 1,
|
|
307
|
+
timestamp: -1,
|
|
308
|
+
}); // IP + user correlation
|
|
283
309
|
|
|
284
310
|
// Text search index for searching activities and user details
|
|
285
311
|
auditTrailSchema.index({
|
|
@@ -292,7 +318,7 @@ auditTrailSchema.index({
|
|
|
292
318
|
// Activity type constants
|
|
293
319
|
auditTrailSchema.statics.ACTIVITY_TYPES = {
|
|
294
320
|
CREATE: "CREATE",
|
|
295
|
-
UPDATE: "UPDATE",
|
|
321
|
+
UPDATE: "UPDATE",
|
|
296
322
|
DELETE: "DELETE",
|
|
297
323
|
AUTH: "AUTH",
|
|
298
324
|
OTHER: "OTHER",
|
|
@@ -317,4 +343,4 @@ auditTrailSchema.statics.DEVICE_TYPES = {
|
|
|
317
343
|
UNKNOWN: "unknown",
|
|
318
344
|
};
|
|
319
345
|
|
|
320
|
-
module.exports = mongoose.model("AuditTrail", auditTrailSchema);
|
|
346
|
+
module.exports = mongoose.model("AuditTrail", auditTrailSchema);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
const mongoose = require("mongoose");
|
|
2
2
|
|
|
3
|
-
//
|
|
4
|
-
const
|
|
3
|
+
// Reading entry schema - each individual reading with metadata
|
|
4
|
+
const readingEntrySchema = new mongoose.Schema(
|
|
5
5
|
{
|
|
6
6
|
value: {
|
|
7
7
|
type: mongoose.Schema.Types.Mixed, // String, Boolean, or Number
|
|
@@ -11,8 +11,47 @@ const childPropertySchema = new mongoose.Schema(
|
|
|
11
11
|
type: Date,
|
|
12
12
|
required: true,
|
|
13
13
|
},
|
|
14
|
+
recordedBy: {
|
|
15
|
+
type: String,
|
|
16
|
+
required: false, // User ID who recorded this reading
|
|
17
|
+
},
|
|
18
|
+
notes: {
|
|
19
|
+
type: String,
|
|
20
|
+
required: false, // Optional notes for this reading
|
|
21
|
+
},
|
|
22
|
+
isActive: {
|
|
23
|
+
type: Boolean,
|
|
24
|
+
default: true, // Allow soft deletion of readings
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
{ _id: true, timestamps: true }, // Keep _id for individual readings and timestamps
|
|
28
|
+
);
|
|
29
|
+
|
|
30
|
+
// Child property schema with historical readings
|
|
31
|
+
const childPropertySchema = new mongoose.Schema(
|
|
32
|
+
{
|
|
33
|
+
name: {
|
|
34
|
+
type: String,
|
|
35
|
+
required: true, // Child property name (e.g., "fuel_level")
|
|
36
|
+
},
|
|
37
|
+
currentValue: {
|
|
38
|
+
type: mongoose.Schema.Types.Mixed, // Latest value for quick access
|
|
39
|
+
required: false,
|
|
40
|
+
},
|
|
41
|
+
currentDate: {
|
|
42
|
+
type: Date,
|
|
43
|
+
required: false, // Date of latest reading
|
|
44
|
+
},
|
|
45
|
+
unit: {
|
|
46
|
+
type: String,
|
|
47
|
+
required: false, // Unit of measurement (e.g., "%", "°C", "bar")
|
|
48
|
+
},
|
|
49
|
+
readings: {
|
|
50
|
+
type: [readingEntrySchema], // Array of all historical readings
|
|
51
|
+
default: [],
|
|
52
|
+
},
|
|
14
53
|
},
|
|
15
|
-
{ _id:
|
|
54
|
+
{ _id: true },
|
|
16
55
|
);
|
|
17
56
|
|
|
18
57
|
// Main facilities monitoring schema
|
|
@@ -22,15 +61,11 @@ const dailyChecklistSchema = new mongoose.Schema(
|
|
|
22
61
|
type: String,
|
|
23
62
|
required: true,
|
|
24
63
|
},
|
|
25
|
-
|
|
26
|
-
//
|
|
27
|
-
// Parent_name -> child_name -> { value, date }
|
|
64
|
+
// Dynamic parent-child structure with historical readings
|
|
65
|
+
// Parent_name -> [child_properties with readings]
|
|
28
66
|
data: {
|
|
29
67
|
type: Map,
|
|
30
|
-
of:
|
|
31
|
-
type: Map,
|
|
32
|
-
of: childPropertySchema,
|
|
33
|
-
},
|
|
68
|
+
of: [childPropertySchema], // Array of child properties for each parent
|
|
34
69
|
default: new Map(),
|
|
35
70
|
},
|
|
36
71
|
},
|
|
@@ -40,43 +75,158 @@ const dailyChecklistSchema = new mongoose.Schema(
|
|
|
40
75
|
);
|
|
41
76
|
|
|
42
77
|
// Helper methods
|
|
43
|
-
dailyChecklistSchema.methods.
|
|
78
|
+
dailyChecklistSchema.methods.addReading = function (
|
|
44
79
|
parentName,
|
|
45
80
|
childName,
|
|
46
81
|
value,
|
|
47
82
|
date = new Date(),
|
|
83
|
+
metadata = {},
|
|
48
84
|
) {
|
|
49
85
|
if (!this.data.has(parentName)) {
|
|
50
|
-
this.data.set(parentName,
|
|
86
|
+
this.data.set(parentName, []);
|
|
51
87
|
}
|
|
52
88
|
|
|
53
|
-
this.data.get(parentName)
|
|
89
|
+
const parent = this.data.get(parentName);
|
|
90
|
+
let childProperty = parent.find((child) => child.name === childName);
|
|
91
|
+
|
|
92
|
+
if (!childProperty) {
|
|
93
|
+
// Create new child property
|
|
94
|
+
childProperty = {
|
|
95
|
+
name: childName,
|
|
96
|
+
currentValue: value,
|
|
97
|
+
currentDate: date,
|
|
98
|
+
unit: metadata.unit || null,
|
|
99
|
+
readings: [],
|
|
100
|
+
};
|
|
101
|
+
parent.push(childProperty);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// Add new reading
|
|
105
|
+
const newReading = {
|
|
106
|
+
value: value,
|
|
107
|
+
date: date,
|
|
108
|
+
recordedBy: metadata.recordedBy || null,
|
|
109
|
+
notes: metadata.notes || null,
|
|
110
|
+
isActive: true,
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
childProperty.readings.push(newReading);
|
|
114
|
+
|
|
115
|
+
// Update current values
|
|
116
|
+
childProperty.currentValue = value;
|
|
117
|
+
childProperty.currentDate = date;
|
|
118
|
+
|
|
119
|
+
// Sort readings by date (newest first)
|
|
120
|
+
childProperty.readings.sort((a, b) => new Date(b.date) - new Date(a.date));
|
|
121
|
+
|
|
54
122
|
this.markModified("data");
|
|
55
123
|
};
|
|
56
124
|
|
|
57
|
-
dailyChecklistSchema.methods.
|
|
125
|
+
dailyChecklistSchema.methods.getCurrentValue = function (
|
|
126
|
+
parentName,
|
|
127
|
+
childName,
|
|
128
|
+
) {
|
|
58
129
|
const parent = this.data.get(parentName);
|
|
59
130
|
if (parent) {
|
|
60
|
-
const child = parent.
|
|
61
|
-
return child ? child.
|
|
131
|
+
const child = parent.find((c) => c.name === childName);
|
|
132
|
+
return child ? child.currentValue : null;
|
|
62
133
|
}
|
|
63
134
|
return null;
|
|
64
135
|
};
|
|
65
136
|
|
|
66
|
-
dailyChecklistSchema.methods.
|
|
137
|
+
dailyChecklistSchema.methods.getReadingHistory = function (
|
|
67
138
|
parentName,
|
|
68
139
|
childName,
|
|
140
|
+
limit = null,
|
|
69
141
|
) {
|
|
70
142
|
const parent = this.data.get(parentName);
|
|
71
143
|
if (parent) {
|
|
72
|
-
|
|
144
|
+
const child = parent.find((c) => c.name === childName);
|
|
145
|
+
if (child) {
|
|
146
|
+
const activeReadings = child.readings.filter((r) => r.isActive);
|
|
147
|
+
return limit ? activeReadings.slice(0, limit) : activeReadings;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
return [];
|
|
151
|
+
};
|
|
152
|
+
|
|
153
|
+
dailyChecklistSchema.methods.getLatestReading = function (
|
|
154
|
+
parentName,
|
|
155
|
+
childName,
|
|
156
|
+
) {
|
|
157
|
+
const parent = this.data.get(parentName);
|
|
158
|
+
if (parent) {
|
|
159
|
+
const child = parent.find((c) => c.name === childName);
|
|
160
|
+
if (child && child.readings.length > 0) {
|
|
161
|
+
return child.readings.find((r) => r.isActive) || null;
|
|
162
|
+
}
|
|
73
163
|
}
|
|
74
164
|
return null;
|
|
75
165
|
};
|
|
76
166
|
|
|
167
|
+
dailyChecklistSchema.methods.updateReading = function (
|
|
168
|
+
parentName,
|
|
169
|
+
childName,
|
|
170
|
+
readingId,
|
|
171
|
+
updates,
|
|
172
|
+
) {
|
|
173
|
+
const parent = this.data.get(parentName);
|
|
174
|
+
if (parent) {
|
|
175
|
+
const child = parent.find((c) => c.name === childName);
|
|
176
|
+
if (child) {
|
|
177
|
+
const reading = child.readings.id(readingId);
|
|
178
|
+
if (reading) {
|
|
179
|
+
Object.assign(reading, updates);
|
|
180
|
+
|
|
181
|
+
// If this was the latest reading, update current values
|
|
182
|
+
const latestReading = child.readings.find((r) => r.isActive);
|
|
183
|
+
if (latestReading && latestReading._id.equals(readingId)) {
|
|
184
|
+
child.currentValue = reading.value;
|
|
185
|
+
child.currentDate = reading.date;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
this.markModified("data");
|
|
189
|
+
return true;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
return false;
|
|
194
|
+
};
|
|
195
|
+
|
|
196
|
+
dailyChecklistSchema.methods.deleteReading = function (
|
|
197
|
+
parentName,
|
|
198
|
+
childName,
|
|
199
|
+
readingId,
|
|
200
|
+
) {
|
|
201
|
+
const parent = this.data.get(parentName);
|
|
202
|
+
if (parent) {
|
|
203
|
+
const child = parent.find((c) => c.name === childName);
|
|
204
|
+
if (child) {
|
|
205
|
+
const reading = child.readings.id(readingId);
|
|
206
|
+
if (reading) {
|
|
207
|
+
reading.isActive = false; // Soft delete
|
|
208
|
+
|
|
209
|
+
// Update current values to next active reading
|
|
210
|
+
const latestActiveReading = child.readings.find((r) => r.isActive);
|
|
211
|
+
if (latestActiveReading) {
|
|
212
|
+
child.currentValue = latestActiveReading.value;
|
|
213
|
+
child.currentDate = latestActiveReading.date;
|
|
214
|
+
} else {
|
|
215
|
+
child.currentValue = null;
|
|
216
|
+
child.currentDate = null;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
this.markModified("data");
|
|
220
|
+
return true;
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
return false;
|
|
225
|
+
};
|
|
226
|
+
|
|
77
227
|
dailyChecklistSchema.methods.createParent = function (parentName) {
|
|
78
228
|
if (!this.data.has(parentName)) {
|
|
79
|
-
this.data.set(parentName,
|
|
229
|
+
this.data.set(parentName, []);
|
|
80
230
|
this.markModified("data");
|
|
81
231
|
}
|
|
82
232
|
};
|
|
@@ -91,7 +241,72 @@ dailyChecklistSchema.methods.getParentNames = function () {
|
|
|
91
241
|
|
|
92
242
|
dailyChecklistSchema.methods.getChildNames = function (parentName) {
|
|
93
243
|
const parent = this.data.get(parentName);
|
|
94
|
-
return parent ?
|
|
244
|
+
return parent ? parent.map((child) => child.name) : [];
|
|
245
|
+
};
|
|
246
|
+
|
|
247
|
+
dailyChecklistSchema.methods.getChildProperty = function (
|
|
248
|
+
parentName,
|
|
249
|
+
childName,
|
|
250
|
+
) {
|
|
251
|
+
const parent = this.data.get(parentName);
|
|
252
|
+
if (parent) {
|
|
253
|
+
return parent.find((child) => child.name === childName) || null;
|
|
254
|
+
}
|
|
255
|
+
return null;
|
|
256
|
+
};
|
|
257
|
+
|
|
258
|
+
// Get readings within a date range
|
|
259
|
+
dailyChecklistSchema.methods.getReadingsByDateRange = function (
|
|
260
|
+
parentName,
|
|
261
|
+
childName,
|
|
262
|
+
startDate,
|
|
263
|
+
endDate,
|
|
264
|
+
) {
|
|
265
|
+
const parent = this.data.get(parentName);
|
|
266
|
+
if (parent) {
|
|
267
|
+
const child = parent.find((c) => c.name === childName);
|
|
268
|
+
if (child) {
|
|
269
|
+
return child.readings.filter((reading) => {
|
|
270
|
+
const readingDate = new Date(reading.date);
|
|
271
|
+
return (
|
|
272
|
+
reading.isActive &&
|
|
273
|
+
readingDate >= new Date(startDate) &&
|
|
274
|
+
readingDate <= new Date(endDate)
|
|
275
|
+
);
|
|
276
|
+
});
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
return [];
|
|
280
|
+
};
|
|
281
|
+
|
|
282
|
+
// Get statistics for a child property
|
|
283
|
+
dailyChecklistSchema.methods.getChildStatistics = function (
|
|
284
|
+
parentName,
|
|
285
|
+
childName,
|
|
286
|
+
) {
|
|
287
|
+
const readings = this.getReadingHistory(parentName, childName);
|
|
288
|
+
if (readings.length === 0) return null;
|
|
289
|
+
|
|
290
|
+
const numericReadings = readings
|
|
291
|
+
.map((r) => r.value)
|
|
292
|
+
.filter((v) => typeof v === "number");
|
|
293
|
+
|
|
294
|
+
if (numericReadings.length === 0) {
|
|
295
|
+
return {
|
|
296
|
+
totalReadings: readings.length,
|
|
297
|
+
type: "non-numeric",
|
|
298
|
+
};
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
return {
|
|
302
|
+
totalReadings: readings.length,
|
|
303
|
+
type: "numeric",
|
|
304
|
+
min: Math.min(...numericReadings),
|
|
305
|
+
max: Math.max(...numericReadings),
|
|
306
|
+
average:
|
|
307
|
+
numericReadings.reduce((a, b) => a + b, 0) / numericReadings.length,
|
|
308
|
+
latest: readings[0].value,
|
|
309
|
+
};
|
|
95
310
|
};
|
|
96
311
|
|
|
97
312
|
module.exports = mongoose.model("DailyChecklist", dailyChecklistSchema);
|
package/src/models/auditlog.js
DELETED
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
const mongoose = require('mongoose');
|
|
2
|
-
|
|
3
|
-
const auditLogSchema = new mongoose.Schema({
|
|
4
|
-
action: {
|
|
5
|
-
type: String,
|
|
6
|
-
required: true,
|
|
7
|
-
trim: true
|
|
8
|
-
},
|
|
9
|
-
page: {
|
|
10
|
-
type: String,
|
|
11
|
-
required: true,
|
|
12
|
-
trim: true
|
|
13
|
-
},
|
|
14
|
-
userId: {
|
|
15
|
-
type: mongoose.Schema.Types.ObjectId,
|
|
16
|
-
ref: 'Company',
|
|
17
|
-
required: true
|
|
18
|
-
},
|
|
19
|
-
userInfo: {
|
|
20
|
-
type: mongoose.Schema.Types.Mixed,
|
|
21
|
-
required: true
|
|
22
|
-
},
|
|
23
|
-
projectId: {
|
|
24
|
-
type: mongoose.Schema.Types.ObjectId,
|
|
25
|
-
ref: 'Project',
|
|
26
|
-
required: true
|
|
27
|
-
},
|
|
28
|
-
projectInfo: {
|
|
29
|
-
type: mongoose.Schema.Types.Mixed,
|
|
30
|
-
required: true
|
|
31
|
-
},
|
|
32
|
-
computerName: {
|
|
33
|
-
type: String,
|
|
34
|
-
required: true,
|
|
35
|
-
trim: true
|
|
36
|
-
},
|
|
37
|
-
browser: {
|
|
38
|
-
type: String,
|
|
39
|
-
required: true,
|
|
40
|
-
trim: true
|
|
41
|
-
},
|
|
42
|
-
ipAddress: {
|
|
43
|
-
type: String,
|
|
44
|
-
required: true,
|
|
45
|
-
trim: true
|
|
46
|
-
},
|
|
47
|
-
time: {
|
|
48
|
-
type: String,
|
|
49
|
-
required: true,
|
|
50
|
-
trim: true
|
|
51
|
-
},
|
|
52
|
-
date: {
|
|
53
|
-
type: String,
|
|
54
|
-
required: true,
|
|
55
|
-
trim: true
|
|
56
|
-
},
|
|
57
|
-
createdOn: {
|
|
58
|
-
type: Date,
|
|
59
|
-
default: Date.now,
|
|
60
|
-
required: true
|
|
61
|
-
},
|
|
62
|
-
oldData: {
|
|
63
|
-
type: mongoose.Schema.Types.Mixed,
|
|
64
|
-
default: {}
|
|
65
|
-
},
|
|
66
|
-
newData: {
|
|
67
|
-
type: mongoose.Schema.Types.Mixed,
|
|
68
|
-
default: {}
|
|
69
|
-
},
|
|
70
|
-
deletedData: {
|
|
71
|
-
type: mongoose.Schema.Types.Mixed,
|
|
72
|
-
default: {}
|
|
73
|
-
}
|
|
74
|
-
}, {
|
|
75
|
-
timestamps: true
|
|
76
|
-
});
|
|
77
|
-
|
|
78
|
-
auditLogSchema.index({ userId: 1, projectId: 1, createdOn: -1 });
|
|
79
|
-
auditLogSchema.index({ action: 1 });
|
|
80
|
-
auditLogSchema.index({ page: 1 });
|
|
81
|
-
const AuditLog = mongoose.model('AuditLog', auditLogSchema);
|
|
82
|
-
|
|
83
|
-
module.exports = AuditLog;
|