@blackcode_sa/metaestetics-api 1.8.13 → 1.8.15
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 +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +536 -213
- package/dist/index.mjs +537 -214
- package/package.json +1 -1
- package/src/services/clinic/utils/filter.utils.ts +242 -57
- package/src/services/practitioner/practitioner.service.ts +195 -82
- package/src/services/procedure/procedure.service.ts +279 -123
- package/src/admin/scripts/migrateProcedures.js +0 -23
- package/src/admin/scripts/serviceAccountKey.json +0 -13
package/dist/index.mjs
CHANGED
|
@@ -6651,6 +6651,7 @@ var PractitionerService = class extends BaseService {
|
|
|
6651
6651
|
validData.basicInfo,
|
|
6652
6652
|
practitionerId
|
|
6653
6653
|
);
|
|
6654
|
+
processedData.fullNameLower = `${processedData.basicInfo.firstName} ${processedData.basicInfo.lastName}`.toLowerCase();
|
|
6654
6655
|
}
|
|
6655
6656
|
const updateData = {
|
|
6656
6657
|
...processedData,
|
|
@@ -6878,80 +6879,163 @@ var PractitionerService = class extends BaseService {
|
|
|
6878
6879
|
*/
|
|
6879
6880
|
async getPractitionersByFilters(filters) {
|
|
6880
6881
|
try {
|
|
6881
|
-
|
|
6882
|
-
if (
|
|
6883
|
-
|
|
6884
|
-
|
|
6885
|
-
|
|
6886
|
-
|
|
6887
|
-
|
|
6888
|
-
|
|
6889
|
-
|
|
6890
|
-
|
|
6891
|
-
|
|
6892
|
-
|
|
6893
|
-
);
|
|
6882
|
+
console.log("[PRACTITIONER_SERVICE] Starting practitioner filtering with fallback strategies");
|
|
6883
|
+
if (filters.location && filters.radiusInKm) {
|
|
6884
|
+
console.log("[PRACTITIONER_SERVICE] Executing geo query:", {
|
|
6885
|
+
location: filters.location,
|
|
6886
|
+
radius: filters.radiusInKm,
|
|
6887
|
+
serviceName: "PractitionerService"
|
|
6888
|
+
});
|
|
6889
|
+
if (!filters.location.latitude || !filters.location.longitude) {
|
|
6890
|
+
console.warn("[PRACTITIONER_SERVICE] Invalid location data:", filters.location);
|
|
6891
|
+
filters.location = void 0;
|
|
6892
|
+
filters.radiusInKm = void 0;
|
|
6893
|
+
}
|
|
6894
6894
|
}
|
|
6895
6895
|
if (filters.nameSearch && filters.nameSearch.trim()) {
|
|
6896
|
-
|
|
6897
|
-
|
|
6898
|
-
|
|
6899
|
-
|
|
6900
|
-
|
|
6901
|
-
|
|
6902
|
-
|
|
6903
|
-
|
|
6904
|
-
|
|
6905
|
-
|
|
6906
|
-
|
|
6907
|
-
|
|
6908
|
-
|
|
6909
|
-
|
|
6910
|
-
|
|
6911
|
-
|
|
6912
|
-
|
|
6913
|
-
|
|
6896
|
+
try {
|
|
6897
|
+
console.log("[PRACTITIONER_SERVICE] Strategy 1: Trying fullNameLower search");
|
|
6898
|
+
const searchTerm = filters.nameSearch.trim().toLowerCase();
|
|
6899
|
+
const constraints = [];
|
|
6900
|
+
if (!filters.includeDraftPractitioners) {
|
|
6901
|
+
constraints.push(where10("status", "==", "active" /* ACTIVE */));
|
|
6902
|
+
}
|
|
6903
|
+
constraints.push(where10("isActive", "==", true));
|
|
6904
|
+
constraints.push(where10("fullNameLower", ">=", searchTerm));
|
|
6905
|
+
constraints.push(where10("fullNameLower", "<=", searchTerm + "\uF8FF"));
|
|
6906
|
+
constraints.push(orderBy4("fullNameLower"));
|
|
6907
|
+
if (filters.lastDoc) {
|
|
6908
|
+
if (typeof filters.lastDoc.data === "function") {
|
|
6909
|
+
constraints.push(startAfter6(filters.lastDoc));
|
|
6910
|
+
} else if (Array.isArray(filters.lastDoc)) {
|
|
6911
|
+
constraints.push(startAfter6(...filters.lastDoc));
|
|
6912
|
+
} else {
|
|
6913
|
+
constraints.push(startAfter6(filters.lastDoc));
|
|
6914
|
+
}
|
|
6915
|
+
}
|
|
6916
|
+
constraints.push(limit7(filters.pagination || 10));
|
|
6917
|
+
const q = query10(collection10(this.db, PRACTITIONERS_COLLECTION), ...constraints);
|
|
6918
|
+
const querySnapshot = await getDocs10(q);
|
|
6919
|
+
const practitioners = querySnapshot.docs.map((doc37) => ({ ...doc37.data(), id: doc37.id }));
|
|
6920
|
+
const lastDoc = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
|
|
6921
|
+
console.log(`[PRACTITIONER_SERVICE] Strategy 1 success: ${practitioners.length} practitioners`);
|
|
6922
|
+
if (practitioners.length < (filters.pagination || 10)) {
|
|
6923
|
+
return { practitioners, lastDoc: null };
|
|
6924
|
+
}
|
|
6925
|
+
return { practitioners, lastDoc };
|
|
6926
|
+
} catch (error) {
|
|
6927
|
+
console.log("[PRACTITIONER_SERVICE] Strategy 1 failed:", error);
|
|
6928
|
+
}
|
|
6914
6929
|
}
|
|
6915
|
-
|
|
6916
|
-
|
|
6917
|
-
|
|
6918
|
-
|
|
6919
|
-
|
|
6920
|
-
|
|
6930
|
+
try {
|
|
6931
|
+
console.log("[PRACTITIONER_SERVICE] Strategy 2: Basic query with createdAt ordering");
|
|
6932
|
+
const constraints = [];
|
|
6933
|
+
if (!filters.includeDraftPractitioners) {
|
|
6934
|
+
constraints.push(where10("status", "==", "active" /* ACTIVE */));
|
|
6935
|
+
}
|
|
6936
|
+
constraints.push(where10("isActive", "==", true));
|
|
6937
|
+
if (filters.certifications && filters.certifications.length > 0) {
|
|
6938
|
+
constraints.push(
|
|
6939
|
+
where10("certification.specialties", "array-contains-any", filters.certifications)
|
|
6940
|
+
);
|
|
6941
|
+
}
|
|
6942
|
+
if (filters.minRating !== void 0) {
|
|
6943
|
+
constraints.push(where10("reviewInfo.averageRating", ">=", filters.minRating));
|
|
6944
|
+
}
|
|
6945
|
+
if (filters.maxRating !== void 0) {
|
|
6946
|
+
constraints.push(where10("reviewInfo.averageRating", "<=", filters.maxRating));
|
|
6947
|
+
}
|
|
6948
|
+
constraints.push(orderBy4("createdAt", "desc"));
|
|
6949
|
+
if (filters.location && filters.radiusInKm) {
|
|
6950
|
+
constraints.push(limit7((filters.pagination || 10) * 2));
|
|
6921
6951
|
} else {
|
|
6922
|
-
|
|
6952
|
+
if (filters.lastDoc) {
|
|
6953
|
+
if (typeof filters.lastDoc.data === "function") {
|
|
6954
|
+
constraints.push(startAfter6(filters.lastDoc));
|
|
6955
|
+
} else if (Array.isArray(filters.lastDoc)) {
|
|
6956
|
+
constraints.push(startAfter6(...filters.lastDoc));
|
|
6957
|
+
} else {
|
|
6958
|
+
constraints.push(startAfter6(filters.lastDoc));
|
|
6959
|
+
}
|
|
6960
|
+
}
|
|
6961
|
+
constraints.push(limit7(filters.pagination || 10));
|
|
6962
|
+
}
|
|
6963
|
+
const q = query10(collection10(this.db, PRACTITIONERS_COLLECTION), ...constraints);
|
|
6964
|
+
const querySnapshot = await getDocs10(q);
|
|
6965
|
+
let practitioners = querySnapshot.docs.map((doc37) => ({ ...doc37.data(), id: doc37.id }));
|
|
6966
|
+
if (filters.location && filters.radiusInKm && filters.radiusInKm > 0) {
|
|
6967
|
+
const location = filters.location;
|
|
6968
|
+
const radiusInKm = filters.radiusInKm;
|
|
6969
|
+
practitioners = practitioners.filter((practitioner) => {
|
|
6970
|
+
const clinics = practitioner.clinicsInfo || [];
|
|
6971
|
+
return clinics.some((clinic) => {
|
|
6972
|
+
const distance = distanceBetween(
|
|
6973
|
+
[location.latitude, location.longitude],
|
|
6974
|
+
[clinic.location.latitude, clinic.location.longitude]
|
|
6975
|
+
);
|
|
6976
|
+
const distanceInKm = distance / 1e3;
|
|
6977
|
+
return distanceInKm <= radiusInKm;
|
|
6978
|
+
});
|
|
6979
|
+
});
|
|
6980
|
+
practitioners = practitioners.slice(0, filters.pagination || 10);
|
|
6981
|
+
}
|
|
6982
|
+
if (filters.nameSearch && filters.nameSearch.trim()) {
|
|
6983
|
+
const searchTerm = filters.nameSearch.trim().toLowerCase();
|
|
6984
|
+
practitioners = practitioners.filter((practitioner) => {
|
|
6985
|
+
var _a, _b;
|
|
6986
|
+
const firstName = (((_a = practitioner.basicInfo) == null ? void 0 : _a.firstName) || "").toLowerCase();
|
|
6987
|
+
const lastName = (((_b = practitioner.basicInfo) == null ? void 0 : _b.lastName) || "").toLowerCase();
|
|
6988
|
+
const fullName = `${firstName} ${lastName}`.trim();
|
|
6989
|
+
const fullNameLower = practitioner.fullNameLower || "";
|
|
6990
|
+
return firstName.includes(searchTerm) || lastName.includes(searchTerm) || fullName.includes(searchTerm) || fullNameLower.includes(searchTerm);
|
|
6991
|
+
});
|
|
6992
|
+
console.log(`[PRACTITIONER_SERVICE] Applied name filter, results: ${practitioners.length}`);
|
|
6923
6993
|
}
|
|
6994
|
+
const lastDoc = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
|
|
6995
|
+
console.log(`[PRACTITIONER_SERVICE] Strategy 2 success: ${practitioners.length} practitioners`);
|
|
6996
|
+
if (practitioners.length < (filters.pagination || 10)) {
|
|
6997
|
+
return { practitioners, lastDoc: null };
|
|
6998
|
+
}
|
|
6999
|
+
return { practitioners, lastDoc };
|
|
7000
|
+
} catch (error) {
|
|
7001
|
+
console.log("[PRACTITIONER_SERVICE] Strategy 2 failed:", error);
|
|
6924
7002
|
}
|
|
6925
|
-
|
|
6926
|
-
|
|
6927
|
-
|
|
6928
|
-
|
|
6929
|
-
|
|
6930
|
-
|
|
6931
|
-
|
|
6932
|
-
|
|
6933
|
-
|
|
6934
|
-
|
|
6935
|
-
|
|
6936
|
-
|
|
6937
|
-
|
|
6938
|
-
|
|
6939
|
-
const
|
|
6940
|
-
|
|
7003
|
+
try {
|
|
7004
|
+
console.log("[PRACTITIONER_SERVICE] Strategy 3: Minimal query fallback");
|
|
7005
|
+
const constraints = [
|
|
7006
|
+
where10("isActive", "==", true),
|
|
7007
|
+
orderBy4("createdAt", "desc"),
|
|
7008
|
+
limit7(filters.pagination || 10)
|
|
7009
|
+
];
|
|
7010
|
+
const q = query10(collection10(this.db, PRACTITIONERS_COLLECTION), ...constraints);
|
|
7011
|
+
const querySnapshot = await getDocs10(q);
|
|
7012
|
+
let practitioners = querySnapshot.docs.map((doc37) => ({ ...doc37.data(), id: doc37.id }));
|
|
7013
|
+
if (filters.nameSearch && filters.nameSearch.trim()) {
|
|
7014
|
+
const searchTerm = filters.nameSearch.trim().toLowerCase();
|
|
7015
|
+
practitioners = practitioners.filter((practitioner) => {
|
|
7016
|
+
var _a, _b;
|
|
7017
|
+
const firstName = (((_a = practitioner.basicInfo) == null ? void 0 : _a.firstName) || "").toLowerCase();
|
|
7018
|
+
const lastName = (((_b = practitioner.basicInfo) == null ? void 0 : _b.lastName) || "").toLowerCase();
|
|
7019
|
+
const fullName = `${firstName} ${lastName}`.trim();
|
|
7020
|
+
const fullNameLower = practitioner.fullNameLower || "";
|
|
7021
|
+
return firstName.includes(searchTerm) || lastName.includes(searchTerm) || fullName.includes(searchTerm) || fullNameLower.includes(searchTerm);
|
|
6941
7022
|
});
|
|
6942
|
-
|
|
7023
|
+
console.log(`[PRACTITIONER_SERVICE] Applied name filter, results: ${practitioners.length}`);
|
|
7024
|
+
}
|
|
7025
|
+
const lastDoc = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
|
|
7026
|
+
console.log(`[PRACTITIONER_SERVICE] Strategy 3 success: ${practitioners.length} practitioners`);
|
|
7027
|
+
if (practitioners.length < (filters.pagination || 10)) {
|
|
7028
|
+
return { practitioners, lastDoc: null };
|
|
7029
|
+
}
|
|
7030
|
+
return { practitioners, lastDoc };
|
|
7031
|
+
} catch (error) {
|
|
7032
|
+
console.log("[PRACTITIONER_SERVICE] Strategy 3 failed:", error);
|
|
6943
7033
|
}
|
|
6944
|
-
|
|
6945
|
-
return {
|
|
6946
|
-
practitioners,
|
|
6947
|
-
lastDoc
|
|
6948
|
-
};
|
|
7034
|
+
console.log("[PRACTITIONER_SERVICE] All strategies failed, returning empty result");
|
|
7035
|
+
return { practitioners: [], lastDoc: null };
|
|
6949
7036
|
} catch (error) {
|
|
6950
|
-
console.error(
|
|
6951
|
-
|
|
6952
|
-
error
|
|
6953
|
-
);
|
|
6954
|
-
throw error;
|
|
7037
|
+
console.error("[PRACTITIONER_SERVICE] Error filtering practitioners:", error);
|
|
7038
|
+
return { practitioners: [], lastDoc: null };
|
|
6955
7039
|
}
|
|
6956
7040
|
}
|
|
6957
7041
|
/**
|
|
@@ -8636,49 +8720,181 @@ import {
|
|
|
8636
8720
|
} from "firebase/firestore";
|
|
8637
8721
|
import { distanceBetween as distanceBetween4 } from "geofire-common";
|
|
8638
8722
|
async function getClinicsByFilters(db, filters) {
|
|
8639
|
-
|
|
8640
|
-
|
|
8641
|
-
|
|
8642
|
-
|
|
8643
|
-
|
|
8644
|
-
|
|
8645
|
-
|
|
8646
|
-
|
|
8647
|
-
|
|
8648
|
-
|
|
8649
|
-
|
|
8650
|
-
|
|
8651
|
-
|
|
8652
|
-
|
|
8653
|
-
|
|
8654
|
-
|
|
8655
|
-
|
|
8656
|
-
|
|
8657
|
-
|
|
8658
|
-
|
|
8659
|
-
|
|
8660
|
-
|
|
8661
|
-
|
|
8662
|
-
|
|
8663
|
-
|
|
8664
|
-
|
|
8665
|
-
|
|
8666
|
-
|
|
8667
|
-
|
|
8668
|
-
|
|
8669
|
-
|
|
8670
|
-
|
|
8671
|
-
|
|
8672
|
-
|
|
8673
|
-
|
|
8674
|
-
|
|
8675
|
-
constraints
|
|
8723
|
+
try {
|
|
8724
|
+
console.log("[CLINIC_SERVICE] Starting clinic filtering with multiple strategies");
|
|
8725
|
+
if (filters.center && filters.radiusInKm) {
|
|
8726
|
+
console.log("[CLINIC_SERVICE] Executing geo query:", {
|
|
8727
|
+
center: filters.center,
|
|
8728
|
+
radius: filters.radiusInKm,
|
|
8729
|
+
serviceName: "ClinicService"
|
|
8730
|
+
});
|
|
8731
|
+
if (!filters.center.latitude || !filters.center.longitude) {
|
|
8732
|
+
console.warn("[CLINIC_SERVICE] Invalid location data:", filters.center);
|
|
8733
|
+
filters.center = void 0;
|
|
8734
|
+
filters.radiusInKm = void 0;
|
|
8735
|
+
}
|
|
8736
|
+
}
|
|
8737
|
+
const getBaseConstraints = () => {
|
|
8738
|
+
var _a;
|
|
8739
|
+
const constraints = [];
|
|
8740
|
+
constraints.push(where15("isActive", "==", (_a = filters.isActive) != null ? _a : true));
|
|
8741
|
+
if (filters.tags && filters.tags.length > 0) {
|
|
8742
|
+
constraints.push(where15("tags", "array-contains", filters.tags[0]));
|
|
8743
|
+
}
|
|
8744
|
+
if (filters.procedureTechnology) {
|
|
8745
|
+
constraints.push(where15("servicesInfo.technology", "==", filters.procedureTechnology));
|
|
8746
|
+
} else if (filters.procedureSubcategory) {
|
|
8747
|
+
constraints.push(where15("servicesInfo.subCategory", "==", filters.procedureSubcategory));
|
|
8748
|
+
} else if (filters.procedureCategory) {
|
|
8749
|
+
constraints.push(where15("servicesInfo.category", "==", filters.procedureCategory));
|
|
8750
|
+
} else if (filters.procedureFamily) {
|
|
8751
|
+
constraints.push(where15("servicesInfo.procedureFamily", "==", filters.procedureFamily));
|
|
8752
|
+
}
|
|
8753
|
+
if (filters.minRating !== void 0) {
|
|
8754
|
+
constraints.push(where15("reviewInfo.averageRating", ">=", filters.minRating));
|
|
8755
|
+
}
|
|
8756
|
+
if (filters.maxRating !== void 0) {
|
|
8757
|
+
constraints.push(where15("reviewInfo.averageRating", "<=", filters.maxRating));
|
|
8758
|
+
}
|
|
8759
|
+
return constraints;
|
|
8760
|
+
};
|
|
8761
|
+
if (filters.nameSearch && filters.nameSearch.trim()) {
|
|
8762
|
+
try {
|
|
8763
|
+
console.log("[CLINIC_SERVICE] Strategy 1: Trying nameLower search");
|
|
8764
|
+
const searchTerm = filters.nameSearch.trim().toLowerCase();
|
|
8765
|
+
const constraints = getBaseConstraints();
|
|
8766
|
+
constraints.push(where15("nameLower", ">=", searchTerm));
|
|
8767
|
+
constraints.push(where15("nameLower", "<=", searchTerm + "\uF8FF"));
|
|
8768
|
+
constraints.push(orderBy5("nameLower"));
|
|
8769
|
+
if (filters.lastDoc) {
|
|
8770
|
+
if (typeof filters.lastDoc.data === "function") {
|
|
8771
|
+
constraints.push(startAfter8(filters.lastDoc));
|
|
8772
|
+
} else if (Array.isArray(filters.lastDoc)) {
|
|
8773
|
+
constraints.push(startAfter8(...filters.lastDoc));
|
|
8774
|
+
} else {
|
|
8775
|
+
constraints.push(startAfter8(filters.lastDoc));
|
|
8776
|
+
}
|
|
8777
|
+
}
|
|
8778
|
+
constraints.push(limit9(filters.pagination || 5));
|
|
8779
|
+
const q = query15(collection15(db, CLINICS_COLLECTION), ...constraints);
|
|
8780
|
+
const querySnapshot = await getDocs15(q);
|
|
8781
|
+
let clinics = querySnapshot.docs.map((doc37) => ({ ...doc37.data(), id: doc37.id }));
|
|
8782
|
+
clinics = applyInMemoryFilters(clinics, filters);
|
|
8783
|
+
const lastDoc = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
|
|
8784
|
+
console.log(`[CLINIC_SERVICE] Strategy 1 success: ${clinics.length} clinics`);
|
|
8785
|
+
if (clinics.length < (filters.pagination || 5)) {
|
|
8786
|
+
return { clinics, lastDoc: null };
|
|
8787
|
+
}
|
|
8788
|
+
return { clinics, lastDoc };
|
|
8789
|
+
} catch (error) {
|
|
8790
|
+
console.log("[CLINIC_SERVICE] Strategy 1 failed:", error);
|
|
8791
|
+
}
|
|
8792
|
+
}
|
|
8793
|
+
if (filters.nameSearch && filters.nameSearch.trim()) {
|
|
8794
|
+
try {
|
|
8795
|
+
console.log("[CLINIC_SERVICE] Strategy 2: Trying name field search");
|
|
8796
|
+
const searchTerm = filters.nameSearch.trim().toLowerCase();
|
|
8797
|
+
const constraints = getBaseConstraints();
|
|
8798
|
+
constraints.push(where15("name", ">=", searchTerm));
|
|
8799
|
+
constraints.push(where15("name", "<=", searchTerm + "\uF8FF"));
|
|
8800
|
+
constraints.push(orderBy5("name"));
|
|
8801
|
+
if (filters.lastDoc) {
|
|
8802
|
+
if (typeof filters.lastDoc.data === "function") {
|
|
8803
|
+
constraints.push(startAfter8(filters.lastDoc));
|
|
8804
|
+
} else if (Array.isArray(filters.lastDoc)) {
|
|
8805
|
+
constraints.push(startAfter8(...filters.lastDoc));
|
|
8806
|
+
} else {
|
|
8807
|
+
constraints.push(startAfter8(filters.lastDoc));
|
|
8808
|
+
}
|
|
8809
|
+
}
|
|
8810
|
+
constraints.push(limit9(filters.pagination || 5));
|
|
8811
|
+
const q = query15(collection15(db, CLINICS_COLLECTION), ...constraints);
|
|
8812
|
+
const querySnapshot = await getDocs15(q);
|
|
8813
|
+
let clinics = querySnapshot.docs.map((doc37) => ({ ...doc37.data(), id: doc37.id }));
|
|
8814
|
+
clinics = applyInMemoryFilters(clinics, filters);
|
|
8815
|
+
const lastDoc = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
|
|
8816
|
+
console.log(`[CLINIC_SERVICE] Strategy 2 success: ${clinics.length} clinics`);
|
|
8817
|
+
if (clinics.length < (filters.pagination || 5)) {
|
|
8818
|
+
return { clinics, lastDoc: null };
|
|
8819
|
+
}
|
|
8820
|
+
return { clinics, lastDoc };
|
|
8821
|
+
} catch (error) {
|
|
8822
|
+
console.log("[CLINIC_SERVICE] Strategy 2 failed:", error);
|
|
8823
|
+
}
|
|
8824
|
+
}
|
|
8825
|
+
try {
|
|
8826
|
+
console.log("[CLINIC_SERVICE] Strategy 3: Using createdAt ordering with client-side filtering");
|
|
8827
|
+
const constraints = getBaseConstraints();
|
|
8828
|
+
constraints.push(orderBy5("createdAt", "desc"));
|
|
8829
|
+
if (filters.lastDoc) {
|
|
8830
|
+
if (typeof filters.lastDoc.data === "function") {
|
|
8831
|
+
constraints.push(startAfter8(filters.lastDoc));
|
|
8832
|
+
} else if (Array.isArray(filters.lastDoc)) {
|
|
8833
|
+
constraints.push(startAfter8(...filters.lastDoc));
|
|
8834
|
+
} else {
|
|
8835
|
+
constraints.push(startAfter8(filters.lastDoc));
|
|
8836
|
+
}
|
|
8837
|
+
}
|
|
8838
|
+
constraints.push(limit9(filters.pagination || 5));
|
|
8839
|
+
const q = query15(collection15(db, CLINICS_COLLECTION), ...constraints);
|
|
8840
|
+
const querySnapshot = await getDocs15(q);
|
|
8841
|
+
let clinics = querySnapshot.docs.map((doc37) => ({ ...doc37.data(), id: doc37.id }));
|
|
8842
|
+
if (filters.nameSearch && filters.nameSearch.trim()) {
|
|
8843
|
+
const searchTerm = filters.nameSearch.trim().toLowerCase();
|
|
8844
|
+
clinics = clinics.filter((clinic) => {
|
|
8845
|
+
const name = (clinic.name || "").toLowerCase();
|
|
8846
|
+
const nameLower = clinic.nameLower || "";
|
|
8847
|
+
return name.includes(searchTerm) || nameLower.includes(searchTerm);
|
|
8848
|
+
});
|
|
8849
|
+
console.log(`[CLINIC_SERVICE] Applied name filter, results: ${clinics.length}`);
|
|
8850
|
+
}
|
|
8851
|
+
clinics = applyInMemoryFilters(clinics, filters);
|
|
8852
|
+
const lastDoc = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
|
|
8853
|
+
console.log(`[CLINIC_SERVICE] Strategy 3 success: ${clinics.length} clinics`);
|
|
8854
|
+
if (clinics.length < (filters.pagination || 5)) {
|
|
8855
|
+
return { clinics, lastDoc: null };
|
|
8856
|
+
}
|
|
8857
|
+
return { clinics, lastDoc };
|
|
8858
|
+
} catch (error) {
|
|
8859
|
+
console.log("[CLINIC_SERVICE] Strategy 3 failed:", error);
|
|
8676
8860
|
}
|
|
8861
|
+
try {
|
|
8862
|
+
console.log("[CLINIC_SERVICE] Strategy 4: Minimal fallback");
|
|
8863
|
+
const constraints = [
|
|
8864
|
+
where15("isActive", "==", true),
|
|
8865
|
+
orderBy5("createdAt", "desc"),
|
|
8866
|
+
limit9(filters.pagination || 5)
|
|
8867
|
+
];
|
|
8868
|
+
const q = query15(collection15(db, CLINICS_COLLECTION), ...constraints);
|
|
8869
|
+
const querySnapshot = await getDocs15(q);
|
|
8870
|
+
let clinics = querySnapshot.docs.map((doc37) => ({ ...doc37.data(), id: doc37.id }));
|
|
8871
|
+
if (filters.nameSearch && filters.nameSearch.trim()) {
|
|
8872
|
+
const searchTerm = filters.nameSearch.trim().toLowerCase();
|
|
8873
|
+
clinics = clinics.filter((clinic) => {
|
|
8874
|
+
const name = (clinic.name || "").toLowerCase();
|
|
8875
|
+
const nameLower = clinic.nameLower || "";
|
|
8876
|
+
return name.includes(searchTerm) || nameLower.includes(searchTerm);
|
|
8877
|
+
});
|
|
8878
|
+
console.log(`[CLINIC_SERVICE] Applied name filter, results: ${clinics.length}`);
|
|
8879
|
+
}
|
|
8880
|
+
clinics = applyInMemoryFilters(clinics, filters);
|
|
8881
|
+
const lastDoc = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
|
|
8882
|
+
console.log(`[CLINIC_SERVICE] Strategy 4 success: ${clinics.length} clinics`);
|
|
8883
|
+
if (clinics.length < (filters.pagination || 5)) {
|
|
8884
|
+
return { clinics, lastDoc: null };
|
|
8885
|
+
}
|
|
8886
|
+
return { clinics, lastDoc };
|
|
8887
|
+
} catch (error) {
|
|
8888
|
+
console.log("[CLINIC_SERVICE] Strategy 4 failed:", error);
|
|
8889
|
+
}
|
|
8890
|
+
console.log("[CLINIC_SERVICE] All strategies failed, returning empty result");
|
|
8891
|
+
return { clinics: [], lastDoc: null };
|
|
8892
|
+
} catch (error) {
|
|
8893
|
+
console.error("[CLINIC_SERVICE] Error filtering clinics:", error);
|
|
8894
|
+
return { clinics: [], lastDoc: null };
|
|
8677
8895
|
}
|
|
8678
|
-
|
|
8679
|
-
|
|
8680
|
-
const querySnapshot = await getDocs15(q);
|
|
8681
|
-
let clinics = querySnapshot.docs.map((doc37) => ({ ...doc37.data(), id: doc37.id }));
|
|
8896
|
+
}
|
|
8897
|
+
function applyInMemoryFilters(clinics, filters) {
|
|
8682
8898
|
if (filters.tags && filters.tags.length > 1) {
|
|
8683
8899
|
clinics = clinics.filter((clinic) => filters.tags.every((tag) => clinic.tags.includes(tag)));
|
|
8684
8900
|
}
|
|
@@ -8691,9 +8907,9 @@ async function getClinicsByFilters(db, filters) {
|
|
|
8691
8907
|
clinic.distance = distance;
|
|
8692
8908
|
return distance <= filters.radiusInKm;
|
|
8693
8909
|
});
|
|
8910
|
+
clinics.sort((a, b) => (a.distance || 0) - (b.distance || 0));
|
|
8694
8911
|
}
|
|
8695
|
-
|
|
8696
|
-
return { clinics, lastDoc: lastVisibleDoc };
|
|
8912
|
+
return clinics;
|
|
8697
8913
|
}
|
|
8698
8914
|
|
|
8699
8915
|
// src/services/clinic/clinic.service.ts
|
|
@@ -14530,7 +14746,7 @@ var procedureSchema = createProcedureSchema.extend({
|
|
|
14530
14746
|
});
|
|
14531
14747
|
|
|
14532
14748
|
// src/services/procedure/procedure.service.ts
|
|
14533
|
-
import { distanceBetween as distanceBetween6
|
|
14749
|
+
import { distanceBetween as distanceBetween6 } from "geofire-common";
|
|
14534
14750
|
var ProcedureService = class extends BaseService {
|
|
14535
14751
|
constructor(db, auth, app, categoryService, subcategoryService, technologyService, productService, mediaService) {
|
|
14536
14752
|
super(db, auth, app);
|
|
@@ -15159,126 +15375,233 @@ var ProcedureService = class extends BaseService {
|
|
|
15159
15375
|
*/
|
|
15160
15376
|
async getProceduresByFilters(filters) {
|
|
15161
15377
|
try {
|
|
15162
|
-
|
|
15163
|
-
|
|
15164
|
-
|
|
15165
|
-
|
|
15166
|
-
|
|
15167
|
-
|
|
15168
|
-
|
|
15169
|
-
|
|
15170
|
-
|
|
15171
|
-
|
|
15172
|
-
|
|
15173
|
-
|
|
15174
|
-
}
|
|
15175
|
-
if (filters.procedureSubcategory) {
|
|
15176
|
-
constraints.push(where29("subcategory.id", "==", filters.procedureSubcategory));
|
|
15177
|
-
}
|
|
15178
|
-
if (filters.procedureTechnology) {
|
|
15179
|
-
constraints.push(where29("technology.id", "==", filters.procedureTechnology));
|
|
15180
|
-
}
|
|
15181
|
-
if (filters.minPrice !== void 0) {
|
|
15182
|
-
constraints.push(where29("price", ">=", filters.minPrice));
|
|
15183
|
-
}
|
|
15184
|
-
if (filters.maxPrice !== void 0) {
|
|
15185
|
-
constraints.push(where29("price", "<=", filters.maxPrice));
|
|
15186
|
-
}
|
|
15187
|
-
if (filters.minRating !== void 0) {
|
|
15188
|
-
constraints.push(where29("reviewInfo.averageRating", ">=", filters.minRating));
|
|
15189
|
-
}
|
|
15190
|
-
if (filters.maxRating !== void 0) {
|
|
15191
|
-
constraints.push(where29("reviewInfo.averageRating", "<=", filters.maxRating));
|
|
15192
|
-
}
|
|
15193
|
-
if (filters.treatmentBenefits && filters.treatmentBenefits.length > 0) {
|
|
15194
|
-
constraints.push(where29("treatmentBenefits", "array-contains-any", filters.treatmentBenefits));
|
|
15378
|
+
console.log("[PROCEDURE_SERVICE] Starting procedure filtering with multiple strategies");
|
|
15379
|
+
if (filters.location && filters.radiusInKm) {
|
|
15380
|
+
console.log("[PROCEDURE_SERVICE] Executing geo query:", {
|
|
15381
|
+
location: filters.location,
|
|
15382
|
+
radius: filters.radiusInKm,
|
|
15383
|
+
serviceName: "ProcedureService"
|
|
15384
|
+
});
|
|
15385
|
+
if (!filters.location.latitude || !filters.location.longitude) {
|
|
15386
|
+
console.warn("[PROCEDURE_SERVICE] Invalid location data:", filters.location);
|
|
15387
|
+
filters.location = void 0;
|
|
15388
|
+
filters.radiusInKm = void 0;
|
|
15389
|
+
}
|
|
15195
15390
|
}
|
|
15196
|
-
|
|
15197
|
-
|
|
15198
|
-
|
|
15199
|
-
searchTerm = filters.nameSearch.trim().toLowerCase();
|
|
15200
|
-
useNameLower = true;
|
|
15201
|
-
constraints.push(where29("nameLower", ">=", searchTerm));
|
|
15202
|
-
constraints.push(where29("nameLower", "<=", searchTerm + "\uF8FF"));
|
|
15203
|
-
constraints.push(orderBy17("nameLower"));
|
|
15204
|
-
} else {
|
|
15205
|
-
constraints.push(orderBy17("nameLower"));
|
|
15391
|
+
const isGeoQuery = filters.location && filters.radiusInKm && filters.radiusInKm > 0;
|
|
15392
|
+
if (isGeoQuery) {
|
|
15393
|
+
return this.handleGeoQuery(filters);
|
|
15206
15394
|
}
|
|
15207
|
-
|
|
15208
|
-
|
|
15209
|
-
|
|
15210
|
-
|
|
15211
|
-
constraints.push(startAfter13(...filters.lastDoc));
|
|
15395
|
+
const getBaseConstraints = () => {
|
|
15396
|
+
const constraints = [];
|
|
15397
|
+
if (filters.isActive !== void 0) {
|
|
15398
|
+
constraints.push(where29("isActive", "==", filters.isActive));
|
|
15212
15399
|
} else {
|
|
15213
|
-
constraints.push(
|
|
15400
|
+
constraints.push(where29("isActive", "==", true));
|
|
15214
15401
|
}
|
|
15215
|
-
|
|
15216
|
-
|
|
15217
|
-
constraints.push(limit15(filters.pagination));
|
|
15218
|
-
}
|
|
15219
|
-
if (isGeoQuery) {
|
|
15220
|
-
const center = filters.location;
|
|
15221
|
-
const radiusInKm = filters.radiusInKm;
|
|
15222
|
-
const bounds = geohashQueryBounds5(
|
|
15223
|
-
[center.latitude, center.longitude],
|
|
15224
|
-
radiusInKm * 1e3
|
|
15225
|
-
// Convert to meters
|
|
15226
|
-
);
|
|
15227
|
-
let allDocs = [];
|
|
15228
|
-
for (const bound of bounds) {
|
|
15229
|
-
const geoConstraints = [
|
|
15230
|
-
...constraints.filter((c) => !c.fieldPath || c.fieldPath !== "name"),
|
|
15231
|
-
// Remove name orderBy for geo
|
|
15232
|
-
where29("clinicInfo.location.geohash", ">=", bound[0]),
|
|
15233
|
-
where29("clinicInfo.location.geohash", "<=", bound[1]),
|
|
15234
|
-
orderBy17("clinicInfo.location.geohash")
|
|
15235
|
-
];
|
|
15236
|
-
const q = query29(collection29(this.db, PROCEDURES_COLLECTION), ...geoConstraints);
|
|
15237
|
-
const querySnapshot = await getDocs29(q);
|
|
15238
|
-
for (const doc37 of querySnapshot.docs) {
|
|
15239
|
-
const procedure = { ...doc37.data(), id: doc37.id };
|
|
15240
|
-
const distance = distanceBetween6(
|
|
15241
|
-
[center.latitude, center.longitude],
|
|
15242
|
-
[procedure.clinicInfo.location.latitude, procedure.clinicInfo.location.longitude]
|
|
15243
|
-
);
|
|
15244
|
-
const distanceInKm = distance / 1e3;
|
|
15245
|
-
if (distanceInKm <= radiusInKm) {
|
|
15246
|
-
allDocs.push({ ...procedure, distance: distanceInKm });
|
|
15247
|
-
}
|
|
15248
|
-
}
|
|
15402
|
+
if (filters.procedureFamily) {
|
|
15403
|
+
constraints.push(where29("family", "==", filters.procedureFamily));
|
|
15249
15404
|
}
|
|
15250
|
-
|
|
15251
|
-
|
|
15252
|
-
|
|
15253
|
-
|
|
15405
|
+
if (filters.procedureCategory) {
|
|
15406
|
+
constraints.push(where29("category.id", "==", filters.procedureCategory));
|
|
15407
|
+
}
|
|
15408
|
+
if (filters.procedureSubcategory) {
|
|
15409
|
+
constraints.push(where29("subcategory.id", "==", filters.procedureSubcategory));
|
|
15410
|
+
}
|
|
15411
|
+
if (filters.procedureTechnology) {
|
|
15412
|
+
constraints.push(where29("technology.id", "==", filters.procedureTechnology));
|
|
15413
|
+
}
|
|
15414
|
+
if (filters.minPrice !== void 0) {
|
|
15415
|
+
constraints.push(where29("price", ">=", filters.minPrice));
|
|
15416
|
+
}
|
|
15417
|
+
if (filters.maxPrice !== void 0) {
|
|
15418
|
+
constraints.push(where29("price", "<=", filters.maxPrice));
|
|
15419
|
+
}
|
|
15420
|
+
if (filters.minRating !== void 0) {
|
|
15421
|
+
constraints.push(where29("reviewInfo.averageRating", ">=", filters.minRating));
|
|
15422
|
+
}
|
|
15423
|
+
if (filters.maxRating !== void 0) {
|
|
15424
|
+
constraints.push(where29("reviewInfo.averageRating", "<=", filters.maxRating));
|
|
15425
|
+
}
|
|
15426
|
+
if (filters.treatmentBenefits && filters.treatmentBenefits.length > 0) {
|
|
15427
|
+
constraints.push(where29("treatmentBenefits", "array-contains-any", filters.treatmentBenefits));
|
|
15428
|
+
}
|
|
15429
|
+
return constraints;
|
|
15430
|
+
};
|
|
15431
|
+
if (filters.nameSearch && filters.nameSearch.trim()) {
|
|
15432
|
+
try {
|
|
15433
|
+
console.log("[PROCEDURE_SERVICE] Strategy 1: Trying nameLower search");
|
|
15434
|
+
const searchTerm = filters.nameSearch.trim().toLowerCase();
|
|
15435
|
+
const constraints = getBaseConstraints();
|
|
15436
|
+
constraints.push(where29("nameLower", ">=", searchTerm));
|
|
15437
|
+
constraints.push(where29("nameLower", "<=", searchTerm + "\uF8FF"));
|
|
15438
|
+
constraints.push(orderBy17("nameLower"));
|
|
15254
15439
|
if (filters.lastDoc) {
|
|
15255
|
-
|
|
15256
|
-
|
|
15440
|
+
if (typeof filters.lastDoc.data === "function") {
|
|
15441
|
+
constraints.push(startAfter13(filters.lastDoc));
|
|
15442
|
+
} else if (Array.isArray(filters.lastDoc)) {
|
|
15443
|
+
constraints.push(startAfter13(...filters.lastDoc));
|
|
15444
|
+
} else {
|
|
15445
|
+
constraints.push(startAfter13(filters.lastDoc));
|
|
15446
|
+
}
|
|
15447
|
+
}
|
|
15448
|
+
constraints.push(limit15(filters.pagination || 10));
|
|
15449
|
+
const q = query29(collection29(this.db, PROCEDURES_COLLECTION), ...constraints);
|
|
15450
|
+
const querySnapshot = await getDocs29(q);
|
|
15451
|
+
const procedures = querySnapshot.docs.map((doc37) => ({ ...doc37.data(), id: doc37.id }));
|
|
15452
|
+
const lastDoc = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
|
|
15453
|
+
console.log(`[PROCEDURE_SERVICE] Strategy 1 success: ${procedures.length} procedures`);
|
|
15454
|
+
if (procedures.length < (filters.pagination || 10)) {
|
|
15455
|
+
return { procedures, lastDoc: null };
|
|
15257
15456
|
}
|
|
15258
|
-
|
|
15457
|
+
return { procedures, lastDoc };
|
|
15458
|
+
} catch (error) {
|
|
15459
|
+
console.log("[PROCEDURE_SERVICE] Strategy 1 failed:", error);
|
|
15259
15460
|
}
|
|
15260
|
-
|
|
15261
|
-
|
|
15262
|
-
|
|
15263
|
-
|
|
15264
|
-
|
|
15265
|
-
|
|
15266
|
-
constraints.pop();
|
|
15267
|
-
constraints.pop();
|
|
15268
|
-
constraints.pop();
|
|
15461
|
+
}
|
|
15462
|
+
if (filters.nameSearch && filters.nameSearch.trim()) {
|
|
15463
|
+
try {
|
|
15464
|
+
console.log("[PROCEDURE_SERVICE] Strategy 2: Trying name field search");
|
|
15465
|
+
const searchTerm = filters.nameSearch.trim().toLowerCase();
|
|
15466
|
+
const constraints = getBaseConstraints();
|
|
15269
15467
|
constraints.push(where29("name", ">=", searchTerm));
|
|
15270
15468
|
constraints.push(where29("name", "<=", searchTerm + "\uF8FF"));
|
|
15271
15469
|
constraints.push(orderBy17("name"));
|
|
15272
|
-
|
|
15273
|
-
|
|
15470
|
+
if (filters.lastDoc) {
|
|
15471
|
+
if (typeof filters.lastDoc.data === "function") {
|
|
15472
|
+
constraints.push(startAfter13(filters.lastDoc));
|
|
15473
|
+
} else if (Array.isArray(filters.lastDoc)) {
|
|
15474
|
+
constraints.push(startAfter13(...filters.lastDoc));
|
|
15475
|
+
} else {
|
|
15476
|
+
constraints.push(startAfter13(filters.lastDoc));
|
|
15477
|
+
}
|
|
15478
|
+
}
|
|
15479
|
+
constraints.push(limit15(filters.pagination || 10));
|
|
15480
|
+
const q = query29(collection29(this.db, PROCEDURES_COLLECTION), ...constraints);
|
|
15481
|
+
const querySnapshot = await getDocs29(q);
|
|
15482
|
+
const procedures = querySnapshot.docs.map((doc37) => ({ ...doc37.data(), id: doc37.id }));
|
|
15483
|
+
const lastDoc = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
|
|
15484
|
+
console.log(`[PROCEDURE_SERVICE] Strategy 2 success: ${procedures.length} procedures`);
|
|
15485
|
+
if (procedures.length < (filters.pagination || 10)) {
|
|
15486
|
+
return { procedures, lastDoc: null };
|
|
15487
|
+
}
|
|
15488
|
+
return { procedures, lastDoc };
|
|
15489
|
+
} catch (error) {
|
|
15490
|
+
console.log("[PROCEDURE_SERVICE] Strategy 2 failed:", error);
|
|
15491
|
+
}
|
|
15492
|
+
}
|
|
15493
|
+
try {
|
|
15494
|
+
console.log("[PROCEDURE_SERVICE] Strategy 3: Using createdAt orderBy with client-side filtering");
|
|
15495
|
+
const constraints = getBaseConstraints();
|
|
15496
|
+
constraints.push(orderBy17("createdAt", "desc"));
|
|
15497
|
+
if (filters.lastDoc) {
|
|
15498
|
+
if (typeof filters.lastDoc.data === "function") {
|
|
15499
|
+
constraints.push(startAfter13(filters.lastDoc));
|
|
15500
|
+
} else if (Array.isArray(filters.lastDoc)) {
|
|
15501
|
+
constraints.push(startAfter13(...filters.lastDoc));
|
|
15502
|
+
} else {
|
|
15503
|
+
constraints.push(startAfter13(filters.lastDoc));
|
|
15504
|
+
}
|
|
15505
|
+
}
|
|
15506
|
+
constraints.push(limit15(filters.pagination || 10));
|
|
15507
|
+
const q = query29(collection29(this.db, PROCEDURES_COLLECTION), ...constraints);
|
|
15508
|
+
const querySnapshot = await getDocs29(q);
|
|
15509
|
+
let procedures = querySnapshot.docs.map((doc37) => ({ ...doc37.data(), id: doc37.id }));
|
|
15510
|
+
if (filters.nameSearch && filters.nameSearch.trim()) {
|
|
15511
|
+
const searchTerm = filters.nameSearch.trim().toLowerCase();
|
|
15512
|
+
procedures = procedures.filter((procedure) => {
|
|
15513
|
+
const name = (procedure.name || "").toLowerCase();
|
|
15514
|
+
const nameLower = procedure.nameLower || "";
|
|
15515
|
+
return name.includes(searchTerm) || nameLower.includes(searchTerm);
|
|
15516
|
+
});
|
|
15517
|
+
console.log(`[PROCEDURE_SERVICE] Applied name filter, results: ${procedures.length}`);
|
|
15518
|
+
}
|
|
15519
|
+
const lastDoc = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
|
|
15520
|
+
console.log(`[PROCEDURE_SERVICE] Strategy 3 success: ${procedures.length} procedures`);
|
|
15521
|
+
if (procedures.length < (filters.pagination || 10)) {
|
|
15522
|
+
return { procedures, lastDoc: null };
|
|
15523
|
+
}
|
|
15524
|
+
return { procedures, lastDoc };
|
|
15525
|
+
} catch (error) {
|
|
15526
|
+
console.log("[PROCEDURE_SERVICE] Strategy 3 failed:", error);
|
|
15527
|
+
}
|
|
15528
|
+
try {
|
|
15529
|
+
console.log("[PROCEDURE_SERVICE] Strategy 4: Minimal query fallback");
|
|
15530
|
+
const constraints = [
|
|
15531
|
+
where29("isActive", "==", true),
|
|
15532
|
+
orderBy17("createdAt", "desc"),
|
|
15533
|
+
limit15(filters.pagination || 10)
|
|
15534
|
+
];
|
|
15535
|
+
const q = query29(collection29(this.db, PROCEDURES_COLLECTION), ...constraints);
|
|
15536
|
+
const querySnapshot = await getDocs29(q);
|
|
15537
|
+
let procedures = querySnapshot.docs.map((doc37) => ({ ...doc37.data(), id: doc37.id }));
|
|
15538
|
+
if (filters.nameSearch && filters.nameSearch.trim()) {
|
|
15539
|
+
const searchTerm = filters.nameSearch.trim().toLowerCase();
|
|
15540
|
+
procedures = procedures.filter((procedure) => {
|
|
15541
|
+
const name = (procedure.name || "").toLowerCase();
|
|
15542
|
+
const nameLower = procedure.nameLower || "";
|
|
15543
|
+
return name.includes(searchTerm) || nameLower.includes(searchTerm);
|
|
15544
|
+
});
|
|
15545
|
+
console.log(`[PROCEDURE_SERVICE] Applied name filter, results: ${procedures.length}`);
|
|
15274
15546
|
}
|
|
15275
|
-
const
|
|
15276
|
-
|
|
15277
|
-
|
|
15547
|
+
const lastDoc = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
|
|
15548
|
+
console.log(`[PROCEDURE_SERVICE] Strategy 4 success: ${procedures.length} procedures`);
|
|
15549
|
+
if (procedures.length < (filters.pagination || 10)) {
|
|
15550
|
+
return { procedures, lastDoc: null };
|
|
15551
|
+
}
|
|
15552
|
+
return { procedures, lastDoc };
|
|
15553
|
+
} catch (error) {
|
|
15554
|
+
console.log("[PROCEDURE_SERVICE] Strategy 4 failed:", error);
|
|
15278
15555
|
}
|
|
15556
|
+
console.log("[PROCEDURE_SERVICE] All strategies failed, returning empty result");
|
|
15557
|
+
return { procedures: [], lastDoc: null };
|
|
15279
15558
|
} catch (error) {
|
|
15280
15559
|
console.error("[PROCEDURE_SERVICE] Error filtering procedures:", error);
|
|
15281
|
-
|
|
15560
|
+
return { procedures: [], lastDoc: null };
|
|
15561
|
+
}
|
|
15562
|
+
}
|
|
15563
|
+
handleGeoQuery(filters) {
|
|
15564
|
+
console.log("[PROCEDURE_SERVICE] Executing geo query with enhanced debugging");
|
|
15565
|
+
try {
|
|
15566
|
+
const location = filters.location;
|
|
15567
|
+
const radiusInKm = filters.radiusInKm;
|
|
15568
|
+
console.log("[PROCEDURE_SERVICE] Geo query parameters:", {
|
|
15569
|
+
latitude: location.latitude,
|
|
15570
|
+
longitude: location.longitude,
|
|
15571
|
+
radiusInKm,
|
|
15572
|
+
pagination: filters.pagination || 10
|
|
15573
|
+
});
|
|
15574
|
+
const constraints = [
|
|
15575
|
+
where29("isActive", "==", true),
|
|
15576
|
+
orderBy17("createdAt", "desc"),
|
|
15577
|
+
limit15((filters.pagination || 10) * 3)
|
|
15578
|
+
// Get more results for geo filtering
|
|
15579
|
+
];
|
|
15580
|
+
const q = query29(collection29(this.db, PROCEDURES_COLLECTION), ...constraints);
|
|
15581
|
+
return getDocs29(q).then((querySnapshot) => {
|
|
15582
|
+
let procedures = querySnapshot.docs.map((doc37) => ({ ...doc37.data(), id: doc37.id }));
|
|
15583
|
+
procedures = procedures.filter((procedure) => {
|
|
15584
|
+
var _a;
|
|
15585
|
+
const clinicLocation = (_a = procedure.clinicInfo) == null ? void 0 : _a.location;
|
|
15586
|
+
if (!(clinicLocation == null ? void 0 : clinicLocation.latitude) || !(clinicLocation == null ? void 0 : clinicLocation.longitude)) {
|
|
15587
|
+
return false;
|
|
15588
|
+
}
|
|
15589
|
+
const distance = distanceBetween6(
|
|
15590
|
+
[location.latitude, location.longitude],
|
|
15591
|
+
[clinicLocation.latitude, clinicLocation.longitude]
|
|
15592
|
+
) / 1e3;
|
|
15593
|
+
procedure.distance = distance;
|
|
15594
|
+
return distance <= radiusInKm;
|
|
15595
|
+
});
|
|
15596
|
+
procedures.sort((a, b) => (a.distance || 0) - (b.distance || 0));
|
|
15597
|
+
procedures = procedures.slice(0, filters.pagination || 10);
|
|
15598
|
+
console.log(`[PROCEDURE_SERVICE] Geo query success: ${procedures.length} procedures within ${radiusInKm}km`);
|
|
15599
|
+
const lastDoc = procedures.length < (filters.pagination || 10) ? null : querySnapshot.docs[querySnapshot.docs.length - 1];
|
|
15600
|
+
return { procedures, lastDoc };
|
|
15601
|
+
});
|
|
15602
|
+
} catch (error) {
|
|
15603
|
+
console.error("[PROCEDURE_SERVICE] Geo query failed:", error);
|
|
15604
|
+
return Promise.resolve({ procedures: [], lastDoc: null });
|
|
15282
15605
|
}
|
|
15283
15606
|
}
|
|
15284
15607
|
/**
|