payservedb 3.8.9 → 3.9.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/index.js +1 -0
- package/package.json +1 -1
- package/src/models/handover.js +192 -86
- package/src/models/water_meter_settings.js +61 -0
package/index.js
CHANGED
|
@@ -108,6 +108,7 @@ const models = {
|
|
|
108
108
|
CountryTaxRate: require('./src/models/country_tax'),
|
|
109
109
|
Meter: require('./src/models/smart_water_meter'),
|
|
110
110
|
DailyConsumption: require('./src/models/smart_meter_daily_consumption'),
|
|
111
|
+
WaterMeterSettings: require('./src/models/water_meter_settings'),
|
|
111
112
|
AnalogMeter: require('./src/models/analog_water_meter'),
|
|
112
113
|
MeterSize: require('./src/models/water_meter_size'),
|
|
113
114
|
MeterProtocol: require('./src/models/water_meter_communication'),
|
package/package.json
CHANGED
package/src/models/handover.js
CHANGED
|
@@ -1,139 +1,245 @@
|
|
|
1
|
-
const mongoose = require(
|
|
1
|
+
const mongoose = require('mongoose');
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
itemName: {
|
|
3
|
+
const handoverItemSchema = new mongoose.Schema({
|
|
4
|
+
name: {
|
|
6
5
|
type: String,
|
|
7
6
|
required: true,
|
|
7
|
+
trim: true
|
|
8
8
|
},
|
|
9
9
|
category: {
|
|
10
10
|
type: String,
|
|
11
11
|
required: true,
|
|
12
|
-
|
|
12
|
+
trim: true,
|
|
13
|
+
enum: ['Furniture', 'Appliance', 'Electronics', 'Fixture', 'Utility', 'Other']
|
|
13
14
|
},
|
|
14
|
-
|
|
15
|
+
description: {
|
|
15
16
|
type: String,
|
|
16
|
-
|
|
17
|
-
enum: ["Working", "Not Working"]
|
|
17
|
+
trim: true
|
|
18
18
|
},
|
|
19
|
-
|
|
19
|
+
condition: {
|
|
20
20
|
type: String,
|
|
21
|
-
|
|
21
|
+
required: true,
|
|
22
|
+
enum: ['Excellent', 'Good', 'Fair', 'Poor', 'Damaged', 'Non-functional']
|
|
22
23
|
},
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
uploadedAt: Date
|
|
26
|
-
}]
|
|
27
|
-
}, {
|
|
28
|
-
timestamps: true
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
// Main Handover Schema
|
|
32
|
-
const handoverSchema = new mongoose.Schema({
|
|
33
|
-
// Basic Information
|
|
34
|
-
handoverType: {
|
|
35
|
-
type: String,
|
|
24
|
+
quantity: {
|
|
25
|
+
type: Number,
|
|
36
26
|
required: true,
|
|
37
|
-
|
|
27
|
+
default: 1,
|
|
28
|
+
min: [1, 'Quantity must be at least 1']
|
|
38
29
|
},
|
|
39
|
-
|
|
40
|
-
type:
|
|
41
|
-
|
|
42
|
-
required: true
|
|
30
|
+
serialNumber: {
|
|
31
|
+
type: String,
|
|
32
|
+
trim: true
|
|
43
33
|
},
|
|
44
|
-
|
|
34
|
+
images: [{
|
|
35
|
+
type: String, // URLs to stored images
|
|
36
|
+
trim: true
|
|
37
|
+
}],
|
|
38
|
+
notes: {
|
|
39
|
+
type: String,
|
|
40
|
+
trim: true
|
|
41
|
+
}
|
|
42
|
+
}, { _id: true });
|
|
43
|
+
|
|
44
|
+
// Define the main Handover schema
|
|
45
|
+
const handoverSchema = new mongoose.Schema({
|
|
46
|
+
// References
|
|
47
|
+
facilityId: {
|
|
45
48
|
type: mongoose.Schema.Types.ObjectId,
|
|
46
|
-
ref:
|
|
49
|
+
ref: 'Facility',
|
|
47
50
|
required: true
|
|
48
51
|
},
|
|
49
|
-
|
|
52
|
+
unitId: {
|
|
50
53
|
type: mongoose.Schema.Types.ObjectId,
|
|
51
|
-
ref:
|
|
54
|
+
ref: 'Unit',
|
|
52
55
|
required: true
|
|
53
56
|
},
|
|
54
|
-
|
|
57
|
+
customerId: {
|
|
55
58
|
type: mongoose.Schema.Types.ObjectId,
|
|
56
|
-
ref:
|
|
59
|
+
ref: 'Customer',
|
|
57
60
|
required: true
|
|
58
61
|
},
|
|
59
|
-
|
|
62
|
+
propertyManagerId: {
|
|
60
63
|
type: mongoose.Schema.Types.ObjectId,
|
|
61
|
-
ref:
|
|
64
|
+
ref: 'User', // Reference to your User model
|
|
62
65
|
required: true
|
|
63
66
|
},
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
67
|
+
|
|
68
|
+
// Handover details
|
|
69
|
+
handoverType: {
|
|
70
|
+
type: String,
|
|
71
|
+
required: true,
|
|
72
|
+
enum: ['MoveIn', 'MoveOut'],
|
|
73
|
+
trim: true
|
|
68
74
|
},
|
|
69
|
-
|
|
70
|
-
// Handover Details
|
|
71
|
-
scheduledDate: {
|
|
75
|
+
handoverDate: {
|
|
72
76
|
type: Date,
|
|
73
|
-
required: true
|
|
74
|
-
|
|
75
|
-
actualHandoverDate: {
|
|
76
|
-
type: Date
|
|
77
|
+
required: true,
|
|
78
|
+
default: Date.now
|
|
77
79
|
},
|
|
78
80
|
status: {
|
|
79
81
|
type: String,
|
|
80
82
|
required: true,
|
|
81
|
-
enum: [
|
|
82
|
-
default:
|
|
83
|
+
enum: ['Draft', 'Completed', 'Disputed', 'Resolved'],
|
|
84
|
+
default: 'Draft'
|
|
83
85
|
},
|
|
84
|
-
|
|
85
|
-
//
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
86
|
+
|
|
87
|
+
// If this is a move-out handover, reference the original move-in handover
|
|
88
|
+
relatedHandoverId: {
|
|
89
|
+
type: mongoose.Schema.Types.ObjectId,
|
|
90
|
+
ref: 'Handover',
|
|
91
|
+
default: null // Only populated for move-out handovers
|
|
92
|
+
},
|
|
93
|
+
|
|
94
|
+
// Items included in the handover
|
|
95
|
+
items: [handoverItemSchema],
|
|
96
|
+
|
|
97
|
+
// Additional information
|
|
98
|
+
meterReadings: {
|
|
90
99
|
electricity: {
|
|
91
|
-
meterNumber: String,
|
|
92
100
|
reading: Number,
|
|
93
|
-
|
|
101
|
+
imageUrl: String
|
|
94
102
|
},
|
|
95
103
|
water: {
|
|
96
|
-
meterNumber: String,
|
|
97
104
|
reading: Number,
|
|
98
|
-
|
|
105
|
+
imageUrl: String
|
|
99
106
|
},
|
|
100
107
|
gas: {
|
|
101
|
-
meterNumber: String,
|
|
102
108
|
reading: Number,
|
|
103
|
-
|
|
109
|
+
imageUrl: String
|
|
104
110
|
}
|
|
105
111
|
},
|
|
106
|
-
|
|
107
|
-
//
|
|
108
|
-
|
|
109
|
-
type:
|
|
110
|
-
|
|
111
|
-
|
|
112
|
+
|
|
113
|
+
// Key handover confirmation
|
|
114
|
+
keysHandedOver: {
|
|
115
|
+
type: Number,
|
|
116
|
+
default: 0,
|
|
117
|
+
min: 0
|
|
118
|
+
},
|
|
119
|
+
|
|
120
|
+
// Security deposit info (for move-out)
|
|
121
|
+
securityDeposit: {
|
|
122
|
+
amount: {
|
|
123
|
+
type: Number,
|
|
124
|
+
default: 0
|
|
112
125
|
},
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
126
|
+
deductions: [{
|
|
127
|
+
reason: {
|
|
128
|
+
type: String,
|
|
129
|
+
trim: true
|
|
130
|
+
},
|
|
131
|
+
amount: {
|
|
132
|
+
type: Number,
|
|
133
|
+
min: 0
|
|
134
|
+
},
|
|
135
|
+
description: String
|
|
136
|
+
}],
|
|
137
|
+
refundAmount: {
|
|
121
138
|
type: Number,
|
|
122
|
-
|
|
123
|
-
|
|
139
|
+
default: 0
|
|
140
|
+
}
|
|
141
|
+
},
|
|
142
|
+
|
|
143
|
+
// Signature and agreement info
|
|
144
|
+
signatures: {
|
|
145
|
+
propertyManager: {
|
|
146
|
+
signature: String, // URL to stored signature image or digital signature data
|
|
147
|
+
date: Date
|
|
124
148
|
},
|
|
125
|
-
|
|
126
|
-
|
|
149
|
+
customer: {
|
|
150
|
+
signature: String, // URL to stored signature image or digital signature data
|
|
151
|
+
date: Date,
|
|
152
|
+
agreement: {
|
|
153
|
+
type: Boolean,
|
|
154
|
+
default: false
|
|
155
|
+
}
|
|
156
|
+
}
|
|
127
157
|
},
|
|
128
|
-
|
|
129
|
-
//
|
|
158
|
+
|
|
159
|
+
// General notes
|
|
130
160
|
notes: {
|
|
131
|
-
type: String
|
|
132
|
-
|
|
161
|
+
type: String,
|
|
162
|
+
trim: true
|
|
163
|
+
},
|
|
164
|
+
|
|
165
|
+
// Any attached documents
|
|
166
|
+
attachments: [{
|
|
167
|
+
name: String,
|
|
168
|
+
fileUrl: String,
|
|
169
|
+
uploadDate: {
|
|
170
|
+
type: Date,
|
|
171
|
+
default: Date.now
|
|
172
|
+
}
|
|
173
|
+
}]
|
|
133
174
|
}, {
|
|
134
|
-
timestamps: true
|
|
175
|
+
timestamps: true,
|
|
176
|
+
toJSON: { virtuals: true }, // Enable virtuals when converting to JSON
|
|
177
|
+
toObject: { virtuals: true } // Enable virtuals when converting to object
|
|
135
178
|
});
|
|
136
179
|
|
|
137
|
-
|
|
180
|
+
// Add indexes for common queries
|
|
181
|
+
handoverSchema.index({ facilityId: 1, unitId: 1, handoverType: 1 });
|
|
182
|
+
handoverSchema.index({ customerId: 1, handoverType: 1 });
|
|
183
|
+
handoverSchema.index({ handoverDate: -1 });
|
|
184
|
+
|
|
185
|
+
// Virtual for calculating total deductions
|
|
186
|
+
handoverSchema.virtual('totalDeductions').get(function() {
|
|
187
|
+
if (!this.securityDeposit.deductions || this.securityDeposit.deductions.length === 0) {
|
|
188
|
+
return 0;
|
|
189
|
+
}
|
|
190
|
+
return this.securityDeposit.deductions.reduce((total, deduction) => total + (deduction.amount || 0), 0);
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
// Add method to compare move-in and move-out states
|
|
194
|
+
handoverSchema.methods.compareWithMoveIn = async function() {
|
|
195
|
+
if (this.handoverType !== 'MoveOut' || !this.relatedHandoverId) {
|
|
196
|
+
throw new Error('This method can only be called on a move-out handover with a related move-in handover');
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
// Find the related move-in handover
|
|
200
|
+
const MoveInHandover = mongoose.model('Handover');
|
|
201
|
+
const moveInHandover = await MoveInHandover.findById(this.relatedHandoverId);
|
|
202
|
+
|
|
203
|
+
if (!moveInHandover) {
|
|
204
|
+
throw new Error('Related move-in handover not found');
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
// Compare items and return differences
|
|
208
|
+
const differences = {
|
|
209
|
+
missing: [],
|
|
210
|
+
damaged: [],
|
|
211
|
+
changed: []
|
|
212
|
+
};
|
|
213
|
+
|
|
214
|
+
// Check for missing or damaged items
|
|
215
|
+
moveInHandover.items.forEach(moveInItem => {
|
|
216
|
+
const moveOutItem = this.items.find(item =>
|
|
217
|
+
item.name === moveInItem.name &&
|
|
218
|
+
item.category === moveInItem.category
|
|
219
|
+
);
|
|
220
|
+
|
|
221
|
+
if (!moveOutItem) {
|
|
222
|
+
differences.missing.push(moveInItem);
|
|
223
|
+
} else if (moveOutItem.condition !== moveInItem.condition) {
|
|
224
|
+
if (['Poor', 'Damaged', 'Non-functional'].includes(moveOutItem.condition)) {
|
|
225
|
+
differences.damaged.push({
|
|
226
|
+
item: moveOutItem,
|
|
227
|
+
originalCondition: moveInItem.condition,
|
|
228
|
+
currentCondition: moveOutItem.condition
|
|
229
|
+
});
|
|
230
|
+
} else {
|
|
231
|
+
differences.changed.push({
|
|
232
|
+
item: moveOutItem,
|
|
233
|
+
originalCondition: moveInItem.condition,
|
|
234
|
+
currentCondition: moveOutItem.condition
|
|
235
|
+
});
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
return differences;
|
|
241
|
+
};
|
|
242
|
+
|
|
243
|
+
const Handover = mongoose.model('Handover', handoverSchema);
|
|
138
244
|
|
|
139
|
-
module.exports = Handover;
|
|
245
|
+
module.exports = Handover;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
const mongoose = require('mongoose');
|
|
2
|
+
|
|
3
|
+
const waterMeterSettingsSchema = new mongoose.Schema({
|
|
4
|
+
facilityId: {
|
|
5
|
+
type: mongoose.Schema.Types.ObjectId,
|
|
6
|
+
ref: 'Facility',
|
|
7
|
+
required: true
|
|
8
|
+
},
|
|
9
|
+
minAmount: {
|
|
10
|
+
type: Number,
|
|
11
|
+
required: true,
|
|
12
|
+
default: 1
|
|
13
|
+
},
|
|
14
|
+
maxAmount: {
|
|
15
|
+
type: Number,
|
|
16
|
+
required: true,
|
|
17
|
+
default: 10000
|
|
18
|
+
},
|
|
19
|
+
gracePeriod: {
|
|
20
|
+
type: Number,
|
|
21
|
+
required: true,
|
|
22
|
+
default: 10
|
|
23
|
+
},
|
|
24
|
+
enforcePayment: {
|
|
25
|
+
type: String,
|
|
26
|
+
enum: ['yes', 'no'],
|
|
27
|
+
required: true,
|
|
28
|
+
default: 'no'
|
|
29
|
+
},
|
|
30
|
+
minimumPaymentAmount: {
|
|
31
|
+
type: Number,
|
|
32
|
+
required: true,
|
|
33
|
+
default: 0
|
|
34
|
+
},
|
|
35
|
+
tariff: {
|
|
36
|
+
type: String,
|
|
37
|
+
enum: ['yes', 'no'],
|
|
38
|
+
required: true,
|
|
39
|
+
default: 'no'
|
|
40
|
+
},
|
|
41
|
+
tariffAmount: {
|
|
42
|
+
type: Number,
|
|
43
|
+
required: true,
|
|
44
|
+
default: 0
|
|
45
|
+
},
|
|
46
|
+
fixedTariffAmount: {
|
|
47
|
+
type: Number,
|
|
48
|
+
required: true,
|
|
49
|
+
default: 0
|
|
50
|
+
},
|
|
51
|
+
notifications: {
|
|
52
|
+
type: Boolean,
|
|
53
|
+
default: false
|
|
54
|
+
}
|
|
55
|
+
}, {
|
|
56
|
+
timestamps: true
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
const WaterMeterSettings = mongoose.model('WaterMeterSettings', waterMeterSettingsSchema);
|
|
60
|
+
|
|
61
|
+
module.exports = WaterMeterSettings;
|