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 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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "payservedb",
3
- "version": "9.2.9",
3
+ "version": "9.3.0",
4
4
  "main": "index.js",
5
5
  "scripts": {
6
6
  "test": "echo \"Error: no test specified\" && exit 1"
@@ -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', default: null, index: true },
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
- withholdingTaxPercentage: {
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
- min: 0,
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;
@@ -22,7 +22,7 @@ const userSchema = new mongoose.Schema({
22
22
  type: String,
23
23
  required: false
24
24
  },
25
- type: {
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 // static on the meter — always present, customer or not
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: false,
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: {