payservedb 9.5.1 → 9.5.3

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 (232) hide show
  1. package/.env +2 -2
  2. package/ZOHO_INTEGRATION_SCHEMA.md +644 -644
  3. package/index.js +418 -417
  4. package/package.json +17 -17
  5. package/src/models/InvoiceWithholdingTax.js +67 -67
  6. package/src/models/account.js +59 -59
  7. package/src/models/agent_departments.js +59 -59
  8. package/src/models/agent_notifications.js +53 -53
  9. package/src/models/agent_performance.js +127 -127
  10. package/src/models/agent_roles.js +77 -77
  11. package/src/models/agents.js +154 -154
  12. package/src/models/apilog.js +18 -18
  13. package/src/models/approvalsWorkflows.js +49 -49
  14. package/src/models/archivedapilog.js +18 -18
  15. package/src/models/asset.js +92 -92
  16. package/src/models/assetsAssignment.js +64 -64
  17. package/src/models/auditTrail.js +346 -346
  18. package/src/models/auto_reply_rule.js +68 -68
  19. package/src/models/bankdetails.js +47 -47
  20. package/src/models/billerAddress.js +124 -124
  21. package/src/models/booking_invoice.js +187 -187
  22. package/src/models/bookinganalytics.js +63 -63
  23. package/src/models/bookingconfig.js +67 -67
  24. package/src/models/bookingproperty.js +187 -187
  25. package/src/models/bookingreservation.js +266 -266
  26. package/src/models/bookingrevenuerecord.js +84 -84
  27. package/src/models/budget.js +95 -95
  28. package/src/models/budgetCategory.js +19 -19
  29. package/src/models/campaigns.js +108 -108
  30. package/src/models/cancellation_policy.js +56 -56
  31. package/src/models/cashpayment.js +289 -289
  32. package/src/models/combinedUnits.js +62 -62
  33. package/src/models/combined_invoice.js +424 -424
  34. package/src/models/common_area_electricity.js +38 -38
  35. package/src/models/common_area_generator.js +41 -41
  36. package/src/models/common_area_utility_alert.js +37 -37
  37. package/src/models/common_area_water.js +39 -39
  38. package/src/models/communication_status.js +33 -33
  39. package/src/models/communication_user_opt.js +32 -32
  40. package/src/models/community_guidelines.js +35 -35
  41. package/src/models/company.js +53 -53
  42. package/src/models/coreBaseSettings.js +16 -16
  43. package/src/models/coreInvoiceSettings.js +100 -100
  44. package/src/models/counter_schema.js +21 -21
  45. package/src/models/country_tax.js +42 -42
  46. package/src/models/currency_settings.js +39 -39
  47. package/src/models/customer.js +251 -251
  48. package/src/models/customer_preference.js +52 -52
  49. package/src/models/customer_satisfaction_survey.js +297 -297
  50. package/src/models/customer_surveys.js +139 -139
  51. package/src/models/customer_tickets.js +237 -237
  52. package/src/models/dailyChecklist.js +312 -312
  53. package/src/models/default_payment_details.js +17 -17
  54. package/src/models/deliveryTimeMarks.js +18 -18
  55. package/src/models/document_type.js +19 -19
  56. package/src/models/dutyRosterChecklist.js +250 -250
  57. package/src/models/dutyroster.js +136 -136
  58. package/src/models/email.js +37 -37
  59. package/src/models/email_cc_config.js +48 -48
  60. package/src/models/email_sms_queue.js +61 -61
  61. package/src/models/email_thread.js +35 -35
  62. package/src/models/entry_exit.js +53 -53
  63. package/src/models/expense.js +99 -99
  64. package/src/models/expense_category.js +45 -45
  65. package/src/models/facility.js +100 -76
  66. package/src/models/facilityBillingPrices.js +29 -29
  67. package/src/models/facilityInvoice.js +240 -240
  68. package/src/models/facilityInvoicePayment.js +52 -52
  69. package/src/models/facilityInvoiceRecipient.js +32 -32
  70. package/src/models/facilityWalletTransactionsMetadata.js +236 -236
  71. package/src/models/facility_departements.js +20 -20
  72. package/src/models/facility_etims_config.js +116 -116
  73. package/src/models/facility_payment_details.js +20 -20
  74. package/src/models/facility_rating.js +78 -78
  75. package/src/models/facilityasset.js +25 -25
  76. package/src/models/faq.js +15 -15
  77. package/src/models/gl_account_double_entries.js +25 -25
  78. package/src/models/gl_accounts.js +56 -56
  79. package/src/models/gl_entries.js +49 -49
  80. package/src/models/goodsReceivedNotes.js +115 -115
  81. package/src/models/guard.js +47 -47
  82. package/src/models/handover.js +258 -258
  83. package/src/models/inspection_category.js +38 -38
  84. package/src/models/invoice.js +569 -569
  85. package/src/models/invoiceCreditAdjustment.js +45 -45
  86. package/src/models/invoice_edit_log.js +81 -81
  87. package/src/models/invoice_generation_approval.js +86 -86
  88. package/src/models/invoicing_schedule.js +40 -40
  89. package/src/models/item_inspection.js +96 -96
  90. package/src/models/knowledge_base.js +109 -109
  91. package/src/models/knowledge_base_rating.js +44 -44
  92. package/src/models/leaseagreement.js +266 -266
  93. package/src/models/leasetemplate.js +17 -17
  94. package/src/models/levy.js +231 -231
  95. package/src/models/levy_deposits.js +139 -139
  96. package/src/models/levy_invoice_settings.js +26 -26
  97. package/src/models/levy_payment_receipt.js +156 -156
  98. package/src/models/levycontract.js +213 -213
  99. package/src/models/levytype.js +23 -23
  100. package/src/models/maintenance_service_vendor.js +38 -38
  101. package/src/models/maintenance_services.js +17 -17
  102. package/src/models/maintenancerequisition.js +31 -31
  103. package/src/models/master_workplan.js +32 -32
  104. package/src/models/master_workplan_child.js +34 -34
  105. package/src/models/message.js +38 -38
  106. package/src/models/module.js +21 -21
  107. package/src/models/movein_amenity.js +13 -13
  108. package/src/models/movein_application.js +28 -28
  109. package/src/models/movein_audit_log.js +21 -21
  110. package/src/models/movein_booking.js +33 -33
  111. package/src/models/movein_commission.js +46 -46
  112. package/src/models/movein_conversation.js +25 -25
  113. package/src/models/movein_deal.js +79 -79
  114. package/src/models/movein_disbursement.js +36 -36
  115. package/src/models/movein_email_thread.js +19 -19
  116. package/src/models/movein_enquiry.js +16 -16
  117. package/src/models/movein_featured_package.js +16 -16
  118. package/src/models/movein_handoff_token.js +16 -16
  119. package/src/models/movein_invoice.js +24 -24
  120. package/src/models/movein_landlord.js +18 -18
  121. package/src/models/movein_landlord_user.js +20 -20
  122. package/src/models/movein_lease.js +37 -37
  123. package/src/models/movein_message.js +27 -27
  124. package/src/models/movein_notification.js +27 -27
  125. package/src/models/movein_otp.js +14 -14
  126. package/src/models/movein_payment.js +46 -46
  127. package/src/models/movein_reminder.js +77 -77
  128. package/src/models/movein_reservation.js +31 -31
  129. package/src/models/movein_settings.js +25 -25
  130. package/src/models/movein_tenancy.js +55 -55
  131. package/src/models/movein_unit.js +59 -59
  132. package/src/models/movein_user.js +15 -15
  133. package/src/models/movein_viewing_slot.js +21 -21
  134. package/src/models/movein_want_unit.js +20 -20
  135. package/src/models/notification.js +44 -44
  136. package/src/models/paymentTermsMarks.js +19 -19
  137. package/src/models/penalty.js +76 -76
  138. package/src/models/pendingCredentials.js +32 -32
  139. package/src/models/powerMeterCommunicationProtocol.js +17 -17
  140. package/src/models/powerMeterCustomerAccount.js +78 -78
  141. package/src/models/powerMeterCustomerBand.js +14 -14
  142. package/src/models/powerMeterDailyReading.js +30 -30
  143. package/src/models/powerMeterGateways.js +40 -40
  144. package/src/models/powerMeterMonthlyReading.js +34 -34
  145. package/src/models/powerMeterPowerCharges.js +85 -85
  146. package/src/models/powerMeterSettings.js +211 -211
  147. package/src/models/powerMeterSingleDayReading.js +32 -32
  148. package/src/models/powerMeters.js +149 -149
  149. package/src/models/powerMetersManufacturer.js +14 -14
  150. package/src/models/power_invoice.js +371 -371
  151. package/src/models/power_meter_account.js +81 -81
  152. package/src/models/power_meter_command_logs.js +30 -30
  153. package/src/models/power_meter_command_queue.js +33 -33
  154. package/src/models/power_meter_negative_balance.js +44 -44
  155. package/src/models/power_prepaid_credits.js +47 -47
  156. package/src/models/power_prepaid_debits.js +53 -53
  157. package/src/models/power_prepaid_orders.js +78 -78
  158. package/src/models/power_sms_notification.js +26 -26
  159. package/src/models/privacy_policy.js +19 -19
  160. package/src/models/propertyManagementSettings.js +55 -55
  161. package/src/models/propertyManagerContract.js +611 -611
  162. package/src/models/propertyManagerRevenue.js +195 -195
  163. package/src/models/propertyManagerRevenueEntry.js +118 -118
  164. package/src/models/purchaseOrderInvoice.js +74 -74
  165. package/src/models/purchase_order.js +213 -213
  166. package/src/models/purchase_request.js +110 -110
  167. package/src/models/quickbooks_config.js +52 -52
  168. package/src/models/recipient_group.js +61 -61
  169. package/src/models/recipient_group_member.js +62 -62
  170. package/src/models/refresh_token.js +23 -23
  171. package/src/models/reminder.js +197 -197
  172. package/src/models/report.js +13 -13
  173. package/src/models/resident.js +121 -121
  174. package/src/models/rfq_details.js +131 -131
  175. package/src/models/rfq_response.js +153 -153
  176. package/src/models/service_charge_invoice_upload.js +42 -42
  177. package/src/models/service_charge_payments.js +27 -27
  178. package/src/models/servicerequest.js +55 -55
  179. package/src/models/settings.js +62 -62
  180. package/src/models/short_urls.js +21 -21
  181. package/src/models/smart_meter_daily_consumption.js +44 -44
  182. package/src/models/sms_africastalking.js +20 -20
  183. package/src/models/sms_balance_notification.js +26 -26
  184. package/src/models/sms_meliora.js +20 -20
  185. package/src/models/staff.js +36 -36
  186. package/src/models/stocksandspare.js +161 -161
  187. package/src/models/suppliers.js +79 -79
  188. package/src/models/terms_and_conditions.js +19 -19
  189. package/src/models/tickets.js +186 -186
  190. package/src/models/tickets_category.js +72 -72
  191. package/src/models/unitManagementTemplate.js +44 -44
  192. package/src/models/unitasset.js +25 -25
  193. package/src/models/units.js +148 -148
  194. package/src/models/user.js +186 -186
  195. package/src/models/valueaddedservices.js +50 -50
  196. package/src/models/vas_invoices_upload.js +50 -50
  197. package/src/models/vas_payments.js +24 -24
  198. package/src/models/vasinvoice.js +196 -196
  199. package/src/models/vasvendor.js +52 -52
  200. package/src/models/visitLog.js +95 -95
  201. package/src/models/visitor.js +67 -67
  202. package/src/models/waitlist.js +45 -45
  203. package/src/models/wallet.js +44 -44
  204. package/src/models/wallet_transaction.js +67 -67
  205. package/src/models/wallet_transactions.js +72 -72
  206. package/src/models/water_invoice.js +362 -362
  207. package/src/models/water_meter_Command_Queue.js +33 -33
  208. package/src/models/water_meter_account.js +86 -86
  209. package/src/models/water_meter_billing.js +58 -58
  210. package/src/models/water_meter_combined_accounts.js +92 -92
  211. package/src/models/water_meter_communication.js +17 -17
  212. package/src/models/water_meter_communication_logs.js +39 -39
  213. package/src/models/water_meter_concentrator.js +77 -77
  214. package/src/models/water_meter_daily_history.js +32 -32
  215. package/src/models/water_meter_high_risk.js +36 -36
  216. package/src/models/water_meter_iot_cards.js +34 -34
  217. package/src/models/water_meter_loan_deduction.js +134 -134
  218. package/src/models/water_meter_manufacturer.js +35 -35
  219. package/src/models/water_meter_monthly_history.js +36 -36
  220. package/src/models/water_meter_negative_amounts.js +44 -44
  221. package/src/models/water_meter_settings.js +296 -296
  222. package/src/models/water_meter_single_day_history.js +34 -34
  223. package/src/models/water_meter_size.js +15 -15
  224. package/src/models/water_meters.js +176 -176
  225. package/src/models/water_meters_delivery.js +76 -76
  226. package/src/models/water_prepaid_credit.js +47 -47
  227. package/src/models/water_prepaid_debit.js +50 -50
  228. package/src/models/whatsapp_conversation.js +23 -23
  229. package/src/models/workorder.js +49 -49
  230. package/src/models/zohoAccount.js +453 -453
  231. package/src/models/zohoIntegration.js +262 -262
  232. package/src/models/zohoItem.js +504 -504
