payservedb 4.8.3 → 4.8.5

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
@@ -140,7 +140,8 @@ const models = {
140
140
  Supplier: require('./src/models/suppliers'),
141
141
  PurchaseRequest: require('./src/models/purchase_request'),
142
142
  PurchaseOrder: require('./src/models/purchase_order'),
143
- RFQ: require('./src/models/quotation'),
143
+ RFQDetails: require('./src/models/rfq_details'),
144
+ RFQResponse: require('./src/models/rfq_response'),
144
145
  ApprovalWorkflow: require('./src/models/approvalsWorkflows'),
145
146
  CommonAreaElectricityReading: require('./src/models/common_area_electricity'),
146
147
  CommonAreaWaterReading: require('./src/models/common_area_water'),
@@ -150,8 +151,8 @@ const models = {
150
151
  BookingReservation: require('./src/models/bookingreservation'),
151
152
  BookingConfig: require('./src/models/bookingconfig'),
152
153
  BookingAnalytics: require('./src/models/bookinganalytics'),
153
- RevenueRecord: require('./src/models/bookingrevenuerecord')
154
-
154
+ RevenueRecord: require('./src/models/bookingrevenuerecord'),
155
+ GLAccount: require('./src/models/gl_accounts'),
155
156
  };
156
157
 
157
158
  // 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": "4.8.3",
3
+ "version": "4.8.5",
4
4
  "main": "index.js",
5
5
  "scripts": {
6
6
  "test": "echo \"Error: no test specified\" && exit 1"
@@ -31,7 +31,6 @@ const accountSchema = new mongoose.Schema({
31
31
  },
32
32
  });
33
33
 
34
- // [ {accountnumber:1,facilityId:1},{accountnumber:2, facility:2}]
35
34
  const Account = mongoose.model('Account', accountSchema);
36
35
 
37
36
  module.exports = Account;
@@ -0,0 +1,53 @@
1
+ const mongoose = require('mongoose');
2
+
3
+ const glAccountsSchema = new mongoose.Schema({
4
+ accountCode: {
5
+ type: String,
6
+ required: true,
7
+ unique: true,
8
+ trim: true,
9
+ },
10
+ accountName: {
11
+ type: String,
12
+ required: true,
13
+ trim: true,
14
+ },
15
+ accountType: {
16
+ type: String,
17
+ required: true,
18
+ trim: true,
19
+ },
20
+ accountBalance: {
21
+ type: Number,
22
+ default: 0,
23
+ },
24
+ facilityId: {
25
+ type: mongoose.Schema.Types.ObjectId,
26
+ ref: 'Facility',
27
+ default: null,
28
+ },
29
+ parentAccountId: {
30
+ type: mongoose.Schema.Types.ObjectId,
31
+ ref: 'GLAccount',
32
+ default: null,
33
+ },
34
+ accountLevel: {
35
+ type: Number,
36
+ required: true,
37
+ default: 0,
38
+ },
39
+ isActive: {
40
+ type: Boolean,
41
+ default: true,
42
+ },
43
+ createdAt: {
44
+ type: Date,
45
+ default: Date.now,
46
+ },
47
+ updatedAt: {
48
+ type: Date,
49
+ default: Date.now,
50
+ },
51
+ });
52
+
53
+ module.exports = mongoose.model('GLAccount', glAccountsSchema);
@@ -0,0 +1,86 @@
1
+ const mongoose = require('mongoose');
2
+
3
+ const rfqDetailsSchema = new mongoose.Schema({
4
+ facilityId: {
5
+ type: mongoose.Schema.Types.ObjectId,
6
+ ref: 'Facility',
7
+ required: true,
8
+ index: true,
9
+ },
10
+ name: {
11
+ type: String,
12
+ required: true,
13
+ trim: true,
14
+ index: true,
15
+ },
16
+ rfqNumber: {
17
+ type: String,
18
+ required: true,
19
+ unique: true,
20
+ trim: true,
21
+ index: true,
22
+ },
23
+
24
+ startDate: {
25
+ type: Date,
26
+ required: true,
27
+ },
28
+ closingDate: {
29
+ type: Date,
30
+ required: true,
31
+ },
32
+
33
+ currency: {
34
+ type: String,
35
+ required: true,
36
+ enum: ['KES', 'USD', 'EUR', 'GBP'],
37
+ default: 'KES',
38
+ },
39
+ rfqType: {
40
+ type: String,
41
+ required: true,
42
+ enum: ['open', 'closed'],
43
+ default: 'closed',
44
+ },
45
+ rfqFee: {
46
+ type: Number,
47
+ default: 0,
48
+ },
49
+ rfqEvaluationType: {
50
+ type: String,
51
+ required: true,
52
+ enum: ['automatic', 'approvers'],
53
+ default: 'automatic',
54
+ },
55
+ notes: {
56
+ type: String,
57
+ trim: true,
58
+ },
59
+ category: {
60
+ type: String,
61
+ trim: true,
62
+ },
63
+
64
+ // just store the IDs you invited
65
+ suppliers: [{
66
+ type: mongoose.Schema.Types.ObjectId,
67
+ ref: 'Supplier',
68
+ required: true,
69
+ }],
70
+
71
+ // the free‑form items your UI collects
72
+ items: [{
73
+ itemName: { type: String, required: true, trim: true },
74
+ description: { type: String, trim: true },
75
+ quantity: { type: Number, required: true, min: 1 },
76
+ unitOfMeasure: { type: String, trim: true },
77
+ specifications: { type: String, trim: true },
78
+ }],
79
+
80
+ }, {
81
+ timestamps: true,
82
+ });
83
+
84
+ const RFQDetails = mongoose.model('RFQDetails', rfqDetailsSchema);
85
+
86
+ module.exports = RFQDetails;
@@ -0,0 +1,109 @@
1
+ const mongoose = require('mongoose');
2
+
3
+ const rfqResponseSchema = new mongoose.Schema({
4
+ facilityId: {
5
+ type: mongoose.Schema.Types.ObjectId,
6
+ ref: 'Facility',
7
+ required: true,
8
+ index: true,
9
+ },
10
+ rfqId: {
11
+ type: mongoose.Schema.Types.ObjectId,
12
+ ref: 'RFQDetails',
13
+ required: true,
14
+ unique: true,
15
+ index: true,
16
+ },
17
+
18
+ // track each supplier’s progress & quotation
19
+ suppliers: [{
20
+ supplierId: {
21
+ type: mongoose.Schema.Types.ObjectId,
22
+ ref: 'Supplier',
23
+ required: true,
24
+ },
25
+ invitationStatus: {
26
+ type: String,
27
+ enum: ['pending', 'accepted', 'declined', 'no-response'],
28
+ default: 'pending',
29
+ },
30
+ invitationDate: {
31
+ type: Date,
32
+ default: Date.now,
33
+ },
34
+ responseDate: Date,
35
+ quotationSubmitted: {
36
+ type: Boolean,
37
+ default: false,
38
+ },
39
+ quotationDetails: {
40
+ submissionDate: Date,
41
+ totalAmount: Number,
42
+ items: [{
43
+ // tie back to the Details’ item index or category
44
+ categoryId: { type: mongoose.Schema.Types.ObjectId, required: true },
45
+ itemId: { type: mongoose.Schema.Types.ObjectId, required: true },
46
+ unitPrice: { type: Number, required: true },
47
+ quantity: { type: Number, required: true },
48
+ totalPrice: { type: Number, required: true },
49
+ notes: { type: String, trim: true },
50
+ }],
51
+ attachments: [{
52
+ name: { type: String, required: true },
53
+ fileType: { type: String, required: true },
54
+ filePath: { type: String, required: true },
55
+ uploadDate: { type: Date, default: Date.now },
56
+ }],
57
+ notes: { type: String, trim: true },
58
+ },
59
+ evaluationScore: { type: Number, min: 0, max: 100 },
60
+ evaluationNotes: { type: String, trim: true },
61
+ }],
62
+
63
+ // overall lifecycle & award
64
+ status: {
65
+ type: String,
66
+ enum: ['open', 'closed', 'awarded', 'canceled'],
67
+ default: 'open',
68
+ index: true,
69
+ },
70
+ awardDetails: {
71
+ awarded: {
72
+ type: Boolean,
73
+ default: false,
74
+ },
75
+ awardedSupplierId: {
76
+ type: mongoose.Schema.Types.ObjectId,
77
+ ref: 'Supplier',
78
+ },
79
+ awardedSupplierName: {
80
+ type: String,
81
+ trim: true,
82
+ },
83
+ awardDate: Date,
84
+ awardNotes: { type: String, trim: true },
85
+
86
+ purchaseOrderCreated: {
87
+ type: Boolean,
88
+ default: false,
89
+ },
90
+ purchaseOrderId: {
91
+ type: mongoose.Schema.Types.ObjectId,
92
+ ref: 'PurchaseOrder',
93
+ },
94
+ },
95
+
96
+ }, {
97
+ timestamps: true,
98
+ });
99
+
100
+ // participation rate virtual
101
+ rfqResponseSchema.virtual('participationRate').get(function () {
102
+ if (!this.suppliers.length) return 0;
103
+ const responded = this.suppliers.filter(s => s.quotationSubmitted).length;
104
+ return (responded / this.suppliers.length) * 100;
105
+ });
106
+
107
+ const RFQResponse = mongoose.model('RFQResponse', rfqResponseSchema);
108
+
109
+ module.exports = RFQResponse;
@@ -1,268 +0,0 @@
1
- const mongoose = require('mongoose');
2
-
3
- const rfqSchema = new mongoose.Schema({
4
- facilityId: {
5
- type: mongoose.Schema.Types.ObjectId,
6
- ref: 'Facility',
7
- required: true,
8
- index: true
9
- },
10
- name: {
11
- type: String,
12
- required: true,
13
- trim: true,
14
- index: true
15
- },
16
- rfqNumber: {
17
- type: String,
18
- required: true,
19
- unique: true,
20
- trim: true,
21
- index: true
22
- },
23
- startDate: {
24
- type: Date,
25
- required: true
26
- },
27
- closingDate: {
28
- type: Date,
29
- required: true
30
- },
31
- currency: {
32
- type: String,
33
- required: true,
34
- default: 'KES',
35
- trim: true
36
- },
37
- rfqType: {
38
- type: String,
39
- required: true,
40
- enum: ['open', 'closed'],
41
- default: 'closed'
42
- },
43
- rfqFee: {
44
- type: Number,
45
- default: 0
46
- },
47
- rfqEvaluationType: {
48
- type: String,
49
- required: true,
50
- enum: ['automatic', 'approvers'],
51
- default: 'approvers'
52
- },
53
- notes: {
54
- type: String,
55
- trim: true
56
- },
57
- status: {
58
- type: String,
59
- enum: ['open','closed', 'awarded', 'canceled'],
60
- default: 'open',
61
- index: true
62
- },
63
- // RFQ Categories (Products or Services)
64
- categories: [{
65
- name: {
66
- type: String,
67
- required: true,
68
- trim: true
69
- },
70
- // For Product type
71
- products: [{
72
- productName: {
73
- type: String,
74
- trim: true,
75
- required: function() {
76
- return this.parent().categoryType === 'product';
77
- }
78
- },
79
- sku: {
80
- type: String,
81
- trim: true
82
- },
83
- quantity: {
84
- type: Number,
85
- required: function() {
86
- return this.parent().categoryType === 'product';
87
- }
88
- },
89
- unitOfMeasure: {
90
- type: String,
91
- trim: true
92
- },
93
- estimatedUnitPrice: {
94
- type: Number
95
- }
96
- }],
97
- // For Service type
98
- services: [{
99
- serviceDescription: {
100
- type: String,
101
- trim: true,
102
- required: function() {
103
- return this.parent().categoryType === 'service';
104
- }
105
- },
106
- quantity: {
107
- type: Number,
108
- required: function() {
109
- return this.parent().categoryType === 'service';
110
- }
111
- },
112
- unitOfMeasure: {
113
- type: String,
114
- trim: true
115
- },
116
- estimatedUnitPrice: {
117
- type: Number
118
- }
119
- }]
120
- }],
121
-
122
- // Suppliers invited to respond to the RFQ
123
- suppliers: [{
124
- supplierId: {
125
- type: mongoose.Schema.Types.ObjectId,
126
- ref: 'Supplier',
127
- required: true
128
- },
129
- supplierName: {
130
- type: String,
131
- required: true,
132
- trim: true
133
- },
134
- invitationStatus: {
135
- type: String,
136
- enum: ['pending', 'accepted', 'declined', 'no-response'],
137
- default: 'pending'
138
- },
139
- invitationDate: {
140
- type: Date,
141
- default: Date.now
142
- },
143
- responseDate: {
144
- type: Date
145
- },
146
- quotationSubmitted: {
147
- type: Boolean,
148
- default: false
149
- },
150
- quotationDetails: {
151
- submissionDate: {
152
- type: Date
153
- },
154
- totalAmount: {
155
- type: Number
156
- },
157
- items: [{
158
- categoryId: {
159
- type: mongoose.Schema.Types.ObjectId,
160
- required: true
161
- },
162
- itemId: {
163
- type: mongoose.Schema.Types.ObjectId,
164
- required: true
165
- },
166
- unitPrice: {
167
- type: Number,
168
- required: true
169
- },
170
- quantity: {
171
- type: Number,
172
- required: true
173
- },
174
- totalPrice: {
175
- type: Number,
176
- required: true
177
- },
178
- notes: {
179
- type: String,
180
- trim: true
181
- }
182
- }],
183
- attachments: [{
184
- name: {
185
- type: String,
186
- required: true
187
- },
188
- fileType: {
189
- type: String,
190
- required: true
191
- },
192
- filePath: {
193
- type: String,
194
- required: true
195
- },
196
- uploadDate: {
197
- type: Date,
198
- default: Date.now
199
- }
200
- }],
201
- notes: {
202
- type: String,
203
- trim: true
204
- }
205
- },
206
- evaluationScore: {
207
- type: Number,
208
- min: 0,
209
- max: 100
210
- },
211
- evaluationNotes: {
212
- type: String,
213
- trim: true
214
- }
215
- }],
216
-
217
-
218
- // Award details after RFQ is closed
219
- awardDetails: {
220
- awarded: {
221
- type: Boolean,
222
- default: false
223
- },
224
- awardedSupplierId: {
225
- type: mongoose.Schema.Types.ObjectId,
226
- ref: 'Supplier'
227
- },
228
- awardedSupplierName: {
229
- type: String,
230
- trim: true
231
- },
232
- awardDate: {
233
- type: Date
234
- },
235
- awardNotes: {
236
- type: String,
237
- trim: true
238
- },
239
- purchaseOrderCreated: {
240
- type: Boolean,
241
- default: false
242
- },
243
- purchaseOrderId: {
244
- type: mongoose.Schema.Types.ObjectId,
245
- ref: 'PurchaseOrder'
246
- }
247
- }
248
- }, {
249
- timestamps: true
250
- });
251
-
252
- // Virtual for tracking participation rate
253
- rfqSchema.virtual('participationRate').get(function() {
254
- if (!this.suppliers || this.suppliers.length === 0) return 0;
255
-
256
- const respondedCount = this.suppliers.filter(
257
- supplier => supplier.quotationSubmitted === true
258
- ).length;
259
-
260
- return (respondedCount / this.suppliers.length) * 100;
261
- });
262
-
263
- // Index for efficient querying by date ranges
264
- rfqSchema.index({ startDate: 1, closingDate: 1 });
265
-
266
- const RFQ = mongoose.model('RFQ', rfqSchema);
267
-
268
- module.exports = RFQ;