@blackcode_sa/metaestetics-api 1.8.17 → 1.10.0

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.js CHANGED
@@ -6964,6 +6964,27 @@ var PractitionerService = class extends BaseService {
6964
6964
  } catch (error) {
6965
6965
  console.log("[PRACTITIONER_SERVICE] Strategy 3 failed:", error);
6966
6966
  }
6967
+ try {
6968
+ console.log("[PRACTITIONER_SERVICE] Strategy 4: Client-side filtering fallback");
6969
+ const constraints = [
6970
+ (0, import_firestore21.where)("isActive", "==", true),
6971
+ (0, import_firestore21.where)("status", "==", "active" /* ACTIVE */),
6972
+ (0, import_firestore21.orderBy)("createdAt", "desc"),
6973
+ (0, import_firestore21.limit)(filters.pagination || 10)
6974
+ ];
6975
+ const q = (0, import_firestore21.query)((0, import_firestore21.collection)(this.db, PRACTITIONERS_COLLECTION), ...constraints);
6976
+ const querySnapshot = await (0, import_firestore21.getDocs)(q);
6977
+ let practitioners = querySnapshot.docs.map((doc37) => ({ ...doc37.data(), id: doc37.id }));
6978
+ practitioners = this.applyInMemoryFilters(practitioners, filters);
6979
+ const lastDoc = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
6980
+ console.log(`[PRACTITIONER_SERVICE] Strategy 4 success: ${practitioners.length} practitioners`);
6981
+ if (practitioners.length < (filters.pagination || 10)) {
6982
+ return { practitioners, lastDoc: null };
6983
+ }
6984
+ return { practitioners, lastDoc };
6985
+ } catch (error) {
6986
+ console.log("[PRACTITIONER_SERVICE] Strategy 4 failed:", error);
6987
+ }
6967
6988
  console.log("[PRACTITIONER_SERVICE] All strategies failed, returning empty result");
6968
6989
  return { practitioners: [], lastDoc: null };
