@bash-app/bash-common 30.314.0 → 30.318.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 (79) hide show
  1. package/dist/__tests__/appleIapProducts.test.d.ts +2 -0
  2. package/dist/__tests__/appleIapProducts.test.d.ts.map +1 -0
  3. package/dist/__tests__/appleIapProducts.test.js +32 -0
  4. package/dist/__tests__/appleIapProducts.test.js.map +1 -0
  5. package/dist/__tests__/hostCrmGrowthPack.test.d.ts +2 -0
  6. package/dist/__tests__/hostCrmGrowthPack.test.d.ts.map +1 -0
  7. package/dist/__tests__/hostCrmGrowthPack.test.js +25 -0
  8. package/dist/__tests__/hostCrmGrowthPack.test.js.map +1 -0
  9. package/dist/__tests__/hostCrmSegments.test.d.ts +2 -0
  10. package/dist/__tests__/hostCrmSegments.test.d.ts.map +1 -0
  11. package/dist/__tests__/hostCrmSegments.test.js +198 -0
  12. package/dist/__tests__/hostCrmSegments.test.js.map +1 -0
  13. package/dist/__tests__/relationshipHealth.test.d.ts +2 -0
  14. package/dist/__tests__/relationshipHealth.test.d.ts.map +1 -0
  15. package/dist/__tests__/relationshipHealth.test.js +265 -0
  16. package/dist/__tests__/relationshipHealth.test.js.map +1 -0
  17. package/dist/appleIapProducts.d.ts +64 -0
  18. package/dist/appleIapProducts.d.ts.map +1 -0
  19. package/dist/appleIapProducts.js +113 -0
  20. package/dist/appleIapProducts.js.map +1 -0
  21. package/dist/definitions.d.ts +3 -1
  22. package/dist/definitions.d.ts.map +1 -1
  23. package/dist/definitions.js +2 -0
  24. package/dist/definitions.js.map +1 -1
  25. package/dist/extendedSchemas.d.ts +27 -0
  26. package/dist/extendedSchemas.d.ts.map +1 -1
  27. package/dist/extendedSchemas.js.map +1 -1
  28. package/dist/hostCrmAutomation.d.ts +89 -0
  29. package/dist/hostCrmAutomation.d.ts.map +1 -0
  30. package/dist/hostCrmAutomation.js +50 -0
  31. package/dist/hostCrmAutomation.js.map +1 -0
  32. package/dist/hostCrmInsights.d.ts +39 -0
  33. package/dist/hostCrmInsights.d.ts.map +1 -0
  34. package/dist/hostCrmInsights.js +2 -0
  35. package/dist/hostCrmInsights.js.map +1 -0
  36. package/dist/hostCrmSegments.d.ts +82 -2
  37. package/dist/hostCrmSegments.d.ts.map +1 -1
  38. package/dist/hostCrmSegments.js +93 -3
  39. package/dist/hostCrmSegments.js.map +1 -1
  40. package/dist/index.d.ts +4 -0
  41. package/dist/index.d.ts.map +1 -1
  42. package/dist/index.js +4 -0
  43. package/dist/index.js.map +1 -1
  44. package/dist/membershipDefinitions.d.ts +2 -0
  45. package/dist/membershipDefinitions.d.ts.map +1 -1
  46. package/dist/membershipDefinitions.js +3 -0
  47. package/dist/membershipDefinitions.js.map +1 -1
  48. package/dist/relationshipHealth.d.ts +28 -0
  49. package/dist/relationshipHealth.d.ts.map +1 -0
  50. package/dist/relationshipHealth.js +91 -0
  51. package/dist/relationshipHealth.js.map +1 -0
  52. package/dist/sms/smsTemplates.d.ts +13 -1
  53. package/dist/sms/smsTemplates.d.ts.map +1 -1
  54. package/dist/sms/smsTemplates.js +3 -0
  55. package/dist/sms/smsTemplates.js.map +1 -1
  56. package/dist/utils/__tests__/slugUtils.test.js +9 -1
  57. package/dist/utils/__tests__/slugUtils.test.js.map +1 -1
  58. package/dist/utils/slugUtils.d.ts +7 -0
  59. package/dist/utils/slugUtils.d.ts.map +1 -1
  60. package/dist/utils/slugUtils.js +9 -0
  61. package/dist/utils/slugUtils.js.map +1 -1
  62. package/package.json +1 -1
  63. package/prisma/schema.prisma +154 -2
  64. package/src/__tests__/appleIapProducts.test.ts +52 -0
  65. package/src/__tests__/hostCrmGrowthPack.test.ts +33 -0
  66. package/src/__tests__/hostCrmSegments.test.ts +247 -0
  67. package/src/__tests__/relationshipHealth.test.ts +370 -0
  68. package/src/appleIapProducts.ts +203 -0
  69. package/src/definitions.ts +2 -0
  70. package/src/extendedSchemas.ts +30 -1
  71. package/src/hostCrmAutomation.ts +138 -0
  72. package/src/hostCrmInsights.ts +39 -0
  73. package/src/hostCrmSegments.ts +208 -7
  74. package/src/index.ts +4 -0
  75. package/src/membershipDefinitions.ts +3 -0
  76. package/src/relationshipHealth.ts +134 -0
  77. package/src/sms/smsTemplates.ts +6 -0
  78. package/src/utils/__tests__/slugUtils.test.ts +15 -0
  79. package/src/utils/slugUtils.ts +13 -0
