payservedb 4.9.3 → 4.9.5

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 (102) hide show
  1. package/.env +2 -2
  2. package/index.js +171 -171
  3. package/package.json +17 -17
  4. package/src/models/account.js +35 -35
  5. package/src/models/analog_water_billing.js +58 -58
  6. package/src/models/apilog.js +18 -18
  7. package/src/models/approvalsWorkflows.js +49 -49
  8. package/src/models/archivedapilog.js +18 -18
  9. package/src/models/archivedauditlog.js +83 -83
  10. package/src/models/asset.js +34 -34
  11. package/src/models/auditlog.js +83 -83
  12. package/src/models/bankdetails.js +40 -40
  13. package/src/models/bookinganalytics.js +63 -63
  14. package/src/models/bookingconfig.js +45 -45
  15. package/src/models/bookingproperty.js +112 -112
  16. package/src/models/bookingreservation.js +192 -192
  17. package/src/models/bookingrevenuerecord.js +84 -84
  18. package/src/models/budget.js +33 -33
  19. package/src/models/budgetCategory.js +19 -19
  20. package/src/models/campaigns.js +72 -72
  21. package/src/models/cashpayment.js +262 -262
  22. package/src/models/combinedUnits.js +62 -62
  23. package/src/models/common_area_electricity.js +38 -38
  24. package/src/models/common_area_generator.js +38 -38
  25. package/src/models/common_area_utility_alert.js +37 -37
  26. package/src/models/common_area_water.js +39 -39
  27. package/src/models/company.js +53 -53
  28. package/src/models/country_tax.js +42 -42
  29. package/src/models/currency_settings.js +39 -39
  30. package/src/models/customer.js +200 -200
  31. package/src/models/default_payment_details.js +17 -17
  32. package/src/models/dutyroster.js +129 -129
  33. package/src/models/email.js +24 -24
  34. package/src/models/entry_exit.js +53 -53
  35. package/src/models/expense.js +55 -55
  36. package/src/models/facility.js +61 -61
  37. package/src/models/facility_payment_details.js +20 -20
  38. package/src/models/facilityasset.js +25 -25
  39. package/src/models/faq.js +18 -18
  40. package/src/models/gl_accounts.js +56 -56
  41. package/src/models/gl_entries.js +51 -55
  42. package/src/models/guard.js +47 -47
  43. package/src/models/handover.js +241 -241
  44. package/src/models/invoice.js +291 -291
  45. package/src/models/item_inspection.js +67 -67
  46. package/src/models/leaseagreement.js +168 -168
  47. package/src/models/leasetemplate.js +17 -17
  48. package/src/models/levy.js +84 -84
  49. package/src/models/levy_invoice_settings.js +26 -26
  50. package/src/models/levycontract.js +77 -77
  51. package/src/models/levytype.js +23 -23
  52. package/src/models/maintenance_service_vendor.js +38 -38
  53. package/src/models/maintenance_services.js +17 -17
  54. package/src/models/maintenancerequisition.js +31 -31
  55. package/src/models/message.js +38 -38
  56. package/src/models/module.js +21 -21
  57. package/src/models/notification.js +24 -24
  58. package/src/models/penalty.js +76 -76
  59. package/src/models/purchase_order.js +190 -190
  60. package/src/models/purchase_request.js +65 -65
  61. package/src/models/refresh_token.js +23 -23
  62. package/src/models/reminder.js +161 -161
  63. package/src/models/report.js +13 -13
  64. package/src/models/resident.js +121 -121
  65. package/src/models/rfq_details.js +87 -87
  66. package/src/models/rfq_response.js +109 -109
  67. package/src/models/service_charge_invoice_upload.js +42 -42
  68. package/src/models/service_charge_payments.js +27 -27
  69. package/src/models/servicerequest.js +55 -55
  70. package/src/models/settings.js +62 -62
  71. package/src/models/smart_meter_daily_consumption.js +44 -44
  72. package/src/models/sms_africastalking.js +20 -20
  73. package/src/models/sms_meliora.js +16 -16
  74. package/src/models/staff.js +36 -36
  75. package/src/models/stocksandspare.js +34 -34
  76. package/src/models/suppliers.js +68 -68
  77. package/src/models/tickets.js +109 -109
  78. package/src/models/unitasset.js +25 -25
  79. package/src/models/units.js +86 -86
  80. package/src/models/user.js +183 -183
  81. package/src/models/valueaddedservices.js +36 -36
  82. package/src/models/vas_invoices_upload.js +50 -50
  83. package/src/models/vas_payments.js +24 -24
  84. package/src/models/vasinvoice.js +159 -159
  85. package/src/models/vasvendor.js +57 -57
  86. package/src/models/visitLog.js +86 -86
  87. package/src/models/visitor.js +63 -63
  88. package/src/models/waitlist.js +45 -45
  89. package/src/models/water_invoice.js +192 -192
  90. package/src/models/water_meter_account.js +74 -74
  91. package/src/models/water_meter_communication.js +17 -17
  92. package/src/models/water_meter_concentrator.js +59 -59
  93. package/src/models/water_meter_daily_history.js +31 -31
  94. package/src/models/water_meter_iot_cards.js +34 -34
  95. package/src/models/water_meter_manufacturer.js +35 -35
  96. package/src/models/water_meter_monthly_history.js +37 -37
  97. package/src/models/water_meter_settings.js +88 -88
  98. package/src/models/water_meter_single_day_history.js +31 -31
  99. package/src/models/water_meter_size.js +15 -15
  100. package/src/models/water_meters.js +103 -103
  101. package/src/models/water_meters_delivery.js +76 -76
  102. package/src/models/workorder.js +49 -49
