@bash-app/bash-common 30.75.2 → 30.78.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 +12 -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/recurrenceUtils.d.ts.map +1 -1
- package/dist/utils/recurrenceUtils.js +136 -2
- package/dist/utils/recurrenceUtils.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 +193 -107
- package/src/definitions.ts +180 -1
- package/src/extendedSchemas.ts +21 -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/recurrenceUtils.ts +180 -4
- package/src/utils/service/frontendServiceBookingUtils.ts +5 -1
- package/src/utils/userSubscriptionUtils.ts +20 -38
- package/src/utils/service/venueUtils.ts +0 -30
|
@@ -37,26 +37,58 @@ function getRecurringBashEventPossibleDatesTimesInternal(
|
|
|
37
37
|
recurrence: Recurrence | undefined | null,
|
|
38
38
|
toDate: boolean
|
|
39
39
|
): (DateTime | Date)[] {
|
|
40
|
+
console.log("🚨 getRecurringBashEventPossibleDatesTimesInternal called:", {
|
|
41
|
+
startDateTime,
|
|
42
|
+
recurrence,
|
|
43
|
+
toDate,
|
|
44
|
+
});
|
|
45
|
+
|
|
40
46
|
if (
|
|
41
47
|
!recurrence ||
|
|
42
48
|
!recurrence.frequency ||
|
|
43
49
|
recurrence.frequency === RecurringFrequency.Never
|
|
44
50
|
) {
|
|
51
|
+
console.log("🚨 Early return: No recurrence or frequency is Never");
|
|
45
52
|
return [];
|
|
46
53
|
}
|
|
47
54
|
|
|
48
55
|
let recurrenceDates: DateTime[] = [];
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
56
|
+
|
|
57
|
+
// For Monthly and Yearly, start from the event's actual date, not "today"
|
|
58
|
+
// This ensures we generate dates relative to the event's schedule
|
|
59
|
+
const shouldUseEventDate =
|
|
60
|
+
recurrence.frequency === RecurringFrequency.Monthly ||
|
|
61
|
+
recurrence.frequency === RecurringFrequency.Yearly;
|
|
62
|
+
|
|
63
|
+
const beginningDate = shouldUseEventDate
|
|
64
|
+
? (startDateTime ? dateTimeFromDate(startDateTime) as DateTime : DateTime.local())
|
|
65
|
+
: findEarliestPossibleBashEventDate(startDateTime) as DateTime;
|
|
66
|
+
|
|
67
|
+
console.log("🚨 beginningDate:", beginningDate?.toISO(), "shouldUseEventDate:", shouldUseEventDate);
|
|
52
68
|
|
|
53
69
|
switch (recurrence.frequency) {
|
|
70
|
+
case RecurringFrequency.Daily:
|
|
71
|
+
console.log("🚨 Calling getDailyRecurringDates");
|
|
72
|
+
recurrenceDates = getDailyRecurringDates(beginningDate, recurrence);
|
|
73
|
+
break;
|
|
54
74
|
case RecurringFrequency.Weekly:
|
|
75
|
+
console.log("🚨 Calling getWeeklyRecurringDates");
|
|
55
76
|
recurrenceDates = getWeeklyRecurringDates(beginningDate, recurrence);
|
|
56
77
|
break;
|
|
78
|
+
case RecurringFrequency.Monthly:
|
|
79
|
+
console.log("🚨 Calling getMonthlyRecurringDates");
|
|
80
|
+
recurrenceDates = getMonthlyRecurringDates(beginningDate, recurrence);
|
|
81
|
+
break;
|
|
82
|
+
case RecurringFrequency.Yearly:
|
|
83
|
+
console.log("🚨 Calling getYearlyRecurringDates");
|
|
84
|
+
recurrenceDates = getYearlyRecurringDates(beginningDate, recurrence);
|
|
85
|
+
break;
|
|
57
86
|
default:
|
|
58
|
-
console.error(`
|
|
87
|
+
console.error(`Unsupported frequency: ${recurrence.frequency}`);
|
|
59
88
|
}
|
|
89
|
+
|
|
90
|
+
console.log("🚨 recurrenceDates before mapping:", recurrenceDates.length, recurrenceDates.map(d => d.toISO()));
|
|
91
|
+
|
|
60
92
|
return recurrenceDates
|
|
61
93
|
.map((date: DateTime): string =>
|
|
62
94
|
date.toFormat(LUXON_DATETIME_FORMAT_ISO_LIKE)
|
|
@@ -75,6 +107,39 @@ function getRecurringBashEventPossibleDatesTimesInternal(
|
|
|
75
107
|
});
|
|
76
108
|
}
|
|
77
109
|
|
|
110
|
+
/**
|
|
111
|
+
* Get the daily recurring dates
|
|
112
|
+
* @param beginningDateTime The beginning DateTime of the event, adjusted to be no earlier than now.
|
|
113
|
+
* @param recurrence
|
|
114
|
+
*/
|
|
115
|
+
function getDailyRecurringDates(
|
|
116
|
+
beginningDateTime: DateTime,
|
|
117
|
+
recurrence: Recurrence
|
|
118
|
+
): DateTime[] {
|
|
119
|
+
if (recurrence.frequency !== RecurringFrequency.Daily) {
|
|
120
|
+
throw new Error(
|
|
121
|
+
`Cannot do a daily recurrence if the frequency isn't daily.`
|
|
122
|
+
);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
const interval = recurrence.interval ?? 1;
|
|
126
|
+
const recurrenceEnds = dateTimeFromDate(recurrence.ends).endOf("day");
|
|
127
|
+
const numberOfDays = recurrenceEnds.diff(beginningDateTime, "days").days;
|
|
128
|
+
const numberOfOccurrences = Math.ceil(numberOfDays / interval);
|
|
129
|
+
|
|
130
|
+
const recurrenceDates: DateTime[] = [];
|
|
131
|
+
let currentDate = beginningDateTime;
|
|
132
|
+
|
|
133
|
+
for (let i = 0; i < numberOfOccurrences && currentDate <= recurrenceEnds; i++) {
|
|
134
|
+
if (currentDate >= beginningDateTime) {
|
|
135
|
+
recurrenceDates.push(currentDate);
|
|
136
|
+
}
|
|
137
|
+
currentDate = currentDate.plus({ days: interval });
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
return recurrenceDates;
|
|
141
|
+
}
|
|
142
|
+
|
|
78
143
|
/**
|
|
79
144
|
* Get the weekly recurring dates
|
|
80
145
|
* @param beginningDateTime The beginning DateTime of the event, adjusted to be no earlier than now.
|
|
@@ -137,6 +202,117 @@ function getBeginningOfWeekInterval(
|
|
|
137
202
|
return date.endOf("week").plus({ days: numberOfDaysToAdd });
|
|
138
203
|
}
|
|
139
204
|
|
|
205
|
+
/**
|
|
206
|
+
* Get the monthly recurring dates
|
|
207
|
+
* @param beginningDateTime The beginning DateTime of the event, adjusted to be no earlier than now.
|
|
208
|
+
* @param recurrence
|
|
209
|
+
*/
|
|
210
|
+
function getMonthlyRecurringDates(
|
|
211
|
+
beginningDateTime: DateTime,
|
|
212
|
+
recurrence: Recurrence
|
|
213
|
+
): DateTime[] {
|
|
214
|
+
if (recurrence.frequency !== RecurringFrequency.Monthly) {
|
|
215
|
+
throw new Error(
|
|
216
|
+
`Cannot do a monthly recurrence if the frequency isn't monthly.`
|
|
217
|
+
);
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
const interval = recurrence.interval ?? 1;
|
|
221
|
+
const recurrenceEnds = dateTimeFromDate(recurrence.ends).endOf("day");
|
|
222
|
+
const dayOfMonth = recurrence.repeatOnDayOfMonth ?? beginningDateTime.day;
|
|
223
|
+
|
|
224
|
+
console.log("📅 Monthly recurrence debug:", {
|
|
225
|
+
beginningDateTime: beginningDateTime.toISO(),
|
|
226
|
+
recurrenceEnds: recurrenceEnds.toISO(),
|
|
227
|
+
dayOfMonth,
|
|
228
|
+
interval,
|
|
229
|
+
"beginningDateTime.day": beginningDateTime.day,
|
|
230
|
+
"beginningDateTime.daysInMonth": beginningDateTime.daysInMonth,
|
|
231
|
+
});
|
|
232
|
+
|
|
233
|
+
const recurrenceDates: DateTime[] = [];
|
|
234
|
+
let currentDate = beginningDateTime.set({ day: Math.min(dayOfMonth, beginningDateTime.daysInMonth || 31) });
|
|
235
|
+
|
|
236
|
+
console.log("📅 Initial currentDate:", currentDate.toISO());
|
|
237
|
+
|
|
238
|
+
// If the day of month is after the current day, start from the current month
|
|
239
|
+
if (currentDate < beginningDateTime) {
|
|
240
|
+
console.log("📅 currentDate < beginningDateTime, adding 1 month");
|
|
241
|
+
currentDate = currentDate.plus({ months: 1 });
|
|
242
|
+
currentDate = currentDate.set({ day: Math.min(dayOfMonth, currentDate.daysInMonth || 31) });
|
|
243
|
+
console.log("📅 New currentDate after adjustment:", currentDate.toISO());
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
let iterations = 0;
|
|
247
|
+
while (currentDate <= recurrenceEnds && iterations < 100) {
|
|
248
|
+
iterations++;
|
|
249
|
+
console.log(`📅 Iteration ${iterations}: currentDate=${currentDate.toISO()}, recurrenceEnds=${recurrenceEnds.toISO()}, currentDate <= recurrenceEnds: ${currentDate <= recurrenceEnds}`);
|
|
250
|
+
|
|
251
|
+
if (currentDate >= beginningDateTime) {
|
|
252
|
+
// Set the time to match the beginning time
|
|
253
|
+
const dateWithTime = dateTimeSetTime(currentDate, beginningDateTime);
|
|
254
|
+
console.log(`📅 Adding date: ${dateWithTime.toISO()}`);
|
|
255
|
+
recurrenceDates.push(dateWithTime);
|
|
256
|
+
}
|
|
257
|
+
currentDate = currentDate.plus({ months: interval });
|
|
258
|
+
// Handle months with fewer days (e.g., Feb 31 -> Feb 28/29)
|
|
259
|
+
currentDate = currentDate.set({ day: Math.min(dayOfMonth, currentDate.daysInMonth || 31) });
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
console.log("📅 Monthly recurrence complete:", {
|
|
263
|
+
totalDates: recurrenceDates.length,
|
|
264
|
+
dates: recurrenceDates.map(d => d.toISO()),
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
return recurrenceDates;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
/**
|
|
271
|
+
* Get the yearly recurring dates
|
|
272
|
+
* @param beginningDateTime The beginning DateTime of the event, adjusted to be no earlier than now.
|
|
273
|
+
* @param recurrence
|
|
274
|
+
*/
|
|
275
|
+
function getYearlyRecurringDates(
|
|
276
|
+
beginningDateTime: DateTime,
|
|
277
|
+
recurrence: Recurrence
|
|
278
|
+
): DateTime[] {
|
|
279
|
+
if (recurrence.frequency !== RecurringFrequency.Yearly) {
|
|
280
|
+
throw new Error(
|
|
281
|
+
`Cannot do a yearly recurrence if the frequency isn't yearly.`
|
|
282
|
+
);
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
const interval = recurrence.interval ?? 1;
|
|
286
|
+
const recurrenceEnds = dateTimeFromDate(recurrence.ends).endOf("day");
|
|
287
|
+
|
|
288
|
+
// Use the repeatYearlyDate if provided, otherwise use the beginning date
|
|
289
|
+
const baseDate = recurrence.repeatYearlyDate
|
|
290
|
+
? dateTimeFromDate(recurrence.repeatYearlyDate)
|
|
291
|
+
: beginningDateTime;
|
|
292
|
+
|
|
293
|
+
const recurrenceDates: DateTime[] = [];
|
|
294
|
+
let currentDate = baseDate.set({
|
|
295
|
+
year: beginningDateTime.year,
|
|
296
|
+
hour: beginningDateTime.hour,
|
|
297
|
+
minute: beginningDateTime.minute,
|
|
298
|
+
second: beginningDateTime.second
|
|
299
|
+
});
|
|
300
|
+
|
|
301
|
+
// If we've already passed this date this year, start from next year
|
|
302
|
+
if (currentDate < beginningDateTime) {
|
|
303
|
+
currentDate = currentDate.plus({ years: interval });
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
while (currentDate <= recurrenceEnds) {
|
|
307
|
+
if (currentDate >= beginningDateTime) {
|
|
308
|
+
recurrenceDates.push(currentDate);
|
|
309
|
+
}
|
|
310
|
+
currentDate = currentDate.plus({ years: interval });
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
return recurrenceDates;
|
|
314
|
+
}
|
|
315
|
+
|
|
140
316
|
export function freqToGrammarString(
|
|
141
317
|
freq: RecurringFrequency,
|
|
142
318
|
interval: number | undefined,
|
|
@@ -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;
|