@blackcode_sa/metaestetics-api 1.12.0 → 1.12.2

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
@@ -6595,7 +6595,9 @@ var PractitionerService = class extends BaseService {
6595
6595
  throw new Error(`Practitioner ${practitionerId} not found`);
6596
6596
  }
6597
6597
  const currentPractitioner = practitionerDoc.data();
6598
- let processedData = { ...validData };
6598
+ let processedData = {
6599
+ ...validData
6600
+ };
6599
6601
  if (validData.basicInfo) {
6600
6602
  processedData.basicInfo = await this.processBasicInfo(
6601
6603
  validData.basicInfo,
@@ -6829,7 +6831,9 @@ var PractitionerService = class extends BaseService {
6829
6831
  */
6830
6832
  async getPractitionersByFilters(filters) {
6831
6833
  try {
6832
- console.log("[PRACTITIONER_SERVICE] Starting practitioner filtering with fallback strategies");
6834
+ console.log(
6835
+ "[PRACTITIONER_SERVICE] Starting practitioner filtering with fallback strategies"
6836
+ );
6833
6837
  if (filters.location && filters.radiusInKm) {
6834
6838
  console.log("[PRACTITIONER_SERVICE] Executing geo query:", {
6835
6839
  location: filters.location,
@@ -6837,14 +6841,19 @@ var PractitionerService = class extends BaseService {
6837
6841
  serviceName: "PractitionerService"
6838
6842
  });
6839
6843
  if (!filters.location.latitude || !filters.location.longitude) {
6840
- console.warn("[PRACTITIONER_SERVICE] Invalid location data:", filters.location);
6844
+ console.warn(
6845
+ "[PRACTITIONER_SERVICE] Invalid location data:",
6846
+ filters.location
6847
+ );
6841
6848
  filters.location = void 0;
6842
6849
  filters.radiusInKm = void 0;
6843
6850
  }
6844
6851
  }
6845
6852
  if (filters.nameSearch && filters.nameSearch.trim()) {
6846
6853
  try {
6847
- console.log("[PRACTITIONER_SERVICE] Strategy 1: Trying fullNameLower search");
6854
+ console.log(
6855
+ "[PRACTITIONER_SERVICE] Strategy 1: Trying fullNameLower search"
6856
+ );
6848
6857
  const searchTerm = filters.nameSearch.trim().toLowerCase();
6849
6858
  const constraints = [];
6850
6859
  if (!filters.includeDraftPractitioners) {
@@ -6864,11 +6873,18 @@ var PractitionerService = class extends BaseService {
6864
6873
  }
6865
6874
  }
6866
6875
  constraints.push((0, import_firestore21.limit)(filters.pagination || 10));
6867
- const q = (0, import_firestore21.query)((0, import_firestore21.collection)(this.db, PRACTITIONERS_COLLECTION), ...constraints);
6876
+ const q = (0, import_firestore21.query)(
6877
+ (0, import_firestore21.collection)(this.db, PRACTITIONERS_COLLECTION),
6878
+ ...constraints
6879
+ );
6868
6880
  const querySnapshot = await (0, import_firestore21.getDocs)(q);
6869
- const practitioners = querySnapshot.docs.map((doc38) => ({ ...doc38.data(), id: doc38.id }));
6881
+ const practitioners = querySnapshot.docs.map(
6882
+ (doc38) => ({ ...doc38.data(), id: doc38.id })
6883
+ );
6870
6884
  const lastDoc = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
6871
- console.log(`[PRACTITIONER_SERVICE] Strategy 1 success: ${practitioners.length} practitioners`);
6885
+ console.log(
6886
+ `[PRACTITIONER_SERVICE] Strategy 1 success: ${practitioners.length} practitioners`
6887
+ );
6872
6888
  if (practitioners.length < (filters.pagination || 10)) {
6873
6889
  return { practitioners, lastDoc: null };
6874
6890
  }
@@ -6878,7 +6894,9 @@ var PractitionerService = class extends BaseService {
6878
6894
  }
6879
6895
  }
6880
6896
  try {
6881
- console.log("[PRACTITIONER_SERVICE] Strategy 2: Basic query with createdAt ordering");
6897
+ console.log(
6898
+ "[PRACTITIONER_SERVICE] Strategy 2: Basic query with createdAt ordering"
6899
+ );
6882
6900
  const constraints = [];
6883
6901
  if (!filters.includeDraftPractitioners) {
6884
6902
  constraints.push((0, import_firestore21.where)("status", "==", "active" /* ACTIVE */));
@@ -6887,14 +6905,22 @@ var PractitionerService = class extends BaseService {
6887
6905
  if (filters.certifications && filters.certifications.length > 0) {
6888
6906
  const certificationsToMatch = filters.certifications;
6889
6907
  constraints.push(
6890
- (0, import_firestore21.where)("certification.specialties", "array-contains-any", certificationsToMatch)
6908
+ (0, import_firestore21.where)(
6909
+ "certification.specialties",
6910
+ "array-contains-any",
6911
+ certificationsToMatch
6912
+ )
6891
6913
  );
6892
6914
  }
6893
6915
  if (filters.minRating !== void 0) {
6894
- constraints.push((0, import_firestore21.where)("reviewInfo.averageRating", ">=", filters.minRating));
6916
+ constraints.push(
6917
+ (0, import_firestore21.where)("reviewInfo.averageRating", ">=", filters.minRating)
6918
+ );
6895
6919
  }
6896
6920
  if (filters.maxRating !== void 0) {
6897
- constraints.push((0, import_firestore21.where)("reviewInfo.averageRating", "<=", filters.maxRating));
6921
+ constraints.push(
6922
+ (0, import_firestore21.where)("reviewInfo.averageRating", "<=", filters.maxRating)
6923
+ );
6898
6924
  }
6899
6925
  constraints.push((0, import_firestore21.orderBy)("createdAt", "desc"));
6900
6926
  if (filters.location && filters.radiusInKm) {
@@ -6911,9 +6937,14 @@ var PractitionerService = class extends BaseService {
6911
6937
  }
6912
6938
  constraints.push((0, import_firestore21.limit)(filters.pagination || 10));
6913
6939
  }
6914
- const q = (0, import_firestore21.query)((0, import_firestore21.collection)(this.db, PRACTITIONERS_COLLECTION), ...constraints);
6940
+ const q = (0, import_firestore21.query)(
6941
+ (0, import_firestore21.collection)(this.db, PRACTITIONERS_COLLECTION),
6942
+ ...constraints
6943
+ );
6915
6944
  const querySnapshot = await (0, import_firestore21.getDocs)(q);
6916
- let practitioners = querySnapshot.docs.map((doc38) => ({ ...doc38.data(), id: doc38.id }));
6945
+ let practitioners = querySnapshot.docs.map(
6946
+ (doc38) => ({ ...doc38.data(), id: doc38.id })
6947
+ );
6917
6948
  if (filters.location && filters.radiusInKm && filters.radiusInKm > 0) {
6918
6949
  const location = filters.location;
6919
6950
  const radiusInKm = filters.radiusInKm;
@@ -6932,7 +6963,9 @@ var PractitionerService = class extends BaseService {
6932
6963
  }
6933
6964
  practitioners = this.applyInMemoryFilters(practitioners, filters);
6934
6965
  const lastDoc = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
6935
- console.log(`[PRACTITIONER_SERVICE] Strategy 2 success: ${practitioners.length} practitioners`);
6966
+ console.log(
6967
+ `[PRACTITIONER_SERVICE] Strategy 2 success: ${practitioners.length} practitioners`
6968
+ );
6936
6969
  if (practitioners.length < (filters.pagination || 10)) {
6937
6970
  return { practitioners, lastDoc: null };
6938
6971
  }
@@ -6941,18 +6974,27 @@ var PractitionerService = class extends BaseService {
6941
6974
  console.log("[PRACTITIONER_SERVICE] Strategy 2 failed:", error);
6942
6975
  }
6943
6976
  try {
6944
- console.log("[PRACTITIONER_SERVICE] Strategy 3: Minimal query fallback");
6977
+ console.log(
6978
+ "[PRACTITIONER_SERVICE] Strategy 3: Minimal query fallback"
6979
+ );
6945
6980
  const constraints = [
6946
6981
  (0, import_firestore21.where)("isActive", "==", true),
6947
6982
  (0, import_firestore21.orderBy)("createdAt", "desc"),
6948
6983
  (0, import_firestore21.limit)(filters.pagination || 10)
6949
6984
  ];
6950
- const q = (0, import_firestore21.query)((0, import_firestore21.collection)(this.db, PRACTITIONERS_COLLECTION), ...constraints);
6985
+ const q = (0, import_firestore21.query)(
6986
+ (0, import_firestore21.collection)(this.db, PRACTITIONERS_COLLECTION),
6987
+ ...constraints
6988
+ );
6951
6989
  const querySnapshot = await (0, import_firestore21.getDocs)(q);
6952
- let practitioners = querySnapshot.docs.map((doc38) => ({ ...doc38.data(), id: doc38.id }));
6990
+ let practitioners = querySnapshot.docs.map(
6991
+ (doc38) => ({ ...doc38.data(), id: doc38.id })
6992
+ );
6953
6993
  practitioners = this.applyInMemoryFilters(practitioners, filters);
6954
6994
  const lastDoc = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
6955
- console.log(`[PRACTITIONER_SERVICE] Strategy 3 success: ${practitioners.length} practitioners`);
6995
+ console.log(
6996
+ `[PRACTITIONER_SERVICE] Strategy 3 success: ${practitioners.length} practitioners`
6997
+ );
6956
6998
  if (practitioners.length < (filters.pagination || 10)) {
6957
6999
  return { practitioners, lastDoc: null };
6958
7000
  }
@@ -6961,19 +7003,28 @@ var PractitionerService = class extends BaseService {
6961
7003
  console.log("[PRACTITIONER_SERVICE] Strategy 3 failed:", error);
6962
7004
  }
6963
7005
  try {
6964
- console.log("[PRACTITIONER_SERVICE] Strategy 4: Client-side filtering fallback");
7006
+ console.log(
7007
+ "[PRACTITIONER_SERVICE] Strategy 4: Client-side filtering fallback"
7008
+ );
6965
7009
  const constraints = [
6966
7010
  (0, import_firestore21.where)("isActive", "==", true),
6967
7011
  (0, import_firestore21.where)("status", "==", "active" /* ACTIVE */),
6968
7012
  (0, import_firestore21.orderBy)("createdAt", "desc"),
6969
7013
  (0, import_firestore21.limit)(filters.pagination || 10)
6970
7014
  ];
6971
- const q = (0, import_firestore21.query)((0, import_firestore21.collection)(this.db, PRACTITIONERS_COLLECTION), ...constraints);
7015
+ const q = (0, import_firestore21.query)(
7016
+ (0, import_firestore21.collection)(this.db, PRACTITIONERS_COLLECTION),
7017
+ ...constraints
7018
+ );
6972
7019
  const querySnapshot = await (0, import_firestore21.getDocs)(q);
6973
- let practitioners = querySnapshot.docs.map((doc38) => ({ ...doc38.data(), id: doc38.id }));
7020
+ let practitioners = querySnapshot.docs.map(
7021
+ (doc38) => ({ ...doc38.data(), id: doc38.id })
7022
+ );
6974
7023
  practitioners = this.applyInMemoryFilters(practitioners, filters);
6975
7024
  const lastDoc = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
6976
- console.log(`[PRACTITIONER_SERVICE] Strategy 4 success: ${practitioners.length} practitioners`);
7025
+ console.log(
7026
+ `[PRACTITIONER_SERVICE] Strategy 4 success: ${practitioners.length} practitioners`
7027
+ );
6977
7028
  if (practitioners.length < (filters.pagination || 10)) {
6978
7029
  return { practitioners, lastDoc: null };
6979
7030
  }
@@ -6981,10 +7032,15 @@ var PractitionerService = class extends BaseService {
6981
7032
  } catch (error) {
6982
7033
  console.log("[PRACTITIONER_SERVICE] Strategy 4 failed:", error);
6983
7034
  }
6984
- console.log("[PRACTITIONER_SERVICE] All strategies failed, returning empty result");
7035
+ console.log(
7036
+ "[PRACTITIONER_SERVICE] All strategies failed, returning empty result"
7037
+ );
6985
7038
  return { practitioners: [], lastDoc: null };
6986
7039
  } catch (error) {
6987
- console.error("[PRACTITIONER_SERVICE] Error filtering practitioners:", error);
7040
+ console.error(
7041
+ "[PRACTITIONER_SERVICE] Error filtering practitioners:",
7042
+ error
7043
+ );
6988
7044
  return { practitioners: [], lastDoc: null };
6989
7045
  }
6990
7046
  }
@@ -7004,63 +7060,93 @@ var PractitionerService = class extends BaseService {
7004
7060
  const fullNameLower = practitioner.fullNameLower || "";
7005
7061
  return firstName.includes(searchTerm) || lastName.includes(searchTerm) || fullName.includes(searchTerm) || fullNameLower.includes(searchTerm);
7006
7062
  });
7007
- console.log(`[PRACTITIONER_SERVICE] Applied name filter, results: ${filteredPractitioners.length}`);
7063
+ console.log(
7064
+ `[PRACTITIONER_SERVICE] Applied name filter, results: ${filteredPractitioners.length}`
7065
+ );
7008
7066
  }
7009
7067
  if (filters.certifications && filters.certifications.length > 0) {
7010
7068
  const certificationsToMatch = filters.certifications;
7011
7069
  filteredPractitioners = filteredPractitioners.filter((practitioner) => {
7012
7070
  var _a;
7013
7071
  const practitionerCerts = ((_a = practitioner.certification) == null ? void 0 : _a.specialties) || [];
7014
- return certificationsToMatch.some((cert) => practitionerCerts.includes(cert));
7072
+ return certificationsToMatch.some(
7073
+ (cert) => practitionerCerts.includes(cert)
7074
+ );
7015
7075
  });
7016
- console.log(`[PRACTITIONER_SERVICE] Applied certifications filter, results: ${filteredPractitioners.length}`);
7076
+ console.log(
7077
+ `[PRACTITIONER_SERVICE] Applied certifications filter, results: ${filteredPractitioners.length}`
7078
+ );
7017
7079
  }
7018
7080
  if (filters.specialties && filters.specialties.length > 0) {
7019
7081
  const specialtiesToMatch = filters.specialties;
7020
7082
  filteredPractitioners = filteredPractitioners.filter((practitioner) => {
7021
7083
  var _a;
7022
7084
  const practitionerSpecs = ((_a = practitioner.certification) == null ? void 0 : _a.specialties) || [];
7023
- return specialtiesToMatch.some((spec) => practitionerSpecs.includes(spec));
7085
+ return specialtiesToMatch.some(
7086
+ (spec) => practitionerSpecs.includes(spec)
7087
+ );
7024
7088
  });
7025
- console.log(`[PRACTITIONER_SERVICE] Applied specialties filter, results: ${filteredPractitioners.length}`);
7089
+ console.log(
7090
+ `[PRACTITIONER_SERVICE] Applied specialties filter, results: ${filteredPractitioners.length}`
7091
+ );
7026
7092
  }
7027
7093
  if (filters.minRating !== void 0 || filters.maxRating !== void 0) {
7028
7094
  filteredPractitioners = filteredPractitioners.filter((practitioner) => {
7029
7095
  var _a;
7030
7096
  const rating = ((_a = practitioner.reviewInfo) == null ? void 0 : _a.averageRating) || 0;
7031
- if (filters.minRating !== void 0 && rating < filters.minRating) return false;
7032
- if (filters.maxRating !== void 0 && rating > filters.maxRating) return false;
7097
+ if (filters.minRating !== void 0 && rating < filters.minRating)
7098
+ return false;
7099
+ if (filters.maxRating !== void 0 && rating > filters.maxRating)
7100
+ return false;
7033
7101
  return true;
7034
7102
  });
7035
- console.log(`[PRACTITIONER_SERVICE] Applied rating filter, results: ${filteredPractitioners.length}`);
7103
+ console.log(
7104
+ `[PRACTITIONER_SERVICE] Applied rating filter, results: ${filteredPractitioners.length}`
7105
+ );
7036
7106
  }
7037
7107
  if (filters.procedureFamily) {
7038
7108
  filteredPractitioners = filteredPractitioners.filter((practitioner) => {
7039
7109
  const proceduresInfo = practitioner.proceduresInfo || [];
7040
- return proceduresInfo.some((proc) => proc.family === filters.procedureFamily);
7110
+ return proceduresInfo.some(
7111
+ (proc) => proc.family === filters.procedureFamily
7112
+ );
7041
7113
  });
7042
- console.log(`[PRACTITIONER_SERVICE] Applied procedure family filter, results: ${filteredPractitioners.length}`);
7114
+ console.log(
7115
+ `[PRACTITIONER_SERVICE] Applied procedure family filter, results: ${filteredPractitioners.length}`
7116
+ );
7043
7117
  }
7044
7118
  if (filters.procedureCategory) {
7045
7119
  filteredPractitioners = filteredPractitioners.filter((practitioner) => {
7046
7120
  const proceduresInfo = practitioner.proceduresInfo || [];
7047
- return proceduresInfo.some((proc) => proc.categoryName === filters.procedureCategory);
7121
+ return proceduresInfo.some(
7122
+ (proc) => proc.categoryName === filters.procedureCategory
7123
+ );
7048
7124
  });
7049
- console.log(`[PRACTITIONER_SERVICE] Applied procedure category filter, results: ${filteredPractitioners.length}`);
7125
+ console.log(
7126
+ `[PRACTITIONER_SERVICE] Applied procedure category filter, results: ${filteredPractitioners.length}`
7127
+ );
7050
7128
  }
7051
7129
  if (filters.procedureSubcategory) {
7052
7130
  filteredPractitioners = filteredPractitioners.filter((practitioner) => {
7053
7131
  const proceduresInfo = practitioner.proceduresInfo || [];
7054
- return proceduresInfo.some((proc) => proc.subcategoryName === filters.procedureSubcategory);
7132
+ return proceduresInfo.some(
7133
+ (proc) => proc.subcategoryName === filters.procedureSubcategory
7134
+ );
7055
7135
  });
7056
- console.log(`[PRACTITIONER_SERVICE] Applied procedure subcategory filter, results: ${filteredPractitioners.length}`);
7136
+ console.log(
7137
+ `[PRACTITIONER_SERVICE] Applied procedure subcategory filter, results: ${filteredPractitioners.length}`
7138
+ );
7057
7139
  }
7058
7140
  if (filters.procedureTechnology) {
7059
7141
  filteredPractitioners = filteredPractitioners.filter((practitioner) => {
7060
7142
  const proceduresInfo = practitioner.proceduresInfo || [];
7061
- return proceduresInfo.some((proc) => proc.technologyName === filters.procedureTechnology);
7143
+ return proceduresInfo.some(
7144
+ (proc) => proc.technologyName === filters.procedureTechnology
7145
+ );
7062
7146
  });
7063
- console.log(`[PRACTITIONER_SERVICE] Applied procedure technology filter, results: ${filteredPractitioners.length}`);
7147
+ console.log(
7148
+ `[PRACTITIONER_SERVICE] Applied procedure technology filter, results: ${filteredPractitioners.length}`
7149
+ );
7064
7150
  }
7065
7151
  if (filters.location && filters.radiusInKm && filters.radiusInKm > 0) {
7066
7152
  const location = filters.location;
@@ -7076,7 +7162,9 @@ var PractitionerService = class extends BaseService {
7076
7162
  return distanceInKm <= radiusInKm;
7077
7163
  });
7078
7164
  });
7079
- console.log(`[PRACTITIONER_SERVICE] Applied geo filter, results: ${filteredPractitioners.length}`);
7165
+ console.log(
7166
+ `[PRACTITIONER_SERVICE] Applied geo filter, results: ${filteredPractitioners.length}`
7167
+ );
7080
7168
  }
7081
7169
  return filteredPractitioners;
7082
7170
  }
@@ -7141,6 +7229,15 @@ var PractitionerService = class extends BaseService {
7141
7229
  price: 0,
7142
7230
  currency: "EUR" /* EUR */,
7143
7231
  pricingMeasure: "per_session" /* PER_SESSION */,
7232
+ productsMetadata: [
7233
+ {
7234
+ productId: "free-consultation-product",
7235
+ price: 0,
7236
+ currency: "EUR" /* EUR */,
7237
+ pricingMeasure: "per_session" /* PER_SESSION */,
7238
+ isDefault: true
7239
+ }
7240
+ ],
7144
7241
  duration: 30,
7145
7242
  // 30 minutes consultation
7146
7243
  practitionerId,
@@ -14732,67 +14829,141 @@ var PatientRequirementsService = class extends BaseService {
14732
14829
  var import_firestore46 = require("firebase/firestore");
14733
14830
 
14734
14831
  // src/validations/procedure.schema.ts
14832
+ var import_zod25 = require("zod");
14833
+
14834
+ // src/validations/procedure-product.schema.ts
14735
14835
  var import_zod24 = require("zod");
14736
- var createProcedureSchema = import_zod24.z.object({
14737
- name: import_zod24.z.string().min(1).max(200),
14738
- // Optional: service will derive from name if not provided by client
14739
- nameLower: import_zod24.z.string().min(1).max(200).optional(),
14740
- description: import_zod24.z.string().min(1).max(2e3),
14741
- family: import_zod24.z.nativeEnum(ProcedureFamily),
14742
- categoryId: import_zod24.z.string().min(1),
14743
- subcategoryId: import_zod24.z.string().min(1),
14744
- technologyId: import_zod24.z.string().min(1),
14745
- productId: import_zod24.z.string().min(1),
14746
- price: import_zod24.z.number().min(0),
14836
+ var procedureProductDataSchema = import_zod24.z.object({
14837
+ /**
14838
+ * The ID of the product. Must be a non-empty string.
14839
+ * @validation
14840
+ */
14841
+ productId: import_zod24.z.string().min(1, "Product ID is required"),
14842
+ /**
14843
+ * The price of the product. Must be a non-negative number.
14844
+ * @validation
14845
+ */
14846
+ price: import_zod24.z.number().min(0, "Price must be a non-negative number"),
14847
+ /**
14848
+ * The currency for the price. Must be one of the values from the Currency enum.
14849
+ * @validation
14850
+ */
14747
14851
  currency: import_zod24.z.nativeEnum(Currency),
14852
+ /**
14853
+ * The pricing measure for the product. Must be one of the values from the PricingMeasure enum.
14854
+ * @validation
14855
+ */
14748
14856
  pricingMeasure: import_zod24.z.nativeEnum(PricingMeasure),
14749
- duration: import_zod24.z.number().min(1).max(480),
14857
+ /**
14858
+ * Whether this is the default product for the procedure.
14859
+ * @validation
14860
+ */
14861
+ isDefault: import_zod24.z.boolean().optional()
14862
+ });
14863
+
14864
+ // src/validations/procedure.schema.ts
14865
+ var storedProcedureProductSchema = import_zod25.z.object({
14866
+ /**
14867
+ * The full product object used in the procedure.
14868
+ */
14869
+ product: import_zod25.z.any(),
14870
+ // We'll validate the full product object separately
14871
+ /**
14872
+ * The price of the procedure when using this specific product.
14873
+ */
14874
+ price: import_zod25.z.number().min(0, "Price must be a non-negative number"),
14875
+ /**
14876
+ * The currency for the price of this product.
14877
+ */
14878
+ currency: import_zod25.z.nativeEnum(Currency),
14879
+ /**
14880
+ * How the price is measured (e.g., per ml, per zone).
14881
+ */
14882
+ pricingMeasure: import_zod25.z.nativeEnum(PricingMeasure),
14883
+ /**
14884
+ * Whether this is the default product for the procedure.
14885
+ */
14886
+ isDefault: import_zod25.z.boolean().optional()
14887
+ });
14888
+ var createProcedureSchema = import_zod25.z.object({
14889
+ name: import_zod25.z.string().min(1).max(200),
14890
+ // Optional: service will derive from name if not provided by client
14891
+ nameLower: import_zod25.z.string().min(1).max(200).optional(),
14892
+ description: import_zod25.z.string().min(1).max(2e3),
14893
+ family: import_zod25.z.nativeEnum(ProcedureFamily),
14894
+ categoryId: import_zod25.z.string().min(1),
14895
+ subcategoryId: import_zod25.z.string().min(1),
14896
+ technologyId: import_zod25.z.string().min(1),
14897
+ productId: import_zod25.z.string().min(1),
14898
+ price: import_zod25.z.number().min(0),
14899
+ currency: import_zod25.z.nativeEnum(Currency),
14900
+ pricingMeasure: import_zod25.z.nativeEnum(PricingMeasure),
14901
+ productsMetadata: import_zod25.z.array(procedureProductDataSchema).min(1),
14902
+ duration: import_zod25.z.number().min(1).max(480),
14750
14903
  // Max 8 hours
14751
- practitionerId: import_zod24.z.string().min(1),
14752
- clinicBranchId: import_zod24.z.string().min(1),
14753
- photos: import_zod24.z.array(mediaResourceSchema).optional()
14904
+ practitionerId: import_zod25.z.string().min(1),
14905
+ clinicBranchId: import_zod25.z.string().min(1),
14906
+ photos: import_zod25.z.array(mediaResourceSchema).optional()
14754
14907
  });
14755
- var updateProcedureSchema = import_zod24.z.object({
14756
- name: import_zod24.z.string().min(3).max(100).optional(),
14757
- nameLower: import_zod24.z.string().min(1).max(200).optional(),
14758
- description: import_zod24.z.string().min(3).max(1e3).optional(),
14759
- price: import_zod24.z.number().min(0).optional(),
14760
- currency: import_zod24.z.nativeEnum(Currency).optional(),
14761
- pricingMeasure: import_zod24.z.nativeEnum(PricingMeasure).optional(),
14762
- duration: import_zod24.z.number().min(0).optional(),
14763
- isActive: import_zod24.z.boolean().optional(),
14764
- practitionerId: import_zod24.z.string().optional(),
14765
- categoryId: import_zod24.z.string().optional(),
14766
- subcategoryId: import_zod24.z.string().optional(),
14767
- technologyId: import_zod24.z.string().optional(),
14768
- productId: import_zod24.z.string().optional(),
14769
- clinicBranchId: import_zod24.z.string().optional(),
14770
- photos: import_zod24.z.array(mediaResourceSchema).optional()
14908
+ var updateProcedureSchema = import_zod25.z.object({
14909
+ name: import_zod25.z.string().min(3).max(100).optional(),
14910
+ nameLower: import_zod25.z.string().min(1).max(200).optional(),
14911
+ description: import_zod25.z.string().min(3).max(1e3).optional(),
14912
+ price: import_zod25.z.number().min(0).optional(),
14913
+ currency: import_zod25.z.nativeEnum(Currency).optional(),
14914
+ pricingMeasure: import_zod25.z.nativeEnum(PricingMeasure).optional(),
14915
+ productsMetadata: import_zod25.z.array(procedureProductDataSchema).min(1).optional(),
14916
+ duration: import_zod25.z.number().min(0).optional(),
14917
+ isActive: import_zod25.z.boolean().optional(),
14918
+ practitionerId: import_zod25.z.string().optional(),
14919
+ categoryId: import_zod25.z.string().optional(),
14920
+ subcategoryId: import_zod25.z.string().optional(),
14921
+ technologyId: import_zod25.z.string().optional(),
14922
+ productId: import_zod25.z.string().optional(),
14923
+ clinicBranchId: import_zod25.z.string().optional(),
14924
+ photos: import_zod25.z.array(mediaResourceSchema).optional()
14771
14925
  });
14772
- var procedureSchema = createProcedureSchema.extend({
14773
- id: import_zod24.z.string().min(1),
14774
- nameLower: import_zod24.z.string().min(1).max(200),
14775
- category: import_zod24.z.any(),
14926
+ var procedureSchema = import_zod25.z.object({
14927
+ id: import_zod25.z.string().min(1),
14928
+ name: import_zod25.z.string().min(1).max(200),
14929
+ nameLower: import_zod25.z.string().min(1).max(200),
14930
+ description: import_zod25.z.string().min(1).max(2e3),
14931
+ family: import_zod25.z.nativeEnum(ProcedureFamily),
14932
+ category: import_zod25.z.any(),
14776
14933
  // We'll validate the full category object separately
14777
- subcategory: import_zod24.z.any(),
14934
+ subcategory: import_zod25.z.any(),
14778
14935
  // We'll validate the full subcategory object separately
14779
- technology: import_zod24.z.any(),
14936
+ technology: import_zod25.z.any(),
14780
14937
  // We'll validate the full technology object separately
14781
- product: import_zod24.z.any(),
14938
+ product: import_zod25.z.any(),
14782
14939
  // We'll validate the full product object separately
14783
- blockingConditions: import_zod24.z.array(import_zod24.z.any()),
14940
+ productsMetadata: import_zod25.z.array(storedProcedureProductSchema).min(1),
14941
+ // Use stored format schema
14942
+ price: import_zod25.z.number().min(0),
14943
+ currency: import_zod25.z.nativeEnum(Currency),
14944
+ pricingMeasure: import_zod25.z.nativeEnum(PricingMeasure),
14945
+ duration: import_zod25.z.number().min(1).max(480),
14946
+ practitionerId: import_zod25.z.string().min(1),
14947
+ clinicBranchId: import_zod25.z.string().min(1),
14948
+ photos: import_zod25.z.array(import_zod25.z.string()).optional(),
14949
+ // Stored as URL strings
14950
+ blockingConditions: import_zod25.z.array(import_zod25.z.any()),
14784
14951
  // We'll validate blocking conditions separately
14785
- contraindications: import_zod24.z.array(import_zod24.z.any()),
14952
+ contraindications: import_zod25.z.array(import_zod25.z.any()),
14786
14953
  // We'll validate contraindications separately
14787
- treatmentBenefits: import_zod24.z.array(import_zod24.z.any()),
14954
+ contraindicationIds: import_zod25.z.array(import_zod25.z.string()),
14955
+ // Array of IDs for efficient querying
14956
+ treatmentBenefits: import_zod25.z.array(import_zod25.z.any()),
14788
14957
  // We'll validate treatment benefits separately
14789
- preRequirements: import_zod24.z.array(import_zod24.z.any()),
14958
+ treatmentBenefitIds: import_zod25.z.array(import_zod25.z.string()),
14959
+ // Array of IDs for efficient querying
14960
+ preRequirements: import_zod25.z.array(import_zod25.z.any()),
14790
14961
  // We'll validate requirements separately
14791
- postRequirements: import_zod24.z.array(import_zod24.z.any()),
14962
+ postRequirements: import_zod25.z.array(import_zod25.z.any()),
14792
14963
  // We'll validate requirements separately
14793
- certificationRequirement: import_zod24.z.any(),
14964
+ certificationRequirement: import_zod25.z.any(),
14794
14965
  // We'll validate certification requirement separately
14795
- documentationTemplates: import_zod24.z.array(import_zod24.z.any()),
14966
+ documentationTemplates: import_zod25.z.array(import_zod25.z.any()),
14796
14967
  // We'll validate documentation templates separately
14797
14968
  clinicInfo: clinicInfoSchema,
14798
14969
  // Clinic info validation
@@ -14800,9 +14971,9 @@ var procedureSchema = createProcedureSchema.extend({
14800
14971
  // Doctor info validation
14801
14972
  reviewInfo: procedureReviewInfoSchema,
14802
14973
  // Procedure review info validation
14803
- isActive: import_zod24.z.boolean(),
14804
- createdAt: import_zod24.z.date(),
14805
- updatedAt: import_zod24.z.date()
14974
+ isActive: import_zod25.z.boolean(),
14975
+ createdAt: import_zod25.z.date(),
14976
+ updatedAt: import_zod25.z.date()
14806
14977
  });
14807
14978
 
14808
14979
  // src/services/procedure/procedure.service.ts
@@ -14829,9 +15000,7 @@ var ProcedureService = class extends BaseService {
14829
15000
  return media;
14830
15001
  }
14831
15002
  if (media instanceof File || media instanceof Blob) {
14832
- console.log(
14833
- `[ProcedureService] Uploading ${collectionName} media for ${ownerId}`
14834
- );
15003
+ console.log(`[ProcedureService] Uploading ${collectionName} media for ${ownerId}`);
14835
15004
  const metadata = await this.mediaService.uploadMedia(
14836
15005
  media,
14837
15006
  ownerId,
@@ -14853,17 +15022,38 @@ var ProcedureService = class extends BaseService {
14853
15022
  if (!mediaArray || mediaArray.length === 0) return [];
14854
15023
  const result = [];
14855
15024
  for (const media of mediaArray) {
14856
- const processedUrl = await this.processMedia(
14857
- media,
14858
- ownerId,
14859
- collectionName
14860
- );
15025
+ const processedUrl = await this.processMedia(media, ownerId, collectionName);
14861
15026
  if (processedUrl) {
14862
15027
  result.push(processedUrl);
14863
15028
  }
14864
15029
  }
14865
15030
  return result;
14866
15031
  }
15032
+ /**
15033
+ * Transforms validated procedure product data (with productId) to ProcedureProduct objects (with full product)
15034
+ * @param productsMetadata Array of validated procedure product data
15035
+ * @param technologyId Technology ID to fetch products from
15036
+ * @returns Array of ProcedureProduct objects with full product information
15037
+ */
15038
+ async transformProductsMetadata(productsMetadata, technologyId) {
15039
+ const transformedProducts = [];
15040
+ for (const productData of productsMetadata) {
15041
+ const product = await this.productService.getById(technologyId, productData.productId);
15042
+ if (!product) {
15043
+ throw new Error(
15044
+ `Product with ID ${productData.productId} not found for technology ${technologyId}`
15045
+ );
15046
+ }
15047
+ transformedProducts.push({
15048
+ product,
15049
+ price: productData.price,
15050
+ currency: productData.currency,
15051
+ pricingMeasure: productData.pricingMeasure,
15052
+ isDefault: productData.isDefault
15053
+ });
15054
+ }
15055
+ return transformedProducts;
15056
+ }
14867
15057
  /**
14868
15058
  * Creates a new procedure
14869
15059
  * @param data - The data for creating a new procedure
@@ -14875,41 +15065,23 @@ var ProcedureService = class extends BaseService {
14875
15065
  const procedureId = this.generateId();
14876
15066
  const [category, subcategory, technology, product] = await Promise.all([
14877
15067
  this.categoryService.getById(validatedData.categoryId),
14878
- this.subcategoryService.getById(
14879
- validatedData.categoryId,
14880
- validatedData.subcategoryId
14881
- ),
15068
+ this.subcategoryService.getById(validatedData.categoryId, validatedData.subcategoryId),
14882
15069
  this.technologyService.getById(validatedData.technologyId),
14883
- this.productService.getById(
14884
- validatedData.technologyId,
14885
- validatedData.productId
14886
- )
15070
+ this.productService.getById(validatedData.technologyId, validatedData.productId)
14887
15071
  ]);
14888
15072
  if (!category || !subcategory || !technology || !product) {
14889
15073
  throw new Error("One or more required base entities not found");
14890
15074
  }
14891
- const clinicRef = (0, import_firestore46.doc)(
14892
- this.db,
14893
- CLINICS_COLLECTION,
14894
- validatedData.clinicBranchId
14895
- );
15075
+ const clinicRef = (0, import_firestore46.doc)(this.db, CLINICS_COLLECTION, validatedData.clinicBranchId);
14896
15076
  const clinicSnapshot = await (0, import_firestore46.getDoc)(clinicRef);
14897
15077
  if (!clinicSnapshot.exists()) {
14898
- throw new Error(
14899
- `Clinic with ID ${validatedData.clinicBranchId} not found`
14900
- );
15078
+ throw new Error(`Clinic with ID ${validatedData.clinicBranchId} not found`);
14901
15079
  }
14902
15080
  const clinic = clinicSnapshot.data();
14903
- const practitionerRef = (0, import_firestore46.doc)(
14904
- this.db,
14905
- PRACTITIONERS_COLLECTION,
14906
- validatedData.practitionerId
14907
- );
15081
+ const practitionerRef = (0, import_firestore46.doc)(this.db, PRACTITIONERS_COLLECTION, validatedData.practitionerId);
14908
15082
  const practitionerSnapshot = await (0, import_firestore46.getDoc)(practitionerRef);
14909
15083
  if (!practitionerSnapshot.exists()) {
14910
- throw new Error(
14911
- `Practitioner with ID ${validatedData.practitionerId} not found`
14912
- );
15084
+ throw new Error(`Practitioner with ID ${validatedData.practitionerId} not found`);
14913
15085
  }
14914
15086
  const practitioner = practitionerSnapshot.data();
14915
15087
  let processedPhotos = [];
@@ -14920,6 +15092,10 @@ var ProcedureService = class extends BaseService {
14920
15092
  "procedure-photos"
14921
15093
  );
14922
15094
  }
15095
+ const transformedProductsMetadata = await this.transformProductsMetadata(
15096
+ validatedData.productsMetadata,
15097
+ validatedData.technologyId
15098
+ );
14923
15099
  const clinicInfo = {
14924
15100
  id: clinicSnapshot.id,
14925
15101
  name: clinic.name,
@@ -14937,9 +15113,10 @@ var ProcedureService = class extends BaseService {
14937
15113
  rating: ((_a = practitioner.reviewInfo) == null ? void 0 : _a.averageRating) || 0,
14938
15114
  services: practitioner.procedures || []
14939
15115
  };
15116
+ const { productsMetadata: _, ...validatedDataWithoutProductsMetadata } = validatedData;
14940
15117
  const newProcedure = {
14941
15118
  id: procedureId,
14942
- ...validatedData,
15119
+ ...validatedDataWithoutProductsMetadata,
14943
15120
  // Ensure nameLower is always set even if omitted by client
14944
15121
  nameLower: validatedData.nameLower || validatedData.name.toLowerCase(),
14945
15122
  photos: processedPhotos,
@@ -14948,6 +15125,8 @@ var ProcedureService = class extends BaseService {
14948
15125
  subcategory,
14949
15126
  technology,
14950
15127
  product,
15128
+ productsMetadata: transformedProductsMetadata,
15129
+ // Use transformed data, not original
14951
15130
  blockingConditions: technology.blockingConditions,
14952
15131
  contraindications: technology.contraindications || [],
14953
15132
  contraindicationIds: ((_b = technology.contraindications) == null ? void 0 : _b.map((c) => c.id)) || [],
@@ -15001,24 +15180,16 @@ var ProcedureService = class extends BaseService {
15001
15180
  const validatedData = createProcedureSchema.parse(validationData);
15002
15181
  const [category, subcategory, technology, product, clinicSnapshot] = await Promise.all([
15003
15182
  this.categoryService.getById(validatedData.categoryId),
15004
- this.subcategoryService.getById(
15005
- validatedData.categoryId,
15006
- validatedData.subcategoryId
15007
- ),
15183
+ this.subcategoryService.getById(validatedData.categoryId, validatedData.subcategoryId),
15008
15184
  this.technologyService.getById(validatedData.technologyId),
15009
- this.productService.getById(
15010
- validatedData.technologyId,
15011
- validatedData.productId
15012
- ),
15185
+ this.productService.getById(validatedData.technologyId, validatedData.productId),
15013
15186
  (0, import_firestore46.getDoc)((0, import_firestore46.doc)(this.db, CLINICS_COLLECTION, validatedData.clinicBranchId))
15014
15187
  ]);
15015
15188
  if (!category || !subcategory || !technology || !product) {
15016
15189
  throw new Error("One or more required base entities not found");
15017
15190
  }
15018
15191
  if (!clinicSnapshot.exists()) {
15019
- throw new Error(
15020
- `Clinic with ID ${validatedData.clinicBranchId} not found`
15021
- );
15192
+ throw new Error(`Clinic with ID ${validatedData.clinicBranchId} not found`);
15022
15193
  }
15023
15194
  const clinic = clinicSnapshot.data();
15024
15195
  let processedPhotos = [];
@@ -15030,6 +15201,10 @@ var ProcedureService = class extends BaseService {
15030
15201
  "procedure-photos-batch"
15031
15202
  );
15032
15203
  }
15204
+ const transformedProductsMetadata = await this.transformProductsMetadata(
15205
+ validatedData.productsMetadata,
15206
+ validatedData.technologyId
15207
+ );
15033
15208
  const practitionersMap = /* @__PURE__ */ new Map();
15034
15209
  for (let i = 0; i < practitionerIds.length; i += 30) {
15035
15210
  const chunk = practitionerIds.slice(i, i + 30);
@@ -15044,12 +15219,8 @@ var ProcedureService = class extends BaseService {
15044
15219
  }
15045
15220
  if (practitionersMap.size !== practitionerIds.length) {
15046
15221
  const foundIds = Array.from(practitionersMap.keys());
15047
- const notFoundIds = practitionerIds.filter(
15048
- (id) => !foundIds.includes(id)
15049
- );
15050
- throw new Error(
15051
- `The following practitioners were not found: ${notFoundIds.join(", ")}`
15052
- );
15222
+ const notFoundIds = practitionerIds.filter((id) => !foundIds.includes(id));
15223
+ throw new Error(`The following practitioners were not found: ${notFoundIds.join(", ")}`);
15053
15224
  }
15054
15225
  const batch = (0, import_firestore46.writeBatch)(this.db);
15055
15226
  const createdProcedureIds = [];
@@ -15074,9 +15245,10 @@ var ProcedureService = class extends BaseService {
15074
15245
  const procedureId = this.generateId();
15075
15246
  createdProcedureIds.push(procedureId);
15076
15247
  const procedureRef = (0, import_firestore46.doc)(this.db, PROCEDURES_COLLECTION, procedureId);
15248
+ const { productsMetadata: _, ...validatedDataWithoutProductsMetadata } = validatedData;
15077
15249
  const newProcedure = {
15078
15250
  id: procedureId,
15079
- ...validatedData,
15251
+ ...validatedDataWithoutProductsMetadata,
15080
15252
  nameLower: validatedData.nameLower || validatedData.name.toLowerCase(),
15081
15253
  practitionerId,
15082
15254
  // Override practitionerId with the correct one
@@ -15085,6 +15257,8 @@ var ProcedureService = class extends BaseService {
15085
15257
  subcategory,
15086
15258
  technology,
15087
15259
  product,
15260
+ productsMetadata: transformedProductsMetadata,
15261
+ // Use transformed data, not original
15088
15262
  blockingConditions: technology.blockingConditions,
15089
15263
  contraindications: technology.contraindications || [],
15090
15264
  contraindicationIds: ((_b = technology.contraindications) == null ? void 0 : _b.map((c) => c.id)) || [],
@@ -15119,10 +15293,7 @@ var ProcedureService = class extends BaseService {
15119
15293
  const fetchedProcedures = [];
15120
15294
  for (let i = 0; i < createdProcedureIds.length; i += 30) {
15121
15295
  const chunk = createdProcedureIds.slice(i, i + 30);
15122
- const q = (0, import_firestore46.query)(
15123
- (0, import_firestore46.collection)(this.db, PROCEDURES_COLLECTION),
15124
- (0, import_firestore46.where)((0, import_firestore46.documentId)(), "in", chunk)
15125
- );
15296
+ const q = (0, import_firestore46.query)((0, import_firestore46.collection)(this.db, PROCEDURES_COLLECTION), (0, import_firestore46.where)((0, import_firestore46.documentId)(), "in", chunk));
15126
15297
  const snapshot = await (0, import_firestore46.getDocs)(q);
15127
15298
  snapshot.forEach((doc38) => {
15128
15299
  fetchedProcedures.push(doc38.data());
@@ -15192,7 +15363,7 @@ var ProcedureService = class extends BaseService {
15192
15363
  * @returns The updated procedure
15193
15364
  */
15194
15365
  async updateProcedure(id, data) {
15195
- var _a, _b, _c;
15366
+ var _a, _b, _c, _d;
15196
15367
  const validatedData = updateProcedureSchema.parse(data);
15197
15368
  const procedureRef = (0, import_firestore46.doc)(this.db, PROCEDURES_COLLECTION, id);
15198
15369
  const procedureSnapshot = await (0, import_firestore46.getDoc)(procedureRef);
@@ -15200,7 +15371,19 @@ var ProcedureService = class extends BaseService {
15200
15371
  throw new Error(`Procedure with ID ${id} not found`);
15201
15372
  }
15202
15373
  const existingProcedure = procedureSnapshot.data();
15203
- let updatedProcedureData = { ...validatedData };
15374
+ let updatedProcedureData = {};
15375
+ if (validatedData.name !== void 0) updatedProcedureData.name = validatedData.name;
15376
+ if (validatedData.description !== void 0)
15377
+ updatedProcedureData.description = validatedData.description;
15378
+ if (validatedData.price !== void 0) updatedProcedureData.price = validatedData.price;
15379
+ if (validatedData.currency !== void 0)
15380
+ updatedProcedureData.currency = validatedData.currency;
15381
+ if (validatedData.pricingMeasure !== void 0)
15382
+ updatedProcedureData.pricingMeasure = validatedData.pricingMeasure;
15383
+ if (validatedData.duration !== void 0)
15384
+ updatedProcedureData.duration = validatedData.duration;
15385
+ if (validatedData.isActive !== void 0)
15386
+ updatedProcedureData.isActive = validatedData.isActive;
15204
15387
  let practitionerChanged = false;
15205
15388
  let clinicChanged = false;
15206
15389
  const oldPractitionerId = existingProcedure.practitionerId;
@@ -15214,6 +15397,16 @@ var ProcedureService = class extends BaseService {
15214
15397
  "procedure-photos"
15215
15398
  );
15216
15399
  }
15400
+ if (validatedData.productsMetadata !== void 0) {
15401
+ const technologyId = (_a = validatedData.technologyId) != null ? _a : existingProcedure.technology.id;
15402
+ if (!technologyId) {
15403
+ throw new Error("Technology ID is required for updating products metadata");
15404
+ }
15405
+ updatedProcedureData.productsMetadata = await this.transformProductsMetadata(
15406
+ validatedData.productsMetadata,
15407
+ technologyId
15408
+ );
15409
+ }
15217
15410
  if (validatedData.practitionerId && validatedData.practitionerId !== oldPractitionerId) {
15218
15411
  practitionerChanged = true;
15219
15412
  const newPractitionerRef = (0, import_firestore46.doc)(
@@ -15223,9 +15416,7 @@ var ProcedureService = class extends BaseService {
15223
15416
  );
15224
15417
  const newPractitionerSnap = await (0, import_firestore46.getDoc)(newPractitionerRef);
15225
15418
  if (!newPractitionerSnap.exists())
15226
- throw new Error(
15227
- `New Practitioner ${validatedData.practitionerId} not found`
15228
- );
15419
+ throw new Error(`New Practitioner ${validatedData.practitionerId} not found`);
15229
15420
  newPractitioner = newPractitionerSnap.data();
15230
15421
  updatedProcedureData.doctorInfo = {
15231
15422
  id: newPractitioner.id,
@@ -15233,17 +15424,13 @@ var ProcedureService = class extends BaseService {
15233
15424
  description: newPractitioner.basicInfo.bio || "",
15234
15425
  photo: typeof newPractitioner.basicInfo.profileImageUrl === "string" ? newPractitioner.basicInfo.profileImageUrl : "",
15235
15426
  // Default to empty string if not a processed URL
15236
- rating: ((_a = newPractitioner.reviewInfo) == null ? void 0 : _a.averageRating) || 0,
15427
+ rating: ((_b = newPractitioner.reviewInfo) == null ? void 0 : _b.averageRating) || 0,
15237
15428
  services: newPractitioner.procedures || []
15238
15429
  };
15239
15430
  }
15240
15431
  if (validatedData.clinicBranchId && validatedData.clinicBranchId !== oldClinicId) {
15241
15432
  clinicChanged = true;
15242
- const newClinicRef = (0, import_firestore46.doc)(
15243
- this.db,
15244
- CLINICS_COLLECTION,
15245
- validatedData.clinicBranchId
15246
- );
15433
+ const newClinicRef = (0, import_firestore46.doc)(this.db, CLINICS_COLLECTION, validatedData.clinicBranchId);
15247
15434
  const newClinicSnap = await (0, import_firestore46.getDoc)(newClinicRef);
15248
15435
  if (!newClinicSnap.exists())
15249
15436
  throw new Error(`New Clinic ${validatedData.clinicBranchId} not found`);
@@ -15262,11 +15449,8 @@ var ProcedureService = class extends BaseService {
15262
15449
  updatedProcedureData.nameLower = validatedData.name.toLowerCase();
15263
15450
  }
15264
15451
  if (validatedData.categoryId) {
15265
- const category = await this.categoryService.getById(
15266
- validatedData.categoryId
15267
- );
15268
- if (!category)
15269
- throw new Error(`Category ${validatedData.categoryId} not found`);
15452
+ const category = await this.categoryService.getById(validatedData.categoryId);
15453
+ if (!category) throw new Error(`Category ${validatedData.categoryId} not found`);
15270
15454
  updatedProcedureData.category = category;
15271
15455
  finalCategoryId = category.id;
15272
15456
  }
@@ -15281,34 +15465,26 @@ var ProcedureService = class extends BaseService {
15281
15465
  );
15282
15466
  updatedProcedureData.subcategory = subcategory;
15283
15467
  } else if (validatedData.subcategoryId) {
15284
- console.warn(
15285
- "Attempted to update subcategory without a valid categoryId"
15286
- );
15468
+ console.warn("Attempted to update subcategory without a valid categoryId");
15287
15469
  }
15288
15470
  let finalTechnologyId = existingProcedure.technology.id;
15289
15471
  if (validatedData.technologyId) {
15290
- const technology = await this.technologyService.getById(
15291
- validatedData.technologyId
15292
- );
15293
- if (!technology)
15294
- throw new Error(`Technology ${validatedData.technologyId} not found`);
15472
+ const technology = await this.technologyService.getById(validatedData.technologyId);
15473
+ if (!technology) throw new Error(`Technology ${validatedData.technologyId} not found`);
15295
15474
  updatedProcedureData.technology = technology;
15296
15475
  finalTechnologyId = technology.id;
15297
15476
  updatedProcedureData.blockingConditions = technology.blockingConditions;
15298
15477
  updatedProcedureData.contraindications = technology.contraindications || [];
15299
- updatedProcedureData.contraindicationIds = ((_b = technology.contraindications) == null ? void 0 : _b.map((c) => c.id)) || [];
15478
+ updatedProcedureData.contraindicationIds = ((_c = technology.contraindications) == null ? void 0 : _c.map((c) => c.id)) || [];
15300
15479
  updatedProcedureData.treatmentBenefits = technology.benefits;
15301
- updatedProcedureData.treatmentBenefitIds = ((_c = technology.benefits) == null ? void 0 : _c.map((b) => b.id)) || [];
15480
+ updatedProcedureData.treatmentBenefitIds = ((_d = technology.benefits) == null ? void 0 : _d.map((b) => b.id)) || [];
15302
15481
  updatedProcedureData.preRequirements = technology.requirements.pre;
15303
15482
  updatedProcedureData.postRequirements = technology.requirements.post;
15304
15483
  updatedProcedureData.certificationRequirement = technology.certificationRequirement;
15305
15484
  updatedProcedureData.documentationTemplates = technology.documentationTemplates || [];
15306
15485
  }
15307
15486
  if (validatedData.productId && finalTechnologyId) {
15308
- const product = await this.productService.getById(
15309
- finalTechnologyId,
15310
- validatedData.productId
15311
- );
15487
+ const product = await this.productService.getById(finalTechnologyId, validatedData.productId);
15312
15488
  if (!product)
15313
15489
  throw new Error(
15314
15490
  `Product ${validatedData.productId} not found for technology ${finalTechnologyId}`
@@ -15390,11 +15566,7 @@ var ProcedureService = class extends BaseService {
15390
15566
  limit21(pagination)
15391
15567
  );
15392
15568
  } else {
15393
- proceduresQuery = (0, import_firestore46.query)(
15394
- proceduresCollection,
15395
- (0, import_firestore46.orderBy)("name"),
15396
- limit21(pagination)
15397
- );
15569
+ proceduresQuery = (0, import_firestore46.query)(proceduresCollection, (0, import_firestore46.orderBy)("name"), limit21(pagination));
15398
15570
  }
15399
15571
  } else {
15400
15572
  proceduresQuery = (0, import_firestore46.query)(proceduresCollection, (0, import_firestore46.orderBy)("name"));
@@ -15443,9 +15615,7 @@ var ProcedureService = class extends BaseService {
15443
15615
  */
15444
15616
  async getProceduresByFilters(filters) {
15445
15617
  try {
15446
- console.log(
15447
- "[PROCEDURE_SERVICE] Starting procedure filtering with multiple strategies"
15448
- );
15618
+ console.log("[PROCEDURE_SERVICE] Starting procedure filtering with multiple strategies");
15449
15619
  if (filters.location && filters.radiusInKm) {
15450
15620
  console.log("[PROCEDURE_SERVICE] Executing geo query:", {
15451
15621
  location: filters.location,
@@ -15453,10 +15623,7 @@ var ProcedureService = class extends BaseService {
15453
15623
  serviceName: "ProcedureService"
15454
15624
  });
15455
15625
  if (!filters.location.latitude || !filters.location.longitude) {
15456
- console.warn(
15457
- "[PROCEDURE_SERVICE] Invalid location data:",
15458
- filters.location
15459
- );
15626
+ console.warn("[PROCEDURE_SERVICE] Invalid location data:", filters.location);
15460
15627
  filters.location = void 0;
15461
15628
  filters.radiusInKm = void 0;
15462
15629
  }
@@ -15476,19 +15643,13 @@ var ProcedureService = class extends BaseService {
15476
15643
  constraints.push((0, import_firestore46.where)("family", "==", filters.procedureFamily));
15477
15644
  }
15478
15645
  if (filters.procedureCategory) {
15479
- constraints.push(
15480
- (0, import_firestore46.where)("category.id", "==", filters.procedureCategory)
15481
- );
15646
+ constraints.push((0, import_firestore46.where)("category.id", "==", filters.procedureCategory));
15482
15647
  }
15483
15648
  if (filters.procedureSubcategory) {
15484
- constraints.push(
15485
- (0, import_firestore46.where)("subcategory.id", "==", filters.procedureSubcategory)
15486
- );
15649
+ constraints.push((0, import_firestore46.where)("subcategory.id", "==", filters.procedureSubcategory));
15487
15650
  }
15488
15651
  if (filters.procedureTechnology) {
15489
- constraints.push(
15490
- (0, import_firestore46.where)("technology.id", "==", filters.procedureTechnology)
15491
- );
15652
+ constraints.push((0, import_firestore46.where)("technology.id", "==", filters.procedureTechnology));
15492
15653
  }
15493
15654
  if (filters.minPrice !== void 0) {
15494
15655
  constraints.push((0, import_firestore46.where)("price", ">=", filters.minPrice));
@@ -15497,32 +15658,20 @@ var ProcedureService = class extends BaseService {
15497
15658
  constraints.push((0, import_firestore46.where)("price", "<=", filters.maxPrice));
15498
15659
  }
15499
15660
  if (filters.minRating !== void 0) {
15500
- constraints.push(
15501
- (0, import_firestore46.where)("reviewInfo.averageRating", ">=", filters.minRating)
15502
- );
15661
+ constraints.push((0, import_firestore46.where)("reviewInfo.averageRating", ">=", filters.minRating));
15503
15662
  }
15504
15663
  if (filters.maxRating !== void 0) {
15505
- constraints.push(
15506
- (0, import_firestore46.where)("reviewInfo.averageRating", "<=", filters.maxRating)
15507
- );
15664
+ constraints.push((0, import_firestore46.where)("reviewInfo.averageRating", "<=", filters.maxRating));
15508
15665
  }
15509
15666
  if (filters.treatmentBenefits && filters.treatmentBenefits.length > 0) {
15510
15667
  const benefitIdsToMatch = filters.treatmentBenefits;
15511
- constraints.push(
15512
- (0, import_firestore46.where)(
15513
- "treatmentBenefitIds",
15514
- "array-contains-any",
15515
- benefitIdsToMatch
15516
- )
15517
- );
15668
+ constraints.push((0, import_firestore46.where)("treatmentBenefitIds", "array-contains-any", benefitIdsToMatch));
15518
15669
  }
15519
15670
  return constraints;
15520
15671
  };
15521
15672
  if (filters.nameSearch && filters.nameSearch.trim()) {
15522
15673
  try {
15523
- console.log(
15524
- "[PROCEDURE_SERVICE] Strategy 1: Trying nameLower search"
15525
- );
15674
+ console.log("[PROCEDURE_SERVICE] Strategy 1: Trying nameLower search");
15526
15675
  const searchTerm = filters.nameSearch.trim().toLowerCase();
15527
15676
  const constraints = getBaseConstraints();
15528
15677
  constraints.push((0, import_firestore46.where)("nameLower", ">=", searchTerm));
@@ -15538,18 +15687,13 @@ var ProcedureService = class extends BaseService {
15538
15687
  }
15539
15688
  }
15540
15689
  constraints.push((0, import_firestore46.limit)(filters.pagination || 10));
15541
- const q = (0, import_firestore46.query)(
15542
- (0, import_firestore46.collection)(this.db, PROCEDURES_COLLECTION),
15543
- ...constraints
15544
- );
15690
+ const q = (0, import_firestore46.query)((0, import_firestore46.collection)(this.db, PROCEDURES_COLLECTION), ...constraints);
15545
15691
  const querySnapshot = await (0, import_firestore46.getDocs)(q);
15546
15692
  const procedures = querySnapshot.docs.map(
15547
15693
  (doc38) => ({ ...doc38.data(), id: doc38.id })
15548
15694
  );
15549
15695
  const lastDoc = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
15550
- console.log(
15551
- `[PROCEDURE_SERVICE] Strategy 1 success: ${procedures.length} procedures`
15552
- );
15696
+ console.log(`[PROCEDURE_SERVICE] Strategy 1 success: ${procedures.length} procedures`);
15553
15697
  if (procedures.length < (filters.pagination || 10)) {
15554
15698
  return { procedures, lastDoc: null };
15555
15699
  }
@@ -15560,9 +15704,7 @@ var ProcedureService = class extends BaseService {
15560
15704
  }
15561
15705
  if (filters.nameSearch && filters.nameSearch.trim()) {
15562
15706
  try {
15563
- console.log(
15564
- "[PROCEDURE_SERVICE] Strategy 2: Trying name field search"
15565
- );
15707
+ console.log("[PROCEDURE_SERVICE] Strategy 2: Trying name field search");
15566
15708
  const searchTerm = filters.nameSearch.trim().toLowerCase();
15567
15709
  const constraints = getBaseConstraints();
15568
15710
  constraints.push((0, import_firestore46.where)("name", ">=", searchTerm));
@@ -15578,18 +15720,13 @@ var ProcedureService = class extends BaseService {
15578
15720
  }
15579
15721
  }
15580
15722
  constraints.push((0, import_firestore46.limit)(filters.pagination || 10));
15581
- const q = (0, import_firestore46.query)(
15582
- (0, import_firestore46.collection)(this.db, PROCEDURES_COLLECTION),
15583
- ...constraints
15584
- );
15723
+ const q = (0, import_firestore46.query)((0, import_firestore46.collection)(this.db, PROCEDURES_COLLECTION), ...constraints);
15585
15724
  const querySnapshot = await (0, import_firestore46.getDocs)(q);
15586
15725
  const procedures = querySnapshot.docs.map(
15587
15726
  (doc38) => ({ ...doc38.data(), id: doc38.id })
15588
15727
  );
15589
15728
  const lastDoc = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
15590
- console.log(
15591
- `[PROCEDURE_SERVICE] Strategy 2 success: ${procedures.length} procedures`
15592
- );
15729
+ console.log(`[PROCEDURE_SERVICE] Strategy 2 success: ${procedures.length} procedures`);
15593
15730
  if (procedures.length < (filters.pagination || 10)) {
15594
15731
  return { procedures, lastDoc: null };
15595
15732
  }
@@ -15614,19 +15751,14 @@ var ProcedureService = class extends BaseService {
15614
15751
  }
15615
15752
  }
15616
15753
  constraints.push((0, import_firestore46.limit)(filters.pagination || 10));
15617
- const q = (0, import_firestore46.query)(
15618
- (0, import_firestore46.collection)(this.db, PROCEDURES_COLLECTION),
15619
- ...constraints
15620
- );
15754
+ const q = (0, import_firestore46.query)((0, import_firestore46.collection)(this.db, PROCEDURES_COLLECTION), ...constraints);
15621
15755
  const querySnapshot = await (0, import_firestore46.getDocs)(q);
15622
15756
  let procedures = querySnapshot.docs.map(
15623
15757
  (doc38) => ({ ...doc38.data(), id: doc38.id })
15624
15758
  );
15625
15759
  procedures = this.applyInMemoryFilters(procedures, filters);
15626
15760
  const lastDoc = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
15627
- console.log(
15628
- `[PROCEDURE_SERVICE] Strategy 3 success: ${procedures.length} procedures`
15629
- );
15761
+ console.log(`[PROCEDURE_SERVICE] Strategy 3 success: ${procedures.length} procedures`);
15630
15762
  if (procedures.length < (filters.pagination || 10)) {
15631
15763
  return { procedures, lastDoc: null };
15632
15764
  }
@@ -15641,19 +15773,14 @@ var ProcedureService = class extends BaseService {
15641
15773
  (0, import_firestore46.orderBy)("createdAt", "desc"),
15642
15774
  (0, import_firestore46.limit)(filters.pagination || 10)
15643
15775
  ];
15644
- const q = (0, import_firestore46.query)(
15645
- (0, import_firestore46.collection)(this.db, PROCEDURES_COLLECTION),
15646
- ...constraints
15647
- );
15776
+ const q = (0, import_firestore46.query)((0, import_firestore46.collection)(this.db, PROCEDURES_COLLECTION), ...constraints);
15648
15777
  const querySnapshot = await (0, import_firestore46.getDocs)(q);
15649
15778
  let procedures = querySnapshot.docs.map(
15650
15779
  (doc38) => ({ ...doc38.data(), id: doc38.id })
15651
15780
  );
15652
15781
  procedures = this.applyInMemoryFilters(procedures, filters);
15653
15782
  const lastDoc = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
15654
- console.log(
15655
- `[PROCEDURE_SERVICE] Strategy 4 success: ${procedures.length} procedures`
15656
- );
15783
+ console.log(`[PROCEDURE_SERVICE] Strategy 4 success: ${procedures.length} procedures`);
15657
15784
  if (procedures.length < (filters.pagination || 10)) {
15658
15785
  return { procedures, lastDoc: null };
15659
15786
  }
@@ -15661,9 +15788,7 @@ var ProcedureService = class extends BaseService {
15661
15788
  } catch (error) {
15662
15789
  console.log("[PROCEDURE_SERVICE] Strategy 4 failed:", error);
15663
15790
  }
15664
- console.log(
15665
- "[PROCEDURE_SERVICE] All strategies failed, returning empty result"
15666
- );
15791
+ console.log("[PROCEDURE_SERVICE] All strategies failed, returning empty result");
15667
15792
  return { procedures: [], lastDoc: null };
15668
15793
  } catch (error) {
15669
15794
  console.error("[PROCEDURE_SERVICE] Error filtering procedures:", error);
@@ -15683,17 +15808,13 @@ var ProcedureService = class extends BaseService {
15683
15808
  const nameLower = procedure.nameLower || "";
15684
15809
  return name.includes(searchTerm) || nameLower.includes(searchTerm);
15685
15810
  });
15686
- console.log(
15687
- `[PROCEDURE_SERVICE] Applied name filter, results: ${filteredProcedures.length}`
15688
- );
15811
+ console.log(`[PROCEDURE_SERVICE] Applied name filter, results: ${filteredProcedures.length}`);
15689
15812
  }
15690
15813
  if (filters.minPrice !== void 0 || filters.maxPrice !== void 0) {
15691
15814
  filteredProcedures = filteredProcedures.filter((procedure) => {
15692
15815
  const price = procedure.price || 0;
15693
- if (filters.minPrice !== void 0 && price < filters.minPrice)
15694
- return false;
15695
- if (filters.maxPrice !== void 0 && price > filters.maxPrice)
15696
- return false;
15816
+ if (filters.minPrice !== void 0 && price < filters.minPrice) return false;
15817
+ if (filters.maxPrice !== void 0 && price > filters.maxPrice) return false;
15697
15818
  return true;
15698
15819
  });
15699
15820
  console.log(
@@ -15704,10 +15825,8 @@ var ProcedureService = class extends BaseService {
15704
15825
  filteredProcedures = filteredProcedures.filter((procedure) => {
15705
15826
  var _a;
15706
15827
  const rating = ((_a = procedure.reviewInfo) == null ? void 0 : _a.averageRating) || 0;
15707
- if (filters.minRating !== void 0 && rating < filters.minRating)
15708
- return false;
15709
- if (filters.maxRating !== void 0 && rating > filters.maxRating)
15710
- return false;
15828
+ if (filters.minRating !== void 0 && rating < filters.minRating) return false;
15829
+ if (filters.maxRating !== void 0 && rating > filters.maxRating) return false;
15711
15830
  return true;
15712
15831
  });
15713
15832
  console.log(
@@ -15783,12 +15902,8 @@ var ProcedureService = class extends BaseService {
15783
15902
  procedure.distance = distance;
15784
15903
  return distance <= radiusInKm;
15785
15904
  });
15786
- console.log(
15787
- `[PROCEDURE_SERVICE] Applied geo filter, results: ${filteredProcedures.length}`
15788
- );
15789
- filteredProcedures.sort(
15790
- (a, b) => (a.distance || 0) - (b.distance || 0)
15791
- );
15905
+ console.log(`[PROCEDURE_SERVICE] Applied geo filter, results: ${filteredProcedures.length}`);
15906
+ filteredProcedures.sort((a, b) => (a.distance || 0) - (b.distance || 0));
15792
15907
  }
15793
15908
  return filteredProcedures;
15794
15909
  }
@@ -15800,30 +15915,19 @@ var ProcedureService = class extends BaseService {
15800
15915
  if (!location || !radiusInKm) {
15801
15916
  return Promise.resolve({ procedures: [], lastDoc: null });
15802
15917
  }
15803
- const bounds = (0, import_geofire_common8.geohashQueryBounds)(
15804
- [location.latitude, location.longitude],
15805
- radiusInKm * 1e3
15806
- );
15918
+ const bounds = (0, import_geofire_common8.geohashQueryBounds)([location.latitude, location.longitude], radiusInKm * 1e3);
15807
15919
  const fetches = bounds.map((b) => {
15808
15920
  const constraints = [
15809
15921
  (0, import_firestore46.where)("clinicInfo.location.geohash", ">=", b[0]),
15810
15922
  (0, import_firestore46.where)("clinicInfo.location.geohash", "<=", b[1]),
15811
- (0, import_firestore46.where)(
15812
- "isActive",
15813
- "==",
15814
- filters.isActive !== void 0 ? filters.isActive : true
15815
- )
15923
+ (0, import_firestore46.where)("isActive", "==", filters.isActive !== void 0 ? filters.isActive : true)
15816
15924
  ];
15817
- return (0, import_firestore46.getDocs)(
15818
- (0, import_firestore46.query)((0, import_firestore46.collection)(this.db, PROCEDURES_COLLECTION), ...constraints)
15819
- );
15925
+ return (0, import_firestore46.getDocs)((0, import_firestore46.query)((0, import_firestore46.collection)(this.db, PROCEDURES_COLLECTION), ...constraints));
15820
15926
  });
15821
15927
  return Promise.all(fetches).then((snaps) => {
15822
15928
  const collected = [];
15823
15929
  snaps.forEach((snap) => {
15824
- snap.docs.forEach(
15825
- (d) => collected.push({ ...d.data(), id: d.id })
15826
- );
15930
+ snap.docs.forEach((d) => collected.push({ ...d.data(), id: d.id }));
15827
15931
  });
15828
15932
  const uniqueMap = /* @__PURE__ */ new Map();
15829
15933
  for (const p of collected) {
@@ -15834,9 +15938,7 @@ var ProcedureService = class extends BaseService {
15834
15938
  const pageSize = filters.pagination || 10;
15835
15939
  let startIndex = 0;
15836
15940
  if (filters.lastDoc && typeof filters.lastDoc === "object" && filters.lastDoc.id) {
15837
- const idx = procedures.findIndex(
15838
- (p) => p.id === filters.lastDoc.id
15839
- );
15941
+ const idx = procedures.findIndex((p) => p.id === filters.lastDoc.id);
15840
15942
  if (idx >= 0) startIndex = idx + 1;
15841
15943
  }
15842
15944
  const page = procedures.slice(startIndex, startIndex + pageSize);
@@ -15877,11 +15979,7 @@ var ProcedureService = class extends BaseService {
15877
15979
  throw new Error(`Clinic with ID ${data.clinicBranchId} not found`);
15878
15980
  }
15879
15981
  const clinic = clinicSnapshot.data();
15880
- const practitionerRef = (0, import_firestore46.doc)(
15881
- this.db,
15882
- PRACTITIONERS_COLLECTION,
15883
- data.practitionerId
15884
- );
15982
+ const practitionerRef = (0, import_firestore46.doc)(this.db, PRACTITIONERS_COLLECTION, data.practitionerId);
15885
15983
  const practitionerSnapshot = await (0, import_firestore46.getDoc)(practitionerRef);
15886
15984
  if (!practitionerSnapshot.exists()) {
15887
15985
  throw new Error(`Practitioner with ID ${data.practitionerId} not found`);
@@ -15889,12 +15987,12 @@ var ProcedureService = class extends BaseService {
15889
15987
  const practitioner = practitionerSnapshot.data();
15890
15988
  let processedPhotos = [];
15891
15989
  if (data.photos && data.photos.length > 0) {
15892
- processedPhotos = await this.processMediaArray(
15893
- data.photos,
15894
- procedureId,
15895
- "procedure-photos"
15896
- );
15990
+ processedPhotos = await this.processMediaArray(data.photos, procedureId, "procedure-photos");
15897
15991
  }
15992
+ const transformedProductsMetadata = await this.transformProductsMetadata(
15993
+ data.productsMetadata,
15994
+ data.technologyId
15995
+ );
15898
15996
  const clinicInfo = {
15899
15997
  id: clinicSnapshot.id,
15900
15998
  name: clinic.name,
@@ -15925,9 +16023,10 @@ var ProcedureService = class extends BaseService {
15925
16023
  createdAt: /* @__PURE__ */ new Date(),
15926
16024
  updatedAt: /* @__PURE__ */ new Date()
15927
16025
  };
16026
+ const { productsMetadata: _, ...dataWithoutProductsMetadata } = data;
15928
16027
  const newProcedure = {
15929
16028
  id: procedureId,
15930
- ...data,
16029
+ ...dataWithoutProductsMetadata,
15931
16030
  nameLower: data.nameLower || data.name.toLowerCase(),
15932
16031
  photos: processedPhotos,
15933
16032
  category,
@@ -15935,6 +16034,8 @@ var ProcedureService = class extends BaseService {
15935
16034
  technology,
15936
16035
  product: consultationProduct,
15937
16036
  // Use placeholder product
16037
+ productsMetadata: transformedProductsMetadata,
16038
+ // Use transformed data, not original
15938
16039
  blockingConditions: technology.blockingConditions,
15939
16040
  contraindications: technology.contraindications || [],
15940
16041
  contraindicationIds: ((_b = technology.contraindications) == null ? void 0 : _b.map((c) => c.id)) || [],
@@ -15994,7 +16095,7 @@ var ProcedureService = class extends BaseService {
15994
16095
 
15995
16096
  // src/services/reviews/reviews.service.ts
15996
16097
  var import_firestore47 = require("firebase/firestore");
15997
- var import_zod25 = require("zod");
16098
+ var import_zod26 = require("zod");
15998
16099
  var ReviewService = class extends BaseService {
15999
16100
  constructor(db, auth, app) {
16000
16101
  super(db, auth, app);
@@ -16081,7 +16182,7 @@ var ReviewService = class extends BaseService {
16081
16182
  });
16082
16183
  return review;
16083
16184
  } catch (error) {
16084
- if (error instanceof import_zod25.z.ZodError) {
16185
+ if (error instanceof import_zod26.z.ZodError) {
16085
16186
  throw new Error(`Invalid review data: ${error.message}`);
16086
16187
  }
16087
16188
  throw error;