@bash-app/bash-common 30.275.0 → 30.277.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/__tests__/groupTicketUtils.test.d.ts +2 -0
- package/dist/__tests__/groupTicketUtils.test.d.ts.map +1 -0
- package/dist/__tests__/groupTicketUtils.test.js +38 -0
- package/dist/__tests__/groupTicketUtils.test.js.map +1 -0
- package/dist/competitionIdeas.d.ts +19 -0
- package/dist/competitionIdeas.d.ts.map +1 -0
- package/dist/competitionIdeas.js +405 -0
- package/dist/competitionIdeas.js.map +1 -0
- package/dist/competitionValidation.d.ts +10 -0
- package/dist/competitionValidation.d.ts.map +1 -0
- package/dist/competitionValidation.js +29 -0
- package/dist/competitionValidation.js.map +1 -0
- package/dist/definitions.d.ts +6 -0
- package/dist/definitions.d.ts.map +1 -1
- package/dist/definitions.js.map +1 -1
- package/dist/extendedSchemas.d.ts +356 -1
- package/dist/extendedSchemas.d.ts.map +1 -1
- package/dist/extendedSchemas.js +15 -0
- package/dist/extendedSchemas.js.map +1 -1
- package/dist/groupTicketUtils.d.ts +19 -0
- package/dist/groupTicketUtils.d.ts.map +1 -0
- package/dist/groupTicketUtils.js +74 -0
- package/dist/groupTicketUtils.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/utils/__tests__/paymentUtils.test.js +80 -8
- package/dist/utils/__tests__/paymentUtils.test.js.map +1 -1
- package/dist/utils/__tests__/recurrenceUtils.test.js +82 -1
- package/dist/utils/__tests__/recurrenceUtils.test.js.map +1 -1
- package/dist/utils/__tests__/ticketListUtils.test.js +10 -0
- package/dist/utils/__tests__/ticketListUtils.test.js.map +1 -1
- package/dist/utils/groupTicketCartUtils.d.ts +12 -0
- package/dist/utils/groupTicketCartUtils.d.ts.map +1 -0
- package/dist/utils/groupTicketCartUtils.js +30 -0
- package/dist/utils/groupTicketCartUtils.js.map +1 -0
- package/dist/utils/paymentUtils.d.ts +56 -0
- package/dist/utils/paymentUtils.d.ts.map +1 -1
- package/dist/utils/paymentUtils.js +114 -18
- package/dist/utils/paymentUtils.js.map +1 -1
- package/dist/utils/recurrenceUtils.d.ts +18 -0
- package/dist/utils/recurrenceUtils.d.ts.map +1 -1
- package/dist/utils/recurrenceUtils.js +70 -0
- package/dist/utils/recurrenceUtils.js.map +1 -1
- package/dist/utils/service/serviceBookingTypes.d.ts +1 -1
- package/dist/utils/service/serviceBookingTypes.d.ts.map +1 -1
- package/dist/utils/ticketListUtils.d.ts.map +1 -1
- package/dist/utils/ticketListUtils.js +15 -3
- package/dist/utils/ticketListUtils.js.map +1 -1
- package/package.json +1 -1
- package/prisma/migrations/competition-prize-catalog-entry-tier.sql +39 -0
- package/prisma/schema.prisma +118 -8
- package/src/__tests__/groupTicketUtils.test.ts +53 -0
- package/src/competitionIdeas.ts +429 -0
- package/src/competitionValidation.ts +42 -0
- package/src/definitions.ts +7 -0
- package/src/extendedSchemas.ts +52 -0
- package/src/groupTicketUtils.ts +101 -0
- package/src/index.ts +4 -0
- package/src/utils/__tests__/paymentUtils.test.ts +123 -8
- package/src/utils/__tests__/recurrenceUtils.test.ts +99 -0
- package/src/utils/__tests__/ticketListUtils.test.ts +12 -0
- package/src/utils/groupTicketCartUtils.ts +36 -0
- package/src/utils/paymentUtils.ts +165 -21
- package/src/utils/recurrenceUtils.ts +104 -0
- package/src/utils/service/serviceBookingTypes.ts +3 -0
- 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
|
|
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":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACjC,OAAO,EAEL,+CAA+C,EAC/C,4BAA4B,EAC5B,sDAAsD,EACtD,6BAA6B,GAC9B,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAEnD;;;GAGG;AACH,SAAS,mBAAmB,CAAC,GAAW;IACtC,IAAI,OAAO,MAAM,KAAK,WAAW,EAAE,CAAC;QAClC,sBAAsB;QACtB,OAAO,IAAI,CAAC,GAAG,CAAC;aACb,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC;aACnB,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC;aACnB,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;IACvB,CAAC;SAAM,CAAC;QACN,mBAAmB;QACnB,OAAO,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC;aACpB,QAAQ,CAAC,QAAQ,CAAC;aAClB,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC;aACnB,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC;aACnB,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;IACvB,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,SAAS,mBAAmB,CAAC,GAAW;IACtC,mBAAmB;IACnB,IAAI,MAAM,GAAG,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IACvD,OAAO,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACzB,MAAM,IAAI,GAAG,CAAC;IAChB,CAAC;IAED,IAAI,OAAO,MAAM,KAAK,WAAW,EAAE,CAAC;QAClC,sBAAsB;QACtB,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC;IACtB,CAAC;SAAM,CAAC;QACN,mBAAmB;QACnB,OAAO,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,QAAQ,EAAE,CAAC;IAClD,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,kBAAkB,CAChC,UAAiD;IAEjD,MAAM,aAAa,GAAa,EAAE,CAAC;IAEnC,KAAK,MAAM,CAAC,YAAY,EAAE,cAAc,CAAC,IAAI,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC;QAClE,MAAM,UAAU,GAAa;YAC3B,GAAG,YAAY,GAAG,sDAAsD,EAAE;SAC3E,CAAC;QACF,IAAI,aAAa,GAAG,KAAK,CAAC,CAAC,oDAAoD;QAE/E,KAAK,MAAM,iBAAiB,IAAI,cAAc,EAAE,CAAC;YAC/C,IAAI,iBAAiB,CAAC,eAAe,GAAG,CAAC,EAAE,CAAC;gBAC1C,aAAa,GAAG,IAAI,CAAC;gBAErB,oDAAoD;gBACpD,IAAI,WAAW,GAAG,iBAAiB,CAAC,cAAc,CAAC;gBACnD,IAAI,WAAW,EAAE,CAAC;oBAChB,2EAA2E;oBAC3E,MAAM,QAAQ,GAAG,gBAAgB,CAAC,WAAW,CAAC,CAAC;oBAC/C,IAAI,QAAQ,CAAC,OAAO,EAAE,CAAC;wBACrB,WAAW,GAAG,QAAQ,CAAC,KAAK,EAAE,IAAI,WAAW,CAAC;oBAChD,CAAC;gBACH,CAAC;gBAED,UAAU,CAAC,IAAI,CACb,GAAG,iBAAiB,CAAC,eAAe,GAAG,6BAA6B,GAAG,WAAW,EAAE,
|
|
1
|
+
{"version":3,"file":"ticketListUtils.js","sourceRoot":"","sources":["../../src/utils/ticketListUtils.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -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');
|
package/prisma/schema.prisma
CHANGED
|
@@ -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
|
|
293
|
-
competitionId
|
|
294
|
-
userId
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
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 {
|
|
@@ -658,6 +704,8 @@ model BashEvent {
|
|
|
658
704
|
country String?
|
|
659
705
|
/// When true, street/place/full location and map pin are hidden until public reveal or gated audience.
|
|
660
706
|
hideLocation Boolean @default(false)
|
|
707
|
+
/// When false, the map is hidden on the bash detail page (address link may still show).
|
|
708
|
+
showMap Boolean @default(true)
|
|
661
709
|
/// Freeform area hint shown to everyone when hideLocation (e.g. "Lower East Side").
|
|
662
710
|
publicAreaHint String?
|
|
663
711
|
locationRevealAudience LocationRevealAudience @default(TicketHolders)
|
|
@@ -687,7 +735,7 @@ model BashEvent {
|
|
|
687
735
|
allowDonations Boolean? @default(false)
|
|
688
736
|
suggestedDonationAmount Int?
|
|
689
737
|
donationDetails String?
|
|
690
|
-
absorbDonationFees Boolean @default(
|
|
738
|
+
absorbDonationFees Boolean @default(true)
|
|
691
739
|
absorbTicketFees Boolean @default(false)
|
|
692
740
|
/// Phase 1 of unified-pricing roadmap: governs where PER_BASHPOINTS_ATTENDEE
|
|
693
741
|
/// settlements are paid from. `HostWallet` (default) pays directly from the
|
|
@@ -2034,8 +2082,13 @@ model TicketTier {
|
|
|
2034
2082
|
bashPassEligible Boolean @default(false)
|
|
2035
2083
|
/// Max BashPass redemptions for this tier (null = unlimited within tier capacity).
|
|
2036
2084
|
bashPassMaxRedemptions Int?
|
|
2085
|
+
/// One checkout buys a fixed package (e.g. table); price is package total, not per-person.
|
|
2086
|
+
isGroupTicket Boolean @default(false)
|
|
2087
|
+
/// Headcount included per package when isGroupTicket (e.g. 6). Required when isGroupTicket.
|
|
2088
|
+
groupTicketSeatCount Int?
|
|
2037
2089
|
ticketGiftGrants TicketGiftGrant[]
|
|
2038
2090
|
tierReleaseReminders TierReleaseReminder[]
|
|
2091
|
+
entryCompetition Competition? @relation("CompetitionEntryTicketTier")
|
|
2039
2092
|
|
|
2040
2093
|
@@unique([bashEventId, title])
|
|
2041
2094
|
@@index([availableAt])
|
|
@@ -2113,6 +2166,8 @@ model Ticket {
|
|
|
2113
2166
|
waitlistUserId String?
|
|
2114
2167
|
/// Rotated when ticket is transferred; QR payload must match for check-in (null = legacy tickets, no strict check).
|
|
2115
2168
|
qrToken String?
|
|
2169
|
+
/// Actual unit price paid at checkout in cents (PWYC tiers; null = use tier.price for legacy rows).
|
|
2170
|
+
paidUnitPriceCents Int?
|
|
2116
2171
|
|
|
2117
2172
|
/// P2P Venmo/Zelle off-platform payment flow
|
|
2118
2173
|
p2pPaymentMethod String?
|
|
@@ -2286,6 +2341,11 @@ model Recurrence {
|
|
|
2286
2341
|
repeatOnDays DayOfWeek[]
|
|
2287
2342
|
repeatOnDayOfMonth Int?
|
|
2288
2343
|
repeatYearlyDate DateTime?
|
|
2344
|
+
// Per-occurrence exceptions for the computed series (no occurrence rows are materialized):
|
|
2345
|
+
// dates the host removed from the series (matched against the generated occurrence start instants).
|
|
2346
|
+
excludedDates DateTime[]
|
|
2347
|
+
// Per-occurrence date/time moves: JSON map of original-occurrence ISO start -> { startDateTime, endDateTime? }.
|
|
2348
|
+
occurrenceOverrides Json?
|
|
2289
2349
|
createdAt DateTime @default(now())
|
|
2290
2350
|
updatedAt DateTime @updatedAt
|
|
2291
2351
|
bashEvent BashEvent @relation(fields: [bashEventId], references: [id], onDelete: Cascade)
|
|
@@ -2470,6 +2530,8 @@ model Prize {
|
|
|
2470
2530
|
prizeType PrizeType
|
|
2471
2531
|
name String // Prize name (e.g., "$100 Cash", "Backpack")
|
|
2472
2532
|
placeName String? // Display name (e.g., "1st Place", "Winner")
|
|
2533
|
+
sponsorLabel String? // e.g. "Contributed by Acme Co"
|
|
2534
|
+
imageUrl String? // Optional prize photo
|
|
2473
2535
|
prizeLevel Int
|
|
2474
2536
|
description String
|
|
2475
2537
|
competitionId String?
|
|
@@ -2477,6 +2539,16 @@ model Prize {
|
|
|
2477
2539
|
winnerUserId String?
|
|
2478
2540
|
wonAt DateTime? // When the prize was awarded
|
|
2479
2541
|
claimedAt DateTime? // When the prize was claimed
|
|
2542
|
+
/// Platform user who donated this prize (optional)
|
|
2543
|
+
contributorUserId String?
|
|
2544
|
+
/// Sponsor marketplace service the prize was picked from (optional)
|
|
2545
|
+
sourceServiceId String?
|
|
2546
|
+
sourceSku String?
|
|
2547
|
+
/// Contributor marked their in-kind commitment fulfilled (off-platform delivery via host)
|
|
2548
|
+
contributorFulfilledAt DateTime?
|
|
2549
|
+
contributorFulfilledNote String?
|
|
2550
|
+
/// Host marked prize handed to winner
|
|
2551
|
+
hostDeliveredAt DateTime?
|
|
2480
2552
|
|
|
2481
2553
|
// Automatic payment fields
|
|
2482
2554
|
autoPayEnabled Boolean @default(false)
|
|
@@ -2497,10 +2569,14 @@ model Prize {
|
|
|
2497
2569
|
|
|
2498
2570
|
competition Competition? @relation(fields: [competitionId], references: [id], onDelete: Cascade)
|
|
2499
2571
|
winner User? @relation(fields: [winnerUserId], references: [id], onDelete: Cascade)
|
|
2572
|
+
contributor User? @relation("PrizeContributor", fields: [contributorUserId], references: [id], onDelete: SetNull)
|
|
2573
|
+
sourceService Service? @relation("PrizeSourceService", fields: [sourceServiceId], references: [id], onDelete: SetNull)
|
|
2500
2574
|
bashPointsTransaction BashCreditTransaction? @relation(fields: [bashPointsTransactionId], references: [id], onDelete: SetNull)
|
|
2501
2575
|
|
|
2502
2576
|
@@index([competitionId])
|
|
2503
2577
|
@@index([winnerUserId]) // For fetching user's wins
|
|
2578
|
+
@@index([contributorUserId])
|
|
2579
|
+
@@index([sourceServiceId])
|
|
2504
2580
|
@@index([bashPointsTransactionId])
|
|
2505
2581
|
}
|
|
2506
2582
|
|
|
@@ -2601,6 +2677,8 @@ model User {
|
|
|
2601
2677
|
/// Preferred processor for dual-rail onboarding (optional; legacy Stripe fields remain source of truth until fully migrated).
|
|
2602
2678
|
paymentProvider PaymentProvider @default(STRIPE)
|
|
2603
2679
|
isSuperUser Boolean @default(false)
|
|
2680
|
+
/// Enterprise: super-users may set event feeHandling to GuestPays/Split for this host.
|
|
2681
|
+
allowGuestFeePassThrough Boolean @default(false)
|
|
2604
2682
|
isSuspended Boolean @default(false)
|
|
2605
2683
|
intent UserIntent?
|
|
2606
2684
|
signupSource String? // e.g. 'jamwith', 'mixlog', 'organic' for attribution
|
|
@@ -2819,6 +2897,8 @@ model User {
|
|
|
2819
2897
|
clubMembers ClubMember[]
|
|
2820
2898
|
competitions Competition[]
|
|
2821
2899
|
competitionSponsorships CompetitionSponsor[]
|
|
2900
|
+
competitionPrizeOffersSubmitted CompetitionPrizeOffer[] @relation("CompetitionPrizeOffersSubmitted")
|
|
2901
|
+
prizesContributed Prize[] @relation("PrizeContributor")
|
|
2822
2902
|
competitionParticipations CompetitionParticipant[]
|
|
2823
2903
|
competitionVotes CompetitionVote[]
|
|
2824
2904
|
competitionJudgeAssignments CompetitionJudgeAssignment[] @relation("CompetitionJudgeAssignments")
|
|
@@ -3084,6 +3164,8 @@ model UserPreferences {
|
|
|
3084
3164
|
autoDetectLocation Boolean @default(false)
|
|
3085
3165
|
recentSearches String[] @default([])
|
|
3086
3166
|
expandedSections String[] @default([])
|
|
3167
|
+
/// Homepage event category rows pinned to the top of Upcoming Events (bashType keys)
|
|
3168
|
+
pinnedHomepageSections String[] @default([])
|
|
3087
3169
|
preferredCurrency String @default("USD")
|
|
3088
3170
|
savePaymentInfo Boolean @default(false)
|
|
3089
3171
|
showEventPrices Boolean @default(true)
|
|
@@ -3555,6 +3637,9 @@ model Service {
|
|
|
3555
3637
|
promotionBlastTemplates PromotionBlastTemplate[]
|
|
3556
3638
|
promotionBlastEntitlements PromotionBlastEntitlement[]
|
|
3557
3639
|
promotionBlasts PromotionBlast[]
|
|
3640
|
+
competitionPrizesSourced Prize[] @relation("PrizeSourceService")
|
|
3641
|
+
competitionSponsorCredits CompetitionSponsor[] @relation("CompetitionSponsorSourceService")
|
|
3642
|
+
competitionPrizeOffersSourced CompetitionPrizeOffer[] @relation("CompetitionPrizeOfferSourceService")
|
|
3558
3643
|
|
|
3559
3644
|
@@index([serviceListingStripeSubscriptionId])
|
|
3560
3645
|
@@index([paymentAccountId])
|
|
@@ -4947,6 +5032,14 @@ model ServiceBooking {
|
|
|
4947
5032
|
settlementDisputedAt DateTime?
|
|
4948
5033
|
// When the delta refund actually lands at the issuing bank.
|
|
4949
5034
|
refundedOn DateTime?
|
|
5035
|
+
// Host-initiated reschedule: when the bash date/time changes we sync the booked
|
|
5036
|
+
// days to the new date (assume-accept) and ask the provider to confirm or reject.
|
|
5037
|
+
// Reject cancels the booking with a full host refund; silence keeps the new date.
|
|
5038
|
+
rescheduleStatus ServiceBookingRescheduleStatus @default(None)
|
|
5039
|
+
rescheduleRequestedOn DateTime?
|
|
5040
|
+
rescheduleDecisionOn DateTime?
|
|
5041
|
+
reschedulePrevStartDate DateTime?
|
|
5042
|
+
reschedulePrevEndDate DateTime?
|
|
4950
5043
|
notification Notification[]
|
|
4951
5044
|
bashEvent BashEvent? @relation(fields: [bashEventId], references: [id])
|
|
4952
5045
|
creator User @relation("BookingCreator", fields: [creatorId], references: [id])
|
|
@@ -6108,6 +6201,13 @@ enum PrizePaymentMethod {
|
|
|
6108
6201
|
Manual
|
|
6109
6202
|
}
|
|
6110
6203
|
|
|
6204
|
+
enum CompetitionPrizeOfferStatus {
|
|
6205
|
+
PENDING
|
|
6206
|
+
ACCEPTED
|
|
6207
|
+
DECLINED
|
|
6208
|
+
WITHDRAWN
|
|
6209
|
+
}
|
|
6210
|
+
|
|
6111
6211
|
enum PrizePaymentStatus {
|
|
6112
6212
|
Pending
|
|
6113
6213
|
AwaitingPayment
|
|
@@ -7470,6 +7570,14 @@ enum ServiceBookingStatus {
|
|
|
7470
7570
|
Canceled
|
|
7471
7571
|
}
|
|
7472
7572
|
|
|
7573
|
+
// Provider's response to a host-initiated bash date change.
|
|
7574
|
+
enum ServiceBookingRescheduleStatus {
|
|
7575
|
+
None
|
|
7576
|
+
Pending
|
|
7577
|
+
Accepted
|
|
7578
|
+
Rejected
|
|
7579
|
+
}
|
|
7580
|
+
|
|
7473
7581
|
enum ServiceBookingType {
|
|
7474
7582
|
Request
|
|
7475
7583
|
Instant
|
|
@@ -9171,6 +9279,8 @@ model GroupMember {
|
|
|
9171
9279
|
userId String
|
|
9172
9280
|
status GroupMemberStatus @default(Invited)
|
|
9173
9281
|
ticketId String? // Set when status = Going
|
|
9282
|
+
/// Group leader marked this member as having reimbursed their share off-platform (Venmo, etc.)
|
|
9283
|
+
reimbursedLeaderAt DateTime?
|
|
9174
9284
|
joinedAt DateTime @default(now())
|
|
9175
9285
|
|
|
9176
9286
|
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
|
+
});
|