flykup_model_production 1.0.16 → 1.0.17

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.
Files changed (40) hide show
  1. package/.gitattributes +2 -0
  2. package/.github/workflows/publish.yml +31 -0
  3. package/auth.js +14 -14
  4. package/config.js +1 -1
  5. package/db_connection.js +23 -23
  6. package/index.js +140 -140
  7. package/models/AadhaarVerification.js +131 -131
  8. package/models/AdminEmail.model.js +38 -38
  9. package/models/BankVerification.js +92 -92
  10. package/models/GSTVerification.js +89 -89
  11. package/models/LiveStreamInteraction.model.js +101 -101
  12. package/models/ProductInteraction.model.js +108 -108
  13. package/models/Review.model.js +121 -121
  14. package/models/SearchAnalytics.js +23 -23
  15. package/models/ShoppableInteraction.model.js +106 -106
  16. package/models/Wishlist.model.js +29 -29
  17. package/models/admin.model.js +42 -42
  18. package/models/appUpdate.model.js +19 -19
  19. package/models/assets.model.js +32 -32
  20. package/models/blockedRegion.models.js +27 -27
  21. package/models/chat.model.js +511 -511
  22. package/models/coHostInvitation.model.js +60 -60
  23. package/models/follow.model.js +38 -38
  24. package/models/loginlogs.model.js +26 -26
  25. package/models/notification.model.js +130 -129
  26. package/models/order.modal.js +385 -385
  27. package/models/orderPayment.model.js +218 -218
  28. package/models/productListing.model.js +322 -322
  29. package/models/profileInteractions.model.js +44 -44
  30. package/models/registerShow.model.js +29 -29
  31. package/models/sellerDraft.model.js +27 -27
  32. package/models/shipper.model.js +126 -126
  33. package/models/shoppableVideo.model.js +237 -237
  34. package/models/shoppableVideoComment.model.js +57 -57
  35. package/models/shoppableVideoLike.model.js +29 -29
  36. package/models/shoppableVideoSave.model.js +27 -27
  37. package/models/shows.model.js +603 -603
  38. package/models/stock.model.js +105 -105
  39. package/models/ticket.model.js +115 -115
  40. package/package.json +18 -18
