@blackcode_sa/metaestetics-api 1.4.7 → 1.4.9
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/index.d.mts +16 -16
- package/dist/index.d.ts +16 -16
- package/dist/index.js +768 -188
- package/dist/index.mjs +787 -200
- package/package.json +1 -1
- package/src/services/auth.service.ts +52 -8
- package/src/services/clinic/clinic-group.service.ts +63 -9
- package/src/services/clinic/clinic.service.ts +32 -9
- package/src/services/clinic/utils/admin.utils.ts +6 -51
- package/src/services/clinic/utils/clinic-group.utils.ts +195 -52
- package/src/services/clinic/utils/clinic.utils.ts +482 -39
- package/src/services/clinic/utils/photos.utils.ts +188 -0
- package/src/services/clinic/utils/review.utils.ts +24 -17
- package/src/services/clinic/utils/tag.utils.ts +33 -8
- package/src/types/clinic/index.ts +5 -5
- package/src/validations/clinic.schema.ts +3 -3
package/dist/index.js
CHANGED
|
@@ -2447,7 +2447,7 @@ var clinicGroupSchema = import_zod9.z.object({
|
|
|
2447
2447
|
admins: import_zod9.z.array(import_zod9.z.string()),
|
|
2448
2448
|
adminsInfo: import_zod9.z.array(adminInfoSchema),
|
|
2449
2449
|
adminTokens: import_zod9.z.array(adminTokenSchema),
|
|
2450
|
-
ownerId: import_zod9.z.string(),
|
|
2450
|
+
ownerId: import_zod9.z.string().nullable(),
|
|
2451
2451
|
createdAt: import_zod9.z.instanceof(Date).or(import_zod9.z.instanceof(import_firestore10.Timestamp)),
|
|
2452
2452
|
// Timestamp
|
|
2453
2453
|
updatedAt: import_zod9.z.instanceof(Date).or(import_zod9.z.instanceof(import_firestore10.Timestamp)),
|
|
@@ -2523,7 +2523,7 @@ var createClinicGroupSchema = import_zod9.z.object({
|
|
|
2523
2523
|
hqLocation: clinicLocationSchema,
|
|
2524
2524
|
contactInfo: clinicContactInfoSchema,
|
|
2525
2525
|
contactPerson: contactPersonSchema,
|
|
2526
|
-
ownerId: import_zod9.z.string(),
|
|
2526
|
+
ownerId: import_zod9.z.string().nullable(),
|
|
2527
2527
|
isActive: import_zod9.z.boolean(),
|
|
2528
2528
|
logo: import_zod9.z.string().optional().nullable(),
|
|
2529
2529
|
practiceType: import_zod9.z.nativeEnum(PracticeType).optional(),
|
|
@@ -2557,7 +2557,7 @@ var createClinicSchema = import_zod9.z.object({
|
|
|
2557
2557
|
});
|
|
2558
2558
|
var createDefaultClinicGroupSchema = import_zod9.z.object({
|
|
2559
2559
|
name: import_zod9.z.string(),
|
|
2560
|
-
ownerId: import_zod9.z.string(),
|
|
2560
|
+
ownerId: import_zod9.z.string().nullable(),
|
|
2561
2561
|
contactPerson: contactPersonSchema,
|
|
2562
2562
|
contactInfo: clinicContactInfoSchema,
|
|
2563
2563
|
hqLocation: clinicLocationSchema,
|
|
@@ -2655,45 +2655,7 @@ async function createClinicAdmin(db, data, clinicGroupService) {
|
|
|
2655
2655
|
hasGroupId: !!clinicGroupId
|
|
2656
2656
|
});
|
|
2657
2657
|
if (validatedData.isGroupOwner && !clinicGroupId) {
|
|
2658
|
-
console.log("[CLINIC_ADMIN]
|
|
2659
|
-
const defaultGroup = {
|
|
2660
|
-
name: `${validatedData.contactInfo.firstName}'s Group`,
|
|
2661
|
-
ownerId: validatedData.userRef,
|
|
2662
|
-
contactPerson: validatedData.contactInfo,
|
|
2663
|
-
contactInfo: {
|
|
2664
|
-
email: validatedData.contactInfo.email,
|
|
2665
|
-
phoneNumber: validatedData.contactInfo.phoneNumber || ""
|
|
2666
|
-
},
|
|
2667
|
-
hqLocation: {
|
|
2668
|
-
address: "",
|
|
2669
|
-
city: "",
|
|
2670
|
-
country: "",
|
|
2671
|
-
postalCode: "",
|
|
2672
|
-
latitude: 0,
|
|
2673
|
-
longitude: 0
|
|
2674
|
-
},
|
|
2675
|
-
isActive: true
|
|
2676
|
-
};
|
|
2677
|
-
console.log("[CLINIC_ADMIN] Default group data prepared", {
|
|
2678
|
-
groupName: defaultGroup.name
|
|
2679
|
-
});
|
|
2680
|
-
try {
|
|
2681
|
-
const clinicGroup = await clinicGroupService.createClinicGroup(
|
|
2682
|
-
defaultGroup,
|
|
2683
|
-
validatedData.userRef,
|
|
2684
|
-
true
|
|
2685
|
-
);
|
|
2686
|
-
clinicGroupId = clinicGroup.id;
|
|
2687
|
-
console.log("[CLINIC_ADMIN] Default group created successfully", {
|
|
2688
|
-
groupId: clinicGroupId
|
|
2689
|
-
});
|
|
2690
|
-
} catch (groupCreationError) {
|
|
2691
|
-
console.error(
|
|
2692
|
-
"[CLINIC_ADMIN] Error creating default group:",
|
|
2693
|
-
groupCreationError
|
|
2694
|
-
);
|
|
2695
|
-
throw groupCreationError;
|
|
2696
|
-
}
|
|
2658
|
+
console.log("[CLINIC_ADMIN] Owner will be assigned to group later");
|
|
2697
2659
|
} else if (!validatedData.isGroupOwner && !clinicGroupId) {
|
|
2698
2660
|
console.error("[CLINIC_ADMIN] Missing clinic group ID for non-owner admin");
|
|
2699
2661
|
throw new Error("Clinic group ID is required for non-owner admins");
|
|
@@ -2723,16 +2685,12 @@ async function createClinicAdmin(db, data, clinicGroupService) {
|
|
|
2723
2685
|
}
|
|
2724
2686
|
}
|
|
2725
2687
|
console.log("[CLINIC_ADMIN] Preparing admin data object");
|
|
2726
|
-
if (!clinicGroupId) {
|
|
2727
|
-
console.error(
|
|
2728
|
-
"[CLINIC_ADMIN] clinicGroupId is undefined, which should not happen at this point"
|
|
2729
|
-
);
|
|
2730
|
-
throw new Error("clinicGroupId is required but was undefined");
|
|
2731
|
-
}
|
|
2732
2688
|
const adminData = {
|
|
2733
|
-
id:
|
|
2689
|
+
id: (0, import_firestore11.doc)((0, import_firestore11.collection)(db, CLINIC_ADMINS_COLLECTION)).id,
|
|
2690
|
+
// Generate a new ID for the admin document
|
|
2734
2691
|
userRef: validatedData.userRef,
|
|
2735
|
-
clinicGroupId,
|
|
2692
|
+
clinicGroupId: clinicGroupId || "",
|
|
2693
|
+
// Empty string for now if no group ID
|
|
2736
2694
|
isGroupOwner: validatedData.isGroupOwner,
|
|
2737
2695
|
clinicsManaged: [],
|
|
2738
2696
|
// Uvek krećemo od prazne liste
|
|
@@ -3756,6 +3714,59 @@ var UserService = class extends BaseService {
|
|
|
3756
3714
|
var import_firestore15 = require("firebase/firestore");
|
|
3757
3715
|
var import_geofire_common2 = require("geofire-common");
|
|
3758
3716
|
var import_zod13 = require("zod");
|
|
3717
|
+
|
|
3718
|
+
// src/services/clinic/utils/photos.utils.ts
|
|
3719
|
+
var import_storage3 = require("firebase/storage");
|
|
3720
|
+
async function uploadPhoto(photo, entityType, entityId, photoType, app, fileName) {
|
|
3721
|
+
if (!photo || typeof photo !== "string" || !photo.startsWith("data:")) {
|
|
3722
|
+
return photo;
|
|
3723
|
+
}
|
|
3724
|
+
try {
|
|
3725
|
+
console.log(
|
|
3726
|
+
`[PHOTO_UTILS] Uploading ${photoType} for ${entityType}/${entityId}`
|
|
3727
|
+
);
|
|
3728
|
+
const storage = (0, import_storage3.getStorage)(app);
|
|
3729
|
+
const storageFileName = fileName || `${photoType}-${Date.now()}`;
|
|
3730
|
+
const storageRef = (0, import_storage3.ref)(
|
|
3731
|
+
storage,
|
|
3732
|
+
`${entityType}/${entityId}/${storageFileName}`
|
|
3733
|
+
);
|
|
3734
|
+
const base64Data = photo.split(",")[1];
|
|
3735
|
+
const contentType = photo.split(";")[0].split(":")[1];
|
|
3736
|
+
const byteCharacters = atob(base64Data);
|
|
3737
|
+
const byteArrays = [];
|
|
3738
|
+
for (let i = 0; i < byteCharacters.length; i++) {
|
|
3739
|
+
byteArrays.push(byteCharacters.charCodeAt(i));
|
|
3740
|
+
}
|
|
3741
|
+
const blob = new Blob([new Uint8Array(byteArrays)], { type: contentType });
|
|
3742
|
+
await (0, import_storage3.uploadBytes)(storageRef, blob, { contentType });
|
|
3743
|
+
const downloadUrl = await (0, import_storage3.getDownloadURL)(storageRef);
|
|
3744
|
+
console.log(`[PHOTO_UTILS] ${photoType} uploaded successfully`, {
|
|
3745
|
+
downloadUrl
|
|
3746
|
+
});
|
|
3747
|
+
return downloadUrl;
|
|
3748
|
+
} catch (error) {
|
|
3749
|
+
console.error(`[PHOTO_UTILS] Error uploading ${photoType}:`, error);
|
|
3750
|
+
return null;
|
|
3751
|
+
}
|
|
3752
|
+
}
|
|
3753
|
+
async function uploadMultiplePhotos(photos, entityType, entityId, photoType, app) {
|
|
3754
|
+
if (!photos || !Array.isArray(photos) || photos.length === 0) {
|
|
3755
|
+
return [];
|
|
3756
|
+
}
|
|
3757
|
+
const uploadPromises = photos.map(
|
|
3758
|
+
(photo, index) => uploadPhoto(photo, entityType, entityId, `${photoType}-${index}`, app)
|
|
3759
|
+
);
|
|
3760
|
+
try {
|
|
3761
|
+
const results = await Promise.all(uploadPromises);
|
|
3762
|
+
return results.filter((url) => url !== null);
|
|
3763
|
+
} catch (error) {
|
|
3764
|
+
console.error(`[PHOTO_UTILS] Error uploading multiple photos:`, error);
|
|
3765
|
+
return photos.filter((photo) => !photo.startsWith("data:"));
|
|
3766
|
+
}
|
|
3767
|
+
}
|
|
3768
|
+
|
|
3769
|
+
// src/services/clinic/utils/clinic-group.utils.ts
|
|
3759
3770
|
function generateId() {
|
|
3760
3771
|
const chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
|
|
3761
3772
|
const timestamp = Date.now().toString(36);
|
|
@@ -3765,7 +3776,8 @@ function generateId() {
|
|
|
3765
3776
|
).join("");
|
|
3766
3777
|
return `${randomPart}-${timestamp}`;
|
|
3767
3778
|
}
|
|
3768
|
-
async function createClinicGroup(db, data, ownerId, isDefault = false, clinicAdminService) {
|
|
3779
|
+
async function createClinicGroup(db, data, ownerId, isDefault = false, clinicAdminService, app) {
|
|
3780
|
+
var _a, _b, _c, _d, _e;
|
|
3769
3781
|
console.log("[CLINIC_GROUP] Starting clinic group creation", {
|
|
3770
3782
|
ownerId,
|
|
3771
3783
|
isDefault
|
|
@@ -3781,14 +3793,23 @@ async function createClinicGroup(db, data, ownerId, isDefault = false, clinicAdm
|
|
|
3781
3793
|
const validatedData = createClinicGroupSchema.parse(data);
|
|
3782
3794
|
try {
|
|
3783
3795
|
console.log("[CLINIC_GROUP] Checking if owner exists", { ownerId });
|
|
3784
|
-
|
|
3785
|
-
|
|
3786
|
-
|
|
3787
|
-
|
|
3788
|
-
|
|
3789
|
-
|
|
3796
|
+
if (isDefault) {
|
|
3797
|
+
console.log(
|
|
3798
|
+
"[CLINIC_GROUP] Skipping owner verification for default group creation"
|
|
3799
|
+
);
|
|
3800
|
+
} else {
|
|
3801
|
+
const owner = await clinicAdminService.getClinicAdmin(ownerId);
|
|
3802
|
+
if (!owner) {
|
|
3803
|
+
console.error(
|
|
3804
|
+
"[CLINIC_GROUP] Owner not found or is not a clinic admin",
|
|
3805
|
+
{
|
|
3806
|
+
ownerId
|
|
3807
|
+
}
|
|
3808
|
+
);
|
|
3809
|
+
throw new Error("Owner not found or is not a clinic admin");
|
|
3810
|
+
}
|
|
3811
|
+
console.log("[CLINIC_GROUP] Owner verified as clinic admin");
|
|
3790
3812
|
}
|
|
3791
|
-
console.log("[CLINIC_GROUP] Owner verified as clinic admin");
|
|
3792
3813
|
} catch (ownerError) {
|
|
3793
3814
|
console.error("[CLINIC_GROUP] Error verifying owner:", ownerError);
|
|
3794
3815
|
throw ownerError;
|
|
@@ -3810,23 +3831,49 @@ async function createClinicGroup(db, data, ownerId, isDefault = false, clinicAdm
|
|
|
3810
3831
|
}
|
|
3811
3832
|
const now = import_firestore15.Timestamp.now();
|
|
3812
3833
|
console.log("[CLINIC_GROUP] Preparing clinic group data object");
|
|
3834
|
+
const groupId = (0, import_firestore15.doc)((0, import_firestore15.collection)(db, CLINIC_GROUPS_COLLECTION)).id;
|
|
3813
3835
|
console.log("[CLINIC_GROUP] Logo value:", {
|
|
3814
3836
|
logoValue: validatedData.logo,
|
|
3815
3837
|
logoType: validatedData.logo === null ? "null" : typeof validatedData.logo
|
|
3816
3838
|
});
|
|
3839
|
+
let logoUrl = await uploadPhoto(
|
|
3840
|
+
validatedData.logo || null,
|
|
3841
|
+
"clinic-groups",
|
|
3842
|
+
groupId,
|
|
3843
|
+
"logo",
|
|
3844
|
+
app
|
|
3845
|
+
);
|
|
3846
|
+
console.log("[CLINIC_GROUP] Logo processed", { logoUrl });
|
|
3817
3847
|
const groupData = {
|
|
3818
3848
|
...validatedData,
|
|
3819
|
-
id:
|
|
3849
|
+
id: groupId,
|
|
3850
|
+
name: validatedData.name,
|
|
3851
|
+
logo: logoUrl,
|
|
3852
|
+
// Use the uploaded logo URL or the original value
|
|
3820
3853
|
description: isDefault ? void 0 : validatedData.description || void 0,
|
|
3821
3854
|
hqLocation: {
|
|
3822
|
-
|
|
3855
|
+
address: validatedData.hqLocation.address || "",
|
|
3856
|
+
city: validatedData.hqLocation.city || "",
|
|
3857
|
+
country: validatedData.hqLocation.country || "",
|
|
3858
|
+
postalCode: validatedData.hqLocation.postalCode || "",
|
|
3859
|
+
latitude: validatedData.hqLocation.latitude || 0,
|
|
3860
|
+
longitude: validatedData.hqLocation.longitude || 0,
|
|
3823
3861
|
geohash: validatedData.hqLocation.geohash || void 0
|
|
3824
3862
|
},
|
|
3825
3863
|
contactInfo: {
|
|
3826
|
-
|
|
3864
|
+
email: validatedData.contactInfo.email || "",
|
|
3865
|
+
phoneNumber: validatedData.contactInfo.phoneNumber || "",
|
|
3827
3866
|
alternativePhoneNumber: isDefault ? void 0 : validatedData.contactInfo.alternativePhoneNumber || void 0,
|
|
3828
3867
|
website: isDefault ? void 0 : validatedData.contactInfo.website || void 0
|
|
3829
3868
|
},
|
|
3869
|
+
contactPerson: {
|
|
3870
|
+
firstName: ((_a = validatedData.contactPerson) == null ? void 0 : _a.firstName) || "",
|
|
3871
|
+
lastName: ((_b = validatedData.contactPerson) == null ? void 0 : _b.lastName) || "",
|
|
3872
|
+
email: ((_c = validatedData.contactPerson) == null ? void 0 : _c.email) || "",
|
|
3873
|
+
title: ((_d = validatedData.contactPerson) == null ? void 0 : _d.title) || null,
|
|
3874
|
+
phoneNumber: ((_e = validatedData.contactPerson) == null ? void 0 : _e.phoneNumber) || null
|
|
3875
|
+
},
|
|
3876
|
+
subscriptionModel: validatedData.subscriptionModel || "no_subscription" /* NO_SUBSCRIPTION */,
|
|
3830
3877
|
clinics: [],
|
|
3831
3878
|
clinicsInfo: [],
|
|
3832
3879
|
admins: [ownerId],
|
|
@@ -3914,35 +3961,75 @@ async function getAllActiveGroups(db) {
|
|
|
3914
3961
|
const querySnapshot = await (0, import_firestore15.getDocs)(q);
|
|
3915
3962
|
return querySnapshot.docs.map((doc14) => doc14.data());
|
|
3916
3963
|
}
|
|
3917
|
-
async function updateClinicGroup(db, groupId, data) {
|
|
3964
|
+
async function updateClinicGroup(db, groupId, data, app) {
|
|
3965
|
+
console.log("[CLINIC_GROUP] Updating clinic group", { groupId });
|
|
3918
3966
|
const group = await getClinicGroup(db, groupId);
|
|
3919
3967
|
if (!group) {
|
|
3968
|
+
console.error("[CLINIC_GROUP] Clinic group not found", { groupId });
|
|
3920
3969
|
throw new Error("Clinic group not found");
|
|
3921
3970
|
}
|
|
3922
|
-
|
|
3923
|
-
|
|
3971
|
+
let updatedData = { ...data };
|
|
3972
|
+
if (data.logo && typeof data.logo === "string" && data.logo.startsWith("data:")) {
|
|
3973
|
+
console.log("[CLINIC_GROUP] Processing logo for update");
|
|
3974
|
+
try {
|
|
3975
|
+
const logoUrl = await uploadPhoto(
|
|
3976
|
+
data.logo,
|
|
3977
|
+
"clinic-groups",
|
|
3978
|
+
groupId,
|
|
3979
|
+
"logo",
|
|
3980
|
+
app
|
|
3981
|
+
);
|
|
3982
|
+
console.log("[CLINIC_GROUP] Logo processed for update", { logoUrl });
|
|
3983
|
+
updatedData.logo = logoUrl;
|
|
3984
|
+
} catch (error) {
|
|
3985
|
+
console.error("[CLINIC_GROUP] Error processing logo for update:", error);
|
|
3986
|
+
}
|
|
3987
|
+
}
|
|
3988
|
+
updatedData = {
|
|
3989
|
+
...updatedData,
|
|
3924
3990
|
updatedAt: import_firestore15.Timestamp.now()
|
|
3925
3991
|
};
|
|
3992
|
+
console.log("[CLINIC_GROUP] Updating clinic group in Firestore");
|
|
3926
3993
|
await (0, import_firestore15.updateDoc)((0, import_firestore15.doc)(db, CLINIC_GROUPS_COLLECTION, groupId), updatedData);
|
|
3994
|
+
console.log("[CLINIC_GROUP] Clinic group updated successfully");
|
|
3927
3995
|
const updatedGroup = await getClinicGroup(db, groupId);
|
|
3928
3996
|
if (!updatedGroup) {
|
|
3997
|
+
console.error("[CLINIC_GROUP] Failed to retrieve updated clinic group");
|
|
3929
3998
|
throw new Error("Failed to retrieve updated clinic group");
|
|
3930
3999
|
}
|
|
3931
4000
|
return updatedGroup;
|
|
3932
4001
|
}
|
|
3933
|
-
async function addAdminToGroup(db, groupId, adminId) {
|
|
3934
|
-
|
|
3935
|
-
|
|
3936
|
-
|
|
3937
|
-
|
|
3938
|
-
|
|
3939
|
-
|
|
4002
|
+
async function addAdminToGroup(db, groupId, adminId, app) {
|
|
4003
|
+
console.log("[CLINIC_GROUP] Adding admin to group", { groupId, adminId });
|
|
4004
|
+
try {
|
|
4005
|
+
const group = await getClinicGroup(db, groupId);
|
|
4006
|
+
if (!group) {
|
|
4007
|
+
console.error("[CLINIC_GROUP] Clinic group not found", { groupId });
|
|
4008
|
+
throw new Error("Clinic group not found");
|
|
4009
|
+
}
|
|
4010
|
+
if (group.admins.includes(adminId)) {
|
|
4011
|
+
console.log("[CLINIC_GROUP] Admin is already in the group", {
|
|
4012
|
+
adminId,
|
|
4013
|
+
groupId
|
|
4014
|
+
});
|
|
4015
|
+
return;
|
|
4016
|
+
}
|
|
4017
|
+
console.log("[CLINIC_GROUP] Updating group with new admin");
|
|
4018
|
+
await updateClinicGroup(
|
|
4019
|
+
db,
|
|
4020
|
+
groupId,
|
|
4021
|
+
{
|
|
4022
|
+
admins: [...group.admins, adminId]
|
|
4023
|
+
},
|
|
4024
|
+
app
|
|
4025
|
+
);
|
|
4026
|
+
console.log("[CLINIC_GROUP] Admin added to group successfully");
|
|
4027
|
+
} catch (error) {
|
|
4028
|
+
console.error("[CLINIC_GROUP] Error adding admin to group:", error);
|
|
4029
|
+
throw error;
|
|
3940
4030
|
}
|
|
3941
|
-
await updateClinicGroup(db, groupId, {
|
|
3942
|
-
admins: [...group.admins, adminId]
|
|
3943
|
-
});
|
|
3944
4031
|
}
|
|
3945
|
-
async function removeAdminFromGroup(db, groupId, adminId) {
|
|
4032
|
+
async function removeAdminFromGroup(db, groupId, adminId, app) {
|
|
3946
4033
|
const group = await getClinicGroup(db, groupId);
|
|
3947
4034
|
if (!group) {
|
|
3948
4035
|
throw new Error("Clinic group not found");
|
|
@@ -3953,21 +4040,30 @@ async function removeAdminFromGroup(db, groupId, adminId) {
|
|
|
3953
4040
|
if (!group.admins.includes(adminId)) {
|
|
3954
4041
|
return;
|
|
3955
4042
|
}
|
|
3956
|
-
await updateClinicGroup(
|
|
3957
|
-
|
|
3958
|
-
|
|
4043
|
+
await updateClinicGroup(
|
|
4044
|
+
db,
|
|
4045
|
+
groupId,
|
|
4046
|
+
{
|
|
4047
|
+
admins: group.admins.filter((id) => id !== adminId)
|
|
4048
|
+
},
|
|
4049
|
+
app
|
|
4050
|
+
);
|
|
3959
4051
|
}
|
|
3960
|
-
async function deactivateClinicGroup(db, groupId) {
|
|
4052
|
+
async function deactivateClinicGroup(db, groupId, app) {
|
|
3961
4053
|
const group = await getClinicGroup(db, groupId);
|
|
3962
4054
|
if (!group) {
|
|
3963
4055
|
throw new Error("Clinic group not found");
|
|
3964
4056
|
}
|
|
3965
|
-
await (
|
|
3966
|
-
|
|
3967
|
-
|
|
3968
|
-
|
|
4057
|
+
await updateClinicGroup(
|
|
4058
|
+
db,
|
|
4059
|
+
groupId,
|
|
4060
|
+
{
|
|
4061
|
+
isActive: false
|
|
4062
|
+
},
|
|
4063
|
+
app
|
|
4064
|
+
);
|
|
3969
4065
|
}
|
|
3970
|
-
async function createAdminToken(db, groupId, creatorAdminId, data) {
|
|
4066
|
+
async function createAdminToken(db, groupId, creatorAdminId, app, data) {
|
|
3971
4067
|
const group = await getClinicGroup(db, groupId);
|
|
3972
4068
|
if (!group) {
|
|
3973
4069
|
throw new Error("Clinic group not found");
|
|
@@ -3988,12 +4084,17 @@ async function createAdminToken(db, groupId, creatorAdminId, data) {
|
|
|
3988
4084
|
createdAt: now,
|
|
3989
4085
|
expiresAt
|
|
3990
4086
|
};
|
|
3991
|
-
await updateClinicGroup(
|
|
3992
|
-
|
|
3993
|
-
|
|
4087
|
+
await updateClinicGroup(
|
|
4088
|
+
db,
|
|
4089
|
+
groupId,
|
|
4090
|
+
{
|
|
4091
|
+
adminTokens: [...group.adminTokens, token]
|
|
4092
|
+
},
|
|
4093
|
+
app
|
|
4094
|
+
);
|
|
3994
4095
|
return token;
|
|
3995
4096
|
}
|
|
3996
|
-
async function verifyAndUseAdminToken(db, groupId, token, userRef) {
|
|
4097
|
+
async function verifyAndUseAdminToken(db, groupId, token, userRef, app) {
|
|
3997
4098
|
const group = await getClinicGroup(db, groupId);
|
|
3998
4099
|
if (!group) {
|
|
3999
4100
|
throw new Error("Clinic group not found");
|
|
@@ -4010,9 +4111,14 @@ async function verifyAndUseAdminToken(db, groupId, token, userRef) {
|
|
|
4010
4111
|
const updatedTokens2 = group.adminTokens.map(
|
|
4011
4112
|
(t) => t.id === adminToken.id ? { ...t, status: "expired" /* EXPIRED */ } : t
|
|
4012
4113
|
);
|
|
4013
|
-
await updateClinicGroup(
|
|
4014
|
-
|
|
4015
|
-
|
|
4114
|
+
await updateClinicGroup(
|
|
4115
|
+
db,
|
|
4116
|
+
groupId,
|
|
4117
|
+
{
|
|
4118
|
+
adminTokens: updatedTokens2
|
|
4119
|
+
},
|
|
4120
|
+
app
|
|
4121
|
+
);
|
|
4016
4122
|
throw new Error("Admin token has expired");
|
|
4017
4123
|
}
|
|
4018
4124
|
const updatedTokens = group.adminTokens.map(
|
|
@@ -4022,12 +4128,17 @@ async function verifyAndUseAdminToken(db, groupId, token, userRef) {
|
|
|
4022
4128
|
usedByUserRef: userRef
|
|
4023
4129
|
} : t
|
|
4024
4130
|
);
|
|
4025
|
-
await updateClinicGroup(
|
|
4026
|
-
|
|
4027
|
-
|
|
4131
|
+
await updateClinicGroup(
|
|
4132
|
+
db,
|
|
4133
|
+
groupId,
|
|
4134
|
+
{
|
|
4135
|
+
adminTokens: updatedTokens
|
|
4136
|
+
},
|
|
4137
|
+
app
|
|
4138
|
+
);
|
|
4028
4139
|
return true;
|
|
4029
4140
|
}
|
|
4030
|
-
async function deleteAdminToken(db, groupId, tokenId, adminId) {
|
|
4141
|
+
async function deleteAdminToken(db, groupId, tokenId, adminId, app) {
|
|
4031
4142
|
const group = await getClinicGroup(db, groupId);
|
|
4032
4143
|
if (!group) {
|
|
4033
4144
|
throw new Error("Clinic group not found");
|
|
@@ -4036,11 +4147,16 @@ async function deleteAdminToken(db, groupId, tokenId, adminId) {
|
|
|
4036
4147
|
throw new Error("Admin does not belong to this clinic group");
|
|
4037
4148
|
}
|
|
4038
4149
|
const updatedTokens = group.adminTokens.filter((t) => t.id !== tokenId);
|
|
4039
|
-
await updateClinicGroup(
|
|
4040
|
-
|
|
4041
|
-
|
|
4150
|
+
await updateClinicGroup(
|
|
4151
|
+
db,
|
|
4152
|
+
groupId,
|
|
4153
|
+
{
|
|
4154
|
+
adminTokens: updatedTokens
|
|
4155
|
+
},
|
|
4156
|
+
app
|
|
4157
|
+
);
|
|
4042
4158
|
}
|
|
4043
|
-
async function getActiveAdminTokens(db, groupId, adminId) {
|
|
4159
|
+
async function getActiveAdminTokens(db, groupId, adminId, app) {
|
|
4044
4160
|
const group = await getClinicGroup(db, groupId);
|
|
4045
4161
|
if (!group) {
|
|
4046
4162
|
throw new Error("Clinic group not found");
|
|
@@ -4066,7 +4182,8 @@ var ClinicGroupService = class extends BaseService {
|
|
|
4066
4182
|
data,
|
|
4067
4183
|
ownerId,
|
|
4068
4184
|
isDefault,
|
|
4069
|
-
this.clinicAdminService
|
|
4185
|
+
this.clinicAdminService,
|
|
4186
|
+
this.app
|
|
4070
4187
|
);
|
|
4071
4188
|
}
|
|
4072
4189
|
/**
|
|
@@ -4085,25 +4202,35 @@ var ClinicGroupService = class extends BaseService {
|
|
|
4085
4202
|
* Ažurira grupaciju klinika
|
|
4086
4203
|
*/
|
|
4087
4204
|
async updateClinicGroup(groupId, data) {
|
|
4088
|
-
return updateClinicGroup(this.db, groupId, data);
|
|
4205
|
+
return updateClinicGroup(this.db, groupId, data, this.app);
|
|
4089
4206
|
}
|
|
4090
4207
|
/**
|
|
4091
4208
|
* Dodaje admina u grupaciju
|
|
4092
4209
|
*/
|
|
4093
4210
|
async addAdminToGroup(groupId, adminId) {
|
|
4094
|
-
return addAdminToGroup(
|
|
4211
|
+
return addAdminToGroup(
|
|
4212
|
+
this.db,
|
|
4213
|
+
groupId,
|
|
4214
|
+
adminId,
|
|
4215
|
+
this.app
|
|
4216
|
+
);
|
|
4095
4217
|
}
|
|
4096
4218
|
/**
|
|
4097
4219
|
* Uklanja admina iz grupacije
|
|
4098
4220
|
*/
|
|
4099
4221
|
async removeAdminFromGroup(groupId, adminId) {
|
|
4100
|
-
return removeAdminFromGroup(
|
|
4222
|
+
return removeAdminFromGroup(
|
|
4223
|
+
this.db,
|
|
4224
|
+
groupId,
|
|
4225
|
+
adminId,
|
|
4226
|
+
this.app
|
|
4227
|
+
);
|
|
4101
4228
|
}
|
|
4102
4229
|
/**
|
|
4103
4230
|
* Deaktivira grupaciju klinika
|
|
4104
4231
|
*/
|
|
4105
4232
|
async deactivateClinicGroup(groupId) {
|
|
4106
|
-
return deactivateClinicGroup(this.db, groupId);
|
|
4233
|
+
return deactivateClinicGroup(this.db, groupId, this.app);
|
|
4107
4234
|
}
|
|
4108
4235
|
/**
|
|
4109
4236
|
* Sets up additional clinic group information after initial creation
|
|
@@ -4113,18 +4240,45 @@ var ClinicGroupService = class extends BaseService {
|
|
|
4113
4240
|
* @returns The updated clinic group
|
|
4114
4241
|
*/
|
|
4115
4242
|
async setupClinicGroup(groupId, setupData) {
|
|
4243
|
+
console.log("[CLINIC_GROUP] Setting up clinic group", { groupId });
|
|
4116
4244
|
const clinicGroup = await this.getClinicGroup(groupId);
|
|
4117
4245
|
if (!clinicGroup) {
|
|
4246
|
+
console.error("[CLINIC_GROUP] Clinic group not found", { groupId });
|
|
4118
4247
|
throw new Error(`Clinic group with ID ${groupId} not found`);
|
|
4119
4248
|
}
|
|
4249
|
+
let logoUrl = setupData.logo;
|
|
4250
|
+
if (logoUrl && typeof logoUrl === "string" && logoUrl.startsWith("data:")) {
|
|
4251
|
+
console.log("[CLINIC_GROUP] Processing logo in setupClinicGroup");
|
|
4252
|
+
try {
|
|
4253
|
+
const uploadedLogoUrl = await uploadPhoto(
|
|
4254
|
+
logoUrl,
|
|
4255
|
+
"clinic-groups",
|
|
4256
|
+
groupId,
|
|
4257
|
+
"logo",
|
|
4258
|
+
this.app
|
|
4259
|
+
);
|
|
4260
|
+
console.log("[CLINIC_GROUP] Logo processed in setupClinicGroup", {
|
|
4261
|
+
uploadedLogoUrl
|
|
4262
|
+
});
|
|
4263
|
+
if (uploadedLogoUrl !== null) {
|
|
4264
|
+
logoUrl = uploadedLogoUrl;
|
|
4265
|
+
}
|
|
4266
|
+
} catch (error) {
|
|
4267
|
+
console.error(
|
|
4268
|
+
"[CLINIC_GROUP] Error processing logo in setupClinicGroup:",
|
|
4269
|
+
error
|
|
4270
|
+
);
|
|
4271
|
+
}
|
|
4272
|
+
}
|
|
4120
4273
|
const updateData = {
|
|
4121
4274
|
languages: setupData.languages,
|
|
4122
4275
|
practiceType: setupData.practiceType,
|
|
4123
4276
|
description: setupData.description,
|
|
4124
|
-
logo:
|
|
4277
|
+
logo: logoUrl,
|
|
4125
4278
|
calendarSyncEnabled: setupData.calendarSyncEnabled,
|
|
4126
4279
|
autoConfirmAppointments: setupData.autoConfirmAppointments
|
|
4127
4280
|
};
|
|
4281
|
+
console.log("[CLINIC_GROUP] Updating clinic group with setup data");
|
|
4128
4282
|
return this.updateClinicGroup(groupId, updateData);
|
|
4129
4283
|
}
|
|
4130
4284
|
/**
|
|
@@ -4135,6 +4289,7 @@ var ClinicGroupService = class extends BaseService {
|
|
|
4135
4289
|
this.db,
|
|
4136
4290
|
groupId,
|
|
4137
4291
|
creatorAdminId,
|
|
4292
|
+
this.app,
|
|
4138
4293
|
data
|
|
4139
4294
|
);
|
|
4140
4295
|
}
|
|
@@ -4146,7 +4301,8 @@ var ClinicGroupService = class extends BaseService {
|
|
|
4146
4301
|
this.db,
|
|
4147
4302
|
groupId,
|
|
4148
4303
|
token,
|
|
4149
|
-
userRef
|
|
4304
|
+
userRef,
|
|
4305
|
+
this.app
|
|
4150
4306
|
);
|
|
4151
4307
|
}
|
|
4152
4308
|
/**
|
|
@@ -4157,14 +4313,20 @@ var ClinicGroupService = class extends BaseService {
|
|
|
4157
4313
|
this.db,
|
|
4158
4314
|
groupId,
|
|
4159
4315
|
tokenId,
|
|
4160
|
-
adminId
|
|
4316
|
+
adminId,
|
|
4317
|
+
this.app
|
|
4161
4318
|
);
|
|
4162
4319
|
}
|
|
4163
4320
|
/**
|
|
4164
4321
|
* Dohvata aktivne admin tokene
|
|
4165
4322
|
*/
|
|
4166
4323
|
async getActiveAdminTokens(groupId, adminId) {
|
|
4167
|
-
return getActiveAdminTokens(
|
|
4324
|
+
return getActiveAdminTokens(
|
|
4325
|
+
this.db,
|
|
4326
|
+
groupId,
|
|
4327
|
+
adminId,
|
|
4328
|
+
this.app
|
|
4329
|
+
);
|
|
4168
4330
|
}
|
|
4169
4331
|
};
|
|
4170
4332
|
|
|
@@ -4172,44 +4334,193 @@ var ClinicGroupService = class extends BaseService {
|
|
|
4172
4334
|
var import_firestore16 = require("firebase/firestore");
|
|
4173
4335
|
var import_geofire_common3 = require("geofire-common");
|
|
4174
4336
|
var import_zod14 = require("zod");
|
|
4175
|
-
async function createClinic(db, data, creatorAdminId, clinicGroupService, clinicAdminService) {
|
|
4176
|
-
|
|
4177
|
-
|
|
4178
|
-
|
|
4179
|
-
|
|
4337
|
+
async function createClinic(db, data, creatorAdminId, clinicGroupService, clinicAdminService, app) {
|
|
4338
|
+
var _a;
|
|
4339
|
+
console.log("[CLINIC] Starting clinic creation", { creatorAdminId });
|
|
4340
|
+
console.log("[CLINIC] Input data:", JSON.stringify(data, null, 2));
|
|
4341
|
+
try {
|
|
4342
|
+
const validatedData2 = createClinicSchema.parse(data);
|
|
4343
|
+
console.log("[CLINIC] Data validation passed");
|
|
4344
|
+
} catch (validationError) {
|
|
4345
|
+
console.error("[CLINIC] Data validation failed:", validationError);
|
|
4346
|
+
throw validationError;
|
|
4180
4347
|
}
|
|
4181
|
-
|
|
4182
|
-
|
|
4348
|
+
const validatedData = createClinicSchema.parse(data);
|
|
4349
|
+
try {
|
|
4350
|
+
console.log("[CLINIC] Checking if admin exists and belongs to group");
|
|
4351
|
+
const admin = await clinicAdminService.getClinicAdmin(creatorAdminId);
|
|
4352
|
+
if (!admin) {
|
|
4353
|
+
console.error("[CLINIC] Admin not found", { creatorAdminId });
|
|
4354
|
+
throw new Error("Admin not found");
|
|
4355
|
+
}
|
|
4356
|
+
if (admin.clinicGroupId !== validatedData.clinicGroupId) {
|
|
4357
|
+
console.error("[CLINIC] Admin does not belong to this clinic group", {
|
|
4358
|
+
adminGroupId: admin.clinicGroupId,
|
|
4359
|
+
requestedGroupId: validatedData.clinicGroupId
|
|
4360
|
+
});
|
|
4361
|
+
throw new Error("Admin does not belong to this clinic group");
|
|
4362
|
+
}
|
|
4363
|
+
console.log("[CLINIC] Admin verified");
|
|
4364
|
+
} catch (adminError) {
|
|
4365
|
+
console.error("[CLINIC] Error verifying admin:", adminError);
|
|
4366
|
+
throw adminError;
|
|
4183
4367
|
}
|
|
4184
|
-
|
|
4185
|
-
|
|
4186
|
-
|
|
4187
|
-
|
|
4188
|
-
|
|
4368
|
+
try {
|
|
4369
|
+
console.log("[CLINIC] Checking if clinic group exists");
|
|
4370
|
+
const group = await clinicGroupService.getClinicGroup(
|
|
4371
|
+
validatedData.clinicGroupId
|
|
4372
|
+
);
|
|
4373
|
+
if (!group) {
|
|
4374
|
+
console.error("[CLINIC] Clinic group not found", {
|
|
4375
|
+
groupId: validatedData.clinicGroupId
|
|
4376
|
+
});
|
|
4377
|
+
throw new Error("Clinic group not found");
|
|
4378
|
+
}
|
|
4379
|
+
console.log("[CLINIC] Clinic group verified");
|
|
4380
|
+
} catch (groupError) {
|
|
4381
|
+
console.error("[CLINIC] Error verifying clinic group:", groupError);
|
|
4382
|
+
throw groupError;
|
|
4189
4383
|
}
|
|
4384
|
+
console.log("[CLINIC] Generating geohash for location");
|
|
4190
4385
|
if (validatedData.location) {
|
|
4191
|
-
|
|
4192
|
-
validatedData.location.
|
|
4193
|
-
|
|
4194
|
-
|
|
4386
|
+
try {
|
|
4387
|
+
validatedData.location.geohash = (0, import_geofire_common3.geohashForLocation)([
|
|
4388
|
+
validatedData.location.latitude,
|
|
4389
|
+
validatedData.location.longitude
|
|
4390
|
+
]);
|
|
4391
|
+
console.log("[CLINIC] Geohash generated successfully", {
|
|
4392
|
+
geohash: validatedData.location.geohash
|
|
4393
|
+
});
|
|
4394
|
+
} catch (geohashError) {
|
|
4395
|
+
console.error("[CLINIC] Error generating geohash:", geohashError);
|
|
4396
|
+
throw geohashError;
|
|
4397
|
+
}
|
|
4398
|
+
}
|
|
4399
|
+
const clinicId = (0, import_firestore16.doc)((0, import_firestore16.collection)(db, CLINICS_COLLECTION)).id;
|
|
4400
|
+
console.log("[CLINIC] Generated clinic ID:", clinicId);
|
|
4401
|
+
console.log("[CLINIC] Processing photos");
|
|
4402
|
+
let logoUrl = null;
|
|
4403
|
+
if (validatedData.logo) {
|
|
4404
|
+
console.log("[CLINIC] Processing logo");
|
|
4405
|
+
try {
|
|
4406
|
+
logoUrl = await uploadPhoto(
|
|
4407
|
+
validatedData.logo,
|
|
4408
|
+
"clinics",
|
|
4409
|
+
clinicId,
|
|
4410
|
+
"logo",
|
|
4411
|
+
app
|
|
4412
|
+
);
|
|
4413
|
+
console.log("[CLINIC] Logo processed", { logoUrl });
|
|
4414
|
+
} catch (logoError) {
|
|
4415
|
+
console.error("[CLINIC] Error processing logo:", logoError);
|
|
4416
|
+
}
|
|
4417
|
+
}
|
|
4418
|
+
let processedPhotos = [];
|
|
4419
|
+
if (validatedData.photos && validatedData.photos.length > 0) {
|
|
4420
|
+
console.log("[CLINIC] Processing regular photos");
|
|
4421
|
+
try {
|
|
4422
|
+
processedPhotos = await uploadMultiplePhotos(
|
|
4423
|
+
validatedData.photos,
|
|
4424
|
+
"clinics",
|
|
4425
|
+
clinicId,
|
|
4426
|
+
"photo",
|
|
4427
|
+
app
|
|
4428
|
+
);
|
|
4429
|
+
console.log("[CLINIC] Regular photos processed", {
|
|
4430
|
+
count: processedPhotos.length
|
|
4431
|
+
});
|
|
4432
|
+
} catch (photosError) {
|
|
4433
|
+
console.error("[CLINIC] Error processing regular photos:", photosError);
|
|
4434
|
+
processedPhotos = validatedData.photos.filter(
|
|
4435
|
+
(photo) => !photo.startsWith("data:")
|
|
4436
|
+
);
|
|
4437
|
+
}
|
|
4438
|
+
}
|
|
4439
|
+
let processedFeaturedPhotos = [];
|
|
4440
|
+
if (validatedData.featuredPhotos && validatedData.featuredPhotos.length > 0) {
|
|
4441
|
+
console.log("[CLINIC] Processing featured photos");
|
|
4442
|
+
try {
|
|
4443
|
+
processedFeaturedPhotos = await uploadMultiplePhotos(
|
|
4444
|
+
validatedData.featuredPhotos,
|
|
4445
|
+
"clinics",
|
|
4446
|
+
clinicId,
|
|
4447
|
+
"featured",
|
|
4448
|
+
app
|
|
4449
|
+
);
|
|
4450
|
+
console.log("[CLINIC] Featured photos processed", {
|
|
4451
|
+
count: processedFeaturedPhotos.length
|
|
4452
|
+
});
|
|
4453
|
+
} catch (featuredError) {
|
|
4454
|
+
console.error(
|
|
4455
|
+
"[CLINIC] Error processing featured photos:",
|
|
4456
|
+
featuredError
|
|
4457
|
+
);
|
|
4458
|
+
processedFeaturedPhotos = validatedData.featuredPhotos.filter(
|
|
4459
|
+
(photo) => !photo.startsWith("data:")
|
|
4460
|
+
);
|
|
4461
|
+
}
|
|
4462
|
+
}
|
|
4463
|
+
let processedPhotosWithTags = validatedData.photosWithTags || [];
|
|
4464
|
+
if (processedPhotosWithTags.length > 0) {
|
|
4465
|
+
console.log("[CLINIC] Processing photos with tags");
|
|
4466
|
+
try {
|
|
4467
|
+
const updatedPhotosWithTags = [];
|
|
4468
|
+
for (const photoWithTag of processedPhotosWithTags) {
|
|
4469
|
+
if (photoWithTag.url && photoWithTag.url.startsWith("data:")) {
|
|
4470
|
+
const uploadedUrl = await uploadPhoto(
|
|
4471
|
+
photoWithTag.url,
|
|
4472
|
+
"clinics",
|
|
4473
|
+
clinicId,
|
|
4474
|
+
`tagged-${photoWithTag.tag}`,
|
|
4475
|
+
app
|
|
4476
|
+
);
|
|
4477
|
+
if (uploadedUrl) {
|
|
4478
|
+
updatedPhotosWithTags.push({
|
|
4479
|
+
url: uploadedUrl,
|
|
4480
|
+
tag: photoWithTag.tag
|
|
4481
|
+
});
|
|
4482
|
+
}
|
|
4483
|
+
} else {
|
|
4484
|
+
updatedPhotosWithTags.push(photoWithTag);
|
|
4485
|
+
}
|
|
4486
|
+
}
|
|
4487
|
+
processedPhotosWithTags = updatedPhotosWithTags;
|
|
4488
|
+
console.log("[CLINIC] Photos with tags processed", {
|
|
4489
|
+
count: processedPhotosWithTags.length
|
|
4490
|
+
});
|
|
4491
|
+
} catch (tagsError) {
|
|
4492
|
+
console.error("[CLINIC] Error processing photos with tags:", tagsError);
|
|
4493
|
+
processedPhotosWithTags = ((_a = validatedData.photosWithTags) == null ? void 0 : _a.filter(
|
|
4494
|
+
(photo) => !photo.url.startsWith("data:")
|
|
4495
|
+
)) || [];
|
|
4496
|
+
}
|
|
4195
4497
|
}
|
|
4196
4498
|
const now = import_firestore16.Timestamp.now();
|
|
4499
|
+
console.log("[CLINIC] Preparing clinic data object");
|
|
4197
4500
|
const clinicData = {
|
|
4198
4501
|
...validatedData,
|
|
4199
|
-
id:
|
|
4502
|
+
id: clinicId,
|
|
4200
4503
|
description: validatedData.description || void 0,
|
|
4201
4504
|
location: {
|
|
4202
|
-
|
|
4505
|
+
address: validatedData.location.address || "",
|
|
4506
|
+
city: validatedData.location.city || "",
|
|
4507
|
+
country: validatedData.location.country || "",
|
|
4508
|
+
postalCode: validatedData.location.postalCode || "",
|
|
4509
|
+
latitude: validatedData.location.latitude || 0,
|
|
4510
|
+
longitude: validatedData.location.longitude || 0,
|
|
4203
4511
|
geohash: validatedData.location.geohash || void 0
|
|
4204
4512
|
},
|
|
4205
4513
|
contactInfo: {
|
|
4206
|
-
|
|
4514
|
+
email: validatedData.contactInfo.email || "",
|
|
4515
|
+
phoneNumber: validatedData.contactInfo.phoneNumber || "",
|
|
4207
4516
|
alternativePhoneNumber: validatedData.contactInfo.alternativePhoneNumber || void 0,
|
|
4208
4517
|
website: validatedData.contactInfo.website || void 0
|
|
4209
4518
|
},
|
|
4519
|
+
logo: logoUrl || void 0,
|
|
4210
4520
|
tags: validatedData.tags || [],
|
|
4211
|
-
featuredPhotos: [],
|
|
4212
|
-
photos:
|
|
4521
|
+
featuredPhotos: processedFeaturedPhotos || [],
|
|
4522
|
+
photos: processedPhotos || [],
|
|
4523
|
+
photosWithTags: processedPhotosWithTags,
|
|
4213
4524
|
doctors: [],
|
|
4214
4525
|
doctorsInfo: [],
|
|
4215
4526
|
services: [],
|
|
@@ -4224,17 +4535,73 @@ async function createClinic(db, data, creatorAdminId, clinicGroupService, clinic
|
|
|
4224
4535
|
isVerified: false
|
|
4225
4536
|
};
|
|
4226
4537
|
try {
|
|
4227
|
-
|
|
4228
|
-
|
|
4229
|
-
|
|
4230
|
-
|
|
4538
|
+
console.log("[CLINIC] Validating complete clinic object");
|
|
4539
|
+
try {
|
|
4540
|
+
clinicSchema.parse(clinicData);
|
|
4541
|
+
console.log("[CLINIC] Clinic validation passed");
|
|
4542
|
+
} catch (schemaError) {
|
|
4543
|
+
console.error(
|
|
4544
|
+
"[CLINIC] Clinic validation failed:",
|
|
4545
|
+
JSON.stringify(schemaError, null, 2)
|
|
4546
|
+
);
|
|
4547
|
+
throw schemaError;
|
|
4548
|
+
}
|
|
4549
|
+
console.log("[CLINIC] Saving clinic to Firestore", {
|
|
4550
|
+
clinicId: clinicData.id
|
|
4551
|
+
});
|
|
4552
|
+
try {
|
|
4553
|
+
await (0, import_firestore16.setDoc)((0, import_firestore16.doc)(db, CLINICS_COLLECTION, clinicData.id), clinicData);
|
|
4554
|
+
console.log("[CLINIC] Clinic saved successfully");
|
|
4555
|
+
} catch (firestoreError) {
|
|
4556
|
+
console.error("[CLINIC] Error saving to Firestore:", firestoreError);
|
|
4557
|
+
throw firestoreError;
|
|
4558
|
+
}
|
|
4559
|
+
console.log("[CLINIC] Adding clinic to clinic group");
|
|
4560
|
+
try {
|
|
4561
|
+
const group = await clinicGroupService.getClinicGroup(
|
|
4562
|
+
validatedData.clinicGroupId
|
|
4563
|
+
);
|
|
4564
|
+
if (group) {
|
|
4565
|
+
await clinicGroupService.updateClinicGroup(
|
|
4566
|
+
validatedData.clinicGroupId,
|
|
4567
|
+
{
|
|
4568
|
+
clinics: [...group.clinics, clinicData.id]
|
|
4569
|
+
}
|
|
4570
|
+
);
|
|
4571
|
+
console.log("[CLINIC] Clinic added to group successfully");
|
|
4572
|
+
}
|
|
4573
|
+
} catch (groupUpdateError) {
|
|
4574
|
+
console.error("[CLINIC] Error adding clinic to group:", groupUpdateError);
|
|
4575
|
+
}
|
|
4576
|
+
console.log("[CLINIC] Adding clinic to admin's managed clinics");
|
|
4577
|
+
try {
|
|
4578
|
+
await clinicAdminService.addClinicToManaged(
|
|
4579
|
+
creatorAdminId,
|
|
4580
|
+
clinicData.id
|
|
4581
|
+
);
|
|
4582
|
+
console.log(
|
|
4583
|
+
"[CLINIC] Clinic added to admin's managed clinics successfully"
|
|
4584
|
+
);
|
|
4585
|
+
} catch (adminUpdateError) {
|
|
4586
|
+
console.error(
|
|
4587
|
+
"[CLINIC] Error adding clinic to admin's managed clinics:",
|
|
4588
|
+
adminUpdateError
|
|
4589
|
+
);
|
|
4590
|
+
}
|
|
4591
|
+
console.log("[CLINIC] Clinic creation completed successfully", {
|
|
4592
|
+
clinicId: clinicData.id,
|
|
4593
|
+
clinicName: clinicData.name
|
|
4231
4594
|
});
|
|
4232
|
-
await clinicAdminService.addClinicToManaged(creatorAdminId, clinicData.id);
|
|
4233
4595
|
return clinicData;
|
|
4234
4596
|
} catch (error) {
|
|
4235
4597
|
if (error instanceof import_zod14.z.ZodError) {
|
|
4598
|
+
console.error(
|
|
4599
|
+
"[CLINIC] Zod validation error:",
|
|
4600
|
+
JSON.stringify(error.errors, null, 2)
|
|
4601
|
+
);
|
|
4236
4602
|
throw new Error("Invalid clinic data: " + error.message);
|
|
4237
4603
|
}
|
|
4604
|
+
console.error("[CLINIC] Unhandled error in createClinic:", error);
|
|
4238
4605
|
throw error;
|
|
4239
4606
|
}
|
|
4240
4607
|
}
|
|
@@ -4255,27 +4622,177 @@ async function getClinicsByGroup(db, groupId) {
|
|
|
4255
4622
|
const querySnapshot = await (0, import_firestore16.getDocs)(q);
|
|
4256
4623
|
return querySnapshot.docs.map((doc14) => doc14.data());
|
|
4257
4624
|
}
|
|
4258
|
-
async function updateClinic(db, clinicId, data, adminId, clinicAdminService) {
|
|
4625
|
+
async function updateClinic(db, clinicId, data, adminId, clinicAdminService, app) {
|
|
4626
|
+
console.log("[CLINIC] Starting clinic update", { clinicId, adminId });
|
|
4259
4627
|
const clinic = await getClinic(db, clinicId);
|
|
4260
4628
|
if (!clinic) {
|
|
4629
|
+
console.error("[CLINIC] Clinic not found", { clinicId });
|
|
4261
4630
|
throw new Error("Clinic not found");
|
|
4262
4631
|
}
|
|
4263
|
-
|
|
4264
|
-
|
|
4265
|
-
|
|
4632
|
+
try {
|
|
4633
|
+
console.log("[CLINIC] Checking admin permissions");
|
|
4634
|
+
const admin = await clinicAdminService.getClinicAdmin(adminId);
|
|
4635
|
+
if (!admin) {
|
|
4636
|
+
console.error("[CLINIC] Admin not found", { adminId });
|
|
4637
|
+
throw new Error("Admin not found");
|
|
4638
|
+
}
|
|
4639
|
+
const hasPermission = admin.isGroupOwner && admin.clinicGroupId === clinic.clinicGroupId || admin.clinicsManaged.includes(clinicId) && clinic.admins && clinic.admins.includes(adminId);
|
|
4640
|
+
if (!hasPermission) {
|
|
4641
|
+
console.error(
|
|
4642
|
+
"[CLINIC] Admin does not have permission to update this clinic",
|
|
4643
|
+
{
|
|
4644
|
+
adminId,
|
|
4645
|
+
clinicId,
|
|
4646
|
+
isGroupOwner: admin.isGroupOwner,
|
|
4647
|
+
clinicsManaged: admin.clinicsManaged,
|
|
4648
|
+
isClinicAdmin: clinic.admins && clinic.admins.includes(adminId)
|
|
4649
|
+
}
|
|
4650
|
+
);
|
|
4651
|
+
throw new Error("Admin does not have permission to update this clinic");
|
|
4652
|
+
}
|
|
4653
|
+
console.log("[CLINIC] Admin permissions verified");
|
|
4654
|
+
} catch (adminError) {
|
|
4655
|
+
console.error("[CLINIC] Error verifying admin permissions:", adminError);
|
|
4656
|
+
throw adminError;
|
|
4657
|
+
}
|
|
4658
|
+
let updatedData = { ...data };
|
|
4659
|
+
if (data.logo && typeof data.logo === "string" && data.logo.startsWith("data:")) {
|
|
4660
|
+
console.log("[CLINIC] Processing logo update");
|
|
4661
|
+
try {
|
|
4662
|
+
const logoUrl = await uploadPhoto(
|
|
4663
|
+
data.logo,
|
|
4664
|
+
"clinics",
|
|
4665
|
+
clinicId,
|
|
4666
|
+
"logo",
|
|
4667
|
+
app
|
|
4668
|
+
);
|
|
4669
|
+
console.log("[CLINIC] Logo update processed", { logoUrl });
|
|
4670
|
+
if (logoUrl !== null) {
|
|
4671
|
+
updatedData.logo = logoUrl;
|
|
4672
|
+
}
|
|
4673
|
+
} catch (logoError) {
|
|
4674
|
+
console.error("[CLINIC] Error processing logo update:", logoError);
|
|
4675
|
+
}
|
|
4266
4676
|
}
|
|
4267
|
-
if (
|
|
4268
|
-
|
|
4677
|
+
if (data.photos && data.photos.length > 0) {
|
|
4678
|
+
console.log("[CLINIC] Processing regular photos update");
|
|
4679
|
+
try {
|
|
4680
|
+
const dataUrlPhotos = data.photos.filter(
|
|
4681
|
+
(photo) => typeof photo === "string" && photo.startsWith("data:")
|
|
4682
|
+
);
|
|
4683
|
+
const existingPhotos = data.photos.filter(
|
|
4684
|
+
(photo) => typeof photo === "string" && !photo.startsWith("data:")
|
|
4685
|
+
);
|
|
4686
|
+
if (dataUrlPhotos.length > 0) {
|
|
4687
|
+
const uploadedPhotos = await uploadMultiplePhotos(
|
|
4688
|
+
dataUrlPhotos,
|
|
4689
|
+
"clinics",
|
|
4690
|
+
clinicId,
|
|
4691
|
+
"photo",
|
|
4692
|
+
app
|
|
4693
|
+
);
|
|
4694
|
+
console.log("[CLINIC] Regular photos update processed", {
|
|
4695
|
+
count: uploadedPhotos.length
|
|
4696
|
+
});
|
|
4697
|
+
updatedData.photos = [...existingPhotos, ...uploadedPhotos];
|
|
4698
|
+
}
|
|
4699
|
+
} catch (photosError) {
|
|
4700
|
+
console.error(
|
|
4701
|
+
"[CLINIC] Error processing regular photos update:",
|
|
4702
|
+
photosError
|
|
4703
|
+
);
|
|
4704
|
+
updatedData.photos = data.photos.filter(
|
|
4705
|
+
(photo) => typeof photo === "string" && !photo.startsWith("data:")
|
|
4706
|
+
);
|
|
4707
|
+
}
|
|
4269
4708
|
}
|
|
4270
|
-
|
|
4271
|
-
|
|
4709
|
+
if (data.featuredPhotos && data.featuredPhotos.length > 0) {
|
|
4710
|
+
console.log("[CLINIC] Processing featured photos update");
|
|
4711
|
+
try {
|
|
4712
|
+
const dataUrlPhotos = data.featuredPhotos.filter(
|
|
4713
|
+
(photo) => typeof photo === "string" && photo.startsWith("data:")
|
|
4714
|
+
);
|
|
4715
|
+
const existingPhotos = data.featuredPhotos.filter(
|
|
4716
|
+
(photo) => typeof photo === "string" && !photo.startsWith("data:")
|
|
4717
|
+
);
|
|
4718
|
+
if (dataUrlPhotos.length > 0) {
|
|
4719
|
+
const uploadedPhotos = await uploadMultiplePhotos(
|
|
4720
|
+
dataUrlPhotos,
|
|
4721
|
+
"clinics",
|
|
4722
|
+
clinicId,
|
|
4723
|
+
"featured",
|
|
4724
|
+
app
|
|
4725
|
+
);
|
|
4726
|
+
console.log("[CLINIC] Featured photos update processed", {
|
|
4727
|
+
count: uploadedPhotos.length
|
|
4728
|
+
});
|
|
4729
|
+
updatedData.featuredPhotos = [...existingPhotos, ...uploadedPhotos];
|
|
4730
|
+
}
|
|
4731
|
+
} catch (featuredError) {
|
|
4732
|
+
console.error(
|
|
4733
|
+
"[CLINIC] Error processing featured photos update:",
|
|
4734
|
+
featuredError
|
|
4735
|
+
);
|
|
4736
|
+
updatedData.featuredPhotos = data.featuredPhotos.filter(
|
|
4737
|
+
(photo) => typeof photo === "string" && !photo.startsWith("data:")
|
|
4738
|
+
);
|
|
4739
|
+
}
|
|
4740
|
+
}
|
|
4741
|
+
if (data.photosWithTags && data.photosWithTags.length > 0) {
|
|
4742
|
+
console.log("[CLINIC] Processing photos with tags update");
|
|
4743
|
+
try {
|
|
4744
|
+
const updatedPhotosWithTags = [];
|
|
4745
|
+
for (const photoWithTag of data.photosWithTags) {
|
|
4746
|
+
if (photoWithTag.url && photoWithTag.url.startsWith("data:")) {
|
|
4747
|
+
const uploadedUrl = await uploadPhoto(
|
|
4748
|
+
photoWithTag.url,
|
|
4749
|
+
"clinics",
|
|
4750
|
+
clinicId,
|
|
4751
|
+
`tagged-${photoWithTag.tag}`,
|
|
4752
|
+
app
|
|
4753
|
+
);
|
|
4754
|
+
if (uploadedUrl) {
|
|
4755
|
+
updatedPhotosWithTags.push({
|
|
4756
|
+
url: uploadedUrl,
|
|
4757
|
+
tag: photoWithTag.tag
|
|
4758
|
+
});
|
|
4759
|
+
}
|
|
4760
|
+
} else {
|
|
4761
|
+
updatedPhotosWithTags.push(photoWithTag);
|
|
4762
|
+
}
|
|
4763
|
+
}
|
|
4764
|
+
updatedData.photosWithTags = updatedPhotosWithTags;
|
|
4765
|
+
console.log("[CLINIC] Photos with tags update processed", {
|
|
4766
|
+
count: updatedPhotosWithTags.length
|
|
4767
|
+
});
|
|
4768
|
+
} catch (tagsError) {
|
|
4769
|
+
console.error(
|
|
4770
|
+
"[CLINIC] Error processing photos with tags update:",
|
|
4771
|
+
tagsError
|
|
4772
|
+
);
|
|
4773
|
+
updatedData.photosWithTags = data.photosWithTags.filter(
|
|
4774
|
+
(photo) => !photo.url.startsWith("data:")
|
|
4775
|
+
);
|
|
4776
|
+
}
|
|
4777
|
+
}
|
|
4778
|
+
updatedData = {
|
|
4779
|
+
...updatedData,
|
|
4272
4780
|
updatedAt: import_firestore16.Timestamp.now()
|
|
4273
4781
|
};
|
|
4274
|
-
|
|
4782
|
+
console.log("[CLINIC] Updating clinic in Firestore");
|
|
4783
|
+
try {
|
|
4784
|
+
await (0, import_firestore16.updateDoc)((0, import_firestore16.doc)(db, CLINICS_COLLECTION, clinicId), updatedData);
|
|
4785
|
+
console.log("[CLINIC] Clinic updated successfully");
|
|
4786
|
+
} catch (updateError) {
|
|
4787
|
+
console.error("[CLINIC] Error updating clinic in Firestore:", updateError);
|
|
4788
|
+
throw updateError;
|
|
4789
|
+
}
|
|
4275
4790
|
const updatedClinic = await getClinic(db, clinicId);
|
|
4276
4791
|
if (!updatedClinic) {
|
|
4792
|
+
console.error("[CLINIC] Failed to retrieve updated clinic");
|
|
4277
4793
|
throw new Error("Failed to retrieve updated clinic");
|
|
4278
4794
|
}
|
|
4795
|
+
console.log("[CLINIC] Clinic update completed successfully");
|
|
4279
4796
|
return updatedClinic;
|
|
4280
4797
|
}
|
|
4281
4798
|
async function deactivateClinic(db, clinicId, adminId, clinicAdminService) {
|
|
@@ -4287,7 +4804,8 @@ async function deactivateClinic(db, clinicId, adminId, clinicAdminService) {
|
|
|
4287
4804
|
if (!admin) {
|
|
4288
4805
|
throw new Error("Admin not found");
|
|
4289
4806
|
}
|
|
4290
|
-
|
|
4807
|
+
const hasPermission = admin.isGroupOwner && admin.clinicGroupId === clinic.clinicGroupId || admin.clinicsManaged.includes(clinicId) && clinic.admins && clinic.admins.includes(adminId);
|
|
4808
|
+
if (!hasPermission) {
|
|
4291
4809
|
throw new Error("Admin does not have permission to deactivate this clinic");
|
|
4292
4810
|
}
|
|
4293
4811
|
await (0, import_firestore16.updateDoc)((0, import_firestore16.doc)(db, CLINICS_COLLECTION, clinicId), {
|
|
@@ -4330,24 +4848,24 @@ async function getActiveClinicsByAdmin(db, adminId, clinicAdminService, clinicGr
|
|
|
4330
4848
|
|
|
4331
4849
|
// src/services/clinic/utils/review.utils.ts
|
|
4332
4850
|
var import_firestore17 = require("firebase/firestore");
|
|
4333
|
-
async function addReview(db, clinicId, review) {
|
|
4334
|
-
const
|
|
4335
|
-
|
|
4851
|
+
async function addReview(db, clinicId, review, app) {
|
|
4852
|
+
const clinicRef = (0, import_firestore17.doc)(db, "clinics", clinicId);
|
|
4853
|
+
const clinicSnap = await (0, import_firestore17.getDoc)(clinicRef);
|
|
4854
|
+
if (!clinicSnap.exists()) {
|
|
4336
4855
|
throw new Error("Clinic not found");
|
|
4337
4856
|
}
|
|
4857
|
+
const clinic = clinicSnap.data();
|
|
4338
4858
|
const now = import_firestore17.Timestamp.now();
|
|
4339
4859
|
const reviewData = {
|
|
4860
|
+
...review,
|
|
4340
4861
|
id: (0, import_firestore17.doc)((0, import_firestore17.collection)(db, "clinic_reviews")).id,
|
|
4341
4862
|
clinicId,
|
|
4342
|
-
patientId: review.patientId,
|
|
4343
|
-
rating: review.rating,
|
|
4344
|
-
comment: review.comment,
|
|
4345
4863
|
createdAt: now,
|
|
4346
4864
|
updatedAt: now,
|
|
4347
4865
|
isVerified: false
|
|
4348
4866
|
};
|
|
4349
4867
|
clinicReviewSchema.parse(reviewData);
|
|
4350
|
-
await (0, import_firestore17.
|
|
4868
|
+
await (0, import_firestore17.addDoc)((0, import_firestore17.collection)(db, "clinic_reviews"), reviewData);
|
|
4351
4869
|
const newRating = clinic.rating ? {
|
|
4352
4870
|
average: (clinic.rating.average * clinic.rating.count + review.rating) / (clinic.rating.count + 1),
|
|
4353
4871
|
count: clinic.rating.count + 1
|
|
@@ -4363,28 +4881,24 @@ async function addReview(db, clinicId, review) {
|
|
|
4363
4881
|
...clinic.reviewsInfo,
|
|
4364
4882
|
{
|
|
4365
4883
|
id: reviewData.id,
|
|
4366
|
-
|
|
4367
|
-
|
|
4368
|
-
|
|
4369
|
-
|
|
4370
|
-
// This should be fetched from patient service
|
|
4371
|
-
patientPhoto: "",
|
|
4372
|
-
// This should be fetched from patient service
|
|
4373
|
-
createdAt: now,
|
|
4374
|
-
updatedAt: now
|
|
4884
|
+
patientId: reviewData.patientId,
|
|
4885
|
+
rating: reviewData.rating,
|
|
4886
|
+
comment: reviewData.comment,
|
|
4887
|
+
createdAt: reviewData.createdAt
|
|
4375
4888
|
}
|
|
4376
4889
|
]
|
|
4377
4890
|
},
|
|
4378
|
-
|
|
4379
|
-
//
|
|
4380
|
-
|
|
4381
|
-
//
|
|
4891
|
+
"system",
|
|
4892
|
+
// System update, no admin ID needed
|
|
4893
|
+
null,
|
|
4894
|
+
// No clinic admin service needed for system updates
|
|
4895
|
+
app
|
|
4382
4896
|
);
|
|
4383
4897
|
return reviewData;
|
|
4384
4898
|
}
|
|
4385
4899
|
|
|
4386
4900
|
// src/services/clinic/utils/tag.utils.ts
|
|
4387
|
-
async function addTags(db, clinicId, adminId, newTags, clinicAdminService) {
|
|
4901
|
+
async function addTags(db, clinicId, adminId, newTags, clinicAdminService, app) {
|
|
4388
4902
|
const clinic = await getClinic(db, clinicId);
|
|
4389
4903
|
if (!clinic) {
|
|
4390
4904
|
throw new Error("Clinic not found");
|
|
@@ -4393,7 +4907,8 @@ async function addTags(db, clinicId, adminId, newTags, clinicAdminService) {
|
|
|
4393
4907
|
if (!admin) {
|
|
4394
4908
|
throw new Error("Admin not found");
|
|
4395
4909
|
}
|
|
4396
|
-
|
|
4910
|
+
const hasPermission = admin.isGroupOwner && admin.clinicGroupId === clinic.clinicGroupId || admin.clinicsManaged.includes(clinicId) && clinic.admins && clinic.admins.includes(adminId);
|
|
4911
|
+
if (!hasPermission) {
|
|
4397
4912
|
throw new Error("Admin does not have permission to update this clinic");
|
|
4398
4913
|
}
|
|
4399
4914
|
const updatedTags = [.../* @__PURE__ */ new Set([...clinic.tags, ...newTags.tags || []])];
|
|
@@ -4404,10 +4919,11 @@ async function addTags(db, clinicId, adminId, newTags, clinicAdminService) {
|
|
|
4404
4919
|
tags: updatedTags
|
|
4405
4920
|
},
|
|
4406
4921
|
adminId,
|
|
4407
|
-
clinicAdminService
|
|
4922
|
+
clinicAdminService,
|
|
4923
|
+
app
|
|
4408
4924
|
);
|
|
4409
4925
|
}
|
|
4410
|
-
async function removeTags(db, clinicId, adminId, tagsToRemove, clinicAdminService) {
|
|
4926
|
+
async function removeTags(db, clinicId, adminId, tagsToRemove, clinicAdminService, app) {
|
|
4411
4927
|
const clinic = await getClinic(db, clinicId);
|
|
4412
4928
|
if (!clinic) {
|
|
4413
4929
|
throw new Error("Clinic not found");
|
|
@@ -4416,14 +4932,12 @@ async function removeTags(db, clinicId, adminId, tagsToRemove, clinicAdminServic
|
|
|
4416
4932
|
if (!admin) {
|
|
4417
4933
|
throw new Error("Admin not found");
|
|
4418
4934
|
}
|
|
4419
|
-
|
|
4935
|
+
const hasPermission = admin.isGroupOwner && admin.clinicGroupId === clinic.clinicGroupId || admin.clinicsManaged.includes(clinicId) && clinic.admins && clinic.admins.includes(adminId);
|
|
4936
|
+
if (!hasPermission) {
|
|
4420
4937
|
throw new Error("Admin does not have permission to update this clinic");
|
|
4421
4938
|
}
|
|
4422
4939
|
const updatedTags = clinic.tags.filter(
|
|
4423
|
-
(tag) =>
|
|
4424
|
-
var _a;
|
|
4425
|
-
return !((_a = tagsToRemove.tags) == null ? void 0 : _a.includes(tag));
|
|
4426
|
-
}
|
|
4940
|
+
(tag) => !tagsToRemove.tags || !tagsToRemove.tags.includes(tag)
|
|
4427
4941
|
);
|
|
4428
4942
|
return updateClinic(
|
|
4429
4943
|
db,
|
|
@@ -4432,7 +4946,8 @@ async function removeTags(db, clinicId, adminId, tagsToRemove, clinicAdminServic
|
|
|
4432
4946
|
tags: updatedTags
|
|
4433
4947
|
},
|
|
4434
4948
|
adminId,
|
|
4435
|
-
clinicAdminService
|
|
4949
|
+
clinicAdminService,
|
|
4950
|
+
app
|
|
4436
4951
|
);
|
|
4437
4952
|
}
|
|
4438
4953
|
|
|
@@ -4502,7 +5017,8 @@ var ClinicService = class extends BaseService {
|
|
|
4502
5017
|
data,
|
|
4503
5018
|
creatorAdminId,
|
|
4504
5019
|
this.clinicGroupService,
|
|
4505
|
-
this.clinicAdminService
|
|
5020
|
+
this.clinicAdminService,
|
|
5021
|
+
this.app
|
|
4506
5022
|
);
|
|
4507
5023
|
}
|
|
4508
5024
|
/**
|
|
@@ -4537,14 +5053,15 @@ var ClinicService = class extends BaseService {
|
|
|
4537
5053
|
clinicId,
|
|
4538
5054
|
data,
|
|
4539
5055
|
adminId,
|
|
4540
|
-
this.clinicAdminService
|
|
5056
|
+
this.clinicAdminService,
|
|
5057
|
+
this.app
|
|
4541
5058
|
);
|
|
4542
5059
|
}
|
|
4543
5060
|
/**
|
|
4544
5061
|
* Dodaje recenziju klinici
|
|
4545
5062
|
*/
|
|
4546
5063
|
async addReview(clinicId, review) {
|
|
4547
|
-
return addReview(this.db, clinicId, review);
|
|
5064
|
+
return addReview(this.db, clinicId, review, this.app);
|
|
4548
5065
|
}
|
|
4549
5066
|
/**
|
|
4550
5067
|
* Deaktivira kliniku
|
|
@@ -4566,7 +5083,8 @@ var ClinicService = class extends BaseService {
|
|
|
4566
5083
|
clinicId,
|
|
4567
5084
|
adminId,
|
|
4568
5085
|
newTags,
|
|
4569
|
-
this.clinicAdminService
|
|
5086
|
+
this.clinicAdminService,
|
|
5087
|
+
this.app
|
|
4570
5088
|
);
|
|
4571
5089
|
}
|
|
4572
5090
|
/**
|
|
@@ -4578,7 +5096,8 @@ var ClinicService = class extends BaseService {
|
|
|
4578
5096
|
clinicId,
|
|
4579
5097
|
adminId,
|
|
4580
5098
|
tagsToRemove,
|
|
4581
|
-
this.clinicAdminService
|
|
5099
|
+
this.clinicAdminService,
|
|
5100
|
+
this.app
|
|
4582
5101
|
);
|
|
4583
5102
|
}
|
|
4584
5103
|
/**
|
|
@@ -4613,12 +5132,21 @@ var ClinicService = class extends BaseService {
|
|
|
4613
5132
|
* @returns The created clinic
|
|
4614
5133
|
*/
|
|
4615
5134
|
async createClinicBranch(clinicGroupId, setupData, adminId) {
|
|
5135
|
+
var _a, _b;
|
|
5136
|
+
console.log("[CLINIC_SERVICE] Starting clinic branch creation", {
|
|
5137
|
+
clinicGroupId,
|
|
5138
|
+
adminId
|
|
5139
|
+
});
|
|
4616
5140
|
const clinicGroup = await this.clinicGroupService.getClinicGroup(
|
|
4617
5141
|
clinicGroupId
|
|
4618
5142
|
);
|
|
4619
5143
|
if (!clinicGroup) {
|
|
5144
|
+
console.error("[CLINIC_SERVICE] Clinic group not found", {
|
|
5145
|
+
clinicGroupId
|
|
5146
|
+
});
|
|
4620
5147
|
throw new Error(`Clinic group with ID ${clinicGroupId} not found`);
|
|
4621
5148
|
}
|
|
5149
|
+
console.log("[CLINIC_SERVICE] Clinic group verified");
|
|
4622
5150
|
const createClinicData = {
|
|
4623
5151
|
clinicGroupId,
|
|
4624
5152
|
name: setupData.name,
|
|
@@ -4627,8 +5155,8 @@ var ClinicService = class extends BaseService {
|
|
|
4627
5155
|
contactInfo: setupData.contactInfo,
|
|
4628
5156
|
workingHours: setupData.workingHours,
|
|
4629
5157
|
tags: setupData.tags,
|
|
4630
|
-
photos: setupData.photos,
|
|
4631
|
-
photosWithTags: setupData.photosWithTags,
|
|
5158
|
+
photos: setupData.photos || [],
|
|
5159
|
+
photosWithTags: setupData.photosWithTags || [],
|
|
4632
5160
|
doctors: [],
|
|
4633
5161
|
services: [],
|
|
4634
5162
|
admins: [adminId],
|
|
@@ -4637,7 +5165,17 @@ var ClinicService = class extends BaseService {
|
|
|
4637
5165
|
logo: setupData.logo,
|
|
4638
5166
|
featuredPhotos: setupData.featuredPhotos || []
|
|
4639
5167
|
};
|
|
5168
|
+
console.log("[CLINIC_SERVICE] Creating clinic branch with data", {
|
|
5169
|
+
name: createClinicData.name,
|
|
5170
|
+
hasLogo: !!createClinicData.logo,
|
|
5171
|
+
photosCount: createClinicData.photos.length,
|
|
5172
|
+
featuredPhotosCount: ((_a = createClinicData.featuredPhotos) == null ? void 0 : _a.length) || 0,
|
|
5173
|
+
photosWithTagsCount: ((_b = createClinicData.photosWithTags) == null ? void 0 : _b.length) || 0
|
|
5174
|
+
});
|
|
4640
5175
|
const clinic = await this.createClinic(createClinicData, adminId);
|
|
5176
|
+
console.log("[CLINIC_SERVICE] Clinic branch created successfully", {
|
|
5177
|
+
clinicId: clinic.id
|
|
5178
|
+
});
|
|
4641
5179
|
return clinic;
|
|
4642
5180
|
}
|
|
4643
5181
|
};
|
|
@@ -4759,12 +5297,38 @@ var AuthService = class extends BaseService {
|
|
|
4759
5297
|
"Clinic group data is required when creating a new group"
|
|
4760
5298
|
);
|
|
4761
5299
|
}
|
|
5300
|
+
console.log("[AUTH] Creating clinic admin first (without group)");
|
|
5301
|
+
const createClinicAdminData = {
|
|
5302
|
+
userRef: firebaseUser.uid,
|
|
5303
|
+
isGroupOwner: true,
|
|
5304
|
+
clinicsManaged: [],
|
|
5305
|
+
contactInfo: contactPerson,
|
|
5306
|
+
roleTitle: data.title,
|
|
5307
|
+
isActive: true
|
|
5308
|
+
// No clinicGroupId yet
|
|
5309
|
+
};
|
|
5310
|
+
let adminProfile;
|
|
5311
|
+
try {
|
|
5312
|
+
adminProfile = await clinicAdminService.createClinicAdmin(
|
|
5313
|
+
createClinicAdminData
|
|
5314
|
+
);
|
|
5315
|
+
console.log("[AUTH] Clinic admin created successfully", {
|
|
5316
|
+
adminId: adminProfile.id
|
|
5317
|
+
});
|
|
5318
|
+
} catch (adminCreationError) {
|
|
5319
|
+
console.error(
|
|
5320
|
+
"[AUTH] Clinic admin creation failed:",
|
|
5321
|
+
adminCreationError
|
|
5322
|
+
);
|
|
5323
|
+
throw adminCreationError;
|
|
5324
|
+
}
|
|
4762
5325
|
const createClinicGroupData = {
|
|
4763
5326
|
name: data.clinicGroupData.name,
|
|
4764
5327
|
hqLocation: data.clinicGroupData.hqLocation,
|
|
4765
5328
|
contactInfo: data.clinicGroupData.contactInfo,
|
|
4766
5329
|
contactPerson,
|
|
4767
|
-
ownerId:
|
|
5330
|
+
ownerId: adminProfile.id,
|
|
5331
|
+
// Use admin profile ID, not user UID
|
|
4768
5332
|
isActive: true,
|
|
4769
5333
|
logo: data.clinicGroupData.logo || null,
|
|
4770
5334
|
subscriptionModel: data.clinicGroupData.subscriptionModel || "no_subscription" /* NO_SUBSCRIPTION */
|
|
@@ -4772,13 +5336,24 @@ var AuthService = class extends BaseService {
|
|
|
4772
5336
|
console.log("[AUTH] Clinic group data prepared", {
|
|
4773
5337
|
groupName: createClinicGroupData.name
|
|
4774
5338
|
});
|
|
5339
|
+
let clinicGroup;
|
|
4775
5340
|
try {
|
|
4776
|
-
await clinicGroupService.createClinicGroup(
|
|
5341
|
+
clinicGroup = await clinicGroupService.createClinicGroup(
|
|
4777
5342
|
createClinicGroupData,
|
|
4778
|
-
|
|
4779
|
-
|
|
5343
|
+
adminProfile.id,
|
|
5344
|
+
// Use admin profile ID, not user UID
|
|
5345
|
+
false
|
|
5346
|
+
// This is not a default group since we're providing complete data
|
|
4780
5347
|
);
|
|
4781
|
-
console.log("[AUTH] Clinic group created successfully"
|
|
5348
|
+
console.log("[AUTH] Clinic group created successfully", {
|
|
5349
|
+
groupId: clinicGroup.id
|
|
5350
|
+
});
|
|
5351
|
+
console.log("[AUTH] Updating admin with clinic group ID");
|
|
5352
|
+
await clinicAdminService.updateClinicAdmin(adminProfile.id, {
|
|
5353
|
+
// Use admin profile ID, not user UID
|
|
5354
|
+
clinicGroupId: clinicGroup.id
|
|
5355
|
+
});
|
|
5356
|
+
console.log("[AUTH] Admin updated with clinic group ID successfully");
|
|
4782
5357
|
} catch (groupCreationError) {
|
|
4783
5358
|
console.error(
|
|
4784
5359
|
"[AUTH] Clinic group creation failed:",
|
|
@@ -4851,9 +5426,14 @@ var AuthService = class extends BaseService {
|
|
|
4851
5426
|
roleTitle: data.title,
|
|
4852
5427
|
isActive: true
|
|
4853
5428
|
};
|
|
5429
|
+
let adminProfile;
|
|
4854
5430
|
try {
|
|
4855
|
-
await clinicAdminService.createClinicAdmin(
|
|
4856
|
-
|
|
5431
|
+
adminProfile = await clinicAdminService.createClinicAdmin(
|
|
5432
|
+
createClinicAdminData
|
|
5433
|
+
);
|
|
5434
|
+
console.log("[AUTH] Clinic admin created successfully", {
|
|
5435
|
+
adminId: adminProfile.id
|
|
5436
|
+
});
|
|
4857
5437
|
} catch (adminCreationError) {
|
|
4858
5438
|
console.error(
|
|
4859
5439
|
"[AUTH] Clinic admin creation failed:",
|