@blackcode_sa/metaestetics-api 1.5.43 → 1.5.45
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.js +159 -23
- package/dist/admin/index.mjs +159 -23
- package/dist/index.d.mts +40 -2
- package/dist/index.d.ts +40 -2
- package/dist/index.js +1138 -942
- package/dist/index.mjs +1012 -798
- package/package.json +1 -1
- package/src/admin/mailing/base.mailing.service.ts +108 -29
- package/src/admin/mailing/practitionerInvite/practitionerInvite.mailing.ts +88 -2
- package/src/services/appointment/appointment.service.ts +55 -0
- package/src/services/patient/patient.service.ts +180 -57
- package/src/services/patient/utils/clinic.utils.ts +80 -0
- package/src/services/patient/utils/practitioner.utils.ts +80 -0
|
@@ -5,8 +5,8 @@ import {
|
|
|
5
5
|
updateDoc,
|
|
6
6
|
arrayUnion,
|
|
7
7
|
serverTimestamp,
|
|
8
|
-
} from
|
|
9
|
-
import { BaseService } from
|
|
8
|
+
} from "firebase/firestore";
|
|
9
|
+
import { BaseService } from "../base.service";
|
|
10
10
|
import {
|
|
11
11
|
PatientProfile,
|
|
12
12
|
PatientSensitiveInfo,
|
|
@@ -31,11 +31,11 @@ import {
|
|
|
31
31
|
PatientClinic,
|
|
32
32
|
SearchPatientsParams,
|
|
33
33
|
RequesterInfo,
|
|
34
|
-
} from
|
|
35
|
-
import { Auth } from
|
|
36
|
-
import { Firestore } from
|
|
37
|
-
import { FirebaseApp } from
|
|
38
|
-
import { Timestamp } from
|
|
34
|
+
} from "../../types/patient";
|
|
35
|
+
import { Auth } from "firebase/auth";
|
|
36
|
+
import { Firestore } from "firebase/firestore";
|
|
37
|
+
import { FirebaseApp } from "firebase/app";
|
|
38
|
+
import { Timestamp } from "firebase/firestore";
|
|
39
39
|
|
|
40
40
|
// Importujemo utility funkcije
|
|
41
41
|
import {
|
|
@@ -52,20 +52,20 @@ import {
|
|
|
52
52
|
updatePatientProfileByUserRefUtil,
|
|
53
53
|
searchPatientsUtil,
|
|
54
54
|
getAllPatientsUtil,
|
|
55
|
-
} from
|
|
55
|
+
} from "./utils/profile.utils";
|
|
56
56
|
|
|
57
57
|
import {
|
|
58
58
|
updatePatientLocationUtil,
|
|
59
59
|
createLocationInfoUtil,
|
|
60
60
|
getLocationInfoUtil,
|
|
61
61
|
updateLocationInfoUtil,
|
|
62
|
-
} from
|
|
62
|
+
} from "./utils/location.utils";
|
|
63
63
|
|
|
64
64
|
import {
|
|
65
65
|
createSensitiveInfoUtil,
|
|
66
66
|
getSensitiveInfoUtil,
|
|
67
67
|
updateSensitiveInfoUtil,
|
|
68
|
-
} from
|
|
68
|
+
} from "./utils/sensitive.utils";
|
|
69
69
|
|
|
70
70
|
import {
|
|
71
71
|
createMedicalInfoUtil,
|
|
@@ -83,21 +83,24 @@ import {
|
|
|
83
83
|
addMedicationUtil,
|
|
84
84
|
updateMedicationUtil,
|
|
85
85
|
removeMedicationUtil,
|
|
86
|
-
} from
|
|
86
|
+
} from "./utils/medical.utils";
|
|
87
87
|
|
|
88
88
|
import {
|
|
89
89
|
getPatientDocRef,
|
|
90
90
|
getSensitiveInfoDocRef,
|
|
91
91
|
getLocationInfoDocRef,
|
|
92
92
|
getMedicalInfoDocRef,
|
|
93
|
-
} from
|
|
93
|
+
} from "./utils/docs.utils";
|
|
94
94
|
|
|
95
95
|
import {
|
|
96
96
|
addDoctorUtil,
|
|
97
97
|
removeDoctorUtil,
|
|
98
98
|
addClinicUtil,
|
|
99
99
|
removeClinicUtil,
|
|
100
|
-
} from
|
|
100
|
+
} from "./utils/medical-stuff.utils";
|
|
101
|
+
|
|
102
|
+
import { getPatientsByPractitionerUtil } from "./utils/practitioner.utils";
|
|
103
|
+
import { getPatientsByClinicUtil } from "./utils/clinic.utils";
|
|
101
104
|
|
|
102
105
|
export class PatientService extends BaseService {
|
|
103
106
|
constructor(db: Firestore, auth: Auth, app: FirebaseApp) {
|
|
@@ -105,7 +108,9 @@ export class PatientService extends BaseService {
|
|
|
105
108
|
}
|
|
106
109
|
|
|
107
110
|
// Metode za rad sa profilom pacijenta
|
|
108
|
-
async createPatientProfile(
|
|
111
|
+
async createPatientProfile(
|
|
112
|
+
data: CreatePatientProfileData
|
|
113
|
+
): Promise<PatientProfile> {
|
|
109
114
|
return createPatientProfileUtil(this.db, data, () => this.generateId());
|
|
110
115
|
}
|
|
111
116
|
|
|
@@ -113,7 +118,9 @@ export class PatientService extends BaseService {
|
|
|
113
118
|
return getPatientProfileUtil(this.db, patientId);
|
|
114
119
|
}
|
|
115
120
|
|
|
116
|
-
async getPatientProfileByUserRef(
|
|
121
|
+
async getPatientProfileByUserRef(
|
|
122
|
+
userRef: string
|
|
123
|
+
): Promise<PatientProfile | null> {
|
|
117
124
|
return getPatientProfileByUserRefUtil(this.db, userRef);
|
|
118
125
|
}
|
|
119
126
|
|
|
@@ -121,7 +128,7 @@ export class PatientService extends BaseService {
|
|
|
121
128
|
async updatePatientLocation(
|
|
122
129
|
patientId: string,
|
|
123
130
|
latitude: number,
|
|
124
|
-
longitude: number
|
|
131
|
+
longitude: number
|
|
125
132
|
): Promise<void> {
|
|
126
133
|
await updatePatientLocationUtil(this.db, patientId, latitude, longitude);
|
|
127
134
|
}
|
|
@@ -129,30 +136,30 @@ export class PatientService extends BaseService {
|
|
|
129
136
|
async updatePatientLocationByUserRef(
|
|
130
137
|
userRef: string,
|
|
131
138
|
latitude: number,
|
|
132
|
-
longitude: number
|
|
139
|
+
longitude: number
|
|
133
140
|
): Promise<void> {
|
|
134
141
|
const profile = await this.getPatientProfileByUserRef(userRef);
|
|
135
|
-
if (!profile) throw new Error(
|
|
142
|
+
if (!profile) throw new Error("Patient profile not found");
|
|
136
143
|
await this.updatePatientLocation(profile.id, latitude, longitude);
|
|
137
144
|
}
|
|
138
145
|
|
|
139
146
|
async createLocationInfo(
|
|
140
147
|
data: CreatePatientLocationInfoData,
|
|
141
|
-
requesterId: string
|
|
148
|
+
requesterId: string
|
|
142
149
|
): Promise<PatientLocationInfo> {
|
|
143
150
|
return createLocationInfoUtil(this.db, data, requesterId);
|
|
144
151
|
}
|
|
145
152
|
|
|
146
153
|
async getLocationInfo(
|
|
147
154
|
patientId: string,
|
|
148
|
-
requesterId: string
|
|
155
|
+
requesterId: string
|
|
149
156
|
): Promise<PatientLocationInfo | null> {
|
|
150
157
|
return getLocationInfoUtil(this.db, patientId, requesterId);
|
|
151
158
|
}
|
|
152
159
|
|
|
153
160
|
async getLocationInfoByUserRef(
|
|
154
161
|
userRef: string,
|
|
155
|
-
requesterId: string
|
|
162
|
+
requesterId: string
|
|
156
163
|
): Promise<PatientLocationInfo | null> {
|
|
157
164
|
const profile = await this.getPatientProfileByUserRef(userRef);
|
|
158
165
|
if (!profile) return null;
|
|
@@ -162,7 +169,7 @@ export class PatientService extends BaseService {
|
|
|
162
169
|
async updateLocationInfo(
|
|
163
170
|
patientId: string,
|
|
164
171
|
data: UpdatePatientLocationInfoData,
|
|
165
|
-
requesterId: string
|
|
172
|
+
requesterId: string
|
|
166
173
|
): Promise<PatientLocationInfo> {
|
|
167
174
|
return updateLocationInfoUtil(this.db, patientId, data, requesterId);
|
|
168
175
|
}
|
|
@@ -170,21 +177,21 @@ export class PatientService extends BaseService {
|
|
|
170
177
|
// Metode za rad sa osetljivim informacijama
|
|
171
178
|
async createSensitiveInfo(
|
|
172
179
|
data: CreatePatientSensitiveInfoData,
|
|
173
|
-
requesterUserId: string
|
|
180
|
+
requesterUserId: string
|
|
174
181
|
): Promise<PatientSensitiveInfo> {
|
|
175
182
|
return createSensitiveInfoUtil(this.db, data, requesterUserId);
|
|
176
183
|
}
|
|
177
184
|
|
|
178
185
|
async getSensitiveInfo(
|
|
179
186
|
patientId: string,
|
|
180
|
-
requesterUserId: string
|
|
187
|
+
requesterUserId: string
|
|
181
188
|
): Promise<PatientSensitiveInfo | null> {
|
|
182
189
|
return getSensitiveInfoUtil(this.db, patientId, requesterUserId);
|
|
183
190
|
}
|
|
184
191
|
|
|
185
192
|
async getSensitiveInfoByUserRef(
|
|
186
193
|
userRef: string,
|
|
187
|
-
requesterUserId: string
|
|
194
|
+
requesterUserId: string
|
|
188
195
|
): Promise<PatientSensitiveInfo | null> {
|
|
189
196
|
const profile = await this.getPatientProfileByUserRef(userRef);
|
|
190
197
|
if (!profile) return null;
|
|
@@ -194,30 +201,47 @@ export class PatientService extends BaseService {
|
|
|
194
201
|
async updateSensitiveInfo(
|
|
195
202
|
patientId: string,
|
|
196
203
|
data: UpdatePatientSensitiveInfoData,
|
|
197
|
-
requesterUserId: string
|
|
204
|
+
requesterUserId: string
|
|
198
205
|
): Promise<PatientSensitiveInfo> {
|
|
199
206
|
return updateSensitiveInfoUtil(this.db, patientId, data, requesterUserId);
|
|
200
207
|
}
|
|
201
208
|
|
|
202
209
|
// Metode za rad sa medicinskim informacijama
|
|
203
|
-
async createMedicalInfo(
|
|
210
|
+
async createMedicalInfo(
|
|
211
|
+
patientId: string,
|
|
212
|
+
data: CreatePatientMedicalInfoData
|
|
213
|
+
): Promise<void> {
|
|
204
214
|
const currentUser = await this.getCurrentUser();
|
|
205
|
-
await createMedicalInfoUtil(
|
|
215
|
+
await createMedicalInfoUtil(
|
|
216
|
+
this.db,
|
|
217
|
+
patientId,
|
|
218
|
+
data,
|
|
219
|
+
currentUser.uid,
|
|
220
|
+
currentUser.roles
|
|
221
|
+
);
|
|
206
222
|
}
|
|
207
223
|
|
|
208
224
|
async getMedicalInfo(patientId: string): Promise<PatientMedicalInfo> {
|
|
209
225
|
const currentUser = await this.getCurrentUser();
|
|
210
|
-
return getMedicalInfoUtil(
|
|
226
|
+
return getMedicalInfoUtil(
|
|
227
|
+
this.db,
|
|
228
|
+
patientId,
|
|
229
|
+
currentUser.uid,
|
|
230
|
+
currentUser.roles
|
|
231
|
+
);
|
|
211
232
|
}
|
|
212
233
|
|
|
213
234
|
async getMedicalInfoByUserRef(userRef: string): Promise<PatientMedicalInfo> {
|
|
214
235
|
const profile = await this.getPatientProfileByUserRef(userRef);
|
|
215
|
-
if (!profile) throw new Error(
|
|
236
|
+
if (!profile) throw new Error("Patient profile not found");
|
|
216
237
|
return this.getMedicalInfo(profile.id);
|
|
217
238
|
}
|
|
218
239
|
|
|
219
240
|
// Metode za rad sa vitalnim statistikama
|
|
220
|
-
async updateVitalStats(
|
|
241
|
+
async updateVitalStats(
|
|
242
|
+
patientId: string,
|
|
243
|
+
data: UpdateVitalStatsData
|
|
244
|
+
): Promise<void> {
|
|
221
245
|
const currentUser = await this.getCurrentUser();
|
|
222
246
|
await updateVitalStatsUtil(this.db, patientId, data, currentUser.uid);
|
|
223
247
|
}
|
|
@@ -228,7 +252,10 @@ export class PatientService extends BaseService {
|
|
|
228
252
|
await addAllergyUtil(this.db, patientId, data, currentUser.uid);
|
|
229
253
|
}
|
|
230
254
|
|
|
231
|
-
async updateAllergy(
|
|
255
|
+
async updateAllergy(
|
|
256
|
+
patientId: string,
|
|
257
|
+
data: UpdateAllergyData
|
|
258
|
+
): Promise<void> {
|
|
232
259
|
const currentUser = await this.getCurrentUser();
|
|
233
260
|
await updateAllergyUtil(this.db, patientId, data, currentUser.uid);
|
|
234
261
|
}
|
|
@@ -239,54 +266,98 @@ export class PatientService extends BaseService {
|
|
|
239
266
|
}
|
|
240
267
|
|
|
241
268
|
// Metode za rad sa blocking conditions
|
|
242
|
-
async addBlockingCondition(
|
|
269
|
+
async addBlockingCondition(
|
|
270
|
+
patientId: string,
|
|
271
|
+
data: AddBlockingConditionData
|
|
272
|
+
): Promise<void> {
|
|
243
273
|
const currentUser = await this.getCurrentUser();
|
|
244
274
|
await addBlockingConditionUtil(this.db, patientId, data, currentUser.uid);
|
|
245
275
|
}
|
|
246
276
|
|
|
247
277
|
async updateBlockingCondition(
|
|
248
278
|
patientId: string,
|
|
249
|
-
data: UpdateBlockingConditionData
|
|
279
|
+
data: UpdateBlockingConditionData
|
|
250
280
|
): Promise<void> {
|
|
251
281
|
const currentUser = await this.getCurrentUser();
|
|
252
|
-
await updateBlockingConditionUtil(
|
|
282
|
+
await updateBlockingConditionUtil(
|
|
283
|
+
this.db,
|
|
284
|
+
patientId,
|
|
285
|
+
data,
|
|
286
|
+
currentUser.uid
|
|
287
|
+
);
|
|
253
288
|
}
|
|
254
289
|
|
|
255
|
-
async removeBlockingCondition(
|
|
290
|
+
async removeBlockingCondition(
|
|
291
|
+
patientId: string,
|
|
292
|
+
conditionIndex: number
|
|
293
|
+
): Promise<void> {
|
|
256
294
|
const currentUser = await this.getCurrentUser();
|
|
257
|
-
await removeBlockingConditionUtil(
|
|
295
|
+
await removeBlockingConditionUtil(
|
|
296
|
+
this.db,
|
|
297
|
+
patientId,
|
|
298
|
+
conditionIndex,
|
|
299
|
+
currentUser.uid
|
|
300
|
+
);
|
|
258
301
|
}
|
|
259
302
|
|
|
260
303
|
// Metode za rad sa kontraindikacijama
|
|
261
|
-
async addContraindication(
|
|
304
|
+
async addContraindication(
|
|
305
|
+
patientId: string,
|
|
306
|
+
data: AddContraindicationData
|
|
307
|
+
): Promise<void> {
|
|
262
308
|
const currentUser = await this.getCurrentUser();
|
|
263
309
|
await addContraindicationUtil(this.db, patientId, data, currentUser.uid);
|
|
264
310
|
}
|
|
265
311
|
|
|
266
|
-
async updateContraindication(
|
|
312
|
+
async updateContraindication(
|
|
313
|
+
patientId: string,
|
|
314
|
+
data: UpdateContraindicationData
|
|
315
|
+
): Promise<void> {
|
|
267
316
|
const currentUser = await this.getCurrentUser();
|
|
268
317
|
await updateContraindicationUtil(this.db, patientId, data, currentUser.uid);
|
|
269
318
|
}
|
|
270
319
|
|
|
271
|
-
async removeContraindication(
|
|
320
|
+
async removeContraindication(
|
|
321
|
+
patientId: string,
|
|
322
|
+
contraindicationIndex: number
|
|
323
|
+
): Promise<void> {
|
|
272
324
|
const currentUser = await this.getCurrentUser();
|
|
273
|
-
await removeContraindicationUtil(
|
|
325
|
+
await removeContraindicationUtil(
|
|
326
|
+
this.db,
|
|
327
|
+
patientId,
|
|
328
|
+
contraindicationIndex,
|
|
329
|
+
currentUser.uid
|
|
330
|
+
);
|
|
274
331
|
}
|
|
275
332
|
|
|
276
333
|
// Metode za rad sa medikacijama
|
|
277
|
-
async addMedication(
|
|
334
|
+
async addMedication(
|
|
335
|
+
patientId: string,
|
|
336
|
+
data: AddMedicationData
|
|
337
|
+
): Promise<void> {
|
|
278
338
|
const currentUser = await this.getCurrentUser();
|
|
279
339
|
await addMedicationUtil(this.db, patientId, data, currentUser.uid);
|
|
280
340
|
}
|
|
281
341
|
|
|
282
|
-
async updateMedication(
|
|
342
|
+
async updateMedication(
|
|
343
|
+
patientId: string,
|
|
344
|
+
data: UpdateMedicationData
|
|
345
|
+
): Promise<void> {
|
|
283
346
|
const currentUser = await this.getCurrentUser();
|
|
284
347
|
await updateMedicationUtil(this.db, patientId, data, currentUser.uid);
|
|
285
348
|
}
|
|
286
349
|
|
|
287
|
-
async removeMedication(
|
|
350
|
+
async removeMedication(
|
|
351
|
+
patientId: string,
|
|
352
|
+
medicationIndex: number
|
|
353
|
+
): Promise<void> {
|
|
288
354
|
const currentUser = await this.getCurrentUser();
|
|
289
|
-
await removeMedicationUtil(
|
|
355
|
+
await removeMedicationUtil(
|
|
356
|
+
this.db,
|
|
357
|
+
patientId,
|
|
358
|
+
medicationIndex,
|
|
359
|
+
currentUser.uid
|
|
360
|
+
);
|
|
290
361
|
}
|
|
291
362
|
|
|
292
363
|
// Pomoćne metode
|
|
@@ -296,7 +367,7 @@ export class PatientService extends BaseService {
|
|
|
296
367
|
|
|
297
368
|
async addExpoTokenByUserRef(userRef: string, token: string): Promise<void> {
|
|
298
369
|
const profile = await this.getPatientProfileByUserRef(userRef);
|
|
299
|
-
if (!profile) throw new Error(
|
|
370
|
+
if (!profile) throw new Error("Patient profile not found");
|
|
300
371
|
await this.addExpoToken(profile.id, token);
|
|
301
372
|
}
|
|
302
373
|
|
|
@@ -304,9 +375,12 @@ export class PatientService extends BaseService {
|
|
|
304
375
|
await removeExpoTokenUtil(this.db, patientId, token);
|
|
305
376
|
}
|
|
306
377
|
|
|
307
|
-
async removeExpoTokenByUserRef(
|
|
378
|
+
async removeExpoTokenByUserRef(
|
|
379
|
+
userRef: string,
|
|
380
|
+
token: string
|
|
381
|
+
): Promise<void> {
|
|
308
382
|
const profile = await this.getPatientProfileByUserRef(userRef);
|
|
309
|
-
if (!profile) throw new Error(
|
|
383
|
+
if (!profile) throw new Error("Patient profile not found");
|
|
310
384
|
await this.removeExpoToken(profile.id, token);
|
|
311
385
|
}
|
|
312
386
|
|
|
@@ -316,17 +390,19 @@ export class PatientService extends BaseService {
|
|
|
316
390
|
|
|
317
391
|
async addPointsByUserRef(userRef: string, points: number): Promise<void> {
|
|
318
392
|
const profile = await this.getPatientProfileByUserRef(userRef);
|
|
319
|
-
if (!profile) throw new Error(
|
|
393
|
+
if (!profile) throw new Error("Patient profile not found");
|
|
320
394
|
await this.addPoints(profile.id, points);
|
|
321
395
|
}
|
|
322
396
|
|
|
323
397
|
private async getCurrentUser(): Promise<any> {
|
|
324
398
|
if (!this.auth.currentUser) {
|
|
325
|
-
throw new Error(
|
|
399
|
+
throw new Error("No authenticated user");
|
|
326
400
|
}
|
|
327
|
-
const userDoc = await getDoc(
|
|
401
|
+
const userDoc = await getDoc(
|
|
402
|
+
doc(this.db, "users", this.auth.currentUser.uid)
|
|
403
|
+
);
|
|
328
404
|
if (!userDoc.exists()) {
|
|
329
|
-
throw new Error(
|
|
405
|
+
throw new Error("User not found");
|
|
330
406
|
}
|
|
331
407
|
return userDoc.data();
|
|
332
408
|
}
|
|
@@ -388,14 +464,14 @@ export class PatientService extends BaseService {
|
|
|
388
464
|
// Metode za ažuriranje profila
|
|
389
465
|
async updatePatientProfile(
|
|
390
466
|
patientId: string,
|
|
391
|
-
data: Partial<Omit<PatientProfile,
|
|
467
|
+
data: Partial<Omit<PatientProfile, "id" | "createdAt" | "updatedAt">>
|
|
392
468
|
): Promise<PatientProfile> {
|
|
393
469
|
return updatePatientProfileUtil(this.db, patientId, data);
|
|
394
470
|
}
|
|
395
471
|
|
|
396
472
|
async updatePatientProfileByUserRef(
|
|
397
473
|
userRef: string,
|
|
398
|
-
data: Partial<Omit<PatientProfile,
|
|
474
|
+
data: Partial<Omit<PatientProfile, "id" | "createdAt" | "updatedAt">>
|
|
399
475
|
): Promise<PatientProfile> {
|
|
400
476
|
return updatePatientProfileByUserRefUtil(this.db, userRef, data);
|
|
401
477
|
}
|
|
@@ -410,7 +486,7 @@ export class PatientService extends BaseService {
|
|
|
410
486
|
*/
|
|
411
487
|
async searchPatients(
|
|
412
488
|
params: SearchPatientsParams,
|
|
413
|
-
requester: RequesterInfo
|
|
489
|
+
requester: RequesterInfo
|
|
414
490
|
): Promise<PatientProfile[]> {
|
|
415
491
|
// We can potentially add more service-level logic here in the future,
|
|
416
492
|
// like fetching additional data or enriching the results.
|
|
@@ -419,7 +495,7 @@ export class PatientService extends BaseService {
|
|
|
419
495
|
`[PatientService.searchPatients] Initiating search with params:`,
|
|
420
496
|
params,
|
|
421
497
|
`by requester:`,
|
|
422
|
-
requester
|
|
498
|
+
requester
|
|
423
499
|
);
|
|
424
500
|
|
|
425
501
|
// The utility function already handles validation and security checks.
|
|
@@ -438,7 +514,54 @@ export class PatientService extends BaseService {
|
|
|
438
514
|
limit?: number;
|
|
439
515
|
startAfter?: string;
|
|
440
516
|
}): Promise<PatientProfile[]> {
|
|
441
|
-
console.log(
|
|
517
|
+
console.log(
|
|
518
|
+
`[PatientService.getAllPatients] Fetching patients with options:`,
|
|
519
|
+
options
|
|
520
|
+
);
|
|
442
521
|
return getAllPatientsUtil(this.db, options);
|
|
443
522
|
}
|
|
523
|
+
|
|
524
|
+
/**
|
|
525
|
+
* Gets all patients associated with a specific practitioner.
|
|
526
|
+
*
|
|
527
|
+
* @param {string} practitionerId - ID of the practitioner whose patients to retrieve
|
|
528
|
+
* @param {Object} options - Optional parameters for pagination
|
|
529
|
+
* @param {number} options.limit - Maximum number of profiles to return
|
|
530
|
+
* @param {string} options.startAfter - The ID of the document to start after (for pagination)
|
|
531
|
+
* @returns {Promise<PatientProfile[]>} A promise resolving to an array of patient profiles
|
|
532
|
+
*/
|
|
533
|
+
async getPatientsByPractitioner(
|
|
534
|
+
practitionerId: string,
|
|
535
|
+
options?: {
|
|
536
|
+
limit?: number;
|
|
537
|
+
startAfter?: string;
|
|
538
|
+
}
|
|
539
|
+
): Promise<PatientProfile[]> {
|
|
540
|
+
console.log(
|
|
541
|
+
`[PatientService.getPatientsByPractitioner] Fetching patients for practitioner: ${practitionerId}`
|
|
542
|
+
);
|
|
543
|
+
return getPatientsByPractitionerUtil(this.db, practitionerId, options);
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
/**
|
|
547
|
+
* Gets all patients associated with a specific clinic.
|
|
548
|
+
*
|
|
549
|
+
* @param {string} clinicId - ID of the clinic whose patients to retrieve
|
|
550
|
+
* @param {Object} options - Optional parameters for pagination
|
|
551
|
+
* @param {number} options.limit - Maximum number of profiles to return
|
|
552
|
+
* @param {string} options.startAfter - The ID of the document to start after (for pagination)
|
|
553
|
+
* @returns {Promise<PatientProfile[]>} A promise resolving to an array of patient profiles
|
|
554
|
+
*/
|
|
555
|
+
async getPatientsByClinic(
|
|
556
|
+
clinicId: string,
|
|
557
|
+
options?: {
|
|
558
|
+
limit?: number;
|
|
559
|
+
startAfter?: string;
|
|
560
|
+
}
|
|
561
|
+
): Promise<PatientProfile[]> {
|
|
562
|
+
console.log(
|
|
563
|
+
`[PatientService.getPatientsByClinic] Fetching patients for clinic: ${clinicId}`
|
|
564
|
+
);
|
|
565
|
+
return getPatientsByClinicUtil(this.db, clinicId, options);
|
|
566
|
+
}
|
|
444
567
|
}
|
|
@@ -0,0 +1,80 @@
|
|
|
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 { PatientProfile, PATIENTS_COLLECTION } from "../../../types/patient";
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Retrieves all patients associated with a specific clinic with pagination support.
|
|
17
|
+
*
|
|
18
|
+
* @param {Firestore} db - Firestore instance
|
|
19
|
+
* @param {string} clinicId - ID of the clinic whose patients to retrieve
|
|
20
|
+
* @param {Object} options - Optional parameters for pagination
|
|
21
|
+
* @param {number} options.limit - Maximum number of profiles to return
|
|
22
|
+
* @param {string} options.startAfter - The ID of the document to start after (for pagination)
|
|
23
|
+
* @returns {Promise<PatientProfile[]>} A promise resolving to an array of patient profiles
|
|
24
|
+
*/
|
|
25
|
+
export const getPatientsByClinicUtil = async (
|
|
26
|
+
db: Firestore,
|
|
27
|
+
clinicId: string,
|
|
28
|
+
options?: { limit?: number; startAfter?: string }
|
|
29
|
+
): Promise<PatientProfile[]> => {
|
|
30
|
+
try {
|
|
31
|
+
console.log(
|
|
32
|
+
`[getPatientsByClinicUtil] Fetching patients for clinic ID: ${clinicId} with options:`,
|
|
33
|
+
options
|
|
34
|
+
);
|
|
35
|
+
|
|
36
|
+
const patientsCollection = collection(db, PATIENTS_COLLECTION);
|
|
37
|
+
const constraints: QueryConstraint[] = [
|
|
38
|
+
where("clinicIds", "array-contains", clinicId),
|
|
39
|
+
];
|
|
40
|
+
|
|
41
|
+
let q = query(patientsCollection, ...constraints);
|
|
42
|
+
|
|
43
|
+
// Apply pagination if needed
|
|
44
|
+
if (options?.limit) {
|
|
45
|
+
q = query(q, limit(options.limit));
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// If startAfter is provided, get that document and use it for pagination
|
|
49
|
+
if (options?.startAfter) {
|
|
50
|
+
const startAfterDoc = await getDoc(
|
|
51
|
+
doc(db, PATIENTS_COLLECTION, options.startAfter)
|
|
52
|
+
);
|
|
53
|
+
if (startAfterDoc.exists()) {
|
|
54
|
+
q = query(q, startAfter(startAfterDoc));
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const patientsSnapshot = await getDocs(q);
|
|
59
|
+
|
|
60
|
+
const patients: PatientProfile[] = [];
|
|
61
|
+
patientsSnapshot.forEach((doc) => {
|
|
62
|
+
patients.push(doc.data() as PatientProfile);
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
console.log(
|
|
66
|
+
`[getPatientsByClinicUtil] Found ${patients.length} patients for clinic ID: ${clinicId}`
|
|
67
|
+
);
|
|
68
|
+
return patients;
|
|
69
|
+
} catch (error) {
|
|
70
|
+
console.error(
|
|
71
|
+
`[getPatientsByClinicUtil] Error fetching patients for clinic:`,
|
|
72
|
+
error
|
|
73
|
+
);
|
|
74
|
+
throw new Error(
|
|
75
|
+
`Failed to retrieve patients for clinic: ${
|
|
76
|
+
error instanceof Error ? error.message : String(error)
|
|
77
|
+
}`
|
|
78
|
+
);
|
|
79
|
+
}
|
|
80
|
+
};
|
|
@@ -0,0 +1,80 @@
|
|
|
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 { PatientProfile, PATIENTS_COLLECTION } from "../../../types/patient";
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Retrieves all patients associated with a specific practitioner with pagination support.
|
|
17
|
+
*
|
|
18
|
+
* @param {Firestore} db - Firestore instance
|
|
19
|
+
* @param {string} practitionerId - ID of the practitioner whose patients to retrieve
|
|
20
|
+
* @param {Object} options - Optional parameters for pagination
|
|
21
|
+
* @param {number} options.limit - Maximum number of profiles to return
|
|
22
|
+
* @param {string} options.startAfter - The ID of the document to start after (for pagination)
|
|
23
|
+
* @returns {Promise<PatientProfile[]>} A promise resolving to an array of patient profiles
|
|
24
|
+
*/
|
|
25
|
+
export const getPatientsByPractitionerUtil = async (
|
|
26
|
+
db: Firestore,
|
|
27
|
+
practitionerId: string,
|
|
28
|
+
options?: { limit?: number; startAfter?: string }
|
|
29
|
+
): Promise<PatientProfile[]> => {
|
|
30
|
+
try {
|
|
31
|
+
console.log(
|
|
32
|
+
`[getPatientsByPractitionerUtil] Fetching patients for practitioner ID: ${practitionerId} with options:`,
|
|
33
|
+
options
|
|
34
|
+
);
|
|
35
|
+
|
|
36
|
+
const patientsCollection = collection(db, PATIENTS_COLLECTION);
|
|
37
|
+
const constraints: QueryConstraint[] = [
|
|
38
|
+
where("doctorIds", "array-contains", practitionerId),
|
|
39
|
+
];
|
|
40
|
+
|
|
41
|
+
let q = query(patientsCollection, ...constraints);
|
|
42
|
+
|
|
43
|
+
// Apply pagination if needed
|
|
44
|
+
if (options?.limit) {
|
|
45
|
+
q = query(q, limit(options.limit));
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// If startAfter is provided, get that document and use it for pagination
|
|
49
|
+
if (options?.startAfter) {
|
|
50
|
+
const startAfterDoc = await getDoc(
|
|
51
|
+
doc(db, PATIENTS_COLLECTION, options.startAfter)
|
|
52
|
+
);
|
|
53
|
+
if (startAfterDoc.exists()) {
|
|
54
|
+
q = query(q, startAfter(startAfterDoc));
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const patientsSnapshot = await getDocs(q);
|
|
59
|
+
|
|
60
|
+
const patients: PatientProfile[] = [];
|
|
61
|
+
patientsSnapshot.forEach((doc) => {
|
|
62
|
+
patients.push(doc.data() as PatientProfile);
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
console.log(
|
|
66
|
+
`[getPatientsByPractitionerUtil] Found ${patients.length} patients for practitioner ID: ${practitionerId}`
|
|
67
|
+
);
|
|
68
|
+
return patients;
|
|
69
|
+
} catch (error) {
|
|
70
|
+
console.error(
|
|
71
|
+
`[getPatientsByPractitionerUtil] Error fetching patients for practitioner:`,
|
|
72
|
+
error
|
|
73
|
+
);
|
|
74
|
+
throw new Error(
|
|
75
|
+
`Failed to retrieve patients for practitioner: ${
|
|
76
|
+
error instanceof Error ? error.message : String(error)
|
|
77
|
+
}`
|
|
78
|
+
);
|
|
79
|
+
}
|
|
80
|
+
};
|