@bash-app/bash-common 30.275.0 → 30.276.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 (57) hide show
  1. package/dist/__tests__/groupTicketUtils.test.d.ts +2 -0
  2. package/dist/__tests__/groupTicketUtils.test.d.ts.map +1 -0
  3. package/dist/__tests__/groupTicketUtils.test.js +38 -0
  4. package/dist/__tests__/groupTicketUtils.test.js.map +1 -0
  5. package/dist/competitionIdeas.d.ts +19 -0
  6. package/dist/competitionIdeas.d.ts.map +1 -0
  7. package/dist/competitionIdeas.js +405 -0
  8. package/dist/competitionIdeas.js.map +1 -0
  9. package/dist/competitionValidation.d.ts +10 -0
  10. package/dist/competitionValidation.d.ts.map +1 -0
  11. package/dist/competitionValidation.js +29 -0
  12. package/dist/competitionValidation.js.map +1 -0
  13. package/dist/definitions.d.ts +4 -0
  14. package/dist/definitions.d.ts.map +1 -1
  15. package/dist/definitions.js.map +1 -1
  16. package/dist/extendedSchemas.d.ts +351 -1
  17. package/dist/extendedSchemas.d.ts.map +1 -1
  18. package/dist/extendedSchemas.js +15 -0
  19. package/dist/extendedSchemas.js.map +1 -1
  20. package/dist/groupTicketUtils.d.ts +19 -0
  21. package/dist/groupTicketUtils.d.ts.map +1 -0
  22. package/dist/groupTicketUtils.js +74 -0
  23. package/dist/groupTicketUtils.js.map +1 -0
  24. package/dist/index.d.ts +4 -0
  25. package/dist/index.d.ts.map +1 -1
  26. package/dist/index.js +4 -0
  27. package/dist/index.js.map +1 -1
  28. package/dist/utils/__tests__/paymentUtils.test.js +18 -0
  29. package/dist/utils/__tests__/paymentUtils.test.js.map +1 -1
  30. package/dist/utils/__tests__/ticketListUtils.test.js +10 -0
  31. package/dist/utils/__tests__/ticketListUtils.test.js.map +1 -1
  32. package/dist/utils/groupTicketCartUtils.d.ts +12 -0
  33. package/dist/utils/groupTicketCartUtils.d.ts.map +1 -0
  34. package/dist/utils/groupTicketCartUtils.js +30 -0
  35. package/dist/utils/groupTicketCartUtils.js.map +1 -0
  36. package/dist/utils/paymentUtils.d.ts +10 -0
  37. package/dist/utils/paymentUtils.d.ts.map +1 -1
  38. package/dist/utils/paymentUtils.js +37 -1
  39. package/dist/utils/paymentUtils.js.map +1 -1
  40. package/dist/utils/ticketListUtils.d.ts.map +1 -1
  41. package/dist/utils/ticketListUtils.js +15 -3
  42. package/dist/utils/ticketListUtils.js.map +1 -1
  43. package/package.json +1 -1
  44. package/prisma/migrations/competition-prize-catalog-entry-tier.sql +39 -0
  45. package/prisma/schema.prisma +90 -7
  46. package/src/__tests__/groupTicketUtils.test.ts +53 -0
  47. package/src/competitionIdeas.ts +429 -0
  48. package/src/competitionValidation.ts +42 -0
  49. package/src/definitions.ts +5 -0
  50. package/src/extendedSchemas.ts +47 -0
  51. package/src/groupTicketUtils.ts +101 -0
  52. package/src/index.ts +4 -0
  53. package/src/utils/__tests__/paymentUtils.test.ts +19 -0
  54. package/src/utils/__tests__/ticketListUtils.test.ts +12 -0
  55. package/src/utils/groupTicketCartUtils.ts +36 -0
  56. package/src/utils/paymentUtils.ts +42 -1
  57. package/src/utils/ticketListUtils.ts +19 -5
@@ -65,7 +65,10 @@ export function ticketListToString(ticketList) {
65
65
  dateTimeStr = dateTime.toISO() || dateTimeStr;
66
66
  }
67
67
  }
