payservedb 6.1.0 → 6.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "payservedb",
3
- "version": "6.1.0",
3
+ "version": "6.1.1",
4
4
  "main": "index.js",
5
5
  "scripts": {
6
6
  "test": "echo \"Error: no test specified\" && exit 1"
@@ -6,6 +6,10 @@ const powerMeterPowerChargeSchema = new mongoose.Schema({
6
6
  ref: 'Facility',
7
7
  required: true
8
8
  },
9
+ yearMonth: {
10
+ type: String,
11
+ required: true
12
+ },
9
13
  // KPLC Power Charges
10
14
  fuelCostCharge: {
11
15
  type: Number,
@@ -67,6 +67,10 @@ const PropertyManagerContractSchema = new Schema(
67
67
  type: Boolean,
68
68
  default: false
69
69
  },
70
+ balanceBroughtForward: {
71
+ type: Number,
72
+ default: 0
73
+ },
70
74
  // Management fee
71
75
  managementFee: {
72
76
  type: {
@@ -90,7 +94,7 @@ const PropertyManagerContractSchema = new Schema(
90
94
  }
91
95
  }
92
96
  },
93
- // GL Account configurations
97
+ // GL Account configurations - updated to match sample data structure
94
98
  invoiceDoubleEntryAccount: {
95
99
  type: mongoose.Schema.Types.ObjectId,
96
100
  ref: 'GLAccountDoubleEntries'
@@ -130,10 +134,26 @@ const PropertyManagerContractSchema = new Schema(
130
134
  createdBy: {
131
135
  type: mongoose.Schema.Types.ObjectId,
132
136
  ref: 'User' // References global User collection
137
+ },
138
+ // Additional fields for contract lifecycle management
139
+ suspensionReason: {
140
+ type: String
141
+ },
142
+ terminationReason: {
143
+ type: String
144
+ },
145
+ terminationDate: {
146
+ type: Date
147
+ },
148
+ completionDate: {
149
+ type: Date
133
150
  }
134
151
  },
135
152
  {
136
- timestamps: true
153
+ timestamps: true,
154
+ // Ensure virtual fields are included in JSON output
155
+ toJSON: { virtuals: true },
156
+ toObject: { virtuals: true }
137
157
  }
138
158
  );
139
159
 
@@ -202,10 +222,11 @@ PropertyManagerContractSchema.pre('save', function (next) {
202
222
  PropertyManagerContractSchema.methods.syncWithLeaseData = async function(leaseData) {
203
223
  if (!leaseData) return;
204
224
 
205
- // Update contract fields from lease data (removed balanceBroughtForward)
225
+ // Update contract fields from lease data
206
226
  this.startDate = leaseData.leaseTerms?.startDate || this.startDate;
207
227
  this.endDate = leaseData.leaseTerms?.endDate || this.endDate;
208
228
  this.paymentDueDate = leaseData.financialTerms?.paymentDueDate || this.paymentDueDate;
229
+ this.balanceBroughtForward = leaseData.financialTerms?.balanceBroughtForward || this.balanceBroughtForward;
209
230
  this.frequency = leaseData.billingCycle?.frequency || this.frequency;
210
231
  this.autoSend = leaseData.billingCycle?.autoSend !== undefined ? leaseData.billingCycle.autoSend : this.autoSend;
211
232
  this.nextInvoiceDate = leaseData.billingCycle?.nextInvoiceDate || this.nextInvoiceDate;
@@ -241,6 +262,7 @@ PropertyManagerContractSchema.virtual('durationInDays').get(function() {
241
262
  const diffTime = Math.abs(this.endDate - this.startDate);
242
263
  return Math.ceil(diffTime / (1000 * 60 * 60 * 24));
243
264
  });
265
+
244
266
  // Virtual for contract remaining days
245
267
  PropertyManagerContractSchema.virtual('remainingDays').get(function() {
246
268
  if (!this.endDate) return null;
@@ -250,6 +272,17 @@ PropertyManagerContractSchema.virtual('remainingDays').get(function() {
250
272
  return Math.ceil(diffTime / (1000 * 60 * 60 * 24));
251
273
  });
252
274
 
275
+ // Virtual for management fee display
276
+ PropertyManagerContractSchema.virtual('managementFeeDisplay').get(function() {
277
+ if (!this.managementFee) return null;
278
+
279
+ if (this.managementFee.type === 'percentage') {
280
+ return `${this.managementFee.value}%`;
281
+ } else {
282
+ return `$${this.managementFee.value.toLocaleString()}`;
283
+ }
284
+ });
285
+
253
286
  // Indexes for better query performance
254
287
  PropertyManagerContractSchema.index({ customerId: 1, status: 1 });
255
288
  PropertyManagerContractSchema.index({ facilityId: 1, status: 1 });
@@ -330,6 +363,32 @@ PropertyManagerContractSchema.statics.findContractsRequiringInvoicing = function
330
363
  .populate('customerId', 'firstName lastName email');
331
364
  };
332
365
 
366
+ PropertyManagerContractSchema.statics.findContractsByFeeType = function(facilityId, feeType) {
367
+ return this.find({
368
+ facilityId: facilityId,
369
+ 'managementFee.type': feeType
370
+ }).populate('propertyManager', 'fullName email')
371
+ .populate('units', 'name unitType')
372
+ .populate('customerId', 'firstName lastName email')
373
+ .sort({ 'managementFee.value': -1 });
374
+ };
375
+
376
+ PropertyManagerContractSchema.statics.getContractStatistics = function(facilityId) {
377
+ return this.aggregate([
378
+ {
379
+ $match: { facilityId: mongoose.Types.ObjectId(facilityId) }
380
+ },
381
+ {
382
+ $group: {
383
+ _id: '$status',
384
+ count: { $sum: 1 },
385
+ totalFeeValue: { $sum: '$managementFee.value' },
386
+ avgFeeValue: { $avg: '$managementFee.value' }
387
+ }
388
+ }
389
+ ]);
390
+ };
391
+
333
392
  // Instance methods for contract management
334
393
  PropertyManagerContractSchema.methods.calculateNextInvoiceDate = function() {
335
394
  if (!this.lastInvoiceDate && !this.startDate) return null;
@@ -401,6 +460,32 @@ PropertyManagerContractSchema.methods.completeContract = async function() {
401
460
  return this.save();
402
461
  };
403
462
 
463
+ // Method to calculate management fee for a given amount
464
+ PropertyManagerContractSchema.methods.calculateManagementFee = function(baseAmount) {
465
+ if (!this.managementFee) return 0;
466
+
467
+ if (this.managementFee.type === 'percentage') {
468
+ return (baseAmount * this.managementFee.value) / 100;
469
+ } else {
470
+ return this.managementFee.value;
471
+ }
472
+ };
473
+
474
+ // Method to get contract summary
475
+ PropertyManagerContractSchema.methods.getContractSummary = function() {
476
+ return {
477
+ id: this._id,
478
+ contractName: this.contractName,
479
+ status: this.status,
480
+ duration: this.durationInDays,
481
+ remainingDays: this.remainingDays,
482
+ managementFee: this.managementFeeDisplay,
483
+ frequency: this.frequency,
484
+ nextInvoiceDate: this.nextInvoiceDate,
485
+ isComplete: this.isComplete
486
+ };
487
+ };
488
+
404
489
  // Pre-findOneAndUpdate middleware to maintain data integrity
405
490
  PropertyManagerContractSchema.pre(['findOneAndUpdate', 'updateOne', 'updateMany'], function() {
406
491
  const update = this.getUpdate();
@@ -431,6 +516,11 @@ PropertyManagerContractSchema.post('save', function(doc) {
431
516
  console.log(`Contract status changed to: ${doc.status}`);
432
517
  // Add notification logic here
433
518
  }
519
+
520
+ // Log invoice date updates
521
+ if (this.isModified('nextInvoiceDate') || this.isModified('lastInvoiceDate')) {
522
+ console.log(`Invoice dates updated for contract: ${doc.contractName}`);
523
+ }
434
524
  });
435
525
 
436
526
  // Error handling for validation errors
@@ -453,6 +543,8 @@ PropertyManagerContractSchema.methods.toJSON = function() {
453
543
  contract.missingRequiredFields = this.getMissingRequiredFields();
454
544
  contract.durationInDays = this.durationInDays;
455
545
  contract.remainingDays = this.remainingDays;
546
+ contract.managementFeeDisplay = this.managementFeeDisplay;
547
+ contract.contractSummary = this.getContractSummary();
456
548
 
457
549
  return contract;
458
550
  };
@@ -461,4 +553,4 @@ PropertyManagerContractSchema.methods.toJSON = function() {
461
553
  module.exports = {
462
554
  schema: PropertyManagerContractSchema,
463
555
  name: 'PropertyManagerContract'
464
- };
556
+ };