@blackcode_sa/metaestetics-api 1.15.16 → 1.15.17-staging.1
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 +377 -222
- package/dist/admin/index.d.ts +377 -222
- package/dist/admin/index.js +625 -206
- package/dist/admin/index.mjs +624 -206
- package/dist/backoffice/index.d.mts +24 -0
- package/dist/backoffice/index.d.ts +24 -0
- package/dist/index.d.mts +292 -4
- package/dist/index.d.ts +292 -4
- package/dist/index.js +1142 -630
- package/dist/index.mjs +1137 -617
- package/package.json +2 -1
- package/src/__mocks__/firstore.ts +10 -10
- package/src/admin/aggregation/README.md +79 -79
- package/src/admin/aggregation/appointment/README.md +151 -129
- package/src/admin/aggregation/appointment/appointment.aggregation.service.ts +2137 -2091
- 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 -966
- 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 +184 -125
- package/src/admin/booking/booking.admin.ts +1330 -1073
- package/src/admin/booking/booking.calculator.ts +850 -712
- package/src/admin/booking/booking.types.ts +76 -59
- package/src/admin/booking/index.ts +3 -3
- package/src/admin/booking/timezones-problem.md +185 -185
- package/src/admin/calendar/README.md +62 -7
- package/src/admin/calendar/calendar.admin.service.ts +345 -345
- package/src/admin/calendar/index.ts +2 -1
- package/src/admin/calendar/resource-calendar.admin.ts +198 -0
- 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 +83 -83
- package/src/admin/logger/index.ts +78 -78
- package/src/admin/mailing/README.md +139 -139
- package/src/admin/mailing/appointment/appointment.mailing.service.ts +1253 -1253
- 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/clinicWelcome/clinicWelcome.mailing.ts +292 -292
- package/src/admin/mailing/clinicWelcome/index.ts +1 -1
- package/src/admin/mailing/clinicWelcome/templates/welcome.template.ts +225 -225
- package/src/admin/mailing/index.ts +5 -5
- package/src/admin/mailing/patientInvite/index.ts +2 -2
- package/src/admin/mailing/patientInvite/patientInvite.mailing.ts +415 -415
- package/src/admin/mailing/patientInvite/templates/invitation.template.ts +105 -105
- 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 +818 -818
- 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 +260 -260
- 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 +557 -557
- 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 +1153 -1153
- 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 +239 -239
- 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 +17 -17
- package/src/config/tiers.config.ts +255 -229
- package/src/errors/auth.error.ts +6 -6
- package/src/errors/auth.errors.ts +211 -211
- 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 +298 -298
- package/src/services/__tests__/auth.service.test.ts +310 -310
- package/src/services/__tests__/base.service.test.ts +36 -36
- package/src/services/__tests__/user.service.test.ts +530 -530
- 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 +2148 -2148
- 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 +2943 -2941
- package/src/services/appointment/index.ts +1 -1
- package/src/services/appointment/utils/appointment.utils.ts +620 -620
- package/src/services/appointment/utils/extended-procedure.utils.ts +354 -354
- package/src/services/appointment/utils/form-initialization.utils.ts +516 -516
- package/src/services/appointment/utils/recommended-procedure.utils.ts +195 -195
- package/src/services/appointment/utils/zone-management.utils.ts +468 -468
- package/src/services/appointment/utils/zone-photo.utils.ts +302 -302
- package/src/services/auth/auth.service.ts +1435 -1435
- 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 +1693 -1693
- 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 +676 -676
- 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 +265 -265
- package/src/services/clinic/__tests__/clinic-group.service.test.ts +222 -222
- package/src/services/clinic/__tests__/clinic.service.test.ts +302 -302
- 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 +720 -720
- 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 +1023 -1023
- package/src/services/clinic/utils/filter.utils.d.ts +23 -23
- package/src/services/clinic/utils/filter.utils.ts +462 -462
- package/src/services/clinic/utils/index.ts +10 -10
- package/src/services/clinic/utils/photos.utils.ts +188 -188
- package/src/services/clinic/utils/search.utils.ts +83 -83
- 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 +597 -597
- package/src/services/documentation-templates/index.ts +2 -2
- package/src/services/index.ts +16 -15
- 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 +286 -286
- package/src/services/patient/index.ts +2 -2
- package/src/services/patient/patient.service.ts +1021 -1021
- package/src/services/patient/patientRequirements.service.ts +309 -309
- package/src/services/patient/utils/aesthetic-analysis.utils.ts +176 -176
- package/src/services/patient/utils/body-assessment.utils.ts +159 -159
- package/src/services/patient/utils/clinic.utils.ts +159 -159
- package/src/services/patient/utils/docs.utils.ts +142 -142
- package/src/services/patient/utils/hair-scalp-assessment.utils.ts +158 -158
- 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/pre-surgical-assessment.utils.ts +161 -161
- 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/skin-quality-assessment.utils.ts +160 -160
- 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 +2355 -2354
- package/src/services/procedure/README.md +163 -163
- package/src/services/procedure/index.ts +1 -1
- package/src/services/procedure/procedure.service.ts +2521 -2521
- package/src/services/resource/README.md +119 -0
- package/src/services/resource/index.ts +1 -0
- package/src/services/resource/resource.service.ts +555 -0
- package/src/services/reviews/index.ts +1 -1
- package/src/services/reviews/reviews.service.ts +745 -745
- package/src/services/tier-enforcement.ts +240 -240
- package/src/services/user/index.ts +1 -1
- package/src/services/user/user.service.ts +533 -533
- package/src/services/user/user.v2.service.ts +467 -467
- 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 +524 -517
- package/src/types/calendar/index.ts +261 -260
- package/src/types/calendar/synced-calendar.types.ts +66 -66
- package/src/types/clinic/index.ts +530 -529
- package/src/types/clinic/practitioner-invite.types.ts +91 -91
- package/src/types/clinic/preferences.types.ts +159 -159
- package/src/types/clinic/rbac.types.ts +64 -63
- package/src/types/clinic/to-do +3 -3
- package/src/types/documentation-templates/index.ts +308 -308
- package/src/types/index.ts +50 -47
- package/src/types/notifications/README.md +77 -77
- package/src/types/notifications/index.ts +300 -300
- package/src/types/patient/aesthetic-analysis.types.ts +66 -66
- package/src/types/patient/allergies.ts +58 -58
- package/src/types/patient/body-assessment.types.ts +93 -93
- package/src/types/patient/hair-scalp-assessment.types.ts +98 -98
- package/src/types/patient/index.ts +279 -279
- package/src/types/patient/medical-info.types.ts +152 -152
- package/src/types/patient/patient-requirements.ts +92 -92
- package/src/types/patient/pre-surgical-assessment.types.ts +95 -95
- package/src/types/patient/skin-quality-assessment.types.ts +105 -105
- package/src/types/patient/token.types.ts +61 -61
- package/src/types/practitioner/index.ts +208 -208
- package/src/types/procedure/index.ts +189 -183
- package/src/types/profile/index.ts +39 -39
- package/src/types/resource/README.md +153 -0
- package/src/types/resource/index.ts +199 -0
- package/src/types/reviews/index.ts +132 -132
- package/src/types/tz-lookup.d.ts +4 -4
- package/src/types/user/index.ts +60 -60
- package/src/utils/TIMESTAMPS.md +176 -176
- package/src/utils/TimestampUtils.ts +241 -241
- package/src/utils/index.ts +1 -1
- package/src/validations/README.md +94 -0
- package/src/validations/appointment.schema.ts +589 -589
- 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 +21 -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/body-assessment.schema.ts +82 -82
- package/src/validations/patient/hair-scalp-assessment.schema.ts +70 -70
- package/src/validations/patient/medical-info.schema.ts +177 -177
- package/src/validations/patient/patient-requirements.schema.ts +84 -84
- package/src/validations/patient/pre-surgical-assessment.schema.ts +78 -78
- package/src/validations/patient/skin-quality-assessment.schema.ts +70 -70
- package/src/validations/patient/token.schema.ts +29 -29
- package/src/validations/patient.schema.ts +217 -217
- package/src/validations/practitioner.schema.ts +224 -224
- package/src/validations/procedure-product.schema.ts +41 -41
- package/src/validations/procedure.schema.ts +136 -124
- package/src/validations/profile-info.schema.ts +41 -41
- package/src/validations/resource.schema.ts +57 -0
- package/src/validations/reviews.schema.ts +195 -195
- package/src/validations/schemas.ts +109 -109
- package/src/validations/shared.schema.ts +78 -78
|
@@ -1,159 +1,159 @@
|
|
|
1
|
-
import {
|
|
2
|
-
collection,
|
|
3
|
-
query,
|
|
4
|
-
where,
|
|
5
|
-
getDocs,
|
|
6
|
-
Firestore,
|
|
7
|
-
limit,
|
|
8
|
-
startAfter,
|
|
9
|
-
doc,
|
|
10
|
-
getDoc,
|
|
11
|
-
QueryConstraint,
|
|
12
|
-
} from "firebase/firestore";
|
|
13
|
-
import {
|
|
14
|
-
PatientProfile,
|
|
15
|
-
PATIENTS_COLLECTION,
|
|
16
|
-
PatientSensitiveInfo,
|
|
17
|
-
} from "../../../types/patient";
|
|
18
|
-
import { getSensitiveInfoDocRef } from "./docs.utils";
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* Retrieves all patients associated with a specific clinic with pagination support.
|
|
22
|
-
*
|
|
23
|
-
* @param {Firestore} db - Firestore instance
|
|
24
|
-
* @param {string} clinicId - ID of the clinic whose patients to retrieve
|
|
25
|
-
* @param {Object} options - Optional parameters for pagination
|
|
26
|
-
* @param {number} options.limit - Maximum number of profiles to return
|
|
27
|
-
* @param {string} options.startAfter - The ID of the document to start after (for pagination)
|
|
28
|
-
* @returns {Promise<PatientProfile[]>} A promise resolving to an array of patient profiles
|
|
29
|
-
*/
|
|
30
|
-
export const getPatientsByClinicUtil = async (
|
|
31
|
-
db: Firestore,
|
|
32
|
-
clinicId: string,
|
|
33
|
-
options?: { limit?: number; startAfter?: string }
|
|
34
|
-
): Promise<PatientProfile[]> => {
|
|
35
|
-
try {
|
|
36
|
-
console.log(
|
|
37
|
-
`[getPatientsByClinicUtil] Fetching patients for clinic ID: ${clinicId} with options:`,
|
|
38
|
-
options
|
|
39
|
-
);
|
|
40
|
-
|
|
41
|
-
const patientsCollection = collection(db, PATIENTS_COLLECTION);
|
|
42
|
-
const constraints: QueryConstraint[] = [
|
|
43
|
-
where("clinicIds", "array-contains", clinicId),
|
|
44
|
-
];
|
|
45
|
-
|
|
46
|
-
let q = query(patientsCollection, ...constraints);
|
|
47
|
-
|
|
48
|
-
// Apply pagination if needed
|
|
49
|
-
if (options?.limit) {
|
|
50
|
-
q = query(q, limit(options.limit));
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
// If startAfter is provided, get that document and use it for pagination
|
|
54
|
-
if (options?.startAfter) {
|
|
55
|
-
const startAfterDoc = await getDoc(
|
|
56
|
-
doc(db, PATIENTS_COLLECTION, options.startAfter)
|
|
57
|
-
);
|
|
58
|
-
if (startAfterDoc.exists()) {
|
|
59
|
-
q = query(q, startAfter(startAfterDoc));
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
const patientsSnapshot = await getDocs(q);
|
|
64
|
-
|
|
65
|
-
const patients: PatientProfile[] = [];
|
|
66
|
-
patientsSnapshot.forEach((doc) => {
|
|
67
|
-
patients.push(doc.data() as PatientProfile);
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
console.log(
|
|
71
|
-
`[getPatientsByClinicUtil] Found ${patients.length} patients for clinic ID: ${clinicId}`
|
|
72
|
-
);
|
|
73
|
-
return patients;
|
|
74
|
-
} catch (error) {
|
|
75
|
-
console.error(
|
|
76
|
-
`[getPatientsByClinicUtil] Error fetching patients for clinic:`,
|
|
77
|
-
error
|
|
78
|
-
);
|
|
79
|
-
throw new Error(
|
|
80
|
-
`Failed to retrieve patients for clinic: ${
|
|
81
|
-
error instanceof Error ? error.message : String(error)
|
|
82
|
-
}`
|
|
83
|
-
);
|
|
84
|
-
}
|
|
85
|
-
};
|
|
86
|
-
|
|
87
|
-
/**
|
|
88
|
-
* Retrieves all patients associated with a specific clinic, including their sensitive info.
|
|
89
|
-
* This merges data from PatientProfile and PatientSensitiveInfo subcollection.
|
|
90
|
-
*
|
|
91
|
-
* @param {Firestore} db - Firestore instance
|
|
92
|
-
* @param {string} clinicId - ID of the clinic whose patients to retrieve
|
|
93
|
-
* @param {Object} options - Optional parameters for pagination
|
|
94
|
-
* @param {number} options.limit - Maximum number of profiles to return
|
|
95
|
-
* @param {string} options.startAfter - The ID of the document to start after (for pagination)
|
|
96
|
-
* @returns {Promise<PatientProfile[]>} A promise resolving to an array of patient profiles with merged sensitive info
|
|
97
|
-
*/
|
|
98
|
-
export const getPatientsByClinicWithDetailsUtil = async (
|
|
99
|
-
db: Firestore,
|
|
100
|
-
clinicId: string,
|
|
101
|
-
options?: { limit?: number; startAfter?: string }
|
|
102
|
-
): Promise<PatientProfile[]> => {
|
|
103
|
-
try {
|
|
104
|
-
console.log(
|
|
105
|
-
`[getPatientsByClinicWithDetailsUtil] Fetching patients with details for clinic ID: ${clinicId} with options:`,
|
|
106
|
-
options
|
|
107
|
-
);
|
|
108
|
-
|
|
109
|
-
// First, get all patient profiles for this clinic
|
|
110
|
-
const patientProfiles = await getPatientsByClinicUtil(db, clinicId, options);
|
|
111
|
-
|
|
112
|
-
// Then, fetch sensitive info for each patient and merge it
|
|
113
|
-
const patientsWithDetails: PatientProfile[] = await Promise.all(
|
|
114
|
-
patientProfiles.map(async (profile) => {
|
|
115
|
-
try {
|
|
116
|
-
const sensitiveInfoDoc = await getDoc(
|
|
117
|
-
getSensitiveInfoDocRef(db, profile.id)
|
|
118
|
-
);
|
|
119
|
-
const sensitiveInfo = sensitiveInfoDoc.exists()
|
|
120
|
-
? (sensitiveInfoDoc.data() as PatientSensitiveInfo)
|
|
121
|
-
: null;
|
|
122
|
-
|
|
123
|
-
// Merge sensitive info into profile (sensitive-info is source of truth for PII)
|
|
124
|
-
return {
|
|
125
|
-
...profile,
|
|
126
|
-
// Prefer phoneNumber from sensitive-info (patient self-updated); fallback to profile (manual creation)
|
|
127
|
-
phoneNumber: sensitiveInfo?.phoneNumber ?? profile.phoneNumber ?? null,
|
|
128
|
-
// Prefer dateOfBirth from sensitive-info
|
|
129
|
-
dateOfBirth: sensitiveInfo?.dateOfBirth ?? profile.dateOfBirth ?? null,
|
|
130
|
-
// Merge photoUrl from sensitive info if available
|
|
131
|
-
photoUrl: sensitiveInfo?.photoUrl || null,
|
|
132
|
-
} as PatientProfile & { photoUrl?: string | null };
|
|
133
|
-
} catch (error) {
|
|
134
|
-
console.error(
|
|
135
|
-
`[getPatientsByClinicWithDetailsUtil] Error fetching sensitive info for patient ${profile.id}:`,
|
|
136
|
-
error
|
|
137
|
-
);
|
|
138
|
-
// Return profile without sensitive info in case of error
|
|
139
|
-
return profile;
|
|
140
|
-
}
|
|
141
|
-
})
|
|
142
|
-
);
|
|
143
|
-
|
|
144
|
-
console.log(
|
|
145
|
-
`[getPatientsByClinicWithDetailsUtil] Found ${patientsWithDetails.length} patients with details for clinic ID: ${clinicId}`
|
|
146
|
-
);
|
|
147
|
-
return patientsWithDetails;
|
|
148
|
-
} catch (error) {
|
|
149
|
-
console.error(
|
|
150
|
-
`[getPatientsByClinicWithDetailsUtil] Error fetching patients with details:`,
|
|
151
|
-
error
|
|
152
|
-
);
|
|
153
|
-
throw new Error(
|
|
154
|
-
`Failed to retrieve patients with details: ${
|
|
155
|
-
error instanceof Error ? error.message : String(error)
|
|
156
|
-
}`
|
|
157
|
-
);
|
|
158
|
-
}
|
|
159
|
-
};
|
|
1
|
+
import {
|
|
2
|
+
collection,
|
|
3
|
+
query,
|
|
4
|
+
where,
|
|
5
|
+
getDocs,
|
|
6
|
+
Firestore,
|
|
7
|
+
limit,
|
|
8
|
+
startAfter,
|
|
9
|
+
doc,
|
|
10
|
+
getDoc,
|
|
11
|
+
QueryConstraint,
|
|
12
|
+
} from "firebase/firestore";
|
|
13
|
+
import {
|
|
14
|
+
PatientProfile,
|
|
15
|
+
PATIENTS_COLLECTION,
|
|
16
|
+
PatientSensitiveInfo,
|
|
17
|
+
} from "../../../types/patient";
|
|
18
|
+
import { getSensitiveInfoDocRef } from "./docs.utils";
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Retrieves all patients associated with a specific clinic with pagination support.
|
|
22
|
+
*
|
|
23
|
+
* @param {Firestore} db - Firestore instance
|
|
24
|
+
* @param {string} clinicId - ID of the clinic whose patients to retrieve
|
|
25
|
+
* @param {Object} options - Optional parameters for pagination
|
|
26
|
+
* @param {number} options.limit - Maximum number of profiles to return
|
|
27
|
+
* @param {string} options.startAfter - The ID of the document to start after (for pagination)
|
|
28
|
+
* @returns {Promise<PatientProfile[]>} A promise resolving to an array of patient profiles
|
|
29
|
+
*/
|
|
30
|
+
export const getPatientsByClinicUtil = async (
|
|
31
|
+
db: Firestore,
|
|
32
|
+
clinicId: string,
|
|
33
|
+
options?: { limit?: number; startAfter?: string }
|
|
34
|
+
): Promise<PatientProfile[]> => {
|
|
35
|
+
try {
|
|
36
|
+
console.log(
|
|
37
|
+
`[getPatientsByClinicUtil] Fetching patients for clinic ID: ${clinicId} with options:`,
|
|
38
|
+
options
|
|
39
|
+
);
|
|
40
|
+
|
|
41
|
+
const patientsCollection = collection(db, PATIENTS_COLLECTION);
|
|
42
|
+
const constraints: QueryConstraint[] = [
|
|
43
|
+
where("clinicIds", "array-contains", clinicId),
|
|
44
|
+
];
|
|
45
|
+
|
|
46
|
+
let q = query(patientsCollection, ...constraints);
|
|
47
|
+
|
|
48
|
+
// Apply pagination if needed
|
|
49
|
+
if (options?.limit) {
|
|
50
|
+
q = query(q, limit(options.limit));
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// If startAfter is provided, get that document and use it for pagination
|
|
54
|
+
if (options?.startAfter) {
|
|
55
|
+
const startAfterDoc = await getDoc(
|
|
56
|
+
doc(db, PATIENTS_COLLECTION, options.startAfter)
|
|
57
|
+
);
|
|
58
|
+
if (startAfterDoc.exists()) {
|
|
59
|
+
q = query(q, startAfter(startAfterDoc));
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const patientsSnapshot = await getDocs(q);
|
|
64
|
+
|
|
65
|
+
const patients: PatientProfile[] = [];
|
|
66
|
+
patientsSnapshot.forEach((doc) => {
|
|
67
|
+
patients.push(doc.data() as PatientProfile);
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
console.log(
|
|
71
|
+
`[getPatientsByClinicUtil] Found ${patients.length} patients for clinic ID: ${clinicId}`
|
|
72
|
+
);
|
|
73
|
+
return patients;
|
|
74
|
+
} catch (error) {
|
|
75
|
+
console.error(
|
|
76
|
+
`[getPatientsByClinicUtil] Error fetching patients for clinic:`,
|
|
77
|
+
error
|
|
78
|
+
);
|
|
79
|
+
throw new Error(
|
|
80
|
+
`Failed to retrieve patients for clinic: ${
|
|
81
|
+
error instanceof Error ? error.message : String(error)
|
|
82
|
+
}`
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Retrieves all patients associated with a specific clinic, including their sensitive info.
|
|
89
|
+
* This merges data from PatientProfile and PatientSensitiveInfo subcollection.
|
|
90
|
+
*
|
|
91
|
+
* @param {Firestore} db - Firestore instance
|
|
92
|
+
* @param {string} clinicId - ID of the clinic whose patients to retrieve
|
|
93
|
+
* @param {Object} options - Optional parameters for pagination
|
|
94
|
+
* @param {number} options.limit - Maximum number of profiles to return
|
|
95
|
+
* @param {string} options.startAfter - The ID of the document to start after (for pagination)
|
|
96
|
+
* @returns {Promise<PatientProfile[]>} A promise resolving to an array of patient profiles with merged sensitive info
|
|
97
|
+
*/
|
|
98
|
+
export const getPatientsByClinicWithDetailsUtil = async (
|
|
99
|
+
db: Firestore,
|
|
100
|
+
clinicId: string,
|
|
101
|
+
options?: { limit?: number; startAfter?: string }
|
|
102
|
+
): Promise<PatientProfile[]> => {
|
|
103
|
+
try {
|
|
104
|
+
console.log(
|
|
105
|
+
`[getPatientsByClinicWithDetailsUtil] Fetching patients with details for clinic ID: ${clinicId} with options:`,
|
|
106
|
+
options
|
|
107
|
+
);
|
|
108
|
+
|
|
109
|
+
// First, get all patient profiles for this clinic
|
|
110
|
+
const patientProfiles = await getPatientsByClinicUtil(db, clinicId, options);
|
|
111
|
+
|
|
112
|
+
// Then, fetch sensitive info for each patient and merge it
|
|
113
|
+
const patientsWithDetails: PatientProfile[] = await Promise.all(
|
|
114
|
+
patientProfiles.map(async (profile) => {
|
|
115
|
+
try {
|
|
116
|
+
const sensitiveInfoDoc = await getDoc(
|
|
117
|
+
getSensitiveInfoDocRef(db, profile.id)
|
|
118
|
+
);
|
|
119
|
+
const sensitiveInfo = sensitiveInfoDoc.exists()
|
|
120
|
+
? (sensitiveInfoDoc.data() as PatientSensitiveInfo)
|
|
121
|
+
: null;
|
|
122
|
+
|
|
123
|
+
// Merge sensitive info into profile (sensitive-info is source of truth for PII)
|
|
124
|
+
return {
|
|
125
|
+
...profile,
|
|
126
|
+
// Prefer phoneNumber from sensitive-info (patient self-updated); fallback to profile (manual creation)
|
|
127
|
+
phoneNumber: sensitiveInfo?.phoneNumber ?? profile.phoneNumber ?? null,
|
|
128
|
+
// Prefer dateOfBirth from sensitive-info
|
|
129
|
+
dateOfBirth: sensitiveInfo?.dateOfBirth ?? profile.dateOfBirth ?? null,
|
|
130
|
+
// Merge photoUrl from sensitive info if available
|
|
131
|
+
photoUrl: sensitiveInfo?.photoUrl || null,
|
|
132
|
+
} as PatientProfile & { photoUrl?: string | null };
|
|
133
|
+
} catch (error) {
|
|
134
|
+
console.error(
|
|
135
|
+
`[getPatientsByClinicWithDetailsUtil] Error fetching sensitive info for patient ${profile.id}:`,
|
|
136
|
+
error
|
|
137
|
+
);
|
|
138
|
+
// Return profile without sensitive info in case of error
|
|
139
|
+
return profile;
|
|
140
|
+
}
|
|
141
|
+
})
|
|
142
|
+
);
|
|
143
|
+
|
|
144
|
+
console.log(
|
|
145
|
+
`[getPatientsByClinicWithDetailsUtil] Found ${patientsWithDetails.length} patients with details for clinic ID: ${clinicId}`
|
|
146
|
+
);
|
|
147
|
+
return patientsWithDetails;
|
|
148
|
+
} catch (error) {
|
|
149
|
+
console.error(
|
|
150
|
+
`[getPatientsByClinicWithDetailsUtil] Error fetching patients with details:`,
|
|
151
|
+
error
|
|
152
|
+
);
|
|
153
|
+
throw new Error(
|
|
154
|
+
`Failed to retrieve patients with details: ${
|
|
155
|
+
error instanceof Error ? error.message : String(error)
|
|
156
|
+
}`
|
|
157
|
+
);
|
|
158
|
+
}
|
|
159
|
+
};
|
|
@@ -1,142 +1,142 @@
|
|
|
1
|
-
import {
|
|
2
|
-
doc,
|
|
3
|
-
collection,
|
|
4
|
-
query,
|
|
5
|
-
where,
|
|
6
|
-
getDocs,
|
|
7
|
-
Firestore,
|
|
8
|
-
getDoc,
|
|
9
|
-
setDoc,
|
|
10
|
-
serverTimestamp,
|
|
11
|
-
} from "firebase/firestore";
|
|
12
|
-
import {
|
|
13
|
-
PATIENTS_COLLECTION,
|
|
14
|
-
PATIENT_SENSITIVE_INFO_COLLECTION,
|
|
15
|
-
PATIENT_LOCATION_INFO_COLLECTION,
|
|
16
|
-
PATIENT_MEDICAL_INFO_COLLECTION,
|
|
17
|
-
} from "../../../types/patient";
|
|
18
|
-
import { createSensitiveInfoUtil } from "./sensitive.utils";
|
|
19
|
-
import { Gender } from "../../../types/patient";
|
|
20
|
-
|
|
21
|
-
// Osnovne reference
|
|
22
|
-
export const getPatientDocRef = (db: Firestore, patientId: string) => {
|
|
23
|
-
return doc(db, PATIENTS_COLLECTION, patientId);
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
export const getPatientDocRefByUserRef = async (
|
|
27
|
-
db: Firestore,
|
|
28
|
-
userRef: string
|
|
29
|
-
) => {
|
|
30
|
-
const patientsRef = collection(db, PATIENTS_COLLECTION);
|
|
31
|
-
const q = query(patientsRef, where("userRef", "==", userRef));
|
|
32
|
-
const querySnapshot = await getDocs(q);
|
|
33
|
-
|
|
34
|
-
if (querySnapshot.empty) {
|
|
35
|
-
throw new Error("Patient profile not found");
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
return doc(db, PATIENTS_COLLECTION, querySnapshot.docs[0].id);
|
|
39
|
-
};
|
|
40
|
-
|
|
41
|
-
// Reference za subkolekcije
|
|
42
|
-
export const getSensitiveInfoDocRef = (db: Firestore, patientId: string) => {
|
|
43
|
-
const path = `${PATIENTS_COLLECTION}/${patientId}/${PATIENT_SENSITIVE_INFO_COLLECTION}/${patientId}`;
|
|
44
|
-
console.log(`[getSensitiveInfoDocRef] Creating reference with path: ${path}`);
|
|
45
|
-
return doc(
|
|
46
|
-
db,
|
|
47
|
-
PATIENTS_COLLECTION,
|
|
48
|
-
patientId,
|
|
49
|
-
PATIENT_SENSITIVE_INFO_COLLECTION,
|
|
50
|
-
patientId
|
|
51
|
-
);
|
|
52
|
-
};
|
|
53
|
-
|
|
54
|
-
export const getLocationInfoDocRef = (db: Firestore, patientId: string) => {
|
|
55
|
-
const path = `${PATIENTS_COLLECTION}/${patientId}/${PATIENT_LOCATION_INFO_COLLECTION}/${patientId}`;
|
|
56
|
-
console.log(`[getLocationInfoDocRef] Creating reference with path: ${path}`);
|
|
57
|
-
return doc(
|
|
58
|
-
db,
|
|
59
|
-
PATIENTS_COLLECTION,
|
|
60
|
-
patientId,
|
|
61
|
-
PATIENT_LOCATION_INFO_COLLECTION,
|
|
62
|
-
patientId
|
|
63
|
-
);
|
|
64
|
-
};
|
|
65
|
-
|
|
66
|
-
export const getMedicalInfoDocRef = (db: Firestore, patientId: string) => {
|
|
67
|
-
const path = `${PATIENTS_COLLECTION}/${patientId}/${PATIENT_MEDICAL_INFO_COLLECTION}/${patientId}`;
|
|
68
|
-
console.log(`[getMedicalInfoDocRef] Creating reference with path: ${path}`);
|
|
69
|
-
return doc(
|
|
70
|
-
db,
|
|
71
|
-
PATIENTS_COLLECTION,
|
|
72
|
-
patientId,
|
|
73
|
-
PATIENT_MEDICAL_INFO_COLLECTION,
|
|
74
|
-
patientId
|
|
75
|
-
);
|
|
76
|
-
};
|
|
77
|
-
|
|
78
|
-
// Funkcija za inicijalizaciju dokumenta sa osetljivim informacijama ako ne postoji
|
|
79
|
-
export const initSensitiveInfoDocIfNotExists = async (
|
|
80
|
-
db: Firestore,
|
|
81
|
-
patientId: string,
|
|
82
|
-
userRef: string
|
|
83
|
-
) => {
|
|
84
|
-
console.log(
|
|
85
|
-
`[initSensitiveInfoDocIfNotExists] Starting for patientId: ${patientId}, userRef: ${userRef}`
|
|
86
|
-
);
|
|
87
|
-
|
|
88
|
-
try {
|
|
89
|
-
const sensitiveInfoRef = getSensitiveInfoDocRef(db, patientId);
|
|
90
|
-
console.log(
|
|
91
|
-
`[initSensitiveInfoDocIfNotExists] Got document reference: ${sensitiveInfoRef.path}`
|
|
92
|
-
);
|
|
93
|
-
|
|
94
|
-
const sensitiveDoc = await getDoc(sensitiveInfoRef);
|
|
95
|
-
console.log(
|
|
96
|
-
`[initSensitiveInfoDocIfNotExists] Document exists: ${sensitiveDoc.exists()}`
|
|
97
|
-
);
|
|
98
|
-
|
|
99
|
-
if (!sensitiveDoc.exists()) {
|
|
100
|
-
// Inicijalizacija sa podrazumevanim vrednostima prema strukturi iz index.ts
|
|
101
|
-
const defaultSensitiveInfo = {
|
|
102
|
-
patientId,
|
|
103
|
-
userRef,
|
|
104
|
-
firstName: "Name",
|
|
105
|
-
lastName: "Surname",
|
|
106
|
-
dateOfBirth: null, // Koristimo serverTimestamp kao placeholder
|
|
107
|
-
gender: Gender.PREFER_NOT_TO_SAY, // Koristimo podrazumevanu vrednost iz Gender enuma
|
|
108
|
-
phoneNumber: "",
|
|
109
|
-
};
|
|
110
|
-
|
|
111
|
-
console.log(
|
|
112
|
-
`[initSensitiveInfoDocIfNotExists] Creating new document with data:`,
|
|
113
|
-
JSON.stringify(defaultSensitiveInfo, (key, value) =>
|
|
114
|
-
value &&
|
|
115
|
-
typeof value === "object" &&
|
|
116
|
-
value.constructor &&
|
|
117
|
-
value.constructor.name === "Object"
|
|
118
|
-
? "[serverTimestamp]"
|
|
119
|
-
: value
|
|
120
|
-
)
|
|
121
|
-
);
|
|
122
|
-
|
|
123
|
-
await createSensitiveInfoUtil(db, defaultSensitiveInfo, userRef, []);
|
|
124
|
-
|
|
125
|
-
// Verify document was created
|
|
126
|
-
const verifyDoc = await getDoc(sensitiveInfoRef);
|
|
127
|
-
console.log(
|
|
128
|
-
`[initSensitiveInfoDocIfNotExists] Verification - document exists: ${verifyDoc.exists()}`
|
|
129
|
-
);
|
|
130
|
-
|
|
131
|
-
return false; // Dokument nije postojao, kreiran je novi
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
console.log(
|
|
135
|
-
`[initSensitiveInfoDocIfNotExists] Document already exists, no action taken`
|
|
136
|
-
);
|
|
137
|
-
return true; // Dokument već postoji
|
|
138
|
-
} catch (error) {
|
|
139
|
-
console.error(`[initSensitiveInfoDocIfNotExists] Error:`, error);
|
|
140
|
-
throw error;
|
|
141
|
-
}
|
|
142
|
-
};
|
|
1
|
+
import {
|
|
2
|
+
doc,
|
|
3
|
+
collection,
|
|
4
|
+
query,
|
|
5
|
+
where,
|
|
6
|
+
getDocs,
|
|
7
|
+
Firestore,
|
|
8
|
+
getDoc,
|
|
9
|
+
setDoc,
|
|
10
|
+
serverTimestamp,
|
|
11
|
+
} from "firebase/firestore";
|
|
12
|
+
import {
|
|
13
|
+
PATIENTS_COLLECTION,
|
|
14
|
+
PATIENT_SENSITIVE_INFO_COLLECTION,
|
|
15
|
+
PATIENT_LOCATION_INFO_COLLECTION,
|
|
16
|
+
PATIENT_MEDICAL_INFO_COLLECTION,
|
|
17
|
+
} from "../../../types/patient";
|
|
18
|
+
import { createSensitiveInfoUtil } from "./sensitive.utils";
|
|
19
|
+
import { Gender } from "../../../types/patient";
|
|
20
|
+
|
|
21
|
+
// Osnovne reference
|
|
22
|
+
export const getPatientDocRef = (db: Firestore, patientId: string) => {
|
|
23
|
+
return doc(db, PATIENTS_COLLECTION, patientId);
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
export const getPatientDocRefByUserRef = async (
|
|
27
|
+
db: Firestore,
|
|
28
|
+
userRef: string
|
|
29
|
+
) => {
|
|
30
|
+
const patientsRef = collection(db, PATIENTS_COLLECTION);
|
|
31
|
+
const q = query(patientsRef, where("userRef", "==", userRef));
|
|
32
|
+
const querySnapshot = await getDocs(q);
|
|
33
|
+
|
|
34
|
+
if (querySnapshot.empty) {
|
|
35
|
+
throw new Error("Patient profile not found");
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
return doc(db, PATIENTS_COLLECTION, querySnapshot.docs[0].id);
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
// Reference za subkolekcije
|
|
42
|
+
export const getSensitiveInfoDocRef = (db: Firestore, patientId: string) => {
|
|
43
|
+
const path = `${PATIENTS_COLLECTION}/${patientId}/${PATIENT_SENSITIVE_INFO_COLLECTION}/${patientId}`;
|
|
44
|
+
console.log(`[getSensitiveInfoDocRef] Creating reference with path: ${path}`);
|
|
45
|
+
return doc(
|
|
46
|
+
db,
|
|
47
|
+
PATIENTS_COLLECTION,
|
|
48
|
+
patientId,
|
|
49
|
+
PATIENT_SENSITIVE_INFO_COLLECTION,
|
|
50
|
+
patientId
|
|
51
|
+
);
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
export const getLocationInfoDocRef = (db: Firestore, patientId: string) => {
|
|
55
|
+
const path = `${PATIENTS_COLLECTION}/${patientId}/${PATIENT_LOCATION_INFO_COLLECTION}/${patientId}`;
|
|
56
|
+
console.log(`[getLocationInfoDocRef] Creating reference with path: ${path}`);
|
|
57
|
+
return doc(
|
|
58
|
+
db,
|
|
59
|
+
PATIENTS_COLLECTION,
|
|
60
|
+
patientId,
|
|
61
|
+
PATIENT_LOCATION_INFO_COLLECTION,
|
|
62
|
+
patientId
|
|
63
|
+
);
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
export const getMedicalInfoDocRef = (db: Firestore, patientId: string) => {
|
|
67
|
+
const path = `${PATIENTS_COLLECTION}/${patientId}/${PATIENT_MEDICAL_INFO_COLLECTION}/${patientId}`;
|
|
68
|
+
console.log(`[getMedicalInfoDocRef] Creating reference with path: ${path}`);
|
|
69
|
+
return doc(
|
|
70
|
+
db,
|
|
71
|
+
PATIENTS_COLLECTION,
|
|
72
|
+
patientId,
|
|
73
|
+
PATIENT_MEDICAL_INFO_COLLECTION,
|
|
74
|
+
patientId
|
|
75
|
+
);
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
// Funkcija za inicijalizaciju dokumenta sa osetljivim informacijama ako ne postoji
|
|
79
|
+
export const initSensitiveInfoDocIfNotExists = async (
|
|
80
|
+
db: Firestore,
|
|
81
|
+
patientId: string,
|
|
82
|
+
userRef: string
|
|
83
|
+
) => {
|
|
84
|
+
console.log(
|
|
85
|
+
`[initSensitiveInfoDocIfNotExists] Starting for patientId: ${patientId}, userRef: ${userRef}`
|
|
86
|
+
);
|
|
87
|
+
|
|
88
|
+
try {
|
|
89
|
+
const sensitiveInfoRef = getSensitiveInfoDocRef(db, patientId);
|
|
90
|
+
console.log(
|
|
91
|
+
`[initSensitiveInfoDocIfNotExists] Got document reference: ${sensitiveInfoRef.path}`
|
|
92
|
+
);
|
|
93
|
+
|
|
94
|
+
const sensitiveDoc = await getDoc(sensitiveInfoRef);
|
|
95
|
+
console.log(
|
|
96
|
+
`[initSensitiveInfoDocIfNotExists] Document exists: ${sensitiveDoc.exists()}`
|
|
97
|
+
);
|
|
98
|
+
|
|
99
|
+
if (!sensitiveDoc.exists()) {
|
|
100
|
+
// Inicijalizacija sa podrazumevanim vrednostima prema strukturi iz index.ts
|
|
101
|
+
const defaultSensitiveInfo = {
|
|
102
|
+
patientId,
|
|
103
|
+
userRef,
|
|
104
|
+
firstName: "Name",
|
|
105
|
+
lastName: "Surname",
|
|
106
|
+
dateOfBirth: null, // Koristimo serverTimestamp kao placeholder
|
|
107
|
+
gender: Gender.PREFER_NOT_TO_SAY, // Koristimo podrazumevanu vrednost iz Gender enuma
|
|
108
|
+
phoneNumber: "",
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
console.log(
|
|
112
|
+
`[initSensitiveInfoDocIfNotExists] Creating new document with data:`,
|
|
113
|
+
JSON.stringify(defaultSensitiveInfo, (key, value) =>
|
|
114
|
+
value &&
|
|
115
|
+
typeof value === "object" &&
|
|
116
|
+
value.constructor &&
|
|
117
|
+
value.constructor.name === "Object"
|
|
118
|
+
? "[serverTimestamp]"
|
|
119
|
+
: value
|
|
120
|
+
)
|
|
121
|
+
);
|
|
122
|
+
|
|
123
|
+
await createSensitiveInfoUtil(db, defaultSensitiveInfo, userRef, []);
|
|
124
|
+
|
|
125
|
+
// Verify document was created
|
|
126
|
+
const verifyDoc = await getDoc(sensitiveInfoRef);
|
|
127
|
+
console.log(
|
|
128
|
+
`[initSensitiveInfoDocIfNotExists] Verification - document exists: ${verifyDoc.exists()}`
|
|
129
|
+
);
|
|
130
|
+
|
|
131
|
+
return false; // Dokument nije postojao, kreiran je novi
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
console.log(
|
|
135
|
+
`[initSensitiveInfoDocIfNotExists] Document already exists, no action taken`
|
|
136
|
+
);
|
|
137
|
+
return true; // Dokument već postoji
|
|
138
|
+
} catch (error) {
|
|
139
|
+
console.error(`[initSensitiveInfoDocIfNotExists] Error:`, error);
|
|
140
|
+
throw error;
|
|
141
|
+
}
|
|
142
|
+
};
|