@blackcode_sa/metaestetics-api 1.12.61 → 1.12.62
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 +2 -0
- package/dist/admin/index.d.ts +2 -0
- package/dist/admin/index.js +45 -4
- package/dist/admin/index.mjs +45 -4
- package/dist/index.d.mts +2 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +53 -11
- package/dist/index.mjs +53 -11
- package/package.json +119 -119
- 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 +1844 -1844
- 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 +703 -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 -641
- 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 +75 -75
- 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 +40 -40
- package/src/backoffice/services/brand.service.ts +256 -256
- package/src/backoffice/services/category.service.ts +318 -318
- 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 +8 -8
- 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 +395 -395
- package/src/backoffice/services/technology.service.ts +1070 -1070
- 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 +62 -62
- 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 +161 -161
- package/src/backoffice/validations/index.ts +1 -1
- package/src/backoffice/validations/schemas.ts +163 -163
- 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 +200 -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/appointment/README.md +17 -17
- package/src/services/appointment/appointment.service.ts +2082 -2082
- 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 +989 -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 +13 -13
- 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 +1742 -1742
- package/src/services/procedure/README.md +163 -163
- package/src/services/procedure/index.ts +1 -1
- package/src/services/procedure/procedure.service.ts +1682 -1682
- package/src/services/reviews/index.ts +1 -1
- package/src/services/reviews/reviews.service.ts +683 -636
- 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/appointment/index.ts +453 -453
- package/src/types/calendar/index.ts +258 -258
- package/src/types/calendar/synced-calendar.types.ts +66 -66
- package/src/types/clinic/index.ts +489 -489
- 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 +44 -44
- package/src/types/notifications/README.md +77 -77
- package/src/types/notifications/index.ts +265 -265
- package/src/types/patient/aesthetic-analysis.types.ts +66 -66
- package/src/types/patient/allergies.ts +58 -58
- package/src/types/patient/index.ts +273 -273
- 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 -130
- 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 +493 -493
- 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 +216 -216
- 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 -189
- package/src/validations/schemas.ts +104 -104
- package/src/validations/shared.schema.ts +78 -78
|
@@ -1,195 +1,195 @@
|
|
|
1
|
-
import { Firestore, updateDoc, serverTimestamp, doc } from 'firebase/firestore';
|
|
2
|
-
import {
|
|
3
|
-
Appointment,
|
|
4
|
-
RecommendedProcedure,
|
|
5
|
-
ExtendedProcedureInfo,
|
|
6
|
-
APPOINTMENTS_COLLECTION,
|
|
7
|
-
} from '../../../types/appointment';
|
|
8
|
-
import { getAppointmentOrThrow, initializeMetadata } from './zone-management.utils';
|
|
9
|
-
import { PROCEDURES_COLLECTION } from '../../../types/procedure';
|
|
10
|
-
import { getDoc } from 'firebase/firestore';
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* Creates ExtendedProcedureInfo from procedure document for recommended procedures
|
|
14
|
-
* @param db Firestore instance
|
|
15
|
-
* @param procedureId Procedure ID
|
|
16
|
-
* @returns Extended procedure info
|
|
17
|
-
*/
|
|
18
|
-
async function createExtendedProcedureInfoForRecommended(
|
|
19
|
-
db: Firestore,
|
|
20
|
-
procedureId: string
|
|
21
|
-
): Promise<ExtendedProcedureInfo> {
|
|
22
|
-
const procedureRef = doc(db, PROCEDURES_COLLECTION, procedureId);
|
|
23
|
-
const procedureSnap = await getDoc(procedureRef);
|
|
24
|
-
|
|
25
|
-
if (!procedureSnap.exists()) {
|
|
26
|
-
throw new Error(`Procedure with ID ${procedureId} not found`);
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
const data = procedureSnap.data();
|
|
30
|
-
|
|
31
|
-
return {
|
|
32
|
-
procedureId: procedureId,
|
|
33
|
-
procedureName: data.name,
|
|
34
|
-
procedureFamily: data.family,
|
|
35
|
-
procedureCategoryId: data.category.id,
|
|
36
|
-
procedureCategoryName: data.category.name,
|
|
37
|
-
procedureSubCategoryId: data.subcategory.id,
|
|
38
|
-
procedureSubCategoryName: data.subcategory.name,
|
|
39
|
-
procedureTechnologyId: data.technology.id,
|
|
40
|
-
procedureTechnologyName: data.technology.name,
|
|
41
|
-
procedureProducts: (data.productsMetadata || [])
|
|
42
|
-
.filter((pp: any) => pp && pp.product) // Safety check for product-free procedures
|
|
43
|
-
.map((pp: any) => ({
|
|
44
|
-
productId: pp.product.id,
|
|
45
|
-
productName: pp.product.name,
|
|
46
|
-
brandId: pp.product.brandId,
|
|
47
|
-
brandName: pp.product.brandName,
|
|
48
|
-
})),
|
|
49
|
-
};
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
/**
|
|
53
|
-
* Adds a recommended procedure to an appointment
|
|
54
|
-
* Multiple recommendations of the same procedure are allowed (e.g., touch-up in 2 weeks, full treatment in 3 months)
|
|
55
|
-
* @param db Firestore instance
|
|
56
|
-
* @param appointmentId Appointment ID
|
|
57
|
-
* @param procedureId Procedure ID to recommend
|
|
58
|
-
* @param note Note explaining the recommendation
|
|
59
|
-
* @param timeframe Suggested timeframe for the procedure
|
|
60
|
-
* @returns Updated appointment
|
|
61
|
-
*/
|
|
62
|
-
export async function addRecommendedProcedureUtil(
|
|
63
|
-
db: Firestore,
|
|
64
|
-
appointmentId: string,
|
|
65
|
-
procedureId: string,
|
|
66
|
-
note: string,
|
|
67
|
-
timeframe: { value: number; unit: 'day' | 'week' | 'month' | 'year' }
|
|
68
|
-
): Promise<Appointment> {
|
|
69
|
-
const appointment = await getAppointmentOrThrow(db, appointmentId);
|
|
70
|
-
const metadata = initializeMetadata(appointment);
|
|
71
|
-
|
|
72
|
-
// Create extended procedure info
|
|
73
|
-
const procedureInfo = await createExtendedProcedureInfoForRecommended(db, procedureId);
|
|
74
|
-
|
|
75
|
-
// Create recommended procedure object
|
|
76
|
-
const recommendedProcedure: RecommendedProcedure = {
|
|
77
|
-
procedure: procedureInfo,
|
|
78
|
-
note,
|
|
79
|
-
timeframe,
|
|
80
|
-
};
|
|
81
|
-
|
|
82
|
-
// Add to recommended procedures array
|
|
83
|
-
const recommendedProcedures = [...(metadata.recommendedProcedures || []), recommendedProcedure];
|
|
84
|
-
|
|
85
|
-
// Update appointment
|
|
86
|
-
const appointmentRef = doc(db, APPOINTMENTS_COLLECTION, appointmentId);
|
|
87
|
-
await updateDoc(appointmentRef, {
|
|
88
|
-
'metadata.recommendedProcedures': recommendedProcedures,
|
|
89
|
-
updatedAt: serverTimestamp(),
|
|
90
|
-
});
|
|
91
|
-
|
|
92
|
-
return getAppointmentOrThrow(db, appointmentId);
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
/**
|
|
96
|
-
* Removes a recommended procedure from an appointment by index
|
|
97
|
-
* @param db Firestore instance
|
|
98
|
-
* @param appointmentId Appointment ID
|
|
99
|
-
* @param recommendationIndex Index of the recommendation to remove in the array
|
|
100
|
-
* @returns Updated appointment
|
|
101
|
-
*/
|
|
102
|
-
export async function removeRecommendedProcedureUtil(
|
|
103
|
-
db: Firestore,
|
|
104
|
-
appointmentId: string,
|
|
105
|
-
recommendationIndex: number
|
|
106
|
-
): Promise<Appointment> {
|
|
107
|
-
const appointment = await getAppointmentOrThrow(db, appointmentId);
|
|
108
|
-
const metadata = initializeMetadata(appointment);
|
|
109
|
-
|
|
110
|
-
if (!metadata.recommendedProcedures || metadata.recommendedProcedures.length === 0) {
|
|
111
|
-
throw new Error('No recommended procedures found for this appointment');
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
// Validate index
|
|
115
|
-
if (recommendationIndex < 0 || recommendationIndex >= metadata.recommendedProcedures.length) {
|
|
116
|
-
throw new Error(`Invalid recommendation index ${recommendationIndex}. Must be between 0 and ${metadata.recommendedProcedures.length - 1}`);
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
// Remove recommendation
|
|
120
|
-
const updatedRecommendedProcedures = [...metadata.recommendedProcedures];
|
|
121
|
-
updatedRecommendedProcedures.splice(recommendationIndex, 1);
|
|
122
|
-
|
|
123
|
-
// Update appointment
|
|
124
|
-
const appointmentRef = doc(db, APPOINTMENTS_COLLECTION, appointmentId);
|
|
125
|
-
await updateDoc(appointmentRef, {
|
|
126
|
-
'metadata.recommendedProcedures': updatedRecommendedProcedures,
|
|
127
|
-
updatedAt: serverTimestamp(),
|
|
128
|
-
});
|
|
129
|
-
|
|
130
|
-
return getAppointmentOrThrow(db, appointmentId);
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
/**
|
|
134
|
-
* Updates a recommended procedure in an appointment by index
|
|
135
|
-
* @param db Firestore instance
|
|
136
|
-
* @param appointmentId Appointment ID
|
|
137
|
-
* @param recommendationIndex Index of the recommendation to update
|
|
138
|
-
* @param updates Partial updates (note and/or timeframe)
|
|
139
|
-
* @returns Updated appointment
|
|
140
|
-
*/
|
|
141
|
-
export async function updateRecommendedProcedureUtil(
|
|
142
|
-
db: Firestore,
|
|
143
|
-
appointmentId: string,
|
|
144
|
-
recommendationIndex: number,
|
|
145
|
-
updates: {
|
|
146
|
-
note?: string;
|
|
147
|
-
timeframe?: { value: number; unit: 'day' | 'week' | 'month' | 'year' };
|
|
148
|
-
}
|
|
149
|
-
): Promise<Appointment> {
|
|
150
|
-
const appointment = await getAppointmentOrThrow(db, appointmentId);
|
|
151
|
-
const metadata = initializeMetadata(appointment);
|
|
152
|
-
|
|
153
|
-
if (!metadata.recommendedProcedures || metadata.recommendedProcedures.length === 0) {
|
|
154
|
-
throw new Error('No recommended procedures found for this appointment');
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
// Validate index
|
|
158
|
-
if (recommendationIndex < 0 || recommendationIndex >= metadata.recommendedProcedures.length) {
|
|
159
|
-
throw new Error(`Invalid recommendation index ${recommendationIndex}. Must be between 0 and ${metadata.recommendedProcedures.length - 1}`);
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
// Update the recommendation
|
|
163
|
-
const updatedRecommendedProcedures = [...metadata.recommendedProcedures];
|
|
164
|
-
const existingRecommendation = updatedRecommendedProcedures[recommendationIndex];
|
|
165
|
-
|
|
166
|
-
updatedRecommendedProcedures[recommendationIndex] = {
|
|
167
|
-
...existingRecommendation,
|
|
168
|
-
...(updates.note !== undefined && { note: updates.note }),
|
|
169
|
-
...(updates.timeframe !== undefined && { timeframe: updates.timeframe }),
|
|
170
|
-
};
|
|
171
|
-
|
|
172
|
-
// Update appointment
|
|
173
|
-
const appointmentRef = doc(db, APPOINTMENTS_COLLECTION, appointmentId);
|
|
174
|
-
await updateDoc(appointmentRef, {
|
|
175
|
-
'metadata.recommendedProcedures': updatedRecommendedProcedures,
|
|
176
|
-
updatedAt: serverTimestamp(),
|
|
177
|
-
});
|
|
178
|
-
|
|
179
|
-
return getAppointmentOrThrow(db, appointmentId);
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
/**
|
|
183
|
-
* Gets all recommended procedures for an appointment
|
|
184
|
-
* @param db Firestore instance
|
|
185
|
-
* @param appointmentId Appointment ID
|
|
186
|
-
* @returns Array of recommended procedures
|
|
187
|
-
*/
|
|
188
|
-
export async function getRecommendedProceduresUtil(
|
|
189
|
-
db: Firestore,
|
|
190
|
-
appointmentId: string
|
|
191
|
-
): Promise<RecommendedProcedure[]> {
|
|
192
|
-
const appointment = await getAppointmentOrThrow(db, appointmentId);
|
|
193
|
-
return appointment.metadata?.recommendedProcedures || [];
|
|
194
|
-
}
|
|
195
|
-
|
|
1
|
+
import { Firestore, updateDoc, serverTimestamp, doc } from 'firebase/firestore';
|
|
2
|
+
import {
|
|
3
|
+
Appointment,
|
|
4
|
+
RecommendedProcedure,
|
|
5
|
+
ExtendedProcedureInfo,
|
|
6
|
+
APPOINTMENTS_COLLECTION,
|
|
7
|
+
} from '../../../types/appointment';
|
|
8
|
+
import { getAppointmentOrThrow, initializeMetadata } from './zone-management.utils';
|
|
9
|
+
import { PROCEDURES_COLLECTION } from '../../../types/procedure';
|
|
10
|
+
import { getDoc } from 'firebase/firestore';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Creates ExtendedProcedureInfo from procedure document for recommended procedures
|
|
14
|
+
* @param db Firestore instance
|
|
15
|
+
* @param procedureId Procedure ID
|
|
16
|
+
* @returns Extended procedure info
|
|
17
|
+
*/
|
|
18
|
+
async function createExtendedProcedureInfoForRecommended(
|
|
19
|
+
db: Firestore,
|
|
20
|
+
procedureId: string
|
|
21
|
+
): Promise<ExtendedProcedureInfo> {
|
|
22
|
+
const procedureRef = doc(db, PROCEDURES_COLLECTION, procedureId);
|
|
23
|
+
const procedureSnap = await getDoc(procedureRef);
|
|
24
|
+
|
|
25
|
+
if (!procedureSnap.exists()) {
|
|
26
|
+
throw new Error(`Procedure with ID ${procedureId} not found`);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const data = procedureSnap.data();
|
|
30
|
+
|
|
31
|
+
return {
|
|
32
|
+
procedureId: procedureId,
|
|
33
|
+
procedureName: data.name,
|
|
34
|
+
procedureFamily: data.family,
|
|
35
|
+
procedureCategoryId: data.category.id,
|
|
36
|
+
procedureCategoryName: data.category.name,
|
|
37
|
+
procedureSubCategoryId: data.subcategory.id,
|
|
38
|
+
procedureSubCategoryName: data.subcategory.name,
|
|
39
|
+
procedureTechnologyId: data.technology.id,
|
|
40
|
+
procedureTechnologyName: data.technology.name,
|
|
41
|
+
procedureProducts: (data.productsMetadata || [])
|
|
42
|
+
.filter((pp: any) => pp && pp.product) // Safety check for product-free procedures
|
|
43
|
+
.map((pp: any) => ({
|
|
44
|
+
productId: pp.product.id,
|
|
45
|
+
productName: pp.product.name,
|
|
46
|
+
brandId: pp.product.brandId,
|
|
47
|
+
brandName: pp.product.brandName,
|
|
48
|
+
})),
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Adds a recommended procedure to an appointment
|
|
54
|
+
* Multiple recommendations of the same procedure are allowed (e.g., touch-up in 2 weeks, full treatment in 3 months)
|
|
55
|
+
* @param db Firestore instance
|
|
56
|
+
* @param appointmentId Appointment ID
|
|
57
|
+
* @param procedureId Procedure ID to recommend
|
|
58
|
+
* @param note Note explaining the recommendation
|
|
59
|
+
* @param timeframe Suggested timeframe for the procedure
|
|
60
|
+
* @returns Updated appointment
|
|
61
|
+
*/
|
|
62
|
+
export async function addRecommendedProcedureUtil(
|
|
63
|
+
db: Firestore,
|
|
64
|
+
appointmentId: string,
|
|
65
|
+
procedureId: string,
|
|
66
|
+
note: string,
|
|
67
|
+
timeframe: { value: number; unit: 'day' | 'week' | 'month' | 'year' }
|
|
68
|
+
): Promise<Appointment> {
|
|
69
|
+
const appointment = await getAppointmentOrThrow(db, appointmentId);
|
|
70
|
+
const metadata = initializeMetadata(appointment);
|
|
71
|
+
|
|
72
|
+
// Create extended procedure info
|
|
73
|
+
const procedureInfo = await createExtendedProcedureInfoForRecommended(db, procedureId);
|
|
74
|
+
|
|
75
|
+
// Create recommended procedure object
|
|
76
|
+
const recommendedProcedure: RecommendedProcedure = {
|
|
77
|
+
procedure: procedureInfo,
|
|
78
|
+
note,
|
|
79
|
+
timeframe,
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
// Add to recommended procedures array
|
|
83
|
+
const recommendedProcedures = [...(metadata.recommendedProcedures || []), recommendedProcedure];
|
|
84
|
+
|
|
85
|
+
// Update appointment
|
|
86
|
+
const appointmentRef = doc(db, APPOINTMENTS_COLLECTION, appointmentId);
|
|
87
|
+
await updateDoc(appointmentRef, {
|
|
88
|
+
'metadata.recommendedProcedures': recommendedProcedures,
|
|
89
|
+
updatedAt: serverTimestamp(),
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
return getAppointmentOrThrow(db, appointmentId);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Removes a recommended procedure from an appointment by index
|
|
97
|
+
* @param db Firestore instance
|
|
98
|
+
* @param appointmentId Appointment ID
|
|
99
|
+
* @param recommendationIndex Index of the recommendation to remove in the array
|
|
100
|
+
* @returns Updated appointment
|
|
101
|
+
*/
|
|
102
|
+
export async function removeRecommendedProcedureUtil(
|
|
103
|
+
db: Firestore,
|
|
104
|
+
appointmentId: string,
|
|
105
|
+
recommendationIndex: number
|
|
106
|
+
): Promise<Appointment> {
|
|
107
|
+
const appointment = await getAppointmentOrThrow(db, appointmentId);
|
|
108
|
+
const metadata = initializeMetadata(appointment);
|
|
109
|
+
|
|
110
|
+
if (!metadata.recommendedProcedures || metadata.recommendedProcedures.length === 0) {
|
|
111
|
+
throw new Error('No recommended procedures found for this appointment');
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// Validate index
|
|
115
|
+
if (recommendationIndex < 0 || recommendationIndex >= metadata.recommendedProcedures.length) {
|
|
116
|
+
throw new Error(`Invalid recommendation index ${recommendationIndex}. Must be between 0 and ${metadata.recommendedProcedures.length - 1}`);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// Remove recommendation
|
|
120
|
+
const updatedRecommendedProcedures = [...metadata.recommendedProcedures];
|
|
121
|
+
updatedRecommendedProcedures.splice(recommendationIndex, 1);
|
|
122
|
+
|
|
123
|
+
// Update appointment
|
|
124
|
+
const appointmentRef = doc(db, APPOINTMENTS_COLLECTION, appointmentId);
|
|
125
|
+
await updateDoc(appointmentRef, {
|
|
126
|
+
'metadata.recommendedProcedures': updatedRecommendedProcedures,
|
|
127
|
+
updatedAt: serverTimestamp(),
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
return getAppointmentOrThrow(db, appointmentId);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Updates a recommended procedure in an appointment by index
|
|
135
|
+
* @param db Firestore instance
|
|
136
|
+
* @param appointmentId Appointment ID
|
|
137
|
+
* @param recommendationIndex Index of the recommendation to update
|
|
138
|
+
* @param updates Partial updates (note and/or timeframe)
|
|
139
|
+
* @returns Updated appointment
|
|
140
|
+
*/
|
|
141
|
+
export async function updateRecommendedProcedureUtil(
|
|
142
|
+
db: Firestore,
|
|
143
|
+
appointmentId: string,
|
|
144
|
+
recommendationIndex: number,
|
|
145
|
+
updates: {
|
|
146
|
+
note?: string;
|
|
147
|
+
timeframe?: { value: number; unit: 'day' | 'week' | 'month' | 'year' };
|
|
148
|
+
}
|
|
149
|
+
): Promise<Appointment> {
|
|
150
|
+
const appointment = await getAppointmentOrThrow(db, appointmentId);
|
|
151
|
+
const metadata = initializeMetadata(appointment);
|
|
152
|
+
|
|
153
|
+
if (!metadata.recommendedProcedures || metadata.recommendedProcedures.length === 0) {
|
|
154
|
+
throw new Error('No recommended procedures found for this appointment');
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// Validate index
|
|
158
|
+
if (recommendationIndex < 0 || recommendationIndex >= metadata.recommendedProcedures.length) {
|
|
159
|
+
throw new Error(`Invalid recommendation index ${recommendationIndex}. Must be between 0 and ${metadata.recommendedProcedures.length - 1}`);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// Update the recommendation
|
|
163
|
+
const updatedRecommendedProcedures = [...metadata.recommendedProcedures];
|
|
164
|
+
const existingRecommendation = updatedRecommendedProcedures[recommendationIndex];
|
|
165
|
+
|
|
166
|
+
updatedRecommendedProcedures[recommendationIndex] = {
|
|
167
|
+
...existingRecommendation,
|
|
168
|
+
...(updates.note !== undefined && { note: updates.note }),
|
|
169
|
+
...(updates.timeframe !== undefined && { timeframe: updates.timeframe }),
|
|
170
|
+
};
|
|
171
|
+
|
|
172
|
+
// Update appointment
|
|
173
|
+
const appointmentRef = doc(db, APPOINTMENTS_COLLECTION, appointmentId);
|
|
174
|
+
await updateDoc(appointmentRef, {
|
|
175
|
+
'metadata.recommendedProcedures': updatedRecommendedProcedures,
|
|
176
|
+
updatedAt: serverTimestamp(),
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
return getAppointmentOrThrow(db, appointmentId);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* Gets all recommended procedures for an appointment
|
|
184
|
+
* @param db Firestore instance
|
|
185
|
+
* @param appointmentId Appointment ID
|
|
186
|
+
* @returns Array of recommended procedures
|
|
187
|
+
*/
|
|
188
|
+
export async function getRecommendedProceduresUtil(
|
|
189
|
+
db: Firestore,
|
|
190
|
+
appointmentId: string
|
|
191
|
+
): Promise<RecommendedProcedure[]> {
|
|
192
|
+
const appointment = await getAppointmentOrThrow(db, appointmentId);
|
|
193
|
+
return appointment.metadata?.recommendedProcedures || [];
|
|
194
|
+
}
|
|
195
|
+
|