payservedb 4.8.5 → 4.8.7

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 (101) hide show
  1. package/.env +2 -2
  2. package/index.js +170 -170
  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 +52 -52
  41. package/src/models/guard.js +47 -47
  42. package/src/models/handover.js +241 -241
  43. package/src/models/invoice.js +276 -276
  44. package/src/models/item_inspection.js +67 -67
  45. package/src/models/leaseagreement.js +168 -168
  46. package/src/models/leasetemplate.js +17 -17
  47. package/src/models/levy.js +84 -84
  48. package/src/models/levy_invoice_settings.js +26 -26
  49. package/src/models/levycontract.js +77 -77
  50. package/src/models/levytype.js +23 -23
  51. package/src/models/maintenance_service_vendor.js +38 -38
  52. package/src/models/maintenance_services.js +17 -17
  53. package/src/models/maintenancerequisition.js +31 -31
  54. package/src/models/message.js +38 -38
  55. package/src/models/module.js +21 -21
  56. package/src/models/notification.js +24 -24
  57. package/src/models/penalty.js +76 -76
  58. package/src/models/purchase_order.js +191 -191
  59. package/src/models/purchase_request.js +65 -65
  60. package/src/models/refresh_token.js +23 -23
  61. package/src/models/reminder.js +161 -161
  62. package/src/models/report.js +13 -13
  63. package/src/models/resident.js +121 -121
  64. package/src/models/rfq_details.js +85 -86
  65. package/src/models/rfq_response.js +109 -109
  66. package/src/models/service_charge_invoice_upload.js +42 -42
  67. package/src/models/service_charge_payments.js +27 -27
  68. package/src/models/servicerequest.js +55 -55
  69. package/src/models/settings.js +62 -62
  70. package/src/models/smart_meter_daily_consumption.js +44 -44
  71. package/src/models/sms_africastalking.js +20 -20
  72. package/src/models/sms_meliora.js +16 -16
  73. package/src/models/staff.js +36 -36
  74. package/src/models/stocksandspare.js +34 -34
  75. package/src/models/suppliers.js +68 -68
  76. package/src/models/tickets.js +109 -109
  77. package/src/models/unitasset.js +25 -25
  78. package/src/models/units.js +86 -86
  79. package/src/models/user.js +94 -94
  80. package/src/models/valueaddedservices.js +36 -36
  81. package/src/models/vas_invoices_upload.js +50 -50
  82. package/src/models/vas_payments.js +24 -24
  83. package/src/models/vasinvoice.js +159 -159
  84. package/src/models/vasvendor.js +57 -57
  85. package/src/models/visitLog.js +86 -86
  86. package/src/models/visitor.js +63 -63
  87. package/src/models/waitlist.js +45 -45
  88. package/src/models/water_invoice.js +192 -192
  89. package/src/models/water_meter_account.js +74 -74
  90. package/src/models/water_meter_communication.js +17 -17
  91. package/src/models/water_meter_concentrator.js +59 -59
  92. package/src/models/water_meter_daily_history.js +31 -31
  93. package/src/models/water_meter_iot_cards.js +34 -34
  94. package/src/models/water_meter_manufacturer.js +35 -35
  95. package/src/models/water_meter_monthly_history.js +37 -37
  96. package/src/models/water_meter_settings.js +88 -88
  97. package/src/models/water_meter_single_day_history.js +31 -31
  98. package/src/models/water_meter_size.js +15 -15
  99. package/src/models/water_meters.js +103 -103
  100. package/src/models/water_meters_delivery.js +76 -76
  101. package/src/models/workorder.js +49 -49
