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