payservedb 8.3.5 → 8.3.6
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/.env +2 -2
- package/.idea/material_theme_project_new.xml +12 -0
- package/.idea/modules.xml +8 -0
- package/.idea/psdb.iml +12 -0
- package/.idea/vcs.xml +6 -0
- package/index.js +306 -306
- package/package.json +17 -17
- package/src/models/account.js +52 -52
- package/src/models/agent_departments.js +59 -59
- package/src/models/agent_notifications.js +53 -53
- package/src/models/agent_performance.js +127 -127
- package/src/models/agent_roles.js +77 -77
- package/src/models/agents.js +154 -154
- package/src/models/apilog.js +18 -18
- package/src/models/approvalsWorkflows.js +49 -49
- package/src/models/archivedapilog.js +18 -18
- package/src/models/asset.js +92 -92
- package/src/models/assetsAssignment.js +64 -64
- package/src/models/auditTrail.js +346 -346
- package/src/models/bankdetails.js +47 -43
- package/src/models/billerAddress.js +124 -124
- package/src/models/booking_invoice.js +151 -151
- package/src/models/bookinganalytics.js +63 -63
- package/src/models/bookingconfig.js +45 -45
- package/src/models/bookingproperty.js +122 -122
- package/src/models/bookingreservation.js +192 -192
- package/src/models/bookingrevenuerecord.js +84 -84
- package/src/models/budget.js +95 -95
- package/src/models/budgetCategory.js +19 -19
- package/src/models/campaigns.js +108 -108
- package/src/models/cashpayment.js +264 -264
- package/src/models/combinedUnits.js +62 -62
- package/src/models/common_area_electricity.js +38 -38
- package/src/models/common_area_generator.js +41 -41
- package/src/models/common_area_utility_alert.js +37 -37
- package/src/models/common_area_water.js +39 -39
- package/src/models/communication_status.js +33 -33
- package/src/models/communication_user_opt.js +32 -32
- package/src/models/company.js +53 -53
- package/src/models/coreBaseSettings.js +16 -16
- package/src/models/coreInvoiceSettings.js +100 -100
- package/src/models/counter_schema.js +21 -21
- package/src/models/country_tax.js +42 -42
- package/src/models/currency_settings.js +39 -39
- package/src/models/customer.js +210 -210
- package/src/models/customer_satisfaction_survey.js +278 -278
- package/src/models/customer_surveys.js +139 -139
- package/src/models/customer_tickets.js +239 -239
- package/src/models/dailyChecklist.js +312 -312
- package/src/models/default_payment_details.js +17 -17
- package/src/models/deliveryTimeMarks.js +18 -18
- package/src/models/document_type.js +19 -19
- package/src/models/dutyRosterChecklist.js +250 -250
- package/src/models/dutyroster.js +136 -136
- package/src/models/email.js +37 -37
- package/src/models/email_sms_queue.js +61 -61
- package/src/models/entry_exit.js +53 -53
- package/src/models/expense.js +99 -99
- package/src/models/expense_category.js +45 -45
- package/src/models/facility.js +62 -62
- package/src/models/facilityBillingPrices.js +29 -29
- package/src/models/facilityInvoice.js +223 -240
- package/src/models/facilityInvoicePayment.js +47 -52
- package/src/models/facilityInvoiceRecipient.js +32 -32
- package/src/models/facilityWalletTransactionsMetadata.js +236 -236
- package/src/models/facility_departements.js +20 -20
- package/src/models/facility_payment_details.js +20 -20
- package/src/models/facilityasset.js +25 -25
- package/src/models/faq.js +18 -18
- package/src/models/gl_account_double_entries.js +25 -25
- package/src/models/gl_accounts.js +56 -56
- package/src/models/gl_entries.js +49 -49
- package/src/models/goodsReceivedNotes.js +115 -115
- package/src/models/guard.js +47 -47
- package/src/models/handover.js +247 -247
- package/src/models/inspection_category.js +38 -38
- package/src/models/invoice.js +387 -387
- package/src/models/invoicing_schedule.js +36 -36
- package/src/models/item_inspection.js +96 -96
- package/src/models/knowledge_base.js +109 -109
- package/src/models/knowledge_base_rating.js +44 -44
- package/src/models/leaseagreement.js +236 -243
- package/src/models/leasetemplate.js +17 -17
- package/src/models/levy.js +223 -223
- package/src/models/levy_invoice_settings.js +26 -26
- package/src/models/levycontract.js +177 -173
- package/src/models/levytype.js +23 -23
- package/src/models/maintenance_service_vendor.js +38 -38
- package/src/models/maintenance_services.js +17 -17
- package/src/models/maintenancerequisition.js +31 -31
- package/src/models/master_workplan.js +32 -32
- package/src/models/master_workplan_child.js +34 -34
- package/src/models/message.js +38 -38
- package/src/models/module.js +21 -21
- package/src/models/notification.js +44 -44
- package/src/models/paymentTermsMarks.js +19 -19
- package/src/models/penalty.js +76 -76
- package/src/models/pendingCredentials.js +32 -32
- package/src/models/powerMeterCommunicationProtocol.js +17 -17
- package/src/models/powerMeterCustomerAccount.js +78 -78
- package/src/models/powerMeterCustomerBand.js +14 -14
- package/src/models/powerMeterDailyReading.js +30 -30
- package/src/models/powerMeterGateways.js +40 -40
- package/src/models/powerMeterMonthlyReading.js +34 -34
- package/src/models/powerMeterPowerCharges.js +85 -85
- package/src/models/powerMeterSettings.js +159 -159
- package/src/models/powerMeterSingleDayReading.js +32 -32
- package/src/models/powerMeters.js +116 -116
- package/src/models/powerMetersManufacturer.js +14 -14
- package/src/models/power_meter_account.js +81 -81
- package/src/models/power_meter_command_logs.js +30 -30
- package/src/models/power_meter_command_queue.js +33 -33
- package/src/models/power_meter_negative_balance.js +44 -44
- package/src/models/power_prepaid_credits.js +47 -47
- package/src/models/power_prepaid_debits.js +53 -53
- package/src/models/power_prepaid_orders.js +78 -78
- package/src/models/power_sms_notification.js +26 -26
- package/src/models/propertyManagerContract.js +556 -556
- package/src/models/propertyManagerRevenue.js +195 -195
- package/src/models/purchaseOrderInvoice.js +74 -74
- package/src/models/purchase_order.js +213 -213
- package/src/models/purchase_request.js +110 -110
- package/src/models/refresh_token.js +23 -23
- package/src/models/reminder.js +197 -197
- package/src/models/report.js +13 -13
- package/src/models/resident.js +121 -121
- package/src/models/rfq_details.js +131 -131
- package/src/models/rfq_response.js +153 -153
- package/src/models/service_charge_invoice_upload.js +42 -42
- package/src/models/service_charge_payments.js +27 -27
- package/src/models/servicerequest.js +55 -55
- package/src/models/settings.js +62 -62
- package/src/models/short_urls.js +21 -21
- package/src/models/smart_meter_daily_consumption.js +44 -44
- package/src/models/sms_africastalking.js +20 -20
- package/src/models/sms_balance_notification.js +26 -26
- package/src/models/sms_meliora.js +20 -20
- package/src/models/staff.js +36 -36
- package/src/models/stocksandspare.js +161 -161
- package/src/models/suppliers.js +74 -74
- package/src/models/tickets.js +173 -173
- package/src/models/tickets_category.js +72 -72
- package/src/models/unitManagementTemplate.js +44 -44
- package/src/models/unitasset.js +25 -25
- package/src/models/units.js +118 -118
- package/src/models/user.js +186 -186
- package/src/models/valueaddedservices.js +79 -79
- package/src/models/vas_invoices_upload.js +50 -50
- package/src/models/vas_payments.js +24 -24
- package/src/models/vasinvoice.js +192 -192
- package/src/models/vasvendor.js +57 -57
- package/src/models/visitLog.js +95 -95
- package/src/models/visitor.js +67 -67
- package/src/models/waitlist.js +45 -45
- package/src/models/wallet.js +44 -44
- package/src/models/wallet_transactions.js +50 -50
- package/src/models/water_invoice.js +351 -351
- package/src/models/water_meter_Command_Queue.js +33 -33
- package/src/models/water_meter_account.js +82 -82
- package/src/models/water_meter_billing.js +58 -58
- package/src/models/water_meter_communication.js +17 -17
- package/src/models/water_meter_communication_logs.js +39 -39
- package/src/models/water_meter_concentrator.js +70 -70
- package/src/models/water_meter_daily_history.js +32 -32
- package/src/models/water_meter_high_risk.js +36 -36
- package/src/models/water_meter_iot_cards.js +34 -34
- package/src/models/water_meter_manufacturer.js +35 -35
- package/src/models/water_meter_monthly_history.js +36 -36
- package/src/models/water_meter_negative_amounts.js +44 -44
- package/src/models/water_meter_settings.js +283 -276
- package/src/models/water_meter_single_day_history.js +34 -34
- package/src/models/water_meter_size.js +15 -15
- package/src/models/water_meters.js +133 -133
- package/src/models/water_meters_delivery.js +76 -76
- package/src/models/water_prepaid_credit.js +47 -47
- package/src/models/water_prepaid_debit.js +50 -50
- package/src/models/workorder.js +49 -49
|
@@ -1,312 +1,312 @@
|
|
|
1
|
-
const mongoose = require("mongoose");
|
|
2
|
-
|
|
3
|
-
// Reading entry schema - each individual reading with metadata
|
|
4
|
-
const readingEntrySchema = new mongoose.Schema(
|
|
5
|
-
{
|
|
6
|
-
value: {
|
|
7
|
-
type: mongoose.Schema.Types.Mixed, // String, Boolean, or Number
|
|
8
|
-
required: true,
|
|
9
|
-
},
|
|
10
|
-
date: {
|
|
11
|
-
type: Date,
|
|
12
|
-
required: true,
|
|
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
|
-
},
|
|
53
|
-
},
|
|
54
|
-
{ _id: true },
|
|
55
|
-
);
|
|
56
|
-
|
|
57
|
-
// Main facilities monitoring schema
|
|
58
|
-
const dailyChecklistSchema = new mongoose.Schema(
|
|
59
|
-
{
|
|
60
|
-
facilityId: {
|
|
61
|
-
type: String,
|
|
62
|
-
required: true,
|
|
63
|
-
},
|
|
64
|
-
// Dynamic parent-child structure with historical readings
|
|
65
|
-
// Parent_name -> [child_properties with readings]
|
|
66
|
-
data: {
|
|
67
|
-
type: Map,
|
|
68
|
-
of: [childPropertySchema], // Array of child properties for each parent
|
|
69
|
-
default: new Map(),
|
|
70
|
-
},
|
|
71
|
-
},
|
|
72
|
-
{
|
|
73
|
-
timestamps: true,
|
|
74
|
-
},
|
|
75
|
-
);
|
|
76
|
-
|
|
77
|
-
// Helper methods
|
|
78
|
-
dailyChecklistSchema.methods.addReading = function (
|
|
79
|
-
parentName,
|
|
80
|
-
childName,
|
|
81
|
-
value,
|
|
82
|
-
date = new Date(),
|
|
83
|
-
metadata = {},
|
|
84
|
-
) {
|
|
85
|
-
if (!this.data.has(parentName)) {
|
|
86
|
-
this.data.set(parentName, []);
|
|
87
|
-
}
|
|
88
|
-
|
|
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
|
-
|
|
122
|
-
this.markModified("data");
|
|
123
|
-
};
|
|
124
|
-
|
|
125
|
-
dailyChecklistSchema.methods.getCurrentValue = function (
|
|
126
|
-
parentName,
|
|
127
|
-
childName,
|
|
128
|
-
) {
|
|
129
|
-
const parent = this.data.get(parentName);
|
|
130
|
-
if (parent) {
|
|
131
|
-
const child = parent.find((c) => c.name === childName);
|
|
132
|
-
return child ? child.currentValue : null;
|
|
133
|
-
}
|
|
134
|
-
return null;
|
|
135
|
-
};
|
|
136
|
-
|
|
137
|
-
dailyChecklistSchema.methods.getReadingHistory = function (
|
|
138
|
-
parentName,
|
|
139
|
-
childName,
|
|
140
|
-
limit = null,
|
|
141
|
-
) {
|
|
142
|
-
const parent = this.data.get(parentName);
|
|
143
|
-
if (parent) {
|
|
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
|
-
}
|
|
163
|
-
}
|
|
164
|
-
return null;
|
|
165
|
-
};
|
|
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
|
-
|
|
227
|
-
dailyChecklistSchema.methods.createParent = function (parentName) {
|
|
228
|
-
if (!this.data.has(parentName)) {
|
|
229
|
-
this.data.set(parentName, []);
|
|
230
|
-
this.markModified("data");
|
|
231
|
-
}
|
|
232
|
-
};
|
|
233
|
-
|
|
234
|
-
dailyChecklistSchema.methods.hasParent = function (parentName) {
|
|
235
|
-
return this.data.has(parentName);
|
|
236
|
-
};
|
|
237
|
-
|
|
238
|
-
dailyChecklistSchema.methods.getParentNames = function () {
|
|
239
|
-
return Array.from(this.data.keys());
|
|
240
|
-
};
|
|
241
|
-
|
|
242
|
-
dailyChecklistSchema.methods.getChildNames = function (parentName) {
|
|
243
|
-
const parent = this.data.get(parentName);
|
|
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
|
-
};
|
|
310
|
-
};
|
|
311
|
-
|
|
312
|
-
module.exports = mongoose.model("DailyChecklist", dailyChecklistSchema);
|
|
1
|
+
const mongoose = require("mongoose");
|
|
2
|
+
|
|
3
|
+
// Reading entry schema - each individual reading with metadata
|
|
4
|
+
const readingEntrySchema = new mongoose.Schema(
|
|
5
|
+
{
|
|
6
|
+
value: {
|
|
7
|
+
type: mongoose.Schema.Types.Mixed, // String, Boolean, or Number
|
|
8
|
+
required: true,
|
|
9
|
+
},
|
|
10
|
+
date: {
|
|
11
|
+
type: Date,
|
|
12
|
+
required: true,
|
|
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
|
+
},
|
|
53
|
+
},
|
|
54
|
+
{ _id: true },
|
|
55
|
+
);
|
|
56
|
+
|
|
57
|
+
// Main facilities monitoring schema
|
|
58
|
+
const dailyChecklistSchema = new mongoose.Schema(
|
|
59
|
+
{
|
|
60
|
+
facilityId: {
|
|
61
|
+
type: String,
|
|
62
|
+
required: true,
|
|
63
|
+
},
|
|
64
|
+
// Dynamic parent-child structure with historical readings
|
|
65
|
+
// Parent_name -> [child_properties with readings]
|
|
66
|
+
data: {
|
|
67
|
+
type: Map,
|
|
68
|
+
of: [childPropertySchema], // Array of child properties for each parent
|
|
69
|
+
default: new Map(),
|
|
70
|
+
},
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
timestamps: true,
|
|
74
|
+
},
|
|
75
|
+
);
|
|
76
|
+
|
|
77
|
+
// Helper methods
|
|
78
|
+
dailyChecklistSchema.methods.addReading = function (
|
|
79
|
+
parentName,
|
|
80
|
+
childName,
|
|
81
|
+
value,
|
|
82
|
+
date = new Date(),
|
|
83
|
+
metadata = {},
|
|
84
|
+
) {
|
|
85
|
+
if (!this.data.has(parentName)) {
|
|
86
|
+
this.data.set(parentName, []);
|
|
87
|
+
}
|
|
88
|
+
|
|
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
|
+
|
|
122
|
+
this.markModified("data");
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
dailyChecklistSchema.methods.getCurrentValue = function (
|
|
126
|
+
parentName,
|
|
127
|
+
childName,
|
|
128
|
+
) {
|
|
129
|
+
const parent = this.data.get(parentName);
|
|
130
|
+
if (parent) {
|
|
131
|
+
const child = parent.find((c) => c.name === childName);
|
|
132
|
+
return child ? child.currentValue : null;
|
|
133
|
+
}
|
|
134
|
+
return null;
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
dailyChecklistSchema.methods.getReadingHistory = function (
|
|
138
|
+
parentName,
|
|
139
|
+
childName,
|
|
140
|
+
limit = null,
|
|
141
|
+
) {
|
|
142
|
+
const parent = this.data.get(parentName);
|
|
143
|
+
if (parent) {
|
|
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
|
+
}
|
|
163
|
+
}
|
|
164
|
+
return null;
|
|
165
|
+
};
|
|
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
|
+
|
|
227
|
+
dailyChecklistSchema.methods.createParent = function (parentName) {
|
|
228
|
+
if (!this.data.has(parentName)) {
|
|
229
|
+
this.data.set(parentName, []);
|
|
230
|
+
this.markModified("data");
|
|
231
|
+
}
|
|
232
|
+
};
|
|
233
|
+
|
|
234
|
+
dailyChecklistSchema.methods.hasParent = function (parentName) {
|
|
235
|
+
return this.data.has(parentName);
|
|
236
|
+
};
|
|
237
|
+
|
|
238
|
+
dailyChecklistSchema.methods.getParentNames = function () {
|
|
239
|
+
return Array.from(this.data.keys());
|
|
240
|
+
};
|
|
241
|
+
|
|
242
|
+
dailyChecklistSchema.methods.getChildNames = function (parentName) {
|
|
243
|
+
const parent = this.data.get(parentName);
|
|
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
|
+
};
|
|
310
|
+
};
|
|
311
|
+
|
|
312
|
+
module.exports = mongoose.model("DailyChecklist", dailyChecklistSchema);
|
|
@@ -1,18 +1,18 @@
|
|
|
1
|
-
const mongoose = require("mongoose");
|
|
2
|
-
|
|
3
|
-
const defaultPaymentDetailsSchema = new mongoose.Schema({
|
|
4
|
-
shortCode: { type: String },
|
|
5
|
-
passkey: { type: String },
|
|
6
|
-
authorizationKey: {
|
|
7
|
-
type: String,
|
|
8
|
-
},
|
|
9
|
-
module: {
|
|
10
|
-
type: String,
|
|
11
|
-
enum: ["All", "Water", "Electricity", "Levy","Lease"],
|
|
12
|
-
default: "All"
|
|
13
|
-
},
|
|
14
|
-
});
|
|
15
|
-
|
|
16
|
-
const DefaultPaymentDetails = mongoose.model('DefaultPaymentDetails', defaultPaymentDetailsSchema);
|
|
17
|
-
|
|
1
|
+
const mongoose = require("mongoose");
|
|
2
|
+
|
|
3
|
+
const defaultPaymentDetailsSchema = new mongoose.Schema({
|
|
4
|
+
shortCode: { type: String },
|
|
5
|
+
passkey: { type: String },
|
|
6
|
+
authorizationKey: {
|
|
7
|
+
type: String,
|
|
8
|
+
},
|
|
9
|
+
module: {
|
|
10
|
+
type: String,
|
|
11
|
+
enum: ["All", "Water", "Electricity", "Levy","Lease"],
|
|
12
|
+
default: "All"
|
|
13
|
+
},
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
const DefaultPaymentDetails = mongoose.model('DefaultPaymentDetails', defaultPaymentDetailsSchema);
|
|
17
|
+
|
|
18
18
|
module.exports = DefaultPaymentDetails;
|