flykup_model_production 1.0.0
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/auth.js +14 -0
- package/config.js +1 -0
- package/db_connection.js +23 -0
- package/index.js +127 -0
- package/info.txt +1 -0
- package/models/AdminEmail.model.js +36 -0
- package/models/LiveStreamInteraction.model.js +93 -0
- package/models/ProductInteraction.model.js +42 -0
- package/models/Review.model.js +121 -0
- package/models/SearchAnalytics.js +22 -0
- package/models/ShoppableInteraction.model.js +89 -0
- package/models/Wishlist.model.js +30 -0
- package/models/admin.model.js +27 -0
- package/models/appUpdate.model.js +18 -0
- package/models/assets.model.js +32 -0
- package/models/blockedRegion.models.js +27 -0
- package/models/category.model.js +29 -0
- package/models/chat.model.js +496 -0
- package/models/coHostInvitation.model.js +56 -0
- package/models/follow.model.js +37 -0
- package/models/loginlogs.model.js +25 -0
- package/models/notification.model.js +116 -0
- package/models/order.modal.js +285 -0
- package/models/productListing.model.js +132 -0
- package/models/profileInteractions.model.js +45 -0
- package/models/registerShow.model.js +28 -0
- package/models/seller.model.js +299 -0
- package/models/settings.model.js +18 -0
- package/models/shipper.model.js +128 -0
- package/models/shoppableVideo.model.js +177 -0
- package/models/shoppableVideoComment.model.js +58 -0
- package/models/shoppableVideoLike.model.js +30 -0
- package/models/shoppableVideoSave.model.js +28 -0
- package/models/shows.model.js +315 -0
- package/models/stock.model.js +128 -0
- package/models/ticket.model.js +115 -0
- package/models/user.model.js +229 -0
- package/package.json +18 -0
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import mongoose from "mongoose";
|
|
2
|
+
|
|
3
|
+
const shoppableVideoSaveSchema = new mongoose.Schema(
|
|
4
|
+
{
|
|
5
|
+
videoId: {
|
|
6
|
+
type: mongoose.Schema.Types.ObjectId,
|
|
7
|
+
ref: "ShoppableVideo",
|
|
8
|
+
required: true,
|
|
9
|
+
},
|
|
10
|
+
userId: {
|
|
11
|
+
type: mongoose.Schema.Types.ObjectId,
|
|
12
|
+
ref: "User",
|
|
13
|
+
required: true,
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
timestamps: true,
|
|
18
|
+
toJSON: { virtuals: true },
|
|
19
|
+
toObject: { virtuals: true },
|
|
20
|
+
}
|
|
21
|
+
);
|
|
22
|
+
|
|
23
|
+
// Add compound index to ensure a user can only save a video once
|
|
24
|
+
shoppableVideoSaveSchema.index({ videoId: 1, userId: 1 }, { unique: true });
|
|
25
|
+
|
|
26
|
+
const ShoppableVideoSave = mongoose.model("ShoppableVideoSave", shoppableVideoSaveSchema);
|
|
27
|
+
|
|
28
|
+
export default ShoppableVideoSave;
|
|
@@ -0,0 +1,315 @@
|
|
|
1
|
+
import mongoose from "mongoose";
|
|
2
|
+
const { Schema } = mongoose;
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
// Comment Schema
|
|
6
|
+
const commentSchema = new Schema({
|
|
7
|
+
user: {
|
|
8
|
+
type: mongoose.Schema.Types.ObjectId,
|
|
9
|
+
ref: "users", // Reference to the User model
|
|
10
|
+
},
|
|
11
|
+
text: {
|
|
12
|
+
type: String,
|
|
13
|
+
},
|
|
14
|
+
timeStamp: {
|
|
15
|
+
type: Date,
|
|
16
|
+
default: Date.now,
|
|
17
|
+
},
|
|
18
|
+
createdAt: {
|
|
19
|
+
type: Date,
|
|
20
|
+
default: Date.now,
|
|
21
|
+
},
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
const bidSchema = new mongoose.Schema({
|
|
25
|
+
user: {
|
|
26
|
+
type: mongoose.Schema.Types.ObjectId,
|
|
27
|
+
ref: "users", // Reference to the User model
|
|
28
|
+
required: true,
|
|
29
|
+
},
|
|
30
|
+
amount: {
|
|
31
|
+
type: Number,
|
|
32
|
+
required: true,
|
|
33
|
+
},
|
|
34
|
+
createdAt: {
|
|
35
|
+
type: Date,
|
|
36
|
+
default: Date.now,
|
|
37
|
+
},
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
// Auction Schema
|
|
41
|
+
const auctionSchema = new mongoose.Schema(
|
|
42
|
+
{
|
|
43
|
+
streamId: {
|
|
44
|
+
type: String,
|
|
45
|
+
required: true,
|
|
46
|
+
},
|
|
47
|
+
product: {
|
|
48
|
+
type: String,
|
|
49
|
+
},
|
|
50
|
+
auctionType: {
|
|
51
|
+
type: String, // 'default' or other types
|
|
52
|
+
},
|
|
53
|
+
startingBid: {
|
|
54
|
+
type: Number,
|
|
55
|
+
},
|
|
56
|
+
increment: {
|
|
57
|
+
type: Number,
|
|
58
|
+
default: 500,
|
|
59
|
+
},
|
|
60
|
+
currentHighestBid: {
|
|
61
|
+
type: Number,
|
|
62
|
+
default: 0,
|
|
63
|
+
},
|
|
64
|
+
nextBid1: {
|
|
65
|
+
type: Number,
|
|
66
|
+
default: 0,
|
|
67
|
+
},
|
|
68
|
+
nextBid2: {
|
|
69
|
+
type: Number,
|
|
70
|
+
default: 0,
|
|
71
|
+
},
|
|
72
|
+
highestBidder: {
|
|
73
|
+
type: mongoose.Schema.Types.ObjectId,
|
|
74
|
+
ref: "users", // Store reference to the highest bidder
|
|
75
|
+
default: null,
|
|
76
|
+
},
|
|
77
|
+
bidderWon: {
|
|
78
|
+
type: mongoose.Schema.Types.ObjectId,
|
|
79
|
+
ref: "users", // Store reference to the highest bidder
|
|
80
|
+
default: null,
|
|
81
|
+
},
|
|
82
|
+
bids: [bidSchema], // Array of bids
|
|
83
|
+
endsAt: {
|
|
84
|
+
type: Date,
|
|
85
|
+
},
|
|
86
|
+
isActive: {
|
|
87
|
+
type: Boolean,
|
|
88
|
+
default: true,
|
|
89
|
+
},
|
|
90
|
+
uniqueStreamId: {
|
|
91
|
+
type: String,
|
|
92
|
+
},
|
|
93
|
+
},
|
|
94
|
+
{ timestamps: true }
|
|
95
|
+
);
|
|
96
|
+
|
|
97
|
+
const giveawayProductSchema = new Schema({
|
|
98
|
+
_id: false,
|
|
99
|
+
productId: { type: Schema.Types.ObjectId, ref: "productlistings", required: true },
|
|
100
|
+
productOwnerSellerId: { type: Schema.Types.ObjectId, ref: 'sellers', required: true },
|
|
101
|
+
productTitle: { type: String },
|
|
102
|
+
|
|
103
|
+
// BGA Integration Fields
|
|
104
|
+
giveawayObjectId: { type: Schema.Types.ObjectId, required: true, index: true },
|
|
105
|
+
giveawayStatus: {
|
|
106
|
+
type: String,
|
|
107
|
+
enum: ['preparing', 'ready', 'active', 'ended', 'failed'],
|
|
108
|
+
default: 'preparing'
|
|
109
|
+
},
|
|
110
|
+
activatedAt: { type: Date, default: null },
|
|
111
|
+
createdAt: { type: Date, default: Date.now }
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
// Show Schema
|
|
115
|
+
const showSchema = new Schema(
|
|
116
|
+
{
|
|
117
|
+
// === MODIFIED START: Host Information ===
|
|
118
|
+
sellerId: { // <--- REMOVE or comment out this line
|
|
119
|
+
type: mongoose.Schema.Types.ObjectId,
|
|
120
|
+
ref: "sellers",
|
|
121
|
+
},
|
|
122
|
+
host: { // New field for the host (Seller or Dropshipper)
|
|
123
|
+
type: mongoose.Schema.Types.ObjectId,
|
|
124
|
+
required: true,
|
|
125
|
+
refPath: 'hostModel' // Dynamic reference
|
|
126
|
+
},
|
|
127
|
+
hostModel: { // New field to define the type of host
|
|
128
|
+
type: String,
|
|
129
|
+
required: true,
|
|
130
|
+
enum: ['sellers', 'dropshippers'] // Allowed host types
|
|
131
|
+
},
|
|
132
|
+
// === MODIFIED END: Host Information ===
|
|
133
|
+
|
|
134
|
+
title: {
|
|
135
|
+
type: String,
|
|
136
|
+
required: true,
|
|
137
|
+
},
|
|
138
|
+
date: {
|
|
139
|
+
type: Date,
|
|
140
|
+
},
|
|
141
|
+
time: {
|
|
142
|
+
type: String,
|
|
143
|
+
},
|
|
144
|
+
scheduledAt: {
|
|
145
|
+
type: Date,
|
|
146
|
+
index: true // Add index for better query performance
|
|
147
|
+
},
|
|
148
|
+
category: {
|
|
149
|
+
type: String,
|
|
150
|
+
},
|
|
151
|
+
subCategory: {
|
|
152
|
+
type: String,
|
|
153
|
+
default: '',
|
|
154
|
+
},
|
|
155
|
+
liveStreamId: { type: String, default: null },
|
|
156
|
+
streamName: {
|
|
157
|
+
type: String,
|
|
158
|
+
default: ''
|
|
159
|
+
},
|
|
160
|
+
tags: {
|
|
161
|
+
type: [String],
|
|
162
|
+
default: [],
|
|
163
|
+
},
|
|
164
|
+
|
|
165
|
+
thumbnailImage: {
|
|
166
|
+
type: String, // URL or file path
|
|
167
|
+
default: null,
|
|
168
|
+
},
|
|
169
|
+
previewVideo: {
|
|
170
|
+
type: String, // URL or file path
|
|
171
|
+
default: null,
|
|
172
|
+
},
|
|
173
|
+
language: {
|
|
174
|
+
type: String,
|
|
175
|
+
},
|
|
176
|
+
isLive: {
|
|
177
|
+
type: Boolean,
|
|
178
|
+
default: false,
|
|
179
|
+
},
|
|
180
|
+
streamUrl: {
|
|
181
|
+
type: String, // URL for the live stream
|
|
182
|
+
default: null,
|
|
183
|
+
},
|
|
184
|
+
showStatus: {
|
|
185
|
+
type: String,
|
|
186
|
+
enum: ['created', 'live', 'cancelled', 'ended'],
|
|
187
|
+
default: 'created'
|
|
188
|
+
},
|
|
189
|
+
comments: [commentSchema], // Array of comments
|
|
190
|
+
likes: {
|
|
191
|
+
type: Number,
|
|
192
|
+
default: 0,
|
|
193
|
+
},
|
|
194
|
+
likedBy: {
|
|
195
|
+
type: [mongoose.Schema.Types.ObjectId],
|
|
196
|
+
ref: 'users',
|
|
197
|
+
default: [],
|
|
198
|
+
},
|
|
199
|
+
// auctions: [auctionSchema], // Array of auctions
|
|
200
|
+
currentAuction: auctionSchema,
|
|
201
|
+
buyNowProducts: {
|
|
202
|
+
type: [
|
|
203
|
+
{
|
|
204
|
+
_id: false,
|
|
205
|
+
productId: { type: Schema.Types.ObjectId, ref: "productlistings" },
|
|
206
|
+
// --- ADDED productOwnerSellerId ---
|
|
207
|
+
productOwnerSellerId: { type: Schema.Types.ObjectId, ref: 'sellers', required: true },
|
|
208
|
+
productPrice: { type: Number, min: 0, default: null }, // Price set by host for this show
|
|
209
|
+
},
|
|
210
|
+
],
|
|
211
|
+
default: [],
|
|
212
|
+
},
|
|
213
|
+
auctionProducts: {
|
|
214
|
+
type: [
|
|
215
|
+
{
|
|
216
|
+
_id: false,
|
|
217
|
+
productId: { type: Schema.Types.ObjectId, ref: "productlistings" },
|
|
218
|
+
// --- ADDED productOwnerSellerId ---
|
|
219
|
+
productOwnerSellerId: { type: Schema.Types.ObjectId, ref: 'sellers', required: true },
|
|
220
|
+
startingPrice: { type: Number, min: 0, default: null },
|
|
221
|
+
reservedPrice: { type: Number, min: 0, default: null },
|
|
222
|
+
isAuctionEnded: {
|
|
223
|
+
type: Boolean,
|
|
224
|
+
default: false
|
|
225
|
+
},
|
|
226
|
+
streamId: {
|
|
227
|
+
type: String,
|
|
228
|
+
},
|
|
229
|
+
// product: {
|
|
230
|
+
// type: String,
|
|
231
|
+
// },
|
|
232
|
+
auctionType: {
|
|
233
|
+
type: String, // 'default' or other types
|
|
234
|
+
},
|
|
235
|
+
startingBid: {
|
|
236
|
+
type: Number,
|
|
237
|
+
},
|
|
238
|
+
increment: {
|
|
239
|
+
type: Number,
|
|
240
|
+
default: 5,
|
|
241
|
+
},
|
|
242
|
+
currentHighestBid: {
|
|
243
|
+
type: Number,
|
|
244
|
+
default: 0,
|
|
245
|
+
},
|
|
246
|
+
nextBid1: {
|
|
247
|
+
type: Number,
|
|
248
|
+
default: 0,
|
|
249
|
+
},
|
|
250
|
+
nextBid2: {
|
|
251
|
+
type: Number,
|
|
252
|
+
default: 0,
|
|
253
|
+
},
|
|
254
|
+
highestBidder: {
|
|
255
|
+
type: mongoose.Schema.Types.ObjectId,
|
|
256
|
+
ref: "users", // Store reference to the highest bidder
|
|
257
|
+
default: null,
|
|
258
|
+
},
|
|
259
|
+
bidderWon: {
|
|
260
|
+
type: mongoose.Schema.Types.ObjectId,
|
|
261
|
+
ref: "users", // Store reference to the highest bidder
|
|
262
|
+
default: null,
|
|
263
|
+
},
|
|
264
|
+
bids: [bidSchema], // Array of bids
|
|
265
|
+
endsAt: {
|
|
266
|
+
type: Date,
|
|
267
|
+
},
|
|
268
|
+
isActive: {
|
|
269
|
+
type: Boolean,
|
|
270
|
+
default: true,
|
|
271
|
+
},
|
|
272
|
+
uniqueStreamId: {
|
|
273
|
+
type: String,
|
|
274
|
+
},
|
|
275
|
+
auctionNumber: { // <-- New field in auctionProducts sub-schema
|
|
276
|
+
type: Number,
|
|
277
|
+
}
|
|
278
|
+
},
|
|
279
|
+
],
|
|
280
|
+
default: [],
|
|
281
|
+
},
|
|
282
|
+
|
|
283
|
+
giveawayProducts: {
|
|
284
|
+
type: [giveawayProductSchema],
|
|
285
|
+
default: []
|
|
286
|
+
},
|
|
287
|
+
notes: {
|
|
288
|
+
type: String,
|
|
289
|
+
default: ''
|
|
290
|
+
},
|
|
291
|
+
// giveaways: [giveawaySchema], // Array of giveaways
|
|
292
|
+
},
|
|
293
|
+
{ timestamps: true }
|
|
294
|
+
);
|
|
295
|
+
|
|
296
|
+
showSchema.pre('save', function (next) {
|
|
297
|
+
const doc = this;
|
|
298
|
+
|
|
299
|
+
// Set liveDrop based on product types
|
|
300
|
+
const hasBuyNow = doc.buyNowProducts && doc.buyNowProducts.length > 0;
|
|
301
|
+
const hasAuction = doc.auctionProducts && doc.auctionProducts.length > 0;
|
|
302
|
+
const hasGiveaway = doc.giveawayProducts && doc.giveawayProducts.length > 0;
|
|
303
|
+
doc.liveDrop = hasBuyNow && hasAuction && hasGiveaway;
|
|
304
|
+
|
|
305
|
+
// Ensure coHost is null if hasCoHost is false
|
|
306
|
+
if (!doc.hasCoHost) {
|
|
307
|
+
doc.coHost = null;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
next();
|
|
311
|
+
});
|
|
312
|
+
|
|
313
|
+
const Show = mongoose.model("shows", showSchema);
|
|
314
|
+
|
|
315
|
+
export default Show;
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import mongoose from "mongoose";
|
|
2
|
+
const { Schema, model } = mongoose;
|
|
3
|
+
|
|
4
|
+
const StockSchema = new Schema(
|
|
5
|
+
{
|
|
6
|
+
sellerId: {
|
|
7
|
+
type: Schema.Types.ObjectId,
|
|
8
|
+
ref: "sellers",
|
|
9
|
+
},
|
|
10
|
+
productListingId: {
|
|
11
|
+
type: Schema.Types.ObjectId,
|
|
12
|
+
ref: "productlistings",
|
|
13
|
+
},
|
|
14
|
+
title: String,
|
|
15
|
+
quantity: {
|
|
16
|
+
type: Number,
|
|
17
|
+
min: 0,
|
|
18
|
+
default: null,
|
|
19
|
+
},
|
|
20
|
+
images: [
|
|
21
|
+
{
|
|
22
|
+
key: { type: String, maxLength: 255, default: null },
|
|
23
|
+
blobName: { type: String, maxLength: 255, default: null },
|
|
24
|
+
azureUrl: { type: String, maxLength: 1024, default: null },
|
|
25
|
+
},
|
|
26
|
+
],
|
|
27
|
+
mfgDate: {
|
|
28
|
+
type: String,
|
|
29
|
+
default: null,
|
|
30
|
+
},
|
|
31
|
+
expDate: {
|
|
32
|
+
type: String,
|
|
33
|
+
default: null,
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
{ timestamps: true }
|
|
37
|
+
);
|
|
38
|
+
|
|
39
|
+
const Stock = model("stocks", StockSchema);
|
|
40
|
+
|
|
41
|
+
export default Stock;
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
// models/Stock.js
|
|
45
|
+
// // models/Stock.js
|
|
46
|
+
// import mongoose from "mongoose";
|
|
47
|
+
// const { Schema, model } = mongoose;
|
|
48
|
+
|
|
49
|
+
// const StockSchema = new Schema(
|
|
50
|
+
// {
|
|
51
|
+
// sellerId: {
|
|
52
|
+
// type: Schema.Types.ObjectId,
|
|
53
|
+
// ref: "sellers",
|
|
54
|
+
// },
|
|
55
|
+
// productListingId: {
|
|
56
|
+
// type: Schema.Types.ObjectId,
|
|
57
|
+
// ref: "productlistings",
|
|
58
|
+
// },
|
|
59
|
+
// title: String,
|
|
60
|
+
// quantity: {
|
|
61
|
+
// type: Number,
|
|
62
|
+
// min: 0,
|
|
63
|
+
// default: 0,
|
|
64
|
+
// },
|
|
65
|
+
// // Track reservations for current and upcoming flash sales
|
|
66
|
+
// flashSaleReservations: [{
|
|
67
|
+
// flashSaleId: {
|
|
68
|
+
// type: Schema.Types.ObjectId,
|
|
69
|
+
// ref: "FlashSale",
|
|
70
|
+
// required: true
|
|
71
|
+
// },
|
|
72
|
+
// productId: {
|
|
73
|
+
// type: Schema.Types.ObjectId,
|
|
74
|
+
// ref: "productlistings",
|
|
75
|
+
// required: true
|
|
76
|
+
// },
|
|
77
|
+
// quantity: {
|
|
78
|
+
// type: Number,
|
|
79
|
+
// min: 0,
|
|
80
|
+
// default: 0
|
|
81
|
+
// },
|
|
82
|
+
// status: {
|
|
83
|
+
// type: String,
|
|
84
|
+
// enum: ['reserved', 'active', 'released', 'sold', 'partially_sold'],
|
|
85
|
+
// default: 'reserved'
|
|
86
|
+
// },
|
|
87
|
+
// reservedAt: {
|
|
88
|
+
// type: Date,
|
|
89
|
+
// default: Date.now
|
|
90
|
+
// },
|
|
91
|
+
// releasedAt: Date,
|
|
92
|
+
// soldQuantity: {
|
|
93
|
+
// type: Number,
|
|
94
|
+
// default: 0
|
|
95
|
+
// }
|
|
96
|
+
// }],
|
|
97
|
+
// // Total reserved quantity (calculated field)
|
|
98
|
+
// totalReserved: {
|
|
99
|
+
// type: Number,
|
|
100
|
+
// min: 0,
|
|
101
|
+
// default: 0
|
|
102
|
+
// }
|
|
103
|
+
// },
|
|
104
|
+
// { timestamps: true }
|
|
105
|
+
// );
|
|
106
|
+
|
|
107
|
+
// // Update totalReserved when flashSaleReservations change
|
|
108
|
+
// StockSchema.pre('save', function(next) {
|
|
109
|
+
// if (this.isModified('flashSaleReservations')) {
|
|
110
|
+
// this.totalReserved = this.flashSaleReservations.reduce((total, reservation) => {
|
|
111
|
+
// return total + (reservation.status === 'reserved' || reservation.status === 'active' ? reservation.quantity : 0);
|
|
112
|
+
// }, 0);
|
|
113
|
+
// }
|
|
114
|
+
// next();
|
|
115
|
+
// });
|
|
116
|
+
|
|
117
|
+
// // Virtual for available quantity (total - reserved)
|
|
118
|
+
// StockSchema.virtual('availableQuantity').get(function() {
|
|
119
|
+
// return Math.max(0, this.quantity - this.totalReserved);
|
|
120
|
+
// });
|
|
121
|
+
|
|
122
|
+
// // Ensure virtuals are included in toJSON output
|
|
123
|
+
// StockSchema.set('toJSON', { virtuals: true });
|
|
124
|
+
// StockSchema.set('toObject', { virtuals: true });
|
|
125
|
+
|
|
126
|
+
// const Stock = model("stocks", StockSchema);
|
|
127
|
+
|
|
128
|
+
// export default Stock;
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
// models/Ticket.js
|
|
2
|
+
import mongoose from 'mongoose';
|
|
3
|
+
|
|
4
|
+
const replySchema = new mongoose.Schema({
|
|
5
|
+
message: {
|
|
6
|
+
type: String,
|
|
7
|
+
required: true,
|
|
8
|
+
},
|
|
9
|
+
repliedBy: {
|
|
10
|
+
type: mongoose.Schema.Types.ObjectId,
|
|
11
|
+
ref: 'users',
|
|
12
|
+
required: true,
|
|
13
|
+
},
|
|
14
|
+
repliedByRole: {
|
|
15
|
+
type: String,
|
|
16
|
+
enum: ['Admin', 'Seller'],
|
|
17
|
+
required: true,
|
|
18
|
+
},
|
|
19
|
+
repliedAt: {
|
|
20
|
+
type: Date,
|
|
21
|
+
default: Date.now,
|
|
22
|
+
},
|
|
23
|
+
attachments: [
|
|
24
|
+
{
|
|
25
|
+
type: String, // URLs or file paths for reply attachments
|
|
26
|
+
required: false,
|
|
27
|
+
},
|
|
28
|
+
],
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
const ticketSchema = new mongoose.Schema(
|
|
32
|
+
{
|
|
33
|
+
ticketId: {
|
|
34
|
+
type: String,
|
|
35
|
+
required: true,
|
|
36
|
+
unique: true,
|
|
37
|
+
},
|
|
38
|
+
raisedBy: {
|
|
39
|
+
type: mongoose.Schema.Types.ObjectId,
|
|
40
|
+
ref: 'users',
|
|
41
|
+
required: true,
|
|
42
|
+
},
|
|
43
|
+
raisedByRole: {
|
|
44
|
+
type: String,
|
|
45
|
+
enum: ['User', 'Seller'],
|
|
46
|
+
required: true,
|
|
47
|
+
},
|
|
48
|
+
|
|
49
|
+
// NEW: Reference to the order this ticket is related to
|
|
50
|
+
orderId: {
|
|
51
|
+
type: mongoose.Schema.Types.ObjectId,
|
|
52
|
+
ref: 'Order', // Assuming your order model is named 'orders'
|
|
53
|
+
required: false,
|
|
54
|
+
},
|
|
55
|
+
// NEW: Reference to the seller user associated with the order
|
|
56
|
+
sellerUserId: {
|
|
57
|
+
type: mongoose.Schema.Types.ObjectId,
|
|
58
|
+
ref: 'users',
|
|
59
|
+
required: false,
|
|
60
|
+
},
|
|
61
|
+
ticketPurposeId: {
|
|
62
|
+
type: String,
|
|
63
|
+
required: true,
|
|
64
|
+
},
|
|
65
|
+
ticketPurposePage: {
|
|
66
|
+
type: String,
|
|
67
|
+
required: true,
|
|
68
|
+
},
|
|
69
|
+
attachments: [
|
|
70
|
+
{
|
|
71
|
+
type: String, // Assuming attachments are stored as URLs or file paths
|
|
72
|
+
required: false,
|
|
73
|
+
},
|
|
74
|
+
],
|
|
75
|
+
issueType: {
|
|
76
|
+
type: String,
|
|
77
|
+
required: true,
|
|
78
|
+
},
|
|
79
|
+
description: {
|
|
80
|
+
type: String,
|
|
81
|
+
required: true,
|
|
82
|
+
},
|
|
83
|
+
status: {
|
|
84
|
+
type: String,
|
|
85
|
+
enum: ['Open', 'In Progress', 'Resolved', 'Closed'],
|
|
86
|
+
default: 'Open',
|
|
87
|
+
},
|
|
88
|
+
// New reply fields
|
|
89
|
+
sellerReply: {
|
|
90
|
+
type: replySchema,
|
|
91
|
+
required: false,
|
|
92
|
+
},
|
|
93
|
+
adminReply: {
|
|
94
|
+
type: replySchema,
|
|
95
|
+
required: false,
|
|
96
|
+
},
|
|
97
|
+
// Track multiple replies (conversation history)
|
|
98
|
+
replies: [replySchema],
|
|
99
|
+
// Last updated by (for tracking purposes)
|
|
100
|
+
lastUpdatedBy: {
|
|
101
|
+
type: mongoose.Schema.Types.ObjectId,
|
|
102
|
+
ref: 'users',
|
|
103
|
+
required: false,
|
|
104
|
+
},
|
|
105
|
+
lastUpdatedByRole: {
|
|
106
|
+
type: String,
|
|
107
|
+
enum: ['User', 'Seller', 'Admin'],
|
|
108
|
+
required: false,
|
|
109
|
+
},
|
|
110
|
+
},
|
|
111
|
+
{ timestamps: true }
|
|
112
|
+
);
|
|
113
|
+
|
|
114
|
+
const Ticket = mongoose.model('Ticket', ticketSchema);
|
|
115
|
+
export default Ticket;
|