@blackcode_sa/metaestetics-api 1.12.0 → 1.12.1

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
@@ -14864,6 +15035,34 @@ var ProcedureService = class extends BaseService {
14864
15035
  }
14865
15036
  return result;
14866
15037
  }
15038
+ /**
15039
+ * Transforms validated procedure product data (with productId) to ProcedureProduct objects (with full product)
15040
+ * @param productsMetadata Array of validated procedure product data
15041
+ * @param technologyId Technology ID to fetch products from
15042
+ * @returns Array of ProcedureProduct objects with full product information
15043
+ */
15044
+ async transformProductsMetadata(productsMetadata, technologyId) {
15045
+ const transformedProducts = [];
15046
+ for (const productData of productsMetadata) {
15047
+ const product = await this.productService.getById(
15048
+ technologyId,
15049
+ productData.productId
15050
+ );
15051
+ if (!product) {
15052
+ throw new Error(
15053
+ `Product with ID ${productData.productId} not found for technology ${technologyId}`
15054
+ );
15055
+ }
15056
+ transformedProducts.push({
15057
+ product,
15058
+ price: productData.price,
15059
+ currency: productData.currency,
15060
+ pricingMeasure: productData.pricingMeasure,
15061
+ isDefault: productData.isDefault
15062
+ });
15063
+ }
15064
+ return transformedProducts;
15065
+ }
14867
15066
  /**
14868
15067
  * Creates a new procedure
14869
15068
  * @param data - The data for creating a new procedure
@@ -14920,6 +15119,10 @@ var ProcedureService = class extends BaseService {
14920
15119
  "procedure-photos"
14921
15120
  );
14922
15121
  }
15122
+ const transformedProductsMetadata = await this.transformProductsMetadata(
15123
+ validatedData.productsMetadata,
15124
+ validatedData.technologyId
15125
+ );
14923
15126
  const clinicInfo = {
14924
15127
  id: clinicSnapshot.id,
14925
15128
  name: clinic.name,
@@ -14948,6 +15151,7 @@ var ProcedureService = class extends BaseService {
14948
15151
  subcategory,
14949
15152
  technology,
14950
15153
  product,
15154
+ productsMetadata: transformedProductsMetadata,
14951
15155
  blockingConditions: technology.blockingConditions,
14952
15156
  contraindications: technology.contraindications || [],
14953
15157
  contraindicationIds: ((_b = technology.contraindications) == null ? void 0 : _b.map((c) => c.id)) || [],
@@ -15030,6 +15234,10 @@ var ProcedureService = class extends BaseService {
15030
15234
  "procedure-photos-batch"
15031
15235
  );
15032
15236
  }
15237
+ const transformedProductsMetadata = await this.transformProductsMetadata(
15238
+ validatedData.productsMetadata,
15239
+ validatedData.technologyId
15240
+ );
15033
15241
  const practitionersMap = /* @__PURE__ */ new Map();
