@mac777/project-pinecone-models 1.0.1 → 1.0.2

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/dist/Event.d.ts CHANGED
@@ -19,6 +19,7 @@ declare const eventSchema: mongoose.Schema<any, mongoose.Model<any, any, any, an
19
19
  visibility: "hidden" | "public" | "invite_only";
20
20
  reserved: number;
21
21
  benefits: string[];
22
+ tier: string;
22
23
  description?: string | null | undefined;
23
24
  price?: {
24
25
  amount: number;
@@ -32,7 +33,6 @@ declare const eventSchema: mongoose.Schema<any, mongoose.Model<any, any, any, an
32
33
  minPerOrder: number;
33
34
  maxPerOrder: number;
34
35
  } | null | undefined;
35
- tier?: "early_bird" | "regular" | "vip" | null | undefined;
36
36
  }, mongoose.Types.Subdocument<mongoose.mongo.BSON.ObjectId, any, {
37
37
  name: string;
38
38
  status: "active" | "sold_out" | "inactive";
@@ -42,6 +42,7 @@ declare const eventSchema: mongoose.Schema<any, mongoose.Model<any, any, any, an
42
42
  visibility: "hidden" | "public" | "invite_only";
43
43
  reserved: number;
44
44
  benefits: string[];
45
+ tier: string;
45
46
  description?: string | null | undefined;
46
47
  price?: {
47
48
  amount: number;
@@ -55,7 +56,6 @@ declare const eventSchema: mongoose.Schema<any, mongoose.Model<any, any, any, an
55
56
  minPerOrder: number;
56
57
  maxPerOrder: number;
57
58
  } | null | undefined;
58
- tier?: "early_bird" | "regular" | "vip" | null | undefined;
59
59
  }> & {
60
60
  name: string;
61
61
  status: "active" | "sold_out" | "inactive";
@@ -65,6 +65,7 @@ declare const eventSchema: mongoose.Schema<any, mongoose.Model<any, any, any, an
65
65
  visibility: "hidden" | "public" | "invite_only";
66
66
  reserved: number;
67
67
  benefits: string[];
68
+ tier: string;
68
69
  description?: string | null | undefined;
69
70
  price?: {
70
71
  amount: number;
@@ -78,7 +79,6 @@ declare const eventSchema: mongoose.Schema<any, mongoose.Model<any, any, any, an
78
79
  minPerOrder: number;
79
80
  maxPerOrder: number;
80
81
  } | null | undefined;
81
- tier?: "early_bird" | "regular" | "vip" | null | undefined;
82
82
  }>;
83
83
  termsAccepted: boolean;
84
84
  legalPermissionAccepted: boolean;
@@ -280,6 +280,7 @@ declare const eventSchema: mongoose.Schema<any, mongoose.Model<any, any, any, an
280
280
  visibility: "hidden" | "public" | "invite_only";
281
281
  reserved: number;
282
282
  benefits: string[];
283
+ tier: string;
283
284
  description?: string | null | undefined;
284
285
  price?: {
285
286
  amount: number;
@@ -293,7 +294,6 @@ declare const eventSchema: mongoose.Schema<any, mongoose.Model<any, any, any, an
293
294
  minPerOrder: number;
294
295
  maxPerOrder: number;
295
296
  } | null | undefined;
