payservedb 8.5.2 → 8.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.
package/index.js CHANGED
@@ -142,6 +142,7 @@ const models = {
142
142
  DefaultPaymentDetails: require("./src/models/default_payment_details"),
143
143
  Currency: require("./src/models/currency_settings"),
144
144
  WaterMeterAccount: require("./src/models/water_meter_account"),
145
+ WaterMeterLoanDeduction: require("./src/models/water_meter_loan_deduction"),
145
146
  SingleDayWaterMeterHistory: require("./src/models/water_meter_single_day_history"),
146
147
  DailyWaterMeterHistory: require("./src/models/water_meter_daily_history"),
147
148
  MonthlyWaterMeterHistory: require("./src/models/water_meter_monthly_history"),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "payservedb",
3
- "version": "8.5.2",
3
+ "version": "8.5.3",
4
4
  "main": "index.js",
5
5
  "scripts": {
6
6
  "test": "echo \"Error: no test specified\" && exit 1"
@@ -0,0 +1,135 @@
1
+ const mongoose = require('mongoose');
2
+
3
+ const waterMeterLoanDeductionSchema = new mongoose.Schema({
4
+ customerId: {
5
+ type: mongoose.Schema.Types.ObjectId,
6
+ ref: 'Customer',
7
+ required: true,
8
+ index: true
9
+ },
10
+ accountId: {
11
+ type: mongoose.Schema.Types.ObjectId,
12
+ ref: 'WaterMeterAccount',
13
+ required: true,
14
+ index: true
15
+ },
16
+ meterId: {
17
+ type: mongoose.Schema.Types.ObjectId,
18
+ ref: 'WaterMeter',
19
+ required: true,
20
+ index: true
21
+ },
22
+ amount: {
23
+ type: Number,
24
+ required: true,
25
+ min: 0
26
+ },
27
+ yearMonth: {
28
+ type: String,
29
+ required: true,
30
+ index: true,
31
+ // Format: YYYY-MM (e.g., "2026-01")
32
+ validate: {
33
+ validator: function(v) {
34
+ return /^\d{4}-(0[1-9]|1[0-2])$/.test(v);
35
+ },
36
+ message: "yearMonth must be in YYYY-MM format"
37
+ }
38
+ },
39
+ deductionDate: {
40
+ type: Date,
41
+ required: true,
42
+ default: Date.now
43
+ },
44
+ status: {
45
+ type: String,
46
+ enum: ['pending', 'completed', 'insufficient_balance'],
47
+ required: true,
48
+ default: 'pending',
49
+ index: true
50
+ },
51
+ debitRecordId: {
52
+ type: mongoose.Schema.Types.ObjectId,
53
+ ref: 'WaterPrepaidDebit',
54
+ // Will be populated when deduction is completed
55
+ },
56
+ balanceAtAttempt: {
57
+ type: Number,
58
+ // Store balance when deduction was attempted
59
+ },
60
+ attempts: {
61
+ type: Number,
62
+ default: 0,
63
+ min: 0
64
+ },
65
+ lastAttemptDate: {
66
+ type: Date
67
+ },
68
+ completedDate: {
69
+ type: Date
70
+ },
71
+ notes: {
72
+ type: String,
73
+ trim: true
74
+ }
75
+ }, {
76
+ timestamps: true
77
+ });
78
+
79
+ // Compound index to ensure one deduction per customer per month
80
+ waterMeterLoanDeductionSchema.index(
81
+ { customerId: 1, yearMonth: 1 },
82
+ { unique: true }
83
+ );
84
+
85
+ // Index for finding pending deductions
86
+ waterMeterLoanDeductionSchema.index({ status: 1, yearMonth: 1 });
87
+
88
+ // Index for finding deductions by account
89
+ waterMeterLoanDeductionSchema.index({ accountId: 1, yearMonth: 1 });
90
+
91
+ // Static method to check if deduction exists for a customer in a given month
92
+ waterMeterLoanDeductionSchema.statics.deductionExists = async function(customerId, yearMonth) {
93
+ const count = await this.countDocuments({ customerId, yearMonth });
94
+ return count > 0;
95
+ };
96
+
97
+ // Static method to get pending deductions
98
+ waterMeterLoanDeductionSchema.statics.getPendingDeductions = async function() {
99
+ return this.find({ status: 'pending' })
100
+ .populate('accountId')
101
+ .populate('meterId')
102
+ .sort({ createdAt: 1 });
103
+ };
104
+
105
+ // Static method to get pending deductions for a specific month
106
+ waterMeterLoanDeductionSchema.statics.getPendingDeductionsForMonth = async function(yearMonth) {
107
+ return this.find({
108
+ status: 'pending',
109
+ yearMonth: yearMonth
110
+ })
111
+ .populate('accountId')
112
+ .populate('meterId')
113
+ .sort({ createdAt: 1 });
114
+ };
115
+
116
+ // Instance method to mark as completed
117
+ waterMeterLoanDeductionSchema.methods.markCompleted = async function(debitRecordId) {
118
+ this.status = 'completed';
119
+ this.debitRecordId = debitRecordId;
120
+ this.completedDate = new Date();
121
+ return this.save();
122
+ };
123
+
124
+ // Instance method to mark as insufficient balance
125
+ waterMeterLoanDeductionSchema.methods.markInsufficientBalance = async function(balance) {
126
+ this.status = 'insufficient_balance';
127
+ this.balanceAtAttempt = balance;
128
+ this.attempts += 1;
129
+ this.lastAttemptDate = new Date();
130
+ return this.save();
131
+ };
132
+
133
+ const WaterMeterLoanDeduction = mongoose.model('WaterMeterLoanDeduction', waterMeterLoanDeductionSchema);
134
+
135
+ module.exports = WaterMeterLoanDeduction;