@bash-app/bash-common 30.260.1 → 30.262.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.
Files changed (79) hide show
  1. package/dist/__tests__/ticketBnplPaymentMethods.cashapp.test.d.ts +2 -0
  2. package/dist/__tests__/ticketBnplPaymentMethods.cashapp.test.d.ts.map +1 -0
  3. package/dist/__tests__/ticketBnplPaymentMethods.cashapp.test.js +33 -0
  4. package/dist/__tests__/ticketBnplPaymentMethods.cashapp.test.js.map +1 -0
  5. package/dist/__tests__/ticketBnplPaymentMethods.test.d.ts +2 -0
  6. package/dist/__tests__/ticketBnplPaymentMethods.test.d.ts.map +1 -0
  7. package/dist/__tests__/ticketBnplPaymentMethods.test.js +46 -0
  8. package/dist/__tests__/ticketBnplPaymentMethods.test.js.map +1 -0
  9. package/dist/definitions.d.ts +6 -1
  10. package/dist/definitions.d.ts.map +1 -1
  11. package/dist/definitions.js.map +1 -1
  12. package/dist/index.d.ts +6 -0
  13. package/dist/index.d.ts.map +1 -1
  14. package/dist/index.js +6 -0
  15. package/dist/index.js.map +1 -1
  16. package/dist/ticketBnplPaymentMethods.d.ts +32 -0
  17. package/dist/ticketBnplPaymentMethods.d.ts.map +1 -0
  18. package/dist/ticketBnplPaymentMethods.js +42 -0
  19. package/dist/ticketBnplPaymentMethods.js.map +1 -0
  20. package/dist/utils/__tests__/featuredDiscoveryGeo.test.d.ts +2 -0
  21. package/dist/utils/__tests__/featuredDiscoveryGeo.test.d.ts.map +1 -0
  22. package/dist/utils/__tests__/featuredDiscoveryGeo.test.js +98 -0
  23. package/dist/utils/__tests__/featuredDiscoveryGeo.test.js.map +1 -0
  24. package/dist/utils/__tests__/flyerUtils.test.js +7 -1
  25. package/dist/utils/__tests__/flyerUtils.test.js.map +1 -1
  26. package/dist/utils/__tests__/guestSurface.test.d.ts +2 -0
  27. package/dist/utils/__tests__/guestSurface.test.d.ts.map +1 -0
  28. package/dist/utils/__tests__/guestSurface.test.js +94 -0
  29. package/dist/utils/__tests__/guestSurface.test.js.map +1 -0
  30. package/dist/utils/__tests__/ticketTierSchedule.test.d.ts +2 -0
  31. package/dist/utils/__tests__/ticketTierSchedule.test.d.ts.map +1 -0
  32. package/dist/utils/__tests__/ticketTierSchedule.test.js +84 -0
  33. package/dist/utils/__tests__/ticketTierSchedule.test.js.map +1 -0
  34. package/dist/utils/featuredDiscoveryGeo.d.ts +30 -0
  35. package/dist/utils/featuredDiscoveryGeo.d.ts.map +1 -0
  36. package/dist/utils/featuredDiscoveryGeo.js +47 -0
  37. package/dist/utils/featuredDiscoveryGeo.js.map +1 -0
  38. package/dist/utils/flyerUtils.d.ts +5 -0
  39. package/dist/utils/flyerUtils.d.ts.map +1 -1
  40. package/dist/utils/flyerUtils.js +24 -0
  41. package/dist/utils/flyerUtils.js.map +1 -1
  42. package/dist/utils/guestSurface.d.ts +114 -0
  43. package/dist/utils/guestSurface.d.ts.map +1 -0
  44. package/dist/utils/guestSurface.js +164 -0
  45. package/dist/utils/guestSurface.js.map +1 -0
  46. package/dist/utils/promotionBlastUtils.d.ts +38 -0
  47. package/dist/utils/promotionBlastUtils.d.ts.map +1 -0
  48. package/dist/utils/promotionBlastUtils.js +88 -0
  49. package/dist/utils/promotionBlastUtils.js.map +1 -0
  50. package/dist/utils/service/__tests__/defaultOfferAmountUtils.test.d.ts +2 -0
  51. package/dist/utils/service/__tests__/defaultOfferAmountUtils.test.d.ts.map +1 -0
  52. package/dist/utils/service/__tests__/defaultOfferAmountUtils.test.js +65 -0
  53. package/dist/utils/service/__tests__/defaultOfferAmountUtils.test.js.map +1 -0
  54. package/dist/utils/service/defaultOfferAmountUtils.d.ts +32 -0
  55. package/dist/utils/service/defaultOfferAmountUtils.d.ts.map +1 -0
  56. package/dist/utils/service/defaultOfferAmountUtils.js +115 -0
  57. package/dist/utils/service/defaultOfferAmountUtils.js.map +1 -0
  58. package/dist/utils/ticketTierSchedule.d.ts +58 -0
  59. package/dist/utils/ticketTierSchedule.d.ts.map +1 -0
  60. package/dist/utils/ticketTierSchedule.js +279 -0
  61. package/dist/utils/ticketTierSchedule.js.map +1 -0
  62. package/package.json +5 -2
  63. package/prisma/schema.prisma +332 -1
  64. package/src/__tests__/ticketBnplPaymentMethods.cashapp.test.ts +45 -0
  65. package/src/__tests__/ticketBnplPaymentMethods.test.ts +66 -0
  66. package/src/definitions.ts +6 -1
  67. package/src/index.ts +6 -0
  68. package/src/ticketBnplPaymentMethods.ts +79 -0
  69. package/src/utils/__tests__/featuredDiscoveryGeo.test.ts +120 -0
  70. package/src/utils/__tests__/flyerUtils.test.ts +10 -0
  71. package/src/utils/__tests__/guestSurface.test.ts +128 -0
  72. package/src/utils/__tests__/ticketTierSchedule.test.ts +131 -0
  73. package/src/utils/featuredDiscoveryGeo.ts +75 -0
  74. package/src/utils/flyerUtils.ts +33 -0
  75. package/src/utils/guestSurface.ts +315 -0
  76. package/src/utils/promotionBlastUtils.ts +127 -0
  77. package/src/utils/service/__tests__/defaultOfferAmountUtils.test.ts +102 -0
  78. package/src/utils/service/defaultOfferAmountUtils.ts +170 -0
  79. package/src/utils/ticketTierSchedule.ts +387 -0