6969
6990
  } catch (error) {
@@ -8689,6 +8710,7 @@ async function findClinicsInRadius(db, center, radiusInKm, filters) {
8689
8710
  var import_firestore26 = require("firebase/firestore");
8690
8711
  var import_geofire_common6 = require("geofire-common");
8691
8712
  async function getClinicsByFilters(db, filters) {
8713
+ var _a;
8692
8714
  try {
8693
8715
  console.log("[CLINIC_SERVICE] Starting clinic filtering with multiple strategies");
8694
8716
  if (filters.center && filters.radiusInKm) {
@@ -8703,10 +8725,53 @@ async function getClinicsByFilters(db, filters) {
8703
8725
  filters.radiusInKm = void 0;
8704
8726
  }
8705
8727
  }
8728
+ if (filters.center && filters.radiusInKm) {
8729
+ try {
8730
+ console.log("[CLINIC_SERVICE] Strategy 0: Geohash bounds prefilter");
8731
+ const bounds = (0, import_geofire_common6.geohashQueryBounds)(
8732
+ [filters.center.latitude, filters.center.longitude],
8733
+ (filters.radiusInKm || 0) * 1e3
8734
+ );
8735
+ const collected = [];
8736
+ for (const b of bounds) {
8737
+ const constraints = [
8738
+ (0, import_firestore26.where)("location.geohash", ">=", b[0]),
8739
+ (0, import_firestore26.where)("location.geohash", "<=", b[1]),
8740
+ (0, import_firestore26.where)("isActive", "==", (_a = filters.isActive) != null ? _a : true)
8741
+ ];
8742
+ if (filters.tags && filters.tags.length > 0) {
8743
+ constraints.push((0, import_firestore26.where)("tags", "array-contains", filters.tags[0]));
8744
+ }
8745
+ const q0 = (0, import_firestore26.query)((0, import_firestore26.collection)(db, CLINICS_COLLECTION), ...constraints);
8746
+ const snap = await (0, import_firestore26.getDocs)(q0);
8747
+ snap.docs.forEach((d) => collected.push({ ...d.data(), id: d.id }));
8748
+ }
8749
+ const uniqueMap = /* @__PURE__ */ new Map();
8750
+ for (const c of collected) {
8751
+ uniqueMap.set(c.id, c);
8752
+ }
8753
+ let clinics = Array.from(uniqueMap.values());
8754
+ clinics = applyInMemoryFilters(clinics, filters);
8755
+ const pageSize = filters.pagination || 5;
8756
+ let startIndex = 0;
8757
+ if (filters.lastDoc && typeof filters.lastDoc === "object" && filters.lastDoc.id) {
8758
+ const idx = clinics.findIndex((c) => c.id === filters.lastDoc.id);
8759
+ if (idx >= 0) startIndex = idx + 1;
8760
+ }
8761
+ const page = clinics.slice(startIndex, startIndex + pageSize);
8762
+ const newLastDoc = page.length === pageSize ? page[page.length - 1] : null;
8763
+ console.log(
8764
+ `[CLINIC_SERVICE] Strategy 0 success: ${page.length} clinics (of ${clinics.length})`
8765
+ );
8766
+ return { clinics: page, lastDoc: newLastDoc };
8767
+ } catch (geoErr) {
8768
+ console.log("[CLINIC_SERVICE] Strategy 0 failed:", geoErr);
8769
+ }
8770
+ }
8706
8771
  const getBaseConstraints = () => {
8707
- var _a;
8772
+ var _a2;
8708
8773
  const constraints = [];
8709
- constraints.push((0, import_firestore26.where)("isActive", "==", (_a = filters.isActive) != null ? _a : true));
8774
+ constraints.push((0, import_firestore26.where)("isActive", "==", (_a2 = filters.isActive) != null ? _a2 : true));
8710
8775
  if (filters.tags && filters.tags.length > 0) {
8711
8776
  constraints.push((0, import_firestore26.where)("tags", "array-contains", filters.tags[0]));
8712
8777
  }
@@ -8783,7 +8848,9 @@ async function getClinicsByFilters(db, filters) {
8783
8848
  }
8784
8849
  }
8785
8850
  try {
8786
- console.log("[CLINIC_SERVICE] Strategy 3: Using createdAt ordering with client-side filtering");
8851
+ console.log(
8852
+ "[CLINIC_SERVICE] Strategy 3: Using createdAt ordering with client-side filtering"
8853
+ );
8787
8854
  const constraints = getBaseConstraints();
8788
8855
  constraints.push((0, import_firestore26.orderBy)("createdAt", "desc"));
8789
8856
  if (filters.lastDoc) {
@@ -8838,20 +8905,24 @@ async function getClinicsByFilters(db, filters) {
8838
8905
  }
8839
8906
  function applyInMemoryFilters(clinics, filters) {
8840
8907
  let filteredClinics = [...clinics];
8841
- console.log(`[CLINIC_SERVICE] Applying in-memory filters - input: ${filteredClinics.length} clinics`);
8908
+ console.log(
8909
+ `[CLINIC_SERVICE] Applying in-memory filters - input: ${filteredClinics.length} clinics`
8910
+ );
8842
8911
  if (filters.tags && filters.tags.length > 1) {
8843
8912
  const initialCount = filteredClinics.length;
8844
8913
  filteredClinics = filteredClinics.filter(
8845
8914
  (clinic) => filters.tags.every((tag) => clinic.tags.includes(tag))
8846
8915
  );
8847
- console.log(`[CLINIC_SERVICE] Applied multi-tag filter: ${initialCount} \u2192 ${filteredClinics.length}`);
8916
+ console.log(
8917
+ `[CLINIC_SERVICE] Applied multi-tag filter: ${initialCount} \u2192 ${filteredClinics.length}`
8918
+ );
8848
8919
  }
8849
8920
  if (filters.tags && filters.tags.length === 1) {
8850
8921
  const initialCount = filteredClinics.length;
8851
- filteredClinics = filteredClinics.filter(
8852
- (clinic) => clinic.tags.includes(filters.tags[0])
8922
+ filteredClinics = filteredClinics.filter((clinic) => clinic.tags.includes(filters.tags[0]));
8923
+ console.log(
8924
+ `[CLINIC_SERVICE] Applied single-tag filter: ${initialCount} \u2192 ${filteredClinics.length}`
8853
8925
  );
8854
- console.log(`[CLINIC_SERVICE] Applied single-tag filter: ${initialCount} \u2192 ${filteredClinics.length}`);
8855
8926
  }
8856
8927
  if (filters.minRating !== void 0 || filters.maxRating !== void 0) {
8857
8928
  const initialCount = filteredClinics.length;
@@ -8862,7 +8933,9 @@ function applyInMemoryFilters(clinics, filters) {
8862
8933
  if (filters.maxRating !== void 0 && rating > filters.maxRating) return false;
8863
8934
  return true;
8864
8935
  });
8865
- console.log(`[CLINIC_SERVICE] Applied rating filter (${filters.minRating}-${filters.maxRating}): ${initialCount} \u2192 ${filteredClinics.length}`);
8936
+ console.log(
8937
+ `[CLINIC_SERVICE] Applied rating filter (${filters.minRating}-${filters.maxRating}): ${initialCount} \u2192 ${filteredClinics.length}`
8938
+ );
8866
8939
  }
8867
8940
  if (filters.nameSearch && filters.nameSearch.trim()) {
8868
8941
  const initialCount = filteredClinics.length;
@@ -8872,7 +8945,9 @@ function applyInMemoryFilters(clinics, filters) {
8872
8945
  const nameLower = clinic.nameLower || "";
8873
8946
  return name.includes(searchTerm) || nameLower.includes(searchTerm);
8874
8947
  });
8875
- console.log(`[CLINIC_SERVICE] Applied name search filter: ${initialCount} \u2192 ${filteredClinics.length}`);
8948
+ console.log(
8949
+ `[CLINIC_SERVICE] Applied name search filter: ${initialCount} \u2192 ${filteredClinics.length}`
8950
+ );
8876
8951
  }
8877
8952
  if (filters.procedureFamily) {
8878
8953
  const initialCount = filteredClinics.length;
@@ -8880,7 +8955,9 @@ function applyInMemoryFilters(clinics, filters) {
8880
8955
  const proceduresInfo = clinic.proceduresInfo || [];
8881
8956
  return proceduresInfo.some((proc) => proc.family === filters.procedureFamily);
8882
8957
  });
8883
- console.log(`[CLINIC_SERVICE] Applied procedure family filter: ${initialCount} \u2192 ${filteredClinics.length}`);
8958
+ console.log(
8959
+ `[CLINIC_SERVICE] Applied procedure family filter: ${initialCount} \u2192 ${filteredClinics.length}`
8960
+ );
8884
8961
  }
8885
8962
  if (filters.procedureCategory) {
8886
8963
  const initialCount = filteredClinics.length;
@@ -8888,7 +8965,9 @@ function applyInMemoryFilters(clinics, filters) {
8888
8965
  const proceduresInfo = clinic.proceduresInfo || [];
8889
8966
  return proceduresInfo.some((proc) => proc.categoryName === filters.procedureCategory);
8890
8967
  });
8891
- console.log(`[CLINIC_SERVICE] Applied procedure category filter: ${initialCount} \u2192 ${filteredClinics.length}`);
8968
+ console.log(
8969
+ `[CLINIC_SERVICE] Applied procedure category filter: ${initialCount} \u2192 ${filteredClinics.length}`
8970
+ );
8892
8971
  }
8893
8972
  if (filters.procedureSubcategory) {
8894
8973
  const initialCount = filteredClinics.length;
@@ -8896,7 +8975,9 @@ function applyInMemoryFilters(clinics, filters) {
8896
8975
  const proceduresInfo = clinic.proceduresInfo || [];
8897
8976
  return proceduresInfo.some((proc) => proc.subcategoryName === filters.procedureSubcategory);
8898
8977
  });
8899
- console.log(`[CLINIC_SERVICE] Applied procedure subcategory filter: ${initialCount} \u2192 ${filteredClinics.length}`);
8978
+ console.log(
8979
+ `[CLINIC_SERVICE] Applied procedure subcategory filter: ${initialCount} \u2192 ${filteredClinics.length}`
8980
+ );
8900
8981
  }
8901
8982
  if (filters.procedureTechnology) {
8902
8983
  const initialCount = filteredClinics.length;
@@ -8904,7 +8985,9 @@ function applyInMemoryFilters(clinics, filters) {
8904
8985
  const proceduresInfo = clinic.proceduresInfo || [];
8905
8986
  return proceduresInfo.some((proc) => proc.technologyName === filters.procedureTechnology);
8906
8987
  });
8907
- console.log(`[CLINIC_SERVICE] Applied procedure technology filter: ${initialCount} \u2192 ${filteredClinics.length}`);
8988
+ console.log(
8989
+ `[CLINIC_SERVICE] Applied procedure technology filter: ${initialCount} \u2192 ${filteredClinics.length}`
8990
+ );
8908
8991
  }
8909
8992
  if (filters.center && filters.radiusInKm) {
8910
8993
  const initialCount = filteredClinics.length;
@@ -8918,11 +9001,15 @@ function applyInMemoryFilters(clinics, filters) {
8918
9001
  [filters.center.latitude, filters.center.longitude],
8919
9002
  [clinic.location.latitude, clinic.location.longitude]
8920
9003
  ) / 1e3;
8921
- console.log(`[CLINIC_SERVICE] Clinic ${clinic.name}: distance ${distance.toFixed(2)}km (limit: ${filters.radiusInKm}km)`);
9004
+ console.log(
9005
+ `[CLINIC_SERVICE] Clinic ${clinic.name}: distance ${distance.toFixed(2)}km (limit: ${filters.radiusInKm}km)`
9006
+ );
8922
9007
  clinic.distance = distance;
8923
9008
  return distance <= filters.radiusInKm;
8924
9009
  });
8925
- console.log(`[CLINIC_SERVICE] Applied geo filter (${filters.radiusInKm}km): ${initialCount} \u2192 ${filteredClinics.length}`);
9010
+ console.log(
9011
+ `[CLINIC_SERVICE] Applied geo filter (${filters.radiusInKm}km): ${initialCount} \u2192 ${filteredClinics.length}`
9012
+ );
8926
9013
  filteredClinics.sort((a, b) => (a.distance || 0) - (b.distance || 0));
8927
9014
  }