296
- tier?: "early_bird" | "regular" | "vip" | null | undefined;
297
297
  }, mongoose.Types.Subdocument<mongoose.mongo.BSON.ObjectId, any, {
298
298
  name: string;
299
299
  status: "active" | "sold_out" | "inactive";
@@ -303,6 +303,7 @@ declare const eventSchema: mongoose.Schema<any, mongoose.Model<any, any, any, an
303
303
  visibility: "hidden" | "public" | "invite_only";
304
304
  reserved: number;
305
305
  benefits: string[];
306
+ tier: string;
306
307
  description?: string | null | undefined;
307
308
  price?: {
308
309
  amount: number;
@@ -316,7 +317,6 @@ declare const eventSchema: mongoose.Schema<any, mongoose.Model<any, any, any, an
316
317
  minPerOrder: number;
317
318
  maxPerOrder: number;
318
319
  } | null | undefined;
319
- tier?: "early_bird" | "regular" | "vip" | null | undefined;
320
320
  }> & {
321
321
  name: string;
322
322
  status: "active" | "sold_out" | "inactive";
@@ -326,6 +326,7 @@ declare const eventSchema: mongoose.Schema<any, mongoose.Model<any, any, any, an
326
326
  visibility: "hidden" | "public" | "invite_only";
327
327
  reserved: number;
328
328
  benefits: string[];
329
+ tier: string;
329
330
  description?: string | null | undefined;
330
331
  price?: {
331
332
  amount: number;
@@ -339,7 +340,6 @@ declare const eventSchema: mongoose.Schema<any, mongoose.Model<any, any, any, an
339
340
  minPerOrder: number;
340
341
  maxPerOrder: number;
341
342
  } | null | undefined;
342
- tier?: "early_bird" | "regular" | "vip" | null | undefined;
343
343
  }>;
344
344
  termsAccepted: boolean;
345
345
  legalPermissionAccepted: boolean;
@@ -541,6 +541,7 @@ declare const eventSchema: mongoose.Schema<any, mongoose.Model<any, any, any, an
541
541
  visibility: "hidden" | "public" | "invite_only";
542
542
  reserved: number;
543
543
  benefits: string[];
544
+ tier: string;
544
545
  description?: string | null | undefined;
545
546
  price?: {
546
547
  amount: number;
@@ -554,7 +555,6 @@ declare const eventSchema: mongoose.Schema<any, mongoose.Model<any, any, any, an
554
555
  minPerOrder: number;
555
556
  maxPerOrder: number;
556
557
  } | null | undefined;
557
- tier?: "early_bird" | "regular" | "vip" | null | undefined;
558
558
  }, mongoose.Types.Subdocument<mongoose.mongo.BSON.ObjectId, any, {
559
559
  name: string;
560
560
  status: "active" | "sold_out" | "inactive";
@@ -564,6 +564,7 @@ declare const eventSchema: mongoose.Schema<any, mongoose.Model<any, any, any, an
564
564
  visibility: "hidden" | "public" | "invite_only";
565
565
  reserved: number;
566
566
  benefits: string[];
567
+ tier: string;
567
568
  description?: string | null | undefined;
568
569
  price?: {
569
570
  amount: number;
@@ -577,7 +578,6 @@ declare const eventSchema: mongoose.Schema<any, mongoose.Model<any, any, any, an
577
578
  minPerOrder: number;
578
579
  maxPerOrder: number;
579
580
  } | null | undefined;
580
- tier?: "early_bird" | "regular" | "vip" | null | undefined;
581
581
  }> & {
582
582
  name: string;
583
583
  status: "active" | "sold_out" | "inactive";
@@ -587,6 +587,7 @@ declare const eventSchema: mongoose.Schema<any, mongoose.Model<any, any, any, an
587
587
  visibility: "hidden" | "public" | "invite_only";
588
588
  reserved: number;
589
589
  benefits: string[];
590
+ tier: string;
590
591
  description?: string | null | undefined;
591
592
  price?: {
592
593
  amount: number;
@@ -600,7 +601,6 @@ declare const eventSchema: mongoose.Schema<any, mongoose.Model<any, any, any, an
600
601
  minPerOrder: number;
601
602
  maxPerOrder: number;
602
603
  } | null | undefined;
603
- tier?: "early_bird" | "regular" | "vip" | null | undefined;
604
604
  }>;
605
605
  termsAccepted: boolean;
606
606
  legalPermissionAccepted: boolean;
package/dist/Event.js CHANGED
@@ -94,7 +94,7 @@ const ticketSchema = new mongoose_1.default.Schema({
94
94
  reserved: { type: Number, default: 0 },
95
95
  status: { type: String, enum: ['active', 'sold_out', 'inactive'], default: 'active' },
96
96
  benefits: [String],
97
- tier: { type: String, enum: ['early_bird', 'regular', 'vip'] },
97
+ tier: { type: String, required: true, default: 'regular' },
98
98
  });
