flykup_model_development 3.1.74 → 3.1.76
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/.gitattributes +2 -0
- package/.github/workflows/main.yml +30 -0
- package/.github/workflows/publish.yml +31 -0
- package/auth.js +14 -14
- package/config.js +1 -1
- package/db_connection.js +23 -23
- package/index.js +140 -140
- package/models/AadhaarVerification.js +131 -131
- package/models/AdminEmail.model.js +39 -38
- package/models/BankVerification.js +92 -92
- package/models/GSTVerification.js +89 -89
- package/models/LiveStreamInteraction.model.js +101 -101
- package/models/ProductInteraction.model.js +108 -108
- package/models/Review.model.js +121 -121
- package/models/SearchAnalytics.js +23 -23
- package/models/ShoppableInteraction.model.js +106 -106
- package/models/Wishlist.model.js +29 -29
- package/models/admin.model.js +42 -42
- package/models/appUpdate.model.js +19 -19
- package/models/assets.model.js +32 -32
- package/models/blockedRegion.models.js +27 -27
- package/models/chat.model.js +511 -511
- package/models/coHostInvitation.model.js +60 -60
- package/models/follow.model.js +38 -38
- package/models/loginlogs.model.js +26 -26
- package/models/notification.model.js +129 -129
- package/models/order.modal.js +386 -385
- package/models/orderPayment.model.js +218 -218
- package/models/productListing.model.js +322 -322
- package/models/profileInteractions.model.js +44 -44
- package/models/registerShow.model.js +29 -29
- package/models/sellerDraft.model.js +27 -27
- package/models/shipper.model.js +126 -126
- package/models/shoppableVideo.model.js +237 -237
- package/models/shoppableVideoComment.model.js +57 -57
- package/models/shoppableVideoLike.model.js +29 -29
- package/models/shoppableVideoSave.model.js +27 -27
- package/models/shows.model.js +604 -604
- package/models/stock.model.js +105 -105
- package/models/ticket.model.js +115 -115
- package/package.json +19 -19
- package/test.html +11 -11
package/models/Review.model.js
CHANGED
|
@@ -1,121 +1,121 @@
|
|
|
1
|
-
import mongoose from "mongoose";
|
|
2
|
-
const { Schema } = mongoose;
|
|
3
|
-
|
|
4
|
-
// Define the ReviewType enum
|
|
5
|
-
const ReviewType = {
|
|
6
|
-
PRODUCT: "product",
|
|
7
|
-
SELLER: "seller"
|
|
8
|
-
};
|
|
9
|
-
|
|
10
|
-
const ReviewSchema = new Schema(
|
|
11
|
-
{
|
|
12
|
-
userId: {
|
|
13
|
-
type: Schema.Types.ObjectId,
|
|
14
|
-
ref: "users",
|
|
15
|
-
required: true
|
|
16
|
-
},
|
|
17
|
-
reviewType: {
|
|
18
|
-
type: String,
|
|
19
|
-
enum: Object.values(ReviewType),
|
|
20
|
-
required: true
|
|
21
|
-
},
|
|
22
|
-
productId: {
|
|
23
|
-
type: Schema.Types.ObjectId,
|
|
24
|
-
ref: "productlistings",
|
|
25
|
-
required: function() {
|
|
26
|
-
return this.reviewType === ReviewType.PRODUCT;
|
|
27
|
-
}
|
|
28
|
-
},
|
|
29
|
-
sellerId: {
|
|
30
|
-
type: Schema.Types.ObjectId,
|
|
31
|
-
ref: "sellers",
|
|
32
|
-
required: function() {
|
|
33
|
-
return this.reviewType === ReviewType.SELLER;
|
|
34
|
-
}
|
|
35
|
-
},
|
|
36
|
-
rating: {
|
|
37
|
-
type: Number,
|
|
38
|
-
required: true,
|
|
39
|
-
min: 1,
|
|
40
|
-
max: 5
|
|
41
|
-
},
|
|
42
|
-
content: {
|
|
43
|
-
type: String,
|
|
44
|
-
required: true,
|
|
45
|
-
trim: true,
|
|
46
|
-
maxlength: 1000
|
|
47
|
-
},
|
|
48
|
-
helpfulVotes: {
|
|
49
|
-
type: [{
|
|
50
|
-
userId: {
|
|
51
|
-
type: Schema.Types.ObjectId,
|
|
52
|
-
ref: "users",
|
|
53
|
-
required: true
|
|
54
|
-
},
|
|
55
|
-
voteType: {
|
|
56
|
-
type: String,
|
|
57
|
-
enum: ["helpful", "not_helpful"],
|
|
58
|
-
required: true
|
|
59
|
-
},
|
|
60
|
-
createdAt: {
|
|
61
|
-
type: Date,
|
|
62
|
-
default: Date.now
|
|
63
|
-
}
|
|
64
|
-
}],
|
|
65
|
-
default: []
|
|
66
|
-
},
|
|
67
|
-
|
|
68
|
-
helpfulCount: {
|
|
69
|
-
type: Number,
|
|
70
|
-
default: 0,
|
|
71
|
-
min: 0
|
|
72
|
-
},
|
|
73
|
-
notHelpfulCount: {
|
|
74
|
-
type: Number,
|
|
75
|
-
default: 0,
|
|
76
|
-
min: 0
|
|
77
|
-
},
|
|
78
|
-
images: {
|
|
79
|
-
type: [String], // Array of image URLs
|
|
80
|
-
default: [],
|
|
81
|
-
validate: {
|
|
82
|
-
validator: function(array) {
|
|
83
|
-
return array.length <= 5;
|
|
84
|
-
},
|
|
85
|
-
message: 'Cannot upload more than 5 images per review'
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
},
|
|
89
|
-
{
|
|
90
|
-
timestamps: true,
|
|
91
|
-
toJSON: { virtuals: true },
|
|
92
|
-
toObject: { virtuals: true }
|
|
93
|
-
}
|
|
94
|
-
);
|
|
95
|
-
|
|
96
|
-
// Indexes
|
|
97
|
-
ReviewSchema.index({ productId: 1 });
|
|
98
|
-
ReviewSchema.index({ sellerId: 1 });
|
|
99
|
-
ReviewSchema.index({ userId: 1 });
|
|
100
|
-
ReviewSchema.index({ reviewType: 1 });
|
|
101
|
-
ReviewSchema.index({ "helpfulVotes.userId": 1 });
|
|
102
|
-
|
|
103
|
-
// Virtual for total feedback count
|
|
104
|
-
ReviewSchema.virtual('totalFeedback').get(function() {
|
|
105
|
-
return this.helpfulCount + this.notHelpfulCount;
|
|
106
|
-
});
|
|
107
|
-
|
|
108
|
-
// Method to check if a user has voted
|
|
109
|
-
ReviewSchema.methods.hasUserVoted = function(userId) {
|
|
110
|
-
return this.helpfulVotes.some(vote => vote.userId.equals(userId));
|
|
111
|
-
};
|
|
112
|
-
|
|
113
|
-
// Method to get user's vote type
|
|
114
|
-
ReviewSchema.methods.getUserVoteType = function(userId) {
|
|
115
|
-
const vote = this.helpfulVotes.find(vote => vote.userId.equals(userId));
|
|
116
|
-
return vote ? vote.voteType : null;
|
|
117
|
-
};
|
|
118
|
-
|
|
119
|
-
// Safe export to prevent OverwriteModelError
|
|
120
|
-
const Review = mongoose.models.reviews || mongoose.model("reviews", ReviewSchema);
|
|
121
|
-
export { Review, ReviewType };
|
|
1
|
+
import mongoose from "mongoose";
|
|
2
|
+
const { Schema } = mongoose;
|
|
3
|
+
|
|
4
|
+
// Define the ReviewType enum
|
|
5
|
+
const ReviewType = {
|
|
6
|
+
PRODUCT: "product",
|
|
7
|
+
SELLER: "seller"
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
const ReviewSchema = new Schema(
|
|
11
|
+
{
|
|
12
|
+
userId: {
|
|
13
|
+
type: Schema.Types.ObjectId,
|
|
14
|
+
ref: "users",
|
|
15
|
+
required: true
|
|
16
|
+
},
|
|
17
|
+
reviewType: {
|
|
18
|
+
type: String,
|
|
19
|
+
enum: Object.values(ReviewType),
|
|
20
|
+
required: true
|
|
21
|
+
},
|
|
22
|
+
productId: {
|
|
23
|
+
type: Schema.Types.ObjectId,
|
|
24
|
+
ref: "productlistings",
|
|
25
|
+
required: function() {
|
|
26
|
+
return this.reviewType === ReviewType.PRODUCT;
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
sellerId: {
|
|
30
|
+
type: Schema.Types.ObjectId,
|
|
31
|
+
ref: "sellers",
|
|
32
|
+
required: function() {
|
|
33
|
+
return this.reviewType === ReviewType.SELLER;
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
rating: {
|
|
37
|
+
type: Number,
|
|
38
|
+
required: true,
|
|
39
|
+
min: 1,
|
|
40
|
+
max: 5
|
|
41
|
+
},
|
|
42
|
+
content: {
|
|
43
|
+
type: String,
|
|
44
|
+
required: true,
|
|
45
|
+
trim: true,
|
|
46
|
+
maxlength: 1000
|
|
47
|
+
},
|
|
48
|
+
helpfulVotes: {
|
|
49
|
+
type: [{
|
|
50
|
+
userId: {
|
|
51
|
+
type: Schema.Types.ObjectId,
|
|
52
|
+
ref: "users",
|
|
53
|
+
required: true
|
|
54
|
+
},
|
|
55
|
+
voteType: {
|
|
56
|
+
type: String,
|
|
57
|
+
enum: ["helpful", "not_helpful"],
|
|
58
|
+
required: true
|
|
59
|
+
},
|
|
60
|
+
createdAt: {
|
|
61
|
+
type: Date,
|
|
62
|
+
default: Date.now
|
|
63
|
+
}
|
|
64
|
+
}],
|
|
65
|
+
default: []
|
|
66
|
+
},
|
|
67
|
+
|
|
68
|
+
helpfulCount: {
|
|
69
|
+
type: Number,
|
|
70
|
+
default: 0,
|
|
71
|
+
min: 0
|
|
72
|
+
},
|
|
73
|
+
notHelpfulCount: {
|
|
74
|
+
type: Number,
|
|
75
|
+
default: 0,
|
|
76
|
+
min: 0
|
|
77
|
+
},
|
|
78
|
+
images: {
|
|
79
|
+
type: [String], // Array of image URLs
|
|
80
|
+
default: [],
|
|
81
|
+
validate: {
|
|
82
|
+
validator: function(array) {
|
|
83
|
+
return array.length <= 5;
|
|
84
|
+
},
|
|
85
|
+
message: 'Cannot upload more than 5 images per review'
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
timestamps: true,
|
|
91
|
+
toJSON: { virtuals: true },
|
|
92
|
+
toObject: { virtuals: true }
|
|
93
|
+
}
|
|
94
|
+
);
|
|
95
|
+
|
|
96
|
+
// Indexes
|
|
97
|
+
ReviewSchema.index({ productId: 1 });
|
|
98
|
+
ReviewSchema.index({ sellerId: 1 });
|
|
99
|
+
ReviewSchema.index({ userId: 1 });
|
|
100
|
+
ReviewSchema.index({ reviewType: 1 });
|
|
101
|
+
ReviewSchema.index({ "helpfulVotes.userId": 1 });
|
|
102
|
+
|
|
103
|
+
// Virtual for total feedback count
|
|
104
|
+
ReviewSchema.virtual('totalFeedback').get(function() {
|
|
105
|
+
return this.helpfulCount + this.notHelpfulCount;
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
// Method to check if a user has voted
|
|
109
|
+
ReviewSchema.methods.hasUserVoted = function(userId) {
|
|
110
|
+
return this.helpfulVotes.some(vote => vote.userId.equals(userId));
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
// Method to get user's vote type
|
|
114
|
+
ReviewSchema.methods.getUserVoteType = function(userId) {
|
|
115
|
+
const vote = this.helpfulVotes.find(vote => vote.userId.equals(userId));
|
|
116
|
+
return vote ? vote.voteType : null;
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
// Safe export to prevent OverwriteModelError
|
|
120
|
+
const Review = mongoose.models.reviews || mongoose.model("reviews", ReviewSchema);
|
|
121
|
+
export { Review, ReviewType };
|
|
@@ -1,23 +1,23 @@
|
|
|
1
|
-
import mongoose, { Schema, model } from 'mongoose';
|
|
2
|
-
|
|
3
|
-
const searchAnalyticsSchema = new mongoose.Schema({
|
|
4
|
-
searchTerm: { type: String, required: true, trim: true },
|
|
5
|
-
category: {
|
|
6
|
-
type: String,
|
|
7
|
-
enum: ["shows", "videos", "products", "users", "all"],
|
|
8
|
-
default: "all"
|
|
9
|
-
},
|
|
10
|
-
userId: { type: mongoose.Schema.Types.ObjectId, ref: "User", required: false },
|
|
11
|
-
resultCount: { type: Number, default: 0 },
|
|
12
|
-
ipAddress: { type: String },
|
|
13
|
-
deviceInfo: { type: String },
|
|
14
|
-
location: {
|
|
15
|
-
city: { type: String },
|
|
16
|
-
region: { type: String },
|
|
17
|
-
country: { type: String }
|
|
18
|
-
},
|
|
19
|
-
createdAt: { type: Date, default: Date.now }
|
|
20
|
-
});
|
|
21
|
-
// Safe export to prevent OverwriteModelError
|
|
22
|
-
const SearchAnalytics = mongoose.models.SearchAnalytics || mongoose.model("SearchAnalytics", searchAnalyticsSchema);
|
|
23
|
-
export default SearchAnalytics;
|
|
1
|
+
import mongoose, { Schema, model } from 'mongoose';
|
|
2
|
+
|
|
3
|
+
const searchAnalyticsSchema = new mongoose.Schema({
|
|
4
|
+
searchTerm: { type: String, required: true, trim: true },
|
|
5
|
+
category: {
|
|
6
|
+
type: String,
|
|
7
|
+
enum: ["shows", "videos", "products", "users", "all"],
|
|
8
|
+
default: "all"
|
|
9
|
+
},
|
|
10
|
+
userId: { type: mongoose.Schema.Types.ObjectId, ref: "User", required: false },
|
|
11
|
+
resultCount: { type: Number, default: 0 },
|
|
12
|
+
ipAddress: { type: String },
|
|
13
|
+
deviceInfo: { type: String },
|
|
14
|
+
location: {
|
|
15
|
+
city: { type: String },
|
|
16
|
+
region: { type: String },
|
|
17
|
+
country: { type: String }
|
|
18
|
+
},
|
|
19
|
+
createdAt: { type: Date, default: Date.now }
|
|
20
|
+
});
|
|
21
|
+
// Safe export to prevent OverwriteModelError
|
|
22
|
+
const SearchAnalytics = mongoose.models.SearchAnalytics || mongoose.model("SearchAnalytics", searchAnalyticsSchema);
|
|
23
|
+
export default SearchAnalytics;
|
|
@@ -1,106 +1,106 @@
|
|
|
1
|
-
import mongoose, { Schema, model } from 'mongoose';
|
|
2
|
-
import crypto from 'crypto';
|
|
3
|
-
|
|
4
|
-
const shoppableVideoInteractionSchema = new mongoose.Schema({
|
|
5
|
-
video: {
|
|
6
|
-
type: mongoose.Schema.Types.ObjectId,
|
|
7
|
-
ref: 'ShoppableVideo', // Reference the correct model name
|
|
8
|
-
required: true
|
|
9
|
-
},
|
|
10
|
-
user: {
|
|
11
|
-
type: mongoose.Schema.Types.ObjectId,
|
|
12
|
-
ref: 'User',
|
|
13
|
-
index: true
|
|
14
|
-
},
|
|
15
|
-
// Used to identify anonymous users by hashing their IP and User-Agent
|
|
16
|
-
sessionIdentifier: {
|
|
17
|
-
type: String,
|
|
18
|
-
index: true
|
|
19
|
-
},
|
|
20
|
-
host: {
|
|
21
|
-
type: mongoose.Schema.Types.ObjectId,
|
|
22
|
-
refPath: 'hostModel',
|
|
23
|
-
required: true
|
|
24
|
-
},
|
|
25
|
-
hostModel: {
|
|
26
|
-
type: String,
|
|
27
|
-
required: true,
|
|
28
|
-
enum: ['sellers', 'dropshippers']
|
|
29
|
-
},
|
|
30
|
-
location: {
|
|
31
|
-
city: String,
|
|
32
|
-
region: String,
|
|
33
|
-
country: String
|
|
34
|
-
},
|
|
35
|
-
platform: {
|
|
36
|
-
type: String,
|
|
37
|
-
enum: ['web', 'mobile', 'unknown'],
|
|
38
|
-
default: 'unknown'
|
|
39
|
-
},
|
|
40
|
-
device: {
|
|
41
|
-
type: String,
|
|
42
|
-
enum: ['mobile', 'desktop', 'tablet', 'other', 'unknown'],
|
|
43
|
-
default: 'unknown'
|
|
44
|
-
},
|
|
45
|
-
browser: String,
|
|
46
|
-
os: String,
|
|
47
|
-
ip: {
|
|
48
|
-
type: String,
|
|
49
|
-
required: true
|
|
50
|
-
},
|
|
51
|
-
watchDuration: { // Total seconds the user watched across sessions
|
|
52
|
-
type: Number,
|
|
53
|
-
default: 0
|
|
54
|
-
},
|
|
55
|
-
completionPercentage: { // The maximum percentage of the video watched
|
|
56
|
-
type: Number,
|
|
57
|
-
min: 0,
|
|
58
|
-
max: 100,
|
|
59
|
-
default: 0
|
|
60
|
-
},
|
|
61
|
-
productsClicked: [{ // Unique list of products clicked by this user for this video
|
|
62
|
-
type: mongoose.Schema.Types.ObjectId,
|
|
63
|
-
ref: 'productlistings'
|
|
64
|
-
}],
|
|
65
|
-
maxSecondReached: {
|
|
66
|
-
type: Number,
|
|
67
|
-
default: 0
|
|
68
|
-
},
|
|
69
|
-
rewatchCount: {
|
|
70
|
-
type: Number,
|
|
71
|
-
default: 0
|
|
72
|
-
},
|
|
73
|
-
watchSessions: [{
|
|
74
|
-
startedAt: Date,
|
|
75
|
-
endedAt: Date,
|
|
76
|
-
duration: Number,
|
|
77
|
-
completionPercentage: Number,
|
|
78
|
-
maxSecond: Number
|
|
79
|
-
}],
|
|
80
|
-
}, {
|
|
81
|
-
timestamps: true
|
|
82
|
-
});
|
|
83
|
-
|
|
84
|
-
// Ensures a unique interaction record per logged-in user per video.
|
|
85
|
-
shoppableVideoInteractionSchema.index({ video: 1, user: 1 }, {
|
|
86
|
-
unique: true,
|
|
87
|
-
partialFilterExpression: { user: { $exists: true } }
|
|
88
|
-
});
|
|
89
|
-
shoppableVideoInteractionSchema.index({ video: 1, maxSecondReached: 1 });
|
|
90
|
-
shoppableVideoInteractionSchema.index({ video: 1, rewatchCount: 1 });
|
|
91
|
-
shoppableVideoInteractionSchema.index({ host: 1, user: 1 });
|
|
92
|
-
|
|
93
|
-
// Ensures a unique interaction record per anonymous session per video.
|
|
94
|
-
shoppableVideoInteractionSchema.index({ video: 1, sessionIdentifier: 1 }, {
|
|
95
|
-
unique: true,
|
|
96
|
-
partialFilterExpression: { sessionIdentifier: { $exists: true } }
|
|
97
|
-
});
|
|
98
|
-
|
|
99
|
-
// Additional indexes for fast analytic queries
|
|
100
|
-
shoppableVideoInteractionSchema.index({ video: 1, createdAt: -1 });
|
|
101
|
-
|
|
102
|
-
const ShoppableVideoInteraction = mongoose.models.ShoppableVideoInteraction || mongoose.model(
|
|
103
|
-
'ShoppableVideoInteraction',
|
|
104
|
-
shoppableVideoInteractionSchema
|
|
105
|
-
);
|
|
106
|
-
export default ShoppableVideoInteraction;
|
|
1
|
+
import mongoose, { Schema, model } from 'mongoose';
|
|
2
|
+
import crypto from 'crypto';
|
|
3
|
+
|
|
4
|
+
const shoppableVideoInteractionSchema = new mongoose.Schema({
|
|
5
|
+
video: {
|
|
6
|
+
type: mongoose.Schema.Types.ObjectId,
|
|
7
|
+
ref: 'ShoppableVideo', // Reference the correct model name
|
|
8
|
+
required: true
|
|
9
|
+
},
|
|
10
|
+
user: {
|
|
11
|
+
type: mongoose.Schema.Types.ObjectId,
|
|
12
|
+
ref: 'User',
|
|
13
|
+
index: true
|
|
14
|
+
},
|
|
15
|
+
// Used to identify anonymous users by hashing their IP and User-Agent
|
|
16
|
+
sessionIdentifier: {
|
|
17
|
+
type: String,
|
|
18
|
+
index: true
|
|
19
|
+
},
|
|
20
|
+
host: {
|
|
21
|
+
type: mongoose.Schema.Types.ObjectId,
|
|
22
|
+
refPath: 'hostModel',
|
|
23
|
+
required: true
|
|
24
|
+
},
|
|
25
|
+
hostModel: {
|
|
26
|
+
type: String,
|
|
27
|
+
required: true,
|
|
28
|
+
enum: ['sellers', 'dropshippers']
|
|
29
|
+
},
|
|
30
|
+
location: {
|
|
31
|
+
city: String,
|
|
32
|
+
region: String,
|
|
33
|
+
country: String
|
|
34
|
+
},
|
|
35
|
+
platform: {
|
|
36
|
+
type: String,
|
|
37
|
+
enum: ['web', 'mobile', 'unknown'],
|
|
38
|
+
default: 'unknown'
|
|
39
|
+
},
|
|
40
|
+
device: {
|
|
41
|
+
type: String,
|
|
42
|
+
enum: ['mobile', 'desktop', 'tablet', 'other', 'unknown'],
|
|
43
|
+
default: 'unknown'
|
|
44
|
+
},
|
|
45
|
+
browser: String,
|
|
46
|
+
os: String,
|
|
47
|
+
ip: {
|
|
48
|
+
type: String,
|
|
49
|
+
required: true
|
|
50
|
+
},
|
|
51
|
+
watchDuration: { // Total seconds the user watched across sessions
|
|
52
|
+
type: Number,
|
|
53
|
+
default: 0
|
|
54
|
+
},
|
|
55
|
+
completionPercentage: { // The maximum percentage of the video watched
|
|
56
|
+
type: Number,
|
|
57
|
+
min: 0,
|
|
58
|
+
max: 100,
|
|
59
|
+
default: 0
|
|
60
|
+
},
|
|
61
|
+
productsClicked: [{ // Unique list of products clicked by this user for this video
|
|
62
|
+
type: mongoose.Schema.Types.ObjectId,
|
|
63
|
+
ref: 'productlistings'
|
|
64
|
+
}],
|
|
65
|
+
maxSecondReached: {
|
|
66
|
+
type: Number,
|
|
67
|
+
default: 0
|
|
68
|
+
},
|
|
69
|
+
rewatchCount: {
|
|
70
|
+
type: Number,
|
|
71
|
+
default: 0
|
|
72
|
+
},
|
|
73
|
+
watchSessions: [{
|
|
74
|
+
startedAt: Date,
|
|
75
|
+
endedAt: Date,
|
|
76
|
+
duration: Number,
|
|
77
|
+
completionPercentage: Number,
|
|
78
|
+
maxSecond: Number
|
|
79
|
+
}],
|
|
80
|
+
}, {
|
|
81
|
+
timestamps: true
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
// Ensures a unique interaction record per logged-in user per video.
|
|
85
|
+
shoppableVideoInteractionSchema.index({ video: 1, user: 1 }, {
|
|
86
|
+
unique: true,
|
|
87
|
+
partialFilterExpression: { user: { $exists: true } }
|
|
88
|
+
});
|
|
89
|
+
shoppableVideoInteractionSchema.index({ video: 1, maxSecondReached: 1 });
|
|
90
|
+
shoppableVideoInteractionSchema.index({ video: 1, rewatchCount: 1 });
|
|
91
|
+
shoppableVideoInteractionSchema.index({ host: 1, user: 1 });
|
|
92
|
+
|
|
93
|
+
// Ensures a unique interaction record per anonymous session per video.
|
|
94
|
+
shoppableVideoInteractionSchema.index({ video: 1, sessionIdentifier: 1 }, {
|
|
95
|
+
unique: true,
|
|
96
|
+
partialFilterExpression: { sessionIdentifier: { $exists: true } }
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
// Additional indexes for fast analytic queries
|
|
100
|
+
shoppableVideoInteractionSchema.index({ video: 1, createdAt: -1 });
|
|
101
|
+
|
|
102
|
+
const ShoppableVideoInteraction = mongoose.models.ShoppableVideoInteraction || mongoose.model(
|
|
103
|
+
'ShoppableVideoInteraction',
|
|
104
|
+
shoppableVideoInteractionSchema
|
|
105
|
+
);
|
|
106
|
+
export default ShoppableVideoInteraction;
|
package/models/Wishlist.model.js
CHANGED
|
@@ -1,29 +1,29 @@
|
|
|
1
|
-
// backend/models/Wishlist.js
|
|
2
|
-
import mongoose from "mongoose";
|
|
3
|
-
const { Schema } = mongoose;
|
|
4
|
-
|
|
5
|
-
const WishlistSchema = new Schema(
|
|
6
|
-
{
|
|
7
|
-
userId: {
|
|
8
|
-
type: Schema.Types.ObjectId,
|
|
9
|
-
ref: "users",
|
|
10
|
-
required: true
|
|
11
|
-
},
|
|
12
|
-
productId: {
|
|
13
|
-
type: Schema.Types.ObjectId,
|
|
14
|
-
ref: "productlistings",
|
|
15
|
-
required: true
|
|
16
|
-
},
|
|
17
|
-
addedAt: {
|
|
18
|
-
type: Date,
|
|
19
|
-
default: Date.now
|
|
20
|
-
}
|
|
21
|
-
},
|
|
22
|
-
{ timestamps: true }
|
|
23
|
-
);
|
|
24
|
-
|
|
25
|
-
// Add compound index to prevent duplicate entries
|
|
26
|
-
WishlistSchema.index({ userId: 1, productId: 1 }, { unique: true });
|
|
27
|
-
|
|
28
|
-
const Wishlist = mongoose.models.wishlists || mongoose.model("wishlists", WishlistSchema);
|
|
29
|
-
export default Wishlist;
|
|
1
|
+
// backend/models/Wishlist.js
|
|
2
|
+
import mongoose from "mongoose";
|
|
3
|
+
const { Schema } = mongoose;
|
|
4
|
+
|
|
5
|
+
const WishlistSchema = new Schema(
|
|
6
|
+
{
|
|
7
|
+
userId: {
|
|
8
|
+
type: Schema.Types.ObjectId,
|
|
9
|
+
ref: "users",
|
|
10
|
+
required: true
|
|
11
|
+
},
|
|
12
|
+
productId: {
|
|
13
|
+
type: Schema.Types.ObjectId,
|
|
14
|
+
ref: "productlistings",
|
|
15
|
+
required: true
|
|
16
|
+
},
|
|
17
|
+
addedAt: {
|
|
18
|
+
type: Date,
|
|
19
|
+
default: Date.now
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
{ timestamps: true }
|
|
23
|
+
);
|
|
24
|
+
|
|
25
|
+
// Add compound index to prevent duplicate entries
|
|
26
|
+
WishlistSchema.index({ userId: 1, productId: 1 }, { unique: true });
|
|
27
|
+
|
|
28
|
+
const Wishlist = mongoose.models.wishlists || mongoose.model("wishlists", WishlistSchema);
|
|
29
|
+
export default Wishlist;
|
package/models/admin.model.js
CHANGED
|
@@ -1,42 +1,42 @@
|
|
|
1
|
-
import mongoose from 'mongoose';
|
|
2
|
-
|
|
3
|
-
const { Schema } = mongoose;
|
|
4
|
-
|
|
5
|
-
const AdminSchema = new Schema(
|
|
6
|
-
{
|
|
7
|
-
name: { type: String, required: true },
|
|
8
|
-
role: { type: String, required: true, default: "admin" },
|
|
9
|
-
email: { type: String, required: true, unique: true },
|
|
10
|
-
mobileNumber: { type: String, required: true },
|
|
11
|
-
password: { type: String, required: true },
|
|
12
|
-
profilePicture: {
|
|
13
|
-
type: String,
|
|
14
|
-
default: "https://img.freepik.com/free-vector/blue-circle-with-white-user_78370-4707.jpg"
|
|
15
|
-
},
|
|
16
|
-
|
|
17
|
-
contentAccess: {
|
|
18
|
-
users: { readOnly: Boolean, edit: Boolean },
|
|
19
|
-
pendingSellers: { readOnly: Boolean, edit: Boolean },
|
|
20
|
-
sellers: { readOnly: Boolean, edit: Boolean },
|
|
21
|
-
orders: { readOnly: Boolean, edit: Boolean },
|
|
22
|
-
category: { readOnly: Boolean, edit: Boolean },
|
|
23
|
-
autoApproved:{readOnly:Boolean,edit:Boolean},
|
|
24
|
-
manualReview:{readOnly:Boolean,edit:Boolean},
|
|
25
|
-
AutoRejected:{readOnly:Boolean,edit:Boolean},
|
|
26
|
-
NewSellers:{readOnly:Boolean,edit:Boolean},
|
|
27
|
-
Coupons:{readOnly:Boolean,edit:Boolean},
|
|
28
|
-
Plans:{readOnly:Boolean,edit:Boolean},
|
|
29
|
-
orderPayments:{readOnly:Boolean,edit:Boolean},
|
|
30
|
-
helpandsupport:{readOnly:Boolean,edit:Boolean},
|
|
31
|
-
// settings: { readOnly: Boolean, edit: Boolean },
|
|
32
|
-
// admins: { readOnly: Boolean, edit: Boolean },
|
|
33
|
-
},
|
|
34
|
-
maskingSwitch: { type: Boolean, default: false },
|
|
35
|
-
},
|
|
36
|
-
{ timestamps: true }
|
|
37
|
-
);
|
|
38
|
-
|
|
39
|
-
// ✅ Fix: Use AdminSchema instead of Schema
|
|
40
|
-
const Admin = mongoose.models.Admin || mongoose.model("Admin", AdminSchema);
|
|
41
|
-
|
|
42
|
-
export default Admin;
|
|
1
|
+
import mongoose from 'mongoose';
|
|
2
|
+
|
|
3
|
+
const { Schema } = mongoose;
|
|
4
|
+
|
|
5
|
+
const AdminSchema = new Schema(
|
|
6
|
+
{
|
|
7
|
+
name: { type: String, required: true },
|
|
8
|
+
role: { type: String, required: true, default: "admin" },
|
|
9
|
+
email: { type: String, required: true, unique: true },
|
|
10
|
+
mobileNumber: { type: String, required: true },
|
|
11
|
+
password: { type: String, required: true },
|
|
12
|
+
profilePicture: {
|
|
13
|
+
type: String,
|
|
14
|
+
default: "https://img.freepik.com/free-vector/blue-circle-with-white-user_78370-4707.jpg"
|
|
15
|
+
},
|
|
16
|
+
|
|
17
|
+
contentAccess: {
|
|
18
|
+
users: { readOnly: Boolean, edit: Boolean },
|
|
19
|
+
pendingSellers: { readOnly: Boolean, edit: Boolean },
|
|
20
|
+
sellers: { readOnly: Boolean, edit: Boolean },
|
|
21
|
+
orders: { readOnly: Boolean, edit: Boolean },
|
|
22
|
+
category: { readOnly: Boolean, edit: Boolean },
|
|
23
|
+
autoApproved:{readOnly:Boolean,edit:Boolean},
|
|
24
|
+
manualReview:{readOnly:Boolean,edit:Boolean},
|
|
25
|
+
AutoRejected:{readOnly:Boolean,edit:Boolean},
|
|
26
|
+
NewSellers:{readOnly:Boolean,edit:Boolean},
|
|
27
|
+
Coupons:{readOnly:Boolean,edit:Boolean},
|
|
28
|
+
Plans:{readOnly:Boolean,edit:Boolean},
|
|
29
|
+
orderPayments:{readOnly:Boolean,edit:Boolean},
|
|
30
|
+
helpandsupport:{readOnly:Boolean,edit:Boolean},
|
|
31
|
+
// settings: { readOnly: Boolean, edit: Boolean },
|
|
32
|
+
// admins: { readOnly: Boolean, edit: Boolean },
|
|
33
|
+
},
|
|
34
|
+
maskingSwitch: { type: Boolean, default: false },
|
|
35
|
+
},
|
|
36
|
+
{ timestamps: true }
|
|
37
|
+
);
|
|
38
|
+
|
|
39
|
+
// ✅ Fix: Use AdminSchema instead of Schema
|
|
40
|
+
const Admin = mongoose.models.Admin || mongoose.model("Admin", AdminSchema);
|
|
41
|
+
|
|
42
|
+
export default Admin;
|