flykup_model_development 3.1.75 → 3.1.77

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 (43) 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 +39 -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 +129 -129
  26. package/models/order.modal.js +386 -386
  27. package/models/orderPayment.model.js +234 -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 +604 -604
  38. package/models/stock.model.js +105 -105
  39. package/models/ticket.model.js +115 -115
  40. package/package.json +19 -19
  41. package/test.html +11 -11
  42. package/models/seller_settlements_2025-11-18 (1).csv +0 -4
  43. package/models/seller_settlements_2025-11-18.csv +0 -4
@@ -1,604 +1,604 @@
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
- ],
214
- default: [],
215
- validate: {
216
- validator: function(products) {
217
- // Custom validation to ensure productOwnerSellerId exists when productId exists
218
- return products.every(product =>
219
- !product.productId || (product.productId && product.productOwnerSellerId)
220
- );
221
- },
222
- message: 'productOwnerSellerId is required when productId is provided'
223
- }
224
- },
225
- bundleSales: {
226
- type: [bundleSaleSchema],
227
- default: []
228
- },
229
-
230
- auctionProducts: {
231
- type: [
232
- {
233
- _id: false,
234
- productId: { type: Schema.Types.ObjectId, ref: "productlistings" },
235
- productOwnerSellerId: {
236
- type: Schema.Types.ObjectId,
237
- ref: 'sellers',
238
- required: function() {
239
- return this.productId != null;
240
- }
241
- },
242
- startingPrice: { type: Number, min: 0, default: null },
243
- reservedPrice: { type: Number, min: 0, default: null },
244
- auctionNumber: {
245
- type: Number,
246
- },
247
- auctionObjectId: {
248
- type: Schema.Types.ObjectId,
249
- required: true,
250
- index: true
251
- }
252
- },
253
- ],
254
- default: [],
255
- },
256
-
257
- giveawayProducts: {
258
- type: [giveawayProductSchema],
259
- default: []
260
- },
261
-
262
- liveFlashSales: {
263
- type: [liveFlashSaleSchema],
264
- default: []
265
- },
266
- currentFlashSale: {
267
- type: Schema.Types.ObjectId,
268
- ref: 'FlashSale',
269
- default: null
270
- },
271
-
272
- enabledProductTypes: {
273
- buyNow: { type: Boolean, default: false },
274
- auction: { type: Boolean, default: false },
275
- giveaway: { type: Boolean, default: false }
276
- },
277
- notes: {
278
- type: String,
279
- default: ''
280
- },
281
- },
282
- { timestamps: true }
283
- );
284
-
285
- // ✅ ADD THIS PRE-SAVE MIDDLEWARE TO CLEAN INVALID DATA
286
- showSchema.pre('save', function(next) {
287
- const doc = this;
288
-
289
- // Clean up buyNowProducts - remove items without required fields
290
- if (doc.buyNowProducts && Array.isArray(doc.buyNowProducts)) {
291
- doc.buyNowProducts = doc.buyNowProducts.filter(product =>
292
- product &&
293
- product.productId &&
294
- product.productOwnerSellerId
295
- );
296
- }
297
-
298
- // Clean up auctionProducts
299
- if (doc.auctionProducts && Array.isArray(doc.auctionProducts)) {
300
- doc.auctionProducts = doc.auctionProducts.filter(product =>
301
- product &&
302
- product.productId &&
303
- product.productOwnerSellerId &&
304
- product.auctionObjectId
305
- );
306
- }
307
-
308
- // Clean up giveawayProducts
309
- if (doc.giveawayProducts && Array.isArray(doc.giveawayProducts)) {
310
- doc.giveawayProducts = doc.giveawayProducts.filter(product =>
311
- product &&
312
- product.productId &&
313
- product.productOwnerSellerId &&
314
- product.giveawayObjectId
315
- );
316
- }
317
-
318
- // Set liveDrop based on product types
319
- const hasBuyNow = doc.buyNowProducts && doc.buyNowProducts.length > 0;
320
- const hasAuction = doc.auctionProducts && doc.auctionProducts.length > 0;
321
- const hasGiveaway = doc.giveawayProducts && doc.giveawayProducts.length > 0;
322
- doc.liveDrop = hasBuyNow && hasAuction && hasGiveaway;
323
-
324
- // Ensure coHost is null if hasCoHost is false
325
- if (!doc.hasCoHost) {
326
- doc.coHost = null;
327
- }
328
-
329
- next();
330
- });
331
-
332
- // ✅ ADD THIS PRE-VALIDATION MIDDLEWARE FOR EXTRA SAFETY
333
- showSchema.pre('validate', function(next) {
334
- // Ensure all arrays exist (prevent undefined errors)
335
- if (!this.buyNowProducts) this.buyNowProducts = [];
336
- if (!this.auctionProducts) this.auctionProducts = [];
337
- if (!this.giveawayProducts) this.giveawayProducts = [];
338
- if (!this.liveFlashSales) this.liveFlashSales = [];
339
-
340
- next();
341
- });
342
-
343
- const Show = mongoose.models.shows || mongoose.model("shows", showSchema);
344
- export default Show;
345
-
346
-
347
-
348
- // import mongoose from "mongoose";
349
- // const { Schema } = mongoose;
350
-
351
- // const giveawayProductSchema = new Schema({
352
- // _id: false,
353
- // productId: { type: Schema.Types.ObjectId, ref: "productlistings", required: true },
354
- // productOwnerSellerId: { type: Schema.Types.ObjectId, ref: 'sellers', required: true },
355
- // productTitle: { type: String },
356
- // giveawayObjectId: { type: Schema.Types.ObjectId, required: true, index: true },
357
- // giveawayStatus: {
358
- // type: String,
359
- // enum: ['preparing', 'ready', 'active', 'ended', 'failed'],
360
- // default: 'preparing'
361
- // },
362
- // requireAutoFollow: {
363
- // type: Boolean,
364
- // default: false
365
- // },
366
- // activatedAt: { type: Date, default: null },
367
- // createdAt: { type: Date, default: Date.now }
368
- // });
369
-
370
- // // Live Flash Sale Schema
371
- // const liveFlashSaleSchema = new Schema({
372
- // _id: false,
373
- // productId: {
374
- // type: Schema.Types.ObjectId,
375
- // ref: "productlistings",
376
- // required: true
377
- // },
378
- // stockId: {
379
- // type: Schema.Types.ObjectId,
380
- // ref: "stocks",
381
- // required: true
382
- // },
383
- // flashPrice: {
384
- // type: Number,
385
- // required: true,
386
- // min: 1
387
- // },
388
- // duration: {
389
- // type: Number,
390
- // required: true,
391
- // enum: [10, 20, 30, 40, 50, 60,240]
392
- // },
393
- // initialStock: {
394
- // type: Number,
395
- // required: true,
396
- // min: 1
397
- // },
398
- // currentStock: {
399
- // type: Number,
400
- // required: true,
401
- // min: 0
402
- // },
403
- // sold: {
404
- // type: Number,
405
- // default: 0
406
- // },
407
- // status: {
408
- // type: String,
409
- // enum: ['scheduled', 'active', 'ended', 'cancelled'],
410
- // default: 'scheduled'
411
- // },
412
- // startTime: Date,
413
- // endTime: Date,
414
- // flashSaleId: {
415
- // type: Schema.Types.ObjectId,
416
- // ref: 'FlashSale'
417
- // },
418
- // createdAt: {
419
- // type: Date,
420
- // default: Date.now
421
- // }
422
- // });
423
- // // Show Schema
424
- // const showSchema = new Schema(
425
- // {
426
- // sellerId: {
427
- // type: mongoose.Schema.Types.ObjectId,
428
- // ref: "sellers",
429
- // },
430
- // // === Host Information ===
431
- // host: {
432
- // type: mongoose.Schema.Types.ObjectId,
433
- // required: true,
434
- // refPath: 'hostModel'
435
- // },
436
- // hostModel: {
437
- // type: String,
438
- // required: true,
439
- // enum: ['sellers', 'dropshippers']
440
- // },
441
-
442
- // title: {
443
- // type: String,
444
- // required: true,
445
- // },
446
- // date: {
447
- // type: Date,
448
- // },
449
- // time: {
450
- // type: String,
451
- // },
452
- // scheduledAt: {
453
- // type: Date,
454
- // index: true
455
- // },
456
- // category: {
457
- // type: String,
458
- // },
459
- // subCategory: {
460
- // type: String,
461
- // default: '',
462
- // },
463
- // liveStreamId: { type: String, default: null },
464
- // streamName: {
465
- // type: String,
466
- // default: ''
467
- // },
468
- // tags: {
469
- // type: [String],
470
- // default: [],
471
- // },
472
-
473
- // thumbnailImage: {
474
- // type: String,
475
- // default: null,
476
- // },
477
- // previewVideo: {
478
- // type: String,
479
- // default: null,
480
- // },
481
- // language: {
482
- // type: String,
483
- // },
484
- // isLive: {
485
- // type: Boolean,
486
- // default: false,
487
- // },
488
- // streamUrl: {
489
- // type: String,
490
- // default: null,
491
- // },
492
-
493
- // // === Stream Layout Configuration ===
494
- // orientation: {
495
- // type: String,
496
- // enum: ['horizontal', 'vertical'],
497
- // default: 'horizontal'
498
- // },
499
- // layout: {
500
- // type: String,
501
- // enum: ['side-by-side', 'top-bottom'],
502
- // default: 'side-by-side'
503
- // },
504
-
505
- // showStatus: {
506
- // type: String,
507
- // enum: ['created', 'live', 'cancelled', 'ended'],
508
- // default: 'created'
509
- // },
510
- // likes: {
511
- // type: Number,
512
- // default: 0,
513
- // },
514
- // likedBy: {
515
- // type: [mongoose.Schema.Types.ObjectId],
516
- // ref: 'users',
517
- // default: [],
518
- // },
519
-
520
- // buyNowProducts: {
521
- // type: [
522
- // {
523
- // _id: false,
524
- // productId: { type: Schema.Types.ObjectId, ref: "productlistings" },
525
- // productOwnerSellerId: { type: Schema.Types.ObjectId, ref: 'sellers', required: true },
526
- // productPrice: { type: Number, min: 0, default: null },
527
- // },
528
- // ],
529
- // default: [],
530
- // },
531
- // auctionProducts: {
532
- // type: [
533
- // {
534
- // _id: false,
535
- // productId: { type: Schema.Types.ObjectId, ref: "productlistings" },
536
- // productOwnerSellerId: { type: Schema.Types.ObjectId, ref: 'sellers', required: true },
537
- // startingPrice: { type: Number, min: 0, default: null },
538
- // reservedPrice: { type: Number, min: 0, default: null },
539
- // auctionNumber: {
540
- // type: Number,
541
- // },
542
- // // BGA Integration - Reference to BGA auction document
543
- // auctionObjectId: {
544
- // type: Schema.Types.ObjectId,
545
- // required: true,
546
- // index: true
547
- // }
548
- // },
549
- // ],
550
- // default: [],
551
- // },
552
-
553
- // giveawayProducts: {
554
- // type: [giveawayProductSchema],
555
- // default: []
556
- // },
557
-
558
- // // === LIVE FLASH SALE FIELDS (ADD THESE) ===
559
- // liveFlashSales: {
560
- // type: [liveFlashSaleSchema],
561
- // default: [] // This ensures it's always an array
562
- // },
563
- // currentFlashSale: {
564
- // type: Schema.Types.ObjectId,
565
- // ref: 'FlashSale',
566
- // default: null
567
- // },
568
-
569
- // enabledProductTypes: {
570
- // buyNow: { type: Boolean, default: false },
571
- // auction: { type: Boolean, default: false },
572
- // giveaway: { type: Boolean, default: false }
573
- // },
574
- // notes: {
575
- // type: String,
576
- // default: ''
577
- // },
578
- // },
579
- // { timestamps: true }
580
- // );
581
-
582
- // showSchema.pre('save', function (next) {
583
- // const doc = this;
584
-
585
- // // Set liveDrop based on product types
586
- // const hasBuyNow = doc.buyNowProducts && doc.buyNowProducts.length > 0;
587
- // const hasAuction = doc.auctionProducts && doc.auctionProducts.length > 0;
588
- // const hasGiveaway = doc.giveawayProducts && doc.giveawayProducts.length > 0;
589
- // doc.liveDrop = hasBuyNow && hasAuction && hasGiveaway;
590
-
591
- // // Ensure coHost is null if hasCoHost is false
592
- // if (!doc.hasCoHost) {
593
- // doc.coHost = null;
594
- // }
595
-
596
- // next();
597
- // });
598
-
599
- // const Show = mongoose.model("shows", showSchema);
600
-
601
- // export default Show;
602
-
603
-
604
-
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 },
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
+ ],
214
+ default: [],
215
+ validate: {
216
+ validator: function(products) {
217
+ // Custom validation to ensure productOwnerSellerId exists when productId exists
218
+ return products.every(product =>
219
+ !product.productId || (product.productId && product.productOwnerSellerId)
220
+ );
221
+ },
222
+ message: 'productOwnerSellerId is required when productId is provided'
223
+ }
224
+ },
225
+ bundleSales: {
226
+ type: [bundleSaleSchema],
227
+ default: []
228
+ },
229
+
230
+ auctionProducts: {
231
+ type: [
232
+ {
233
+ _id: false,
234
+ productId: { type: Schema.Types.ObjectId, ref: "productlistings" },
235
+ productOwnerSellerId: {
236
+ type: Schema.Types.ObjectId,
237
+ ref: 'sellers',
238
+ required: function() {
239
+ return this.productId != null;
240
+ }
241
+ },
242
+ startingPrice: { type: Number, min: 0, default: null },
243
+ reservedPrice: { type: Number, min: 0, default: null },
244
+ auctionNumber: {
245
+ type: Number,
246
+ },
247
+ auctionObjectId: {
248
+ type: Schema.Types.ObjectId,
249
+ required: true,
250
+ index: true
251
+ }
252
+ },
253
+ ],
254
+ default: [],
255
+ },
256
+
257
+ giveawayProducts: {
258
+ type: [giveawayProductSchema],
259
+ default: []
260
+ },
261
+
262
+ liveFlashSales: {
263
+ type: [liveFlashSaleSchema],
264
+ default: []
265
+ },
266
+ currentFlashSale: {
267
+ type: Schema.Types.ObjectId,
268
+ ref: 'FlashSale',
269
+ default: null
270
+ },
271
+
272
+ enabledProductTypes: {
273
+ buyNow: { type: Boolean, default: false },
274
+ auction: { type: Boolean, default: false },
275
+ giveaway: { type: Boolean, default: false }
276
+ },
277
+ notes: {
278
+ type: String,
279
+ default: ''
280
+ },
281
+ },
282
+ { timestamps: true }
283
+ );
284
+
285
+ // ✅ ADD THIS PRE-SAVE MIDDLEWARE TO CLEAN INVALID DATA
286
+ showSchema.pre('save', function(next) {
287
+ const doc = this;
288
+
289
+ // Clean up buyNowProducts - remove items without required fields
290
+ if (doc.buyNowProducts && Array.isArray(doc.buyNowProducts)) {
291
+ doc.buyNowProducts = doc.buyNowProducts.filter(product =>
292
+ product &&
293
+ product.productId &&
294
+ product.productOwnerSellerId
295
+ );
296
+ }
297
+
298
+ // Clean up auctionProducts
299
+ if (doc.auctionProducts && Array.isArray(doc.auctionProducts)) {
300
+ doc.auctionProducts = doc.auctionProducts.filter(product =>
301
+ product &&
302
+ product.productId &&
303
+ product.productOwnerSellerId &&
304
+ product.auctionObjectId
305
+ );
306
+ }
307
+
308
+ // Clean up giveawayProducts
309
+ if (doc.giveawayProducts && Array.isArray(doc.giveawayProducts)) {
310
+ doc.giveawayProducts = doc.giveawayProducts.filter(product =>
311
+ product &&
312
+ product.productId &&
313
+ product.productOwnerSellerId &&
314
+ product.giveawayObjectId
315
+ );
316
+ }
317
+
318
+ // Set liveDrop based on product types
319
+ const hasBuyNow = doc.buyNowProducts && doc.buyNowProducts.length > 0;
320
+ const hasAuction = doc.auctionProducts && doc.auctionProducts.length > 0;
321
+ const hasGiveaway = doc.giveawayProducts && doc.giveawayProducts.length > 0;
322
+ doc.liveDrop = hasBuyNow && hasAuction && hasGiveaway;
323
+
324
+ // Ensure coHost is null if hasCoHost is false
325
+ if (!doc.hasCoHost) {
326
+ doc.coHost = null;
327
+ }
328
+
329
+ next();
330
+ });
331
+
332
+ // ✅ ADD THIS PRE-VALIDATION MIDDLEWARE FOR EXTRA SAFETY
333
+ showSchema.pre('validate', function(next) {
334
+ // Ensure all arrays exist (prevent undefined errors)
335
+ if (!this.buyNowProducts) this.buyNowProducts = [];
336
+ if (!this.auctionProducts) this.auctionProducts = [];
337
+ if (!this.giveawayProducts) this.giveawayProducts = [];
338
+ if (!this.liveFlashSales) this.liveFlashSales = [];
339
+
340
+ next();
341
+ });
342
+
343
+ const Show = mongoose.models.shows || mongoose.model("shows", showSchema);
344
+ export default Show;
345
+
346
+
347
+
348
+ // import mongoose from "mongoose";
349
+ // const { Schema } = mongoose;
350
+
351
+ // const giveawayProductSchema = new Schema({
352
+ // _id: false,
353
+ // productId: { type: Schema.Types.ObjectId, ref: "productlistings", required: true },
354
+ // productOwnerSellerId: { type: Schema.Types.ObjectId, ref: 'sellers', required: true },
355
+ // productTitle: { type: String },
356
+ // giveawayObjectId: { type: Schema.Types.ObjectId, required: true, index: true },
357
+ // giveawayStatus: {
358
+ // type: String,
359
+ // enum: ['preparing', 'ready', 'active', 'ended', 'failed'],
360
+ // default: 'preparing'
361
+ // },
362
+ // requireAutoFollow: {
363
+ // type: Boolean,
364
+ // default: false
365
+ // },
366
+ // activatedAt: { type: Date, default: null },
367
+ // createdAt: { type: Date, default: Date.now }
368
+ // });
369
+
370
+ // // Live Flash Sale Schema
371
+ // const liveFlashSaleSchema = new Schema({
372
+ // _id: false,
373
+ // productId: {
374
+ // type: Schema.Types.ObjectId,
375
+ // ref: "productlistings",
376
+ // required: true
377
+ // },
378
+ // stockId: {
379
+ // type: Schema.Types.ObjectId,
380
+ // ref: "stocks",
381
+ // required: true
382
+ // },
383
+ // flashPrice: {
384
+ // type: Number,
385
+ // required: true,
386
+ // min: 1
387
+ // },
388
+ // duration: {
389
+ // type: Number,
390
+ // required: true,
391
+ // enum: [10, 20, 30, 40, 50, 60,240]
392
+ // },
393
+ // initialStock: {
394
+ // type: Number,
395
+ // required: true,
396
+ // min: 1
397
+ // },
398
+ // currentStock: {
399
+ // type: Number,
400
+ // required: true,
401
+ // min: 0
402
+ // },
403
+ // sold: {
404
+ // type: Number,
405
+ // default: 0
406
+ // },
407
+ // status: {
408
+ // type: String,
409
+ // enum: ['scheduled', 'active', 'ended', 'cancelled'],
410
+ // default: 'scheduled'
411
+ // },
412
+ // startTime: Date,
413
+ // endTime: Date,
414
+ // flashSaleId: {
415
+ // type: Schema.Types.ObjectId,
416
+ // ref: 'FlashSale'
417
+ // },
418
+ // createdAt: {
419
+ // type: Date,
420
+ // default: Date.now
421
+ // }
422
+ // });
423
+ // // Show Schema
424
+ // const showSchema = new Schema(
425
+ // {
426
+ // sellerId: {
427
+ // type: mongoose.Schema.Types.ObjectId,
428
+ // ref: "sellers",
429
+ // },
430
+ // // === Host Information ===
431
+ // host: {
432
+ // type: mongoose.Schema.Types.ObjectId,
433
+ // required: true,
434
+ // refPath: 'hostModel'
435
+ // },
436
+ // hostModel: {
437
+ // type: String,
438
+ // required: true,
439
+ // enum: ['sellers', 'dropshippers']
440
+ // },
441
+
442
+ // title: {
443
+ // type: String,
444
+ // required: true,
445
+ // },
446
+ // date: {
447
+ // type: Date,
448
+ // },
449
+ // time: {
450
+ // type: String,
451
+ // },
452
+ // scheduledAt: {
453
+ // type: Date,
454
+ // index: true
455
+ // },
456
+ // category: {
457
+ // type: String,
458
+ // },
459
+ // subCategory: {
460
+ // type: String,
461
+ // default: '',
462
+ // },
463
+ // liveStreamId: { type: String, default: null },
464
+ // streamName: {
465
+ // type: String,
466
+ // default: ''
467
+ // },
468
+ // tags: {
469
+ // type: [String],
470
+ // default: [],
471
+ // },
472
+
473
+ // thumbnailImage: {
474
+ // type: String,
475
+ // default: null,
476
+ // },
477
+ // previewVideo: {
478
+ // type: String,
479
+ // default: null,
480
+ // },
481
+ // language: {
482
+ // type: String,
483
+ // },
484
+ // isLive: {
485
+ // type: Boolean,
486
+ // default: false,
487
+ // },
488
+ // streamUrl: {
489
+ // type: String,
490
+ // default: null,
491
+ // },
492
+
493
+ // // === Stream Layout Configuration ===
494
+ // orientation: {
495
+ // type: String,
496
+ // enum: ['horizontal', 'vertical'],
497
+ // default: 'horizontal'
498
+ // },
499
+ // layout: {
500
+ // type: String,
501
+ // enum: ['side-by-side', 'top-bottom'],
502
+ // default: 'side-by-side'
503
+ // },
504
+
505
+ // showStatus: {
506
+ // type: String,
507
+ // enum: ['created', 'live', 'cancelled', 'ended'],
508
+ // default: 'created'
509
+ // },
510
+ // likes: {
511
+ // type: Number,
512
+ // default: 0,
513
+ // },
514
+ // likedBy: {
515
+ // type: [mongoose.Schema.Types.ObjectId],
516
+ // ref: 'users',
517
+ // default: [],
518
+ // },
519
+
520
+ // buyNowProducts: {
521
+ // type: [
522
+ // {
523
+ // _id: false,
524
+ // productId: { type: Schema.Types.ObjectId, ref: "productlistings" },
525
+ // productOwnerSellerId: { type: Schema.Types.ObjectId, ref: 'sellers', required: true },
526
+ // productPrice: { type: Number, min: 0, default: null },
527
+ // },
528
+ // ],
529
+ // default: [],
530
+ // },
531
+ // auctionProducts: {
532
+ // type: [
533
+ // {
534
+ // _id: false,
535
+ // productId: { type: Schema.Types.ObjectId, ref: "productlistings" },
536
+ // productOwnerSellerId: { type: Schema.Types.ObjectId, ref: 'sellers', required: true },
537
+ // startingPrice: { type: Number, min: 0, default: null },
538
+ // reservedPrice: { type: Number, min: 0, default: null },
539
+ // auctionNumber: {
540
+ // type: Number,
541
+ // },
542
+ // // BGA Integration - Reference to BGA auction document
543
+ // auctionObjectId: {
544
+ // type: Schema.Types.ObjectId,
545
+ // required: true,
546
+ // index: true
547
+ // }
548
+ // },
549
+ // ],
550
+ // default: [],
551
+ // },
552
+
553
+ // giveawayProducts: {
554
+ // type: [giveawayProductSchema],
555
+ // default: []
556
+ // },
557
+
558
+ // // === LIVE FLASH SALE FIELDS (ADD THESE) ===
559
+ // liveFlashSales: {
560
+ // type: [liveFlashSaleSchema],
561
+ // default: [] // This ensures it's always an array
562
+ // },
563
+ // currentFlashSale: {
564
+ // type: Schema.Types.ObjectId,
565
+ // ref: 'FlashSale',
566
+ // default: null
567
+ // },
568
+
569
+ // enabledProductTypes: {
570
+ // buyNow: { type: Boolean, default: false },
571
+ // auction: { type: Boolean, default: false },
572
+ // giveaway: { type: Boolean, default: false }
573
+ // },
574
+ // notes: {
575
+ // type: String,
576
+ // default: ''
577
+ // },
578
+ // },
579
+ // { timestamps: true }
580
+ // );
581
+
582
+ // showSchema.pre('save', function (next) {
583
+ // const doc = this;
584
+
585
+ // // Set liveDrop based on product types
586
+ // const hasBuyNow = doc.buyNowProducts && doc.buyNowProducts.length > 0;
587
+ // const hasAuction = doc.auctionProducts && doc.auctionProducts.length > 0;
588
+ // const hasGiveaway = doc.giveawayProducts && doc.giveawayProducts.length > 0;
589
+ // doc.liveDrop = hasBuyNow && hasAuction && hasGiveaway;
590
+
591
+ // // Ensure coHost is null if hasCoHost is false
592
+ // if (!doc.hasCoHost) {
593
+ // doc.coHost = null;
594
+ // }
595
+
596
+ // next();
597
+ // });
598
+
599
+ // const Show = mongoose.model("shows", showSchema);
600
+
601
+ // export default Show;
602
+
603
+
604
+