@@ -1,603 +1,603 @@
1
- import mongoose from "mongoose";
2
- const { Schema } = mongoose;
3
-
4
- const giveawayProductSchema = new Schema({
5
- _id: false,
6
- productId: { type: Schema.Types.ObjectId, ref: "productlistings", required: true },
7
- productOwnerSellerId: { type: Schema.Types.ObjectId, ref: 'sellers', required: true },
8
- productTitle: { type: String },
9
- giveawayObjectId: { type: Schema.Types.ObjectId, required: true, index: true },
10
- giveawayStatus: {
11
- type: String,
12
- enum: ['preparing', 'ready', 'active', 'ended', 'failed'],
13
- default: 'preparing'
14
- },
15
- requireAutoFollow: {
16
- type: Boolean,
17
- default: false
18
- },
19
- activatedAt: { type: Date, default: null },
20
- createdAt: { type: Date, default: Date.now }
21
- });
22
-
23
- const liveFlashSaleSchema = new Schema({
24
- _id: false,
25
- productId: {
26
- type: Schema.Types.ObjectId,
27
- ref: "productlistings",
28
- required: true
29
- },
30
- stockId: {
31
- type: Schema.Types.ObjectId,
32
- ref: "stocks",
33
- required: true
34
- },
35
- flashPrice: {
36
- type: Number,
37
- required: true,
38
- min: 1
39
- },
40
- duration: {
41
- type: Number,
42
- required: true,
43
- enum: [10, 20, 30, 40, 50, 60, 240]
44
- },
45
- initialStock: {
46
- type: Number,
47
- required: true,
48
- min: 1
49
- },
50
- currentStock: {
51
- type: Number,
52
- required: true,
53
- min: 0
54
- },
55
- sold: {
56
- type: Number,
57
- default: 0
58
- },
59
- status: {
60
- type: String,
61
- enum: ['scheduled', 'active', 'ended', 'cancelled'],
62
- default: 'scheduled'
63
- },
64
- startTime: Date,
65
- endTime: Date,
66
- flashSaleId: {
67
- type: Schema.Types.ObjectId,
68
- ref: 'FlashSale'
69
- },
70
- createdAt: {
71
- type: Date,
72
- default: Date.now
73
- }
74
- });
75
- const bundleSaleSchema = new Schema({
76
- _id: false,
77
- bundleSaleId: {
78
- type: Schema.Types.ObjectId,
79
- ref: "bundlesales",
80
- required: true
81
- },
82
- bundleOwnerSellerId: {
83
- type: Schema.Types.ObjectId,
84
- ref: 'sellers',
85
- required: function() {
86
- return this.bundleSaleId != null;
87
- }
88
- },
89
- bundleTitle: { type: String }, // Quick reference title
90
- bundleMRP: { type: Number, min: 0, default: null }, // Original MRP
91
- sellingPrice: { type: Number, min: 0, default: null }, // Actual selling price
92
- bundleImage: { // Bundle thumbnail image
93
- key: { type: String, default: null },
94
- url: { type: String, default: null }
95
- },
96
- createdAt: { type: Date, default: Date.now }
97
- });
98
-
99
- // Show Schema with FIXED validation
100
- const showSchema = new Schema(
101
- {
102
- sellerId: {
103
- type: mongoose.Schema.Types.ObjectId,
104
- ref: "sellers",
105
- },
106
- host: {
107
- type: mongoose.Schema.Types.ObjectId,
108
- required: true,
109
- refPath: 'hostModel'
110
- },
111
- hostModel: {
112
- type: String,
113
- required: true,
114
- enum: ['sellers', 'dropshippers']
115
- },
116
- title: {
117
- type: String,
118
- required: true,
119
- },
120
- date: {
121
- type: Date,
122
- },
123
- time: {
124
- type: String,
125
- },
126
- scheduledAt: {
127
- type: Date,
128
- index: true
129
- },
130
- category: {
131
- type: String,
132
- },
133
- subCategory: {
134
- type: String,
135
- default: '',
136
- },
137
- liveStreamId: { type: String, default: null },
138
- streamName: {
139
- type: String,
140
- default: ''
141
- },
142
- tags: {
143
- type: [String],
144
- default: [],
145
- },
146
- thumbnailImage: {
147
- type: String,
148
- default: null,
149
- },
150
- previewVideo: {
151
- type: String,
152
- default: null,
153
- },
154
- language: {
155
- type: String,
156
- },
157
- isLive: {
158
- type: Boolean,
159
- default: false,
160
- },
161
- streamUrl: {
162
- type: String,
163
- default: null,
164
- },
165
- orientation: {
166
- type: String,
167
- enum: ['horizontal', 'vertical'],
168
- default: 'horizontal'
169
- },
170
- layout: {
171
- type: String,
172
- enum: ['side-by-side', 'top-bottom'],
173
- default: 'side-by-side'
174
- },
175
- showStatus: {
176
- type: String,
177
- enum: ['created', 'live', 'cancelled', 'ended'],
178
- default: 'created'
179
- },
180
- viewerCount: {
181
- type: Number,
182
- default: 0,
183
- min: 0
184
- },
185
-
186
- likes: {
187
- type: Number,
188
- default: 0,
189
- },
190
- likedBy: {
191
- type: [mongoose.Schema.Types.ObjectId],
192
- ref: 'users',
193
- default: [],
194
- },
195
-
196
- // ✅ FIXED: Better validation for buyNowProducts
197
- buyNowProducts: {
198
- type: [
199
- {
200
- _id: false,
201
- productId: { type: Schema.Types.ObjectId, ref: "productlistings" },
202
- productOwnerSellerId: {
203
- type: Schema.Types.ObjectId,
204
- ref: 'sellers',
205
- required: function() {
206
- // Only require if productId exists
207
- return this.productId != null;
208
- }
209
- },
210
- productPrice: { type: Number, min: 0, default: null },
211
- },
212
- ],
213
- default: [],
214
- validate: {
215
- validator: function(products) {
216
- // Custom validation to ensure productOwnerSellerId exists when productId exists
217
- return products.every(product =>
218
- !product.productId || (product.productId && product.productOwnerSellerId)
219
- );
220
- },
221
- message: 'productOwnerSellerId is required when productId is provided'
222
- }
223
- },
224
- bundleSales: {
225
- type: [bundleSaleSchema],
226
- default: []
227
- },
228
-
229
- auctionProducts: {
230
- type: [
231
- {
232
- _id: false,
233
- productId: { type: Schema.Types.ObjectId, ref: "productlistings" },
234
- productOwnerSellerId: {
235
- type: Schema.Types.ObjectId,
236
- ref: 'sellers',
237
- required: function() {
238
- return this.productId != null;
239
- }
240
- },
241
- startingPrice: { type: Number, min: 0, default: null },
242
- reservedPrice: { type: Number, min: 0, default: null },
243
- auctionNumber: {
244
- type: Number,
245
- },
246
- auctionObjectId: {
247
- type: Schema.Types.ObjectId,
248
- required: true,
249
- index: true
250
- }
251
- },
252
- ],
253
- default: [],
254
- },
255
-
256
- giveawayProducts: {
257
- type: [giveawayProductSchema],
258
- default: []
259
- },
260
-
261
- liveFlashSales: {
262
- type: [liveFlashSaleSchema],
263
- default: []
264
- },
265
- currentFlashSale: {
266
- type: Schema.Types.ObjectId,
267
- ref: 'FlashSale',
268
- default: null
269
- },
270
-
271
- enabledProductTypes: {
272
- buyNow: { type: Boolean, default: false },
273
- auction: { type: Boolean, default: false },
274
- giveaway: { type: Boolean, default: false }
275
- },
276
- notes: {
277
- type: String,
278
- default: ''
279
- },
280
- },
281
- { timestamps: true }
282
- );
283
-
284
- // ✅ ADD THIS PRE-SAVE MIDDLEWARE TO CLEAN INVALID DATA
285
- showSchema.pre('save', function(next) {
286
- const doc = this;
287
-
288
- // Clean up buyNowProducts - remove items without required fields
289
- if (doc.buyNowProducts && Array.isArray(doc.buyNowProducts)) {
290
- doc.buyNowProducts = doc.buyNowProducts.filter(product =>
291
- product &&
292
- product.productId &&
293
- product.productOwnerSellerId
294
- );
295
- }
296
-
297
- // Clean up auctionProducts
298
- if (doc.auctionProducts && Array.isArray(doc.auctionProducts)) {
299
- doc.auctionProducts = doc.auctionProducts.filter(product =>
300
- product &&
301
- product.productId &&
302
- product.productOwnerSellerId &&
303
- product.auctionObjectId
304
- );
305
- }
306
-
307
- // Clean up giveawayProducts
308
- if (doc.giveawayProducts && Array.isArray(doc.giveawayProducts)) {
309
- doc.giveawayProducts = doc.giveawayProducts.filter(product =>
310
- product &&
311
- product.productId &&
312
- product.productOwnerSellerId &&
313
- product.giveawayObjectId
314
- );
315
- }
316
-
317
- // Set liveDrop based on product types
318
- const hasBuyNow = doc.buyNowProducts && doc.buyNowProducts.length > 0;
319
- const hasAuction = doc.auctionProducts && doc.auctionProducts.length > 0;
320
- const hasGiveaway = doc.giveawayProducts && doc.giveawayProducts.length > 0;
321
- doc.liveDrop = hasBuyNow && hasAuction && hasGiveaway;
322
-
323
- // Ensure coHost is null if hasCoHost is false
324
- if (!doc.hasCoHost) {
325
- doc.coHost = null;
326
- }
327
-
328
- next();
329
- });
330
-
331
- // ✅ ADD THIS PRE-VALIDATION MIDDLEWARE FOR EXTRA SAFETY
332
- showSchema.pre('validate', function(next) {
333
- // Ensure all arrays exist (prevent undefined errors)
334
- if (!this.buyNowProducts) this.buyNowProducts = [];
335
- if (!this.auctionProducts) this.auctionProducts = [];
336
- if (!this.giveawayProducts) this.giveawayProducts = [];
337
- if (!this.liveFlashSales) this.liveFlashSales = [];
338
-
339
- next();
340
- });
341
-
342
- const Show = mongoose.models.shows || mongoose.model("shows", showSchema);
343
- export default Show;
344
-
345
-
346
-
347
- // import mongoose from "mongoose";
348
- // const { Schema } = mongoose;
349
-
350
- // const giveawayProductSchema = new Schema({
351
- // _id: false,
352
- // productId: { type: Schema.Types.ObjectId, ref: "productlistings", required: true },
353
- // productOwnerSellerId: { type: Schema.Types.ObjectId, ref: 'sellers', required: true },
354
- // productTitle: { type: String },
355
- // giveawayObjectId: { type: Schema.Types.ObjectId, required: true, index: true },
356
- // giveawayStatus: {
357
- // type: String,
358
- // enum: ['preparing', 'ready', 'active', 'ended', 'failed'],
359
- // default: 'preparing'
360
- // },
361
- // requireAutoFollow: {
362
- // type: Boolean,
363
- // default: false
364
- // },
365
- // activatedAt: { type: Date, default: null },
366
- // createdAt: { type: Date, default: Date.now }
367
- // });
368
-
369
- // // Live Flash Sale Schema
370
- // const liveFlashSaleSchema = new Schema({
371
- // _id: false,
372
- // productId: {
373
- // type: Schema.Types.ObjectId,
374
- // ref: "productlistings",
375
- // required: true
376
- // },
377
- // stockId: {
378
- // type: Schema.Types.ObjectId,
379
- // ref: "stocks",
380
- // required: true
381
- // },
382
- // flashPrice: {
383
- // type: Number,
384
- // required: true,
385
- // min: 1
386
- // },
387
- // duration: {
388
- // type: Number,
389
- // required: true,
390
- // enum: [10, 20, 30, 40, 50, 60,240]
391
- // },
392
- // initialStock: {
393
- // type: Number,
394
- // required: true,
395
- // min: 1
396
- // },
397
- // currentStock: {
398
- // type: Number,
399
- // required: true,
400
- // min: 0
401
- // },
402
- // sold: {
403
- // type: Number,
404
- // default: 0
405
- // },
406
- // status: {
407
- // type: String,
408
- // enum: ['scheduled', 'active', 'ended', 'cancelled'],
409
- // default: 'scheduled'
410
- // },
411
- // startTime: Date,
412
- // endTime: Date,
413
- // flashSaleId: {
414
- // type: Schema.Types.ObjectId,
415
- // ref: 'FlashSale'
416
- // },
417
- // createdAt: {
418
- // type: Date,
419
- // default: Date.now
420
- // }
421
- // });
422
- // // Show Schema
423
- // const showSchema = new Schema(
424
- // {
425
- // sellerId: {
426
- // type: mongoose.Schema.Types.ObjectId,
427
- // ref: "sellers",
428
- // },
429
- // // === Host Information ===
430
- // host: {
431
- // type: mongoose.Schema.Types.ObjectId,
432
- // required: true,
433
- // refPath: 'hostModel'
434
- // },
435
- // hostModel: {
436
- // type: String,
437
- // required: true,
438
- // enum: ['sellers', 'dropshippers']
439
- // },
440
-
441
- // title: {
442
- // type: String,
443
- // required: true,
444
- // },
445
- // date: {
446
- // type: Date,
447
- // },
448
- // time: {
449
- // type: String,
450
- // },
451
- // scheduledAt: {
452
- // type: Date,
453
- // index: true
454
- // },
455
- // category: {
456
- // type: String,
457
- // },
458
- // subCategory: {
459
- // type: String,
460
- // default: '',
461
- // },
462
- // liveStreamId: { type: String, default: null },
463
- // streamName: {
464
- // type: String,
465
- // default: ''
466
- // },
467
- // tags: {
468
- // type: [String],
469
- // default: [],
470
- // },
471
-
472
- // thumbnailImage: {
473
- // type: String,
474
- // default: null,
475
- // },
476
- // previewVideo: {
477
- // type: String,
478
- // default: null,
479
- // },
480
- // language: {
481
- // type: String,
482
- // },
483
- // isLive: {
484
- // type: Boolean,
485
- // default: false,
486
- // },
487
- // streamUrl: {
488
- // type: String,
489
- // default: null,
490
- // },
491
-
492
- // // === Stream Layout Configuration ===
493
- // orientation: {
494
- // type: String,
495
- // enum: ['horizontal', 'vertical'],
496
- // default: 'horizontal'
497
- // },
498
- // layout: {
499
- // type: String,
500
- // enum: ['side-by-side', 'top-bottom'],
501
- // default: 'side-by-side'
502
- // },
503
-
504
- // showStatus: {
505
- // type: String,
506
- // enum: ['created', 'live', 'cancelled', 'ended'],
507
- // default: 'created'
508
- // },
509
- // likes: {
510
- // type: Number,
511
- // default: 0,
512
- // },
513
- // likedBy: {
514
- // type: [mongoose.Schema.Types.ObjectId],
515
- // ref: 'users',
516
- // default: [],
517
- // },
518
-
519
- // buyNowProducts: {
520
- // type: [
521
- // {
522
- // _id: false,
523
- // productId: { type: Schema.Types.ObjectId, ref: "productlistings" },
524
- // productOwnerSellerId: { type: Schema.Types.ObjectId, ref: 'sellers', required: true },
525
- // productPrice: { type: Number, min: 0, default: null },
526
- // },
527
- // ],
528
- // default: [],
529
- // },
530
- // auctionProducts: {
531
- // type: [
532
- // {
533
- // _id: false,
534
- // productId: { type: Schema.Types.ObjectId, ref: "productlistings" },
535
- // productOwnerSellerId: { type: Schema.Types.ObjectId, ref: 'sellers', required: true },
536
- // startingPrice: { type: Number, min: 0, default: null },
537
- // reservedPrice: { type: Number, min: 0, default: null },
538
- // auctionNumber: {
539
- // type: Number,
540
- // },
541
- // // BGA Integration - Reference to BGA auction document
542
- // auctionObjectId: {
543
- // type: Schema.Types.ObjectId,
544
- // required: true,
545
- // index: true
546
- // }
547
- // },
548
- // ],
549
- // default: [],
550
- // },
551
-
552
- // giveawayProducts: {
553
- // type: [giveawayProductSchema],
554
- // default: []
555
- // },
556
-
557
- // // === LIVE FLASH SALE FIELDS (ADD THESE) ===
558
- // liveFlashSales: {
559
- // type: [liveFlashSaleSchema],
560
- // default: [] // This ensures it's always an array
561
- // },
562
- // currentFlashSale: {
563
- // type: Schema.Types.ObjectId,
564
- // ref: 'FlashSale',
565
- // default: null
566
- // },
567
-
568
- // enabledProductTypes: {
569
- // buyNow: { type: Boolean, default: false },
570
- // auction: { type: Boolean, default: false },
571
- // giveaway: { type: Boolean, default: false }
572
- // },
573
- // notes: {
574
- // type: String,
575
- // default: ''
576
- // },
577
- // },
578
- // { timestamps: true }
579
- // );
580
-
581
- // showSchema.pre('save', function (next) {
582
- // const doc = this;
583
-
584
- // // Set liveDrop based on product types
585
- // const hasBuyNow = doc.buyNowProducts && doc.buyNowProducts.length > 0;
586
- // const hasAuction = doc.auctionProducts && doc.auctionProducts.length > 0;
587
- // const hasGiveaway = doc.giveawayProducts && doc.giveawayProducts.length > 0;
588
- // doc.liveDrop = hasBuyNow && hasAuction && hasGiveaway;
589
-
590
- // // Ensure coHost is null if hasCoHost is false
591
- // if (!doc.hasCoHost) {
592
- // doc.coHost = null;
593
- // }
594
-
595
- // next();
596
- // });
597
-
598
- // const Show = mongoose.model("shows", showSchema);
599
-
600
- // export default Show;
601
-
602
-
603
-
1
+ import mongoose from "mongoose";
2
+ const { Schema } = mongoose;
3
+
4
+ const giveawayProductSchema = new Schema({
5
+ _id: false,
6
+ productId: { type: Schema.Types.ObjectId, ref: "productlistings", required: true },
7
+ productOwnerSellerId: { type: Schema.Types.ObjectId, ref: 'sellers', required: true },
8
+ productTitle: { type: String },
9
+ giveawayObjectId: { type: Schema.Types.ObjectId, required: true, index: true },
10
+ giveawayStatus: {
11
+ type: String,
12
+ enum: ['preparing', 'ready', 'active', 'ended', 'failed'],
13
+ default: 'preparing'
14
+ },
15
+ requireAutoFollow: {
16
+ type: Boolean,
17
+ default: false
18
+ },
19
+ activatedAt: { type: Date, default: null },
20
+ createdAt: { type: Date, default: Date.now }
21
+ });
22
+
23
+ const liveFlashSaleSchema = new Schema({
24
+ _id: false,
25
+ productId: {
26
+ type: Schema.Types.ObjectId,
27
+ ref: "productlistings",
28
+ required: true
29
+ },
30
+ stockId: {
31
+ type: Schema.Types.ObjectId,
32
+ ref: "stocks",
33
+ required: true
34
+ },
35
+ flashPrice: {
36
+ type: Number,
37
+ required: true,
38
+ min: 1
39
+ },
40
+ duration: {
41
+ type: Number,
42
+ required: true,
43
+ enum: [10, 20, 30, 40, 50, 60, 240]
44
+ },
45
+ initialStock: {
46
+ type: Number,
47
+ required: true,
48
+ min: 1
49
+ },
50
+ currentStock: {
51
+ type: Number,
52
+ required: true,
53
+ min: 0
54
+ },
55
+ sold: {
56
+ type: Number,
57
+ default: 0
58
+ },
59
+ status: {
60
+ type: String,
61
+ enum: ['scheduled', 'active', 'ended', 'cancelled'],
62
+ default: 'scheduled'
63
+ },
64
+ startTime: Date,
65
+ endTime: Date,
66
+ flashSaleId: {
67
+ type: Schema.Types.ObjectId,
68
+ ref: 'FlashSale'
69
+ },
70
+ createdAt: {
71
+ type: Date,
72
+ default: Date.now
73
+ }
74
+ });
75
+ const bundleSaleSchema = new Schema({
76
+ _id: false,
77
+ bundleSaleId: {
78
+ type: Schema.Types.ObjectId,
79
+ ref: "bundlesales",
80
+ required: true
81
+ },
82
+ bundleOwnerSellerId: {
83
+ type: Schema.Types.ObjectId,
84
+ ref: 'sellers',
85
+ required: function() {
86
+ return this.bundleSaleId != null;
87
+ }
88
+ },
89
+ bundleTitle: { type: String }, // Quick reference title
90
+ bundleMRP: { type: Number, min: 0, default: null }, // Original MRP
91
+ sellingPrice: { type: Number, min: 0, default: null }, // Actual selling price
92
+ bundleImage: { // Bundle thumbnail image
93
+ key: { type: String, default: null },
94
+ url: { type: String, default: null }
95
+ },
96
+ createdAt: { type: Date, default: Date.now }
97
+ });
98
+
99
+ // Show Schema with FIXED validation
100
+ const showSchema = new Schema(
101
+ {
102
+ sellerId: {
103
+ type: mongoose.Schema.Types.ObjectId,
104
+ ref: "sellers",
105
+ },
106
+ host: {
107
+ type: mongoose.Schema.Types.ObjectId,
108
+ required: true,
109
+ refPath: 'hostModel'
110
+ },
111
+ hostModel: {
112
+ type: String,
113
+ required: true,
114
+ enum: ['sellers', 'dropshippers']
115
+ },
116
+ title: {
117
+ type: String,
118
+ required: true,
119
+ },
120
+ date: {
121
+ type: Date,
122
+ },
123
+ time: {
124
+ type: String,
125
+ },
126
+ scheduledAt: {
127
+ type: Date,
128
+ index: true
129
+ },
130
+ category: {
131
+ type: String,
132
+ },
133
+ subCategory: {
134
+ type: String,
135
+ default: '',
136
+ },
137
+ liveStreamId: { type: String, default: null },
138
+ streamName: {
139
+ type: String,
140
+ default: ''
141
+ },
142
+ tags: {
143
+ type: [String],
144
+ default: [],
145
+ },
146
+ thumbnailImage: {
147
+ type: String,
148
+ default: null,
149
+ },
150
+ previewVideo: {
151
+ type: String,
152
+ default: null,
153
+ },
154
+ language: {
155
+ type: String,
156
+ },
157
+ isLive: {
158
+ type: Boolean,
159
+ default: false,
160
+ },
161
+ streamUrl: {
162
+ type: String,
163
+ default: null,
164
+ },
165
+ orientation: {
166
+ type: String,
167
+ enum: ['horizontal', 'vertical'],
168
+ default: 'horizontal'
169
+ },
170
+ layout: {
171
+ type: String,
172
+ enum: ['side-by-side', 'top-bottom'],
173
+ default: 'side-by-side'
174
+ },
175
+ showStatus: {
176
+ type: String,
177
+ enum: ['created', 'live', 'cancelled', 'ended'],
178
+ default: 'created'
179
+ },
180
+ viewerCount: {
181
+ type: Number,
182
+ default: 0,
183
+ min: 0
184
+ },
185
+
186
+ likes: {
187
+ type: Number,
188
+ default: 0,
189
+ },
190
+ likedBy: {
191
+ type: [mongoose.Schema.Types.ObjectId],
192
+ ref: 'users',
193
+ default: [],
194
+ },
195
+
196
+ // ✅ FIXED: Better validation for buyNowProducts
197
+ buyNowProducts: {
198
+ type: [
199
+ {
200
+ _id: false,
201
+ productId: { type: Schema.Types.ObjectId, ref: "productlistings" },
202
+ productOwnerSellerId: {
203
+ type: Schema.Types.ObjectId,
204
+ ref: 'sellers',
205
+ required: function() {
206
+ // Only require if productId exists
207
+ return this.productId != null;
208
+ }
209
+ },
210
+ productPrice: { type: Number, min: 0, default: null },
211
+ },
212
+ ],
213
+ default: [],
214
+ validate: {
215
+ validator: function(products) {
216
+ // Custom validation to ensure productOwnerSellerId exists when productId exists
217
+ return products.every(product =>
218
+ !product.productId || (product.productId && product.productOwnerSellerId)
219
+ );
220
+ },
221
+ message: 'productOwnerSellerId is required when productId is provided'
222
+ }
223
+ },
224
+ bundleSales: {
225
+ type: [bundleSaleSchema],
226
+ default: []
227
+ },
228
+
229
+ auctionProducts: {
230
+ type: [
231
+ {
232
+ _id: false,
233
+ productId: { type: Schema.Types.ObjectId, ref: "productlistings" },
234
+ productOwnerSellerId: {
235
+ type: Schema.Types.ObjectId,
236
+ ref: 'sellers',
237
+ required: function() {
238
+ return this.productId != null;
239
+ }
240
+ },
241
+ startingPrice: { type: Number, min: 0, default: null },
242
+ reservedPrice: { type: Number, min: 0, default: null },
243
+ auctionNumber: {
244
+ type: Number,
245
+ },
246
+ auctionObjectId: {
247
+ type: Schema.Types.ObjectId,
248
+ required: true,
249
+ index: true
250
+ }
251
+ },
252
+ ],
253
+ default: [],
254
+ },
255
+
256
+ giveawayProducts: {
257
+ type: [giveawayProductSchema],
258
+ default: []
259
+ },
260
+
261
+ liveFlashSales: {
262
+ type: [liveFlashSaleSchema],
263
+ default: []
264
+ },
265
+ currentFlashSale: {
266
+ type: Schema.Types.ObjectId,
267
+ ref: 'FlashSale',
268
+ default: null
269
+ },
270
+
271
+ enabledProductTypes: {
272
+ buyNow: { type: Boolean, default: false },
273
+ auction: { type: Boolean, default: false },
274
+ giveaway: { type: Boolean, default: false }
275
+ },
276
+ notes: {
277
+ type: String,
278
+ default: ''
279
+ },
280
+ },
281
+ { timestamps: true }
282
+ );
283
+
284
+ // ✅ ADD THIS PRE-SAVE MIDDLEWARE TO CLEAN INVALID DATA
285
+ showSchema.pre('save', function(next) {
286
+ const doc = this;
287
+
288
+ // Clean up buyNowProducts - remove items without required fields
289
+ if (doc.buyNowProducts && Array.isArray(doc.buyNowProducts)) {
290
+ doc.buyNowProducts = doc.buyNowProducts.filter(product =>
291
+ product &&
292
+ product.productId &&
293
+ product.productOwnerSellerId
294
+ );
295
+ }
296
+
297
+ // Clean up auctionProducts
298
+ if (doc.auctionProducts && Array.isArray(doc.auctionProducts)) {
299
+ doc.auctionProducts = doc.auctionProducts.filter(product =>
300
+ product &&
301
+ product.productId &&
302
+ product.productOwnerSellerId &&
303
+ product.auctionObjectId
304
+ );
305
+ }
306
+
307
+ // Clean up giveawayProducts
308
+ if (doc.giveawayProducts && Array.isArray(doc.giveawayProducts)) {
309
+ doc.giveawayProducts = doc.giveawayProducts.filter(product =>
310
+ product &&
311
+ product.productId &&
312
+ product.productOwnerSellerId &&
313
+ product.giveawayObjectId
314
+ );
315
+ }
316
+
317
+ // Set liveDrop based on product types
318
+ const hasBuyNow = doc.buyNowProducts && doc.buyNowProducts.length > 0;
319
+ const hasAuction = doc.auctionProducts && doc.auctionProducts.length > 0;
320
+ const hasGiveaway = doc.giveawayProducts && doc.giveawayProducts.length > 0;
321
+ doc.liveDrop = hasBuyNow && hasAuction && hasGiveaway;
322
+
323
+ // Ensure coHost is null if hasCoHost is false
324
+ if (!doc.hasCoHost) {
325
+ doc.coHost = null;
326
+ }
327
+
328
+ next();
329
+ });
330
+
331
+ // ✅ ADD THIS PRE-VALIDATION MIDDLEWARE FOR EXTRA SAFETY
332
+ showSchema.pre('validate', function(next) {
333
+ // Ensure all arrays exist (prevent undefined errors)
334
+ if (!this.buyNowProducts) this.buyNowProducts = [];
335
+ if (!this.auctionProducts) this.auctionProducts = [];
336
+ if (!this.giveawayProducts) this.giveawayProducts = [];
337
+ if (!this.liveFlashSales) this.liveFlashSales = [];
338
+
339
+ next();
340
+ });
341
+
342
+ const Show = mongoose.models.shows || mongoose.model("shows", showSchema);
343
+ export default Show;
344
+
345
+
346
+
347
+ // import mongoose from "mongoose";
348
+ // const { Schema } = mongoose;
349
+
350
+ // const giveawayProductSchema = new Schema({
351
+ // _id: false,
352
+ // productId: { type: Schema.Types.ObjectId, ref: "productlistings", required: true },
353
+ // productOwnerSellerId: { type: Schema.Types.ObjectId, ref: 'sellers', required: true },
354
+ // productTitle: { type: String },
355
+ // giveawayObjectId: { type: Schema.Types.ObjectId, required: true, index: true },
356
+ // giveawayStatus: {
357
+ // type: String,
358
+ // enum: ['preparing', 'ready', 'active', 'ended', 'failed'],
359
+ // default: 'preparing'
360
+ // },
361
+ // requireAutoFollow: {
362
+ // type: Boolean,
363
+ // default: false
364
+ // },
365
+ // activatedAt: { type: Date, default: null },
366
+ // createdAt: { type: Date, default: Date.now }
367
+ // });
368
+
369
+ // // Live Flash Sale Schema
370
+ // const liveFlashSaleSchema = new Schema({
371
+ // _id: false,
372
+ // productId: {
373
+ // type: Schema.Types.ObjectId,
374
+ // ref: "productlistings",
375
+ // required: true
376
+ // },
377
+ // stockId: {
378
+ // type: Schema.Types.ObjectId,
379
+ // ref: "stocks",
380
+ // required: true
381
+ // },
382
+ // flashPrice: {
383
+ // type: Number,
384
+ // required: true,
385
+ // min: 1
386
+ // },
387
+ // duration: {
388
+ // type: Number,
389
+ // required: true,
390
+ // enum: [10, 20, 30, 40, 50, 60,240]
391
+ // },
392
+ // initialStock: {
393
+ // type: Number,
394
+ // required: true,
395
+ // min: 1
396
+ // },
397
+ // currentStock: {
398
+ // type: Number,
399
+ // required: true,
400
+ // min: 0
401
+ // },
402
+ // sold: {
403
+ // type: Number,
404
+ // default: 0
405
+ // },
406
+ // status: {
407
+ // type: String,
408
+ // enum: ['scheduled', 'active', 'ended', 'cancelled'],
409
+ // default: 'scheduled'
410
+ // },
411
+ // startTime: Date,
412
+ // endTime: Date,
413
+ // flashSaleId: {
414
+ // type: Schema.Types.ObjectId,
415
+ // ref: 'FlashSale'
416
+ // },
417
+ // createdAt: {
418
+ // type: Date,
419
+ // default: Date.now
420
+ // }
421
+ // });
422
+ // // Show Schema
423
+ // const showSchema = new Schema(
424
+ // {
425
+ // sellerId: {
426
+ // type: mongoose.Schema.Types.ObjectId,
427
+ // ref: "sellers",
428
+ // },
429
+ // // === Host Information ===
430
+ // host: {
431
+ // type: mongoose.Schema.Types.ObjectId,
432
+ // required: true,
433
+ // refPath: 'hostModel'
434
+ // },
435
+ // hostModel: {
436
+ // type: String,
437
+ // required: true,
438
+ // enum: ['sellers', 'dropshippers']
439
+ // },
440
+
441
+ // title: {
442
+ // type: String,
443
+ // required: true,
444
+ // },
445
+ // date: {
446
+ // type: Date,
447
+ // },
448
+ // time: {
449
+ // type: String,
450
+ // },
451
+ // scheduledAt: {
452
+ // type: Date,
453
+ // index: true
454
+ // },
455
+ // category: {
456
+ // type: String,
457
+ // },
458
+ // subCategory: {
459
+ // type: String,
460
+ // default: '',
461
+ // },
462
+ // liveStreamId: { type: String, default: null },
463
+ // streamName: {
464
+ // type: String,
465
+ // default: ''
466
+ // },
467
+ // tags: {
468
+ // type: [String],
469
+ // default: [],
470
+ // },
471
+
472
+ // thumbnailImage: {
473
+ // type: String,
474
+ // default: null,
475
+ // },
476
+ // previewVideo: {
477
+ // type: String,
478
+ // default: null,
479
+ // },
480
+ // language: {
481
+ // type: String,
482
+ // },
483
+ // isLive: {
484
+ // type: Boolean,
485
+ // default: false,
486
+ // },
487
+ // streamUrl: {
488
+ // type: String,
489
+ // default: null,
490
+ // },
491
+
492
+ // // === Stream Layout Configuration ===
493
+ // orientation: {
494
+ // type: String,
495
+ // enum: ['horizontal', 'vertical'],
496
+ // default: 'horizontal'
497
+ // },
498
+ // layout: {
499
+ // type: String,
500
+ // enum: ['side-by-side', 'top-bottom'],
501
+ // default: 'side-by-side'
502
+ // },
503
+
504
+ // showStatus: {
505
+ // type: String,
506
+ // enum: ['created', 'live', 'cancelled', 'ended'],
507
+ // default: 'created'
508
+ // },
509
+ // likes: {
510
+ // type: Number,
511
+ // default: 0,
512
+ // },
513
+ // likedBy: {
514
+ // type: [mongoose.Schema.Types.ObjectId],
515
+ // ref: 'users',
516
+ // default: [],
517
+ // },
518
+
519
+ // buyNowProducts: {
520
+ // type: [
521
+ // {
522
+ // _id: false,
523
+ // productId: { type: Schema.Types.ObjectId, ref: "productlistings" },
524
+ // productOwnerSellerId: { type: Schema.Types.ObjectId, ref: 'sellers', required: true },
525
+ // productPrice: { type: Number, min: 0, default: null },
526
+ // },
527
+ // ],
528
+ // default: [],
529
+ // },
530
+ // auctionProducts: {
531
+ // type: [
532
+ // {
533
+ // _id: false,
534
+ // productId: { type: Schema.Types.ObjectId, ref: "productlistings" },
535
+ // productOwnerSellerId: { type: Schema.Types.ObjectId, ref: 'sellers', required: true },
536
+ // startingPrice: { type: Number, min: 0, default: null },
537
+ // reservedPrice: { type: Number, min: 0, default: null },
538
+ // auctionNumber: {
539
+ // type: Number,
540
+ // },
541
+ // // BGA Integration - Reference to BGA auction document
542
+ // auctionObjectId: {
543
+ // type: Schema.Types.ObjectId,
544
+ // required: true,
545
+ // index: true
546
+ // }
547
+ // },
548
+ // ],
549
+ // default: [],
550
+ // },
551
+
552
+ // giveawayProducts: {
553
+ // type: [giveawayProductSchema],
554
+ // default: []
555
+ // },
556
+
557
+ // // === LIVE FLASH SALE FIELDS (ADD THESE) ===
558
+ // liveFlashSales: {
559
+ // type: [liveFlashSaleSchema],
560
+ // default: [] // This ensures it's always an array
561
+ // },
562
+ // currentFlashSale: {
563
+ // type: Schema.Types.ObjectId,
564
+ // ref: 'FlashSale',
565
+ // default: null
566
+ // },
567
+
568
+ // enabledProductTypes: {
569
+ // buyNow: { type: Boolean, default: false },
570
+ // auction: { type: Boolean, default: false },
571
+ // giveaway: { type: Boolean, default: false }
572
+ // },
573
+ // notes: {
574
+ // type: String,
575
+ // default: ''
576
+ // },
577
+ // },
578
+ // { timestamps: true }
579
+ // );
580
+
581
+ // showSchema.pre('save', function (next) {
582
+ // const doc = this;
583
+
584
+ // // Set liveDrop based on product types
585
+ // const hasBuyNow = doc.buyNowProducts && doc.buyNowProducts.length > 0;
586
+ // const hasAuction = doc.auctionProducts && doc.auctionProducts.length > 0;
587
+ // const hasGiveaway = doc.giveawayProducts && doc.giveawayProducts.length > 0;
588
+ // doc.liveDrop = hasBuyNow && hasAuction && hasGiveaway;
589
+
590
+ // // Ensure coHost is null if hasCoHost is false
591
+ // if (!doc.hasCoHost) {
592
+ // doc.coHost = null;
593
+ // }
594
+
595
+ // next();
596
+ // });
597
+
598
+ // const Show = mongoose.model("shows", showSchema);
599
+
600
+ // export default Show;
601
+
602
+
603
+