@blackcode_sa/metaestetics-api 1.5.29 → 1.5.31
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 +126 -1
- package/dist/admin/index.d.ts +126 -1
- package/dist/admin/index.js +347 -10
- package/dist/admin/index.mjs +345 -10
- package/dist/index.d.mts +64 -71
- package/dist/index.d.ts +64 -71
- package/dist/index.js +327 -710
- package/dist/index.mjs +363 -750
- package/package.json +2 -1
- package/src/admin/aggregation/README.md +79 -0
- package/src/admin/aggregation/clinic/README.md +52 -0
- package/src/admin/aggregation/patient/README.md +27 -0
- package/src/admin/aggregation/practitioner/README.md +42 -0
- package/src/admin/aggregation/procedure/README.md +43 -0
- package/src/admin/index.ts +17 -2
- package/src/admin/mailing/README.md +95 -0
- package/src/admin/mailing/base.mailing.service.ts +131 -0
- package/src/admin/mailing/index.ts +2 -0
- package/src/admin/mailing/practitionerInvite/index.ts +1 -0
- package/src/admin/mailing/practitionerInvite/practitionerInvite.mailing.ts +256 -0
- package/src/admin/mailing/practitionerInvite/templates/invitation.template.ts +101 -0
- package/src/services/README.md +106 -0
- package/src/services/calendar/utils/appointment.utils.ts +42 -91
- package/src/services/clinic/README.md +87 -0
- package/src/services/clinic/clinic.service.ts +3 -126
- package/src/services/clinic/utils/clinic.utils.ts +2 -2
- package/src/services/practitioner/README.md +145 -0
- package/src/services/practitioner/practitioner.service.ts +119 -395
- package/src/services/procedure/README.md +88 -0
- package/src/services/procedure/procedure.service.ts +332 -369
package/dist/index.mjs
CHANGED
|
@@ -1,10 +1,3 @@
|
|
|
1
|
-
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
2
|
-
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
3
|
-
}) : x)(function(x) {
|
|
4
|
-
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
5
|
-
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
6
|
-
});
|
|
7
|
-
|
|
8
1
|
// src/config/firebase.ts
|
|
9
2
|
import { initializeApp } from "firebase/app";
|
|
10
3
|
import { getFirestore } from "firebase/firestore";
|
|
@@ -3451,7 +3444,6 @@ import {
|
|
|
3451
3444
|
limit as limit2,
|
|
3452
3445
|
startAfter as startAfter2,
|
|
3453
3446
|
orderBy,
|
|
3454
|
-
writeBatch as writeBatch2,
|
|
3455
3447
|
arrayUnion as arrayUnion5,
|
|
3456
3448
|
arrayRemove as arrayRemove4
|
|
3457
3449
|
} from "firebase/firestore";
|
|
@@ -3464,86 +3456,21 @@ var PractitionerService = class extends BaseService {
|
|
|
3464
3456
|
}
|
|
3465
3457
|
getClinicService() {
|
|
3466
3458
|
if (!this.clinicService) {
|
|
3467
|
-
throw new Error("
|
|
3459
|
+
throw new Error("Clinic service not initialized!");
|
|
3468
3460
|
}
|
|
3469
3461
|
return this.clinicService;
|
|
3470
3462
|
}
|
|
3471
|
-
/**
|
|
3472
|
-
* Postavlja referencu na ClinicService nakon inicijalizacije
|
|
3473
|
-
*/
|
|
3474
3463
|
setClinicService(clinicService) {
|
|
3475
3464
|
this.clinicService = clinicService;
|
|
3476
3465
|
}
|
|
3477
3466
|
/**
|
|
3478
|
-
*
|
|
3479
|
-
* @param clinicIds Array of clinic IDs the practitioner works at
|
|
3480
|
-
* @returns Array of ClinicInfo objects
|
|
3481
|
-
*/
|
|
3482
|
-
async aggregateClinicInfo(clinicIds) {
|
|
3483
|
-
const clinicsInfo = [];
|
|
3484
|
-
for (const clinicId of clinicIds) {
|
|
3485
|
-
const clinic = await this.getClinicService().getClinic(clinicId);
|
|
3486
|
-
if (!clinic) continue;
|
|
3487
|
-
clinicsInfo.push({
|
|
3488
|
-
id: clinic.id,
|
|
3489
|
-
featuredPhoto: clinic.featuredPhotos && clinic.featuredPhotos.length > 0 ? clinic.featuredPhotos[0] : clinic.coverPhoto || "",
|
|
3490
|
-
name: clinic.name,
|
|
3491
|
-
description: clinic.description || "",
|
|
3492
|
-
location: clinic.location,
|
|
3493
|
-
contactInfo: clinic.contactInfo
|
|
3494
|
-
});
|
|
3495
|
-
}
|
|
3496
|
-
return clinicsInfo;
|
|
3497
|
-
}
|
|
3498
|
-
/**
|
|
3499
|
-
* @deprecated Aggregation of procedure info is now handled by ProcedureService.
|
|
3500
|
-
*/
|
|
3501
|
-
async aggregateProcedureInfo(clinicIds, practitionerId) {
|
|
3502
|
-
console.warn("PractitionerService.aggregateProcedureInfo is deprecated.");
|
|
3503
|
-
return [];
|
|
3504
|
-
}
|
|
3505
|
-
/**
|
|
3506
|
-
* Updates aggregated data (clinics and procedures) for a practitioner
|
|
3507
|
-
* @param practitionerId ID of the practitioner to update
|
|
3508
|
-
* @returns Updated practitioner
|
|
3509
|
-
*/
|
|
3510
|
-
async updateAggregatedData(practitionerId) {
|
|
3511
|
-
const practitioner = await this.getPractitioner(practitionerId);
|
|
3512
|
-
if (!practitioner) {
|
|
3513
|
-
return null;
|
|
3514
|
-
}
|
|
3515
|
-
const clinicsInfo = await this.aggregateClinicInfo(practitioner.clinics);
|
|
3516
|
-
const proceduresInfo = await this.aggregateProcedureInfo(
|
|
3517
|
-
practitioner.clinics,
|
|
3518
|
-
practitionerId
|
|
3519
|
-
);
|
|
3520
|
-
const updatedPractitioner = await this.updatePractitioner(practitionerId, {
|
|
3521
|
-
clinicsInfo,
|
|
3522
|
-
proceduresInfo
|
|
3523
|
-
});
|
|
3524
|
-
return updatedPractitioner;
|
|
3525
|
-
}
|
|
3526
|
-
/**
|
|
3527
|
-
* Kreira novog zdravstvenog radnika
|
|
3467
|
+
* Creates a new practitioner
|
|
3528
3468
|
*/
|
|
3529
3469
|
async createPractitioner(data) {
|
|
3530
3470
|
try {
|
|
3531
|
-
const
|
|
3532
|
-
const
|
|
3533
|
-
|
|
3534
|
-
);
|
|
3535
|
-
if (existingPractitioner) {
|
|
3536
|
-
throw new Error("User already has a practitioner profile");
|
|
3537
|
-
}
|
|
3538
|
-
if (validatedData.clinics) {
|
|
3539
|
-
for (const clinicId of validatedData.clinics) {
|
|
3540
|
-
const clinic = await this.getClinicService().getClinic(clinicId);
|
|
3541
|
-
if (!clinic) {
|
|
3542
|
-
throw new Error(`Clinic ${clinicId} not found`);
|
|
3543
|
-
}
|
|
3544
|
-
}
|
|
3545
|
-
}
|
|
3546
|
-
const defaultReviewInfo = {
|
|
3471
|
+
const validData = createPractitionerSchema.parse(data);
|
|
3472
|
+
const practitionerId = this.generateId();
|
|
3473
|
+
const reviewInfo = {
|
|
3547
3474
|
totalReviews: 0,
|
|
3548
3475
|
averageRating: 0,
|
|
3549
3476
|
knowledgeAndExpertise: 0,
|
|
@@ -3553,50 +3480,46 @@ var PractitionerService = class extends BaseService {
|
|
|
3553
3480
|
trustworthiness: 0,
|
|
3554
3481
|
recommendationPercentage: 0
|
|
3555
3482
|
};
|
|
3556
|
-
const
|
|
3557
|
-
let clinicsInfo = validatedData.clinicsInfo || [];
|
|
3558
|
-
if (clinicsInfo.length === 0 && validatedData.clinics && validatedData.clinics.length > 0) {
|
|
3559
|
-
clinicsInfo = await this.aggregateClinicInfo(validatedData.clinics);
|
|
3560
|
-
}
|
|
3561
|
-
const proceduresInfo = [];
|
|
3562
|
-
const practitionerData = {
|
|
3483
|
+
const practitioner = {
|
|
3563
3484
|
id: practitionerId,
|
|
3564
|
-
userRef:
|
|
3565
|
-
basicInfo:
|
|
3566
|
-
certification:
|
|
3567
|
-
clinics:
|
|
3568
|
-
clinicWorkingHours:
|
|
3569
|
-
clinicsInfo,
|
|
3485
|
+
userRef: validData.userRef,
|
|
3486
|
+
basicInfo: validData.basicInfo,
|
|
3487
|
+
certification: validData.certification,
|
|
3488
|
+
clinics: validData.clinics || [],
|
|
3489
|
+
clinicWorkingHours: validData.clinicWorkingHours || [],
|
|
3490
|
+
clinicsInfo: [],
|
|
3570
3491
|
procedures: [],
|
|
3571
|
-
proceduresInfo,
|
|
3572
|
-
reviewInfo
|
|
3573
|
-
isActive:
|
|
3574
|
-
isVerified:
|
|
3575
|
-
status:
|
|
3492
|
+
proceduresInfo: [],
|
|
3493
|
+
reviewInfo,
|
|
3494
|
+
isActive: validData.isActive !== void 0 ? validData.isActive : true,
|
|
3495
|
+
isVerified: validData.isVerified !== void 0 ? validData.isVerified : false,
|
|
3496
|
+
status: validData.status || "active" /* ACTIVE */,
|
|
3576
3497
|
createdAt: serverTimestamp9(),
|
|
3577
3498
|
updatedAt: serverTimestamp9()
|
|
3578
3499
|
};
|
|
3579
3500
|
practitionerSchema.parse({
|
|
3580
|
-
...
|
|
3501
|
+
...practitioner,
|
|
3581
3502
|
createdAt: Timestamp8.now(),
|
|
3582
3503
|
updatedAt: Timestamp8.now()
|
|
3583
3504
|
});
|
|
3584
|
-
|
|
3585
|
-
|
|
3586
|
-
|
|
3505
|
+
const practitionerRef = doc6(
|
|
3506
|
+
this.db,
|
|
3507
|
+
PRACTITIONERS_COLLECTION,
|
|
3508
|
+
practitionerId
|
|
3587
3509
|
);
|
|
3588
|
-
|
|
3589
|
-
|
|
3590
|
-
|
|
3591
|
-
|
|
3592
|
-
|
|
3593
|
-
|
|
3510
|
+
await setDoc7(practitionerRef, practitioner);
|
|
3511
|
+
const createdPractitioner = await this.getPractitioner(practitionerId);
|
|
3512
|
+
if (!createdPractitioner) {
|
|
3513
|
+
throw new Error(
|
|
3514
|
+
`Failed to retrieve created practitioner ${practitionerId}`
|
|
3515
|
+
);
|
|
3594
3516
|
}
|
|
3595
|
-
return
|
|
3517
|
+
return createdPractitioner;
|
|
3596
3518
|
} catch (error) {
|
|
3597
3519
|
if (error instanceof z12.ZodError) {
|
|
3598
|
-
throw new Error(
|
|
3520
|
+
throw new Error(`Invalid practitioner data: ${error.message}`);
|
|
3599
3521
|
}
|
|
3522
|
+
console.error("Error creating practitioner:", error);
|
|
3600
3523
|
throw error;
|
|
3601
3524
|
}
|
|
3602
3525
|
}
|
|
@@ -3637,10 +3560,7 @@ var PractitionerService = class extends BaseService {
|
|
|
3637
3560
|
recommendationPercentage: 0
|
|
3638
3561
|
};
|
|
3639
3562
|
const practitionerId = this.generateId();
|
|
3640
|
-
|
|
3641
|
-
if (clinicsInfo.length === 0 && clinics.length > 0) {
|
|
3642
|
-
clinicsInfo = await this.aggregateClinicInfo(clinics);
|
|
3643
|
-
}
|
|
3563
|
+
const clinicsInfo = validatedData.clinicsInfo || [];
|
|
3644
3564
|
const proceduresInfo = [];
|
|
3645
3565
|
const practitionerData = {
|
|
3646
3566
|
id: practitionerId,
|
|
@@ -3877,113 +3797,100 @@ var PractitionerService = class extends BaseService {
|
|
|
3877
3797
|
return querySnapshot.docs.map((doc28) => doc28.data());
|
|
3878
3798
|
}
|
|
3879
3799
|
/**
|
|
3880
|
-
*
|
|
3800
|
+
* Updates a practitioner
|
|
3881
3801
|
*/
|
|
3882
3802
|
async updatePractitioner(practitionerId, data) {
|
|
3883
|
-
const practitionerRef = doc6(
|
|
3884
|
-
this.db,
|
|
3885
|
-
PRACTITIONERS_COLLECTION,
|
|
3886
|
-
practitionerId
|
|
3887
|
-
);
|
|
3888
|
-
const practitionerDoc = await getDoc9(practitionerRef);
|
|
3889
|
-
if (!practitionerDoc.exists()) {
|
|
3890
|
-
throw new Error("Practitioner not found");
|
|
3891
|
-
}
|
|
3892
3803
|
try {
|
|
3893
|
-
const
|
|
3894
|
-
|
|
3895
|
-
|
|
3896
|
-
|
|
3897
|
-
|
|
3898
|
-
|
|
3899
|
-
|
|
3900
|
-
|
|
3901
|
-
|
|
3902
|
-
data.clinicsInfo = await this.aggregateClinicInfo(data.clinics);
|
|
3903
|
-
}
|
|
3904
|
-
if (!data.proceduresInfo) {
|
|
3905
|
-
data.proceduresInfo = await this.aggregateProcedureInfo(
|
|
3906
|
-
data.clinics,
|
|
3907
|
-
practitionerId
|
|
3908
|
-
);
|
|
3909
|
-
}
|
|
3804
|
+
const validData = data;
|
|
3805
|
+
const practitionerRef = doc6(
|
|
3806
|
+
this.db,
|
|
3807
|
+
PRACTITIONERS_COLLECTION,
|
|
3808
|
+
practitionerId
|
|
3809
|
+
);
|
|
3810
|
+
const practitionerDoc = await getDoc9(practitionerRef);
|
|
3811
|
+
if (!practitionerDoc.exists()) {
|
|
3812
|
+
throw new Error(`Practitioner ${practitionerId} not found`);
|
|
3910
3813
|
}
|
|
3814
|
+
const currentPractitioner = practitionerDoc.data();
|
|
3911
3815
|
const updateData = {
|
|
3912
|
-
...
|
|
3816
|
+
...validData,
|
|
3913
3817
|
updatedAt: serverTimestamp9()
|
|
3914
3818
|
};
|
|
3915
|
-
practitionerSchema.parse({
|
|
3916
|
-
...currentPractitioner,
|
|
3917
|
-
...data,
|
|
3918
|
-
updatedAt: Timestamp8.now()
|
|
3919
|
-
});
|
|
3920
3819
|
await updateDoc8(practitionerRef, updateData);
|
|
3921
3820
|
const updatedPractitioner = await this.getPractitioner(practitionerId);
|
|
3922
3821
|
if (!updatedPractitioner) {
|
|
3923
|
-
throw new Error(
|
|
3822
|
+
throw new Error(
|
|
3823
|
+
`Failed to retrieve updated practitioner ${practitionerId}`
|
|
3824
|
+
);
|
|
3924
3825
|
}
|
|
3925
3826
|
return updatedPractitioner;
|
|
3926
3827
|
} catch (error) {
|
|
3927
3828
|
if (error instanceof z12.ZodError) {
|
|
3928
|
-
throw new Error(
|
|
3829
|
+
throw new Error(`Invalid practitioner update data: ${error.message}`);
|
|
3929
3830
|
}
|
|
3831
|
+
console.error(`Error updating practitioner ${practitionerId}:`, error);
|
|
3930
3832
|
throw error;
|
|
3931
3833
|
}
|
|
3932
3834
|
}
|
|
3933
3835
|
/**
|
|
3934
|
-
*
|
|
3836
|
+
* Adds a clinic to a practitioner
|
|
3935
3837
|
*/
|
|
3936
3838
|
async addClinic(practitionerId, clinicId) {
|
|
3937
|
-
|
|
3938
|
-
|
|
3939
|
-
|
|
3940
|
-
|
|
3941
|
-
|
|
3942
|
-
|
|
3943
|
-
|
|
3944
|
-
|
|
3945
|
-
|
|
3946
|
-
|
|
3839
|
+
var _a;
|
|
3840
|
+
try {
|
|
3841
|
+
const practitionerRef = doc6(
|
|
3842
|
+
this.db,
|
|
3843
|
+
PRACTITIONERS_COLLECTION,
|
|
3844
|
+
practitionerId
|
|
3845
|
+
);
|
|
3846
|
+
const practitionerDoc = await getDoc9(practitionerRef);
|
|
3847
|
+
if (!practitionerDoc.exists()) {
|
|
3848
|
+
throw new Error(`Practitioner ${practitionerId} not found`);
|
|
3849
|
+
}
|
|
3850
|
+
const practitioner = practitionerDoc.data();
|
|
3851
|
+
if ((_a = practitioner.clinics) == null ? void 0 : _a.includes(clinicId)) {
|
|
3852
|
+
console.log(
|
|
3853
|
+
`Clinic ${clinicId} already added to practitioner ${practitionerId}`
|
|
3854
|
+
);
|
|
3855
|
+
return;
|
|
3856
|
+
}
|
|
3857
|
+
await updateDoc8(practitionerRef, {
|
|
3858
|
+
clinics: arrayUnion5(clinicId),
|
|
3859
|
+
updatedAt: serverTimestamp9()
|
|
3860
|
+
});
|
|
3861
|
+
} catch (error) {
|
|
3862
|
+
console.error(
|
|
3863
|
+
`Error adding clinic ${clinicId} to practitioner ${practitionerId}:`,
|
|
3864
|
+
error
|
|
3865
|
+
);
|
|
3866
|
+
throw error;
|
|
3947
3867
|
}
|
|
3948
|
-
const updatedClinics = [...practitioner.clinics, clinicId];
|
|
3949
|
-
const clinicInfo = {
|
|
3950
|
-
id: clinic.id,
|
|
3951
|
-
name: clinic.name,
|
|
3952
|
-
description: clinic.description || "",
|
|
3953
|
-
featuredPhoto: clinic.featuredPhotos && clinic.featuredPhotos.length > 0 ? clinic.featuredPhotos[0] : clinic.coverPhoto || "",
|
|
3954
|
-
location: clinic.location,
|
|
3955
|
-
contactInfo: clinic.contactInfo
|
|
3956
|
-
};
|
|
3957
|
-
const updatedClinicsInfo = [...practitioner.clinicsInfo, clinicInfo];
|
|
3958
|
-
await this.updatePractitioner(practitionerId, {
|
|
3959
|
-
clinics: updatedClinics,
|
|
3960
|
-
clinicsInfo: updatedClinicsInfo
|
|
3961
|
-
});
|
|
3962
|
-
await this.updateAggregatedData(practitionerId);
|
|
3963
3868
|
}
|
|
3964
3869
|
/**
|
|
3965
|
-
*
|
|
3870
|
+
* Removes a clinic from a practitioner
|
|
3966
3871
|
*/
|
|
3967
3872
|
async removeClinic(practitionerId, clinicId) {
|
|
3968
|
-
|
|
3969
|
-
|
|
3970
|
-
|
|
3971
|
-
|
|
3972
|
-
|
|
3973
|
-
|
|
3873
|
+
try {
|
|
3874
|
+
const practitionerRef = doc6(
|
|
3875
|
+
this.db,
|
|
3876
|
+
PRACTITIONERS_COLLECTION,
|
|
3877
|
+
practitionerId
|
|
3878
|
+
);
|
|
3879
|
+
const practitionerDoc = await getDoc9(practitionerRef);
|
|
3880
|
+
if (!practitionerDoc.exists()) {
|
|
3881
|
+
throw new Error(`Practitioner ${practitionerId} not found`);
|
|
3882
|
+
}
|
|
3883
|
+
await updateDoc8(practitionerRef, {
|
|
3884
|
+
clinics: arrayRemove4(clinicId),
|
|
3885
|
+
updatedAt: serverTimestamp9()
|
|
3886
|
+
});
|
|
3887
|
+
} catch (error) {
|
|
3888
|
+
console.error(
|
|
3889
|
+
`Error removing clinic ${clinicId} from practitioner ${practitionerId}:`,
|
|
3890
|
+
error
|
|
3891
|
+
);
|
|
3892
|
+
throw error;
|
|
3974
3893
|
}
|
|
3975
|
-
const updatedClinics = practitioner.clinics.filter((id) => id !== clinicId);
|
|
3976
|
-
const updatedClinicsInfo = practitioner.clinicsInfo.filter(
|
|
3977
|
-
(clinic) => clinic.id !== clinicId
|
|
3978
|
-
);
|
|
3979
|
-
const updatedProceduresInfo = practitioner.proceduresInfo.filter(
|
|
3980
|
-
(procedure) => procedure.clinicId !== clinicId
|
|
3981
|
-
);
|
|
3982
|
-
await this.updatePractitioner(practitionerId, {
|
|
3983
|
-
clinics: updatedClinics,
|
|
3984
|
-
clinicsInfo: updatedClinicsInfo,
|
|
3985
|
-
proceduresInfo: updatedProceduresInfo
|
|
3986
|
-
});
|
|
3987
3894
|
}
|
|
3988
3895
|
/**
|
|
3989
3896
|
* Deaktivira profil zdravstvenog radnika
|
|
@@ -4221,112 +4128,6 @@ var PractitionerService = class extends BaseService {
|
|
|
4221
4128
|
throw error;
|
|
4222
4129
|
}
|
|
4223
4130
|
}
|
|
4224
|
-
// --- Helper Functions ---
|
|
4225
|
-
/**
|
|
4226
|
-
* Aggregates essential clinic information for embedding in Practitioner.
|
|
4227
|
-
* @param clinicIds Array of clinic IDs the practitioner works at
|
|
4228
|
-
* @returns Array of ClinicInfo objects
|
|
4229
|
-
*/
|
|
4230
|
-
async _aggregateClinicInfoForPractitioner(clinicIds) {
|
|
4231
|
-
const clinicsInfo = [];
|
|
4232
|
-
const clinicService = this.getClinicService();
|
|
4233
|
-
for (const clinicId of clinicIds) {
|
|
4234
|
-
try {
|
|
4235
|
-
const clinic = await clinicService.getClinic(clinicId);
|
|
4236
|
-
if (!clinic) {
|
|
4237
|
-
console.warn(
|
|
4238
|
-
`Clinic ${clinicId} not found during practitioner aggregation.`
|
|
4239
|
-
);
|
|
4240
|
-
continue;
|
|
4241
|
-
}
|
|
4242
|
-
clinicsInfo.push({
|
|
4243
|
-
id: clinic.id,
|
|
4244
|
-
featuredPhoto: clinic.featuredPhotos && clinic.featuredPhotos.length > 0 ? clinic.featuredPhotos[0] : clinic.coverPhoto || "",
|
|
4245
|
-
name: clinic.name,
|
|
4246
|
-
description: clinic.description || "",
|
|
4247
|
-
location: clinic.location,
|
|
4248
|
-
contactInfo: clinic.contactInfo
|
|
4249
|
-
});
|
|
4250
|
-
} catch (error) {
|
|
4251
|
-
console.error(
|
|
4252
|
-
`Error fetching clinic ${clinicId} for practitioner aggregation:`,
|
|
4253
|
-
error
|
|
4254
|
-
);
|
|
4255
|
-
}
|
|
4256
|
-
}
|
|
4257
|
-
return clinicsInfo;
|
|
4258
|
-
}
|
|
4259
|
-
/**
|
|
4260
|
-
* Creates an aggregated DoctorInfo object from Practitioner data.
|
|
4261
|
-
* @param practitioner The practitioner object
|
|
4262
|
-
* @returns DoctorInfo object
|
|
4263
|
-
*/
|
|
4264
|
-
_createDoctorInfoForClinic(practitioner) {
|
|
4265
|
-
var _a;
|
|
4266
|
-
return {
|
|
4267
|
-
id: practitioner.id,
|
|
4268
|
-
name: `${practitioner.basicInfo.firstName} ${practitioner.basicInfo.lastName}`,
|
|
4269
|
-
description: practitioner.basicInfo.bio || "",
|
|
4270
|
-
photo: practitioner.basicInfo.profileImageUrl || "",
|
|
4271
|
-
rating: ((_a = practitioner.reviewInfo) == null ? void 0 : _a.averageRating) || 0,
|
|
4272
|
-
services: practitioner.procedures || []
|
|
4273
|
-
// List of procedure IDs
|
|
4274
|
-
};
|
|
4275
|
-
}
|
|
4276
|
-
/**
|
|
4277
|
-
* Updates the DoctorInfo within the doctorsInfo array for multiple clinics.
|
|
4278
|
-
* @param clinicIds IDs of clinics to update
|
|
4279
|
-
* @param doctorInfo The updated DoctorInfo object
|
|
4280
|
-
*/
|
|
4281
|
-
async _updateDoctorInfoInClinics(clinicIds, doctorInfo) {
|
|
4282
|
-
const batch = writeBatch2(this.db);
|
|
4283
|
-
const practitionerId = doctorInfo.id;
|
|
4284
|
-
for (const clinicId of clinicIds) {
|
|
4285
|
-
const clinicRef = doc6(this.db, CLINICS_COLLECTION, clinicId);
|
|
4286
|
-
batch.update(clinicRef, {
|
|
4287
|
-
doctorsInfo: arrayRemove4(...[{ id: practitionerId }]),
|
|
4288
|
-
updatedAt: serverTimestamp9()
|
|
4289
|
-
});
|
|
4290
|
-
batch.update(clinicRef, {
|
|
4291
|
-
doctorsInfo: arrayUnion5(doctorInfo),
|
|
4292
|
-
updatedAt: serverTimestamp9()
|
|
4293
|
-
});
|
|
4294
|
-
}
|
|
4295
|
-
try {
|
|
4296
|
-
await batch.commit();
|
|
4297
|
-
} catch (error) {
|
|
4298
|
-
console.error(
|
|
4299
|
-
`Error updating doctor info in clinics for practitioner ${practitionerId}:`,
|
|
4300
|
-
error
|
|
4301
|
-
);
|
|
4302
|
-
}
|
|
4303
|
-
}
|
|
4304
|
-
/**
|
|
4305
|
-
* Removes DoctorInfo from the doctorsInfo array for multiple clinics.
|
|
4306
|
-
* @param clinicIds IDs of clinics to update
|
|
4307
|
-
* @param practitionerId ID of the practitioner whose info should be removed
|
|
4308
|
-
*/
|
|
4309
|
-
async _removeDoctorInfoFromClinics(clinicIds, practitionerId) {
|
|
4310
|
-
const batch = writeBatch2(this.db);
|
|
4311
|
-
for (const clinicId of clinicIds) {
|
|
4312
|
-
const clinicRef = doc6(this.db, CLINICS_COLLECTION, clinicId);
|
|
4313
|
-
batch.update(clinicRef, {
|
|
4314
|
-
doctors: arrayRemove4(practitionerId),
|
|
4315
|
-
// Also remove from simple ID list
|
|
4316
|
-
doctorsInfo: arrayRemove4(...[{ id: practitionerId }]),
|
|
4317
|
-
// Remove by ID matcher
|
|
4318
|
-
updatedAt: serverTimestamp9()
|
|
4319
|
-
});
|
|
4320
|
-
}
|
|
4321
|
-
try {
|
|
4322
|
-
await batch.commit();
|
|
4323
|
-
} catch (error) {
|
|
4324
|
-
console.error(
|
|
4325
|
-
`Error removing doctor info from clinics for practitioner ${practitionerId}:`,
|
|
4326
|
-
error
|
|
4327
|
-
);
|
|
4328
|
-
}
|
|
4329
|
-
}
|
|
4330
4131
|
};
|
|
4331
4132
|
|
|
4332
4133
|
// src/services/user.service.ts
|
|
@@ -5263,8 +5064,7 @@ import {
|
|
|
5263
5064
|
Timestamp as Timestamp12,
|
|
5264
5065
|
serverTimestamp as serverTimestamp12,
|
|
5265
5066
|
writeBatch as writeBatch4,
|
|
5266
|
-
arrayUnion as arrayUnion6
|
|
5267
|
-
arrayRemove as arrayRemove5
|
|
5067
|
+
arrayUnion as arrayUnion6
|
|
5268
5068
|
} from "firebase/firestore";
|
|
5269
5069
|
import {
|
|
5270
5070
|
geohashForLocation as geohashForLocation4
|
|
@@ -5281,7 +5081,9 @@ import {
|
|
|
5281
5081
|
where as where7,
|
|
5282
5082
|
updateDoc as updateDoc11,
|
|
5283
5083
|
setDoc as setDoc10,
|
|
5284
|
-
Timestamp as Timestamp11
|
|
5084
|
+
Timestamp as Timestamp11,
|
|
5085
|
+
limit as limit3,
|
|
5086
|
+
startAfter as startAfter3
|
|
5285
5087
|
} from "firebase/firestore";
|
|
5286
5088
|
import {
|
|
5287
5089
|
geohashForLocation as geohashForLocation3,
|
|
@@ -5531,15 +5333,14 @@ async function getAllClinics(db, pagination, lastDoc) {
|
|
|
5531
5333
|
const clinicsCollection = collection7(db, CLINICS_COLLECTION);
|
|
5532
5334
|
let clinicsQuery = query7(clinicsCollection);
|
|
5533
5335
|
if (pagination && pagination > 0) {
|
|
5534
|
-
const { limit: limit6, startAfter: startAfter6 } = __require("firebase/firestore");
|
|
5535
5336
|
if (lastDoc) {
|
|
5536
5337
|
clinicsQuery = query7(
|
|
5537
5338
|
clinicsCollection,
|
|
5538
|
-
|
|
5539
|
-
|
|
5339
|
+
startAfter3(lastDoc),
|
|
5340
|
+
limit3(pagination)
|
|
5540
5341
|
);
|
|
5541
5342
|
} else {
|
|
5542
|
-
clinicsQuery = query7(clinicsCollection,
|
|
5343
|
+
clinicsQuery = query7(clinicsCollection, limit3(pagination));
|
|
5543
5344
|
}
|
|
5544
5345
|
}
|
|
5545
5346
|
const clinicsSnapshot = await getDocs7(clinicsQuery);
|
|
@@ -5729,8 +5530,8 @@ import {
|
|
|
5729
5530
|
query as query9,
|
|
5730
5531
|
where as where9,
|
|
5731
5532
|
getDocs as getDocs9,
|
|
5732
|
-
startAfter as
|
|
5733
|
-
limit as
|
|
5533
|
+
startAfter as startAfter4,
|
|
5534
|
+
limit as limit4,
|
|
5734
5535
|
documentId,
|
|
5735
5536
|
orderBy as orderBy2
|
|
5736
5537
|
} from "firebase/firestore";
|
|
@@ -5768,10 +5569,10 @@ async function getClinicsByFilters(db, filters) {
|
|
|
5768
5569
|
);
|
|
5769
5570
|
}
|
|
5770
5571
|
if (filters.pagination && filters.pagination > 0 && filters.lastDoc) {
|
|
5771
|
-
constraints.push(
|
|
5772
|
-
constraints.push(
|
|
5572
|
+
constraints.push(startAfter4(filters.lastDoc));
|
|
5573
|
+
constraints.push(limit4(filters.pagination));
|
|
5773
5574
|
} else if (filters.pagination && filters.pagination > 0) {
|
|
5774
|
-
constraints.push(
|
|
5575
|
+
constraints.push(limit4(filters.pagination));
|
|
5775
5576
|
}
|
|
5776
5577
|
constraints.push(orderBy2(documentId()));
|
|
5777
5578
|
let clinicsResult = [];
|
|
@@ -5888,59 +5689,8 @@ var ClinicService = class extends BaseService {
|
|
|
5888
5689
|
this.clinicAdminService = clinicAdminService;
|
|
5889
5690
|
this.clinicGroupService = clinicGroupService;
|
|
5890
5691
|
}
|
|
5891
|
-
// --- Helper Functions ---
|
|
5892
|
-
/**
|
|
5893
|
-
* Creates an aggregated ClinicInfo object from Clinic data.
|
|
5894
|
-
* @param clinic The clinic object
|
|
5895
|
-
* @returns ClinicInfo object
|
|
5896
|
-
*/
|
|
5897
|
-
_createClinicInfoForAggregation(clinic) {
|
|
5898
|
-
return {
|
|
5899
|
-
id: clinic.id,
|
|
5900
|
-
featuredPhoto: clinic.featuredPhotos && clinic.featuredPhotos.length > 0 ? clinic.featuredPhotos[0] : clinic.coverPhoto || "",
|
|
5901
|
-
name: clinic.name,
|
|
5902
|
-
description: clinic.description || "",
|
|
5903
|
-
location: clinic.location,
|
|
5904
|
-
contactInfo: clinic.contactInfo
|
|
5905
|
-
};
|
|
5906
|
-
}
|
|
5907
|
-
/**
|
|
5908
|
-
* Updates the ClinicInfo within the clinicsInfo array for multiple practitioners.
|
|
5909
|
-
* @param practitionerIds IDs of practitioners to update
|
|
5910
|
-
* @param clinicInfo The updated ClinicInfo object
|
|
5911
|
-
*/
|
|
5912
|
-
async _updateClinicInfoInPractitioners(practitionerIds, clinicInfo) {
|
|
5913
|
-
const batch = writeBatch4(this.db);
|
|
5914
|
-
const clinicId = clinicInfo.id;
|
|
5915
|
-
for (const practitionerId of practitionerIds) {
|
|
5916
|
-
const practitionerRef = doc10(
|
|
5917
|
-
this.db,
|
|
5918
|
-
PRACTITIONERS_COLLECTION,
|
|
5919
|
-
practitionerId
|
|
5920
|
-
);
|
|
5921
|
-
batch.update(practitionerRef, {
|
|
5922
|
-
clinicsInfo: arrayRemove5(...[{ id: clinicId }]),
|
|
5923
|
-
updatedAt: serverTimestamp12()
|
|
5924
|
-
});
|
|
5925
|
-
batch.update(practitionerRef, {
|
|
5926
|
-
clinicsInfo: arrayUnion6(clinicInfo),
|
|
5927
|
-
updatedAt: serverTimestamp12()
|
|
5928
|
-
});
|
|
5929
|
-
}
|
|
5930
|
-
try {
|
|
5931
|
-
await batch.commit();
|
|
5932
|
-
} catch (error) {
|
|
5933
|
-
console.error(
|
|
5934
|
-
`Error updating clinic info in practitioners for clinic ${clinicId}:`,
|
|
5935
|
-
error
|
|
5936
|
-
);
|
|
5937
|
-
}
|
|
5938
|
-
}
|
|
5939
|
-
// --- Core Service Methods (Updated) ---
|
|
5940
5692
|
/**
|
|
5941
5693
|
* Creates a new clinic.
|
|
5942
|
-
* Initializes empty doctorsInfo and proceduresInfo.
|
|
5943
|
-
* Aggregation into Clinic happens via PractitionerService and ProcedureService.
|
|
5944
5694
|
*/
|
|
5945
5695
|
async createClinic(data, creatorAdminId) {
|
|
5946
5696
|
try {
|
|
@@ -5997,20 +5747,6 @@ var ClinicService = class extends BaseService {
|
|
|
5997
5747
|
const batch = writeBatch4(this.db);
|
|
5998
5748
|
const clinicRef = doc10(this.db, CLINICS_COLLECTION, clinicId);
|
|
5999
5749
|
batch.set(clinicRef, clinicData);
|
|
6000
|
-
const groupRef = doc10(
|
|
6001
|
-
this.db,
|
|
6002
|
-
CLINIC_GROUPS_COLLECTION,
|
|
6003
|
-
validatedData.clinicGroupId
|
|
6004
|
-
);
|
|
6005
|
-
const newClinicInfoForGroup = this._createClinicInfoForAggregation({
|
|
6006
|
-
...clinicData,
|
|
6007
|
-
id: clinicId
|
|
6008
|
-
});
|
|
6009
|
-
batch.update(groupRef, {
|
|
6010
|
-
clinics: arrayUnion6(clinicId),
|
|
6011
|
-
clinicsInfo: arrayUnion6(newClinicInfoForGroup),
|
|
6012
|
-
updatedAt: serverTimestamp12()
|
|
6013
|
-
});
|
|
6014
5750
|
const adminRef = doc10(this.db, CLINIC_ADMINS_COLLECTION, creatorAdminId);
|
|
6015
5751
|
batch.update(adminRef, {
|
|
6016
5752
|
clinicsManaged: arrayUnion6(clinicId),
|
|
@@ -6029,7 +5765,7 @@ var ClinicService = class extends BaseService {
|
|
|
6029
5765
|
}
|
|
6030
5766
|
}
|
|
6031
5767
|
/**
|
|
6032
|
-
* Updates a clinic
|
|
5768
|
+
* Updates a clinic.
|
|
6033
5769
|
*/
|
|
6034
5770
|
async updateClinic(clinicId, data, adminId) {
|
|
6035
5771
|
const clinicRef = doc10(this.db, CLINICS_COLLECTION, clinicId);
|
|
@@ -6064,32 +5800,7 @@ var ClinicService = class extends BaseService {
|
|
|
6064
5800
|
...updatePayload,
|
|
6065
5801
|
updatedAt: serverTimestamp12()
|
|
6066
5802
|
};
|
|
6067
|
-
|
|
6068
|
-
batch.update(clinicRef, updateDataForFirestore);
|
|
6069
|
-
const groupRef = doc10(
|
|
6070
|
-
this.db,
|
|
6071
|
-
CLINIC_GROUPS_COLLECTION,
|
|
6072
|
-
currentClinic.clinicGroupId
|
|
6073
|
-
);
|
|
6074
|
-
const updatedClinicInfoForGroup = this._createClinicInfoForAggregation(
|
|
6075
|
-
finalStateForValidation
|
|
6076
|
-
);
|
|
6077
|
-
batch.update(groupRef, {
|
|
6078
|
-
clinicsInfo: arrayRemove5(...[{ id: clinicId }]),
|
|
6079
|
-
updatedAt: serverTimestamp12()
|
|
6080
|
-
});
|
|
6081
|
-
batch.update(groupRef, {
|
|
6082
|
-
clinicsInfo: arrayUnion6(updatedClinicInfoForGroup),
|
|
6083
|
-
updatedAt: serverTimestamp12()
|
|
6084
|
-
});
|
|
6085
|
-
const practitionerIds = currentClinic.doctors || [];
|
|
6086
|
-
if (practitionerIds.length > 0) {
|
|
6087
|
-
await this._updateClinicInfoInPractitioners(
|
|
6088
|
-
practitionerIds,
|
|
6089
|
-
updatedClinicInfoForGroup
|
|
6090
|
-
);
|
|
6091
|
-
}
|
|
6092
|
-
await batch.commit();
|
|
5803
|
+
await updateDoc12(clinicRef, updateDataForFirestore);
|
|
6093
5804
|
const updatedClinic = await this.getClinic(clinicId);
|
|
6094
5805
|
if (!updatedClinic) throw new Error("Failed to retrieve updated clinic");
|
|
6095
5806
|
return updatedClinic;
|
|
@@ -6105,7 +5816,6 @@ var ClinicService = class extends BaseService {
|
|
|
6105
5816
|
}
|
|
6106
5817
|
/**
|
|
6107
5818
|
* Deactivates a clinic.
|
|
6108
|
-
* Note: Does not currently remove ClinicInfo from practitioners (might be desired).
|
|
6109
5819
|
*/
|
|
6110
5820
|
async deactivateClinic(clinicId, adminId) {
|
|
6111
5821
|
const clinicRef = doc10(this.db, CLINICS_COLLECTION, clinicId);
|
|
@@ -6114,10 +5824,6 @@ var ClinicService = class extends BaseService {
|
|
|
6114
5824
|
updatedAt: serverTimestamp12()
|
|
6115
5825
|
});
|
|
6116
5826
|
}
|
|
6117
|
-
// --- Other Methods ---
|
|
6118
|
-
// (getClinic, getClinicsByGroup, findClinicsInRadius, addTags, removeTags, getClinicsByAdmin, etc.)
|
|
6119
|
-
// Review these methods to ensure they don't rely on outdated aggregation logic (e.g., filtering ServiceInfo)
|
|
6120
|
-
// and update them to use proceduresInfo if necessary for filtering.
|
|
6121
5827
|
/**
|
|
6122
5828
|
* Dohvata kliniku po ID-u
|
|
6123
5829
|
*/
|
|
@@ -6132,12 +5838,8 @@ var ClinicService = class extends BaseService {
|
|
|
6132
5838
|
}
|
|
6133
5839
|
/**
|
|
6134
5840
|
* Pretražuje klinike u određenom radijusu
|
|
6135
|
-
* REVIEW: SearchUtils.findClinicsInRadius might need updating for filters.
|
|
6136
5841
|
*/
|
|
6137
5842
|
async findClinicsInRadius(center, radiusInKm, filters) {
|
|
6138
|
-
console.warn(
|
|
6139
|
-
"SearchUtils.findClinicsInRadius filter logic might need updating for proceduresInfo."
|
|
6140
|
-
);
|
|
6141
5843
|
return findClinicsInRadius(
|
|
6142
5844
|
this.db,
|
|
6143
5845
|
center,
|
|
@@ -7111,11 +6813,14 @@ import {
|
|
|
7111
6813
|
getDocs as getDocs13,
|
|
7112
6814
|
query as query13,
|
|
7113
6815
|
where as where13,
|
|
6816
|
+
updateDoc as updateDoc15,
|
|
6817
|
+
setDoc as setDoc13,
|
|
6818
|
+
deleteDoc as deleteDoc8,
|
|
7114
6819
|
serverTimestamp as serverTimestamp14,
|
|
7115
|
-
|
|
7116
|
-
|
|
7117
|
-
|
|
7118
|
-
|
|
6820
|
+
orderBy as orderBy4,
|
|
6821
|
+
limit as limit5,
|
|
6822
|
+
startAfter as startAfter5,
|
|
6823
|
+
documentId as documentId2
|
|
7119
6824
|
} from "firebase/firestore";
|
|
7120
6825
|
|
|
7121
6826
|
// src/types/procedure/index.ts
|
|
@@ -7188,6 +6893,7 @@ var procedureSchema = createProcedureSchema.extend({
|
|
|
7188
6893
|
});
|
|
7189
6894
|
|
|
7190
6895
|
// src/services/procedure/procedure.service.ts
|
|
6896
|
+
import { distanceBetween as distanceBetween6, geohashQueryBounds as geohashQueryBounds5 } from "geofire-common";
|
|
7191
6897
|
var ProcedureService = class extends BaseService {
|
|
7192
6898
|
constructor(db, auth, app, categoryService, subcategoryService, technologyService, productService) {
|
|
7193
6899
|
super(db, auth, app);
|
|
@@ -7196,108 +6902,8 @@ var ProcedureService = class extends BaseService {
|
|
|
7196
6902
|
this.technologyService = technologyService;
|
|
7197
6903
|
this.productService = productService;
|
|
7198
6904
|
}
|
|
7199
|
-
// Helper function to create ProcedureSummaryInfo
|
|
7200
|
-
_createProcedureSummaryInfo(procedure) {
|
|
7201
|
-
var _a, _b, _c, _d, _e;
|
|
7202
|
-
const categoryName = ((_a = procedure.category) == null ? void 0 : _a.name) || "N/A";
|
|
7203
|
-
const subcategoryName = ((_b = procedure.subcategory) == null ? void 0 : _b.name) || "N/A";
|
|
7204
|
-
const technologyName = ((_c = procedure.technology) == null ? void 0 : _c.name) || "N/A";
|
|
7205
|
-
const clinicName = ((_d = procedure.clinicInfo) == null ? void 0 : _d.name) || "N/A";
|
|
7206
|
-
const practitionerName = ((_e = procedure.doctorInfo) == null ? void 0 : _e.name) || "N/A";
|
|
7207
|
-
return {
|
|
7208
|
-
id: procedure.id,
|
|
7209
|
-
name: procedure.name,
|
|
7210
|
-
description: procedure.description || "",
|
|
7211
|
-
photo: "",
|
|
7212
|
-
// No photo source identified yet
|
|
7213
|
-
family: procedure.family,
|
|
7214
|
-
categoryName,
|
|
7215
|
-
subcategoryName,
|
|
7216
|
-
technologyName,
|
|
7217
|
-
price: procedure.price,
|
|
7218
|
-
pricingMeasure: procedure.pricingMeasure,
|
|
7219
|
-
currency: procedure.currency,
|
|
7220
|
-
duration: procedure.duration,
|
|
7221
|
-
clinicId: procedure.clinicBranchId,
|
|
7222
|
-
clinicName,
|
|
7223
|
-
practitionerId: procedure.practitionerId,
|
|
7224
|
-
practitionerName
|
|
7225
|
-
};
|
|
7226
|
-
}
|
|
7227
|
-
// Helper to update practitioner's procedures
|
|
7228
|
-
async _updatePractitionerProcedures(practitionerId, procedureSummary, procedureIdToRemove) {
|
|
7229
|
-
const practitionerRef = doc13(
|
|
7230
|
-
this.db,
|
|
7231
|
-
PRACTITIONERS_COLLECTION,
|
|
7232
|
-
practitionerId
|
|
7233
|
-
);
|
|
7234
|
-
const updateData = {};
|
|
7235
|
-
if (procedureSummary) {
|
|
7236
|
-
updateData["procedures"] = arrayUnion7(procedureSummary.id);
|
|
7237
|
-
updateData["proceduresInfo"] = arrayRemove6(
|
|
7238
|
-
...[
|
|
7239
|
-
// Need to spread the arrayRemove arguments
|
|
7240
|
-
// Create a 'matcher' object with only the ID for removal
|
|
7241
|
-
{ id: procedureSummary.id }
|
|
7242
|
-
]
|
|
7243
|
-
);
|
|
7244
|
-
} else if (procedureIdToRemove) {
|
|
7245
|
-
updateData["procedures"] = arrayRemove6(procedureIdToRemove);
|
|
7246
|
-
updateData["proceduresInfo"] = arrayRemove6(
|
|
7247
|
-
...[{ id: procedureIdToRemove }]
|
|
7248
|
-
// Use matcher for removal
|
|
7249
|
-
);
|
|
7250
|
-
} else {
|
|
7251
|
-
return;
|
|
7252
|
-
}
|
|
7253
|
-
updateData["updatedAt"] = serverTimestamp14();
|
|
7254
|
-
const batch = writeBatch6(this.db);
|
|
7255
|
-
batch.update(practitionerRef, updateData);
|
|
7256
|
-
if (procedureSummary) {
|
|
7257
|
-
batch.update(practitionerRef, {
|
|
7258
|
-
proceduresInfo: arrayUnion7(procedureSummary)
|
|
7259
|
-
});
|
|
7260
|
-
}
|
|
7261
|
-
await batch.commit();
|
|
7262
|
-
}
|
|
7263
|
-
// Helper to update clinic's procedures
|
|
7264
|
-
async _updateClinicProcedures(clinicId, procedureSummary, procedureIdToRemove) {
|
|
7265
|
-
const clinicRef = doc13(this.db, CLINICS_COLLECTION, clinicId);
|
|
7266
|
-
const clinicSnap = await getDoc16(clinicRef);
|
|
7267
|
-
if (!clinicSnap.exists()) {
|
|
7268
|
-
console.warn(
|
|
7269
|
-
`Clinic ${clinicId} not found, skipping procedure aggregation update.`
|
|
7270
|
-
);
|
|
7271
|
-
return;
|
|
7272
|
-
}
|
|
7273
|
-
const updateData = {};
|
|
7274
|
-
if (procedureSummary) {
|
|
7275
|
-
updateData["services"] = arrayUnion7(procedureSummary.id);
|
|
7276
|
-
updateData["proceduresInfo"] = arrayRemove6(
|
|
7277
|
-
...[{ id: procedureSummary.id }]
|
|
7278
|
-
// Use matcher for removal
|
|
7279
|
-
);
|
|
7280
|
-
} else if (procedureIdToRemove) {
|
|
7281
|
-
updateData["services"] = arrayRemove6(procedureIdToRemove);
|
|
7282
|
-
updateData["proceduresInfo"] = arrayRemove6(
|
|
7283
|
-
...[{ id: procedureIdToRemove }]
|
|
7284
|
-
// Use matcher for removal
|
|
7285
|
-
);
|
|
7286
|
-
} else {
|
|
7287
|
-
return;
|
|
7288
|
-
}
|
|
7289
|
-
updateData["updatedAt"] = serverTimestamp14();
|
|
7290
|
-
const batch = writeBatch6(this.db);
|
|
7291
|
-
batch.update(clinicRef, updateData);
|
|
7292
|
-
if (procedureSummary) {
|
|
7293
|
-
batch.update(clinicRef, {
|
|
7294
|
-
proceduresInfo: arrayUnion7(procedureSummary)
|
|
7295
|
-
});
|
|
7296
|
-
}
|
|
7297
|
-
await batch.commit();
|
|
7298
|
-
}
|
|
7299
6905
|
/**
|
|
7300
|
-
* Creates a new procedure
|
|
6906
|
+
* Creates a new procedure
|
|
7301
6907
|
* @param data - The data for creating a new procedure
|
|
7302
6908
|
* @returns The created procedure
|
|
7303
6909
|
*/
|
|
@@ -7357,9 +6963,7 @@ var ProcedureService = class extends BaseService {
|
|
|
7357
6963
|
description: practitioner.basicInfo.bio || "",
|
|
7358
6964
|
photo: practitioner.basicInfo.profileImageUrl || "",
|
|
7359
6965
|
rating: ((_a = practitioner.reviewInfo) == null ? void 0 : _a.averageRating) || 0,
|
|
7360
|
-
// Example rating source
|
|
7361
6966
|
services: practitioner.procedures || []
|
|
7362
|
-
// Link services to practitioner's procedures
|
|
7363
6967
|
};
|
|
7364
6968
|
const procedureId = this.generateId();
|
|
7365
6969
|
const newProcedure = {
|
|
@@ -7394,37 +6998,12 @@ var ProcedureService = class extends BaseService {
|
|
|
7394
6998
|
isActive: true
|
|
7395
6999
|
// Default to active
|
|
7396
7000
|
};
|
|
7397
|
-
const batch = writeBatch6(this.db);
|
|
7398
7001
|
const procedureRef = doc13(this.db, PROCEDURES_COLLECTION, procedureId);
|
|
7399
|
-
|
|
7002
|
+
await setDoc13(procedureRef, {
|
|
7400
7003
|
...newProcedure,
|
|
7401
7004
|
createdAt: serverTimestamp14(),
|
|
7402
7005
|
updatedAt: serverTimestamp14()
|
|
7403
7006
|
});
|
|
7404
|
-
const procedureSummary = this._createProcedureSummaryInfo({
|
|
7405
|
-
...newProcedure,
|
|
7406
|
-
createdAt: /* @__PURE__ */ new Date(),
|
|
7407
|
-
// Use placeholder date for summary creation
|
|
7408
|
-
updatedAt: /* @__PURE__ */ new Date()
|
|
7409
|
-
});
|
|
7410
|
-
const practitionerUpdateData = {
|
|
7411
|
-
procedures: arrayUnion7(procedureId),
|
|
7412
|
-
proceduresInfo: arrayUnion7(procedureSummary),
|
|
7413
|
-
updatedAt: serverTimestamp14()
|
|
7414
|
-
};
|
|
7415
|
-
batch.update(practitionerRef, practitionerUpdateData);
|
|
7416
|
-
const clinicUpdateData = {
|
|
7417
|
-
// services: arrayUnion(procedureId), // Decide if 'services' array is still needed
|
|
7418
|
-
proceduresInfo: arrayUnion7(procedureSummary),
|
|
7419
|
-
// Potentially update clinic.doctors array if not already present
|
|
7420
|
-
doctors: arrayUnion7(validatedData.practitionerId),
|
|
7421
|
-
// Potentially update clinic.doctorsInfo array
|
|
7422
|
-
// This requires fetching existing doctorsInfo and adding/updating
|
|
7423
|
-
// For simplicity now, we'll just add the procedure summary
|
|
7424
|
-
updatedAt: serverTimestamp14()
|
|
7425
|
-
};
|
|
7426
|
-
batch.update(clinicRef, clinicUpdateData);
|
|
7427
|
-
await batch.commit();
|
|
7428
7007
|
const savedDoc = await getDoc16(procedureRef);
|
|
7429
7008
|
return savedDoc.data();
|
|
7430
7009
|
}
|
|
@@ -7470,7 +7049,7 @@ var ProcedureService = class extends BaseService {
|
|
|
7470
7049
|
return snapshot.docs.map((doc28) => doc28.data());
|
|
7471
7050
|
}
|
|
7472
7051
|
/**
|
|
7473
|
-
* Updates a procedure
|
|
7052
|
+
* Updates a procedure
|
|
7474
7053
|
* @param id - The ID of the procedure to update
|
|
7475
7054
|
* @param data - The data to update the procedure with
|
|
7476
7055
|
* @returns The updated procedure
|
|
@@ -7587,104 +7166,15 @@ var ProcedureService = class extends BaseService {
|
|
|
7587
7166
|
} else if (validatedData.productId) {
|
|
7588
7167
|
console.warn("Attempted to update product without a valid technologyId");
|
|
7589
7168
|
}
|
|
7590
|
-
|
|
7591
|
-
batch.update(procedureRef, {
|
|
7169
|
+
await updateDoc15(procedureRef, {
|
|
7592
7170
|
...updatedProcedureData,
|
|
7593
7171
|
updatedAt: serverTimestamp14()
|
|
7594
7172
|
});
|
|
7595
|
-
const finalProcedureStateForSummary = {
|
|
7596
|
-
...existingProcedure,
|
|
7597
|
-
...updatedProcedureData,
|
|
7598
|
-
// Apply updates
|
|
7599
|
-
// Ensure nested objects needed for summary are present
|
|
7600
|
-
category: updatedProcedureData.category || existingProcedure.category,
|
|
7601
|
-
subcategory: updatedProcedureData.subcategory || existingProcedure.subcategory,
|
|
7602
|
-
technology: updatedProcedureData.technology || existingProcedure.technology,
|
|
7603
|
-
product: updatedProcedureData.product || existingProcedure.product,
|
|
7604
|
-
clinicInfo: updatedProcedureData.clinicInfo || existingProcedure.clinicInfo,
|
|
7605
|
-
doctorInfo: updatedProcedureData.doctorInfo || existingProcedure.doctorInfo,
|
|
7606
|
-
practitionerId: validatedData.practitionerId || existingProcedure.practitionerId,
|
|
7607
|
-
// Use potentially updated IDs
|
|
7608
|
-
clinicBranchId: validatedData.clinicBranchId || existingProcedure.clinicBranchId
|
|
7609
|
-
};
|
|
7610
|
-
const updatedProcedureSummary = this._createProcedureSummaryInfo(
|
|
7611
|
-
finalProcedureStateForSummary
|
|
7612
|
-
);
|
|
7613
|
-
if (practitionerChanged) {
|
|
7614
|
-
const oldPractitionerRef = doc13(
|
|
7615
|
-
this.db,
|
|
7616
|
-
PRACTITIONERS_COLLECTION,
|
|
7617
|
-
oldPractitionerId
|
|
7618
|
-
);
|
|
7619
|
-
batch.update(oldPractitionerRef, {
|
|
7620
|
-
procedures: arrayRemove6(id),
|
|
7621
|
-
proceduresInfo: arrayRemove6(...[{ id }]),
|
|
7622
|
-
// Matcher for removal
|
|
7623
|
-
updatedAt: serverTimestamp14()
|
|
7624
|
-
});
|
|
7625
|
-
const newPractitionerRef = doc13(
|
|
7626
|
-
this.db,
|
|
7627
|
-
PRACTITIONERS_COLLECTION,
|
|
7628
|
-
updatedProcedureSummary.practitionerId
|
|
7629
|
-
);
|
|
7630
|
-
batch.update(newPractitionerRef, {
|
|
7631
|
-
procedures: arrayUnion7(id),
|
|
7632
|
-
proceduresInfo: arrayUnion7(updatedProcedureSummary),
|
|
7633
|
-
updatedAt: serverTimestamp14()
|
|
7634
|
-
});
|
|
7635
|
-
} else {
|
|
7636
|
-
const currentPractitionerRef = doc13(
|
|
7637
|
-
this.db,
|
|
7638
|
-
PRACTITIONERS_COLLECTION,
|
|
7639
|
-
oldPractitionerId
|
|
7640
|
-
);
|
|
7641
|
-
batch.update(currentPractitionerRef, {
|
|
7642
|
-
proceduresInfo: arrayRemove6(...[{ id }]),
|
|
7643
|
-
updatedAt: serverTimestamp14()
|
|
7644
|
-
});
|
|
7645
|
-
batch.update(currentPractitionerRef, {
|
|
7646
|
-
proceduresInfo: arrayUnion7(updatedProcedureSummary),
|
|
7647
|
-
updatedAt: serverTimestamp14()
|
|
7648
|
-
});
|
|
7649
|
-
}
|
|
7650
|
-
if (clinicChanged) {
|
|
7651
|
-
const oldClinicRef = doc13(this.db, CLINICS_COLLECTION, oldClinicId);
|
|
7652
|
-
batch.update(oldClinicRef, {
|
|
7653
|
-
// services: arrayRemove(id),
|
|
7654
|
-
proceduresInfo: arrayRemove6(...[{ id }]),
|
|
7655
|
-
// Matcher for removal
|
|
7656
|
-
updatedAt: serverTimestamp14()
|
|
7657
|
-
// Potentially remove from clinic.doctors and clinic.doctorsInfo if practitioner also changed or was last one for this clinic
|
|
7658
|
-
});
|
|
7659
|
-
const newClinicRef = doc13(
|
|
7660
|
-
this.db,
|
|
7661
|
-
CLINICS_COLLECTION,
|
|
7662
|
-
updatedProcedureSummary.clinicId
|
|
7663
|
-
);
|
|
7664
|
-
batch.update(newClinicRef, {
|
|
7665
|
-
// services: arrayUnion(id),
|
|
7666
|
-
proceduresInfo: arrayUnion7(updatedProcedureSummary),
|
|
7667
|
-
doctors: arrayUnion7(updatedProcedureSummary.practitionerId),
|
|
7668
|
-
// Ensure practitioner is listed
|
|
7669
|
-
updatedAt: serverTimestamp14()
|
|
7670
|
-
});
|
|
7671
|
-
} else {
|
|
7672
|
-
const currentClinicRef = doc13(this.db, CLINICS_COLLECTION, oldClinicId);
|
|
7673
|
-
batch.update(currentClinicRef, {
|
|
7674
|
-
proceduresInfo: arrayRemove6(...[{ id }]),
|
|
7675
|
-
updatedAt: serverTimestamp14()
|
|
7676
|
-
});
|
|
7677
|
-
batch.update(currentClinicRef, {
|
|
7678
|
-
proceduresInfo: arrayUnion7(updatedProcedureSummary),
|
|
7679
|
-
updatedAt: serverTimestamp14()
|
|
7680
|
-
});
|
|
7681
|
-
}
|
|
7682
|
-
await batch.commit();
|
|
7683
7173
|
const updatedSnapshot = await getDoc16(procedureRef);
|
|
7684
7174
|
return updatedSnapshot.data();
|
|
7685
7175
|
}
|
|
7686
7176
|
/**
|
|
7687
|
-
* Deactivates a procedure (soft delete)
|
|
7177
|
+
* Deactivates a procedure (soft delete)
|
|
7688
7178
|
* @param id - The ID of the procedure to deactivate
|
|
7689
7179
|
*/
|
|
7690
7180
|
async deactivateProcedure(id) {
|
|
@@ -7694,39 +7184,13 @@ var ProcedureService = class extends BaseService {
|
|
|
7694
7184
|
console.warn(`Procedure ${id} not found for deactivation.`);
|
|
7695
7185
|
return;
|
|
7696
7186
|
}
|
|
7697
|
-
|
|
7698
|
-
const batch = writeBatch6(this.db);
|
|
7699
|
-
batch.update(procedureRef, {
|
|
7187
|
+
await updateDoc15(procedureRef, {
|
|
7700
7188
|
isActive: false,
|
|
7701
7189
|
updatedAt: serverTimestamp14()
|
|
7702
7190
|
});
|
|
7703
|
-
const practitionerRef = doc13(
|
|
7704
|
-
this.db,
|
|
7705
|
-
PRACTITIONERS_COLLECTION,
|
|
7706
|
-
procedure.practitionerId
|
|
7707
|
-
);
|
|
7708
|
-
batch.update(practitionerRef, {
|
|
7709
|
-
procedures: arrayRemove6(id),
|
|
7710
|
-
proceduresInfo: arrayRemove6(...[{ id }]),
|
|
7711
|
-
// Matcher for removal
|
|
7712
|
-
updatedAt: serverTimestamp14()
|
|
7713
|
-
});
|
|
7714
|
-
const clinicRef = doc13(
|
|
7715
|
-
this.db,
|
|
7716
|
-
CLINICS_COLLECTION,
|
|
7717
|
-
procedure.clinicBranchId
|
|
7718
|
-
);
|
|
7719
|
-
batch.update(clinicRef, {
|
|
7720
|
-
// services: arrayRemove(id),
|
|
7721
|
-
proceduresInfo: arrayRemove6(...[{ id }]),
|
|
7722
|
-
// Matcher for removal
|
|
7723
|
-
updatedAt: serverTimestamp14()
|
|
7724
|
-
// Potentially update clinic.doctors/doctorsInfo if this was the last active procedure for this doctor at this clinic
|
|
7725
|
-
});
|
|
7726
|
-
await batch.commit();
|
|
7727
7191
|
}
|
|
7728
7192
|
/**
|
|
7729
|
-
* Deletes a procedure permanently
|
|
7193
|
+
* Deletes a procedure permanently
|
|
7730
7194
|
* @param id - The ID of the procedure to delete
|
|
7731
7195
|
* @returns A boolean indicating if the deletion was successful
|
|
7732
7196
|
*/
|
|
@@ -7736,37 +7200,7 @@ var ProcedureService = class extends BaseService {
|
|
|
7736
7200
|
if (!procedureSnapshot.exists()) {
|
|
7737
7201
|
return false;
|
|
7738
7202
|
}
|
|
7739
|
-
|
|
7740
|
-
const batch = writeBatch6(this.db);
|
|
7741
|
-
if (procedure.practitionerId) {
|
|
7742
|
-
const practitionerRef = doc13(
|
|
7743
|
-
this.db,
|
|
7744
|
-
PRACTITIONERS_COLLECTION,
|
|
7745
|
-
procedure.practitionerId
|
|
7746
|
-
);
|
|
7747
|
-
batch.update(practitionerRef, {
|
|
7748
|
-
procedures: arrayRemove6(id),
|
|
7749
|
-
proceduresInfo: arrayRemove6(...[{ id }]),
|
|
7750
|
-
// Matcher for removal
|
|
7751
|
-
updatedAt: serverTimestamp14()
|
|
7752
|
-
});
|
|
7753
|
-
}
|
|
7754
|
-
if (procedure.clinicBranchId) {
|
|
7755
|
-
const clinicRef = doc13(
|
|
7756
|
-
this.db,
|
|
7757
|
-
CLINICS_COLLECTION,
|
|
7758
|
-
procedure.clinicBranchId
|
|
7759
|
-
);
|
|
7760
|
-
batch.update(clinicRef, {
|
|
7761
|
-
// services: arrayRemove(id),
|
|
7762
|
-
proceduresInfo: arrayRemove6(...[{ id }]),
|
|
7763
|
-
// Matcher for removal
|
|
7764
|
-
updatedAt: serverTimestamp14()
|
|
7765
|
-
// Potentially update clinic.doctors/doctorsInfo
|
|
7766
|
-
});
|
|
7767
|
-
}
|
|
7768
|
-
batch.delete(procedureRef);
|
|
7769
|
-
await batch.commit();
|
|
7203
|
+
await deleteDoc8(procedureRef);
|
|
7770
7204
|
return true;
|
|
7771
7205
|
}
|
|
7772
7206
|
/**
|
|
@@ -7795,20 +7229,20 @@ var ProcedureService = class extends BaseService {
|
|
|
7795
7229
|
const proceduresCollection = collection13(this.db, PROCEDURES_COLLECTION);
|
|
7796
7230
|
let proceduresQuery = query13(proceduresCollection);
|
|
7797
7231
|
if (pagination && pagination > 0) {
|
|
7798
|
-
const { limit:
|
|
7232
|
+
const { limit: limit8, startAfter: startAfter8 } = await import("firebase/firestore");
|
|
7799
7233
|
if (lastDoc) {
|
|
7800
7234
|
proceduresQuery = query13(
|
|
7801
7235
|
proceduresCollection,
|
|
7802
7236
|
orderBy4("name"),
|
|
7803
7237
|
// Use imported orderBy
|
|
7804
|
-
|
|
7805
|
-
|
|
7238
|
+
startAfter8(lastDoc),
|
|
7239
|
+
limit8(pagination)
|
|
7806
7240
|
);
|
|
7807
7241
|
} else {
|
|
7808
7242
|
proceduresQuery = query13(
|
|
7809
7243
|
proceduresCollection,
|
|
7810
7244
|
orderBy4("name"),
|
|
7811
|
-
|
|
7245
|
+
limit8(pagination)
|
|
7812
7246
|
);
|
|
7813
7247
|
}
|
|
7814
7248
|
} else {
|
|
@@ -7833,6 +7267,203 @@ var ProcedureService = class extends BaseService {
|
|
|
7833
7267
|
throw error;
|
|
7834
7268
|
}
|
|
7835
7269
|
}
|
|
7270
|
+
/**
|
|
7271
|
+
* Searches and filters procedures based on multiple criteria
|
|
7272
|
+
*
|
|
7273
|
+
* @param filters - Various filters to apply
|
|
7274
|
+
* @param filters.nameSearch - Optional search text for procedure name
|
|
7275
|
+
* @param filters.treatmentBenefits - Optional array of treatment benefits to filter by
|
|
7276
|
+
* @param filters.procedureFamily - Optional procedure family to filter by
|
|
7277
|
+
* @param filters.procedureCategory - Optional procedure category to filter by
|
|
7278
|
+
* @param filters.procedureSubcategory - Optional procedure subcategory to filter by
|
|
7279
|
+
* @param filters.procedureTechnology - Optional procedure technology to filter by
|
|
7280
|
+
* @param filters.location - Optional location for distance-based search
|
|
7281
|
+
* @param filters.radiusInKm - Optional radius in kilometers (required if location is provided)
|
|
7282
|
+
* @param filters.minPrice - Optional minimum price
|
|
7283
|
+
* @param filters.maxPrice - Optional maximum price
|
|
7284
|
+
* @param filters.minRating - Optional minimum rating (0-5)
|
|
7285
|
+
* @param filters.maxRating - Optional maximum rating (0-5)
|
|
7286
|
+
* @param filters.pagination - Optional number of results per page
|
|
7287
|
+
* @param filters.lastDoc - Optional last document for pagination
|
|
7288
|
+
* @param filters.isActive - Optional filter for active procedures only
|
|
7289
|
+
* @returns Filtered procedures and the last document for pagination
|
|
7290
|
+
*/
|
|
7291
|
+
async getProceduresByFilters(filters) {
|
|
7292
|
+
try {
|
|
7293
|
+
console.log(
|
|
7294
|
+
"[PROCEDURE_SERVICE] Starting procedure filtering with criteria:",
|
|
7295
|
+
filters
|
|
7296
|
+
);
|
|
7297
|
+
const isGeoQuery = filters.location && filters.radiusInKm && filters.radiusInKm > 0;
|
|
7298
|
+
const constraints = [];
|
|
7299
|
+
if (filters.isActive !== void 0) {
|
|
7300
|
+
constraints.push(where13("isActive", "==", filters.isActive));
|
|
7301
|
+
} else {
|
|
7302
|
+
constraints.push(where13("isActive", "==", true));
|
|
7303
|
+
}
|
|
7304
|
+
if (filters.procedureFamily) {
|
|
7305
|
+
constraints.push(where13("family", "==", filters.procedureFamily));
|
|
7306
|
+
}
|
|
7307
|
+
constraints.push(orderBy4(documentId2()));
|
|
7308
|
+
if (filters.pagination && filters.pagination > 0 && filters.lastDoc) {
|
|
7309
|
+
constraints.push(startAfter5(filters.lastDoc));
|
|
7310
|
+
constraints.push(limit5(filters.pagination));
|
|
7311
|
+
} else if (filters.pagination && filters.pagination > 0) {
|
|
7312
|
+
constraints.push(limit5(filters.pagination));
|
|
7313
|
+
}
|
|
7314
|
+
let proceduresResult = [];
|
|
7315
|
+
let lastVisibleDoc = null;
|
|
7316
|
+
if (isGeoQuery) {
|
|
7317
|
+
const center = filters.location;
|
|
7318
|
+
const radiusInKm = filters.radiusInKm;
|
|
7319
|
+
const bounds = geohashQueryBounds5(
|
|
7320
|
+
[center.latitude, center.longitude],
|
|
7321
|
+
radiusInKm * 1e3
|
|
7322
|
+
// Convert to meters
|
|
7323
|
+
);
|
|
7324
|
+
const matchingProcedures = [];
|
|
7325
|
+
for (const bound of bounds) {
|
|
7326
|
+
const geoConstraints = [
|
|
7327
|
+
...constraints,
|
|
7328
|
+
where13("clinicInfo.location.geohash", ">=", bound[0]),
|
|
7329
|
+
where13("clinicInfo.location.geohash", "<=", bound[1])
|
|
7330
|
+
];
|
|
7331
|
+
const q = query13(
|
|
7332
|
+
collection13(this.db, PROCEDURES_COLLECTION),
|
|
7333
|
+
...geoConstraints
|
|
7334
|
+
);
|
|
7335
|
+
const querySnapshot = await getDocs13(q);
|
|
7336
|
+
console.log(
|
|
7337
|
+
`[PROCEDURE_SERVICE] Found ${querySnapshot.docs.length} procedures in geo bound`
|
|
7338
|
+
);
|
|
7339
|
+
for (const doc28 of querySnapshot.docs) {
|
|
7340
|
+
const procedure = { ...doc28.data(), id: doc28.id };
|
|
7341
|
+
const distance = distanceBetween6(
|
|
7342
|
+
[center.latitude, center.longitude],
|
|
7343
|
+
[
|
|
7344
|
+
procedure.clinicInfo.location.latitude,
|
|
7345
|
+
procedure.clinicInfo.location.longitude
|
|
7346
|
+
]
|
|
7347
|
+
);
|
|
7348
|
+
const distanceInKm = distance / 1e3;
|
|
7349
|
+
if (distanceInKm <= radiusInKm) {
|
|
7350
|
+
matchingProcedures.push({
|
|
7351
|
+
...procedure,
|
|
7352
|
+
distance: distanceInKm
|
|
7353
|
+
});
|
|
7354
|
+
}
|
|
7355
|
+
}
|
|
7356
|
+
}
|
|
7357
|
+
let filteredProcedures = matchingProcedures;
|
|
7358
|
+
filteredProcedures = this.applyInMemoryFilters(
|
|
7359
|
+
filteredProcedures,
|
|
7360
|
+
filters
|
|
7361
|
+
);
|
|
7362
|
+
filteredProcedures.sort((a, b) => a.distance - b.distance);
|
|
7363
|
+
if (filters.pagination && filters.pagination > 0) {
|
|
7364
|
+
let startIndex = 0;
|
|
7365
|
+
if (filters.lastDoc) {
|
|
7366
|
+
const lastDocIndex = filteredProcedures.findIndex(
|
|
7367
|
+
(procedure) => procedure.id === filters.lastDoc.id
|
|
7368
|
+
);
|
|
7369
|
+
if (lastDocIndex !== -1) {
|
|
7370
|
+
startIndex = lastDocIndex + 1;
|
|
7371
|
+
}
|
|
7372
|
+
}
|
|
7373
|
+
const paginatedProcedures = filteredProcedures.slice(
|
|
7374
|
+
startIndex,
|
|
7375
|
+
startIndex + filters.pagination
|
|
7376
|
+
);
|
|
7377
|
+
lastVisibleDoc = paginatedProcedures.length > 0 ? paginatedProcedures[paginatedProcedures.length - 1] : null;
|
|
7378
|
+
proceduresResult = paginatedProcedures;
|
|
7379
|
+
} else {
|
|
7380
|
+
proceduresResult = filteredProcedures;
|
|
7381
|
+
}
|
|
7382
|
+
} else {
|
|
7383
|
+
const q = query13(
|
|
7384
|
+
collection13(this.db, PROCEDURES_COLLECTION),
|
|
7385
|
+
...constraints
|
|
7386
|
+
);
|
|
7387
|
+
const querySnapshot = await getDocs13(q);
|
|
7388
|
+
console.log(
|
|
7389
|
+
`[PROCEDURE_SERVICE] Found ${querySnapshot.docs.length} procedures with regular query`
|
|
7390
|
+
);
|
|
7391
|
+
const procedures = querySnapshot.docs.map((doc28) => {
|
|
7392
|
+
return { ...doc28.data(), id: doc28.id };
|
|
7393
|
+
});
|
|
7394
|
+
let filteredProcedures = this.applyInMemoryFilters(procedures, filters);
|
|
7395
|
+
lastVisibleDoc = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
|
|
7396
|
+
proceduresResult = filteredProcedures;
|
|
7397
|
+
}
|
|
7398
|
+
return {
|
|
7399
|
+
procedures: proceduresResult,
|
|
7400
|
+
lastDoc: lastVisibleDoc
|
|
7401
|
+
};
|
|
7402
|
+
} catch (error) {
|
|
7403
|
+
console.error("[PROCEDURE_SERVICE] Error filtering procedures:", error);
|
|
7404
|
+
throw error;
|
|
7405
|
+
}
|
|
7406
|
+
}
|
|
7407
|
+
/**
|
|
7408
|
+
* Helper method to apply in-memory filters to procedures
|
|
7409
|
+
* Used by getProceduresByFilters to apply filters that can't be done in Firestore queries
|
|
7410
|
+
*
|
|
7411
|
+
* @param procedures - The procedures to filter
|
|
7412
|
+
* @param filters - The filters to apply
|
|
7413
|
+
* @returns Filtered procedures
|
|
7414
|
+
*/
|
|
7415
|
+
applyInMemoryFilters(procedures, filters) {
|
|
7416
|
+
let filteredProcedures = procedures;
|
|
7417
|
+
if (filters.nameSearch && filters.nameSearch.trim() !== "") {
|
|
7418
|
+
const searchTerm = filters.nameSearch.toLowerCase().trim();
|
|
7419
|
+
filteredProcedures = filteredProcedures.filter((procedure) => {
|
|
7420
|
+
return procedure.name.toLowerCase().includes(searchTerm);
|
|
7421
|
+
});
|
|
7422
|
+
}
|
|
7423
|
+
if (filters.treatmentBenefits && filters.treatmentBenefits.length > 0) {
|
|
7424
|
+
filteredProcedures = filteredProcedures.filter((procedure) => {
|
|
7425
|
+
return filters.treatmentBenefits.every(
|
|
7426
|
+
(benefit) => procedure.treatmentBenefits.includes(benefit)
|
|
7427
|
+
);
|
|
7428
|
+
});
|
|
7429
|
+
}
|
|
7430
|
+
if (filters.procedureCategory) {
|
|
7431
|
+
filteredProcedures = filteredProcedures.filter(
|
|
7432
|
+
(procedure) => procedure.category.id === filters.procedureCategory
|
|
7433
|
+
);
|
|
7434
|
+
}
|
|
7435
|
+
if (filters.procedureSubcategory) {
|
|
7436
|
+
filteredProcedures = filteredProcedures.filter(
|
|
7437
|
+
(procedure) => procedure.subcategory.id === filters.procedureSubcategory
|
|
7438
|
+
);
|
|
7439
|
+
}
|
|
7440
|
+
if (filters.procedureTechnology) {
|
|
7441
|
+
filteredProcedures = filteredProcedures.filter(
|
|
7442
|
+
(procedure) => procedure.technology.id === filters.procedureTechnology
|
|
7443
|
+
);
|
|
7444
|
+
}
|
|
7445
|
+
if (filters.minPrice !== void 0) {
|
|
7446
|
+
filteredProcedures = filteredProcedures.filter(
|
|
7447
|
+
(procedure) => procedure.price >= filters.minPrice
|
|
7448
|
+
);
|
|
7449
|
+
}
|
|
7450
|
+
if (filters.maxPrice !== void 0) {
|
|
7451
|
+
filteredProcedures = filteredProcedures.filter(
|
|
7452
|
+
(procedure) => procedure.price <= filters.maxPrice
|
|
7453
|
+
);
|
|
7454
|
+
}
|
|
7455
|
+
if (filters.minRating !== void 0) {
|
|
7456
|
+
filteredProcedures = filteredProcedures.filter(
|
|
7457
|
+
(procedure) => procedure.reviewInfo.averageRating >= filters.minRating
|
|
7458
|
+
);
|
|
7459
|
+
}
|
|
7460
|
+
if (filters.maxRating !== void 0) {
|
|
7461
|
+
filteredProcedures = filteredProcedures.filter(
|
|
7462
|
+
(procedure) => procedure.reviewInfo.averageRating <= filters.maxRating
|
|
7463
|
+
);
|
|
7464
|
+
}
|
|
7465
|
+
return filteredProcedures;
|
|
7466
|
+
}
|
|
7836
7467
|
};
|
|
7837
7468
|
|
|
7838
7469
|
// src/services/documentation-templates/documentation-template.service.ts
|
|
@@ -7847,8 +7478,8 @@ import {
|
|
|
7847
7478
|
query as query14,
|
|
7848
7479
|
where as where14,
|
|
7849
7480
|
orderBy as orderBy5,
|
|
7850
|
-
limit as
|
|
7851
|
-
startAfter as
|
|
7481
|
+
limit as limit6,
|
|
7482
|
+
startAfter as startAfter6
|
|
7852
7483
|
} from "firebase/firestore";
|
|
7853
7484
|
var DocumentationTemplateService = class extends BaseService {
|
|
7854
7485
|
constructor() {
|
|
@@ -7952,10 +7583,10 @@ var DocumentationTemplateService = class extends BaseService {
|
|
|
7952
7583
|
this.collectionRef,
|
|
7953
7584
|
where14("isActive", "==", true),
|
|
7954
7585
|
orderBy5("updatedAt", "desc"),
|
|
7955
|
-
|
|
7586
|
+
limit6(pageSize)
|
|
7956
7587
|
);
|
|
7957
7588
|
if (lastDoc) {
|
|
7958
|
-
q = query14(q,
|
|
7589
|
+
q = query14(q, startAfter6(lastDoc));
|
|
7959
7590
|
}
|
|
7960
7591
|
const querySnapshot = await getDocs14(q);
|
|
7961
7592
|
const templates = [];
|
|
@@ -7982,10 +7613,10 @@ var DocumentationTemplateService = class extends BaseService {
|
|
|
7982
7613
|
where14("isActive", "==", true),
|
|
7983
7614
|
where14("tags", "array-contains-any", tags),
|
|
7984
7615
|
orderBy5("updatedAt", "desc"),
|
|
7985
|
-
|
|
7616
|
+
limit6(pageSize)
|
|
7986
7617
|
);
|
|
7987
7618
|
if (lastDoc) {
|
|
7988
|
-
q = query14(q,
|
|
7619
|
+
q = query14(q, startAfter6(lastDoc));
|
|
7989
7620
|
}
|
|
7990
7621
|
const querySnapshot = await getDocs14(q);
|
|
7991
7622
|
const templates = [];
|
|
@@ -8011,10 +7642,10 @@ var DocumentationTemplateService = class extends BaseService {
|
|
|
8011
7642
|
this.collectionRef,
|
|
8012
7643
|
where14("createdBy", "==", userId),
|
|
8013
7644
|
orderBy5("updatedAt", "desc"),
|
|
8014
|
-
|
|
7645
|
+
limit6(pageSize)
|
|
8015
7646
|
);
|
|
8016
7647
|
if (lastDoc) {
|
|
8017
|
-
q = query14(q,
|
|
7648
|
+
q = query14(q, startAfter6(lastDoc));
|
|
8018
7649
|
}
|
|
8019
7650
|
const querySnapshot = await getDocs14(q);
|
|
8020
7651
|
const templates = [];
|
|
@@ -8041,8 +7672,8 @@ import {
|
|
|
8041
7672
|
query as query15,
|
|
8042
7673
|
where as where15,
|
|
8043
7674
|
orderBy as orderBy6,
|
|
8044
|
-
limit as
|
|
8045
|
-
startAfter as
|
|
7675
|
+
limit as limit7,
|
|
7676
|
+
startAfter as startAfter7
|
|
8046
7677
|
} from "firebase/firestore";
|
|
8047
7678
|
var FilledDocumentService = class extends BaseService {
|
|
8048
7679
|
constructor(...args) {
|
|
@@ -8066,10 +7697,10 @@ var FilledDocumentService = class extends BaseService {
|
|
|
8066
7697
|
if (!template) {
|
|
8067
7698
|
throw new Error(`Template with ID ${templateId} not found`);
|
|
8068
7699
|
}
|
|
8069
|
-
const
|
|
7700
|
+
const documentId3 = this.generateId();
|
|
8070
7701
|
const now = Date.now();
|
|
8071
7702
|
const filledDocument = {
|
|
8072
|
-
id:
|
|
7703
|
+
id: documentId3,
|
|
8073
7704
|
templateId,
|
|
8074
7705
|
templateVersion: template.version,
|
|
8075
7706
|
patientId,
|
|
@@ -8080,7 +7711,7 @@ var FilledDocumentService = class extends BaseService {
|
|
|
8080
7711
|
values: {},
|
|
8081
7712
|
status: "draft" /* DRAFT */
|
|
8082
7713
|
};
|
|
8083
|
-
const docRef = doc15(this.collectionRef,
|
|
7714
|
+
const docRef = doc15(this.collectionRef, documentId3);
|
|
8084
7715
|
await setDoc15(docRef, filledDocument);
|
|
8085
7716
|
return filledDocument;
|
|
8086
7717
|
}
|
|
@@ -8089,8 +7720,8 @@ var FilledDocumentService = class extends BaseService {
|
|
|
8089
7720
|
* @param documentId - ID of the filled document to retrieve
|
|
8090
7721
|
* @returns The filled document or null if not found
|
|
8091
7722
|
*/
|
|
8092
|
-
async getFilledDocumentById(
|
|
8093
|
-
const docRef = doc15(this.collectionRef,
|
|
7723
|
+
async getFilledDocumentById(documentId3) {
|
|
7724
|
+
const docRef = doc15(this.collectionRef, documentId3);
|
|
8094
7725
|
const docSnap = await getDoc18(docRef);
|
|
8095
7726
|
if (!docSnap.exists()) {
|
|
8096
7727
|
return null;
|
|
@@ -8104,10 +7735,10 @@ var FilledDocumentService = class extends BaseService {
|
|
|
8104
7735
|
* @param status - Optional new status for the document
|
|
8105
7736
|
* @returns The updated filled document
|
|
8106
7737
|
*/
|
|
8107
|
-
async updateFilledDocument(
|
|
8108
|
-
const filledDocument = await this.getFilledDocumentById(
|
|
7738
|
+
async updateFilledDocument(documentId3, values, status) {
|
|
7739
|
+
const filledDocument = await this.getFilledDocumentById(documentId3);
|
|
8109
7740
|
if (!filledDocument) {
|
|
8110
|
-
throw new Error(`Filled document with ID ${
|
|
7741
|
+
throw new Error(`Filled document with ID ${documentId3} not found`);
|
|
8111
7742
|
}
|
|
8112
7743
|
const updateData = {
|
|
8113
7744
|
values: {
|
|
@@ -8119,7 +7750,7 @@ var FilledDocumentService = class extends BaseService {
|
|
|
8119
7750
|
if (status) {
|
|
8120
7751
|
updateData.status = status;
|
|
8121
7752
|
}
|
|
8122
|
-
const docRef = doc15(this.collectionRef,
|
|
7753
|
+
const docRef = doc15(this.collectionRef, documentId3);
|
|
8123
7754
|
await updateDoc17(docRef, updateData);
|
|
8124
7755
|
return {
|
|
8125
7756
|
...filledDocument,
|
|
@@ -8138,10 +7769,10 @@ var FilledDocumentService = class extends BaseService {
|
|
|
8138
7769
|
this.collectionRef,
|
|
8139
7770
|
where15("patientId", "==", patientId),
|
|
8140
7771
|
orderBy6("updatedAt", "desc"),
|
|
8141
|
-
|
|
7772
|
+
limit7(pageSize)
|
|
8142
7773
|
);
|
|
8143
7774
|
if (lastDoc) {
|
|
8144
|
-
q = query15(q,
|
|
7775
|
+
q = query15(q, startAfter7(lastDoc));
|
|
8145
7776
|
}
|
|
8146
7777
|
const querySnapshot = await getDocs15(q);
|
|
8147
7778
|
const documents = [];
|
|
@@ -8167,10 +7798,10 @@ var FilledDocumentService = class extends BaseService {
|
|
|
8167
7798
|
this.collectionRef,
|
|
8168
7799
|
where15("practitionerId", "==", practitionerId),
|
|
8169
7800
|
orderBy6("updatedAt", "desc"),
|
|
8170
|
-
|
|
7801
|
+
limit7(pageSize)
|
|
8171
7802
|
);
|
|
8172
7803
|
if (lastDoc) {
|
|
8173
|
-
q = query15(q,
|
|
7804
|
+
q = query15(q, startAfter7(lastDoc));
|
|
8174
7805
|
}
|
|
8175
7806
|
const querySnapshot = await getDocs15(q);
|
|
8176
7807
|
const documents = [];
|
|
@@ -8196,10 +7827,10 @@ var FilledDocumentService = class extends BaseService {
|
|
|
8196
7827
|
this.collectionRef,
|
|
8197
7828
|
where15("clinicId", "==", clinicId),
|
|
8198
7829
|
orderBy6("updatedAt", "desc"),
|
|
8199
|
-
|
|
7830
|
+
limit7(pageSize)
|
|
8200
7831
|
);
|
|
8201
7832
|
if (lastDoc) {
|
|
8202
|
-
q = query15(q,
|
|
7833
|
+
q = query15(q, startAfter7(lastDoc));
|
|
8203
7834
|
}
|
|
8204
7835
|
const querySnapshot = await getDocs15(q);
|
|
8205
7836
|
const documents = [];
|
|
@@ -8225,10 +7856,10 @@ var FilledDocumentService = class extends BaseService {
|
|
|
8225
7856
|
this.collectionRef,
|
|
8226
7857
|
where15("templateId", "==", templateId),
|
|
8227
7858
|
orderBy6("updatedAt", "desc"),
|
|
8228
|
-
|
|
7859
|
+
limit7(pageSize)
|
|
8229
7860
|
);
|
|
8230
7861
|
if (lastDoc) {
|
|
8231
|
-
q = query15(q,
|
|
7862
|
+
q = query15(q, startAfter7(lastDoc));
|
|
8232
7863
|
}
|
|
8233
7864
|
const querySnapshot = await getDocs15(q);
|
|
8234
7865
|
const documents = [];
|
|
@@ -8254,10 +7885,10 @@ var FilledDocumentService = class extends BaseService {
|
|
|
8254
7885
|
this.collectionRef,
|
|
8255
7886
|
where15("status", "==", status),
|
|
8256
7887
|
orderBy6("updatedAt", "desc"),
|
|
8257
|
-
|
|
7888
|
+
limit7(pageSize)
|
|
8258
7889
|
);
|
|
8259
7890
|
if (lastDoc) {
|
|
8260
|
-
q = query15(q,
|
|
7891
|
+
q = query15(q, startAfter7(lastDoc));
|
|
8261
7892
|
}
|
|
8262
7893
|
const querySnapshot = await getDocs15(q);
|
|
8263
7894
|
const documents = [];
|
|
@@ -8706,37 +8337,19 @@ async function createAppointmentUtil(db, clinicId, practitionerId, patientId, ev
|
|
|
8706
8337
|
() => eventId
|
|
8707
8338
|
// Use the same ID for all calendars
|
|
8708
8339
|
);
|
|
8709
|
-
const [clinicEvent] = await Promise.all([
|
|
8710
|
-
clinicPromise,
|
|
8711
|
-
practitionerPromise,
|
|
8712
|
-
patientPromise
|
|
8713
|
-
]);
|
|
8340
|
+
const [clinicEvent] = await Promise.all([clinicPromise, practitionerPromise, patientPromise]);
|
|
8714
8341
|
return clinicEvent;
|
|
8715
8342
|
}
|
|
8716
8343
|
async function updateAppointmentUtil(db, clinicId, practitionerId, patientId, eventId, updateData) {
|
|
8717
|
-
const clinicPromise = updateClinicCalendarEventUtil(
|
|
8718
|
-
db,
|
|
8719
|
-
clinicId,
|
|
8720
|
-
eventId,
|
|
8721
|
-
updateData
|
|
8722
|
-
);
|
|
8344
|
+
const clinicPromise = updateClinicCalendarEventUtil(db, clinicId, eventId, updateData);
|
|
8723
8345
|
const practitionerPromise = updatePractitionerCalendarEventUtil(
|
|
8724
8346
|
db,
|
|
8725
8347
|
practitionerId,
|
|
8726
8348
|
eventId,
|
|
8727
8349
|
updateData
|
|
8728
8350
|
);
|
|
8729
|
-
const patientPromise = updatePatientCalendarEventUtil(
|
|
8730
|
-
|
|
8731
|
-
patientId,
|
|
8732
|
-
eventId,
|
|
8733
|
-
updateData
|
|
8734
|
-
);
|
|
8735
|
-
const [clinicEvent] = await Promise.all([
|
|
8736
|
-
clinicPromise,
|
|
8737
|
-
practitionerPromise,
|
|
8738
|
-
patientPromise
|
|
8739
|
-
]);
|
|
8351
|
+
const patientPromise = updatePatientCalendarEventUtil(db, patientId, eventId, updateData);
|
|
8352
|
+
const [clinicEvent] = await Promise.all([clinicPromise, practitionerPromise, patientPromise]);
|
|
8740
8353
|
return clinicEvent;
|
|
8741
8354
|
}
|
|
8742
8355
|
|