68
- ticketArgs.push(`${ticketNumAndDates.numberOfTickets}${URL_PARAMS_TICKETS_DATE_DELIM}${dateTimeStr}`);
68
+ ticketArgs.push(`${ticketNumAndDates.numberOfTickets}${URL_PARAMS_TICKETS_DATE_DELIM}${dateTimeStr}${ticketNumAndDates.unitPriceCents != null &&
69
+ ticketNumAndDates.unitPriceCents > 0
70
+ ? `${URL_PARAMS_TICKETS_DATE_DELIM}${ticketNumAndDates.unitPriceCents}`
71
+ : ""}`);
69
72
  }
70
73
  }
71
74
  // Only include this tier if we found at least one ticket > 0
@@ -114,16 +117,25 @@ export function ticketListStrToTicketList(ticketListStr) {
114
117
  .split(URL_PARAMS_NUMBER_OF_TICKETS_TICKETS_DATE_DELIM)
115
118
  .filter((ticketNumAndDateStr) => !!ticketNumAndDateStr);
116
119
  for (const ticketNumAndDateStr of ticketNumAndDates) {
117
- // [numberOfTickets];;[date]
118
- const [numberOfTickets, ticketDateTimeStr] = ticketNumAndDateStr.split(URL_PARAMS_TICKETS_DATE_DELIM);
120
+ // [numberOfTickets];;[date];;[unitPriceCents?]
121
+ const segments = ticketNumAndDateStr.split(URL_PARAMS_TICKETS_DATE_DELIM);
122
+ const numberOfTickets = segments[0];
123
+ const ticketDateTimeStr = segments[1];
124
+ const unitPriceCentsRaw = segments[2];
119
125
  const ticketDateTime = DateTime.fromISO(ticketDateTimeStr);
120
126
  let ticketDateTimeFormattedStr = undefined;
121
127
  if (ticketDateTime.isValid) {
122
128
  ticketDateTimeFormattedStr = ticketDateTime.toISO() ?? undefined;
123
129
  }
130
+ const unitPriceCents = unitPriceCentsRaw != null && unitPriceCentsRaw !== ""
131
+ ? parseInt(unitPriceCentsRaw, 10)
132
+ : undefined;
124
133
  ticketNumAndDatesArr.push({
125
134
  numberOfTickets: parseInt(numberOfTickets),
126
135
  ticketDateTime: ticketDateTimeFormattedStr,
136
+ ...(unitPriceCents != null && !Number.isNaN(unitPriceCents)
137
+ ? { unitPriceCents }
138
+ : {}),
127
139
  });
128
140
  }
129
141
  ticketList.set(ticketTierId, ticketNumAndDatesArr);
@@ -1 +1 @@
1
- {"version":3,"file":"ticketListUtils.js","sourceRoot":"","sources":["../../src/utils/ticketListUtils.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ticketListUtils.js","sourceRoot":"","sources":["../../src/utils/ticketListUtils.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bash-app/bash-common",
3
- "version": "30.275.0",
3
+ "version": "30.276.0",
4
4
  "description": "Common data and scripts to use on the frontend and backend",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -0,0 +1,39 @@
1
+ -- Competition prize catalog + entry ticket tier link
2
+ -- Safe additive migration — preserves all data
3
+ BEGIN;
4
+
5
+ -- Prize catalog fields
6
+ ALTER TABLE "Prize" ADD COLUMN IF NOT EXISTS "sponsorLabel" TEXT;
7
+ ALTER TABLE "Prize" ADD COLUMN IF NOT EXISTS "imageUrl" TEXT;
8
+
9
+ -- Competition entry ticket tier + host promotions acknowledgment
10
+ ALTER TABLE "Competition" ADD COLUMN IF NOT EXISTS "entryTicketTierId" TEXT;
11
+ ALTER TABLE "Competition" ADD COLUMN IF NOT EXISTS "hostPromotionsAckAt" TIMESTAMP(3);
12
+
13
+ DO $$
14
+ BEGIN
15
+ IF NOT EXISTS (
16
+ SELECT 1 FROM pg_constraint WHERE conname = 'Competition_entryTicketTierId_key'
17
+ ) THEN
18
+ ALTER TABLE "Competition"
19
+ ADD CONSTRAINT "Competition_entryTicketTierId_key" UNIQUE ("entryTicketTierId");
20
+ END IF;
21
+ END $$;
22
+
23
+ DO $$
24
+ BEGIN
25
+ IF NOT EXISTS (
26
+ SELECT 1 FROM pg_constraint WHERE conname = 'Competition_entryTicketTierId_fkey'
27
+ ) THEN
28
+ ALTER TABLE "Competition"
29
+ ADD CONSTRAINT "Competition_entryTicketTierId_fkey"
30
+ FOREIGN KEY ("entryTicketTierId") REFERENCES "TicketTier"("id")
31
+ ON DELETE SET NULL ON UPDATE CASCADE;
32
+ END IF;
33
+ END $$;
34
+
35
+ COMMIT;
36
+
37
+ -- Verification
38
+ -- SELECT column_name FROM information_schema.columns WHERE table_name = 'Prize' AND column_name IN ('sponsorLabel', 'imageUrl');
39
+ -- SELECT column_name FROM information_schema.columns WHERE table_name = 'Competition' AND column_name IN ('entryTicketTierId', 'hostPromotionsAckAt');
@@ -239,12 +239,25 @@ model Competition {
239
239
  bracketData Json? // Store bracket structure/metadata
240
240
  bracketVisible Boolean @default(true)
241
241
 
242
+ /// Optional ticket tier required for competition entry (participation fee / game entry)
243
+ entryTicketTierId String? @unique
244
+ entryTicketTier TicketTier? @relation("CompetitionEntryTicketTier", fields: [entryTicketTierId], references: [id], onDelete: SetNull)
245
+ /// When the host acknowledged contests/promotions Terms at setup
246
+ hostPromotionsAckAt DateTime?
247
+ /// Minimum event donation (cents) that qualifies for game entry when no linked tier (or OR with tier).
248
+ entryMinDonationCents Int?
249
+ /// Optional fundraising goal for public progress display (participation revenue + donations).
250
+ fundraiserGoalCents Int?
251
+ /// Host accepts inbound prize contributions from users/businesses.
252
+ seekingPrizes Boolean @default(false)
253
+
242
254
  createdAt DateTime @default(now())
243
255
  updatedAt DateTime @updatedAt
244
256
  bashEvent BashEvent @relation(fields: [bashEventId], references: [id], onDelete: Cascade)
245
257
  owner User @relation(fields: [userId], references: [id], onDelete: Cascade)
246
258
  sponsor CompetitionSponsor[]
247
259
  prizes Prize[]
260
+ prizeOffers CompetitionPrizeOffer[]
248
261
  participants CompetitionParticipant[]
249
262
  votes CompetitionVote[]
250
263
  matches CompetitionMatch[]
@@ -289,13 +302,46 @@ model CompetitionJudgeScore {
289
302
  }
290
303
 
291
304
  model CompetitionSponsor {
292
- id String @id @default(cuid())
293
- competitionId String
294
- userId String
295
- description String
296
- paidOn String?
297
- competition Competition @relation(fields: [competitionId], references: [id], onDelete: Cascade)
298
- sponsor User @relation(fields: [userId], references: [id], onDelete: Cascade)
305
+ id String @id @default(cuid())
306
+ competitionId String
307
+ userId String?
308
+ /// Optional link to a Sponsor marketplace service for discovery/branding
309
+ sourceServiceId String?
310
+ /// Display name when sponsor is not a platform user
311
+ sponsorName String?
312
+ logoUrl String?
313
+ description String?
314
+ paidOn String?
315
+ competition Competition @relation(fields: [competitionId], references: [id], onDelete: Cascade)
316
+ sponsor User? @relation(fields: [userId], references: [id], onDelete: Cascade)
317
+ sourceService Service? @relation("CompetitionSponsorSourceService", fields: [sourceServiceId], references: [id], onDelete: SetNull)
318
+
319
+ @@index([sourceServiceId])
320
+ }
321
+
322
+ /// Inbound prize contribution proposal (Bash matchmaker — host accepts → Prize row).
323
+ model CompetitionPrizeOffer {
324
+ id String @id @default(cuid())
325
+ competitionId String
326
+ offeredByUserId String
327
+ status CompetitionPrizeOfferStatus @default(PENDING)
328
+ name String
329
+ description String @db.Text
330
+ imageUrl String?
331
+ sponsorLabel String?
332
+ sourceServiceId String?
333
+ sourceSku String?
334
+ hostNote String?
335
+ createdAt DateTime @default(now())
336
+ updatedAt DateTime @updatedAt
337
+ respondedAt DateTime?
338
+ competition Competition @relation(fields: [competitionId], references: [id], onDelete: Cascade)
339
+ offeredBy User @relation("CompetitionPrizeOffersSubmitted", fields: [offeredByUserId], references: [id], onDelete: Cascade)
340
+ sourceService Service? @relation("CompetitionPrizeOfferSourceService", fields: [sourceServiceId], references: [id], onDelete: SetNull)
341
+
342
+ @@index([competitionId])
343
+ @@index([offeredByUserId])
344
+ @@index([status])
299
345
  }
300
346
 
301
347
  model CompetitionParticipant {
@@ -2034,8 +2080,13 @@ model TicketTier {
2034
2080
  bashPassEligible Boolean @default(false)
2035
2081
  /// Max BashPass redemptions for this tier (null = unlimited within tier capacity).
2036
2082
  bashPassMaxRedemptions Int?
2083
+ /// One checkout buys a fixed package (e.g. table); price is package total, not per-person.
2084
+ isGroupTicket Boolean @default(false)
2085
+ /// Headcount included per package when isGroupTicket (e.g. 6). Required when isGroupTicket.
2086
+ groupTicketSeatCount Int?
2037
2087
  ticketGiftGrants TicketGiftGrant[]
2038
2088
  tierReleaseReminders TierReleaseReminder[]
2089
+ entryCompetition Competition? @relation("CompetitionEntryTicketTier")
2039
2090
 
2040
2091
  @@unique([bashEventId, title])
2041
2092
  @@index([availableAt])
@@ -2113,6 +2164,8 @@ model Ticket {
2113
2164
  waitlistUserId String?
2114
2165
  /// Rotated when ticket is transferred; QR payload must match for check-in (null = legacy tickets, no strict check).
2115
2166
  qrToken String?
2167
+ /// Actual unit price paid at checkout in cents (PWYC tiers; null = use tier.price for legacy rows).
2168
+ paidUnitPriceCents Int?
2116
2169
 
2117
2170
  /// P2P Venmo/Zelle off-platform payment flow
2118
2171
  p2pPaymentMethod String?
@@ -2470,6 +2523,8 @@ model Prize {
2470
2523
  prizeType PrizeType
2471
2524
  name String // Prize name (e.g., "$100 Cash", "Backpack")
2472
2525
  placeName String? // Display name (e.g., "1st Place", "Winner")
2526
+ sponsorLabel String? // e.g. "Contributed by Acme Co"
2527
+ imageUrl String? // Optional prize photo
2473
2528
  prizeLevel Int
2474
2529
  description String
2475
2530
  competitionId String?
@@ -2477,6 +2532,16 @@ model Prize {
2477
2532
  winnerUserId String?
2478
2533
  wonAt DateTime? // When the prize was awarded
2479
2534
  claimedAt DateTime? // When the prize was claimed
2535
+ /// Platform user who donated this prize (optional)
2536
+ contributorUserId String?
2537
+ /// Sponsor marketplace service the prize was picked from (optional)
2538
+ sourceServiceId String?
2539
+ sourceSku String?
2540
+ /// Contributor marked their in-kind commitment fulfilled (off-platform delivery via host)
2541
+ contributorFulfilledAt DateTime?
2542
+ contributorFulfilledNote String?
2543
+ /// Host marked prize handed to winner
2544
+ hostDeliveredAt DateTime?
2480
2545
 
2481
2546
  // Automatic payment fields
2482
2547
  autoPayEnabled Boolean @default(false)
@@ -2497,10 +2562,14 @@ model Prize {
2497
2562
 
2498
2563
  competition Competition? @relation(fields: [competitionId], references: [id], onDelete: Cascade)
2499
2564
  winner User? @relation(fields: [winnerUserId], references: [id], onDelete: Cascade)
2565
+ contributor User? @relation("PrizeContributor", fields: [contributorUserId], references: [id], onDelete: SetNull)
2566
+ sourceService Service? @relation("PrizeSourceService", fields: [sourceServiceId], references: [id], onDelete: SetNull)
2500
2567
  bashPointsTransaction BashCreditTransaction? @relation(fields: [bashPointsTransactionId], references: [id], onDelete: SetNull)
2501
2568
 
2502
2569
  @@index([competitionId])
2503
2570
  @@index([winnerUserId]) // For fetching user's wins
2571
+ @@index([contributorUserId])
2572
+ @@index([sourceServiceId])
2504
2573
  @@index([bashPointsTransactionId])
2505
2574
  }
2506
2575
 
@@ -2819,6 +2888,8 @@ model User {
2819
2888
  clubMembers ClubMember[]
2820
2889
  competitions Competition[]
2821
2890
  competitionSponsorships CompetitionSponsor[]
2891
+ competitionPrizeOffersSubmitted CompetitionPrizeOffer[] @relation("CompetitionPrizeOffersSubmitted")
2892
+ prizesContributed Prize[] @relation("PrizeContributor")
2822
2893
  competitionParticipations CompetitionParticipant[]
2823
2894
  competitionVotes CompetitionVote[]
2824
2895
  competitionJudgeAssignments CompetitionJudgeAssignment[] @relation("CompetitionJudgeAssignments")
@@ -3555,6 +3626,9 @@ model Service {
3555
3626
  promotionBlastTemplates PromotionBlastTemplate[]
3556
3627
  promotionBlastEntitlements PromotionBlastEntitlement[]
3557
3628
  promotionBlasts PromotionBlast[]
3629
+ competitionPrizesSourced Prize[] @relation("PrizeSourceService")
3630
+ competitionSponsorCredits CompetitionSponsor[] @relation("CompetitionSponsorSourceService")
3631
+ competitionPrizeOffersSourced CompetitionPrizeOffer[] @relation("CompetitionPrizeOfferSourceService")
3558
3632
 
3559
3633
  @@index([serviceListingStripeSubscriptionId])
3560
3634
  @@index([paymentAccountId])
@@ -6108,6 +6182,13 @@ enum PrizePaymentMethod {
6108
6182
  Manual
6109
6183
  }
6110
6184
 
6185
+ enum CompetitionPrizeOfferStatus {
6186
+ PENDING
6187
+ ACCEPTED
6188
+ DECLINED
6189
+ WITHDRAWN
6190
+ }
6191
+
6111
6192
  enum PrizePaymentStatus {
6112
6193
  Pending
6113
6194
  AwaitingPayment
@@ -9171,6 +9252,8 @@ model GroupMember {
9171
9252
  userId String
9172
9253
  status GroupMemberStatus @default(Invited)
9173
9254
  ticketId String? // Set when status = Going
9255
+ /// Group leader marked this member as having reimbursed their share off-platform (Venmo, etc.)
9256
+ reimbursedLeaderAt DateTime?
9174
9257
  joinedAt DateTime @default(now())
9175
9258
 
9176
9259
  group EventGroup @relation(fields: [groupId], references: [id], onDelete: Cascade)
@@ -0,0 +1,53 @@
1
+ import {
2
+ formatGroupPackagePerPersonUsd,
3
+ groupPackageShareCents,
4
+ isGroupTicketTier,
5
+ packagesSoldFromTicketCount,
6
+ validateGroupTicketTierInput,
7
+ } from "../groupTicketUtils.js";
8
+
9
+ describe("isGroupTicketTier", () => {
10
+ it("returns true when flag and seat count are valid", () => {
11
+ expect(
12
+ isGroupTicketTier({ isGroupTicket: true, groupTicketSeatCount: 6 })
13
+ ).toBe(true);
14
+ });
15
+
16
+ it("returns false when seat count is below minimum", () => {
17
+ expect(
18
+ isGroupTicketTier({ isGroupTicket: true, groupTicketSeatCount: 1 })
19
+ ).toBe(false);
20
+ });
21
+ });
22
+
23
+ describe("packagesSoldFromTicketCount", () => {
24
+ it("converts seat rows to package count", () => {
25
+ expect(packagesSoldFromTicketCount(12, 6)).toBe(2);
26
+ expect(packagesSoldFromTicketCount(7, 6)).toBe(2);
27
+ });
28
+ });
29
+
30
+ describe("groupPackageShareCents", () => {
31
+ it("splits package price evenly in cents", () => {
32
+ expect(groupPackageShareCents(60000, 6)).toBe(10000);
33
+ });
34
+ });
35
+
36
+ describe("formatGroupPackagePerPersonUsd", () => {
37
+ it("formats per-person USD", () => {
38
+ expect(formatGroupPackagePerPersonUsd(60000, 6)).toMatch(/\$100/);
39
+ });
40
+ });
41
+
42
+ describe("validateGroupTicketTierInput", () => {
43
+ it("rejects donation group packages", () => {
44
+ const result = validateGroupTicketTierInput({
45
+ isGroupTicket: true,
46
+ groupTicketSeatCount: 6,
47
+ isDonationTier: true,
48
+ isWaitlistTier: false,
49
+ pricingType: "USD",
50
+ });
51
+ expect(result.ok).toBe(false);
52
+ });
53
+ });