@@ -1,292 +1,292 @@
1
- const mongoose = require("mongoose");
2
-
3
- const invoiceSchema = new mongoose.Schema(
4
- {
5
- invoiceNumber: {
6
- type: String,
7
- required: true,
8
- unique: true,
9
- },
10
- accountNumber: {
11
- type: String,
12
- required: true,
13
- unique: true,
14
- },
15
- client: {
16
- clientId: {
17
- type: mongoose.Schema.Types.ObjectId,
18
- ref: "Customer",
19
- required: true,
20
- },
21
- firstName: {
22
- type: String,
23
- required: true
24
- },
25
- lastName: {
26
- type: String,
27
- required: true
28
- }
29
- },
30
- facility: {
31
- id: {
32
- type: mongoose.Schema.Types.ObjectId,
33
- ref: "Facility",
34
- required: true,
35
- },
36
- name: {
37
- type: String,
38
- required: true
39
- }
40
- },
41
- unit: {
42
- id: { type: mongoose.Schema.Types.ObjectId, ref: "Unit", required: true },
43
- name: { type: String, required: true },
44
- },
45
- currency: {
46
- id: {
47
- type: mongoose.Schema.Types.ObjectId,
48
- ref: "Currency",
49
- required: true
50
- },
51
- name: {
52
- type: String,
53
- required: true
54
- },
55
- code: {
56
- type: String,
57
- required: true,
58
- uppercase: true,
59
- minlength: 3,
60
- maxlength: 3
61
- }
62
- },
63
- items: [
64
- {
65
- description: { type: String, required: true },
66
- quantity: { type: Number, required: true, min: 1 },
67
- unitPrice: { type: Number, required: true, min: 0 },
68
- },
69
- ],
70
- subTotal: {
71
- type: Number,
72
- required: true,
73
- },
74
- tax: {
75
- type: Number,
76
- required: true,
77
- },
78
- totalAmount: {
79
- type: Number,
80
- required: true,
81
- },
82
- amountPaid: {
83
- type: Number,
84
- default: 0,
85
- min: 0,
86
- },
87
- // Mark as deprecated, keep for backward compatibility
88
- overpay: {
89
- type: Number,
90
- default: 0,
91
- min: 0,
92
- deprecated: true
93
- },
94
- issueDate: {
95
- type: Date,
96
- required: true,
97
- },
98
- dueDate: {
99
- type: Date,
100
- required: true,
101
- },
102
- status: {
103
- type: String,
104
- required: true,
105
- enum: ["Unpaid", "Pending", "Paid", "Overdue", "Cancelled", "Partially Paid", "Void"],
106
- },
107
- penalty: {
108
- type: Number,
109
- default: 0,
110
- },
111
- whatFor: {
112
- invoiceType: { type: String, required: true },
113
- description: { type: String },
114
- },
115
- invoiceNote: {
116
- type: String,
117
- default: null,
118
- },
119
- balanceBroughtForward: {
120
- type: Number,
121
- default: 0,
122
- },
123
- voidMetadata: {
124
- voidedBy: {
125
- userId: { type: mongoose.Schema.Types.ObjectId, ref: "User" },
126
- name: { type: String },
127
- role: { type: String }
128
- },
129
- voidedAt: { type: Date },
130
- reason: { type: String }
131
- },
132
- cancelMetadata: {
133
- cancelledBy: {
134
- userId: { type: mongoose.Schema.Types.ObjectId, ref: "User" },
135
- name: { type: String },
136
- role: { type: String }
137
- },
138
- cancelledAt: { type: Date },
139
- reason: { type: String }
140
- },
141
- lastReminderSent: Date,
142
- reminderHistory: [
143
- {
144
- sentAt: Date,
145
- reminderId: mongoose.Schema.Types.ObjectId,
146
- notificationTypes: [String],
147
- },
148
- ],
149
- reconciliationHistory: [{
150
- date: { type: Date, required: true },
151
- amount: { type: Number, required: true },
152
- type: {
153
- type: String,
154
- enum: ['payment', 'cash', 'cheque', 'bank-transfer', 'mpesa-transfer', 'overpay-transfer', 'balance-deduction', 'overpay-received', 'credit-forward', 'debit-forward'],
155
- required: true
156
- },
157
- sourceInvoice: String,
158
- destinationInvoice: String,
159
- paymentReference: String,
160
- paymentCompletion: String,
161
- remainingBalance: Number,
162
- notes: String,
163
- exchangeRate: {
164
- type: Number,
165
- default: 1 // For cross-currency reconciliations
166
- },
167
- originalCurrency: {
168
- code: String, // Original currency code if different from invoice currency
169
- amount: Number // Amount in original currency
170
- }
171
- }],
172
- paymentDetails: {
173
- paymentStatus: { type: String, required: true },
174
- paymentMethod: { type: String },
175
- paymentDate: { type: Date },
176
- transactionId: { type: String },
177
- },
178
- // New field to track when an invoice has been viewed
179
- viewStatus: {
180
- isOpened: { type: Boolean, default: false },
181
- openedAt: { type: Date, default: null },
182
- openedBy: {
183
- facilityId: { type: mongoose.Schema.Types.ObjectId, ref: "Facility" },
184
- userId: { type: mongoose.Schema.Types.ObjectId, ref: "User" },
185
- userRole: { type: String }
186
- },
187
- viewHistory: [{
188
- viewedAt: { type: Date, required: true },
189
- facilityId: { type: mongoose.Schema.Types.ObjectId, ref: "Facility" },
190
- userId: { type: mongoose.Schema.Types.ObjectId, ref: "User" }
191
- }]
192
- }
193
- },
194
- {
195
- timestamps: true,
196
- }
197
- );
198
-
199
- // Add indexes for frequently queried fields
200
- invoiceSchema.index({ accountNumber: 1 });
201
- invoiceSchema.index({ status: 1 });
202
- invoiceSchema.index({ 'client.clientId': 1, status: 1 });
203
- invoiceSchema.index({ 'reconciliationHistory.paymentReference': 1 });
204
- invoiceSchema.index({ issueDate: -1 });
205
- invoiceSchema.index({ 'currency.code': 1 }); // Add index for currency code
206
- invoiceSchema.index({ 'currency.id': 1 }); // Add index for currency ID
207
- invoiceSchema.index({ 'currency.code': 1, 'client.clientId': 1, status: 1 }); // Compound index for currency-based queries
208
- invoiceSchema.index({ 'client.clientId': 1, balanceBroughtForward: 1 }); // Add index for finding invoices with credit balances
209
- invoiceSchema.index({ 'viewStatus.isOpened': 1 }); // Add index for view status
210
- invoiceSchema.index({ 'viewStatus.openedBy.facilityId': 1 }); // Add index for facility view tracking
211
-
212
- // Add virtual field for calculating balance
213
- invoiceSchema.virtual('calculatedBalance').get(function () {
214
- const baseBalance = this.totalAmount - (this.amountPaid || 0);
215
-
216
- // Add positive balanceBroughtForward (customer owes money)
217
- if (this.balanceBroughtForward > 0) {
218
- return baseBalance + this.balanceBroughtForward;
219
- }
220
-
221
- // Subtract negative balanceBroughtForward (credit)
222
- return baseBalance;
223
- });
224
-
225
- // Add virtual field for credit balance
226
- invoiceSchema.virtual('creditBalance').get(function () {
227
- return this.balanceBroughtForward < 0 ? Math.abs(this.balanceBroughtForward) : 0;
228
- });
229
-
230
- // Getter for compatible overpay field
231
- invoiceSchema.virtual('effectiveOverpay').get(function () {
232
- return this.balanceBroughtForward < 0 ? Math.abs(this.balanceBroughtForward) : 0;
233
- });
234
-
235
- // Add method for currency conversion if needed
236
- invoiceSchema.methods.convertAmount = function (amount, fromCurrency, toCurrency, exchangeRate) {
237
- if (fromCurrency === toCurrency) {
238
- return amount;
239
- }
240
- return amount * exchangeRate;
241
- };
242
-
243
- // Add static method to find invoices by currency
244
- invoiceSchema.statics.findByCurrency = function (currencyCode) {
245
- return this.find({ 'currency.code': currencyCode.toUpperCase() });
246
- };
247
-
248
- // Add static method to find invoices with credit balance
249
- invoiceSchema.statics.findWithCreditBalance = function (clientId) {
250
- return this.find({
251
- 'client.clientId': clientId,
252
- 'balanceBroughtForward': { $lt: 0 }
253
- }).sort({ updatedAt: -1 });
254
- };
255
-
256
- // Add static method to calculate totals by currency
257
- invoiceSchema.statics.calculateTotalsByCurrency = function (query = {}) {
258
- return this.aggregate([
259
- { $match: query },
260
- {
261
- $group: {
262
- _id: '$currency.code',
263
- totalAmount: { $sum: '$totalAmount' },
264
- totalPaid: { $sum: '$amountPaid' },
265
- count: { $sum: 1 }
266
- }
267
- }
268
- ]);
269
- };
270
-
271
- // New static method to find all unviewed invoices
272
- invoiceSchema.statics.findUnviewedInvoices = function (facilityId) {
273
- return this.find({
274
- 'facility.id': facilityId,
275
- 'viewStatus.isOpened': false
276
- });
277
- };
278
-
279
- // Pre-save middleware to ensure overpay and balanceBroughtForward stay in sync during transition
280
- invoiceSchema.pre('save', function (next) {
281
- // If balanceBroughtForward is negative (credit), sync with overpay for backwards compatibility
282
- if (this.balanceBroughtForward < 0) {
283
- this.overpay = Math.abs(this.balanceBroughtForward);
284
- } else {
285
- this.overpay = 0; // No overpay if there's no negative balance
286
- }
287
- next();
288
- });
289
-
290
- const Invoice = mongoose.model('Invoice', invoiceSchema);
291
-
1
+ const mongoose = require("mongoose");
2
+
3
+ const invoiceSchema = new mongoose.Schema(
4
+ {
5
+ invoiceNumber: {
6
+ type: String,
7
+ required: true,
8
+ unique: true,
9
+ },
10
+ accountNumber: {
11
+ type: String,
12
+ required: true,
13
+ unique: true,
14
+ },
15
+ client: {
16
+ clientId: {
17
+ type: mongoose.Schema.Types.ObjectId,
18
+ ref: "Customer",
19
+ required: true,
20
+ },
21
+ firstName: {
22
+ type: String,
23
+ required: true
24
+ },
25
+ lastName: {
26
+ type: String,
27
+ required: true
28
+ }
29
+ },
30
+ facility: {
31
+ id: {
32
+ type: mongoose.Schema.Types.ObjectId,
33
+ ref: "Facility",
34
+ required: true,
35
+ },
36
+ name: {
37
+ type: String,
38
+ required: true
39
+ }
40
+ },
41
+ unit: {
42
+ id: { type: mongoose.Schema.Types.ObjectId, ref: "Unit", required: true },
43
+ name: { type: String, required: true },
44
+ },
45
+ currency: {
46
+ id: {
47
+ type: mongoose.Schema.Types.ObjectId,
48
+ ref: "Currency",
49
+ required: true
50
+ },
51
+ name: {
52
+ type: String,
53
+ required: true
54
+ },
55
+ code: {
56
+ type: String,
57
+ required: true,
58
+ uppercase: true,
59
+ minlength: 3,
60
+ maxlength: 3
61
+ }
62
+ },
63
+ items: [
64
+ {
65
+ description: { type: String, required: true },
66
+ quantity: { type: Number, required: true, min: 1 },
67
+ unitPrice: { type: Number, required: true, min: 0 },
68
+ },
69
+ ],
70
+ subTotal: {
71
+ type: Number,
72
+ required: true,
73
+ },
74
+ tax: {
75
+ type: Number,
76
+ required: true,
77
+ },
78
+ totalAmount: {
79
+ type: Number,
80
+ required: true,
81
+ },
82
+ amountPaid: {
83
+ type: Number,
84
+ default: 0,
85
+ min: 0,
86
+ },
87
+ // Mark as deprecated, keep for backward compatibility
88
+ overpay: {
89
+ type: Number,
90
+ default: 0,
91
+ min: 0,
92
+ deprecated: true
93
+ },
94
+ issueDate: {
95
+ type: Date,
96
+ required: true,
97
+ },
98
+ dueDate: {
99
+ type: Date,
100
+ required: true,
101
+ },
102
+ status: {
103
+ type: String,
104
+ required: true,
105
+ enum: ["Unpaid", "Pending", "Paid", "Overdue", "Cancelled", "Partially Paid", "Void"],
106
+ },
107
+ penalty: {
108
+ type: Number,
109
+ default: 0,
110
+ },
111
+ whatFor: {
112
+ invoiceType: { type: String, required: true },
113
+ description: { type: String },
114
+ },
115
+ invoiceNote: {
116
+ type: String,
117
+ default: null,
118
+ },
119
+ balanceBroughtForward: {
120
+ type: Number,
121
+ default: 0,
122
+ },
123
+ voidMetadata: {
124
+ voidedBy: {
125
+ userId: { type: mongoose.Schema.Types.ObjectId, ref: "User" },
126
+ name: { type: String },
127
+ role: { type: String }
128
+ },
129
+ voidedAt: { type: Date },
130
+ reason: { type: String }
131
+ },
132
+ cancelMetadata: {
133
+ cancelledBy: {
134
+ userId: { type: mongoose.Schema.Types.ObjectId, ref: "User" },
135
+ name: { type: String },
136
+ role: { type: String }
137
+ },
138
+ cancelledAt: { type: Date },
139
+ reason: { type: String }
140
+ },
141
+ lastReminderSent: Date,
142
+ reminderHistory: [
143
+ {
144
+ sentAt: Date,
145
+ reminderId: mongoose.Schema.Types.ObjectId,
146
+ notificationTypes: [String],
147
+ },
148
+ ],
149
+ reconciliationHistory: [{
150
+ date: { type: Date, required: true },
151
+ amount: { type: Number, required: true },
152
+ type: {
153
+ type: String,
154
+ enum: ['payment', 'cash', 'cheque', 'bank-transfer', 'mpesa-transfer', 'overpay-transfer', 'balance-deduction', 'overpay-received', 'credit-forward', 'debit-forward'],
155
+ required: true
156
+ },
157
+ sourceInvoice: String,
158
+ destinationInvoice: String,
159
+ paymentReference: String,
160
+ paymentCompletion: String,
161
+ remainingBalance: Number,
162
+ notes: String,
163
+ exchangeRate: {
164
+ type: Number,
165
+ default: 1 // For cross-currency reconciliations
166
+ },
167
+ originalCurrency: {
168
+ code: String, // Original currency code if different from invoice currency
169
+ amount: Number // Amount in original currency
170
+ }
171
+ }],
172
+ paymentDetails: {
173
+ paymentStatus: { type: String, required: true },
174
+ paymentMethod: { type: String },
175
+ paymentDate: { type: Date },
176
+ transactionId: { type: String },
177
+ },
178
+ // New field to track when an invoice has been viewed
179
+ viewStatus: {
180
+ isOpened: { type: Boolean, default: false },
181
+ openedAt: { type: Date, default: null },
182
+ openedBy: {
183
+ facilityId: { type: mongoose.Schema.Types.ObjectId, ref: "Facility" },
184
+ userId: { type: mongoose.Schema.Types.ObjectId, ref: "User" },
185
+ userRole: { type: String }
186
+ },
187
+ viewHistory: [{
188
+ viewedAt: { type: Date, required: true },
189
+ facilityId: { type: mongoose.Schema.Types.ObjectId, ref: "Facility" },
190
+ userId: { type: mongoose.Schema.Types.ObjectId, ref: "User" }
191
+ }]
192
+ }
193
+ },
194
+ {
195
+ timestamps: true,
196
+ }
197
+ );
198
+
199
+ // Add indexes for frequently queried fields
200
+ invoiceSchema.index({ accountNumber: 1 });
201
+ invoiceSchema.index({ status: 1 });
202
+ invoiceSchema.index({ 'client.clientId': 1, status: 1 });
203
+ invoiceSchema.index({ 'reconciliationHistory.paymentReference': 1 });
204
+ invoiceSchema.index({ issueDate: -1 });
205
+ invoiceSchema.index({ 'currency.code': 1 }); // Add index for currency code
206
+ invoiceSchema.index({ 'currency.id': 1 }); // Add index for currency ID
207
+ invoiceSchema.index({ 'currency.code': 1, 'client.clientId': 1, status: 1 }); // Compound index for currency-based queries
208
+ invoiceSchema.index({ 'client.clientId': 1, balanceBroughtForward: 1 }); // Add index for finding invoices with credit balances
209
+ invoiceSchema.index({ 'viewStatus.isOpened': 1 }); // Add index for view status
210
+ invoiceSchema.index({ 'viewStatus.openedBy.facilityId': 1 }); // Add index for facility view tracking
211
+
212
+ // Add virtual field for calculating balance
213
+ invoiceSchema.virtual('calculatedBalance').get(function () {
214
+ const baseBalance = this.totalAmount - (this.amountPaid || 0);
215
+
216
+ // Add positive balanceBroughtForward (customer owes money)
217
+ if (this.balanceBroughtForward > 0) {
218
+ return baseBalance + this.balanceBroughtForward;
219
+ }
220
+
221
+ // Subtract negative balanceBroughtForward (credit)
222
+ return baseBalance;
223
+ });
224
+
225
+ // Add virtual field for credit balance
226
+ invoiceSchema.virtual('creditBalance').get(function () {
227
+ return this.balanceBroughtForward < 0 ? Math.abs(this.balanceBroughtForward) : 0;
228
+ });
229
+
230
+ // Getter for compatible overpay field
231
+ invoiceSchema.virtual('effectiveOverpay').get(function () {
232
+ return this.balanceBroughtForward < 0 ? Math.abs(this.balanceBroughtForward) : 0;
233
+ });
234
+
235
+ // Add method for currency conversion if needed
236
+ invoiceSchema.methods.convertAmount = function (amount, fromCurrency, toCurrency, exchangeRate) {
237
+ if (fromCurrency === toCurrency) {
238
+ return amount;
239
+ }
240
+ return amount * exchangeRate;
241
+ };
242
+
243
+ // Add static method to find invoices by currency
244
+ invoiceSchema.statics.findByCurrency = function (currencyCode) {
245
+ return this.find({ 'currency.code': currencyCode.toUpperCase() });
246
+ };
247
+
248
+ // Add static method to find invoices with credit balance
249
+ invoiceSchema.statics.findWithCreditBalance = function (clientId) {
250
+ return this.find({
251
+ 'client.clientId': clientId,
252
+ 'balanceBroughtForward': { $lt: 0 }
253
+ }).sort({ updatedAt: -1 });
254
+ };
255
+
256
+ // Add static method to calculate totals by currency
257
+ invoiceSchema.statics.calculateTotalsByCurrency = function (query = {}) {
258
+ return this.aggregate([
259
+ { $match: query },
260
+ {
261
+ $group: {
262
+ _id: '$currency.code',
263
+ totalAmount: { $sum: '$totalAmount' },
264
+ totalPaid: { $sum: '$amountPaid' },
265
+ count: { $sum: 1 }
266
+ }
267
+ }
268
+ ]);
269
+ };
270
+
271
+ // New static method to find all unviewed invoices
272
+ invoiceSchema.statics.findUnviewedInvoices = function (facilityId) {
273
+ return this.find({
274
+ 'facility.id': facilityId,
275
+ 'viewStatus.isOpened': false
276
+ });
277
+ };
278
+
279
+ // Pre-save middleware to ensure overpay and balanceBroughtForward stay in sync during transition
280
+ invoiceSchema.pre('save', function (next) {
281
+ // If balanceBroughtForward is negative (credit), sync with overpay for backwards compatibility
282
+ if (this.balanceBroughtForward < 0) {
283
+ this.overpay = Math.abs(this.balanceBroughtForward);
284
+ } else {
285
+ this.overpay = 0; // No overpay if there's no negative balance
286
+ }
287
+ next();
288
+ });
289
+
290
+ const Invoice = mongoose.model('Invoice', invoiceSchema);
291
+
292
292
  module.exports = Invoice;