@blackcode_sa/metaestetics-api 1.13.4 → 1.13.5

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.
Files changed (293) hide show
  1. package/dist/admin/index.d.mts +15 -28
  2. package/dist/admin/index.d.ts +15 -28
  3. package/dist/index.d.mts +16 -29
  4. package/dist/index.d.ts +16 -29
  5. package/dist/index.js +1 -0
  6. package/dist/index.mjs +1 -0
  7. package/package.json +121 -119
  8. package/src/__mocks__/firstore.ts +10 -10
  9. package/src/admin/aggregation/README.md +79 -79
  10. package/src/admin/aggregation/appointment/README.md +128 -128
  11. package/src/admin/aggregation/appointment/appointment.aggregation.service.ts +1984 -1984
  12. package/src/admin/aggregation/appointment/index.ts +1 -1
  13. package/src/admin/aggregation/clinic/README.md +52 -52
  14. package/src/admin/aggregation/clinic/clinic.aggregation.service.ts +703 -703
  15. package/src/admin/aggregation/clinic/index.ts +1 -1
  16. package/src/admin/aggregation/forms/README.md +13 -13
  17. package/src/admin/aggregation/forms/filled-forms.aggregation.service.ts +322 -322
  18. package/src/admin/aggregation/forms/index.ts +1 -1
  19. package/src/admin/aggregation/index.ts +8 -8
  20. package/src/admin/aggregation/patient/README.md +27 -27
  21. package/src/admin/aggregation/patient/index.ts +1 -1
  22. package/src/admin/aggregation/patient/patient.aggregation.service.ts +141 -141
  23. package/src/admin/aggregation/practitioner/README.md +42 -42
  24. package/src/admin/aggregation/practitioner/index.ts +1 -1
  25. package/src/admin/aggregation/practitioner/practitioner.aggregation.service.ts +433 -433
  26. package/src/admin/aggregation/practitioner-invite/index.ts +1 -1
  27. package/src/admin/aggregation/practitioner-invite/practitioner-invite.aggregation.service.ts +961 -961
  28. package/src/admin/aggregation/procedure/README.md +43 -43
  29. package/src/admin/aggregation/procedure/index.ts +1 -1
  30. package/src/admin/aggregation/procedure/procedure.aggregation.service.ts +702 -702
  31. package/src/admin/aggregation/reviews/index.ts +1 -1
  32. package/src/admin/aggregation/reviews/reviews.aggregation.service.ts +689 -689
  33. package/src/admin/analytics/analytics.admin.service.ts +278 -278
  34. package/src/admin/analytics/index.ts +2 -2
  35. package/src/admin/booking/README.md +125 -125
  36. package/src/admin/booking/booking.admin.ts +1037 -1037
  37. package/src/admin/booking/booking.calculator.ts +712 -712
  38. package/src/admin/booking/booking.types.ts +59 -59
  39. package/src/admin/booking/index.ts +3 -3
  40. package/src/admin/booking/timezones-problem.md +185 -185
  41. package/src/admin/calendar/README.md +7 -7
  42. package/src/admin/calendar/calendar.admin.service.ts +345 -345
  43. package/src/admin/calendar/index.ts +1 -1
  44. package/src/admin/documentation-templates/document-manager.admin.ts +260 -260
  45. package/src/admin/documentation-templates/index.ts +1 -1
  46. package/src/admin/free-consultation/free-consultation-utils.admin.ts +148 -148
  47. package/src/admin/free-consultation/index.ts +1 -1
  48. package/src/admin/index.ts +81 -81
  49. package/src/admin/logger/index.ts +78 -78
  50. package/src/admin/mailing/README.md +95 -95
  51. package/src/admin/mailing/appointment/appointment.mailing.service.ts +732 -732
  52. package/src/admin/mailing/appointment/index.ts +1 -1
  53. package/src/admin/mailing/appointment/templates/patient/appointment-confirmed.html +40 -40
  54. package/src/admin/mailing/base.mailing.service.ts +208 -208
  55. package/src/admin/mailing/index.ts +3 -3
  56. package/src/admin/mailing/practitionerInvite/existing-practitioner-invite.mailing.ts +611 -611
  57. package/src/admin/mailing/practitionerInvite/index.ts +2 -2
  58. package/src/admin/mailing/practitionerInvite/practitionerInvite.mailing.ts +395 -395
  59. package/src/admin/mailing/practitionerInvite/templates/existing-practitioner-invitation.template.ts +155 -155
  60. package/src/admin/mailing/practitionerInvite/templates/invitation.template.ts +101 -101
  61. package/src/admin/mailing/practitionerInvite/templates/invite-accepted-notification.template.ts +228 -228
  62. package/src/admin/mailing/practitionerInvite/templates/invite-rejected-notification.template.ts +242 -242
  63. package/src/admin/notifications/index.ts +1 -1
  64. package/src/admin/notifications/notifications.admin.ts +710 -710
  65. package/src/admin/requirements/README.md +128 -128
  66. package/src/admin/requirements/index.ts +1 -1
  67. package/src/admin/requirements/patient-requirements.admin.service.ts +475 -475
  68. package/src/admin/users/index.ts +1 -1
  69. package/src/admin/users/user-profile.admin.ts +405 -405
  70. package/src/backoffice/constants/certification.constants.ts +13 -13
  71. package/src/backoffice/constants/index.ts +1 -1
  72. package/src/backoffice/errors/backoffice.errors.ts +181 -181
  73. package/src/backoffice/errors/index.ts +1 -1
  74. package/src/backoffice/expo-safe/README.md +26 -26
  75. package/src/backoffice/expo-safe/index.ts +41 -41
  76. package/src/backoffice/index.ts +5 -5
  77. package/src/backoffice/services/FIXES_README.md +102 -102
  78. package/src/backoffice/services/README.md +57 -57
  79. package/src/backoffice/services/analytics.service.proposal.md +863 -863
  80. package/src/backoffice/services/analytics.service.summary.md +143 -143
  81. package/src/backoffice/services/brand.service.ts +256 -256
  82. package/src/backoffice/services/category.service.ts +384 -384
  83. package/src/backoffice/services/constants.service.ts +385 -385
  84. package/src/backoffice/services/documentation-template.service.ts +202 -202
  85. package/src/backoffice/services/index.ts +10 -10
  86. package/src/backoffice/services/migrate-products.ts +116 -116
  87. package/src/backoffice/services/product.service.ts +553 -553
  88. package/src/backoffice/services/requirement.service.ts +235 -235
  89. package/src/backoffice/services/subcategory.service.ts +461 -461
  90. package/src/backoffice/services/technology.service.ts +1151 -1151
  91. package/src/backoffice/types/README.md +12 -12
  92. package/src/backoffice/types/admin-constants.types.ts +69 -69
  93. package/src/backoffice/types/brand.types.ts +29 -29
  94. package/src/backoffice/types/category.types.ts +67 -67
  95. package/src/backoffice/types/documentation-templates.types.ts +28 -28
  96. package/src/backoffice/types/index.ts +10 -10
  97. package/src/backoffice/types/procedure-product.types.ts +38 -38
  98. package/src/backoffice/types/product.types.ts +240 -240
  99. package/src/backoffice/types/requirement.types.ts +63 -63
  100. package/src/backoffice/types/static/README.md +18 -18
  101. package/src/backoffice/types/static/blocking-condition.types.ts +21 -21
  102. package/src/backoffice/types/static/certification.types.ts +37 -37
  103. package/src/backoffice/types/static/contraindication.types.ts +19 -19
  104. package/src/backoffice/types/static/index.ts +6 -6
  105. package/src/backoffice/types/static/pricing.types.ts +16 -16
  106. package/src/backoffice/types/static/procedure-family.types.ts +14 -14
  107. package/src/backoffice/types/static/treatment-benefit.types.ts +22 -22
  108. package/src/backoffice/types/subcategory.types.ts +34 -34
  109. package/src/backoffice/types/technology.types.ts +168 -168
  110. package/src/backoffice/validations/index.ts +1 -1
  111. package/src/backoffice/validations/schemas.ts +164 -164
  112. package/src/config/__mocks__/firebase.ts +99 -99
  113. package/src/config/firebase.ts +78 -78
  114. package/src/config/index.ts +9 -9
  115. package/src/errors/auth.error.ts +6 -6
  116. package/src/errors/auth.errors.ts +200 -200
  117. package/src/errors/clinic.errors.ts +32 -32
  118. package/src/errors/firebase.errors.ts +47 -47
  119. package/src/errors/user.errors.ts +99 -99
  120. package/src/index.backup.ts +407 -407
  121. package/src/index.ts +6 -6
  122. package/src/locales/en.ts +31 -31
  123. package/src/recommender/admin/index.ts +1 -1
  124. package/src/recommender/admin/services/recommender.service.admin.ts +5 -5
  125. package/src/recommender/front/index.ts +1 -1
  126. package/src/recommender/front/services/onboarding.service.ts +5 -5
  127. package/src/recommender/front/services/recommender.service.ts +3 -3
  128. package/src/recommender/index.ts +1 -1
  129. package/src/services/PATIENTAUTH.MD +197 -197
  130. package/src/services/README.md +106 -106
  131. package/src/services/__tests__/auth/auth.mock.test.ts +17 -17
  132. package/src/services/__tests__/auth/auth.setup.ts +293 -293
  133. package/src/services/__tests__/auth.service.test.ts +346 -346
  134. package/src/services/__tests__/base.service.test.ts +77 -77
  135. package/src/services/__tests__/user.service.test.ts +528 -528
  136. package/src/services/analytics/ARCHITECTURE.md +199 -199
  137. package/src/services/analytics/CLOUD_FUNCTIONS.md +225 -225
  138. package/src/services/analytics/GROUPED_ANALYTICS.md +501 -501
  139. package/src/services/analytics/QUICK_START.md +393 -393
  140. package/src/services/analytics/README.md +304 -304
  141. package/src/services/analytics/SUMMARY.md +141 -141
  142. package/src/services/analytics/TRENDS.md +380 -380
  143. package/src/services/analytics/USAGE_GUIDE.md +518 -518
  144. package/src/services/analytics/analytics-cloud.service.ts +222 -222
  145. package/src/services/analytics/analytics.service.ts +2142 -2142
  146. package/src/services/analytics/index.ts +4 -4
  147. package/src/services/analytics/review-analytics.service.ts +941 -941
  148. package/src/services/analytics/utils/appointment-filtering.utils.ts +138 -138
  149. package/src/services/analytics/utils/cost-calculation.utils.ts +182 -182
  150. package/src/services/analytics/utils/grouping.utils.ts +434 -434
  151. package/src/services/analytics/utils/stored-analytics.utils.ts +347 -347
  152. package/src/services/analytics/utils/time-calculation.utils.ts +186 -186
  153. package/src/services/analytics/utils/trend-calculation.utils.ts +200 -200
  154. package/src/services/appointment/README.md +17 -17
  155. package/src/services/appointment/appointment.service.ts +2558 -2558
  156. package/src/services/appointment/index.ts +1 -1
  157. package/src/services/appointment/utils/appointment.utils.ts +552 -552
  158. package/src/services/appointment/utils/extended-procedure.utils.ts +314 -314
  159. package/src/services/appointment/utils/form-initialization.utils.ts +225 -225
  160. package/src/services/appointment/utils/recommended-procedure.utils.ts +195 -195
  161. package/src/services/appointment/utils/zone-management.utils.ts +353 -353
  162. package/src/services/appointment/utils/zone-photo.utils.ts +152 -152
  163. package/src/services/auth/auth.service.ts +989 -989
  164. package/src/services/auth/auth.v2.service.ts +961 -961
  165. package/src/services/auth/index.ts +7 -7
  166. package/src/services/auth/utils/error.utils.ts +90 -90
  167. package/src/services/auth/utils/firebase.utils.ts +49 -49
  168. package/src/services/auth/utils/index.ts +21 -21
  169. package/src/services/auth/utils/practitioner.utils.ts +125 -125
  170. package/src/services/base.service.ts +41 -41
  171. package/src/services/calendar/calendar.service.ts +1077 -1077
  172. package/src/services/calendar/calendar.v2.service.ts +1683 -1683
  173. package/src/services/calendar/calendar.v3.service.ts +313 -313
  174. package/src/services/calendar/externalCalendar.service.ts +178 -178
  175. package/src/services/calendar/index.ts +5 -5
  176. package/src/services/calendar/synced-calendars.service.ts +743 -743
  177. package/src/services/calendar/utils/appointment.utils.ts +265 -265
  178. package/src/services/calendar/utils/calendar-event.utils.ts +646 -646
  179. package/src/services/calendar/utils/clinic.utils.ts +237 -237
  180. package/src/services/calendar/utils/docs.utils.ts +157 -157
  181. package/src/services/calendar/utils/google-calendar.utils.ts +697 -697
  182. package/src/services/calendar/utils/index.ts +8 -8
  183. package/src/services/calendar/utils/patient.utils.ts +198 -198
  184. package/src/services/calendar/utils/practitioner.utils.ts +221 -221
  185. package/src/services/calendar/utils/synced-calendar.utils.ts +472 -472
  186. package/src/services/clinic/README.md +204 -204
  187. package/src/services/clinic/__tests__/clinic-admin.service.test.ts +287 -287
  188. package/src/services/clinic/__tests__/clinic-group.service.test.ts +352 -352
  189. package/src/services/clinic/__tests__/clinic.service.test.ts +354 -354
  190. package/src/services/clinic/billing-transactions.service.ts +217 -217
  191. package/src/services/clinic/clinic-admin.service.ts +202 -202
  192. package/src/services/clinic/clinic-group.service.ts +310 -310
  193. package/src/services/clinic/clinic.service.ts +708 -708
  194. package/src/services/clinic/index.ts +5 -5
  195. package/src/services/clinic/practitioner-invite.service.ts +519 -519
  196. package/src/services/clinic/utils/admin.utils.ts +551 -551
  197. package/src/services/clinic/utils/clinic-group.utils.ts +646 -646
  198. package/src/services/clinic/utils/clinic.utils.ts +949 -949
  199. package/src/services/clinic/utils/filter.utils.d.ts +23 -23
  200. package/src/services/clinic/utils/filter.utils.ts +446 -446
  201. package/src/services/clinic/utils/index.ts +11 -11
  202. package/src/services/clinic/utils/photos.utils.ts +188 -188
  203. package/src/services/clinic/utils/search.utils.ts +84 -84
  204. package/src/services/clinic/utils/tag.utils.ts +124 -124
  205. package/src/services/documentation-templates/documentation-template.service.ts +537 -537
  206. package/src/services/documentation-templates/filled-document.service.ts +587 -587
  207. package/src/services/documentation-templates/index.ts +2 -2
  208. package/src/services/index.ts +14 -14
  209. package/src/services/media/index.ts +1 -1
  210. package/src/services/media/media.service.ts +418 -418
  211. package/src/services/notifications/__tests__/notification.service.test.ts +242 -242
  212. package/src/services/notifications/index.ts +1 -1
  213. package/src/services/notifications/notification.service.ts +215 -215
  214. package/src/services/patient/README.md +48 -48
  215. package/src/services/patient/To-Do.md +43 -43
  216. package/src/services/patient/__tests__/patient.service.test.ts +294 -294
  217. package/src/services/patient/index.ts +2 -2
  218. package/src/services/patient/patient.service.ts +883 -883
  219. package/src/services/patient/patientRequirements.service.ts +285 -285
  220. package/src/services/patient/utils/aesthetic-analysis.utils.ts +176 -176
  221. package/src/services/patient/utils/clinic.utils.ts +80 -80
  222. package/src/services/patient/utils/docs.utils.ts +142 -142
  223. package/src/services/patient/utils/index.ts +9 -9
  224. package/src/services/patient/utils/location.utils.ts +126 -126
  225. package/src/services/patient/utils/medical-stuff.utils.ts +143 -143
  226. package/src/services/patient/utils/medical.utils.ts +458 -458
  227. package/src/services/patient/utils/practitioner.utils.ts +260 -260
  228. package/src/services/patient/utils/profile.utils.ts +510 -510
  229. package/src/services/patient/utils/sensitive.utils.ts +260 -260
  230. package/src/services/patient/utils/token.utils.ts +211 -211
  231. package/src/services/practitioner/README.md +145 -145
  232. package/src/services/practitioner/index.ts +1 -1
  233. package/src/services/practitioner/practitioner.service.ts +1742 -1742
  234. package/src/services/procedure/README.md +163 -163
  235. package/src/services/procedure/index.ts +1 -1
  236. package/src/services/procedure/procedure.service.ts +2200 -2200
  237. package/src/services/reviews/index.ts +1 -1
  238. package/src/services/reviews/reviews.service.ts +734 -734
  239. package/src/services/user/index.ts +1 -1
  240. package/src/services/user/user.service.ts +489 -489
  241. package/src/services/user/user.v2.service.ts +466 -466
  242. package/src/types/analytics/analytics.types.ts +597 -597
  243. package/src/types/analytics/grouped-analytics.types.ts +173 -173
  244. package/src/types/analytics/index.ts +4 -4
  245. package/src/types/analytics/stored-analytics.types.ts +137 -137
  246. package/src/types/appointment/index.ts +480 -480
  247. package/src/types/calendar/index.ts +258 -258
  248. package/src/types/calendar/synced-calendar.types.ts +66 -66
  249. package/src/types/clinic/index.ts +498 -489
  250. package/src/types/clinic/practitioner-invite.types.ts +91 -91
  251. package/src/types/clinic/preferences.types.ts +159 -159
  252. package/src/types/clinic/to-do +3 -3
  253. package/src/types/documentation-templates/index.ts +308 -308
  254. package/src/types/index.ts +47 -47
  255. package/src/types/notifications/README.md +77 -77
  256. package/src/types/notifications/index.ts +286 -286
  257. package/src/types/patient/aesthetic-analysis.types.ts +66 -66
  258. package/src/types/patient/allergies.ts +58 -58
  259. package/src/types/patient/index.ts +275 -275
  260. package/src/types/patient/medical-info.types.ts +152 -152
  261. package/src/types/patient/patient-requirements.ts +92 -92
  262. package/src/types/patient/token.types.ts +61 -61
  263. package/src/types/practitioner/index.ts +206 -206
  264. package/src/types/procedure/index.ts +181 -181
  265. package/src/types/profile/index.ts +39 -39
  266. package/src/types/reviews/index.ts +132 -132
  267. package/src/types/tz-lookup.d.ts +4 -4
  268. package/src/types/user/index.ts +38 -38
  269. package/src/utils/TIMESTAMPS.md +176 -176
  270. package/src/utils/TimestampUtils.ts +241 -241
  271. package/src/utils/index.ts +1 -1
  272. package/src/validations/appointment.schema.ts +574 -574
  273. package/src/validations/calendar.schema.ts +225 -225
  274. package/src/validations/clinic.schema.ts +494 -493
  275. package/src/validations/common.schema.ts +25 -25
  276. package/src/validations/documentation-templates/index.ts +1 -1
  277. package/src/validations/documentation-templates/template.schema.ts +220 -220
  278. package/src/validations/documentation-templates.schema.ts +10 -10
  279. package/src/validations/index.ts +20 -20
  280. package/src/validations/media.schema.ts +10 -10
  281. package/src/validations/notification.schema.ts +90 -90
  282. package/src/validations/patient/aesthetic-analysis.schema.ts +55 -55
  283. package/src/validations/patient/medical-info.schema.ts +125 -125
  284. package/src/validations/patient/patient-requirements.schema.ts +84 -84
  285. package/src/validations/patient/token.schema.ts +29 -29
  286. package/src/validations/patient.schema.ts +217 -217
  287. package/src/validations/practitioner.schema.ts +222 -222
  288. package/src/validations/procedure-product.schema.ts +41 -41
  289. package/src/validations/procedure.schema.ts +124 -124
  290. package/src/validations/profile-info.schema.ts +41 -41
  291. package/src/validations/reviews.schema.ts +195 -195
  292. package/src/validations/schemas.ts +104 -104
  293. package/src/validations/shared.schema.ts +78 -78