8928
9015
  console.log(`[CLINIC_SERVICE] Final filtered result: ${filteredClinics.length} clinics`);
@@ -8950,9 +9037,7 @@ var ClinicService = class extends BaseService {
8950
9037
  return media;
8951
9038
  }
8952
9039
  if (media instanceof File || media instanceof Blob) {
8953
- console.log(
8954
- `[ClinicService] Uploading ${collectionName} media for ${ownerId}`
8955
- );
9040
+ console.log(`[ClinicService] Uploading ${collectionName} media for ${ownerId}`);
8956
9041
  const metadata = await this.mediaService.uploadMedia(
8957
9042
  media,
8958
9043
  ownerId,
@@ -8974,11 +9059,7 @@ var ClinicService = class extends BaseService {
8974
9059
  if (!mediaArray || mediaArray.length === 0) return [];
8975
9060
  const result = [];
8976
9061
  for (const media of mediaArray) {
8977
- const processedUrl = await this.processMedia(
8978
- media,
8979
- ownerId,
8980
- collectionName
8981
- );
9062
+ const processedUrl = await this.processMedia(media, ownerId, collectionName);
8982
9063
  if (processedUrl) {
8983
9064
  result.push(processedUrl);
8984
9065
  }
@@ -8996,11 +9077,7 @@ var ClinicService = class extends BaseService {
8996
9077
  if (!photosWithTags || photosWithTags.length === 0) return [];
8997
9078
  const result = [];
8998
9079
  for (const item of photosWithTags) {
8999
- const processedUrl = await this.processMedia(
9000
- item.url,
9001
- ownerId,
9002
- collectionName
9003
- );
9080
+ const processedUrl = await this.processMedia(item.url, ownerId, collectionName);
9004
9081
  if (processedUrl) {
9005
9082
  result.push({
9006
9083
  url: processedUrl,
@@ -9018,19 +9095,11 @@ var ClinicService = class extends BaseService {
9018
9095
  try {
9019
9096
  const clinicId = this.generateId();
9020
9097
  const validatedData = createClinicSchema.parse(data);
9021
- const group = await this.clinicGroupService.getClinicGroup(
9022
- validatedData.clinicGroupId
9023
- );
9098
+ const group = await this.clinicGroupService.getClinicGroup(validatedData.clinicGroupId);
9024
9099
  if (!group) {
9025
- throw new Error(
9026
- `Clinic group ${validatedData.clinicGroupId} not found`
9027
- );
9100
+ throw new Error(`Clinic group ${validatedData.clinicGroupId} not found`);
9028
9101
  }
9029
- const logoUrl = await this.processMedia(
9030
- validatedData.logo,
9031
- clinicId,
9032
- "clinic-logos"
9033
- );
9102
+ const logoUrl = await this.processMedia(validatedData.logo, clinicId, "clinic-logos");
9034
9103
  const coverPhotoUrl = await this.processMedia(
9035
9104
  validatedData.coverPhoto,
9036
9105
  clinicId,
@@ -9120,11 +9189,7 @@ var ClinicService = class extends BaseService {
9120
9189
  const validatedData = updateClinicSchema.parse(data);
9121
9190
  const updatePayload = {};
9122
9191
  if (validatedData.logo !== void 0) {
9123
- updatePayload.logo = await this.processMedia(
9124
- validatedData.logo,
9125
- clinicId,
9126
- "clinic-logos"
9127
- );
9192
+ updatePayload.logo = await this.processMedia(validatedData.logo, clinicId, "clinic-logos");
9128
9193
  }
9129
9194
  if (validatedData.coverPhoto !== void 0) {
9130
9195
  updatePayload.coverPhoto = await this.processMedia(
@@ -9224,22 +9289,10 @@ var ClinicService = class extends BaseService {
9224
9289
  * Pretražuje klinike u određenom radijusu
9225
9290
  */
9226
9291
  async findClinicsInRadius(center, radiusInKm, filters) {
9227
- return findClinicsInRadius(
9228
- this.db,
9229
- center,
9230
- radiusInKm,
9231
- filters
9232
- );
9292
+ return findClinicsInRadius(this.db, center, radiusInKm, filters);
9233
9293
  }
9234
9294
  async addTags(clinicId, adminId, newTags) {
9235
- return addTags(
9236
- this.db,
9237
- clinicId,
9238
- adminId,
9239
- newTags,
9240
- this.clinicAdminService,
9241
- this.app
9242
- );
9295
+ return addTags(this.db, clinicId, adminId, newTags, this.clinicAdminService, this.app);
9243
9296
  }
9244
9297
  async removeTags(clinicId, adminId, tagsToRemove) {
9245
9298
  return removeTags(
@@ -9277,9 +9330,7 @@ var ClinicService = class extends BaseService {
9277
9330
  clinicGroupId,
9278
9331
  adminId
9279
9332
  });
9280
- const clinicGroup = await this.clinicGroupService.getClinicGroup(
9281
- clinicGroupId
9282
- );
9333
+ const clinicGroup = await this.clinicGroupService.getClinicGroup(clinicGroupId);
9283
9334
  if (!clinicGroup) {
9284
9335
  console.error("[CLINIC_SERVICE] Clinic group not found", {
9285
9336
  clinicGroupId
@@ -9325,13 +9376,7 @@ var ClinicService = class extends BaseService {
9325
9376
  return getAllClinics(this.db, pagination, lastDoc);
9326
9377
  }
9327
9378
  async getAllClinicsInRange(center, rangeInKm, pagination, lastDoc) {
9328
- return getAllClinicsInRange(
9329
- this.db,
9330
- center,
9331
- rangeInKm,
9332
- pagination,
9333
- lastDoc
9334
- );
9379
+ return getAllClinicsInRange(this.db, center, rangeInKm, pagination, lastDoc);
9335
9380
  }
9336
9381
  /**
9337
9382
  * Get clinics based on multiple filtering criteria
@@ -14637,9 +14682,7 @@ var ProcedureService = class extends BaseService {
14637
14682
  return media;
14638
14683
  }
14639
14684
  if (media instanceof File || media instanceof Blob) {
14640
- console.log(
14641
- `[ProcedureService] Uploading ${collectionName} media for ${ownerId}`
14642
- );
14685
+ console.log(`[ProcedureService] Uploading ${collectionName} media for ${ownerId}`);
14643
14686
  const metadata = await this.mediaService.uploadMedia(
14644
14687
  media,
14645
14688
  ownerId,
@@ -14661,11 +14704,7 @@ var ProcedureService = class extends BaseService {
14661
14704
  if (!mediaArray || mediaArray.length === 0) return [];
14662
14705
  const result = [];
14663
14706
  for (const media of mediaArray) {
14664
- const processedUrl = await this.processMedia(
14665
- media,
14666
- ownerId,
14667
- collectionName
14668
- );
14707
+ const processedUrl = await this.processMedia(media, ownerId, collectionName);
14669
14708
  if (processedUrl) {
14670
14709
  result.push(processedUrl);
14671
14710
  }
@@ -14683,41 +14722,23 @@ var ProcedureService = class extends BaseService {
14683
14722
  const procedureId = this.generateId();
14684
14723
  const [category, subcategory, technology, product] = await Promise.all([
14685
14724
  this.categoryService.getById(validatedData.categoryId),
14686
- this.subcategoryService.getById(
14687
- validatedData.categoryId,
14688
- validatedData.subcategoryId
14689
- ),
14725
+ this.subcategoryService.getById(validatedData.categoryId, validatedData.subcategoryId),
14690
14726
  this.technologyService.getById(validatedData.technologyId),
14691
- this.productService.getById(
14692
- validatedData.technologyId,
14693
- validatedData.productId
14694
- )
14727
+ this.productService.getById(validatedData.technologyId, validatedData.productId)
14695
14728
  ]);
14696
14729
  if (!category || !subcategory || !technology || !product) {
14697
14730
  throw new Error("One or more required base entities not found");
14698
14731
  }
14699
- const clinicRef = (0, import_firestore45.doc)(
14700
- this.db,
14701
- CLINICS_COLLECTION,
14702
- validatedData.clinicBranchId
14703
- );
14732
+ const clinicRef = (0, import_firestore45.doc)(this.db, CLINICS_COLLECTION, validatedData.clinicBranchId);
14704
14733
  const clinicSnapshot = await (0, import_firestore45.getDoc)(clinicRef);
14705
14734
  if (!clinicSnapshot.exists()) {
14706
- throw new Error(
14707
- `Clinic with ID ${validatedData.clinicBranchId} not found`
14708
- );
14735
+ throw new Error(`Clinic with ID ${validatedData.clinicBranchId} not found`);
14709
14736
  }
14710
14737
  const clinic = clinicSnapshot.data();
14711
- const practitionerRef = (0, import_firestore45.doc)(
14712
- this.db,
14713
- PRACTITIONERS_COLLECTION,
14714
- validatedData.practitionerId
14715
- );
14738
+ const practitionerRef = (0, import_firestore45.doc)(this.db, PRACTITIONERS_COLLECTION, validatedData.practitionerId);
14716
14739
  const practitionerSnapshot = await (0, import_firestore45.getDoc)(practitionerRef);
14717
14740
  if (!practitionerSnapshot.exists()) {
14718
- throw new Error(
14719
- `Practitioner with ID ${validatedData.practitionerId} not found`
14720
- );
14741
+ throw new Error(`Practitioner with ID ${validatedData.practitionerId} not found`);
14721
14742
  }
14722
14743
  const practitioner = practitionerSnapshot.data();
14723
14744
  let processedPhotos = [];
@@ -14806,24 +14827,16 @@ var ProcedureService = class extends BaseService {
14806
14827
  const validatedData = createProcedureSchema.parse(validationData);
14807
14828
  const [category, subcategory, technology, product, clinicSnapshot] = await Promise.all([
14808
14829
  this.categoryService.getById(validatedData.categoryId),
14809
- this.subcategoryService.getById(
14810
- validatedData.categoryId,
14811
- validatedData.subcategoryId
14812
- ),
14830
+ this.subcategoryService.getById(validatedData.categoryId, validatedData.subcategoryId),
14813
14831
  this.technologyService.getById(validatedData.technologyId),
14814
- this.productService.getById(
14815
- validatedData.technologyId,
14816
- validatedData.productId
14817
- ),
14832
+ this.productService.getById(validatedData.technologyId, validatedData.productId),
14818
14833
  (0, import_firestore45.getDoc)((0, import_firestore45.doc)(this.db, CLINICS_COLLECTION, validatedData.clinicBranchId))
14819
14834
  ]);
14820
14835
  if (!category || !subcategory || !technology || !product) {
14821
14836
  throw new Error("One or more required base entities not found");
14822
14837
  }
14823
14838
  if (!clinicSnapshot.exists()) {
14824
- throw new Error(
14825
- `Clinic with ID ${validatedData.clinicBranchId} not found`
14826
- );
14839
+ throw new Error(`Clinic with ID ${validatedData.clinicBranchId} not found`);
14827
14840
  }
14828
14841
  const clinic = clinicSnapshot.data();
14829
14842
  let processedPhotos = [];
@@ -14849,12 +14862,8 @@ var ProcedureService = class extends BaseService {
14849
14862
  }
14850
14863
  if (practitionersMap.size !== practitionerIds.length) {
14851
14864
  const foundIds = Array.from(practitionersMap.keys());
14852
- const notFoundIds = practitionerIds.filter(
14853
- (id) => !foundIds.includes(id)
14854
- );
14855
- throw new Error(
14856
- `The following practitioners were not found: ${notFoundIds.join(", ")}`
14857
- );
14865
+ const notFoundIds = practitionerIds.filter((id) => !foundIds.includes(id));
14866
+ throw new Error(`The following practitioners were not found: ${notFoundIds.join(", ")}`);
14858
14867
  }
14859
14868
  const batch = (0, import_firestore45.writeBatch)(this.db);
14860
14869
  const createdProcedureIds = [];
@@ -14922,10 +14931,7 @@ var ProcedureService = class extends BaseService {
14922
14931
  const fetchedProcedures = [];
14923
14932
  for (let i = 0; i < createdProcedureIds.length; i += 30) {
14924
14933
  const chunk = createdProcedureIds.slice(i, i + 30);
14925
- const q = (0, import_firestore45.query)(
14926
- (0, import_firestore45.collection)(this.db, PROCEDURES_COLLECTION),
14927
- (0, import_firestore45.where)((0, import_firestore45.documentId)(), "in", chunk)
14928
- );
14934
+ const q = (0, import_firestore45.query)((0, import_firestore45.collection)(this.db, PROCEDURES_COLLECTION), (0, import_firestore45.where)((0, import_firestore45.documentId)(), "in", chunk));
14929
14935
  const snapshot = await (0, import_firestore45.getDocs)(q);
14930
14936
  snapshot.forEach((doc37) => {
14931
14937
  fetchedProcedures.push(doc37.data());
@@ -15026,9 +15032,7 @@ var ProcedureService = class extends BaseService {
15026
15032
  );
15027
15033
  const newPractitionerSnap = await (0, import_firestore45.getDoc)(newPractitionerRef);
15028
15034
  if (!newPractitionerSnap.exists())
15029
- throw new Error(
15030
- `New Practitioner ${validatedData.practitionerId} not found`
15031
- );
15035
+ throw new Error(`New Practitioner ${validatedData.practitionerId} not found`);
15032
15036
  newPractitioner = newPractitionerSnap.data();
15033
15037
  updatedProcedureData.doctorInfo = {
15034
15038
  id: newPractitioner.id,
@@ -15042,11 +15046,7 @@ var ProcedureService = class extends BaseService {
15042
15046
  }
15043
15047
  if (validatedData.clinicBranchId && validatedData.clinicBranchId !== oldClinicId) {
15044
15048
  clinicChanged = true;
15045
- const newClinicRef = (0, import_firestore45.doc)(
15046
- this.db,
15047
- CLINICS_COLLECTION,
15048
- validatedData.clinicBranchId
15049
- );
15049
+ const newClinicRef = (0, import_firestore45.doc)(this.db, CLINICS_COLLECTION, validatedData.clinicBranchId);
15050
15050
  const newClinicSnap = await (0, import_firestore45.getDoc)(newClinicRef);
15051
15051
  if (!newClinicSnap.exists())
15052
15052
  throw new Error(`New Clinic ${validatedData.clinicBranchId} not found`);
@@ -15065,11 +15065,8 @@ var ProcedureService = class extends BaseService {
15065
15065
  updatedProcedureData.nameLower = validatedData.name.toLowerCase();
15066
15066
  }
15067
15067
  if (validatedData.categoryId) {
15068
- const category = await this.categoryService.getById(
15069
- validatedData.categoryId
15070
- );
15071
- if (!category)
15072
- throw new Error(`Category ${validatedData.categoryId} not found`);
15068
+ const category = await this.categoryService.getById(validatedData.categoryId);
15069
+ if (!category) throw new Error(`Category ${validatedData.categoryId} not found`);
15073
15070
  updatedProcedureData.category = category;
15074
15071
  finalCategoryId = category.id;
15075
15072
  }
@@ -15084,17 +15081,12 @@ var ProcedureService = class extends BaseService {
15084
15081
  );
15085
15082
  updatedProcedureData.subcategory = subcategory;
15086
15083
  } else if (validatedData.subcategoryId) {
15087
- console.warn(
15088
- "Attempted to update subcategory without a valid categoryId"
15089
- );
15084
+ console.warn("Attempted to update subcategory without a valid categoryId");
15090
15085
  }
15091
15086
  let finalTechnologyId = existingProcedure.technology.id;
15092
15087
  if (validatedData.technologyId) {
15093
- const technology = await this.technologyService.getById(
15094
- validatedData.technologyId
15095
- );
15096
- if (!technology)
15097
- throw new Error(`Technology ${validatedData.technologyId} not found`);
15088
+ const technology = await this.technologyService.getById(validatedData.technologyId);
15089
+ if (!technology) throw new Error(`Technology ${validatedData.technologyId} not found`);
15098
15090
  updatedProcedureData.technology = technology;
15099
15091
  finalTechnologyId = technology.id;
15100
15092
  updatedProcedureData.blockingConditions = technology.blockingConditions;
@@ -15105,10 +15097,7 @@ var ProcedureService = class extends BaseService {
15105
15097
  updatedProcedureData.documentationTemplates = technology.documentationTemplates || [];
15106
15098
  }
15107
15099
  if (validatedData.productId && finalTechnologyId) {
15108
- const product = await this.productService.getById(
15109
- finalTechnologyId,
15110
- validatedData.productId
15111
- );
15100
+ const product = await this.productService.getById(finalTechnologyId, validatedData.productId);
15112
15101
  if (!product)
15113
15102
  throw new Error(
15114
15103
  `Product ${validatedData.productId} not found for technology ${finalTechnologyId}`
@@ -15190,11 +15179,7 @@ var ProcedureService = class extends BaseService {
15190
15179
  limit16(pagination)
15191
15180
  );
15192
15181
  } else {
15193
- proceduresQuery = (0, import_firestore45.query)(
15194
- proceduresCollection,
15195
- (0, import_firestore45.orderBy)("name"),
15196
- limit16(pagination)
15197
- );
15182
+ proceduresQuery = (0, import_firestore45.query)(proceduresCollection, (0, import_firestore45.orderBy)("name"), limit16(pagination));
15198
15183
  }
15199
15184
  } else {
15200
15185
  proceduresQuery = (0, import_firestore45.query)(proceduresCollection, (0, import_firestore45.orderBy)("name"));
@@ -15317,7 +15302,9 @@ var ProcedureService = class extends BaseService {
15317
15302
  constraints.push((0, import_firestore45.limit)(filters.pagination || 10));
15318
15303
  const q = (0, import_firestore45.query)((0, import_firestore45.collection)(this.db, PROCEDURES_COLLECTION), ...constraints);
15319
15304
  const querySnapshot = await (0, import_firestore45.getDocs)(q);
15320
- const procedures = querySnapshot.docs.map((doc37) => ({ ...doc37.data(), id: doc37.id }));
15305
+ const procedures = querySnapshot.docs.map(
15306
+ (doc37) => ({ ...doc37.data(), id: doc37.id })
15307
+ );
15321
15308
  const lastDoc = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
15322
15309
  console.log(`[PROCEDURE_SERVICE] Strategy 1 success: ${procedures.length} procedures`);
15323
15310
  if (procedures.length < (filters.pagination || 10)) {
@@ -15348,7 +15335,9 @@ var ProcedureService = class extends BaseService {
15348
15335
  constraints.push((0, import_firestore45.limit)(filters.pagination || 10));
15349
15336
  const q = (0, import_firestore45.query)((0, import_firestore45.collection)(this.db, PROCEDURES_COLLECTION), ...constraints);
15350
15337
  const querySnapshot = await (0, import_firestore45.getDocs)(q);
15351
- const procedures = querySnapshot.docs.map((doc37) => ({ ...doc37.data(), id: doc37.id }));
15338
+ const procedures = querySnapshot.docs.map(
15339
+ (doc37) => ({ ...doc37.data(), id: doc37.id })
15340
+ );
15352
15341
  const lastDoc = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
15353
15342
  console.log(`[PROCEDURE_SERVICE] Strategy 2 success: ${procedures.length} procedures`);
15354
15343
  if (procedures.length < (filters.pagination || 10)) {
@@ -15360,7 +15349,9 @@ var ProcedureService = class extends BaseService {
15360
15349
  }
15361
15350
  }
15362
15351
  try {
15363
- console.log("[PROCEDURE_SERVICE] Strategy 3: Using createdAt orderBy with client-side filtering");
15352
+ console.log(
15353
+ "[PROCEDURE_SERVICE] Strategy 3: Using createdAt orderBy with client-side filtering"
15354
+ );
15364
15355
  const constraints = getBaseConstraints();
15365
15356
  constraints.push((0, import_firestore45.orderBy)("createdAt", "desc"));
15366
15357
  if (filters.lastDoc) {
@@ -15375,7 +15366,9 @@ var ProcedureService = class extends BaseService {
15375
15366
  constraints.push((0, import_firestore45.limit)(filters.pagination || 10));
15376
15367
  const q = (0, import_firestore45.query)((0, import_firestore45.collection)(this.db, PROCEDURES_COLLECTION), ...constraints);
15377
15368
  const querySnapshot = await (0, import_firestore45.getDocs)(q);
15378
- let procedures = querySnapshot.docs.map((doc37) => ({ ...doc37.data(), id: doc37.id }));
15369
+ let procedures = querySnapshot.docs.map(
15370
+ (doc37) => ({ ...doc37.data(), id: doc37.id })
15371
+ );
15379
15372
  procedures = this.applyInMemoryFilters(procedures, filters);
15380
15373
  const lastDoc = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
15381
15374
  console.log(`[PROCEDURE_SERVICE] Strategy 3 success: ${procedures.length} procedures`);
@@ -15395,7 +15388,9 @@ var ProcedureService = class extends BaseService {
15395
15388
  ];
15396
15389
  const q = (0, import_firestore45.query)((0, import_firestore45.collection)(this.db, PROCEDURES_COLLECTION), ...constraints);
15397
15390
  const querySnapshot = await (0, import_firestore45.getDocs)(q);
15398
- let procedures = querySnapshot.docs.map((doc37) => ({ ...doc37.data(), id: doc37.id }));
15391
+ let procedures = querySnapshot.docs.map(
15392
+ (doc37) => ({ ...doc37.data(), id: doc37.id })
15393
+ );
15399
15394
  procedures = this.applyInMemoryFilters(procedures, filters);
15400
15395
  const lastDoc = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
15401
15396
  console.log(`[PROCEDURE_SERVICE] Strategy 4 success: ${procedures.length} procedures`);
@@ -15435,7 +15430,9 @@ var ProcedureService = class extends BaseService {
15435
15430
  if (filters.maxPrice !== void 0 && price > filters.maxPrice) return false;
15436
15431
  return true;
15437
15432
  });
15438
- console.log(`[PROCEDURE_SERVICE] Applied price filter (${filters.minPrice}-${filters.maxPrice}), results: ${filteredProcedures.length}`);
15433
+ console.log(
15434
+ `[PROCEDURE_SERVICE] Applied price filter (${filters.minPrice}-${filters.maxPrice}), results: ${filteredProcedures.length}`
15435
+ );
15439
15436
  }
15440
15437
  if (filters.minRating !== void 0 || filters.maxRating !== void 0) {
15441
15438
  filteredProcedures = filteredProcedures.filter((procedure) => {
@@ -15445,7 +15442,9 @@ var ProcedureService = class extends BaseService {
15445
15442
  if (filters.maxRating !== void 0 && rating > filters.maxRating) return false;
15446
15443
  return true;
15447
15444
  });
15448
- console.log(`[PROCEDURE_SERVICE] Applied rating filter, results: ${filteredProcedures.length}`);
15445
+ console.log(
15446
+ `[PROCEDURE_SERVICE] Applied rating filter, results: ${filteredProcedures.length}`
15447
+ );
15449
15448
  }
15450
15449
  if (filters.treatmentBenefits && filters.treatmentBenefits.length > 0) {
15451
15450
  const benefitsToMatch = filters.treatmentBenefits;
@@ -15453,32 +15452,50 @@ var ProcedureService = class extends BaseService {
15453
15452
  const procedureBenefits = procedure.treatmentBenefits || [];
15454
15453
  return benefitsToMatch.some((benefit) => procedureBenefits.includes(benefit));
15455
15454
  });
15456
- console.log(`[PROCEDURE_SERVICE] Applied benefits filter, results: ${filteredProcedures.length}`);
15455
+ console.log(
15456
+ `[PROCEDURE_SERVICE] Applied benefits filter, results: ${filteredProcedures.length}`
15457
+ );
15457
15458
  }
15458
15459
  if (filters.procedureFamily) {
15459
- filteredProcedures = filteredProcedures.filter((procedure) => procedure.family === filters.procedureFamily);
15460
- console.log(`[PROCEDURE_SERVICE] Applied family filter, results: ${filteredProcedures.length}`);
15460
+ filteredProcedures = filteredProcedures.filter(
15461
+ (procedure) => procedure.family === filters.procedureFamily
15462
+ );
15463
+ console.log(
15464
+ `[PROCEDURE_SERVICE] Applied family filter, results: ${filteredProcedures.length}`
15465
+ );
15461
15466
  }
15462
15467
  if (filters.procedureCategory) {
15463
- filteredProcedures = filteredProcedures.filter((procedure) => {
15464
- var _a;
15465
- return ((_a = procedure.category) == null ? void 0 : _a.id) === filters.procedureCategory;
15466
- });
15467
- console.log(`[PROCEDURE_SERVICE] Applied category filter, results: ${filteredProcedures.length}`);
15468
+ filteredProcedures = filteredProcedures.filter(
15469
+ (procedure) => {
15470
+ var _a;
15471
+ return ((_a = procedure.category) == null ? void 0 : _a.id) === filters.procedureCategory;
15472
+ }
15473
+ );
15474
+ console.log(
15475
+ `[PROCEDURE_SERVICE] Applied category filter, results: ${filteredProcedures.length}`
15476
+ );
15468
15477
  }
15469
15478
  if (filters.procedureSubcategory) {
15470
- filteredProcedures = filteredProcedures.filter((procedure) => {
15471
- var _a;
15472
- return ((_a = procedure.subcategory) == null ? void 0 : _a.id) === filters.procedureSubcategory;
15473
- });
15474
- console.log(`[PROCEDURE_SERVICE] Applied subcategory filter, results: ${filteredProcedures.length}`);
15479
+ filteredProcedures = filteredProcedures.filter(
15480
+ (procedure) => {
15481
+ var _a;
15482
+ return ((_a = procedure.subcategory) == null ? void 0 : _a.id) === filters.procedureSubcategory;
15483
+ }
15484
+ );
15485
+ console.log(
15486
+ `[PROCEDURE_SERVICE] Applied subcategory filter, results: ${filteredProcedures.length}`
15487
+ );
15475
15488
  }
15476
15489
  if (filters.procedureTechnology) {
15477
- filteredProcedures = filteredProcedures.filter((procedure) => {
15478
- var _a;
15479
- return ((_a = procedure.technology) == null ? void 0 : _a.id) === filters.procedureTechnology;
15480
- });
15481
- console.log(`[PROCEDURE_SERVICE] Applied technology filter, results: ${filteredProcedures.length}`);
15490
+ filteredProcedures = filteredProcedures.filter(
15491
+ (procedure) => {
15492
+ var _a;
15493
+ return ((_a = procedure.technology) == null ? void 0 : _a.id) === filters.procedureTechnology;
15494
+ }
15495
+ );
15496
+ console.log(
15497
+ `[PROCEDURE_SERVICE] Applied technology filter, results: ${filteredProcedures.length}`
15498
+ );
15482
15499
  }
15483
15500
  if (filters.location && filters.radiusInKm && filters.radiusInKm > 0) {
15484
15501
  const location = filters.location;
@@ -15502,29 +15519,48 @@ var ProcedureService = class extends BaseService {
15502
15519
  return filteredProcedures;
15503
15520
  }
15504
15521
  handleGeoQuery(filters) {
15505
- console.log("[PROCEDURE_SERVICE] Executing geo query with enhanced debugging");
15522
+ console.log("[PROCEDURE_SERVICE] Executing geo query with geohash bounds");
15506
15523
  try {
15507
15524
  const location = filters.location;
15508
15525
  const radiusInKm = filters.radiusInKm;
15509
- console.log("[PROCEDURE_SERVICE] Geo query parameters:", {
15510
- latitude: location.latitude,
15511
- longitude: location.longitude,
15512
- radiusInKm,
15513
- pagination: filters.pagination || 10
15526
+ if (!location || !radiusInKm) {
15527
+ return Promise.resolve({ procedures: [], lastDoc: null });
15528
+ }
15529
+ const bounds = (0, import_geofire_common8.geohashQueryBounds)([location.latitude, location.longitude], radiusInKm * 1e3);
15530
+ const fetches = bounds.map((b) => {
15531
+ const constraints = [
15532
+ (0, import_firestore45.where)("clinicInfo.location.geohash", ">=", b[0]),
15533
+ (0, import_firestore45.where)("clinicInfo.location.geohash", "<=", b[1]),
15534
+ (0, import_firestore45.where)("isActive", "==", filters.isActive !== void 0 ? filters.isActive : true)
15535
+ ];
15536
+ return (0, import_firestore45.getDocs)((0, import_firestore45.query)((0, import_firestore45.collection)(this.db, PROCEDURES_COLLECTION), ...constraints));
15514
15537
  });
15515
- const constraints = [
15516
- (0, import_firestore45.where)("isActive", "==", true),
15517
- (0, import_firestore45.orderBy)("createdAt", "desc"),
15518
- (0, import_firestore45.limit)((filters.pagination || 10) * 3)
15519
- // Get more results for geo filtering
15520
- ];
15521
- const q = (0, import_firestore45.query)((0, import_firestore45.collection)(this.db, PROCEDURES_COLLECTION), ...constraints);
15522
- return (0, import_firestore45.getDocs)(q).then((querySnapshot) => {
15523
- let procedures = querySnapshot.docs.map((doc37) => ({ ...doc37.data(), id: doc37.id }));
15538
+ return Promise.all(fetches).then((snaps) => {
15539
+ const collected = [];
15540
+ snaps.forEach((snap) => {
15541
+ snap.docs.forEach((d) => collected.push({ ...d.data(), id: d.id }));
15542
+ });
15543
+ const uniqueMap = /* @__PURE__ */ new Map();
15544
+ for (const p of collected) {
15545
+ uniqueMap.set(p.id, p);
15546
+ }
15547
+ let procedures = Array.from(uniqueMap.values());
15524
15548
  procedures = this.applyInMemoryFilters(procedures, filters);
15525
- console.log(`[PROCEDURE_SERVICE] Geo query success: ${procedures.length} procedures within ${radiusInKm}km`);
15526
- const lastDoc = procedures.length < (filters.pagination || 10) ? null : querySnapshot.docs[querySnapshot.docs.length - 1];
15527
- return { procedures, lastDoc };
15549
+ const pageSize = filters.pagination || 10;
15550
+ let startIndex = 0;
15551
+ if (filters.lastDoc && typeof filters.lastDoc === "object" && filters.lastDoc.id) {
15552
+ const idx = procedures.findIndex((p) => p.id === filters.lastDoc.id);
15553
+ if (idx >= 0) startIndex = idx + 1;
15554
+ }
15555
+ const page = procedures.slice(startIndex, startIndex + pageSize);
15556
+ const newLastDoc = page.length === pageSize ? page[page.length - 1] : null;
15557
+ console.log(
15558
+ `[PROCEDURE_SERVICE] Geo query success: ${page.length} (of ${procedures.length}) within ${radiusInKm}km`
15559
+ );
15560
+ return { procedures: page, lastDoc: newLastDoc };
15561
+ }).catch((err) => {
15562
+ console.error("[PROCEDURE_SERVICE] Geo bounds fetch failed:", err);
15563
+ return { procedures: [], lastDoc: null };
15528
15564
  });
15529
15565
  } catch (error) {
15530
15566
  console.error("[PROCEDURE_SERVICE] Geo query failed:", error);
@@ -15554,11 +15590,7 @@ var ProcedureService = class extends BaseService {
15554
15590
  throw new Error(`Clinic with ID ${data.clinicBranchId} not found`);
15555
15591
  }
15556
15592
  const clinic = clinicSnapshot.data();
15557
- const practitionerRef = (0, import_firestore45.doc)(
15558
- this.db,
15559
- PRACTITIONERS_COLLECTION,
15560
- data.practitionerId
15561
- );
15593
+ const practitionerRef = (0, import_firestore45.doc)(this.db, PRACTITIONERS_COLLECTION, data.practitionerId);
15562
15594
  const practitionerSnapshot = await (0, import_firestore45.getDoc)(practitionerRef);
15563
15595
  if (!practitionerSnapshot.exists()) {
15564
15596
  throw new Error(`Practitioner with ID ${data.practitionerId} not found`);
@@ -15566,11 +15598,7 @@ var ProcedureService = class extends BaseService {
15566
15598
  const practitioner = practitionerSnapshot.data();
15567
15599
  let processedPhotos = [];
15568
15600
  if (data.photos && data.photos.length > 0) {
15569
- processedPhotos = await this.processMediaArray(
15570
- data.photos,
15571
- procedureId,
15572
- "procedure-photos"
15573
- );
15601
+ processedPhotos = await this.processMediaArray(data.photos, procedureId, "procedure-photos");
15574
15602
  }
15575
15603
  const clinicInfo = {
15576
15604
  id: clinicSnapshot.id,