database-connector 2.4.2 → 2.4.4

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/CHANGELOG.md CHANGED
@@ -3,6 +3,48 @@
3
3
  ## [Unreleased]
4
4
 
5
5
  ### Added
6
+ - **PlanType Model**: Created new `PlanType` model for plan categorization and feature management
7
+ - Schema includes `name` (unique, required), `endDate` (optional, nullable), `active` (boolean, default: true), and `features` (Map of string keys to Mixed values - boolean or number)
8
+ - Features can be boolean flags (enabled/disabled) or numeric limits/quotas (e.g., maxProducts: 100)
9
+ - Used to categorize subscription plans and manage feature sets (lock/unlock features)
10
+ - Added Swagger documentation for API endpoints
11
+ - Indexed `active` and `name` fields for performance optimization
12
+ - Exported PlanType model in `models/index.js`
13
+
14
+ - **Plan Model**: Added `additionalStoreReductionPercentage` field
15
+ - Type: Number (default: 0, range: 0-100)
16
+ - Represents the percentage of reduction applied when adding additional stores to a subscription
17
+ - Base price is for one store; this field controls discounts for multi-store subscriptions
18
+ - Updated Swagger documentation to reflect new field
19
+
20
+ - **ReductionOffer Model**: Added `additionalStoreReductionPercentage` field
21
+ - Type: Number (nullable, default: null, range: 0-100)
22
+ - Allows reduction offers to override the plan's additional store reduction percentage
23
+ - Null value means no reduction on additional stores for this offer
24
+ - Updated Swagger documentation to reflect new field
25
+
26
+ - **User Model**: Added `preferredLang` field
27
+ - Type: String, enum: ['ar', 'en', 'fr'], default: 'en'
28
+ - Stores user's preferred language for interface and communications
29
+ - Updated Swagger documentation to reflect new field
30
+
31
+ - **Subscription Model**: Added multiple new fields and improvements
32
+ - `planTypeId`: ObjectId reference to PlanType model
33
+ - `numberOfStores`: Number (default: 1, minimum: 1) - tracks number of stores in subscription
34
+ - `billingAddress`: Mixed object for billing address (Adresse de facturation)
35
+ - `invoiceRecipient`: Object with type (Person/Company enum) and name fields (Facture au nom de)
36
+ - `invoiceLink`: String (nullable, default: null) - link to the invoice document
37
+ - Updated `subscriptionsHistory` and `upcomingSubscriptions` arrays to include complete subscription snapshots
38
+ - Both now include all fields: storeId, planId, planTypeId, paymentTypeId, paymentIntentId, reductionOfferId, numberOfStores, billingAddress, invoiceRecipient, invoiceLink
39
+ - Makes history tracking consistent and comprehensive
40
+ - Added `planTypeId` index for performance optimization
41
+ - Updated history snapshot builder to include all new fields including invoiceLink
42
+ - Updated Swagger documentation to reflect all new fields
43
+
44
+ - **Order Model**: Added invoice link field
45
+ - `invoiceLink`: String (nullable, default: null) - link to the invoice document
46
+ - Updated Swagger documentation to reflect new field
47
+
6
48
  - **Rayon Model**: Created new independent `Rayon` model for product and store organization
7
49
  - Schema includes `name` field and `subRayons` array for hierarchical organization
8
50
  - Added `confirmed` boolean on rayon and sub-rayons (default: false)
@@ -20,6 +62,19 @@
20
62
  - Now references the `Rayon` model with support for sub-rayons (similar to `productCategorieIds` structure)
21
63
  - Structure: `{ rayonId: ObjectId, subRayons: [ObjectId] }`
22
64
  - **Database Schema Documentation**: Updated `DATABASE_SCHEMA.md`
