@blackcode_sa/metaestetics-api 1.5.16 → 1.5.18
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/backoffice/index.d.mts +2 -2
- package/dist/backoffice/index.d.ts +2 -2
- package/dist/index.d.mts +233 -40
- package/dist/index.d.ts +233 -40
- package/dist/index.js +748 -427
- package/dist/index.mjs +1073 -739
- package/package.json +1 -1
- package/src/index.ts +5 -0
- package/src/services/calendar/calendar-refactored.service.ts +147 -0
- package/src/services/calendar/utils/calendar-event.utils.ts +136 -0
- package/src/services/calendar/utils/index.ts +5 -5
- package/src/services/patient/patient.service.ts +100 -127
- package/src/services/patient/utils/medical-stuff.utils.ts +69 -18
- package/src/services/patient/utils/profile.utils.ts +206 -94
- package/src/types/calendar/index.ts +41 -0
- package/src/types/patient/index.ts +31 -1
- package/src/types/practitioner/index.ts +13 -14
- package/src/validations/patient.schema.ts +43 -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,
|
|
@@ -29,11 +29,13 @@ import {
|
|
|
29
29
|
UpdateMedicationData,
|
|
30
30
|
PatientDoctor,
|
|
31
31
|
PatientClinic,
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
import {
|
|
36
|
-
import {
|
|
32
|
+
SearchPatientsParams,
|
|
33
|
+
RequesterInfo,
|
|
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';
|
|
37
39
|
|
|
38
40
|
// Importujemo utility funkcije
|
|
39
41
|
import {
|
|
@@ -48,20 +50,22 @@ import {
|
|
|
48
50
|
deleteProfilePhotoUtil,
|
|
49
51
|
updatePatientProfileUtil,
|
|
50
52
|
updatePatientProfileByUserRefUtil,
|
|
51
|
-
|
|
53
|
+
searchPatientsUtil,
|
|
54
|
+
getAllPatientsUtil,
|
|
55
|
+
} from './utils/profile.utils';
|
|
52
56
|
|
|
53
57
|
import {
|
|
54
58
|
updatePatientLocationUtil,
|
|
55
59
|
createLocationInfoUtil,
|
|
56
60
|
getLocationInfoUtil,
|
|
57
61
|
updateLocationInfoUtil,
|
|
58
|
-
} from
|
|
62
|
+
} from './utils/location.utils';
|
|
59
63
|
|
|
60
64
|
import {
|
|
61
65
|
createSensitiveInfoUtil,
|
|
62
66
|
getSensitiveInfoUtil,
|
|
63
67
|
updateSensitiveInfoUtil,
|
|
64
|
-
} from
|
|
68
|
+
} from './utils/sensitive.utils';
|
|
65
69
|
|
|
66
70
|
import {
|
|
67
71
|
createMedicalInfoUtil,
|
|
@@ -79,21 +83,21 @@ import {
|
|
|
79
83
|
addMedicationUtil,
|
|
80
84
|
updateMedicationUtil,
|
|
81
85
|
removeMedicationUtil,
|
|
82
|
-
} from
|
|
86
|
+
} from './utils/medical.utils';
|
|
83
87
|
|
|
84
88
|
import {
|
|
85
89
|
getPatientDocRef,
|
|
86
90
|
getSensitiveInfoDocRef,
|
|
87
91
|
getLocationInfoDocRef,
|
|
88
92
|
getMedicalInfoDocRef,
|
|
89
|
-
} from
|
|
93
|
+
} from './utils/docs.utils';
|
|
90
94
|
|
|
91
95
|
import {
|
|
92
96
|
addDoctorUtil,
|
|
93
97
|
removeDoctorUtil,
|
|
94
98
|
addClinicUtil,
|
|
95
99
|
removeClinicUtil,
|
|
96
|
-
} from
|
|
100
|
+
} from './utils/medical-stuff.utils';
|
|
97
101
|
|
|
98
102
|
export class PatientService extends BaseService {
|
|
99
103
|
constructor(db: Firestore, auth: Auth, app: FirebaseApp) {
|
|
@@ -101,9 +105,7 @@ export class PatientService extends BaseService {
|
|
|
101
105
|
}
|
|
102
106
|
|
|
103
107
|
// Metode za rad sa profilom pacijenta
|
|
104
|
-
async createPatientProfile(
|
|
105
|
-
data: CreatePatientProfileData
|
|
106
|
-
): Promise<PatientProfile> {
|
|
108
|
+
async createPatientProfile(data: CreatePatientProfileData): Promise<PatientProfile> {
|
|
107
109
|
return createPatientProfileUtil(this.db, data, () => this.generateId());
|
|
108
110
|
}
|
|
109
111
|
|
|
@@ -111,9 +113,7 @@ export class PatientService extends BaseService {
|
|
|
111
113
|
return getPatientProfileUtil(this.db, patientId);
|
|
112
114
|
}
|
|
113
115
|
|
|
114
|
-
async getPatientProfileByUserRef(
|
|
115
|
-
userRef: string
|
|
116
|
-
): Promise<PatientProfile | null> {
|
|
116
|
+
async getPatientProfileByUserRef(userRef: string): Promise<PatientProfile | null> {
|
|
117
117
|
return getPatientProfileByUserRefUtil(this.db, userRef);
|
|
118
118
|
}
|
|
119
119
|
|
|
@@ -121,7 +121,7 @@ export class PatientService extends BaseService {
|
|
|
121
121
|
async updatePatientLocation(
|
|
122
122
|
patientId: string,
|
|
123
123
|
latitude: number,
|
|
124
|
-
longitude: number
|
|
124
|
+
longitude: number,
|
|
125
125
|
): Promise<void> {
|
|
126
126
|
await updatePatientLocationUtil(this.db, patientId, latitude, longitude);
|
|
127
127
|
}
|
|
@@ -129,30 +129,30 @@ export class PatientService extends BaseService {
|
|
|
129
129
|
async updatePatientLocationByUserRef(
|
|
130
130
|
userRef: string,
|
|
131
131
|
latitude: number,
|
|
132
|
-
longitude: number
|
|
132
|
+
longitude: number,
|
|
133
133
|
): Promise<void> {
|
|
134
134
|
const profile = await this.getPatientProfileByUserRef(userRef);
|
|
135
|
-
if (!profile) throw new Error(
|
|
135
|
+
if (!profile) throw new Error('Patient profile not found');
|
|
136
136
|
await this.updatePatientLocation(profile.id, latitude, longitude);
|
|
137
137
|
}
|
|
138
138
|
|
|
139
139
|
async createLocationInfo(
|
|
140
140
|
data: CreatePatientLocationInfoData,
|
|
141
|
-
requesterId: string
|
|
141
|
+
requesterId: string,
|
|
142
142
|
): Promise<PatientLocationInfo> {
|
|
143
143
|
return createLocationInfoUtil(this.db, data, requesterId);
|
|
144
144
|
}
|
|
145
145
|
|
|
146
146
|
async getLocationInfo(
|
|
147
147
|
patientId: string,
|
|
148
|
-
requesterId: string
|
|
148
|
+
requesterId: string,
|
|
149
149
|
): Promise<PatientLocationInfo | null> {
|
|
150
150
|
return getLocationInfoUtil(this.db, patientId, requesterId);
|
|
151
151
|
}
|
|
152
152
|
|
|
153
153
|
async getLocationInfoByUserRef(
|
|
154
154
|
userRef: string,
|
|
155
|
-
requesterId: string
|
|
155
|
+
requesterId: string,
|
|
156
156
|
): Promise<PatientLocationInfo | null> {
|
|
157
157
|
const profile = await this.getPatientProfileByUserRef(userRef);
|
|
158
158
|
if (!profile) return null;
|
|
@@ -162,7 +162,7 @@ export class PatientService extends BaseService {
|
|
|
162
162
|
async updateLocationInfo(
|
|
163
163
|
patientId: string,
|
|
164
164
|
data: UpdatePatientLocationInfoData,
|
|
165
|
-
requesterId: string
|
|
165
|
+
requesterId: string,
|
|
166
166
|
): Promise<PatientLocationInfo> {
|
|
167
167
|
return updateLocationInfoUtil(this.db, patientId, data, requesterId);
|
|
168
168
|
}
|
|
@@ -170,21 +170,21 @@ export class PatientService extends BaseService {
|
|
|
170
170
|
// Metode za rad sa osetljivim informacijama
|
|
171
171
|
async createSensitiveInfo(
|
|
172
172
|
data: CreatePatientSensitiveInfoData,
|
|
173
|
-
requesterUserId: string
|
|
173
|
+
requesterUserId: string,
|
|
174
174
|
): Promise<PatientSensitiveInfo> {
|
|
175
175
|
return createSensitiveInfoUtil(this.db, data, requesterUserId);
|
|
176
176
|
}
|
|
177
177
|
|
|
178
178
|
async getSensitiveInfo(
|
|
179
179
|
patientId: string,
|
|
180
|
-
requesterUserId: string
|
|
180
|
+
requesterUserId: string,
|
|
181
181
|
): Promise<PatientSensitiveInfo | null> {
|
|
182
182
|
return getSensitiveInfoUtil(this.db, patientId, requesterUserId);
|
|
183
183
|
}
|
|
184
184
|
|
|
185
185
|
async getSensitiveInfoByUserRef(
|
|
186
186
|
userRef: string,
|
|
187
|
-
requesterUserId: string
|
|
187
|
+
requesterUserId: string,
|
|
188
188
|
): Promise<PatientSensitiveInfo | null> {
|
|
189
189
|
const profile = await this.getPatientProfileByUserRef(userRef);
|
|
190
190
|
if (!profile) return null;
|
|
@@ -194,47 +194,30 @@ export class PatientService extends BaseService {
|
|
|
194
194
|
async updateSensitiveInfo(
|
|
195
195
|
patientId: string,
|
|
196
196
|
data: UpdatePatientSensitiveInfoData,
|
|
197
|
-
requesterUserId: string
|
|
197
|
+
requesterUserId: string,
|
|
198
198
|
): Promise<PatientSensitiveInfo> {
|
|
199
199
|
return updateSensitiveInfoUtil(this.db, patientId, data, requesterUserId);
|
|
200
200
|
}
|
|
201
201
|
|
|
202
202
|
// Metode za rad sa medicinskim informacijama
|
|
203
|
-
async createMedicalInfo(
|
|
204
|
-
patientId: string,
|
|
205
|
-
data: CreatePatientMedicalInfoData
|
|
206
|
-
): Promise<void> {
|
|
203
|
+
async createMedicalInfo(patientId: string, data: CreatePatientMedicalInfoData): Promise<void> {
|
|
207
204
|
const currentUser = await this.getCurrentUser();
|
|
208
|
-
await createMedicalInfoUtil(
|
|
209
|
-
this.db,
|
|
210
|
-
patientId,
|
|
211
|
-
data,
|
|
212
|
-
currentUser.uid,
|
|
213
|
-
currentUser.roles
|
|
214
|
-
);
|
|
205
|
+
await createMedicalInfoUtil(this.db, patientId, data, currentUser.uid, currentUser.roles);
|
|
215
206
|
}
|
|
216
207
|
|
|
217
208
|
async getMedicalInfo(patientId: string): Promise<PatientMedicalInfo> {
|
|
218
209
|
const currentUser = await this.getCurrentUser();
|
|
219
|
-
return getMedicalInfoUtil(
|
|
220
|
-
this.db,
|
|
221
|
-
patientId,
|
|
222
|
-
currentUser.uid,
|
|
223
|
-
currentUser.roles
|
|
224
|
-
);
|
|
210
|
+
return getMedicalInfoUtil(this.db, patientId, currentUser.uid, currentUser.roles);
|
|
225
211
|
}
|
|
226
212
|
|
|
227
213
|
async getMedicalInfoByUserRef(userRef: string): Promise<PatientMedicalInfo> {
|
|
228
214
|
const profile = await this.getPatientProfileByUserRef(userRef);
|
|
229
|
-
if (!profile) throw new Error(
|
|
215
|
+
if (!profile) throw new Error('Patient profile not found');
|
|
230
216
|
return this.getMedicalInfo(profile.id);
|
|
231
217
|
}
|
|
232
218
|
|
|
233
219
|
// Metode za rad sa vitalnim statistikama
|
|
234
|
-
async updateVitalStats(
|
|
235
|
-
patientId: string,
|
|
236
|
-
data: UpdateVitalStatsData
|
|
237
|
-
): Promise<void> {
|
|
220
|
+
async updateVitalStats(patientId: string, data: UpdateVitalStatsData): Promise<void> {
|
|
238
221
|
const currentUser = await this.getCurrentUser();
|
|
239
222
|
await updateVitalStatsUtil(this.db, patientId, data, currentUser.uid);
|
|
240
223
|
}
|
|
@@ -245,10 +228,7 @@ export class PatientService extends BaseService {
|
|
|
245
228
|
await addAllergyUtil(this.db, patientId, data, currentUser.uid);
|
|
246
229
|
}
|
|
247
230
|
|
|
248
|
-
async updateAllergy(
|
|
249
|
-
patientId: string,
|
|
250
|
-
data: UpdateAllergyData
|
|
251
|
-
): Promise<void> {
|
|
231
|
+
async updateAllergy(patientId: string, data: UpdateAllergyData): Promise<void> {
|
|
252
232
|
const currentUser = await this.getCurrentUser();
|
|
253
233
|
await updateAllergyUtil(this.db, patientId, data, currentUser.uid);
|
|
254
234
|
}
|
|
@@ -259,98 +239,54 @@ export class PatientService extends BaseService {
|
|
|
259
239
|
}
|
|
260
240
|
|
|
261
241
|
// Metode za rad sa blocking conditions
|
|
262
|
-
async addBlockingCondition(
|
|
263
|
-
patientId: string,
|
|
264
|
-
data: AddBlockingConditionData
|
|
265
|
-
): Promise<void> {
|
|
242
|
+
async addBlockingCondition(patientId: string, data: AddBlockingConditionData): Promise<void> {
|
|
266
243
|
const currentUser = await this.getCurrentUser();
|
|
267
244
|
await addBlockingConditionUtil(this.db, patientId, data, currentUser.uid);
|
|
268
245
|
}
|
|
269
246
|
|
|
270
247
|
async updateBlockingCondition(
|
|
271
248
|
patientId: string,
|
|
272
|
-
data: UpdateBlockingConditionData
|
|
249
|
+
data: UpdateBlockingConditionData,
|
|
273
250
|
): Promise<void> {
|
|
274
251
|
const currentUser = await this.getCurrentUser();
|
|
275
|
-
await updateBlockingConditionUtil(
|
|
276
|
-
this.db,
|
|
277
|
-
patientId,
|
|
278
|
-
data,
|
|
279
|
-
currentUser.uid
|
|
280
|
-
);
|
|
252
|
+
await updateBlockingConditionUtil(this.db, patientId, data, currentUser.uid);
|
|
281
253
|
}
|
|
282
254
|
|
|
283
|
-
async removeBlockingCondition(
|
|
284
|
-
patientId: string,
|
|
285
|
-
conditionIndex: number
|
|
286
|
-
): Promise<void> {
|
|
255
|
+
async removeBlockingCondition(patientId: string, conditionIndex: number): Promise<void> {
|
|
287
256
|
const currentUser = await this.getCurrentUser();
|
|
288
|
-
await removeBlockingConditionUtil(
|
|
289
|
-
this.db,
|
|
290
|
-
patientId,
|
|
291
|
-
conditionIndex,
|
|
292
|
-
currentUser.uid
|
|
293
|
-
);
|
|
257
|
+
await removeBlockingConditionUtil(this.db, patientId, conditionIndex, currentUser.uid);
|
|
294
258
|
}
|
|
295
259
|
|
|
296
260
|
// Metode za rad sa kontraindikacijama
|
|
297
|
-
async addContraindication(
|
|
298
|
-
patientId: string,
|
|
299
|
-
data: AddContraindicationData
|
|
300
|
-
): Promise<void> {
|
|
261
|
+
async addContraindication(patientId: string, data: AddContraindicationData): Promise<void> {
|
|
301
262
|
const currentUser = await this.getCurrentUser();
|
|
302
263
|
await addContraindicationUtil(this.db, patientId, data, currentUser.uid);
|
|
303
264
|
}
|
|
304
265
|
|
|
305
|
-
async updateContraindication(
|
|
306
|
-
patientId: string,
|
|
307
|
-
data: UpdateContraindicationData
|
|
308
|
-
): Promise<void> {
|
|
266
|
+
async updateContraindication(patientId: string, data: UpdateContraindicationData): Promise<void> {
|
|
309
267
|
const currentUser = await this.getCurrentUser();
|
|
310
268
|
await updateContraindicationUtil(this.db, patientId, data, currentUser.uid);
|
|
311
269
|
}
|
|
312
270
|
|
|
313
|
-
async removeContraindication(
|
|
314
|
-
patientId: string,
|
|
315
|
-
contraindicationIndex: number
|
|
316
|
-
): Promise<void> {
|
|
271
|
+
async removeContraindication(patientId: string, contraindicationIndex: number): Promise<void> {
|
|
317
272
|
const currentUser = await this.getCurrentUser();
|
|
318
|
-
await removeContraindicationUtil(
|
|
319
|
-
this.db,
|
|
320
|
-
patientId,
|
|
321
|
-
contraindicationIndex,
|
|
322
|
-
currentUser.uid
|
|
323
|
-
);
|
|
273
|
+
await removeContraindicationUtil(this.db, patientId, contraindicationIndex, currentUser.uid);
|
|
324
274
|
}
|
|
325
275
|
|
|
326
276
|
// Metode za rad sa medikacijama
|
|
327
|
-
async addMedication(
|
|
328
|
-
patientId: string,
|
|
329
|
-
data: AddMedicationData
|
|
330
|
-
): Promise<void> {
|
|
277
|
+
async addMedication(patientId: string, data: AddMedicationData): Promise<void> {
|
|
331
278
|
const currentUser = await this.getCurrentUser();
|
|
332
279
|
await addMedicationUtil(this.db, patientId, data, currentUser.uid);
|
|
333
280
|
}
|
|
334
281
|
|
|
335
|
-
async updateMedication(
|
|
336
|
-
patientId: string,
|
|
337
|
-
data: UpdateMedicationData
|
|
338
|
-
): Promise<void> {
|
|
282
|
+
async updateMedication(patientId: string, data: UpdateMedicationData): Promise<void> {
|
|
339
283
|
const currentUser = await this.getCurrentUser();
|
|
340
284
|
await updateMedicationUtil(this.db, patientId, data, currentUser.uid);
|
|
341
285
|
}
|
|
342
286
|
|
|
343
|
-
async removeMedication(
|
|
344
|
-
patientId: string,
|
|
345
|
-
medicationIndex: number
|
|
346
|
-
): Promise<void> {
|
|
287
|
+
async removeMedication(patientId: string, medicationIndex: number): Promise<void> {
|
|
347
288
|
const currentUser = await this.getCurrentUser();
|
|
348
|
-
await removeMedicationUtil(
|
|
349
|
-
this.db,
|
|
350
|
-
patientId,
|
|
351
|
-
medicationIndex,
|
|
352
|
-
currentUser.uid
|
|
353
|
-
);
|
|
289
|
+
await removeMedicationUtil(this.db, patientId, medicationIndex, currentUser.uid);
|
|
354
290
|
}
|
|
355
291
|
|
|
356
292
|
// Pomoćne metode
|
|
@@ -360,7 +296,7 @@ export class PatientService extends BaseService {
|
|
|
360
296
|
|
|
361
297
|
async addExpoTokenByUserRef(userRef: string, token: string): Promise<void> {
|
|
362
298
|
const profile = await this.getPatientProfileByUserRef(userRef);
|
|
363
|
-
if (!profile) throw new Error(
|
|
299
|
+
if (!profile) throw new Error('Patient profile not found');
|
|
364
300
|
await this.addExpoToken(profile.id, token);
|
|
365
301
|
}
|
|
366
302
|
|
|
@@ -368,12 +304,9 @@ export class PatientService extends BaseService {
|
|
|
368
304
|
await removeExpoTokenUtil(this.db, patientId, token);
|
|
369
305
|
}
|
|
370
306
|
|
|
371
|
-
async removeExpoTokenByUserRef(
|
|
372
|
-
userRef: string,
|
|
373
|
-
token: string
|
|
374
|
-
): Promise<void> {
|
|
307
|
+
async removeExpoTokenByUserRef(userRef: string, token: string): Promise<void> {
|
|
375
308
|
const profile = await this.getPatientProfileByUserRef(userRef);
|
|
376
|
-
if (!profile) throw new Error(
|
|
309
|
+
if (!profile) throw new Error('Patient profile not found');
|
|
377
310
|
await this.removeExpoToken(profile.id, token);
|
|
378
311
|
}
|
|
379
312
|
|
|
@@ -383,19 +316,17 @@ export class PatientService extends BaseService {
|
|
|
383
316
|
|
|
384
317
|
async addPointsByUserRef(userRef: string, points: number): Promise<void> {
|
|
385
318
|
const profile = await this.getPatientProfileByUserRef(userRef);
|
|
386
|
-
if (!profile) throw new Error(
|
|
319
|
+
if (!profile) throw new Error('Patient profile not found');
|
|
387
320
|
await this.addPoints(profile.id, points);
|
|
388
321
|
}
|
|
389
322
|
|
|
390
323
|
private async getCurrentUser(): Promise<any> {
|
|
391
324
|
if (!this.auth.currentUser) {
|
|
392
|
-
throw new Error(
|
|
325
|
+
throw new Error('No authenticated user');
|
|
393
326
|
}
|
|
394
|
-
const userDoc = await getDoc(
|
|
395
|
-
doc(this.db, "users", this.auth.currentUser.uid)
|
|
396
|
-
);
|
|
327
|
+
const userDoc = await getDoc(doc(this.db, 'users', this.auth.currentUser.uid));
|
|
397
328
|
if (!userDoc.exists()) {
|
|
398
|
-
throw new Error(
|
|
329
|
+
throw new Error('User not found');
|
|
399
330
|
}
|
|
400
331
|
return userDoc.data();
|
|
401
332
|
}
|
|
@@ -457,15 +388,57 @@ export class PatientService extends BaseService {
|
|
|
457
388
|
// Metode za ažuriranje profila
|
|
458
389
|
async updatePatientProfile(
|
|
459
390
|
patientId: string,
|
|
460
|
-
data: Partial<Omit<PatientProfile,
|
|
391
|
+
data: Partial<Omit<PatientProfile, 'id' | 'createdAt' | 'updatedAt'>>,
|
|
461
392
|
): Promise<PatientProfile> {
|
|
462
393
|
return updatePatientProfileUtil(this.db, patientId, data);
|
|
463
394
|
}
|
|
464
395
|
|
|
465
396
|
async updatePatientProfileByUserRef(
|
|
466
397
|
userRef: string,
|
|
467
|
-
data: Partial<Omit<PatientProfile,
|
|
398
|
+
data: Partial<Omit<PatientProfile, 'id' | 'createdAt' | 'updatedAt'>>,
|
|
468
399
|
): Promise<PatientProfile> {
|
|
469
400
|
return updatePatientProfileByUserRefUtil(this.db, userRef, data);
|
|
470
401
|
}
|
|
402
|
+
|
|
403
|
+
/**
|
|
404
|
+
* Searches for patient profiles based on clinic/practitioner association.
|
|
405
|
+
* Requires information about the requester for security checks.
|
|
406
|
+
*
|
|
407
|
+
* @param {SearchPatientsParams} params - The search criteria (clinicId, practitionerId).
|
|
408
|
+
* @param {RequesterInfo} requester - Information about the user performing the search (ID, role, associated IDs).
|
|
409
|
+
* @returns {Promise<PatientProfile[]>} A promise resolving to an array of matching patient profiles.
|
|
410
|
+
*/
|
|
411
|
+
async searchPatients(
|
|
412
|
+
params: SearchPatientsParams,
|
|
413
|
+
requester: RequesterInfo,
|
|
414
|
+
): Promise<PatientProfile[]> {
|
|
415
|
+
// We can potentially add more service-level logic here in the future,
|
|
416
|
+
// like fetching additional data or enriching the results.
|
|
417
|
+
// For now, we delegate directly to the utility function.
|
|
418
|
+
console.log(
|
|
419
|
+
`[PatientService.searchPatients] Initiating search with params:`,
|
|
420
|
+
params,
|
|
421
|
+
`by requester:`,
|
|
422
|
+
requester,
|
|
423
|
+
);
|
|
424
|
+
|
|
425
|
+
// The utility function already handles validation and security checks.
|
|
426
|
+
return searchPatientsUtil(this.db, params, requester);
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
/**
|
|
430
|
+
* Gets all patient profiles.
|
|
431
|
+
*
|
|
432
|
+
* @param {Object} options - Optional parameters for pagination
|
|
433
|
+
* @param {number} options.limit - Maximum number of profiles to return
|
|
434
|
+
* @param {string} options.startAfter - The ID of the document to start after (for pagination)
|
|
435
|
+
* @returns {Promise<PatientProfile[]>} A promise resolving to an array of all patient profiles.
|
|
436
|
+
*/
|
|
437
|
+
async getAllPatients(options?: {
|
|
438
|
+
limit?: number;
|
|
439
|
+
startAfter?: string;
|
|
440
|
+
}): Promise<PatientProfile[]> {
|
|
441
|
+
console.log(`[PatientService.getAllPatients] Fetching patients with options:`, options);
|
|
442
|
+
return getAllPatientsUtil(this.db, options);
|
|
443
|
+
}
|
|
471
444
|
}
|
|
@@ -2,6 +2,7 @@ import {
|
|
|
2
2
|
getDoc,
|
|
3
3
|
updateDoc,
|
|
4
4
|
arrayUnion,
|
|
5
|
+
arrayRemove,
|
|
5
6
|
Firestore,
|
|
6
7
|
serverTimestamp,
|
|
7
8
|
Timestamp,
|
|
@@ -27,10 +28,32 @@ export const addDoctorUtil = async (
|
|
|
27
28
|
isActive: true,
|
|
28
29
|
};
|
|
29
30
|
|
|
30
|
-
await
|
|
31
|
-
|
|
31
|
+
const patientDoc = await getDoc(getPatientDocRef(db, patientId));
|
|
32
|
+
if (!patientDoc.exists()) throw new Error("Patient profile not found");
|
|
33
|
+
const patientData = patientDoc.data() as PatientProfile;
|
|
34
|
+
const existingDoctorIndex = patientData.doctors?.findIndex(
|
|
35
|
+
(d) => d.userRef === doctorRef
|
|
36
|
+
);
|
|
37
|
+
|
|
38
|
+
const updates: any = {
|
|
32
39
|
updatedAt: serverTimestamp(),
|
|
33
|
-
|
|
40
|
+
doctorIds: arrayUnion(doctorRef),
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
if (existingDoctorIndex !== undefined && existingDoctorIndex > -1) {
|
|
44
|
+
const updatedDoctors = [...patientData.doctors];
|
|
45
|
+
updatedDoctors[existingDoctorIndex] = {
|
|
46
|
+
...updatedDoctors[existingDoctorIndex],
|
|
47
|
+
isActive: true,
|
|
48
|
+
assignedAt: Timestamp.now(),
|
|
49
|
+
assignedBy,
|
|
50
|
+
};
|
|
51
|
+
updates.doctors = updatedDoctors;
|
|
52
|
+
} else {
|
|
53
|
+
updates.doctors = arrayUnion(newDoctor);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
await updateDoc(getPatientDocRef(db, patientId), updates);
|
|
34
57
|
};
|
|
35
58
|
|
|
36
59
|
export const removeDoctorUtil = async (
|
|
@@ -38,16 +61,19 @@ export const removeDoctorUtil = async (
|
|
|
38
61
|
patientId: string,
|
|
39
62
|
doctorRef: string
|
|
40
63
|
): Promise<void> => {
|
|
41
|
-
const
|
|
64
|
+
const patientDocRef = getPatientDocRef(db, patientId);
|
|
65
|
+
const patientDoc = await getDoc(patientDocRef);
|
|
42
66
|
if (!patientDoc.exists()) throw new Error("Patient profile not found");
|
|
43
67
|
|
|
44
68
|
const patientData = patientDoc.data() as PatientProfile;
|
|
45
|
-
const updatedDoctors = patientData.doctors.map((doctor) =>
|
|
46
|
-
doctor.userRef === doctorRef ? { ...doctor, isActive: false } : doctor
|
|
47
|
-
);
|
|
48
69
|
|
|
49
|
-
|
|
50
|
-
|
|
70
|
+
// Filter out the doctor object by userRef
|
|
71
|
+
const updatedDoctors =
|
|
72
|
+
patientData.doctors?.filter((doctor) => doctor.userRef !== doctorRef) || []; // Ensure it's an array even if doctors field didn't exist or was empty
|
|
73
|
+
|
|
74
|
+
await updateDoc(patientDocRef, {
|
|
75
|
+
doctors: updatedDoctors, // Set the filtered array
|
|
76
|
+
doctorIds: arrayRemove(doctorRef), // Remove ID from the denormalized list
|
|
51
77
|
updatedAt: serverTimestamp(),
|
|
52
78
|
});
|
|
53
79
|
};
|
|
@@ -66,10 +92,32 @@ export const addClinicUtil = async (
|
|
|
66
92
|
isActive: true,
|
|
67
93
|
};
|
|
68
94
|
|
|
69
|
-
await
|
|
70
|
-
|
|
95
|
+
const patientDoc = await getDoc(getPatientDocRef(db, patientId));
|
|
96
|
+
if (!patientDoc.exists()) throw new Error("Patient profile not found");
|
|
97
|
+
const patientData = patientDoc.data() as PatientProfile;
|
|
98
|
+
const existingClinicIndex = patientData.clinics?.findIndex(
|
|
99
|
+
(c) => c.clinicId === clinicId
|
|
100
|
+
);
|
|
101
|
+
|
|
102
|
+
const updates: any = {
|
|
71
103
|
updatedAt: serverTimestamp(),
|
|
72
|
-
|
|
104
|
+
clinicIds: arrayUnion(clinicId),
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
if (existingClinicIndex !== undefined && existingClinicIndex > -1) {
|
|
108
|
+
const updatedClinics = [...patientData.clinics];
|
|
109
|
+
updatedClinics[existingClinicIndex] = {
|
|
110
|
+
...updatedClinics[existingClinicIndex],
|
|
111
|
+
isActive: true,
|
|
112
|
+
assignedAt: Timestamp.now(),
|
|
113
|
+
assignedBy,
|
|
114
|
+
};
|
|
115
|
+
updates.clinics = updatedClinics;
|
|
116
|
+
} else {
|
|
117
|
+
updates.clinics = arrayUnion(newClinic);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
await updateDoc(getPatientDocRef(db, patientId), updates);
|
|
73
121
|
};
|
|
74
122
|
|
|
75
123
|
export const removeClinicUtil = async (
|
|
@@ -77,16 +125,19 @@ export const removeClinicUtil = async (
|
|
|
77
125
|
patientId: string,
|
|
78
126
|
clinicId: string
|
|
79
127
|
): Promise<void> => {
|
|
80
|
-
const
|
|
128
|
+
const patientDocRef = getPatientDocRef(db, patientId);
|
|
129
|
+
const patientDoc = await getDoc(patientDocRef);
|
|
81
130
|
if (!patientDoc.exists()) throw new Error("Patient profile not found");
|
|
82
131
|
|
|
83
132
|
const patientData = patientDoc.data() as PatientProfile;
|
|
84
|
-
const updatedClinics = patientData.clinics.map((clinic) =>
|
|
85
|
-
clinic.clinicId === clinicId ? { ...clinic, isActive: false } : clinic
|
|
86
|
-
);
|
|
87
133
|
|
|
88
|
-
|
|
89
|
-
|
|
134
|
+
// Filter out the clinic object by clinicId
|
|
135
|
+
const updatedClinics =
|
|
136
|
+
patientData.clinics?.filter((clinic) => clinic.clinicId !== clinicId) || []; // Ensure it's an array
|
|
137
|
+
|
|
138
|
+
await updateDoc(patientDocRef, {
|
|
139
|
+
clinics: updatedClinics, // Set the filtered array
|
|
140
|
+
clinicIds: arrayRemove(clinicId), // Remove ID from the denormalized list
|
|
90
141
|
updatedAt: serverTimestamp(),
|
|
91
142
|
});
|
|
92
143
|
};
|