@blackcode_sa/metaestetics-api 1.13.5 → 1.13.8
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/admin/index.d.mts +20 -1
- package/dist/admin/index.d.ts +20 -1
- package/dist/admin/index.js +217 -1
- package/dist/admin/index.mjs +217 -1
- package/dist/index.d.mts +26 -3
- package/dist/index.d.ts +26 -3
- package/dist/index.js +168 -6
- package/dist/index.mjs +168 -6
- package/package.json +121 -121
- package/src/__mocks__/firstore.ts +10 -10
- package/src/admin/aggregation/README.md +79 -79
- package/src/admin/aggregation/appointment/README.md +128 -128
- package/src/admin/aggregation/appointment/appointment.aggregation.service.ts +1984 -1984
- package/src/admin/aggregation/appointment/index.ts +1 -1
- package/src/admin/aggregation/clinic/README.md +52 -52
- package/src/admin/aggregation/clinic/clinic.aggregation.service.ts +966 -703
- package/src/admin/aggregation/clinic/index.ts +1 -1
- package/src/admin/aggregation/forms/README.md +13 -13
- package/src/admin/aggregation/forms/filled-forms.aggregation.service.ts +322 -322
- package/src/admin/aggregation/forms/index.ts +1 -1
- package/src/admin/aggregation/index.ts +8 -8
- package/src/admin/aggregation/patient/README.md +27 -27
- package/src/admin/aggregation/patient/index.ts +1 -1
- package/src/admin/aggregation/patient/patient.aggregation.service.ts +141 -141
- package/src/admin/aggregation/practitioner/README.md +42 -42
- package/src/admin/aggregation/practitioner/index.ts +1 -1
- package/src/admin/aggregation/practitioner/practitioner.aggregation.service.ts +433 -433
- package/src/admin/aggregation/practitioner-invite/index.ts +1 -1
- package/src/admin/aggregation/practitioner-invite/practitioner-invite.aggregation.service.ts +961 -961
- package/src/admin/aggregation/procedure/README.md +43 -43
- package/src/admin/aggregation/procedure/index.ts +1 -1
- package/src/admin/aggregation/procedure/procedure.aggregation.service.ts +702 -702
- package/src/admin/aggregation/reviews/index.ts +1 -1
- package/src/admin/aggregation/reviews/reviews.aggregation.service.ts +689 -689
- package/src/admin/analytics/analytics.admin.service.ts +278 -278
- package/src/admin/analytics/index.ts +2 -2
- package/src/admin/booking/README.md +125 -125
- package/src/admin/booking/booking.admin.ts +1037 -1037
- package/src/admin/booking/booking.calculator.ts +712 -712
- package/src/admin/booking/booking.types.ts +59 -59
- package/src/admin/booking/index.ts +3 -3
- package/src/admin/booking/timezones-problem.md +185 -185
- package/src/admin/calendar/README.md +7 -7
- package/src/admin/calendar/calendar.admin.service.ts +345 -345
- package/src/admin/calendar/index.ts +1 -1
- package/src/admin/documentation-templates/document-manager.admin.ts +260 -260
- package/src/admin/documentation-templates/index.ts +1 -1
- package/src/admin/free-consultation/free-consultation-utils.admin.ts +148 -148
- package/src/admin/free-consultation/index.ts +1 -1
- package/src/admin/index.ts +81 -81
- package/src/admin/logger/index.ts +78 -78
- package/src/admin/mailing/README.md +95 -95
- package/src/admin/mailing/appointment/appointment.mailing.service.ts +732 -732
- package/src/admin/mailing/appointment/index.ts +1 -1
- package/src/admin/mailing/appointment/templates/patient/appointment-confirmed.html +40 -40
- package/src/admin/mailing/base.mailing.service.ts +208 -208
- package/src/admin/mailing/index.ts +3 -3
- package/src/admin/mailing/practitionerInvite/existing-practitioner-invite.mailing.ts +611 -611
- package/src/admin/mailing/practitionerInvite/index.ts +2 -2
- package/src/admin/mailing/practitionerInvite/practitionerInvite.mailing.ts +395 -395
- package/src/admin/mailing/practitionerInvite/templates/existing-practitioner-invitation.template.ts +155 -155
- package/src/admin/mailing/practitionerInvite/templates/invitation.template.ts +101 -101
- package/src/admin/mailing/practitionerInvite/templates/invite-accepted-notification.template.ts +228 -228
- package/src/admin/mailing/practitionerInvite/templates/invite-rejected-notification.template.ts +242 -242
- package/src/admin/notifications/index.ts +1 -1
- package/src/admin/notifications/notifications.admin.ts +710 -710
- package/src/admin/requirements/README.md +128 -128
- package/src/admin/requirements/index.ts +1 -1
- package/src/admin/requirements/patient-requirements.admin.service.ts +475 -475
- package/src/admin/users/index.ts +1 -1
- package/src/admin/users/user-profile.admin.ts +405 -405
- package/src/backoffice/constants/certification.constants.ts +13 -13
- package/src/backoffice/constants/index.ts +1 -1
- package/src/backoffice/errors/backoffice.errors.ts +181 -181
- package/src/backoffice/errors/index.ts +1 -1
- package/src/backoffice/expo-safe/README.md +26 -26
- package/src/backoffice/expo-safe/index.ts +41 -41
- package/src/backoffice/index.ts +5 -5
- package/src/backoffice/services/FIXES_README.md +102 -102
- package/src/backoffice/services/README.md +57 -57
- package/src/backoffice/services/analytics.service.proposal.md +863 -863
- package/src/backoffice/services/analytics.service.summary.md +143 -143
- package/src/backoffice/services/brand.service.ts +256 -256
- package/src/backoffice/services/category.service.ts +384 -384
- package/src/backoffice/services/constants.service.ts +385 -385
- package/src/backoffice/services/documentation-template.service.ts +202 -202
- package/src/backoffice/services/index.ts +10 -10
- package/src/backoffice/services/migrate-products.ts +116 -116
- package/src/backoffice/services/product.service.ts +553 -553
- package/src/backoffice/services/requirement.service.ts +235 -235
- package/src/backoffice/services/subcategory.service.ts +461 -461
- package/src/backoffice/services/technology.service.ts +1151 -1151
- package/src/backoffice/types/README.md +12 -12
- package/src/backoffice/types/admin-constants.types.ts +69 -69
- package/src/backoffice/types/brand.types.ts +29 -29
- package/src/backoffice/types/category.types.ts +67 -67
- package/src/backoffice/types/documentation-templates.types.ts +28 -28
- package/src/backoffice/types/index.ts +10 -10
- package/src/backoffice/types/procedure-product.types.ts +38 -38
- package/src/backoffice/types/product.types.ts +240 -240
- package/src/backoffice/types/requirement.types.ts +63 -63
- package/src/backoffice/types/static/README.md +18 -18
- package/src/backoffice/types/static/blocking-condition.types.ts +21 -21
- package/src/backoffice/types/static/certification.types.ts +37 -37
- package/src/backoffice/types/static/contraindication.types.ts +19 -19
- package/src/backoffice/types/static/index.ts +6 -6
- package/src/backoffice/types/static/pricing.types.ts +16 -16
- package/src/backoffice/types/static/procedure-family.types.ts +14 -14
- package/src/backoffice/types/static/treatment-benefit.types.ts +22 -22
- package/src/backoffice/types/subcategory.types.ts +34 -34
- package/src/backoffice/types/technology.types.ts +168 -168
- package/src/backoffice/validations/index.ts +1 -1
- package/src/backoffice/validations/schemas.ts +164 -164
- package/src/config/__mocks__/firebase.ts +99 -99
- package/src/config/firebase.ts +78 -78
- package/src/config/index.ts +9 -9
- package/src/errors/auth.error.ts +6 -6
- package/src/errors/auth.errors.ts +211 -200
- package/src/errors/clinic.errors.ts +32 -32
- package/src/errors/firebase.errors.ts +47 -47
- package/src/errors/user.errors.ts +99 -99
- package/src/index.backup.ts +407 -407
- package/src/index.ts +6 -6
- package/src/locales/en.ts +31 -31
- package/src/recommender/admin/index.ts +1 -1
- package/src/recommender/admin/services/recommender.service.admin.ts +5 -5
- package/src/recommender/front/index.ts +1 -1
- package/src/recommender/front/services/onboarding.service.ts +5 -5
- package/src/recommender/front/services/recommender.service.ts +3 -3
- package/src/recommender/index.ts +1 -1
- package/src/services/PATIENTAUTH.MD +197 -197
- package/src/services/README.md +106 -106
- package/src/services/__tests__/auth/auth.mock.test.ts +17 -17
- package/src/services/__tests__/auth/auth.setup.ts +293 -293
- package/src/services/__tests__/auth.service.test.ts +346 -346
- package/src/services/__tests__/base.service.test.ts +77 -77
- package/src/services/__tests__/user.service.test.ts +528 -528
- package/src/services/analytics/ARCHITECTURE.md +199 -199
- package/src/services/analytics/CLOUD_FUNCTIONS.md +225 -225
- package/src/services/analytics/GROUPED_ANALYTICS.md +501 -501
- package/src/services/analytics/QUICK_START.md +393 -393
- package/src/services/analytics/README.md +304 -304
- package/src/services/analytics/SUMMARY.md +141 -141
- package/src/services/analytics/TRENDS.md +380 -380
- package/src/services/analytics/USAGE_GUIDE.md +518 -518
- package/src/services/analytics/analytics-cloud.service.ts +222 -222
- package/src/services/analytics/analytics.service.ts +2142 -2142
- package/src/services/analytics/index.ts +4 -4
- package/src/services/analytics/review-analytics.service.ts +941 -941
- package/src/services/analytics/utils/appointment-filtering.utils.ts +138 -138
- package/src/services/analytics/utils/cost-calculation.utils.ts +182 -182
- package/src/services/analytics/utils/grouping.utils.ts +434 -434
- package/src/services/analytics/utils/stored-analytics.utils.ts +347 -347
- package/src/services/analytics/utils/time-calculation.utils.ts +186 -186
- package/src/services/analytics/utils/trend-calculation.utils.ts +200 -200
- package/src/services/appointment/README.md +17 -17
- package/src/services/appointment/appointment.service.ts +2558 -2558
- package/src/services/appointment/index.ts +1 -1
- package/src/services/appointment/utils/appointment.utils.ts +552 -552
- package/src/services/appointment/utils/extended-procedure.utils.ts +314 -314
- package/src/services/appointment/utils/form-initialization.utils.ts +225 -225
- package/src/services/appointment/utils/recommended-procedure.utils.ts +195 -195
- package/src/services/appointment/utils/zone-management.utils.ts +353 -353
- package/src/services/appointment/utils/zone-photo.utils.ts +152 -152
- package/src/services/auth/auth.service.ts +1043 -989
- package/src/services/auth/auth.v2.service.ts +961 -961
- package/src/services/auth/index.ts +7 -7
- package/src/services/auth/utils/error.utils.ts +90 -90
- package/src/services/auth/utils/firebase.utils.ts +49 -49
- package/src/services/auth/utils/index.ts +21 -21
- package/src/services/auth/utils/practitioner.utils.ts +125 -125
- package/src/services/base.service.ts +41 -41
- package/src/services/calendar/calendar.service.ts +1077 -1077
- package/src/services/calendar/calendar.v2.service.ts +1683 -1683
- package/src/services/calendar/calendar.v3.service.ts +313 -313
- package/src/services/calendar/externalCalendar.service.ts +178 -178
- package/src/services/calendar/index.ts +5 -5
- package/src/services/calendar/synced-calendars.service.ts +743 -743
- package/src/services/calendar/utils/appointment.utils.ts +265 -265
- package/src/services/calendar/utils/calendar-event.utils.ts +646 -646
- package/src/services/calendar/utils/clinic.utils.ts +237 -237
- package/src/services/calendar/utils/docs.utils.ts +157 -157
- package/src/services/calendar/utils/google-calendar.utils.ts +697 -697
- package/src/services/calendar/utils/index.ts +8 -8
- package/src/services/calendar/utils/patient.utils.ts +198 -198
- package/src/services/calendar/utils/practitioner.utils.ts +221 -221
- package/src/services/calendar/utils/synced-calendar.utils.ts +472 -472
- package/src/services/clinic/README.md +204 -204
- package/src/services/clinic/__tests__/clinic-admin.service.test.ts +287 -287
- package/src/services/clinic/__tests__/clinic-group.service.test.ts +352 -352
- package/src/services/clinic/__tests__/clinic.service.test.ts +354 -354
- package/src/services/clinic/billing-transactions.service.ts +217 -217
- package/src/services/clinic/clinic-admin.service.ts +202 -202
- package/src/services/clinic/clinic-group.service.ts +310 -310
- package/src/services/clinic/clinic.service.ts +708 -708
- package/src/services/clinic/index.ts +5 -5
- package/src/services/clinic/practitioner-invite.service.ts +519 -519
- package/src/services/clinic/utils/admin.utils.ts +551 -551
- package/src/services/clinic/utils/clinic-group.utils.ts +646 -646
- package/src/services/clinic/utils/clinic.utils.ts +949 -949
- package/src/services/clinic/utils/filter.utils.d.ts +23 -23
- package/src/services/clinic/utils/filter.utils.ts +446 -446
- package/src/services/clinic/utils/index.ts +11 -11
- package/src/services/clinic/utils/photos.utils.ts +188 -188
- package/src/services/clinic/utils/search.utils.ts +84 -84
- package/src/services/clinic/utils/tag.utils.ts +124 -124
- package/src/services/documentation-templates/documentation-template.service.ts +537 -537
- package/src/services/documentation-templates/filled-document.service.ts +587 -587
- package/src/services/documentation-templates/index.ts +2 -2
- package/src/services/index.ts +14 -14
- package/src/services/media/index.ts +1 -1
- package/src/services/media/media.service.ts +418 -418
- package/src/services/notifications/__tests__/notification.service.test.ts +242 -242
- package/src/services/notifications/index.ts +1 -1
- package/src/services/notifications/notification.service.ts +215 -215
- package/src/services/patient/README.md +48 -48
- package/src/services/patient/To-Do.md +43 -43
- package/src/services/patient/__tests__/patient.service.test.ts +294 -294
- package/src/services/patient/index.ts +2 -2
- package/src/services/patient/patient.service.ts +883 -883
- package/src/services/patient/patientRequirements.service.ts +285 -285
- package/src/services/patient/utils/aesthetic-analysis.utils.ts +176 -176
- package/src/services/patient/utils/clinic.utils.ts +80 -80
- package/src/services/patient/utils/docs.utils.ts +142 -142
- package/src/services/patient/utils/index.ts +9 -9
- package/src/services/patient/utils/location.utils.ts +126 -126
- package/src/services/patient/utils/medical-stuff.utils.ts +143 -143
- package/src/services/patient/utils/medical.utils.ts +458 -458
- package/src/services/patient/utils/practitioner.utils.ts +260 -260
- package/src/services/patient/utils/profile.utils.ts +510 -510
- package/src/services/patient/utils/sensitive.utils.ts +260 -260
- package/src/services/patient/utils/token.utils.ts +211 -211
- package/src/services/practitioner/README.md +145 -145
- package/src/services/practitioner/index.ts +1 -1
- package/src/services/practitioner/practitioner.service.ts +1799 -1742
- package/src/services/procedure/README.md +163 -163
- package/src/services/procedure/index.ts +1 -1
- package/src/services/procedure/procedure.service.ts +2307 -2200
- package/src/services/reviews/index.ts +1 -1
- package/src/services/reviews/reviews.service.ts +734 -734
- package/src/services/user/index.ts +1 -1
- package/src/services/user/user.service.ts +489 -489
- package/src/services/user/user.v2.service.ts +466 -466
- package/src/types/analytics/analytics.types.ts +597 -597
- package/src/types/analytics/grouped-analytics.types.ts +173 -173
- package/src/types/analytics/index.ts +4 -4
- package/src/types/analytics/stored-analytics.types.ts +137 -137
- package/src/types/appointment/index.ts +480 -480
- package/src/types/calendar/index.ts +258 -258
- package/src/types/calendar/synced-calendar.types.ts +66 -66
- package/src/types/clinic/index.ts +498 -498
- package/src/types/clinic/practitioner-invite.types.ts +91 -91
- package/src/types/clinic/preferences.types.ts +159 -159
- package/src/types/clinic/to-do +3 -3
- package/src/types/documentation-templates/index.ts +308 -308
- package/src/types/index.ts +47 -47
- package/src/types/notifications/README.md +77 -77
- package/src/types/notifications/index.ts +286 -286
- package/src/types/patient/aesthetic-analysis.types.ts +66 -66
- package/src/types/patient/allergies.ts +58 -58
- package/src/types/patient/index.ts +275 -275
- package/src/types/patient/medical-info.types.ts +152 -152
- package/src/types/patient/patient-requirements.ts +92 -92
- package/src/types/patient/token.types.ts +61 -61
- package/src/types/practitioner/index.ts +206 -206
- package/src/types/procedure/index.ts +181 -181
- package/src/types/profile/index.ts +39 -39
- package/src/types/reviews/index.ts +132 -132
- package/src/types/tz-lookup.d.ts +4 -4
- package/src/types/user/index.ts +38 -38
- package/src/utils/TIMESTAMPS.md +176 -176
- package/src/utils/TimestampUtils.ts +241 -241
- package/src/utils/index.ts +1 -1
- package/src/validations/appointment.schema.ts +574 -574
- package/src/validations/calendar.schema.ts +225 -225
- package/src/validations/clinic.schema.ts +494 -494
- package/src/validations/common.schema.ts +25 -25
- package/src/validations/documentation-templates/index.ts +1 -1
- package/src/validations/documentation-templates/template.schema.ts +220 -220
- package/src/validations/documentation-templates.schema.ts +10 -10
- package/src/validations/index.ts +20 -20
- package/src/validations/media.schema.ts +10 -10
- package/src/validations/notification.schema.ts +90 -90
- package/src/validations/patient/aesthetic-analysis.schema.ts +55 -55
- package/src/validations/patient/medical-info.schema.ts +125 -125
- package/src/validations/patient/patient-requirements.schema.ts +84 -84
- package/src/validations/patient/token.schema.ts +29 -29
- package/src/validations/patient.schema.ts +217 -217
- package/src/validations/practitioner.schema.ts +222 -222
- package/src/validations/procedure-product.schema.ts +41 -41
- package/src/validations/procedure.schema.ts +124 -124
- package/src/validations/profile-info.schema.ts +41 -41
- package/src/validations/reviews.schema.ts +195 -195
- package/src/validations/schemas.ts +104 -104
- package/src/validations/shared.schema.ts +78 -78
|
@@ -1,225 +1,225 @@
|
|
|
1
|
-
import { z } from "zod";
|
|
2
|
-
import { Timestamp, FieldValue } from "firebase/firestore";
|
|
3
|
-
import {
|
|
4
|
-
CalendarEventStatus,
|
|
5
|
-
CalendarEventType,
|
|
6
|
-
CalendarSyncStatus,
|
|
7
|
-
CreateBlockingEventParams,
|
|
8
|
-
UpdateBlockingEventParams,
|
|
9
|
-
} from "../types/calendar";
|
|
10
|
-
import { SyncedCalendarProvider } from "../types/calendar/synced-calendar.types";
|
|
11
|
-
import {
|
|
12
|
-
Currency,
|
|
13
|
-
PricingMeasure,
|
|
14
|
-
} from "../backoffice/types/static/pricing.types";
|
|
15
|
-
import { clinicLocationSchema } from "./clinic.schema";
|
|
16
|
-
import {
|
|
17
|
-
clinicBranchInfoSchema,
|
|
18
|
-
patientProfileInfoSchema,
|
|
19
|
-
practitionerProfileInfoSchema,
|
|
20
|
-
} from "./profile-info.schema";
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* Minimum appointment duration in minutes
|
|
24
|
-
*/
|
|
25
|
-
const MIN_APPOINTMENT_DURATION = 15;
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* Validation schema for calendar event time
|
|
29
|
-
*/
|
|
30
|
-
export const calendarEventTimeSchema = z
|
|
31
|
-
.object({
|
|
32
|
-
start: z.instanceof(Date).or(z.instanceof(Timestamp)),
|
|
33
|
-
end: z.instanceof(Date).or(z.instanceof(Timestamp)),
|
|
34
|
-
})
|
|
35
|
-
.refine(
|
|
36
|
-
(data) => {
|
|
37
|
-
// Convert to Date objects for comparison if they are Timestamps
|
|
38
|
-
const startDate =
|
|
39
|
-
data.start instanceof Timestamp ? data.start.toDate() : data.start;
|
|
40
|
-
const endDate =
|
|
41
|
-
data.end instanceof Timestamp ? data.end.toDate() : data.end;
|
|
42
|
-
|
|
43
|
-
// Ensure end time is after start time
|
|
44
|
-
return startDate < endDate;
|
|
45
|
-
},
|
|
46
|
-
{
|
|
47
|
-
message: "End time must be after start time",
|
|
48
|
-
path: ["end"],
|
|
49
|
-
}
|
|
50
|
-
)
|
|
51
|
-
.refine(
|
|
52
|
-
(data) => {
|
|
53
|
-
// Convert to Date objects for comparison if they are Timestamps
|
|
54
|
-
const startDate =
|
|
55
|
-
data.start instanceof Timestamp ? data.start.toDate() : data.start;
|
|
56
|
-
|
|
57
|
-
// Ensure start time is in the future
|
|
58
|
-
return startDate > new Date();
|
|
59
|
-
},
|
|
60
|
-
{
|
|
61
|
-
message: "Appointment must be scheduled in the future",
|
|
62
|
-
path: ["start"],
|
|
63
|
-
}
|
|
64
|
-
);
|
|
65
|
-
|
|
66
|
-
/**
|
|
67
|
-
* Validation schema for time slot
|
|
68
|
-
*/
|
|
69
|
-
export const timeSlotSchema = z
|
|
70
|
-
.object({
|
|
71
|
-
start: z.date(),
|
|
72
|
-
end: z.date(),
|
|
73
|
-
isAvailable: z.boolean(),
|
|
74
|
-
})
|
|
75
|
-
.refine((data) => data.start < data.end, {
|
|
76
|
-
message: "End time must be after start time",
|
|
77
|
-
path: ["end"],
|
|
78
|
-
});
|
|
79
|
-
|
|
80
|
-
/**
|
|
81
|
-
* Validation schema for synced calendar event
|
|
82
|
-
*/
|
|
83
|
-
export const syncedCalendarEventSchema = z.object({
|
|
84
|
-
eventId: z.string(),
|
|
85
|
-
syncedCalendarProvider: z.nativeEnum(SyncedCalendarProvider),
|
|
86
|
-
syncedAt: z.instanceof(Date).or(z.instanceof(Timestamp)),
|
|
87
|
-
});
|
|
88
|
-
|
|
89
|
-
/**
|
|
90
|
-
* Validation schema for procedure info
|
|
91
|
-
*/
|
|
92
|
-
export const procedureInfoSchema = z.object({
|
|
93
|
-
name: z.string(),
|
|
94
|
-
description: z.string(),
|
|
95
|
-
duration: z.number().min(MIN_APPOINTMENT_DURATION),
|
|
96
|
-
price: z.number().min(0),
|
|
97
|
-
currency: z.nativeEnum(Currency),
|
|
98
|
-
});
|
|
99
|
-
|
|
100
|
-
/**
|
|
101
|
-
* Validation schema for procedure categorization
|
|
102
|
-
*/
|
|
103
|
-
export const procedureCategorizationSchema = z.object({
|
|
104
|
-
procedureFamily: z.string(), // Replace with proper enum when available
|
|
105
|
-
procedureCategory: z.string(), // Replace with proper enum when available
|
|
106
|
-
procedureSubcategory: z.string(), // Replace with proper enum when available
|
|
107
|
-
procedureTechnology: z.string(), // Replace with proper enum when available
|
|
108
|
-
procedureProduct: z.string(), // Replace with proper enum when available
|
|
109
|
-
});
|
|
110
|
-
|
|
111
|
-
/**
|
|
112
|
-
* Validation schema for creating a calendar event
|
|
113
|
-
*/
|
|
114
|
-
export const createCalendarEventSchema = z.object({
|
|
115
|
-
id: z.string(),
|
|
116
|
-
clinicBranchId: z.string().nullable().optional(),
|
|
117
|
-
clinicBranchInfo: clinicBranchInfoSchema.nullable().optional(),
|
|
118
|
-
practitionerProfileId: z.string().nullable().optional(),
|
|
119
|
-
practitionerProfileInfo: practitionerProfileInfoSchema.nullable().optional(),
|
|
120
|
-
patientProfileId: z.string().nullable().optional(),
|
|
121
|
-
patientProfileInfo: patientProfileInfoSchema.nullable().optional(),
|
|
122
|
-
procedureId: z.string().nullable().optional(),
|
|
123
|
-
procedureInfo: procedureInfoSchema.nullable().optional(),
|
|
124
|
-
procedureCategorization: procedureCategorizationSchema.nullable().optional(),
|
|
125
|
-
appointmentId: z.string().nullable().optional(),
|
|
126
|
-
syncedCalendarEventId: z
|
|
127
|
-
.array(syncedCalendarEventSchema)
|
|
128
|
-
.nullable()
|
|
129
|
-
.optional(),
|
|
130
|
-
eventName: z.string(),
|
|
131
|
-
eventLocation: clinicLocationSchema.optional(),
|
|
132
|
-
eventTime: calendarEventTimeSchema,
|
|
133
|
-
description: z.string().optional(),
|
|
134
|
-
status: z.nativeEnum(CalendarEventStatus),
|
|
135
|
-
syncStatus: z.nativeEnum(CalendarSyncStatus),
|
|
136
|
-
eventType: z.nativeEnum(CalendarEventType),
|
|
137
|
-
createdAt: z.any(), // FieldValue for server timestamp
|
|
138
|
-
updatedAt: z.any(), // FieldValue for server timestamp
|
|
139
|
-
});
|
|
140
|
-
|
|
141
|
-
/**
|
|
142
|
-
* Validation schema for updating a calendar event
|
|
143
|
-
*/
|
|
144
|
-
export const updateCalendarEventSchema = z.object({
|
|
145
|
-
syncedCalendarEventId: z
|
|
146
|
-
.array(syncedCalendarEventSchema)
|
|
147
|
-
.nullable()
|
|
148
|
-
.optional(),
|
|
149
|
-
appointmentId: z.string().nullable().optional(),
|
|
150
|
-
eventName: z.string().optional(),
|
|
151
|
-
eventTime: calendarEventTimeSchema.optional(),
|
|
152
|
-
description: z.string().optional(),
|
|
153
|
-
status: z.nativeEnum(CalendarEventStatus).optional(),
|
|
154
|
-
syncStatus: z.nativeEnum(CalendarSyncStatus).optional(),
|
|
155
|
-
eventType: z.nativeEnum(CalendarEventType).optional(),
|
|
156
|
-
updatedAt: z.any(), // FieldValue for server timestamp
|
|
157
|
-
});
|
|
158
|
-
|
|
159
|
-
/**
|
|
160
|
-
* Validation schema for calendar event
|
|
161
|
-
*/
|
|
162
|
-
export const calendarEventSchema = z.object({
|
|
163
|
-
id: z.string(),
|
|
164
|
-
clinicBranchId: z.string().nullable().optional(),
|
|
165
|
-
clinicBranchInfo: clinicBranchInfoSchema.nullable().optional(), // Will be replaced with proper clinic info schema
|
|
166
|
-
practitionerProfileId: z.string().nullable().optional(),
|
|
167
|
-
practitionerProfileInfo: practitionerProfileInfoSchema.nullable().optional(),
|
|
168
|
-
patientProfileId: z.string().nullable().optional(),
|
|
169
|
-
patientProfileInfo: patientProfileInfoSchema.nullable().optional(),
|
|
170
|
-
procedureId: z.string().nullable().optional(),
|
|
171
|
-
procedureInfo: procedureInfoSchema.nullable().optional(),
|
|
172
|
-
procedureCategorization: procedureCategorizationSchema.nullable().optional(),
|
|
173
|
-
appointmentId: z.string().nullable().optional(),
|
|
174
|
-
syncedCalendarEventId: z
|
|
175
|
-
.array(syncedCalendarEventSchema)
|
|
176
|
-
.nullable()
|
|
177
|
-
.optional(),
|
|
178
|
-
eventName: z.string(),
|
|
179
|
-
eventLocation: clinicLocationSchema.optional(),
|
|
180
|
-
eventTime: calendarEventTimeSchema,
|
|
181
|
-
description: z.string().optional(),
|
|
182
|
-
status: z.nativeEnum(CalendarEventStatus),
|
|
183
|
-
syncStatus: z.nativeEnum(CalendarSyncStatus),
|
|
184
|
-
eventType: z.nativeEnum(CalendarEventType),
|
|
185
|
-
createdAt: z.instanceof(Date).or(z.instanceof(Timestamp)),
|
|
186
|
-
updatedAt: z.instanceof(Date).or(z.instanceof(Timestamp)),
|
|
187
|
-
});
|
|
188
|
-
|
|
189
|
-
/**
|
|
190
|
-
* Validation schema for creating blocking events
|
|
191
|
-
* Based on CreateBlockingEventParams interface
|
|
192
|
-
*/
|
|
193
|
-
export const createBlockingEventSchema = z.object({
|
|
194
|
-
entityType: z.enum(["practitioner", "clinic"]),
|
|
195
|
-
entityId: z.string().min(1, "Entity ID is required"),
|
|
196
|
-
eventName: z
|
|
197
|
-
.string()
|
|
198
|
-
.min(1, "Event name is required")
|
|
199
|
-
.max(200, "Event name too long"),
|
|
200
|
-
eventTime: calendarEventTimeSchema,
|
|
201
|
-
eventType: z.enum([
|
|
202
|
-
CalendarEventType.BLOCKING,
|
|
203
|
-
CalendarEventType.BREAK,
|
|
204
|
-
CalendarEventType.FREE_DAY,
|
|
205
|
-
CalendarEventType.OTHER,
|
|
206
|
-
]),
|
|
207
|
-
description: z.string().max(1000, "Description too long").optional(),
|
|
208
|
-
});
|
|
209
|
-
|
|
210
|
-
/**
|
|
211
|
-
* Validation schema for updating blocking events
|
|
212
|
-
* Based on UpdateBlockingEventParams interface
|
|
213
|
-
*/
|
|
214
|
-
export const updateBlockingEventSchema = z.object({
|
|
215
|
-
entityType: z.enum(["practitioner", "clinic"]),
|
|
216
|
-
entityId: z.string().min(1, "Entity ID is required"),
|
|
217
|
-
eventId: z.string().min(1, "Event ID is required"),
|
|
218
|
-
eventName: z
|
|
219
|
-
.string()
|
|
220
|
-
.min(1, "Event name is required")
|
|
221
|
-
.max(200, "Event name too long")
|
|
222
|
-
.optional(),
|
|
223
|
-
eventTime: calendarEventTimeSchema.optional(),
|
|
224
|
-
description: z.string().max(1000, "Description too long").optional(),
|
|
225
|
-
});
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { Timestamp, FieldValue } from "firebase/firestore";
|
|
3
|
+
import {
|
|
4
|
+
CalendarEventStatus,
|
|
5
|
+
CalendarEventType,
|
|
6
|
+
CalendarSyncStatus,
|
|
7
|
+
CreateBlockingEventParams,
|
|
8
|
+
UpdateBlockingEventParams,
|
|
9
|
+
} from "../types/calendar";
|
|
10
|
+
import { SyncedCalendarProvider } from "../types/calendar/synced-calendar.types";
|
|
11
|
+
import {
|
|
12
|
+
Currency,
|
|
13
|
+
PricingMeasure,
|
|
14
|
+
} from "../backoffice/types/static/pricing.types";
|
|
15
|
+
import { clinicLocationSchema } from "./clinic.schema";
|
|
16
|
+
import {
|
|
17
|
+
clinicBranchInfoSchema,
|
|
18
|
+
patientProfileInfoSchema,
|
|
19
|
+
practitionerProfileInfoSchema,
|
|
20
|
+
} from "./profile-info.schema";
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Minimum appointment duration in minutes
|
|
24
|
+
*/
|
|
25
|
+
const MIN_APPOINTMENT_DURATION = 15;
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Validation schema for calendar event time
|
|
29
|
+
*/
|
|
30
|
+
export const calendarEventTimeSchema = z
|
|
31
|
+
.object({
|
|
32
|
+
start: z.instanceof(Date).or(z.instanceof(Timestamp)),
|
|
33
|
+
end: z.instanceof(Date).or(z.instanceof(Timestamp)),
|
|
34
|
+
})
|
|
35
|
+
.refine(
|
|
36
|
+
(data) => {
|
|
37
|
+
// Convert to Date objects for comparison if they are Timestamps
|
|
38
|
+
const startDate =
|
|
39
|
+
data.start instanceof Timestamp ? data.start.toDate() : data.start;
|
|
40
|
+
const endDate =
|
|
41
|
+
data.end instanceof Timestamp ? data.end.toDate() : data.end;
|
|
42
|
+
|
|
43
|
+
// Ensure end time is after start time
|
|
44
|
+
return startDate < endDate;
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
message: "End time must be after start time",
|
|
48
|
+
path: ["end"],
|
|
49
|
+
}
|
|
50
|
+
)
|
|
51
|
+
.refine(
|
|
52
|
+
(data) => {
|
|
53
|
+
// Convert to Date objects for comparison if they are Timestamps
|
|
54
|
+
const startDate =
|
|
55
|
+
data.start instanceof Timestamp ? data.start.toDate() : data.start;
|
|
56
|
+
|
|
57
|
+
// Ensure start time is in the future
|
|
58
|
+
return startDate > new Date();
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
message: "Appointment must be scheduled in the future",
|
|
62
|
+
path: ["start"],
|
|
63
|
+
}
|
|
64
|
+
);
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Validation schema for time slot
|
|
68
|
+
*/
|
|
69
|
+
export const timeSlotSchema = z
|
|
70
|
+
.object({
|
|
71
|
+
start: z.date(),
|
|
72
|
+
end: z.date(),
|
|
73
|
+
isAvailable: z.boolean(),
|
|
74
|
+
})
|
|
75
|
+
.refine((data) => data.start < data.end, {
|
|
76
|
+
message: "End time must be after start time",
|
|
77
|
+
path: ["end"],
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Validation schema for synced calendar event
|
|
82
|
+
*/
|
|
83
|
+
export const syncedCalendarEventSchema = z.object({
|
|
84
|
+
eventId: z.string(),
|
|
85
|
+
syncedCalendarProvider: z.nativeEnum(SyncedCalendarProvider),
|
|
86
|
+
syncedAt: z.instanceof(Date).or(z.instanceof(Timestamp)),
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Validation schema for procedure info
|
|
91
|
+
*/
|
|
92
|
+
export const procedureInfoSchema = z.object({
|
|
93
|
+
name: z.string(),
|
|
94
|
+
description: z.string(),
|
|
95
|
+
duration: z.number().min(MIN_APPOINTMENT_DURATION),
|
|
96
|
+
price: z.number().min(0),
|
|
97
|
+
currency: z.nativeEnum(Currency),
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Validation schema for procedure categorization
|
|
102
|
+
*/
|
|
103
|
+
export const procedureCategorizationSchema = z.object({
|
|
104
|
+
procedureFamily: z.string(), // Replace with proper enum when available
|
|
105
|
+
procedureCategory: z.string(), // Replace with proper enum when available
|
|
106
|
+
procedureSubcategory: z.string(), // Replace with proper enum when available
|
|
107
|
+
procedureTechnology: z.string(), // Replace with proper enum when available
|
|
108
|
+
procedureProduct: z.string(), // Replace with proper enum when available
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Validation schema for creating a calendar event
|
|
113
|
+
*/
|
|
114
|
+
export const createCalendarEventSchema = z.object({
|
|
115
|
+
id: z.string(),
|
|
116
|
+
clinicBranchId: z.string().nullable().optional(),
|
|
117
|
+
clinicBranchInfo: clinicBranchInfoSchema.nullable().optional(),
|
|
118
|
+
practitionerProfileId: z.string().nullable().optional(),
|
|
119
|
+
practitionerProfileInfo: practitionerProfileInfoSchema.nullable().optional(),
|
|
120
|
+
patientProfileId: z.string().nullable().optional(),
|
|
121
|
+
patientProfileInfo: patientProfileInfoSchema.nullable().optional(),
|
|
122
|
+
procedureId: z.string().nullable().optional(),
|
|
123
|
+
procedureInfo: procedureInfoSchema.nullable().optional(),
|
|
124
|
+
procedureCategorization: procedureCategorizationSchema.nullable().optional(),
|
|
125
|
+
appointmentId: z.string().nullable().optional(),
|
|
126
|
+
syncedCalendarEventId: z
|
|
127
|
+
.array(syncedCalendarEventSchema)
|
|
128
|
+
.nullable()
|
|
129
|
+
.optional(),
|
|
130
|
+
eventName: z.string(),
|
|
131
|
+
eventLocation: clinicLocationSchema.optional(),
|
|
132
|
+
eventTime: calendarEventTimeSchema,
|
|
133
|
+
description: z.string().optional(),
|
|
134
|
+
status: z.nativeEnum(CalendarEventStatus),
|
|
135
|
+
syncStatus: z.nativeEnum(CalendarSyncStatus),
|
|
136
|
+
eventType: z.nativeEnum(CalendarEventType),
|
|
137
|
+
createdAt: z.any(), // FieldValue for server timestamp
|
|
138
|
+
updatedAt: z.any(), // FieldValue for server timestamp
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Validation schema for updating a calendar event
|
|
143
|
+
*/
|
|
144
|
+
export const updateCalendarEventSchema = z.object({
|
|
145
|
+
syncedCalendarEventId: z
|
|
146
|
+
.array(syncedCalendarEventSchema)
|
|
147
|
+
.nullable()
|
|
148
|
+
.optional(),
|
|
149
|
+
appointmentId: z.string().nullable().optional(),
|
|
150
|
+
eventName: z.string().optional(),
|
|
151
|
+
eventTime: calendarEventTimeSchema.optional(),
|
|
152
|
+
description: z.string().optional(),
|
|
153
|
+
status: z.nativeEnum(CalendarEventStatus).optional(),
|
|
154
|
+
syncStatus: z.nativeEnum(CalendarSyncStatus).optional(),
|
|
155
|
+
eventType: z.nativeEnum(CalendarEventType).optional(),
|
|
156
|
+
updatedAt: z.any(), // FieldValue for server timestamp
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Validation schema for calendar event
|
|
161
|
+
*/
|
|
162
|
+
export const calendarEventSchema = z.object({
|
|
163
|
+
id: z.string(),
|
|
164
|
+
clinicBranchId: z.string().nullable().optional(),
|
|
165
|
+
clinicBranchInfo: clinicBranchInfoSchema.nullable().optional(), // Will be replaced with proper clinic info schema
|
|
166
|
+
practitionerProfileId: z.string().nullable().optional(),
|
|
167
|
+
practitionerProfileInfo: practitionerProfileInfoSchema.nullable().optional(),
|
|
168
|
+
patientProfileId: z.string().nullable().optional(),
|
|
169
|
+
patientProfileInfo: patientProfileInfoSchema.nullable().optional(),
|
|
170
|
+
procedureId: z.string().nullable().optional(),
|
|
171
|
+
procedureInfo: procedureInfoSchema.nullable().optional(),
|
|
172
|
+
procedureCategorization: procedureCategorizationSchema.nullable().optional(),
|
|
173
|
+
appointmentId: z.string().nullable().optional(),
|
|
174
|
+
syncedCalendarEventId: z
|
|
175
|
+
.array(syncedCalendarEventSchema)
|
|
176
|
+
.nullable()
|
|
177
|
+
.optional(),
|
|
178
|
+
eventName: z.string(),
|
|
179
|
+
eventLocation: clinicLocationSchema.optional(),
|
|
180
|
+
eventTime: calendarEventTimeSchema,
|
|
181
|
+
description: z.string().optional(),
|
|
182
|
+
status: z.nativeEnum(CalendarEventStatus),
|
|
183
|
+
syncStatus: z.nativeEnum(CalendarSyncStatus),
|
|
184
|
+
eventType: z.nativeEnum(CalendarEventType),
|
|
185
|
+
createdAt: z.instanceof(Date).or(z.instanceof(Timestamp)),
|
|
186
|
+
updatedAt: z.instanceof(Date).or(z.instanceof(Timestamp)),
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* Validation schema for creating blocking events
|
|
191
|
+
* Based on CreateBlockingEventParams interface
|
|
192
|
+
*/
|
|
193
|
+
export const createBlockingEventSchema = z.object({
|
|
194
|
+
entityType: z.enum(["practitioner", "clinic"]),
|
|
195
|
+
entityId: z.string().min(1, "Entity ID is required"),
|
|
196
|
+
eventName: z
|
|
197
|
+
.string()
|
|
198
|
+
.min(1, "Event name is required")
|
|
199
|
+
.max(200, "Event name too long"),
|
|
200
|
+
eventTime: calendarEventTimeSchema,
|
|
201
|
+
eventType: z.enum([
|
|
202
|
+
CalendarEventType.BLOCKING,
|
|
203
|
+
CalendarEventType.BREAK,
|
|
204
|
+
CalendarEventType.FREE_DAY,
|
|
205
|
+
CalendarEventType.OTHER,
|
|
206
|
+
]),
|
|
207
|
+
description: z.string().max(1000, "Description too long").optional(),
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* Validation schema for updating blocking events
|
|
212
|
+
* Based on UpdateBlockingEventParams interface
|
|
213
|
+
*/
|
|
214
|
+
export const updateBlockingEventSchema = z.object({
|
|
215
|
+
entityType: z.enum(["practitioner", "clinic"]),
|
|
216
|
+
entityId: z.string().min(1, "Entity ID is required"),
|
|
217
|
+
eventId: z.string().min(1, "Event ID is required"),
|
|
218
|
+
eventName: z
|
|
219
|
+
.string()
|
|
220
|
+
.min(1, "Event name is required")
|
|
221
|
+
.max(200, "Event name too long")
|
|
222
|
+
.optional(),
|
|
223
|
+
eventTime: calendarEventTimeSchema.optional(),
|
|
224
|
+
description: z.string().max(1000, "Description too long").optional(),
|
|
225
|
+
});
|