@@ -723,7 +723,25 @@ model BashEvent {
723
723
  allowPublicInterestRsvp Boolean @default(false)
724
724
  /// When true, guests can join a waitlist (activated automatically when amountOfGuests.allowWaitlistAtMax is set and max capacity is reached)
725
725
  waitlistEnabled Boolean @default(false)
726
- attendeeDisplayMode String @default("All") // "All" | "NetworkOnly" | "Hidden"
726
+ /// High-demand on-sale: virtual waiting room before checkout (requires queue worker when enabled).
727
+ queueEnabled Boolean @default(false)
728
+ /// When the waiting room opens (optional; null = opens at first paid checkout attempt).
729
+ queueOpensAt DateTime?
730
+ /// Target admits per second when queue is active.
731
+ queueAdmitRatePerSecond Int?
732
+ /// Stripe BNPL (Afterpay/Klarna) on eligible paid checkout.
733
+ installmentsEnabled Boolean @default(false)
734
+ /// Stripe Cash App Pay on eligible paid checkout (not Square OAuth).
735
+ cashAppEnabled Boolean @default(false)
736
+ /// Send confirmation SMS for this event when user opted in and env allows.
737
+ smsConfirmationsEnabled Boolean @default(false)
738
+ /// Collect named holder per seat at checkout.
739
+ namedTicketsEnabled Boolean @default(false)
740
+ attendeeDisplayMode String @default("All") // "All" | "CountOnly" | "NetworkOnly" | "Hidden"
741
+ /// Optional headline above featured guests on bash detail (curated guest visibility).
742
+ featuredGuestsHeadline String?
743
+ /// When true, bash detail shows the full privacy-filtered guest list to everyone (not just tier holders).
744
+ attendeeListPublic Boolean @default(false)
727
745
  showOrganizerTitles Boolean @default(false)
728
746
  servicePreferences Json? // New tiered status: { "Entertainment": "need", "Sponsors": "booked_closed", ... }
729
747
  bookedServices Json? // Booked service details: { "Entertainment": { serviceId: "...", providerId: "...", bookedAt: "..." }, ... }
@@ -822,6 +840,7 @@ model BashEvent {
822
840
  tickets Ticket[]
823
841
  ticketGiftGrants TicketGiftGrant[]
824
842
  ticketTiers TicketTier[]
843
+ tierReleaseReminders TierReleaseReminder[]
825
844
  favoritedBy UserFavorite[]
826
845
  userPromoCodeRedemption UserPromoCodeRedemption[]
827
846
  userReport UserReport[]
@@ -887,6 +906,8 @@ model BashEvent {
887
906
  bashEventArtists BashEventArtist[]
888
907
  vanityPaths EventVanityPath[]
889
908
  flyerCampaigns FlyerCampaign[]
909
+ featuredGuests EventFeaturedGuest[]
910
+ attendeeVisibilities EventAttendeeVisibility[]
890
911
 
891
912
  /// Latest AI moderator verdict (see `bashApprovalAiService` + `mapAiResultToDecision`).
892
913
  /// Null = never reviewed by AI. Recomputed each time the bash transitions to Pending
@@ -903,6 +924,8 @@ model BashEvent {
903
924
  aiApprovalContentHash String?
904
925
 
905
926
  bookingOffers ServiceBookingOffer[]
927
+ promotionBlastEntitlements PromotionBlastEntitlement[]
928
+ promotionBlasts PromotionBlast[]
906
929
 
907
930
  @@index([templateId])
908
931
  @@index([parentEventId])
@@ -975,6 +998,7 @@ enum FlyerSponsorSlot {
975
998
 
976
999
  enum FlyerSponsorReviewStatus {
977
1000
  DRAFT
1001
+ INVITE_PENDING
978
1002
  PAYMENT_PENDING
979
1003
  PAID
980
1004
  REVIEW_PENDING
@@ -1038,6 +1062,7 @@ model FlyerCampaign {
1038
1062
  artworkVersions FlyerArtwork[]
1039
1063
  sponsors FlyerCampaignSponsor[]
1040
1064
  conversions FlyerConversion[]
1065
+ bookingOffers ServiceBookingOffer[]
1041
1066
 
1042
1067
  createdAt DateTime @default(now())
1043
1068
  updatedAt DateTime @updatedAt
@@ -1121,6 +1146,7 @@ model FlyerCampaignSponsor {
1121
1146
 
1122
1147
  slotType FlyerSponsorSlot
1123
1148
  businessName String
1149
+ contactEmail String?
1124
1150
  logoS3Key String?
1125
1151
  logoAltText String?
1126
1152
  ctaText String?
@@ -1200,6 +1226,199 @@ model FlyerConversion {
1200
1226
  @@index([ticketId])
1201
1227
  }
1202
1228
 
1229
+ // --- Promotion Blast (on-site partner promos: time-boxed + geofence) ---
1230
+
1231
+ enum PromotionBlastTriggerType {
1232
+ TIME_BOXED
1233
+ GEOFENCE
1234
+ }
1235
+
1236
+ enum PromotionBlastTemplateReviewStatus {
1237
+ REVIEW_PENDING
1238
+ APPROVED
1239
+ FLAGGED
1240
+ }
1241
+
1242
+ enum PromotionBlastEntitlementStatus {
1243
+ PENDING_PAYMENT
1244
+ ACTIVE
1245
+ EXHAUSTED
1246
+ REVOKED
1247
+ REFUNDED
1248
+ }
1249
+
1250
+ enum PromotionBlastStatus {
1251
+ DRAFT
1252
+ SCHEDULED
1253
+ LIVE
1254
+ PAUSED
1255
+ ENDED
1256
+ CANCELLED
1257
+ }
1258
+
1259
+ enum PromotionBlastRedemptionMethod {
1260
+ QR
1261
+ MANUAL
1262
+ }
1263
+
1264
+ /// Reusable promo template saved on a partner service profile (How wizard).
1265
+ model PromotionBlastTemplate {
1266
+ id String @id @default(cuid())
1267
+ createdAt DateTime @default(now())
1268
+ updatedAt DateTime @updatedAt
1269
+
1270
+ serviceId String
1271
+ service Service @relation(fields: [serviceId], references: [id], onDelete: Cascade)
1272
+
1273
+ name String
1274
+ triggerType PromotionBlastTriggerType @default(TIME_BOXED)
1275
+ headline String
1276
+ body String?
1277
+ ctaLabel String @default("Show at booth")
1278
+ imageUrl String?
1279
+
1280
+ defaultDurationMinutes Int?
1281
+ defaultRadiusFeet Int?
1282
+ defaultMaxRedemptions Int?
1283
+
1284
+ serviceAddonId String?
1285
+ specialOfferId String?
1286
+
1287
+ reviewStatus PromotionBlastTemplateReviewStatus @default(REVIEW_PENDING)
1288
+ reviewNotes String?
1289
+ reviewedAt DateTime?
1290
+ reviewedByUserId String?
1291
+ reviewedBy User? @relation("PromotionBlastTemplateReviewedBy", fields: [reviewedByUserId], references: [id], onDelete: SetNull)
1292
+ isActive Boolean @default(true)
1293
+ sortOrder Int @default(0)
1294
+
1295
+ blasts PromotionBlast[]
1296
+
1297
+ @@index([serviceId])
1298
+ @@index([serviceId, isActive])
1299
+ }
1300
+
1301
+ /// Paid package granting blast activations for a booking at an event.
1302
+ model PromotionBlastEntitlement {
1303
+ id String @id @default(cuid())
1304
+ createdAt DateTime @default(now())
1305
+ updatedAt DateTime @updatedAt
1306
+
1307
+ serviceBookingId String @unique
1308
+ serviceBooking ServiceBooking @relation(fields: [serviceBookingId], references: [id], onDelete: Cascade)
1309
+ bashEventId String
1310
+ bashEvent BashEvent @relation(fields: [bashEventId], references: [id], onDelete: Cascade)
1311
+ serviceId String
1312
+ service Service @relation(fields: [serviceId], references: [id], onDelete: Cascade)
1313
+ partnerUserId String
1314
+ partnerUser User @relation("PromotionBlastPartner", fields: [partnerUserId], references: [id], onDelete: Cascade)
1315
+
1316
+ maxBlasts Int @default(3)
1317
+ maxPushRecipients Int?
1318
+ maxRadiusFeet Int @default(500)
1319
+ allowedTriggerTypes PromotionBlastTriggerType[] @default([TIME_BOXED, GEOFENCE])
1320
+
1321
+ hostAccessFeeCents Int @default(0)
1322
+ bashPlatformFeeCents Int @default(0)
1323
+ paidAt DateTime?
1324
+ stripePaymentIntentId String?
1325
+
1326
+ blastsUsed Int @default(0)
1327
+ status PromotionBlastEntitlementStatus @default(PENDING_PAYMENT)
1328
+
1329
+ packageTier String?
1330
+
1331
+ blasts PromotionBlast[]
1332
+
1333
+ @@index([bashEventId])
1334
+ @@index([serviceId])
1335
+ @@index([partnerUserId])
1336
+ @@index([status])
1337
+ }
1338
+
1339
+ /// Runtime promo instance activated at an event.
1340
+ model PromotionBlast {
1341
+ id String @id @default(cuid())
1342
+ createdAt DateTime @default(now())
1343
+ updatedAt DateTime @updatedAt
1344
+
1345
+ entitlementId String
1346
+ entitlement PromotionBlastEntitlement @relation(fields: [entitlementId], references: [id], onDelete: Cascade)
1347
+ templateId String?
1348
+ template PromotionBlastTemplate? @relation(fields: [templateId], references: [id], onDelete: SetNull)
1349
+ bashEventId String
1350
+ bashEvent BashEvent @relation(fields: [bashEventId], references: [id], onDelete: Cascade)
1351
+ serviceId String
1352
+ service Service @relation(fields: [serviceId], references: [id], onDelete: Cascade)
1353
+ partnerUserId String
1354
+ partnerUser User @relation("PromotionBlastOwner", fields: [partnerUserId], references: [id], onDelete: Cascade)
1355
+
1356
+ triggerType PromotionBlastTriggerType
1357
+ startsAt DateTime
1358
+ endsAt DateTime?
1359
+ radiusFeet Int?
1360
+ centerLat Float?
1361
+ centerLng Float?
1362
+
1363
+ headline String
1364
+ body String?
1365
+ ctaLabel String @default("Show at booth")
1366
+ imageUrl String?
1367
+
1368
+ status PromotionBlastStatus @default(DRAFT)
1369
+
1370
+ pushSentCount Int @default(0)
1371
+ impressionCount Int @default(0)
1372
+ redemptionCount Int @default(0)
1373
+
1374
+ pausedAt DateTime?
1375
+ pausedByUserId String?
1376
+ pausedBy User? @relation("PromotionBlastPausedBy", fields: [pausedByUserId], references: [id], onDelete: SetNull)
1377
+
1378
+ redemptions PromotionBlastRedemption[]
1379
+ pushDeliveries PromotionBlastPushDelivery[]
1380
+
1381
+ @@index([bashEventId, status])
1382
+ @@index([entitlementId])
1383
+ @@index([serviceId])
1384
+ @@index([partnerUserId])
1385
+ @@index([status, endsAt])
1386
+ }
1387
+
1388
+ model PromotionBlastRedemption {
1389
+ id String @id @default(cuid())
1390
+ createdAt DateTime @default(now())
1391
+
1392
+ promotionBlastId String
1393
+ promotionBlast PromotionBlast @relation(fields: [promotionBlastId], references: [id], onDelete: Cascade)
1394
+ userId String
1395
+ user User @relation(fields: [userId], references: [id], onDelete: Cascade)
1396
+
1397
+ confirmationCode String?
1398
+ redeemedAt DateTime?
1399
+ method PromotionBlastRedemptionMethod @default(MANUAL)
1400
+
1401
+ @@unique([promotionBlastId, userId])
1402
+ @@index([promotionBlastId])
1403
+ @@index([userId])
1404
+ }
1405
+
1406
+ /// Tracks push sends for dedupe and global event caps.
1407
+ model PromotionBlastPushDelivery {
1408
+ id String @id @default(cuid())
1409
+ createdAt DateTime @default(now())
1410
+
1411
+ promotionBlastId String
1412
+ promotionBlast PromotionBlast @relation(fields: [promotionBlastId], references: [id], onDelete: Cascade)
1413
+ userId String
1414
+ user User @relation(fields: [userId], references: [id], onDelete: Cascade)
1415
+ bashEventId String
1416
+
1417
+ @@unique([promotionBlastId, userId])
1418
+ @@index([userId, bashEventId, createdAt])
1419
+ @@index([bashEventId])
1420
+ }
1421
+
1203
1422
  /// USPS carrier-route catalog (Utah MVP; expand for national rollout).
1204
1423
  model PostalCarrierRoute {
1205
1424
  id String @id @default(cuid())
@@ -1714,13 +1933,26 @@ model TicketTier {
1714
1933
  // Availability rules
1715
1934
  availabilityType String @default("Immediate") // "Immediate" | "OnDate" | "EngagedUsersOnly" | "UnlockWhenInterestReached" | "UnlockWhenTicketsSold"
1716
1935
  availableAt DateTime? // OnDate: when tier unlocks
1936
+ expiresAt DateTime? // Hide + block purchase after this instant
1937
+ preReleaseDisplay String @default("Tease") // "Tease" | "Hidden" before availableAt when OnDate
1938
+ isManuallySoldOut Boolean @default(false)
1939
+ notifyOnRelease Boolean @default(true)
1940
+ tierReleaseNotifiedAt DateTime?
1717
1941
  availableWhenInterestReached Int? // UnlockWhenInterestReached: min IdeaInterest count
1718
1942
  unlockWhenTicketsSold Int? // UnlockWhenTicketsSold: min tickets sold across event to unlock this tier
1719
1943
  maxTicketsPerUser Int? // Optional per-user purchase cap
1944
+ /// Presale audience gate (PR7): "Public" | "Ambashador" | "BashInsider" | "Promoters"
1945
+ presaleAudience String @default("Public")
1946
+ /// When presaleAudience != Public, public sale opens at this time (optional; falls back to availableAt)
1947
+ publicAvailableAt DateTime?
1720
1948
 
1721
1949
  // Privacy: "Public" | "LinkOnly" | "InviteOnly"
1722
1950
  tierPrivacy String @default("Public")
1723
1951
 
1952
+ /// Guest list visibility depth for ticket holders: "None" | "Partial" | "Full"
1953
+ guestListDepth String @default("None")
1954
+ partialRosterLimit Int?
1955
+
1724
1956
  // Checkout timer: host-configurable per-tier timeout (minutes). null = no timer.
1725
1957
  checkoutTimeoutMinutes Int?
1726
1958
 
@@ -1729,8 +1961,10 @@ model TicketTier {
1729
1961
  /// Max BashPass redemptions for this tier (null = unlimited within tier capacity).
1730
1962
  bashPassMaxRedemptions Int?
1731
1963
  ticketGiftGrants TicketGiftGrant[]
1964
+ tierReleaseReminders TierReleaseReminder[]
1732
1965
 
1733
1966
  @@unique([bashEventId, title])
1967
+ @@index([availableAt])
1734
1968
  }
1735
1969
 
1736
1970
  enum TicketGiftGrantStatus {
@@ -1805,6 +2039,14 @@ model Ticket {
1805
2039
  /// Rotated when ticket is transferred; QR payload must match for check-in (null = legacy tickets, no strict check).
1806
2040
  qrToken String?
1807
2041
 
2042
+ /// P2P Venmo/Zelle off-platform payment flow
2043
+ p2pPaymentMethod String?
2044
+ p2pTransactionId String?
2045
+ p2pRequestedAt DateTime?
2046
+ p2pConfirmedAt DateTime?
2047
+ /// Set when we send the ~24h-before-event P2P reminder to the host (once per ticket).
2048
+ p2pHostReminderSentAt DateTime?
2049
+
1808
2050
  // BashPoints Purchase Tracking
1809
2051
  purchaseType String? // "USD", "BashPoints", "Free", "Comp", "BashPass", "PayAtDoor", "Cash"
1810
2052
  /// Promo entered at Pay-at-Door reservation; discount applied when they pay at the door (analytics: unpaid rows with code set).
@@ -1845,6 +2087,37 @@ model Ticket {
1845
2087
  @@index([giftGrantId])
1846
2088
  }
1847
2089
 
2090
+ /// Host-curated spotlight row on bash detail (image + name only).
2091
+ model EventFeaturedGuest {
2092
+ id String @id @default(cuid())
2093
+ bashEventId String
2094
+ userId String
2095
+ sortOrder Int @default(0)
2096
+ featuredAt DateTime @default(now())
2097
+ featuredBy String
2098
+ bashEvent BashEvent @relation(fields: [bashEventId], references: [id], onDelete: Cascade)
2099
+ user User @relation("FeaturedGuestOnEvent", fields: [userId], references: [id], onDelete: Cascade)
2100
+
2101
+ @@unique([bashEventId, userId])
2102
+ @@index([bashEventId, sortOrder])
2103
+ }
2104
+
2105
+ /// Per-guest visibility for an event (user × event).
2106
+ model EventAttendeeVisibility {
2107
+ id String @id @default(cuid())
2108
+ bashEventId String
2109
+ userId String
2110
+ visibility String @default("Visible") // Visible | Hidden | FeaturedPending | FeaturedInvited
2111
+ priorVisibility String? // Visible | Hidden — snapshot when host sends featured invite
2112
+ setAt DateTime @default(now())
2113
+ setBy String?
2114
+ bashEvent BashEvent @relation(fields: [bashEventId], references: [id], onDelete: Cascade)
2115
+ user User @relation("AttendeeVisibilityOnEvent", fields: [userId], references: [id], onDelete: Cascade)
2116
+
2117
+ @@unique([bashEventId, userId])
2118
+ @@index([bashEventId, visibility])
2119
+ }
2120
+
1848
2121
  model TicketTransfer {
1849
2122
  id String @id @default(cuid())
1850
2123
  ticketId String
@@ -2515,6 +2788,12 @@ model User {
2515
2788
  serviceBookingMessages ServiceBookingMessage[] @relation("ServiceMessageSender")
2516
2789
  sentBookingOffers ServiceBookingOffer[] @relation("OfferSender")
2517
2790
  receivedBookingOffers ServiceBookingOffer[] @relation("OfferRecipient")
2791
+ promotionBlastEntitlements PromotionBlastEntitlement[] @relation("PromotionBlastPartner")
2792
+ promotionBlastsOwned PromotionBlast[] @relation("PromotionBlastOwner")
2793
+ promotionBlastsPaused PromotionBlast[] @relation("PromotionBlastPausedBy")
2794
+ promotionBlastRedemptions PromotionBlastRedemption[]
2795
+ promotionBlastPushDeliveries PromotionBlastPushDelivery[]
2796
+ promotionBlastTemplatesReviewed PromotionBlastTemplate[] @relation("PromotionBlastTemplateReviewedBy")
2518
2797
  sessions Session[]
2519
2798
  socialMediaProfiles SocialMediaProfile[]
2520
2799
  sponsorBookingRequestsAsHost SponsorBookingRequest[] @relation("SponsorBookingHost")
@@ -2523,6 +2802,8 @@ model User {
2523
2802
  paymentProviderAccounts PaymentProviderAccount[]
2524
2803
  ticketsISent Ticket[] @relation("TicketsISent")
2525
2804
  ticketsIOwn Ticket[] @relation("TicketsIOwn")
2805
+ eventFeaturedGuestSpots EventFeaturedGuest[] @relation("FeaturedGuestOnEvent")
2806
+ eventAttendeeVisibilities EventAttendeeVisibility[] @relation("AttendeeVisibilityOnEvent")
2526
2807
  bashEventDonations BashEventDonation[]
2527
2808
  bashCreativeSubmissions BashCreativeSubmission[]
2528
2809
  ticketsOnWaitlist Ticket[] @relation("TicketsOnWaitlist")
@@ -2572,6 +2853,7 @@ model User {
2572
2853
  redeemedVouchers Voucher[]
2573
2854
  bashEventPromoCodesIUsed BashEventPromoCode[] @relation("BashEventPromoCodeToUser")
2574
2855
  ticketTiersWaitListsIveJoined TicketTier[] @relation("TicketTierToUser")
2856
+ tierReleaseReminders TierReleaseReminder[]
2575
2857
  scoutReferralsMade ScoutReferral[] @relation("ScoutReferrer")
2576
2858
  eventReferralsMade EventReferral[] @relation("EventReferralsMade")
2577
2859
  eventReferralsReceived EventReferral[] @relation("EventReferralsReceived")
@@ -2683,6 +2965,8 @@ model UserPreferences {
2683
2965
  invitationNotify Boolean @default(true)
2684
2966
  commentNotify Boolean @default(true)
2685
2967
  servicePromotionsNotify Boolean @default(true)
2968
+ locationPromotionsOptIn Boolean @default(false)
2969
+ ticketTierUpdatesNotify Boolean @default(true)
2686
2970
  profileVisibility String @default("public")
2687
2971
  eventHistoryVisibility Boolean @default(true)
2688
2972
  servicesVisibility Boolean @default(true)
@@ -3179,6 +3463,9 @@ model Service {
3179
3463
  addonRequests ServiceAddonRequest[]
3180
3464
  serviceBudgets Budget[] @relation("ServiceBudgets")
3181
3465
  bookingOffers ServiceBookingOffer[]
3466
+ promotionBlastTemplates PromotionBlastTemplate[]
3467
+ promotionBlastEntitlements PromotionBlastEntitlement[]
3468
+ promotionBlasts PromotionBlast[]
3182
3469
 
3183
3470
  @@index([serviceListingStripeSubscriptionId])
3184
3471
  @@index([paymentAccountId])
@@ -3193,6 +3480,10 @@ model StripeAccount {
3193
3480
  ownerId String
3194
3481
  stripeAccountId String @unique
3195
3482
  stripeCustomerId String? @unique
3483
+ /// Cached from Stripe account.updated webhook — Connect BNPL eligibility.
3484
+ stripeKlarnaPaymentsActive Boolean?
3485
+ stripeCashappPaymentsActive Boolean?
3486
+ stripeCardPaymentsActive Boolean?
3196
3487
  logoId String?
3197
3488
  createdAt DateTime @default(now())
3198
3489
  updatedAt DateTime @updatedAt
@@ -4575,6 +4866,7 @@ model ServiceBooking {
4575
4866
  commissions BookingCommission[] @relation("BookingCommissions")
4576
4867
  sentReminders SentReminder[]
4577
4868
  offers ServiceBookingOffer[]
4869
+ promotionBlastEntitlement PromotionBlastEntitlement?
4578
4870
 
4579
4871
  @@index([status])
4580
4872
  @@index([creatorId])
@@ -5224,6 +5516,33 @@ enum NotificationType {
5224
5516
  BudgetInvoiceDueToday // Host/organizer: invoice due today
5225
5517
  BudgetInvoicePastDue // Host/organizer: invoice 1 day past due
5226
5518
  BudgetInvoicePastDueFinal // Host/organizer: invoice 15+ days past due
5519
+ TicketTierReleased // Tier scheduled release went live
5520
+ TicketTierExpiringSoon // Tier sale window closing soon
5521
+ TicketTierRestocked // Host reopened sold-out tier or added capacity
5522
+ FeaturedGuestInvited // Host invited ticket holder to be a featured guest
5523
+ FeaturedGuestInviteAccepted // Host: guest accepted featured guest invite
5524
+ FeaturedGuestInviteDeclined // Host: guest declined featured guest invite
5525
+ PartnerPromotionBlast // Attendee: partner on-site promo deal at an event
5526
+ }
5527
+
5528
+ /// Opt-in reminder for a scheduled tier release (v1.5).
5529
+ model TierReleaseReminder {
5530
+ id String @id @default(cuid())
5531
+ userId String
5532
+ user User @relation(fields: [userId], references: [id], onDelete: Cascade)
5533
+ ticketTierId String
5534
+ ticketTier TicketTier @relation(fields: [ticketTierId], references: [id], onDelete: Cascade)
5535
+ bashEventId String
5536
+ bashEvent BashEvent @relation(fields: [bashEventId], references: [id], onDelete: Cascade)
5537
+ reminded24hAt DateTime?
5538
+ reminded1hAt DateTime?
5539
+ remindedAtReleaseAt DateTime?
5540
+ expiryReminded1hAt DateTime?
5541
+ createdAt DateTime @default(now())
5542
+
5543
+ @@unique([userId, ticketTierId])
5544
+ @@index([bashEventId])
5545
+ @@index([ticketTierId])
5227
5546
  }
5228
5547
 
5229
5548
  enum NotificationPriority {
@@ -5263,6 +5582,9 @@ enum TicketStatus {
5263
5582
  Pending
5264
5583
  WaitlistPending // Requested a spot on a host-approval waitlist; awaiting decision
5265
5584
  RefundPending // Refund requested; held while next waitlister is given a claim window
5585
+ P2PPending // Venmo/Zelle payment requested; awaiting host confirmation
5586
+ P2PConfirmed // Host confirmed P2P payment; valid for admission
5587
+ P2PExpired // Event ended with unconfirmed P2P request (cleanup job)
5266
5588
  }
5267
5589
 
5268
5590
  enum DayOfWeek {
@@ -7112,6 +7434,13 @@ model ServiceBookingOffer {
7112
7434
  serviceBookingId String? // set once attached to a Pending booking or after accept
7113
7435
  vendorBookingRequestId String? // for Vendor/Exhibitor/Sponsor flow
7114
7436
 
7437
+ /// Flyer Blast sponsor slot offer — when set, accept materializes FlyerCampaignSponsor.
7438
+ flyerCampaignId String?
7439
+ flyerSlotType FlyerSponsorSlot?
7440
+
7441
+ /// Promotion Blast package terms during negotiation (JSON).
7442
+ promotionBlastPackageJson Json?
7443
+
7115
7444
  parentOfferId String? // the offer this is countering
7116
7445
  roundNumber Int // 1, 2, or 3 — server-enforced cap of 3
7117
7446
 
@@ -7147,6 +7476,7 @@ model ServiceBookingOffer {
7147
7476
  bashEvent BashEvent @relation(fields: [bashEventId], references: [id], onDelete: Cascade)
7148
7477
  serviceBooking ServiceBooking? @relation(fields: [serviceBookingId], references: [id], onDelete: SetNull)
7149
7478
  vendorBookingRequest VendorBookingRequest? @relation(fields: [vendorBookingRequestId], references: [id], onDelete: SetNull)
7479
+ flyerCampaign FlyerCampaign? @relation(fields: [flyerCampaignId], references: [id], onDelete: SetNull)
7150
7480
  parentOffer ServiceBookingOffer? @relation("OfferCounters", fields: [parentOfferId], references: [id], onDelete: SetNull)
7151
7481
  counters ServiceBookingOffer[] @relation("OfferCounters")
7152
7482
  sender User @relation("OfferSender", fields: [senderId], references: [id])
@@ -7156,6 +7486,7 @@ model ServiceBookingOffer {
7156
7486
  @@index([serviceBookingId])
7157
7487
  @@index([recipientId, status])
7158
7488
  @@index([senderId])
7489
+ @@index([flyerCampaignId, flyerSlotType])
7159
7490
  }
7160
7491
 
7161
7492
  enum VendorBookingStatus {
@@ -0,0 +1,45 @@
1
+ /**
2
+ * @jest-environment node
3
+ */
4
+ import { describe, expect, it } from "@jest/globals";
5
+
6
+ import {
7
+ resolveTicketCheckoutPaymentMethodTypes,
8
+ ticketCheckoutOffersCashApp,
9
+ } from "../ticketBnplPaymentMethods.js";
10
+
11
+ describe("resolveTicketCheckoutPaymentMethodTypes cashapp", () => {
12
+ it("includes cashapp when host toggle and USD order", () => {
13
+ expect(
14
+ resolveTicketCheckoutPaymentMethodTypes({
15
+ installmentsEnabled: false,
16
+ cashAppEnabled: true,
17
+ totalChargedCents: 1500,
18
+ currency: "usd",
19
+ })
20
+ ).toContain("cashapp");
21
+ });
22
+
23
+ it("excludes cashapp when globally disabled", () => {
24
+ expect(
25
+ resolveTicketCheckoutPaymentMethodTypes({
26
+ installmentsEnabled: false,
27
+ cashAppEnabled: true,
28
+ totalChargedCents: 1500,
29
+ currency: "usd",
30
+ cashAppGloballyEnabled: false,
31
+ })
32
+ ).not.toContain("cashapp");
33
+ });
34
+
35
+ it("ticketCheckoutOffersCashApp reflects resolver", () => {
36
+ expect(
37
+ ticketCheckoutOffersCashApp({
38
+ cashAppEnabled: true,
39
+ installmentsEnabled: false,
40
+ totalChargedCents: 500,
41
+ currency: "usd",
42
+ })
43
+ ).toBe(true);
44
+ });
45
+ });
@@ -0,0 +1,66 @@
1
+ import {
2
+ resolveTicketCheckoutPaymentMethodTypes,
3
+ ticketCheckoutOffersBnpl,
4
+ TICKET_BNPL_MAX_CENTS_USD,
5
+ TICKET_BNPL_MIN_CENTS_USD,
6
+ } from "../ticketBnplPaymentMethods.js";
7
+
8
+ describe("ticketBnplPaymentMethods", () => {
9
+ const eligible = {
10
+ installmentsEnabled: true,
11
+ totalChargedCents: 12_000,
12
+ currency: "usd",
13
+ };
14
+
15
+ it("returns card+link only when installments disabled", () => {
16
+ expect(
17
+ resolveTicketCheckoutPaymentMethodTypes({
18
+ ...eligible,
19
+ installmentsEnabled: false,
20
+ })
21
+ ).toEqual(["card", "link"]);
22
+ });
23
+
24
+ it("adds klarna and afterpay_clearpay when eligible", () => {
25
+ expect(resolveTicketCheckoutPaymentMethodTypes(eligible)).toEqual([
26
+ "card",
27
+ "link",
28
+ "klarna",
29
+ "afterpay_clearpay",
30
+ ]);
31
+ expect(ticketCheckoutOffersBnpl(eligible)).toBe(true);
32
+ });
33
+
34
+ it("skips BNPL below minimum or above maximum", () => {
35
+ expect(
36
+ resolveTicketCheckoutPaymentMethodTypes({
37
+ ...eligible,
38
+ totalChargedCents: TICKET_BNPL_MIN_CENTS_USD - 1,
39
+ })
40
+ ).toEqual(["card", "link"]);
41
+ expect(
42
+ resolveTicketCheckoutPaymentMethodTypes({
43
+ ...eligible,
44
+ totalChargedCents: TICKET_BNPL_MAX_CENTS_USD + 1,
45
+ })
46
+ ).toEqual(["card", "link"]);
47
+ });
48
+
49
+ it("skips BNPL for non-USD", () => {
50
+ expect(
51
+ resolveTicketCheckoutPaymentMethodTypes({
52
+ ...eligible,
53
+ currency: "eur",
54
+ })
55
+ ).toEqual(["card", "link"]);
56
+ });
57
+
58
+ it("respects global kill switch", () => {
59
+ expect(
60
+ resolveTicketCheckoutPaymentMethodTypes({
61
+ ...eligible,
62
+ bnplGloballyEnabled: false,
63
+ })
64
+ ).toEqual(["card", "link"]);
65
+ });
66
+ });
@@ -751,7 +751,7 @@ export interface NumberOfTicketsForDate {
751
751
 
752
752
  export interface TicketTierAvailability {
753
753
  available: boolean;
754
- reason?: "OnDate" | "EngagedUsersOnly" | "UnlockWhenInterestReached" | "UnlockWhenTicketsSold";
754
+ reason?: "OnDate" | "EngagedUsersOnly" | "UnlockWhenInterestReached" | "UnlockWhenTicketsSold" | "SoldOut";
755
755
  availableAt?: string; // ISO string, OnDate
756
756
  interestCount?: number; // current count, UnlockWhenInterestReached
757
757
  interestThreshold?: number; // target, UnlockWhenInterestReached
@@ -1017,6 +1017,11 @@ export type StripeLinkingStatus = {
1017
1017
  hasOutstandingRequirements: boolean;
1018
1018
  paymentsEnabled: boolean;
1019
1019
  taxMonitoringEnabled: boolean;
1020
+ /** Host account missing business_type or MCC — blocks Cash App eligibility. */
1021
+ missingBusinessProfileForCashApp?: boolean;
1022
+ cardPaymentsActive?: boolean;
1023
+ klarnaPaymentsActive?: boolean;
1024
+ cashappPaymentsActive?: boolean;
1020
1025
  };
1021
1026
 
1022
1027
  export type StripeBusinessDataPublic = {
package/src/index.ts CHANGED
@@ -9,9 +9,11 @@ export * from "./partnerStoreTypes.js";
9
9
  export * from "./bashFeedTypes.js";
10
10
  export * from "./membershipDefinitions.js";
11
11
  export * from "./onSaleCapabilityRecommendations.js";
12
+ export * from "./ticketBnplPaymentMethods.js";
12
13
  export * from "./aiApproval.js";
13
14
  export * from "./userReportTypes.js";
14
15
  export * from "./mirroredPrismaEnums.js";
16
+ export * from "./utils/featuredDiscoveryGeo.js";
15
17
 
16
18
  // Re-export ALL Prisma enums as values (usable as runtime constants, e.g. ServiceTypes.Entertainment)
17
19
  // Excludes enums already re-exported by definitions.ts, mirroredPrismaEnums.ts, and membershipDefinitions.ts:
@@ -314,6 +316,7 @@ export * from "./utils/service/venueSettlementUtils.js";
314
316
  export * from "./utils/service/offerAllowListUtils.js";
315
317
  export * from "./utils/service/offerComparisonUtils.js";
316
318
  export * from "./utils/service/unifiedPricingResolver.js";
319
+ export * from "./utils/service/defaultOfferAmountUtils.js";
317
320
  export * from "./utils/service/volunteerCompensationUtils.js";
318
321
  export * from "./utils/service/cancellationPolicyRefundResolver.js";
319
322
  export * from "./utils/venueLoyalty/eligibilityUtils.js";
@@ -331,6 +334,9 @@ export * from "./utils/blog/blogCommentDbUtils.js";
331
334
  export * from "./utils/blogUtils.js";
332
335
  export * from "./utils/entityUtils.js";
333
336
  export * from "./utils/flyerUtils.js";
337
+ export * from "./utils/promotionBlastUtils.js";
338
+ export * from "./utils/guestSurface.js";
339
+ export * from "./utils/ticketTierSchedule.js";
334
340
  export * from "./utils/lobFlyerUtils.js";
335
341
  export * from "./utils/generalDateTimeUtils.js";
336
342
  export * from "./utils/locationVisibility.js";