@blackcode_sa/metaestetics-api 1.12.21 → 1.12.22

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
@@ -16491,7 +16491,17 @@ var ReviewService = class extends BaseService {
16491
16491
  * @returns The created review
16492
16492
  */
16493
16493
  async createReview(data, appointmentId) {
16494
+ var _a, _b, _c, _d, _e, _f;
16494
16495
  try {
16496
+ console.log("\u{1F50D} ReviewService.createReview - Input data:", {
16497
+ appointmentId,
16498
+ hasClinicReview: !!data.clinicReview,
16499
+ hasPractitionerReview: !!data.practitionerReview,
16500
+ hasProcedureReview: !!data.procedureReview,
16501
+ practitionerId: (_a = data.practitionerReview) == null ? void 0 : _a.practitionerId,
16502
+ clinicId: (_b = data.clinicReview) == null ? void 0 : _b.clinicId,
16503
+ procedureId: (_c = data.procedureReview) == null ? void 0 : _c.procedureId
16504
+ });
16495
16505
  const validatedData = createReviewSchema.parse(data);
16496
16506
  const ratings = [];
16497
16507
  if (data.clinicReview) {
@@ -16564,6 +16574,12 @@ var ReviewService = class extends BaseService {
16564
16574
  createdAt: serverTimestamp26(),
16565
16575
  updatedAt: serverTimestamp26()
16566
16576
  });
16577
+ console.log("\u2705 ReviewService.createReview - Review saved to Firestore:", {
16578
+ reviewId,
16579
+ practitionerId: (_d = review.practitionerReview) == null ? void 0 : _d.practitionerId,
16580
+ clinicId: (_e = review.clinicReview) == null ? void 0 : _e.clinicId,
16581
+ procedureId: (_f = review.procedureReview) == null ? void 0 : _f.procedureId
16582
+ });
16567
16583
  return review;
16568
16584
  } catch (error) {
16569
16585
  if (error instanceof z26.ZodError) {
@@ -16573,69 +16589,332 @@ var ReviewService = class extends BaseService {
16573
16589
  }
16574
16590
  }
16575
16591
  /**
16576
- * Gets a review by ID
16592
+ * Gets a review by ID with enhanced entity names
16577
16593
  * @param reviewId The ID of the review to get
16578
- * @returns The review if found, null otherwise
16594
+ * @returns The review with entity names if found, null otherwise
16579
16595
  */
16580
16596
  async getReview(reviewId) {
16597
+ var _a, _b, _c;
16598
+ console.log("\u{1F50D} ReviewService.getReview - Getting review:", reviewId);
16581
16599
  const docRef = doc31(this.db, REVIEWS_COLLECTION, reviewId);
16582
16600
  const docSnap = await getDoc33(docRef);
16583
16601
  if (!docSnap.exists()) {
16602
+ console.log("\u274C ReviewService.getReview - Review not found:", reviewId);
16584
16603
  return null;
16585
16604
  }
16586
- return docSnap.data();
16605
+ const review = { ...docSnap.data(), id: reviewId };
16606
+ try {
16607
+ const appointmentDoc = await getDoc33(
16608
+ doc31(this.db, APPOINTMENTS_COLLECTION, review.appointmentId)
16609
+ );
16610
+ if (appointmentDoc.exists()) {
16611
+ const appointment = appointmentDoc.data();
16612
+ const enhancedReview = { ...review };
16613
+ if (enhancedReview.clinicReview && appointment.clinicInfo) {
16614
+ enhancedReview.clinicReview = {
16615
+ ...enhancedReview.clinicReview,
16616
+ clinicName: appointment.clinicInfo.name
16617
+ };
16618
+ }
16619
+ if (enhancedReview.practitionerReview && appointment.practitionerInfo) {
16620
+ enhancedReview.practitionerReview = {
16621
+ ...enhancedReview.practitionerReview,
16622
+ practitionerName: appointment.practitionerInfo.name
16623
+ };
16624
+ }
16625
+ if (enhancedReview.procedureReview && appointment.procedureInfo) {
16626
+ enhancedReview.procedureReview = {
16627
+ ...enhancedReview.procedureReview,
16628
+ procedureName: appointment.procedureInfo.name
16629
+ };
16630
+ }
16631
+ if (appointment.patientInfo) {
16632
+ enhancedReview.patientName = appointment.patientInfo.fullName;
16633
+ }
16634
+ console.log("\u2705 ReviewService.getReview - Enhanced review:", {
16635
+ reviewId,
16636
+ hasEntityNames: !!(((_a = enhancedReview.clinicReview) == null ? void 0 : _a.clinicName) || ((_b = enhancedReview.practitionerReview) == null ? void 0 : _b.practitionerName) || ((_c = enhancedReview.procedureReview) == null ? void 0 : _c.procedureName) || enhancedReview.patientName)
16637
+ });
16638
+ return enhancedReview;
16639
+ }
16640
+ console.log("\u26A0\uFE0F ReviewService.getReview - Appointment not found for review:", reviewId);
16641
+ return review;
16642
+ } catch (error) {
16643
+ console.warn(`Failed to enhance review ${reviewId} with entity names:`, error);
16644
+ return review;
16645
+ }
16587
16646
  }
16588
16647
  /**
16589
- * Gets all reviews for a specific patient
16648
+ * Gets all reviews for a specific patient with enhanced entity names
16590
16649
  * @param patientId The ID of the patient
16591
- * @returns Array of reviews for the patient
16650
+ * @returns Array of reviews for the patient with clinic, practitioner, and procedure names
16592
16651
  */
16593
16652
  async getReviewsByPatient(patientId) {
16594
- const q = query31(
16595
- collection31(this.db, REVIEWS_COLLECTION),
16596
- where31("patientId", "==", patientId)
16597
- );
16653
+ const q = query31(collection31(this.db, REVIEWS_COLLECTION), where31("patientId", "==", patientId));
16598
16654
  const snapshot = await getDocs31(q);
16599
- return snapshot.docs.map((doc38) => doc38.data());
16655
+ const reviews = snapshot.docs.map((doc38) => doc38.data());
16656
+ const enhancedReviews = await Promise.all(
16657
+ reviews.map(async (review) => {
16658
+ try {
16659
+ const appointmentDoc = await getDoc33(
16660
+ doc31(this.db, APPOINTMENTS_COLLECTION, review.appointmentId)
16661
+ );
16662
+ if (appointmentDoc.exists()) {
16663
+ const appointment = appointmentDoc.data();
16664
+ const enhancedReview = { ...review };
16665
+ if (enhancedReview.clinicReview && appointment.clinicInfo) {
16666
+ enhancedReview.clinicReview = {
16667
+ ...enhancedReview.clinicReview,
16668
+ clinicName: appointment.clinicInfo.name
16669
+ };
16670
+ }
16671
+ if (enhancedReview.practitionerReview && appointment.practitionerInfo) {
16672
+ enhancedReview.practitionerReview = {
16673
+ ...enhancedReview.practitionerReview,
16674
+ practitionerName: appointment.practitionerInfo.name
16675
+ };
16676
+ }
16677
+ if (enhancedReview.procedureReview && appointment.procedureInfo) {
16678
+ enhancedReview.procedureReview = {
16679
+ ...enhancedReview.procedureReview,
16680
+ procedureName: appointment.procedureInfo.name
16681
+ };
16682
+ }
16683
+ if (appointment.patientInfo) {
16684
+ enhancedReview.patientName = appointment.patientInfo.fullName;
16685
+ }
16686
+ return enhancedReview;
16687
+ }
16688
+ return review;
16689
+ } catch (error) {
16690
+ console.warn(`Failed to enhance review ${review.id} with entity names:`, error);
16691
+ return review;
16692
+ }
16693
+ })
16694
+ );
16695
+ return enhancedReviews;
16600
16696
  }
16601
16697
  /**
16602
- * Gets all reviews for a specific clinic
16698
+ * Gets all reviews for a specific clinic with enhanced entity names
16603
16699
  * @param clinicId The ID of the clinic
16604
- * @returns Array of reviews containing clinic reviews
16700
+ * @returns Array of reviews containing clinic reviews with clinic, practitioner, and procedure names
16605
16701
  */
16606
16702
  async getReviewsByClinic(clinicId) {
16703
+ console.log("\u{1F50D} ReviewService.getReviewsByClinic - Querying for clinic:", clinicId);
16607
16704
  const q = query31(
16608
16705
  collection31(this.db, REVIEWS_COLLECTION),
16609
16706
  where31("clinicReview.clinicId", "==", clinicId)
16610
16707
  );
16611
16708
  const snapshot = await getDocs31(q);
16612
- return snapshot.docs.map((doc38) => doc38.data());
16709
+ const reviews = snapshot.docs.map((doc38) => {
16710
+ const data = doc38.data();
16711
+ return { ...data, id: doc38.id };
16712
+ });
16713
+ console.log("\u{1F50D} ReviewService.getReviewsByClinic - Found reviews before enhancement:", {
16714
+ clinicId,
16715
+ reviewCount: reviews.length,
16716
+ reviewIds: reviews.map((r) => r.id)
16717
+ });
16718
+ const enhancedReviews = await Promise.all(
16719
+ reviews.map(async (review) => {
16720
+ try {
16721
+ const appointmentDoc = await getDoc33(
16722
+ doc31(this.db, APPOINTMENTS_COLLECTION, review.appointmentId)
16723
+ );
16724
+ if (appointmentDoc.exists()) {
16725
+ const appointment = appointmentDoc.data();
16726
+ const enhancedReview = { ...review };
16727
+ if (enhancedReview.clinicReview && appointment.clinicInfo) {
16728
+ enhancedReview.clinicReview = {
16729
+ ...enhancedReview.clinicReview,
16730
+ clinicName: appointment.clinicInfo.name
16731
+ };
16732
+ }
16733
+ if (enhancedReview.practitionerReview && appointment.practitionerInfo) {
16734
+ enhancedReview.practitionerReview = {
16735
+ ...enhancedReview.practitionerReview,
16736
+ practitionerName: appointment.practitionerInfo.name
16737
+ };
16738
+ }
16739
+ if (enhancedReview.procedureReview && appointment.procedureInfo) {
16740
+ enhancedReview.procedureReview = {
16741
+ ...enhancedReview.procedureReview,
16742
+ procedureName: appointment.procedureInfo.name
16743
+ };
16744
+ }
16745
+ if (appointment.patientInfo) {
16746
+ enhancedReview.patientName = appointment.patientInfo.fullName;
16747
+ }
16748
+ return enhancedReview;
16749
+ }
16750
+ return review;
16751
+ } catch (error) {
16752
+ console.warn(`Failed to enhance review ${review.id} with entity names:`, error);
16753
+ return review;
16754
+ }
16755
+ })
16756
+ );
16757
+ console.log("\u2705 ReviewService.getReviewsByClinic - Enhanced reviews:", {
16758
+ clinicId,
16759
+ reviewCount: enhancedReviews.length,
16760
+ reviewIds: enhancedReviews.map((r) => r.id),
16761
+ hasEntityNames: enhancedReviews.some(
16762
+ (r) => {
16763
+ var _a, _b, _c;
16764
+ return ((_a = r.clinicReview) == null ? void 0 : _a.clinicName) || ((_b = r.practitionerReview) == null ? void 0 : _b.practitionerName) || ((_c = r.procedureReview) == null ? void 0 : _c.procedureName) || r.patientName;
16765
+ }
16766
+ )
16767
+ });
16768
+ return enhancedReviews;
16613
16769
  }
16614
16770
  /**
16615
- * Gets all reviews for a specific practitioner
16771
+ * Gets all reviews for a specific practitioner with enhanced entity names
16616
16772
  * @param practitionerId The ID of the practitioner
16617
- * @returns Array of reviews containing practitioner reviews
16773
+ * @returns Array of reviews containing practitioner reviews with clinic, practitioner, and procedure names
16618
16774
  */
16619
16775
  async getReviewsByPractitioner(practitionerId) {
16776
+ console.log(
16777
+ "\u{1F50D} ReviewService.getReviewsByPractitioner - Querying for practitioner:",
16778
+ practitionerId
16779
+ );
16620
16780
  const q = query31(
16621
16781
  collection31(this.db, REVIEWS_COLLECTION),
16622
16782
  where31("practitionerReview.practitionerId", "==", practitionerId)
16623
16783
  );
16624
16784
  const snapshot = await getDocs31(q);
16625
- return snapshot.docs.map((doc38) => doc38.data());
16785
+ const reviews = snapshot.docs.map((doc38) => {
16786
+ const data = doc38.data();
16787
+ return { ...data, id: doc38.id };
16788
+ });
16789
+ console.log("\u{1F50D} ReviewService.getReviewsByPractitioner - Found reviews before enhancement:", {
16790
+ practitionerId,
16791
+ reviewCount: reviews.length,
16792
+ reviewIds: reviews.map((r) => r.id)
16793
+ });
16794
+ const enhancedReviews = await Promise.all(
16795
+ reviews.map(async (review) => {
16796
+ try {
16797
+ const appointmentDoc = await getDoc33(
16798
+ doc31(this.db, APPOINTMENTS_COLLECTION, review.appointmentId)
16799
+ );
16800
+ if (appointmentDoc.exists()) {
16801
+ const appointment = appointmentDoc.data();
16802
+ const enhancedReview = { ...review };
16803
+ if (enhancedReview.clinicReview && appointment.clinicInfo) {
16804
+ enhancedReview.clinicReview = {
16805
+ ...enhancedReview.clinicReview,
16806
+ clinicName: appointment.clinicInfo.name
16807
+ };
16808
+ }
16809
+ if (enhancedReview.practitionerReview && appointment.practitionerInfo) {
16810
+ enhancedReview.practitionerReview = {
16811
+ ...enhancedReview.practitionerReview,
16812
+ practitionerName: appointment.practitionerInfo.name
16813
+ };
16814
+ }
16815
+ if (enhancedReview.procedureReview && appointment.procedureInfo) {
16816
+ enhancedReview.procedureReview = {
16817
+ ...enhancedReview.procedureReview,
16818
+ procedureName: appointment.procedureInfo.name
16819
+ };
16820
+ }
16821
+ if (appointment.patientInfo) {
16822
+ enhancedReview.patientName = appointment.patientInfo.fullName;
16823
+ }
16824
+ return enhancedReview;
16825
+ }
16826
+ return review;
16827
+ } catch (error) {
16828
+ console.warn(`Failed to enhance review ${review.id} with entity names:`, error);
16829
+ return review;
16830
+ }
16831
+ })
16832
+ );
16833
+ console.log("\u2705 ReviewService.getReviewsByPractitioner - Enhanced reviews:", {
16834
+ practitionerId,
16835
+ reviewCount: enhancedReviews.length,
16836
+ reviewIds: enhancedReviews.map((r) => r.id),
16837
+ hasEntityNames: enhancedReviews.some(
16838
+ (r) => {
16839
+ var _a, _b, _c;
16840
+ return ((_a = r.clinicReview) == null ? void 0 : _a.clinicName) || ((_b = r.practitionerReview) == null ? void 0 : _b.practitionerName) || ((_c = r.procedureReview) == null ? void 0 : _c.procedureName);
16841
+ }
16842
+ )
16843
+ });
16844
+ return enhancedReviews;
16626
16845
  }
16627
16846
  /**
16628
- * Gets all reviews for a specific procedure
16847
+ * Gets all reviews for a specific procedure with enhanced entity names
16629
16848
  * @param procedureId The ID of the procedure
16630
- * @returns Array of reviews containing procedure reviews
16849
+ * @returns Array of reviews containing procedure reviews with clinic, practitioner, and procedure names
16631
16850
  */
16632
16851
  async getReviewsByProcedure(procedureId) {
16852
+ console.log("\u{1F50D} ReviewService.getReviewsByProcedure - Querying for procedure:", procedureId);
16633
16853
  const q = query31(
16634
16854
  collection31(this.db, REVIEWS_COLLECTION),
16635
16855
  where31("procedureReview.procedureId", "==", procedureId)
16636
16856
  );
16637
16857
  const snapshot = await getDocs31(q);
16638
- return snapshot.docs.map((doc38) => doc38.data());
16858
+ const reviews = snapshot.docs.map((doc38) => {
16859
+ const data = doc38.data();
16860
+ return { ...data, id: doc38.id };
16861
+ });
16862
+ console.log("\u{1F50D} ReviewService.getReviewsByProcedure - Found reviews before enhancement:", {
16863
+ procedureId,
16864
+ reviewCount: reviews.length,
16865
+ reviewIds: reviews.map((r) => r.id)
16866
+ });
16867
+ const enhancedReviews = await Promise.all(
16868
+ reviews.map(async (review) => {
16869
+ try {
16870
+ const appointmentDoc = await getDoc33(
16871
+ doc31(this.db, APPOINTMENTS_COLLECTION, review.appointmentId)
16872
+ );
16873
+ if (appointmentDoc.exists()) {
16874
+ const appointment = appointmentDoc.data();
16875
+ const enhancedReview = { ...review };
16876
+ if (enhancedReview.clinicReview && appointment.clinicInfo) {
16877
+ enhancedReview.clinicReview = {
16878
+ ...enhancedReview.clinicReview,
16879
+ clinicName: appointment.clinicInfo.name
16880
+ };
16881
+ }
16882
+ if (enhancedReview.practitionerReview && appointment.practitionerInfo) {
16883
+ enhancedReview.practitionerReview = {
16884
+ ...enhancedReview.practitionerReview,
16885
+ practitionerName: appointment.practitionerInfo.name
16886
+ };
16887
+ }
16888
+ if (enhancedReview.procedureReview && appointment.procedureInfo) {
16889
+ enhancedReview.procedureReview = {
16890
+ ...enhancedReview.procedureReview,
16891
+ procedureName: appointment.procedureInfo.name
16892
+ };
16893
+ }
16894
+ if (appointment.patientInfo) {
16895
+ enhancedReview.patientName = appointment.patientInfo.fullName;
16896
+ }
16897
+ return enhancedReview;
16898
+ }
16899
+ return review;
16900
+ } catch (error) {
16901
+ console.warn(`Failed to enhance review ${review.id} with entity names:`, error);
16902
+ return review;
16903
+ }
16904
+ })
16905
+ );
16906
+ console.log("\u2705 ReviewService.getReviewsByProcedure - Enhanced reviews:", {
16907
+ procedureId,
16908
+ reviewCount: enhancedReviews.length,
16909
+ reviewIds: enhancedReviews.map((r) => r.id),
16910
+ hasEntityNames: enhancedReviews.some(
16911
+ (r) => {
16912
+ var _a, _b, _c;
16913
+ return ((_a = r.clinicReview) == null ? void 0 : _a.clinicName) || ((_b = r.practitionerReview) == null ? void 0 : _b.practitionerName) || ((_c = r.procedureReview) == null ? void 0 : _c.procedureName) || r.patientName;
16914
+ }
16915
+ )
16916
+ });
16917
+ return enhancedReviews;
16639
16918
  }
16640
16919
  /**
16641
16920
  * Gets all reviews for a specific appointment
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@blackcode_sa/metaestetics-api",
3
3
  "private": false,
4
- "version": "1.12.21",
4
+ "version": "1.12.22",
5
5
  "description": "Firebase authentication service with anonymous upgrade support",
6
6
  "main": "dist/index.js",
7
7
  "module": "dist/index.mjs",
@@ -0,0 +1,129 @@
1
+ # Reviews Service - Enhanced with Entity Names
2
+
3
+ ## Overview
4
+
5
+ The Reviews Service has been enhanced to automatically include entity names (clinic, practitioner, procedure, and patient names) in all review responses. This eliminates the need for frontend applications to make additional API calls to fetch entity details.
6
+
7
+ ## Enhanced Methods
8
+
9
+ All review retrieval methods now include entity names from associated appointments:
10
+
11
+ ### 1. `getReview(reviewId: string)`
12
+ - **Enhanced**: ✅ Returns single review with entity names
13
+ - **Entity Names**: Clinic name, practitioner name, procedure name, patient name
14
+ - **Source**: Fetched from associated appointment data
15
+
16
+ ### 2. `getReviewsByPatient(patientId: string)`
17
+ - **Enhanced**: ✅ Returns patient reviews with entity names
18
+ - **Entity Names**: Clinic name, practitioner name, procedure name, patient name
19
+ - **Use Case**: Patient app - "My Reviews" screen
20
+
21
+ ### 3. `getReviewsByPractitioner(practitionerId: string)`
22
+ - **Enhanced**: ✅ Returns practitioner reviews with entity names
23
+ - **Entity Names**: Clinic name, practitioner name, procedure name, patient name
24
+ - **Use Case**: Doctor app - "Reviews" screen
25
+
26
+ ### 4. `getReviewsByClinic(clinicId: string)`
27
+ - **Enhanced**: ✅ Returns clinic reviews with entity names
28
+ - **Entity Names**: Clinic name, practitioner name, procedure name, patient name
29
+ - **Use Case**: Clinic dashboard - "Reviews" section
30
+
31
+ ### 5. `getReviewsByProcedure(procedureId: string)`
32
+ - **Enhanced**: ✅ Returns procedure reviews with entity names
33
+ - **Entity Names**: Clinic name, practitioner name, procedure name, patient name
34
+ - **Use Case**: Procedure analytics and reporting
35
+
36
+ ## Enhanced Review Structure
37
+
38
+ ```typescript
39
+ interface Review {
40
+ id: string;
41
+ appointmentId: string;
42
+ patientId: string;
43
+ patientName?: string; // 🆕 Enhanced field
44
+ createdAt: Date;
45
+ updatedAt: Date;
46
+ clinicReview?: {
47
+ // ... existing fields
48
+ clinicName?: string; // 🆕 Enhanced field
49
+ };
50
+ practitionerReview?: {
51
+ // ... existing fields
52
+ practitionerName?: string; // 🆕 Enhanced field
53
+ };
54
+ procedureReview?: {
55
+ // ... existing fields
56
+ procedureName?: string; // 🆕 Enhanced field
57
+ };
58
+ overallComment: string;
59
+ overallRating: number;
60
+ }
61
+ ```
62
+
63
+ ## Data Sources
64
+
65
+ Entity names are fetched from the associated appointment's aggregated information:
66
+
67
+ - **Clinic Name**: `appointment.clinicInfo.name`
68
+ - **Practitioner Name**: `appointment.practitionerInfo.name`
69
+ - **Procedure Name**: `appointment.procedureInfo.name`
70
+ - **Patient Name**: `appointment.patientInfo.fullName`
71
+
72
+ ## Error Handling
73
+
74
+ - If appointment is not found, review is returned without enhancement
75
+ - Individual enhancement failures are logged but don't break the entire operation
76
+ - Graceful fallback ensures API reliability
77
+
78
+ ## Logging
79
+
80
+ Enhanced logging provides detailed information about:
81
+ - Query parameters
82
+ - Number of reviews found
83
+ - Enhancement success/failure
84
+ - Entity names availability
85
+
86
+ ## Performance Considerations
87
+
88
+ - Each review requires one additional Firestore read for appointment data
89
+ - Enhancement is performed in parallel for multiple reviews
90
+ - Consider caching strategies for high-volume applications
91
+
92
+ ## Migration Notes
93
+
94
+ - **Backward Compatible**: Existing code continues to work
95
+ - **Optional Fields**: All enhanced fields are optional
96
+ - **No Breaking Changes**: API signature remains the same
97
+
98
+ ## Usage Examples
99
+
100
+ ### Doctor App - Reviews Screen
101
+ ```typescript
102
+ const reviews = await reviewService.getReviewsByPractitioner(practitionerId);
103
+ // Now includes practitioner names, clinic names, procedure names, and patient names
104
+ ```
105
+
106
+ ### Patient App - My Reviews
107
+ ```typescript
108
+ const reviews = await reviewService.getReviewsByPatient(patientId);
109
+ // Now includes all entity names for better UX
110
+ ```
111
+
112
+ ### Clinic Dashboard
113
+ ```typescript
114
+ const reviews = await reviewService.getReviewsByClinic(clinicId);
115
+ // Now includes practitioner and procedure names for each review
116
+ ```
117
+
118
+ ## Testing
119
+
120
+ All enhanced methods include comprehensive logging for debugging:
121
+ - Input parameters
122
+ - Query results
123
+ - Enhancement status
124
+ - Entity name availability
125
+
126
+ Monitor logs with:
127
+ ```bash
128
+ firebase functions:log --only reviewService
129
+ ```