99
99
  const scheduleSchema = new mongoose_1.default.Schema({
100
100
  startDate: { type: Date, required: true },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mac777/project-pinecone-models",
3
- "version": "1.0.1",
3
+ "version": "1.0.2",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "scripts": {
@@ -12,10 +12,6 @@
12
12
  "zod": "^3.22.4",
13
13
  "zxcvbn": "^4.4.2"
14
14
  },
15
- "files": ["dist"],
16
- "publishConfig": {
17
- "access": "public"
18
- },
19
15
  "devDependencies": {
20
16
  "typescript": "^5.0.0"
21
17
  }
package/src/Bkash.ts ADDED
@@ -0,0 +1,10 @@
1
+ import mongoose from 'mongoose';
2
+
3
+ const bkashSchema = new mongoose.Schema({
4
+ auth_token: {
5
+ type: String,
6
+ required: true,
7
+ }
8
+ }, { timestamps: true });
9
+
10
+ export default bkashSchema;
package/src/Event.ts ADDED
@@ -0,0 +1,274 @@
1
+ import mongoose from 'mongoose';
2
+
3
+ const mediaSchema = new mongoose.Schema({
4
+ coverImage: {
5
+ url: String,
6
+ thumbnailUrl: String,
7
+ alt: String,
8
+ },
9
+ gallery: [{
10
+ url: String,
11
+ caption: String,
12
+ order: Number,
13
+ }],
14
+ }, { _id: false });
15
+
16
+ const addressSchema = new mongoose.Schema({
17
+ street: String,
18
+ city: { type: String, required: true },
19
+ state: String,
20
+ postalCode: String,
21
+ country: { type: String, required: true },
22
+ }, { _id: false });
23
+
24
+ const venueSchema = new mongoose.Schema({
25
+ name: { type: String, required: true },
26
+ address: addressSchema,
27
+ coordinates: {
28
+ type: {
29
+ type: String,
30
+ enum: ['Point'],
31
+ default: 'Point'
32
+ },
33
+ coordinates: [Number] // [lng, lat]
34
+ },
35
+ capacity: { type: Number, required: true, min: 10, max: 100000 },
36
+ type: { type: String, enum: ['indoor', 'outdoor', 'hybrid'] },
37
+ parking: Boolean,
38
+ publicTransit: String,
39
+ }, { _id: false });
40
+
41
+ const contactPersonSchema = new mongoose.Schema({
42
+ name: { type: String, required: true },
43
+ phone: { type: String, required: true },
44
+ email: { type: String, required: true },
45
+ designation: String,
46
+ }, { _id: false });
47
+
48
+ const organizerSchema = new mongoose.Schema({
49
+ role: { type: String, enum: ['event_organizer', 'venue_owner', 'authorized_rep', 'artist'] },
50
+ companyName: String,
51
+ contactPerson: contactPersonSchema,
52
+ }, { _id: false });
53
+
54
+ const documentSchema = new mongoose.Schema({
55
+ type: { type: String, enum: ['venue_booking', 'permit', 'insurance', 'license', 'portfolio', 'other'] },
56
+ url: String,
57
+ filename: String,
58
+ objectKey: String,
59
+ uploadedAt: Date,
60
+ status: { type: String, enum: ['pending', 'approved', 'rejected'] },
61
+ rejectionReason: String,
62
+ }, { _id: false });
63
+
64
+ const verificationSchema = new mongoose.Schema({
65
+ status: { type: String, enum: ['unverified', 'pending', 'verified', 'rejected', 'needs_info'], default: 'unverified' },
66
+ documents: [documentSchema],
67
+ additionalInfo: String,
68
+ adminNotes: String,
69
+ reviewedBy: mongoose.Schema.Types.ObjectId,
70
+ reviewedAt: Date,
71
+ rejectionReason: String,
72
+ requestedInfo: String,
73
+ }, { _id: false });
74
+
75
+ const priceSchema = new mongoose.Schema({
76
+ amount: { type: Number, required: true },
77
+ currency: { type: String, default: 'USD' },
78
+ }, { _id: false });
79
+
80
+ const salesWindowSchema = new mongoose.Schema({
81
+ startDate: Date,
82
+ endDate: Date,
83
+ }, { _id: false });
84
+
85
+ const limitsSchema = new mongoose.Schema({
86
+ minPerOrder: { type: Number, default: 1 },
87
+ maxPerOrder: { type: Number, default: 10 },
88
+ }, { _id: false });
89
+
90
+ const ticketSchema = new mongoose.Schema({
91
+ name: { type: String, required: true },
92
+ description: String,
93
+ price: priceSchema,
94
+ quantity: { type: Number, required: true },
95
+ sold: { type: Number, default: 0 },
96
+ remaining: { type: Number, default: function(this: any) { return this.quantity - this.sold; } },
97
+ salesWindow: salesWindowSchema,
98
+ limits: limitsSchema,
99
+ visibility: { type: String, enum: ['public', 'hidden', 'invite_only'], default: 'public' },
100
+ reserved: { type: Number, default: 0 },
101
+ status: { type: String, enum: ['active', 'sold_out', 'inactive'], default: 'active' },
102
+ benefits: [String],
103
+ tier: { type: String, required: true, default: 'regular' },
104
+ });
105
+
106
+ const scheduleSchema = new mongoose.Schema({
107
+ startDate: { type: Date, required: true },
108
+ endDate: { type: Date, required: true },
109
+ timezone: String,
110
+ isMultiDay: Boolean,
111
+ doors: String,
112
+ }, { _id: false });
113
+
114
+ const metricsSchema = new mongoose.Schema({
115
+ views: { type: Number, default: 0 },
116
+ ticketsSold: { type: Number, default: 0 },
117
+ revenue: { type: Number, default: 0 },
118
+ checkIns: { type: Number, default: 0 },
119
+ averageRating: Number,
120
+ reviewCount: { type: Number, default: 0 },
121
+ }, { _id: false });
122
+
123
+ const pricingSchema = new mongoose.Schema({
124
+ platformFee: { type: Number, default: 5 },
125
+ paymentProcessingFee: Number,
126
+ currency: String,
127
+ }, { _id: false });
128
+
129
+ const payoutSchema = new mongoose.Schema({
130
+ status: { type: String, enum: ['pending', 'scheduled', 'completed'] },
131
+ amount: Number,
132
+ scheduledDate: Date,
133
+ paidAt: Date,
134
+ stripePayoutId: String,
135
+ }, { _id: false });
136
+
137
+ const cancellationSchema = new mongoose.Schema({
138
+ allowed: { type: Boolean, default: true },
139
+ refundPercentage: { type: Number, default: 100 },
140
+ deadlineHours: Number,
141
+ }, { _id: false });
142
+
143
+ const policiesSchema = new mongoose.Schema({
144
+ cancellation: cancellationSchema,
145
+ transferable: { type: Boolean, default: false },
146
+ }, { _id: false });
147
+
148
+ const flagSchema = new mongoose.Schema({
149
+ reportedBy: mongoose.Schema.Types.ObjectId,
150
+ reason: String,
151
+ description: String,
152
+ createdAt: { type: Date, default: Date.now },
153
+ status: { type: String, enum: ['pending', 'resolved', 'dismissed'], default: 'pending' },
154
+ }, { _id: false });
155
+
156
+ const moderationSchema = new mongoose.Schema({
157
+ isFlagged: { type: Boolean, default: false },
158
+ flags: [flagSchema],
159
+ suspendedUntil: Date,
160
+ banReason: String,
161
+ }, { _id: false });
162
+
163
+ const seoSchema = new mongoose.Schema({
164
+ metaTitle: String,
165
+ metaDescription: String,
166
+ keywords: [String],
167
+ ogImage: String,
168
+ }, { _id: false });
169
+
170
+ const featuresSchema = new mongoose.Schema({
171
+ isFeatured: { type: Boolean, default: false },
172
+ isPremium: { type: Boolean, default: false },
173
+ badges: [String],
174
+ }, { _id: false });
175
+
176
+ const historySchema = new mongoose.Schema({
177
+ action: String,
178
+ performedBy: mongoose.Schema.Types.ObjectId,
179
+ timestamp: { type: Date, default: Date.now },
180
+ changes: mongoose.Schema.Types.Mixed,
181
+ }, { _id: false });
182
+
183
+ const eventSchema = new mongoose.Schema({
184
+ hostId: { type: mongoose.Schema.Types.ObjectId, required: true },
185
+ slug: String,
186
+
187
+ // STEP 1: BASICS
188
+ title: { type: String, required: true, minlength: 10, maxlength: 100 },
189
+ type: { type: String, enum: ['concert', 'sports', 'conference', 'festival', 'theater', 'comedy', 'networking', 'workshop', 'other'], required: true },
190
+ categories: [{ type: String }],
191
+ tagline: { type: String, maxlength: 150 },
192
+
193
+ // STEP 2: DETAILS
194
+ description: { type: String, minlength: 50, maxlength: 5000 },
195
+ highlights: [{ type: String }],
196
+ languages: [String],
197
+ ageRestriction: { type: String, enum: ['all_ages', '18+', '21+'] },
198
+ dressCode: String,
199
+
200
+ media: mediaSchema,
201
+
202
+ // STEP 3: DATE, TIME & LOCATION
203
+ schedule: scheduleSchema,
204
+ venue: venueSchema,
205
+
206
+ // STEP 4: VERIFICATION
207
+ organizer: organizerSchema,
208
+ verification: verificationSchema,
209
+
210
+ // STEP 5: TICKETS
211
+ tickets: [ticketSchema],
212
+ termsAccepted: { type: Boolean, default: false },
213
+ legalPermissionAccepted: { type: Boolean, default: false },
214
+ platformTermsAccepted: { type: Boolean, default: false },
215
+ // STATUS & WORKFLOW
216
+ status: { type: String, enum: ['draft', 'pending_approval', 'approved', 'rejected', 'published', 'live', 'ended', 'cancelled'], default: 'draft' },
217
+ rejectionReason: String,
218
+ visibility: { type: String, enum: ['public', 'private', 'unlisted'], default: 'public' },
219
+ publishedAt: Date,
220
+
221
+ // METRICS
222
+ metrics: metricsSchema,
223
+
224
+ // BUSINESS
225
+ pricing: pricingSchema,
226
+ payout: payoutSchema,
227
+
228
+ // POLICIES
229
+ policies: policiesSchema,
230
+
231
+ // MODERATION
232
+ moderation: moderationSchema,
233
+
234
+ // SEO
235
+ seo: seoSchema,
236
+
237
+ // FEATURES
238
+ features: featuresSchema,
239
+
240
+ // AUDIT
241
+ createdAt: { type: Date, default: Date.now },
242
+ updatedAt: { type: Date, default: Date.now },
243
+ submittedAt: Date,
244
+ history: [historySchema],
245
+ deletedAt: Date,
246
+ });
247
+
248
+ // Indexes
249
+ eventSchema.index({ slug: 1 });
250
+ eventSchema.index({ 'venue.coordinates': '2dsphere' });
251
+ eventSchema.index({ status: 1, visibility: 1 });
252
+ eventSchema.index({ hostId: 1 });
253
+ eventSchema.index({ 'schedule.startDate': 1 });
254
+ eventSchema.index({ type: 1 });
255
+ eventSchema.index({ categories: 1 });
256
+
257
+ // Validation: sum(tickets.quantity) <= venue.capacity
258
+ eventSchema.pre('save', function(next) {
259
+ if (this.tickets && this.tickets.length > 0 && this.venue) {
260
+ const totalCapacity = this.tickets.reduce((sum, ticket) => sum + ticket.quantity, 0);
261
+ if (totalCapacity > this.venue.capacity) {
262
+ return next(new Error('Total ticket quantity exceeds venue capacity'));
263
+ }
264
+ }
265
+ next();
266
+ });
267
+
268
+ // Update updatedAt on save
269
+ eventSchema.pre('save', function(next) {
270
+ this.updatedAt = new Date();
271
+ next();
272
+ });
273
+
274
+ export default eventSchema;
package/src/Media.ts ADDED
@@ -0,0 +1,36 @@
1
+ import mongoose from 'mongoose';
2
+
3
+ const mediaSchema = new mongoose.Schema({
4
+ userId: { type: mongoose.Schema.Types.ObjectId, required: true },
5
+ type: { type: String, enum: ['event_cover', 'event_gallery', 'verification_doc'], required: true },
6
+ provider: { type: String, enum: ['imagekit', 'backblaze'], required: true },
7
+ status: { type: String, enum: ['temp', 'permanent', 'deleted'], required: true },
8
+
9
+ // ImageKit specific
10
+ fileId: String,
11
+ url: String,
12
+ thumbnailUrl: String,
13
+
14
+ // Backblaze specific
15
+ bucketName: String,
16
+ objectKey: String,
17
+
18
+ // Metadata
19
+ filename: { type: String, required: true },
20
+ mimeType: { type: String, required: true },
21
+ size: { type: Number, required: false },
22
+
23
+ // Lifecycle
24
+ uploadedAt: { type: Date, default: Date.now },
25
+ movedToPermanentAt: Date,
26
+ expiresAt: Date, // For temp files
27
+ deletedAt: Date,
28
+ });
29
+
30
+ // Indexes
31
+ mediaSchema.index({ userId: 1 });
32
+ mediaSchema.index({ status: 1 });
33
+ mediaSchema.index({ expiresAt: 1 });
34
+ mediaSchema.index({ uploadedAt: 1 });
35
+
36
+ export default mediaSchema;
package/src/Order.ts ADDED
@@ -0,0 +1,201 @@
1
+ import mongoose from 'mongoose';
2
+
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
27
+ }
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']
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
178
+ });
179
+
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 });
184
+
185
+ // Auto-generate order number
186
+ orderSchema.pre('save', function(next) {
187
+ 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}`;
191
+ }
192
+ next();
193
+ });
194
+
195
+ // Update updatedAt on save
196
+ orderSchema.pre('save', function(next) {
197
+ // Note: We don't have updatedAt field, but could add if needed
198
+ next();
199
+ });
200
+
201
+ export default orderSchema;
package/src/Payment.ts ADDED
@@ -0,0 +1,61 @@
1
+ import mongoose from 'mongoose';
2
+
3
+ // Payment schema for transaction logging
4
+ const paymentSchema = new mongoose.Schema({
5
+ // LINKS
6
+ orderId: { type: mongoose.Schema.Types.ObjectId, required: true, index: true }, // Which order
7
+ userId: { type: mongoose.Schema.Types.ObjectId, required: true, index: true }, // Who paid
8
+
9
+ paymentId: { type: String, required: true, unique: true, index: true }, // Stripe PI (unique)
10
+
11
+ // MONEY
12
+ amount: { type: Number, required: true },
13
+ currency: { type: String, required: true, default: 'BDT' },
14
+
15
+ // STATUS
16
+ status: {
17
+ type: String,
18
+ required: true,
19
+ enum: ['pending', 'succeeded', 'failed', 'refunded'],
20
+ default: 'pending'
21
+ },
22
+
23
+ // METADATA
24
+ paymentMethod: { type: String, required: true, enum: ['bkash', 'card'] },
25
+ last4: String, // Card last 4 digits (for receipt)
26
+ brand: { type: String, enum: ['visa', 'mastercard', 'amex', 'discover'] }, // Card brand
27
+
28
+ // FAILURE (if failed)
29
+ failureCode: String, // "insufficient_funds", "card_declined", etc.
30
+ failureMessage: String,
31
+
32
+ // REFUND (if refunded)
33
+ refundId: String, // Stripe refund ID
34
+ refundAmount: Number,
35
+ refundedAt: Date,
36
+
37
+ // TIMESTAMPS
38
+ createdAt: { type: Date, default: Date.now },
39
+ succeededAt: Date,
40
+ failedAt: Date,
41
+ });
42
+
43
+ // Indexes for performance
44
+ paymentSchema.index({ orderId: 1 });
45
+ paymentSchema.index({ userId: 1, createdAt: -1 });
46
+ paymentSchema.index({ status: 1, createdAt: -1 });
47
+
48
+ // Pre-save middleware to set timestamps based on status
49
+ paymentSchema.pre('save', function(next) {
50
+ if (this.isModified('status')) {
51
+ const now = new Date();
52
+ if (this.status === 'succeeded' && !this.succeededAt) {
53
+ this.succeededAt = now;
54
+ } else if (this.status === 'failed' && !this.failedAt) {
55
+ this.failedAt = now;
56
+ }
57
+ }
58
+ next();
59
+ });
60
+
61
+ export default paymentSchema;
package/src/Ticket.ts ADDED
@@ -0,0 +1,105 @@
1
+ import mongoose from 'mongoose';
2
+
3
+ // Ticket schema for individual issued tickets
4
+ const ticketSchema = new mongoose.Schema({
5
+ ticketNumber: { type: String, required: true, unique: true, index: true }, // Human-readable: "TKT-EVT123-A3K9-01"
6
+
7
+ // BELONGS TO
8
+ orderId: { type: mongoose.Schema.Types.ObjectId, required: true, index: true }, // Parent order
9
+ eventId: { type: mongoose.Schema.Types.ObjectId, required: true, index: true }, // Which event
10
+ userId: { type: mongoose.Schema.Types.ObjectId, required: true, index: true }, // Owner
11
+ ticketVariantId: { type: mongoose.Schema.Types.ObjectId, required: true }, // Which type (VIP, GA, etc)
12
+
13
+ // DETAILS (denormalized for speed)
14
+ eventTitle: { type: String, required: true },
15
+ eventDate: { type: Date, required: true },
16
+ eventVenue: { type: String, required: true },
17
+ ticketType: { type: String, required: true }, // "VIP Pass"
18
+ price: { type: Number, required: true },
19
+
20
+ // QR CODE
21
+ qrCode: { type: String, unique: true, required: true }, // Unique hash: SHA256(ticketId + secret)
22
+ qrCodeUrl: { type: String, required: true }, // ImageKit/S3 URL to QR image
23
+
24
+ // STATUS
25
+ status: {
26
+ type: String,
27
+ required: true,
28
+ enum: ['valid', 'used', 'cancelled', 'refunded', 'transferred'],
29
+ default: 'valid',
30
+ index: true
31
+ },
32
+
33
+ // CHECK-IN
34
+ checkInStatus: {
35
+ type: String,
36
+ required: true,
37
+ enum: ['not_checked_in', 'checked_in'],
38
+ default: 'not_checked_in'
39
+ },
40
+ checkedInAt: Date,
41
+ checkedInBy: mongoose.Schema.Types.ObjectId, // Staff/scanner user ID
42
+
43
+ // TRANSFER (if user transfers ticket to friend)
44
+ transferredTo: mongoose.Schema.Types.ObjectId, // New owner user ID
45
+ transferredAt: Date,
46
+
47
+ // LIFECYCLE
48
+ issuedAt: { type: Date, default: Date.now }, // When ticket was created
49
+ validUntil: { type: Date, required: true }, // Event end date (after this, ticket expires)
50
+
51
+ // SECURITY
52
+ secretHash: { type: String, required: true }, // Internal validation hash (never exposed)
53
+ });
54
+
55
+
56
+ // Pre-save middleware to set default validUntil if not provided
57
+ ticketSchema.pre('save', function(next) {
58
+ if (this.isNew && !this.validUntil && this.eventDate) {
59
+ // Set validUntil to end of event day if eventDate is provided
60
+ const eventEnd = new Date(this.eventDate);
61
+ eventEnd.setHours(23, 59, 59, 999); // End of the event day
62
+ this.validUntil = eventEnd;
63
+ }
64
+ next();
65
+ });
66
+
67
+ // Virtual for checking if ticket is expired
68
+ ticketSchema.virtual('isExpired').get(function() {
69
+ return new Date() > this.validUntil;
70
+ });
71
+
72
+ // Method to check if ticket can be used
73
+ ticketSchema.methods.canBeUsed = function() {
74
+ return this.status === 'valid' &&
75
+ this.checkInStatus === 'not_checked_in' &&
76
+ !this.isExpired;
77
+ };
78
+
79
+ // Method to mark as used (check-in)
80
+ ticketSchema.methods.checkIn = function(staffUserId: string) {
81
+ if (!this.canBeUsed()) {
82
+ throw new Error('Ticket cannot be checked in');
83
+ }
84
+
85
+ this.checkInStatus = 'checked_in';
86
+ this.checkedInAt = new Date();
87
+ this.checkedInBy = new mongoose.Types.ObjectId(staffUserId);
88
+
89
+ return this.save();
90
+ };
91
+
92
+ // Method to transfer ticket
93
+ ticketSchema.methods.transfer = function(newOwnerId: string) {
94
+ if (this.status !== 'valid') {
95
+ throw new Error('Only valid tickets can be transferred');
96
+ }
97
+
98
+ this.transferredTo = new mongoose.Types.ObjectId(newOwnerId);
99
+ this.transferredAt = new Date();
100
+ this.userId = new mongoose.Types.ObjectId(newOwnerId); // Update ownership
101
+
102
+ return this.save();
103
+ };
104
+
105
+ export default ticketSchema;
package/src/User.ts ADDED
@@ -0,0 +1,47 @@
1
+ import mongoose from "mongoose";
2
+
3
+ const userSchema = new mongoose.Schema({
4
+ firstName: {
5
+ type: String,
6
+ required: true
7
+ },
8
+ lastName: {
9
+ type: String,
10
+ required: true
11
+ },
12
+ email: {
13
+ type: String,
14
+ required: true,
15
+ unique: true
16
+ },
17
+ password: {
18
+ type: String,
19
+ required: false
20
+ },
21
+ organization: {
22
+ type: String,
23
+ required: false
24
+ },
25
+ role: {
26
+ type: String,
27
+ enum: ['user', 'host', 'admin'],
28
+ default: 'user'
29
+ },
30
+ refreshToken: {
31
+ type: String,
32
+ required: false
33
+ },
34
+ provider: {
35
+ type: String,
36
+ enum: ['google', 'local'],
37
+ default: 'local'
38
+ },
39
+ googleId: {
40
+ type: String,
41
+ required: false
42
+ }
43
+ }, {
44
+ timestamps: true
45
+ })
46
+
47
+ export default userSchema;
package/src/index.ts ADDED
@@ -0,0 +1,9 @@
1
+ // Shared database models for Pinecone microservices
2
+ export { default as eventSchema } from './Event';
3
+ export { default as ticketSchema } from './Ticket';
4
+ export { default as mediaSchema } from './Media';
5
+ export { default as bkashSchema } from './Bkash';
6
+ export { default as paymentSchema } from './Payment';
7
+ export { default as orderSchema } from './Order';
8
+ export { default as userSchema } from './User';
9
+
package/tsconfig.json ADDED
@@ -0,0 +1,16 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2020",
4
+ "module": "CommonJS",
5
+ "moduleResolution": "node",
6
+ "declaration": true,
7
+ "outDir": "dist",
8
+ "strict": true,
9
+ "esModuleInterop": true,
10
+ "skipLibCheck": true,
11
+ "forceConsistentCasingInFileNames": true,
12
+ "resolveJsonModule": true
13
+ },
14
+ "include": ["src/**/*"],
15
+ "exclude": ["node_modules", "dist", "**/*.test.ts"]
16
+ }