@bash-app/bash-common 30.113.0 → 30.115.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/dist/definitions.d.ts +2 -2
- package/dist/definitions.d.ts.map +1 -1
- package/dist/definitions.js +2 -2
- package/dist/definitions.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/utils/__tests__/recurrenceUtils.test.d.ts +2 -0
- package/dist/utils/__tests__/recurrenceUtils.test.d.ts.map +1 -0
- package/dist/utils/__tests__/recurrenceUtils.test.js +193 -0
- package/dist/utils/__tests__/recurrenceUtils.test.js.map +1 -0
- package/dist/utils/discountEngine/bestPriceResolver.d.ts +31 -0
- package/dist/utils/discountEngine/bestPriceResolver.d.ts.map +1 -0
- package/dist/utils/discountEngine/bestPriceResolver.js +147 -0
- package/dist/utils/discountEngine/bestPriceResolver.js.map +1 -0
- package/dist/utils/discountEngine/discountCalculator.d.ts +56 -0
- package/dist/utils/discountEngine/discountCalculator.d.ts.map +1 -0
- package/dist/utils/discountEngine/discountCalculator.js +219 -0
- package/dist/utils/discountEngine/discountCalculator.js.map +1 -0
- package/dist/utils/discountEngine/eligibilityValidator.d.ts +36 -0
- package/dist/utils/discountEngine/eligibilityValidator.d.ts.map +1 -0
- package/dist/utils/discountEngine/eligibilityValidator.js +189 -0
- package/dist/utils/discountEngine/eligibilityValidator.js.map +1 -0
- package/dist/utils/discountEngine/index.d.ts +4 -0
- package/dist/utils/discountEngine/index.d.ts.map +1 -0
- package/dist/utils/discountEngine/index.js +5 -0
- package/dist/utils/discountEngine/index.js.map +1 -0
- package/dist/utils/recurrenceUtils.d.ts.map +1 -1
- package/dist/utils/recurrenceUtils.js +17 -4
- package/dist/utils/recurrenceUtils.js.map +1 -1
- package/package.json +5 -5
- package/prisma/schema.prisma +387 -81
- package/src/definitions.ts +2 -1
- package/src/index.ts +2 -0
- package/src/utils/discountEngine/bestPriceResolver.ts +212 -0
- package/src/utils/discountEngine/discountCalculator.ts +281 -0
- package/src/utils/discountEngine/eligibilityValidator.ts +256 -0
- package/src/utils/discountEngine/index.ts +5 -0
- package/src/utils/recurrenceUtils.ts +20 -4
package/prisma/schema.prisma
CHANGED
|
@@ -54,15 +54,20 @@ model BashComment {
|
|
|
54
54
|
|
|
55
55
|
// BashFeed Models - Event-Centric Social Discovery Feed
|
|
56
56
|
model BashFeedPost {
|
|
57
|
-
id
|
|
58
|
-
userId
|
|
59
|
-
bashId
|
|
60
|
-
content
|
|
61
|
-
mediaIds
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
57
|
+
id String @id @default(cuid())
|
|
58
|
+
userId String
|
|
59
|
+
bashId String
|
|
60
|
+
content String? @db.Text
|
|
61
|
+
mediaIds String[] // Array of Media IDs
|
|
62
|
+
mentionedUserIds String[] // Array of User IDs mentioned in post
|
|
63
|
+
isAnonymous Boolean @default(false) // User can choose to post anonymously
|
|
64
|
+
viewCount Int @default(0) // Analytics only, not shown publicly
|
|
65
|
+
isFeatured Boolean @default(false) // Post is promoted/featured
|
|
66
|
+
featuredAt DateTime? // When post was featured
|
|
67
|
+
featuredBoost Float @default(0) // Current boost score (time-decayed)
|
|
68
|
+
createdAt DateTime @default(now())
|
|
69
|
+
updatedAt DateTime @updatedAt
|
|
70
|
+
editedAt DateTime?
|
|
66
71
|
|
|
67
72
|
// Relationships
|
|
68
73
|
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
@@ -78,6 +83,7 @@ model BashFeedPost {
|
|
|
78
83
|
@@index([userId])
|
|
79
84
|
@@index([createdAt])
|
|
80
85
|
@@index([isAnonymous])
|
|
86
|
+
@@index([isFeatured, featuredBoost])
|
|
81
87
|
}
|
|
82
88
|
|
|
83
89
|
model BashFeedLike {
|
|
@@ -94,13 +100,14 @@ model BashFeedLike {
|
|
|
94
100
|
}
|
|
95
101
|
|
|
96
102
|
model BashFeedComment {
|
|
97
|
-
id
|
|
98
|
-
userId
|
|
99
|
-
postId
|
|
100
|
-
content
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
103
|
+
id String @id @default(cuid())
|
|
104
|
+
userId String
|
|
105
|
+
postId String
|
|
106
|
+
content String @db.Text
|
|
107
|
+
mentionedUserIds String[] // Array of User IDs mentioned in comment
|
|
108
|
+
parentId String? // For nested replies
|
|
109
|
+
createdAt DateTime @default(now())
|
|
110
|
+
updatedAt DateTime @updatedAt
|
|
104
111
|
|
|
105
112
|
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
106
113
|
post BashFeedPost @relation(fields: [postId], references: [id], onDelete: Cascade)
|
|
@@ -194,29 +201,36 @@ model BashFeedRepost {
|
|
|
194
201
|
}
|
|
195
202
|
|
|
196
203
|
model Competition {
|
|
197
|
-
id String
|
|
204
|
+
id String @id @default(cuid())
|
|
198
205
|
name String
|
|
199
|
-
description String
|
|
206
|
+
description String @db.Text
|
|
200
207
|
userId String
|
|
201
208
|
bashEventId String
|
|
202
209
|
numberOfPrizes Int
|
|
203
210
|
competitionType CompetitionType? // Main category
|
|
204
211
|
subtype String? // Subcategory
|
|
205
|
-
rules String?
|
|
212
|
+
rules String? @db.Text // Detailed rules/disclaimers
|
|
206
213
|
judgingType JudgingType? // How winner is determined
|
|
207
214
|
startTime DateTime? // Competition start time (for voting)
|
|
208
215
|
endTime DateTime? // Competition end time (for voting)
|
|
209
|
-
allowSelfRegistration Boolean
|
|
216
|
+
allowSelfRegistration Boolean @default(false)
|
|
210
217
|
maxParticipants Int? // Optional cap on participants
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
218
|
+
|
|
219
|
+
// Tournament bracket fields
|
|
220
|
+
bracketType BracketType? @default(NONE)
|
|
221
|
+
bracketData Json? // Store bracket structure/metadata
|
|
222
|
+
bracketVisible Boolean @default(true)
|
|
223
|
+
|
|
224
|
+
createdAt DateTime @default(now())
|
|
225
|
+
updatedAt DateTime @updatedAt
|
|
226
|
+
bashEvent BashEvent @relation(fields: [bashEventId], references: [id], onDelete: Cascade)
|
|
227
|
+
owner User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
228
|
+
sponsor CompetitionSponsor[]
|
|
229
|
+
prizes Prize[]
|
|
230
|
+
participants CompetitionParticipant[]
|
|
231
|
+
votes CompetitionVote[]
|
|
232
|
+
matches CompetitionMatch[]
|
|
233
|
+
notifications Notification[]
|
|
220
234
|
|
|
221
235
|
@@index([bashEventId])
|
|
222
236
|
@@index([competitionType])
|
|
@@ -238,20 +252,63 @@ model CompetitionParticipant {
|
|
|
238
252
|
id String @id @default(cuid())
|
|
239
253
|
competitionId String
|
|
240
254
|
userId String? // Optional: links to user if registered
|
|
255
|
+
email String? // For non-registered participants
|
|
241
256
|
name String // Display name
|
|
242
257
|
description String? @db.Text // Why they should win
|
|
243
258
|
imageUrl String? // Photo/avatar
|
|
244
259
|
order Int @default(0) // Display order
|
|
245
260
|
voteCount Int @default(0) // Denormalized for performance
|
|
261
|
+
isEliminated Boolean @default(false) // For tournament brackets
|
|
262
|
+
placement Int? // Final placement (1st, 2nd, 3rd, etc.)
|
|
246
263
|
addedBy String @default("host") // 'host' or 'self'
|
|
264
|
+
status ParticipantStatus @default(ACCEPTED) // Invitation/request status
|
|
265
|
+
invitedAt DateTime? // When host invited them
|
|
266
|
+
acceptedAt DateTime? // When they accepted invitation
|
|
267
|
+
declinedAt DateTime? // When they declined invitation/request
|
|
247
268
|
createdAt DateTime @default(now())
|
|
248
269
|
competition Competition @relation(fields: [competitionId], references: [id], onDelete: Cascade)
|
|
249
270
|
user User? @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
250
271
|
votes CompetitionVote[]
|
|
251
272
|
|
|
273
|
+
// Tournament bracket relations
|
|
274
|
+
matchesAsParticipant1 CompetitionMatch[] @relation("MatchParticipant1")
|
|
275
|
+
matchesAsParticipant2 CompetitionMatch[] @relation("MatchParticipant2")
|
|
276
|
+
matchesWon CompetitionMatch[] @relation("MatchWinner")
|
|
277
|
+
|
|
252
278
|
@@index([competitionId])
|
|
253
279
|
@@index([userId])
|
|
280
|
+
@@index([email])
|
|
254
281
|
@@index([voteCount])
|
|
282
|
+
@@index([status])
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
// Tournament bracket matches
|
|
286
|
+
model CompetitionMatch {
|
|
287
|
+
id String @id @default(cuid())
|
|
288
|
+
competitionId String
|
|
289
|
+
round Int // 1 = first round, 2 = semifinals, etc.
|
|
290
|
+
matchNumber Int // Position in round (1, 2, 3...)
|
|
291
|
+
|
|
292
|
+
participant1Id String?
|
|
293
|
+
participant2Id String?
|
|
294
|
+
winnerId String?
|
|
295
|
+
|
|
296
|
+
scheduledTime DateTime?
|
|
297
|
+
completedAt DateTime?
|
|
298
|
+
score Json? // {participant1: 10, participant2: 8}
|
|
299
|
+
notes String? // Match notes
|
|
300
|
+
|
|
301
|
+
competition Competition @relation(fields: [competitionId], references: [id], onDelete: Cascade)
|
|
302
|
+
participant1 CompetitionParticipant? @relation("MatchParticipant1", fields: [participant1Id], references: [id])
|
|
303
|
+
participant2 CompetitionParticipant? @relation("MatchParticipant2", fields: [participant2Id], references: [id])
|
|
304
|
+
winner CompetitionParticipant? @relation("MatchWinner", fields: [winnerId], references: [id])
|
|
305
|
+
|
|
306
|
+
createdAt DateTime @default(now())
|
|
307
|
+
updatedAt DateTime @updatedAt
|
|
308
|
+
|
|
309
|
+
@@unique([competitionId, round, matchNumber])
|
|
310
|
+
@@index([competitionId])
|
|
311
|
+
@@index([round])
|
|
255
312
|
}
|
|
256
313
|
|
|
257
314
|
model CompetitionVote {
|
|
@@ -617,6 +674,9 @@ model BashEvent {
|
|
|
617
674
|
bashFeedRatings BashFeedRating[]
|
|
618
675
|
eventRankings EventRankings?
|
|
619
676
|
|
|
677
|
+
// Analytics Relations
|
|
678
|
+
analyticsPredictions AnalyticsPrediction[]
|
|
679
|
+
|
|
620
680
|
@@index([templateId])
|
|
621
681
|
@@index([parentEventId])
|
|
622
682
|
}
|
|
@@ -630,14 +690,15 @@ model Coordinates {
|
|
|
630
690
|
}
|
|
631
691
|
|
|
632
692
|
model Checkout {
|
|
633
|
-
id String
|
|
693
|
+
id String @id @default(cuid())
|
|
634
694
|
ownerId String
|
|
635
695
|
bashEventId String
|
|
636
|
-
checkoutDateTime DateTime?
|
|
637
|
-
stripeCheckoutSessionId String?
|
|
638
|
-
bashEvent BashEvent
|
|
639
|
-
owner User
|
|
696
|
+
checkoutDateTime DateTime? @default(now())
|
|
697
|
+
stripeCheckoutSessionId String? @unique
|
|
698
|
+
bashEvent BashEvent @relation(fields: [bashEventId], references: [id], onDelete: Cascade)
|
|
699
|
+
owner User @relation(fields: [ownerId], references: [id], onDelete: Cascade)
|
|
640
700
|
tickets Ticket[]
|
|
701
|
+
appliedDiscounts AppliedDiscount[] // NEW - Discounts applied to this checkout
|
|
641
702
|
|
|
642
703
|
@@index([bashEventId])
|
|
643
704
|
}
|
|
@@ -784,12 +845,14 @@ model TicketTier {
|
|
|
784
845
|
tickets Ticket[]
|
|
785
846
|
bashEvent BashEvent @relation(fields: [bashEventId], references: [id], onDelete: Cascade)
|
|
786
847
|
waitList User[] @relation("TicketTierToUser")
|
|
848
|
+
specialOffers SpecialOffer[] // NEW - Special offers for this tier
|
|
849
|
+
appliedDiscounts AppliedDiscount[] // NEW - Discounts applied to this tier
|
|
787
850
|
|
|
788
851
|
@@unique([bashEventId, title])
|
|
789
852
|
}
|
|
790
853
|
|
|
791
854
|
model Ticket {
|
|
792
|
-
id String
|
|
855
|
+
id String @id @default(cuid())
|
|
793
856
|
ownerId String
|
|
794
857
|
bashEventId String
|
|
795
858
|
ticketTierId String?
|
|
@@ -799,35 +862,36 @@ model Ticket {
|
|
|
799
862
|
email String?
|
|
800
863
|
paidOn DateTime?
|
|
801
864
|
allowPromiseToPay Boolean?
|
|
802
|
-
status TicketStatus
|
|
865
|
+
status TicketStatus @default(Pending)
|
|
803
866
|
isFreeGuest Boolean?
|
|
804
867
|
geoFenceCheckInUnnecessary Boolean?
|
|
805
868
|
checkedInAt DateTime?
|
|
806
869
|
checkedOutAt DateTime?
|
|
807
870
|
invitationId String?
|
|
808
871
|
checkoutId String?
|
|
809
|
-
checkedInMethod String?
|
|
872
|
+
checkedInMethod String? @default("manual")
|
|
810
873
|
waitlistPosition Int?
|
|
811
874
|
waitlistJoinedAt DateTime?
|
|
812
875
|
waitlistNotifiedAt DateTime?
|
|
813
876
|
waitlistExpiresAt DateTime?
|
|
814
877
|
checkInLocation String?
|
|
815
878
|
checkOutLocation String?
|
|
816
|
-
checkOutMethod String?
|
|
879
|
+
checkOutMethod String? @default("manual")
|
|
817
880
|
lastLocationUpdate DateTime?
|
|
818
|
-
validationAttempts Int
|
|
881
|
+
validationAttempts Int @default(0)
|
|
819
882
|
lastValidationAttempt DateTime?
|
|
820
883
|
lastValidatedBy String?
|
|
821
884
|
waitlistUserId String?
|
|
822
|
-
bashEvent BashEvent
|
|
823
|
-
checkout Checkout?
|
|
824
|
-
forUser User?
|
|
825
|
-
invitation Invitation?
|
|
826
|
-
owner User
|
|
827
|
-
ticketTier TicketTier?
|
|
828
|
-
waitlistUser User?
|
|
885
|
+
bashEvent BashEvent @relation(fields: [bashEventId], references: [id])
|
|
886
|
+
checkout Checkout? @relation(fields: [checkoutId], references: [id])
|
|
887
|
+
forUser User? @relation("TicketsISent", fields: [forUserId], references: [id])
|
|
888
|
+
invitation Invitation? @relation("TicketsForInvitation", fields: [invitationId], references: [id])
|
|
889
|
+
owner User @relation("TicketsIOwn", fields: [ownerId], references: [id])
|
|
890
|
+
ticketTier TicketTier? @relation(fields: [ticketTierId], references: [id])
|
|
891
|
+
waitlistUser User? @relation("TicketsOnWaitlist", fields: [waitlistUserId], references: [id])
|
|
829
892
|
metadata TicketMetadata[]
|
|
830
893
|
transfers TicketTransfer[]
|
|
894
|
+
appliedDiscounts AppliedDiscount[] // NEW - Discounts applied to this ticket
|
|
831
895
|
|
|
832
896
|
@@index([bashEventId])
|
|
833
897
|
@@index([waitlistUserId])
|
|
@@ -872,10 +936,14 @@ model Recurrence {
|
|
|
872
936
|
interval Int @default(1)
|
|
873
937
|
bashEventId String @unique
|
|
874
938
|
frequency RecurringFrequency @default(Never)
|
|
875
|
-
ends DateTime
|
|
939
|
+
ends DateTime? // Nullable - used when endsType = ON_DATE
|
|
940
|
+
repeatCount Int? // Used when endsType = AFTER_COUNT
|
|
941
|
+
endsType RecurrenceEndsType @default(ON_DATE)
|
|
876
942
|
repeatOnDays DayOfWeek[]
|
|
877
943
|
repeatOnDayOfMonth Int?
|
|
878
944
|
repeatYearlyDate DateTime?
|
|
945
|
+
createdAt DateTime @default(now())
|
|
946
|
+
updatedAt DateTime @updatedAt
|
|
879
947
|
bashEvent BashEvent @relation(fields: [bashEventId], references: [id], onDelete: Cascade)
|
|
880
948
|
}
|
|
881
949
|
|
|
@@ -1339,6 +1407,9 @@ model User {
|
|
|
1339
1407
|
reviewedCategoryRequests ServiceCategoryRequest[] @relation("ReviewedCategoryRequests")
|
|
1340
1408
|
bookingCommissionsEarned BookingCommission[] @relation("CommissionReferrer")
|
|
1341
1409
|
|
|
1410
|
+
// Special Offers - Discount Attribution
|
|
1411
|
+
discountAttributions AppliedDiscount[] @relation("DiscountAttribution")
|
|
1412
|
+
|
|
1342
1413
|
// BashCash Referral Relations
|
|
1343
1414
|
referredBy User? @relation("Referrals", fields: [referredById], references: [id])
|
|
1344
1415
|
referrals User[] @relation("Referrals")
|
|
@@ -1423,40 +1494,46 @@ model UserPreferences {
|
|
|
1423
1494
|
preferredCurrency String @default("USD")
|
|
1424
1495
|
savePaymentInfo Boolean @default(false)
|
|
1425
1496
|
showEventPrices Boolean @default(true)
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1497
|
+
|
|
1498
|
+
// BashFeed Preferences
|
|
1499
|
+
bashFeedDefaultTab String @default("all") // "all", "upcoming", "live", "past", "saved", "my-posts"
|
|
1500
|
+
bashFeedDefaultSort String @default("chronological") // "for_you", "chronological", "trending", etc.
|
|
1501
|
+
bashFeedFilters Json? // Saved filter preferences as JSON
|
|
1502
|
+
|
|
1503
|
+
createdAt DateTime @default(now())
|
|
1504
|
+
updatedAt DateTime @updatedAt
|
|
1505
|
+
smsNotifications Boolean @default(false)
|
|
1506
|
+
friendRequestNotify Boolean @default(true)
|
|
1507
|
+
allowTagging Boolean @default(true)
|
|
1508
|
+
showActivityStatus Boolean @default(true)
|
|
1509
|
+
hiddenBashIds String[] @default([])
|
|
1510
|
+
hideActivitySection Boolean @default(false)
|
|
1511
|
+
allowLocationSharing Boolean @default(false)
|
|
1512
|
+
defaultLandingPage String @default("dashboard")
|
|
1513
|
+
contentDensity String @default("COMFORTABLE")
|
|
1514
|
+
fontScale String @default("MEDIUM")
|
|
1515
|
+
animationsEnabled Boolean @default(true)
|
|
1516
|
+
useHighContrastMode Boolean @default(false)
|
|
1517
|
+
contentFilters String[] @default([])
|
|
1518
|
+
topicInterests String[] @default([])
|
|
1519
|
+
hideSeenContent Boolean @default(false)
|
|
1520
|
+
autoplayVideos Boolean @default(true)
|
|
1521
|
+
contentSortPreference String @default("RECENT")
|
|
1522
|
+
contentLanguages String[] @default(["en"])
|
|
1523
|
+
showSensitiveContent Boolean @default(false)
|
|
1524
|
+
defaultEventReminder Int @default(60)
|
|
1525
|
+
communicationFrequency String @default("NORMAL")
|
|
1526
|
+
preferredContactMethod String @default("EMAIL")
|
|
1527
|
+
googleCalendarSyncEnabled Boolean @default(false)
|
|
1528
|
+
googleCalendarEventsSync Boolean @default(false)
|
|
1529
|
+
googleCalendarServicesSync Boolean @default(false)
|
|
1530
|
+
localEventsToCalendarSync Boolean @default(false)
|
|
1531
|
+
localEventsCity String @default("")
|
|
1532
|
+
localEventsState String @default("")
|
|
1533
|
+
showRankings Boolean @default(true) // Show rankings on profile
|
|
1534
|
+
showAttendeeRank Boolean @default(true) // Show attendee rank publicly
|
|
1535
|
+
showHostRank Boolean @default(true) // Show host rank publicly
|
|
1536
|
+
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
1460
1537
|
}
|
|
1461
1538
|
|
|
1462
1539
|
model UserFollowing {
|
|
@@ -2971,6 +3048,12 @@ enum NotificationType {
|
|
|
2971
3048
|
CompetitionEnding
|
|
2972
3049
|
CompetitionWon
|
|
2973
3050
|
CompetitionResults
|
|
3051
|
+
CompetitionParticipantInvited // Host invited you to compete
|
|
3052
|
+
CompetitionParticipantAccepted // Participant accepted invitation
|
|
3053
|
+
CompetitionParticipantDeclined // Participant declined invitation
|
|
3054
|
+
CompetitionParticipantRequested // Someone requested to join your competition
|
|
3055
|
+
CompetitionParticipantApproved // Host approved your request to compete
|
|
3056
|
+
CompetitionParticipantRejected // Host rejected your request
|
|
2974
3057
|
BashRating
|
|
2975
3058
|
BashRatingMilestone
|
|
2976
3059
|
BashFeedPost
|
|
@@ -3366,6 +3449,29 @@ enum JudgingType {
|
|
|
3366
3449
|
HOST_CHOOSES // Host/organizer picks winner
|
|
3367
3450
|
FIRST_COME // First X people win
|
|
3368
3451
|
HIGHEST_BID // Auction-style
|
|
3452
|
+
BRACKET_TOURNAMENT // Winner determined through tournament bracket progression
|
|
3453
|
+
}
|
|
3454
|
+
|
|
3455
|
+
enum BracketType {
|
|
3456
|
+
NONE // No bracket (voting/judging only)
|
|
3457
|
+
SINGLE_ELIMINATION // Lose once, you're out
|
|
3458
|
+
DOUBLE_ELIMINATION // Lose twice, you're out
|
|
3459
|
+
ROUND_ROBIN // Everyone plays everyone
|
|
3460
|
+
SWISS // Pairing based on performance
|
|
3461
|
+
}
|
|
3462
|
+
|
|
3463
|
+
enum ParticipantStatus {
|
|
3464
|
+
INVITED // Host invited them, waiting for acceptance
|
|
3465
|
+
PENDING // User requested to join, waiting for host approval
|
|
3466
|
+
ACCEPTED // Confirmed participant
|
|
3467
|
+
DECLINED // Declined invitation or request denied
|
|
3468
|
+
REMOVED // Host removed them
|
|
3469
|
+
}
|
|
3470
|
+
|
|
3471
|
+
enum RecurrenceEndsType {
|
|
3472
|
+
NEVER // Never ends
|
|
3473
|
+
ON_DATE // Ends on specific date
|
|
3474
|
+
AFTER_COUNT // Ends after X occurrences
|
|
3369
3475
|
}
|
|
3370
3476
|
|
|
3371
3477
|
enum Sex {
|
|
@@ -5274,3 +5380,203 @@ enum EventFormat {
|
|
|
5274
5380
|
Virtual
|
|
5275
5381
|
Hybrid
|
|
5276
5382
|
}
|
|
5383
|
+
|
|
5384
|
+
// ============================================
|
|
5385
|
+
// SPECIAL OFFERS & UNIFIED DISCOUNT SYSTEM
|
|
5386
|
+
// ============================================
|
|
5387
|
+
|
|
5388
|
+
enum DiscountSourceType {
|
|
5389
|
+
PROMO_CODE
|
|
5390
|
+
SPECIAL_OFFER
|
|
5391
|
+
PLATFORM_CREDIT // For future BashCash integration
|
|
5392
|
+
MANUAL_OVERRIDE // Admin adjustments
|
|
5393
|
+
}
|
|
5394
|
+
|
|
5395
|
+
enum DiscountScope {
|
|
5396
|
+
ORDER // Applied to entire order
|
|
5397
|
+
LINE_ITEM // Applied to specific line item
|
|
5398
|
+
TICKET_TIER // Applied to specific ticket tier
|
|
5399
|
+
}
|
|
5400
|
+
|
|
5401
|
+
enum SpecialOfferType {
|
|
5402
|
+
BOGO // Buy One Get One
|
|
5403
|
+
GROUP_DISCOUNT // Group rates
|
|
5404
|
+
EARLY_BIRD // Early bird pricing
|
|
5405
|
+
FLASH_SALE // Time-limited offer
|
|
5406
|
+
BUNDLE // Package deal
|
|
5407
|
+
REFERRAL // Friend referral (needs attribution)
|
|
5408
|
+
VOLUME_DISCOUNT // Buy more save more
|
|
5409
|
+
FAMILY_PACK // Family package
|
|
5410
|
+
LOYALTY // Repeat customer
|
|
5411
|
+
COUNTDOWN // Urgency timer
|
|
5412
|
+
}
|
|
5413
|
+
|
|
5414
|
+
enum OfferDiscountType {
|
|
5415
|
+
PERCENTAGE // X% off
|
|
5416
|
+
FIXED_AMOUNT // $X off
|
|
5417
|
+
FREE_ITEMS // Buy X get Y free
|
|
5418
|
+
UPGRADED_TIER // Free upgrade to VIP
|
|
5419
|
+
}
|
|
5420
|
+
|
|
5421
|
+
// Unified discount tracking - captures ALL discounts at checkout
|
|
5422
|
+
model AppliedDiscount {
|
|
5423
|
+
id String @id @default(cuid())
|
|
5424
|
+
createdAt DateTime @default(now())
|
|
5425
|
+
|
|
5426
|
+
// What discount was applied
|
|
5427
|
+
sourceType DiscountSourceType
|
|
5428
|
+
sourceId String // ID of PromoCode or SpecialOffer
|
|
5429
|
+
sourceName String // "SUMMER20" or "Early Bird Special"
|
|
5430
|
+
|
|
5431
|
+
// Scope and target
|
|
5432
|
+
scope DiscountScope
|
|
5433
|
+
checkoutId String?
|
|
5434
|
+
ticketId String?
|
|
5435
|
+
ticketTierId String?
|
|
5436
|
+
|
|
5437
|
+
// Discount details
|
|
5438
|
+
discountType String // "PERCENTAGE" or "FIXED_AMOUNT"
|
|
5439
|
+
discountValue Int // Percentage or cents
|
|
5440
|
+
amountDiscounted Int // Actual discount applied in cents
|
|
5441
|
+
originalPrice Int // Price before discount
|
|
5442
|
+
finalPrice Int // Price after discount
|
|
5443
|
+
|
|
5444
|
+
// Attribution (optional - for PromoCodes and Referral offers)
|
|
5445
|
+
hasAttribution Boolean @default(false)
|
|
5446
|
+
attributionUserId String? // Promoter/Influencer/Referrer
|
|
5447
|
+
attributionCampaignId String?
|
|
5448
|
+
commissionRate Float?
|
|
5449
|
+
commissionAmount Int? // In cents
|
|
5450
|
+
|
|
5451
|
+
// Display
|
|
5452
|
+
displayReason String? // "Early Bird Discount" for receipt
|
|
5453
|
+
internalNote String? // For support/debugging
|
|
5454
|
+
|
|
5455
|
+
// Relations
|
|
5456
|
+
checkout Checkout? @relation(fields: [checkoutId], references: [id])
|
|
5457
|
+
ticket Ticket? @relation(fields: [ticketId], references: [id])
|
|
5458
|
+
ticketTier TicketTier? @relation(fields: [ticketTierId], references: [id])
|
|
5459
|
+
attributionUser User? @relation("DiscountAttribution", fields: [attributionUserId], references: [id])
|
|
5460
|
+
|
|
5461
|
+
@@index([checkoutId])
|
|
5462
|
+
@@index([sourceType, sourceId])
|
|
5463
|
+
@@index([attributionUserId])
|
|
5464
|
+
@@index([createdAt])
|
|
5465
|
+
}
|
|
5466
|
+
|
|
5467
|
+
// Special offers - automatic, visible, conversion-oriented deals
|
|
5468
|
+
model SpecialOffer {
|
|
5469
|
+
id String @id @default(cuid())
|
|
5470
|
+
createdAt DateTime @default(now())
|
|
5471
|
+
updatedAt DateTime @updatedAt
|
|
5472
|
+
|
|
5473
|
+
// Basic Info
|
|
5474
|
+
ticketTierId String
|
|
5475
|
+
offerType SpecialOfferType
|
|
5476
|
+
title String // "Early Bird Special", "BOGO Deal"
|
|
5477
|
+
description String? @db.Text
|
|
5478
|
+
isActive Boolean @default(true)
|
|
5479
|
+
displayBadge Boolean @default(true)
|
|
5480
|
+
badgeText String? // "50% OFF", "BOGO"
|
|
5481
|
+
|
|
5482
|
+
// Discount Configuration
|
|
5483
|
+
discountType OfferDiscountType
|
|
5484
|
+
discountValue Int // Percentage or cents
|
|
5485
|
+
|
|
5486
|
+
// BOGO Configuration
|
|
5487
|
+
buyQuantity Int? // Buy X tickets
|
|
5488
|
+
getQuantity Int? // Get Y tickets
|
|
5489
|
+
getDiscountPercent Int? // Get Y at Z% off (0-100)
|
|
5490
|
+
|
|
5491
|
+
// Group Discount Configuration
|
|
5492
|
+
minGroupSize Int?
|
|
5493
|
+
maxGroupSize Int?
|
|
5494
|
+
tieredDiscounts Json? // [{qty: 5, discount: 10}, {qty: 10, discount: 20}]
|
|
5495
|
+
|
|
5496
|
+
// Time-Based Configuration
|
|
5497
|
+
startDate DateTime?
|
|
5498
|
+
endDate DateTime?
|
|
5499
|
+
availableUntil DateTime? // Early bird cutoff
|
|
5500
|
+
|
|
5501
|
+
// Quantity Limitations
|
|
5502
|
+
maxRedemptions Int?
|
|
5503
|
+
maxPerUser Int?
|
|
5504
|
+
limitedQuantity Int?
|
|
5505
|
+
currentRedemptions Int @default(0)
|
|
5506
|
+
|
|
5507
|
+
// Social Proof Tracking
|
|
5508
|
+
viewCount Int @default(0) // How many times this offer was viewed
|
|
5509
|
+
clickCount Int @default(0) // How many times users clicked "Apply"
|
|
5510
|
+
lastRedemptionAt DateTime? // When was the last redemption
|
|
5511
|
+
|
|
5512
|
+
// Price Increase (Countdown)
|
|
5513
|
+
priceIncreasesAt DateTime?
|
|
5514
|
+
newPriceAfterIncrease Int?
|
|
5515
|
+
countdownEnabled Boolean @default(false)
|
|
5516
|
+
|
|
5517
|
+
// Bundle Configuration
|
|
5518
|
+
bundledItems Json?
|
|
5519
|
+
bundleSavings Int?
|
|
5520
|
+
|
|
5521
|
+
// Attribution (ONLY for Referral type offers)
|
|
5522
|
+
requiresAttribution Boolean @default(false)
|
|
5523
|
+
referralDiscountForBuyer Int?
|
|
5524
|
+
referralDiscountForFriend Int?
|
|
5525
|
+
commissionRate Float? // For referrer
|
|
5526
|
+
|
|
5527
|
+
// Loyalty Configuration
|
|
5528
|
+
requiresEventAttendance Int?
|
|
5529
|
+
hostSpecificLoyalty Boolean @default(false)
|
|
5530
|
+
|
|
5531
|
+
// Stacking Rules
|
|
5532
|
+
canStackWithPromoCodes Boolean @default(true) // Host decides
|
|
5533
|
+
canStackWithOtherOffers Boolean @default(false)
|
|
5534
|
+
priority Int @default(0) // Higher = applied first
|
|
5535
|
+
|
|
5536
|
+
// Display & Marketing
|
|
5537
|
+
urgencyMessage String? @db.Text
|
|
5538
|
+
showSocialProof Boolean @default(false)
|
|
5539
|
+
highlightColor String?
|
|
5540
|
+
sortOrder Int @default(0)
|
|
5541
|
+
|
|
5542
|
+
// Guardrails
|
|
5543
|
+
minPriceFloor Int? // Never discount below this
|
|
5544
|
+
maxDiscountPercent Int? // Never discount more than X%
|
|
5545
|
+
|
|
5546
|
+
// Relations
|
|
5547
|
+
ticketTier TicketTier @relation(fields: [ticketTierId], references: [id], onDelete: Cascade)
|
|
5548
|
+
|
|
5549
|
+
@@index([ticketTierId])
|
|
5550
|
+
@@index([offerType])
|
|
5551
|
+
@@index([isActive])
|
|
5552
|
+
@@index([endDate])
|
|
5553
|
+
}
|
|
5554
|
+
|
|
5555
|
+
// Analytics Prediction Cache Model
|
|
5556
|
+
model AnalyticsPrediction {
|
|
5557
|
+
id String @id @default(cuid())
|
|
5558
|
+
bashEventId String
|
|
5559
|
+
type PredictionType
|
|
5560
|
+
source PredictionSource
|
|
5561
|
+
prediction Json
|
|
5562
|
+
confidence Float
|
|
5563
|
+
generatedAt DateTime @default(now())
|
|
5564
|
+
validUntil DateTime
|
|
5565
|
+
|
|
5566
|
+
bashEvent BashEvent @relation(fields: [bashEventId], references: [id], onDelete: Cascade)
|
|
5567
|
+
|
|
5568
|
+
@@index([bashEventId, type])
|
|
5569
|
+
@@index([validUntil])
|
|
5570
|
+
}
|
|
5571
|
+
|
|
5572
|
+
enum PredictionType {
|
|
5573
|
+
REVENUE_FORECAST
|
|
5574
|
+
PRICING_OPTIMIZATION
|
|
5575
|
+
SELLOUT_PROBABILITY
|
|
5576
|
+
ACTION_RECOMMENDATION
|
|
5577
|
+
}
|
|
5578
|
+
|
|
5579
|
+
enum PredictionSource {
|
|
5580
|
+
RULE_BASED
|
|
5581
|
+
AI_ENHANCED
|
|
5582
|
+
}
|
package/src/definitions.ts
CHANGED
|
@@ -2,6 +2,7 @@ import {
|
|
|
2
2
|
BashEventDressTags,
|
|
3
3
|
BashEventType,
|
|
4
4
|
BashEventVibeTags,
|
|
5
|
+
BracketType,
|
|
5
6
|
CompetitionType,
|
|
6
7
|
Contact,
|
|
7
8
|
EntertainmentServiceType,
|
|
@@ -879,7 +880,7 @@ export const YearsOfExperienceToString: { [key in YearsOfExperience]: string } =
|
|
|
879
880
|
};
|
|
880
881
|
|
|
881
882
|
// Export Prisma enums for use in frontend
|
|
882
|
-
export { YearsOfExperience, EntertainmentServiceType, MusicGenreType, ServiceTypes, CompetitionType, JudgingType };
|
|
883
|
+
export { YearsOfExperience, EntertainmentServiceType, MusicGenreType, ServiceTypes, CompetitionType, JudgingType, BracketType };
|
|
883
884
|
|
|
884
885
|
export type BashEventTypeToStringType = {
|
|
885
886
|
[key in BashEventType]: string;
|
package/src/index.ts
CHANGED
|
@@ -8,6 +8,8 @@ export * from "./utils/awsS3Utils";
|
|
|
8
8
|
export * from "./utils/bashCashPaymentUtils";
|
|
9
9
|
export * from "./utils/contentFilterUtils";
|
|
10
10
|
export * from "./utils/dateTimeUtils";
|
|
11
|
+
export * from "./utils/discountEngine/bestPriceResolver";
|
|
12
|
+
export * from "./utils/discountEngine/eligibilityValidator";
|
|
11
13
|
export * from "./utils/objUtils";
|
|
12
14
|
export * from "./utils/paymentUtils";
|
|
13
15
|
export * from "./utils/promoCodesUtils";
|