15034
15242
  for (let i = 0; i < practitionerIds.length; i += 30) {
15035
15243
  const chunk = practitionerIds.slice(i, i + 30);
@@ -15085,6 +15293,7 @@ var ProcedureService = class extends BaseService {
15085
15293
  subcategory,
15086
15294
  technology,
15087
15295
  product,
15296
+ productsMetadata: transformedProductsMetadata,
15088
15297
  blockingConditions: technology.blockingConditions,
15089
15298
  contraindications: technology.contraindications || [],
15090
15299
  contraindicationIds: ((_b = technology.contraindications) == null ? void 0 : _b.map((c) => c.id)) || [],
@@ -15192,7 +15401,7 @@ var ProcedureService = class extends BaseService {
15192
15401
  * @returns The updated procedure
15193
15402
  */
15194
15403
  async updateProcedure(id, data) {
15195
- var _a, _b, _c;
15404
+ var _a, _b, _c, _d;
15196
15405
  const validatedData = updateProcedureSchema.parse(data);
15197
15406
  const procedureRef = (0, import_firestore46.doc)(this.db, PROCEDURES_COLLECTION, id);
15198
15407
  const procedureSnapshot = await (0, import_firestore46.getDoc)(procedureRef);
@@ -15200,7 +15409,21 @@ var ProcedureService = class extends BaseService {
15200
15409
  throw new Error(`Procedure with ID ${id} not found`);
15201
15410
  }
15202
15411
  const existingProcedure = procedureSnapshot.data();
15203
- let updatedProcedureData = { ...validatedData };
15412
+ let updatedProcedureData = {};
15413
+ if (validatedData.name !== void 0)
15414
+ updatedProcedureData.name = validatedData.name;
15415
+ if (validatedData.description !== void 0)
15416
+ updatedProcedureData.description = validatedData.description;
15417
+ if (validatedData.price !== void 0)
15418
+ updatedProcedureData.price = validatedData.price;
15419
+ if (validatedData.currency !== void 0)
15420
+ updatedProcedureData.currency = validatedData.currency;
15421
+ if (validatedData.pricingMeasure !== void 0)
15422
+ updatedProcedureData.pricingMeasure = validatedData.pricingMeasure;
15423
+ if (validatedData.duration !== void 0)
15424
+ updatedProcedureData.duration = validatedData.duration;
15425
+ if (validatedData.isActive !== void 0)
15426
+ updatedProcedureData.isActive = validatedData.isActive;
15204
15427
  let practitionerChanged = false;
15205
15428
  let clinicChanged = false;
15206
15429
  const oldPractitionerId = existingProcedure.practitionerId;
@@ -15214,6 +15437,18 @@ var ProcedureService = class extends BaseService {
15214
15437
  "procedure-photos"
15215
15438
  );
15216
15439
  }
15440
+ if (validatedData.productsMetadata !== void 0) {
15441
+ const technologyId = (_a = validatedData.technologyId) != null ? _a : existingProcedure.technology.id;
15442
+ if (!technologyId) {
15443
+ throw new Error(
15444
+ "Technology ID is required for updating products metadata"
15445
+ );
15446
+ }
15447
+ updatedProcedureData.productsMetadata = await this.transformProductsMetadata(
15448
+ validatedData.productsMetadata,
15449
+ technologyId
15450
+ );
15451
+ }
15217
15452
  if (validatedData.practitionerId && validatedData.practitionerId !== oldPractitionerId) {
15218
15453
  practitionerChanged = true;
15219
15454
  const newPractitionerRef = (0, import_firestore46.doc)(
@@ -15233,7 +15468,7 @@ var ProcedureService = class extends BaseService {
15233
15468
  description: newPractitioner.basicInfo.bio || "",
15234
15469
  photo: typeof newPractitioner.basicInfo.profileImageUrl === "string" ? newPractitioner.basicInfo.profileImageUrl : "",
15235
15470
  // Default to empty string if not a processed URL
15236
- rating: ((_a = newPractitioner.reviewInfo) == null ? void 0 : _a.averageRating) || 0,
15471
+ rating: ((_b = newPractitioner.reviewInfo) == null ? void 0 : _b.averageRating) || 0,
15237
15472
  services: newPractitioner.procedures || []
15238
15473
  };
15239
15474
  }
@@ -15296,9 +15531,9 @@ var ProcedureService = class extends BaseService {
15296
15531
  finalTechnologyId = technology.id;
15297
15532
  updatedProcedureData.blockingConditions = technology.blockingConditions;
15298
15533
  updatedProcedureData.contraindications = technology.contraindications || [];
15299
- updatedProcedureData.contraindicationIds = ((_b = technology.contraindications) == null ? void 0 : _b.map((c) => c.id)) || [];
15534
+ updatedProcedureData.contraindicationIds = ((_c = technology.contraindications) == null ? void 0 : _c.map((c) => c.id)) || [];
15300
15535
  updatedProcedureData.treatmentBenefits = technology.benefits;
15301
- updatedProcedureData.treatmentBenefitIds = ((_c = technology.benefits) == null ? void 0 : _c.map((b) => b.id)) || [];
15536
+ updatedProcedureData.treatmentBenefitIds = ((_d = technology.benefits) == null ? void 0 : _d.map((b) => b.id)) || [];
15302
15537
  updatedProcedureData.preRequirements = technology.requirements.pre;
15303
15538
  updatedProcedureData.postRequirements = technology.requirements.post;
15304
15539
  updatedProcedureData.certificationRequirement = technology.certificationRequirement;
@@ -15895,6 +16130,10 @@ var ProcedureService = class extends BaseService {
15895
16130
  "procedure-photos"
15896
16131
  );
15897
16132
  }
16133
+ const transformedProductsMetadata = await this.transformProductsMetadata(
16134
+ data.productsMetadata,
16135
+ data.technologyId
16136
+ );
15898
16137
  const clinicInfo = {
15899
16138
  id: clinicSnapshot.id,
15900
16139
  name: clinic.name,
@@ -15935,6 +16174,7 @@ var ProcedureService = class extends BaseService {
15935
16174
  technology,
15936
16175
  product: consultationProduct,
15937
16176
  // Use placeholder product
16177
+ productsMetadata: transformedProductsMetadata,
15938
16178
  blockingConditions: technology.blockingConditions,
15939
16179
  contraindications: technology.contraindications || [],
15940
16180
  contraindicationIds: ((_b = technology.contraindications) == null ? void 0 : _b.map((c) => c.id)) || [],
@@ -15994,7 +16234,7 @@ var ProcedureService = class extends BaseService {
15994
16234
 
15995
16235
  // src/services/reviews/reviews.service.ts
15996
16236
  var import_firestore47 = require("firebase/firestore");
15997
- var import_zod25 = require("zod");
16237
+ var import_zod26 = require("zod");
15998
16238
  var ReviewService = class extends BaseService {
15999
16239
  constructor(db, auth, app) {
16000
16240
  super(db, auth, app);
@@ -16081,7 +16321,7 @@ var ReviewService = class extends BaseService {
16081
16321
  });
16082
16322
  return review;
16083
16323
  } catch (error) {
16084
- if (error instanceof import_zod25.z.ZodError) {
16324
+ if (error instanceof import_zod26.z.ZodError) {
16085
16325
  throw new Error(`Invalid review data: ${error.message}`);
16086
16326
  }
16087
16327
  throw error;