@bash-app/bash-common 30.118.0 → 30.118.1

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 (2) hide show
  1. package/package.json +1 -1
  2. package/prisma/schema.prisma +391 -292
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bash-app/bash-common",
3
- "version": "30.118.0",
3
+ "version": "30.118.1",
4
4
  "description": "Common data and scripts to use on the frontend and backend",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -342,7 +342,7 @@ model EventTask {
342
342
  neededCount Int? // Number of volunteers needed
343
343
  estimatedDuration Int? // Estimated duration in minutes
344
344
  createdAt DateTime? @default(now())
345
- organizationId String? // Organization association
345
+ organizationId String? // Organization association
346
346
  assignedTo User? @relation("TasksAssignedToMe", fields: [assignedToId], references: [id], onDelete: Cascade)
347
347
  bashEvent BashEvent @relation(fields: [bashEventId], references: [id], onDelete: Cascade)
348
348
  creator User @relation(fields: [creatorId], references: [id], onDelete: Cascade)
@@ -552,99 +552,99 @@ model Invitation {
552
552
  }
553
553
 
554
554
  model BashEvent {
555
- id String @id @default(cuid())
556
- source BashEventSource @default(Bash)
557
- title String
558
- slug String? @unique
559
- creatorId String
560
- createdAt DateTime? @default(now())
561
- isApproved Boolean? @default(false)
562
- description String?
563
- eventType String @default("Other")
564
- timezone String?
565
- startDateTime DateTime?
566
- endDateTime DateTime?
567
- waiverUrl String?
568
- waiverRequired Boolean @default(false)
569
- waiverDisplayType String? @default("inline")
570
- targetAudienceId String? @unique
571
- amountOfGuestsId String? @unique
572
- vibe String?
573
- occasion String?
574
- dress String?
575
- allowed String?
576
- notAllowed String?
577
- eventFormat EventFormat? // Derived from location and videoLink: In-Person, Virtual, or Hybrid
578
- nonProfit Boolean?
579
- nonProfitId String?
580
- privacy Privacy @default(Public)
581
- capacity Int?
582
- location String?
583
- street String?
584
- city String?
585
- state String?
586
- zipCode String?
587
- country String?
588
- status BashStatus @default(Draft)
589
- tags String[]
590
- coverPhoto String?
591
- clubId String?
592
- dateTimePublished DateTime?
593
- includedItems String[]
594
- videoLink String?
595
- subtitle String?
596
- isFeatured Boolean?
597
- isTrending Boolean?
598
- venueId String?
599
- averageRating Float? @default(0)
600
- totalRatings Int? @default(0) // Total count of all ratings (Review + BashFeedRating)
601
- totalReviews Int? @default(0) // Count of Review records (anonymous quick ratings)
602
- totalFeedRatings Int? @default(0) // Count of BashFeedRating records (from posts)
603
- allowDonations Boolean? @default(true)
604
- suggestedDonationAmount Int?
605
- donationDetails String?
606
- absorbDonationFees Boolean @default(false)
607
- absorbTicketFees Boolean @default(false)
608
- showAttendees Boolean @default(true)
609
- servicePreferences Json? // New tiered status: { "Entertainment": "need", "Sponsors": "booked_closed", ... }
610
- bookedServices Json? // Booked service details: { "Entertainment": { serviceId: "...", providerId: "...", bookedAt: "..." }, ... }
611
- serviceVisibility Json? // DEPRECATED: Use servicePreferences instead. Kept for backward compatibility during migration.
612
- originalCreatorId String?
613
- transferredAt DateTime?
614
- transferredFromId String?
615
- transferCount Int @default(0)
616
- startTimeLocked Boolean @default(false)
617
- p2pPaymentMethod String?
618
- venmoUsername String?
619
- venmoQRCodeUrl String?
620
- zelleEmail String?
621
- zellePhone String?
622
- zelleQRCodeUrl String?
623
- externalTicketUrl String? // URL to external ticket purchase page (for imported events)
624
- externalPriceMin Int? // Minimum ticket price in cents (for imported events)
625
- externalPriceMax Int? // Maximum ticket price in cents (for imported events)
626
- externalPriceSummary String? // Human-readable price summary e.g., "$50 - $150" or "$75"
627
- customTermsAndConditions String?
628
- itinerary Json? // Array of { id: string, title: string, startTime: string, endTime: string, description?: string }
629
-
555
+ id String @id @default(cuid())
556
+ source BashEventSource @default(Bash)
557
+ title String
558
+ slug String? @unique
559
+ creatorId String
560
+ createdAt DateTime? @default(now())
561
+ isApproved Boolean? @default(false)
562
+ description String?
563
+ eventType String @default("Other")
564
+ timezone String?
565
+ startDateTime DateTime?
566
+ endDateTime DateTime?
567
+ waiverUrl String?
568
+ waiverRequired Boolean @default(false)
569
+ waiverDisplayType String? @default("inline")
570
+ targetAudienceId String? @unique
571
+ amountOfGuestsId String? @unique
572
+ vibe String?
573
+ occasion String?
574
+ dress String?
575
+ allowed String?
576
+ notAllowed String?
577
+ eventFormat EventFormat? // Derived from location and videoLink: In-Person, Virtual, or Hybrid
578
+ nonProfit Boolean?
579
+ nonProfitId String?
580
+ privacy Privacy @default(Public)
581
+ capacity Int?
582
+ location String?
583
+ street String?
584
+ city String?
585
+ state String?
586
+ zipCode String?
587
+ country String?
588
+ status BashStatus @default(Draft)
589
+ tags String[]
590
+ coverPhoto String?
591
+ clubId String?
592
+ dateTimePublished DateTime?
593
+ includedItems String[]
594
+ videoLink String?
595
+ subtitle String?
596
+ isFeatured Boolean?
597
+ isTrending Boolean?
598
+ venueId String?
599
+ averageRating Float? @default(0)
600
+ totalRatings Int? @default(0) // Total count of all ratings (Review + BashFeedRating)
601
+ totalReviews Int? @default(0) // Count of Review records (anonymous quick ratings)
602
+ totalFeedRatings Int? @default(0) // Count of BashFeedRating records (from posts)
603
+ allowDonations Boolean? @default(true)
604
+ suggestedDonationAmount Int?
605
+ donationDetails String?
606
+ absorbDonationFees Boolean @default(false)
607
+ absorbTicketFees Boolean @default(false)
608
+ showAttendees Boolean @default(true)
609
+ servicePreferences Json? // New tiered status: { "Entertainment": "need", "Sponsors": "booked_closed", ... }
610
+ bookedServices Json? // Booked service details: { "Entertainment": { serviceId: "...", providerId: "...", bookedAt: "..." }, ... }
611
+ serviceVisibility Json? // DEPRECATED: Use servicePreferences instead. Kept for backward compatibility during migration.
612
+ originalCreatorId String?
613
+ transferredAt DateTime?
614
+ transferredFromId String?
615
+ transferCount Int @default(0)
616
+ startTimeLocked Boolean @default(false)
617
+ p2pPaymentMethod String?
618
+ venmoUsername String?
619
+ venmoQRCodeUrl String?
620
+ zelleEmail String?
621
+ zellePhone String?
622
+ zelleQRCodeUrl String?
623
+ externalTicketUrl String? // URL to external ticket purchase page (for imported events)
624
+ externalPriceMin Int? // Minimum ticket price in cents (for imported events)
625
+ externalPriceMax Int? // Maximum ticket price in cents (for imported events)
626
+ externalPriceSummary String? // Human-readable price summary e.g., "$50 - $150" or "$75"
627
+ customTermsAndConditions String?
628
+ itinerary Json? // Array of { id: string, title: string, startTime: string, endTime: string, description?: string }
629
+
630
630
  // Idea-specific fields (only used when status = 'Idea')
631
- ideaExpiresAt DateTime?
632
- ideaInterestThreshold Int? @default(35)
633
- hideInterestCount Boolean @default(false)
634
- isAutoApprovable Boolean @default(false)
635
- autoApprovedAt DateTime?
636
- lastEngagementAt DateTime? // Track last interest/share for decay
637
-
631
+ ideaExpiresAt DateTime?
632
+ ideaInterestThreshold Int? @default(35)
633
+ hideInterestCount Boolean @default(false)
634
+ isAutoApprovable Boolean @default(false)
635
+ autoApprovedAt DateTime?
636
+ lastEngagementAt DateTime? // Track last interest/share for decay
637
+
638
638
  // Organization field
639
- organizationId String?
640
- organization Organization? @relation("OrganizationBashEvents", fields: [organizationId], references: [id])
641
-
639
+ organizationId String?
640
+ organization Organization? @relation("OrganizationBashEvents", fields: [organizationId], references: [id])
641
+
642
642
  // Organization access controls (only apply when organizationId is set)
643
- requiresOrgMembership Boolean @default(false) // Must be member to attend/RSVP
644
- allowMemberGuests Boolean @default(false) // Members can bring +1s
645
- maxGuestsPerMember Int? // Guest limit per member (null = unlimited)
646
- restrictToOrgDepartments String[] @default([]) // Empty = all departments can see/join
647
-
643
+ requiresOrgMembership Boolean @default(false) // Must be member to attend/RSVP
644
+ allowMemberGuests Boolean @default(false) // Members can bring +1s
645
+ maxGuestsPerMember Int? // Guest limit per member (null = unlimited)
646
+ restrictToOrgDepartments String[] @default([]) // Empty = all departments can see/join
647
+
648
648
  associatedBashesReferencingMe AssociatedBash[]
649
649
  comments BashComment[]
650
650
  amountOfGuests AmountOfGuests? @relation(fields: [amountOfGuestsId], references: [id], onDelete: Cascade)
@@ -697,17 +697,17 @@ model BashEvent {
697
697
  bashFeedPosts BashFeedPost[]
698
698
  bashFeedRatings BashFeedRating[]
699
699
  eventRankings EventRankings?
700
-
700
+
701
701
  // Idea Relations
702
- interests IdeaInterest[]
703
- configurations IdeaConfiguration[]
702
+ interests IdeaInterest[]
703
+ configurations IdeaConfiguration[]
704
704
 
705
705
  // Analytics Relations
706
706
  analyticsPredictions AnalyticsPrediction[]
707
-
707
+
708
708
  // Organization Relations
709
- budgets Budget[] @relation("EventBudgets")
710
- rsvps EventRSVP[] @relation("EventRSVPs")
709
+ budgets Budget[] @relation("EventBudgets")
710
+ rsvps EventRSVP[] @relation("EventRSVPs")
711
711
 
712
712
  @@index([templateId])
713
713
  @@index([parentEventId])
@@ -719,22 +719,22 @@ model BashEvent {
719
719
  // ============================================
720
720
 
721
721
  model IdeaInterest {
722
- id String @id @default(cuid())
722
+ id String @id @default(cuid())
723
723
  bashEventId String
724
724
  email String
725
725
  phone String?
726
- source String? // 'tiktok_bio', 'bashfeed', 'share', 'direct'
727
- ipAddress String? // For fraud prevention
726
+ source String? // 'tiktok_bio', 'bashfeed', 'share', 'direct'
727
+ ipAddress String? // For fraud prevention
728
728
  userAgent String?
729
- convertedToUserId String? // If they later create account
730
- createdAt DateTime @default(now())
731
- updatedAt DateTime @updatedAt
732
-
729
+ convertedToUserId String? // If they later create account
730
+ createdAt DateTime @default(now())
731
+ updatedAt DateTime @updatedAt
732
+
733
733
  // Relationships
734
- bashEvent BashEvent @relation(fields: [bashEventId], references: [id], onDelete: Cascade)
735
- user User? @relation(fields: [convertedToUserId], references: [id])
736
- responses IdeaInterestResponse[]
737
-
734
+ bashEvent BashEvent @relation(fields: [bashEventId], references: [id], onDelete: Cascade)
735
+ user User? @relation(fields: [convertedToUserId], references: [id])
736
+ responses IdeaInterestResponse[]
737
+
738
738
  @@unique([bashEventId, email])
739
739
  @@index([bashEventId])
740
740
  @@index([email])
@@ -742,38 +742,38 @@ model IdeaInterest {
742
742
  }
743
743
 
744
744
  model IdeaInterestResponse {
745
- id String @id @default(cuid())
745
+ id String @id @default(cuid())
746
746
  interestId String
747
- questionType String // 'base_price', 'configuration_price', 'preferred_date', 'must_have'
748
- questionText String? // For custom host questions
749
- responseValue String // JSON: {min: 20, max: 50} or "Yes" or date string
750
- configurationId String? // Links to specific configuration if applicable
751
- createdAt DateTime @default(now())
752
-
747
+ questionType String // 'base_price', 'configuration_price', 'preferred_date', 'must_have'
748
+ questionText String? // For custom host questions
749
+ responseValue String // JSON: {min: 20, max: 50} or "Yes" or date string
750
+ configurationId String? // Links to specific configuration if applicable
751
+ createdAt DateTime @default(now())
752
+
753
753
  // Relationships
754
- interest IdeaInterest @relation(fields: [interestId], references: [id], onDelete: Cascade)
755
- configuration IdeaConfiguration? @relation(fields: [configurationId], references: [id], onDelete: SetNull)
756
-
754
+ interest IdeaInterest @relation(fields: [interestId], references: [id], onDelete: Cascade)
755
+ configuration IdeaConfiguration? @relation(fields: [configurationId], references: [id], onDelete: SetNull)
756
+
757
757
  @@index([interestId])
758
758
  @@index([configurationId])
759
759
  @@index([questionType])
760
760
  }
761
761
 
762
762
  model IdeaConfiguration {
763
- id String @id @default(cuid())
764
- bashEventId String
765
- name String // "Premium Open Bar", "Food Truck", "Live DJ"
766
- description String?
767
- estimatedCost Int? // In cents - helps host with pricing
768
- isActive Boolean @default(true)
769
- sortOrder Int @default(0)
770
- createdAt DateTime @default(now())
771
- updatedAt DateTime @updatedAt
772
-
763
+ id String @id @default(cuid())
764
+ bashEventId String
765
+ name String // "Premium Open Bar", "Food Truck", "Live DJ"
766
+ description String?
767
+ estimatedCost Int? // In cents - helps host with pricing
768
+ isActive Boolean @default(true)
769
+ sortOrder Int @default(0)
770
+ createdAt DateTime @default(now())
771
+ updatedAt DateTime @updatedAt
772
+
773
773
  // Relationships
774
- bashEvent BashEvent @relation(fields: [bashEventId], references: [id], onDelete: Cascade)
775
- responses IdeaInterestResponse[]
776
-
774
+ bashEvent BashEvent @relation(fields: [bashEventId], references: [id], onDelete: Cascade)
775
+ responses IdeaInterestResponse[]
776
+
777
777
  @@index([bashEventId])
778
778
  @@index([isActive])
779
779
  }
@@ -944,12 +944,12 @@ model TicketTier {
944
944
  waitList User[] @relation("TicketTierToUser")
945
945
  specialOffers SpecialOffer[] // NEW - Special offers for this tier
946
946
  appliedDiscounts AppliedDiscount[] // NEW - Discounts applied to this tier
947
-
947
+
948
948
  // Organization member restrictions (for org events)
949
- restrictedToRoles String[] @default([]) // ["Admin", "Owner"] - empty = all roles
950
- restrictedToDepartments String[] @default([]) // [deptId1, deptId2] - empty = all departments
949
+ restrictedToRoles String[] @default([]) // ["Admin", "Owner"] - empty = all roles
950
+ restrictedToDepartments String[] @default([]) // [deptId1, deptId2] - empty = all departments
951
951
  restrictedToMembershipTiers String[] @default([]) // ["Premium"] - empty = all membership tiers
952
- isGuestTier Boolean @default(false) // Ticket for member +1s
952
+ isGuestTier Boolean @default(false) // Ticket for member +1s
953
953
 
954
954
  @@unique([bashEventId, title])
955
955
  }
@@ -1533,21 +1533,26 @@ model User {
1533
1533
  nominationsGiven Nomination[] @relation("NominatingUser")
1534
1534
  votesGiven NominationVote[]
1535
1535
  categoriesCreated NominationCategory[]
1536
-
1536
+
1537
1537
  // Idea Interest Relations
1538
1538
  ideaInterests IdeaInterest[]
1539
-
1539
+
1540
1540
  // Organization Relations
1541
- ownedOrganizations Organization[] @relation("OrganizationOwner")
1542
- organizationMemberships OrganizationMember[] @relation("OrganizationMemberUser")
1543
- organizationEventRSVPs EventRSVP[] @relation("OrganizationEventRSVP")
1544
- submittedExpenses Expense[] @relation("ExpenseSubmitter")
1545
- approvedExpenses Expense[] @relation("ExpenseApprover")
1546
- approvedBudgets Budget[] @relation("BudgetApprover")
1547
- submittedBudgets Budget[] @relation("BudgetSubmitter")
1548
- ownedBudgets Budget[] @relation("UserBudgets")
1549
- departmentsHeaded Department[] @relation("DepartmentHead")
1550
- favoriteOrganizations Organization[] @relation("FavoriteOrganizations")
1541
+ ownedOrganizations Organization[] @relation("OrganizationOwner")
1542
+ organizationMemberships OrganizationMember[] @relation("OrganizationMemberUser")
1543
+ organizationEventRSVPs EventRSVP[] @relation("OrganizationEventRSVP")
1544
+ submittedExpenses Expense[] @relation("ExpenseSubmitter")
1545
+ approvedExpenses Expense[] @relation("ExpenseApprover")
1546
+ approvedBudgets Budget[] @relation("BudgetApprover")
1547
+ submittedBudgets Budget[] @relation("BudgetSubmitter")
1548
+ ownedBudgets Budget[] @relation("UserBudgets")
1549
+ departmentsHeaded Department[] @relation("DepartmentHead")
1550
+ favoriteOrganizations Organization[] @relation("FavoriteOrganizations")
1551
+
1552
+ // Service Includes & Add-On Requests
1553
+ suggestedIncludes ServiceInclude[] @relation("SuggestedIncludes")
1554
+ includeVotes ServiceIncludeVote[]
1555
+ requestedAddons ServiceAddonRequest[] @relation("RequestedAddons")
1551
1556
  }
1552
1557
 
1553
1558
  model UserPreferences {
@@ -2028,6 +2033,8 @@ model Service {
2028
2033
  bookingCommissions BookingCommission[] @relation("CommissionServiceProfile")
2029
2034
  venueMatches VenueEntertainmentMatch[] @relation("VenueMatches")
2030
2035
  entertainerMatches VenueEntertainmentMatch[] @relation("EntertainerMatches")
2036
+ includes ServiceInclude[]
2037
+ addonRequests ServiceAddonRequest[]
2031
2038
 
2032
2039
  @@index([serviceListingStripeSubscriptionId])
2033
2040
  @@index([isFreeFirstListing])
@@ -2364,53 +2371,53 @@ model UserPromoCodeRedemption {
2364
2371
  }
2365
2372
 
2366
2373
  model Organization {
2367
- id String @id @default(cuid())
2368
- name String
2369
- slug String @unique
2370
- organizationType OrganizationType[]
2371
- bio String?
2372
- mission String?
2373
- pocName String?
2374
- pocEmail String?
2375
- pocPhone String?
2376
- street String?
2377
- city String?
2378
- state String?
2379
- zipCode String?
2380
- country String? @default("US")
2381
- coverPhoto String?
2382
- logoUrl String?
2383
- websiteUrl String?
2384
- socialLinks Json?
2385
- goodsOrServices String[]
2386
- venueTypes String[]
2387
- secondaryVenueTypes String[] @default([])
2388
- baseMembershipPriceCents Int?
2389
- premiumMembershipPriceCents Int?
2390
- allowGuestsByDefault Boolean @default(false)
2391
- defaultGuestLimit Int @default(0)
2392
- visibility String @default("Public")
2393
- requiresApproval Boolean @default(true)
2394
- memberAutoApproval Boolean @default(false)
2395
- ownerId String
2396
- parentOrganizationId String?
2397
- departmentName String?
2398
- hierarchyLevel Int @default(0)
2399
- subscriptionTier String?
2400
- subscriptionStatus String?
2401
- stripeSubscriptionId String? @unique
2402
- stripeCustomerId String?
2403
- createdAt DateTime @default(now())
2404
- updatedAt DateTime @updatedAt
2405
- service Service?
2406
- owner User @relation("OrganizationOwner", fields: [ownerId], references: [id], onDelete: Restrict)
2407
- parentOrganization Organization? @relation("OrganizationHierarchy", fields: [parentOrganizationId], references: [id])
2408
- childOrganizations Organization[] @relation("OrganizationHierarchy")
2409
- members OrganizationMember[]
2410
- budgets Budget[] @relation("OrganizationBudgets")
2411
- departments Department[]
2412
- bashEvents BashEvent[] @relation("OrganizationBashEvents")
2413
- favoriteBy User[] @relation("FavoriteOrganizations")
2374
+ id String @id @default(cuid())
2375
+ name String
2376
+ slug String @unique
2377
+ organizationType OrganizationType[]
2378
+ bio String?
2379
+ mission String?
2380
+ pocName String?
2381
+ pocEmail String?
2382
+ pocPhone String?
2383
+ street String?
2384
+ city String?
2385
+ state String?
2386
+ zipCode String?
2387
+ country String? @default("US")
2388
+ coverPhoto String?
2389
+ logoUrl String?
2390
+ websiteUrl String?
2391
+ socialLinks Json?
2392
+ goodsOrServices String[]
2393
+ venueTypes String[]
2394
+ secondaryVenueTypes String[] @default([])
2395
+ baseMembershipPriceCents Int?
2396
+ premiumMembershipPriceCents Int?
2397
+ allowGuestsByDefault Boolean @default(false)
2398
+ defaultGuestLimit Int @default(0)
2399
+ visibility String @default("Public")
2400
+ requiresApproval Boolean @default(true)
2401
+ memberAutoApproval Boolean @default(false)
2402
+ ownerId String
2403
+ parentOrganizationId String?
2404
+ departmentName String?
2405
+ hierarchyLevel Int @default(0)
2406
+ subscriptionTier String?
2407
+ subscriptionStatus String?
2408
+ stripeSubscriptionId String? @unique
2409
+ stripeCustomerId String?
2410
+ createdAt DateTime @default(now())
2411
+ updatedAt DateTime @updatedAt
2412
+ service Service?
2413
+ owner User @relation("OrganizationOwner", fields: [ownerId], references: [id], onDelete: Restrict)
2414
+ parentOrganization Organization? @relation("OrganizationHierarchy", fields: [parentOrganizationId], references: [id])
2415
+ childOrganizations Organization[] @relation("OrganizationHierarchy")
2416
+ members OrganizationMember[]
2417
+ budgets Budget[] @relation("OrganizationBudgets")
2418
+ departments Department[]
2419
+ bashEvents BashEvent[] @relation("OrganizationBashEvents")
2420
+ favoriteBy User[] @relation("FavoriteOrganizations")
2414
2421
 
2415
2422
  @@index([ownerId])
2416
2423
  @@index([slug])
@@ -2444,40 +2451,39 @@ model OrganizationMember {
2444
2451
  }
2445
2452
 
2446
2453
  model Department {
2447
- id String @id @default(cuid())
2448
- organizationId String
2449
- name String
2450
- description String?
2451
- parentDeptId String?
2452
- headUserId String?
2453
- budgetCents Int?
2454
- createdAt DateTime @default(now())
2455
- updatedAt DateTime @updatedAt
2456
- organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)
2457
- parentDept Department? @relation("DepartmentHierarchy", fields: [parentDeptId], references: [id])
2458
- childDepts Department[] @relation("DepartmentHierarchy")
2459
- head User? @relation("DepartmentHead", fields: [headUserId], references: [id])
2460
- budgets Budget[] @relation("DepartmentBudgets")
2454
+ id String @id @default(cuid())
2455
+ organizationId String
2456
+ name String
2457
+ description String?
2458
+ parentDeptId String?
2459
+ headUserId String?
2460
+ budgetCents Int?
2461
+ createdAt DateTime @default(now())
2462
+ updatedAt DateTime @updatedAt
2463
+ organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)
2464
+ parentDept Department? @relation("DepartmentHierarchy", fields: [parentDeptId], references: [id])
2465
+ childDepts Department[] @relation("DepartmentHierarchy")
2466
+ head User? @relation("DepartmentHead", fields: [headUserId], references: [id])
2467
+ budgets Budget[] @relation("DepartmentBudgets")
2461
2468
 
2462
2469
  @@index([organizationId])
2463
2470
  @@index([parentDeptId])
2464
2471
  }
2465
2472
 
2466
-
2467
2473
  model EventRSVP {
2468
- id String @id @default(cuid())
2469
- eventId String
2470
- memberId String
2471
- userId String
2472
- status String @default("Going") // Going, Maybe, NotGoing
2473
- guestsCount Int @default(0)
2474
- checkedIn Boolean @default(false)
2475
- checkedInAt DateTime?
2476
- createdAt DateTime @default(now())
2477
- updatedAt DateTime @updatedAt
2478
- event BashEvent @relation("EventRSVPs", fields: [eventId], references: [id], onDelete: Cascade)
2479
- member OrganizationMember @relation(fields: [memberId], references: [id], onDelete: Cascade)
2480
- user User @relation("OrganizationEventRSVP", fields: [userId], references: [id])
2474
+ id String @id @default(cuid())
2475
+ eventId String
2476
+ memberId String
2477
+ userId String
2478
+ status String @default("Going") // Going, Maybe, NotGoing
2479
+ guestsCount Int @default(0)
2480
+ checkedIn Boolean @default(false)
2481
+ checkedInAt DateTime?
2482
+ createdAt DateTime @default(now())
2483
+ updatedAt DateTime @updatedAt
2484
+ event BashEvent @relation("EventRSVPs", fields: [eventId], references: [id], onDelete: Cascade)
2485
+ member OrganizationMember @relation(fields: [memberId], references: [id], onDelete: Cascade)
2486
+ user User @relation("OrganizationEventRSVP", fields: [userId], references: [id])
2481
2487
 
2482
2488
  @@unique([eventId, userId])
2483
2489
  @@index([eventId])
@@ -2485,50 +2491,50 @@ model EventRSVP {
2485
2491
  }
2486
2492
 
2487
2493
  model Budget {
2488
- id String @id @default(cuid())
2489
- name String
2490
-
2494
+ id String @id @default(cuid())
2495
+ name String
2496
+
2491
2497
  // Flexible ownership - at least ONE should be set
2492
- organizationId String?
2493
- bashEventId String?
2494
- clubId String?
2495
- departmentId String?
2496
- userId String? // For personal event budgets
2497
-
2498
+ organizationId String?
2499
+ bashEventId String?
2500
+ clubId String?
2501
+ departmentId String?
2502
+ userId String? // For personal event budgets
2503
+
2498
2504
  // Budget details
2499
- totalAllocatedCents Int
2500
- totalBudgetCents Int? // Alias for backward compatibility
2501
- spentCents Int @default(0)
2502
- remainingCents Int? // Can be computed: totalAllocatedCents - spentCents
2503
-
2505
+ totalAllocatedCents Int
2506
+ totalBudgetCents Int? // Alias for backward compatibility
2507
+ spentCents Int @default(0)
2508
+ remainingCents Int? // Can be computed: totalAllocatedCents - spentCents
2509
+
2504
2510
  // Categorization
2505
- category String? // "Marketing", "Catering", "Venue", "Annual", "Activities"
2506
- fiscalYear String? // Keep as String for flexibility ("2026", "2026-Q1", "FY2026")
2507
-
2511
+ category String? // "Marketing", "Catering", "Venue", "Annual", "Activities"
2512
+ fiscalYear String? // Keep as String for flexibility ("2026", "2026-Q1", "FY2026")
2513
+
2508
2514
  // Approval workflow
2509
- status String? @default("Draft") // Draft, Submitted, Approved, Active, Closed, Archived
2510
- submittedBy String?
2511
- approverId String?
2512
- approvedBy String? // Alias for approverId
2513
- approvedAt DateTime?
2514
-
2515
+ status String? @default("Draft") // Draft, Submitted, Approved, Active, Closed, Archived
2516
+ submittedBy String?
2517
+ approverId String?
2518
+ approvedBy String? // Alias for approverId
2519
+ approvedAt DateTime?
2520
+
2515
2521
  // Date ranges
2516
- startDate DateTime?
2517
- endDate DateTime?
2518
-
2522
+ startDate DateTime?
2523
+ endDate DateTime?
2524
+
2519
2525
  // Timestamps
2520
- createdAt DateTime @default(now())
2521
- updatedAt DateTime @updatedAt
2522
-
2526
+ createdAt DateTime @default(now())
2527
+ updatedAt DateTime @updatedAt
2528
+
2523
2529
  // Relations
2524
- organization Organization? @relation("OrganizationBudgets", fields: [organizationId], references: [id], onDelete: Cascade)
2525
- bashEvent BashEvent? @relation("EventBudgets", fields: [bashEventId], references: [id], onDelete: Cascade)
2526
- club Club? @relation("ClubBudgets", fields: [clubId], references: [id], onDelete: Cascade)
2527
- department Department? @relation("DepartmentBudgets", fields: [departmentId], references: [id], onDelete: Cascade)
2528
- user User? @relation("UserBudgets", fields: [userId], references: [id], onDelete: Cascade)
2529
- submitter User? @relation("BudgetSubmitter", fields: [submittedBy], references: [id])
2530
- approver User? @relation("BudgetApprover", fields: [approverId], references: [id])
2531
- expenses Expense[]
2530
+ organization Organization? @relation("OrganizationBudgets", fields: [organizationId], references: [id], onDelete: Cascade)
2531
+ bashEvent BashEvent? @relation("EventBudgets", fields: [bashEventId], references: [id], onDelete: Cascade)
2532
+ club Club? @relation("ClubBudgets", fields: [clubId], references: [id], onDelete: Cascade)
2533
+ department Department? @relation("DepartmentBudgets", fields: [departmentId], references: [id], onDelete: Cascade)
2534
+ user User? @relation("UserBudgets", fields: [userId], references: [id], onDelete: Cascade)
2535
+ submitter User? @relation("BudgetSubmitter", fields: [submittedBy], references: [id])
2536
+ approver User? @relation("BudgetApprover", fields: [approverId], references: [id])
2537
+ expenses Expense[]
2532
2538
 
2533
2539
  @@index([organizationId])
2534
2540
  @@index([bashEventId])
@@ -2540,23 +2546,23 @@ model Budget {
2540
2546
  }
2541
2547
 
2542
2548
  model Expense {
2543
- id String @id @default(cuid())
2544
- budgetId String
2545
- submittedBy String
2546
- description String
2547
- amountCents Int
2548
- category String?
2549
- receiptUrl String?
2550
- expenseDate DateTime? // When the expense occurred
2551
- status String @default("Pending") // Pending, Approved, Rejected
2552
- approvedBy String?
2553
- approvedAt DateTime?
2554
- rejectionReason String?
2555
- createdAt DateTime @default(now())
2556
- updatedAt DateTime @updatedAt
2557
- budget Budget @relation(fields: [budgetId], references: [id], onDelete: Cascade)
2558
- submitter User @relation("ExpenseSubmitter", fields: [submittedBy], references: [id])
2559
- approver User? @relation("ExpenseApprover", fields: [approvedBy], references: [id])
2549
+ id String @id @default(cuid())
2550
+ budgetId String
2551
+ submittedBy String
2552
+ description String
2553
+ amountCents Int
2554
+ category String?
2555
+ receiptUrl String?
2556
+ expenseDate DateTime? // When the expense occurred
2557
+ status String @default("Pending") // Pending, Approved, Rejected
2558
+ approvedBy String?
2559
+ approvedAt DateTime?
2560
+ rejectionReason String?
2561
+ createdAt DateTime @default(now())
2562
+ updatedAt DateTime @updatedAt
2563
+ budget Budget @relation(fields: [budgetId], references: [id], onDelete: Cascade)
2564
+ submitter User @relation("ExpenseSubmitter", fields: [submittedBy], references: [id])
2565
+ approver User? @relation("ExpenseApprover", fields: [approvedBy], references: [id])
2560
2566
 
2561
2567
  @@index([budgetId])
2562
2568
  @@index([submittedBy])
@@ -2582,11 +2588,87 @@ model ServiceAddon {
2582
2588
  priceCents Int
2583
2589
  quantity Int
2584
2590
  status ServiceAddonStatus @default(Enabled)
2591
+ imageUrl String? // Add-on image URL
2592
+ imageAlt String? // Alt text for accessibility
2585
2593
  servicePackageId String?
2586
2594
  serviceRatesAssociationId String?
2587
2595
  servicePackage ServicePackage? @relation(fields: [servicePackageId], references: [id], onDelete: Cascade)
2588
2596
  serviceRatesAssociation ServiceRatesAssociation? @relation(fields: [serviceRatesAssociationId], references: [id], onDelete: Cascade)
2589
2597
  ServiceBookingAddOn ServiceBookingAddOn[]
2598
+ convertedFromInclude ServiceInclude[] @relation("IncludeConvertedToAddon")
2599
+ convertedFromRequest ServiceAddonRequest[] @relation("RequestConvertedToAddon")
2600
+
2601
+ @@index([imageUrl])
2602
+ }
2603
+
2604
+ model ServiceInclude {
2605
+ id String @id @default(cuid())
2606
+ serviceId String
2607
+ suggestedByUserId String? // Who suggested it (null if anonymous)
2608
+ name String // e.g., "Tables and Chairs"
2609
+ description String? // Optional details
2610
+ status ServiceIncludeStatus @default(Pending)
2611
+ providerResponse ServiceIncludeResponse? // How provider responded
2612
+ responseNote String? // Optional note from provider
2613
+ convertedToAddonId String? // If converted to paid add-on
2614
+ voteCount Int @default(0) // Net votes (upvotes - downvotes)
2615
+ upvoteCount Int @default(0)
2616
+ downvoteCount Int @default(0)
2617
+ isActuallyIncluded Boolean @default(false) // Provider confirmed it IS included
2618
+ createdAt DateTime @default(now())
2619
+ updatedAt DateTime @updatedAt
2620
+
2621
+ service Service @relation(fields: [serviceId], references: [id], onDelete: Cascade)
2622
+ suggestedBy User? @relation("SuggestedIncludes", fields: [suggestedByUserId], references: [id], onDelete: SetNull)
2623
+ convertedToAddon ServiceAddon? @relation("IncludeConvertedToAddon", fields: [convertedToAddonId], references: [id], onDelete: SetNull)
2624
+ votes ServiceIncludeVote[]
2625
+
2626
+ @@unique([serviceId, name]) // Prevent duplicate suggestions for same service
2627
+ @@index([serviceId])
2628
+ @@index([status])
2629
+ @@index([voteCount])
2630
+ @@index([createdAt])
2631
+ }
2632
+
2633
+ model ServiceIncludeVote {
2634
+ id String @id @default(cuid())
2635
+ serviceIncludeId String
2636
+ userId String
2637
+ voteType VoteType // Upvote or Downvote
2638
+ createdAt DateTime @default(now())
2639
+ updatedAt DateTime @updatedAt
2640
+
2641
+ serviceInclude ServiceInclude @relation(fields: [serviceIncludeId], references: [id], onDelete: Cascade)
2642
+ user User @relation(fields: [userId], references: [id], onDelete: Cascade)
2643
+
2644
+ @@unique([serviceIncludeId, userId]) // One vote per user per include
2645
+ @@index([serviceIncludeId])
2646
+ @@index([userId])
2647
+ }
2648
+
2649
+ model ServiceAddonRequest {
2650
+ id String @id @default(cuid())
2651
+ serviceId String
2652
+ userId String? // null if anonymous
2653
+ name String // e.g., "Specialty Lighting Package"
2654
+ description String? // Optional details
2655
+ status ServiceAddonRequestStatus @default(Pending)
2656
+ providerNote String? // Provider's response/notes
2657
+ notifyOnAvailable Boolean @default(false) // Customer wants notification
2658
+ convertedToAddonId String? // Links to actual ServiceAddon if created
2659
+ requestCount Int @default(1) // How many customers requested this
2660
+ createdAt DateTime @default(now())
2661
+ updatedAt DateTime @updatedAt
2662
+
2663
+ service Service @relation(fields: [serviceId], references: [id], onDelete: Cascade)
2664
+ user User? @relation("RequestedAddons", fields: [userId], references: [id], onDelete: SetNull)
2665
+ convertedToAddon ServiceAddon? @relation("RequestConvertedToAddon", fields: [convertedToAddonId], references: [id], onDelete: SetNull)
2666
+
2667
+ @@index([serviceId])
2668
+ @@index([status])
2669
+ @@index([userId])
2670
+ @@index([requestCount])
2671
+ @@index([createdAt])
2590
2672
  }
2591
2673
 
2592
2674
  model ServicePackage {
@@ -3647,7 +3729,7 @@ enum UserIntent {
3647
3729
  }
3648
3730
 
3649
3731
  enum BashStatus {
3650
- Idea // Pre-event idea gauging interest
3732
+ Idea // Pre-event idea gauging interest
3651
3733
  Draft
3652
3734
  Pending
3653
3735
  PreSale
@@ -5006,25 +5088,14 @@ enum OrganizationType {
5006
5088
  GreekLife
5007
5089
  SocialClub
5008
5090
  Nonprofit
5009
- Corporation
5010
- EducationalInstitution
5011
- Sports
5012
- Government
5013
- Cultural
5014
- Lifestyle
5015
- Political
5016
- Tourism
5017
- Youth
5018
- Senior
5019
- Tradeshow
5091
+ Other
5020
5092
  Professional
5021
5093
  RecordLabel
5022
5094
  School
5023
5095
  StudentClub
5024
- Conference
5025
- FoodAndBeverage
5026
- TechAndStartups
5027
- Other
5096
+ Sports
5097
+ Youth
5098
+ Cultural
5028
5099
  }
5029
5100
 
5030
5101
  enum YearsOfExperience {
@@ -5045,6 +5116,34 @@ enum ServiceAddonStatus {
5045
5116
  Disabled
5046
5117
  }
5047
5118
 
5119
+ enum ServiceIncludeStatus {
5120
+ Pending // Customer suggested, awaiting provider review
5121
+ Approved // Provider confirmed it IS included
5122
+ Declined // Provider says not possible/won't include
5123
+ Duplicate // Same as another suggestion
5124
+ }
5125
+
5126
+ enum ServiceIncludeResponse {
5127
+ NotPossible // Can't offer this
5128
+ Added // Now included in base package
5129
+ AlreadyIncluded // Was already included
5130
+ AvailableAsAddOn // Can offer but as paid add-on
5131
+ UnderConsideration // Thinking about it
5132
+ }
5133
+
5134
+ enum VoteType {
5135
+ Upvote
5136
+ Downvote
5137
+ }
5138
+
5139
+ enum ServiceAddonRequestStatus {
5140
+ Pending // New request
5141
+ Acknowledged // Provider saw it
5142
+ Added // Provider created the add-on
5143
+ Declined // Provider won't offer this
5144
+ Duplicate // Same as another request
5145
+ }
5146
+
5048
5147
  enum ServiceBookingFeeType {
5049
5148
  CleaningFee
5050
5149
  ProcessingFee