payservedb 9.2.9 → 9.3.0
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 +4 -3
- package/package.json +1 -1
- package/src/models/levycontract.js +0 -13
- package/src/models/movein_application.js +1 -1
- package/src/models/power_invoice.js +9 -4
- package/src/models/propertyManagementSettings.js +60 -0
- package/src/models/propertyManagerRevenueEntry.js +108 -0
- package/src/models/user.js +1 -7
- package/src/models/valueaddedservices.js +29 -0
- package/src/models/water_invoice.js +2 -36
package/index.js
CHANGED
|
@@ -94,6 +94,7 @@ const models = {
|
|
|
94
94
|
Levy: require("./src/models/levy"),
|
|
95
95
|
LevyType: require("./src/models/levytype"),
|
|
96
96
|
LevyContract: require("./src/models/levycontract"),
|
|
97
|
+
DepositSchema: require("./src/models/levy_deposits"),
|
|
97
98
|
Invoice: require("./src/models/invoice"),
|
|
98
99
|
CombinedInvoice: require("./src/models/combined_invoice"),
|
|
99
100
|
InvoiceGeneration: require("./src/models/invoice_generation_approval"),
|
|
@@ -143,8 +144,6 @@ const models = {
|
|
|
143
144
|
Expense: require("./src/models/expense"),
|
|
144
145
|
ExpenseCategory: require("./src/models/expense_category"),
|
|
145
146
|
InvoiceSettings: require("./src/models/levy_invoice_settings"),
|
|
146
|
-
DepositSchema: require("./src/models/levy_deposits"),
|
|
147
|
-
ContractPaymentReceiptSchema: require("./src/models/levy_payment_receipt"),
|
|
148
147
|
Account: require("./src/models/account"),
|
|
149
148
|
FacilityPaymentDetails: require("./src/models/facility_payment_details"),
|
|
150
149
|
DefaultPaymentDetails: require("./src/models/default_payment_details"),
|
|
@@ -190,9 +189,12 @@ const models = {
|
|
|
190
189
|
UnitManagementTemplate: require("./src/models/unitManagementTemplate"),
|
|
191
190
|
PropertyManagerRevenue: require("./src/models/propertyManagerRevenue"),
|
|
192
191
|
PropertyManagerContract: require("./src/models/propertyManagerContract"),
|
|
192
|
+
PropertyManagerRevenueEntry: require("./src/models/propertyManagerRevenueEntry"),
|
|
193
|
+
PropertyManagementSettings: require("./src/models/propertyManagementSettings"),
|
|
193
194
|
BillerAddress: require("./src/models/billerAddress"),
|
|
194
195
|
AssetAssignment: require("./src/models/assetsAssignment"),
|
|
195
196
|
Wallet: require("./src/models/wallet"),
|
|
197
|
+
WalletTransaction: require("./src/models/wallet_transactions"),
|
|
196
198
|
GoodsReceivedNote: require("./src/models/goodsReceivedNotes"),
|
|
197
199
|
CommunicationStatus: require("./src/models/communication_status"),
|
|
198
200
|
MeterCommandQueue: require("./src/models/water_meter_Command_Queue"),
|
|
@@ -266,7 +268,6 @@ const models = {
|
|
|
266
268
|
RecipientGroupMember: require("./src/models/recipient_group_member"),
|
|
267
269
|
InvoiceWithholdingTax: require("./src/models/InvoiceWithholdingTax"),
|
|
268
270
|
InvoiceCreditAdjustment: require("./src/models/invoiceCreditAdjustment"),
|
|
269
|
-
WalletTransaction: require("./src/models/wallet_transaction"),
|
|
270
271
|
};
|
|
271
272
|
|
|
272
273
|
// Function to get models dynamically from a specific database connection
|
package/package.json
CHANGED
|
@@ -118,19 +118,6 @@ const LevyContractSchema = new Schema(
|
|
|
118
118
|
default: 0,
|
|
119
119
|
min: [0, 'Upfront amount cannot be negative']
|
|
120
120
|
},
|
|
121
|
-
numberOfMonths: {
|
|
122
|
-
type: Number,
|
|
123
|
-
min: [1, 'Number of months must be at least 1']
|
|
124
|
-
},
|
|
125
|
-
amountPerMonth: {
|
|
126
|
-
type: Number,
|
|
127
|
-
min: [0, 'Amount per month cannot be negative']
|
|
128
|
-
},
|
|
129
|
-
calculationMode: {
|
|
130
|
-
type: String,
|
|
131
|
-
enum: ['auto', 'custom'],
|
|
132
|
-
default: 'auto'
|
|
133
|
-
},
|
|
134
121
|
billingPeriods: {
|
|
135
122
|
type: [String],
|
|
136
123
|
default: []
|
|
@@ -3,7 +3,7 @@ const mongoose = require('mongoose');
|
|
|
3
3
|
const moveInApplicationSchema = new mongoose.Schema(
|
|
4
4
|
{
|
|
5
5
|
unitId: { type: mongoose.Schema.Types.ObjectId, required: true, index: true },
|
|
6
|
-
facilityId: { type: mongoose.Schema.Types.ObjectId, ref: 'Facility',
|
|
6
|
+
facilityId: { type: mongoose.Schema.Types.ObjectId, ref: 'Facility', required: true, index: true },
|
|
7
7
|
unitName: { type: String, default: null },
|
|
8
8
|
facilityName: { type: String, default: null },
|
|
9
9
|
tenantId: { type: mongoose.Schema.Types.ObjectId, ref: 'User', required: true, index: true },
|
|
@@ -46,11 +46,16 @@ const powerInvoiceSchema = new mongoose.Schema(
|
|
|
46
46
|
// Positive = arrears carried forward; Negative = credit from overpayment
|
|
47
47
|
},
|
|
48
48
|
|
|
49
|
-
|
|
49
|
+
withholdingTaxes: [
|
|
50
|
+
{
|
|
51
|
+
name: { type: String, required: true }, // e.g. "withholding"
|
|
52
|
+
percentage: { type: Number, required: true }, // e.g. 5
|
|
53
|
+
amount: { type: Number, required: true }, // e.g. 50 (subTotal * percentage / 100)
|
|
54
|
+
},
|
|
55
|
+
],
|
|
56
|
+
totalWithholdingTax: {
|
|
50
57
|
type: Number,
|
|
51
|
-
|
|
52
|
-
max: 100,
|
|
53
|
-
default: 0
|
|
58
|
+
default: 0,
|
|
54
59
|
},
|
|
55
60
|
|
|
56
61
|
// ── Biller Address ─────────────────────────────────────────────────────────
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
const mongoose = require('mongoose');
|
|
2
|
+
|
|
3
|
+
const feeRuleSchema = new mongoose.Schema(
|
|
4
|
+
{
|
|
5
|
+
type: {
|
|
6
|
+
type: String,
|
|
7
|
+
enum: ['percentage', 'amount'],
|
|
8
|
+
default: 'percentage'
|
|
9
|
+
},
|
|
10
|
+
value: {
|
|
11
|
+
type: Number,
|
|
12
|
+
default: 0,
|
|
13
|
+
min: [0, 'Fee value cannot be negative']
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
{ _id: false }
|
|
17
|
+
);
|
|
18
|
+
|
|
19
|
+
// Per-facility property management revenue settings.
|
|
20
|
+
// Booking commission is configured in the booking module (BookingConfig /
|
|
21
|
+
// BookingProperty), so only lease fee and rent commission live here.
|
|
22
|
+
const propertyManagementSettingsSchema = new mongoose.Schema(
|
|
23
|
+
{
|
|
24
|
+
facility: {
|
|
25
|
+
type: mongoose.Schema.Types.ObjectId,
|
|
26
|
+
ref: 'Facility',
|
|
27
|
+
required: true,
|
|
28
|
+
unique: true
|
|
29
|
+
},
|
|
30
|
+
// One-time fee earned when the first rent payment lands on a managed unit
|
|
31
|
+
leaseFee: {
|
|
32
|
+
type: feeRuleSchema,
|
|
33
|
+
default: () => ({ type: 'percentage', value: 0 })
|
|
34
|
+
},
|
|
35
|
+
// Commission earned on every rent payment collected on a managed unit
|
|
36
|
+
rentCommission: {
|
|
37
|
+
type: feeRuleSchema,
|
|
38
|
+
default: () => ({ type: 'percentage', value: 0 })
|
|
39
|
+
},
|
|
40
|
+
updatedBy: {
|
|
41
|
+
type: mongoose.Schema.Types.ObjectId,
|
|
42
|
+
ref: 'User'
|
|
43
|
+
}
|
|
44
|
+
},
|
|
45
|
+
{ timestamps: true }
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
propertyManagementSettingsSchema.pre('validate', function (next) {
|
|
49
|
+
const rules = [this.leaseFee, this.rentCommission];
|
|
50
|
+
for (const rule of rules) {
|
|
51
|
+
if (rule && rule.type === 'percentage' && rule.value > 100) {
|
|
52
|
+
return next(new Error('Percentage fee cannot exceed 100%'));
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
next();
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
const PropertyManagementSettings = mongoose.model('PropertyManagementSettings', propertyManagementSettingsSchema);
|
|
59
|
+
|
|
60
|
+
module.exports = PropertyManagementSettings;
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
const mongoose = require('mongoose');
|
|
2
|
+
|
|
3
|
+
// One document per revenue event earned by a property manager.
|
|
4
|
+
// Sources: booking commission, lease fee (first rent payment) and rent commission.
|
|
5
|
+
const propertyManagerRevenueEntrySchema = new mongoose.Schema({
|
|
6
|
+
facility: {
|
|
7
|
+
type: mongoose.Schema.Types.ObjectId,
|
|
8
|
+
ref: 'Facility',
|
|
9
|
+
required: true,
|
|
10
|
+
index: true
|
|
11
|
+
},
|
|
12
|
+
propertyManager: {
|
|
13
|
+
id: {
|
|
14
|
+
type: mongoose.Schema.Types.ObjectId,
|
|
15
|
+
ref: 'User',
|
|
16
|
+
required: true,
|
|
17
|
+
index: true
|
|
18
|
+
},
|
|
19
|
+
fullName: String,
|
|
20
|
+
email: String,
|
|
21
|
+
phoneNumber: String
|
|
22
|
+
},
|
|
23
|
+
contractId: {
|
|
24
|
+
type: mongoose.Schema.Types.ObjectId,
|
|
25
|
+
ref: 'PropertyManagerContract'
|
|
26
|
+
},
|
|
27
|
+
contractName: String,
|
|
28
|
+
unit: {
|
|
29
|
+
type: mongoose.Schema.Types.ObjectId,
|
|
30
|
+
ref: 'Unit',
|
|
31
|
+
required: true
|
|
32
|
+
},
|
|
33
|
+
unitName: String,
|
|
34
|
+
source: {
|
|
35
|
+
type: String,
|
|
36
|
+
enum: ['booking_commission', 'lease_fee', 'rent_commission'],
|
|
37
|
+
required: true,
|
|
38
|
+
index: true
|
|
39
|
+
},
|
|
40
|
+
// Amount the rate was applied to (paid amount of the invoice / booking)
|
|
41
|
+
baseAmount: {
|
|
42
|
+
type: Number,
|
|
43
|
+
default: 0
|
|
44
|
+
},
|
|
45
|
+
rate: {
|
|
46
|
+
type: {
|
|
47
|
+
type: String,
|
|
48
|
+
enum: ['percentage', 'amount']
|
|
49
|
+
},
|
|
50
|
+
value: {
|
|
51
|
+
type: Number,
|
|
52
|
+
default: 0
|
|
53
|
+
}
|
|
54
|
+
},
|
|
55
|
+
// Revenue earned by the property manager
|
|
56
|
+
amount: {
|
|
57
|
+
type: Number,
|
|
58
|
+
required: true,
|
|
59
|
+
default: 0
|
|
60
|
+
},
|
|
61
|
+
// Source document that generated this entry (dedupe key)
|
|
62
|
+
reference: {
|
|
63
|
+
kind: {
|
|
64
|
+
type: String,
|
|
65
|
+
enum: ['invoice', 'reservation'],
|
|
66
|
+
required: true
|
|
67
|
+
},
|
|
68
|
+
id: {
|
|
69
|
+
type: mongoose.Schema.Types.ObjectId,
|
|
70
|
+
required: true
|
|
71
|
+
},
|
|
72
|
+
number: String
|
|
73
|
+
},
|
|
74
|
+
// Tenant / guest the revenue relates to
|
|
75
|
+
client: {
|
|
76
|
+
id: mongoose.Schema.Types.ObjectId,
|
|
77
|
+
name: String
|
|
78
|
+
},
|
|
79
|
+
earnedDate: {
|
|
80
|
+
type: Date,
|
|
81
|
+
default: Date.now,
|
|
82
|
+
index: true
|
|
83
|
+
},
|
|
84
|
+
status: {
|
|
85
|
+
type: String,
|
|
86
|
+
enum: ['earned', 'cancelled'],
|
|
87
|
+
default: 'earned'
|
|
88
|
+
},
|
|
89
|
+
notes: String,
|
|
90
|
+
createdBy: {
|
|
91
|
+
type: mongoose.Schema.Types.ObjectId,
|
|
92
|
+
ref: 'User'
|
|
93
|
+
}
|
|
94
|
+
}, {
|
|
95
|
+
timestamps: true
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
// A source document can only generate one entry per revenue stream
|
|
99
|
+
propertyManagerRevenueEntrySchema.index(
|
|
100
|
+
{ facility: 1, source: 1, 'reference.id': 1 },
|
|
101
|
+
{ unique: true }
|
|
102
|
+
);
|
|
103
|
+
propertyManagerRevenueEntrySchema.index({ facility: 1, 'propertyManager.id': 1, source: 1, earnedDate: -1 });
|
|
104
|
+
propertyManagerRevenueEntrySchema.index({ facility: 1, earnedDate: -1 });
|
|
105
|
+
|
|
106
|
+
const PropertyManagerRevenueEntry = mongoose.model('PropertyManagerRevenueEntry', propertyManagerRevenueEntrySchema);
|
|
107
|
+
|
|
108
|
+
module.exports = PropertyManagerRevenueEntry;
|
package/src/models/user.js
CHANGED
|
@@ -22,7 +22,7 @@ const userSchema = new mongoose.Schema({
|
|
|
22
22
|
type: String,
|
|
23
23
|
required: false
|
|
24
24
|
},
|
|
25
|
-
|
|
25
|
+
type: {
|
|
26
26
|
type: String,
|
|
27
27
|
required: [true, 'Type is required'],
|
|
28
28
|
enum: ['Company', 'Project Manager', 'Universal', 'Core', 'Resident', 'Landlord', 'Supplier', 'Customer_Support', 'Customer'],
|
|
@@ -125,12 +125,6 @@ const userSchema = new mongoose.Schema({
|
|
|
125
125
|
}
|
|
126
126
|
}
|
|
127
127
|
},
|
|
128
|
-
canReceiveReports: {
|
|
129
|
-
water: { type: Boolean, default: false },
|
|
130
|
-
levy: { type: Boolean, default: false },
|
|
131
|
-
power: { type: Boolean, default: false },
|
|
132
|
-
lease: { type: Boolean, default: false },
|
|
133
|
-
},
|
|
134
128
|
kyc: {
|
|
135
129
|
|
|
136
130
|
Id: {
|
|
@@ -14,6 +14,35 @@ const valueAddedServiceSchema = new mongoose.Schema({
|
|
|
14
14
|
providerType: {
|
|
15
15
|
type: String,
|
|
16
16
|
required: true,
|
|
17
|
+
},
|
|
18
|
+
pricingModel: {
|
|
19
|
+
type: String,
|
|
20
|
+
required: true,
|
|
21
|
+
},
|
|
22
|
+
fixedprice: {
|
|
23
|
+
type: String,
|
|
24
|
+
required: true,
|
|
25
|
+
},
|
|
26
|
+
applicableTaxes: [{
|
|
27
|
+
taxId: {
|
|
28
|
+
type: mongoose.Schema.Types.ObjectId,
|
|
29
|
+
ref: 'CountryTaxRate'
|
|
30
|
+
},
|
|
31
|
+
taxName: String,
|
|
32
|
+
taxRate: Number
|
|
33
|
+
}],
|
|
34
|
+
// GL Account configurations
|
|
35
|
+
invoiceDoubleEntryAccount: {
|
|
36
|
+
type: mongoose.Schema.Types.ObjectId,
|
|
37
|
+
ref: 'GLAccountDoubleEntries'
|
|
38
|
+
},
|
|
39
|
+
paymentDoubleEntryAccount: {
|
|
40
|
+
type: mongoose.Schema.Types.ObjectId,
|
|
41
|
+
ref: 'GLAccountDoubleEntries'
|
|
42
|
+
},
|
|
43
|
+
taxDoubleEntryAccount: {
|
|
44
|
+
type: mongoose.Schema.Types.ObjectId,
|
|
45
|
+
ref: 'GLAccountDoubleEntries'
|
|
17
46
|
}
|
|
18
47
|
}, {
|
|
19
48
|
timestamps: true
|
|
@@ -10,12 +10,7 @@ const waterInvoiceSchema = new mongoose.Schema(
|
|
|
10
10
|
},
|
|
11
11
|
accountNumber: {
|
|
12
12
|
type: String,
|
|
13
|
-
required: true
|
|
14
|
-
},
|
|
15
|
-
unitId: {
|
|
16
|
-
type: mongoose.Schema.Types.ObjectId,
|
|
17
|
-
ref: 'Unit',
|
|
18
|
-
default: null
|
|
13
|
+
required: true
|
|
19
14
|
},
|
|
20
15
|
unitName: {
|
|
21
16
|
type: String,
|
|
@@ -29,18 +24,10 @@ const waterInvoiceSchema = new mongoose.Schema(
|
|
|
29
24
|
type: mongoose.Schema.Types.ObjectId,
|
|
30
25
|
required: true
|
|
31
26
|
},
|
|
32
|
-
|
|
33
|
-
// Customer is now OPTIONAL — a meter can be billed with no active tenant
|
|
34
27
|
customerId: {
|
|
35
28
|
type: mongoose.Schema.Types.ObjectId,
|
|
36
|
-
required:
|
|
37
|
-
default: null
|
|
38
|
-
},
|
|
39
|
-
hasActiveCustomer: {
|
|
40
|
-
type: Boolean,
|
|
41
|
-
default: true
|
|
29
|
+
required: true
|
|
42
30
|
},
|
|
43
|
-
|
|
44
31
|
billingType: {
|
|
45
32
|
type: String,
|
|
46
33
|
enum: ['postpaid'],
|
|
@@ -50,27 +37,6 @@ const waterInvoiceSchema = new mongoose.Schema(
|
|
|
50
37
|
default: 0
|
|
51
38
|
},
|
|
52
39
|
|
|
53
|
-
// Tracks WHY the balance was carried forward the way it was —
|
|
54
|
-
// critical for audit trail when tenants move in/out of a unit.
|
|
55
|
-
balanceSource: {
|
|
56
|
-
type: String,
|
|
57
|
-
enum: ['customer', 'unit', 'reset-new-tenant', 'none', 'error'],
|
|
58
|
-
default: 'none'
|
|
59
|
-
},
|
|
60
|
-
|
|
61
|
-
// If a tenant changed and there was an outstanding balance from the
|
|
62
|
-
// PREVIOUS tenant, it is NOT carried onto the new tenant's invoice.
|
|
63
|
-
// It's recorded here instead so it isn't silently lost, and can be
|
|
64
|
-
// picked up by a separate collections/reconciliation process.
|
|
65
|
-
unresolvedPriorBalance: {
|
|
66
|
-
type: Number,
|
|
67
|
-
default: 0
|
|
68
|
-
},
|
|
69
|
-
unresolvedPriorCustomerId: {
|
|
70
|
-
type: mongoose.Schema.Types.ObjectId,
|
|
71
|
-
default: null
|
|
72
|
-
},
|
|
73
|
-
|
|
74
40
|
paymentMethods: {
|
|
75
41
|
mobilePayment: {
|
|
76
42
|
status: {
|