65
+ - Added PlanType entity to ER diagram with relationships to Plan and Subscription models
66
+ - Updated PlanType to show features support both boolean and number values
67
+ - Added PlanType model description in Subscription & Payment Models section
68
+ - Updated Plan model documentation to include `additionalStoreReductionPercentage` field
69
+ - Updated ReductionOffer model documentation to include `additionalStoreReductionPercentage` field
70
+ - Updated User entity to include `preferredLang` field
71
+ - Updated User model description to include `preferredLang` field
72
+ - Updated Subscription entity to include `planTypeId`, `numberOfStores`, `billingAddress`, and `invoiceRecipient` fields
73
+ - Updated Subscription model description with comprehensive details on new fields and improved history tracking
74
+ - Added `planTypeId` to Subscription indexes section
75
+ - Updated subscription chain relationships to include Plan → PlanType and Subscription → PlanType
76
+ - Added PlanType indexes section (active, name)
77
+ - Updated subscription chain relationships to include Plan → PlanType
23
78
  - Added Rayon entity to ER diagram
24
79
  - Added Rayon model description in Catalog Models section
25
80
  - Updated relationship documentation to include Rayon relationships
package/models/Offer.js CHANGED
@@ -72,6 +72,11 @@ const mongoose = require('mongoose');
72
72
  * items:
73
73
  * type: string
74
74
  * description: Array of user IDs (used when type is 'specific')
75
+ * blacklist:
76
+ * type: array
77
+ * items:
78
+ * type: string
79
+ * description: Array of user IDs blacklisted from this offer
75
80
  * addToSlider:
76
81
  * type: boolean
77
82
  * default: false
@@ -173,6 +178,11 @@ const OfferSchema = new mongoose.Schema(
173
178
  ref: 'User',
174
179
  default: [],
175
180
  },
