@blackcode_sa/metaestetics-api 1.13.5 → 1.13.6
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/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 +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/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 +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 +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 +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 +2200 -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,211 +1,211 @@
|
|
|
1
|
-
import {
|
|
2
|
-
collection,
|
|
3
|
-
doc,
|
|
4
|
-
getDoc,
|
|
5
|
-
getDocs,
|
|
6
|
-
query,
|
|
7
|
-
where,
|
|
8
|
-
setDoc,
|
|
9
|
-
updateDoc,
|
|
10
|
-
Timestamp,
|
|
11
|
-
collectionGroup,
|
|
12
|
-
} from "firebase/firestore";
|
|
13
|
-
import { Firestore } from "firebase/firestore";
|
|
14
|
-
import { z } from "zod";
|
|
15
|
-
import {
|
|
16
|
-
PatientToken,
|
|
17
|
-
CreatePatientTokenData,
|
|
18
|
-
PatientTokenStatus,
|
|
19
|
-
INVITE_TOKENS_COLLECTION,
|
|
20
|
-
} from "../../../types/patient/token.types";
|
|
21
|
-
import {
|
|
22
|
-
patientTokenSchema,
|
|
23
|
-
createPatientTokenSchema,
|
|
24
|
-
} from "../../../validations/patient/token.schema";
|
|
25
|
-
import { getPatientDocRef } from "./docs.utils";
|
|
26
|
-
import { PATIENTS_COLLECTION } from "../../../types/patient";
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* Creates a token for inviting a patient to claim their profile.
|
|
30
|
-
*
|
|
31
|
-
* @param {Firestore} db - The Firestore database instance.
|
|
32
|
-
* @param {CreatePatientTokenData} data - Data for creating the token.
|
|
33
|
-
* @param {string} createdBy - ID of the user creating the token.
|
|
34
|
-
* @param {() => string} generateId - Function to generate a unique ID.
|
|
35
|
-
* @returns {Promise<PatientToken>} The created token.
|
|
36
|
-
* @throws {Error} If the patient profile is not found, is not a manual profile, or if data is invalid.
|
|
37
|
-
*/
|
|
38
|
-
export const createPatientTokenUtil = async (
|
|
39
|
-
db: Firestore,
|
|
40
|
-
data: CreatePatientTokenData,
|
|
41
|
-
createdBy: string,
|
|
42
|
-
generateId: () => string
|
|
43
|
-
): Promise<PatientToken> => {
|
|
44
|
-
const validatedData = createPatientTokenSchema.parse(data);
|
|
45
|
-
|
|
46
|
-
// Check if patient exists and is a manual profile
|
|
47
|
-
const patientRef = getPatientDocRef(db, validatedData.patientId);
|
|
48
|
-
const patientDoc = await getDoc(patientRef);
|
|
49
|
-
if (!patientDoc.exists() || !patientDoc.data()?.isManual) {
|
|
50
|
-
throw new Error(
|
|
51
|
-
"Patient profile not found or is not a manually created profile."
|
|
52
|
-
);
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
// Default expiration is 7 days from now if not specified
|
|
56
|
-
const expiration =
|
|
57
|
-
validatedData.expiresAt || new Date(Date.now() + 7 * 24 * 60 * 60 * 1000);
|
|
58
|
-
|
|
59
|
-
const tokenString = generateId().slice(0, 6).toUpperCase();
|
|
60
|
-
|
|
61
|
-
const token: PatientToken = {
|
|
62
|
-
id: generateId(),
|
|
63
|
-
token: tokenString,
|
|
64
|
-
patientId: validatedData.patientId,
|
|
65
|
-
email: validatedData.email,
|
|
66
|
-
clinicId: validatedData.clinicId,
|
|
67
|
-
status: PatientTokenStatus.ACTIVE,
|
|
68
|
-
createdBy: createdBy,
|
|
69
|
-
createdAt: Timestamp.now(),
|
|
70
|
-
expiresAt: Timestamp.fromDate(expiration),
|
|
71
|
-
};
|
|
72
|
-
|
|
73
|
-
patientTokenSchema.parse(token);
|
|
74
|
-
|
|
75
|
-
const tokenRef = doc(
|
|
76
|
-
db,
|
|
77
|
-
PATIENTS_COLLECTION,
|
|
78
|
-
validatedData.patientId,
|
|
79
|
-
INVITE_TOKENS_COLLECTION,
|
|
80
|
-
token.id
|
|
81
|
-
);
|
|
82
|
-
await setDoc(tokenRef, token);
|
|
83
|
-
|
|
84
|
-
return token;
|
|
85
|
-
};
|
|
86
|
-
|
|
87
|
-
/**
|
|
88
|
-
* Validates a patient invitation token.
|
|
89
|
-
*
|
|
90
|
-
* @param {Firestore} db - The Firestore database instance.
|
|
91
|
-
* @param {string} tokenString - The token string to validate.
|
|
92
|
-
* @returns {Promise<PatientToken | null>} The token if found and valid, otherwise null.
|
|
93
|
-
*/
|
|
94
|
-
export const validatePatientTokenUtil = async (
|
|
95
|
-
db: Firestore,
|
|
96
|
-
tokenString: string
|
|
97
|
-
): Promise<PatientToken | null> => {
|
|
98
|
-
const patientsRef = collection(db, PATIENTS_COLLECTION);
|
|
99
|
-
const patientsSnapshot = await getDocs(patientsRef);
|
|
100
|
-
|
|
101
|
-
for (const patientDoc of patientsSnapshot.docs) {
|
|
102
|
-
const tokensRef = collection(
|
|
103
|
-
db,
|
|
104
|
-
patientDoc.ref.path,
|
|
105
|
-
INVITE_TOKENS_COLLECTION
|
|
106
|
-
);
|
|
107
|
-
const q = query(
|
|
108
|
-
tokensRef,
|
|
109
|
-
where("token", "==", tokenString),
|
|
110
|
-
where("status", "==", PatientTokenStatus.ACTIVE),
|
|
111
|
-
where("expiresAt", ">", Timestamp.now())
|
|
112
|
-
);
|
|
113
|
-
|
|
114
|
-
const tokenSnapshot = await getDocs(q);
|
|
115
|
-
if (!tokenSnapshot.empty) {
|
|
116
|
-
return tokenSnapshot.docs[0].data() as PatientToken;
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
return null;
|
|
121
|
-
};
|
|
122
|
-
|
|
123
|
-
/**
|
|
124
|
-
* Marks a patient invitation token as used.
|
|
125
|
-
*
|
|
126
|
-
* @param {Firestore} db - The Firestore database instance.
|
|
127
|
-
* @param {string} tokenId - The ID of the token to mark as used.
|
|
128
|
-
* @param {string} patientId - The ID of the patient associated with the token.
|
|
129
|
-
* @param {string} userId - The ID of the user who is using the token.
|
|
130
|
-
* @returns {Promise<void>}
|
|
131
|
-
*/
|
|
132
|
-
export const markPatientTokenAsUsedUtil = async (
|
|
133
|
-
db: Firestore,
|
|
134
|
-
tokenId: string,
|
|
135
|
-
patientId: string,
|
|
136
|
-
userId: string
|
|
137
|
-
): Promise<void> => {
|
|
138
|
-
const tokenRef = doc(
|
|
139
|
-
db,
|
|
140
|
-
PATIENTS_COLLECTION,
|
|
141
|
-
patientId,
|
|
142
|
-
INVITE_TOKENS_COLLECTION,
|
|
143
|
-
tokenId
|
|
144
|
-
);
|
|
145
|
-
await updateDoc(tokenRef, {
|
|
146
|
-
status: PatientTokenStatus.USED,
|
|
147
|
-
usedBy: userId,
|
|
148
|
-
usedAt: Timestamp.now(),
|
|
149
|
-
});
|
|
150
|
-
};
|
|
151
|
-
|
|
152
|
-
/**
|
|
153
|
-
* Retrieves all active invitation tokens for a specific clinic.
|
|
154
|
-
* This uses a collection group query to find tokens across all patients.
|
|
155
|
-
*
|
|
156
|
-
* @param {Firestore} db - The Firestore database instance.
|
|
157
|
-
* @param {string} clinicId - The ID of the clinic.
|
|
158
|
-
* @returns {Promise<PatientToken[]>} An array of active tokens for the clinic.
|
|
159
|
-
*/
|
|
160
|
-
export const getActiveInviteTokensByClinicUtil = async (
|
|
161
|
-
db: Firestore,
|
|
162
|
-
clinicId: string
|
|
163
|
-
): Promise<PatientToken[]> => {
|
|
164
|
-
const tokensQuery = query(
|
|
165
|
-
collectionGroup(db, INVITE_TOKENS_COLLECTION),
|
|
166
|
-
where("clinicId", "==", clinicId),
|
|
167
|
-
where("status", "==", PatientTokenStatus.ACTIVE),
|
|
168
|
-
where("expiresAt", ">", Timestamp.now())
|
|
169
|
-
);
|
|
170
|
-
|
|
171
|
-
const querySnapshot = await getDocs(tokensQuery);
|
|
172
|
-
|
|
173
|
-
if (querySnapshot.empty) {
|
|
174
|
-
return [];
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
return querySnapshot.docs.map((doc) => doc.data() as PatientToken);
|
|
178
|
-
};
|
|
179
|
-
|
|
180
|
-
/**
|
|
181
|
-
* Retrieves all active invitation tokens for a specific patient.
|
|
182
|
-
*
|
|
183
|
-
* @param {Firestore} db - The Firestore database instance.
|
|
184
|
-
* @param {string} patientId - The ID of the patient.
|
|
185
|
-
* @returns {Promise<PatientToken[]>} An array of active tokens for the patient.
|
|
186
|
-
*/
|
|
187
|
-
export const getActiveInviteTokensByPatientUtil = async (
|
|
188
|
-
db: Firestore,
|
|
189
|
-
patientId: string
|
|
190
|
-
): Promise<PatientToken[]> => {
|
|
191
|
-
const tokensRef = collection(
|
|
192
|
-
db,
|
|
193
|
-
PATIENTS_COLLECTION,
|
|
194
|
-
patientId,
|
|
195
|
-
INVITE_TOKENS_COLLECTION
|
|
196
|
-
);
|
|
197
|
-
|
|
198
|
-
const q = query(
|
|
199
|
-
tokensRef,
|
|
200
|
-
where("status", "==", PatientTokenStatus.ACTIVE),
|
|
201
|
-
where("expiresAt", ">", Timestamp.now())
|
|
202
|
-
);
|
|
203
|
-
|
|
204
|
-
const querySnapshot = await getDocs(q);
|
|
205
|
-
|
|
206
|
-
if (querySnapshot.empty) {
|
|
207
|
-
return [];
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
return querySnapshot.docs.map((doc) => doc.data() as PatientToken);
|
|
211
|
-
};
|
|
1
|
+
import {
|
|
2
|
+
collection,
|
|
3
|
+
doc,
|
|
4
|
+
getDoc,
|
|
5
|
+
getDocs,
|
|
6
|
+
query,
|
|
7
|
+
where,
|
|
8
|
+
setDoc,
|
|
9
|
+
updateDoc,
|
|
10
|
+
Timestamp,
|
|
11
|
+
collectionGroup,
|
|
12
|
+
} from "firebase/firestore";
|
|
13
|
+
import { Firestore } from "firebase/firestore";
|
|
14
|
+
import { z } from "zod";
|
|
15
|
+
import {
|
|
16
|
+
PatientToken,
|
|
17
|
+
CreatePatientTokenData,
|
|
18
|
+
PatientTokenStatus,
|
|
19
|
+
INVITE_TOKENS_COLLECTION,
|
|
20
|
+
} from "../../../types/patient/token.types";
|
|
21
|
+
import {
|
|
22
|
+
patientTokenSchema,
|
|
23
|
+
createPatientTokenSchema,
|
|
24
|
+
} from "../../../validations/patient/token.schema";
|
|
25
|
+
import { getPatientDocRef } from "./docs.utils";
|
|
26
|
+
import { PATIENTS_COLLECTION } from "../../../types/patient";
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Creates a token for inviting a patient to claim their profile.
|
|
30
|
+
*
|
|
31
|
+
* @param {Firestore} db - The Firestore database instance.
|
|
32
|
+
* @param {CreatePatientTokenData} data - Data for creating the token.
|
|
33
|
+
* @param {string} createdBy - ID of the user creating the token.
|
|
34
|
+
* @param {() => string} generateId - Function to generate a unique ID.
|
|
35
|
+
* @returns {Promise<PatientToken>} The created token.
|
|
36
|
+
* @throws {Error} If the patient profile is not found, is not a manual profile, or if data is invalid.
|
|
37
|
+
*/
|
|
38
|
+
export const createPatientTokenUtil = async (
|
|
39
|
+
db: Firestore,
|
|
40
|
+
data: CreatePatientTokenData,
|
|
41
|
+
createdBy: string,
|
|
42
|
+
generateId: () => string
|
|
43
|
+
): Promise<PatientToken> => {
|
|
44
|
+
const validatedData = createPatientTokenSchema.parse(data);
|
|
45
|
+
|
|
46
|
+
// Check if patient exists and is a manual profile
|
|
47
|
+
const patientRef = getPatientDocRef(db, validatedData.patientId);
|
|
48
|
+
const patientDoc = await getDoc(patientRef);
|
|
49
|
+
if (!patientDoc.exists() || !patientDoc.data()?.isManual) {
|
|
50
|
+
throw new Error(
|
|
51
|
+
"Patient profile not found or is not a manually created profile."
|
|
52
|
+
);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// Default expiration is 7 days from now if not specified
|
|
56
|
+
const expiration =
|
|
57
|
+
validatedData.expiresAt || new Date(Date.now() + 7 * 24 * 60 * 60 * 1000);
|
|
58
|
+
|
|
59
|
+
const tokenString = generateId().slice(0, 6).toUpperCase();
|
|
60
|
+
|
|
61
|
+
const token: PatientToken = {
|
|
62
|
+
id: generateId(),
|
|
63
|
+
token: tokenString,
|
|
64
|
+
patientId: validatedData.patientId,
|
|
65
|
+
email: validatedData.email,
|
|
66
|
+
clinicId: validatedData.clinicId,
|
|
67
|
+
status: PatientTokenStatus.ACTIVE,
|
|
68
|
+
createdBy: createdBy,
|
|
69
|
+
createdAt: Timestamp.now(),
|
|
70
|
+
expiresAt: Timestamp.fromDate(expiration),
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
patientTokenSchema.parse(token);
|
|
74
|
+
|
|
75
|
+
const tokenRef = doc(
|
|
76
|
+
db,
|
|
77
|
+
PATIENTS_COLLECTION,
|
|
78
|
+
validatedData.patientId,
|
|
79
|
+
INVITE_TOKENS_COLLECTION,
|
|
80
|
+
token.id
|
|
81
|
+
);
|
|
82
|
+
await setDoc(tokenRef, token);
|
|
83
|
+
|
|
84
|
+
return token;
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Validates a patient invitation token.
|
|
89
|
+
*
|
|
90
|
+
* @param {Firestore} db - The Firestore database instance.
|
|
91
|
+
* @param {string} tokenString - The token string to validate.
|
|
92
|
+
* @returns {Promise<PatientToken | null>} The token if found and valid, otherwise null.
|
|
93
|
+
*/
|
|
94
|
+
export const validatePatientTokenUtil = async (
|
|
95
|
+
db: Firestore,
|
|
96
|
+
tokenString: string
|
|
97
|
+
): Promise<PatientToken | null> => {
|
|
98
|
+
const patientsRef = collection(db, PATIENTS_COLLECTION);
|
|
99
|
+
const patientsSnapshot = await getDocs(patientsRef);
|
|
100
|
+
|
|
101
|
+
for (const patientDoc of patientsSnapshot.docs) {
|
|
102
|
+
const tokensRef = collection(
|
|
103
|
+
db,
|
|
104
|
+
patientDoc.ref.path,
|
|
105
|
+
INVITE_TOKENS_COLLECTION
|
|
106
|
+
);
|
|
107
|
+
const q = query(
|
|
108
|
+
tokensRef,
|
|
109
|
+
where("token", "==", tokenString),
|
|
110
|
+
where("status", "==", PatientTokenStatus.ACTIVE),
|
|
111
|
+
where("expiresAt", ">", Timestamp.now())
|
|
112
|
+
);
|
|
113
|
+
|
|
114
|
+
const tokenSnapshot = await getDocs(q);
|
|
115
|
+
if (!tokenSnapshot.empty) {
|
|
116
|
+
return tokenSnapshot.docs[0].data() as PatientToken;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
return null;
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Marks a patient invitation token as used.
|
|
125
|
+
*
|
|
126
|
+
* @param {Firestore} db - The Firestore database instance.
|
|
127
|
+
* @param {string} tokenId - The ID of the token to mark as used.
|
|
128
|
+
* @param {string} patientId - The ID of the patient associated with the token.
|
|
129
|
+
* @param {string} userId - The ID of the user who is using the token.
|
|
130
|
+
* @returns {Promise<void>}
|
|
131
|
+
*/
|
|
132
|
+
export const markPatientTokenAsUsedUtil = async (
|
|
133
|
+
db: Firestore,
|
|
134
|
+
tokenId: string,
|
|
135
|
+
patientId: string,
|
|
136
|
+
userId: string
|
|
137
|
+
): Promise<void> => {
|
|
138
|
+
const tokenRef = doc(
|
|
139
|
+
db,
|
|
140
|
+
PATIENTS_COLLECTION,
|
|
141
|
+
patientId,
|
|
142
|
+
INVITE_TOKENS_COLLECTION,
|
|
143
|
+
tokenId
|
|
144
|
+
);
|
|
145
|
+
await updateDoc(tokenRef, {
|
|
146
|
+
status: PatientTokenStatus.USED,
|
|
147
|
+
usedBy: userId,
|
|
148
|
+
usedAt: Timestamp.now(),
|
|
149
|
+
});
|
|
150
|
+
};
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Retrieves all active invitation tokens for a specific clinic.
|
|
154
|
+
* This uses a collection group query to find tokens across all patients.
|
|
155
|
+
*
|
|
156
|
+
* @param {Firestore} db - The Firestore database instance.
|
|
157
|
+
* @param {string} clinicId - The ID of the clinic.
|
|
158
|
+
* @returns {Promise<PatientToken[]>} An array of active tokens for the clinic.
|
|
159
|
+
*/
|
|
160
|
+
export const getActiveInviteTokensByClinicUtil = async (
|
|
161
|
+
db: Firestore,
|
|
162
|
+
clinicId: string
|
|
163
|
+
): Promise<PatientToken[]> => {
|
|
164
|
+
const tokensQuery = query(
|
|
165
|
+
collectionGroup(db, INVITE_TOKENS_COLLECTION),
|
|
166
|
+
where("clinicId", "==", clinicId),
|
|
167
|
+
where("status", "==", PatientTokenStatus.ACTIVE),
|
|
168
|
+
where("expiresAt", ">", Timestamp.now())
|
|
169
|
+
);
|
|
170
|
+
|
|
171
|
+
const querySnapshot = await getDocs(tokensQuery);
|
|
172
|
+
|
|
173
|
+
if (querySnapshot.empty) {
|
|
174
|
+
return [];
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
return querySnapshot.docs.map((doc) => doc.data() as PatientToken);
|
|
178
|
+
};
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Retrieves all active invitation tokens for a specific patient.
|
|
182
|
+
*
|
|
183
|
+
* @param {Firestore} db - The Firestore database instance.
|
|
184
|
+
* @param {string} patientId - The ID of the patient.
|
|
185
|
+
* @returns {Promise<PatientToken[]>} An array of active tokens for the patient.
|
|
186
|
+
*/
|
|
187
|
+
export const getActiveInviteTokensByPatientUtil = async (
|
|
188
|
+
db: Firestore,
|
|
189
|
+
patientId: string
|
|
190
|
+
): Promise<PatientToken[]> => {
|
|
191
|
+
const tokensRef = collection(
|
|
192
|
+
db,
|
|
193
|
+
PATIENTS_COLLECTION,
|
|
194
|
+
patientId,
|
|
195
|
+
INVITE_TOKENS_COLLECTION
|
|
196
|
+
);
|
|
197
|
+
|
|
198
|
+
const q = query(
|
|
199
|
+
tokensRef,
|
|
200
|
+
where("status", "==", PatientTokenStatus.ACTIVE),
|
|
201
|
+
where("expiresAt", ">", Timestamp.now())
|
|
202
|
+
);
|
|
203
|
+
|
|
204
|
+
const querySnapshot = await getDocs(q);
|
|
205
|
+
|
|
206
|
+
if (querySnapshot.empty) {
|
|
207
|
+
return [];
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
return querySnapshot.docs.map((doc) => doc.data() as PatientToken);
|
|
211
|
+
};
|