@@ -1,18 +1,18 @@
1
- const mongoose = require('mongoose');
2
-
3
- const deliveryTimeMarkSchema = new mongoose.Schema({
4
- deliveryDays: {
5
- type: Number,
6
- required: true
7
- },
8
- marks: {
9
- type: Number,
10
- required: true
11
- }
12
- }, {
13
- timestamps: true
14
- });
15
-
16
- const DeliveryTimeMark = mongoose.model('DeliveryTimeMark', deliveryTimeMarkSchema);
17
-
18
- module.exports = DeliveryTimeMark;
1
+ const mongoose = require('mongoose');
2
+
3
+ const deliveryTimeMarkSchema = new mongoose.Schema({
4
+ deliveryDays: {
5
+ type: Number,
6
+ required: true
7
+ },
8
+ marks: {
9
+ type: Number,
10
+ required: true
11
+ }
12
+ }, {
13
+ timestamps: true
14
+ });
15
+
16
+ const DeliveryTimeMark = mongoose.model('DeliveryTimeMark', deliveryTimeMarkSchema);
17
+
18
+ module.exports = DeliveryTimeMark;
@@ -1,20 +1,20 @@
1
- const mongoose = require('mongoose');
2
-
3
- const documentTypeSchema = new mongoose.Schema({
4
- facilityId: {
5
- type: mongoose.Schema.Types.ObjectId,
6
- ref: 'Facility',
7
- },
8
- name: {
9
- type: String,
10
- required: true,
11
- unique: true,
12
- trim: true,
13
- },
14
- }, {
15
- timestamps: true,
16
- });
17
-
18
- const DocumentType = mongoose.model('DocumentType', documentTypeSchema);
19
-
1
+ const mongoose = require('mongoose');
2
+
3
+ const documentTypeSchema = new mongoose.Schema({
4
+ facilityId: {
5
+ type: mongoose.Schema.Types.ObjectId,
6
+ ref: 'Facility',
7
+ },
8
+ name: {
9
+ type: String,
10
+ required: true,
11
+ unique: true,
12
+ trim: true,
13
+ },
14
+ }, {
15
+ timestamps: true,
16
+ });
17
+
18
+ const DocumentType = mongoose.model('DocumentType', documentTypeSchema);
19
+
20
20
  module.exports = DocumentType;
