payservedb 6.5.8 → 6.6.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.
Files changed (141) hide show
  1. package/.env +2 -2
  2. package/index.js +277 -277
  3. package/package.json +17 -17
  4. package/src/models/account.js +35 -35
  5. package/src/models/apilog.js +18 -18
  6. package/src/models/approvalsWorkflows.js +49 -49
  7. package/src/models/archivedapilog.js +18 -18
  8. package/src/models/archivedauditlog.js +83 -83
  9. package/src/models/asset.js +92 -92
  10. package/src/models/assetsAssignment.js +64 -64
  11. package/src/models/auditTrail.js +319 -319
  12. package/src/models/auditlog.js +83 -83
  13. package/src/models/bankdetails.js +40 -40
  14. package/src/models/billerAddress.js +119 -119
  15. package/src/models/booking_invoice.js +151 -151
  16. package/src/models/bookinganalytics.js +63 -63
  17. package/src/models/bookingconfig.js +45 -45
  18. package/src/models/bookingproperty.js +122 -122
  19. package/src/models/bookingreservation.js +192 -192
  20. package/src/models/bookingrevenuerecord.js +84 -84
  21. package/src/models/budget.js +95 -95
  22. package/src/models/budgetCategory.js +19 -19
  23. package/src/models/campaigns.js +94 -94
  24. package/src/models/cashpayment.js +264 -264
  25. package/src/models/combinedUnits.js +62 -62
  26. package/src/models/common_area_electricity.js +38 -38
  27. package/src/models/common_area_generator.js +41 -41
  28. package/src/models/common_area_utility_alert.js +37 -37
  29. package/src/models/common_area_water.js +39 -39
  30. package/src/models/communication_status.js +33 -33
  31. package/src/models/company.js +53 -53
  32. package/src/models/country_tax.js +42 -42
  33. package/src/models/currency_settings.js +39 -39
  34. package/src/models/customer.js +208 -208
  35. package/src/models/dailyChecklist.js +97 -0
  36. package/src/models/default_payment_details.js +17 -17
  37. package/src/models/deliveryTimeMarks.js +18 -18
  38. package/src/models/dutyRosterChecklist.js +250 -250
  39. package/src/models/dutyroster.js +136 -136
  40. package/src/models/email.js +37 -37
  41. package/src/models/email_sms_queue.js +61 -61
  42. package/src/models/entry_exit.js +53 -53
  43. package/src/models/expense.js +99 -99
  44. package/src/models/expense_category.js +45 -45
  45. package/src/models/facility.js +61 -61
  46. package/src/models/facilityWalletTransactionsMetadata.js +236 -236
  47. package/src/models/facility_departements.js +20 -20
  48. package/src/models/facility_payment_details.js +20 -20
  49. package/src/models/facilityasset.js +25 -25
  50. package/src/models/faq.js +18 -18
  51. package/src/models/gl_account_double_entries.js +25 -25
  52. package/src/models/gl_accounts.js +56 -56
  53. package/src/models/gl_entries.js +49 -49
  54. package/src/models/goodsReceivedNotes.js +115 -115
  55. package/src/models/guard.js +47 -47
  56. package/src/models/handover.js +246 -246
  57. package/src/models/invoice.js +336 -336
  58. package/src/models/item_inspection.js +67 -67
  59. package/src/models/leaseagreement.js +226 -226
  60. package/src/models/leasetemplate.js +17 -17
  61. package/src/models/levy.js +206 -206
  62. package/src/models/levy_invoice_settings.js +26 -26
  63. package/src/models/levycontract.js +117 -117
  64. package/src/models/levytype.js +23 -23
  65. package/src/models/maintenance_service_vendor.js +38 -38
  66. package/src/models/maintenance_services.js +17 -17
  67. package/src/models/maintenancerequisition.js +31 -31
  68. package/src/models/master_workplan.js +32 -32
  69. package/src/models/master_workplan_child.js +34 -34
  70. package/src/models/message.js +38 -38
  71. package/src/models/module.js +21 -21
  72. package/src/models/notification.js +44 -44
  73. package/src/models/paymentTermsMarks.js +19 -19
  74. package/src/models/penalty.js +76 -76
  75. package/src/models/pendingCredentials.js +32 -32
  76. package/src/models/powerMeterCustomerAccount.js +78 -78
  77. package/src/models/powerMeterCustomerBand.js +14 -14
  78. package/src/models/powerMeterDailyReading.js +30 -30
  79. package/src/models/powerMeterMonthlyReading.js +34 -34
  80. package/src/models/powerMeterPowerCharges.js +53 -53
  81. package/src/models/powerMeterSettings.js +138 -138
  82. package/src/models/powerMeterSingleDayReading.js +32 -32
  83. package/src/models/powerMeters.js +65 -65
  84. package/src/models/powerMetersManufacturer.js +14 -14
  85. package/src/models/propertyManagerContract.js +556 -556
  86. package/src/models/propertyManagerRevenue.js +195 -195
  87. package/src/models/purchaseOrderInvoice.js +74 -74
  88. package/src/models/purchase_order.js +213 -213
  89. package/src/models/purchase_request.js +110 -110
  90. package/src/models/refresh_token.js +23 -23
  91. package/src/models/reminder.js +197 -197
  92. package/src/models/report.js +13 -13
  93. package/src/models/resident.js +121 -121
  94. package/src/models/rfq_details.js +131 -131
  95. package/src/models/rfq_response.js +153 -153
  96. package/src/models/service_charge_invoice_upload.js +42 -42
  97. package/src/models/service_charge_payments.js +27 -27
  98. package/src/models/servicerequest.js +55 -55
  99. package/src/models/settings.js +62 -62
  100. package/src/models/smart_meter_daily_consumption.js +44 -44
  101. package/src/models/sms_africastalking.js +20 -20
  102. package/src/models/sms_balance_notification.js +26 -26
  103. package/src/models/sms_meliora.js +20 -20
  104. package/src/models/staff.js +36 -36
  105. package/src/models/stocksandspare.js +161 -161
  106. package/src/models/suppliers.js +74 -74
  107. package/src/models/tickets.js +121 -121
  108. package/src/models/unitManagementTemplate.js +44 -44
  109. package/src/models/unitasset.js +25 -25
  110. package/src/models/units.js +117 -117
  111. package/src/models/user.js +186 -186
  112. package/src/models/valueaddedservices.js +79 -79
  113. package/src/models/vas_invoices_upload.js +50 -50
  114. package/src/models/vas_payments.js +24 -24
  115. package/src/models/vasinvoice.js +192 -192
  116. package/src/models/vasvendor.js +57 -57
  117. package/src/models/visitLog.js +86 -86
  118. package/src/models/visitor.js +67 -67
  119. package/src/models/waitlist.js +45 -45
  120. package/src/models/wallet.js +44 -44
  121. package/src/models/wallet_transactions.js +50 -50
  122. package/src/models/water_invoice.js +305 -305
  123. package/src/models/water_meter_Command_Queue.js +33 -33
  124. package/src/models/water_meter_account.js +78 -78
  125. package/src/models/water_meter_billing.js +58 -58
  126. package/src/models/water_meter_communication.js +17 -17
  127. package/src/models/water_meter_communication_logs.js +30 -30
  128. package/src/models/water_meter_concentrator.js +66 -66
  129. package/src/models/water_meter_daily_history.js +32 -32
  130. package/src/models/water_meter_iot_cards.js +34 -34
  131. package/src/models/water_meter_manufacturer.js +35 -35
  132. package/src/models/water_meter_monthly_history.js +36 -36
  133. package/src/models/water_meter_negative_amounts.js +38 -38
  134. package/src/models/water_meter_settings.js +180 -180
  135. package/src/models/water_meter_single_day_history.js +34 -34
  136. package/src/models/water_meter_size.js +15 -15
  137. package/src/models/water_meters.js +134 -134
  138. package/src/models/water_meters_delivery.js +76 -76
  139. package/src/models/water_prepaid_credit.js +47 -47
  140. package/src/models/water_prepaid_debit.js +50 -50
  141. package/src/models/workorder.js +49 -49
