@blackcode_sa/metaestetics-api 1.12.68 → 1.12.70

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
@@ -188,13 +188,13 @@ var AppointmentStatus = /* @__PURE__ */ ((AppointmentStatus2) => {
188
188
  AppointmentStatus2["RESCHEDULED_BY_CLINIC"] = "rescheduled_by_clinic";
189
189
  return AppointmentStatus2;
190
190
  })(AppointmentStatus || {});
191
- var PaymentStatus = /* @__PURE__ */ ((PaymentStatus4) => {
192
- PaymentStatus4["UNPAID"] = "unpaid";
193
- PaymentStatus4["PAID"] = "paid";
194
- PaymentStatus4["PARTIALLY_PAID"] = "partially_paid";
195
- PaymentStatus4["REFUNDED"] = "refunded";
196
- PaymentStatus4["NOT_APPLICABLE"] = "not_applicable";
197
- return PaymentStatus4;
191
+ var PaymentStatus = /* @__PURE__ */ ((PaymentStatus3) => {
192
+ PaymentStatus3["UNPAID"] = "unpaid";
193
+ PaymentStatus3["PAID"] = "paid";
194
+ PaymentStatus3["PARTIALLY_PAID"] = "partially_paid";
195
+ PaymentStatus3["REFUNDED"] = "refunded";
196
+ PaymentStatus3["NOT_APPLICABLE"] = "not_applicable";
197
+ return PaymentStatus3;
198
198
  })(PaymentStatus || {});
199
199
  var MediaType = /* @__PURE__ */ ((MediaType2) => {
200
200
  MediaType2["BEFORE_PHOTO"] = "before_photo";
@@ -3430,6 +3430,7 @@ var AppointmentService = class extends BaseService {
3430
3430
  finalbilling: null,
3431
3431
  finalizationNotes: null
3432
3432
  };
3433
+ const shouldUpdatePaymentStatus = finalbilling.finalPrice > 0 && appointment.paymentStatus === "not_applicable" /* NOT_APPLICABLE */;
3433
3434
  const updateData = {
3434
3435
  metadata: {
3435
3436
  selectedZones: currentMetadata.selectedZones,
@@ -3445,6 +3446,9 @@ var AppointmentService = class extends BaseService {
3445
3446
  finalbilling,
3446
3447
  finalizationNotes: currentMetadata.finalizationNotes
3447
3448
  },
3449
+ ...shouldUpdatePaymentStatus && {
3450
+ paymentStatus: "unpaid" /* UNPAID */
3451
+ },
3448
3452
  updatedAt: (0, import_firestore11.serverTimestamp)()
3449
3453
  };
3450
3454
  return await this.updateAppointment(appointmentId, updateData);
@@ -3658,8 +3662,36 @@ var AppointmentService = class extends BaseService {
3658
3662
  showCanceled: false,
3659
3663
  showNoShow: false
3660
3664
  });
3665
+ const now = /* @__PURE__ */ new Date();
3666
+ const allPastAppointments = await this.getPatientAppointments(patientId, {
3667
+ endDate: now,
3668
+ status: [
3669
+ "completed" /* COMPLETED */,
3670
+ "confirmed" /* CONFIRMED */,
3671
+ "checked_in" /* CHECKED_IN */,
3672
+ "in_progress" /* IN_PROGRESS */
3673
+ ]
3674
+ });
3675
+ const appointmentsWithRecommendations = allPastAppointments.appointments.filter(
3676
+ (appointment) => {
3677
+ var _a2, _b2, _c2, _d;
3678
+ const endTime = ((_a2 = appointment.appointmentEndTime) == null ? void 0 : _a2.toMillis) ? appointment.appointmentEndTime.toMillis() : ((_b2 = appointment.appointmentEndTime) == null ? void 0 : _b2.seconds) ? appointment.appointmentEndTime.seconds * 1e3 : null;
3679
+ if (!endTime) return false;
3680
+ const isPastEndTime = endTime < now.getTime();
3681
+ const hasRecommendations = (((_d = (_c2 = appointment.metadata) == null ? void 0 : _c2.recommendedProcedures) == null ? void 0 : _d.length) || 0) > 0;
3682
+ return isPastEndTime && hasRecommendations;
3683
+ }
3684
+ );
3685
+ const allAppointmentsMap = /* @__PURE__ */ new Map();
3686
+ pastAppointments.appointments.forEach((apt) => {
3687
+ allAppointmentsMap.set(apt.id, apt);
3688
+ });
3689
+ appointmentsWithRecommendations.forEach((apt) => {
3690
+ allAppointmentsMap.set(apt.id, apt);
3691
+ });
3692
+ const allAppointments = Array.from(allAppointmentsMap.values());
3661
3693
  const recommendations = [];
3662
- for (const appointment of pastAppointments.appointments) {
3694
+ for (const appointment of allAppointments) {
3663
3695
  if ((options == null ? void 0 : options.clinicBranchId) && appointment.clinicBranchId !== options.clinicBranchId) {
3664
3696
  continue;
3665
3697
  }
@@ -3696,9 +3728,6 @@ var AppointmentService = class extends BaseService {
3696
3728
  return dateB - dateA;
3697
3729
  });
3698
3730
  const limitedRecommendations = (options == null ? void 0 : options.limit) ? recommendations.slice(0, options.limit) : recommendations;
3699
- console.log(
3700
- `[APPOINTMENT_SERVICE] Found ${limitedRecommendations.length} next steps recommendations for patient ${patientId}`
3701
- );
3702
3731
  return limitedRecommendations;
3703
3732
  } catch (error) {
3704
3733
  console.error(
@@ -3967,6 +3996,7 @@ var NotificationType = /* @__PURE__ */ ((NotificationType3) => {
3967
3996
  NotificationType3["FORM_REMINDER"] = "formReminder";
3968
3997
  NotificationType3["FORM_SUBMISSION_CONFIRMATION"] = "formSubmissionConfirmation";
3969
3998
  NotificationType3["REVIEW_REQUEST"] = "reviewRequest";
3999
+ NotificationType3["PROCEDURE_RECOMMENDATION"] = "procedureRecommendation";
3970
4000
  NotificationType3["PAYMENT_DUE"] = "paymentDue";
3971
4001
  NotificationType3["PAYMENT_CONFIRMATION"] = "paymentConfirmation";
3972
4002
  NotificationType3["PAYMENT_FAILED"] = "paymentFailed";
@@ -17491,6 +17521,10 @@ var ProcedureService = class extends BaseService {
17491
17521
  console.log("[PROCEDURE_SERVICE] Strategy 1: Trying nameLower search");
17492
17522
  const searchTerm = filters.nameSearch.trim().toLowerCase();
17493
17523
  const constraints = getBaseConstraints();
17524
+ const hasNestedFilters = !!(filters.procedureTechnology || filters.procedureCategory || filters.procedureSubcategory);
17525
+ if (hasNestedFilters) {
17526
+ console.log("[PROCEDURE_SERVICE] Strategy 1: Has nested filters, will apply client-side after query");
17527
+ }
17494
17528
  constraints.push((0, import_firestore55.where)("nameLower", ">=", searchTerm));
17495
17529
  constraints.push((0, import_firestore55.where)("nameLower", "<=", searchTerm + "\uF8FF"));
17496
17530
  constraints.push((0, import_firestore55.orderBy)("nameLower"));
@@ -17506,9 +17540,12 @@ var ProcedureService = class extends BaseService {
17506
17540
  constraints.push((0, import_firestore55.limit)(filters.pagination || 10));
17507
17541
  const q = (0, import_firestore55.query)((0, import_firestore55.collection)(this.db, PROCEDURES_COLLECTION), ...constraints);
17508
17542
  const querySnapshot = await (0, import_firestore55.getDocs)(q);
17509
- const procedures = querySnapshot.docs.map(
17543
+ let procedures = querySnapshot.docs.map(
17510
17544
  (doc45) => ({ ...doc45.data(), id: doc45.id })
17511
17545
  );
17546
+ if (hasNestedFilters) {
17547
+ procedures = this.applyInMemoryFilters(procedures, filters);
17548
+ }
17512
17549
  const lastDoc = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
17513
17550
  console.log(`[PROCEDURE_SERVICE] Strategy 1 success: ${procedures.length} procedures`);
17514
17551
  if (procedures.length < (filters.pagination || 10)) {
@@ -17524,6 +17561,10 @@ var ProcedureService = class extends BaseService {
17524
17561
  console.log("[PROCEDURE_SERVICE] Strategy 2: Trying name field search");
17525
17562
  const searchTerm = filters.nameSearch.trim().toLowerCase();
17526
17563
  const constraints = getBaseConstraints();
17564
+ const hasNestedFilters = !!(filters.procedureTechnology || filters.procedureCategory || filters.procedureSubcategory);
17565
+ if (hasNestedFilters) {
17566
+ console.log("[PROCEDURE_SERVICE] Strategy 2: Has nested filters, will apply client-side after query");
17567
+ }
17527
17568
  constraints.push((0, import_firestore55.where)("name", ">=", searchTerm));
17528
17569
  constraints.push((0, import_firestore55.where)("name", "<=", searchTerm + "\uF8FF"));
17529
17570
  constraints.push((0, import_firestore55.orderBy)("name"));
@@ -17539,9 +17580,12 @@ var ProcedureService = class extends BaseService {
17539
17580
  constraints.push((0, import_firestore55.limit)(filters.pagination || 10));
17540
17581
  const q = (0, import_firestore55.query)((0, import_firestore55.collection)(this.db, PROCEDURES_COLLECTION), ...constraints);
17541
17582
  const querySnapshot = await (0, import_firestore55.getDocs)(q);
17542
- const procedures = querySnapshot.docs.map(
17583
+ let procedures = querySnapshot.docs.map(
17543
17584
  (doc45) => ({ ...doc45.data(), id: doc45.id })
17544
17585
  );
17586
+ if (hasNestedFilters) {
17587
+ procedures = this.applyInMemoryFilters(procedures, filters);
17588
+ }
17545
17589
  const lastDoc = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
17546
17590
  console.log(`[PROCEDURE_SERVICE] Strategy 2 success: ${procedures.length} procedures`);
17547
17591
  if (procedures.length < (filters.pagination || 10)) {
@@ -17554,9 +17598,47 @@ var ProcedureService = class extends BaseService {
17554
17598
  }
17555
17599
  try {
17556
17600
  console.log(
17557
- "[PROCEDURE_SERVICE] Strategy 3: Using createdAt orderBy with client-side filtering"
17601
+ "[PROCEDURE_SERVICE] Strategy 3: Using createdAt orderBy with client-side filtering",
17602
+ {
17603
+ procedureTechnology: filters.procedureTechnology,
17604
+ hasTechnologyFilter: !!filters.procedureTechnology
17605
+ }
17606
+ );
17607
+ const constraints = [];
17608
+ if (filters.isActive !== void 0) {
17609
+ constraints.push((0, import_firestore55.where)("isActive", "==", filters.isActive));
17610
+ } else {
17611
+ constraints.push((0, import_firestore55.where)("isActive", "==", true));
17612
+ }
17613
+ if (filters.procedureFamily) {
17614
+ constraints.push((0, import_firestore55.where)("family", "==", filters.procedureFamily));
17615
+ }
17616
+ if (filters.practitionerId) {
17617
+ constraints.push((0, import_firestore55.where)("practitionerId", "==", filters.practitionerId));
17618
+ }
17619
+ if (filters.clinicId) {
17620
+ constraints.push((0, import_firestore55.where)("clinicBranchId", "==", filters.clinicId));
17621
+ }
17622
+ if (filters.minPrice !== void 0) {
17623
+ constraints.push((0, import_firestore55.where)("price", ">=", filters.minPrice));
17624
+ }
17625
+ if (filters.maxPrice !== void 0) {
17626
+ constraints.push((0, import_firestore55.where)("price", "<=", filters.maxPrice));
17627
+ }
17628
+ if (filters.minRating !== void 0) {
17629
+ constraints.push((0, import_firestore55.where)("reviewInfo.averageRating", ">=", filters.minRating));
17630
+ }
17631
+ if (filters.maxRating !== void 0) {
17632
+ constraints.push((0, import_firestore55.where)("reviewInfo.averageRating", "<=", filters.maxRating));
17633
+ }
17634
+ if (filters.treatmentBenefits && filters.treatmentBenefits.length > 0) {
17635
+ const benefitIdsToMatch = filters.treatmentBenefits;
17636
+ constraints.push((0, import_firestore55.where)("treatmentBenefitIds", "array-contains-any", benefitIdsToMatch));
17637
+ }
17638
+ console.log(
17639
+ "[PROCEDURE_SERVICE] Strategy 3 Firestore constraints (nested filters excluded):",
17640
+ constraints.map((c) => c.fieldPath || "unknown")
17558
17641
  );
17559
- const constraints = getBaseConstraints();
17560
17642
  constraints.push((0, import_firestore55.orderBy)("createdAt", "desc"));
17561
17643
  if (filters.lastDoc) {
17562
17644
  if (typeof filters.lastDoc.data === "function") {
@@ -17573,7 +17655,20 @@ var ProcedureService = class extends BaseService {
17573
17655
  let procedures = querySnapshot.docs.map(
17574
17656
  (doc45) => ({ ...doc45.data(), id: doc45.id })
17575
17657
  );
17658
+ console.log("[PROCEDURE_SERVICE] Before applyInMemoryFilters (Strategy 3):", {
17659
+ procedureCount: procedures.length,
17660
+ procedureTechnology: filters.procedureTechnology,
17661
+ filtersObject: {
17662
+ procedureTechnology: filters.procedureTechnology,
17663
+ procedureFamily: filters.procedureFamily,
17664
+ procedureCategory: filters.procedureCategory,
17665
+ procedureSubcategory: filters.procedureSubcategory
17666
+ }
17667
+ });
17576
17668
  procedures = this.applyInMemoryFilters(procedures, filters);
17669
+ console.log("[PROCEDURE_SERVICE] After applyInMemoryFilters (Strategy 3):", {
17670
+ procedureCount: procedures.length
17671
+ });
17577
17672
  const lastDoc = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
17578
17673
  console.log(`[PROCEDURE_SERVICE] Strategy 3 success: ${procedures.length} procedures`);
17579
17674
  if (procedures.length < (filters.pagination || 10)) {
@@ -17624,6 +17719,12 @@ var ProcedureService = class extends BaseService {
17624
17719
  */
17625
17720
  applyInMemoryFilters(procedures, filters) {
17626
17721
  let filteredProcedures = [...procedures];
17722
+ console.log("[PROCEDURE_SERVICE] applyInMemoryFilters called:", {
17723
+ procedureCount: procedures.length,
17724
+ procedureTechnology: filters.procedureTechnology,
17725
+ hasTechnologyFilter: !!filters.procedureTechnology,
17726
+ allFilterKeys: Object.keys(filters).filter((k) => filters[k] !== void 0 && filters[k] !== null)
17727
+ });
17627
17728
  if (filters.nameSearch && filters.nameSearch.trim()) {
17628
17729
  const searchTerm = filters.nameSearch.trim().toLowerCase();
17629
17730
  filteredProcedures = filteredProcedures.filter((procedure) => {
@@ -17699,6 +17800,7 @@ var ProcedureService = class extends BaseService {
17699
17800
  );
17700
17801
  }
17701
17802
  if (filters.procedureTechnology) {
17803
+ const beforeCount = filteredProcedures.length;
17702
17804
  filteredProcedures = filteredProcedures.filter(
17703
17805
  (procedure) => {
17704
17806
  var _a;
@@ -17706,8 +17808,18 @@ var ProcedureService = class extends BaseService {
17706
17808
  }
17707
17809
  );
17708
17810
  console.log(
17709
- `[PROCEDURE_SERVICE] Applied technology filter, results: ${filteredProcedures.length}`
17811
+ `[PROCEDURE_SERVICE] Applied technology filter (${filters.procedureTechnology}), before: ${beforeCount}, after: ${filteredProcedures.length}`
17710
17812
  );
17813
+ if (beforeCount > filteredProcedures.length) {
17814
+ const filteredOut = procedures.filter((p) => {
17815
+ var _a;
17816
+ return ((_a = p.technology) == null ? void 0 : _a.id) !== filters.procedureTechnology;
17817
+ }).slice(0, 3).map((p) => {
17818
+ var _a;
17819
+ return { id: p.id, techId: (_a = p.technology) == null ? void 0 : _a.id, name: p.name };
17820
+ });
17821
+ console.log("[PROCEDURE_SERVICE] Filtered out sample procedures:", filteredOut);
17822
+ }
17711
17823
  }
17712
17824
  if (filters.practitionerId) {
17713
17825
  filteredProcedures = filteredProcedures.filter(
@@ -17976,6 +18088,60 @@ var ReviewService = class extends BaseService {
17976
18088
  constructor(db, auth, app) {
17977
18089
  super(db, auth, app);
17978
18090
  }
18091
+ /**
18092
+ * Helper function to convert Firestore Timestamps to Date objects
18093
+ * @param timestamp The timestamp to convert
18094
+ * @returns A JavaScript Date object or null
18095
+ */
18096
+ convertTimestamp(timestamp) {
18097
+ if (!timestamp) return /* @__PURE__ */ new Date();
18098
+ if (timestamp && timestamp.__isTimestamp === true && typeof timestamp.seconds === "number") {
18099
+ return new Date(timestamp.seconds * 1e3 + (timestamp.nanoseconds || 0) / 1e6);
18100
+ }
18101
+ if (timestamp && timestamp.toDate && typeof timestamp.toDate === "function") {
18102
+ return timestamp.toDate();
18103
+ }
18104
+ if (timestamp instanceof Date) {
18105
+ return timestamp;
18106
+ }
18107
+ if (typeof timestamp === "string" || typeof timestamp === "number") {
18108
+ const date = new Date(timestamp);
18109
+ if (!isNaN(date.getTime())) {
18110
+ return date;
18111
+ }
18112
+ }
18113
+ return /* @__PURE__ */ new Date();
18114
+ }
18115
+ /**
18116
+ * Converts a Firestore document to a Review object with proper date handling
18117
+ * @param docData The raw Firestore document data
18118
+ * @returns A Review object with properly converted dates
18119
+ */
18120
+ convertDocToReview(docData) {
18121
+ const review = docData;
18122
+ review.createdAt = this.convertTimestamp(docData.createdAt);
18123
+ review.updatedAt = this.convertTimestamp(docData.updatedAt);
18124
+ if (review.clinicReview) {
18125
+ review.clinicReview.createdAt = this.convertTimestamp(review.clinicReview.createdAt);
18126
+ review.clinicReview.updatedAt = this.convertTimestamp(review.clinicReview.updatedAt);
18127
+ }
18128
+ if (review.practitionerReview) {
18129
+ review.practitionerReview.createdAt = this.convertTimestamp(review.practitionerReview.createdAt);
18130
+ review.practitionerReview.updatedAt = this.convertTimestamp(review.practitionerReview.updatedAt);
18131
+ }
18132
+ if (review.procedureReview) {
18133
+ review.procedureReview.createdAt = this.convertTimestamp(review.procedureReview.createdAt);
18134
+ review.procedureReview.updatedAt = this.convertTimestamp(review.procedureReview.updatedAt);
18135
+ }
18136
+ if (review.extendedProcedureReviews && Array.isArray(review.extendedProcedureReviews)) {
18137
+ review.extendedProcedureReviews = review.extendedProcedureReviews.map((extReview) => ({
18138
+ ...extReview,
18139
+ createdAt: this.convertTimestamp(extReview.createdAt),
18140
+ updatedAt: this.convertTimestamp(extReview.updatedAt)
18141
+ }));
18142
+ }
18143
+ return review;
18144
+ }
17979
18145
  /**
17980
18146
  * Creates a new review
17981
18147
  * @param data - The review data to create
@@ -18119,7 +18285,7 @@ var ReviewService = class extends BaseService {
18119
18285
  console.log("\u274C ReviewService.getReview - Review not found:", reviewId);
18120
18286
  return null;
18121
18287
  }
18122
- const review = { ...docSnap.data(), id: reviewId };
18288
+ const review = { ...this.convertDocToReview(docSnap.data()), id: reviewId };
18123
18289
  try {
18124
18290
  const appointmentDoc = await (0, import_firestore56.getDoc)(
18125
18291
  (0, import_firestore56.doc)(this.db, APPOINTMENTS_COLLECTION, review.appointmentId)
@@ -18184,7 +18350,7 @@ var ReviewService = class extends BaseService {
18184
18350
  async getReviewsByPatient(patientId) {
18185
18351
  const q = (0, import_firestore56.query)((0, import_firestore56.collection)(this.db, REVIEWS_COLLECTION), (0, import_firestore56.where)("patientId", "==", patientId));
18186
18352
  const snapshot = await (0, import_firestore56.getDocs)(q);
18187
- const reviews = snapshot.docs.map((doc45) => doc45.data());
18353
+ const reviews = snapshot.docs.map((doc45) => this.convertDocToReview(doc45.data()));
18188
18354
  const enhancedReviews = await Promise.all(
18189
18355
  reviews.map(async (review) => {
18190
18356
  try {
@@ -18239,8 +18405,8 @@ var ReviewService = class extends BaseService {
18239
18405
  );
18240
18406
  const snapshot = await (0, import_firestore56.getDocs)(q);
18241
18407
  const reviews = snapshot.docs.map((doc45) => {
18242
- const data = doc45.data();
18243
- return { ...data, id: doc45.id };
18408
+ const review = this.convertDocToReview(doc45.data());
18409
+ return { ...review, id: doc45.id };
18244
18410
  });
18245
18411
  console.log("\u{1F50D} ReviewService.getReviewsByClinic - Found reviews before enhancement:", {
18246
18412
  clinicId,
@@ -18315,8 +18481,8 @@ var ReviewService = class extends BaseService {
18315
18481
  );
18316
18482
  const snapshot = await (0, import_firestore56.getDocs)(q);
18317
18483
  const reviews = snapshot.docs.map((doc45) => {
18318
- const data = doc45.data();
18319
- return { ...data, id: doc45.id };
18484
+ const review = this.convertDocToReview(doc45.data());
18485
+ return { ...review, id: doc45.id };
18320
18486
  });
18321
18487
  console.log("\u{1F50D} ReviewService.getReviewsByPractitioner - Found reviews before enhancement:", {
18322
18488
  practitionerId,
@@ -18462,7 +18628,7 @@ var ReviewService = class extends BaseService {
18462
18628
  if (snapshot.empty) {
18463
18629
  return null;
18464
18630
  }
18465
- return snapshot.docs[0].data();
18631
+ return this.convertDocToReview(snapshot.docs[0].data());
18466
18632
  }
18467
18633
  /**
18468
18634
  * Deletes a review