@@ -1,250 +1,250 @@
1
- const mongoose = require("mongoose");
2
-
3
- const DutyRosterChecklistSchema = new mongoose.Schema(
4
- {
5
- dutyRosterId: {
6
- type: mongoose.Schema.Types.ObjectId,
7
- ref: "DutyRoster",
8
- required: true,
9
- },
10
- facilityId: {
11
- type: mongoose.Schema.Types.ObjectId,
12
- ref: "Facility",
13
- required: true,
14
- },
15
- staffId: {
16
- type: mongoose.Schema.Types.ObjectId,
17
- ref: "User",
18
- required: true,
19
- },
20
- masterWorkplanId: {
21
- type: mongoose.Schema.Types.ObjectId,
22
- ref: "MasterWorkplan",
23
- required: true,
24
- },
25
- // Array of tasks with their individual dates and status
26
- tasks: [
27
- {
28
- childWorkplanId: {
29
- type: mongoose.Schema.Types.ObjectId,
30
- ref: "ChildWorkplan",
31
- required: true,
32
- },
33
- // Each task can have multiple scheduled dates
34
- scheduledDates: [
35
- {
36
- date: {
37
- type: Date,
38
- required: true,
39
- },
40
- status: {
41
- type: String,
42
- enum: [
43
- "pending",
44
- "completed",
45
- "missed",
46
- "cancelled",
47
- "in-progress",
48
- ],
49
- default: "pending",
50
- required: true,
51
- },
52
- completedAt: {
53
- type: Date,
54
- },
55
- completedBy: {
56
- type: mongoose.Schema.Types.ObjectId,
57
- ref: "User",
58
- },
59
- notes: {
60
- type: String,
61
- maxlength: 500,
62
- },
63
- // Time tracking
64
- startTime: String,
65
- endTime: String,
66
- actualDuration: Number, // in minutes
67
- },
68
- ],
69
- // Task metadata
70
- priority: {
71
- type: String,
72
- enum: ["low", "medium", "high", "critical"],
73
- default: "medium",
74
- },
75
- estimatedDuration: Number, // in minutes
76
- isRecurring: {
77
- type: Boolean,
78
- default: false,
79
- },
80
- recurringPattern: {
81
- type: String,
82
- enum: ["daily", "weekly", "monthly", "custom"],
83
- },
84
- },
85
- ],
86
- // Overall checklist metadata
87
- period: {
88
- startDate: {
89
- type: Date,
90
- required: true,
91
- },
92
- endDate: {
93
- type: Date,
94
- required: true,
95
- },
96
- },
97
- // Summary statistics
98
- summary: {
99
- totalTasks: {
100
- type: Number,
101
- default: 0,
102
- },
103
- completedTasks: {
104
- type: Number,
105
- default: 0,
106
- },
107
- pendingTasks: {
108
- type: Number,
109
- default: 0,
110
- },
111
- missedTasks: {
112
- type: Number,
113
- default: 0,
114
- },
115
- completionPercentage: {
116
- type: Number,
117
- default: 0,
118
- min: 0,
119
- max: 100,
120
- },
121
- },
122
- status: {
123
- type: String,
124
- enum: ["active", "completed", "expired", "cancelled"],
125
- default: "active",
126
- },
127
- },
128
- {
129
- timestamps: true,
130
- },
131
- );
132
-
133
- // Pre-save middleware to update summary statistics
134
- DutyRosterChecklistSchema.pre("save", function (next) {
135
- // Validate period dates
136
- if (this.period.startDate >= this.period.endDate) {
137
- return next(new Error("End date must be after start date"));
138
- }
139
-
140
- // Calculate summary statistics
141
- let totalScheduledDates = 0;
142
- let completedScheduledDates = 0;
143
- let pendingScheduledDates = 0;
144
- let missedScheduledDates = 0;
145
-
146
- this.tasks.forEach((task) => {
147
- task.scheduledDates.forEach((scheduledDate) => {
148
- totalScheduledDates++;
149
- switch (scheduledDate.status) {
150
- case "completed":
151
- completedScheduledDates++;
152
- break;
153
- case "pending":
154
- case "in-progress":
155
- pendingScheduledDates++;
156
- break;
157
- case "missed":
158
- missedScheduledDates++;
159
- break;
160
- }
161
- });
162
- });
163
-
164
- this.summary.totalTasks = totalScheduledDates;
165
- this.summary.completedTasks = completedScheduledDates;
166
- this.summary.pendingTasks = pendingScheduledDates;
167
- this.summary.missedTasks = missedScheduledDates;
168
- this.summary.completionPercentage =
169
- totalScheduledDates > 0
170
- ? Math.round((completedScheduledDates / totalScheduledDates) * 100)
171
- : 0;
172
-
173
- next();
174
- });
175
-
176
- // Static method to generate dates between start and end date
177
- DutyRosterChecklistSchema.statics.generateDateRange = function (
178
- startDate,
179
- endDate,
180
- frequency = "daily",
181
- ) {
182
- const dates = [];
183
- const current = new Date(startDate);
184
- const end = new Date(endDate);
185
-
186
- while (current <= end) {
187
- dates.push(new Date(current));
188
-
189
- switch (frequency) {
190
- case "daily":
191
- current.setDate(current.getDate() + 1);
192
- break;
193
- case "weekly":
194
- current.setDate(current.getDate() + 7);
195
- break;
196
- case "monthly":
197
- current.setMonth(current.getMonth() + 1);
198
- break;
199
- default:
200
- current.setDate(current.getDate() + 1);
201
- }
202
- }
203
-
204
- return dates;
205
- };
206
-
207
- // Instance method to update task status
208
- DutyRosterChecklistSchema.methods.updateTaskStatus = function (
209
- taskId,
210
- dateId,
211
- status,
212
- completedBy,
213
- notes,
214
- ) {
215
- const task = this.tasks.id(taskId);
216
- if (!task) {
217
- throw new Error("Task not found");
218
- }
219
-
220
- const scheduledDate = task.scheduledDates.id(dateId);
221
- if (!scheduledDate) {
222
- throw new Error("Scheduled date not found");
223
- }
224
-
225
- scheduledDate.status = status;
226
- if (status === "completed") {
227
- scheduledDate.completedAt = new Date();
228
- scheduledDate.completedBy = completedBy;
229
- }
230
- if (notes) {
231
- scheduledDate.notes = notes;
232
- }
233
-
234
- return this.save();
235
- };
236
-
237
- // Add indexes for efficient queries
238
- DutyRosterChecklistSchema.index({ dutyRosterId: 1 });
239
- DutyRosterChecklistSchema.index({ facilityId: 1, staffId: 1 });
240
- DutyRosterChecklistSchema.index({ masterWorkplanId: 1 });
241
- DutyRosterChecklistSchema.index({ "period.startDate": 1, "period.endDate": 1 });
242
- DutyRosterChecklistSchema.index({ "tasks.scheduledDates.date": 1 });
243
- DutyRosterChecklistSchema.index({ status: 1 });
244
-
245
- const DutyRosterChecklist = mongoose.model(
246
- "DutyRosterChecklist",
247
- DutyRosterChecklistSchema,
248
- );
249
-
250
- module.exports = DutyRosterChecklist;
1
+ const mongoose = require("mongoose");
2
+
3
+ const DutyRosterChecklistSchema = new mongoose.Schema(
4
+ {
5
+ dutyRosterId: {
6
+ type: mongoose.Schema.Types.ObjectId,
7
+ ref: "DutyRoster",
8
+ required: true,
9
+ },
10
+ facilityId: {
11
+ type: mongoose.Schema.Types.ObjectId,
12
+ ref: "Facility",
13
+ required: true,
14
+ },
15
+ staffId: {
16
+ type: mongoose.Schema.Types.ObjectId,
17
+ ref: "User",
18
+ required: true,
19
+ },
20
+ masterWorkplanId: {
21
+ type: mongoose.Schema.Types.ObjectId,
22
+ ref: "MasterWorkplan",
23
+ required: true,
24
+ },
25
+ // Array of tasks with their individual dates and status
26
+ tasks: [
27
+ {
28
+ childWorkplanId: {
29
+ type: mongoose.Schema.Types.ObjectId,
30
+ ref: "ChildWorkplan",
31
+ required: true,
32
+ },
33
+ // Each task can have multiple scheduled dates
34
+ scheduledDates: [
35
+ {
36
+ date: {
37
+ type: Date,
38
+ required: true,
39
+ },
40
+ status: {
41
+ type: String,
42
+ enum: [
43
+ "pending",
44
+ "completed",
45
+ "missed",
46
+ "cancelled",
47
+ "in-progress",
48
+ ],
49
+ default: "pending",
50
+ required: true,
51
+ },
52
+ completedAt: {
53
+ type: Date,
54
+ },
55
+ completedBy: {
56
+ type: mongoose.Schema.Types.ObjectId,
57
+ ref: "User",
58
+ },
59
+ notes: {
60
+ type: String,
61
+ maxlength: 500,
62
+ },
63
+ // Time tracking
64
+ startTime: String,
65
+ endTime: String,
66
+ actualDuration: Number, // in minutes
67
+ },
68
+ ],
69
+ // Task metadata
70
+ priority: {
71
+ type: String,
72
+ enum: ["low", "medium", "high", "critical"],
73
+ default: "medium",
74
+ },
75
+ estimatedDuration: Number, // in minutes
76
+ isRecurring: {
77
+ type: Boolean,
78
+ default: false,
79
+ },
80
+ recurringPattern: {
81
+ type: String,
82
+ enum: ["daily", "weekly", "monthly", "custom"],
83
+ },
84
+ },
85
+ ],
86
+ // Overall checklist metadata
87
+ period: {
88
+ startDate: {
89
+ type: Date,
90
+ required: true,
91
+ },
92
+ endDate: {
93
+ type: Date,
94
+ required: true,
95
+ },
96
+ },
97
+ // Summary statistics
98
+ summary: {
99
+ totalTasks: {
100
+ type: Number,
101
+ default: 0,
102
+ },
103
+ completedTasks: {
104
+ type: Number,
105
+ default: 0,
106
+ },
107
+ pendingTasks: {
108
+ type: Number,
109
+ default: 0,
110
+ },
111
+ missedTasks: {
112
+ type: Number,
113
+ default: 0,
114
+ },
115
+ completionPercentage: {
116
+ type: Number,
117
+ default: 0,
118
+ min: 0,
119
+ max: 100,
120
+ },
121
+ },
122
+ status: {
123
+ type: String,
124
+ enum: ["active", "completed", "expired", "cancelled"],
125
+ default: "active",
126
+ },
127
+ },
128
+ {
129
+ timestamps: true,
130
+ },
131
+ );
132
+
133
+ // Pre-save middleware to update summary statistics
134
+ DutyRosterChecklistSchema.pre("save", function (next) {
135
+ // Validate period dates
136
+ if (this.period.startDate >= this.period.endDate) {
137
+ return next(new Error("End date must be after start date"));
138
+ }
139
+
140
+ // Calculate summary statistics
141
+ let totalScheduledDates = 0;
142
+ let completedScheduledDates = 0;
143
+ let pendingScheduledDates = 0;
144
+ let missedScheduledDates = 0;
145
+
146
+ this.tasks.forEach((task) => {
147
+ task.scheduledDates.forEach((scheduledDate) => {
148
+ totalScheduledDates++;
149
+ switch (scheduledDate.status) {
150
+ case "completed":
151
+ completedScheduledDates++;
152
+ break;
153
+ case "pending":
154
+ case "in-progress":
155
+ pendingScheduledDates++;
156
+ break;
157
+ case "missed":
158
+ missedScheduledDates++;
159
+ break;
160
+ }
161
+ });
162
+ });
163
+
164
+ this.summary.totalTasks = totalScheduledDates;
165
+ this.summary.completedTasks = completedScheduledDates;
166
+ this.summary.pendingTasks = pendingScheduledDates;
167
+ this.summary.missedTasks = missedScheduledDates;
168
+ this.summary.completionPercentage =
169
+ totalScheduledDates > 0
170
+ ? Math.round((completedScheduledDates / totalScheduledDates) * 100)
171
+ : 0;
172
+
173
+ next();
174
+ });
175
+
176
+ // Static method to generate dates between start and end date
177
+ DutyRosterChecklistSchema.statics.generateDateRange = function (
178
+ startDate,
179
+ endDate,
180
+ frequency = "daily",
181
+ ) {
182
+ const dates = [];
183
+ const current = new Date(startDate);
184
+ const end = new Date(endDate);
185
+
186
+ while (current <= end) {
187
+ dates.push(new Date(current));
188
+
189
+ switch (frequency) {
190
+ case "daily":
191
+ current.setDate(current.getDate() + 1);
192
+ break;
193
+ case "weekly":
194
+ current.setDate(current.getDate() + 7);
195
+ break;
196
+ case "monthly":
197
+ current.setMonth(current.getMonth() + 1);
198
+ break;
199
+ default:
200
+ current.setDate(current.getDate() + 1);
201
+ }
202
+ }
203
+
204
+ return dates;
205
+ };
206
+
207
+ // Instance method to update task status
208
+ DutyRosterChecklistSchema.methods.updateTaskStatus = function (
209
+ taskId,
210
+ dateId,
211
+ status,
212
+ completedBy,
213
+ notes,
214
+ ) {
215
+ const task = this.tasks.id(taskId);
216
+ if (!task) {
217
+ throw new Error("Task not found");
218
+ }
219
+
220
+ const scheduledDate = task.scheduledDates.id(dateId);
221
+ if (!scheduledDate) {
222
+ throw new Error("Scheduled date not found");
223
+ }
224
+
225
+ scheduledDate.status = status;
226
+ if (status === "completed") {
227
+ scheduledDate.completedAt = new Date();
228
+ scheduledDate.completedBy = completedBy;
229
+ }
230
+ if (notes) {
231
+ scheduledDate.notes = notes;
232
+ }
233
+
234
+ return this.save();
235
+ };
236
+
237
+ // Add indexes for efficient queries
238
+ DutyRosterChecklistSchema.index({ dutyRosterId: 1 });
239
+ DutyRosterChecklistSchema.index({ facilityId: 1, staffId: 1 });
240
+ DutyRosterChecklistSchema.index({ masterWorkplanId: 1 });
241
+ DutyRosterChecklistSchema.index({ "period.startDate": 1, "period.endDate": 1 });
242
+ DutyRosterChecklistSchema.index({ "tasks.scheduledDates.date": 1 });
243
+ DutyRosterChecklistSchema.index({ status: 1 });
244
+
245
+ const DutyRosterChecklist = mongoose.model(
246
+ "DutyRosterChecklist",
247
+ DutyRosterChecklistSchema,
248
+ );
249
+
250
+ module.exports = DutyRosterChecklist;