payservedb 6.6.0 → 6.6.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "payservedb",
3
- "version": "6.6.0",
3
+ "version": "6.6.1",
4
4
  "main": "index.js",
5
5
  "scripts": {
6
6
  "test": "echo \"Error: no test specified\" && exit 1"
@@ -1,7 +1,7 @@
1
1
  const mongoose = require("mongoose");
2
2
 
3
- // Child property schema with date
4
- const childPropertySchema = new mongoose.Schema(
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: false },
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
- // Dynamic parent-child structure with dates
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.setValue = function (
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, new Map());
86
+ this.data.set(parentName, []);
51
87
  }
52
88
 
53
- this.data.get(parentName).set(childName, { value, date });
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.getValue = function (parentName, childName) {
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.get(childName);
61
- return child ? child.value : null;
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.getChildWithDate = function (
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
- return parent.get(childName) || null;
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, new Map());
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 ? Array.from(parent.keys()) : [];
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);