@blackcode_sa/metaestetics-api 1.8.12 → 1.8.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/admin/index.d.mts +2 -0
- package/dist/admin/index.d.ts +2 -0
- package/dist/backoffice/index.d.mts +1 -0
- package/dist/backoffice/index.d.ts +1 -0
- package/dist/index.d.mts +28 -0
- package/dist/index.d.ts +28 -0
- package/dist/index.js +140 -222
- package/dist/index.mjs +143 -223
- package/package.json +1 -1
- package/src/admin/scripts/migrateProcedures.js +23 -0
- package/src/admin/scripts/serviceAccountKey.json +13 -0
- package/src/services/clinic/clinic.service.ts +33 -0
- package/src/services/clinic/utils/filter.utils.ts +54 -225
- package/src/services/practitioner/practitioner.service.ts +47 -115
- package/src/services/procedure/procedure.service.ts +43 -3
- package/src/types/clinic/index.ts +1 -0
- package/src/types/practitioner/index.ts +1 -0
package/dist/index.mjs
CHANGED
|
@@ -6257,6 +6257,7 @@ var PractitionerService = class extends BaseService {
|
|
|
6257
6257
|
trustworthiness: 0,
|
|
6258
6258
|
recommendationPercentage: 0
|
|
6259
6259
|
};
|
|
6260
|
+
const fullNameLower = `${validData.basicInfo.firstName} ${validData.basicInfo.lastName}`.toLowerCase();
|
|
6260
6261
|
const practitioner = {
|
|
6261
6262
|
id: practitionerId,
|
|
6262
6263
|
userRef: validData.userRef,
|
|
@@ -6264,6 +6265,8 @@ var PractitionerService = class extends BaseService {
|
|
|
6264
6265
|
validData.basicInfo,
|
|
6265
6266
|
practitionerId
|
|
6266
6267
|
),
|
|
6268
|
+
fullNameLower,
|
|
6269
|
+
// Ensure this is present
|
|
6267
6270
|
certification: validData.certification,
|
|
6268
6271
|
clinics: validData.clinics || [],
|
|
6269
6272
|
clinicWorkingHours: validData.clinicWorkingHours || [],
|
|
@@ -6359,6 +6362,7 @@ var PractitionerService = class extends BaseService {
|
|
|
6359
6362
|
}
|
|
6360
6363
|
const finalClinicsInfo = validatedData.clinicsInfo && validatedData.clinicsInfo.length > 0 ? validatedData.clinicsInfo : clinicsInfo;
|
|
6361
6364
|
const proceduresInfo = [];
|
|
6365
|
+
const fullNameLowerDraft = `${validatedData.basicInfo.firstName} ${validatedData.basicInfo.lastName}`.toLowerCase();
|
|
6362
6366
|
const practitionerData = {
|
|
6363
6367
|
id: practitionerId,
|
|
6364
6368
|
userRef: "",
|
|
@@ -6367,6 +6371,8 @@ var PractitionerService = class extends BaseService {
|
|
|
6367
6371
|
validatedData.basicInfo,
|
|
6368
6372
|
practitionerId
|
|
6369
6373
|
),
|
|
6374
|
+
fullNameLower: fullNameLowerDraft,
|
|
6375
|
+
// Ensure this is present
|
|
6370
6376
|
certification: validatedData.certification,
|
|
6371
6377
|
clinics,
|
|
6372
6378
|
clinicWorkingHours: validatedData.clinicWorkingHours || [],
|
|
@@ -6872,10 +6878,6 @@ var PractitionerService = class extends BaseService {
|
|
|
6872
6878
|
*/
|
|
6873
6879
|
async getPractitionersByFilters(filters) {
|
|
6874
6880
|
try {
|
|
6875
|
-
console.log(
|
|
6876
|
-
"[PRACTITIONER_SERVICE] Starting practitioner filtering with criteria:",
|
|
6877
|
-
filters
|
|
6878
|
-
);
|
|
6879
6881
|
const constraints = [];
|
|
6880
6882
|
if (!filters.includeDraftPractitioners) {
|
|
6881
6883
|
constraints.push(where10("status", "==", "active" /* ACTIVE */));
|
|
@@ -6890,60 +6892,40 @@ var PractitionerService = class extends BaseService {
|
|
|
6890
6892
|
)
|
|
6891
6893
|
);
|
|
6892
6894
|
}
|
|
6893
|
-
|
|
6894
|
-
|
|
6895
|
-
|
|
6896
|
-
|
|
6897
|
-
constraints.push(startAfter6(filters.lastDoc));
|
|
6898
|
-
}
|
|
6899
|
-
constraints.push(limit7(filters.pagination));
|
|
6895
|
+
if (filters.nameSearch && filters.nameSearch.trim()) {
|
|
6896
|
+
const searchTerm = filters.nameSearch.trim().toLowerCase();
|
|
6897
|
+
constraints.push(where10("fullNameLower", ">=", searchTerm));
|
|
6898
|
+
constraints.push(where10("fullNameLower", "<=", searchTerm + "\uF8FF"));
|
|
6900
6899
|
}
|
|
6901
|
-
|
|
6902
|
-
|
|
6903
|
-
|
|
6904
|
-
|
|
6905
|
-
|
|
6906
|
-
|
|
6907
|
-
|
|
6908
|
-
|
|
6909
|
-
let practitioners = querySnapshot.docs.map((doc37) => {
|
|
6910
|
-
return { ...doc37.data(), id: doc37.id };
|
|
6911
|
-
});
|
|
6912
|
-
const lastDoc = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
|
|
6913
|
-
if (filters.nameSearch && filters.nameSearch.trim() !== "") {
|
|
6914
|
-
const searchTerm = filters.nameSearch.toLowerCase().trim();
|
|
6915
|
-
practitioners = practitioners.filter((practitioner) => {
|
|
6916
|
-
const fullName = `${practitioner.basicInfo.firstName} ${practitioner.basicInfo.lastName}`.toLowerCase();
|
|
6917
|
-
return fullName.includes(searchTerm);
|
|
6918
|
-
});
|
|
6900
|
+
if (filters.procedureTechnology) {
|
|
6901
|
+
constraints.push(where10("proceduresInfo.technologyName", "==", filters.procedureTechnology));
|
|
6902
|
+
} else if (filters.procedureSubcategory) {
|
|
6903
|
+
constraints.push(where10("proceduresInfo.subcategoryName", "==", filters.procedureSubcategory));
|
|
6904
|
+
} else if (filters.procedureCategory) {
|
|
6905
|
+
constraints.push(where10("proceduresInfo.categoryName", "==", filters.procedureCategory));
|
|
6906
|
+
} else if (filters.procedureFamily) {
|
|
6907
|
+
constraints.push(where10("proceduresInfo.family", "==", filters.procedureFamily));
|
|
6919
6908
|
}
|
|
6920
|
-
if (filters.
|
|
6921
|
-
|
|
6922
|
-
return filters.specialties.every(
|
|
6923
|
-
(specialty) => practitioner.certification.specialties.includes(specialty)
|
|
6924
|
-
);
|
|
6925
|
-
});
|
|
6909
|
+
if (filters.minRating !== void 0) {
|
|
6910
|
+
constraints.push(where10("reviewInfo.averageRating", ">=", filters.minRating));
|
|
6926
6911
|
}
|
|
6927
|
-
if (filters.
|
|
6928
|
-
|
|
6929
|
-
|
|
6930
|
-
|
|
6931
|
-
|
|
6932
|
-
|
|
6933
|
-
|
|
6934
|
-
|
|
6935
|
-
|
|
6936
|
-
|
|
6937
|
-
|
|
6938
|
-
|
|
6939
|
-
}
|
|
6940
|
-
if (filters.procedureFamily) {
|
|
6941
|
-
return procedure.family === filters.procedureFamily;
|
|
6942
|
-
}
|
|
6943
|
-
return false;
|
|
6944
|
-
});
|
|
6945
|
-
});
|
|
6912
|
+
if (filters.maxRating !== void 0) {
|
|
6913
|
+
constraints.push(where10("reviewInfo.averageRating", "<=", filters.maxRating));
|
|
6914
|
+
}
|
|
6915
|
+
constraints.push(orderBy4("fullNameLower"));
|
|
6916
|
+
if (filters.lastDoc) {
|
|
6917
|
+
if (typeof filters.lastDoc.data === "function") {
|
|
6918
|
+
constraints.push(startAfter6(filters.lastDoc));
|
|
6919
|
+
} else if (Array.isArray(filters.lastDoc)) {
|
|
6920
|
+
constraints.push(startAfter6(...filters.lastDoc));
|
|
6921
|
+
} else {
|
|
6922
|
+
constraints.push(startAfter6(filters.lastDoc));
|
|
6923
|
+
}
|
|
6946
6924
|
}
|
|
6925
|
+
constraints.push(limit7(filters.pagination || 5));
|
|
6926
|
+
const q = query10(collection10(this.db, PRACTITIONERS_COLLECTION), ...constraints);
|
|
6927
|
+
const querySnapshot = await getDocs10(q);
|
|
6928
|
+
let practitioners = querySnapshot.docs.map((doc37) => ({ ...doc37.data(), id: doc37.id }));
|
|
6947
6929
|
if (filters.location && filters.radiusInKm && filters.radiusInKm > 0) {
|
|
6948
6930
|
const location = filters.location;
|
|
6949
6931
|
const radiusInKm = filters.radiusInKm;
|
|
@@ -6959,22 +6941,7 @@ var PractitionerService = class extends BaseService {
|
|
|
6959
6941
|
});
|
|
6960
6942
|
});
|
|
6961
6943
|
}
|
|
6962
|
-
|
|
6963
|
-
practitioners = practitioners.filter(
|
|
6964
|
-
(p) => p.reviewInfo.averageRating >= filters.minRating
|
|
6965
|
-
);
|
|
6966
|
-
}
|
|
6967
|
-
if (filters.maxRating !== void 0) {
|
|
6968
|
-
practitioners = practitioners.filter(
|
|
6969
|
-
(p) => p.reviewInfo.averageRating <= filters.maxRating
|
|
6970
|
-
);
|
|
6971
|
-
}
|
|
6972
|
-
console.log(
|
|
6973
|
-
`[PRACTITIONER_SERVICE] Filtered to ${practitioners.length} practitioners`
|
|
6974
|
-
);
|
|
6975
|
-
if (filters.pagination && filters.pagination > 0) {
|
|
6976
|
-
practitioners = practitioners.slice(0, filters.pagination);
|
|
6977
|
-
}
|
|
6944
|
+
const lastDoc = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
|
|
6978
6945
|
return {
|
|
6979
6946
|
practitioners,
|
|
6980
6947
|
lastDoc
|
|
@@ -8190,8 +8157,10 @@ var ClinicGroupService = class extends BaseService {
|
|
|
8190
8157
|
|
|
8191
8158
|
// src/services/clinic/clinic.service.ts
|
|
8192
8159
|
import {
|
|
8160
|
+
collection as collection16,
|
|
8193
8161
|
doc as doc15,
|
|
8194
8162
|
getDoc as getDoc18,
|
|
8163
|
+
getDocs as getDocs16,
|
|
8195
8164
|
updateDoc as updateDoc15,
|
|
8196
8165
|
serverTimestamp as serverTimestamp14,
|
|
8197
8166
|
writeBatch as writeBatch4,
|
|
@@ -8665,170 +8634,66 @@ import {
|
|
|
8665
8634
|
limit as limit9,
|
|
8666
8635
|
orderBy as orderBy5
|
|
8667
8636
|
} from "firebase/firestore";
|
|
8668
|
-
import {
|
|
8637
|
+
import { distanceBetween as distanceBetween4 } from "geofire-common";
|
|
8669
8638
|
async function getClinicsByFilters(db, filters) {
|
|
8670
|
-
|
|
8671
|
-
"[FILTER_UTILS] Starting clinic filtering with criteria:",
|
|
8672
|
-
filters
|
|
8673
|
-
);
|
|
8674
|
-
const isGeoQuery = filters.center && filters.radiusInKm && filters.radiusInKm > 0;
|
|
8639
|
+
var _a;
|
|
8675
8640
|
const constraints = [];
|
|
8676
|
-
|
|
8677
|
-
constraints.push(where15("isActive", "==", filters.isActive));
|
|
8678
|
-
} else {
|
|
8679
|
-
constraints.push(where15("isActive", "==", true));
|
|
8680
|
-
}
|
|
8641
|
+
constraints.push(where15("isActive", "==", (_a = filters.isActive) != null ? _a : true));
|
|
8681
8642
|
if (filters.tags && filters.tags.length > 0) {
|
|
8682
8643
|
constraints.push(where15("tags", "array-contains", filters.tags[0]));
|
|
8683
8644
|
}
|
|
8684
8645
|
if (filters.procedureTechnology) {
|
|
8685
|
-
constraints.push(
|
|
8686
|
-
where15("servicesInfo.technology", "==", filters.procedureTechnology)
|
|
8687
|
-
);
|
|
8646
|
+
constraints.push(where15("servicesInfo.technology", "==", filters.procedureTechnology));
|
|
8688
8647
|
} else if (filters.procedureSubcategory) {
|
|
8689
|
-
constraints.push(
|
|
8690
|
-
where15("servicesInfo.subCategory", "==", filters.procedureSubcategory)
|
|
8691
|
-
);
|
|
8648
|
+
constraints.push(where15("servicesInfo.subCategory", "==", filters.procedureSubcategory));
|
|
8692
8649
|
} else if (filters.procedureCategory) {
|
|
8693
|
-
constraints.push(
|
|
8694
|
-
where15("servicesInfo.category", "==", filters.procedureCategory)
|
|
8695
|
-
);
|
|
8650
|
+
constraints.push(where15("servicesInfo.category", "==", filters.procedureCategory));
|
|
8696
8651
|
} else if (filters.procedureFamily) {
|
|
8697
|
-
constraints.push(
|
|
8698
|
-
|
|
8699
|
-
|
|
8700
|
-
|
|
8701
|
-
if (filters.
|
|
8702
|
-
|
|
8703
|
-
constraints.push(
|
|
8704
|
-
|
|
8705
|
-
|
|
8706
|
-
}
|
|
8707
|
-
|
|
8708
|
-
|
|
8709
|
-
|
|
8710
|
-
if (
|
|
8711
|
-
|
|
8712
|
-
|
|
8713
|
-
|
|
8714
|
-
|
|
8715
|
-
|
|
8716
|
-
|
|
8717
|
-
)
|
|
8718
|
-
|
|
8719
|
-
for (const bound of bounds) {
|
|
8720
|
-
const geoConstraints = [
|
|
8721
|
-
...constraints,
|
|
8722
|
-
where15("location.geohash", ">=", bound[0]),
|
|
8723
|
-
where15("location.geohash", "<=", bound[1])
|
|
8724
|
-
];
|
|
8725
|
-
const q = query15(collection15(db, CLINICS_COLLECTION), ...geoConstraints);
|
|
8726
|
-
const querySnapshot = await getDocs15(q);
|
|
8727
|
-
console.log(
|
|
8728
|
-
`[FILTER_UTILS] Found ${querySnapshot.docs.length} clinics in geo bound`
|
|
8729
|
-
);
|
|
8730
|
-
for (const doc37 of querySnapshot.docs) {
|
|
8731
|
-
const clinic = { ...doc37.data(), id: doc37.id };
|
|
8732
|
-
const distance = distanceBetween4(
|
|
8733
|
-
[center.latitude, center.longitude],
|
|
8734
|
-
[clinic.location.latitude, clinic.location.longitude]
|
|
8735
|
-
);
|
|
8736
|
-
const distanceInKm = distance / 1e3;
|
|
8737
|
-
if (distanceInKm <= radiusInKm) {
|
|
8738
|
-
matchingClinics.push({
|
|
8739
|
-
...clinic,
|
|
8740
|
-
distance: distanceInKm
|
|
8741
|
-
});
|
|
8742
|
-
}
|
|
8743
|
-
}
|
|
8744
|
-
}
|
|
8745
|
-
let filteredClinics = matchingClinics;
|
|
8746
|
-
if (filters.tags && filters.tags.length > 1) {
|
|
8747
|
-
filteredClinics = filteredClinics.filter((clinic) => {
|
|
8748
|
-
return filters.tags.every((tag) => clinic.tags.includes(tag));
|
|
8749
|
-
});
|
|
8750
|
-
}
|
|
8751
|
-
if (filters.minRating !== void 0) {
|
|
8752
|
-
filteredClinics = filteredClinics.filter(
|
|
8753
|
-
(clinic) => clinic.reviewInfo.averageRating >= filters.minRating
|
|
8754
|
-
);
|
|
8755
|
-
}
|
|
8756
|
-
if (filters.maxRating !== void 0) {
|
|
8757
|
-
filteredClinics = filteredClinics.filter(
|
|
8758
|
-
(clinic) => clinic.reviewInfo.averageRating <= filters.maxRating
|
|
8759
|
-
);
|
|
8760
|
-
}
|
|
8761
|
-
filteredClinics.sort((a, b) => a.distance - b.distance);
|
|
8762
|
-
if (filters.pagination && filters.pagination > 0) {
|
|
8763
|
-
let startIndex = 0;
|
|
8764
|
-
if (filters.lastDoc) {
|
|
8765
|
-
const lastDocIndex = filteredClinics.findIndex(
|
|
8766
|
-
(clinic) => clinic.id === filters.lastDoc.id
|
|
8767
|
-
);
|
|
8768
|
-
if (lastDocIndex !== -1) {
|
|
8769
|
-
startIndex = lastDocIndex + 1;
|
|
8770
|
-
}
|
|
8771
|
-
}
|
|
8772
|
-
const paginatedClinics = filteredClinics.slice(
|
|
8773
|
-
startIndex,
|
|
8774
|
-
startIndex + filters.pagination
|
|
8775
|
-
);
|
|
8776
|
-
lastVisibleDoc = paginatedClinics.length > 0 ? paginatedClinics[paginatedClinics.length - 1] : null;
|
|
8777
|
-
clinicsResult = paginatedClinics;
|
|
8652
|
+
constraints.push(where15("servicesInfo.procedureFamily", "==", filters.procedureFamily));
|
|
8653
|
+
}
|
|
8654
|
+
let useNameLower = false;
|
|
8655
|
+
let searchTerm = "";
|
|
8656
|
+
if (filters.nameSearch && filters.nameSearch.trim()) {
|
|
8657
|
+
searchTerm = filters.nameSearch.trim().toLowerCase();
|
|
8658
|
+
constraints.push(where15("nameLower", ">=", searchTerm));
|
|
8659
|
+
constraints.push(where15("nameLower", "<=", searchTerm + "\uF8FF"));
|
|
8660
|
+
useNameLower = true;
|
|
8661
|
+
}
|
|
8662
|
+
if (filters.minRating !== void 0) {
|
|
8663
|
+
constraints.push(where15("reviewInfo.averageRating", ">=", filters.minRating));
|
|
8664
|
+
}
|
|
8665
|
+
if (filters.maxRating !== void 0) {
|
|
8666
|
+
constraints.push(where15("reviewInfo.averageRating", "<=", filters.maxRating));
|
|
8667
|
+
}
|
|
8668
|
+
constraints.push(orderBy5("nameLower"));
|
|
8669
|
+
if (filters.lastDoc) {
|
|
8670
|
+
if (typeof filters.lastDoc.data === "function") {
|
|
8671
|
+
constraints.push(startAfter8(filters.lastDoc));
|
|
8672
|
+
} else if (Array.isArray(filters.lastDoc)) {
|
|
8673
|
+
constraints.push(startAfter8(...filters.lastDoc));
|
|
8778
8674
|
} else {
|
|
8779
|
-
|
|
8675
|
+
constraints.push(startAfter8(filters.lastDoc));
|
|
8780
8676
|
}
|
|
8781
|
-
}
|
|
8782
|
-
|
|
8783
|
-
|
|
8784
|
-
|
|
8785
|
-
|
|
8786
|
-
|
|
8787
|
-
|
|
8788
|
-
|
|
8677
|
+
}
|
|
8678
|
+
constraints.push(limit9(filters.pagination || 5));
|
|
8679
|
+
const q = query15(collection15(db, CLINICS_COLLECTION), ...constraints);
|
|
8680
|
+
const querySnapshot = await getDocs15(q);
|
|
8681
|
+
let clinics = querySnapshot.docs.map((doc37) => ({ ...doc37.data(), id: doc37.id }));
|
|
8682
|
+
if (filters.tags && filters.tags.length > 1) {
|
|
8683
|
+
clinics = clinics.filter((clinic) => filters.tags.every((tag) => clinic.tags.includes(tag)));
|
|
8684
|
+
}
|
|
8685
|
+
if (filters.center && filters.radiusInKm) {
|
|
8686
|
+
clinics = clinics.filter((clinic) => {
|
|
8687
|
+
const distance = distanceBetween4(
|
|
8688
|
+
[filters.center.latitude, filters.center.longitude],
|
|
8689
|
+
[clinic.location.latitude, clinic.location.longitude]
|
|
8690
|
+
) / 1e3;
|
|
8691
|
+
clinic.distance = distance;
|
|
8692
|
+
return distance <= filters.radiusInKm;
|
|
8789
8693
|
});
|
|
8790
|
-
let filteredClinics = clinics;
|
|
8791
|
-
if (filters.center) {
|
|
8792
|
-
const center = filters.center;
|
|
8793
|
-
const clinicsWithDistance = [];
|
|
8794
|
-
filteredClinics.forEach((clinic) => {
|
|
8795
|
-
const distance = distanceBetween4(
|
|
8796
|
-
[center.latitude, center.longitude],
|
|
8797
|
-
[clinic.location.latitude, clinic.location.longitude]
|
|
8798
|
-
);
|
|
8799
|
-
clinicsWithDistance.push({
|
|
8800
|
-
...clinic,
|
|
8801
|
-
distance: distance / 1e3
|
|
8802
|
-
// Convert to kilometers
|
|
8803
|
-
});
|
|
8804
|
-
});
|
|
8805
|
-
filteredClinics = clinicsWithDistance;
|
|
8806
|
-
filteredClinics.sort(
|
|
8807
|
-
(a, b) => a.distance - b.distance
|
|
8808
|
-
);
|
|
8809
|
-
}
|
|
8810
|
-
if (filters.tags && filters.tags.length > 1) {
|
|
8811
|
-
filteredClinics = filteredClinics.filter((clinic) => {
|
|
8812
|
-
return filters.tags.every((tag) => clinic.tags.includes(tag));
|
|
8813
|
-
});
|
|
8814
|
-
}
|
|
8815
|
-
if (filters.minRating !== void 0) {
|
|
8816
|
-
filteredClinics = filteredClinics.filter(
|
|
8817
|
-
(clinic) => clinic.reviewInfo.averageRating >= filters.minRating
|
|
8818
|
-
);
|
|
8819
|
-
}
|
|
8820
|
-
if (filters.maxRating !== void 0) {
|
|
8821
|
-
filteredClinics = filteredClinics.filter(
|
|
8822
|
-
(clinic) => clinic.reviewInfo.averageRating <= filters.maxRating
|
|
8823
|
-
);
|
|
8824
|
-
}
|
|
8825
|
-
lastVisibleDoc = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
|
|
8826
|
-
clinicsResult = filteredClinics;
|
|
8827
8694
|
}
|
|
8828
|
-
|
|
8829
|
-
|
|
8830
|
-
lastDoc: lastVisibleDoc
|
|
8831
|
-
};
|
|
8695
|
+
const lastVisibleDoc = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
|
|
8696
|
+
return { clinics, lastDoc: lastVisibleDoc };
|
|
8832
8697
|
}
|
|
8833
8698
|
|
|
8834
8699
|
// src/services/clinic/clinic.service.ts
|
|
@@ -8964,6 +8829,8 @@ var ClinicService = class extends BaseService {
|
|
|
8964
8829
|
id: clinicId,
|
|
8965
8830
|
clinicGroupId: validatedData.clinicGroupId,
|
|
8966
8831
|
name: validatedData.name,
|
|
8832
|
+
nameLower: validatedData.name.toLowerCase(),
|
|
8833
|
+
// Add this line
|
|
8967
8834
|
description: validatedData.description,
|
|
8968
8835
|
location: { ...location, geohash: hash },
|
|
8969
8836
|
contactInfo: validatedData.contactInfo,
|
|
@@ -9064,6 +8931,9 @@ var ClinicService = class extends BaseService {
|
|
|
9064
8931
|
updatePayload[field] = validatedData[field];
|
|
9065
8932
|
}
|
|
9066
8933
|
}
|
|
8934
|
+
if (validatedData.name) {
|
|
8935
|
+
updatePayload.nameLower = validatedData.name.toLowerCase();
|
|
8936
|
+
}
|
|
9067
8937
|
if (validatedData.location) {
|
|
9068
8938
|
const loc = validatedData.location;
|
|
9069
8939
|
updatePayload.location = {
|
|
@@ -9239,6 +9109,27 @@ var ClinicService = class extends BaseService {
|
|
|
9239
9109
|
async getClinicsByFilters(filters) {
|
|
9240
9110
|
return getClinicsByFilters(this.db, filters);
|
|
9241
9111
|
}
|
|
9112
|
+
/**
|
|
9113
|
+
* Gets all clinics with minimal info for map display (id, name, address, latitude, longitude)
|
|
9114
|
+
* This is optimized for mobile map usage to reduce payload size.
|
|
9115
|
+
* @returns Array of minimal clinic info for map
|
|
9116
|
+
*/
|
|
9117
|
+
async getClinicsForMap() {
|
|
9118
|
+
const clinicsRef = collection16(this.db, CLINICS_COLLECTION);
|
|
9119
|
+
const snapshot = await getDocs16(clinicsRef);
|
|
9120
|
+
const clinicsForMap = snapshot.docs.map((doc37) => {
|
|
9121
|
+
var _a, _b, _c;
|
|
9122
|
+
const data = doc37.data();
|
|
9123
|
+
return {
|
|
9124
|
+
id: doc37.id,
|
|
9125
|
+
name: data.name,
|
|
9126
|
+
address: ((_a = data.location) == null ? void 0 : _a.address) || "",
|
|
9127
|
+
latitude: (_b = data.location) == null ? void 0 : _b.latitude,
|
|
9128
|
+
longitude: (_c = data.location) == null ? void 0 : _c.longitude
|
|
9129
|
+
};
|
|
9130
|
+
});
|
|
9131
|
+
return clinicsForMap;
|
|
9132
|
+
}
|
|
9242
9133
|
};
|
|
9243
9134
|
|
|
9244
9135
|
// src/services/auth/utils/firebase.utils.ts
|
|
@@ -15087,7 +14978,7 @@ var ProcedureService = class extends BaseService {
|
|
|
15087
14978
|
}
|
|
15088
14979
|
let finalCategoryId = existingProcedure.category.id;
|
|
15089
14980
|
if (validatedData.name) {
|
|
15090
|
-
updatedProcedureData.nameLower = validatedData.
|
|
14981
|
+
updatedProcedureData.nameLower = validatedData.name.toLowerCase();
|
|
15091
14982
|
}
|
|
15092
14983
|
if (validatedData.categoryId) {
|
|
15093
14984
|
const category = await this.categoryService.getById(
|
|
@@ -15314,7 +15205,13 @@ var ProcedureService = class extends BaseService {
|
|
|
15314
15205
|
constraints.push(orderBy17("nameLower"));
|
|
15315
15206
|
}
|
|
15316
15207
|
if (filters.lastDoc) {
|
|
15317
|
-
|
|
15208
|
+
if (typeof filters.lastDoc.data === "function") {
|
|
15209
|
+
constraints.push(startAfter13(filters.lastDoc));
|
|
15210
|
+
} else if (Array.isArray(filters.lastDoc)) {
|
|
15211
|
+
constraints.push(startAfter13(...filters.lastDoc));
|
|
15212
|
+
} else {
|
|
15213
|
+
constraints.push(startAfter13(filters.lastDoc));
|
|
15214
|
+
}
|
|
15318
15215
|
}
|
|
15319
15216
|
if (filters.pagination && filters.pagination > 0) {
|
|
15320
15217
|
constraints.push(limit15(filters.pagination));
|
|
@@ -15493,6 +15390,29 @@ var ProcedureService = class extends BaseService {
|
|
|
15493
15390
|
const savedDoc = await getDoc32(procedureRef);
|
|
15494
15391
|
return savedDoc.data();
|
|
15495
15392
|
}
|
|
15393
|
+
/**
|
|
15394
|
+
* Gets all procedures with minimal info for map display (id, name, clinicId, clinicName, address, latitude, longitude)
|
|
15395
|
+
* This is optimized for mobile map usage to reduce payload size.
|
|
15396
|
+
* @returns Array of minimal procedure info for map
|
|
15397
|
+
*/
|
|
15398
|
+
async getProceduresForMap() {
|
|
15399
|
+
const proceduresRef = collection29(this.db, PROCEDURES_COLLECTION);
|
|
15400
|
+
const snapshot = await getDocs29(proceduresRef);
|
|
15401
|
+
const proceduresForMap = snapshot.docs.map((doc37) => {
|
|
15402
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
15403
|
+
const data = doc37.data();
|
|
15404
|
+
return {
|
|
15405
|
+
id: doc37.id,
|
|
15406
|
+
name: data.name,
|
|
15407
|
+
clinicId: (_a = data.clinicInfo) == null ? void 0 : _a.id,
|
|
15408
|
+
clinicName: (_b = data.clinicInfo) == null ? void 0 : _b.name,
|
|
15409
|
+
address: ((_d = (_c = data.clinicInfo) == null ? void 0 : _c.location) == null ? void 0 : _d.address) || "",
|
|
15410
|
+
latitude: (_f = (_e = data.clinicInfo) == null ? void 0 : _e.location) == null ? void 0 : _f.latitude,
|
|
15411
|
+
longitude: (_h = (_g = data.clinicInfo) == null ? void 0 : _g.location) == null ? void 0 : _h.longitude
|
|
15412
|
+
};
|
|
15413
|
+
});
|
|
15414
|
+
return proceduresForMap;
|
|
15415
|
+
}
|
|
15496
15416
|
};
|
|
15497
15417
|
|
|
15498
15418
|
// src/services/reviews/reviews.service.ts
|
package/package.json
CHANGED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
const admin = require("firebase-admin");
|
|
2
|
+
const serviceAccount = require("./serviceAccountKey.json");
|
|
3
|
+
|
|
4
|
+
admin.initializeApp({
|
|
5
|
+
credential: admin.credential.cert(serviceAccount),
|
|
6
|
+
projectId: "metaestetics"
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
const db = admin.firestore();
|
|
10
|
+
|
|
11
|
+
async function migrateProcedures() {
|
|
12
|
+
const snapshot = await db.collection("procedures").get();
|
|
13
|
+
for (const doc of snapshot.docs) {
|
|
14
|
+
const data = doc.data();
|
|
15
|
+
if (!data.nameLower && data.name) {
|
|
16
|
+
await doc.ref.update({ nameLower: data.name.toLowerCase() });
|
|
17
|
+
console.log(`Updated ${doc.id}`);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
console.log("Migration complete!");
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
migrateProcedures();
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{
|
|
2
|
+
"type": "service_account",
|
|
3
|
+
"project_id": "metaestetics",
|
|
4
|
+
"private_key_id": "e2dccd35845667bdebcea99959ca40a52f54d27f",
|
|
5
|
+
"private_key": "-----BEGIN PRIVATE KEY-----\nMIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC7yzLPjlr/6pSA\ns3Og/2kuwdAfoBr8+M2HoVlydy/WXm73u29i9ps+ilvUBB90PRkidBCaBmqOwjdV\n0MEgUWF+7Zi3PLbfuFGX929uzpAEWuNR3ZqiyrtqsnGycNw0tdccH/RM4pTgDrLP\nETyN6HlnKIcaPgpU/qKXasOYEv8UlMRuSAFG6ZjsMr15fHzECgHNUqDwHz4u1aN3\nNDwYAnucVIpCQqKjwp6nxtSO8WSLKP5P/E3J2Dob1EYEPf8UvhXwtWVXXI/rbIQe\nfnQopHSLesvw2poks9hCQXNsLNptCRG3hj1asNZ6HutMPWqQPAKss/FpkkF6/RNu\niOnWOzf/AgMBAAECggEAFnQpUx/WSZsmvmy2ep2PWgPaeq2ODIlDKeBk7YbKtXr9\nEanbm52Y2lV4vVTw3dkgVDpEceYqf39BVoVrUg3o9mA6Tk54Hy/OsbjoHfucxKiJ\nXZR9lNFgr1U+uvM7oSHM4pP/heHhoxie0Jti/iS5v1fdL4oTei4oCqq9UEWVMkSS\n52yoBH7oeH15WVp2B3KEVU7cAI5MeFXQxQ8idFfqqShhR5uQnwx8uR38b9vaq+Cy\nK5zV+dStsphVq3/gEsjmFkYe7BgpMQyHkw7kmNuISDYdy/W1G6t0kUNn5LzhJ88E\nICr1FttaNQDeBE4VgnC3Daj1hBOQyrbGszbgxmklgQKBgQDm1f3uyLwmVTsTF3sE\nsggTYsmz9AppI778IuWjhiegfmbWI5YsgGl9c9XOcBCZ+2vI7rIDeFneRxBX4TrT\nAPcT+z8AG5PiJuyOa7Nny+tNzplfPf/2X2MrQXaYvWihPWDZtXmqYY3p/Z8wkYhA\n1C/2vMLyKiP/Md7mtSBXmjgnrwKBgQDQRAQL69osb07mJDNoln+FWyQhJQoVQFSw\npPBkcic0d1gglW7ne2O43mOUG7t3EQBPgXg8xXMiv4dqz1PQpVJp4CewCklbAh/C\nfFmhWCUvgG21Sc3t0hpvsPLN3xeqVOUeB5FNhf5t+j4HqTGClD98Plks0iXVnfFO\nPmNYK764sQKBgD4W+UKtQ86bxlQQUMqmiH2OaOq6jcJSFyEC0fn2L9p/pXGcCNzX\nfYh9C9mHUy/X7NoTOlasnJ+pRcAdmREAhXUec4e340NFbQOx/IPC2fwHwkFYD+1Z\nIveTmC7lY6tbMx3cLmmh6+Ywjg0mWBv39x7LDzTMGPqfk3FC7vwhQ1GJAoGARpoY\nKRZuYsvlGl3BU75ZQpMQH3BYB7ZEP5HasKKGKeIfbQRbkXuh5cT2SvpPxeBsk4dX\nhHqHOotlU88vIbc5xgyoR6RlE8YXkC3pkKm6CW1nQ6LefbXRInYBCcuMUUDwXwq/\ntmErTIsdxikUUKkDEJJuVqRzEQS3DghWU0iZIjECgYEA5PMdyGMZJQVTzP/QjSjC\no5uEDGOAjg/wMGFfXRbKBcJZ1yoqUuSOKuuacyNborfTj3RTckl9uO/I68wnFk5p\nRNNndYQXWAmjSvPBKnRuE+eSE1eDPmpZPPBgJqwbSxUfWMprY7yEWpKF2oEbkzpD\nrUkzrniMVABYZnj8CoNV3DM=\n-----END PRIVATE KEY-----\n",
|
|
6
|
+
"client_email": "firebase-adminsdk-5nsyj@metaestetics.iam.gserviceaccount.com",
|
|
7
|
+
"client_id": "114278988963249785723",
|
|
8
|
+
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
|
|
9
|
+
"token_uri": "https://oauth2.googleapis.com/token",
|
|
10
|
+
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
|
|
11
|
+
"client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/firebase-adminsdk-5nsyj%40metaestetics.iam.gserviceaccount.com",
|
|
12
|
+
"universe_domain": "googleapis.com"
|
|
13
|
+
}
|
|
@@ -244,6 +244,7 @@ export class ClinicService extends BaseService {
|
|
|
244
244
|
id: clinicId,
|
|
245
245
|
clinicGroupId: validatedData.clinicGroupId,
|
|
246
246
|
name: validatedData.name,
|
|
247
|
+
nameLower: validatedData.name.toLowerCase(), // Add this line
|
|
247
248
|
description: validatedData.description,
|
|
248
249
|
location: { ...location, geohash: hash },
|
|
249
250
|
contactInfo: validatedData.contactInfo,
|
|
@@ -384,6 +385,11 @@ export class ClinicService extends BaseService {
|
|
|
384
385
|
}
|
|
385
386
|
}
|
|
386
387
|
|
|
388
|
+
// Always update nameLower if name is changed
|
|
389
|
+
if (validatedData.name) {
|
|
390
|
+
updatePayload.nameLower = validatedData.name.toLowerCase();
|
|
391
|
+
}
|
|
392
|
+
|
|
387
393
|
// Handle location update with geohash
|
|
388
394
|
if (validatedData.location) {
|
|
389
395
|
const loc = validatedData.location;
|
|
@@ -646,4 +652,31 @@ export class ClinicService extends BaseService {
|
|
|
646
652
|
}> {
|
|
647
653
|
return FilterUtils.getClinicsByFilters(this.db, filters);
|
|
648
654
|
}
|
|
655
|
+
|
|
656
|
+
/**
|
|
657
|
+
* Gets all clinics with minimal info for map display (id, name, address, latitude, longitude)
|
|
658
|
+
* This is optimized for mobile map usage to reduce payload size.
|
|
659
|
+
* @returns Array of minimal clinic info for map
|
|
660
|
+
*/
|
|
661
|
+
async getClinicsForMap(): Promise<{
|
|
662
|
+
id: string;
|
|
663
|
+
name: string;
|
|
664
|
+
address: string;
|
|
665
|
+
latitude: number | undefined;
|
|
666
|
+
longitude: number | undefined;
|
|
667
|
+
}[]> {
|
|
668
|
+
const clinicsRef = collection(this.db, CLINICS_COLLECTION);
|
|
669
|
+
const snapshot = await getDocs(clinicsRef);
|
|
670
|
+
const clinicsForMap = snapshot.docs.map(doc => {
|
|
671
|
+
const data = doc.data();
|
|
672
|
+
return {
|
|
673
|
+
id: doc.id,
|
|
674
|
+
name: data.name,
|
|
675
|
+
address: data.location?.address || '',
|
|
676
|
+
latitude: data.location?.latitude,
|
|
677
|
+
longitude: data.location?.longitude,
|
|
678
|
+
};
|
|
679
|
+
});
|
|
680
|
+
return clinicsForMap;
|
|
681
|
+
}
|
|
649
682
|
}
|