@@ -1,277 +1,277 @@
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"],
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
- // Enhanced balanceBroughtForward field
120
- // Positive values = customer owes money
121
- // Negative values = credit (previously tracked in overpay field)
122
- balanceBroughtForward: {
123
- type: Number,
124
- default: 0,
125
- },
126
- lastReminderSent: Date,
127
- reminderHistory: [
128
- {
129
- sentAt: Date,
130
- reminderId: mongoose.Schema.Types.ObjectId,
131
- notificationTypes: [String],
132
- },
133
- ],
134
- reconciliationHistory: [{
135
- date: { type: Date, required: true },
136
- amount: { type: Number, required: true },
137
- type: {
138
- type: String,
139
- enum: ['payment', 'cash', 'cheque', 'bank-transfer', 'mpesa-transfer', 'overpay-transfer', 'balance-deduction', 'overpay-received', 'credit-forward', 'debit-forward'],
140
- required: true
141
- },
142
- sourceInvoice: String,
143
- destinationInvoice: String,
144
- paymentReference: String,
145
- paymentCompletion: String,
146
- remainingBalance: Number,
147
- notes: String,
148
- exchangeRate: {
149
- type: Number,
150
- default: 1 // For cross-currency reconciliations
151
- },
152
- originalCurrency: {
153
- code: String, // Original currency code if different from invoice currency
154
- amount: Number // Amount in original currency
155
- }
156
- }],
157
- paymentDetails: {
158
- paymentStatus: { type: String, required: true },
159
- paymentMethod: { type: String },
160
- paymentDate: { type: Date },
161
- transactionId: { type: String },
162
- },
163
- // New field to track when an invoice has been viewed
164
- viewStatus: {
165
- isOpened: { type: Boolean, default: false },
166
- openedAt: { type: Date, default: null },
167
- openedBy: {
168
- facilityId: { type: mongoose.Schema.Types.ObjectId, ref: "Facility" },
169
- userId: { type: mongoose.Schema.Types.ObjectId, ref: "User" },
170
- userRole: { type: String }
171
- },
172
- viewHistory: [{
173
- viewedAt: { type: Date, required: true },
174
- facilityId: { type: mongoose.Schema.Types.ObjectId, ref: "Facility" },
175
- userId: { type: mongoose.Schema.Types.ObjectId, ref: "User" }
176
- }]
177
- }
178
- },
179
- {
180
- timestamps: true,
181
- }
182
- );
183
-
184
- // Add indexes for frequently queried fields
185
- invoiceSchema.index({ accountNumber: 1 });
186
- invoiceSchema.index({ status: 1 });
187
- invoiceSchema.index({ 'client.clientId': 1, status: 1 });
188
- invoiceSchema.index({ 'reconciliationHistory.paymentReference': 1 });
189
- invoiceSchema.index({ issueDate: -1 });
190
- invoiceSchema.index({ 'currency.code': 1 }); // Add index for currency code
191
- invoiceSchema.index({ 'currency.id': 1 }); // Add index for currency ID
192
- invoiceSchema.index({ 'currency.code': 1, 'client.clientId': 1, status: 1 }); // Compound index for currency-based queries
193
- invoiceSchema.index({ 'client.clientId': 1, balanceBroughtForward: 1 }); // Add index for finding invoices with credit balances
194
- invoiceSchema.index({ 'viewStatus.isOpened': 1 }); // Add index for view status
195
- invoiceSchema.index({ 'viewStatus.openedBy.facilityId': 1 }); // Add index for facility view tracking
196
-
197
- // Add virtual field for calculating balance
198
- invoiceSchema.virtual('calculatedBalance').get(function () {
199
- const baseBalance = this.totalAmount - (this.amountPaid || 0);
200
-
201
- // Add positive balanceBroughtForward (customer owes money)
202
- if (this.balanceBroughtForward > 0) {
203
- return baseBalance + this.balanceBroughtForward;
204
- }
205
-
206
- // Subtract negative balanceBroughtForward (credit)
207
- return baseBalance;
208
- });
209
-
210
- // Add virtual field for credit balance
211
- invoiceSchema.virtual('creditBalance').get(function () {
212
- return this.balanceBroughtForward < 0 ? Math.abs(this.balanceBroughtForward) : 0;
213
- });
214
-
215
- // Getter for compatible overpay field
216
- invoiceSchema.virtual('effectiveOverpay').get(function () {
217
- return this.balanceBroughtForward < 0 ? Math.abs(this.balanceBroughtForward) : 0;
218
- });
219
-
220
- // Add method for currency conversion if needed
221
- invoiceSchema.methods.convertAmount = function (amount, fromCurrency, toCurrency, exchangeRate) {
222
- if (fromCurrency === toCurrency) {
223
- return amount;
224
- }
225
- return amount * exchangeRate;
226
- };
227
-
228
- // Add static method to find invoices by currency
229
- invoiceSchema.statics.findByCurrency = function (currencyCode) {
230
- return this.find({ 'currency.code': currencyCode.toUpperCase() });
231
- };
232
-
233
- // Add static method to find invoices with credit balance
234
- invoiceSchema.statics.findWithCreditBalance = function (clientId) {
235
- return this.find({
236
- 'client.clientId': clientId,
237
- 'balanceBroughtForward': { $lt: 0 }
238
- }).sort({ updatedAt: -1 });
239
- };
240
-
241
- // Add static method to calculate totals by currency
242
- invoiceSchema.statics.calculateTotalsByCurrency = function (query = {}) {
243
- return this.aggregate([
244
- { $match: query },
245
- {
246
- $group: {
247
- _id: '$currency.code',
248
- totalAmount: { $sum: '$totalAmount' },
249
- totalPaid: { $sum: '$amountPaid' },
250
- count: { $sum: 1 }
251
- }
252
- }
253
- ]);
254
- };
255
-
256
- // New static method to find all unviewed invoices
257
- invoiceSchema.statics.findUnviewedInvoices = function (facilityId) {
258
- return this.find({
259
- 'facility.id': facilityId,
260
- 'viewStatus.isOpened': false
261
- });
262
- };
263
-
264
- // Pre-save middleware to ensure overpay and balanceBroughtForward stay in sync during transition
265
- invoiceSchema.pre('save', function (next) {
266
- // If balanceBroughtForward is negative (credit), sync with overpay for backwards compatibility
267
- if (this.balanceBroughtForward < 0) {
268
- this.overpay = Math.abs(this.balanceBroughtForward);
269
- } else {
270
- this.overpay = 0; // No overpay if there's no negative balance
271
- }
272
- next();
273
- });
274
-
275
- const Invoice = mongoose.model('Invoice', invoiceSchema);
276
-
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"],
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
+ // Enhanced balanceBroughtForward field
120
+ // Positive values = customer owes money
121
+ // Negative values = credit (previously tracked in overpay field)
122
+ balanceBroughtForward: {
123
+ type: Number,
124
+ default: 0,
125
+ },
126
+ lastReminderSent: Date,
127
+ reminderHistory: [
128
+ {
129
+ sentAt: Date,
130
+ reminderId: mongoose.Schema.Types.ObjectId,
131
+ notificationTypes: [String],
132
+ },
133
+ ],
134
+ reconciliationHistory: [{
135
+ date: { type: Date, required: true },
136
+ amount: { type: Number, required: true },
137
+ type: {
138
+ type: String,
139
+ enum: ['payment', 'cash', 'cheque', 'bank-transfer', 'mpesa-transfer', 'overpay-transfer', 'balance-deduction', 'overpay-received', 'credit-forward', 'debit-forward'],
140
+ required: true
141
+ },
142
+ sourceInvoice: String,
143
+ destinationInvoice: String,
144
+ paymentReference: String,
145
+ paymentCompletion: String,
146
+ remainingBalance: Number,
147
+ notes: String,
148
+ exchangeRate: {
149
+ type: Number,
150
+ default: 1 // For cross-currency reconciliations
151
+ },
152
+ originalCurrency: {
153
+ code: String, // Original currency code if different from invoice currency
154
+ amount: Number // Amount in original currency
155
+ }
156
+ }],
157
+ paymentDetails: {
158
+ paymentStatus: { type: String, required: true },
159
+ paymentMethod: { type: String },
160
+ paymentDate: { type: Date },
161
+ transactionId: { type: String },
162
+ },
163
+ // New field to track when an invoice has been viewed
164
+ viewStatus: {
165
+ isOpened: { type: Boolean, default: false },
166
+ openedAt: { type: Date, default: null },
167
+ openedBy: {
168
+ facilityId: { type: mongoose.Schema.Types.ObjectId, ref: "Facility" },
169
+ userId: { type: mongoose.Schema.Types.ObjectId, ref: "User" },
170
+ userRole: { type: String }
171
+ },
172
+ viewHistory: [{
173
+ viewedAt: { type: Date, required: true },
174
+ facilityId: { type: mongoose.Schema.Types.ObjectId, ref: "Facility" },
175
+ userId: { type: mongoose.Schema.Types.ObjectId, ref: "User" }
176
+ }]
177
+ }
178
+ },
179
+ {
180
+ timestamps: true,
181
+ }
182
+ );
183
+
184
+ // Add indexes for frequently queried fields
185
+ invoiceSchema.index({ accountNumber: 1 });
186
+ invoiceSchema.index({ status: 1 });
187
+ invoiceSchema.index({ 'client.clientId': 1, status: 1 });
188
+ invoiceSchema.index({ 'reconciliationHistory.paymentReference': 1 });
189
+ invoiceSchema.index({ issueDate: -1 });
190
+ invoiceSchema.index({ 'currency.code': 1 }); // Add index for currency code
191
+ invoiceSchema.index({ 'currency.id': 1 }); // Add index for currency ID
192
+ invoiceSchema.index({ 'currency.code': 1, 'client.clientId': 1, status: 1 }); // Compound index for currency-based queries
193
+ invoiceSchema.index({ 'client.clientId': 1, balanceBroughtForward: 1 }); // Add index for finding invoices with credit balances
194
+ invoiceSchema.index({ 'viewStatus.isOpened': 1 }); // Add index for view status
195
+ invoiceSchema.index({ 'viewStatus.openedBy.facilityId': 1 }); // Add index for facility view tracking
196
+
197
+ // Add virtual field for calculating balance
198
+ invoiceSchema.virtual('calculatedBalance').get(function () {
199
+ const baseBalance = this.totalAmount - (this.amountPaid || 0);
200
+
201
+ // Add positive balanceBroughtForward (customer owes money)
202
+ if (this.balanceBroughtForward > 0) {
203
+ return baseBalance + this.balanceBroughtForward;
204
+ }
205
+
206
+ // Subtract negative balanceBroughtForward (credit)
207
+ return baseBalance;
208
+ });
209
+
210
+ // Add virtual field for credit balance
211
+ invoiceSchema.virtual('creditBalance').get(function () {
212
+ return this.balanceBroughtForward < 0 ? Math.abs(this.balanceBroughtForward) : 0;
213
+ });
214
+
215
+ // Getter for compatible overpay field
216
+ invoiceSchema.virtual('effectiveOverpay').get(function () {
217
+ return this.balanceBroughtForward < 0 ? Math.abs(this.balanceBroughtForward) : 0;
218
+ });
219
+
220
+ // Add method for currency conversion if needed
221
+ invoiceSchema.methods.convertAmount = function (amount, fromCurrency, toCurrency, exchangeRate) {
222
+ if (fromCurrency === toCurrency) {
223
+ return amount;
224
+ }
225
+ return amount * exchangeRate;
226
+ };
227
+
228
+ // Add static method to find invoices by currency
229
+ invoiceSchema.statics.findByCurrency = function (currencyCode) {
230
+ return this.find({ 'currency.code': currencyCode.toUpperCase() });
231
+ };
232
+
233
+ // Add static method to find invoices with credit balance
234
+ invoiceSchema.statics.findWithCreditBalance = function (clientId) {
235
+ return this.find({
236
+ 'client.clientId': clientId,
237
+ 'balanceBroughtForward': { $lt: 0 }
238
+ }).sort({ updatedAt: -1 });
239
+ };
240
+
241
+ // Add static method to calculate totals by currency
242
+ invoiceSchema.statics.calculateTotalsByCurrency = function (query = {}) {
243
+ return this.aggregate([
244
+ { $match: query },
245
+ {
246
+ $group: {
247
+ _id: '$currency.code',
248
+ totalAmount: { $sum: '$totalAmount' },
249
+ totalPaid: { $sum: '$amountPaid' },
250
+ count: { $sum: 1 }
251
+ }
252
+ }
253
+ ]);
254
+ };
255
+
256
+ // New static method to find all unviewed invoices
257
+ invoiceSchema.statics.findUnviewedInvoices = function (facilityId) {
258
+ return this.find({
259
+ 'facility.id': facilityId,
260
+ 'viewStatus.isOpened': false
261
+ });
262
+ };
263
+
264
+ // Pre-save middleware to ensure overpay and balanceBroughtForward stay in sync during transition
265
+ invoiceSchema.pre('save', function (next) {
266
+ // If balanceBroughtForward is negative (credit), sync with overpay for backwards compatibility
267
+ if (this.balanceBroughtForward < 0) {
268
+ this.overpay = Math.abs(this.balanceBroughtForward);
269
+ } else {
270
+ this.overpay = 0; // No overpay if there's no negative balance
271
+ }
272
+ next();
273
+ });
274
+
275
+ const Invoice = mongoose.model('Invoice', invoiceSchema);
276
+
277
277
  module.exports = Invoice;