@bash-app/bash-common 30.226.0 → 30.227.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/aiApproval.d.ts +25 -0
- package/dist/aiApproval.d.ts.map +1 -1
- package/dist/aiApproval.js +32 -4
- package/dist/aiApproval.js.map +1 -1
- package/dist/extendedSchemas.d.ts +43 -1
- package/dist/extendedSchemas.d.ts.map +1 -1
- package/dist/extendedSchemas.js +22 -0
- package/dist/extendedSchemas.js.map +1 -1
- package/dist/index.d.ts +4 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/utils/__tests__/flyerUtils.test.d.ts +2 -0
- package/dist/utils/__tests__/flyerUtils.test.d.ts.map +1 -0
- package/dist/utils/__tests__/flyerUtils.test.js +49 -0
- package/dist/utils/__tests__/flyerUtils.test.js.map +1 -0
- package/dist/utils/flyerUtils.d.ts +42 -0
- package/dist/utils/flyerUtils.d.ts.map +1 -0
- package/dist/utils/flyerUtils.js +104 -0
- package/dist/utils/flyerUtils.js.map +1 -0
- package/package.json +1 -1
- package/prisma/schema.prisma +319 -50
- package/src/aiApproval.ts +118 -0
- package/src/extendedSchemas.ts +45 -1
- package/src/index.ts +14 -0
- package/src/utils/__tests__/flyerUtils.test.ts +70 -0
- package/src/utils/flyerUtils.ts +137 -0
- package/dist/utils/__tests__/cancellationPolicyRefundResolver.test.d.ts +0 -6
- package/dist/utils/__tests__/cancellationPolicyRefundResolver.test.d.ts.map +0 -1
- package/dist/utils/__tests__/cancellationPolicyRefundResolver.test.js +0 -104
- package/dist/utils/__tests__/cancellationPolicyRefundResolver.test.js.map +0 -1
- package/dist/utils/service/serviceRateDBUtils.d.ts +0 -1
- package/dist/utils/service/serviceRateDBUtils.d.ts.map +0 -1
- package/dist/utils/service/serviceRateDBUtils.js +0 -159
- package/dist/utils/service/serviceRateDBUtils.js.map +0 -1
- package/prisma/migrations/add_bash_availability.sql +0 -53
- package/prisma/migrations/add_bashcash_pricing_to_ticket_tier.sql +0 -15
- package/prisma/migrations/add_bashpoints_purchase_tracking.sql +0 -33
- package/prisma/migrations/add_event_group_allow_auto_join.sql +0 -17
- package/prisma/migrations/add_group_member_status_not_going_maybe.sql +0 -5
- package/prisma/migrations/add_groups_and_momentum.sql +0 -135
- package/prisma/migrations/add_groups_momentum_phase0_4.sql +0 -200
- package/prisma/migrations/add_new_feature_tables.sql +0 -140
- package/prisma/migrations/add_pricing_type_enum.sql +0 -88
- package/prisma/migrations/add_tier_privacy_and_fee_handling.sql +0 -29
- package/prisma/migrations/diagnostic_bashcash_columns.sql +0 -157
- package/prisma/migrations/fix_bashcash_referral_code_schema_mismatch.sql +0 -81
- package/prisma/migrations/rename_bashcash_to_bashpoints.sql +0 -183
- package/prisma/migrations/rename_bashcredits_to_bashpoints.sql +0 -96
package/prisma/schema.prisma
CHANGED
|
@@ -393,6 +393,7 @@ model EventTask {
|
|
|
393
393
|
notificationsReferencingMe Notification[]
|
|
394
394
|
comments TaskComment[]
|
|
395
395
|
invitations TaskInvitation[]
|
|
396
|
+
expenses Expense[]
|
|
396
397
|
potluckItem PotluckItem? @relation("PotluckItemTask")
|
|
397
398
|
bashEventSuggestion BashEventSuggestion? @relation("SuggestionTask")
|
|
398
399
|
}
|
|
@@ -693,7 +694,7 @@ model BashEvent {
|
|
|
693
694
|
servicePreferences Json? // New tiered status: { "Entertainment": "need", "Sponsors": "booked_closed", ... }
|
|
694
695
|
bookedServices Json? // Booked service details: { "Entertainment": { serviceId: "...", providerId: "...", bookedAt: "..." }, ... }
|
|
695
696
|
serviceVisibility Json? // DEPRECATED: Use servicePreferences instead. Kept for backward compatibility during migration.
|
|
696
|
-
plannedServiceIds String[]
|
|
697
|
+
plannedServiceIds String[] @default([]) // Service IDs the host has flagged as "plan to book" in the wizard
|
|
697
698
|
originalCreatorId String?
|
|
698
699
|
transferredAt DateTime?
|
|
699
700
|
transferredFromId String?
|
|
@@ -749,6 +750,9 @@ model BashEvent {
|
|
|
749
750
|
maxGuestsPerMember Int? // Guest limit per member (null = unlimited)
|
|
750
751
|
restrictToOrgDepartments String[] @default([]) // Empty = all departments can see/join
|
|
751
752
|
|
|
753
|
+
/// When true, new event expenses default to Pending until host/org approves (see Expense.status).
|
|
754
|
+
requireExpenseApproval Boolean @default(false)
|
|
755
|
+
|
|
752
756
|
associatedBashesReferencingMe AssociatedBash[]
|
|
753
757
|
comments BashComment[]
|
|
754
758
|
amountOfGuests AmountOfGuests? @relation(fields: [amountOfGuestsId], references: [id], onDelete: Cascade)
|
|
@@ -848,11 +852,27 @@ model BashEvent {
|
|
|
848
852
|
|
|
849
853
|
bashEventArtists BashEventArtist[]
|
|
850
854
|
vanityPaths EventVanityPath[]
|
|
855
|
+
flyerCampaigns FlyerCampaign[]
|
|
856
|
+
|
|
857
|
+
/// Latest AI moderator verdict (see `bashApprovalAiService` + `mapAiResultToDecision`).
|
|
858
|
+
/// Null = never reviewed by AI. Recomputed each time the bash transitions to Pending
|
|
859
|
+
/// or a super-user clicks "Re-run AI review".
|
|
860
|
+
aiApprovalVerdict AiApprovalVerdict?
|
|
861
|
+
aiApprovalConfidence Float?
|
|
862
|
+
/// Structured `AiApprovalReasons` (criteria scores + hostFacingMessage + adminFacingNotes).
|
|
863
|
+
/// Schema lives in `bash-common/src/extendedSchemas.ts`.
|
|
864
|
+
aiApprovalReasons Json?
|
|
865
|
+
aiApprovalReviewedAt DateTime?
|
|
866
|
+
aiApprovalModel String?
|
|
867
|
+
aiApprovalRunCount Int @default(0)
|
|
868
|
+
/// SHA-256 of the snapshot fed to the AI; lets us skip a re-run when nothing changed.
|
|
869
|
+
aiApprovalContentHash String?
|
|
851
870
|
|
|
852
871
|
@@index([templateId])
|
|
853
872
|
@@index([parentEventId])
|
|
854
873
|
@@index([organizationId])
|
|
855
874
|
@@index([eventSeriesId])
|
|
875
|
+
@@index([status, aiApprovalVerdict])
|
|
856
876
|
}
|
|
857
877
|
|
|
858
878
|
/// Lineup / attribution roster for an event (optional act list for checkout tagging).
|
|
@@ -872,6 +892,197 @@ model BashEventArtist {
|
|
|
872
892
|
@@index([serviceId])
|
|
873
893
|
}
|
|
874
894
|
|
|
895
|
+
// --- Flyer Blast (USPS EDDM neighborhood mail campaigns) ---
|
|
896
|
+
enum FlyerTargetingMode {
|
|
897
|
+
RADIUS
|
|
898
|
+
CUSTOM
|
|
899
|
+
}
|
|
900
|
+
|
|
901
|
+
enum FlyerFulfillmentType {
|
|
902
|
+
SELF_MAIL
|
|
903
|
+
DONE_FOR_YOU
|
|
904
|
+
}
|
|
905
|
+
|
|
906
|
+
enum FlyerCampaignStatus {
|
|
907
|
+
DRAFT
|
|
908
|
+
ARTWORK_REVIEW
|
|
909
|
+
PAID
|
|
910
|
+
PRINTING
|
|
911
|
+
IN_TRANSIT
|
|
912
|
+
DELIVERED
|
|
913
|
+
CANCELLED
|
|
914
|
+
}
|
|
915
|
+
|
|
916
|
+
enum FlyerSponsorSlot {
|
|
917
|
+
FEATURED
|
|
918
|
+
SUPPORTING_1
|
|
919
|
+
SUPPORTING_2
|
|
920
|
+
}
|
|
921
|
+
|
|
922
|
+
enum FlyerConversionType {
|
|
923
|
+
QR_SCAN
|
|
924
|
+
RSVP
|
|
925
|
+
TICKET_PURCHASE
|
|
926
|
+
SPONSOR_QR_SCAN
|
|
927
|
+
}
|
|
928
|
+
|
|
929
|
+
model FlyerCampaign {
|
|
930
|
+
id String @id @default(cuid())
|
|
931
|
+
bashEventId String
|
|
932
|
+
hostUserId String
|
|
933
|
+
|
|
934
|
+
targetingMode FlyerTargetingMode @default(RADIUS)
|
|
935
|
+
radiusMiles Float?
|
|
936
|
+
centerLat Float?
|
|
937
|
+
centerLng Float?
|
|
938
|
+
customPolygon Json?
|
|
939
|
+
totalHouseholds Int?
|
|
940
|
+
|
|
941
|
+
fulfillmentType FlyerFulfillmentType @default(DONE_FOR_YOU)
|
|
942
|
+
|
|
943
|
+
printPostageCostCents Int?
|
|
944
|
+
bashFeeCents Int?
|
|
945
|
+
sponsorRevenueCents Int?
|
|
946
|
+
hostTotalCostCents Int?
|
|
947
|
+
stripePaymentIntentId String?
|
|
948
|
+
paidAt DateTime?
|
|
949
|
+
|
|
950
|
+
campaignQrSlug String @unique
|
|
951
|
+
campaignPromoCode String?
|
|
952
|
+
|
|
953
|
+
ctaLabel String?
|
|
954
|
+
templateVariant String @default("default")
|
|
955
|
+
|
|
956
|
+
status FlyerCampaignStatus @default(DRAFT)
|
|
957
|
+
|
|
958
|
+
vendorOrderRef String?
|
|
959
|
+
vendorStatus String?
|
|
960
|
+
|
|
961
|
+
bashEvent BashEvent @relation(fields: [bashEventId], references: [id], onDelete: Cascade)
|
|
962
|
+
host User @relation(fields: [hostUserId], references: [id], onDelete: Cascade)
|
|
963
|
+
routes FlyerMailingRoute[]
|
|
964
|
+
artworkVersions FlyerArtwork[]
|
|
965
|
+
sponsors FlyerCampaignSponsor[]
|
|
966
|
+
conversions FlyerConversion[]
|
|
967
|
+
|
|
968
|
+
createdAt DateTime @default(now())
|
|
969
|
+
updatedAt DateTime @updatedAt
|
|
970
|
+
|
|
971
|
+
@@index([bashEventId])
|
|
972
|
+
@@index([hostUserId])
|
|
973
|
+
}
|
|
974
|
+
|
|
975
|
+
model FlyerMailingRoute {
|
|
976
|
+
id String @id @default(cuid())
|
|
977
|
+
campaignId String
|
|
978
|
+
campaign FlyerCampaign @relation(fields: [campaignId], references: [id], onDelete: Cascade)
|
|
979
|
+
|
|
980
|
+
crrtCode String
|
|
981
|
+
zipCode String
|
|
982
|
+
city String
|
|
983
|
+
state String @default("UT")
|
|
984
|
+
householdCount Int
|
|
985
|
+
|
|
986
|
+
medianIncomeBand String?
|
|
987
|
+
avgHouseholdSize Float?
|
|
988
|
+
medianAge Float?
|
|
989
|
+
|
|
990
|
+
createdAt DateTime @default(now())
|
|
991
|
+
|
|
992
|
+
@@unique([campaignId, crrtCode, zipCode])
|
|
993
|
+
@@index([campaignId])
|
|
994
|
+
}
|
|
995
|
+
|
|
996
|
+
model FlyerArtwork {
|
|
997
|
+
id String @id @default(cuid())
|
|
998
|
+
campaignId String
|
|
999
|
+
campaign FlyerCampaign @relation(fields: [campaignId], references: [id], onDelete: Cascade)
|
|
1000
|
+
|
|
1001
|
+
version Int
|
|
1002
|
+
s3KeyPrintPdf String?
|
|
1003
|
+
s3KeyPreviewPng String?
|
|
1004
|
+
|
|
1005
|
+
widthIn Float @default(6.25)
|
|
1006
|
+
heightIn Float @default(11)
|
|
1007
|
+
isEddmCompliant Boolean @default(false)
|
|
1008
|
+
|
|
1009
|
+
createdAt DateTime @default(now())
|
|
1010
|
+
|
|
1011
|
+
@@index([campaignId])
|
|
1012
|
+
}
|
|
1013
|
+
|
|
1014
|
+
model FlyerCampaignSponsor {
|
|
1015
|
+
id String @id @default(cuid())
|
|
1016
|
+
campaignId String
|
|
1017
|
+
campaign FlyerCampaign @relation(fields: [campaignId], references: [id], onDelete: Cascade)
|
|
1018
|
+
|
|
1019
|
+
slotType FlyerSponsorSlot
|
|
1020
|
+
businessName String
|
|
1021
|
+
logoS3Key String?
|
|
1022
|
+
ctaText String?
|
|
1023
|
+
sponsorQrSlug String? @unique
|
|
1024
|
+
|
|
1025
|
+
slotPriceCents Int @default(0)
|
|
1026
|
+
stripePaymentIntentId String?
|
|
1027
|
+
paidAt DateTime?
|
|
1028
|
+
|
|
1029
|
+
hostPayoutCents Int?
|
|
1030
|
+
bashFeeCents Int?
|
|
1031
|
+
|
|
1032
|
+
conversions FlyerConversion[]
|
|
1033
|
+
|
|
1034
|
+
createdAt DateTime @default(now())
|
|
1035
|
+
|
|
1036
|
+
@@unique([campaignId, slotType])
|
|
1037
|
+
@@index([campaignId])
|
|
1038
|
+
}
|
|
1039
|
+
|
|
1040
|
+
model FlyerConversion {
|
|
1041
|
+
id String @id @default(cuid())
|
|
1042
|
+
campaignId String
|
|
1043
|
+
campaign FlyerCampaign @relation(fields: [campaignId], references: [id], onDelete: Cascade)
|
|
1044
|
+
|
|
1045
|
+
type FlyerConversionType @default(QR_SCAN)
|
|
1046
|
+
sponsorId String?
|
|
1047
|
+
ticketId String?
|
|
1048
|
+
|
|
1049
|
+
crrtCode String?
|
|
1050
|
+
userAgent String?
|
|
1051
|
+
|
|
1052
|
+
occurredAt DateTime @default(now())
|
|
1053
|
+
|
|
1054
|
+
sponsor FlyerCampaignSponsor? @relation(fields: [sponsorId], references: [id], onDelete: SetNull)
|
|
1055
|
+
ticket Ticket? @relation(fields: [ticketId], references: [id], onDelete: SetNull)
|
|
1056
|
+
|
|
1057
|
+
@@index([campaignId])
|
|
1058
|
+
@@index([occurredAt])
|
|
1059
|
+
@@index([sponsorId])
|
|
1060
|
+
@@index([ticketId])
|
|
1061
|
+
}
|
|
1062
|
+
|
|
1063
|
+
/// USPS carrier-route catalog (Utah MVP; expand for national rollout).
|
|
1064
|
+
model PostalCarrierRoute {
|
|
1065
|
+
id String @id @default(cuid())
|
|
1066
|
+
crrtCode String
|
|
1067
|
+
zipCode String
|
|
1068
|
+
city String
|
|
1069
|
+
state String @default("UT")
|
|
1070
|
+
latitude Float
|
|
1071
|
+
longitude Float
|
|
1072
|
+
householdCount Int
|
|
1073
|
+
residentialOnly Boolean @default(true)
|
|
1074
|
+
medianIncomeBand String?
|
|
1075
|
+
avgHouseholdSize Float?
|
|
1076
|
+
medianAge Float?
|
|
1077
|
+
|
|
1078
|
+
createdAt DateTime @default(now())
|
|
1079
|
+
updatedAt DateTime @updatedAt
|
|
1080
|
+
|
|
1081
|
+
@@unique([zipCode, crrtCode])
|
|
1082
|
+
@@index([latitude, longitude])
|
|
1083
|
+
@@index([zipCode])
|
|
1084
|
+
}
|
|
1085
|
+
|
|
875
1086
|
enum BashCreativeStatus {
|
|
876
1087
|
Pending
|
|
877
1088
|
InReview
|
|
@@ -1502,6 +1713,7 @@ model Ticket {
|
|
|
1502
1713
|
transferInvite TicketTransferInvite?
|
|
1503
1714
|
appliedDiscounts AppliedDiscount[] // NEW - Discounts applied to this ticket
|
|
1504
1715
|
eventReferral EventReferral? // When this ticket was purchased via a referral link
|
|
1716
|
+
flyerConversions FlyerConversion[]
|
|
1505
1717
|
|
|
1506
1718
|
@@index([bashEventId])
|
|
1507
1719
|
@@index([waitlistUserId])
|
|
@@ -1931,26 +2143,26 @@ model User {
|
|
|
1931
2143
|
|
|
1932
2144
|
givenName String?
|
|
1933
2145
|
familyName String?
|
|
1934
|
-
nameChangeCount Int
|
|
2146
|
+
nameChangeCount Int @default(0)
|
|
1935
2147
|
hash String?
|
|
1936
|
-
previousPasswordHashes String[]
|
|
2148
|
+
previousPasswordHashes String[] @default([]) // Last 5 bcrypt hashes (oldest first) for password-reuse prevention
|
|
1937
2149
|
emailVerified DateTime?
|
|
1938
2150
|
image String?
|
|
1939
2151
|
imageUpdatedAt DateTime? // When Google/OAuth image was last updated
|
|
1940
2152
|
uploadedImage String?
|
|
1941
2153
|
uploadedImageUpdatedAt DateTime? // When manually uploaded image was last updated
|
|
1942
2154
|
dob DateTime?
|
|
1943
|
-
showBirthdayOnProfile Boolean
|
|
2155
|
+
showBirthdayOnProfile Boolean @default(false) // If true, show month/day on public profile
|
|
1944
2156
|
// Part B: Birthday Rewards full product
|
|
1945
|
-
birthdayRewardsOptIn Boolean
|
|
2157
|
+
birthdayRewardsOptIn Boolean @default(false)
|
|
1946
2158
|
birthdayRewardsOptInAt DateTime?
|
|
1947
2159
|
birthdayLocationId String? // FK UserLocation (birthday home base)
|
|
1948
|
-
birthdayMaxDistanceMiles Int
|
|
1949
|
-
birthdayNoPurchaseOnly Boolean
|
|
2160
|
+
birthdayMaxDistanceMiles Int @default(25)
|
|
2161
|
+
birthdayNoPurchaseOnly Boolean @default(false)
|
|
1950
2162
|
/// Email reminder N days before birthday (birthday rewards plan nudge)
|
|
1951
|
-
birthdayReminderEnabled Boolean
|
|
1952
|
-
birthdayReminderDaysAdvance Int
|
|
1953
|
-
birthdayCategories String[]
|
|
2163
|
+
birthdayReminderEnabled Boolean @default(true)
|
|
2164
|
+
birthdayReminderDaysAdvance Int @default(7)
|
|
2165
|
+
birthdayCategories String[] @default([]) // e.g. restaurant, coffee, dessert
|
|
1954
2166
|
/// Calendar year when we last sent the "your birthday month freebies" reminder (cron on 1st of month).
|
|
1955
2167
|
birthdayMonthReminderSentYear Int?
|
|
1956
2168
|
idDocumentUrl String? // Optional: secure ID upload for verification
|
|
@@ -1959,41 +2171,41 @@ model User {
|
|
|
1959
2171
|
genderIdentity String?
|
|
1960
2172
|
sex Sex?
|
|
1961
2173
|
/// Public-profile visibility flags for self-reported demographics
|
|
1962
|
-
showAgeOnProfile Boolean
|
|
1963
|
-
showGenderOnProfile Boolean
|
|
2174
|
+
showAgeOnProfile Boolean @default(true)
|
|
2175
|
+
showGenderOnProfile Boolean @default(true)
|
|
1964
2176
|
/// Master visibility toggle for ID/Payment/Host/Student trust badges
|
|
1965
|
-
showVerifiedBadgesOnProfile Boolean
|
|
2177
|
+
showVerifiedBadgesOnProfile Boolean @default(true)
|
|
1966
2178
|
organization String?
|
|
1967
2179
|
jobTitle String?
|
|
1968
|
-
roles UserRole[]
|
|
2180
|
+
roles UserRole[] @default([User])
|
|
1969
2181
|
aboutMe String?
|
|
1970
2182
|
levelBadge String?
|
|
1971
|
-
temporaryBadges String[]
|
|
2183
|
+
temporaryBadges String[] @default([])
|
|
1972
2184
|
status UserStatus
|
|
1973
2185
|
hostRating Float?
|
|
1974
2186
|
totalRatings Int?
|
|
1975
|
-
totalEventsHosted Int?
|
|
1976
|
-
totalAttendeesHosted Int?
|
|
1977
|
-
totalBookingsAccepted Int?
|
|
1978
|
-
totalBookingsCompleted Int?
|
|
2187
|
+
totalEventsHosted Int? @default(0) // Total published/completed events hosted
|
|
2188
|
+
totalAttendeesHosted Int? @default(0) // Total checked-in attendees across all events
|
|
2189
|
+
totalBookingsAccepted Int? @default(0) // Service provider stat
|
|
2190
|
+
totalBookingsCompleted Int? @default(0) // Service provider stat
|
|
1979
2191
|
magicLink String?
|
|
1980
2192
|
magicLinkExpiration DateTime?
|
|
1981
2193
|
hostNumber Int?
|
|
1982
|
-
foundingHostBadgeAwarded Boolean
|
|
2194
|
+
foundingHostBadgeAwarded Boolean @default(false)
|
|
1983
2195
|
firstBashWithAttendeesDate DateTime?
|
|
1984
|
-
bashesCreatedCount Int
|
|
1985
|
-
bashesPublishedCount Int
|
|
1986
|
-
bashesApprovedCount Int
|
|
1987
|
-
bashesCompletedCount Int
|
|
2196
|
+
bashesCreatedCount Int @default(0)
|
|
2197
|
+
bashesPublishedCount Int @default(0)
|
|
2198
|
+
bashesApprovedCount Int @default(0)
|
|
2199
|
+
bashesCompletedCount Int @default(0)
|
|
1988
2200
|
magicLinkUsed DateTime?
|
|
1989
2201
|
idVerified DateTime?
|
|
1990
2202
|
street String?
|
|
1991
2203
|
city String?
|
|
1992
2204
|
state String?
|
|
1993
2205
|
zipCode String?
|
|
1994
|
-
country String?
|
|
2206
|
+
country String? @default("US")
|
|
1995
2207
|
phone String?
|
|
1996
|
-
documentIDId String?
|
|
2208
|
+
documentIDId String? @unique
|
|
1997
2209
|
/// Encrypted-S3 key for the user's stored government-ID image (deleted per retention policy / on ID expiration)
|
|
1998
2210
|
govIdImageS3Key String?
|
|
1999
2211
|
/// When the gov-ID image becomes deletable (null = "indefinite, until I remove it").
|
|
@@ -2012,40 +2224,40 @@ model User {
|
|
|
2012
2224
|
schoolName String?
|
|
2013
2225
|
/// Whether `schoolName` came from the AI vision model or was edited by the user
|
|
2014
2226
|
schoolNameSource SchoolNameSource?
|
|
2015
|
-
accepted Boolean?
|
|
2016
|
-
boughtTicket Boolean?
|
|
2017
|
-
noPay Boolean?
|
|
2018
|
-
supportedEvent Boolean?
|
|
2227
|
+
accepted Boolean? @default(false)
|
|
2228
|
+
boughtTicket Boolean? @default(false)
|
|
2229
|
+
noPay Boolean? @default(false)
|
|
2230
|
+
supportedEvent Boolean? @default(false)
|
|
2019
2231
|
suspendedUntil DateTime?
|
|
2020
2232
|
suspendedById String?
|
|
2021
|
-
isLightweightAccount Boolean
|
|
2022
|
-
notifyForTrendingBashes Boolean
|
|
2023
|
-
trendingBashThreshold Int
|
|
2024
|
-
artistsToSee String[]
|
|
2233
|
+
isLightweightAccount Boolean @default(false)
|
|
2234
|
+
notifyForTrendingBashes Boolean @default(false)
|
|
2235
|
+
trendingBashThreshold Int @default(10)
|
|
2236
|
+
artistsToSee String[] @default([])
|
|
2025
2237
|
googleCalendarSyncSettings String?
|
|
2026
|
-
membershipTier MembershipTier
|
|
2238
|
+
membershipTier MembershipTier @default(Basic)
|
|
2027
2239
|
membershipExpiresAt DateTime?
|
|
2028
|
-
membershipAutoRenew Boolean
|
|
2240
|
+
membershipAutoRenew Boolean @default(false)
|
|
2029
2241
|
membershipBillingInterval String?
|
|
2030
2242
|
membershipLastBilledAt DateTime?
|
|
2031
|
-
membershipFeaturedEventsUsed Int
|
|
2032
|
-
membershipStripeSubscriptionId String?
|
|
2243
|
+
membershipFeaturedEventsUsed Int @default(0)
|
|
2244
|
+
membershipStripeSubscriptionId String? @unique
|
|
2033
2245
|
/// Optional consumer BashPass subscription (waives guest platform fee on tickets; monthly BashPoints).
|
|
2034
|
-
bashPassStripeSubscriptionId String?
|
|
2246
|
+
bashPassStripeSubscriptionId String? @unique
|
|
2035
2247
|
bashPassCurrentPeriodEnd DateTime?
|
|
2036
2248
|
/// Stripe price tier for standalone BashPass; effective tier may also come from membership bundle.
|
|
2037
2249
|
bashPassTier BashPassTier?
|
|
2038
|
-
bashPassEventsUsedThisMonth Int
|
|
2250
|
+
bashPassEventsUsedThisMonth Int @default(0)
|
|
2039
2251
|
bashPassMonthlyCapResetAt DateTime?
|
|
2040
|
-
isVerified Boolean
|
|
2252
|
+
isVerified Boolean @default(false)
|
|
2041
2253
|
verificationMethod String?
|
|
2042
2254
|
verifiedAt DateTime?
|
|
2043
|
-
verificationScore Int
|
|
2255
|
+
verificationScore Int @default(0)
|
|
2044
2256
|
/// $1 card verification (Stripe) — distinct from Stripe Identity / isVerified
|
|
2045
|
-
paymentVerified Boolean
|
|
2257
|
+
paymentVerified Boolean @default(false)
|
|
2046
2258
|
paymentVerifiedAt DateTime?
|
|
2047
2259
|
/// One-time BashPoints bonus after $1 verification payment succeeded
|
|
2048
|
-
paymentVerificationBonusAwarded Boolean
|
|
2260
|
+
paymentVerificationBonusAwarded Boolean @default(false)
|
|
2049
2261
|
biometricFingerprint String?
|
|
2050
2262
|
venmoUsername String?
|
|
2051
2263
|
venmoQRCodeUrl String?
|
|
@@ -2054,17 +2266,17 @@ model User {
|
|
|
2054
2266
|
paymentHandle String?
|
|
2055
2267
|
zellePhone String?
|
|
2056
2268
|
zelleQRCodeUrl String?
|
|
2057
|
-
isAmbashador Boolean
|
|
2269
|
+
isAmbashador Boolean @default(false)
|
|
2058
2270
|
ambashadorAwardedAt DateTime?
|
|
2059
|
-
isBashInsider Boolean
|
|
2271
|
+
isBashInsider Boolean @default(false)
|
|
2060
2272
|
insiderAwardedAt DateTime?
|
|
2061
|
-
scoutTier ScoutTier
|
|
2273
|
+
scoutTier ScoutTier @default(None)
|
|
2062
2274
|
scoutAwardedAt DateTime?
|
|
2063
2275
|
agentAwardedAt DateTime?
|
|
2064
|
-
totalServiceReferrals Int
|
|
2065
|
-
isFirstInCity Boolean
|
|
2276
|
+
totalServiceReferrals Int @default(0)
|
|
2277
|
+
isFirstInCity Boolean @default(false)
|
|
2066
2278
|
firstInCityAt DateTime?
|
|
2067
|
-
fcmTokens String[]
|
|
2279
|
+
fcmTokens String[] @default([]) // Firebase Cloud Messaging tokens for push notifications
|
|
2068
2280
|
|
|
2069
2281
|
// BashPoints System Fields
|
|
2070
2282
|
bashPointsBalance Int @default(0)
|
|
@@ -2104,6 +2316,7 @@ model User {
|
|
|
2104
2316
|
referredTransactions BashCreditTransaction[] @relation("ReferredUser")
|
|
2105
2317
|
creditTransactions BashCreditTransaction[]
|
|
2106
2318
|
createdEvents BashEvent[] @relation("CreatedEvent")
|
|
2319
|
+
flyerCampaigns FlyerCampaign[]
|
|
2107
2320
|
bashEventsTransferredFrom BashEvent[] @relation("TransferredFrom")
|
|
2108
2321
|
bashEventsPayoutRecipient BashEvent[] @relation("BashEventsPayoutRecipient")
|
|
2109
2322
|
bashEventMessagesSent BashEventMessage[] @relation("BashMessageSender")
|
|
@@ -2798,6 +3011,7 @@ model Service {
|
|
|
2798
3011
|
entertainerMatches VenueEntertainmentMatch[] @relation("EntertainerMatches")
|
|
2799
3012
|
includes ServiceInclude[]
|
|
2800
3013
|
addonRequests ServiceAddonRequest[]
|
|
3014
|
+
serviceBudgets Budget[] @relation("ServiceBudgets")
|
|
2801
3015
|
|
|
2802
3016
|
@@index([serviceListingStripeSubscriptionId])
|
|
2803
3017
|
@@index([isFreeFirstListing])
|
|
@@ -3430,6 +3644,8 @@ model Budget {
|
|
|
3430
3644
|
clubId String?
|
|
3431
3645
|
departmentId String?
|
|
3432
3646
|
userId String? // For personal event budgets
|
|
3647
|
+
/// Optional: budgets tied to a service profile (vendor/exhibitor/sponsor owner costs).
|
|
3648
|
+
serviceId String?
|
|
3433
3649
|
|
|
3434
3650
|
// Budget details
|
|
3435
3651
|
totalAllocatedCents Int
|
|
@@ -3462,6 +3678,7 @@ model Budget {
|
|
|
3462
3678
|
club Club? @relation("ClubBudgets", fields: [clubId], references: [id], onDelete: Cascade)
|
|
3463
3679
|
department Department? @relation("DepartmentBudgets", fields: [departmentId], references: [id], onDelete: Cascade)
|
|
3464
3680
|
user User? @relation("UserBudgets", fields: [userId], references: [id], onDelete: Cascade)
|
|
3681
|
+
service Service? @relation("ServiceBudgets", fields: [serviceId], references: [id], onDelete: Cascade)
|
|
3465
3682
|
submitter User? @relation("BudgetSubmitter", fields: [submittedBy], references: [id])
|
|
3466
3683
|
approver User? @relation("BudgetApprover", fields: [approverId], references: [id])
|
|
3467
3684
|
expenses Expense[]
|
|
@@ -3471,10 +3688,18 @@ model Budget {
|
|
|
3471
3688
|
@@index([clubId])
|
|
3472
3689
|
@@index([departmentId])
|
|
3473
3690
|
@@index([userId])
|
|
3691
|
+
@@index([serviceId])
|
|
3474
3692
|
@@index([status])
|
|
3475
3693
|
@@index([fiscalYear])
|
|
3476
3694
|
}
|
|
3477
3695
|
|
|
3696
|
+
enum ExpenseExtractionStatus {
|
|
3697
|
+
none
|
|
3698
|
+
pending
|
|
3699
|
+
complete
|
|
3700
|
+
failed
|
|
3701
|
+
}
|
|
3702
|
+
|
|
3478
3703
|
model Expense {
|
|
3479
3704
|
id String @id @default(cuid())
|
|
3480
3705
|
budgetId String
|
|
@@ -3490,6 +3715,29 @@ model Expense {
|
|
|
3490
3715
|
rejectionReason String?
|
|
3491
3716
|
createdAt DateTime @default(now())
|
|
3492
3717
|
updatedAt DateTime @updatedAt
|
|
3718
|
+
|
|
3719
|
+
/// Optional link to an event task (e.g. volunteer receipt for a specific task).
|
|
3720
|
+
eventTaskId String?
|
|
3721
|
+
eventTask EventTask? @relation(fields: [eventTaskId], references: [id], onDelete: SetNull)
|
|
3722
|
+
|
|
3723
|
+
/// User-confirmed or extracted metadata (Textract suggestions are confirmed before save).
|
|
3724
|
+
vendorName String?
|
|
3725
|
+
taxCents Int?
|
|
3726
|
+
subtotalCents Int?
|
|
3727
|
+
currency String? @default("USD")
|
|
3728
|
+
|
|
3729
|
+
extractionStatus ExpenseExtractionStatus @default(none)
|
|
3730
|
+
textractRaw Json?
|
|
3731
|
+
|
|
3732
|
+
/// Vendor invoice number (manual or extracted).
|
|
3733
|
+
invoiceNumber String?
|
|
3734
|
+
/// When payment is due (separate from expenseDate / receipt date).
|
|
3735
|
+
invoiceDueDate DateTime?
|
|
3736
|
+
/// Host marked invoice as paid outside the app — stops due-date reminders.
|
|
3737
|
+
invoicePaidAt DateTime?
|
|
3738
|
+
/// Tracks which invoice due reminders were sent: { dueSoon, dueDay, pastDue1, pastDue15 }.
|
|
3739
|
+
invoiceDueRemindersSent Json?
|
|
3740
|
+
|
|
3493
3741
|
budget Budget @relation(fields: [budgetId], references: [id], onDelete: Cascade)
|
|
3494
3742
|
submitter User @relation("ExpenseSubmitter", fields: [submittedBy], references: [id])
|
|
3495
3743
|
approver User? @relation("ExpenseApprover", fields: [approvedBy], references: [id])
|
|
@@ -3497,6 +3745,8 @@ model Expense {
|
|
|
3497
3745
|
@@index([budgetId])
|
|
3498
3746
|
@@index([submittedBy])
|
|
3499
3747
|
@@index([status])
|
|
3748
|
+
@@index([eventTaskId])
|
|
3749
|
+
@@index([invoiceDueDate])
|
|
3500
3750
|
}
|
|
3501
3751
|
|
|
3502
3752
|
model ServiceRange {
|
|
@@ -4418,6 +4668,12 @@ enum NotificationType {
|
|
|
4418
4668
|
HostTopPromoter // Host: "Top promoter: Alex (6 tickets today)"
|
|
4419
4669
|
HostSalesSlowing // Host: "Sales slowed today. Try sharing your event."
|
|
4420
4670
|
TicketSold // Host: a ticket was purchased for your event (debounced in webhook)
|
|
4671
|
+
BudgetExpenseSubmitted // Host/organizer: assignee or member submitted an expense
|
|
4672
|
+
BudgetLineThreshold // Host/organizer: budget line crossed a spend threshold (e.g. 80% / 100%)
|
|
4673
|
+
BudgetInvoiceDueSoon // Host/organizer: invoice due in ~3 days
|
|
4674
|
+
BudgetInvoiceDueToday // Host/organizer: invoice due today
|
|
4675
|
+
BudgetInvoicePastDue // Host/organizer: invoice 1 day past due
|
|
4676
|
+
BudgetInvoicePastDueFinal // Host/organizer: invoice 15+ days past due
|
|
4421
4677
|
}
|
|
4422
4678
|
|
|
4423
4679
|
enum NotificationPriority {
|
|
@@ -4744,6 +5000,15 @@ enum CustomScopeStatus {
|
|
|
4744
5000
|
Rejected
|
|
4745
5001
|
}
|
|
4746
5002
|
|
|
5003
|
+
/// AI bash-approval reviewer verdict (see `bashApprovalAiService`).
|
|
5004
|
+
/// `Approve` and `Reject` are recommendations; whether the system acts on them
|
|
5005
|
+
/// vs. queues for a human depends on confidence + AI_BASH_APPROVAL_MODE.
|
|
5006
|
+
enum AiApprovalVerdict {
|
|
5007
|
+
Approve
|
|
5008
|
+
Flag
|
|
5009
|
+
Reject
|
|
5010
|
+
}
|
|
5011
|
+
|
|
4747
5012
|
/// How a user is associated with a bash (for BashFeedPost display: "Sarah attended...", "Mike is hosting...")
|
|
4748
5013
|
enum BashAssociationType {
|
|
4749
5014
|
Hosting
|
|
@@ -5026,6 +5291,7 @@ enum FoodAndBeverageSubType {
|
|
|
5026
5291
|
Bartenders
|
|
5027
5292
|
DessertBar
|
|
5028
5293
|
BeverageCart
|
|
5294
|
+
ConcessionStand
|
|
5029
5295
|
}
|
|
5030
5296
|
|
|
5031
5297
|
enum CleaningSubType {
|
|
@@ -5057,6 +5323,9 @@ enum RentalEquipmentSubType {
|
|
|
5057
5323
|
Generators
|
|
5058
5324
|
DanceFloor
|
|
5059
5325
|
PhotoBooth
|
|
5326
|
+
BounceHouse
|
|
5327
|
+
WaterSlide
|
|
5328
|
+
CarnivalGames
|
|
5060
5329
|
}
|
|
5061
5330
|
|
|
5062
5331
|
enum MediaProductionAndCreativeSubType {
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared shapes for the AI bash-approval reviewer.
|
|
3
|
+
*
|
|
4
|
+
* The Zod runtime envelope lives in `api/src/utils/ai/aiApprovalEnvelope.ts` (zod is an api
|
|
5
|
+
* dependency, not a bash-common one). This file is the type-only source of truth that both
|
|
6
|
+
* the api worker and bash-app's admin UI/host-facing banners read.
|
|
7
|
+
*
|
|
8
|
+
* The persisted `BashEvent.aiApprovalReasons` JSON column is exactly an `AiApprovalReasons`.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import type { AiApprovalVerdict } from "@prisma/client";
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Each criterion the model grades on.
|
|
15
|
+
*
|
|
16
|
+
* Keep this list short and stable — it controls the persisted JSON shape, the prompt
|
|
17
|
+
* the model sees, and the badges the admin UI renders. Adding a new criterion is a
|
|
18
|
+
* schema change (existing rows will be missing it).
|
|
19
|
+
*/
|
|
20
|
+
export const AI_APPROVAL_CRITERION_KEYS = [
|
|
21
|
+
"completeness",
|
|
22
|
+
"authenticity",
|
|
23
|
+
"safety",
|
|
24
|
+
"policyFit",
|
|
25
|
+
] as const;
|
|
26
|
+
|
|
27
|
+
export type AiApprovalCriterionKey = (typeof AI_APPROVAL_CRITERION_KEYS)[number];
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Display labels for criteria — used in the admin queue and any host-facing breakdown.
|
|
31
|
+
* Keep keys exhaustive against `AiApprovalCriterionKey` (compiler will yell if drift).
|
|
32
|
+
*/
|
|
33
|
+
export const AiApprovalCriterionLabel: Record<AiApprovalCriterionKey, string> = {
|
|
34
|
+
completeness: "Completeness",
|
|
35
|
+
authenticity: "Authenticity",
|
|
36
|
+
safety: "Safety",
|
|
37
|
+
policyFit: "Policy fit",
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* One criterion's grade. `score` is 0..1; `notes` is short free-text the model wrote
|
|
42
|
+
* about why (shown in the admin UI tooltip / host rejection reasons).
|
|
43
|
+
*/
|
|
44
|
+
export interface AiApprovalCriterionResult {
|
|
45
|
+
score: number;
|
|
46
|
+
notes: string;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Persisted shape for `BashEvent.aiApprovalReasons` (Json column).
|
|
51
|
+
*
|
|
52
|
+
* - `criteria` keys are exhaustive over `AiApprovalCriterionKey`.
|
|
53
|
+
* - `hostFacingMessage` is shown to the host on rejection; written specifically to be
|
|
54
|
+
* actionable ("Add a start time and a location, then resubmit"), not generic.
|
|
55
|
+
* Null on approve.
|
|
56
|
+
* - `adminFacingNotes` is for super-users in the review queue; can be more candid
|
|
57
|
+
* ("Looks like a duplicate of bash xyz" / "Probably a service ad in disguise").
|
|
58
|
+
*/
|
|
59
|
+
export interface AiApprovalReasons {
|
|
60
|
+
criteria: Record<AiApprovalCriterionKey, AiApprovalCriterionResult>;
|
|
61
|
+
hostFacingMessage: string | null;
|
|
62
|
+
adminFacingNotes: string;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Runtime values for the Prisma `AiApprovalVerdict` enum.
|
|
67
|
+
*
|
|
68
|
+
* Browser code (bash-app) cannot rely on `@prisma/client`'s runtime enum exports — the
|
|
69
|
+
* package's `browser` resolution doesn't reliably surface them when imported transitively
|
|
70
|
+
* via `@bash-app/bash-common`. So we mirror the enum here as a plain string-keyed object
|
|
71
|
+
* and `satisfies Record<AiApprovalVerdict, AiApprovalVerdict>` to guarantee at compile
|
|
72
|
+
* time that the keys/values stay in lockstep with `schema.prisma`. Prefer
|
|
73
|
+
* `AI_APPROVAL_VERDICTS.Approve` over `AiApprovalVerdict.Approve` in any code path that
|
|
74
|
+
* may be bundled for the browser.
|
|
75
|
+
*/
|
|
76
|
+
export const AI_APPROVAL_VERDICTS = {
|
|
77
|
+
Approve: "Approve",
|
|
78
|
+
Flag: "Flag",
|
|
79
|
+
Reject: "Reject",
|
|
80
|
+
} as const satisfies Record<AiApprovalVerdict, AiApprovalVerdict>;
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Display labels for the Prisma `AiApprovalVerdict` enum, used in admin pills and the
|
|
84
|
+
* host rejection banner so callers don't reach for ad-hoc switch statements.
|
|
85
|
+
*
|
|
86
|
+
* The `Record<AiApprovalVerdict, string>` annotation enforces exhaustiveness at compile
|
|
87
|
+
* time, so adding/renaming an enum member in `schema.prisma` will fail tsc here.
|
|
88
|
+
*/
|
|
89
|
+
export const AiApprovalVerdictLabel: Record<AiApprovalVerdict, string> = {
|
|
90
|
+
Approve: "Approve",
|
|
91
|
+
Flag: "Flag for review",
|
|
92
|
+
Reject: "Reject",
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Feature-flag values for `AI_BASH_APPROVAL_MODE`.
|
|
97
|
+
*
|
|
98
|
+
* - `off` - AI service is never invoked. Existing manual-only workflow.
|
|
99
|
+
* - `shadow` - AI runs and persists verdict + reasons, but every outcome is `flag`.
|
|
100
|
+
* Admins still decide everything; we use the data to tune thresholds.
|
|
101
|
+
* - `auto-with-flag` - High-confidence approve/reject act automatically; the rest flag for human.
|
|
102
|
+
* - `auto-approve-only` - High-confidence approve acts automatically; rejects always flag for human.
|
|
103
|
+
*/
|
|
104
|
+
export const AI_BASH_APPROVAL_MODES = [
|
|
105
|
+
"off",
|
|
106
|
+
"shadow",
|
|
107
|
+
"auto-with-flag",
|
|
108
|
+
"auto-approve-only",
|
|
109
|
+
] as const;
|
|
110
|
+
|
|
111
|
+
export type AiBashApprovalMode = (typeof AI_BASH_APPROVAL_MODES)[number];
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Default thresholds. Tune in the api consumer if behavior needs to change post-rollout;
|
|
115
|
+
* exporting here so tests in api can import a single source of truth.
|
|
116
|
+
*/
|
|
117
|
+
export const AI_APPROVAL_AUTO_APPROVE_CONFIDENCE = 0.85;
|
|
118
|
+
export const AI_APPROVAL_AUTO_REJECT_CONFIDENCE = 0.9;
|