@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.mjs CHANGED
@@ -6639,7 +6639,9 @@ var PractitionerService = class extends BaseService {
6639
6639
  throw new Error(`Practitioner ${practitionerId} not found`);
6640
6640
  }
6641
6641
  const currentPractitioner = practitionerDoc.data();
6642
- let processedData = { ...validData };
6642
+ let processedData = {
6643
+ ...validData
6644
+ };
6643
6645
  if (validData.basicInfo) {
6644
6646
  processedData.basicInfo = await this.processBasicInfo(
6645
6647
  validData.basicInfo,
@@ -6873,7 +6875,9 @@ var PractitionerService = class extends BaseService {
6873
6875
  */
6874
6876
  async getPractitionersByFilters(filters) {
6875
6877
  try {
6876
- console.log("[PRACTITIONER_SERVICE] Starting practitioner filtering with fallback strategies");
6878
+ console.log(
6879
+ "[PRACTITIONER_SERVICE] Starting practitioner filtering with fallback strategies"
6880
+ );
6877
6881
  if (filters.location && filters.radiusInKm) {
6878
6882
  console.log("[PRACTITIONER_SERVICE] Executing geo query:", {
6879
6883
  location: filters.location,
@@ -6881,14 +6885,19 @@ var PractitionerService = class extends BaseService {
6881
6885
  serviceName: "PractitionerService"
6882
6886
  });
6883
6887
  if (!filters.location.latitude || !filters.location.longitude) {
6884
- console.warn("[PRACTITIONER_SERVICE] Invalid location data:", filters.location);
6888
+ console.warn(
6889
+ "[PRACTITIONER_SERVICE] Invalid location data:",
6890
+ filters.location
6891
+ );
6885
6892
  filters.location = void 0;
6886
6893
  filters.radiusInKm = void 0;
6887
6894
  }
6888
6895
  }
6889
6896
  if (filters.nameSearch && filters.nameSearch.trim()) {
6890
6897
  try {
6891
- console.log("[PRACTITIONER_SERVICE] Strategy 1: Trying fullNameLower search");
6898
+ console.log(
6899
+ "[PRACTITIONER_SERVICE] Strategy 1: Trying fullNameLower search"
6900
+ );
6892
6901
  const searchTerm = filters.nameSearch.trim().toLowerCase();
6893
6902
  const constraints = [];
6894
6903
  if (!filters.includeDraftPractitioners) {
@@ -6908,11 +6917,18 @@ var PractitionerService = class extends BaseService {
6908
6917
  }
6909
6918
  }
6910
6919
  constraints.push(limit7(filters.pagination || 10));
6911
- const q = query10(collection10(this.db, PRACTITIONERS_COLLECTION), ...constraints);
6920
+ const q = query10(
6921
+ collection10(this.db, PRACTITIONERS_COLLECTION),
6922
+ ...constraints
6923
+ );
6912
6924
  const querySnapshot = await getDocs10(q);
6913
- const practitioners = querySnapshot.docs.map((doc38) => ({ ...doc38.data(), id: doc38.id }));
6925
+ const practitioners = querySnapshot.docs.map(
6926
+ (doc38) => ({ ...doc38.data(), id: doc38.id })
6927
+ );
6914
6928
  const lastDoc = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
6915
- console.log(`[PRACTITIONER_SERVICE] Strategy 1 success: ${practitioners.length} practitioners`);
6929
+ console.log(
6930
+ `[PRACTITIONER_SERVICE] Strategy 1 success: ${practitioners.length} practitioners`
6931
+ );
6916
6932
  if (practitioners.length < (filters.pagination || 10)) {
6917
6933
  return { practitioners, lastDoc: null };
6918
6934
  }
@@ -6922,7 +6938,9 @@ var PractitionerService = class extends BaseService {
6922
6938
  }
6923
6939
  }
6924
6940
  try {
6925
- console.log("[PRACTITIONER_SERVICE] Strategy 2: Basic query with createdAt ordering");
6941
+ console.log(
6942
+ "[PRACTITIONER_SERVICE] Strategy 2: Basic query with createdAt ordering"
6943
+ );
6926
6944
  const constraints = [];
6927
6945
  if (!filters.includeDraftPractitioners) {
6928
6946
  constraints.push(where10("status", "==", "active" /* ACTIVE */));
@@ -6931,14 +6949,22 @@ var PractitionerService = class extends BaseService {
6931
6949
  if (filters.certifications && filters.certifications.length > 0) {
6932
6950
  const certificationsToMatch = filters.certifications;
6933
6951
  constraints.push(
6934
- where10("certification.specialties", "array-contains-any", certificationsToMatch)
6952
+ where10(
6953
+ "certification.specialties",
6954
+ "array-contains-any",
6955
+ certificationsToMatch
6956
+ )
6935
6957
  );
6936
6958
  }
6937
6959
  if (filters.minRating !== void 0) {
6938
- constraints.push(where10("reviewInfo.averageRating", ">=", filters.minRating));
6960
+ constraints.push(
6961
+ where10("reviewInfo.averageRating", ">=", filters.minRating)
6962
+ );
6939
6963
  }
6940
6964
  if (filters.maxRating !== void 0) {
6941
- constraints.push(where10("reviewInfo.averageRating", "<=", filters.maxRating));
6965
+ constraints.push(
6966
+ where10("reviewInfo.averageRating", "<=", filters.maxRating)
6967
+ );
6942
6968
  }
6943
6969
  constraints.push(orderBy4("createdAt", "desc"));
6944
6970
  if (filters.location && filters.radiusInKm) {
@@ -6955,9 +6981,14 @@ var PractitionerService = class extends BaseService {
6955
6981
  }
6956
6982
  constraints.push(limit7(filters.pagination || 10));
6957
6983
  }
6958
- const q = query10(collection10(this.db, PRACTITIONERS_COLLECTION), ...constraints);
6984
+ const q = query10(
6985
+ collection10(this.db, PRACTITIONERS_COLLECTION),
6986
+ ...constraints
6987
+ );
6959
6988
  const querySnapshot = await getDocs10(q);
6960
- let practitioners = querySnapshot.docs.map((doc38) => ({ ...doc38.data(), id: doc38.id }));
6989
+ let practitioners = querySnapshot.docs.map(
6990
+ (doc38) => ({ ...doc38.data(), id: doc38.id })
6991
+ );
6961
6992
  if (filters.location && filters.radiusInKm && filters.radiusInKm > 0) {
6962
6993
  const location = filters.location;
6963
6994
  const radiusInKm = filters.radiusInKm;
@@ -6976,7 +7007,9 @@ var PractitionerService = class extends BaseService {
6976
7007
  }
6977
7008
  practitioners = this.applyInMemoryFilters(practitioners, filters);
6978
7009
  const lastDoc = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
6979
- console.log(`[PRACTITIONER_SERVICE] Strategy 2 success: ${practitioners.length} practitioners`);
7010
+ console.log(
7011
+ `[PRACTITIONER_SERVICE] Strategy 2 success: ${practitioners.length} practitioners`
7012
+ );
6980
7013
  if (practitioners.length < (filters.pagination || 10)) {
6981
7014
  return { practitioners, lastDoc: null };
6982
7015
  }
@@ -6985,18 +7018,27 @@ var PractitionerService = class extends BaseService {
6985
7018
  console.log("[PRACTITIONER_SERVICE] Strategy 2 failed:", error);
6986
7019
  }
6987
7020
  try {
6988
- console.log("[PRACTITIONER_SERVICE] Strategy 3: Minimal query fallback");
7021
+ console.log(
7022
+ "[PRACTITIONER_SERVICE] Strategy 3: Minimal query fallback"
7023
+ );
6989
7024
  const constraints = [
6990
7025
  where10("isActive", "==", true),
6991
7026
  orderBy4("createdAt", "desc"),
6992
7027
  limit7(filters.pagination || 10)
6993
7028
  ];
6994
- const q = query10(collection10(this.db, PRACTITIONERS_COLLECTION), ...constraints);
7029
+ const q = query10(
7030
+ collection10(this.db, PRACTITIONERS_COLLECTION),
7031
+ ...constraints
7032
+ );
6995
7033
  const querySnapshot = await getDocs10(q);
6996
- let practitioners = querySnapshot.docs.map((doc38) => ({ ...doc38.data(), id: doc38.id }));
7034
+ let practitioners = querySnapshot.docs.map(
7035
+ (doc38) => ({ ...doc38.data(), id: doc38.id })
7036
+ );
6997
7037
  practitioners = this.applyInMemoryFilters(practitioners, filters);
6998
7038
  const lastDoc = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
6999
- console.log(`[PRACTITIONER_SERVICE] Strategy 3 success: ${practitioners.length} practitioners`);
7039
+ console.log(
7040
+ `[PRACTITIONER_SERVICE] Strategy 3 success: ${practitioners.length} practitioners`
7041
+ );
7000
7042
  if (practitioners.length < (filters.pagination || 10)) {
7001
7043
  return { practitioners, lastDoc: null };
7002
7044
  }
@@ -7005,19 +7047,28 @@ var PractitionerService = class extends BaseService {
7005
7047
  console.log("[PRACTITIONER_SERVICE] Strategy 3 failed:", error);
7006
7048
  }
7007
7049
  try {
7008
- console.log("[PRACTITIONER_SERVICE] Strategy 4: Client-side filtering fallback");
7050
+ console.log(
7051
+ "[PRACTITIONER_SERVICE] Strategy 4: Client-side filtering fallback"
7052
+ );
7009
7053
  const constraints = [
7010
7054
  where10("isActive", "==", true),
7011
7055
  where10("status", "==", "active" /* ACTIVE */),
7012
7056
  orderBy4("createdAt", "desc"),
7013
7057
  limit7(filters.pagination || 10)
7014
7058
  ];
7015
- const q = query10(collection10(this.db, PRACTITIONERS_COLLECTION), ...constraints);
7059
+ const q = query10(
7060
+ collection10(this.db, PRACTITIONERS_COLLECTION),
7061
+ ...constraints
7062
+ );
7016
7063
  const querySnapshot = await getDocs10(q);
7017
- let practitioners = querySnapshot.docs.map((doc38) => ({ ...doc38.data(), id: doc38.id }));
7064
+ let practitioners = querySnapshot.docs.map(
7065
+ (doc38) => ({ ...doc38.data(), id: doc38.id })
7066
+ );
7018
7067
  practitioners = this.applyInMemoryFilters(practitioners, filters);
7019
7068
  const lastDoc = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
7020
- console.log(`[PRACTITIONER_SERVICE] Strategy 4 success: ${practitioners.length} practitioners`);
7069
+ console.log(
7070
+ `[PRACTITIONER_SERVICE] Strategy 4 success: ${practitioners.length} practitioners`
7071
+ );
7021
7072
  if (practitioners.length < (filters.pagination || 10)) {
7022
7073
  return { practitioners, lastDoc: null };
7023
7074
  }
@@ -7025,10 +7076,15 @@ var PractitionerService = class extends BaseService {
7025
7076
  } catch (error) {
7026
7077
  console.log("[PRACTITIONER_SERVICE] Strategy 4 failed:", error);
7027
7078
  }
7028
- console.log("[PRACTITIONER_SERVICE] All strategies failed, returning empty result");
7079
+ console.log(
7080
+ "[PRACTITIONER_SERVICE] All strategies failed, returning empty result"
7081
+ );
7029
7082
  return { practitioners: [], lastDoc: null };
7030
7083
  } catch (error) {
7031
- console.error("[PRACTITIONER_SERVICE] Error filtering practitioners:", error);
7084
+ console.error(
7085
+ "[PRACTITIONER_SERVICE] Error filtering practitioners:",
7086
+ error
7087
+ );
7032
7088
  return { practitioners: [], lastDoc: null };
7033
7089
  }
7034
7090
  }
@@ -7048,63 +7104,93 @@ var PractitionerService = class extends BaseService {
7048
7104
  const fullNameLower = practitioner.fullNameLower || "";
7049
7105
  return firstName.includes(searchTerm) || lastName.includes(searchTerm) || fullName.includes(searchTerm) || fullNameLower.includes(searchTerm);
7050
7106
  });
7051
- console.log(`[PRACTITIONER_SERVICE] Applied name filter, results: ${filteredPractitioners.length}`);
7107
+ console.log(
7108
+ `[PRACTITIONER_SERVICE] Applied name filter, results: ${filteredPractitioners.length}`
7109
+ );
7052
7110
  }
7053
7111
  if (filters.certifications && filters.certifications.length > 0) {
7054
7112
  const certificationsToMatch = filters.certifications;
7055
7113
  filteredPractitioners = filteredPractitioners.filter((practitioner) => {
7056
7114
  var _a;
7057
7115
  const practitionerCerts = ((_a = practitioner.certification) == null ? void 0 : _a.specialties) || [];
7058
- return certificationsToMatch.some((cert) => practitionerCerts.includes(cert));
7116
+ return certificationsToMatch.some(
7117
+ (cert) => practitionerCerts.includes(cert)
7118
+ );
7059
7119
  });
7060
- console.log(`[PRACTITIONER_SERVICE] Applied certifications filter, results: ${filteredPractitioners.length}`);
7120
+ console.log(
7121
+ `[PRACTITIONER_SERVICE] Applied certifications filter, results: ${filteredPractitioners.length}`
7122
+ );
7061
7123
  }
7062
7124
  if (filters.specialties && filters.specialties.length > 0) {
7063
7125
  const specialtiesToMatch = filters.specialties;
7064
7126
  filteredPractitioners = filteredPractitioners.filter((practitioner) => {
7065
7127
  var _a;
7066
7128
  const practitionerSpecs = ((_a = practitioner.certification) == null ? void 0 : _a.specialties) || [];
7067
- return specialtiesToMatch.some((spec) => practitionerSpecs.includes(spec));
7129
+ return specialtiesToMatch.some(
7130
+ (spec) => practitionerSpecs.includes(spec)
7131
+ );
7068
7132
  });
7069
- console.log(`[PRACTITIONER_SERVICE] Applied specialties filter, results: ${filteredPractitioners.length}`);
7133
+ console.log(
7134
+ `[PRACTITIONER_SERVICE] Applied specialties filter, results: ${filteredPractitioners.length}`
7135
+ );
7070
7136
  }
7071
7137
  if (filters.minRating !== void 0 || filters.maxRating !== void 0) {
7072
7138
  filteredPractitioners = filteredPractitioners.filter((practitioner) => {
7073
7139
  var _a;
7074
7140
  const rating = ((_a = practitioner.reviewInfo) == null ? void 0 : _a.averageRating) || 0;
7075
- if (filters.minRating !== void 0 && rating < filters.minRating) return false;
7076
- if (filters.maxRating !== void 0 && rating > filters.maxRating) return false;
7141
+ if (filters.minRating !== void 0 && rating < filters.minRating)
7142
+ return false;
7143
+ if (filters.maxRating !== void 0 && rating > filters.maxRating)
7144
+ return false;
7077
7145
  return true;
7078
7146
  });
7079
- console.log(`[PRACTITIONER_SERVICE] Applied rating filter, results: ${filteredPractitioners.length}`);
7147
+ console.log(
7148
+ `[PRACTITIONER_SERVICE] Applied rating filter, results: ${filteredPractitioners.length}`
7149
+ );
7080
7150
  }
7081
7151
  if (filters.procedureFamily) {
7082
7152
  filteredPractitioners = filteredPractitioners.filter((practitioner) => {
7083
7153
  const proceduresInfo = practitioner.proceduresInfo || [];
7084
- return proceduresInfo.some((proc) => proc.family === filters.procedureFamily);
7154
+ return proceduresInfo.some(
7155
+ (proc) => proc.family === filters.procedureFamily
7156
+ );
7085
7157
  });
7086
- console.log(`[PRACTITIONER_SERVICE] Applied procedure family filter, results: ${filteredPractitioners.length}`);
7158
+ console.log(
7159
+ `[PRACTITIONER_SERVICE] Applied procedure family filter, results: ${filteredPractitioners.length}`
7160
+ );
7087
7161
  }
7088
7162
  if (filters.procedureCategory) {
7089
7163
  filteredPractitioners = filteredPractitioners.filter((practitioner) => {
7090
7164
  const proceduresInfo = practitioner.proceduresInfo || [];
7091
- return proceduresInfo.some((proc) => proc.categoryName === filters.procedureCategory);
7165
+ return proceduresInfo.some(
7166
+ (proc) => proc.categoryName === filters.procedureCategory
7167
+ );
7092
7168
  });
7093
- console.log(`[PRACTITIONER_SERVICE] Applied procedure category filter, results: ${filteredPractitioners.length}`);
7169
+ console.log(
7170
+ `[PRACTITIONER_SERVICE] Applied procedure category filter, results: ${filteredPractitioners.length}`
7171
+ );
7094
7172
  }
7095
7173
  if (filters.procedureSubcategory) {
7096
7174
  filteredPractitioners = filteredPractitioners.filter((practitioner) => {
7097
7175
  const proceduresInfo = practitioner.proceduresInfo || [];
7098
- return proceduresInfo.some((proc) => proc.subcategoryName === filters.procedureSubcategory);
7176
+ return proceduresInfo.some(
7177
+ (proc) => proc.subcategoryName === filters.procedureSubcategory
7178
+ );
7099
7179
  });
7100
- console.log(`[PRACTITIONER_SERVICE] Applied procedure subcategory filter, results: ${filteredPractitioners.length}`);
7180
+ console.log(
7181
+ `[PRACTITIONER_SERVICE] Applied procedure subcategory filter, results: ${filteredPractitioners.length}`
7182
+ );
7101
7183
  }
7102
7184
  if (filters.procedureTechnology) {
7103
7185
  filteredPractitioners = filteredPractitioners.filter((practitioner) => {
7104
7186
  const proceduresInfo = practitioner.proceduresInfo || [];
7105
- return proceduresInfo.some((proc) => proc.technologyName === filters.procedureTechnology);
7187
+ return proceduresInfo.some(
7188
+ (proc) => proc.technologyName === filters.procedureTechnology
7189
+ );
7106
7190
  });
7107
- console.log(`[PRACTITIONER_SERVICE] Applied procedure technology filter, results: ${filteredPractitioners.length}`);
7191
+ console.log(
7192
+ `[PRACTITIONER_SERVICE] Applied procedure technology filter, results: ${filteredPractitioners.length}`
7193
+ );
7108
7194
  }
7109
7195
  if (filters.location && filters.radiusInKm && filters.radiusInKm > 0) {
7110
7196
  const location = filters.location;
@@ -7120,7 +7206,9 @@ var PractitionerService = class extends BaseService {
7120
7206
  return distanceInKm <= radiusInKm;
7121
7207
  });
7122
7208
  });
7123
- console.log(`[PRACTITIONER_SERVICE] Applied geo filter, results: ${filteredPractitioners.length}`);
7209
+ console.log(
7210
+ `[PRACTITIONER_SERVICE] Applied geo filter, results: ${filteredPractitioners.length}`
7211
+ );
7124
7212
  }
7125
7213
  return filteredPractitioners;
7126
7214
  }
@@ -7185,6 +7273,15 @@ var PractitionerService = class extends BaseService {
7185
7273
  price: 0,
7186
7274
  currency: "EUR" /* EUR */,
7187
7275
  pricingMeasure: "per_session" /* PER_SESSION */,
7276
+ productsMetadata: [
7277
+ {
7278
+ productId: "free-consultation-product",
7279
+ price: 0,
7280
+ currency: "EUR" /* EUR */,
7281
+ pricingMeasure: "per_session" /* PER_SESSION */,
7282
+ isDefault: true
7283
+ }
7284
+ ],
7188
7285
  duration: 30,
7189
7286
  // 30 minutes consultation
7190
7287
  practitionerId,
@@ -14981,67 +15078,141 @@ import {
14981
15078
  } from "firebase/firestore";
14982
15079
 
14983
15080
  // src/validations/procedure.schema.ts
15081
+ import { z as z25 } from "zod";
15082
+
15083
+ // src/validations/procedure-product.schema.ts
14984
15084
  import { z as z24 } from "zod";
14985
- var createProcedureSchema = z24.object({
14986
- name: z24.string().min(1).max(200),
14987
- // Optional: service will derive from name if not provided by client
14988
- nameLower: z24.string().min(1).max(200).optional(),
14989
- description: z24.string().min(1).max(2e3),
14990
- family: z24.nativeEnum(ProcedureFamily),
14991
- categoryId: z24.string().min(1),
14992
- subcategoryId: z24.string().min(1),
14993
- technologyId: z24.string().min(1),
14994
- productId: z24.string().min(1),
14995
- price: z24.number().min(0),
15085
+ var procedureProductDataSchema = z24.object({
15086
+ /**
15087
+ * The ID of the product. Must be a non-empty string.
15088
+ * @validation
15089
+ */
15090
+ productId: z24.string().min(1, "Product ID is required"),
15091
+ /**
15092
+ * The price of the product. Must be a non-negative number.
15093
+ * @validation
15094
+ */
15095
+ price: z24.number().min(0, "Price must be a non-negative number"),
15096
+ /**
15097
+ * The currency for the price. Must be one of the values from the Currency enum.
15098
+ * @validation
15099
+ */
14996
15100
  currency: z24.nativeEnum(Currency),
15101
+ /**
15102
+ * The pricing measure for the product. Must be one of the values from the PricingMeasure enum.
15103
+ * @validation
15104
+ */
14997
15105
  pricingMeasure: z24.nativeEnum(PricingMeasure),
14998
- duration: z24.number().min(1).max(480),
15106
+ /**
15107
+ * Whether this is the default product for the procedure.
15108
+ * @validation
15109
+ */
15110
+ isDefault: z24.boolean().optional()
15111
+ });
15112
+
15113
+ // src/validations/procedure.schema.ts
15114
+ var storedProcedureProductSchema = z25.object({
15115
+ /**
15116
+ * The full product object used in the procedure.
15117
+ */
15118
+ product: z25.any(),
15119
+ // We'll validate the full product object separately
15120
+ /**
15121
+ * The price of the procedure when using this specific product.
15122
+ */
15123
+ price: z25.number().min(0, "Price must be a non-negative number"),
15124
+ /**
15125
+ * The currency for the price of this product.
15126
+ */
15127
+ currency: z25.nativeEnum(Currency),
15128
+ /**
15129
+ * How the price is measured (e.g., per ml, per zone).
15130
+ */
15131
+ pricingMeasure: z25.nativeEnum(PricingMeasure),
15132
+ /**
15133
+ * Whether this is the default product for the procedure.
15134
+ */
15135
+ isDefault: z25.boolean().optional()
15136
+ });
15137
+ var createProcedureSchema = z25.object({
15138
+ name: z25.string().min(1).max(200),
15139
+ // Optional: service will derive from name if not provided by client
15140
+ nameLower: z25.string().min(1).max(200).optional(),
15141
+ description: z25.string().min(1).max(2e3),
15142
+ family: z25.nativeEnum(ProcedureFamily),
15143
+ categoryId: z25.string().min(1),
15144
+ subcategoryId: z25.string().min(1),
15145
+ technologyId: z25.string().min(1),
15146
+ productId: z25.string().min(1),
15147
+ price: z25.number().min(0),
15148
+ currency: z25.nativeEnum(Currency),
15149
+ pricingMeasure: z25.nativeEnum(PricingMeasure),
15150
+ productsMetadata: z25.array(procedureProductDataSchema).min(1),
15151
+ duration: z25.number().min(1).max(480),
14999
15152
  // Max 8 hours
15000
- practitionerId: z24.string().min(1),
15001
- clinicBranchId: z24.string().min(1),
15002
- photos: z24.array(mediaResourceSchema).optional()
15153
+ practitionerId: z25.string().min(1),
15154
+ clinicBranchId: z25.string().min(1),
15155
+ photos: z25.array(mediaResourceSchema).optional()
15003
15156
  });
15004
- var updateProcedureSchema = z24.object({
15005
- name: z24.string().min(3).max(100).optional(),
15006
- nameLower: z24.string().min(1).max(200).optional(),
15007
- description: z24.string().min(3).max(1e3).optional(),
15008
- price: z24.number().min(0).optional(),
15009
- currency: z24.nativeEnum(Currency).optional(),
15010
- pricingMeasure: z24.nativeEnum(PricingMeasure).optional(),
15011
- duration: z24.number().min(0).optional(),
15012
- isActive: z24.boolean().optional(),
15013
- practitionerId: z24.string().optional(),
15014
- categoryId: z24.string().optional(),
15015
- subcategoryId: z24.string().optional(),
15016
- technologyId: z24.string().optional(),
15017
- productId: z24.string().optional(),
15018
- clinicBranchId: z24.string().optional(),
15019
- photos: z24.array(mediaResourceSchema).optional()
15157
+ var updateProcedureSchema = z25.object({
15158
+ name: z25.string().min(3).max(100).optional(),
15159
+ nameLower: z25.string().min(1).max(200).optional(),
15160
+ description: z25.string().min(3).max(1e3).optional(),
15161
+ price: z25.number().min(0).optional(),
15162
+ currency: z25.nativeEnum(Currency).optional(),
15163
+ pricingMeasure: z25.nativeEnum(PricingMeasure).optional(),
15164
+ productsMetadata: z25.array(procedureProductDataSchema).min(1).optional(),
15165
+ duration: z25.number().min(0).optional(),
15166
+ isActive: z25.boolean().optional(),
15167
+ practitionerId: z25.string().optional(),
15168
+ categoryId: z25.string().optional(),
15169
+ subcategoryId: z25.string().optional(),
15170
+ technologyId: z25.string().optional(),
15171
+ productId: z25.string().optional(),
15172
+ clinicBranchId: z25.string().optional(),
15173
+ photos: z25.array(mediaResourceSchema).optional()
15020
15174
  });
15021
- var procedureSchema = createProcedureSchema.extend({
15022
- id: z24.string().min(1),
15023
- nameLower: z24.string().min(1).max(200),
15024
- category: z24.any(),
15175
+ var procedureSchema = z25.object({
15176
+ id: z25.string().min(1),
15177
+ name: z25.string().min(1).max(200),
15178
+ nameLower: z25.string().min(1).max(200),
15179
+ description: z25.string().min(1).max(2e3),
15180
+ family: z25.nativeEnum(ProcedureFamily),
15181
+ category: z25.any(),
15025
15182
  // We'll validate the full category object separately
15026
- subcategory: z24.any(),
15183
+ subcategory: z25.any(),
15027
15184
  // We'll validate the full subcategory object separately
15028
- technology: z24.any(),
15185
+ technology: z25.any(),
15029
15186
  // We'll validate the full technology object separately
15030
- product: z24.any(),
15187
+ product: z25.any(),
15031
15188
  // We'll validate the full product object separately
15032
- blockingConditions: z24.array(z24.any()),
15189
+ productsMetadata: z25.array(storedProcedureProductSchema).min(1),
15190
+ // Use stored format schema
15191
+ price: z25.number().min(0),
15192
+ currency: z25.nativeEnum(Currency),
15193
+ pricingMeasure: z25.nativeEnum(PricingMeasure),
15194
+ duration: z25.number().min(1).max(480),
15195
+ practitionerId: z25.string().min(1),
15196
+ clinicBranchId: z25.string().min(1),
15197
+ photos: z25.array(z25.string()).optional(),
15198
+ // Stored as URL strings
15199
+ blockingConditions: z25.array(z25.any()),
15033
15200
  // We'll validate blocking conditions separately
15034
- contraindications: z24.array(z24.any()),
15201
+ contraindications: z25.array(z25.any()),
15035
15202
  // We'll validate contraindications separately
15036
- treatmentBenefits: z24.array(z24.any()),
15203
+ contraindicationIds: z25.array(z25.string()),
15204
+ // Array of IDs for efficient querying
15205
+ treatmentBenefits: z25.array(z25.any()),
15037
15206
  // We'll validate treatment benefits separately
15038
- preRequirements: z24.array(z24.any()),
15207
+ treatmentBenefitIds: z25.array(z25.string()),
15208
+ // Array of IDs for efficient querying
15209
+ preRequirements: z25.array(z25.any()),
15039
15210
  // We'll validate requirements separately
15040
- postRequirements: z24.array(z24.any()),
15211
+ postRequirements: z25.array(z25.any()),
15041
15212
  // We'll validate requirements separately
15042
- certificationRequirement: z24.any(),
15213
+ certificationRequirement: z25.any(),
15043
15214
  // We'll validate certification requirement separately
15044
- documentationTemplates: z24.array(z24.any()),
15215
+ documentationTemplates: z25.array(z25.any()),
15045
15216
  // We'll validate documentation templates separately
15046
15217
  clinicInfo: clinicInfoSchema,
15047
15218
  // Clinic info validation
@@ -15049,9 +15220,9 @@ var procedureSchema = createProcedureSchema.extend({
15049
15220
  // Doctor info validation
15050
15221
  reviewInfo: procedureReviewInfoSchema,
15051
15222
  // Procedure review info validation
15052
- isActive: z24.boolean(),
15053
- createdAt: z24.date(),
15054
- updatedAt: z24.date()
15223
+ isActive: z25.boolean(),
15224
+ createdAt: z25.date(),
15225
+ updatedAt: z25.date()
15055
15226
  });
15056
15227
 
15057
15228
  // src/services/procedure/procedure.service.ts
@@ -15113,6 +15284,34 @@ var ProcedureService = class extends BaseService {
15113
15284
  }
15114
15285
  return result;
15115
15286
  }
15287
+ /**
15288
+ * Transforms validated procedure product data (with productId) to ProcedureProduct objects (with full product)
15289
+ * @param productsMetadata Array of validated procedure product data
15290
+ * @param technologyId Technology ID to fetch products from
15291
+ * @returns Array of ProcedureProduct objects with full product information
15292
+ */
15293
+ async transformProductsMetadata(productsMetadata, technologyId) {
15294
+ const transformedProducts = [];
15295
+ for (const productData of productsMetadata) {
15296
+ const product = await this.productService.getById(
15297
+ technologyId,
15298
+ productData.productId
15299
+ );
15300
+ if (!product) {
15301
+ throw new Error(
15302
+ `Product with ID ${productData.productId} not found for technology ${technologyId}`
15303
+ );
15304
+ }
15305
+ transformedProducts.push({
15306
+ product,
15307
+ price: productData.price,
15308
+ currency: productData.currency,
15309
+ pricingMeasure: productData.pricingMeasure,
15310
+ isDefault: productData.isDefault
15311
+ });
15312
+ }
15313
+ return transformedProducts;
15314
+ }
15116
15315
  /**
15117
15316
  * Creates a new procedure
15118
15317
  * @param data - The data for creating a new procedure
@@ -15169,6 +15368,10 @@ var ProcedureService = class extends BaseService {
15169
15368
  "procedure-photos"
15170
15369
  );
15171
15370
  }
15371
+ const transformedProductsMetadata = await this.transformProductsMetadata(
15372
+ validatedData.productsMetadata,
15373
+ validatedData.technologyId
15374
+ );
15172
15375
  const clinicInfo = {
15173
15376
  id: clinicSnapshot.id,
15174
15377
  name: clinic.name,
@@ -15197,6 +15400,7 @@ var ProcedureService = class extends BaseService {
15197
15400
  subcategory,
15198
15401
  technology,
15199
15402
  product,
15403
+ productsMetadata: transformedProductsMetadata,
15200
15404
  blockingConditions: technology.blockingConditions,
15201
15405
  contraindications: technology.contraindications || [],
15202
15406
  contraindicationIds: ((_b = technology.contraindications) == null ? void 0 : _b.map((c) => c.id)) || [],
@@ -15279,6 +15483,10 @@ var ProcedureService = class extends BaseService {
15279
15483
  "procedure-photos-batch"
15280
15484
  );
15281
15485
  }
15486
+ const transformedProductsMetadata = await this.transformProductsMetadata(
15487
+ validatedData.productsMetadata,
15488
+ validatedData.technologyId
15489
+ );
15282
15490
  const practitionersMap = /* @__PURE__ */ new Map();
15283
15491
  for (let i = 0; i < practitionerIds.length; i += 30) {
15284
15492
  const chunk = practitionerIds.slice(i, i + 30);
@@ -15334,6 +15542,7 @@ var ProcedureService = class extends BaseService {
15334
15542
  subcategory,
15335
15543
  technology,
15336
15544
  product,
15545
+ productsMetadata: transformedProductsMetadata,
15337
15546
  blockingConditions: technology.blockingConditions,
15338
15547
  contraindications: technology.contraindications || [],
15339
15548
  contraindicationIds: ((_b = technology.contraindications) == null ? void 0 : _b.map((c) => c.id)) || [],
@@ -15441,7 +15650,7 @@ var ProcedureService = class extends BaseService {
15441
15650
  * @returns The updated procedure
15442
15651
  */
15443
15652
  async updateProcedure(id, data) {
15444
- var _a, _b, _c;
15653
+ var _a, _b, _c, _d;
15445
15654
  const validatedData = updateProcedureSchema.parse(data);
15446
15655
  const procedureRef = doc30(this.db, PROCEDURES_COLLECTION, id);
15447
15656
  const procedureSnapshot = await getDoc32(procedureRef);
@@ -15449,7 +15658,21 @@ var ProcedureService = class extends BaseService {
15449
15658
  throw new Error(`Procedure with ID ${id} not found`);
15450
15659
  }
15451
15660
  const existingProcedure = procedureSnapshot.data();
15452
- let updatedProcedureData = { ...validatedData };
15661
+ let updatedProcedureData = {};
15662
+ if (validatedData.name !== void 0)
15663
+ updatedProcedureData.name = validatedData.name;
15664
+ if (validatedData.description !== void 0)
15665
+ updatedProcedureData.description = validatedData.description;
15666
+ if (validatedData.price !== void 0)
15667
+ updatedProcedureData.price = validatedData.price;
15668
+ if (validatedData.currency !== void 0)
15669
+ updatedProcedureData.currency = validatedData.currency;
15670
+ if (validatedData.pricingMeasure !== void 0)
15671
+ updatedProcedureData.pricingMeasure = validatedData.pricingMeasure;
15672
+ if (validatedData.duration !== void 0)
15673
+ updatedProcedureData.duration = validatedData.duration;
15674
+ if (validatedData.isActive !== void 0)
15675
+ updatedProcedureData.isActive = validatedData.isActive;
15453
15676
  let practitionerChanged = false;
15454
15677
  let clinicChanged = false;
15455
15678
  const oldPractitionerId = existingProcedure.practitionerId;
@@ -15463,6 +15686,18 @@ var ProcedureService = class extends BaseService {
15463
15686
  "procedure-photos"
15464
15687
  );
15465
15688
  }
15689
+ if (validatedData.productsMetadata !== void 0) {
15690
+ const technologyId = (_a = validatedData.technologyId) != null ? _a : existingProcedure.technology.id;
15691
+ if (!technologyId) {
15692
+ throw new Error(
15693
+ "Technology ID is required for updating products metadata"
15694
+ );
15695
+ }
15696
+ updatedProcedureData.productsMetadata = await this.transformProductsMetadata(
15697
+ validatedData.productsMetadata,
15698
+ technologyId
15699
+ );
15700
+ }
15466
15701
  if (validatedData.practitionerId && validatedData.practitionerId !== oldPractitionerId) {
15467
15702
  practitionerChanged = true;
15468
15703
  const newPractitionerRef = doc30(
@@ -15482,7 +15717,7 @@ var ProcedureService = class extends BaseService {
15482
15717
  description: newPractitioner.basicInfo.bio || "",
15483
15718
  photo: typeof newPractitioner.basicInfo.profileImageUrl === "string" ? newPractitioner.basicInfo.profileImageUrl : "",
15484
15719
  // Default to empty string if not a processed URL
15485
- rating: ((_a = newPractitioner.reviewInfo) == null ? void 0 : _a.averageRating) || 0,
15720
+ rating: ((_b = newPractitioner.reviewInfo) == null ? void 0 : _b.averageRating) || 0,
15486
15721
  services: newPractitioner.procedures || []
15487
15722
  };
15488
15723
  }
@@ -15545,9 +15780,9 @@ var ProcedureService = class extends BaseService {
15545
15780
  finalTechnologyId = technology.id;
15546
15781
  updatedProcedureData.blockingConditions = technology.blockingConditions;
15547
15782
  updatedProcedureData.contraindications = technology.contraindications || [];
15548
- updatedProcedureData.contraindicationIds = ((_b = technology.contraindications) == null ? void 0 : _b.map((c) => c.id)) || [];
15783
+ updatedProcedureData.contraindicationIds = ((_c = technology.contraindications) == null ? void 0 : _c.map((c) => c.id)) || [];
15549
15784
  updatedProcedureData.treatmentBenefits = technology.benefits;
15550
- updatedProcedureData.treatmentBenefitIds = ((_c = technology.benefits) == null ? void 0 : _c.map((b) => b.id)) || [];
15785
+ updatedProcedureData.treatmentBenefitIds = ((_d = technology.benefits) == null ? void 0 : _d.map((b) => b.id)) || [];
15551
15786
  updatedProcedureData.preRequirements = technology.requirements.pre;
15552
15787
  updatedProcedureData.postRequirements = technology.requirements.post;
15553
15788
  updatedProcedureData.certificationRequirement = technology.certificationRequirement;
@@ -16144,6 +16379,10 @@ var ProcedureService = class extends BaseService {
16144
16379
  "procedure-photos"
16145
16380
  );
16146
16381
  }
16382
+ const transformedProductsMetadata = await this.transformProductsMetadata(
16383
+ data.productsMetadata,
16384
+ data.technologyId
16385
+ );
16147
16386
  const clinicInfo = {
16148
16387
  id: clinicSnapshot.id,
16149
16388
  name: clinic.name,
@@ -16184,6 +16423,7 @@ var ProcedureService = class extends BaseService {
16184
16423
  technology,
16185
16424
  product: consultationProduct,
16186
16425
  // Use placeholder product
16426
+ productsMetadata: transformedProductsMetadata,
16187
16427
  blockingConditions: technology.blockingConditions,
16188
16428
  contraindications: technology.contraindications || [],
16189
16429
  contraindicationIds: ((_b = technology.contraindications) == null ? void 0 : _b.map((c) => c.id)) || [],
@@ -16253,7 +16493,7 @@ import {
16253
16493
  deleteDoc as deleteDoc19,
16254
16494
  serverTimestamp as serverTimestamp26
16255
16495
  } from "firebase/firestore";
16256
- import { z as z25 } from "zod";
16496
+ import { z as z26 } from "zod";
16257
16497
  var ReviewService = class extends BaseService {
16258
16498
  constructor(db, auth, app) {
16259
16499
  super(db, auth, app);
@@ -16340,7 +16580,7 @@ var ReviewService = class extends BaseService {
16340
16580
  });
16341
16581
  return review;
16342
16582
  } catch (error) {
16343
- if (error instanceof z25.ZodError) {
16583
+ if (error instanceof z26.ZodError) {
16344
16584
  throw new Error(`Invalid review data: ${error.message}`);
16345
16585
  }
16346
16586
  throw error;