@bash-app/bash-common 30.75.1 → 30.76.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/definitions.d.ts +116 -0
- package/dist/definitions.d.ts.map +1 -1
- package/dist/definitions.js +143 -1
- package/dist/definitions.js.map +1 -1
- package/dist/extendedSchemas.d.ts +7 -0
- package/dist/extendedSchemas.d.ts.map +1 -1
- package/dist/extendedSchemas.js.map +1 -1
- package/dist/index.d.ts +0 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/membershipDefinitions.d.ts +1 -0
- package/dist/membershipDefinitions.d.ts.map +1 -1
- package/dist/membershipDefinitions.js.map +1 -1
- package/dist/utils/paymentUtils.d.ts +41 -1
- package/dist/utils/paymentUtils.d.ts.map +1 -1
- package/dist/utils/paymentUtils.js +146 -1
- package/dist/utils/paymentUtils.js.map +1 -1
- package/dist/utils/service/frontendServiceBookingUtils.d.ts.map +1 -1
- package/dist/utils/service/frontendServiceBookingUtils.js +5 -1
- package/dist/utils/service/frontendServiceBookingUtils.js.map +1 -1
- package/dist/utils/userSubscriptionUtils.d.ts +4 -12
- package/dist/utils/userSubscriptionUtils.d.ts.map +1 -1
- package/dist/utils/userSubscriptionUtils.js +13 -20
- package/dist/utils/userSubscriptionUtils.js.map +1 -1
- package/package.json +1 -1
- package/prisma/schema.prisma +2031 -2547
- package/src/definitions.ts +180 -1
- package/src/extendedSchemas.ts +16 -2
- package/src/index.ts +1 -1
- package/src/membershipDefinitions.ts +1 -0
- package/src/utils/contentFilterUtils.ts +2 -0
- package/src/utils/paymentUtils.ts +221 -1
- package/src/utils/service/frontendServiceBookingUtils.ts +5 -1
- package/src/utils/userSubscriptionUtils.ts +20 -38
- package/src/utils/service/venueUtils.ts +0 -30
package/src/definitions.ts
CHANGED
|
@@ -85,7 +85,186 @@ export const URL_PARAMS_TICKETS_DATE_DELIM = ";;" as const;
|
|
|
85
85
|
export const URL_INCLUDE_QUERY_PARAM_DELIM = "," as const;
|
|
86
86
|
export const URL_INCLUDE_PRISMA_DATA_KEYS_DELIM = "." as const;
|
|
87
87
|
|
|
88
|
-
|
|
88
|
+
// Platform fee structure
|
|
89
|
+
export const BASH_FEE_PERCENTAGE = 0.10; // 10% base platform fee for bash tickets/donations
|
|
90
|
+
export const SERVICE_FEE_PERCENTAGE = 0.15; // 15% platform fee for service bookings (Allies, Patrons)
|
|
91
|
+
export const PARTNER_FEE_PERCENTAGE = 0.08; // 8% platform fee for Partner payments (Vendors, Exhibitors, Sponsors)
|
|
92
|
+
|
|
93
|
+
// Minimum pricing (ensures quality events + sustainable model)
|
|
94
|
+
export const BASH_EVENT_TICKET_MINIMUM = 5.00; // $5 minimum ticket price (quality signal, prevents race to bottom)
|
|
95
|
+
export const BASH_EVENT_FEE_MINIMUM = 0.50; // $0.50 minimum platform fee (prevents gaming, covers Stripe fees)
|
|
96
|
+
|
|
97
|
+
// Free trial settings
|
|
98
|
+
export const CREATOR_TIER_TRIAL_DAYS = 30; // 30-day free trial for Creator tier (encourages conversions)
|
|
99
|
+
|
|
100
|
+
// Membership tier fee discounts (for bash tickets/donations)
|
|
101
|
+
// Note: BASH_EVENT_FEE_MINIMUM ($0.50) applies to all tiers, so effective minimums are higher on low-priced tickets
|
|
102
|
+
export const BASH_FEE_BASIC = 0.10; // 10% - Basic (free) members (min $0.50)
|
|
103
|
+
export const BASH_FEE_PRO = 0.08; // 8% - Pro members (20% discount, min $0.50)
|
|
104
|
+
export const BASH_FEE_CREATOR = 0.06; // 6% - Creator members (40% discount, min $0.50)
|
|
105
|
+
export const BASH_FEE_ELITE = 0.04; // 4% - Elite members (60% discount, min $0.50)
|
|
106
|
+
export const BASH_FEE_LEGEND = 0.02; // 2% - Legend members (80% discount, min $0.50 = 10% effective minimum on $5 tickets)
|
|
107
|
+
|
|
108
|
+
// Service fee discounts (for Allies/Patrons service bookings)
|
|
109
|
+
export const SERVICE_FEE_BASIC = 0.15; // 15% - Basic (free) members
|
|
110
|
+
export const SERVICE_FEE_PRO = 0.12; // 12% - Pro members (20% discount)
|
|
111
|
+
export const SERVICE_FEE_CREATOR = 0.09; // 9% - Creator members (40% discount)
|
|
112
|
+
export const SERVICE_FEE_ELITE = 0.06; // 6% - Elite members (60% discount)
|
|
113
|
+
export const SERVICE_FEE_LEGEND = 0.05; // 5% - Legend members (67% discount, sustainable floor)
|
|
114
|
+
|
|
115
|
+
// Partner fee discounts (for Vendors/Exhibitors/Sponsors payments)
|
|
116
|
+
export const PARTNER_FEE_BASIC = 0.08; // 8% - Basic (free) members
|
|
117
|
+
export const PARTNER_FEE_PRO = 0.06; // 6% - Pro members (25% discount)
|
|
118
|
+
export const PARTNER_FEE_CREATOR = 0.05; // 5% - Creator members (37.5% discount, sustainable floor)
|
|
119
|
+
export const PARTNER_FEE_ELITE = 0.05; // 5% - Elite members (same as Creator, sustainable floor)
|
|
120
|
+
export const PARTNER_FEE_LEGEND = 0.05; // 5% - Legend members (same as Creator/Elite, sustainable floor)
|
|
121
|
+
|
|
122
|
+
// Platform fee caps by membership tier (in cents)
|
|
123
|
+
export const BASH_FEE_CAP_BASIC = 25000; // $250 cap for Basic
|
|
124
|
+
export const BASH_FEE_CAP_PRO = 20000; // $200 cap for Pro
|
|
125
|
+
export const BASH_FEE_CAP_CREATOR = 15000; // $150 cap for Creator
|
|
126
|
+
export const BASH_FEE_CAP_ELITE = 10000; // $100 cap for Elite
|
|
127
|
+
export const BASH_FEE_CAP_LEGEND = 5000; // $50 cap for Legend
|
|
128
|
+
|
|
129
|
+
export const SERVICE_FEE_CAP_BASIC = 37500; // $375 cap for Basic
|
|
130
|
+
export const SERVICE_FEE_CAP_PRO = 30000; // $300 cap for Pro
|
|
131
|
+
export const SERVICE_FEE_CAP_CREATOR = 22500; // $225 cap for Creator
|
|
132
|
+
export const SERVICE_FEE_CAP_ELITE = 15000; // $150 cap for Elite
|
|
133
|
+
export const SERVICE_FEE_CAP_LEGEND = 7500; // $75 cap for Legend
|
|
134
|
+
|
|
135
|
+
// Partner payment fee caps (Partners pay less since they bring value to hosts)
|
|
136
|
+
export const PARTNER_FEE_CAP_BASIC = 20000; // $200 cap for Basic (8%)
|
|
137
|
+
export const PARTNER_FEE_CAP_PRO = 15000; // $150 cap for Pro (6%)
|
|
138
|
+
export const PARTNER_FEE_CAP_CREATOR = 12500; // $125 cap for Creator (5%)
|
|
139
|
+
export const PARTNER_FEE_CAP_ELITE = 7500; // $75 cap for Elite (3%)
|
|
140
|
+
export const PARTNER_FEE_CAP_LEGEND = 7500; // $75 cap for Legend (3%)
|
|
141
|
+
|
|
142
|
+
// ============================================
|
|
143
|
+
// SERVICE SUBSCRIPTION TIERS
|
|
144
|
+
// ============================================
|
|
145
|
+
// Service provider subscription tiers with pricing and limits
|
|
146
|
+
// These are separate from user membership tiers (Basic, Creator, Pro, Elite, Legend)
|
|
147
|
+
|
|
148
|
+
export type UserSubscriptionServiceTierInfo = {
|
|
149
|
+
name: string;
|
|
150
|
+
type?: ServiceSubscriptionTier;
|
|
151
|
+
description: string;
|
|
152
|
+
price: number;
|
|
153
|
+
features?: string[];
|
|
154
|
+
limits?: {
|
|
155
|
+
maxServices?: number;
|
|
156
|
+
maxPhotos?: number;
|
|
157
|
+
priorityPlacement?: boolean;
|
|
158
|
+
customBranding?: boolean;
|
|
159
|
+
analytics?: boolean;
|
|
160
|
+
prioritySupport?: boolean;
|
|
161
|
+
bookingFeePercentage?: number; // Percentage taken on each booking (0.15 = 15%)
|
|
162
|
+
};
|
|
163
|
+
};
|
|
164
|
+
|
|
165
|
+
export type UserSubscriptionServiceTierInfoMap = {
|
|
166
|
+
[key in ServiceSubscriptionTier]: UserSubscriptionServiceTierInfo;
|
|
167
|
+
};
|
|
168
|
+
|
|
169
|
+
export const SERVICE_SUBSCRIPTION_TIERS = {
|
|
170
|
+
Free: {
|
|
171
|
+
name: "Free",
|
|
172
|
+
description: "List your first service free - perfect for testing the platform",
|
|
173
|
+
price: 0,
|
|
174
|
+
features: [
|
|
175
|
+
"1 service listing",
|
|
176
|
+
"Up to 5 photos",
|
|
177
|
+
"Standard search placement",
|
|
178
|
+
"Basic booking management",
|
|
179
|
+
"15% booking fee",
|
|
180
|
+
"Community support"
|
|
181
|
+
],
|
|
182
|
+
limits: {
|
|
183
|
+
maxServices: 1,
|
|
184
|
+
maxPhotos: 5,
|
|
185
|
+
priorityPlacement: false,
|
|
186
|
+
customBranding: false,
|
|
187
|
+
analytics: false,
|
|
188
|
+
prioritySupport: false,
|
|
189
|
+
bookingFeePercentage: 0.15
|
|
190
|
+
}
|
|
191
|
+
},
|
|
192
|
+
Ally: {
|
|
193
|
+
name: "Ally",
|
|
194
|
+
description: "Enhanced features for growing entertainment and event service providers",
|
|
195
|
+
price: 14,
|
|
196
|
+
features: [
|
|
197
|
+
"Up to 5 service listings",
|
|
198
|
+
"Unlimited photos & videos",
|
|
199
|
+
"Priority search placement (top 50%)",
|
|
200
|
+
"Featured provider badge",
|
|
201
|
+
"12% booking fee (save 3%)",
|
|
202
|
+
"Basic analytics and insights",
|
|
203
|
+
"Calendar integration",
|
|
204
|
+
"Email support"
|
|
205
|
+
],
|
|
206
|
+
limits: {
|
|
207
|
+
maxServices: 5,
|
|
208
|
+
maxPhotos: -1, // unlimited
|
|
209
|
+
priorityPlacement: true,
|
|
210
|
+
customBranding: false,
|
|
211
|
+
analytics: true,
|
|
212
|
+
prioritySupport: false,
|
|
213
|
+
bookingFeePercentage: 0.12
|
|
214
|
+
}
|
|
215
|
+
},
|
|
216
|
+
Partner: {
|
|
217
|
+
name: "Partner",
|
|
218
|
+
description: "Professional tools for established vendors and service providers",
|
|
219
|
+
price: 49,
|
|
220
|
+
features: [
|
|
221
|
+
"Unlimited service listings",
|
|
222
|
+
"Unlimited photos & videos",
|
|
223
|
+
"Premium placement (top 25%)",
|
|
224
|
+
"Custom branding on booking pages",
|
|
225
|
+
"8% booking fee (save 7%)",
|
|
226
|
+
"Advanced analytics & reporting",
|
|
227
|
+
"Automated marketing campaigns",
|
|
228
|
+
"Priority support (chat & email)",
|
|
229
|
+
"Lead generation tools"
|
|
230
|
+
],
|
|
231
|
+
limits: {
|
|
232
|
+
maxServices: -1, // unlimited
|
|
233
|
+
maxPhotos: -1, // unlimited
|
|
234
|
+
priorityPlacement: true,
|
|
235
|
+
customBranding: true,
|
|
236
|
+
analytics: true,
|
|
237
|
+
prioritySupport: true,
|
|
238
|
+
bookingFeePercentage: 0.08
|
|
239
|
+
}
|
|
240
|
+
},
|
|
241
|
+
Patron: {
|
|
242
|
+
name: "Patron",
|
|
243
|
+
description: "Premium enterprise solution for venues and large organizations",
|
|
244
|
+
price: 99,
|
|
245
|
+
features: [
|
|
246
|
+
"Everything in Partner +",
|
|
247
|
+
"Featured first (top placement)",
|
|
248
|
+
"5% booking fee (save 10%)",
|
|
249
|
+
"Dedicated account manager",
|
|
250
|
+
"White-label booking pages",
|
|
251
|
+
"Custom integrations & API access",
|
|
252
|
+
"Custom reporting dashboards",
|
|
253
|
+
"Lead generation alerts",
|
|
254
|
+
"24/7 priority support"
|
|
255
|
+
],
|
|
256
|
+
limits: {
|
|
257
|
+
maxServices: -1, // unlimited
|
|
258
|
+
maxPhotos: -1, // unlimited
|
|
259
|
+
priorityPlacement: true,
|
|
260
|
+
customBranding: true,
|
|
261
|
+
analytics: true,
|
|
262
|
+
prioritySupport: true,
|
|
263
|
+
bookingFeePercentage: 0.05
|
|
264
|
+
}
|
|
265
|
+
},
|
|
266
|
+
} as const satisfies UserSubscriptionServiceTierInfoMap;
|
|
267
|
+
|
|
89
268
|
export const GOOGLE_CALLBACK_URL = "/auth/google/callback" as const;
|
|
90
269
|
export const CHECKOUT_RETURN_SUCCESS_URL =
|
|
91
270
|
`/checkout-success/{CHECKOUT_SESSION_ID}` as const;
|
package/src/extendedSchemas.ts
CHANGED
|
@@ -571,8 +571,10 @@ export interface ServiceExt extends Service {
|
|
|
571
571
|
|
|
572
572
|
// googleReviews: GoogleReview[];
|
|
573
573
|
|
|
574
|
+
// For availability filtering - matches Prisma relation name "bookings"
|
|
575
|
+
bookings?: ServiceBookingExt[];
|
|
576
|
+
|
|
574
577
|
// bookedCheckouts: ServiceBookingCheckoutExt[]; //not necessary to include
|
|
575
|
-
// bookings?: ServiceBookingExt[];
|
|
576
578
|
}
|
|
577
579
|
|
|
578
580
|
export type ServiceExtNonSpecific = Exclude<
|
|
@@ -650,7 +652,19 @@ export interface VendorExt extends Vendor {
|
|
|
650
652
|
};
|
|
651
653
|
}
|
|
652
654
|
|
|
653
|
-
|
|
655
|
+
// Future type for venue unavailable dates (not yet implemented in database)
|
|
656
|
+
// To implement: Add VenueUnavailableDate model to Prisma schema
|
|
657
|
+
export interface UnavailableDate {
|
|
658
|
+
id: string;
|
|
659
|
+
startDate: Date;
|
|
660
|
+
endDate: Date;
|
|
661
|
+
reason?: string;
|
|
662
|
+
}
|
|
663
|
+
|
|
664
|
+
export interface VenueExt extends Venue {
|
|
665
|
+
// Note: unavailableDates field doesn't exist in database yet
|
|
666
|
+
// When implemented, add: unavailableDates?: UnavailableDate[];
|
|
667
|
+
}
|
|
654
668
|
|
|
655
669
|
export interface OrganizationExt extends Organization {
|
|
656
670
|
amountOfGuests?: AmountOfGuests;
|
package/src/index.ts
CHANGED
|
@@ -15,7 +15,7 @@ export * from "./utils/recurrenceUtils";
|
|
|
15
15
|
export * from "./utils/service/attendeeOptionUtils";
|
|
16
16
|
export * from "./utils/service/regexUtils";
|
|
17
17
|
export * from "./utils/service/serviceUtils";
|
|
18
|
-
|
|
18
|
+
// Venue utils moved to paymentUtils.ts for better organization
|
|
19
19
|
export * from "./utils/slugUtils";
|
|
20
20
|
export * from "./utils/sortUtils";
|
|
21
21
|
export * from "./utils/stringUtils";
|
|
@@ -41,6 +41,7 @@ export interface UserMembershipStatus {
|
|
|
41
41
|
currentPeriodStart?: number;
|
|
42
42
|
currentPeriodEnd?: number;
|
|
43
43
|
cancelAtPeriodEnd?: boolean;
|
|
44
|
+
trialEnd?: string; // ISO string of when trial ends (if in trial period)
|
|
44
45
|
}
|
|
45
46
|
|
|
46
47
|
// Additional interfaces for membership API
|
|
@@ -1,6 +1,38 @@
|
|
|
1
|
-
import { BashEventPromoCode, TicketTier } from "@prisma/client";
|
|
1
|
+
import { BashEventPromoCode, MembershipTier, TicketTier, VenuePricingPlan as VenuePricingPlanOption } from "@prisma/client";
|
|
2
2
|
import {
|
|
3
3
|
BASH_FEE_PERCENTAGE,
|
|
4
|
+
SERVICE_FEE_PERCENTAGE,
|
|
5
|
+
PARTNER_FEE_PERCENTAGE,
|
|
6
|
+
BASH_FEE_BASIC,
|
|
7
|
+
BASH_FEE_PRO,
|
|
8
|
+
BASH_FEE_CREATOR,
|
|
9
|
+
BASH_FEE_ELITE,
|
|
10
|
+
BASH_FEE_LEGEND,
|
|
11
|
+
SERVICE_FEE_BASIC,
|
|
12
|
+
SERVICE_FEE_PRO,
|
|
13
|
+
SERVICE_FEE_CREATOR,
|
|
14
|
+
SERVICE_FEE_ELITE,
|
|
15
|
+
SERVICE_FEE_LEGEND,
|
|
16
|
+
PARTNER_FEE_BASIC,
|
|
17
|
+
PARTNER_FEE_PRO,
|
|
18
|
+
PARTNER_FEE_CREATOR,
|
|
19
|
+
PARTNER_FEE_ELITE,
|
|
20
|
+
PARTNER_FEE_LEGEND,
|
|
21
|
+
BASH_FEE_CAP_BASIC,
|
|
22
|
+
BASH_FEE_CAP_PRO,
|
|
23
|
+
BASH_FEE_CAP_CREATOR,
|
|
24
|
+
BASH_FEE_CAP_ELITE,
|
|
25
|
+
BASH_FEE_CAP_LEGEND,
|
|
26
|
+
SERVICE_FEE_CAP_BASIC,
|
|
27
|
+
SERVICE_FEE_CAP_PRO,
|
|
28
|
+
SERVICE_FEE_CAP_CREATOR,
|
|
29
|
+
SERVICE_FEE_CAP_ELITE,
|
|
30
|
+
SERVICE_FEE_CAP_LEGEND,
|
|
31
|
+
PARTNER_FEE_CAP_BASIC,
|
|
32
|
+
PARTNER_FEE_CAP_PRO,
|
|
33
|
+
PARTNER_FEE_CAP_CREATOR,
|
|
34
|
+
PARTNER_FEE_CAP_ELITE,
|
|
35
|
+
PARTNER_FEE_CAP_LEGEND,
|
|
4
36
|
NumberOfTicketsForDate,
|
|
5
37
|
PRICE_DOLLARS_AND_CENTS_RATIO,
|
|
6
38
|
} from "../definitions";
|
|
@@ -69,3 +101,191 @@ export function convertDollarsToCents(
|
|
|
69
101
|
export function calculateBashAppFee(total: number): number {
|
|
70
102
|
return parseFloat((total * BASH_FEE_PERCENTAGE).toFixed(2));
|
|
71
103
|
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Bash ticket/donation fee percentages by membership tier
|
|
107
|
+
* Imported from definitions.ts
|
|
108
|
+
*/
|
|
109
|
+
const BASH_FEE_PERCENTAGES: Record<MembershipTier, number> = {
|
|
110
|
+
Basic: BASH_FEE_BASIC,
|
|
111
|
+
Pro: BASH_FEE_PRO,
|
|
112
|
+
Creator: BASH_FEE_CREATOR,
|
|
113
|
+
Elite: BASH_FEE_ELITE,
|
|
114
|
+
Legend: BASH_FEE_LEGEND,
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Service booking fee percentages by membership tier (Allies, Patrons)
|
|
119
|
+
* Imported from definitions.ts
|
|
120
|
+
*/
|
|
121
|
+
const SERVICE_FEE_PERCENTAGES: Record<MembershipTier, number> = {
|
|
122
|
+
Basic: SERVICE_FEE_BASIC,
|
|
123
|
+
Pro: SERVICE_FEE_PRO,
|
|
124
|
+
Creator: SERVICE_FEE_CREATOR,
|
|
125
|
+
Elite: SERVICE_FEE_ELITE,
|
|
126
|
+
Legend: SERVICE_FEE_LEGEND,
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Bash ticket/donation fee caps by membership tier (in cents)
|
|
131
|
+
* Imported from definitions.ts
|
|
132
|
+
*/
|
|
133
|
+
const BASH_FEE_CAPS: Record<MembershipTier, number> = {
|
|
134
|
+
Basic: BASH_FEE_CAP_BASIC,
|
|
135
|
+
Pro: BASH_FEE_CAP_PRO,
|
|
136
|
+
Creator: BASH_FEE_CAP_CREATOR,
|
|
137
|
+
Elite: BASH_FEE_CAP_ELITE,
|
|
138
|
+
Legend: BASH_FEE_CAP_LEGEND,
|
|
139
|
+
};
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Service booking fee caps by membership tier (in cents)
|
|
143
|
+
* Imported from definitions.ts
|
|
144
|
+
*/
|
|
145
|
+
const SERVICE_FEE_CAPS: Record<MembershipTier, number> = {
|
|
146
|
+
Basic: SERVICE_FEE_CAP_BASIC,
|
|
147
|
+
Pro: SERVICE_FEE_CAP_PRO,
|
|
148
|
+
Creator: SERVICE_FEE_CAP_CREATOR,
|
|
149
|
+
Elite: SERVICE_FEE_CAP_ELITE,
|
|
150
|
+
Legend: SERVICE_FEE_CAP_LEGEND,
|
|
151
|
+
};
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Partner payment fee percentages by membership tier (Vendors, Exhibitors, Sponsors)
|
|
155
|
+
* Imported from definitions.ts
|
|
156
|
+
*/
|
|
157
|
+
const PARTNER_FEE_PERCENTAGES: Record<MembershipTier, number> = {
|
|
158
|
+
Basic: PARTNER_FEE_BASIC,
|
|
159
|
+
Pro: PARTNER_FEE_PRO,
|
|
160
|
+
Creator: PARTNER_FEE_CREATOR,
|
|
161
|
+
Elite: PARTNER_FEE_ELITE,
|
|
162
|
+
Legend: PARTNER_FEE_LEGEND,
|
|
163
|
+
};
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Partner payment fee caps by membership tier (in cents)
|
|
167
|
+
* Imported from definitions.ts
|
|
168
|
+
*/
|
|
169
|
+
const PARTNER_FEE_CAPS: Record<MembershipTier, number> = {
|
|
170
|
+
Basic: PARTNER_FEE_CAP_BASIC,
|
|
171
|
+
Pro: PARTNER_FEE_CAP_PRO,
|
|
172
|
+
Creator: PARTNER_FEE_CAP_CREATOR,
|
|
173
|
+
Elite: PARTNER_FEE_CAP_ELITE,
|
|
174
|
+
Legend: PARTNER_FEE_CAP_LEGEND,
|
|
175
|
+
};
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* Calculate platform fee for bash tickets/donations with membership tier discounts and caps
|
|
179
|
+
* @param total - Transaction amount in cents
|
|
180
|
+
* @param membershipTier - User's membership tier (defaults to Basic if not provided)
|
|
181
|
+
* @returns Platform fee in cents, respecting both percentage discount and cap
|
|
182
|
+
*/
|
|
183
|
+
export function calculateBashAppFeeWithMembershipDiscount(
|
|
184
|
+
total: number,
|
|
185
|
+
membershipTier?: MembershipTier | null
|
|
186
|
+
): number {
|
|
187
|
+
// Default to Basic tier if no membership provided
|
|
188
|
+
const tier = membershipTier || 'Basic';
|
|
189
|
+
|
|
190
|
+
// Calculate fee based on membership tier percentage
|
|
191
|
+
const feePercentage = BASH_FEE_PERCENTAGES[tier] || BASH_FEE_PERCENTAGE;
|
|
192
|
+
const calculatedFee = total * feePercentage;
|
|
193
|
+
|
|
194
|
+
// Apply cap for the membership tier
|
|
195
|
+
const feeCap = BASH_FEE_CAPS[tier] || BASH_FEE_CAPS.Basic;
|
|
196
|
+
const cappedFee = Math.min(calculatedFee, feeCap);
|
|
197
|
+
|
|
198
|
+
// Round to 2 decimal places (cents precision)
|
|
199
|
+
return parseFloat(cappedFee.toFixed(2));
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* Calculate platform fee for service bookings (Allies, Patrons) with membership tier discounts and caps
|
|
204
|
+
* @param total - Transaction amount in cents
|
|
205
|
+
* @param membershipTier - User's membership tier (defaults to Basic if not provided)
|
|
206
|
+
* @returns Platform fee in cents, respecting both percentage discount and cap
|
|
207
|
+
*/
|
|
208
|
+
export function calculateServiceFeeWithMembershipDiscount(
|
|
209
|
+
total: number,
|
|
210
|
+
membershipTier?: MembershipTier | null
|
|
211
|
+
): number {
|
|
212
|
+
// Default to Basic tier if no membership provided
|
|
213
|
+
const tier = membershipTier || 'Basic';
|
|
214
|
+
|
|
215
|
+
// Calculate fee based on membership tier percentage
|
|
216
|
+
const feePercentage = SERVICE_FEE_PERCENTAGES[tier] || SERVICE_FEE_PERCENTAGE;
|
|
217
|
+
const calculatedFee = total * feePercentage;
|
|
218
|
+
|
|
219
|
+
// Apply cap for the membership tier
|
|
220
|
+
const feeCap = SERVICE_FEE_CAPS[tier] || SERVICE_FEE_CAPS.Basic;
|
|
221
|
+
const cappedFee = Math.min(calculatedFee, feeCap);
|
|
222
|
+
|
|
223
|
+
// Round to 2 decimal places (cents precision)
|
|
224
|
+
return parseFloat(cappedFee.toFixed(2));
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* Calculate platform fee for Partner payments (Vendors, Exhibitors, Sponsors) with membership tier discounts and caps
|
|
229
|
+
* Partners pay the host for booth/sponsorship space, and platform takes a small fee
|
|
230
|
+
* @param total - Transaction amount in cents
|
|
231
|
+
* @param membershipTier - Partner's membership tier (defaults to Basic if not provided)
|
|
232
|
+
* @returns Platform fee in cents, respecting both percentage discount and cap
|
|
233
|
+
*/
|
|
234
|
+
export function calculatePartnerFeeWithMembershipDiscount(
|
|
235
|
+
total: number,
|
|
236
|
+
membershipTier?: MembershipTier | null
|
|
237
|
+
): number {
|
|
238
|
+
// Default to Basic tier if no membership provided
|
|
239
|
+
const tier = membershipTier || 'Basic';
|
|
240
|
+
|
|
241
|
+
// Calculate fee based on membership tier percentage
|
|
242
|
+
const feePercentage = PARTNER_FEE_PERCENTAGES[tier] || PARTNER_FEE_PERCENTAGE;
|
|
243
|
+
const calculatedFee = total * feePercentage;
|
|
244
|
+
|
|
245
|
+
// Apply cap for the membership tier
|
|
246
|
+
const feeCap = PARTNER_FEE_CAPS[tier] || PARTNER_FEE_CAPS.Basic;
|
|
247
|
+
const cappedFee = Math.min(calculatedFee, feeCap);
|
|
248
|
+
|
|
249
|
+
// Round to 2 decimal places (cents precision)
|
|
250
|
+
return parseFloat(cappedFee.toFixed(2));
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
// ============================================
|
|
254
|
+
// VENUE PRICING PLANS
|
|
255
|
+
// ============================================
|
|
256
|
+
|
|
257
|
+
export type VenuePricingPlanData = {
|
|
258
|
+
name: string;
|
|
259
|
+
description: string;
|
|
260
|
+
percentageFee: number;
|
|
261
|
+
monthlyFee: number;
|
|
262
|
+
flatFee: number;
|
|
263
|
+
};
|
|
264
|
+
|
|
265
|
+
export type VenuePricingPlanMap = {
|
|
266
|
+
[key in VenuePricingPlanOption]: VenuePricingPlanData;
|
|
267
|
+
};
|
|
268
|
+
|
|
269
|
+
/**
|
|
270
|
+
* Venue pricing plan options
|
|
271
|
+
* Moved from venueUtils.ts for centralization
|
|
272
|
+
*
|
|
273
|
+
* Note: Uses SERVICE_FEE_PERCENTAGE (15% base rate) for percentage-based plan.
|
|
274
|
+
* Actual fees may be lower based on membership tier (see SERVICE_FEE_BASIC, SERVICE_FEE_PRO, etc.)
|
|
275
|
+
*/
|
|
276
|
+
export const VENUE_PRICING_PLAN_DATA: VenuePricingPlanMap = {
|
|
277
|
+
[VenuePricingPlanOption.Percentage]: {
|
|
278
|
+
name: "Pay per booking",
|
|
279
|
+
description: "15% of each booking goes to Bash.",
|
|
280
|
+
percentageFee: SERVICE_FEE_PERCENTAGE, // Use centralized constant (15%)
|
|
281
|
+
monthlyFee: 0.0,
|
|
282
|
+
flatFee: 0.0,
|
|
283
|
+
},
|
|
284
|
+
[VenuePricingPlanOption.Subscription]: {
|
|
285
|
+
name: "Monthly subscription",
|
|
286
|
+
description: "Pay $100/month and keep 100% of each booking.",
|
|
287
|
+
percentageFee: 0.0,
|
|
288
|
+
monthlyFee: 100.0,
|
|
289
|
+
flatFee: 0.0,
|
|
290
|
+
},
|
|
291
|
+
} as const;
|
|
@@ -33,8 +33,12 @@ import {
|
|
|
33
33
|
ServiceBookingAddOnBase,
|
|
34
34
|
} from "./serviceBookingTypes";
|
|
35
35
|
import { convertDollarsToCents } from "../paymentUtils";
|
|
36
|
+
import { SERVICE_FEE_PERCENTAGE } from "../../definitions";
|
|
36
37
|
|
|
37
|
-
|
|
38
|
+
// Use centralized service fee percentage (15% base rate for Basic tier)
|
|
39
|
+
// Note: This is the DEFAULT processing fee. Actual fees may be lower based on membership tier.
|
|
40
|
+
// See definitions.ts for SERVICE_FEE_BASIC, SERVICE_FEE_PRO, etc.
|
|
41
|
+
export const SERVICE_BOOKING_PROCESSING_FEE_PERCENT = SERVICE_FEE_PERCENTAGE;
|
|
38
42
|
|
|
39
43
|
export interface ServiceAddonInput extends ServiceAddon {
|
|
40
44
|
chosenQuantity?: number;
|
|
@@ -1,22 +1,19 @@
|
|
|
1
1
|
import { ServiceTypes, MembershipTier } from "@prisma/client";
|
|
2
2
|
|
|
3
|
+
// Re-export from definitions.ts for backwards compatibility
|
|
4
|
+
export {
|
|
5
|
+
SERVICE_SUBSCRIPTION_TIERS,
|
|
6
|
+
type UserSubscriptionServiceTierInfo,
|
|
7
|
+
type UserSubscriptionServiceTierInfoMap
|
|
8
|
+
} from "../definitions";
|
|
9
|
+
|
|
3
10
|
export const ServiceSubscriptionTier = {
|
|
4
|
-
|
|
11
|
+
Free: "Free",
|
|
12
|
+
Ally: "Ally",
|
|
5
13
|
Partner: "Partner",
|
|
6
|
-
|
|
14
|
+
Patron: "Patron",
|
|
7
15
|
} as const;
|
|
8
|
-
export type ServiceSubscriptionTier = "Ally" | "Partner" | "Patron";
|
|
9
|
-
|
|
10
|
-
export type UserSubscriptionServiceTierInfo = {
|
|
11
|
-
name: string;
|
|
12
|
-
type?: ServiceSubscriptionTier;
|
|
13
|
-
description: string;
|
|
14
|
-
price: number;
|
|
15
|
-
};
|
|
16
|
-
|
|
17
|
-
export type UserSubscriptionServiceTierInfoMap = {
|
|
18
|
-
[key in ServiceSubscriptionTier]: UserSubscriptionServiceTierInfo;
|
|
19
|
-
};
|
|
16
|
+
export type ServiceSubscriptionTier = "Free" | "Ally" | "Partner" | "Patron";
|
|
20
17
|
|
|
21
18
|
export type UserSubscriptionInfo = {
|
|
22
19
|
name: string;
|
|
@@ -40,6 +37,7 @@ export type UserServiceSubscriptionTierFromServiceTypes = {
|
|
|
40
37
|
};
|
|
41
38
|
|
|
42
39
|
export const SERVICE_TIER_TO_SERVICES_LIST = {
|
|
40
|
+
Free: ["EventServices", "EntertainmentServices"],
|
|
43
41
|
Ally: ["EventServices", "EntertainmentServices"],
|
|
44
42
|
Partner: ["Vendors", "Exhibitors", "Sponsors"],
|
|
45
43
|
Patron: ["Venues", "Organizations"],
|
|
@@ -48,9 +46,13 @@ export const SERVICE_TIER_TO_SERVICES_LIST = {
|
|
|
48
46
|
export const SERVICE_TIER_FROM_SERVICE_TYPE = Object.entries(
|
|
49
47
|
SERVICE_TIER_TO_SERVICES_LIST
|
|
50
48
|
).reduce((sofar, [type, serviceTypes]) => {
|
|
51
|
-
serviceTypes.forEach(
|
|
52
|
-
|
|
53
|
-
|
|
49
|
+
serviceTypes.forEach((serviceType) => {
|
|
50
|
+
// Default to Free tier for EventServices and EntertainmentServices
|
|
51
|
+
// Higher tiers can be chosen by the user
|
|
52
|
+
if (!sofar[serviceType] || type === "Free") {
|
|
53
|
+
sofar[serviceType] = type as ServiceSubscriptionTier;
|
|
54
|
+
}
|
|
55
|
+
});
|
|
54
56
|
return sofar;
|
|
55
57
|
}, {} as UserServiceSubscriptionTierFromServiceTypes);
|
|
56
58
|
|
|
@@ -77,27 +79,7 @@ export const USER_SUBSCRIPTION_TYPES = {
|
|
|
77
79
|
// }
|
|
78
80
|
} as UserSubscriptionServiceInfoMap;
|
|
79
81
|
|
|
80
|
-
|
|
81
|
-
Ally: {
|
|
82
|
-
name: "Ally",
|
|
83
|
-
description: "Ally",
|
|
84
|
-
price: 14,
|
|
85
|
-
},
|
|
86
|
-
Partner: {
|
|
87
|
-
name: "Partner",
|
|
88
|
-
description: "Partner",
|
|
89
|
-
price: 49.0,
|
|
90
|
-
},
|
|
91
|
-
Patron: {
|
|
92
|
-
name: "Patron",
|
|
93
|
-
description: "Patron",
|
|
94
|
-
price: 99.0,
|
|
95
|
-
},
|
|
96
|
-
} as UserSubscriptionServiceTierInfoMap;
|
|
97
|
-
|
|
82
|
+
// Set the type field on each tier info object
|
|
98
83
|
Object.entries(USER_SUBSCRIPTION_TYPES).forEach(
|
|
99
84
|
([type, info]) => (info.type = type as MembershipTier)
|
|
100
85
|
);
|
|
101
|
-
Object.entries(SERVICE_SUBSCRIPTION_TIERS).forEach(
|
|
102
|
-
([type, info]) => (info.type = type as ServiceSubscriptionTier)
|
|
103
|
-
);
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import { VenuePricingPlan as VenuePricingPlanOption } from "@prisma/client";
|
|
2
|
-
|
|
3
|
-
export type VenuePricingPlanData = {
|
|
4
|
-
name: string;
|
|
5
|
-
description: string;
|
|
6
|
-
percentageFee: number;
|
|
7
|
-
monthlyFee: number;
|
|
8
|
-
flatFee: number;
|
|
9
|
-
};
|
|
10
|
-
|
|
11
|
-
export type VenuePricingPlanMap = {
|
|
12
|
-
[key in VenuePricingPlanOption]: VenuePricingPlanData;
|
|
13
|
-
};
|
|
14
|
-
|
|
15
|
-
export const VENUE_PRICING_PLAN_DATA: VenuePricingPlanMap = {
|
|
16
|
-
[VenuePricingPlanOption.Percentage]: {
|
|
17
|
-
name: "Pay per booking",
|
|
18
|
-
description: "15% of each booking goes to Bash.",
|
|
19
|
-
percentageFee: 0.15,
|
|
20
|
-
monthlyFee: 0.0,
|
|
21
|
-
flatFee: 0.0,
|
|
22
|
-
},
|
|
23
|
-
[VenuePricingPlanOption.Subscription]: {
|
|
24
|
-
name: "Monthly subscription",
|
|
25
|
-
description: "Pay $100/month and keep 100% of each booking.",
|
|
26
|
-
percentageFee: 0.0,
|
|
27
|
-
monthlyFee: 100.0,
|
|
28
|
-
flatFee: 0.0,
|
|
29
|
-
},
|
|
30
|
-
} as const;
|