@@ -1 +1 @@
1
- {"version":3,"file":"slugUtils.test.js","sourceRoot":"","sources":["../../../src/utils/__tests__/slugUtils.test.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"slugUtils.test.js","sourceRoot":"","sources":["../../../src/utils/__tests__/slugUtils.test.ts"],"names":[],"mappings":"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"}
@@ -6,6 +6,13 @@ export declare function generateBashDetailUrl(bashEventId: string, slug: string)
6
6
  * With a slug: `/bash/{id}-{slug}`; without: `/bash/{id}` (legacy id-only segment).
7
7
  */
8
8
  export declare function getPublicBashDetailPath(bashEventId: string, slug: string | null | undefined): string;
9
+ /**
10
+ * Public, shareable Memories recap path for a bash — nested under the bash
11
+ * detail path so it inherits the same id/slug parsing (`/bash/{id}-{slug}/memories`).
12
+ * No-login-required by design: the whole point of Memories is that a shared
13
+ * link works for people who aren't signed in yet.
14
+ */
15
+ export declare function getPublicBashMemoriesPath(bashEventId: string, slug: string | null | undefined): string;
9
16
  /** Wizard URL with explicit step (see bash-app `/bash-event-wizard/$id/$major/$sub`). */
10
17
  export declare function getBashEventWizardStepPath(bashEventId: string, majorStep: number, subStep: number): string;
11
18
  /** Host redirect target: "How" → Payout (Stripe Connect / ticket proceeds). */
@@ -1 +1 @@
1
- {"version":3,"file":"slugUtils.d.ts","sourceRoot":"","sources":["../../src/utils/slugUtils.ts"],"names":[],"mappings":"AAQA,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAMlD;AAED,wBAAsB,kBAAkB,CACtC,KAAK,EAAE,MAAM,EACb,eAAe,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,EACvE,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,MAAM,CAAC,CAajB;AAED,wBAAgB,qBAAqB,CAAC,WAAW,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAE/E;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,CACrC,WAAW,EAAE,MAAM,EACnB,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAC9B,MAAM,CAMR;AAED,yFAAyF;AACzF,wBAAgB,0BAA0B,CACxC,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,GACd,MAAM,CAER;AAED,+EAA+E;AAC/E,wBAAgB,gCAAgC,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAM5E;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,GAAG,IAAI,CAqB5F;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAGlD"}
1
+ {"version":3,"file":"slugUtils.d.ts","sourceRoot":"","sources":["../../src/utils/slugUtils.ts"],"names":[],"mappings":"AAQA,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAMlD;AAED,wBAAsB,kBAAkB,CACtC,KAAK,EAAE,MAAM,EACb,eAAe,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,EACvE,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,MAAM,CAAC,CAajB;AAED,wBAAgB,qBAAqB,CAAC,WAAW,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAE/E;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,CACrC,WAAW,EAAE,MAAM,EACnB,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAC9B,MAAM,CAMR;AAED;;;;;GAKG;AACH,wBAAgB,yBAAyB,CACvC,WAAW,EAAE,MAAM,EACnB,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAC9B,MAAM,CAER;AAED,yFAAyF;AACzF,wBAAgB,0BAA0B,CACxC,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,GACd,MAAM,CAER;AAED,+EAA+E;AAC/E,wBAAgB,gCAAgC,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAM5E;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,GAAG,IAAI,CAqB5F;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAGlD"}
@@ -34,6 +34,15 @@ export function getPublicBashDetailPath(bashEventId, slug) {
34
34
  }
35
35
  return `${BASH_DETAIL_URL}/${bashEventId}`;
36
36
  }
37
+ /**
38
+ * Public, shareable Memories recap path for a bash — nested under the bash
39
+ * detail path so it inherits the same id/slug parsing (`/bash/{id}-{slug}/memories`).
40
+ * No-login-required by design: the whole point of Memories is that a shared
41
+ * link works for people who aren't signed in yet.
42
+ */
43
+ export function getPublicBashMemoriesPath(bashEventId, slug) {
44
+ return `${getPublicBashDetailPath(bashEventId, slug)}/memories`;
45
+ }
37
46
  /** Wizard URL with explicit step (see bash-app `/bash-event-wizard/$id/$major/$sub`). */
38
47
  export function getBashEventWizardStepPath(bashEventId, majorStep, subStep) {
39
48
  return `${BASH_EVENT_WIZARD_PATH_PREFIX}/${bashEventId}/${majorStep}/${subStep}`;
@@ -1 +1 @@
1
- {"version":3,"file":"slugUtils.js","sourceRoot":"","sources":["../../src/utils/slugUtils.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,SAAS,CAAC;AAC9B,OAAO,EACL,eAAe,EACf,gCAAgC,EAChC,oCAAoC,EACpC,6BAA6B,GAC9B,MAAM,mBAAmB,CAAC;AAE3B,MAAM,UAAU,YAAY,CAAC,KAAa;IACxC,OAAO,OAAO,CAAC,KAAK,EAAE;QACpB,KAAK,EAAE,IAAI;QACX,MAAM,EAAE,IAAI;QACZ,MAAM,EAAE,gBAAgB;KACzB,CAAC,CAAC;AACL,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,KAAa,EACb,eAAuE,EACvE,SAAkB;IAElB,MAAM,QAAQ,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC;IACrC,IAAI,IAAI,GAAG,QAAQ,CAAC;IACpB,IAAI,OAAO,GAAG,CAAC,CAAC;IAEhB,OAAO,IAAI,EAAE,CAAC;QACZ,MAAM,MAAM,GAAG,MAAM,eAAe,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;QACtD,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,OAAO,IAAI,CAAC;QACd,CAAC;QACD,IAAI,GAAG,GAAG,QAAQ,IAAI,OAAO,EAAE,CAAC;QAChC,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED,MAAM,UAAU,qBAAqB,CAAC,WAAmB,EAAE,IAAY;IACrE,OAAO,SAAS,WAAW,IAAI,IAAI,EAAE,CAAC;AACxC,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,uBAAuB,CACrC,WAAmB,EACnB,IAA+B;IAE/B,MAAM,CAAC,GAAG,IAAI,EAAE,IAAI,EAAE,CAAC;IACvB,IAAI,CAAC,EAAE,CAAC;QACN,OAAO,qBAAqB,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC;IAC/C,CAAC;IACD,OAAO,GAAG,eAAe,IAAI,WAAW,EAAE,CAAC;AAC7C,CAAC;AAED,yFAAyF;AACzF,MAAM,UAAU,0BAA0B,CACxC,WAAmB,EACnB,SAAiB,EACjB,OAAe;IAEf,OAAO,GAAG,6BAA6B,IAAI,WAAW,IAAI,SAAS,IAAI,OAAO,EAAE,CAAC;AACnF,CAAC;AAED,+EAA+E;AAC/E,MAAM,UAAU,gCAAgC,CAAC,WAAmB;IAClE,OAAO,0BAA0B,CAC/B,WAAW,EACX,gCAAgC,EAChC,oCAAoC,CACrC,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,KAAa;IAC9C,sEAAsE;IACtE,MAAM,SAAS,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IAErC,IAAI,SAAS,KAAK,CAAC,CAAC,EAAE,CAAC;QACrB,0BAA0B;QAC1B,IAAI,KAAK,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC9B,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;QACnC,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,EAAE,GAAG,KAAK,CAAC,SAAS,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC;IACzC,MAAM,IAAI,GAAG,KAAK,CAAC,SAAS,CAAC,SAAS,GAAG,CAAC,CAAC,CAAC;IAE5C,IAAI,CAAC,EAAE,EAAE,CAAC;QACR,OAAO,IAAI,CAAC;IACd,CAAC;IAED,sBAAsB;IACtB,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,IAAI,IAAI,EAAE,CAAC;AACpC,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,IAAY;IACvC,sEAAsE;IACtE,OAAO,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACnC,CAAC"}
1
+ {"version":3,"file":"slugUtils.js","sourceRoot":"","sources":["../../src/utils/slugUtils.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.314.0",
3
+ "version": "30.318.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",
@@ -810,6 +810,17 @@ model BashEvent {
810
810
  bashPointsPayoutSource BashPointsPayoutSource @default(HostWallet)
811
811
  /// When true, attendees may request a refund from the app/email (host approves in Tickets → Refunds). When false, self-serve refund CTAs are hidden.
812
812
  allowAttendeeRefundRequests Boolean @default(true)
813
+ /// Free-text cancellation / refund policy shown at checkout and on the guest's ticket.
814
+ cancellationPolicy String?
815
+ /// When true (default), cancelling the bash auto-refunds paid ticket holders. Hosts may set false only before any ticket/RSVP exists.
816
+ refundsGuaranteedOnCancellation Boolean @default(true)
817
+ /// When true, host may postpone after tickets exist. May only flip false→true before any ticket/RSVP exists.
818
+ postponementAllowed Boolean @default(false)
819
+ /// True after the host has invoked Postpone at least once (cleared only by republish flows if desired; kept for guest banners).
820
+ isPostponed Boolean @default(false)
821
+ postponedAt DateTime?
822
+ /// Deadline for guests to keep or decline their ticket after a postponement.
823
+ postponeResponseDeadline DateTime?
813
824
  // GuestPays / Split: Stripe processing + Bash platform fee presentation (see platformFeeEnabled).
814
825
  feeHandling String @default("HostAbsorbs") // "GuestPays" | "HostAbsorbs" | "Split"
815
826
  /// When true, Bash charges platformFeeRate on ticket gross (e.g. 3%) in addition to Stripe processing pass-through.
@@ -907,7 +918,7 @@ model BashEvent {
907
918
  /// When false, included/allowed/not-allowed chips are read-only (no upvotes or suggestions)
908
919
  collaborationEnabled Boolean @default(true)
909
920
  /// Host opt-in: show icebreaker prompts on the bash detail page for guests
910
- icebreakerEnabled Boolean @default(true)
921
+ icebreakerEnabled Boolean @default(false)
911
922
  /// Optional host-authored / host-picked icebreaker prompt. When set, it is shown
912
923
  /// instead of a random canned prompt on the bash detail page.
913
924
  icebreakerPrompt String?
@@ -925,6 +936,8 @@ model BashEvent {
925
936
  aiSuggestedTasks Json?
926
937
  backgroundImage String? // Custom or curated background image URL for the bash detail page
927
938
  backgroundEffect BackgroundEffect @default(None)
939
+ /// Soft blur on theme photo backgrounds (Spotify-style). Hosts can turn off for a sharp image.
940
+ backgroundBlurEnabled Boolean @default(true)
928
941
  themeColor String? // Dominant hex color extracted from the event flyer (e.g. "#7c3aed")
929
942
  /// RSVP-gated discussion thread on bash detail
930
943
  discussionEnabled Boolean @default(true)
@@ -1924,6 +1937,8 @@ model PublicBashRsvp {
1924
1937
  /// Guest-managed plus-ones for Rsvp-mode events. Names optional; count drives capacity.
1925
1938
  plusOnesCount Int @default(0)
1926
1939
  plusOneNames String[] @default([])
1940
+ /// Set when the guest keeps or declines after a postponement; cleared on each new Postpone.
1941
+ postponeRespondedAt DateTime?
1927
1942
  createdAt DateTime @default(now())
1928
1943
  updatedAt DateTime @updatedAt
1929
1944
 
@@ -2357,6 +2372,47 @@ model EventAlbumItem {
2357
2372
  @@index([bashEventId])
2358
2373
  }
2359
2374
 
2375
+ /// Curated Memories recap for a finished bash — best few photos/badge
2376
+ /// highlights, generated once by the memories cron (see
2377
+ /// api/src/utils/memories/) rather than recomputed per view, so the "moment"
2378
+ /// a host/attendee sees on a shared link stays stable over time. `viewCount`
2379
+ /// / `shareCount` back the share-rate instrumentation required before this
2380
+ /// feature is considered proven as a growth loop.
2381
+ model BashMemories {
2382
+ id String @id @default(cuid())
2383
+ bashEventId String @unique
2384
+ /// Best few photo URLs (capped at generation time — this is a curated
2385
+ /// handful, not every photo tagged to the event).
2386
+ photoUrls String[] @default([])
2387
+ /// Curated badge/award highlights: Array<{ name, imageUrl, awardCount }>.
2388
+ badgeHighlights Json @default("[]")
2389
+ attendeeCount Int @default(0)
2390
+ generatedAt DateTime @default(now())
2391
+ notifiedAt DateTime?
2392
+ viewCount Int @default(0)
2393
+ shareCount Int @default(0)
2394
+ createdAt DateTime @default(now())
2395
+ updatedAt DateTime @updatedAt
2396
+
2397
+ @@index([bashEventId])
2398
+ }
2399
+
2400
+ /// "Tag your friends who were there" on a public Memories recap — a lightweight,
2401
+ /// event-scoped social edge (Zuck: "every tag is a new edge in the graph").
2402
+ /// Deliberately not wired into `UserFollowing` (that model's `isOrganizer` follow
2403
+ /// carries specific "notify me of new bashes" semantics a casual recap tag shouldn't imply).
2404
+ model BashMemoriesTag {
2405
+ id String @id @default(cuid())
2406
+ bashEventId String
2407
+ taggedByUserId String
2408
+ taggedUserId String
2409
+ createdAt DateTime @default(now())
2410
+
2411
+ @@unique([bashEventId, taggedByUserId, taggedUserId])
2412
+ @@index([bashEventId])
2413
+ @@index([taggedUserId])
2414
+ }
2415
+
2360
2416
  /// Post-event networking opt-in: attendees who agreed to be discoverable to others who went.
2361
2417
  model EventNetworkingOptIn {
2362
2418
  id String @id @default(cuid())
@@ -2379,12 +2435,45 @@ model HostAttendeeProfile {
2379
2435
  createdAt DateTime @default(now())
2380
2436
  updatedAt DateTime @updatedAt
2381
2437
 
2438
+ /// Relationship Health status as of the last time this host's CRM was read;
2439
+ /// compared to the freshly-computed status on each read to detect a
2440
+ /// Cooling/AtRisk transition for the host-approved win-back recommendation.
2441
+ lastHealthStatusSeen String?
2442
+ lastHealthStatusSeenAt DateTime?
2443
+
2382
2444
  host User @relation("HostAttendeeProfilesOwned", fields: [hostUserId], references: [id], onDelete: Cascade)
2383
2445
  attendee User? @relation("HostAttendeeProfilesTarget", fields: [attendeeUserId], references: [id], onDelete: SetNull)
2384
2446
 
2385
2447
  @@index([hostUserId])
2386
2448
  }
2387
2449
 
2450
+ enum HostAttendeeActivityType {
2451
+ NoteAdded
2452
+ NoteUpdated
2453
+ TagAdded
2454
+ TagRemoved
2455
+ }
2456
+
2457
+ /// Durable append-only log of host edits to an attendee's CRM profile (notes/tags).
2458
+ /// Everything else in the attendee detail-drawer timeline is read live from its
2459
+ /// existing source table (Ticket, AppliedDiscount, HostCrmEmailSendLog, SmsSendLog)
2460
+ /// rather than duplicated here — see attendeeAudienceApi.ts's `/detail` route.
2461
+ model HostAttendeeActivity {
2462
+ id String @id @default(cuid())
2463
+ hostUserId String
2464
+ attendeeUserId String?
2465
+ attendeeEmail String?
2466
+ type HostAttendeeActivityType
2467
+ detail String? @db.Text
2468
+ createdAt DateTime @default(now())
2469
+
2470
+ host User @relation("HostAttendeeActivityHost", fields: [hostUserId], references: [id], onDelete: Cascade)
2471
+ attendee User? @relation("HostAttendeeActivityAttendee", fields: [attendeeUserId], references: [id], onDelete: SetNull)
2472
+
2473
+ @@index([hostUserId, attendeeUserId, createdAt])
2474
+ @@index([hostUserId, attendeeEmail, createdAt])
2475
+ }
2476
+
2388
2477
  /// Host-defined reusable CRM audience filters (tag, cadence, lapsed, cohorts).
2389
2478
  model HostCrmSavedSegment {
2390
2479
  id String @id @default(cuid())
@@ -2394,7 +2483,8 @@ model HostCrmSavedSegment {
2394
2483
  createdAt DateTime @default(now())
2395
2484
  updatedAt DateTime @updatedAt
2396
2485
 
2397
- host User @relation("HostCrmSavedSegments", fields: [hostUserId], references: [id], onDelete: Cascade)
2486
+ host User @relation("HostCrmSavedSegments", fields: [hostUserId], references: [id], onDelete: Cascade)
2487
+ automations HostCrmAutomation[]
2398
2488
 
2399
2489
  @@unique([hostUserId, name])
2400
2490
  @@index([hostUserId])
@@ -2417,6 +2507,53 @@ model HostCrmEmailSendLog {
2417
2507
  @@index([email, templateKey, sentAt])
2418
2508
  }
2419
2509
 
2510
+ enum HostCrmAutomationTrigger {
2511
+ Recurring
2512
+ NewlyAtRisk
2513
+ PostEvent
2514
+ }
2515
+
2516
+ enum HostCrmAutomationChannel {
2517
+ Email
2518
+ Sms
2519
+ }
2520
+
2521
+ enum HostCrmAutomationAudienceType {
2522
+ Preset
2523
+ Segment
2524
+ }
2525
+
2526
+ /// Host-defined CRM automation: a named trigger+channel+audience+template
2527
+ /// combo (e.g. "Monthly win-back email to lapsed regulars"). Replaces the
2528
+ /// single hostCrmWinBackAutoEnabled toggle and single postEventCrmTemplate
2529
+ /// pair on UserPreferences with multiple, independently-configurable
2530
+ /// automations per host.
2531
+ model HostCrmAutomation {
2532
+ id String @id @default(cuid())
2533
+ hostUserId String
2534
+ name String
2535
+ trigger HostCrmAutomationTrigger
2536
+ channel HostCrmAutomationChannel
2537
+ /// Ignored for PostEvent — audience there is implicit (that event's ticket holders).
2538
+ audienceType HostCrmAutomationAudienceType?
2539
+ audiencePresetId String?
2540
+ audienceSegmentId String?
2541
+ subject String?
2542
+ body String @db.Text
2543
+ /// Only used by the Recurring trigger.
2544
+ cadenceDays Int? @default(30)
2545
+ enabled Boolean @default(true)
2546
+ lastRunAt DateTime?
2547
+ createdAt DateTime @default(now())
2548
+ updatedAt DateTime @updatedAt
2549
+
2550
+ host User @relation("HostCrmAutomationsHost", fields: [hostUserId], references: [id], onDelete: Cascade)
2551
+ segment HostCrmSavedSegment? @relation(fields: [audienceSegmentId], references: [id], onDelete: SetNull)
2552
+
2553
+ @@index([hostUserId])
2554
+ @@index([trigger, enabled])
2555
+ }
2556
+
2420
2557
  // Tracks referrals: attendee A referred person B who bought a ticket
2421
2558
  model EventReferral {
2422
2559
  id String @id @default(cuid())
@@ -2811,7 +2948,10 @@ model Ticket {
2811
2948
  lastReminded1hAt DateTime?
2812
2949
  lastReminded24hAt DateTime?
2813
2950
  lastReminded1weekAt DateTime?
2951
+ lastReminded3hAt DateTime?
2814
2952
  refundRequestedAt DateTime? // Set when RefundPending; cleared once refund processes
2953
+ /// Set when the guest keeps or declines after a postponement; cleared on each new Postpone.
2954
+ postponeRespondedAt DateTime?
2815
2955
  checkInLocation String?
2816
2956
  checkOutLocation String?
2817
2957
  checkOutMethod String? @default("manual")
@@ -3558,8 +3698,14 @@ model User {
3558
3698
  membershipLastBilledAt DateTime?
3559
3699
  membershipFeaturedEventsUsed Int @default(0)
3560
3700
  membershipStripeSubscriptionId String? @unique
3701
+ /// App Store originalTransactionId when membership is billed via StoreKit IAP.
3702
+ membershipAppleOriginalTransactionId String? @unique
3703
+ /// Which provider owns the active membership billing relationship.
3704
+ membershipBillingProvider String? // "stripe" | "apple" | null
3561
3705
  /// Optional consumer BashPass subscription (waives guest platform fee on tickets; monthly BashPoints).
3562
3706
  bashPassStripeSubscriptionId String? @unique
3707
+ /// App Store originalTransactionId when BashPass is billed via StoreKit IAP.
3708
+ bashPassAppleOriginalTransactionId String? @unique
3563
3709
  bashPassCurrentPeriodEnd DateTime?
3564
3710
  /// Stripe price tier for standalone BashPass; effective tier may also come from membership bundle.
3565
3711
  bashPassTier BashPassTier?
@@ -3793,6 +3939,9 @@ model User {
3793
3939
  hostCrmSavedSegments HostCrmSavedSegment[] @relation("HostCrmSavedSegments")
3794
3940
  hostCrmEmailSendLogsAsHost HostCrmEmailSendLog[] @relation("HostCrmEmailSendLogsHost")
3795
3941
  hostCrmEmailSendLogsAsUser HostCrmEmailSendLog[] @relation("HostCrmEmailSendLogsUser")
3942
+ hostCrmAutomations HostCrmAutomation[] @relation("HostCrmAutomationsHost")
3943
+ hostAttendeeActivityAsHost HostAttendeeActivity[] @relation("HostAttendeeActivityHost")
3944
+ hostAttendeeActivityAsTarget HostAttendeeActivity[] @relation("HostAttendeeActivityAttendee")
3796
3945
  bashListsCreated BashList[]
3797
3946
  userItineraries UserItinerary[]
3798
3947
  aiRecommendationLogs AIRecommendationLog[]
@@ -4298,6 +4447,8 @@ model UserSubscription {
4298
4447
  stripeAccountId String @unique
4299
4448
  stripeSubscriptionId String? @unique
4300
4449
  stripeCheckoutSessionId String? @unique
4450
+ /// App Store originalTransactionId when listing seats are billed via StoreKit IAP.
4451
+ appleOriginalTransactionId String? @unique
4301
4452
  type MembershipTier?
4302
4453
  status UserSubscriptionStatus?
4303
4454
  subscriptionCountId String @unique
@@ -4310,6 +4461,7 @@ model UserSubscription {
4310
4461
  @@index([ownerId])
4311
4462
  @@index([stripeCheckoutSessionId])
4312
4463
  @@index([stripeSubscriptionId])
4464
+ @@index([appleOriginalTransactionId])
4313
4465
  }
4314
4466
 
4315
4467
  model Service {
@@ -0,0 +1,52 @@
1
+ import {
2
+ APPLE_BASHPASS_PRODUCTS,
3
+ APPLE_FEATURE_BOOST_PRODUCTS,
4
+ APPLE_IAP_PRODUCTS,
5
+ APPLE_LISTING_PRODUCTS,
6
+ APPLE_MEMBERSHIP_PRODUCTS,
7
+ findAppleMembershipProduct,
8
+ getAppleIapProduct,
9
+ isAppleIapProductId,
10
+ listAppleIapProductIds,
11
+ } from "../appleIapProducts";
12
+ import { MembershipTier } from "@prisma/client";
13
+
14
+ describe("appleIapProducts", () => {
15
+ it("defines unique product IDs across all families", () => {
16
+ const ids = APPLE_IAP_PRODUCTS.map((p) => p.productId);
17
+ expect(new Set(ids).size).toBe(ids.length);
18
+ });
19
+
20
+ it("covers membership monthly/yearly/lifetime for paid tiers", () => {
21
+ expect(APPLE_MEMBERSHIP_PRODUCTS).toHaveLength(12);
22
+ expect(
23
+ findAppleMembershipProduct(MembershipTier.Premium, "monthly")?.productId
24
+ ).toBe("community.bash.us.membership.premium.monthly");
25
+ expect(
26
+ findAppleMembershipProduct(MembershipTier.Legend, "lifetime")?.productId
27
+ ).toBe("community.bash.us.membership.legend.lifetime");
28
+ });
29
+
30
+ it("covers listing Ally/Partner/Patron monthly", () => {
31
+ expect(APPLE_LISTING_PRODUCTS.map((p) => p.tier)).toEqual([
32
+ "Ally",
33
+ "Partner",
34
+ "Patron",
35
+ ]);
36
+ });
37
+
38
+ it("covers BashPass and feature boost catalogs", () => {
39
+ expect(APPLE_BASHPASS_PRODUCTS.length).toBe(3);
40
+ expect(APPLE_FEATURE_BOOST_PRODUCTS.length).toBe(5);
41
+ expect(
42
+ getAppleIapProduct("community.bash.us.boost.7d")?.family
43
+ ).toBe("feature_boost");
44
+ });
45
+
46
+ it("listAppleIapProductIds filters by family", () => {
47
+ const membershipIds = listAppleIapProductIds("membership");
48
+ expect(membershipIds.every((id) => id.includes(".membership."))).toBe(true);
49
+ expect(isAppleIapProductId(membershipIds[0]!)).toBe(true);
50
+ expect(isAppleIapProductId("not.a.product")).toBe(false);
51
+ });
52
+ });
@@ -0,0 +1,33 @@
1
+ import {
2
+ hostCrmGrowthPackIsComplete,
3
+ hostCrmHasPostEventPackAutomation,
4
+ hostCrmHasWinBackPackAutomation,
5
+ HOST_CRM_GROWTH_PACK_WINBACK_PRESET_ID,
6
+ } from "../hostCrmAutomation.js";
7
+
8
+ describe("host CRM growth pack detection", () => {
9
+ it("detects win-back and post-event pack rows", () => {
10
+ const empty: Array<{ trigger: string; channel: string; audiencePresetId?: string | null }> =
11
+ [];
12
+ expect(hostCrmHasWinBackPackAutomation(empty)).toBe(false);
13
+ expect(hostCrmHasPostEventPackAutomation(empty)).toBe(false);
14
+ expect(hostCrmGrowthPackIsComplete(empty)).toBe(false);
15
+
16
+ const winBack = [
17
+ {
18
+ trigger: "Recurring",
19
+ channel: "Email",
20
+ audiencePresetId: HOST_CRM_GROWTH_PACK_WINBACK_PRESET_ID,
21
+ },
22
+ ];
23
+ expect(hostCrmHasWinBackPackAutomation(winBack)).toBe(true);
24
+ expect(hostCrmGrowthPackIsComplete(winBack)).toBe(false);
25
+
26
+ const both = [
27
+ ...winBack,
28
+ { trigger: "PostEvent", channel: "Email", audiencePresetId: null },
29
+ ];
30
+ expect(hostCrmHasPostEventPackAutomation(both)).toBe(true);
31
+ expect(hostCrmGrowthPackIsComplete(both)).toBe(true);
32
+ });
33
+ });
@@ -0,0 +1,247 @@
1
+ import {
2
+ applyHostCrmSegmentRules,
3
+ HOST_CRM_PRESET_SEGMENTS,
4
+ type HostCrmAudienceMember,
5
+ } from "../hostCrmSegments.js";
6
+
7
+ const NOW = new Date("2026-07-14T12:00:00Z");
8
+
9
+ function member(
10
+ overrides: Partial<HostCrmAudienceMember> & { userId?: string | null } = {}
11
+ ): HostCrmAudienceMember {
12
+ return {
13
+ userId: overrides.userId ?? "u1",
14
+ email: "u@example.com",
15
+ name: "Guest",
16
+ image: null,
17
+ eventCount: 1,
18
+ eventTitles: ["Bash"],
19
+ tags: [],
20
+ notes: null,
21
+ profileId: null,
22
+ socialEventCadence: null,
23
+ reachableEmail: true,
24
+ reachableSms: false,
25
+ lastAttendedAt: null,
26
+ firstAttendedAt: null,
27
+ city: null,
28
+ tierTitles: [],
29
+ sourceEventIds: ["evt-a"],
30
+ emailOnly: false,
31
+ totalSpendCents: 0,
32
+ noShowCount: 0,
33
+ discountResponsive: false,
34
+ fastDecider: false,
35
+ seriesLoyalist: false,
36
+ refundChurn: false,
37
+ bringsGuests: false,
38
+ discoverySource: "direct",
39
+ expectedGapDays: null,
40
+ nextExpectedAt: null,
41
+ ...overrides,
42
+ };
43
+ }
44
+
45
+ describe("applyHostCrmSegmentRules", () => {
46
+ it("filters by sourceEventId (trims whitespace)", () => {
47
+ const audience = [
48
+ member({ userId: "a", sourceEventIds: ["evt-a", "evt-b"] }),
49
+ member({ userId: "b", sourceEventIds: ["evt-c"] }),
50
+ member({ userId: "c", sourceEventIds: undefined }),
51
+ ];
52
+ const filtered = applyHostCrmSegmentRules(audience, {
53
+ sourceEventId: " evt-a ",
54
+ });
55
+ expect(filtered.map((r) => r.userId)).toEqual(["a"]);
56
+ });
57
+
58
+ it("filters by excludeEventId", () => {
59
+ const audience = [
60
+ member({ userId: "a", sourceEventIds: ["evt-a"] }),
61
+ member({ userId: "b", sourceEventIds: ["evt-b"] }),
62
+ member({ userId: "c", sourceEventIds: ["evt-a", "evt-b"] }),
63
+ ];
64
+ const filtered = applyHostCrmSegmentRules(audience, {
65
+ excludeEventId: "evt-a",
66
+ });
67
+ expect(filtered.map((r) => r.userId)).toEqual(["b"]);
68
+ });
69
+
70
+ it("keeps rows with no lastAttendedAt when applying lapsedDays", () => {
71
+ const audience = [
72
+ member({
73
+ userId: "never",
74
+ lastAttendedAt: null,
75
+ }),
76
+ member({
77
+ userId: "recent",
78
+ lastAttendedAt: new Date("2026-07-01T00:00:00Z").toISOString(),
79
+ }),
80
+ member({
81
+ userId: "old",
82
+ lastAttendedAt: new Date("2026-01-01T00:00:00Z").toISOString(),
83
+ }),
84
+ ];
85
+ const filtered = applyHostCrmSegmentRules(
86
+ audience,
87
+ { lapsedDays: 90 },
88
+ NOW
89
+ );
90
+ expect(filtered.map((r) => r.userId).sort()).toEqual(["never", "old"]);
91
+ });
92
+
93
+ it("filters by tag, cadence, minEventCount, tierTitle, and city together", () => {
94
+ const audience = [
95
+ member({
96
+ userId: "keep",
97
+ tags: ["vip"],
98
+ socialEventCadence: "Often",
99
+ eventCount: 3,
100
+ tierTitles: ["GA", "VIP"],
101
+ city: "Brooklyn",
102
+ sourceEventIds: ["evt-a"],
103
+ }),
104
+ member({
105
+ userId: "drop-tag",
106
+ tags: ["regular"],
107
+ socialEventCadence: "Often",
108
+ eventCount: 3,
109
+ tierTitles: ["VIP"],
110
+ city: "Brooklyn",
111
+ }),
112
+ member({
113
+ userId: "drop-city",
114
+ tags: ["vip"],
115
+ socialEventCadence: "Often",
116
+ eventCount: 3,
117
+ tierTitles: ["VIP"],
118
+ city: "Queens",
119
+ }),
120
+ ];
121
+ const filtered = applyHostCrmSegmentRules(audience, {
122
+ tag: " vip ",
123
+ cadence: "Often",
124
+ minEventCount: 2,
125
+ tierTitle: "vip",
126
+ city: "brook",
127
+ });
128
+ expect(filtered.map((r) => r.userId)).toEqual(["keep"]);
129
+ });
130
+
131
+ it("filters by sourceEventIdIn (matches any of the given event ids)", () => {
132
+ const audience = [
133
+ member({ userId: "a", sourceEventIds: ["evt-a"] }),
134
+ member({ userId: "b", sourceEventIds: ["evt-b"] }),
135
+ member({ userId: "c", sourceEventIds: ["evt-c"] }),
136
+ member({ userId: "d", sourceEventIds: undefined }),
137
+ ];
138
+ const filtered = applyHostCrmSegmentRules(audience, {
139
+ sourceEventIdIn: ["evt-a", "evt-b"],
140
+ });
141
+ expect(filtered.map((r) => r.userId).sort()).toEqual(["a", "b"]);
142
+ });
143
+
144
+ it("ignores an empty sourceEventIdIn array", () => {
145
+ const audience = [member({ userId: "a" })];
146
+ expect(applyHostCrmSegmentRules(audience, { sourceEventIdIn: [] })).toHaveLength(1);
147
+ });
148
+
149
+ it("ignores blank source/exclude/tier/city/tag strings", () => {
150
+ const audience = [member({ userId: "a" })];
151
+ expect(
152
+ applyHostCrmSegmentRules(audience, {
153
+ tag: " ",
154
+ sourceEventId: "",
155
+ excludeEventId: " ",
156
+ tierTitle: "",
157
+ city: " ",
158
+ })
159
+ ).toHaveLength(1);
160
+ });
161
+
162
+ it("filters by maxEventCount (first-timers style segments)", () => {
163
+ const audience = [
164
+ member({ userId: "first-timer", eventCount: 1 }),
165
+ member({ userId: "repeat", eventCount: 4 }),
166
+ ];
167
+ const filtered = applyHostCrmSegmentRules(audience, { maxEventCount: 1 });
168
+ expect(filtered.map((r) => r.userId)).toEqual(["first-timer"]);
169
+ });
170
+ });
171
+
172
+ describe("HOST_CRM_PRESET_SEGMENTS", () => {
173
+ it("includes repeat, lapsed, spend, and behavioral presets with expected rules", () => {
174
+ const ids = HOST_CRM_PRESET_SEGMENTS.map((p) => p.id);
175
+ expect(ids).toEqual(
176
+ expect.arrayContaining([
177
+ "repeat_guests",
178
+ "frequent_guest",
179
+ "lapsed_90",
180
+ "lapsed_180",
181
+ "top_spenders",
182
+ "no_show",
183
+ "uses_promo_codes",
184
+ "last_minute_buyer",
185
+ "refund_churn",
186
+ "series_regular",
187
+ "brings_friends",
188
+ "last3Events",
189
+ "first_timers",
190
+ ])
191
+ );
192
+ expect(ids).not.toContain("cadence_often");
193
+ expect(
194
+ HOST_CRM_PRESET_SEGMENTS.find((p) => p.id === "repeat_guests")?.rules
195
+ ).toEqual({ minEventCount: 2 });
196
+ expect(
197
+ HOST_CRM_PRESET_SEGMENTS.find((p) => p.id === "first_timers")?.rules
198
+ ).toEqual({ maxEventCount: 1 });
199
+ expect(
200
+ HOST_CRM_PRESET_SEGMENTS.find((p) => p.id === "top_spenders")?.rules
201
+ ).toEqual({});
202
+ expect(
203
+ HOST_CRM_PRESET_SEGMENTS.find((p) => p.id === "no_show")?.rules
204
+ ).toEqual({ noShow: true });
205
+ // last3Events is resolved at query time (host's most recently ended
206
+ // events) rather than static rules — see filterHostCrmAudience.
207
+ expect(
208
+ HOST_CRM_PRESET_SEGMENTS.find((p) => p.id === "last3Events")?.rules
209
+ ).toEqual({});
210
+ });
211
+ });
212
+
213
+ describe("applyHostCrmSegmentRules — behavioral + spend rules", () => {
214
+ it("filters by minTotalSpendCents, noShow, and the behavioral flags", () => {
215
+ const audience = [
216
+ member({ userId: "spender", totalSpendCents: 50000 }),
217
+ member({ userId: "casual", totalSpendCents: 500 }),
218
+ ];
219
+ expect(
220
+ applyHostCrmSegmentRules(audience, { minTotalSpendCents: 10000 }).map(
221
+ (r) => r.userId
222
+ )
223
+ ).toEqual(["spender"]);
224
+
225
+ const behavioral = [
226
+ member({ userId: "loyal", seriesLoyalist: true }),
227
+ member({ userId: "not-loyal", seriesLoyalist: false }),
228
+ ];
229
+ expect(
230
+ applyHostCrmSegmentRules(behavioral, { seriesLoyalist: true }).map(
231
+ (r) => r.userId
232
+ )
233
+ ).toEqual(["loyal"]);
234
+ });
235
+
236
+ it("filters by healthStatus when relationshipHealth is attached to the row", () => {
237
+ const audience = [
238
+ { ...member({ userId: "risky" }), relationshipHealth: { status: "AtRisk", reasons: [], daysSinceLastAttended: null, expectedGapDays: null } },
239
+ { ...member({ userId: "steady" }), relationshipHealth: { status: "Steady", reasons: [], daysSinceLastAttended: null, expectedGapDays: null } },
240
+ ];
241
+ expect(
242
+ applyHostCrmSegmentRules(audience, { healthStatus: "AtRisk" }).map(
243
+ (r) => r.userId
244
+ )
245
+ ).toEqual(["risky"]);
246
+ });
247
+ });