@@ -1,518 +1,518 @@
1
- # Analytics Service - Complete Usage Guide
2
-
3
- ## Table of Contents
4
- 1. [What We Can Do](#what-we-can-do)
5
- 2. [How It Works: Computed vs On-Demand](#how-it-works)
6
- 3. [Available Analytics](#available-analytics)
7
- 4. [Specific Use Cases](#specific-use-cases)
8
-
9
- ---
10
-
11
- ## What We Can Do
12
-
13
- The Analytics Service provides comprehensive insights into your clinic operations:
14
-
15
- ### 📊 **Financial Intelligence**
16
- - Track total revenue, average revenue per appointment
17
- - Monitor payment status (paid, unpaid, refunded)
18
- - Analyze costs per patient
19
- - Revenue trends over time
20
-
21
- ### 👨‍⚕️ **Practitioner Performance**
22
- - Appointment counts and completion rates
23
- - Cancellation and no-show rates per doctor
24
- - Time efficiency (booked vs actual time)
25
- - Revenue generation per practitioner
26
- - Patient retention rates
27
-
28
- ### 🏥 **Procedure Analytics**
29
- - Most popular procedures
30
- - Most profitable procedures
31
- - Procedure performance by category/technology
32
- - Product usage per procedure
33
-
34
- ### ⏱️ **Time Management**
35
- - Booked time vs actual time spent
36
- - Efficiency percentages
37
- - Overrun/underutilization analysis
38
- - Peak hours identification
39
-
40
- ### ❌ **Cancellation & No-Show Analysis**
41
- - Rates by clinic, practitioner, patient, or procedure
42
- - Cancellation reasons breakdown
43
- - Average cancellation lead time
44
- - Patterns and trends
45
-
46
- ### 👥 **Patient Insights**
47
- - Patient lifetime value
48
- - Retention rates
49
- - Appointment frequency
50
- - Cancellation patterns per patient
51
-
52
- ### 📦 **Product Usage**
53
- - Products used per appointment
54
- - Revenue contribution by product
55
- - Usage by procedure
56
- - Quantity and pricing trends
57
-
58
- ### 🏢 **Clinic Performance**
59
- - Overall clinic metrics
60
- - Practitioner comparisons
61
- - Procedure popularity
62
- - Efficiency metrics
63
-
64
- ---
65
-
66
- ## How It Works: Computed vs On-Demand
67
-
68
- ### 🔄 **Hybrid Architecture**
69
-
70
- The service uses a **smart hybrid approach**:
71
-
72
- ```
73
- ┌─────────────────────────────────────────┐
74
- │ Client Request │
75
- └──────────────┬──────────────────────────┘
76
-
77
-
78
- ┌─────────────────────────────────────────┐
79
- │ Check Stored Analytics? │
80
- └──────┬──────────────────────┬───────────┘
81
- │ │
82
- YES │ │ NO
83
- ▼ ▼
84
- ┌──────────────┐ ┌─────────────────────┐
85
- │ Data Fresh? │ │ Calculate On-Demand │
86
- │ (< 12 hours) │ │ (Query Appointments)│
87
- └──┬───────┬───┘ └─────────────────────┘
88
- │ │
89
- YES│ │NO
90
- │ │
91
- ▼ ▼
92
- ┌─────┐ ┌─────────────────────┐
93
- │ ✅ │ │ Calculate On-Demand │
94
- │Fast │ │ (Query Appointments)│
95
- └─────┘ └─────────────────────┘
96
- ```
97
-
98
- ### 📦 **Pre-Computed Analytics (Recommended)**
99
-
100
- **How it works:**
101
- 1. **Cloud Function runs every 12 hours** (scheduled)
102
- 2. Computes analytics for all clinics
103
- 3. Stores results in Firestore: `clinics/{clinicBranchId}/analytics/`
104
- 4. Client reads cached data (1 document read = instant)
105
-
106
- **Benefits:**
107
- - ⚡ **Fast**: Instant response (single document read)
108
- - 💰 **Cheap**: 1 read vs hundreds/thousands
109
- - 📈 **Scalable**: Works with large datasets
110
-
111
- **Example:**
112
- ```typescript
113
- // Automatically uses cached data if available and fresh (< 12 hours)
114
- const dashboard = await analyticsService.getDashboardData(
115
- { clinicBranchId: 'clinic-123' },
116
- { start: new Date('2024-01-01'), end: new Date('2024-12-31') }
117
- );
118
- // Returns instantly from cache! ⚡
119
- ```
120
-
121
- ### 🔄 **On-Demand Calculation (Fallback)**
122
-
123
- **When it happens:**
124
- - No cached data exists yet
125
- - Cached data is stale (> 12 hours old)
126
- - You explicitly disable cache: `{ useCache: false }`
127
- - Custom date range that doesn't match pre-computed periods
128
-
129
- **How it works:**
130
- 1. Queries all appointments matching filters
131
- 2. Calculates metrics in real-time
132
- 3. Returns results
133
-
134
- **Example:**
135
- ```typescript
136
- // Force on-demand calculation
137
- const dashboard = await analyticsService.getDashboardData(
138
- { clinicBranchId: 'clinic-123' },
139
- { start: new Date('2024-01-01'), end: new Date('2024-12-31') },
140
- { useCache: false } // Force calculation
141
- );
142
- // Calculates from scratch (slower but always fresh)
143
- ```
144
-
145
- ### ⚙️ **Configuration**
146
-
147
- **Change cache freshness:**
148
- ```typescript
149
- // Use cache if data is less than 6 hours old
150
- const dashboard = await analyticsService.getDashboardData(
151
- { clinicBranchId: 'clinic-123' },
152
- dateRange,
153
- { maxCacheAgeHours: 6 }
154
- );
155
- ```
156
-
157
- **Change Cloud Function schedule:**
158
- Edit `Cloud/functions/src/analytics/computeAnalytics.ts`:
159
- ```typescript
160
- schedule: "every 6 hours" // or "every 24 hours", etc.
161
- ```
162
-
163
- ---
164
-
165
- ## Available Analytics
166
-
167
- ### 1. **Practitioner Analytics** 👨‍⚕️
168
-
169
- ```typescript
170
- const metrics = await analyticsService.getPractitionerAnalytics(
171
- 'practitioner-id-123',
172
- { start: new Date('2024-01-01'), end: new Date('2024-12-31') }
173
- );
174
-
175
- // Returns:
176
- {
177
- practitionerId: string;
178
- practitionerName: string;
179
- totalAppointments: number;
180
- completedAppointments: number;
181
- canceledAppointments: number;
182
- noShowAppointments: number;
183
- cancellationRate: number; // percentage
184
- noShowRate: number; // percentage
185
- averageBookedTime: number; // minutes
186
- averageActualTime: number; // minutes
187
- timeEfficiency: number; // percentage
188
- totalRevenue: number;
189
- averageRevenuePerAppointment: number;
190
- topProcedures: Array<{ procedureId, procedureName, count, revenue }>;
191
- patientRetentionRate: number;
192
- uniquePatients: number;
193
- }
194
- ```
195
-
196
- ### 2. **Procedure Analytics** 🏥
197
-
198
- ```typescript
199
- // Single procedure
200
- const procedure = await analyticsService.getProcedureAnalytics(
201
- 'procedure-id-123',
202
- dateRange
203
- );
204
-
205
- // All procedures
206
- const allProcedures = await analyticsService.getProcedureAnalytics(
207
- undefined,
208
- dateRange
209
- );
210
-
211
- // Most popular
212
- const popular = await analyticsService.getProcedurePopularity(dateRange, 10);
213
-
214
- // Most profitable
215
- const profitable = await analyticsService.getProcedureProfitability(dateRange, 10);
216
- ```
217
-
218
- ### 3. **Time Efficiency** ⏱️
219
-
220
- ```typescript
221
- const timeMetrics = await analyticsService.getTimeEfficiencyMetrics(
222
- { clinicBranchId: 'clinic-123' },
223
- dateRange
224
- );
225
-
226
- // Returns:
227
- {
228
- averageBookedDuration: number; // minutes
229
- averageActualDuration: number; // minutes
230
- averageEfficiency: number; // percentage
231
- averageOverrun: number; // minutes
232
- averageUnderutilization: number; // minutes
233
- efficiencyDistribution: Array<{ range: string, count: number }>;
234
- }
235
- ```
236
-
237
- ### 4. **Cancellation Metrics** ❌
238
-
239
- ```typescript
240
- // Grouped by clinic, practitioner, patient, or procedure
241
- const cancellations = await analyticsService.getCancellationMetrics(
242
- 'practitioner', // or 'clinic', 'patient', 'procedure'
243
- dateRange
244
- );
245
-
246
- // Returns array of:
247
- {
248
- entityId: string;
249
- entityName: string;
250
- entityType: 'practitioner' | 'clinic' | 'patient' | 'procedure';
251
- totalAppointments: number;
252
- canceledAppointments: number;
253
- cancellationRate: number; // percentage
254
- canceledByPatient: number;
255
- canceledByClinic: number;
256
- averageCancellationLeadTime: number; // hours
257
- cancellationReasons: Array<{ reason: string, count: number }>;
258
- }
259
- ```
260
-
261
- ### 5. **No-Show Metrics** 🚫
262
-
263
- ```typescript
264
- const noShows = await analyticsService.getNoShowMetrics(
265
- 'practitioner', // or 'clinic', 'patient', 'procedure'
266
- dateRange
267
- );
268
-
269
- // Returns array of:
270
- {
271
- entityId: string;
272
- entityName: string;
273
- entityType: 'practitioner' | 'clinic' | 'patient' | 'procedure';
274
- totalAppointments: number;
275
- noShowAppointments: number;
276
- noShowRate: number; // percentage
277
- }
278
- ```
279
-
280
- ### 6. **Revenue Metrics** 💰
281
-
282
- ```typescript
283
- const revenue = await analyticsService.getRevenueMetrics(
284
- { clinicBranchId: 'clinic-123' },
285
- dateRange
286
- );
287
-
288
- // Returns:
289
- {
290
- totalRevenue: number;
291
- averageRevenuePerAppointment: number;
292
- revenueByStatus: Record<AppointmentStatus, number>;
293
- revenueByPaymentStatus: Record<PaymentStatus, number>;
294
- unpaidRevenue: number;
295
- refundedRevenue: number;
296
- }
297
- ```
298
-
299
- ### 7. **Product Usage** 📦
300
-
301
- ```typescript
302
- // All products
303
- const products = await analyticsService.getProductUsageMetrics(
304
- undefined,
305
- dateRange
306
- );
307
-
308
- // Specific product
309
- const product = await analyticsService.getProductUsageMetrics(
310
- 'product-id-123',
311
- dateRange
312
- );
313
- ```
314
-
315
- ### 8. **Patient Analytics** 👥
316
-
317
- ```typescript
318
- // Single patient
319
- const patient = await analyticsService.getPatientAnalytics(
320
- 'patient-id-123',
321
- dateRange
322
- );
323
-
324
- // All patients
325
- const allPatients = await analyticsService.getPatientAnalytics(
326
- undefined,
327
- dateRange
328
- );
329
- ```
330
-
331
- ### 9. **Dashboard Data** 📊
332
-
333
- ```typescript
334
- const dashboard = await analyticsService.getDashboardData(
335
- { clinicBranchId: 'clinic-123' },
336
- dateRange
337
- );
338
-
339
- // Returns comprehensive dashboard with:
340
- // - Overview metrics
341
- // - Top practitioners
342
- // - Top procedures
343
- // - Cancellation/no-show metrics
344
- // - Revenue trends
345
- // - Time efficiency
346
- // - Top products
347
- // - Recent activity
348
- ```
349
-
350
- ---
351
-
352
- ## Specific Use Cases
353
-
354
- ### Use Case 1: Patient No-Show Per Doctor 👨‍⚕️
355
-
356
- **Question**: "Which patients have the highest no-show rate for each doctor?"
357
-
358
- **Solution**: Get no-show metrics grouped by practitioner, then filter by patient if needed.
359
-
360
- ```typescript
361
- // Step 1: Get no-show metrics grouped by practitioner
362
- const noShowByPractitioner = await analyticsService.getNoShowMetrics(
363
- 'practitioner',
364
- { start: new Date('2024-01-01'), end: new Date('2024-12-31') }
365
- );
366
-
367
- // Returns array like:
368
- // [
369
- // {
370
- // entityId: 'practitioner-123',
371
- // entityName: 'Dr. Smith',
372
- // entityType: 'practitioner',
373
- // totalAppointments: 100,
374
- // noShowAppointments: 15,
375
- // noShowRate: 15.0
376
- // },
377
- // ...
378
- // ]
379
-
380
- // Step 2: For a specific practitioner, get patient-level no-shows
381
- // (You can filter appointments and calculate manually, or use patient analytics)
382
-
383
- // Get all appointments for a specific practitioner
384
- const practitionerAppointments = await analyticsService['fetchAppointments'](
385
- { practitionerId: 'practitioner-123' },
386
- dateRange
387
- );
388
-
389
- // Group no-shows by patient
390
- const noShowByPatient = new Map<string, { name: string; noShows: number; total: number }>();
391
-
392
- practitionerAppointments.forEach(appointment => {
393
- const patientId = appointment.patientId;
394
- const patientName = appointment.patientInfo?.fullName || 'Unknown';
395
-
396
- if (!noShowByPatient.has(patientId)) {
397
- noShowByPatient.set(patientId, { name: patientName, noShows: 0, total: 0 });
398
- }
399
-
400
- const patientData = noShowByPatient.get(patientId)!;
401
- patientData.total++;
402
-
403
- if (appointment.status === AppointmentStatus.NO_SHOW) {
404
- patientData.noShows++;
405
- }
406
- });
407
-
408
- // Calculate rates
409
- const patientNoShowRates = Array.from(noShowByPatient.entries()).map(([patientId, data]) => ({
410
- patientId,
411
- patientName: data.name,
412
- totalAppointments: data.total,
413
- noShowCount: data.noShows,
414
- noShowRate: (data.noShows / data.total) * 100
415
- })).sort((a, b) => b.noShowRate - a.noShowRate);
416
-
417
- console.log('Patient no-show rates for this practitioner:');
418
- patientNoShowRates.forEach(patient => {
419
- console.log(`${patient.patientName}: ${patient.noShowRate.toFixed(1)}% (${patient.noShowCount}/${patient.total})`);
420
- });
421
- ```
422
-
423
- ### Use Case 2: Doctor Performance Comparison 📊
424
-
425
- ```typescript
426
- // Get all practitioners for a clinic
427
- const practitioners = await analyticsService.getCancellationMetrics(
428
- 'practitioner',
429
- { start: new Date('2024-01-01'), end: new Date('2024-12-31') }
430
- );
431
-
432
- // Filter by clinic if needed (would need clinicBranchId in filters)
433
- const clinicPractitioners = practitioners.filter(p =>
434
- // Filter logic based on your needs
435
- );
436
-
437
- // Compare metrics
438
- practitioners.forEach(practitioner => {
439
- console.log(`${practitioner.entityName}:`);
440
- console.log(` Cancellation Rate: ${practitioner.cancellationRate}%`);
441
- console.log(` Total Appointments: ${practitioner.totalAppointments}`);
442
- });
443
- ```
444
-
445
- ### Use Case 3: Procedure Profitability Analysis 💰
446
-
447
- ```typescript
448
- // Get most profitable procedures
449
- const profitable = await analyticsService.getProcedureProfitability(
450
- { start: new Date('2024-01-01'), end: new Date('2024-12-31') },
451
- 10 // Top 10
452
- );
453
-
454
- profitable.forEach((procedure, index) => {
455
- console.log(`${index + 1}. ${procedure.procedureName}`);
456
- console.log(` Revenue: ${procedure.totalRevenue} ${procedure.currency || 'CHF'}`);
457
- console.log(` Appointments: ${procedure.appointmentCount}`);
458
- console.log(` Avg Revenue: ${procedure.averageRevenue.toFixed(2)}`);
459
- });
460
- ```
461
-
462
- ### Use Case 4: Time Efficiency by Doctor ⏱️
463
-
464
- ```typescript
465
- // Get time efficiency for a specific practitioner
466
- const practitionerMetrics = await analyticsService.getPractitionerAnalytics(
467
- 'practitioner-id-123',
468
- dateRange
469
- );
470
-
471
- console.log(`Time Efficiency: ${practitionerMetrics.timeEfficiency}%`);
472
- console.log(`Avg Booked Time: ${practitionerMetrics.averageBookedTime} min`);
473
- console.log(`Avg Actual Time: ${practitionerMetrics.averageActualTime} min`);
474
-
475
- // Or get overall time efficiency with filters
476
- const timeMetrics = await analyticsService.getTimeEfficiencyMetrics(
477
- { practitionerId: 'practitioner-id-123' },
478
- dateRange
479
- );
480
- ```
481
-
482
- ### Use Case 5: Product Cost Analysis 📦
483
-
484
- ```typescript
485
- // Get product usage for a specific procedure
486
- const procedureAnalytics = await analyticsService.getProcedureAnalytics(
487
- 'procedure-id-123',
488
- dateRange
489
- );
490
-
491
- // Check product usage
492
- procedureAnalytics.productUsage.forEach(product => {
493
- console.log(`${product.productName}:`);
494
- console.log(` Total Quantity: ${product.totalQuantity}`);
495
- console.log(` Total Revenue: ${product.totalRevenue}`);
496
- console.log(` Used in ${product.usageCount} appointments`);
497
- });
498
- ```
499
-
500
- ---
501
-
502
- ## Performance Tips
503
-
504
- 1. **Use pre-computed analytics** when possible (default behavior)
505
- 2. **Specify clinicBranchId** in filters to enable caching
506
- 3. **Use standard date ranges** (daily, weekly, monthly) for better cache hits
507
- 4. **Batch requests** when getting multiple practitioners/procedures
508
- 5. **Cache results** on the client side for frequently accessed dashboards
509
-
510
- ---
511
-
512
- ## Next Steps
513
-
514
- 1. **Deploy Cloud Function**: Deploy `computeAnalytics.ts` to start pre-computing
515
- 2. **Test with real data**: Verify analytics accuracy
516
- 3. **Monitor performance**: Check Cloud Function logs and Firestore usage
517
- 4. **Customize**: Adjust cache age and computation schedule as needed
518
-
1
+ # Analytics Service - Complete Usage Guide
2
+
3
+ ## Table of Contents
4
+ 1. [What We Can Do](#what-we-can-do)
5
+ 2. [How It Works: Computed vs On-Demand](#how-it-works)
6
+ 3. [Available Analytics](#available-analytics)
7
+ 4. [Specific Use Cases](#specific-use-cases)
8
+
9
+ ---
10
+
11
+ ## What We Can Do
12
+
13
+ The Analytics Service provides comprehensive insights into your clinic operations:
14
+
15
+ ### 📊 **Financial Intelligence**
16
+ - Track total revenue, average revenue per appointment
17
+ - Monitor payment status (paid, unpaid, refunded)
18
+ - Analyze costs per patient
19
+ - Revenue trends over time
20
+
21
+ ### 👨‍⚕️ **Practitioner Performance**
22
+ - Appointment counts and completion rates
23
+ - Cancellation and no-show rates per doctor
24
+ - Time efficiency (booked vs actual time)
25
+ - Revenue generation per practitioner
26
+ - Patient retention rates
27
+
28
+ ### 🏥 **Procedure Analytics**
29
+ - Most popular procedures
30
+ - Most profitable procedures
31
+ - Procedure performance by category/technology
32
+ - Product usage per procedure
33
+
34
+ ### ⏱️ **Time Management**
35
+ - Booked time vs actual time spent
36
+ - Efficiency percentages
37
+ - Overrun/underutilization analysis
38
+ - Peak hours identification
39
+
40
+ ### ❌ **Cancellation & No-Show Analysis**
41
+ - Rates by clinic, practitioner, patient, or procedure
42
+ - Cancellation reasons breakdown
43
+ - Average cancellation lead time
44
+ - Patterns and trends
45
+
46
+ ### 👥 **Patient Insights**
47
+ - Patient lifetime value
48
+ - Retention rates
49
+ - Appointment frequency
50
+ - Cancellation patterns per patient
51
+
52
+ ### 📦 **Product Usage**
53
+ - Products used per appointment
54
+ - Revenue contribution by product
55
+ - Usage by procedure
56
+ - Quantity and pricing trends
57
+
58
+ ### 🏢 **Clinic Performance**
59
+ - Overall clinic metrics
60
+ - Practitioner comparisons
61
+ - Procedure popularity
62
+ - Efficiency metrics
63
+
64
+ ---
65
+
66
+ ## How It Works: Computed vs On-Demand
67
+
68
+ ### 🔄 **Hybrid Architecture**
69
+
70
+ The service uses a **smart hybrid approach**:
71
+
72
+ ```
73
+ ┌─────────────────────────────────────────┐
74
+ │ Client Request │
75
+ └──────────────┬──────────────────────────┘
76
+
77
+
78
+ ┌─────────────────────────────────────────┐
79
+ │ Check Stored Analytics? │
80
+ └──────┬──────────────────────┬───────────┘
81
+ │ │
82
+ YES │ │ NO
83
+ ▼ ▼
84
+ ┌──────────────┐ ┌─────────────────────┐
85
+ │ Data Fresh? │ │ Calculate On-Demand │
86
+ │ (< 12 hours) │ │ (Query Appointments)│
87
+ └──┬───────┬───┘ └─────────────────────┘
88
+ │ │
89
+ YES│ │NO
90
+ │ │
91
+ ▼ ▼
92
+ ┌─────┐ ┌─────────────────────┐
93
+ │ ✅ │ │ Calculate On-Demand │
94
+ │Fast │ │ (Query Appointments)│
95
+ └─────┘ └─────────────────────┘
96
+ ```
97
+
98
+ ### 📦 **Pre-Computed Analytics (Recommended)**
99
+
100
+ **How it works:**
101
+ 1. **Cloud Function runs every 12 hours** (scheduled)
102
+ 2. Computes analytics for all clinics
103
+ 3. Stores results in Firestore: `clinics/{clinicBranchId}/analytics/`
104
+ 4. Client reads cached data (1 document read = instant)
105
+
106
+ **Benefits:**
107
+ - ⚡ **Fast**: Instant response (single document read)
108
+ - 💰 **Cheap**: 1 read vs hundreds/thousands
109
+ - 📈 **Scalable**: Works with large datasets
110
+
111
+ **Example:**
112
+ ```typescript
113
+ // Automatically uses cached data if available and fresh (< 12 hours)
114
+ const dashboard = await analyticsService.getDashboardData(
115
+ { clinicBranchId: 'clinic-123' },
116
+ { start: new Date('2024-01-01'), end: new Date('2024-12-31') }
117
+ );
118
+ // Returns instantly from cache! ⚡
119
+ ```
120
+
121
+ ### 🔄 **On-Demand Calculation (Fallback)**
122
+
123
+ **When it happens:**
124
+ - No cached data exists yet
125
+ - Cached data is stale (> 12 hours old)
126
+ - You explicitly disable cache: `{ useCache: false }`
127
+ - Custom date range that doesn't match pre-computed periods
128
+
129
+ **How it works:**
130
+ 1. Queries all appointments matching filters
131
+ 2. Calculates metrics in real-time
132
+ 3. Returns results
133
+
134
+ **Example:**
135
+ ```typescript
136
+ // Force on-demand calculation
137
+ const dashboard = await analyticsService.getDashboardData(
138
+ { clinicBranchId: 'clinic-123' },
139
+ { start: new Date('2024-01-01'), end: new Date('2024-12-31') },
140
+ { useCache: false } // Force calculation
141
+ );
142
+ // Calculates from scratch (slower but always fresh)
143
+ ```
144
+
145
+ ### ⚙️ **Configuration**
146
+
147
+ **Change cache freshness:**
148
+ ```typescript
149
+ // Use cache if data is less than 6 hours old
150
+ const dashboard = await analyticsService.getDashboardData(
151
+ { clinicBranchId: 'clinic-123' },
152
+ dateRange,
153
+ { maxCacheAgeHours: 6 }
154
+ );
155
+ ```
156
+
157
+ **Change Cloud Function schedule:**
158
+ Edit `Cloud/functions/src/analytics/computeAnalytics.ts`:
159
+ ```typescript
160
+ schedule: "every 6 hours" // or "every 24 hours", etc.
161
+ ```
162
+
163
+ ---
164
+
165
+ ## Available Analytics
166
+
167
+ ### 1. **Practitioner Analytics** 👨‍⚕️
168
+
169
+ ```typescript
170
+ const metrics = await analyticsService.getPractitionerAnalytics(
171
+ 'practitioner-id-123',
172
+ { start: new Date('2024-01-01'), end: new Date('2024-12-31') }
173
+ );
174
+
175
+ // Returns:
176
+ {
177
+ practitionerId: string;
178
+ practitionerName: string;
179
+ totalAppointments: number;
180
+ completedAppointments: number;
181
+ canceledAppointments: number;
182
+ noShowAppointments: number;
183
+ cancellationRate: number; // percentage
184
+ noShowRate: number; // percentage
185
+ averageBookedTime: number; // minutes
186
+ averageActualTime: number; // minutes
187
+ timeEfficiency: number; // percentage
188
+ totalRevenue: number;
189
+ averageRevenuePerAppointment: number;
190
+ topProcedures: Array<{ procedureId, procedureName, count, revenue }>;
191
+ patientRetentionRate: number;
192
+ uniquePatients: number;
193
+ }
194
+ ```
195
+
196
+ ### 2. **Procedure Analytics** 🏥
197
+
198
+ ```typescript
199
+ // Single procedure
200
+ const procedure = await analyticsService.getProcedureAnalytics(
201
+ 'procedure-id-123',
202
+ dateRange
203
+ );
204
+
205
+ // All procedures
206
+ const allProcedures = await analyticsService.getProcedureAnalytics(
207
+ undefined,
208
+ dateRange
209
+ );
210
+
211
+ // Most popular
212
+ const popular = await analyticsService.getProcedurePopularity(dateRange, 10);
213
+
214
+ // Most profitable
215
+ const profitable = await analyticsService.getProcedureProfitability(dateRange, 10);
216
+ ```
217
+
218
+ ### 3. **Time Efficiency** ⏱️
219
+
220
+ ```typescript
221
+ const timeMetrics = await analyticsService.getTimeEfficiencyMetrics(
222
+ { clinicBranchId: 'clinic-123' },
223
+ dateRange
224
+ );
225
+
226
+ // Returns:
227
+ {
228
+ averageBookedDuration: number; // minutes
229
+ averageActualDuration: number; // minutes
230
+ averageEfficiency: number; // percentage
231
+ averageOverrun: number; // minutes
232
+ averageUnderutilization: number; // minutes
233
+ efficiencyDistribution: Array<{ range: string, count: number }>;
234
+ }
235
+ ```
236
+
237
+ ### 4. **Cancellation Metrics** ❌
238
+
239
+ ```typescript
240
+ // Grouped by clinic, practitioner, patient, or procedure
241
+ const cancellations = await analyticsService.getCancellationMetrics(
242
+ 'practitioner', // or 'clinic', 'patient', 'procedure'
243
+ dateRange
244
+ );
245
+
246
+ // Returns array of:
247
+ {
248
+ entityId: string;
249
+ entityName: string;
250
+ entityType: 'practitioner' | 'clinic' | 'patient' | 'procedure';
251
+ totalAppointments: number;
252
+ canceledAppointments: number;
253
+ cancellationRate: number; // percentage
254
+ canceledByPatient: number;
255
+ canceledByClinic: number;
256
+ averageCancellationLeadTime: number; // hours
257
+ cancellationReasons: Array<{ reason: string, count: number }>;
258
+ }
259
+ ```
260
+
261
+ ### 5. **No-Show Metrics** 🚫
262
+
263
+ ```typescript
264
+ const noShows = await analyticsService.getNoShowMetrics(
265
+ 'practitioner', // or 'clinic', 'patient', 'procedure'
266
+ dateRange
267
+ );
268
+
269
+ // Returns array of:
270
+ {
271
+ entityId: string;
272
+ entityName: string;
273
+ entityType: 'practitioner' | 'clinic' | 'patient' | 'procedure';
274
+ totalAppointments: number;
275
+ noShowAppointments: number;
276
+ noShowRate: number; // percentage
277
+ }
278
+ ```
279
+
280
+ ### 6. **Revenue Metrics** 💰
281
+
282
+ ```typescript
283
+ const revenue = await analyticsService.getRevenueMetrics(
284
+ { clinicBranchId: 'clinic-123' },
285
+ dateRange
286
+ );
287
+
288
+ // Returns:
289
+ {
290
+ totalRevenue: number;
291
+ averageRevenuePerAppointment: number;
292
+ revenueByStatus: Record<AppointmentStatus, number>;
293
+ revenueByPaymentStatus: Record<PaymentStatus, number>;
294
+ unpaidRevenue: number;
295
+ refundedRevenue: number;
296
+ }
297
+ ```
298
+
299
+ ### 7. **Product Usage** 📦
300
+
301
+ ```typescript
302
+ // All products
303
+ const products = await analyticsService.getProductUsageMetrics(
304
+ undefined,
305
+ dateRange
306
+ );
307
+
308
+ // Specific product
309
+ const product = await analyticsService.getProductUsageMetrics(
310
+ 'product-id-123',
311
+ dateRange
312
+ );
313
+ ```
314
+
315
+ ### 8. **Patient Analytics** 👥
316
+
317
+ ```typescript
318
+ // Single patient
319
+ const patient = await analyticsService.getPatientAnalytics(
320
+ 'patient-id-123',
321
+ dateRange
322
+ );
323
+
324
+ // All patients
325
+ const allPatients = await analyticsService.getPatientAnalytics(
326
+ undefined,
327
+ dateRange
328
+ );
329
+ ```
330
+
331
+ ### 9. **Dashboard Data** 📊
332
+
333
+ ```typescript
334
+ const dashboard = await analyticsService.getDashboardData(
335
+ { clinicBranchId: 'clinic-123' },
336
+ dateRange
337
+ );
338
+
339
+ // Returns comprehensive dashboard with:
340
+ // - Overview metrics
341
+ // - Top practitioners
342
+ // - Top procedures
343
+ // - Cancellation/no-show metrics
344
+ // - Revenue trends
345
+ // - Time efficiency
346
+ // - Top products
347
+ // - Recent activity
348
+ ```
349
+
350
+ ---
351
+
352
+ ## Specific Use Cases
353
+
354
+ ### Use Case 1: Patient No-Show Per Doctor 👨‍⚕️
355
+
356
+ **Question**: "Which patients have the highest no-show rate for each doctor?"
357
+
358
+ **Solution**: Get no-show metrics grouped by practitioner, then filter by patient if needed.
359
+
360
+ ```typescript
361
+ // Step 1: Get no-show metrics grouped by practitioner
362
+ const noShowByPractitioner = await analyticsService.getNoShowMetrics(
363
+ 'practitioner',
364
+ { start: new Date('2024-01-01'), end: new Date('2024-12-31') }
365
+ );
366
+
367
+ // Returns array like:
368
+ // [
369
+ // {
370
+ // entityId: 'practitioner-123',
371
+ // entityName: 'Dr. Smith',
372
+ // entityType: 'practitioner',
373
+ // totalAppointments: 100,
374
+ // noShowAppointments: 15,
375
+ // noShowRate: 15.0
376
+ // },
377
+ // ...
378
+ // ]
379
+
380
+ // Step 2: For a specific practitioner, get patient-level no-shows
381
+ // (You can filter appointments and calculate manually, or use patient analytics)
382
+
383
+ // Get all appointments for a specific practitioner
384
+ const practitionerAppointments = await analyticsService['fetchAppointments'](
385
+ { practitionerId: 'practitioner-123' },
386
+ dateRange
387
+ );
388
+
389
+ // Group no-shows by patient
390
+ const noShowByPatient = new Map<string, { name: string; noShows: number; total: number }>();
391
+
392
+ practitionerAppointments.forEach(appointment => {
393
+ const patientId = appointment.patientId;
394
+ const patientName = appointment.patientInfo?.fullName || 'Unknown';
395
+
396
+ if (!noShowByPatient.has(patientId)) {
397
+ noShowByPatient.set(patientId, { name: patientName, noShows: 0, total: 0 });
398
+ }
399
+
400
+ const patientData = noShowByPatient.get(patientId)!;
401
+ patientData.total++;
402
+
403
+ if (appointment.status === AppointmentStatus.NO_SHOW) {
404
+ patientData.noShows++;
405
+ }
406
+ });
407
+
408
+ // Calculate rates
409
+ const patientNoShowRates = Array.from(noShowByPatient.entries()).map(([patientId, data]) => ({
410
+ patientId,
411
+ patientName: data.name,
412
+ totalAppointments: data.total,
413
+ noShowCount: data.noShows,
414
+ noShowRate: (data.noShows / data.total) * 100
415
+ })).sort((a, b) => b.noShowRate - a.noShowRate);
416
+
417
+ console.log('Patient no-show rates for this practitioner:');
418
+ patientNoShowRates.forEach(patient => {
419
+ console.log(`${patient.patientName}: ${patient.noShowRate.toFixed(1)}% (${patient.noShowCount}/${patient.total})`);
420
+ });
421
+ ```
422
+
423
+ ### Use Case 2: Doctor Performance Comparison 📊
424
+
425
+ ```typescript
426
+ // Get all practitioners for a clinic
427
+ const practitioners = await analyticsService.getCancellationMetrics(
428
+ 'practitioner',
429
+ { start: new Date('2024-01-01'), end: new Date('2024-12-31') }
430
+ );
431
+
432
+ // Filter by clinic if needed (would need clinicBranchId in filters)
433
+ const clinicPractitioners = practitioners.filter(p =>
434
+ // Filter logic based on your needs
435
+ );
436
+
437
+ // Compare metrics
438
+ practitioners.forEach(practitioner => {
439
+ console.log(`${practitioner.entityName}:`);
440
+ console.log(` Cancellation Rate: ${practitioner.cancellationRate}%`);
441
+ console.log(` Total Appointments: ${practitioner.totalAppointments}`);
442
+ });
443
+ ```
444
+
445
+ ### Use Case 3: Procedure Profitability Analysis 💰
446
+
447
+ ```typescript
448
+ // Get most profitable procedures
449
+ const profitable = await analyticsService.getProcedureProfitability(
450
+ { start: new Date('2024-01-01'), end: new Date('2024-12-31') },
451
+ 10 // Top 10
452
+ );
453
+
454
+ profitable.forEach((procedure, index) => {
455
+ console.log(`${index + 1}. ${procedure.procedureName}`);
456
+ console.log(` Revenue: ${procedure.totalRevenue} ${procedure.currency || 'CHF'}`);
457
+ console.log(` Appointments: ${procedure.appointmentCount}`);
458
+ console.log(` Avg Revenue: ${procedure.averageRevenue.toFixed(2)}`);
459
+ });
460
+ ```
461
+
462
+ ### Use Case 4: Time Efficiency by Doctor ⏱️
463
+
464
+ ```typescript
465
+ // Get time efficiency for a specific practitioner
466
+ const practitionerMetrics = await analyticsService.getPractitionerAnalytics(
467
+ 'practitioner-id-123',
468
+ dateRange
469
+ );
470
+
471
+ console.log(`Time Efficiency: ${practitionerMetrics.timeEfficiency}%`);
472
+ console.log(`Avg Booked Time: ${practitionerMetrics.averageBookedTime} min`);
473
+ console.log(`Avg Actual Time: ${practitionerMetrics.averageActualTime} min`);
474
+
475
+ // Or get overall time efficiency with filters
476
+ const timeMetrics = await analyticsService.getTimeEfficiencyMetrics(
477
+ { practitionerId: 'practitioner-id-123' },
478
+ dateRange
479
+ );
480
+ ```
481
+
482
+ ### Use Case 5: Product Cost Analysis 📦
483
+
484
+ ```typescript
485
+ // Get product usage for a specific procedure
486
+ const procedureAnalytics = await analyticsService.getProcedureAnalytics(
487
+ 'procedure-id-123',
488
+ dateRange
489
+ );
490
+
491
+ // Check product usage
492
+ procedureAnalytics.productUsage.forEach(product => {
493
+ console.log(`${product.productName}:`);
494
+ console.log(` Total Quantity: ${product.totalQuantity}`);
495
+ console.log(` Total Revenue: ${product.totalRevenue}`);
496
+ console.log(` Used in ${product.usageCount} appointments`);
497
+ });
498
+ ```
499
+
500
+ ---
501
+
502
+ ## Performance Tips
503
+
504
+ 1. **Use pre-computed analytics** when possible (default behavior)
505
+ 2. **Specify clinicBranchId** in filters to enable caching
506
+ 3. **Use standard date ranges** (daily, weekly, monthly) for better cache hits
507
+ 4. **Batch requests** when getting multiple practitioners/procedures
508
+ 5. **Cache results** on the client side for frequently accessed dashboards
509
+
510
+ ---
511
+
512
+ ## Next Steps
513
+
514
+ 1. **Deploy Cloud Function**: Deploy `computeAnalytics.ts` to start pre-computing
515
+ 2. **Test with real data**: Verify analytics accuracy
516
+ 3. **Monitor performance**: Check Cloud Function logs and Firestore usage
517
+ 4. **Customize**: Adjust cache age and computation schedule as needed
518
+