@bash-app/bash-common 30.3.0 → 30.4.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/package.json +1 -1
- package/prisma/schema.prisma +140 -87
- package/scripts/symlinks.sh +2 -0
- package/src/definitions.ts +37 -43
- package/src/extendedSchemas.ts +122 -104
- package/src/index.ts +4 -3
- package/src/utils/arrayUtils.ts +8 -0
- package/src/utils/luxonUtils.ts +78 -15
- package/src/utils/service/apiServiceBookingApiUtils.ts +222 -0
- package/src/utils/service/frontendServiceBookingUtils.ts +310 -0
- package/src/utils/service/serviceBookingStatusUtils.ts +96 -27
- package/src/utils/service/serviceBookingTypes.ts +56 -0
- package/src/utils/service/serviceDBUtils.ts +35 -35
- package/src/utils/service/serviceRateDBUtils.ts +179 -179
- package/src/utils/service/serviceRateTypes.ts +18 -0
- package/src/utils/service/serviceRateUtils.ts +38 -64
- package/src/utils/service/serviceUtils.ts +35 -3
- package/src/utils/stringUtils.ts +1 -1
- package/src/utils/service/serviceBookingApiUtils.ts +0 -259
- package/src/utils/service/serviceBookingUtils.ts +0 -391
|
@@ -1,179 +1,179 @@
|
|
|
1
|
-
import { ServiceRate } from "@prisma/client";
|
|
2
|
-
import { ApiResult } from "../../definitions";
|
|
3
|
-
import { ServiceSpecialRatesExt } from "../../extendedSchemas";
|
|
4
|
-
import { convertDollarsToCents, convertCentsToDollars } from "../paymentUtils";
|
|
5
|
-
|
|
6
|
-
export function specialRateConvertToDb(
|
|
7
|
-
|
|
8
|
-
): Partial<ServiceSpecialRatesExt> {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
export function specialRateConvertFromDb(
|
|
15
|
-
|
|
16
|
-
): ServiceSpecialRatesExt {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
function specialRateConvertDateStringsToDb(
|
|
24
|
-
|
|
25
|
-
): Partial<ServiceSpecialRatesExt> {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
function specialRateConvertDateStringsFromDb(
|
|
65
|
-
|
|
66
|
-
): ServiceSpecialRatesExt {
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
function specialRateConvertRatesToDB(
|
|
107
|
-
|
|
108
|
-
): Partial<ServiceSpecialRatesExt> {
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
function specialRateConvertRatesFromDB(
|
|
118
|
-
|
|
119
|
-
): ServiceSpecialRatesExt {
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
export function generalRatesConvertRatesToDB(
|
|
129
|
-
|
|
130
|
-
): ServiceRate {
|
|
131
|
-
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
export function generalRatesConvertRatesToDBHelper(
|
|
135
|
-
|
|
136
|
-
): ServiceRate {
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
export function generalRatesConvertRatesFromDB(
|
|
158
|
-
|
|
159
|
-
): ServiceRate {
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
}
|
|
1
|
+
// import { ServiceRate } from "@prisma/client";
|
|
2
|
+
// import { ApiResult } from "../../definitions";
|
|
3
|
+
// import { ServiceSpecialRatesExt } from "../../extendedSchemas";
|
|
4
|
+
// import { convertDollarsToCents, convertCentsToDollars } from "../paymentUtils";
|
|
5
|
+
|
|
6
|
+
// export function specialRateConvertToDb(
|
|
7
|
+
// specialRate: Partial<ServiceSpecialRatesExt>
|
|
8
|
+
// ): Partial<ServiceSpecialRatesExt> {
|
|
9
|
+
// return specialRateConvertRatesToDB(
|
|
10
|
+
// specialRateConvertDateStringsToDb(structuredClone(specialRate))
|
|
11
|
+
// );
|
|
12
|
+
// }
|
|
13
|
+
|
|
14
|
+
// export function specialRateConvertFromDb(
|
|
15
|
+
// specialRate: ServiceSpecialRatesExt
|
|
16
|
+
// ): ServiceSpecialRatesExt {
|
|
17
|
+
// // console.log(`specialRateConvertFromDb`);
|
|
18
|
+
// return specialRateConvertRatesFromDB(
|
|
19
|
+
// specialRateConvertDateStringsFromDb(specialRate)
|
|
20
|
+
// );
|
|
21
|
+
// }
|
|
22
|
+
|
|
23
|
+
// function specialRateConvertDateStringsToDb(
|
|
24
|
+
// specialRate: Partial<ServiceSpecialRatesExt>
|
|
25
|
+
// ): Partial<ServiceSpecialRatesExt> {
|
|
26
|
+
// // const oldStart = new Date(specialRate.startDate!);
|
|
27
|
+
// // const oldEnd = new Date(specialRate.endDate!);
|
|
28
|
+
|
|
29
|
+
// // specialRate.startDate = dateTimeLocalToUTCDate(specialRate.startDate!);
|
|
30
|
+
// // specialRate.endDate = dateTimeLocalToUTCDate(specialRate.endDate!);
|
|
31
|
+
// // specialRate.startDate = normalizeDate(specialRate.startDate!);
|
|
32
|
+
// // specialRate.endDate = normalizeDate(specialRate.endDate!);
|
|
33
|
+
|
|
34
|
+
// // const localStart = dateTimeLocalFromUTCDate(new Date(specialRate.startDate!));
|
|
35
|
+
// // const localEnd = dateTimeLocalFromUTCDate(new Date(specialRate.endDate!));
|
|
36
|
+
|
|
37
|
+
// // console.log(
|
|
38
|
+
// // `specialRateConvertDateStringsToDb oldStart: ${oldStart?.toString()}`
|
|
39
|
+
// // );
|
|
40
|
+
// // console.log(
|
|
41
|
+
// // `specialRateConvertDateStringsToDb oldEnd: ${oldEnd?.toString()}`
|
|
42
|
+
// // );
|
|
43
|
+
// // console.log(
|
|
44
|
+
// // `specialRateConvertDateStringsToDb specialRate.startDate: ${specialRate.startDate?.toString()}`
|
|
45
|
+
// // );
|
|
46
|
+
// // console.log(
|
|
47
|
+
// // `specialRateConvertDateStringsToDb specialRate.endDate: ${specialRate.endDate?.toString()}`
|
|
48
|
+
// // );
|
|
49
|
+
// // console.log(
|
|
50
|
+
// // `specialRateConvertDateStringsToDb localStart: ${localStart?.toString()}`
|
|
51
|
+
// // );
|
|
52
|
+
// // console.log(
|
|
53
|
+
// // `specialRateConvertDateStringsToDb localEnd: ${localEnd?.toString()}`
|
|
54
|
+
// // );
|
|
55
|
+
|
|
56
|
+
// // const a = 3 + 4;
|
|
57
|
+
|
|
58
|
+
// // specialRate.startDate = specialRate.startDate.toISOString();
|
|
59
|
+
// // specialRate.endDate = specialRate.endDate.toISOString();
|
|
60
|
+
// // return specialRate;
|
|
61
|
+
// return specialRate;
|
|
62
|
+
// }
|
|
63
|
+
|
|
64
|
+
// function specialRateConvertDateStringsFromDb(
|
|
65
|
+
// specialRate: ServiceSpecialRatesExt
|
|
66
|
+
// ): ServiceSpecialRatesExt {
|
|
67
|
+
// // specialRate.startDate = localDateToUTC(new Date(specialRate.startDate));
|
|
68
|
+
// // specialRate.endDate = localDateToUTC(new Date(specialRate.endDate));
|
|
69
|
+
|
|
70
|
+
// //this shouldnt even be necessary as javascript dates are always stored in UTC timezone (they lack timezone information)
|
|
71
|
+
// // specialRate.startDate = ensureDateTimeIsLocalDateTime(
|
|
72
|
+
// // new Date(specialRate.startDate)
|
|
73
|
+
// // ).toDate();
|
|
74
|
+
// // specialRate.endDate = ensureDateTimeIsLocalDateTime(
|
|
75
|
+
// // new Date(specialRate.endDate)
|
|
76
|
+
// // ).toDate();
|
|
77
|
+
|
|
78
|
+
// specialRate.startDate = new Date(specialRate.startDate);
|
|
79
|
+
// specialRate.endDate = new Date(specialRate.endDate);
|
|
80
|
+
|
|
81
|
+
// // const oldStart = new Date(specialRate.startDate!);
|
|
82
|
+
// // const oldEnd = new Date(specialRate.endDate!);
|
|
83
|
+
|
|
84
|
+
// // specialRate.startDate = dateTimeLocalFromUTCDate(
|
|
85
|
+
// // new Date(specialRate.startDate)
|
|
86
|
+
// // );
|
|
87
|
+
// // specialRate.endDate = dateTimeLocalFromUTCDate(new Date(specialRate.endDate));
|
|
88
|
+
|
|
89
|
+
// // // specialRate.startDate = ensureDateTimeIsLocalDateTime(
|
|
90
|
+
// // // new Date(specialRate.startDate)
|
|
91
|
+
// // // ).toDate();
|
|
92
|
+
// // // specialRate.endDate = ensureDateTimeIsLocalDateTime(
|
|
93
|
+
// // // new Date(specialRate.endDate)
|
|
94
|
+
// // // ).toDate();
|
|
95
|
+
|
|
96
|
+
// // // specialRate.startDate = localDateToUTC(new Date(specialRate.startDate));
|
|
97
|
+
// // // specialRate.endDate = localDateToUTC(new Date(specialRate.endDate));
|
|
98
|
+
|
|
99
|
+
// // const date2 = normalizeDate(specialRate.startDate)!;
|
|
100
|
+
// // const date3 = normalizeDate(specialRate.endDate)!;
|
|
101
|
+
|
|
102
|
+
// // const a = 3 + 4;
|
|
103
|
+
// return specialRate;
|
|
104
|
+
// }
|
|
105
|
+
|
|
106
|
+
// function specialRateConvertRatesToDB(
|
|
107
|
+
// specialRate: Partial<ServiceSpecialRatesExt>
|
|
108
|
+
// ): Partial<ServiceSpecialRatesExt> {
|
|
109
|
+
// if (specialRate.serviceRate) {
|
|
110
|
+
// specialRate.serviceRate = generalRatesConvertRatesToDB(
|
|
111
|
+
// specialRate.serviceRate
|
|
112
|
+
// ) as ServiceRate;
|
|
113
|
+
// }
|
|
114
|
+
// return specialRate;
|
|
115
|
+
// }
|
|
116
|
+
|
|
117
|
+
// function specialRateConvertRatesFromDB(
|
|
118
|
+
// specialRate: ServiceSpecialRatesExt
|
|
119
|
+
// ): ServiceSpecialRatesExt {
|
|
120
|
+
// if (specialRate.serviceRate) {
|
|
121
|
+
// specialRate.serviceRate = generalRatesConvertRatesFromDB(
|
|
122
|
+
// specialRate.serviceRate
|
|
123
|
+
// );
|
|
124
|
+
// }
|
|
125
|
+
// return specialRate;
|
|
126
|
+
// }
|
|
127
|
+
|
|
128
|
+
// export function generalRatesConvertRatesToDB(
|
|
129
|
+
// generalRate: ServiceRate
|
|
130
|
+
// ): ServiceRate {
|
|
131
|
+
// return generalRatesConvertRatesToDBHelper(structuredClone(generalRate));
|
|
132
|
+
// }
|
|
133
|
+
|
|
134
|
+
// export function generalRatesConvertRatesToDBHelper(
|
|
135
|
+
// generalRate: ServiceRate
|
|
136
|
+
// ): ServiceRate {
|
|
137
|
+
// // console.log(
|
|
138
|
+
// // `generalRatesConvertRatesToDBHelper A: ${JSON.stringify(generalRate)}`
|
|
139
|
+
// // );
|
|
140
|
+
// if (generalRate?.dailyRate) {
|
|
141
|
+
// generalRate.dailyRate = convertDollarsToCents(generalRate.dailyRate);
|
|
142
|
+
// }
|
|
143
|
+
// if (generalRate?.hourlyRate) {
|
|
144
|
+
// generalRate.hourlyRate = convertDollarsToCents(generalRate.hourlyRate);
|
|
145
|
+
// }
|
|
146
|
+
// if (generalRate?.cleaningFeePerBooking) {
|
|
147
|
+
// generalRate.cleaningFeePerBooking = convertDollarsToCents(
|
|
148
|
+
// generalRate.cleaningFeePerBooking
|
|
149
|
+
// );
|
|
150
|
+
// }
|
|
151
|
+
// // console.log(
|
|
152
|
+
// // `generalRatesConvertRatesToDBHelper B: ${JSON.stringify(generalRate)}`
|
|
153
|
+
// // );
|
|
154
|
+
// return generalRate;
|
|
155
|
+
// }
|
|
156
|
+
|
|
157
|
+
// export function generalRatesConvertRatesFromDB(
|
|
158
|
+
// generalRate: ServiceRate
|
|
159
|
+
// ): ServiceRate {
|
|
160
|
+
// // console.log(
|
|
161
|
+
// // `generalRatesConvertRatesFromDB A: ${JSON.stringify(generalRate)}`
|
|
162
|
+
// // );
|
|
163
|
+
// // console.log(`specialRateConvertRatesFromDB`);
|
|
164
|
+
// if (generalRate?.dailyRate) {
|
|
165
|
+
// generalRate.dailyRate = convertCentsToDollars(generalRate.dailyRate);
|
|
166
|
+
// }
|
|
167
|
+
// if (generalRate?.hourlyRate) {
|
|
168
|
+
// generalRate.hourlyRate = convertCentsToDollars(generalRate.hourlyRate);
|
|
169
|
+
// }
|
|
170
|
+
// if (generalRate?.cleaningFeePerBooking) {
|
|
171
|
+
// generalRate.cleaningFeePerBooking = convertCentsToDollars(
|
|
172
|
+
// generalRate.cleaningFeePerBooking
|
|
173
|
+
// );
|
|
174
|
+
// }
|
|
175
|
+
// // console.log(
|
|
176
|
+
// // `generalRatesConvertRatesFromDB B: ${JSON.stringify(generalRate)}`
|
|
177
|
+
// // );
|
|
178
|
+
// return generalRate;
|
|
179
|
+
// }
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ServiceDailyRatesExt,
|
|
3
|
+
ServiceSpecialRatesExt,
|
|
4
|
+
} from "../../extendedSchemas";
|
|
5
|
+
import { LuxonDateRange } from "../luxonUtils";
|
|
6
|
+
|
|
7
|
+
export type ServiceDailyRatesExtT = Omit<
|
|
8
|
+
ServiceDailyRatesExt,
|
|
9
|
+
"startDate" | "endDate"
|
|
10
|
+
> & {
|
|
11
|
+
dateTimeRange: LuxonDateRange;
|
|
12
|
+
};
|
|
13
|
+
export type ServiceSpecialRatesExtT = Omit<
|
|
14
|
+
ServiceSpecialRatesExt,
|
|
15
|
+
"startDate" | "endDate"
|
|
16
|
+
> & {
|
|
17
|
+
dateTimeRange: LuxonDateRange;
|
|
18
|
+
};
|
|
@@ -1,4 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
Service,
|
|
3
|
+
ServiceRate,
|
|
4
|
+
ServiceRatePricingType,
|
|
5
|
+
ServiceRateType,
|
|
6
|
+
} from "@prisma/client";
|
|
2
7
|
import {
|
|
3
8
|
ServiceDailyRatesExt,
|
|
4
9
|
ServiceRateExt,
|
|
@@ -16,29 +21,18 @@ import {
|
|
|
16
21
|
dateTimeRangeHours,
|
|
17
22
|
} from "../luxonUtils";
|
|
18
23
|
import { DateTime } from "luxon";
|
|
24
|
+
import {
|
|
25
|
+
ServiceDailyRatesExtT,
|
|
26
|
+
ServiceSpecialRatesExtT,
|
|
27
|
+
} from "./serviceRateTypes";
|
|
28
|
+
import { ServiceBookingPriceBreakdownBaseT } from "./serviceBookingTypes";
|
|
19
29
|
|
|
20
30
|
export const SERVICE_DAILY_RATE_HOURS_MIN = 8;
|
|
21
31
|
|
|
22
|
-
export type ServiceRatePricingType = "Hourly" | "Daily";
|
|
23
|
-
|
|
24
|
-
export type ServiceDailyRatesExtLuxon = Exclude<
|
|
25
|
-
ServiceDailyRatesExt,
|
|
26
|
-
"startDate" | "endDate"
|
|
27
|
-
> & {
|
|
28
|
-
dateTimeRange: LuxonDateRange;
|
|
29
|
-
};
|
|
30
|
-
|
|
31
|
-
export type ServiceSpecialRatesExtLuxon = Exclude<
|
|
32
|
-
ServiceSpecialRatesExt,
|
|
33
|
-
"startDate" | "endDate"
|
|
34
|
-
> & {
|
|
35
|
-
dateTimeRange: LuxonDateRange;
|
|
36
|
-
};
|
|
37
|
-
|
|
38
32
|
export function serviceRateToLuxonRate(
|
|
39
33
|
rate: ServiceDailyRatesExt | ServiceSpecialRatesExt,
|
|
40
34
|
timezone: string | undefined | null
|
|
41
|
-
):
|
|
35
|
+
): ServiceDailyRatesExtT | ServiceSpecialRatesExtT {
|
|
42
36
|
const { startDate, endDate, ...rest } = rate;
|
|
43
37
|
|
|
44
38
|
return {
|
|
@@ -47,47 +41,27 @@ export function serviceRateToLuxonRate(
|
|
|
47
41
|
start: dateTimeFromDate(startDate, undefined, timezone ?? undefined),
|
|
48
42
|
end: dateTimeFromDate(endDate, undefined, timezone ?? undefined),
|
|
49
43
|
},
|
|
50
|
-
} as
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
export const ServiceRatePricingType = {
|
|
54
|
-
Hourly: "Hourly" as ServiceRatePricingType,
|
|
55
|
-
Daily: "Daily" as ServiceRatePricingType,
|
|
56
|
-
} as const;
|
|
57
|
-
|
|
58
|
-
export interface ServiceRatePricingInfo {
|
|
59
|
-
rateType: ServiceRateType;
|
|
60
|
-
pricingType: ServiceRatePricingType;
|
|
61
|
-
|
|
62
|
-
dateTimeRange: LuxonDateRange;
|
|
63
|
-
|
|
64
|
-
hours: number; //number of hours removed from total
|
|
65
|
-
unitCount: number; // number of days (8 hour blocks)/hours used unitCount * rate = piTotal
|
|
66
|
-
rate: number;
|
|
67
|
-
piTotal: number;
|
|
68
|
-
|
|
69
|
-
// cleaningFee: number; //only aplicable to generalRate,
|
|
70
|
-
// minimumTimeBlockHours: number; //only aplicable to generalRate
|
|
44
|
+
} as ServiceDailyRatesExtT | ServiceSpecialRatesExtT;
|
|
71
45
|
}
|
|
72
46
|
|
|
73
|
-
export function
|
|
74
|
-
pricingInfo:
|
|
47
|
+
export function serviceBookingPriceBreakdownGetTypeText(
|
|
48
|
+
pricingInfo: ServiceBookingPriceBreakdownBaseT
|
|
75
49
|
) {
|
|
76
50
|
return `${pricingInfo.rateType} ${pricingInfo.pricingType}`;
|
|
77
51
|
}
|
|
78
52
|
|
|
79
|
-
export function
|
|
53
|
+
export function serviceBookingCalcDayPriceBreakdown(
|
|
80
54
|
dateTimeRange: LuxonDateRange,
|
|
81
55
|
serviceRates: (ServiceRate | null | undefined)[],
|
|
82
56
|
isFullDay: boolean,
|
|
83
57
|
hoursRemaining: number
|
|
84
|
-
):
|
|
85
|
-
let pricingInfo:
|
|
58
|
+
): ServiceBookingPriceBreakdownBaseT {
|
|
59
|
+
let pricingInfo: ServiceBookingPriceBreakdownBaseT = {
|
|
86
60
|
rateType: "General",
|
|
87
61
|
pricingType: "Hourly",
|
|
88
62
|
hours: 0,
|
|
89
|
-
|
|
90
|
-
|
|
63
|
+
piTotalCents: 0,
|
|
64
|
+
rateCents: 0,
|
|
91
65
|
unitCount: 0,
|
|
92
66
|
dateTimeRange: dateTimeRange,
|
|
93
67
|
// cleaningFee: 0,
|
|
@@ -98,12 +72,12 @@ export function serviceRatesToPricingInfo(
|
|
|
98
72
|
const validServiceRate = serviceRates.find(
|
|
99
73
|
(rate) =>
|
|
100
74
|
rate != null &&
|
|
101
|
-
((isFullDay && rate.
|
|
102
|
-
(!isFullDay && rate.
|
|
75
|
+
((isFullDay && rate.dailyRateCents != null) ||
|
|
76
|
+
(!isFullDay && rate.hourlyRateCents != null))
|
|
103
77
|
);
|
|
104
78
|
|
|
105
79
|
if (isFullDay && !validServiceRate) {
|
|
106
|
-
return
|
|
80
|
+
return serviceBookingCalcDayPriceBreakdown(
|
|
107
81
|
//default to non-daily rate if it is null
|
|
108
82
|
dateTimeRange,
|
|
109
83
|
serviceRates,
|
|
@@ -127,15 +101,15 @@ export function serviceRatesToPricingInfo(
|
|
|
127
101
|
const days = Math.floor(hoursRemaining / SERVICE_DAILY_RATE_HOURS_MIN);
|
|
128
102
|
pricingInfo.unitCount = days;
|
|
129
103
|
pricingInfo.hours = pricingInfo.unitCount * SERVICE_DAILY_RATE_HOURS_MIN;
|
|
130
|
-
pricingInfo.
|
|
104
|
+
pricingInfo.rateCents = validServiceRate.dailyRateCents ?? 0;
|
|
131
105
|
} else {
|
|
132
106
|
pricingInfo.pricingType = ServiceRatePricingType.Hourly;
|
|
133
107
|
pricingInfo.unitCount = hoursRemaining;
|
|
134
108
|
pricingInfo.hours = pricingInfo.unitCount;
|
|
135
|
-
pricingInfo.
|
|
109
|
+
pricingInfo.rateCents = validServiceRate.hourlyRateCents ?? 0;
|
|
136
110
|
}
|
|
137
111
|
|
|
138
|
-
pricingInfo.
|
|
112
|
+
pricingInfo.piTotalCents = pricingInfo.unitCount * pricingInfo.rateCents;
|
|
139
113
|
|
|
140
114
|
pricingInfo.dateTimeRange = {
|
|
141
115
|
start: dateTimeRange.start,
|
|
@@ -148,12 +122,12 @@ export function serviceRatesToPricingInfo(
|
|
|
148
122
|
export function getServiceRatePricingInfo(
|
|
149
123
|
dateTimeRange: LuxonDateRange,
|
|
150
124
|
generalRate: ServiceRate | null | undefined,
|
|
151
|
-
dailyRates:
|
|
152
|
-
specialRates:
|
|
125
|
+
dailyRates: ServiceDailyRatesExtT[], //filtered to remove unavailable dates
|
|
126
|
+
specialRates: ServiceSpecialRatesExtT[], //filtered to remove unavailable dates
|
|
153
127
|
// overlappingBusinessHours: LuxonDateRange[] | null,
|
|
154
128
|
timezone: string | null | undefined,
|
|
155
129
|
hoursRemaining: number
|
|
156
|
-
):
|
|
130
|
+
): ServiceBookingPriceBreakdownBaseT {
|
|
157
131
|
const specialRate = specialRates?.at(-1); //last element
|
|
158
132
|
const dailyRate = dailyRates?.at(-1); //last element
|
|
159
133
|
// const specialRate = findRateByDate(specialRates, dateTimeRange, timezone) as
|
|
@@ -181,7 +155,7 @@ export function getServiceRatePricingInfo(
|
|
|
181
155
|
generalRate,
|
|
182
156
|
].filter((rate) => !!rate);
|
|
183
157
|
|
|
184
|
-
return
|
|
158
|
+
return serviceBookingCalcDayPriceBreakdown(
|
|
185
159
|
dateTimeRange,
|
|
186
160
|
rates,
|
|
187
161
|
isFullDay,
|
|
@@ -191,8 +165,8 @@ export function getServiceRatePricingInfo(
|
|
|
191
165
|
|
|
192
166
|
export interface ServiceRatesLuxon {
|
|
193
167
|
generalRate: ServiceRate | null | undefined;
|
|
194
|
-
specialRates:
|
|
195
|
-
dailyRates:
|
|
168
|
+
specialRates: ServiceSpecialRatesExtT[];
|
|
169
|
+
dailyRates: ServiceDailyRatesExtT[];
|
|
196
170
|
}
|
|
197
171
|
|
|
198
172
|
export function serviceGetFilteredRates(
|
|
@@ -246,14 +220,14 @@ export function serviceRatesHasRates(rates: ServiceRatesLuxon) {
|
|
|
246
220
|
const { generalRate, specialRates, dailyRates } = rates;
|
|
247
221
|
|
|
248
222
|
const isValidSpecialOrDailyRate = (
|
|
249
|
-
rate:
|
|
223
|
+
rate: ServiceSpecialRatesExtT | ServiceDailyRatesExtT
|
|
250
224
|
) =>
|
|
251
225
|
rate?.serviceRate &&
|
|
252
|
-
((rate.serviceRate?.
|
|
253
|
-
(rate.serviceRate?.
|
|
226
|
+
((rate.serviceRate?.dailyRateCents ?? 0) > 0 ||
|
|
227
|
+
(rate.serviceRate?.hourlyRateCents ?? 0) > 0);
|
|
254
228
|
|
|
255
229
|
const isValidGeneralRate = (rate: ServiceRate | undefined | null) =>
|
|
256
|
-
rate && ((rate.
|
|
230
|
+
rate && ((rate.dailyRateCents ?? 0) > 0 || (rate.hourlyRateCents ?? 0) > 0);
|
|
257
231
|
|
|
258
232
|
const hasValidSpecialOrDailyRate = [...specialRates, ...dailyRates].some(
|
|
259
233
|
isValidSpecialOrDailyRate
|
|
@@ -276,7 +250,7 @@ export function serviceRatesToLuxonRates(
|
|
|
276
250
|
?.filter((specialRate) => specialRate.isAvailable)
|
|
277
251
|
?.map(
|
|
278
252
|
(rate) =>
|
|
279
|
-
serviceRateToLuxonRate(rate, timezone) as
|
|
253
|
+
serviceRateToLuxonRate(rate, timezone) as ServiceSpecialRatesExtT
|
|
280
254
|
) ?? [];
|
|
281
255
|
|
|
282
256
|
const dailyRatesLuxon =
|
|
@@ -284,7 +258,7 @@ export function serviceRatesToLuxonRates(
|
|
|
284
258
|
const newRate = serviceRateToLuxonRate(
|
|
285
259
|
rate,
|
|
286
260
|
timezone
|
|
287
|
-
) as
|
|
261
|
+
) as ServiceDailyRatesExtT;
|
|
288
262
|
|
|
289
263
|
dateTimeRanges.forEach((range) => {
|
|
290
264
|
newRate.dateTimeRange = dateRangeNormalizeToMWY(
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import {
|
|
2
|
+
Service,
|
|
2
3
|
ServiceCancellationPolicy as ServiceCancellationPolicyOption,
|
|
3
4
|
ServiceSubscriptionStatus,
|
|
4
5
|
ServiceTypes,
|
|
@@ -135,6 +136,39 @@ export function serviceSubscriptionIsActive(
|
|
|
135
136
|
).includes(status);
|
|
136
137
|
}
|
|
137
138
|
|
|
139
|
+
export interface ServiceSpecificTypeInfo {
|
|
140
|
+
serviceId: string;
|
|
141
|
+
serviceType: ServiceTypes;
|
|
142
|
+
specificFieldName: ServiceSpecificName;
|
|
143
|
+
specificId: string;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
export function serviceGetSpecificType<BookingType extends Service>(
|
|
147
|
+
service: BookingType
|
|
148
|
+
): ServiceSpecificTypeInfo | null {
|
|
149
|
+
if (service.serviceType == null) {
|
|
150
|
+
// throw new Error(`serviceGetSpecificType invalid serviceType`);
|
|
151
|
+
return null;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
const specificFieldName = serviceTypeToField(service.serviceType);
|
|
155
|
+
if (specificFieldName == null) {
|
|
156
|
+
// throw new Error(`serviceGetSpecificType invalid serviceType`);
|
|
157
|
+
return null;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
const specificId = service[
|
|
161
|
+
`${specificFieldName}Id` as keyof BookingType
|
|
162
|
+
] as string;
|
|
163
|
+
|
|
164
|
+
return {
|
|
165
|
+
serviceId: service.id,
|
|
166
|
+
serviceType: service.serviceType,
|
|
167
|
+
specificFieldName: specificFieldName,
|
|
168
|
+
specificId: specificId,
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
|
|
138
172
|
export function serviceDetailUrl(
|
|
139
173
|
serviceId: string,
|
|
140
174
|
serviceType: string,
|
|
@@ -178,8 +212,6 @@ export const specificServiceMap: Record<ServiceTypes, ServiceSpecificName> = {
|
|
|
178
212
|
Organizations: "organization",
|
|
179
213
|
} as const;
|
|
180
214
|
|
|
181
|
-
|
|
182
|
-
serviceType: ServiceTypes
|
|
183
|
-
): ServiceSpecificName => {
|
|
215
|
+
const serviceTypeToField = (serviceType: ServiceTypes): ServiceSpecificName => {
|
|
184
216
|
return specificServiceMap[serviceType];
|
|
185
217
|
};
|
package/src/utils/stringUtils.ts
CHANGED
|
@@ -2,7 +2,7 @@ export function formatString<T extends Record<string, string | number>>(
|
|
|
2
2
|
template: string,
|
|
3
3
|
data: T
|
|
4
4
|
): string {
|
|
5
|
-
return template.replace(
|
|
5
|
+
return template.replace(/\${(\w+)}/g, (_, key) => {
|
|
6
6
|
return data[key] !== undefined ? data[key].toString() : "";
|
|
7
7
|
});
|
|
8
8
|
}
|