flykup_model_development 3.1.6 → 3.1.8
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/models/ProductInteraction.model.js +47 -29
- package/models/stock.model.js +27 -27
- package/package.json +1 -1
|
@@ -1,35 +1,53 @@
|
|
|
1
1
|
import mongoose, { Schema, model } from 'mongoose';
|
|
2
2
|
|
|
3
3
|
const productInteractionSchema = new mongoose.Schema({
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
4
|
+
product: { type: mongoose.Schema.Types.ObjectId, ref: 'Product', required: true },
|
|
5
|
+
user: { type: mongoose.Schema.Types.ObjectId, ref: 'User', index: true },
|
|
6
|
+
seller: { type: mongoose.Schema.Types.ObjectId, ref: 'Seller', required: true },
|
|
7
|
+
location: {
|
|
8
|
+
city: String,
|
|
9
|
+
region: String,
|
|
10
|
+
country: String
|
|
11
|
+
},
|
|
12
|
+
platform: { type: String, enum: ['web', 'mobile', 'unknown'], default: 'mobile' },
|
|
13
|
+
device: { type: String, enum: ['mobile', 'desktop', 'tablet', 'other'] },
|
|
14
|
+
browser: String,
|
|
15
|
+
os: String,
|
|
16
|
+
ip: { type: String, required: true },
|
|
17
|
+
isIndianRegion: { type: Boolean, default: false },
|
|
18
|
+
rating: {
|
|
19
|
+
type: Number,
|
|
20
|
+
min: 1,
|
|
21
|
+
max: 5,
|
|
22
|
+
validate: {
|
|
23
|
+
validator: Number.isInteger,
|
|
24
|
+
message: '{VALUE} is not an integer value'
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
review: {
|
|
28
|
+
type: String,
|
|
29
|
+
maxlength: 500
|
|
30
|
+
},
|
|
31
|
+
viewCount: { type: Number, default: 1 },
|
|
32
|
+
// NEW: Trust signals tracking
|
|
33
|
+
trustSignals: {
|
|
34
|
+
reviewViews: { type: Number, default: 0 }, // How many times user viewed reviews
|
|
35
|
+
reviewViewDuration: { type: Number, default: 0 }, // Total time spent on reviews (seconds)
|
|
36
|
+
comparisonViews: { type: Number, default: 0 }, // How many times user compared with other products
|
|
37
|
+
priceCheckCount: { type: Number, default: 0 }, // How many times user checked pricing
|
|
38
|
+
lastTrustSignalAt: { type: Date } // When the last trust signal was recorded
|
|
39
|
+
},
|
|
40
|
+
// NEW: Engagement status for sellers
|
|
41
|
+
engagementStatus: {
|
|
42
|
+
type: String,
|
|
43
|
+
enum: ['new', 'interested', 'hesitant', 'contacted', 'converted'],
|
|
44
|
+
default: 'new'
|
|
45
|
+
},
|
|
46
|
+
sellerNotes: [{
|
|
47
|
+
note: String,
|
|
48
|
+
createdAt: { type: Date, default: Date.now },
|
|
49
|
+
updatedAt: { type: Date, default: Date.now }
|
|
50
|
+
}]
|
|
33
51
|
}, { timestamps: true });
|
|
34
52
|
|
|
35
53
|
// Ensures a user's view is counted only once per product
|
package/models/stock.model.js
CHANGED
|
@@ -39,10 +39,19 @@
|
|
|
39
39
|
// const Stock = mongoose.models.stocks || mongoose.model("stocks", StockSchema);
|
|
40
40
|
// export default Stock;
|
|
41
41
|
|
|
42
|
-
|
|
43
42
|
// models/Stock.js
|
|
44
43
|
import mongoose from "mongoose";
|
|
45
|
-
const { Schema
|
|
44
|
+
const { Schema } = mongoose;
|
|
45
|
+
|
|
46
|
+
// Sub-schema for manual stock updates
|
|
47
|
+
const StockUpdateHistorySchema = new Schema({
|
|
48
|
+
change: { type: Number, required: true }, // e.g., +50 or -10
|
|
49
|
+
previousQuantity: { type: Number, required: true },
|
|
50
|
+
newQuantity: { type: Number, required: true },
|
|
51
|
+
reason: { type: String, default: "Manual update by seller" },
|
|
52
|
+
updatedAt: { type: Date, default: Date.now }
|
|
53
|
+
});
|
|
54
|
+
|
|
46
55
|
|
|
47
56
|
const StockSchema = new Schema(
|
|
48
57
|
{
|
|
@@ -55,44 +64,35 @@ const StockSchema = new Schema(
|
|
|
55
64
|
ref: "productlistings",
|
|
56
65
|
},
|
|
57
66
|
title: String,
|
|
67
|
+
images: [{
|
|
68
|
+
key: String,
|
|
69
|
+
url: String
|
|
70
|
+
}],
|
|
58
71
|
quantity: {
|
|
59
72
|
type: Number,
|
|
60
73
|
min: 0,
|
|
61
74
|
default: 0,
|
|
62
75
|
},
|
|
63
|
-
//
|
|
76
|
+
// History for manual stock adjustments
|
|
77
|
+
stockUpdateHistory: [StockUpdateHistorySchema],
|
|
78
|
+
|
|
79
|
+
// Track reservations for flash sales
|
|
64
80
|
flashSaleReservations: [{
|
|
65
81
|
flashSaleId: {
|
|
66
82
|
type: Schema.Types.ObjectId,
|
|
67
83
|
ref: "FlashSale",
|
|
68
84
|
required: true
|
|
69
85
|
},
|
|
70
|
-
|
|
71
|
-
type: Schema.Types.ObjectId,
|
|
72
|
-
ref: "productlistings",
|
|
73
|
-
required: true
|
|
74
|
-
},
|
|
75
|
-
quantity: {
|
|
76
|
-
type: Number,
|
|
77
|
-
min: 0,
|
|
78
|
-
default: 0
|
|
79
|
-
},
|
|
86
|
+
quantity: { type: Number, min: 0, default: 0 },
|
|
80
87
|
status: {
|
|
81
88
|
type: String,
|
|
82
89
|
enum: ['reserved', 'active', 'released', 'sold', 'partially_sold'],
|
|
83
90
|
default: 'reserved'
|
|
84
91
|
},
|
|
85
|
-
reservedAt: {
|
|
86
|
-
type: Date,
|
|
87
|
-
default: Date.now
|
|
88
|
-
},
|
|
92
|
+
reservedAt: { type: Date, default: Date.now },
|
|
89
93
|
releasedAt: Date,
|
|
90
|
-
soldQuantity: {
|
|
91
|
-
type: Number,
|
|
92
|
-
default: 0
|
|
93
|
-
}
|
|
94
|
+
soldQuantity: { type: Number, default: 0 }
|
|
94
95
|
}],
|
|
95
|
-
// Total reserved quantity (calculated field)
|
|
96
96
|
totalReserved: {
|
|
97
97
|
type: Number,
|
|
98
98
|
min: 0,
|
|
@@ -102,24 +102,24 @@ const StockSchema = new Schema(
|
|
|
102
102
|
{ timestamps: true }
|
|
103
103
|
);
|
|
104
104
|
|
|
105
|
-
//
|
|
105
|
+
// Pre-save hook to calculate totalReserved
|
|
106
106
|
StockSchema.pre('save', function(next) {
|
|
107
107
|
if (this.isModified('flashSaleReservations')) {
|
|
108
108
|
this.totalReserved = this.flashSaleReservations.reduce((total, reservation) => {
|
|
109
|
-
return total + (
|
|
109
|
+
return total + (['reserved', 'active'].includes(reservation.status) ? reservation.quantity : 0);
|
|
110
110
|
}, 0);
|
|
111
111
|
}
|
|
112
112
|
next();
|
|
113
113
|
});
|
|
114
114
|
|
|
115
|
-
// Virtual for available quantity
|
|
115
|
+
// Virtual for available quantity
|
|
116
116
|
StockSchema.virtual('availableQuantity').get(function() {
|
|
117
117
|
return Math.max(0, this.quantity - this.totalReserved);
|
|
118
118
|
});
|
|
119
119
|
|
|
120
|
-
// Ensure virtuals are included in
|
|
120
|
+
// Ensure virtuals are included in JSON output
|
|
121
121
|
StockSchema.set('toJSON', { virtuals: true });
|
|
122
122
|
StockSchema.set('toObject', { virtuals: true });
|
|
123
123
|
|
|
124
124
|
const Stock = mongoose.models.stocks || mongoose.model("stocks", StockSchema);
|
|
125
|
-
export default Stock;
|
|
125
|
+
export default Stock;
|