@@ -1,320 +1,320 @@
1
- const mongoose = require("mongoose");
2
-
3
- // User details sub-schema (from JWT token)
4
- const userDetailsSchema = new mongoose.Schema(
5
- {
6
- userId: {
7
- type: String,
8
- required: true,
9
- },
10
- email: {
11
- type: String,
12
- required: true,
13
- },
14
- fullName: {
15
- type: String,
16
- required: true,
17
- },
18
- role: {
19
- type: String,
20
- required: true,
21
- },
22
- phoneNumber: {
23
- type: String,
24
- required: false,
25
- },
26
- facilityId: {
27
- type: String,
28
- required: false,
29
- },
30
- permissions: {
31
- type: mongoose.Schema.Types.Mixed,
32
- required: false,
33
- },
34
- tokenExpiry: {
35
- type: Date,
36
- required: false,
37
- },
38
- tokenIssued: {
39
- type: Date,
40
- required: false,
41
- },
42
- },
43
- { _id: false }
44
- );
45
-
46
- // Main audit trail schema
47
- const auditTrailSchema = new mongoose.Schema(
48
- {
49
- // Basic request information
50
- timestamp: {
51
- type: Date,
52
- required: true,
53
- default: Date.now,
54
- },
55
- method: {
56
- type: String,
57
- enum: ["GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS", "HEAD"],
58
- required: true,
59
- },
60
- url: {
61
- type: String,
62
- required: true,
63
- },
64
- ip_address: {
65
- type: String,
66
- required: true,
67
- },
68
- platform: {
69
- type: String,
70
- required: true,
71
- },
72
-
73
- // Authorization and user information
74
- is_authorized: {
75
- type: Boolean,
76
- required: true,
77
- default: false,
78
- },
79
- user_details: {
80
- type: userDetailsSchema,
81
- required: false,
82
- },
83
-
84
- // Device and browser information
85
- browser: {
86
- type: String,
87
- required: true,
88
- default: "unknown",
89
- },
90
- operating_system: {
91
- type: String,
92
- required: true,
93
- default: "unknown",
94
- },
95
- device_type: {
96
- type: String,
97
- enum: ["desktop", "mobile", "tablet", "unknown"],
98
- required: true,
99
- default: "unknown",
100
- },
101
- user_agent: {
102
- type: String,
103
- required: false,
104
- },
105
-
106
- // Request data
107
- request_data: {
108
- type: mongoose.Schema.Types.Mixed,
109
- required: false,
110
- },
111
- query_params: {
112
- type: mongoose.Schema.Types.Mixed,
113
- required: false,
114
- default: {},
115
- },
116
- route_params: {
117
- type: mongoose.Schema.Types.Mixed,
118
- required: false,
119
- default: {},
120
- },
121
-
122
- // Activity information
123
- activity: {
124
- type: String,
125
- required: true,
126
- },
127
-
128
- // Method-specific data
129
- previous_data: {
130
- type: mongoose.Schema.Types.Mixed,
131
- required: false,
132
- },
133
- deleted_data: {
134
- type: mongoose.Schema.Types.Mixed,
135
- required: false,
136
- },
137
-
138
- // Custom additional data
139
- custom_data: {
140
- type: mongoose.Schema.Types.Mixed,
141
- required: false,
142
- },
143
-
144
- // Request tracking
145
- request_id: {
146
- type: String,
147
- required: false,
148
- },
149
- },
150
- {
151
- timestamps: true,
152
- }
153
- );
154
-
155
- // Pre-save middleware for data validation and cleanup
156
- auditTrailSchema.pre("save", function (next) {
157
- // Ensure timestamp is set
158
- if (!this.timestamp) {
159
- this.timestamp = new Date();
160
- }
161
-
162
- // Validate that authorized requests have user details
163
- if (this.is_authorized && !this.user_details) {
164
- console.warn("Authorized request without user details detected");
165
- }
166
-
167
- // Ensure query_params and route_params are objects
168
- if (!this.query_params || typeof this.query_params !== "object") {
169
- this.query_params = {};
170
- }
171
- if (!this.route_params || typeof this.route_params !== "object") {
172
- this.route_params = {};
173
- }
174
-
175
- // Set browser to unknown if not provided
176
- if (!this.browser) {
177
- this.browser = "unknown";
178
- }
179
-
180
- // Set operating_system to unknown if not provided
181
- if (!this.operating_system) {
182
- this.operating_system = "unknown";
183
- }
184
-
185
- next();
186
- });
187
-
188
- // Static methods for common queries
189
- auditTrailSchema.statics.findByUser = function (userId, startDate, endDate) {
190
- const query = { "user_details.userId": userId };
191
- if (startDate || endDate) {
192
- query.timestamp = {};
193
- if (startDate) query.timestamp.$gte = startDate;
194
- if (endDate) query.timestamp.$lte = endDate;
195
- }
196
- return this.find(query).sort({ timestamp: -1 });
197
- };
198
-
199
- auditTrailSchema.statics.findByActivity = function (activity, limit = 100) {
200
- return this.find({ activity: new RegExp(activity, "i") })
201
- .sort({ timestamp: -1 })
202
- .limit(limit);
203
- };
204
-
205
- auditTrailSchema.statics.findByFacility = function (facilityId, startDate, endDate) {
206
- const query = { "route_params.facilityId": facilityId };
207
- if (startDate || endDate) {
208
- query.timestamp = {};
209
- if (startDate) query.timestamp.$gte = startDate;
210
- if (endDate) query.timestamp.$lte = endDate;
211
- }
212
- return this.find(query).sort({ timestamp: -1 });
213
- };
214
-
215
- auditTrailSchema.statics.findByAsset = function (assetId, startDate, endDate) {
216
- const query = { "route_params.assetId": assetId };
217
- if (startDate || endDate) {
218
- query.timestamp = {};
219
- if (startDate) query.timestamp.$gte = startDate;
220
- if (endDate) query.timestamp.$lte = endDate;
221
- }
222
- return this.find(query).sort({ timestamp: -1 });
223
- };
224
-
225
- auditTrailSchema.statics.findByIP = function (ipAddress, startDate, endDate) {
226
- const query = { ip_address: ipAddress };
227
- if (startDate || endDate) {
228
- query.timestamp = {};
229
- if (startDate) query.timestamp.$gte = startDate;
230
- if (endDate) query.timestamp.$lte = endDate;
231
- }
232
- return this.find(query).sort({ timestamp: -1 });
233
- };
234
-
235
- auditTrailSchema.statics.findByMethod = function (method, startDate, endDate) {
236
- const query = { method: method.toUpperCase() };
237
- if (startDate || endDate) {
238
- query.timestamp = {};
239
- if (startDate) query.timestamp.$gte = startDate;
240
- if (endDate) query.timestamp.$lte = endDate;
241
- }
242
- return this.find(query).sort({ timestamp: -1 });
243
- };
244
-
245
- // Instance methods
246
- auditTrailSchema.methods.getActivityType = function () {
247
- if (this.activity.includes("Create")) return "CREATE";
248
- if (this.activity.includes("Update")) return "UPDATE";
249
- if (this.activity.includes("Delete")) return "DELETE";
250
- if (this.activity.includes("Login")) return "AUTH";
251
- return "OTHER";
252
- };
253
-
254
- auditTrailSchema.methods.isSuccessful = function () {
255
- return this.activity.includes("Success") ||
256
- (!this.activity.includes("Failed") &&
257
- !this.activity.includes("Error") &&
258
- !this.activity.includes("Not Found"));
259
- };
260
-
261
- auditTrailSchema.methods.hasDataChanges = function () {
262
- return !!(this.previous_data || this.deleted_data);
263
- };
264
-
265
- // Create indexes for efficient queries
266
- auditTrailSchema.index({ timestamp: -1 }); // Recent activities first
267
- auditTrailSchema.index({ "user_details.userId": 1, timestamp: -1 }); // User activity history
268
- auditTrailSchema.index({ "user_details.email": 1, timestamp: -1 }); // User by email
269
- auditTrailSchema.index({ ip_address: 1, timestamp: -1 }); // IP-based queries
270
- auditTrailSchema.index({ method: 1, timestamp: -1 }); // Method-based queries
271
- auditTrailSchema.index({ activity: 1, timestamp: -1 }); // Activity-based queries
272
- auditTrailSchema.index({ platform: 1, timestamp: -1 }); // Platform-based queries
273
- auditTrailSchema.index({ "route_params.facilityId": 1, timestamp: -1 }); // Facility-based queries
274
- auditTrailSchema.index({ "route_params.assetId": 1, timestamp: -1 }); // Asset-based queries
275
- auditTrailSchema.index({ is_authorized: 1, timestamp: -1 }); // Authorization status
276
- auditTrailSchema.index({ device_type: 1, timestamp: -1 }); // Device type queries
277
- auditTrailSchema.index({ browser: 1, timestamp: -1 }); // Browser-based queries
278
-
279
- // Compound indexes for common query patterns
280
- auditTrailSchema.index({ "user_details.userId": 1, activity: 1, timestamp: -1 }); // User + activity
281
- auditTrailSchema.index({ "route_params.facilityId": 1, method: 1, timestamp: -1 }); // Facility + method
282
- auditTrailSchema.index({ ip_address: 1, "user_details.userId": 1, timestamp: -1 }); // IP + user correlation
283
-
284
- // Text search index for searching activities and user details
285
- auditTrailSchema.index({
286
- activity: "text",
287
- "user_details.email": "text",
288
- "user_details.fullName": "text",
289
- url: "text",
290
- });
291
-
292
- // Activity type constants
293
- auditTrailSchema.statics.ACTIVITY_TYPES = {
294
- CREATE: "CREATE",
295
- UPDATE: "UPDATE",
296
- DELETE: "DELETE",
297
- AUTH: "AUTH",
298
- OTHER: "OTHER",
299
- };
300
-
301
- // Method constants
302
- auditTrailSchema.statics.METHODS = {
303
- GET: "GET",
304
- POST: "POST",
305
- PUT: "PUT",
306
- PATCH: "PATCH",
307
- DELETE: "DELETE",
308
- OPTIONS: "OPTIONS",
309
- HEAD: "HEAD",
310
- };
311
-
312
- // Device type constants
313
- auditTrailSchema.statics.DEVICE_TYPES = {
314
- DESKTOP: "desktop",
315
- MOBILE: "mobile",
316
- TABLET: "tablet",
317
- UNKNOWN: "unknown",
318
- };
319
-
1
+ const mongoose = require("mongoose");
2
+
3
+ // User details sub-schema (from JWT token)
4
+ const userDetailsSchema = new mongoose.Schema(
5
+ {
6
+ userId: {
7
+ type: String,
8
+ required: true,
9
+ },
10
+ email: {
11
+ type: String,
12
+ required: true,
13
+ },
14
+ fullName: {
15
+ type: String,
16
+ required: true,
17
+ },
18
+ role: {
19
+ type: String,
20
+ required: true,
21
+ },
22
+ phoneNumber: {
23
+ type: String,
24
+ required: false,
25
+ },
26
+ facilityId: {
27
+ type: String,
28
+ required: false,
29
+ },
30
+ permissions: {
31
+ type: mongoose.Schema.Types.Mixed,
32
+ required: false,
33
+ },
34
+ tokenExpiry: {
35
+ type: Date,
36
+ required: false,
37
+ },
38
+ tokenIssued: {
39
+ type: Date,
40
+ required: false,
41
+ },
42
+ },
43
+ { _id: false }
44
+ );
45
+
46
+ // Main audit trail schema
47
+ const auditTrailSchema = new mongoose.Schema(
48
+ {
49
+ // Basic request information
50
+ timestamp: {
51
+ type: Date,
52
+ required: true,
53
+ default: Date.now,
54
+ },
55
+ method: {
56
+ type: String,
57
+ enum: ["GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS", "HEAD"],
58
+ required: true,
59
+ },
60
+ url: {
61
+ type: String,
62
+ required: true,
63
+ },
64
+ ip_address: {
65
+ type: String,
66
+ required: true,
67
+ },
68
+ platform: {
69
+ type: String,
70
+ required: true,
71
+ },
72
+
73
+ // Authorization and user information
74
+ is_authorized: {
75
+ type: Boolean,
76
+ required: true,
77
+ default: false,
78
+ },
79
+ user_details: {
80
+ type: userDetailsSchema,
81
+ required: false,
82
+ },
83
+
84
+ // Device and browser information
85
+ browser: {
86
+ type: String,
87
+ required: true,
88
+ default: "unknown",
89
+ },
90
+ operating_system: {
91
+ type: String,
92
+ required: true,
93
+ default: "unknown",
94
+ },
95
+ device_type: {
96
+ type: String,
97
+ enum: ["desktop", "mobile", "tablet", "unknown"],
98
+ required: true,
99
+ default: "unknown",
100
+ },
101
+ user_agent: {
102
+ type: String,
103
+ required: false,
104
+ },
105
+
106
+ // Request data
107
+ request_data: {
108
+ type: mongoose.Schema.Types.Mixed,
109
+ required: false,
110
+ },
111
+ query_params: {
112
+ type: mongoose.Schema.Types.Mixed,
113
+ required: false,
114
+ default: {},
115
+ },
116
+ route_params: {
117
+ type: mongoose.Schema.Types.Mixed,
118
+ required: false,
119
+ default: {},
120
+ },
121
+
122
+ // Activity information
123
+ activity: {
124
+ type: String,
125
+ required: true,
126
+ },
127
+
128
+ // Method-specific data
129
+ previous_data: {
130
+ type: mongoose.Schema.Types.Mixed,
131
+ required: false,
132
+ },
133
+ deleted_data: {
134
+ type: mongoose.Schema.Types.Mixed,
135
+ required: false,
136
+ },
137
+
138
+ // Custom additional data
139
+ custom_data: {
140
+ type: mongoose.Schema.Types.Mixed,
141
+ required: false,
142
+ },
143
+
144
+ // Request tracking
145
+ request_id: {
146
+ type: String,
147
+ required: false,
148
+ },
149
+ },
150
+ {
151
+ timestamps: true,
152
+ }
153
+ );
154
+
155
+ // Pre-save middleware for data validation and cleanup
156
+ auditTrailSchema.pre("save", function (next) {
157
+ // Ensure timestamp is set
158
+ if (!this.timestamp) {
159
+ this.timestamp = new Date();
160
+ }
161
+
162
+ // Validate that authorized requests have user details
163
+ if (this.is_authorized && !this.user_details) {
164
+ console.warn("Authorized request without user details detected");
165
+ }
166
+
167
+ // Ensure query_params and route_params are objects
168
+ if (!this.query_params || typeof this.query_params !== "object") {
169
+ this.query_params = {};
170
+ }
171
+ if (!this.route_params || typeof this.route_params !== "object") {
172
+ this.route_params = {};
173
+ }
174
+
175
+ // Set browser to unknown if not provided
176
+ if (!this.browser) {
177
+ this.browser = "unknown";
178
+ }
179
+
180
+ // Set operating_system to unknown if not provided
181
+ if (!this.operating_system) {
182
+ this.operating_system = "unknown";
183
+ }
184
+
185
+ next();
186
+ });
187
+
188
+ // Static methods for common queries
189
+ auditTrailSchema.statics.findByUser = function (userId, startDate, endDate) {
190
+ const query = { "user_details.userId": userId };
191
+ if (startDate || endDate) {
192
+ query.timestamp = {};
193
+ if (startDate) query.timestamp.$gte = startDate;
194
+ if (endDate) query.timestamp.$lte = endDate;
195
+ }
196
+ return this.find(query).sort({ timestamp: -1 });
197
+ };
198
+
199
+ auditTrailSchema.statics.findByActivity = function (activity, limit = 100) {
200
+ return this.find({ activity: new RegExp(activity, "i") })
201
+ .sort({ timestamp: -1 })
202
+ .limit(limit);
203
+ };
204
+
205
+ auditTrailSchema.statics.findByFacility = function (facilityId, startDate, endDate) {
206
+ const query = { "route_params.facilityId": facilityId };
207
+ if (startDate || endDate) {
208
+ query.timestamp = {};
209
+ if (startDate) query.timestamp.$gte = startDate;
210
+ if (endDate) query.timestamp.$lte = endDate;
211
+ }
212
+ return this.find(query).sort({ timestamp: -1 });
213
+ };
214
+
215
+ auditTrailSchema.statics.findByAsset = function (assetId, startDate, endDate) {
216
+ const query = { "route_params.assetId": assetId };
217
+ if (startDate || endDate) {
218
+ query.timestamp = {};
219
+ if (startDate) query.timestamp.$gte = startDate;
220
+ if (endDate) query.timestamp.$lte = endDate;
221
+ }
222
+ return this.find(query).sort({ timestamp: -1 });
223
+ };
224
+
225
+ auditTrailSchema.statics.findByIP = function (ipAddress, startDate, endDate) {
226
+ const query = { ip_address: ipAddress };
227
+ if (startDate || endDate) {
228
+ query.timestamp = {};
229
+ if (startDate) query.timestamp.$gte = startDate;
230
+ if (endDate) query.timestamp.$lte = endDate;
231
+ }
232
+ return this.find(query).sort({ timestamp: -1 });
233
+ };
234
+
235
+ auditTrailSchema.statics.findByMethod = function (method, startDate, endDate) {
236
+ const query = { method: method.toUpperCase() };
237
+ if (startDate || endDate) {
238
+ query.timestamp = {};
239
+ if (startDate) query.timestamp.$gte = startDate;
240
+ if (endDate) query.timestamp.$lte = endDate;
241
+ }
242
+ return this.find(query).sort({ timestamp: -1 });
243
+ };
244
+
245
+ // Instance methods
246
+ auditTrailSchema.methods.getActivityType = function () {
247
+ if (this.activity.includes("Create")) return "CREATE";
248
+ if (this.activity.includes("Update")) return "UPDATE";
249
+ if (this.activity.includes("Delete")) return "DELETE";
250
+ if (this.activity.includes("Login")) return "AUTH";
251
+ return "OTHER";
252
+ };
253
+
254
+ auditTrailSchema.methods.isSuccessful = function () {
255
+ return this.activity.includes("Success") ||
256
+ (!this.activity.includes("Failed") &&
257
+ !this.activity.includes("Error") &&
258
+ !this.activity.includes("Not Found"));
259
+ };
260
+
261
+ auditTrailSchema.methods.hasDataChanges = function () {
262
+ return !!(this.previous_data || this.deleted_data);
263
+ };
264
+
265
+ // Create indexes for efficient queries
266
+ auditTrailSchema.index({ timestamp: -1 }); // Recent activities first
267
+ auditTrailSchema.index({ "user_details.userId": 1, timestamp: -1 }); // User activity history
268
+ auditTrailSchema.index({ "user_details.email": 1, timestamp: -1 }); // User by email
269
+ auditTrailSchema.index({ ip_address: 1, timestamp: -1 }); // IP-based queries
270
+ auditTrailSchema.index({ method: 1, timestamp: -1 }); // Method-based queries
271
+ auditTrailSchema.index({ activity: 1, timestamp: -1 }); // Activity-based queries
272
+ auditTrailSchema.index({ platform: 1, timestamp: -1 }); // Platform-based queries
273
+ auditTrailSchema.index({ "route_params.facilityId": 1, timestamp: -1 }); // Facility-based queries
274
+ auditTrailSchema.index({ "route_params.assetId": 1, timestamp: -1 }); // Asset-based queries
275
+ auditTrailSchema.index({ is_authorized: 1, timestamp: -1 }); // Authorization status
276
+ auditTrailSchema.index({ device_type: 1, timestamp: -1 }); // Device type queries
277
+ auditTrailSchema.index({ browser: 1, timestamp: -1 }); // Browser-based queries
278
+
279
+ // Compound indexes for common query patterns
280
+ auditTrailSchema.index({ "user_details.userId": 1, activity: 1, timestamp: -1 }); // User + activity
281
+ auditTrailSchema.index({ "route_params.facilityId": 1, method: 1, timestamp: -1 }); // Facility + method
282
+ auditTrailSchema.index({ ip_address: 1, "user_details.userId": 1, timestamp: -1 }); // IP + user correlation
283
+
284
+ // Text search index for searching activities and user details
285
+ auditTrailSchema.index({
286
+ activity: "text",
287
+ "user_details.email": "text",
288
+ "user_details.fullName": "text",
289
+ url: "text",
290
+ });
291
+
292
+ // Activity type constants
293
+ auditTrailSchema.statics.ACTIVITY_TYPES = {
294
+ CREATE: "CREATE",
295
+ UPDATE: "UPDATE",
296
+ DELETE: "DELETE",
297
+ AUTH: "AUTH",
298
+ OTHER: "OTHER",
299
+ };
300
+
301
+ // Method constants
302
+ auditTrailSchema.statics.METHODS = {
303
+ GET: "GET",
304
+ POST: "POST",
305
+ PUT: "PUT",
306
+ PATCH: "PATCH",
307
+ DELETE: "DELETE",
308
+ OPTIONS: "OPTIONS",
309
+ HEAD: "HEAD",
310
+ };
311
+
312
+ // Device type constants
313
+ auditTrailSchema.statics.DEVICE_TYPES = {
314
+ DESKTOP: "desktop",
315
+ MOBILE: "mobile",
316
+ TABLET: "tablet",
317
+ UNKNOWN: "unknown",
318
+ };
319
+
320
320
  module.exports = mongoose.model("AuditTrail", auditTrailSchema);