payservedb 6.1.0 → 6.1.2

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/index.js CHANGED
@@ -206,9 +206,90 @@ async function getModelFromDB(dbConnection, modelName, schema) {
206
206
  return dbConnection.models[modelName]; // Return existing model if already registered
207
207
  }
208
208
 
209
+ // Function to initialize service with specific models
210
+ function initializeService(modelNames = []) {
211
+ const serviceModels = {};
212
+ let currentConnection = null;
213
+
214
+ // Enhanced connect function that also registers models
215
+ async function connectWithModels(dbName, secured, username, password, url, port) {
216
+ await connectToMongoDB(dbName, secured, username, password, url, port);
217
+ currentConnection = mongoose.connection;
218
+
219
+ // Register models with the current connection
220
+ modelNames.forEach(modelName => {
221
+ if (models[modelName] && !currentConnection.models[modelName]) {
222
+ serviceModels[modelName] = currentConnection.model(modelName, models[modelName]);
223
+ } else if (currentConnection.models[modelName]) {
224
+ serviceModels[modelName] = currentConnection.models[modelName];
225
+ }
226
+ });
227
+
228
+ return serviceModels;
229
+ }
230
+
231
+ // Enhanced switchDB function that also registers models
232
+ async function switchDBWithModels(dbName) {
233
+ const dbConnection = await switchDB(dbName);
234
+ currentConnection = dbConnection;
235
+
236
+ // Register models with the new connection
237
+ const dbModels = {};
238
+ modelNames.forEach(modelName => {
239
+ if (models[modelName]) {
240
+ if (!dbConnection.models[modelName]) {
241
+ dbModels[modelName] = dbConnection.model(modelName, models[modelName]);
242
+ } else {
243
+ dbModels[modelName] = dbConnection.models[modelName];
244
+ }
245
+ }
246
+ });
247
+
248
+ return { connection: dbConnection, models: dbModels };
249
+ }
250
+
251
+ // Function to get models for the current connection
252
+ function getModels() {
253
+ if (!currentConnection) {
254
+ throw new Error('No active database connection. Please connect first.');
255
+ }
256
+
257
+ const connectionModels = {};
258
+ modelNames.forEach(modelName => {
259
+ if (currentConnection.models[modelName]) {
260
+ connectionModels[modelName] = currentConnection.models[modelName];
261
+ }
262
+ });
263
+
264
+ return connectionModels;
265
+ }
266
+
267
+ // Function to get a specific model
268
+ function getModel(modelName) {
269
+ if (!currentConnection) {
270
+ throw new Error('No active database connection. Please connect first.');
271
+ }
272
+
273
+ if (!modelNames.includes(modelName)) {
274
+ throw new Error(`Model ${modelName} not initialized in this service`);
275
+ }
276
+
277
+ return currentConnection.models[modelName];
278
+ }
279
+
280
+ return {
281
+ connectToMongoDB: connectWithModels,
282
+ switchDB: switchDBWithModels,
283
+ getModels,
284
+ getModel,
285
+ getCurrentConnection: () => currentConnection
286
+ };
287
+ }
288
+
209
289
  module.exports = {
210
290
  connectToMongoDB,
211
291
  switchDB,
212
292
  getModelFromDB,
293
+ initializeService,
213
294
  ...models, // Spread operator to export all models
214
- };
295
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "payservedb",
3
- "version": "6.1.0",
3
+ "version": "6.1.2",
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
+ };
@@ -29,8 +29,8 @@ const concentratorSchema = new mongoose.Schema({
29
29
  status: {
30
30
  type: String,
31
31
  required: true,
32
- enum: ['Online', 'Offline', 'Maintenance'],
33
- default: 'Offline'
32
+ enum: ['online', 'offline', 'maintenance'],
33
+ default: '0ffline'
34
34
  },
35
35
  meter_fails: {
36
36
  type: Number,
@@ -55,6 +55,9 @@ const concentratorSchema = new mongoose.Schema({
55
55
  min: -180,
56
56
  max: 180
57
57
  }
58
+ },
59
+ lastUpdated: {
60
+ type: String
58
61
  }
59
62
  }, {
60
63
  timestamps: true