@bash-app/bash-common 30.113.0 → 30.114.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 +1 -1
- package/prisma/schema.prisma +366 -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])
|
|
@@ -243,17 +257,53 @@ model CompetitionParticipant {
|
|
|
243
257
|
imageUrl String? // Photo/avatar
|
|
244
258
|
order Int @default(0) // Display order
|
|
245
259
|
voteCount Int @default(0) // Denormalized for performance
|
|
260
|
+
isEliminated Boolean @default(false) // For tournament brackets
|
|
261
|
+
placement Int? // Final placement (1st, 2nd, 3rd, etc.)
|
|
246
262
|
addedBy String @default("host") // 'host' or 'self'
|
|
247
263
|
createdAt DateTime @default(now())
|
|
248
264
|
competition Competition @relation(fields: [competitionId], references: [id], onDelete: Cascade)
|
|
249
265
|
user User? @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
250
266
|
votes CompetitionVote[]
|
|
251
267
|
|
|
268
|
+
// Tournament bracket relations
|
|
269
|
+
matchesAsParticipant1 CompetitionMatch[] @relation("MatchParticipant1")
|
|
270
|
+
matchesAsParticipant2 CompetitionMatch[] @relation("MatchParticipant2")
|
|
271
|
+
matchesWon CompetitionMatch[] @relation("MatchWinner")
|
|
272
|
+
|
|
252
273
|
@@index([competitionId])
|
|
253
274
|
@@index([userId])
|
|
254
275
|
@@index([voteCount])
|
|
255
276
|
}
|
|
256
277
|
|
|
278
|
+
// Tournament bracket matches
|
|
279
|
+
model CompetitionMatch {
|
|
280
|
+
id String @id @default(cuid())
|
|
281
|
+
competitionId String
|
|
282
|
+
round Int // 1 = first round, 2 = semifinals, etc.
|
|
283
|
+
matchNumber Int // Position in round (1, 2, 3...)
|
|
284
|
+
|
|
285
|
+
participant1Id String?
|
|
286
|
+
participant2Id String?
|
|
287
|
+
winnerId String?
|
|
288
|
+
|
|
289
|
+
scheduledTime DateTime?
|
|
290
|
+
completedAt DateTime?
|
|
291
|
+
score Json? // {participant1: 10, participant2: 8}
|
|
292
|
+
notes String? // Match notes
|
|
293
|
+
|
|
294
|
+
competition Competition @relation(fields: [competitionId], references: [id], onDelete: Cascade)
|
|
295
|
+
participant1 CompetitionParticipant? @relation("MatchParticipant1", fields: [participant1Id], references: [id])
|
|
296
|
+
participant2 CompetitionParticipant? @relation("MatchParticipant2", fields: [participant2Id], references: [id])
|
|
297
|
+
winner CompetitionParticipant? @relation("MatchWinner", fields: [winnerId], references: [id])
|
|
298
|
+
|
|
299
|
+
createdAt DateTime @default(now())
|
|
300
|
+
updatedAt DateTime @updatedAt
|
|
301
|
+
|
|
302
|
+
@@unique([competitionId, round, matchNumber])
|
|
303
|
+
@@index([competitionId])
|
|
304
|
+
@@index([round])
|
|
305
|
+
}
|
|
306
|
+
|
|
257
307
|
model CompetitionVote {
|
|
258
308
|
id String @id @default(cuid())
|
|
259
309
|
competitionId String
|
|
@@ -617,6 +667,9 @@ model BashEvent {
|
|
|
617
667
|
bashFeedRatings BashFeedRating[]
|
|
618
668
|
eventRankings EventRankings?
|
|
619
669
|
|
|
670
|
+
// Analytics Relations
|
|
671
|
+
analyticsPredictions AnalyticsPrediction[]
|
|
672
|
+
|
|
620
673
|
@@index([templateId])
|
|
621
674
|
@@index([parentEventId])
|
|
622
675
|
}
|
|
@@ -630,14 +683,15 @@ model Coordinates {
|
|
|
630
683
|
}
|
|
631
684
|
|
|
632
685
|
model Checkout {
|
|
633
|
-
id String
|
|
686
|
+
id String @id @default(cuid())
|
|
634
687
|
ownerId String
|
|
635
688
|
bashEventId String
|
|
636
|
-
checkoutDateTime DateTime?
|
|
637
|
-
stripeCheckoutSessionId String?
|
|
638
|
-
bashEvent BashEvent
|
|
639
|
-
owner User
|
|
689
|
+
checkoutDateTime DateTime? @default(now())
|
|
690
|
+
stripeCheckoutSessionId String? @unique
|
|
691
|
+
bashEvent BashEvent @relation(fields: [bashEventId], references: [id], onDelete: Cascade)
|
|
692
|
+
owner User @relation(fields: [ownerId], references: [id], onDelete: Cascade)
|
|
640
693
|
tickets Ticket[]
|
|
694
|
+
appliedDiscounts AppliedDiscount[] // NEW - Discounts applied to this checkout
|
|
641
695
|
|
|
642
696
|
@@index([bashEventId])
|
|
643
697
|
}
|
|
@@ -784,12 +838,14 @@ model TicketTier {
|
|
|
784
838
|
tickets Ticket[]
|
|
785
839
|
bashEvent BashEvent @relation(fields: [bashEventId], references: [id], onDelete: Cascade)
|
|
786
840
|
waitList User[] @relation("TicketTierToUser")
|
|
841
|
+
specialOffers SpecialOffer[] // NEW - Special offers for this tier
|
|
842
|
+
appliedDiscounts AppliedDiscount[] // NEW - Discounts applied to this tier
|
|
787
843
|
|
|
788
844
|
@@unique([bashEventId, title])
|
|
789
845
|
}
|
|
790
846
|
|
|
791
847
|
model Ticket {
|
|
792
|
-
id String
|
|
848
|
+
id String @id @default(cuid())
|
|
793
849
|
ownerId String
|
|
794
850
|
bashEventId String
|
|
795
851
|
ticketTierId String?
|
|
@@ -799,35 +855,36 @@ model Ticket {
|
|
|
799
855
|
email String?
|
|
800
856
|
paidOn DateTime?
|
|
801
857
|
allowPromiseToPay Boolean?
|
|
802
|
-
status TicketStatus
|
|
858
|
+
status TicketStatus @default(Pending)
|
|
803
859
|
isFreeGuest Boolean?
|
|
804
860
|
geoFenceCheckInUnnecessary Boolean?
|
|
805
861
|
checkedInAt DateTime?
|
|
806
862
|
checkedOutAt DateTime?
|
|
807
863
|
invitationId String?
|
|
808
864
|
checkoutId String?
|
|
809
|
-
checkedInMethod String?
|
|
865
|
+
checkedInMethod String? @default("manual")
|
|
810
866
|
waitlistPosition Int?
|
|
811
867
|
waitlistJoinedAt DateTime?
|
|
812
868
|
waitlistNotifiedAt DateTime?
|
|
813
869
|
waitlistExpiresAt DateTime?
|
|
814
870
|
checkInLocation String?
|
|
815
871
|
checkOutLocation String?
|
|
816
|
-
checkOutMethod String?
|
|
872
|
+
checkOutMethod String? @default("manual")
|
|
817
873
|
lastLocationUpdate DateTime?
|
|
818
|
-
validationAttempts Int
|
|
874
|
+
validationAttempts Int @default(0)
|
|
819
875
|
lastValidationAttempt DateTime?
|
|
820
876
|
lastValidatedBy String?
|
|
821
877
|
waitlistUserId String?
|
|
822
|
-
bashEvent BashEvent
|
|
823
|
-
checkout Checkout?
|
|
824
|
-
forUser User?
|
|
825
|
-
invitation Invitation?
|
|
826
|
-
owner User
|
|
827
|
-
ticketTier TicketTier?
|
|
828
|
-
waitlistUser User?
|
|
878
|
+
bashEvent BashEvent @relation(fields: [bashEventId], references: [id])
|
|
879
|
+
checkout Checkout? @relation(fields: [checkoutId], references: [id])
|
|
880
|
+
forUser User? @relation("TicketsISent", fields: [forUserId], references: [id])
|
|
881
|
+
invitation Invitation? @relation("TicketsForInvitation", fields: [invitationId], references: [id])
|
|
882
|
+
owner User @relation("TicketsIOwn", fields: [ownerId], references: [id])
|
|
883
|
+
ticketTier TicketTier? @relation(fields: [ticketTierId], references: [id])
|
|
884
|
+
waitlistUser User? @relation("TicketsOnWaitlist", fields: [waitlistUserId], references: [id])
|
|
829
885
|
metadata TicketMetadata[]
|
|
830
886
|
transfers TicketTransfer[]
|
|
887
|
+
appliedDiscounts AppliedDiscount[] // NEW - Discounts applied to this ticket
|
|
831
888
|
|
|
832
889
|
@@index([bashEventId])
|
|
833
890
|
@@index([waitlistUserId])
|
|
@@ -872,10 +929,14 @@ model Recurrence {
|
|
|
872
929
|
interval Int @default(1)
|
|
873
930
|
bashEventId String @unique
|
|
874
931
|
frequency RecurringFrequency @default(Never)
|
|
875
|
-
ends DateTime
|
|
932
|
+
ends DateTime? // Nullable - used when endsType = ON_DATE
|
|
933
|
+
repeatCount Int? // Used when endsType = AFTER_COUNT
|
|
934
|
+
endsType RecurrenceEndsType @default(ON_DATE)
|
|
876
935
|
repeatOnDays DayOfWeek[]
|
|
877
936
|
repeatOnDayOfMonth Int?
|
|
878
937
|
repeatYearlyDate DateTime?
|
|
938
|
+
createdAt DateTime @default(now())
|
|
939
|
+
updatedAt DateTime @updatedAt
|
|
879
940
|
bashEvent BashEvent @relation(fields: [bashEventId], references: [id], onDelete: Cascade)
|
|
880
941
|
}
|
|
881
942
|
|
|
@@ -1339,6 +1400,9 @@ model User {
|
|
|
1339
1400
|
reviewedCategoryRequests ServiceCategoryRequest[] @relation("ReviewedCategoryRequests")
|
|
1340
1401
|
bookingCommissionsEarned BookingCommission[] @relation("CommissionReferrer")
|
|
1341
1402
|
|
|
1403
|
+
// Special Offers - Discount Attribution
|
|
1404
|
+
discountAttributions AppliedDiscount[] @relation("DiscountAttribution")
|
|
1405
|
+
|
|
1342
1406
|
// BashCash Referral Relations
|
|
1343
1407
|
referredBy User? @relation("Referrals", fields: [referredById], references: [id])
|
|
1344
1408
|
referrals User[] @relation("Referrals")
|
|
@@ -1423,40 +1487,46 @@ model UserPreferences {
|
|
|
1423
1487
|
preferredCurrency String @default("USD")
|
|
1424
1488
|
savePaymentInfo Boolean @default(false)
|
|
1425
1489
|
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
|
-
|
|
1490
|
+
|
|
1491
|
+
// BashFeed Preferences
|
|
1492
|
+
bashFeedDefaultTab String @default("all") // "all", "upcoming", "live", "past", "saved", "my-posts"
|
|
1493
|
+
bashFeedDefaultSort String @default("chronological") // "for_you", "chronological", "trending", etc.
|
|
1494
|
+
bashFeedFilters Json? // Saved filter preferences as JSON
|
|
1495
|
+
|
|
1496
|
+
createdAt DateTime @default(now())
|
|
1497
|
+
updatedAt DateTime @updatedAt
|
|
1498
|
+
smsNotifications Boolean @default(false)
|
|
1499
|
+
friendRequestNotify Boolean @default(true)
|
|
1500
|
+
allowTagging Boolean @default(true)
|
|
1501
|
+
showActivityStatus Boolean @default(true)
|
|
1502
|
+
hiddenBashIds String[] @default([])
|
|
1503
|
+
hideActivitySection Boolean @default(false)
|
|
1504
|
+
allowLocationSharing Boolean @default(false)
|
|
1505
|
+
defaultLandingPage String @default("dashboard")
|
|
1506
|
+
contentDensity String @default("COMFORTABLE")
|
|
1507
|
+
fontScale String @default("MEDIUM")
|
|
1508
|
+
animationsEnabled Boolean @default(true)
|
|
1509
|
+
useHighContrastMode Boolean @default(false)
|
|
1510
|
+
contentFilters String[] @default([])
|
|
1511
|
+
topicInterests String[] @default([])
|
|
1512
|
+
hideSeenContent Boolean @default(false)
|
|
1513
|
+
autoplayVideos Boolean @default(true)
|
|
1514
|
+
contentSortPreference String @default("RECENT")
|
|
1515
|
+
contentLanguages String[] @default(["en"])
|
|
1516
|
+
showSensitiveContent Boolean @default(false)
|
|
1517
|
+
defaultEventReminder Int @default(60)
|
|
1518
|
+
communicationFrequency String @default("NORMAL")
|
|
1519
|
+
preferredContactMethod String @default("EMAIL")
|
|
1520
|
+
googleCalendarSyncEnabled Boolean @default(false)
|
|
1521
|
+
googleCalendarEventsSync Boolean @default(false)
|
|
1522
|
+
googleCalendarServicesSync Boolean @default(false)
|
|
1523
|
+
localEventsToCalendarSync Boolean @default(false)
|
|
1524
|
+
localEventsCity String @default("")
|
|
1525
|
+
localEventsState String @default("")
|
|
1526
|
+
showRankings Boolean @default(true) // Show rankings on profile
|
|
1527
|
+
showAttendeeRank Boolean @default(true) // Show attendee rank publicly
|
|
1528
|
+
showHostRank Boolean @default(true) // Show host rank publicly
|
|
1529
|
+
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
1460
1530
|
}
|
|
1461
1531
|
|
|
1462
1532
|
model UserFollowing {
|
|
@@ -3366,6 +3436,21 @@ enum JudgingType {
|
|
|
3366
3436
|
HOST_CHOOSES // Host/organizer picks winner
|
|
3367
3437
|
FIRST_COME // First X people win
|
|
3368
3438
|
HIGHEST_BID // Auction-style
|
|
3439
|
+
BRACKET_TOURNAMENT // Winner determined through tournament bracket progression
|
|
3440
|
+
}
|
|
3441
|
+
|
|
3442
|
+
enum BracketType {
|
|
3443
|
+
NONE // No bracket (voting/judging only)
|
|
3444
|
+
SINGLE_ELIMINATION // Lose once, you're out
|
|
3445
|
+
DOUBLE_ELIMINATION // Lose twice, you're out
|
|
3446
|
+
ROUND_ROBIN // Everyone plays everyone
|
|
3447
|
+
SWISS // Pairing based on performance
|
|
3448
|
+
}
|
|
3449
|
+
|
|
3450
|
+
enum RecurrenceEndsType {
|
|
3451
|
+
NEVER // Never ends
|
|
3452
|
+
ON_DATE // Ends on specific date
|
|
3453
|
+
AFTER_COUNT // Ends after X occurrences
|
|
3369
3454
|
}
|
|
3370
3455
|
|
|
3371
3456
|
enum Sex {
|
|
@@ -5274,3 +5359,203 @@ enum EventFormat {
|
|
|
5274
5359
|
Virtual
|
|
5275
5360
|
Hybrid
|
|
5276
5361
|
}
|
|
5362
|
+
|
|
5363
|
+
// ============================================
|
|
5364
|
+
// SPECIAL OFFERS & UNIFIED DISCOUNT SYSTEM
|
|
5365
|
+
// ============================================
|
|
5366
|
+
|
|
5367
|
+
enum DiscountSourceType {
|
|
5368
|
+
PROMO_CODE
|
|
5369
|
+
SPECIAL_OFFER
|
|
5370
|
+
PLATFORM_CREDIT // For future BashCash integration
|
|
5371
|
+
MANUAL_OVERRIDE // Admin adjustments
|
|
5372
|
+
}
|
|
5373
|
+
|
|
5374
|
+
enum DiscountScope {
|
|
5375
|
+
ORDER // Applied to entire order
|
|
5376
|
+
LINE_ITEM // Applied to specific line item
|
|
5377
|
+
TICKET_TIER // Applied to specific ticket tier
|
|
5378
|
+
}
|
|
5379
|
+
|
|
5380
|
+
enum SpecialOfferType {
|
|
5381
|
+
BOGO // Buy One Get One
|
|
5382
|
+
GROUP_DISCOUNT // Group rates
|
|
5383
|
+
EARLY_BIRD // Early bird pricing
|
|
5384
|
+
FLASH_SALE // Time-limited offer
|
|
5385
|
+
BUNDLE // Package deal
|
|
5386
|
+
REFERRAL // Friend referral (needs attribution)
|
|
5387
|
+
VOLUME_DISCOUNT // Buy more save more
|
|
5388
|
+
FAMILY_PACK // Family package
|
|
5389
|
+
LOYALTY // Repeat customer
|
|
5390
|
+
COUNTDOWN // Urgency timer
|
|
5391
|
+
}
|
|
5392
|
+
|
|
5393
|
+
enum OfferDiscountType {
|
|
5394
|
+
PERCENTAGE // X% off
|
|
5395
|
+
FIXED_AMOUNT // $X off
|
|
5396
|
+
FREE_ITEMS // Buy X get Y free
|
|
5397
|
+
UPGRADED_TIER // Free upgrade to VIP
|
|
5398
|
+
}
|
|
5399
|
+
|
|
5400
|
+
// Unified discount tracking - captures ALL discounts at checkout
|
|
5401
|
+
model AppliedDiscount {
|
|
5402
|
+
id String @id @default(cuid())
|
|
5403
|
+
createdAt DateTime @default(now())
|
|
5404
|
+
|
|
5405
|
+
// What discount was applied
|
|
5406
|
+
sourceType DiscountSourceType
|
|
5407
|
+
sourceId String // ID of PromoCode or SpecialOffer
|
|
5408
|
+
sourceName String // "SUMMER20" or "Early Bird Special"
|
|
5409
|
+
|
|
5410
|
+
// Scope and target
|
|
5411
|
+
scope DiscountScope
|
|
5412
|
+
checkoutId String?
|
|
5413
|
+
ticketId String?
|
|
5414
|
+
ticketTierId String?
|
|
5415
|
+
|
|
5416
|
+
// Discount details
|
|
5417
|
+
discountType String // "PERCENTAGE" or "FIXED_AMOUNT"
|
|
5418
|
+
discountValue Int // Percentage or cents
|
|
5419
|
+
amountDiscounted Int // Actual discount applied in cents
|
|
5420
|
+
originalPrice Int // Price before discount
|
|
5421
|
+
finalPrice Int // Price after discount
|
|
5422
|
+
|
|
5423
|
+
// Attribution (optional - for PromoCodes and Referral offers)
|
|
5424
|
+
hasAttribution Boolean @default(false)
|
|
5425
|
+
attributionUserId String? // Promoter/Influencer/Referrer
|
|
5426
|
+
attributionCampaignId String?
|
|
5427
|
+
commissionRate Float?
|
|
5428
|
+
commissionAmount Int? // In cents
|
|
5429
|
+
|
|
5430
|
+
// Display
|
|
5431
|
+
displayReason String? // "Early Bird Discount" for receipt
|
|
5432
|
+
internalNote String? // For support/debugging
|
|
5433
|
+
|
|
5434
|
+
// Relations
|
|
5435
|
+
checkout Checkout? @relation(fields: [checkoutId], references: [id])
|
|
5436
|
+
ticket Ticket? @relation(fields: [ticketId], references: [id])
|
|
5437
|
+
ticketTier TicketTier? @relation(fields: [ticketTierId], references: [id])
|
|
5438
|
+
attributionUser User? @relation("DiscountAttribution", fields: [attributionUserId], references: [id])
|
|
5439
|
+
|
|
5440
|
+
@@index([checkoutId])
|
|
5441
|
+
@@index([sourceType, sourceId])
|
|
5442
|
+
@@index([attributionUserId])
|
|
5443
|
+
@@index([createdAt])
|
|
5444
|
+
}
|
|
5445
|
+
|
|
5446
|
+
// Special offers - automatic, visible, conversion-oriented deals
|
|
5447
|
+
model SpecialOffer {
|
|
5448
|
+
id String @id @default(cuid())
|
|
5449
|
+
createdAt DateTime @default(now())
|
|
5450
|
+
updatedAt DateTime @updatedAt
|
|
5451
|
+
|
|
5452
|
+
// Basic Info
|
|
5453
|
+
ticketTierId String
|
|
5454
|
+
offerType SpecialOfferType
|
|
5455
|
+
title String // "Early Bird Special", "BOGO Deal"
|
|
5456
|
+
description String? @db.Text
|
|
5457
|
+
isActive Boolean @default(true)
|
|
5458
|
+
displayBadge Boolean @default(true)
|
|
5459
|
+
badgeText String? // "50% OFF", "BOGO"
|
|
5460
|
+
|
|
5461
|
+
// Discount Configuration
|
|
5462
|
+
discountType OfferDiscountType
|
|
5463
|
+
discountValue Int // Percentage or cents
|
|
5464
|
+
|
|
5465
|
+
// BOGO Configuration
|
|
5466
|
+
buyQuantity Int? // Buy X tickets
|
|
5467
|
+
getQuantity Int? // Get Y tickets
|
|
5468
|
+
getDiscountPercent Int? // Get Y at Z% off (0-100)
|
|
5469
|
+
|
|
5470
|
+
// Group Discount Configuration
|
|
5471
|
+
minGroupSize Int?
|
|
5472
|
+
maxGroupSize Int?
|
|
5473
|
+
tieredDiscounts Json? // [{qty: 5, discount: 10}, {qty: 10, discount: 20}]
|
|
5474
|
+
|
|
5475
|
+
// Time-Based Configuration
|
|
5476
|
+
startDate DateTime?
|
|
5477
|
+
endDate DateTime?
|
|
5478
|
+
availableUntil DateTime? // Early bird cutoff
|
|
5479
|
+
|
|
5480
|
+
// Quantity Limitations
|
|
5481
|
+
maxRedemptions Int?
|
|
5482
|
+
maxPerUser Int?
|
|
5483
|
+
limitedQuantity Int?
|
|
5484
|
+
currentRedemptions Int @default(0)
|
|
5485
|
+
|
|
5486
|
+
// Social Proof Tracking
|
|
5487
|
+
viewCount Int @default(0) // How many times this offer was viewed
|
|
5488
|
+
clickCount Int @default(0) // How many times users clicked "Apply"
|
|
5489
|
+
lastRedemptionAt DateTime? // When was the last redemption
|
|
5490
|
+
|
|
5491
|
+
// Price Increase (Countdown)
|
|
5492
|
+
priceIncreasesAt DateTime?
|
|
5493
|
+
newPriceAfterIncrease Int?
|
|
5494
|
+
countdownEnabled Boolean @default(false)
|
|
5495
|
+
|
|
5496
|
+
// Bundle Configuration
|
|
5497
|
+
bundledItems Json?
|
|
5498
|
+
bundleSavings Int?
|
|
5499
|
+
|
|
5500
|
+
// Attribution (ONLY for Referral type offers)
|
|
5501
|
+
requiresAttribution Boolean @default(false)
|
|
5502
|
+
referralDiscountForBuyer Int?
|
|
5503
|
+
referralDiscountForFriend Int?
|
|
5504
|
+
commissionRate Float? // For referrer
|
|
5505
|
+
|
|
5506
|
+
// Loyalty Configuration
|
|
5507
|
+
requiresEventAttendance Int?
|
|
5508
|
+
hostSpecificLoyalty Boolean @default(false)
|
|
5509
|
+
|
|
5510
|
+
// Stacking Rules
|
|
5511
|
+
canStackWithPromoCodes Boolean @default(true) // Host decides
|
|
5512
|
+
canStackWithOtherOffers Boolean @default(false)
|
|
5513
|
+
priority Int @default(0) // Higher = applied first
|
|
5514
|
+
|
|
5515
|
+
// Display & Marketing
|
|
5516
|
+
urgencyMessage String? @db.Text
|
|
5517
|
+
showSocialProof Boolean @default(false)
|
|
5518
|
+
highlightColor String?
|
|
5519
|
+
sortOrder Int @default(0)
|
|
5520
|
+
|
|
5521
|
+
// Guardrails
|
|
5522
|
+
minPriceFloor Int? // Never discount below this
|
|
5523
|
+
maxDiscountPercent Int? // Never discount more than X%
|
|
5524
|
+
|
|
5525
|
+
// Relations
|
|
5526
|
+
ticketTier TicketTier @relation(fields: [ticketTierId], references: [id], onDelete: Cascade)
|
|
5527
|
+
|
|
5528
|
+
@@index([ticketTierId])
|
|
5529
|
+
@@index([offerType])
|
|
5530
|
+
@@index([isActive])
|
|
5531
|
+
@@index([endDate])
|
|
5532
|
+
}
|
|
5533
|
+
|
|
5534
|
+
// Analytics Prediction Cache Model
|
|
5535
|
+
model AnalyticsPrediction {
|
|
5536
|
+
id String @id @default(cuid())
|
|
5537
|
+
bashEventId String
|
|
5538
|
+
type PredictionType
|
|
5539
|
+
source PredictionSource
|
|
5540
|
+
prediction Json
|
|
5541
|
+
confidence Float
|
|
5542
|
+
generatedAt DateTime @default(now())
|
|
5543
|
+
validUntil DateTime
|
|
5544
|
+
|
|
5545
|
+
bashEvent BashEvent @relation(fields: [bashEventId], references: [id], onDelete: Cascade)
|
|
5546
|
+
|
|
5547
|
+
@@index([bashEventId, type])
|
|
5548
|
+
@@index([validUntil])
|
|
5549
|
+
}
|
|
5550
|
+
|
|
5551
|
+
enum PredictionType {
|
|
5552
|
+
REVENUE_FORECAST
|
|
5553
|
+
PRICING_OPTIMIZATION
|
|
5554
|
+
SELLOUT_PROBABILITY
|
|
5555
|
+
ACTION_RECOMMENDATION
|
|
5556
|
+
}
|
|
5557
|
+
|
|
5558
|
+
enum PredictionSource {
|
|
5559
|
+
RULE_BASED
|
|
5560
|
+
AI_ENHANCED
|
|
5561
|
+
}
|
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";
|