@mac777/project-pinecone-models 1.1.8 → 1.1.11

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/src/Order.ts CHANGED
@@ -1,201 +1,252 @@
1
- import mongoose from 'mongoose';
1
+ import mongoose from "mongoose";
2
+
3
+ /* ----------------------------------
4
+ * Embedded Schemas
5
+ * ---------------------------------- */
6
+
7
+ const orderTicketSchema = new mongoose.Schema(
8
+ {
9
+ ticketVariantId: {
10
+ type: mongoose.Schema.Types.ObjectId,
11
+ required: true,
12
+ ref: "TicketVariant"
13
+ },
14
+ variantName: {
15
+ type: String,
16
+ required: true,
17
+ trim: true
18
+ },
19
+ quantity: {
20
+ type: Number,
21
+ required: true,
22
+ min: 1
23
+ },
24
+ pricePerTicket: {
25
+ type: Number,
26
+ required: true,
27
+ min: 0
28
+ },
29
+ subtotal: {
30
+ type: Number,
31
+ required: true,
32
+ min: 0
33
+ }
34
+ },
35
+ { _id: false }
36
+ );
37
+
38
+ const pricingSchema = new mongoose.Schema(
39
+ {
40
+ subtotal: { type: Number, required: true, min: 0 },
41
+ platformFee: { type: Number, required: true, min: 0 },
42
+ paymentFee: { type: Number, required: true, min: 0 },
43
+ total: { type: Number, required: true, min: 0 },
44
+ currency: { type: String, default: "BDT" },
45
+ hostPayout: { type: Number, required: true, min: 0 }
46
+ },
47
+ { _id: false }
48
+ );
49
+
50
+ const refundSchema = new mongoose.Schema(
51
+ {
52
+ reason: {
53
+ type: String,
54
+ enum: ["event_cancelled", "user_request", "fraud"],
55
+ required: true
56
+ },
57
+ amount: {
58
+ type: Number,
59
+ required: true,
60
+ min: 0
61
+ },
62
+ refundedAt: {
63
+ type: Date,
64
+ default: Date.now
65
+ },
66
+ stripeRefundId: String
67
+ },
68
+ { _id: false }
69
+ );
70
+
71
+ /* ----------------------------------
72
+ * Main Order Schema
73
+ * ---------------------------------- */
74
+
75
+ const orderSchema = new mongoose.Schema(
76
+ {
77
+ /* ---------- Identity ---------- */
78
+
79
+ orderNumber: {
80
+ type: String,
81
+ unique: true,
82
+ index: true
83
+ },
84
+
85
+ userId: {
86
+ type: mongoose.Schema.Types.ObjectId,
87
+ ref: "User",
88
+ required: true,
89
+ index: true
90
+ },
91
+
92
+ eventId: {
93
+ type: mongoose.Schema.Types.ObjectId,
94
+ ref: "Event",
95
+ required: true,
96
+ index: true
97
+ },
98
+
99
+ /* ---------- Tickets ---------- */
100
+
101
+ tickets: {
102
+ type: [orderTicketSchema],
103
+ validate: (v: any) => v.length > 0
104
+ },
105
+
106
+ ticketCount: {
107
+ type: Number,
108
+ required: true,
109
+ min: 1
110
+ },
111
+
112
+ ticketIds: [{
113
+ type: mongoose.Schema.Types.ObjectId,
114
+ ref: "Ticket"
115
+ }],
116
+
117
+ /* ---------- Pricing ---------- */
118
+
119
+ pricing: {
120
+ type: pricingSchema,
121
+ required: true
122
+ },
123
+
124
+ /* ---------- Payment ---------- */
125
+
126
+ paymentId: String,
127
+
128
+ paymentMethod: {
129
+ type: String,
130
+ enum: ["card", "bkash", "bank_transfer", "free"],
131
+ required: true
132
+ },
133
+
134
+ paymentStatus: {
135
+ type: String,
136
+ enum: ["pending", "succeeded", "failed"],
137
+ default: "pending",
138
+ index: true
139
+ },
140
+
141
+ paidAt: Date,
142
+
143
+ /* ---------- Order Lifecycle ---------- */
144
+
145
+ status: {
146
+ type: String,
147
+ enum: ["pending", "confirmed", "cancelled", "refunded"],
148
+ default: "pending",
149
+ index: true
150
+ },
151
+
152
+ requiresManualReview: {
153
+ type: Boolean,
154
+ default: false
155
+ },
156
+
157
+ manualReviewReason: String,
158
+
159
+ confirmedAt: Date,
160
+ cancelledAt: Date,
161
+ refundedAt: Date,
162
+
163
+ expiresAt: {
164
+ type: Date,
165
+ required: true,
166
+ index: true
167
+ },
168
+
169
+ reminderSentAt: Date,
170
+
171
+ /* ---------- Buyer ---------- */
172
+
173
+ buyerEmail: {
174
+ type: String,
175
+ required: true,
176
+ lowercase: true,
177
+ trim: true,
178
+ index: true
179
+ },
180
+
181
+ buyerPhone: String,
182
+
183
+ /* ---------- Refund ---------- */
184
+
185
+ refund: {
186
+ type: refundSchema,
187
+ validate: {
188
+ validator(refund: any) {
189
+ return !refund || refund.amount <= this.pricing.total;
190
+ },
191
+ message: "Refund amount exceeds order total"
192
+ }
193
+ },
194
+
195
+ /* ---------- Audit ---------- */
2
196
 
3
- // Order Ticket Schema
4
- const orderTicketSchema = new mongoose.Schema({
5
- ticketVariantId: {
6
- type: mongoose.Schema.Types.ObjectId,
7
- required: true
8
- },
9
- variantName: {
10
- type: String,
11
- required: true
12
- },
13
- quantity: {
14
- type: Number,
15
- required: true,
16
- min: 1
17
- },
18
- pricePerTicket: {
19
- type: Number,
20
- required: true,
21
- min: 0
22
- },
23
- subtotal: {
24
- type: Number,
25
- required: true,
26
- min: 0
197
+ ipAddress: String,
198
+ userAgent: String
199
+ },
200
+ {
201
+ timestamps: true,
202
+ strict: true
27
203
  }
28
- }, { _id: false });
29
-
30
- // Pricing Schema
31
- const pricingSchema = new mongoose.Schema({
32
- subtotal: {
33
- type: Number,
34
- required: true,
35
- min: 0
36
- },
37
- platformFee: {
38
- type: Number,
39
- required: true,
40
- min: 0
41
- },
42
- paymentFee: {
43
- type: Number,
44
- required: true,
45
- min: 0
46
- },
47
- total: {
48
- type: Number,
49
- required: true,
50
- min: 0
51
- },
52
- currency: {
53
- type: String,
54
- required: true,
55
- default: 'BDT'
56
- },
57
- hostPayout: {
58
- type: Number,
59
- required: true,
60
- min: 0
61
- }
62
- }, { _id: false });
63
-
64
- // Refund Schema
65
- const refundSchema = new mongoose.Schema({
66
- reason: {
67
- type: String,
68
- required: true,
69
- enum: ['event_cancelled', 'user_request', 'fraud']
70
- },
71
- amount: {
72
- type: Number,
73
- required: true,
74
- min: 0
75
- },
76
- refundedAt: {
77
- type: Date,
78
- default: Date.now
79
- },
80
- stripeRefundId: String
81
- }, { _id: false });
82
-
83
- // Main Order Schema
84
- const orderSchema = new mongoose.Schema({
85
- orderNumber: {
86
- type: String,
87
- required: true,
88
- unique: true,
89
- },
90
-
91
- // WHO
92
- userId: {
93
- type: mongoose.Schema.Types.ObjectId,
94
- required: true,
95
- },
96
-
97
- // WHAT
98
- eventId: {
99
- type: mongoose.Schema.Types.ObjectId,
100
- required: true,
101
- },
102
-
103
- paymentId: {
104
- type: String,
105
- required: false,
106
- },
107
-
108
- tickets: [orderTicketSchema],
109
-
110
- // MONEY
111
- pricing: pricingSchema,
112
-
113
- // STATUS
114
- status: {
115
- type: String,
116
- required: true,
117
- enum: ['pending', 'confirmed', 'cancelled', 'refunded'],
118
- default: 'pending'
119
- },
120
-
121
- requiresManualReview: {
122
- type: Boolean,
123
- default: false
124
- },
125
-
126
- manualReviewReason: {
127
- type: String,
128
- default: null
129
- },
130
-
131
- paymentMethod: {
132
- type: String,
133
- required: true,
134
- enum: ['card', 'bkash', 'bank_transfer', 'free']
135
- },
136
- paymentStatus: {
137
- type: String,
138
- required: true,
139
- enum: ['pending', 'succeeded', 'failed'],
140
- default: 'pending'
141
- },
142
- paidAt: Date,
143
-
144
- // TICKETS ISSUED
145
- ticketIds: [{
146
- type: mongoose.Schema.Types.ObjectId,
147
- ref: 'Ticket'
148
- }],
149
-
150
- // LIFECYCLE
151
- createdAt: {
152
- type: Date,
153
- default: Date.now,
154
- index: true
155
- },
156
- expiresAt: {
157
- type: Date,
158
- required: true
159
- },
160
- confirmedAt: Date,
161
- cancelledAt: Date,
162
- refundedAt: Date,
163
- reminderSentAt: Date,
164
-
165
- // CONTACT
166
- buyerEmail: {
167
- type: String,
168
- required: true
169
- },
170
- buyerPhone: String,
171
-
172
- // AUDIT
173
- ipAddress: String,
174
- userAgent: String,
175
-
176
- // REFUND (if applicable)
177
- refund: refundSchema
204
+ );
205
+
206
+ /* ----------------------------------
207
+ * Indexes
208
+ * ---------------------------------- */
209
+
210
+ orderSchema.index({ status: 1, createdAt: -1 });
211
+ orderSchema.index({ eventId: 1, status: 1, createdAt: -1 });
212
+ orderSchema.index({ paymentStatus: 1, createdAt: -1 });
213
+ orderSchema.index({ expiresAt: 1 }, {
214
+ expireAfterSeconds: 0,
215
+ partialFilterExpression: { status: "pending" }
178
216
  });
179
217
 
180
- // Indexes for performance
181
- orderSchema.index({ userId: 1, createdAt: -1 });
182
- orderSchema.index({ eventId: 1, status: 1 });
183
- orderSchema.index({ status: 1, expiresAt: 1 });
218
+ /* ----------------------------------
219
+ * Hooks
220
+ * ---------------------------------- */
184
221
 
185
- // Auto-generate order number
186
- orderSchema.pre('save', function(next) {
222
+ // Generate order number
223
+ orderSchema.pre("save", function (next) {
187
224
  if (this.isNew && !this.orderNumber) {
188
- const timestamp = Date.now().toString().slice(-6);
189
- const random = Math.random().toString(36).substring(2, 8).toUpperCase();
190
- this.orderNumber = `ORD-${timestamp}-${random}`;
225
+ const ts = Date.now().toString().slice(-6);
226
+ const rand = Math.random().toString(36).substring(2, 8).toUpperCase();
227
+ this.orderNumber = `ORD-${ts}-${rand}`;
228
+ }
229
+ next();
230
+ });
231
+
232
+ // Compute ticket count
233
+ orderSchema.pre("validate", function (next) {
234
+ if (this.tickets?.length) {
235
+ this.ticketCount = this.tickets.reduce((sum, t) => sum + t.quantity, 0);
191
236
  }
192
237
  next();
193
238
  });
194
239
 
195
- // Update updatedAt on save
196
- orderSchema.pre('save', function(next) {
197
- // Note: We don't have updatedAt field, but could add if needed
240
+ // Pricing immutability after confirmation
241
+ orderSchema.pre("save", function (next) {
242
+ if (!this.isNew && this.isModified("pricing") && this.status !== "pending") {
243
+ return next(new Error("Pricing cannot be modified after confirmation"));
244
+ }
198
245
  next();
199
246
  });
200
247
 
201
- export default orderSchema;
248
+ /* ----------------------------------
249
+ * Export
250
+ * ---------------------------------- */
251
+
252
+ export default mongoose.model("Order", orderSchema);
package/src/index.ts CHANGED
@@ -7,4 +7,5 @@ export { default as paymentSchema } from './Payment';
7
7
  export { default as orderSchema } from './Order';
8
8
  export { default as userSchema } from './User';
9
9
  export { default as eventViewsSchema } from './Event.views';
10
- export { default as payoutSchema } from './Payout';
10
+ export { default as payoutSchema } from './Payout';
11
+ export { default as auditLogSchema } from './AuditLog';