181
+ blacklist: {
182
+ type: [mongoose.Schema.Types.ObjectId],
183
+ ref: 'User',
184
+ default: [],
185
+ },
176
186
  addToSlider: {
177
187
  type: Boolean,
178
188
  default: false,
@@ -207,5 +217,6 @@ OfferSchema.index({ createdAt: -1 });
207
217
  OfferSchema.index({ offerDeleted: 1 });
208
218
  OfferSchema.index({ type: 1 });
209
219
  OfferSchema.index({ userIds: 1 });
220
+ OfferSchema.index({ blacklist: 1 });
210
221
 
211
222
  module.exports = mongoose.model('Offer', OfferSchema);
package/models/Order.js CHANGED
@@ -237,6 +237,10 @@ const { policySchema } = require('./Policy');
237
237
  * type: string
238
238
  * motif:
239
239
  * type: string
240
+ * invoiceLink:
241
+ * type: string
242
+ * nullable: true
243
+ * description: Link to the invoice document
240
244
  * status:
241
245
  * type: string
242
246
  * enum: [Pending, Payed, InPreparation, LoadingDelivery, OnTheWay, Delivered, AwaitingRecovery, Recovered, Reserved, WaitingForReturn, Returned, UnderRefund, Refunded, succeeded]
@@ -460,6 +464,10 @@ const orderSchema = new mongoose.Schema(
460
464
  userId: { type: mongoose.Schema.Types.ObjectId },
461
465
  motif: { type: String },
462
466
  },
467
+ invoiceLink: {
468
+ type: String,
469
+ default: null,
470
+ },
463
471
  status: {
464
472
  type: String, required: true, enum: [
465
473
  'Pending',
package/models/Plan.js CHANGED
@@ -22,7 +22,11 @@ const mongoose = require('mongoose');
22
22
  * description: Number of months in the plan
23
23
  * price:
24
24
  * type: number
25
- * description: Plan price
25
+ * description: Plan price for one store
26
+ * additionalStoreReductionPercentage:
27
+ * type: number
28
+ * description: Percentage of reduction on each new store added to the subscription
29
+ * default: 0
26
30
  * reductionOffers:
27
31
  * type: array
28
32
  * items:
@@ -38,6 +42,7 @@ const mongoose = require('mongoose');
38
42
  * type: "Annual"
39
43
  * months: 12
40
44
  * price: 99.99
45
+ * additionalStoreReductionPercentage: 10
41
46
  * status: "active"
42
47
  */
43
48
  const planSchema = new mongoose.Schema(
@@ -63,6 +68,12 @@ const planSchema = new mongoose.Schema(
63
68
  type: Number,
64
69
  required: true,
65
70
  },
71
+ additionalStoreReductionPercentage: {
72
+ type: Number,
73
+ default: 0,
74
+ min: 0,
75
+ max: 100,
76
+ },
66
77
  reductionOffers: [
67
78
  {
68
79
  type: mongoose.Schema.Types.ObjectId,
@@ -0,0 +1,85 @@
1
+ const mongoose = require('mongoose');
2
+
3
+ /**
4
+ * @swagger
5
+ * components:
6
+ * schemas:
7
+ * PlanType:
8
+ * type: object
9
+ * required:
10
+ * - name
11
+ * properties:
12
+ * id:
13
+ * type: string
14
+ * description: The plan type identifier
15
+ * name:
16
+ * type: string
17
+ * description: Unique name for the plan type
18
+ * endDate:
19
+ * type: string
20
+ * format: date-time
21
+ * description: Optional end date for the plan type (can be null)
22
+ * active:
23
+ * type: boolean
24
+ * default: true
25
+ * description: Whether this plan type is currently active
26
+ * features:
27
+ * type: object
28
+ * additionalProperties:
29
+ * oneOf:
30
+ * - type: boolean
31
+ * - type: number
32
+ * description: Object with string keys and boolean or number values representing features to lock/unlock
33
+ * example:
34
+ * socialMedia: true
35
+ * BIanalytics: false
36
+ * promotionalSystem: true
37
+ * maxProducts: 100
38
+ * createdAt:
39
+ * type: string
40
+ * format: date-time
41
+ * updatedAt:
42
+ * type: string
43
+ * format: date-time
44
+ * example:
45
+ * id: "507f1f77bcf86cd799439011"
46
+ * name: "Premium"
47
+ * endDate: null
48
+ * active: true
49
+ * features:
50
+ * socialMedia: true
51
+ * BIanalytics: false
52
+ * promotionalSystem: true
53
+ * createdAt: "2025-11-01T10:30:00.000Z"
54
+ * updatedAt: "2025-12-01T15:45:00.000Z"
55
+ */
56
+ const planTypeSchema = new mongoose.Schema(
57
+ {
58
+ name: {
59
+ type: String,
60
+ required: true,
61
+ unique: true,
62
+ },
63
+ endDate: {
64
+ type: Date,
65
+ required: false,
66
+ default: null,
67
+ },
68
+ active: {
69
+ type: Boolean,
70
+ default: true,
71
+ },
72
+ features: {
73
+ type: Map,
74
+ of: mongoose.Schema.Types.Mixed,
75
+ default: () => new Map(),
76
+ },
77
+ },
78
+ { timestamps: true }
79
+ );
80
+
81
+ // Index for efficient queries on active plan types
82
+ planTypeSchema.index({ active: 1 });
83
+ planTypeSchema.index({ name: 1 });
84
+
85
+ module.exports = mongoose.model('PlanType', planTypeSchema);
@@ -9,7 +9,6 @@ const mongoose = require('mongoose');
9
9
  * required:
10
10
  * - name
11
11
  * - discount
12
- * - storesNumber
13
12
  * - plan
14
13
  * properties:
15
14
  * id:
@@ -21,9 +20,9 @@ const mongoose = require('mongoose');
21
20
  * discount:
22
21
  * type: number
23
22
  * description: Discount amount or percentage
24
- * storesNumber:
23
+ * additionalStoreReductionPercentage:
25
24
  * type: number
26
- * description: Number of stores included
25
+ * description: Percentage of reduction on each new store added (can be null for no reduction)
27
26
  * plan:
28
27
  * type: string
29
28
  * description: Reference to the plan
@@ -53,7 +52,6 @@ const mongoose = require('mongoose');
53
52
  * id: "507f1f77bcf86cd799439011"
54
53
  * name: "Holiday Special"
55
54
  * discount: 15
56
- * storesNumber: 5
57
55
  * status: "active"
58
56
  * createdAt: "2025-11-01T10:30:00.000Z"
59
57
  * updatedAt: "2025-12-01T15:45:00.000Z"
@@ -69,9 +67,11 @@ const ReductionOfferSchema = new mongoose.Schema(
69
67
  type: Number,
70
68
  required: true,
71
69
  },
72
- storesNumber: {
70
+ additionalStoreReductionPercentage: {
73
71
  type: Number,
74
- required: true,
72
+ default: null,
73
+ min: 0,
74
+ max: 100,
75
75
  },
76
76
  plan: {
77
77
  type: mongoose.Schema.Types.ObjectId,
@@ -5,11 +5,16 @@ const buildSubscriptionHistorySnapshot = (subscriptionDoc) => ({
5
5
  paymentManagerId: subscriptionDoc.paymentManagerId,
6
6
  storeId: subscriptionDoc.storeId,
7
7
  planId: subscriptionDoc.planId,
8
+ planTypeId: subscriptionDoc.planTypeId,
8
9
  subscriptionOfferId: subscriptionDoc.subscriptionOfferId,
9
10
  paymentAmount: subscriptionDoc.paymentAmount,
10
11
  paymentTypeId: subscriptionDoc.paymentTypeId,
11
12
  paymentIntentId: subscriptionDoc.paymentIntentId,
12
13
  reductionOfferId: subscriptionDoc.reductionOfferId,
14
+ numberOfStores: subscriptionDoc.numberOfStores,
15
+ billingAddress: subscriptionDoc.billingAddress,
16
+ invoiceRecipient: subscriptionDoc.invoiceRecipient,
17
+ invoiceLink: subscriptionDoc.invoiceLink,
13
18
  status: subscriptionDoc.status,
14
19
  startDate: subscriptionDoc.startDate,
15
20
  endDate: subscriptionDoc.endDate,
@@ -65,9 +70,28 @@ const deleteSubscriptionHistories = async (subscriptionId) => {
65
70
  * planId:
66
71
  * type: string
67
72
  * description: Reference to the plan
73
+ * planTypeId:
74
+ * type: string
75
+ * description: Reference to the plan type
68
76
  * subscriptionOfferId:
69
77
  * type: string
70
78
  * description: Reference to subscription offer
79
+ * numberOfStores:
80
+ * type: number
81
+ * default: 1
82
+ * description: Number of stores in this subscription
83
+ * billingAddress:
84
+ * type: object
85
+ * description: Billing address for the subscription
86
+ * invoiceRecipient:
87
+ * type: object
88
+ * properties:
89
+ * type:
90
+ * type: string
91
+ * enum: [Person, Company]
92
+ * name:
93
+ * type: string
94
+ * description: Invoice recipient information (Person or Company)
71
95
  * paymentAmount:
72
96
  * type: number
73
97
  * description: Payment amount
@@ -99,6 +123,10 @@ const deleteSubscriptionHistories = async (subscriptionId) => {
99
123
  * items:
100
124
  * type: string
101
125
  * description: Notes about the subscription
126
+ * invoiceLink:
127
+ * type: string
128
+ * nullable: true
129
+ * description: Link to the invoice document
102
130
  * histories:
103
131
  * type: array
104
132
  * description: Immutable list of recorded subscription snapshots
@@ -131,11 +159,36 @@ const subscriptionSchema = new mongoose.Schema(
131
159
  required: false,
132
160
  ref: 'Plan',
133
161
  },
162
+ planTypeId: {
163
+ type: mongoose.Schema.Types.ObjectId,
164
+ required: false,
165
+ ref: 'PlanType',
166
+ },
134
167
  subscriptionOfferId: {
135
168
  type: mongoose.Schema.Types.ObjectId,
136
169
  required: false,
137
170
  ref: 'SubscriptionOffer',
138
171
  },
172
+ numberOfStores: {
173
+ type: Number,
174
+ default: 1,
175
+ min: 1,
176
+ },
177
+ billingAddress: {
178
+ type: mongoose.Schema.Types.Mixed,
179
+ required: false,
180
+ },
181
+ invoiceRecipient: {
182
+ type: {
183
+ type: String,
184
+ enum: ['Person', 'Company'],
185
+ required: false,
186
+ },
187
+ name: {
188
+ type: String,
189
+ required: false,
190
+ },
191
+ },
139
192
  paymentAmount: {
140
193
  type: Number,
141
194
  required: true,
@@ -170,6 +223,10 @@ const subscriptionSchema = new mongoose.Schema(
170
223
  required: true,
171
224
  },
172
225
  notes: [{ type: String }],
226
+ invoiceLink: {
227
+ type: String,
228
+ default: null,
229
+ },
173
230
  histories: [
174
231
  {
175
232
  type: mongoose.Schema.Types.ObjectId,
@@ -180,14 +237,24 @@ const subscriptionSchema = new mongoose.Schema(
180
237
  {
181
238
  paymentManagerId: {
182
239
  type: mongoose.Schema.Types.ObjectId,
183
- required: true,
240
+ required: false,
184
241
  ref: 'User',
185
242
  },
243
+ storeId: {
244
+ type: mongoose.Schema.Types.ObjectId,
245
+ required: false,
246
+ ref: 'Store',
247
+ },
186
248
  planId: {
187
249
  type: mongoose.Schema.Types.ObjectId,
188
- required: true,
250
+ required: false,
189
251
  ref: 'Plan',
190
252
  },
253
+ planTypeId: {
254
+ type: mongoose.Schema.Types.ObjectId,
255
+ required: false,
256
+ ref: 'PlanType',
257
+ },
191
258
  subscriptionOfferId: {
192
259
  type: mongoose.Schema.Types.ObjectId,
193
260
  required: false,
@@ -195,7 +262,41 @@ const subscriptionSchema = new mongoose.Schema(
195
262
  },
196
263
  paymentAmount: {
197
264
  type: Number,
198
- required: true,
265
+ required: false,
266
+ },
267
+ paymentTypeId: {
268
+ type: mongoose.Schema.Types.ObjectId,
269
+ required: false,
270
+ ref: 'PaymentType',
271
+ },
272
+ paymentIntentId: {
273
+ type: mongoose.Schema.Types.ObjectId,
274
+ required: false,
275
+ ref: 'Payment',
276
+ },
277
+ reductionOfferId: {
278
+ type: mongoose.Schema.Types.ObjectId,
279
+ required: false,
280
+ ref: 'ReductionOffer',
281
+ },
282
+ numberOfStores: {
283
+ type: Number,
284
+ default: 1,
285
+ },
286
+ billingAddress: {
287
+ type: mongoose.Schema.Types.Mixed,
288
+ required: false,
289
+ },
290
+ invoiceRecipient: {
291
+ type: {
292
+ type: String,
293
+ enum: ['Person', 'Company'],
294
+ required: false,
295
+ },
296
+ name: {
297
+ type: String,
298
+ required: false,
299
+ },
199
300
  },
200
301
  status: {
201
302
  type: String,
@@ -203,27 +304,41 @@ const subscriptionSchema = new mongoose.Schema(
203
304
  },
204
305
  startDate: {
205
306
  type: Date,
206
- required: true,
307
+ required: false,
207
308
  },
208
309
  endDate: {
209
310
  type: Date,
210
- required: true,
311
+ required: false,
211
312
  },
212
313
  notes: [{ type: String }],
314
+ invoiceLink: {
315
+ type: String,
316
+ default: null,
317
+ },
213
318
  },
214
319
  ],
215
320
  upcomingSubscriptions: [
216
321
  {
217
322
  paymentManagerId: {
218
323
  type: mongoose.Schema.Types.ObjectId,
219
- required: true,
324
+ required: false,
220
325
  ref: 'User',
221
326
  },
327
+ storeId: {
328
+ type: mongoose.Schema.Types.ObjectId,
329
+ required: false,
330
+ ref: 'Store',
331
+ },
222
332
  planId: {
223
333
  type: mongoose.Schema.Types.ObjectId,
224
- required: true,
334
+ required: false,
225
335
  ref: 'Plan',
226
336
  },
337
+ planTypeId: {
338
+ type: mongoose.Schema.Types.ObjectId,
339
+ required: false,
340
+ ref: 'PlanType',
341
+ },
227
342
  subscriptionOfferId: {
228
343
  type: mongoose.Schema.Types.ObjectId,
229
344
  required: false,
@@ -231,7 +346,41 @@ const subscriptionSchema = new mongoose.Schema(
231
346
  },
232
347
  paymentAmount: {
233
348
  type: Number,
234
- required: true,
349
+ required: false,
350
+ },
351
+ paymentTypeId: {
352
+ type: mongoose.Schema.Types.ObjectId,
353
+ required: false,
354
+ ref: 'PaymentType',
355
+ },
356
+ paymentIntentId: {
357
+ type: mongoose.Schema.Types.ObjectId,
358
+ required: false,
359
+ ref: 'Payment',
360
+ },
361
+ reductionOfferId: {
362
+ type: mongoose.Schema.Types.ObjectId,
363
+ required: false,
364
+ ref: 'ReductionOffer',
365
+ },
366
+ numberOfStores: {
367
+ type: Number,
368
+ default: 1,
369
+ },
370
+ billingAddress: {
371
+ type: mongoose.Schema.Types.Mixed,
372
+ required: false,
373
+ },
374
+ invoiceRecipient: {
375
+ type: {
376
+ type: String,
377
+ enum: ['Person', 'Company'],
378
+ required: false,
379
+ },
380
+ name: {
381
+ type: String,
382
+ required: false,
383
+ },
235
384
  },
236
385
  status: {
237
386
  type: String,
@@ -239,13 +388,17 @@ const subscriptionSchema = new mongoose.Schema(
239
388
  },
240
389
  startDate: {
241
390
  type: Date,
242
- required: true,
391
+ required: false,
243
392
  },
244
393
  endDate: {
245
394
  type: Date,
246
- required: true,
395
+ required: false,
247
396
  },
248
397
  notes: [{ type: String }],
398
+ invoiceLink: {
399
+ type: String,
400
+ default: null,
401
+ },
249
402
  },
250
403
  ],
251
404
  },
@@ -295,6 +448,7 @@ subscriptionSchema.index({ status: 1 });
295
448
  subscriptionSchema.index({ endDate: 1 });
296
449
  subscriptionSchema.index({ startDate: 1 });
297
450
  subscriptionSchema.index({ planId: 1 });
451
+ subscriptionSchema.index({ planTypeId: 1 });
298
452
  subscriptionSchema.index({ paymentManagerId: 1 });
299
453
  subscriptionSchema.index({ storeId: 1, status: 1 });
300
454
  subscriptionSchema.index({ status: 1, endDate: 1 });
package/models/User.js CHANGED
@@ -99,6 +99,11 @@ const { policySchema } = require('database-connector/models/Policy');
99
99
  * type: number
100
100
  * default: 20
101
101
  * description: Proximity range in kilometers
102
+ * preferredLang:
103
+ * type: string
104
+ * enum: [ar, en, fr]
105
+ * default: en
106
+ * description: User's preferred language
102
107
  * storeCategorieIds:
103
108
  * type: array
104
109
  * items:
@@ -241,6 +246,11 @@ const userSchema = new mongoose.Schema(
241
246
  type: Number,
242
247
  default: 20,
243
248
  },
249
+ preferredLang: {
250
+ type: String,
251
+ enum: ['ar', 'en', 'fr'],
252
+ default: 'en',
253
+ },
244
254
  storeCategorieIds: [
245
255
  {
246
256
  type: mongoose.Schema.Types.ObjectId,
package/models/index.js CHANGED
@@ -52,6 +52,7 @@ const StoreRate = require('./StoreRate');
52
52
  const SubscriptionHistory = require('./SubscriptionHistory');
53
53
  const Subscription = require('./Subscription');
54
54
  const Plan = require('./Plan');
55
+ const PlanType = require('./PlanType');
55
56
  const SubscriptionOffer = require('./SubscriptionOffer');
56
57
  const FlashDeal = require('./FlashDeal');
57
58
  const Notification = require('./Notification');
@@ -94,6 +95,7 @@ module.exports = {
94
95
  SubscriptionHistory,
95
96
  Subscription,
96
97
  Plan,
98
+ PlanType,
97
99
  SubscriptionOffer,
98
100
  UserAction,
99
101
  Advertisement,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "database-connector",
3
- "version": "2.4.2",
3
+ "version": "2.4.4",
4
4
  "description": "MongoDB models package with Mongoose schemas for e-commerce applications. Includes User, Product, Store, Order and more with built-in validation and virtual properties.",
5
5
  "main": "models/index.js",
6
6
  "scripts": {