@bash-app/bash-common 30.142.0 → 30.143.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/package.json +1 -1
- package/prisma/schema.prisma +342 -0
package/package.json
CHANGED
package/prisma/schema.prisma
CHANGED
|
@@ -555,6 +555,7 @@ model Invitation {
|
|
|
555
555
|
model BashEvent {
|
|
556
556
|
id String @id @default(cuid())
|
|
557
557
|
source BashEventSource @default(Bash)
|
|
558
|
+
sourcePartnerId String? // When source=Partner, e.g. 'jamwith', 'mixlog'
|
|
558
559
|
title String
|
|
559
560
|
slug String? @unique
|
|
560
561
|
creatorId String
|
|
@@ -1374,6 +1375,7 @@ model User {
|
|
|
1374
1375
|
isSuperUser Boolean @default(false)
|
|
1375
1376
|
isSuspended Boolean @default(false)
|
|
1376
1377
|
intent UserIntent?
|
|
1378
|
+
signupSource String? // e.g. 'jamwith', 'mixlog', 'organic' for attribution
|
|
1377
1379
|
googleCalendarAccess String?
|
|
1378
1380
|
|
|
1379
1381
|
// Google OAuth tokens for API access (Contacts, Calendar, etc.)
|
|
@@ -1391,6 +1393,15 @@ model User {
|
|
|
1391
1393
|
uploadedImage String?
|
|
1392
1394
|
uploadedImageUpdatedAt DateTime? // When manually uploaded image was last updated
|
|
1393
1395
|
dob DateTime?
|
|
1396
|
+
showBirthdayOnProfile Boolean @default(false) // If true, show month/day on public profile
|
|
1397
|
+
// Part B: Birthday Rewards full product
|
|
1398
|
+
birthdayRewardsOptIn Boolean @default(false)
|
|
1399
|
+
birthdayRewardsOptInAt DateTime?
|
|
1400
|
+
birthdayLocationId String? // FK UserLocation (birthday home base)
|
|
1401
|
+
birthdayMaxDistanceMiles Int @default(25)
|
|
1402
|
+
birthdayNoPurchaseOnly Boolean @default(false)
|
|
1403
|
+
birthdayCategories String[] @default([]) // e.g. restaurant, coffee, dessert
|
|
1404
|
+
idDocumentUrl String? // Optional: secure ID upload for verification
|
|
1394
1405
|
gender Gender?
|
|
1395
1406
|
sex Sex?
|
|
1396
1407
|
organization String?
|
|
@@ -1478,6 +1489,15 @@ model User {
|
|
|
1478
1489
|
auditLogs AuditLog[] @relation("UserAuditLogs")
|
|
1479
1490
|
auditLogsPerformed AuditLog[] @relation("PerformedByUser")
|
|
1480
1491
|
consents UserConsent[]
|
|
1492
|
+
birthdayOfferOptIns UserBirthdayOfferOptIn[]
|
|
1493
|
+
birthdayOfferDeliveries BirthdayOfferDelivery[]
|
|
1494
|
+
birthdayBoostGrants BirthdayBoostGrant[]
|
|
1495
|
+
birthdayRewardRedemptions BirthdayRewardRedemption[]
|
|
1496
|
+
birthdayDealSuggestions BirthdayDealSuggestion[]
|
|
1497
|
+
userLocations UserLocation[]
|
|
1498
|
+
birthdayLocation UserLocation? @relation("UserBirthdayLocation", fields: [birthdayLocationId], references: [id], onDelete: SetNull)
|
|
1499
|
+
offerClaims OfferClaim[]
|
|
1500
|
+
birthdayPlans BirthdayPlan[]
|
|
1481
1501
|
|
|
1482
1502
|
associatedBashes AssociatedBash[]
|
|
1483
1503
|
associatedServices AssociatedService[]
|
|
@@ -3610,6 +3630,8 @@ enum BashEventSource {
|
|
|
3610
3630
|
LinkedIn
|
|
3611
3631
|
Meetup
|
|
3612
3632
|
Facebook
|
|
3633
|
+
JamWith
|
|
3634
|
+
Partner // Generic: use sourcePartnerId for partner key (e.g. 'mixlog', custom integrations)
|
|
3613
3635
|
}
|
|
3614
3636
|
|
|
3615
3637
|
enum TicketStatus {
|
|
@@ -5516,6 +5538,7 @@ enum CreditSourceType {
|
|
|
5516
5538
|
FirstFavoriteBash // First bash added to favorites
|
|
5517
5539
|
FirstShareBash // First time sharing a bash event
|
|
5518
5540
|
FirstInviteToBash // First invite to someone else's bash
|
|
5541
|
+
BirthdayReward // Annual BashPoints boost on user's birthday
|
|
5519
5542
|
}
|
|
5520
5543
|
|
|
5521
5544
|
enum PendingGiftStatus {
|
|
@@ -5577,6 +5600,325 @@ enum ConsentType {
|
|
|
5577
5600
|
Analytics // Optional: Google Analytics, Mixpanel, etc.
|
|
5578
5601
|
Marketing // Optional: Promotional emails
|
|
5579
5602
|
ThirdPartySharing // Optional: Share data with partners
|
|
5603
|
+
BirthdayOffers // Optional: Receive birthday offers from partner companies
|
|
5604
|
+
}
|
|
5605
|
+
|
|
5606
|
+
// Birthday offers from partner companies: users opt in once, we send minimal PII to partner APIs
|
|
5607
|
+
model BirthdayOfferPartner {
|
|
5608
|
+
id String @id @default(cuid())
|
|
5609
|
+
name String
|
|
5610
|
+
slug String @unique
|
|
5611
|
+
description String? @db.Text
|
|
5612
|
+
apiEndpoint String // Partner API URL; API keys live in env (BIRTHDAY_PARTNER_<SLUG>_API_KEY)
|
|
5613
|
+
config Json? // Partner-specific: e.g. sendFullDob (bool), extra fields
|
|
5614
|
+
requiresPhone Boolean @default(false) // Part B: when true, share User.phone with partner
|
|
5615
|
+
isActive Boolean @default(true)
|
|
5616
|
+
createdAt DateTime @default(now())
|
|
5617
|
+
updatedAt DateTime @updatedAt
|
|
5618
|
+
optIns UserBirthdayOfferOptIn[]
|
|
5619
|
+
deliveries BirthdayOfferDelivery[]
|
|
5620
|
+
catalogEntries BirthdayFreebieCatalog[]
|
|
5621
|
+
|
|
5622
|
+
@@index([isActive])
|
|
5623
|
+
}
|
|
5624
|
+
|
|
5625
|
+
model UserBirthdayOfferOptIn {
|
|
5626
|
+
id String @id @default(cuid())
|
|
5627
|
+
userId String
|
|
5628
|
+
partnerId String
|
|
5629
|
+
optedInAt DateTime @default(now())
|
|
5630
|
+
lastSentAt DateTime? // Last time we sent this user to this partner (for idempotency)
|
|
5631
|
+
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
5632
|
+
partner BirthdayOfferPartner @relation(fields: [partnerId], references: [id], onDelete: Cascade)
|
|
5633
|
+
|
|
5634
|
+
@@unique([userId, partnerId])
|
|
5635
|
+
@@index([partnerId])
|
|
5636
|
+
@@index([userId])
|
|
5637
|
+
}
|
|
5638
|
+
|
|
5639
|
+
model BirthdayOfferDelivery {
|
|
5640
|
+
id String @id @default(cuid())
|
|
5641
|
+
userId String
|
|
5642
|
+
partnerId String
|
|
5643
|
+
birthdayYear Int // Year when the send counted (for idempotency: one send per user/partner/year)
|
|
5644
|
+
sentAt DateTime @default(now())
|
|
5645
|
+
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
5646
|
+
partner BirthdayOfferPartner @relation(fields: [partnerId], references: [id], onDelete: Cascade)
|
|
5647
|
+
|
|
5648
|
+
@@unique([userId, partnerId, birthdayYear])
|
|
5649
|
+
@@index([partnerId])
|
|
5650
|
+
@@index([userId])
|
|
5651
|
+
}
|
|
5652
|
+
|
|
5653
|
+
// Birthday Rewards focused scope (v1): annual BashPoints boost idempotency
|
|
5654
|
+
model BirthdayBoostGrant {
|
|
5655
|
+
id String @id @default(cuid())
|
|
5656
|
+
userId String
|
|
5657
|
+
birthdayYear Int // Year for which boost was granted
|
|
5658
|
+
grantedAt DateTime @default(now())
|
|
5659
|
+
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
5660
|
+
|
|
5661
|
+
@@unique([userId, birthdayYear])
|
|
5662
|
+
@@index([userId])
|
|
5663
|
+
@@index([birthdayYear])
|
|
5664
|
+
}
|
|
5665
|
+
|
|
5666
|
+
// User-recorded places where they picked up a birthday reward (with optional rating)
|
|
5667
|
+
model BirthdayRewardRedemption {
|
|
5668
|
+
id String @id @default(cuid())
|
|
5669
|
+
userId String
|
|
5670
|
+
placeName String // e.g. "Freddy's", "Starbucks"
|
|
5671
|
+
redeemedAt DateTime @default(now())
|
|
5672
|
+
birthdayYear Int
|
|
5673
|
+
notes String? @db.Text
|
|
5674
|
+
difficultyScore Int? // 1-10
|
|
5675
|
+
qualityScore Int? // 1-10
|
|
5676
|
+
ratingComment String? @db.Text
|
|
5677
|
+
ratedAt DateTime?
|
|
5678
|
+
offerId String? // Part B: optional FK to structured BirthdayOffer
|
|
5679
|
+
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
5680
|
+
offer BirthdayOffer? @relation(fields: [offerId], references: [id], onDelete: SetNull)
|
|
5681
|
+
|
|
5682
|
+
@@index([userId])
|
|
5683
|
+
@@index([userId, birthdayYear])
|
|
5684
|
+
@@index([offerId])
|
|
5685
|
+
}
|
|
5686
|
+
|
|
5687
|
+
enum BirthdayDealSuggestionStatus {
|
|
5688
|
+
Pending
|
|
5689
|
+
Approved
|
|
5690
|
+
Rejected
|
|
5691
|
+
}
|
|
5692
|
+
|
|
5693
|
+
// User-suggested birthday deals (admin can approve and add to catalog later)
|
|
5694
|
+
model BirthdayDealSuggestion {
|
|
5695
|
+
id String @id @default(cuid())
|
|
5696
|
+
userId String
|
|
5697
|
+
brandOrPlaceName String
|
|
5698
|
+
dealDescription String @db.Text
|
|
5699
|
+
sourceWhereHeard String? @db.Text
|
|
5700
|
+
linkUrl String? @db.Text
|
|
5701
|
+
status BirthdayDealSuggestionStatus @default(Pending)
|
|
5702
|
+
createdAt DateTime @default(now())
|
|
5703
|
+
reviewedAt DateTime?
|
|
5704
|
+
reviewedById String?
|
|
5705
|
+
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
5706
|
+
catalogEntry BirthdayFreebieCatalog?
|
|
5707
|
+
|
|
5708
|
+
@@index([userId])
|
|
5709
|
+
@@index([status])
|
|
5710
|
+
}
|
|
5711
|
+
|
|
5712
|
+
// Public SEO catalog for birthday freebie pages (programmatic by city/state)
|
|
5713
|
+
enum BirthdayFreebieCategory {
|
|
5714
|
+
NoPurchaseRequired
|
|
5715
|
+
PurchaseRequired
|
|
5716
|
+
}
|
|
5717
|
+
|
|
5718
|
+
enum BirthdayFreebieExpirationType {
|
|
5719
|
+
DayOf
|
|
5720
|
+
Valid30Days
|
|
5721
|
+
}
|
|
5722
|
+
|
|
5723
|
+
enum BirthdayFreebieSource {
|
|
5724
|
+
Partner
|
|
5725
|
+
Suggestion
|
|
5726
|
+
Manual
|
|
5727
|
+
}
|
|
5728
|
+
|
|
5729
|
+
enum BirthdayFreebieSector {
|
|
5730
|
+
CoffeeAndBeverages
|
|
5731
|
+
FoodAndRestaurants
|
|
5732
|
+
DessertsAndIceCream
|
|
5733
|
+
BeautyAndRetail
|
|
5734
|
+
Entertainment
|
|
5735
|
+
Other
|
|
5736
|
+
}
|
|
5737
|
+
|
|
5738
|
+
model BirthdayFreebieCatalog {
|
|
5739
|
+
id String @id @default(cuid())
|
|
5740
|
+
brandOrPlaceName String
|
|
5741
|
+
description String? @db.Text
|
|
5742
|
+
logoUrl String? @db.Text
|
|
5743
|
+
sector BirthdayFreebieSector @default(Other)
|
|
5744
|
+
category BirthdayFreebieCategory
|
|
5745
|
+
expirationType BirthdayFreebieExpirationType
|
|
5746
|
+
lastVerifiedAt DateTime
|
|
5747
|
+
requiresAdvanceSignup Boolean? @default(false)
|
|
5748
|
+
source BirthdayFreebieSource
|
|
5749
|
+
partnerId String?
|
|
5750
|
+
suggestionId String? @unique // one-to-one: at most one catalog entry per suggestion
|
|
5751
|
+
stateSlug String
|
|
5752
|
+
citySlug String?
|
|
5753
|
+
isActive Boolean @default(true)
|
|
5754
|
+
createdAt DateTime @default(now())
|
|
5755
|
+
updatedAt DateTime @updatedAt
|
|
5756
|
+
|
|
5757
|
+
partner BirthdayOfferPartner? @relation(fields: [partnerId], references: [id], onDelete: SetNull)
|
|
5758
|
+
suggestion BirthdayDealSuggestion? @relation(fields: [suggestionId], references: [id], onDelete: SetNull)
|
|
5759
|
+
|
|
5760
|
+
@@index([stateSlug, citySlug])
|
|
5761
|
+
@@index([isActive])
|
|
5762
|
+
@@index([sector])
|
|
5763
|
+
}
|
|
5764
|
+
|
|
5765
|
+
// Part B: User saved locations (birthday home base, etc.)
|
|
5766
|
+
model UserLocation {
|
|
5767
|
+
id String @id @default(cuid())
|
|
5768
|
+
userId String
|
|
5769
|
+
label String? // e.g. "Home", "Work"
|
|
5770
|
+
address1 String
|
|
5771
|
+
address2 String?
|
|
5772
|
+
city String
|
|
5773
|
+
state String
|
|
5774
|
+
zip String
|
|
5775
|
+
country String? @default("US")
|
|
5776
|
+
lat Float?
|
|
5777
|
+
lng Float?
|
|
5778
|
+
isDefault Boolean? @default(false)
|
|
5779
|
+
createdAt DateTime @default(now())
|
|
5780
|
+
updatedAt DateTime @updatedAt
|
|
5781
|
+
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
5782
|
+
usersWithBirthdayLocation User[] @relation("UserBirthdayLocation")
|
|
5783
|
+
|
|
5784
|
+
@@index([userId])
|
|
5785
|
+
}
|
|
5786
|
+
|
|
5787
|
+
// Part B: Structured birthday offers (catalog)
|
|
5788
|
+
enum RedemptionMethod {
|
|
5789
|
+
APP
|
|
5790
|
+
EMAIL
|
|
5791
|
+
IN_STORE
|
|
5792
|
+
ONLINE
|
|
5793
|
+
}
|
|
5794
|
+
|
|
5795
|
+
enum BirthdayOfferExpirationType {
|
|
5796
|
+
DAY_OF // End of birthday day
|
|
5797
|
+
DAYS_FROM_BDAY
|
|
5798
|
+
END_OF_MONTH
|
|
5799
|
+
VARIABLE
|
|
5800
|
+
}
|
|
5801
|
+
|
|
5802
|
+
enum BirthdayOfferSourceType {
|
|
5803
|
+
BRAND_SITE
|
|
5804
|
+
USER_REPORTED
|
|
5805
|
+
PARTNER
|
|
5806
|
+
}
|
|
5807
|
+
|
|
5808
|
+
enum OfferClaimStatus {
|
|
5809
|
+
CLICKED
|
|
5810
|
+
SAVED
|
|
5811
|
+
CLAIMED
|
|
5812
|
+
REDEEMED
|
|
5813
|
+
EXPIRED
|
|
5814
|
+
}
|
|
5815
|
+
|
|
5816
|
+
model Brand {
|
|
5817
|
+
id String @id @default(cuid())
|
|
5818
|
+
name String
|
|
5819
|
+
websiteUrl String? @db.Text
|
|
5820
|
+
logoUrl String? @db.Text
|
|
5821
|
+
categoryDefault String? // restaurant, coffee, dessert, retail, entertainment
|
|
5822
|
+
isNational Boolean @default(true)
|
|
5823
|
+
createdAt DateTime @default(now())
|
|
5824
|
+
updatedAt DateTime @updatedAt
|
|
5825
|
+
offers BirthdayOffer[]
|
|
5826
|
+
locations BrandLocation[]
|
|
5827
|
+
|
|
5828
|
+
@@index([isNational])
|
|
5829
|
+
}
|
|
5830
|
+
|
|
5831
|
+
model BirthdayOffer {
|
|
5832
|
+
id String @id @default(cuid())
|
|
5833
|
+
brandId String
|
|
5834
|
+
title String // e.g. "Free burger reward"
|
|
5835
|
+
descriptionShort String? @db.Text
|
|
5836
|
+
purchaseRequired Boolean @default(false)
|
|
5837
|
+
signupRequired Boolean @default(false)
|
|
5838
|
+
appRequired Boolean @default(false)
|
|
5839
|
+
requiresPhone Boolean @default(false)
|
|
5840
|
+
redemptionMethod RedemptionMethod
|
|
5841
|
+
expirationType BirthdayOfferExpirationType
|
|
5842
|
+
expirationDays Int? // when expirationType = DAYS_FROM_BDAY
|
|
5843
|
+
windowStartOffsetDays Int @default(0)
|
|
5844
|
+
termsUrl String? @db.Text
|
|
5845
|
+
termsNotes String? @db.Text
|
|
5846
|
+
sourceType BirthdayOfferSourceType
|
|
5847
|
+
lastVerifiedAt DateTime?
|
|
5848
|
+
isActive Boolean @default(true)
|
|
5849
|
+
priorityScore Int @default(0)
|
|
5850
|
+
featuredUntil DateTime?
|
|
5851
|
+
createdAt DateTime @default(now())
|
|
5852
|
+
updatedAt DateTime @updatedAt
|
|
5853
|
+
brand Brand @relation(fields: [brandId], references: [id], onDelete: Cascade)
|
|
5854
|
+
claims OfferClaim[]
|
|
5855
|
+
redemptions BirthdayRewardRedemption[]
|
|
5856
|
+
|
|
5857
|
+
@@index([brandId])
|
|
5858
|
+
@@index([isActive])
|
|
5859
|
+
@@index([sourceType])
|
|
5860
|
+
}
|
|
5861
|
+
|
|
5862
|
+
model BrandLocation {
|
|
5863
|
+
id String @id @default(cuid())
|
|
5864
|
+
brandId String
|
|
5865
|
+
address1 String
|
|
5866
|
+
address2 String?
|
|
5867
|
+
city String
|
|
5868
|
+
state String
|
|
5869
|
+
zip String
|
|
5870
|
+
lat Float
|
|
5871
|
+
lng Float
|
|
5872
|
+
isActive Boolean @default(true)
|
|
5873
|
+
createdAt DateTime @default(now())
|
|
5874
|
+
updatedAt DateTime @updatedAt
|
|
5875
|
+
brand Brand @relation(fields: [brandId], references: [id], onDelete: Cascade)
|
|
5876
|
+
|
|
5877
|
+
@@index([brandId])
|
|
5878
|
+
@@index([isActive])
|
|
5879
|
+
}
|
|
5880
|
+
|
|
5881
|
+
model OfferClaim {
|
|
5882
|
+
id String @id @default(cuid())
|
|
5883
|
+
userId String
|
|
5884
|
+
birthdayOfferId String
|
|
5885
|
+
claimedAt DateTime @default(now())
|
|
5886
|
+
birthdayYear Int
|
|
5887
|
+
status OfferClaimStatus
|
|
5888
|
+
meta Json?
|
|
5889
|
+
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
5890
|
+
birthdayOffer BirthdayOffer @relation(fields: [birthdayOfferId], references: [id], onDelete: Cascade)
|
|
5891
|
+
|
|
5892
|
+
@@index([userId])
|
|
5893
|
+
@@index([birthdayOfferId])
|
|
5894
|
+
@@index([userId, birthdayYear])
|
|
5895
|
+
}
|
|
5896
|
+
|
|
5897
|
+
model BirthdayPlan {
|
|
5898
|
+
id String @id @default(cuid())
|
|
5899
|
+
userId String
|
|
5900
|
+
birthdayYear Int
|
|
5901
|
+
generatedAt DateTime @default(now())
|
|
5902
|
+
preferencesSnapshot Json // distance, filters, optimizeFor
|
|
5903
|
+
items Json // ordered stops: plannedDate, brandId, offerId, locationId?, distanceFromHome, deadline, purchaseRequired
|
|
5904
|
+
validFrom DateTime
|
|
5905
|
+
validTo DateTime
|
|
5906
|
+
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
5907
|
+
|
|
5908
|
+
@@index([userId])
|
|
5909
|
+
@@index([userId, birthdayYear])
|
|
5910
|
+
}
|
|
5911
|
+
|
|
5912
|
+
// Part B: Geocoding cache to avoid repeated API calls (birthday rewards, UserLocation, etc.)
|
|
5913
|
+
model GeocodeCache {
|
|
5914
|
+
id String @id @default(cuid())
|
|
5915
|
+
addressQuery String @unique // Normalized query string (trimmed, collapsed whitespace)
|
|
5916
|
+
lat Float
|
|
5917
|
+
lng Float
|
|
5918
|
+
normalizedAddress String @db.Text // formatted_address from provider
|
|
5919
|
+
createdAt DateTime @default(now())
|
|
5920
|
+
|
|
5921
|
+
@@index([addressQuery])
|
|
5580
5922
|
}
|
|
5581
5923
|
|
|
5582
5924
|
model AuditLog {
|